From 1b053d937c7c25e298662d3286ad9348d541de58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Pietraszewicz?= Date: Mon, 26 Feb 2024 23:23:56 +0100 Subject: [PATCH 01/10] enhancement: introduce new liabilities suspention methods --- bin/lms-maketcnew.php | 24 +- bin/lms-notify.php | 71 +- bin/lms-payments.php | 1057 +++++++---- css/style.css | 2 +- css/style.less | 13 + .../customer/customerassignments.css | 2 +- .../customer/customerassignments.less | 32 +- .../customer/customerassignmentssuspend.css | 1 + .../customer/customerassignmentssuspend.less | 123 ++ doc/lms.mysql | 383 +++- doc/lms.pgsql | 399 +++- js/customerassignmenthelper.js | 269 ++- lib/LMS.class.php | 67 +- lib/LMSDB_common.class.php | 2 +- lib/LMSManagers/LMSCustomerManager.php | 236 ++- lib/LMSManagers/LMSFinanceManager.php | 1625 ++++++++++++++--- .../LMSFinanceManagerInterface.php | 22 +- lib/LMSManagers/LMSNodeManager.php | 8 +- lib/SYSLOG.class.php | 4 + lib/SmartyPlugins/block.tab_header.php | 3 +- lib/common.php | 2 +- lib/config.php | 8 +- lib/definitions.php | 21 + lib/locale/pl_PL/strings.php | 34 + lib/upgradedb/mysql.2024052400.php | 883 +++++++++ lib/upgradedb/postgres.2024052400.php | 1033 +++++++++++ modules/configlist.php | 8 +- modules/customer.inc.php | 7 +- modules/customerassignmentadd.php | 501 ++++- modules/customerassignmentedit.php | 1222 ++++++++----- modules/messageadd.php | 28 +- modules/netdevedit.php | 2 +- modules/netdevinfo.php | 2 +- modules/nodeservicelist.php | 13 +- modules/print.php | 629 +++++-- modules/suspensiondel.php | 52 + modules/tarifflist.php | 18 +- modules/ukepit.php | 84 +- modules/ukesiis.php | 53 +- .../customer/customerassignmenthelper.html | 213 ++- .../default/customer/customerassignments.html | 1216 +++++++----- .../customer/customerassignmentsedit.html | 44 +- .../customer/customerassignmentssuspend.html | 346 ++++ userpanel/modules/finances/main.php | 2 +- .../bclean/templates/userassignments.html | 121 +- .../finances/templates/userassignments.html | 239 +-- 46 files changed, 8809 insertions(+), 2315 deletions(-) create mode 100644 css/templates/customer/customerassignmentssuspend.css create mode 100644 css/templates/customer/customerassignmentssuspend.less create mode 100644 lib/upgradedb/mysql.2024052400.php create mode 100644 lib/upgradedb/postgres.2024052400.php create mode 100644 modules/suspensiondel.php create mode 100644 templates/default/customer/customerassignmentssuspend.html diff --git a/bin/lms-maketcnew.php b/bin/lms-maketcnew.php index 40991b77bf..3c01ef5b18 100755 --- a/bin/lms-maketcnew.php +++ b/bin/lms-maketcnew.php @@ -258,16 +258,14 @@ function ($value) { JOIN assignments a ON (na.assignmentid = a.id) " . ($ignore_assignment_suspensions ? '' - : "LEFT JOIN ( - SELECT customerid, COUNT(id) AS allsuspended FROM assignments - WHERE tariffid IS NULL AND liabilityid IS NULL - AND datefrom <= ?NOW? AND (dateto = 0 OR dateto > ?NOW?) - GROUP BY customerid - ) s ON s.customerid = a.customerid") . " + : "LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0)") . " JOIN tariffs t ON (a.tariffid = t.id) JOIN vnodes n ON (na.nodeid = n.id) JOIN customers c ON (a.customerid = c.id) - WHERE " . ($ignore_assignment_suspensions ? '' : "s.allsuspended IS NULL AND a.suspended = 0 AND ") . "a.commited = 1 + WHERE " . ($ignore_assignment_suspensions ? '' : "vas.suspended IS NOT NULL AND ") . "a.commited = 1 AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) AND n.access = 1 AND (t.downrate > 0 OR t.downceil > 0 OR t.uprate > 0 OR t.upceil > 0) @@ -292,12 +290,10 @@ function ($value) { FROM assignments a " . ($ignore_assignment_suspensions ? '' - : "LEFT JOIN ( - SELECT customerid, COUNT(id) AS allsuspended FROM assignments - WHERE tariffid IS NULL AND liabilityid IS NULL - AND datefrom <= ?NOW? AND (dateto = 0 OR dateto > ?NOW?) - GROUP BY customerid - ) s ON s.customerid = a.customerid") . " + : "LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = na.assignmentid + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0)") . " JOIN tariffs t ON t.id = a.tariffid JOIN customers c ON c.id = a.customerid JOIN ( @@ -308,7 +304,7 @@ function ($value) { WHERE (vn.ownerid > 0 AND nd.id IS NULL) OR (vn.ownerid IS NULL AND nd.id IS NOT NULL) ) n ON n.ownerid = c.id - WHERE " . ($ignore_assignment_suspensions ? '' : "s.allsuspended IS NULL AND a.suspended = 0 AND ") . "a.commited = 1 + WHERE " . ($ignore_assignment_suspensions ? '' : "vas.suspended IS NOT NULL AND ") . "a.commited = 1 AND n.id NOT IN (SELECT DISTINCT nodeid FROM nodeassignments) AND a.id NOT IN (SELECT DISTINCT assignmentid FROM nodeassignments) AND a.datefrom <= ?NOW? diff --git a/bin/lms-notify.php b/bin/lms-notify.php index 0fa1e49900..d631136647 100755 --- a/bin/lms-notify.php +++ b/bin/lms-notify.php @@ -411,7 +411,6 @@ 'ssl_allow_self_signed' => ConfigHelper::checkConfig($config_section . '.smtp_ssl_allow_self_signed'), ); -$suspension_percentage = floatval(ConfigHelper::getConfig('payments.suspension_percentage', ConfigHelper::getConfig('finances.suspension_percentage', 0))); $debug_email = ConfigHelper::getConfig($config_section . '.debug_email', '', true); $mail_from = ConfigHelper::getConfig($config_section . '.sender_email', ConfigHelper::getConfig($config_section . '.mailfrom', '', true)); $mail_fname = ConfigHelper::getConfig($config_section . '.sender_name', ConfigHelper::getConfig($config_section . '.mailfname', '', true)); @@ -720,30 +719,29 @@ function parse_customer_data($data, $format, $row) ); if (preg_match("/\%abonament/", $data)) { $assignments = $DB->GetAll( - 'SELECT SUM(ROUND(((((100 - a.pdiscount) * (CASE WHEN a.liabilityid IS NULL THEN t.value ELSE l.value END)) / 100) - a.vdiscount) * - (CASE a.suspended WHEN 0 - THEN 1.0 - ELSE ? - END), 2)) AS value, + 'SELECT SUM( + (CASE WHEN vas.suspended IS NULL + THEN ROUND(((((100 - a.pdiscount) * (CASE WHEN a.liabilityid IS NULL THEN t.value ELSE l.value END)) / 100) - a.vdiscount), 2) + ELSE vas.suspension_price + END) + ) AS value, (CASE WHEN a.liabilityid IS NULL THEN t.currency ELSE l.currency END) AS acurrency FROM assignments a LEFT JOIN tariffs t ON t.id = a.tariffid LEFT JOIN liabilities l ON l.id = a.liabilityid - WHERE a.customerid = ? AND (t.id IS NOT NULL OR l.id IS NOT NULL) - AND a.datefrom <= ? AND (a.dateto > ? OR a.dateto = 0) - AND NOT EXISTS ( - SELECT 1 FROM assignments - WHERE customerid = a.customerid AND tariffid IS NULL AND liabilityid IS NULL - AND datefrom <= ? AND (dateto > ? OR dateto = 0) - ) + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ? + AND (vas.suspension_dateto >= ? OR vas.suspension_dateto = 0) + AND datefrom <= ? AND (dateto > ? OR dateto = 0) + WHERE a.customerid = ? + AND vas.suspended IS NULL GROUP BY acurrency', array( - round($GLOBALS['suspension_percentage'] / 100, 2), - $row['id'], $GLOBALS['currtime'], $GLOBALS['currtime'], $GLOBALS['currtime'], $GLOBALS['currtime'], + $row['id'], ) ); $saldo = array(); @@ -3536,8 +3534,13 @@ function send_sms_to_user($phone, $data) WHERE status <> ' . $target_cstatus . ' AND customers.id = c.id)'; break; case 'all-assignment-suspension': - $where_customers[] = 'NOT EXISTS (SELECT id FROM assignments - WHERE customerid = c.id AND tariffid IS NULL AND liabilityid IS NULL)'; + $where_customers[] = 'NOT EXISTS (SELECT id + FROM assignments + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) + WHERE customerid = c.id AND vas.suspension_suspend_all = 1)'; break; case 'customer-group': $where_customers[] = 'NOT EXISTS ( @@ -3745,7 +3748,10 @@ function send_sms_to_user($phone, $data) ); foreach ($customers as $cid) { if (!$DB->GetOne( - "SELECT id FROM assignments WHERE customerid = ? AND tariffid IS NULL AND liabilityid IS NULL", + "SELECT id + FROM assignments + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + WHERE customerid = ? AND vas.suspension_suspend_all = 1", array($cid) )) { if (!$quiet) { @@ -3875,8 +3881,10 @@ function send_sms_to_user($phone, $data) WHERE status <> ' . $target_cstatus . ' AND customers.id = c.id)'; break; case 'all-assignment-suspension': - $where_customers[] = 'EXISTS (SELECT id FROM assignments - WHERE customerid = c.id AND tariffid IS NULL AND liabilityid IS NULL)'; + $where_customers[] = 'EXISTS (SELECT id + FROM assignments + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + WHERE customerid = c.id AND vas.suspension_suspend_all = 1)'; break; case 'customer-group': $where_customers[] = 'EXISTS ( @@ -4073,15 +4081,23 @@ function send_sms_to_user($phone, $data) $SYSLOG->NewTransaction('lms-notify.php'); } if ($datefrom = $DB->GetOne( - "SELECT datefrom FROM assignments WHERE customerid = ? AND tariffid IS NULL AND liabilityid IS NULL", + "SELECT datefrom + FROM assignments + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + WHERE customerid = ? AND vas.suspension_suspend_all = 1", array($cid) )) { $year = intval(date('Y', $datefrom)); $month = intval(date('m', $datefrom)); if ($year < $current_year || ($year == $current_year && $month < $current_month)) { $aids = $DB->GetCol( - "SELECT id FROM assignments - WHERE customerid = ? AND (tariffid IS NOT NULL OR liabilityid IS NOT NULL) + "SELECT id + FROM assignments + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) + WHERE customerid = ? AND vas.suspension_suspend_all = 1 AND datefrom < ?NOW? AND (dateto = 0 OR dateto > ?NOW?)", array($cid) ); @@ -4104,8 +4120,13 @@ function send_sms_to_user($phone, $data) } } } - $aids = $DB->GetCol("SELECT id FROM assignments - WHERE customerid = ? AND tariffid IS NULL AND liabilityid IS NULL", array($cid)); + $aids = $DB->GetCol( + "SELECT id + FROM assignments + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + WHERE customerid = ? AND vas.suspension_suspend_all = 1", + array($cid) + ); if (!empty($aids)) { foreach ($aids as $aid) { if (!$quiet) { diff --git a/bin/lms-payments.php b/bin/lms-payments.php index 0af033e061..f4e34ac8bd 100755 --- a/bin/lms-payments.php +++ b/bin/lms-payments.php @@ -92,7 +92,12 @@ $s_comment = ConfigHelper::getConfig($config_section . '.settlement_comment', $comment); $s_backward_comment = ConfigHelper::getConfig($config_section . '.settlement_backward_comment', $s_comment); $suspension_description = ConfigHelper::getConfig($config_section . '.suspension_description', ''); -$suspension_percentage = ConfigHelper::getConfig('payments.suspension_percentage', ConfigHelper::getConfig('finances.suspension_percentage', 0)); +$defaultSuspensionPercentage = ConfigHelper::getConfig( + 'suspensions.default_percentage', + ConfigHelper::getConfig('payments.suspension_percentage', ConfigHelper::getConfig('finances.suspension_percentage', 0)) +); +$defaultSuspensionPercentage = f_round($defaultSuspensionPercentage); +$defaultSuspensionValue = f_round(ConfigHelper::getConfig('suspensions.default_value', 0)); $unit_name = trans(ConfigHelper::getConfig($config_section . '.default_unit_name')); $check_invoices = ConfigHelper::checkConfig($config_section . '.check_invoices'); $proforma_generates_commitment = ConfigHelper::checkConfig('phpui.proforma_invoice_generates_commitment'); @@ -232,7 +237,7 @@ // calculate start and end of numbering period function get_period($period) { - global $dom, $month, $year; + global $dom, $weekday, $month, $year; if (empty($period)) { $period = YEARLY; } @@ -401,70 +406,92 @@ function get_period($period) } else { // let's go, fetch *ALL* assignments in given day $query = "SELECT - a.id, - a.tariffid, - a.liabilityid, - a.customerid, - a.recipient_address_id, - (CASE WHEN ca2.address_id IS NULL THEN ca1.address_id ELSE ca2.address_id END) AS post_address_id, - a.period, - a.backwardperiod, - a.at, - a.suspended, - a.settlement, - a.datefrom, - a.dateto, - a.pdiscount, - a.vdiscount, - a.invoice, - a.separatedocument, - a.separateitem, - c.type AS customertype, - (CASE WHEN c.type = ? THEN 0 ELSE (CASE WHEN a.liabilityid IS NULL - THEN (CASE WHEN t.flags & ? > 0 THEN 1 ELSE 0 END) - ELSE (CASE WHEN l.flags & ? > 0 THEN 1 ELSE 0 END) - END) END) AS splitpayment, - (CASE WHEN a.liabilityid IS NULL - THEN (CASE WHEN t.flags & ? > 0 THEN 1 ELSE 0 END) - ELSE (CASE WHEN l.flags & ? > 0 THEN 1 ELSE 0 END) - END) AS netflag, - (CASE WHEN a.liabilityid IS NULL THEN t.taxcategory ELSE l.taxcategory END) AS taxcategory, - t.description AS description, - a.id AS assignmentid, - c.divisionid, - c.paytime, - c.paytype, - c.flags AS customerflags, - a.paytime AS a_paytime, - a.paytype AS a_paytype, - a.numberplanid, - a.attribute, - p.name AS promotion_name, - ps.name AS promotion_schema_name, - ps.length AS promotion_schema_length, - d.inv_paytime AS d_paytime, - d.inv_paytype AS d_paytype, - t.period AS t_period, - t.numberplanid AS tariffnumberplanid, - t.flags, - (CASE WHEN cc1.type IS NULL THEN 0 ELSE 1 END) AS einvoice, - (CASE WHEN cc2.type IS NULL THEN 0 ELSE 1 END) AS mail_marketing, - (CASE WHEN cc3.type IS NULL THEN 0 ELSE 1 END) AS sms_marketing, - (CASE WHEN a.tariffid IS NULL THEN l.type ELSE t.type END) AS tarifftype, - (CASE WHEN a.liabilityid IS NULL THEN t.name ELSE l.name END) AS name, - (CASE WHEN a.liabilityid IS NULL THEN t.taxid ELSE l.taxid END) AS taxid, - (CASE WHEN a.liabilityid IS NULL THEN t.prodid ELSE l.prodid END) AS prodid, - voipphones.phones, - ROUND(((((100 - a.pdiscount) * (CASE WHEN a.liabilityid IS NULL THEN tvalue ELSE lvalue END)) / 100) - a.vdiscount), 3) AS price, - (CASE WHEN a.liabilityid IS NULL THEN t.taxrate ELSE l.taxrate END) AS taxrate, - (CASE WHEN a.liabilityid IS NULL THEN t.currency ELSE l.currency END) AS currency, - a.count AS count, - (SELECT COUNT(id) FROM assignments - WHERE customerid = c.id AND tariffid IS NULL AND liabilityid IS NULL - AND datefrom <= $currtime - AND (dateto > $currtime OR dateto = 0)) AS allsuspended + a.at, + a.attribute, + a.backwardperiod, + a.count AS count, + a.customerid, + a.datefrom, + a.dateto, + a.id, + a.id AS assignmentid, + a.invoice, + a.liabilityid, + a.numberplanid, + a.paytime AS a_paytime, + a.paytype AS a_paytype, + a.pdiscount, + a.period, + a.recipient_address_id, + a.separatedocument, + a.separateitem, + a.settlement, + a.tariffid, + a.vdiscount, + c.divisionid, + c.flags AS customerflags, + c.paytime, + c.paytype, + c.type AS customertype, + d.inv_paytime AS d_paytime, + d.inv_paytype AS d_paytype, + p.name AS promotion_name, + ps.length AS promotion_schema_length, + ps.name AS promotion_schema_name, + t.description AS description, + t.flags, + t.numberplanid AS tariffnumberplanid, + t.period AS t_period, + (CASE WHEN ca2.address_id IS NULL THEN ca1.address_id ELSE ca2.address_id END) AS post_address_id, + (CASE WHEN c.type = ? THEN 0 ELSE (CASE WHEN a.liabilityid IS NULL + THEN (CASE WHEN t.flags & ? > 0 THEN 1 ELSE 0 END) + ELSE (CASE WHEN l.flags & ? > 0 THEN 1 ELSE 0 END) + END) END) AS splitpayment, + (CASE WHEN a.liabilityid IS NULL + THEN (CASE WHEN t.flags & ? > 0 THEN 1 ELSE 0 END) + ELSE (CASE WHEN l.flags & ? > 0 THEN 1 ELSE 0 END) + END) AS netflag, + (CASE WHEN a.liabilityid IS NULL THEN t.taxcategory ELSE l.taxcategory END) AS taxcategory, + (CASE WHEN cc1.type IS NULL THEN 0 ELSE 1 END) AS einvoice, + (CASE WHEN cc2.type IS NULL THEN 0 ELSE 1 END) AS mail_marketing, + (CASE WHEN cc3.type IS NULL THEN 0 ELSE 1 END) AS sms_marketing, + (CASE WHEN a.tariffid IS NULL THEN l.type ELSE t.type END) AS tarifftype, + (CASE WHEN a.liabilityid IS NULL THEN t.name ELSE l.name END) AS name, + (CASE WHEN a.liabilityid IS NULL THEN t.taxid ELSE l.taxid END) AS taxid, + (CASE WHEN a.liabilityid IS NULL THEN t.prodid ELSE l.prodid END) AS prodid, + (CASE WHEN a.liabilityid IS NULL THEN t.taxrate ELSE l.taxrate END) AS taxrate, + (CASE WHEN a.liabilityid IS NULL THEN t.currency ELSE l.currency END) AS currency, + (CASE WHEN price_variants.tpv_price IS NULL + THEN + ROUND(((((100 - a.pdiscount) * (CASE WHEN a.liabilityid IS NULL THEN tvalue ELSE lvalue END)) / 100) - a.vdiscount), 3) + ELSE + ROUND(((((100 - a.pdiscount) * price_variants.tpv_price) / 100) - a.vdiscount), 3) + END) AS price, + voipphones.phones, + vas.*, + (CASE + WHEN vas.suspended IS NOT NULL + AND + ( + ( + vas.suspension_charge_method = ? AND vas.suspension_at = ? + ) + OR + ( + ( + vas.suspension_charge_method = ? + OR + (vas.suspension_charge_method = ? AND vas.suspension_at IN ?) + ) + AND vas.suspension_datefrom <= ? + AND (vas.suspension_dateto > ? OR vas.suspension_dateto = 0) + ) + ) + THEN 1 + ELSE 0 + END) AS charge_suspension FROM assignments a - JOIN customers c ON a.customerid = c.id + JOIN customers c ON (a.customerid = c.id) LEFT JOIN customerconsents cc1 ON cc1.customerid = c.id AND cc1.type = " . CCONSENT_EINVOICE . " LEFT JOIN customerconsents cc2 ON cc2.customerid = c.id AND cc2.type = " . CCONSENT_MAIL_MARKETING . " LEFT JOIN customerconsents cc3 ON cc3.customerid = c.id AND cc3.type = " . CCONSENT_SMS_MARKETING . " @@ -473,7 +500,7 @@ function get_period($period) LEFT JOIN promotionschemas ps ON ps.id = a.promotionschemaid LEFT JOIN promotions p ON p.id = ps.promotionid LEFT JOIN ( - SELECT + SELECT tariffs.*, taxes.value AS taxrate, (CASE WHEN tariffs.flags & ? > 0 THEN tariffs.netvalue ELSE tariffs.value END) AS tvalue @@ -481,7 +508,7 @@ function get_period($period) JOIN taxes ON taxes.id = tariffs.taxid ) t ON a.tariffid = t.id LEFT JOIN ( - SELECT + SELECT liabilities.*, taxes.value AS taxrate, (CASE WHEN liabilities.flags & ? > 0 THEN liabilities.netvalue ELSE liabilities.value END) AS lvalue @@ -489,29 +516,65 @@ function get_period($period) JOIN taxes ON taxes.id = liabilities.taxid ) l ON a.liabilityid = l.id LEFT JOIN ( - SELECT - vna.assignment_id, " . $DB->GroupConcat('vn.phone', ',') . " AS phones + SELECT + vna.assignment_id, + " . $DB->GroupConcat('vn.phone', ',') . " AS phones FROM voip_number_assignments vna LEFT JOIN voip_numbers vn ON vn.id = vna.number_id GROUP BY vna.assignment_id ) voipphones ON voipphones.assignment_id = a.id - LEFT JOIN divisions d ON d.id = c.divisionid + LEFT JOIN divisions d ON (d.id = c.divisionid) + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ? + AND (vas.suspension_dateto > ? OR vas.suspension_dateto = 0) + LEFT JOIN ( + SELECT + tpv.* + FROM assignments a + JOIN ( + SELECT + tariffpricevariants.quantity_threshold AS tpv_quantity_threshold, tariffs.id AS tpv_tariffid, + (CASE WHEN tariffs.flags & ? > 0 THEN tariffpricevariants.net_price ELSE tariffpricevariants.gross_price END) AS tpv_price + FROM tariffs + JOIN tariffpricevariants ON tariffs.id = tariffpricevariants.tariffid + ) tpv ON a.tariffid = tpv.tpv_tariffid AND tpv.tpv_quantity_threshold <= a.count AND tpv.tpv_tariffid = a.tariffid + ORDER BY tpv.tpv_quantity_threshold DESC LIMIT 1 + ) AS price_variants ON a.tariffid = price_variants.tpv_tariffid WHERE " . ($customerid ? 'c.id = ' . $customerid : '1 = 1') . $customer_status_condition . ($divisionid ? ' AND c.divisionid = ' . $divisionid : '') . " AND a.commited = 1 - AND ((a.period = ? AND at = ?) - OR ((a.period = ? - OR (a.period = ? AND at = ?) - OR (a.period = ? AND at IN ?) - OR (a.period = ? AND at = ?) - OR (a.period = ? AND at = ?) - OR (a.period = ? AND at = ?)) - AND a.datefrom <= ? AND (a.dateto > ? OR a.dateto = 0)))" + AND ( + (a.period = ? AND at = ?) + OR ( + ( + a.period = ? + OR (a.period = ? AND at = ?) + OR (a.period = ? AND at IN ?) + OR (a.period = ? AND at = ?) + OR (a.period = ? AND at = ?) + OR (a.period = ? AND at = ?) + ) + AND a.datefrom <= ? AND (a.dateto > ? OR a.dateto = 0) + ) + OR ( + (vas.suspension_charge_method = ? AND vas.suspension_at = ?) + OR ( + ( + vas.suspension_charge_method = ? + OR + (vas.suspension_charge_method = ? AND vas.suspension_at IN ?) + ) + AND vas.suspension_datefrom <= ? + AND (vas.suspension_dateto >= ? OR vas.suspension_dateto = 0) + AND a.datefrom <= ? AND (a.dateto > ? OR a.dateto = 0) + ) + ) + )" . ($customergroups ? str_replace('%customerid_alias%', 'c.id', $customergroups) : '') . ($tariff_tags ?: '') - . " ORDER BY a.customerid, a.recipient_address_id, a.invoice, a.paytime, c.paytime, d.inv_paytime, - a.paytype, c.paytype, d.inv_paytype, a.numberplanid, t.numberplanid, a.separatedocument, a.separateitem, currency, netflag, price DESC, a.id"; + ." ORDER BY a.customerid, a.recipient_address_id, a.invoice, a.paytime, c.paytime, d.inv_paytime, + a.paytype, c.paytype, d.inv_paytype, a.numberplanid, t.numberplanid, a.separatedocument, a.separateitem, currency, netflag, price DESC, a.id"; $services = $DB->GetAll( $query, @@ -534,159 +597,177 @@ function get_period($period) $empty_billings = ConfigHelper::checkConfig('voip.empty_billings'); $query = "SELECT - a.id, a.tariffid, a.customerid, a.recipient_address_id, - (CASE WHEN ca2.address_id IS NULL THEN ca1.address_id ELSE ca2.address_id END) AS post_address_id, - a.period, a.backwardperiod, a.at, a.suspended, a.settlement, a.datefrom, - 0 AS pdiscount, 0 AS vdiscount, a.invoice, - a.separatedocument, - a.separateitem, - c.type AS customertype, - t.type AS tarifftype, - t.taxcategory AS taxcategory, - t.description AS description, a.id AS assignmentid, - c.divisionid, c.paytype, c.paytime, c.flags AS customerflags, - a.paytime AS a_paytime, a.paytype AS a_paytype, a.numberplanid, a.attribute, - p.name AS promotion_name, ps.name AS promotion_schema_name, ps.length AS promotion_schema_length, - d.inv_paytime AS d_paytime, d.inv_paytype AS d_paytype, t.period AS t_period, t.numberplanid AS tariffnumberplanid, - 0 AS flags, - t.taxid AS taxid, '' as prodid, - COALESCE(voipcost.value, 0) AS price, - COALESCE(voipcost.totaltime, 0) AS call_time, - " . ($billing_invoice_separate_fractions ? ' COALESCE(voipcost.call_count, 0) AS call_count, COALESCE(voipcost.call_fraction, \'\') AS call_fraction , ' : '') . " - taxes.value AS taxrate, - (CASE WHEN c.type = ? - THEN 0 - ELSE (CASE WHEN t.flags & ? > 0 - THEN 1 - ELSE 0 - END) - END) AS splitpayment, - (CASE WHEN t.flags & ? > 0 - THEN 1 - ELSE 0 - END) AS netflag, - t.currency, voipphones.phones, - 'set' AS liabilityid, '$billing_invoice_description' AS name, - ? AS count, - (SELECT COUNT(id) - FROM assignments - WHERE - customerid = c.id AND - tariffid IS NULL AND - liabilityid IS NULL AND - datefrom <= $currtime AND - (dateto > $currtime OR dateto = 0)) AS allsuspended, - (CASE WHEN EXISTS (SELECT 1 FROM customerconsents cc WHERE cc.customerid = c.id AND cc.type IN ?) THEN 1 ELSE 0 END) AS billingconsent - FROM assignments a - JOIN tariffs t ON t.id = a.tariffid - JOIN taxes ON taxes.id = t.taxid - LEFT JOIN promotionschemas ps ON ps.id = a.promotionschemaid - LEFT JOIN promotions p ON p.id = ps.promotionid - JOIN customers c ON (a.customerid = c.id) - LEFT JOIN customer_addresses ca1 ON ca1.customer_id = c.id AND ca1.type = " . BILLING_ADDRESS . " - LEFT JOIN customer_addresses ca2 ON ca2.customer_id = c.id AND ca2.type = " . POSTAL_ADDRESS . " - " . ($empty_billings ? 'LEFT ' : '') . "JOIN ( - SELECT ROUND(sum(price), 2) AS value, - SUM(vc.billedtime) AS totaltime, - " . ($billing_invoice_separate_fractions ? ' COUNT(vc.*) AS call_count, vc.fraction AS call_fraction, ' : '') - . "va.ownerid AS customerid, - a2.id AS assignmentid - FROM voip_cdr vc - JOIN voipaccounts va ON va.id = vc.callervoipaccountid AND vc.direction = " . BILLING_RECORD_DIRECTION_OUTGOING . " OR va.id = vc.calleevoipaccountid AND vc.direction = " . BILLING_RECORD_DIRECTION_INCOMING . " - JOIN voip_numbers vn ON vn.voip_account_id = va.id - AND ( - ( - vn.voip_account_id = vc.callervoipaccountid - AND - vn.phone = vc.caller - AND - vc.direction = " . BILLING_RECORD_DIRECTION_OUTGOING . " - ) OR ( - vn.voip_account_id = vc.calleevoipaccountid - AND - vn.phone = vc.callee - AND - vc.direction = " . BILLING_RECORD_DIRECTION_INCOMING . " - ) - ) - JOIN voip_number_assignments vna ON vna.number_id = vn.id - JOIN assignments a2 ON a2.id = vna.assignment_id - JOIN tariffs t ON t.id = a2.tariffid AND t.type = ? - WHERE ( - ( - vc.call_start_time >= (CASE a2.period - WHEN " . YEARLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year-1) . ' - WHEN ' . HALFYEARLY . ' THEN ' . mktime(0, 0, 0, $month-6, 1, $year) . ' - WHEN ' . QUARTERLY . ' THEN ' . mktime(0, 0, 0, $month-3, 1, $year) . ' - WHEN ' . MONTHLY . ' THEN ' . mktime(0, 0, 0, $month-1, 1, $year) . ' - WHEN ' . DISPOSABLE . ' THEN ' . $currtime . " - END) - AND - vc.call_start_time < (CASE a2.period - WHEN " . YEARLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year) . ' - WHEN ' . HALFYEARLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year) . ' - WHEN ' . QUARTERLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year) . ' - WHEN ' . MONTHLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year) . ' - WHEN ' . DISPOSABLE . ' THEN ' . ($currtime + 86400) . " - END) - ) OR ( - vc.call_start_time + totaltime >= (CASE a2.period - WHEN " . YEARLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year-1) . ' - WHEN ' . HALFYEARLY . ' THEN ' . mktime(0, 0, 0, $month-6, 1, $year) . ' - WHEN ' . QUARTERLY . ' THEN ' . mktime(0, 0, 0, $month-3, 1, $year) . ' - WHEN ' . MONTHLY . ' THEN ' . mktime(0, 0, 0, $month-1, 1, $year) . ' - WHEN ' . DISPOSABLE . ' THEN ' . $currtime . " - END) - AND - vc.call_start_time + totaltime < (CASE a2.period - WHEN " . YEARLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year) . ' - WHEN ' . HALFYEARLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year) . ' - WHEN ' . QUARTERLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year) . ' - WHEN ' . MONTHLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year) . ' - WHEN ' . DISPOSABLE . ' THEN ' . ($currtime + 86400) . " - END) - ) - ) - GROUP BY va.ownerid, a2.id" . ($billing_invoice_separate_fractions ? ', vc.fraction' : '') . " - ) voipcost ON voipcost.customerid = a.customerid AND voipcost.assignmentid = a.id - LEFT JOIN ( - SELECT vna2.assignment_id, " . $DB->GroupConcat('vn2.phone', ', ') . " AS phones - FROM voip_number_assignments vna2 - LEFT JOIN voip_numbers vn2 ON vn2.id = vna2.number_id - GROUP BY vna2.assignment_id - ) voipphones ON voipphones.assignment_id = a.id - LEFT JOIN divisions d ON (d.id = c.divisionid) - WHERE " . ($customerid ? 'c.id = ' . $customerid : '1 = 1') - . $customer_status_condition - . ($divisionid ? ' AND c.divisionid = ' . $divisionid : '') - . " AND t.type = ? AND - a.commited = 1 AND - ((a.period = ? AND at = ?) OR - ((a.period = ? OR - (a.period = ? AND at = ?) OR - (a.period = ? AND at IN ?) OR - (a.period = ? AND at = ?) OR - (a.period = ? AND at = ?) OR - (a.period = ? AND at = ?)) AND - a.datefrom <= ? AND - (a.dateto = 0 OR a.dateto > (CASE a.period - WHEN " . YEARLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year - 1) . " - WHEN " . HALFYEARLY . ' THEN ' . mktime(0, 0, 0, $month - 6, 1, $year) . " - WHEN " . QUARTERLY . ' THEN ' . mktime(0, 0, 0, $month - 3, 1, $year) . " - WHEN " . MONTHLY . ' THEN ' . mktime(0, 0, 0, $month - 1, 1, $year) - . " END))))" - . ($customergroups ? str_replace('%customerid_alias%', 'c.id', $customergroups) : '') - . ($tariff_tags ?: '') - ." ORDER BY a.customerid, a.recipient_address_id, a.invoice, a.paytime, c.paytime, d.inv_paytime, - a.paytype, c.paytype, d.inv_paytype, a.numberplanid, a.separatedocument, a.separateitem, currency, netflag, voipcost.value DESC, a.id"; + a.at, + a.attribute, + a.backwardperiod, + ? AS count, + a.customerid, + a.datefrom, + a.dateto, + a.id, + a.id AS assignmentid, + a.invoice, + 'set' AS liabilityid, + a.numberplanid, + a.paytime AS a_paytime, + a.paytype AS a_paytype, + 0 AS pdiscount, + a.period, + a.recipient_address_id, + a.separatedocument, + a.separateitem, + a.settlement, + a.tariffid, + 0 AS vdiscount, + c.divisionid, + c.flags AS customerflags, + c.paytime, + c.paytype, + c.type AS customertype, + d.inv_paytime AS d_paytime, + d.inv_paytype AS d_paytype, + p.name AS promotion_name, + ps.length AS promotion_schema_length, + ps.name AS promotion_schema_name, + t.description AS description, + 0 AS flags, + t.numberplanid AS tariffnumberplanid, + t.period AS t_period, + (CASE WHEN ca2.address_id IS NULL THEN ca1.address_id ELSE ca2.address_id END) AS post_address_id, + (CASE WHEN c.type = ? + THEN 0 + ELSE (CASE WHEN t.flags & ? > 0 + THEN 1 + ELSE 0 + END) + END) AS splitpayment, + (CASE WHEN t.flags & ? > 0 + THEN 1 + ELSE 0 + END) AS netflag, + t.taxcategory AS taxcategory, + t.type AS tarifftype, + '$billing_invoice_description' AS name, + t.taxid AS taxid, + '' as prodid, + taxes.value AS taxrate, + t.currency, + COALESCE(voipcost.value, 0) AS price, + COALESCE(voipcost.totaltime, 0) AS call_time, + " . ($billing_invoice_separate_fractions ? ' COALESCE(voipcost.call_count, 0) AS call_count, COALESCE(voipcost.call_fraction, \'\') AS call_fraction , ' : '') . " + voipphones.phones, + (CASE WHEN EXISTS (SELECT 1 FROM customerconsents cc WHERE cc.customerid = c.id AND cc.type IN ?) THEN 1 ELSE 0 END) AS billingconsent +FROM assignments a +JOIN customers c ON (a.customerid = c.id) +JOIN tariffs t ON t.id = a.tariffid +JOIN taxes ON taxes.id = t.taxid +LEFT JOIN promotionschemas ps ON ps.id = a.promotionschemaid +LEFT JOIN promotions p ON p.id = ps.promotionid +LEFT JOIN customer_addresses ca1 ON ca1.customer_id = c.id AND ca1.type = " . BILLING_ADDRESS . " +LEFT JOIN customer_addresses ca2 ON ca2.customer_id = c.id AND ca2.type = " . POSTAL_ADDRESS . " +" . ($empty_billings ? 'LEFT ' : '') . "JOIN ( + SELECT ROUND(sum(price), 2) AS value, + SUM(vc.billedtime) AS totaltime, + " . ($billing_invoice_separate_fractions ? ' COUNT(vc.*) AS call_count, vc.fraction AS call_fraction, ' : '') + . "va.ownerid AS customerid, + a2.id AS assignmentid + FROM voip_cdr vc + JOIN voipaccounts va ON va.id = vc.callervoipaccountid AND vc.direction = " . BILLING_RECORD_DIRECTION_OUTGOING . " OR va.id = vc.calleevoipaccountid AND vc.direction = " . BILLING_RECORD_DIRECTION_INCOMING . " + JOIN voip_numbers vn ON vn.voip_account_id = va.id + AND ( + ( + vn.voip_account_id = vc.callervoipaccountid + AND + vn.phone = vc.caller + AND + vc.direction = " . BILLING_RECORD_DIRECTION_OUTGOING . " + ) OR ( + vn.voip_account_id = vc.calleevoipaccountid + AND + vn.phone = vc.callee + AND + vc.direction = " . BILLING_RECORD_DIRECTION_INCOMING . " + ) + ) + JOIN voip_number_assignments vna ON vna.number_id = vn.id + JOIN assignments a2 ON a2.id = vna.assignment_id + JOIN tariffs t ON t.id = a2.tariffid AND t.type = ? + WHERE ( + ( + vc.call_start_time >= (CASE a2.period + WHEN " . YEARLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year-1) . ' + WHEN ' . HALFYEARLY . ' THEN ' . mktime(0, 0, 0, $month-6, 1, $year) . ' + WHEN ' . QUARTERLY . ' THEN ' . mktime(0, 0, 0, $month-3, 1, $year) . ' + WHEN ' . MONTHLY . ' THEN ' . mktime(0, 0, 0, $month-1, 1, $year) . ' + WHEN ' . DISPOSABLE . ' THEN ' . $currtime . " + END) + AND + vc.call_start_time < (CASE a2.period + WHEN " . YEARLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year) . ' + WHEN ' . HALFYEARLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year) . ' + WHEN ' . QUARTERLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year) . ' + WHEN ' . MONTHLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year) . ' + WHEN ' . DISPOSABLE . ' THEN ' . ($currtime + 86400) . " + END) + ) OR ( + vc.call_start_time + totaltime >= (CASE a2.period + WHEN " . YEARLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year-1) . ' + WHEN ' . HALFYEARLY . ' THEN ' . mktime(0, 0, 0, $month-6, 1, $year) . ' + WHEN ' . QUARTERLY . ' THEN ' . mktime(0, 0, 0, $month-3, 1, $year) . ' + WHEN ' . MONTHLY . ' THEN ' . mktime(0, 0, 0, $month-1, 1, $year) . ' + WHEN ' . DISPOSABLE . ' THEN ' . $currtime . " + END) + AND + vc.call_start_time + totaltime < (CASE a2.period + WHEN " . YEARLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year) . ' + WHEN ' . HALFYEARLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year) . ' + WHEN ' . QUARTERLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year) . ' + WHEN ' . MONTHLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year) . ' + WHEN ' . DISPOSABLE . ' THEN ' . ($currtime + 86400) . " + END) + ) + ) + GROUP BY va.ownerid, a2.id" . ($billing_invoice_separate_fractions ? ', vc.fraction' : '') . " +) voipcost ON voipcost.customerid = a.customerid AND voipcost.assignmentid = a.id +LEFT JOIN ( + SELECT vna2.assignment_id, " . $DB->GroupConcat('vn2.phone', ', ') . " AS phones + FROM voip_number_assignments vna2 + LEFT JOIN voip_numbers vn2 ON vn2.id = vna2.number_id + GROUP BY vna2.assignment_id +) voipphones ON voipphones.assignment_id = a.id +LEFT JOIN divisions d ON (d.id = c.divisionid) +WHERE " + . ($customerid ? 'c.id = ' . $customerid : '1 = 1') + . $customer_status_condition + . ($divisionid ? ' AND c.divisionid = ' . $divisionid : '') + . " AND t.type = ? AND + a.commited = 1 AND + ((a.period = ? AND at = ?) OR + ((a.period = ? OR + (a.period = ? AND at = ?) OR + (a.period = ? AND at IN ?) OR + (a.period = ? AND at = ?) OR + (a.period = ? AND at = ?) OR + (a.period = ? AND at = ?)) AND + a.datefrom <= ? AND + (a.dateto = 0 OR a.dateto > (CASE a.period + WHEN " . YEARLY . ' THEN ' . mktime(0, 0, 0, $month, 1, $year - 1) . " + WHEN " . HALFYEARLY . ' THEN ' . mktime(0, 0, 0, $month - 6, 1, $year) . " + WHEN " . QUARTERLY . ' THEN ' . mktime(0, 0, 0, $month - 3, 1, $year) . " + WHEN " . MONTHLY . ' THEN ' . mktime(0, 0, 0, $month - 1, 1, $year) + . " END))))" + . ($customergroups ? str_replace('%customerid_alias%', 'c.id', $customergroups) : '') + . ($tariff_tags ?: '') +." ORDER BY a.customerid, a.recipient_address_id, a.invoice, a.paytime, c.paytime, d.inv_paytime, +a.paytype, c.paytype, d.inv_paytype, a.numberplanid, a.separatedocument, a.separateitem, currency, netflag, voipcost.value DESC, a.id"; $billings = $DB->GetAll( $query, array( + 1, CTYPES_PRIVATE, TARIFF_FLAG_SPLIT_PAYMENT, TARIFF_FLAG_NET_ACCOUNT, - 1, array(CCONSENT_FULL_PHONE_BILLING, CCONSENT_SIMPLIFIED_PHONE_BILLING), SERVICE_PHONE, SERVICE_PHONE, @@ -771,18 +852,15 @@ function get_period($period) JOIN nodes n ON n.id = na.nodeid JOIN assignments a ON a.id = na.assignmentid LEFT JOIN netdevices nd ON nd.id = n.netdev + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) WHERE nd.ownerid IS NOT NULL AND ((n.ownerid IS NULL AND n.netdev IS NOT NULL) OR n.ownerid IS NOT NULL) - AND a.suspended = 0 + AND vas.suspended IS NULL AND a.period IN (" . implode(',', array(YEARLY, HALFYEARLY, QUARTERLY, MONTHLY, DISPOSABLE)) . ") AND a.datefrom < ?NOW? AND (a.dateto = 0 OR a.dateto > ?NOW?) - AND NOT EXISTS ( - SELECT id FROM assignments aa - WHERE aa.customerid = (CASE WHEN n.ownerid IS NULL THEN nd.ownerid ELSE n.ownerid END) - AND aa.tariffid IS NULL AND aa.liabilityid IS NULL - AND aa.datefrom < ?NOW? - AND (aa.dateto > ?NOW? OR aa.dateto = 0) - ) GROUP BY na.nodeid", 'nodeid'); if (empty($node_assignments)) { $node_assignments = array(); @@ -880,17 +958,15 @@ function find_nodes_for_netdev($netlink, &$customer_nodes, &$customer_netlinks, AND EXISTS ( SELECT na.id FROM nodeassignments na JOIN assignments a ON a.id = na.assignmentid - WHERE na.nodeid = n.id AND a.suspended = 0 + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) + WHERE na.nodeid = n.id + AND vas.suspended IS NULL AND a.period IN (" . implode(',', array(YEARLY, HALFYEARLY, QUARTERLY, MONTHLY, DISPOSABLE)) . ") AND a.datefrom < ?NOW? AND (a.dateto = 0 OR a.dateto > ?NOW?) ) - AND NOT EXISTS ( - SELECT id FROM assignments aa - WHERE aa.customerid = (CASE WHEN n.ownerid IS NULL THEN nd.ownerid ELSE n.ownerid END) - AND aa.tariffid IS NULL AND aa.liabilityid IS NULL - AND aa.datefrom < ?NOW? - AND (aa.dateto > ?NOW? OR aa.dateto = 0) - ) GROUP BY customerid_netdev", 'customerid_netdev' ); @@ -1067,29 +1143,12 @@ function find_nodes_for_netdev($netlink, &$customer_nodes, &$customer_netlinks, } if (!empty($assigns)) { - // determine currency values for assignments with foreign currency - // if payments.prefer_netto = true, use value netto+tax - // if assignment based on tariff with price variants get price by quantity - foreach ($assigns as &$assign) { - if (!empty($assign['tariffid'])) { - $priceVariant = $LMS->getTariffPriceVariantByQuantityThreshold($assign['tariffid'], $assign['count']); - if (!empty($priceVariant)) { - $suspension = empty($assign['suspended']) && empty($assign['allsuspended']) ? 1 : ($suspension_percentage / 100); - if (!empty($assign['netflag'])) { - $assign['price'] = round(((((100 - $assign['pdiscount']) * $priceVariant['net_price']) / 100) - $assign['vdiscount']) * $suspension, 3); - $assign['netvalue'] = round($assign['price'] * $assign['count'], 2); - } else { - $assign['price'] = round(((((100 - $assign['pdiscount']) * $priceVariant['gross_price']) / 100) - $assign['vdiscount']) * $suspension, 3); - $assign['value'] = round($assign['price'] * $assign['count'], 2); - } - } - } - if ($prefer_netto) { - if (!empty($assign['netvalue'])) { - $assign['value'] = round($assign['netvalue'] * (100 + $taxeslist[$assign['taxid']]['value']) / 100, 2); - } - } + $suspensionsByCurrency = array(); + $suspensionsById = array(); + $suspendedAssignemnts = array(); + foreach ($assigns as &$assign) { + // determine currency values for assignments with foreign currency $currency = $assign['currency']; if (empty($currency)) { $assign['currency'] = Localisation::getCurrentCurrency(); @@ -1103,10 +1162,428 @@ function find_nodes_for_netdev($netlink, &$customer_nodes, &$customer_netlinks, } } } + + if ($assign['liabilityid'] != 'set') { + if ($assign['t_period'] && $assign['period'] != DISPOSABLE + && $assign['t_period'] != $assign['period']) { + if ($assign['t_period'] == YEARLY) { + $assign['price'] = $assign['price'] / 12.0; + } elseif ($assign['t_period'] == HALFYEARLY) { + $assign['price'] = $assign['price'] / 6.0; + } elseif ($assign['t_period'] == QUARTERLY) { + $assign['price'] = $assign['price'] / 3.0; + } + + if ($assign['period'] == YEARLY) { + $assign['price'] = $assign['price'] * 12.0; + } elseif ($assign['period'] == HALFYEARLY) { + $assign['price'] = $assign['price'] * 6.0; + } elseif ($assign['period'] == QUARTERLY) { + $assign['price'] = $assign['price'] * 3.0; + } elseif ($assign['period'] == WEEKLY) { + $assign['price'] = $assign['price'] / 4.0; + } elseif ($assign['period'] == DAILY) { + $assign['price'] = $assign['price'] / 30.0; + } + } + + if (!empty($assign['netflag'])) { + $assign['net_price'] = $assign['price']; // calcualted variant and discount in main sql already + + $assign['net_value'] = f_round($assign['net_price'] * $assign['count']); + $assign['gross_price'] = f_round($assign['net_price'] * ($assign['taxrate'] / 100 + 1), 3); + $assign['tax_value'] = f_round($assign['net_value'] * ($assign['taxrate'] / 100)); + $assign['gross_value'] = f_round($assign['net_value'] + $assign['tax_value']); + } else { + $assign['gross_price'] = $assign['price']; // price is discounted in sql already + + $assign['gross_value'] = f_round($assign['gross_price'] * $assign['count']); + $assign['net_price'] = f_round($assign['gross_price'] / ($assign['taxrate'] / 100 + 1), 3); + $assign['tax_value'] = f_round(($assign['gross_value'] * $assign['taxrate']) / (100 + $assign['taxrate'])); + $assign['net_value'] = f_round(($assign['gross_value'] - $assign['tax_value'])); + } + + if (!empty($assign['suspended'])) { + if (!empty($assign['charge_suspension'])) { + if ($assign['suspension_charge_method'] != SUSPENSION_CHARGE_METHOD_NONE) { + switch ($assign['suspension_calculation_method']) { + case SUSPENSION_CALCULATION_METHOD_PERCENTAGE: + if (!isset($suspensionsByCurrency[$assign['currency']][$assign['taxid']][$assign['suspension_id']])) { + $suspensionDatefrom = !empty($assign['suspension_datefrom']) ? (' '. trans('From:') .date('Y-m-d', $assign['suspension_datefrom'])) : ''; + $suspensionDateto = !empty($assign['suspension_dateto']) ? (' '. trans('To:') . date('Y-m-d', $assign['suspension_dateto'])) : ''; + $suspensionCommon = array( + 'tariffid' => null, + 'liabilityid' => null, + 'count' => 1, + 'invoice' => DOC_INVOICE, + 'a_paytype' => null, + 'paytype' => null, + 'd_paytype' => null, + 'a_paytime' => null, + 'paytime' => '-1', + 'd_paytime' => null, + 'numberplanid' => null, + 'tariffnumberplanid' => null, + 'settlement' => '0', + 'splitpayment' => '0', + 'separatedocument' => '0', + 'separateitem' => '1', + 'backwardperiod' => '0', + 'taxcategory' => '0', + 'prodid' => '', + 'tarifftype' => '-1', + 'suspended' => '0', + 'period' => $assign['suspension_charge_method'] == SUSPENSION_CHARGE_METHOD_PERIODICALLY ? MONTHLY : DISPOSABLE, + 'name' => trans("Suspension") . $suspensionDatefrom . $suspensionDateto, + 'total_net_value' => 0, + 'total_gross_value' => 0, + 'datefrom' => $assign['suspension_datefrom'], + 'dateto' => $assign['suspension_dateto'], + 'pdiscount' => 0, + 'vdiscount' => 0, + ); + $suspensionsByCurrency[$assign['currency']][$assign['taxid']][$assign['suspension_id']] = array_merge($assign, $suspensionCommon); + } + if (!isset($suspensionsById[$assign['suspension_id']])) { + $suspensionsById[$assign['suspension_id']]['suspension_id'] = $assign['suspension_id']; + } + + $suspension = $suspensionsByCurrency[$assign['currency']][$assign['taxid']][$assign['suspension_id']]; + + $suspension['suspend_assignments'][$assign['id']]['assignment_id'] = $assign['id']; + $suspension['suspend_assignments'][$assign['id']]['assignment_name'] = $assign['name']; + + $suspensionPercentage = !is_null($assign['suspension_percentage']) ? f_round($assign['suspension_percentage']) : $defaultSuspensionPercentage; + if (!empty($assign['netflag'])) { + $suspension['net_price'] = f_round($assign['net_price'] * ($suspensionPercentage / 100), 3); + if ($assign['suspension_charge_method'] == SUSPENSION_CHARGE_METHOD_PERIODICALLY) { + if ($assign['period'] == YEARLY) { + $suspension['net_price'] = $suspension['net_price'] / 12; + } elseif ($assign['period'] == HALFYEARLY) { + $suspension['net_price'] = $suspension['net_price'] / 6; + } elseif ($assign['period'] == QUARTERLY) { + $suspension['net_price'] = $suspension['net_price'] / 3; + } elseif ($assign['period'] == WEEKLY) { + $suspension['net_price'] = $suspension['net_price'] * 4; + } elseif ($assign['period'] == DAILY) { + $suspension['net_price'] = $suspension['net_price'] * 30; + } + } + $suspension['net_value'] = f_round($suspension['net_price'] * $assign['count']); + $suspension['gross_price'] = f_round($suspension['net_price'] * ($assign['taxrate'] / 100 + 1), 3); + $suspension['tax_value'] = f_round($suspension['net_value'] * ($assign['taxrate'] / 100)); + $suspension['gross_value'] = f_round($suspension['net_value'] + $suspension['tax_value']); + } else { + $suspension['gross_price'] = f_round($assign['gross_price'] * ($suspensionPercentage / 100), 3); + if ($assign['suspension_charge_method'] == SUSPENSION_CHARGE_METHOD_PERIODICALLY) { + if ($assign['period'] == YEARLY) { + $suspension['gross_price'] = $suspension['gross_price'] / 12; + } elseif ($assign['period'] == HALFYEARLY) { + $suspension['gross_price'] = $suspension['gross_price'] / 6; + } elseif ($assign['period'] == QUARTERLY) { + $suspension['gross_price'] = $suspension['gross_price'] / 3; + } elseif ($assign['period'] == WEEKLY) { + $suspension['gross_price'] = $suspension['gross_price'] * 4; + } elseif ($assign['period'] == DAILY) { + $suspension['gross_price'] = $suspension['gross_price'] * 30; + } + } + $suspension['gross_value'] = f_round($suspension['gross_price'] * $assign['count']); + $suspension['net_price'] = f_round($suspension['gross_price'] / ($assign['taxrate'] / 100 + 1), 3); + $suspension['tax_value'] = f_round(($suspension['gross_value'] * $assign['taxrate']) / (100 + $assign['taxrate'])); + $suspension['net_value'] = f_round(($suspension['gross_value'] - $suspension['tax_value'])); + } + + $suspension['total_net_value'] += $suspension['net_value']; + $suspension['total_gross_value'] += $suspension['gross_value']; + + $suspensionsByCurrency[$assign['currency']][$assign['taxid']][$assign['suspension_id']] = $suspension; + break; + case SUSPENSION_CALCULATION_METHOD_VALUE: + // account only once for all assignemnts having this suspension + if (!isset($suspensionsByCurrency[$assign['suspension_currency']][$assign['suspension_tax_id']][$assign['suspension_id']]) + && !isset($suspensionsById[$assign['suspension_id']])) { + $suspensionDatefrom = !empty($assign['suspension_datefrom']) ? (' '. trans('From:') .date('Y-m-d', $assign['suspension_datefrom'])) : ''; + $suspensionDateto = !empty($assign['suspension_dateto']) ? (' '. trans('To:') . date('Y-m-d', $assign['suspension_dateto'])) : ''; + $suspensionCommon = array( + 'tariffid' => null, + 'liabilityid' => null, + 'count' => 1, + 'invoice' => DOC_INVOICE, + 'a_paytype' => null, + 'paytype' => null, + 'd_paytype' => null, + 'a_paytime' => null, + 'paytime' => '-1', + 'd_paytime' => null, + 'numberplanid' => null, + 'tariffnumberplanid' => null, + 'settlement' => '0', + 'splitpayment' => '0', + 'separatedocument' => '0', + 'separateitem' => '1', + 'backwardperiod' => '0', + 'taxcategory' => '0', + 'prodid' => '', + 'tarifftype' => '-1', + 'suspended' => '0', + 'period' => $assign['suspension_charge_method'] == SUSPENSION_CHARGE_METHOD_PERIODICALLY ? MONTHLY : DISPOSABLE, + 'name' => trans("Suspension") . $suspensionDatefrom . $suspensionDateto, + 'total_net_value' => 0, + 'total_gross_value' => 0, + 'value' => !is_null($assign['suspension_value']) ? $assign['suspension_value'] : $defaultSuspensionValue, + 'netflag' => $assign['suspension_netflag'], + 'taxid' => $assign['suspension_tax_id'], + 'taxlabel' => $assign['suspension_taxlabel'], + 'taxrate' => $assign['suspension_taxrate'], + 'currency' => $assign['suspension_currency'], + 'datefrom' => $assign['suspension_datefrom'], + 'dateto' => $assign['suspension_dateto'], + 'pdiscount' => 0, + 'vdiscount' => 0, + + ); + $suspensionsByCurrency[$assign['suspension_currency']][$assign['suspension_tax_id']][$assign['suspension_id']] = array_merge($assign, $suspensionCommon); + $suspensionsById[$assign['suspension_id']]['suspension_id'] = $assign['suspension_id']; + + $suspension = $suspensionsByCurrency[$assign['suspension_currency']][$assign['suspension_tax_id']][$assign['suspension_id']]; + $suspension['suspend_assignments'][$assign['id']]['assignment_id'] = $assign['id']; + $suspension['suspend_assignments'][$assign['id']]['assignment_name'] = $assign['name']; + + if (!empty($assign['suspension_netflag'])) { + $suspension['net_value'] = f_round($suspension['value']); + if ($assign['suspension_charge_method'] == SUSPENSION_CHARGE_METHOD_PERIODICALLY) { + if ($assign['period'] == YEARLY) { + $suspension['net_value'] = $suspension['net_value'] / 12; + } elseif ($assign['period'] == HALFYEARLY) { + $suspension['net_value'] = $suspension['net_value'] / 6; + } elseif ($assign['period'] == QUARTERLY) { + $suspension['net_value'] = $suspension['net_value'] / 3; + } elseif ($assign['period'] == WEEKLY) { + $suspension['net_value'] = $suspension['net_value'] * 4; + } elseif ($assign['period'] == DAILY) { + $suspension['net_value'] = $suspension['net_value'] * 30; + } + } + $suspension['tax_value'] = f_round($suspension['net_value'] * ($assign['suspension_taxrate'] / 100)); + $suspension['gross_value'] = f_round($suspension['net_value'] + $suspension['tax_value']); + } else { + $suspension['gross_value'] = f_round($suspension['value']); + if ($assign['suspension_charge_method'] == SUSPENSION_CHARGE_METHOD_PERIODICALLY) { + if ($assign['period'] == YEARLY) { + $suspension['gross_value'] = $suspension['gross_value'] / 12; + } elseif ($assign['period'] == HALFYEARLY) { + $suspension['gross_value'] = $suspension['gross_value'] / 6; + } elseif ($assign['period'] == QUARTERLY) { + $suspension['gross_value'] = $suspension['gross_value'] / 3; + } elseif ($assign['period'] == WEEKLY) { + $suspension['gross_value'] = $suspension['gross_value'] * 4; + } elseif ($assign['period'] == DAILY) { + $suspension['gross_value'] = $suspension['gross_value'] * 30; + } + } + $suspension['tax_value'] = f_round(($suspension['gross_value'] * $assign['suspension_taxrate']) / (100 + $assign['suspension_taxrate'])); + $suspension['net_value'] = f_round(($suspension['gross_value'] - $suspension['tax_value'])); + } + + $suspension['total_net_value'] = $suspension['net_value']; + $suspension['total_gross_value'] = $suspension['gross_value']; + $suspension['total_tax_value'] = $suspension['tax_value']; + + $suspensionsByCurrency[$assign['suspension_currency']][$assign['suspension_tax_id']][$assign['suspension_id']] = $suspension; + } + $suspensionsByCurrency[$assign['suspension_currency']][$assign['suspension_tax_id']][$assign['suspension_id']]['suspend_assignments'][$assign['id']]['assignment_id'] = $assign['id']; + $suspensionsByCurrency[$assign['suspension_currency']][$assign['suspension_tax_id']][$assign['suspension_id']]['suspend_assignments'][$assign['id']]['assignment_name'] = $assign['name']; + + break; + } + } else { + switch ($assign['suspension_calculation_method']) { + case SUSPENSION_CALCULATION_METHOD_PERCENTAGE: + if (!isset($suspensionsByCurrency[$assign['currency']][$assign['taxid']][$assign['suspension_id']])) { + $suspensionDatefrom = !empty($assign['suspension_datefrom']) ? (' '. trans('From:') .date('Y-m-d', $assign['suspension_datefrom'])) : ''; + $suspensionDateto = !empty($assign['suspension_dateto']) ? (' '. trans('To:') . date('Y-m-d', $assign['suspension_dateto'])) : ''; + $suspensionCommon = array( + 'tariffid' => null, + 'liabilityid' => null, + 'count' => 1, + 'invoice' => DOC_INVOICE, + 'a_paytype' => null, + 'paytype' => null, + 'd_paytype' => null, + 'a_paytime' => null, + 'paytime' => '-1', + 'd_paytime' => null, + 'numberplanid' => null, + 'tariffnumberplanid' => null, + 'settlement' => '0', + 'splitpayment' => '0', + 'separatedocument' => '0', + 'separateitem' => '1', + 'backwardperiod' => '0', + 'taxcategory' => '0', + 'prodid' => '', + 'tarifftype' => '-1', + 'suspended' => '0', + 'period' => $assign['suspension_charge_method'] == SUSPENSION_CHARGE_METHOD_PERIODICALLY ? MONTHLY : DISPOSABLE, + 'name' => trans("Suspension") . $suspensionDatefrom . $suspensionDateto, + 'total_net_value' => 0, + 'total_gross_value' => 0, + 'datefrom' => $assign['suspension_datefrom'], + 'dateto' => $assign['suspension_dateto'], + 'pdiscount' => 0, + 'vdiscount' => 0, + ); + $suspensionsByCurrency[$assign['currency']][$assign['taxid']][$assign['suspension_id']] = array_merge($assign, $suspensionCommon); + } + if (!isset($suspensionsById[$assign['suspension_id']])) { + $suspensionsById[$assign['suspension_id']]['suspension_id'] = $assign['suspension_id']; + } + + $suspension = $suspensionsByCurrency[$assign['currency']][$assign['taxid']][$assign['suspension_id']]; + $suspension['suspend_assignments'][$assign['id']]['assignment_id'] = $assign['id']; + $suspension['suspend_assignments'][$assign['id']]['assignment_name'] = $assign['name']; + + $suspension['net_price'] = 0; + $suspension['net_value'] = 0; + $suspension['gross_price'] = 0; + $suspension['tax_value'] = 0; + $suspension['gross_value'] = 0; + + $suspension['total_net_value'] = 0; + $suspension['total_tax_value'] = 0; + $suspension['total_gross_value'] = 0; + + $suspensionsByCurrency[$assign['currency']][$assign['taxid']][$assign['suspension_id']] = $suspension; + break; + case SUSPENSION_CALCULATION_METHOD_VALUE: + // account only once for all assignemnts having this suspension + if (!isset($suspensionsByCurrency[$assign['suspension_currency']][$assign['suspension_tax_id']][$assign['suspension_id']]) + && !isset($suspensionsById[$assign['suspension_id']])) { + $suspensionDatefrom = !empty($assign['suspension_datefrom']) ? (' '. trans('From:') .date('Y-m-d', $assign['suspension_datefrom'])) : ''; + $suspensionDateto = !empty($assign['suspension_dateto']) ? (' '. trans('To:') . date('Y-m-d', $assign['suspension_dateto'])) : ''; + $suspensionCommon = array( + 'tariffid' => null, + 'liabilityid' => null, + 'count' => 1, + 'invoice' => DOC_INVOICE, + 'a_paytype' => null, + 'paytype' => null, + 'd_paytype' => null, + 'a_paytime' => null, + 'paytime' => '-1', + 'd_paytime' => null, + 'numberplanid' => null, + 'tariffnumberplanid' => null, + 'settlement' => '0', + 'splitpayment' => '0', + 'separatedocument' => '0', + 'separateitem' => '1', + 'backwardperiod' => '0', + 'taxcategory' => '0', + 'prodid' => '', + 'tarifftype' => '-1', + 'suspended' => '0', + 'period' => $assign['suspension_charge_method'] == SUSPENSION_CHARGE_METHOD_PERIODICALLY ? MONTHLY : DISPOSABLE, + 'name' => trans("Suspension") . $suspensionDatefrom . $suspensionDateto, + 'total_net_value' => 0, + 'total_gross_value' => 0, + 'value' => !is_null($assign['suspension_value']) ? $assign['suspension_value'] : $defaultSuspensionValue, + 'netflag' => $assign['suspension_netflag'], + 'taxid' => $assign['suspension_tax_id'], + 'taxlabel' => $assign['suspension_taxlabel'], + 'taxrate' => $assign['suspension_taxrate'], + 'currency' => $assign['suspension_currency'], + 'datefrom' => $assign['suspension_datefrom'], + 'dateto' => $assign['suspension_dateto'], + 'pdiscount' => 0, + 'vdiscount' => 0, + + ); + $suspensionsByCurrency[$assign['suspension_currency']][$assign['suspension_tax_id']][$assign['suspension_id']] = array_merge($assign, $suspensionCommon); + $suspensionsById[$assign['suspension_id']]['suspension_id'] = $assign['suspension_id']; + + $suspension = $suspensionsByCurrency[$assign['suspension_currency']][$assign['suspension_tax_id']][$assign['suspension_id']]; + $suspension['suspend_assignments'][$assign['id']]['assignment_id'] = $assign['id']; + $suspension['suspend_assignments'][$assign['id']]['assignment_name'] = $assign['name']; + + $suspension['net_value'] = 0; + $suspension['tax_value'] = 0; + $suspension['gross_value'] = 0; + + $suspension['total_net_value'] = 0; + $suspension['total_gross_value'] = 0; + $suspension['total_tax_value'] = 0; + + $suspensionsByCurrency[$assign['suspension_currency']][$assign['suspension_tax_id']][$assign['suspension_id']] = $suspension; + } + + $suspensionsByCurrency[$assign['suspension_currency']][$assign['suspension_tax_id']][$assign['suspension_id']]['suspend_assignments'][$assign['id']]['assignment_id'] = $assign['id']; + $suspensionsByCurrency[$assign['suspension_currency']][$assign['suspension_tax_id']][$assign['suspension_id']]['suspend_assignments'][$assign['id']]['assignment_name'] = $assign['name']; + + break; + } + } + } + $suspendedAssignemnts[$assign['id']]['id'] = $assign['id']; + } + } else { + // if payments.prefer_netto = true, ignore assignment netflag and calculate billing gross price from net price + if (!empty($assign['netflag']) || $prefer_netto) { + $assign['net_price'] = $assign['price']; // variant and discount are calcualted in main sql already + + $assign['net_value'] = f_round($assign['net_price'] * $assign['count']); + $assign['gross_price'] = f_round($assign['net_price'] * ($assign['taxrate'] / 100 + 1), 3); + $assign['tax_value'] = f_round($assign['net_value'] * ($assign['taxrate'] / 100)); + $assign['gross_value'] = f_round($assign['net_value'] + $assign['tax_value']); + } else { + $assign['gross_price'] = $assign['price']; // price is discounted in sql already + + $assign['gross_value'] = f_round($assign['gross_price'] * $assign['count']); + $assign['net_price'] = f_round($assign['gross_price'] / ($assign['taxrate'] / 100 + 1), 3); + $assign['tax_value'] = f_round(($assign['gross_value'] * $assign['taxrate']) / (100 + $assign['taxrate'])); + $assign['net_value'] = f_round(($assign['gross_value'] - $assign['tax_value'])); + } + } + } + unset($assign, $suspension); +} + +//region get rid of suspended assignments and add suspension +if (!empty($suspendedAssignemnts)) { + foreach ($assigns as $idx => $assign) { + if ($assign['liabilityid'] != 'set' && isset($suspendedAssignemnts[$assign['id']])) { + unset($assigns[$idx]); + } } - unset($assign); + $assigns = array_values($assigns); } +if (!empty($suspensionsByCurrency)) { + $suspensions = array(); + foreach ($suspensionsByCurrency as $currency => $currencySuspensions) { + foreach ($currencySuspensions as $taxid => $currencyTaxesSuspensions) { + foreach ($currencyTaxesSuspensions as $sid => $currencyTaxSuspension) { + if ($currencyTaxSuspension['total_net_value'] != 0) { + $suspensions[$sid] = $currencyTaxSuspension; + $suspensions[$sid]['net_price'] = $currencyTaxSuspension['total_net_value']; + $suspensions[$sid]['gross_price'] = $currencyTaxSuspension['total_gross_value']; + $suspensions[$sid]['net_value'] = $currencyTaxSuspension['total_net_value']; + $suspensions[$sid]['gross_value'] = $currencyTaxSuspension['total_gross_value']; + $suspensions[$sid]['suspend_assignments'] = $currencyTaxSuspension['suspend_assignments']; + } + } + } + } + + $suspensions = array_values($suspensions); +} + +if (!empty($suspensions)) { + $assigns = array_merge($assigns, $suspensions); +} +//endregion + if (!empty($currencyvalues) && !$quiet) { print "Currency quotes:" . PHP_EOL; foreach ($currencyvalues as $currency => $value) { @@ -1429,16 +1906,13 @@ function GetBillingTemplates($document_dirs) $linktechnology = isset($assignment_linktechnologies[$assign['id']]) ? $assignment_linktechnologies[$assign['id']]['technology'] : null; - if (!empty($assign['suspended']) || !empty($assign['allsuspended'])) { - $assign['price'] = round($assign['price'] * $suspension_percentage / 100, 3); - $assign['value'] = round($assign['price'] * $assign['count'], 2); - } - if (empty($assign['value']) && ($assign['liabilityid'] != 'set' || !$empty_billings || !empty($assign['suspended']))) { - continue; - } - if ($assign['liabilityid'] && !$use_comment_for_liabilities) { $desc = $assign['name']; + } elseif (!empty($assign['suspend_assignments'])) { + foreach ($assign['suspend_assignments'] as $suspend_assignment) { + $suspendedAssignemntsNames[] = $suspend_assignment['assignment_name']; + } + $desc = $assign['name'] . ' ' . $suspension_description . ' (' . implode(',', $suspendedAssignemntsNames) . ')'; } else { if (empty($assign['backwardperiod'])) { $desc = $comment; @@ -1582,10 +2056,6 @@ function GetBillingTemplates($document_dirs) $desc = str_replace('%phones', $assign['phones'], $desc); } - if ($suspension_percentage && ($assign['suspended'] || $assign['allsuspended'])) { - $desc .= ' ' . $suspension_description; - } - if (!isset($invoices[$cid]) || $assign['separatedocument']) { $invoices[$cid] = 0; } @@ -1603,45 +2073,16 @@ function GetBillingTemplates($document_dirs) } if ($assign['price'] != 0 || $empty_billings && $assign['liabilityid'] == 'set') { - $price = $assign['price']; $currency = $assign['currency']; $netflag = intval($assign['netflag']); $splitpayment = $assign['splitpayment']; - if ($assign['t_period'] && $assign['period'] != DISPOSABLE - && $assign['t_period'] != $assign['period']) { - if ($assign['t_period'] == YEARLY) { - $price = $price / 12.0; - } elseif ($assign['t_period'] == HALFYEARLY) { - $price = $price / 6.0; - } elseif ($assign['t_period'] == QUARTERLY) { - $price = $price / 3.0; - } - - if ($assign['period'] == YEARLY) { - $price = $price * 12.0; - } elseif ($assign['period'] == HALFYEARLY) { - $price = $price * 6.0; - } elseif ($assign['period'] == QUARTERLY) { - $price = $price * 3.0; - } elseif ($assign['period'] == WEEKLY) { - $price = $price / 4.0; - } elseif ($assign['period'] == DAILY) { - $price = $price / 30.0; - } - } - - $price = round($price, 3); - $value = round($price * $assign['count'], 2); $telecom_service = $force_telecom_service_flag && $assign['tarifftype'] != SERVICE_OTHER && ($assign['customertype'] == CTYPES_PRIVATE || ($check_customer_vat_payer_flag_for_telecom_service && !($assign['customerflags'] & CUSTOMER_FLAG_VAT_PAYER))) && $issuetime < mktime(0, 0, 0, 7, 1, 2021); - if ($netflag) { - $grossvalue = $value + round($value * ($assign['taxrate'] / 100), 2); - } else { - $grossvalue = $value; - } + $price = $netflag ? $assign['net_price'] : $assign['gross_price']; + $grossvalue = $assign['gross_value']; if ($assign['invoice']) { if ($assign['a_paytype']) { diff --git a/css/style.css b/css/style.css index ccec4d008d..2f443c3c36 100644 --- a/css/style.css +++ b/css/style.css @@ -10,4 +10,4 @@ */@font-face{font-family:'Font Awesome 5 Brands';font-style:normal;font-weight:400;font-display:block;src:url(fontawesome/webfonts/fa-brands-400.eot);src:url(fontawesome/webfonts/fa-brands-400.eot?#iefix) format('embedded-opentype'),url(fontawesome/webfonts/fa-brands-400.woff2) format('woff2'),url(fontawesome/webfonts/fa-brands-400.woff) format('woff'),url(fontawesome/webfonts/fa-brands-400.ttf) format('truetype'),url(fontawesome/webfonts/fa-brands-400.svg#fontawesome) format('svg')}.fab{font-family:'Font Awesome 5 Brands';font-weight:400}/*! * Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) - */@font-face{font-family:'Font Awesome 5 Free';font-style:normal;font-weight:400;font-display:block;src:url(fontawesome/webfonts/fa-regular-400.eot);src:url(fontawesome/webfonts/fa-regular-400.eot?#iefix) format('embedded-opentype'),url(fontawesome/webfonts/fa-regular-400.woff2) format('woff2'),url(fontawesome/webfonts/fa-regular-400.woff) format('woff'),url(fontawesome/webfonts/fa-regular-400.ttf) format('truetype'),url(fontawesome/webfonts/fa-regular-400.svg#fontawesome) format('svg')}.far{font-family:'Font Awesome 5 Free';font-weight:400}.lms-ui-icon{line-height:unset;vertical-align:unset;font-size:130%}@media screen and (max-width:800px){.lms-ui-icon{font-size:125%}}.lms-ui-icon-fixed-width{width:1.5em;text-align:center}.lms-ui-icon-spacer{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-spacer.fa-pull-left{margin-right:.3em}.lms-ui-icon-spacer.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-spacer{font-size:125%}}.lms-ui-icon-spacer:before{content:"\f111";color:transparent}.lms-ui-icon-start-watch,.lms-ui-icon-watch,.lms-ui-icon-watch-start{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-start-watch.fa-pull-left,.lms-ui-icon-watch-start.fa-pull-left,.lms-ui-icon-watch.fa-pull-left{margin-right:.3em}.lms-ui-icon-start-watch.fa-pull-right,.lms-ui-icon-watch-start.fa-pull-right,.lms-ui-icon-watch.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-start-watch,.lms-ui-icon-watch,.lms-ui-icon-watch-start{font-size:125%}}.lms-ui-icon-start-watch:before,.lms-ui-icon-watch-start:before,.lms-ui-icon-watch:before{content:"\f06e"}.lms-ui-icon-stop-watch,.lms-ui-icon-unwatch,.lms-ui-icon-watch-stop{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-stop-watch.fa-pull-left,.lms-ui-icon-unwatch.fa-pull-left,.lms-ui-icon-watch-stop.fa-pull-left{margin-right:.3em}.lms-ui-icon-stop-watch.fa-pull-right,.lms-ui-icon-unwatch.fa-pull-right,.lms-ui-icon-watch-stop.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-stop-watch,.lms-ui-icon-unwatch,.lms-ui-icon-watch-stop{font-size:125%}}.lms-ui-icon-stop-watch:before,.lms-ui-icon-unwatch:before,.lms-ui-icon-watch-stop:before{content:"\f070"}.lms-ui-icon-tariff-limit{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-tariff-limit.fa-pull-left{margin-right:.3em}.lms-ui-icon-tariff-limit.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-tariff-limit{font-size:125%}}.lms-ui-icon-tariff-limit:before{content:"\f252"}.lms-ui-icon-map-pin{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-map-pin.fa-pull-left{margin-right:.3em}.lms-ui-icon-map-pin.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-map-pin{font-size:125%}}.lms-ui-icon-map-pin:before{content:"\f276"}.lms-ui-icon-customer-location{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%;color:red}.lms-ui-icon-customer-location.fa-pull-left{margin-right:.3em}.lms-ui-icon-customer-location.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-customer-location{font-size:125%}}.lms-ui-icon-customer-location:before{content:"\f276"}.lms-ui-icon-default-customer-location{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%;color:#00f}.lms-ui-icon-default-customer-location.fa-pull-left{margin-right:.3em}.lms-ui-icon-default-customer-location.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-default-customer-location{font-size:125%}}.lms-ui-icon-default-customer-location:before{content:"\f276"}.lms-ui-icon-memo,.lms-ui-icon-sticky-note{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-memo.fa-pull-left,.lms-ui-icon-sticky-note.fa-pull-left{margin-right:.3em}.lms-ui-icon-memo.fa-pull-right,.lms-ui-icon-sticky-note.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-memo,.lms-ui-icon-sticky-note{font-size:125%}}.lms-ui-icon-memo:before,.lms-ui-icon-sticky-note:before{content:"\f249"}.lms-ui-icon-quick-send{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-quick-send.fa-pull-left{margin-right:.3em}.lms-ui-icon-quick-send.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-quick-send{font-size:125%}}.lms-ui-icon-quick-send:before{content:"\f2f6"}.lms-ui-icon-nodesession,.lms-ui-icon-session{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%;-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";transform:rotate(90deg)}.lms-ui-icon-nodesession.fa-pull-left,.lms-ui-icon-session.fa-pull-left{margin-right:.3em}.lms-ui-icon-nodesession.fa-pull-right,.lms-ui-icon-session.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-nodesession,.lms-ui-icon-session{font-size:125%}}.lms-ui-icon-nodesession:before,.lms-ui-icon-session:before{content:"\f362"}.lms-ui-icon-change-format{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-change-format.fa-pull-left{margin-right:.3em}.lms-ui-icon-change-format.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-change-format{font-size:125%}}.lms-ui-icon-change-format:before{content:"\f362"}.lms-ui-icon-lock,.lms-ui-icon-nodelock{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-lock.fa-pull-left,.lms-ui-icon-nodelock.fa-pull-left{margin-right:.3em}.lms-ui-icon-lock.fa-pull-right,.lms-ui-icon-nodelock.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-lock,.lms-ui-icon-nodelock{font-size:125%}}.lms-ui-icon-lock:before,.lms-ui-icon-nodelock:before{content:"\f023"}.lms-ui-icon-convert,.lms-ui-icon-transform{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-convert.fa-pull-left,.lms-ui-icon-transform.fa-pull-left{margin-right:.3em}.lms-ui-icon-convert.fa-pull-right,.lms-ui-icon-transform.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-convert,.lms-ui-icon-transform{font-size:125%}}.lms-ui-icon-convert:before,.lms-ui-icon-transform:before{content:"\f362"}.lms-ui-icon-correct,.lms-ui-icon-correction{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-correct.fa-pull-left,.lms-ui-icon-correction.fa-pull-left{margin-right:.3em}.lms-ui-icon-correct.fa-pull-right,.lms-ui-icon-correction.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-correct,.lms-ui-icon-correction{font-size:125%}}.lms-ui-icon-correct:before,.lms-ui-icon-correction:before{content:"\f0ad"}.lms-ui-icon-cashsource,.lms-ui-icon-importsource,.lms-ui-icon-isource{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-cashsource.fa-pull-left,.lms-ui-icon-importsource.fa-pull-left,.lms-ui-icon-isource.fa-pull-left{margin-right:.3em}.lms-ui-icon-cashsource.fa-pull-right,.lms-ui-icon-importsource.fa-pull-right,.lms-ui-icon-isource.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-cashsource,.lms-ui-icon-importsource,.lms-ui-icon-isource{font-size:125%}}.lms-ui-icon-cashsource:before,.lms-ui-icon-importsource:before,.lms-ui-icon-isource:before{content:"\f570"}.lms-ui-icon-import{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-import.fa-pull-left{margin-right:.3em}.lms-ui-icon-import.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-import{font-size:125%}}.lms-ui-icon-import:before{content:"\f56f"}.lms-ui-icon-debitnote,.lms-ui-icon-dnote{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-debitnote.fa-pull-left,.lms-ui-icon-dnote.fa-pull-left{margin-right:.3em}.lms-ui-icon-debitnote.fa-pull-right,.lms-ui-icon-dnote.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-debitnote,.lms-ui-icon-dnote{font-size:125%}}.lms-ui-icon-debitnote:before,.lms-ui-icon-dnote:before{content:"\f571"}.lms-ui-icon-cash,.lms-ui-icon-money,.lms-ui-icon-paytype{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-cash.fa-pull-left,.lms-ui-icon-money.fa-pull-left,.lms-ui-icon-paytype.fa-pull-left{margin-right:.3em}.lms-ui-icon-cash.fa-pull-right,.lms-ui-icon-money.fa-pull-right,.lms-ui-icon-paytype.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-cash,.lms-ui-icon-money,.lms-ui-icon-paytype{font-size:125%}}.lms-ui-icon-cash:before,.lms-ui-icon-money:before,.lms-ui-icon-paytype:before{content:"\f0d6"}.lms-ui-icon-settle,.lms-ui-icon-value{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-settle.fa-pull-left,.lms-ui-icon-value.fa-pull-left{margin-right:.3em}.lms-ui-icon-settle.fa-pull-right,.lms-ui-icon-value.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-settle,.lms-ui-icon-value{font-size:125%}}.lms-ui-icon-settle:before,.lms-ui-icon-value:before{content:"\f51e"}.lms-ui-icon-signout{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-signout.fa-pull-left{margin-right:.3em}.lms-ui-icon-signout.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-signout{font-size:125%}}.lms-ui-icon-signout:before{content:"\f127"}.lms-ui-icon-hourglass,.lms-ui-icon-wait{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:400;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-hourglass.fa-pull-left,.lms-ui-icon-wait.fa-pull-left{margin-right:.3em}.lms-ui-icon-hourglass.fa-pull-right,.lms-ui-icon-wait.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-hourglass,.lms-ui-icon-wait{font-size:125%}}.lms-ui-icon-hourglass:before,.lms-ui-icon-wait:before{content:"\f254"}.lms-ui-icon-option,.lms-ui-icon-options{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-option.fa-pull-left,.lms-ui-icon-options.fa-pull-left{margin-right:.3em}.lms-ui-icon-option.fa-pull-right,.lms-ui-icon-options.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-option,.lms-ui-icon-options{font-size:125%}}.lms-ui-icon-option:before,.lms-ui-icon-options:before{content:"\f0ce"}.lms-ui-icon-consent,.lms-ui-icon-sign,.lms-ui-icon-signature{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-consent.fa-pull-left,.lms-ui-icon-sign.fa-pull-left,.lms-ui-icon-signature.fa-pull-left{margin-right:.3em}.lms-ui-icon-consent.fa-pull-right,.lms-ui-icon-sign.fa-pull-right,.lms-ui-icon-signature.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-consent,.lms-ui-icon-sign,.lms-ui-icon-signature{font-size:125%}}.lms-ui-icon-consent:before,.lms-ui-icon-sign:before,.lms-ui-icon-signature:before{content:"\f5b7"}.lms-ui-icon-assign,.lms-ui-icon-assignment{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-assign.fa-pull-left,.lms-ui-icon-assignment.fa-pull-left{margin-right:.3em}.lms-ui-icon-assign.fa-pull-right,.lms-ui-icon-assignment.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-assign,.lms-ui-icon-assignment{font-size:125%}}.lms-ui-icon-assign:before,.lms-ui-icon-assignment:before{content:"\f53d"}.lms-ui-icon-save,.lms-ui-icon-submit{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-save.fa-pull-left,.lms-ui-icon-submit.fa-pull-left{margin-right:.3em}.lms-ui-icon-save.fa-pull-right,.lms-ui-icon-submit.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-save,.lms-ui-icon-submit{font-size:125%}}.lms-ui-icon-save:before,.lms-ui-icon-submit:before{content:"\f0c7"}.lms-ui-icon-cancel{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-cancel.fa-pull-left{margin-right:.3em}.lms-ui-icon-cancel.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-cancel{font-size:125%}}.lms-ui-icon-cancel:before{content:"\f55a"}.lms-ui-icon-location{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-location.fa-pull-left{margin-right:.3em}.lms-ui-icon-location.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-location{font-size:125%}}.lms-ui-icon-location:before{content:"\f3c5"}.lms-ui-icon-location-netstork{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-location-netstork.fa-pull-left{margin-right:.3em}.lms-ui-icon-location-netstork.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-location-netstork{font-size:125%}}.lms-ui-icon-location-netstork:before{content:"\f124"}.lms-ui-icon-location-geoportal{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-location-geoportal.fa-pull-left{margin-right:.3em}.lms-ui-icon-location-geoportal.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-location-geoportal{font-size:125%}}.lms-ui-icon-location-geoportal:before{content:"\f1b2"}.lms-ui-icon-location-sidusis{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-location-sidusis.fa-pull-left{margin-right:.3em}.lms-ui-icon-location-sidusis.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-location-sidusis{font-size:125%}}.lms-ui-icon-location-sidusis:before{content:"\f279"}.lms-ui-icon-search{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-search.fa-pull-left{margin-right:.3em}.lms-ui-icon-search.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-search{font-size:125%}}.lms-ui-icon-search:before{content:"\f002"}.lms-ui-icon-next{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-next.fa-pull-left{margin-right:.3em}.lms-ui-icon-next.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-next{font-size:125%}}.lms-ui-icon-next:before{content:"\f101"}.lms-ui-icon-fast-next{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-fast-next.fa-pull-left{margin-right:.3em}.lms-ui-icon-fast-next.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-fast-next{font-size:125%}}.lms-ui-icon-fast-next:before{content:"\f050"}.lms-ui-icon-previous{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-previous.fa-pull-left{margin-right:.3em}.lms-ui-icon-previous.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-previous{font-size:125%}}.lms-ui-icon-previous:before{content:"\f100"}.lms-ui-icon-fast-previous{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-fast-previous.fa-pull-left{margin-right:.3em}.lms-ui-icon-fast-previous.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-fast-previous{font-size:125%}}.lms-ui-icon-fast-previous:before{content:"\f049"}.lms-ui-icon-current-year{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-current-year.fa-pull-left{margin-right:.3em}.lms-ui-icon-current-year.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-current-year{font-size:125%}}.lms-ui-icon-current-year:before{content:"\f102"}.lms-ui-icon-clone,.lms-ui-icon-copy{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-clone.fa-pull-left,.lms-ui-icon-copy.fa-pull-left{margin-right:.3em}.lms-ui-icon-clone.fa-pull-right,.lms-ui-icon-copy.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-clone,.lms-ui-icon-copy{font-size:125%}}.lms-ui-icon-clone:before,.lms-ui-icon-copy:before{content:"\f0c5"}.lms-ui-icon-clean,.lms-ui-icon-clear{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-clean.fa-pull-left,.lms-ui-icon-clear.fa-pull-left{margin-right:.3em}.lms-ui-icon-clean.fa-pull-right,.lms-ui-icon-clear.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-clean,.lms-ui-icon-clear{font-size:125%}}.lms-ui-icon-clean:before,.lms-ui-icon-clear:before{content:"\f12d"}.lms-ui-icon-delete,.lms-ui-icon-remove,.lms-ui-icon-trash{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-delete.fa-pull-left,.lms-ui-icon-remove.fa-pull-left,.lms-ui-icon-trash.fa-pull-left{margin-right:.3em}.lms-ui-icon-delete.fa-pull-right,.lms-ui-icon-remove.fa-pull-right,.lms-ui-icon-trash.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-delete,.lms-ui-icon-remove,.lms-ui-icon-trash{font-size:125%}}.lms-ui-icon-delete:before,.lms-ui-icon-remove:before,.lms-ui-icon-trash:before{content:"\f1f8"}.lms-ui-icon-change,.lms-ui-icon-edit,.lms-ui-icon-modify{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-change.fa-pull-left,.lms-ui-icon-edit.fa-pull-left,.lms-ui-icon-modify.fa-pull-left{margin-right:.3em}.lms-ui-icon-change.fa-pull-right,.lms-ui-icon-edit.fa-pull-right,.lms-ui-icon-modify.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-change,.lms-ui-icon-edit,.lms-ui-icon-modify{font-size:125%}}.lms-ui-icon-change:before,.lms-ui-icon-edit:before,.lms-ui-icon-modify:before{content:"\f044"}.lms-ui-icon-attachment,.lms-ui-icon-fileupload{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-attachment.fa-pull-left,.lms-ui-icon-fileupload.fa-pull-left{margin-right:.3em}.lms-ui-icon-attachment.fa-pull-right,.lms-ui-icon-fileupload.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-attachment,.lms-ui-icon-fileupload{font-size:125%}}.lms-ui-icon-attachment:before,.lms-ui-icon-fileupload:before{content:"\f0c6"}.lms-ui-icon-download{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-download.fa-pull-left{margin-right:.3em}.lms-ui-icon-download.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-download{font-size:125%}}.lms-ui-icon-download:before{content:"\f019"}.lms-ui-icon-upload{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-upload.fa-pull-left{margin-right:.3em}.lms-ui-icon-upload.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-upload{font-size:125%}}.lms-ui-icon-upload:before{content:"\f093"}.lms-ui-icon-back,.lms-ui-icon-return{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-back.fa-pull-left,.lms-ui-icon-return.fa-pull-left{margin-right:.3em}.lms-ui-icon-back.fa-pull-right,.lms-ui-icon-return.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-back,.lms-ui-icon-return{font-size:125%}}.lms-ui-icon-back:before,.lms-ui-icon-return:before{content:"\f151"}.lms-ui-icon-expired{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-expired.fa-pull-left{margin-right:.3em}.lms-ui-icon-expired.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-expired{font-size:125%}}.lms-ui-icon-expired:before{content:"\f06a"}.lms-ui-icon-add,.lms-ui-icon-append,.lms-ui-icon-new{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-add.fa-pull-left,.lms-ui-icon-append.fa-pull-left,.lms-ui-icon-new.fa-pull-left{margin-right:.3em}.lms-ui-icon-add.fa-pull-right,.lms-ui-icon-append.fa-pull-right,.lms-ui-icon-new.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-add,.lms-ui-icon-append,.lms-ui-icon-new{font-size:125%}}.lms-ui-icon-add:before,.lms-ui-icon-append:before,.lms-ui-icon-new:before{content:"\f0fe"}.lms-ui-icon-print{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-print.fa-pull-left{margin-right:.3em}.lms-ui-icon-print.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-print{font-size:125%}}.lms-ui-icon-print:before{content:"\f02f"}.lms-ui-icon-descending{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-descending.fa-pull-left{margin-right:.3em}.lms-ui-icon-descending.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-descending{font-size:125%}}.lms-ui-icon-descending:before{content:"\f0dd"}.lms-ui-icon-sorting{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-sorting.fa-pull-left{margin-right:.3em}.lms-ui-icon-sorting.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-sorting{font-size:125%}}.lms-ui-icon-sorting:before{content:"\f0dc"}.lms-ui-icon-ascending{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-ascending.fa-pull-left{margin-right:.3em}.lms-ui-icon-ascending.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-ascending{font-size:125%}}.lms-ui-icon-ascending:before{content:"\f0de"}.lms-ui-icon-apply,.lms-ui-icon-confirm{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-apply.fa-pull-left,.lms-ui-icon-confirm.fa-pull-left{margin-right:.3em}.lms-ui-icon-apply.fa-pull-right,.lms-ui-icon-confirm.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-apply,.lms-ui-icon-confirm{font-size:125%}}.lms-ui-icon-apply:before,.lms-ui-icon-confirm:before{content:"\f560"}.lms-ui-icon-mail{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-mail.fa-pull-left{margin-right:.3em}.lms-ui-icon-mail.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-mail{font-size:125%}}.lms-ui-icon-mail:before{content:"\f1fa"}.lms-ui-icon-send{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-send.fa-pull-left{margin-right:.3em}.lms-ui-icon-send.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-send{font-size:125%}}.lms-ui-icon-send:before{content:"\f0e0"}.lms-ui-icon-call,.lms-ui-icon-phone{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-call.fa-pull-left,.lms-ui-icon-phone.fa-pull-left{margin-right:.3em}.lms-ui-icon-call.fa-pull-right,.lms-ui-icon-phone.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-call,.lms-ui-icon-phone{font-size:125%}}.lms-ui-icon-call:before,.lms-ui-icon-phone:before{content:"\f095"}.lms-ui-icon-phone-call{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-phone-call.fa-pull-left{margin-right:.3em}.lms-ui-icon-phone-call.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-phone-call{font-size:125%}}.lms-ui-icon-phone-call:before{content:"\f2a0"}.lms-ui-icon-mobile,.lms-ui-icon-sms{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-mobile.fa-pull-left,.lms-ui-icon-sms.fa-pull-left{margin-right:.3em}.lms-ui-icon-mobile.fa-pull-right,.lms-ui-icon-sms.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-mobile,.lms-ui-icon-sms{font-size:125%}}.lms-ui-icon-mobile:before,.lms-ui-icon-sms:before{content:"\f3cd"}.lms-ui-icon-web,.lms-ui-icon-www{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Brands';font-weight:400;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-web.fa-pull-left,.lms-ui-icon-www.fa-pull-left{margin-right:.3em}.lms-ui-icon-web.fa-pull-right,.lms-ui-icon-www.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-web,.lms-ui-icon-www{font-size:125%}}.lms-ui-icon-web:before,.lms-ui-icon-www:before{content:"\f268"}.lms-ui-icon-panel,.lms-ui-icon-userpanel{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-panel.fa-pull-left,.lms-ui-icon-userpanel.fa-pull-left{margin-right:.3em}.lms-ui-icon-panel.fa-pull-right,.lms-ui-icon-userpanel.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-panel,.lms-ui-icon-userpanel{font-size:125%}}.lms-ui-icon-panel:before,.lms-ui-icon-userpanel:before{content:"\f0c0"}.lms-ui-icon-clipboard,.lms-ui-icon-notes{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-clipboard.fa-pull-left,.lms-ui-icon-notes.fa-pull-left{margin-right:.3em}.lms-ui-icon-clipboard.fa-pull-right,.lms-ui-icon-notes.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-clipboard,.lms-ui-icon-notes{font-size:125%}}.lms-ui-icon-clipboard:before,.lms-ui-icon-notes:before{content:"\f0ea"}.lms-ui-icon-view{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-view.fa-pull-left{margin-right:.3em}.lms-ui-icon-view.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-view{font-size:125%}}.lms-ui-icon-view:before{content:"\f06e"}.lms-ui-icon-view.pdf:before{content:"\f1c1"}.lms-ui-icon-view.xls:before{content:"\f1c3"}.lms-ui-icon-details,.lms-ui-icon-info{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-details.fa-pull-left,.lms-ui-icon-info.fa-pull-left{margin-right:.3em}.lms-ui-icon-details.fa-pull-right,.lms-ui-icon-info.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-details,.lms-ui-icon-info{font-size:125%}}.lms-ui-icon-details:before,.lms-ui-icon-info:before{content:"\f129"}.lms-ui-icon-help,.lms-ui-icon-hint{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:400;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-help.fa-pull-left,.lms-ui-icon-hint.fa-pull-left{margin-right:.3em}.lms-ui-icon-help.fa-pull-right,.lms-ui-icon-hint.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-help,.lms-ui-icon-hint{font-size:125%}}.lms-ui-icon-help:before,.lms-ui-icon-hint:before{content:"\f059"}.lms-ui-icon-open{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-open.fa-pull-left{margin-right:.3em}.lms-ui-icon-open.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-open{font-size:125%}}.lms-ui-icon-open:before{content:"\f518"}.lms-ui-icon-close{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-close.fa-pull-left{margin-right:.3em}.lms-ui-icon-close.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-close{font-size:125%}}.lms-ui-icon-close:before{content:"\f02d"}.lms-ui-icon-unread{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-unread.fa-pull-left{margin-right:.3em}.lms-ui-icon-unread.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-unread{font-size:125%}}.lms-ui-icon-unread:before{content:"\f02d";color:#4169e1}.lms-ui-icon-read{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-read.fa-pull-left{margin-right:.3em}.lms-ui-icon-read.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-read{font-size:125%}}.lms-ui-icon-read:before{content:"\f518"}.lms-ui-icon-urgent{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-urgent.fa-pull-left{margin-right:.3em}.lms-ui-icon-urgent.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-urgent{font-size:125%}}.lms-ui-icon-urgent:before{content:"\f0f3";color:#ff8c00}.lms-ui-icon-critical{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-critical.fa-pull-left{margin-right:.3em}.lms-ui-icon-critical.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-critical{font-size:125%}}.lms-ui-icon-critical:before{content:"\f0f3";color:red}.lms-ui-icon-ng,.lms-ui-icon-ngroup,.lms-ui-icon-nodegroup{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-ng.fa-pull-left,.lms-ui-icon-ngroup.fa-pull-left,.lms-ui-icon-nodegroup.fa-pull-left{margin-right:.3em}.lms-ui-icon-ng.fa-pull-right,.lms-ui-icon-ngroup.fa-pull-right,.lms-ui-icon-nodegroup.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-ng,.lms-ui-icon-ngroup,.lms-ui-icon-nodegroup{font-size:125%}}.lms-ui-icon-ng:before,.lms-ui-icon-ngroup:before,.lms-ui-icon-nodegroup:before{content:"\f5fd"}.lms-ui-icon-cg,.lms-ui-icon-cgroup,.lms-ui-icon-customergroup{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-cg.fa-pull-left,.lms-ui-icon-cgroup.fa-pull-left,.lms-ui-icon-customergroup.fa-pull-left{margin-right:.3em}.lms-ui-icon-cg.fa-pull-right,.lms-ui-icon-cgroup.fa-pull-right,.lms-ui-icon-customergroup.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-cg,.lms-ui-icon-cgroup,.lms-ui-icon-customergroup{font-size:125%}}.lms-ui-icon-cg:before,.lms-ui-icon-cgroup:before,.lms-ui-icon-customergroup:before{content:"\f0c0"}.lms-ui-icon-tag,.lms-ui-icon-ug,.lms-ui-icon-ugroup,.lms-ui-icon-usergroup{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-tag.fa-pull-left,.lms-ui-icon-ug.fa-pull-left,.lms-ui-icon-ugroup.fa-pull-left,.lms-ui-icon-usergroup.fa-pull-left{margin-right:.3em}.lms-ui-icon-tag.fa-pull-right,.lms-ui-icon-ug.fa-pull-right,.lms-ui-icon-ugroup.fa-pull-right,.lms-ui-icon-usergroup.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-tag,.lms-ui-icon-ug,.lms-ui-icon-ugroup,.lms-ui-icon-usergroup{font-size:125%}}.lms-ui-icon-tag:before,.lms-ui-icon-ug:before,.lms-ui-icon-ugroup:before,.lms-ui-icon-usergroup:before{content:"\f507"}.lms-ui-icon-lock,.lms-ui-icon-suspend{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-lock.fa-pull-left,.lms-ui-icon-suspend.fa-pull-left{margin-right:.3em}.lms-ui-icon-lock.fa-pull-right,.lms-ui-icon-suspend.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-lock,.lms-ui-icon-suspend{font-size:125%}}.lms-ui-icon-lock:before,.lms-ui-icon-suspend:before{content:"\f023"}.lms-ui-icon-unlock{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-unlock.fa-pull-left{margin-right:.3em}.lms-ui-icon-unlock.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-unlock{font-size:125%}}.lms-ui-icon-unlock:before{content:"\f09c"}.lms-ui-icon-warn,.lms-ui-icon-warning,.lms-ui-icon-warnoff{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-warn.fa-pull-left,.lms-ui-icon-warning.fa-pull-left,.lms-ui-icon-warnoff.fa-pull-left{margin-right:.3em}.lms-ui-icon-warn.fa-pull-right,.lms-ui-icon-warning.fa-pull-right,.lms-ui-icon-warnoff.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-warn,.lms-ui-icon-warning,.lms-ui-icon-warnoff{font-size:125%}}.lms-ui-icon-warn:before,.lms-ui-icon-warning:before,.lms-ui-icon-warnoff:before{content:"\f071"}.lms-ui-icon-warnoff:before{color:#000!important}.lms-ui-icon-warnmix{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-warnmix.fa-pull-left{margin-right:.3em}.lms-ui-icon-warnmix.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-warnmix{font-size:125%}}.lms-ui-icon-warnmix:before{content:"\f071"}.lms-ui-icon-warnmix:before{color:#deb887!important;text-stroke-width:1px;text-stroke-color:#000;-webkit-text-stroke-width:1px;-webkit-text-stroke-color:#000}.lms-ui-icon-warnon{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-warnon.fa-pull-left{margin-right:.3em}.lms-ui-icon-warnon.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-warnon{font-size:125%}}.lms-ui-icon-warnon:before{content:"\f071"}.lms-ui-icon-warnon:before{color:gold!important;text-stroke-width:1px;text-stroke-color:#000;-webkit-text-stroke-width:1px;-webkit-text-stroke-color:#000}.lms-ui-icon-connect{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-connect.fa-pull-left{margin-right:.3em}.lms-ui-icon-connect.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-connect{font-size:125%}}.lms-ui-icon-connect:before{content:"\f205"}.lms-ui-icon-plug{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-plug.fa-pull-left{margin-right:.3em}.lms-ui-icon-plug.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-plug{font-size:125%}}.lms-ui-icon-plug:before{content:"\f1e6"}.lms-ui-icon-connected{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-connected.fa-pull-left{margin-right:.3em}.lms-ui-icon-connected.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-connected{font-size:125%}}.lms-ui-icon-connected:before{content:"\f205"}.lms-ui-icon-connected:before{color:gold!important;text-stroke-width:1px;text-stroke-color:#000;-webkit-text-stroke-width:1px;-webkit-text-stroke-color:#000}.lms-ui-icon-mixconnected{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-mixconnected.fa-pull-left{margin-right:.3em}.lms-ui-icon-mixconnected.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-mixconnected{font-size:125%}}.lms-ui-icon-mixconnected:before{content:"\f205"}.lms-ui-icon-mixconnected:before{color:#deb887!important;text-stroke-width:1px;text-stroke-color:#000;-webkit-text-stroke-width:1px;-webkit-text-stroke-color:#000}.lms-ui-icon-disconnected{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%;-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";transform:scale(-1,1)}.lms-ui-icon-disconnected.fa-pull-left{margin-right:.3em}.lms-ui-icon-disconnected.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-disconnected{font-size:125%}}.lms-ui-icon-disconnected:before{content:"\f205";color:#000!important}.lms-ui-icon-vlan{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-vlan.fa-pull-left{margin-right:.3em}.lms-ui-icon-vlan.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-vlan{font-size:125%}}.lms-ui-icon-vlan:before{content:"\f542"}.lms-ui-icon-id,.lms-ui-icon-serial,.lms-ui-icon-serialnumber,.lms-ui-icon-sn{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-id.fa-pull-left,.lms-ui-icon-serial.fa-pull-left,.lms-ui-icon-serialnumber.fa-pull-left,.lms-ui-icon-sn.fa-pull-left{margin-right:.3em}.lms-ui-icon-id.fa-pull-right,.lms-ui-icon-serial.fa-pull-right,.lms-ui-icon-serialnumber.fa-pull-right,.lms-ui-icon-sn.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-id,.lms-ui-icon-serial,.lms-ui-icon-serialnumber,.lms-ui-icon-sn{font-size:125%}}.lms-ui-icon-id:before,.lms-ui-icon-serial:before,.lms-ui-icon-serialnumber:before,.lms-ui-icon-sn:before{content:"\f0cb"}.lms-ui-icon-window-close{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-window-close.fa-pull-left{margin-right:.3em}.lms-ui-icon-window-close.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-window-close{font-size:125%}}.lms-ui-icon-window-close:before{content:"\f410"}.lms-ui-icon-node{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-node.fa-pull-left{margin-right:.3em}.lms-ui-icon-node.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-node{font-size:125%}}.lms-ui-icon-node:before{content:"\f108"}.lms-ui-icon-verifier{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-verifier.fa-pull-left{margin-right:.3em}.lms-ui-icon-verifier.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-verifier{font-size:125%}}.lms-ui-icon-verifier:before{content:"\f51c"}.lms-ui-icon-deadline{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-deadline.fa-pull-left{margin-right:.3em}.lms-ui-icon-deadline.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-deadline{font-size:125%}}.lms-ui-icon-deadline:before{content:"\f253"}.lms-ui-icon-actions{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-actions.fa-pull-left{margin-right:.3em}.lms-ui-icon-actions.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-actions{font-size:125%}}.lms-ui-icon-actions:before{content:"\f085"}.lms-ui-icon-time,.lms-ui-icon-uptime{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-time.fa-pull-left,.lms-ui-icon-uptime.fa-pull-left{margin-right:.3em}.lms-ui-icon-time.fa-pull-right,.lms-ui-icon-uptime.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-time,.lms-ui-icon-uptime{font-size:125%}}.lms-ui-icon-time:before,.lms-ui-icon-uptime:before{content:"\f017"}.lms-ui-icon-categories{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-categories.fa-pull-left{margin-right:.3em}.lms-ui-icon-categories.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-categories{font-size:125%}}.lms-ui-icon-categories:before{content:"\f14a"}.lms-ui-icon-check,.lms-ui-icon-checked{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-check.fa-pull-left,.lms-ui-icon-checked.fa-pull-left{margin-right:.3em}.lms-ui-icon-check.fa-pull-right,.lms-ui-icon-checked.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-check,.lms-ui-icon-checked{font-size:125%}}.lms-ui-icon-check:before,.lms-ui-icon-checked:before{content:"\f00c"}.lms-ui-icon-restore{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-restore.fa-pull-left{margin-right:.3em}.lms-ui-icon-restore.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-restore{font-size:125%}}.lms-ui-icon-restore:before{content:"\f2ea"}.lms-ui-icon-recover{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-recover.fa-pull-left{margin-right:.3em}.lms-ui-icon-recover.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-recover{font-size:125%}}.lms-ui-icon-recover:before{content:"\f829"}.lms-ui-icon-description{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-description.fa-pull-left{margin-right:.3em}.lms-ui-icon-description.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-description{font-size:125%}}.lms-ui-icon-description:before{content:"\f29e"}.lms-ui-icon-nodeoff{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-nodeoff.fa-pull-left{margin-right:.3em}.lms-ui-icon-nodeoff.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-nodeoff{font-size:125%}}.lms-ui-icon-nodeoff:before{content:"\f108"}.lms-ui-icon-nodeoff.fa-pull-left{margin-right:.3em}.lms-ui-icon-nodeoff.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-nodeoff{font-size:125%}}.lms-ui-icon-nodeoff:before{content:"\f108"}.lms-ui-icon-nodeon{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%;text-stroke-width:1px;text-stroke-color:#32cd32;-webkit-text-stroke-width:1px;-webkit-text-stroke-color:#32cd32}.lms-ui-icon-nodeon.fa-pull-left{margin-right:.3em}.lms-ui-icon-nodeon.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-nodeon{font-size:125%}}.lms-ui-icon-nodeon:before{content:"\f108"}.lms-ui-icon-nodeon.fa-pull-left{margin-right:.3em}.lms-ui-icon-nodeon.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-nodeon{font-size:125%}}.lms-ui-icon-nodeon:before{content:"\f108"}.lms-ui-icon-nodeunk{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%;text-stroke-width:1px;text-stroke-color:red;-webkit-text-stroke-width:1px;-webkit-text-stroke-color:red}.lms-ui-icon-nodeunk.fa-pull-left{margin-right:.3em}.lms-ui-icon-nodeunk.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-nodeunk{font-size:125%}}.lms-ui-icon-nodeunk:before{content:"\f108"}.lms-ui-icon-nodeunk.fa-pull-left{margin-right:.3em}.lms-ui-icon-nodeunk.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-nodeunk{font-size:125%}}.lms-ui-icon-nodeunk:before{content:"\f108"}.lms-ui-icon-device,.lms-ui-icon-netdevice{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-device.fa-pull-left,.lms-ui-icon-netdevice.fa-pull-left{margin-right:.3em}.lms-ui-icon-device.fa-pull-right,.lms-ui-icon-netdevice.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-device,.lms-ui-icon-netdevice{font-size:125%}}.lms-ui-icon-device:before,.lms-ui-icon-netdevice:before{content:"\f0a0"}.lms-ui-icon-netdev{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-netdev.fa-pull-left{margin-right:.3em}.lms-ui-icon-netdev.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-netdev{font-size:125%}}.lms-ui-icon-netdev:before{content:"\f0a0"}.lms-ui-icon-netdevoff{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-netdevoff.fa-pull-left{margin-right:.3em}.lms-ui-icon-netdevoff.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-netdevoff{font-size:125%}}.lms-ui-icon-netdevoff:before{content:"\f0a0"}.lms-ui-icon-netdevon{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%;text-stroke-width:1px;text-stroke-color:#32cd32;-webkit-text-stroke-width:1px;-webkit-text-stroke-color:#32cd32}.lms-ui-icon-netdevon.fa-pull-left{margin-right:.3em}.lms-ui-icon-netdevon.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-netdevon{font-size:125%}}.lms-ui-icon-netdevon:before{content:"\f0a0"}.lms-ui-icon-netdevunk{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%;text-stroke-width:1px;text-stroke-color:red;-webkit-text-stroke-width:1px;-webkit-text-stroke-color:red}.lms-ui-icon-netdevunk.fa-pull-left{margin-right:.3em}.lms-ui-icon-netdevunk.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-netdevunk{font-size:125%}}.lms-ui-icon-netdevunk:before{content:"\f0a0"}.lms-ui-icon-mailsent{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-mailsent.fa-pull-left{margin-right:.3em}.lms-ui-icon-mailsent.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-mailsent{font-size:125%}}.lms-ui-icon-mailsent:before{content:"\f1fa"}.lms-ui-icon-mailsent:before{color:#888!important}.lms-ui-icon-customer{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-customer.fa-pull-left{margin-right:.3em}.lms-ui-icon-customer.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-customer{font-size:125%}}.lms-ui-icon-customer:before{content:"\f007"}.lms-ui-icon-phone{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-phone.fa-pull-left{margin-right:.3em}.lms-ui-icon-phone.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-phone{font-size:125%}}.lms-ui-icon-phone:before{content:"\f095"}.lms-ui-icon-node{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-node.fa-pull-left{margin-right:.3em}.lms-ui-icon-node.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-node{font-size:125%}}.lms-ui-icon-node:before{content:"\f108"}.lms-ui-icon-ipnetwork,.lms-ui-icon-network,.lms-ui-icon-networks{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-ipnetwork.fa-pull-left,.lms-ui-icon-network.fa-pull-left,.lms-ui-icon-networks.fa-pull-left{margin-right:.3em}.lms-ui-icon-ipnetwork.fa-pull-right,.lms-ui-icon-network.fa-pull-right,.lms-ui-icon-networks.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-ipnetwork,.lms-ui-icon-network,.lms-ui-icon-networks{font-size:125%}}.lms-ui-icon-ipnetwork:before,.lms-ui-icon-network:before,.lms-ui-icon-networks:before{content:"\f0ac"}.lms-ui-icon-subject{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-subject.fa-pull-left{margin-right:.3em}.lms-ui-icon-subject.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-subject{font-size:125%}}.lms-ui-icon-subject:before{content:"\f64a"}.lms-ui-icon-user{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-user.fa-pull-left{margin-right:.3em}.lms-ui-icon-user.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-user{font-size:125%}}.lms-ui-icon-user:before{content:"\f007"}.lms-ui-icon-owner{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-owner.fa-pull-left{margin-right:.3em}.lms-ui-icon-owner.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-owner{font-size:125%}}.lms-ui-icon-owner:before{content:"\f2bd"}.lms-ui-icon-queue{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-queue.fa-pull-left{margin-right:.3em}.lms-ui-icon-queue.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-queue{font-size:125%}}.lms-ui-icon-queue:before{content:"\f0ae"}.lms-ui-icon-netnode{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-netnode.fa-pull-left{margin-right:.3em}.lms-ui-icon-netnode.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-netnode{font-size:125%}}.lms-ui-icon-netnode:before{content:"\f5fd"}.lms-ui-icon-service{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-service.fa-pull-left{margin-right:.3em}.lms-ui-icon-service.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-service{font-size:125%}}.lms-ui-icon-service:before{content:"\f013"}.lms-ui-icon-type{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-type.fa-pull-left{margin-right:.3em}.lms-ui-icon-type.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-type{font-size:125%}}.lms-ui-icon-type:before{content:"\f3ff"}.lms-ui-icon-event-type{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-event-type.fa-pull-left{margin-right:.3em}.lms-ui-icon-event-type.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-event-type{font-size:125%}}.lms-ui-icon-event-type:before{content:"\f133"}.lms-ui-icon-requestor{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-requestor.fa-pull-left{margin-right:.3em}.lms-ui-icon-requestor.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-requestor{font-size:125%}}.lms-ui-icon-requestor:before{content:"\f183"}.lms-ui-icon-helpdesk{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-helpdesk.fa-pull-left{margin-right:.3em}.lms-ui-icon-helpdesk.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-helpdesk{font-size:125%}}.lms-ui-icon-helpdesk:before{content:"\f0ae"}.lms-ui-icon-billing,.lms-ui-icon-calendar,.lms-ui-icon-timetable{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-billing.fa-pull-left,.lms-ui-icon-calendar.fa-pull-left,.lms-ui-icon-timetable.fa-pull-left{margin-right:.3em}.lms-ui-icon-billing.fa-pull-right,.lms-ui-icon-calendar.fa-pull-right,.lms-ui-icon-timetable.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-billing,.lms-ui-icon-calendar,.lms-ui-icon-timetable{font-size:125%}}.lms-ui-icon-billing:before,.lms-ui-icon-calendar:before,.lms-ui-icon-timetable:before{content:"\f073"}.lms-ui-icon-administration{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-administration.fa-pull-left{margin-right:.3em}.lms-ui-icon-administration.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-administration{font-size:125%}}.lms-ui-icon-administration:before{content:"\f54a"}.lms-ui-icon-dropdown2{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-dropdown2.fa-pull-left{margin-right:.3em}.lms-ui-icon-dropdown2.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-dropdown2{font-size:125%}}.lms-ui-icon-dropdown2:before{content:"\f141"}.lms-ui-icon-factory-reset,.lms-ui-icon-reload{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-factory-reset.fa-pull-left,.lms-ui-icon-reload.fa-pull-left{margin-right:.3em}.lms-ui-icon-factory-reset.fa-pull-right,.lms-ui-icon-reload.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-factory-reset,.lms-ui-icon-reload{font-size:125%}}.lms-ui-icon-factory-reset:before,.lms-ui-icon-reload:before{content:"\f2f1"}.lms-ui-icon-relatedticket{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-relatedticket.fa-pull-left{margin-right:.3em}.lms-ui-icon-relatedticket.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-relatedticket{font-size:125%}}.lms-ui-icon-relatedticket:before{content:"\f31e"}.lms-ui-icon-childticket{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-childticket.fa-pull-left{margin-right:.3em}.lms-ui-icon-childticket.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-childticket{font-size:125%}}.lms-ui-icon-childticket:before{content:"\f0ab"}.lms-ui-icon-net-to-gross{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-net-to-gross.fa-pull-left{margin-right:.3em}.lms-ui-icon-net-to-gross.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-net-to-gross{font-size:125%}}.lms-ui-icon-net-to-gross:before{color:gold;text-stroke-width:1px;text-stroke-color:#000;-webkit-text-stroke-width:1px;-webkit-text-stroke-color:#000;content:"\f35a"}.lms-ui-icon-gross-to-net{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-gross-to-net.fa-pull-left{margin-right:.3em}.lms-ui-icon-gross-to-net.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-gross-to-net{font-size:125%}}.lms-ui-icon-gross-to-net:before{content:"\f359"}.lms-ui-icon-parentticket{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-parentticket.fa-pull-left{margin-right:.3em}.lms-ui-icon-parentticket.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-parentticket{font-size:125%}}.lms-ui-icon-parentticket:before{content:"\f122"}.lms-ui-icon-source{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-source.fa-pull-left{margin-right:.3em}.lms-ui-icon-source.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-source{font-size:125%}}.lms-ui-icon-source:before{content:"\f00a"}.lms-ui-icon-priority{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-priority.fa-pull-left{margin-right:.3em}.lms-ui-icon-priority.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-priority{font-size:125%}}.lms-ui-icon-priority:before{content:"\f2cb"}.lms-ui-icon-cause{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-cause.fa-pull-left{margin-right:.3em}.lms-ui-icon-cause.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-cause{font-size:125%}}.lms-ui-icon-cause:before{content:"\f069"}.lms-ui-icon-logout{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-logout.fa-pull-left{margin-right:.3em}.lms-ui-icon-logout.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-logout{font-size:125%}}.lms-ui-icon-logout:before{content:"\f011"}.lms-ui-icon-login{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-login.fa-pull-left{margin-right:.3em}.lms-ui-icon-login.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-login{font-size:125%}}.lms-ui-icon-login:before{content:"\f2f6"}.lms-ui-icon-configuration{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-configuration.fa-pull-left{margin-right:.3em}.lms-ui-icon-configuration.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-configuration{font-size:125%}}.lms-ui-icon-configuration:before{content:"\f0ad"}.lms-ui-icon-archive,.lms-ui-icon-archiveview,.lms-ui-icon-history,.lms-ui-icon-log,.lms-ui-icon-logging,.lms-ui-icon-transaction,.lms-ui-icon-transactions{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-archive.fa-pull-left,.lms-ui-icon-archiveview.fa-pull-left,.lms-ui-icon-history.fa-pull-left,.lms-ui-icon-log.fa-pull-left,.lms-ui-icon-logging.fa-pull-left,.lms-ui-icon-transaction.fa-pull-left,.lms-ui-icon-transactions.fa-pull-left{margin-right:.3em}.lms-ui-icon-archive.fa-pull-right,.lms-ui-icon-archiveview.fa-pull-right,.lms-ui-icon-history.fa-pull-right,.lms-ui-icon-log.fa-pull-right,.lms-ui-icon-logging.fa-pull-right,.lms-ui-icon-transaction.fa-pull-right,.lms-ui-icon-transactions.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-archive,.lms-ui-icon-archiveview,.lms-ui-icon-history,.lms-ui-icon-log,.lms-ui-icon-logging,.lms-ui-icon-transaction,.lms-ui-icon-transactions{font-size:125%}}.lms-ui-icon-archive:before,.lms-ui-icon-archiveview:before,.lms-ui-icon-history:before,.lms-ui-icon-log:before,.lms-ui-icon-logging:before,.lms-ui-icon-transaction:before,.lms-ui-icon-transactions:before{content:"\f1da"}.lms-ui-icon-finances{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-finances.fa-pull-left{margin-right:.3em}.lms-ui-icon-finances.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-finances{font-size:125%}}.lms-ui-icon-finances:before{content:"\f0d6"}.lms-ui-icon-invproject{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-invproject.fa-pull-left{margin-right:.3em}.lms-ui-icon-invproject.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-invproject{font-size:125%}}.lms-ui-icon-invproject:before{content:"\f0d6"}.lms-ui-icon-status{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-status.fa-pull-left{margin-right:.3em}.lms-ui-icon-status.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-status{font-size:125%}}.lms-ui-icon-status:before{color:#6495ed;content:"\f02d"}.lms-ui-icon-status-resolved{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-status-resolved.fa-pull-left{margin-right:.3em}.lms-ui-icon-status-resolved.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-status-resolved{font-size:125%}}.lms-ui-icon-status-resolved:before{color:#696969;content:"\f02d"}.lms-ui-icon-wireless{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-wireless.fa-pull-left{margin-right:.3em}.lms-ui-icon-wireless.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-wireless{font-size:125%}}.lms-ui-icon-wireless:before{content:"\f1eb"}.lms-ui-icon-port,.lms-ui-icon-wired{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-port.fa-pull-left,.lms-ui-icon-wired.fa-pull-left{margin-right:.3em}.lms-ui-icon-port.fa-pull-right,.lms-ui-icon-wired.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-port,.lms-ui-icon-wired{font-size:125%}}.lms-ui-icon-port:before,.lms-ui-icon-wired:before{content:"\f796"}.lms-ui-icon-port-connected,.lms-ui-icon-port-taken{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-port-connected.fa-pull-left,.lms-ui-icon-port-taken.fa-pull-left{margin-right:.3em}.lms-ui-icon-port-connected.fa-pull-right,.lms-ui-icon-port-taken.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-port-connected,.lms-ui-icon-port-taken{font-size:125%}}.lms-ui-icon-port-connected:before,.lms-ui-icon-port-taken:before{content:"\f796"}.lms-ui-icon-port-connected:before,.lms-ui-icon-port-taken:before{color:gold!important;text-stroke-width:1px;text-stroke-color:#000;-webkit-text-stroke-width:1px;-webkit-text-stroke-color:#000}.lms-ui-icon-hosting,.lms-ui-icon-radius{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-hosting.fa-pull-left,.lms-ui-icon-radius.fa-pull-left{margin-right:.3em}.lms-ui-icon-hosting.fa-pull-right,.lms-ui-icon-radius.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-hosting,.lms-ui-icon-radius{font-size:125%}}.lms-ui-icon-hosting:before,.lms-ui-icon-radius:before{content:"\f233"}.lms-ui-icon-document{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-document.fa-pull-left{margin-right:.3em}.lms-ui-icon-document.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-document{font-size:125%}}.lms-ui-icon-document:before{content:"\f15c"}.lms-ui-icon-stats{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-stats.fa-pull-left{margin-right:.3em}.lms-ui-icon-stats.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-stats{font-size:125%}}.lms-ui-icon-stats:before{content:"\f201"}.lms-ui-icon-externalid{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-externalid.fa-pull-left{margin-right:.3em}.lms-ui-icon-externalid.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-externalid{font-size:125%}}.lms-ui-icon-externalid:before{content:"\f1c0"}.lms-ui-icon-external,.lms-ui-icon-popup{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-external.fa-pull-left,.lms-ui-icon-popup.fa-pull-left{margin-right:.3em}.lms-ui-icon-external.fa-pull-right,.lms-ui-icon-popup.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-external,.lms-ui-icon-popup{font-size:125%}}.lms-ui-icon-external:before,.lms-ui-icon-popup:before{content:"\f35d"}.lms-ui-icon-message{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-message.fa-pull-left{margin-right:.3em}.lms-ui-icon-message.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-message{font-size:125%}}.lms-ui-icon-message:before{content:"\f0e0"}.lms-ui-icon-note{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-note.fa-pull-left{margin-right:.3em}.lms-ui-icon-note.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-note{font-size:125%}}.lms-ui-icon-note:before{content:"\f304"}.lms-ui-icon-documentation{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-documentation.fa-pull-left{margin-right:.3em}.lms-ui-icon-documentation.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-documentation{font-size:125%}}.lms-ui-icon-documentation:before{content:"\f02d"}.lms-ui-icon-lastloggedin .lms-ui-icon-key,.lms-ui-icon-password,.lms-ui-icon-sensible,.lms-ui-icon-sensible-data{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-lastloggedin .lms-ui-icon-key.fa-pull-left,.lms-ui-icon-password.fa-pull-left,.lms-ui-icon-sensible-data.fa-pull-left,.lms-ui-icon-sensible.fa-pull-left{margin-right:.3em}.lms-ui-icon-lastloggedin .lms-ui-icon-key.fa-pull-right,.lms-ui-icon-password.fa-pull-right,.lms-ui-icon-sensible-data.fa-pull-right,.lms-ui-icon-sensible.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-lastloggedin .lms-ui-icon-key,.lms-ui-icon-password,.lms-ui-icon-sensible,.lms-ui-icon-sensible-data{font-size:125%}}.lms-ui-icon-lastloggedin .lms-ui-icon-key:before,.lms-ui-icon-password:before,.lms-ui-icon-sensible-data:before,.lms-ui-icon-sensible:before{content:"\f084"}.lms-ui-icon-reply,.lms-ui-icon-reply-all{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-reply-all.fa-pull-left,.lms-ui-icon-reply.fa-pull-left{margin-right:.3em}.lms-ui-icon-reply-all.fa-pull-right,.lms-ui-icon-reply.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-reply,.lms-ui-icon-reply-all{font-size:125%}}.lms-ui-icon-reply-all:before,.lms-ui-icon-reply:before{content:"\f122"}.lms-ui-icon-citing,.lms-ui-icon-quote{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-citing.fa-pull-left,.lms-ui-icon-quote.fa-pull-left{margin-right:.3em}.lms-ui-icon-citing.fa-pull-right,.lms-ui-icon-quote.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-citing,.lms-ui-icon-quote{font-size:125%}}.lms-ui-icon-citing:before,.lms-ui-icon-quote:before{content:"\f10e"}.lms-ui-icon-chat,.lms-ui-icon-comment,.lms-ui-icon-comments{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-chat.fa-pull-left,.lms-ui-icon-comment.fa-pull-left,.lms-ui-icon-comments.fa-pull-left{margin-right:.3em}.lms-ui-icon-chat.fa-pull-right,.lms-ui-icon-comment.fa-pull-right,.lms-ui-icon-comments.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-chat,.lms-ui-icon-comment,.lms-ui-icon-comments{font-size:125%}}.lms-ui-icon-chat:before,.lms-ui-icon-comment:before,.lms-ui-icon-comments:before{content:"\f086"}.lms-ui-icon-home{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-home.fa-pull-left{margin-right:.3em}.lms-ui-icon-home.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-home{font-size:125%}}.lms-ui-icon-home:before{content:"\f015"}.lms-ui-icon-link,.lms-ui-icon-url{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-link.fa-pull-left,.lms-ui-icon-url.fa-pull-left{margin-right:.3em}.lms-ui-icon-link.fa-pull-right,.lms-ui-icon-url.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-link,.lms-ui-icon-url{font-size:125%}}.lms-ui-icon-link:before,.lms-ui-icon-url:before{content:"\f0c1"}.lms-ui-icon-handshake,.lms-ui-icon-trust,.lms-ui-icon-warranty{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-handshake.fa-pull-left,.lms-ui-icon-trust.fa-pull-left,.lms-ui-icon-warranty.fa-pull-left{margin-right:.3em}.lms-ui-icon-handshake.fa-pull-right,.lms-ui-icon-trust.fa-pull-right,.lms-ui-icon-warranty.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-handshake,.lms-ui-icon-trust,.lms-ui-icon-warranty{font-size:125%}}.lms-ui-icon-handshake:before,.lms-ui-icon-trust:before,.lms-ui-icon-warranty:before{content:"\f2b5"}.lms-ui-icon-list{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-list.fa-pull-left{margin-right:.3em}.lms-ui-icon-list.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-list{font-size:125%}}.lms-ui-icon-list:before{content:"\f03a"}.lms-ui-icon-label,.lms-ui-icon-tags{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-label.fa-pull-left,.lms-ui-icon-tags.fa-pull-left{margin-right:.3em}.lms-ui-icon-label.fa-pull-right,.lms-ui-icon-tags.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-label,.lms-ui-icon-tags{font-size:125%}}.lms-ui-icon-label:before,.lms-ui-icon-tags:before{content:"\f02c"}.lms-ui-icon-fullscreen-on{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-fullscreen-on.fa-pull-left{margin-right:.3em}.lms-ui-icon-fullscreen-on.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-fullscreen-on{font-size:125%}}.lms-ui-icon-fullscreen-on:before{content:"\f0b2"}.lms-ui-icon-fullscreen-off{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-fullscreen-off.fa-pull-left{margin-right:.3em}.lms-ui-icon-fullscreen-off.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-fullscreen-off{font-size:125%}}.lms-ui-icon-fullscreen-off:before{content:"\f78c"}.lms-ui-icon-hide{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-hide.fa-pull-left{margin-right:.3em}.lms-ui-icon-hide.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-hide{font-size:125%}}.lms-ui-icon-hide:before{content:"\f00d"}.lms-ui-icon-gallery{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:400;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-gallery.fa-pull-left{margin-right:.3em}.lms-ui-icon-gallery.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-gallery{font-size:125%}}.lms-ui-icon-gallery:before{content:"\f302"}.lms-ui-icon-customisation{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-customisation.fa-pull-left{margin-right:.3em}.lms-ui-icon-customisation.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-customisation{font-size:125%}}.lms-ui-icon-customisation:before{content:"\f0d7"}.lms-ui-icon-optional-info{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-optional-info.fa-pull-left{margin-right:.3em}.lms-ui-icon-optional-info.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-optional-info{font-size:125%}}.lms-ui-icon-optional-info:before{content:"\f05a"}.lms-ui-icon-modified-date{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-modified-date.fa-pull-left{margin-right:.3em}.lms-ui-icon-modified-date.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-modified-date{font-size:125%}}.lms-ui-icon-modified-date:before{content:"\f4fd"}.lms-ui-icon-legal-personality{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-legal-personality.fa-pull-left{margin-right:.3em}.lms-ui-icon-legal-personality.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-legal-personality{font-size:125%}}.lms-ui-icon-legal-personality:before{content:"\f0b1"}.lms-ui-icon-division{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-division.fa-pull-left{margin-right:.3em}.lms-ui-icon-division.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-division{font-size:125%}}.lms-ui-icon-division:before{content:"\f1ad"}.lms-ui-icon-customer-pin-code{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-customer-pin-code.fa-pull-left{margin-right:.3em}.lms-ui-icon-customer-pin-code.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-customer-pin-code{font-size:125%}}.lms-ui-icon-customer-pin-code:before{content:"\f141"}.lms-ui-icon-more{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-more.fa-pull-left{margin-right:.3em}.lms-ui-icon-more.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-more{font-size:125%}}.lms-ui-icon-more:before{content:"\f103"}.lms-ui-icon-less{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-less.fa-pull-left{margin-right:.3em}.lms-ui-icon-less.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-less{font-size:125%}}.lms-ui-icon-less:before{content:"\f102"}.lms-ui-icon-user-id-number{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-user-id-number.fa-pull-left{margin-right:.3em}.lms-ui-icon-user-id-number.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-user-id-number{font-size:125%}}.lms-ui-icon-user-id-number:before{content:"\f2c2"}.lms-ui-icon-operator,.lms-ui-icon-sum,.lms-ui-icon-summary,.lms-ui-icon-total{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-operator.fa-pull-left,.lms-ui-icon-sum.fa-pull-left,.lms-ui-icon-summary.fa-pull-left,.lms-ui-icon-total.fa-pull-left{margin-right:.3em}.lms-ui-icon-operator.fa-pull-right,.lms-ui-icon-sum.fa-pull-right,.lms-ui-icon-summary.fa-pull-right,.lms-ui-icon-total.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-operator,.lms-ui-icon-sum,.lms-ui-icon-summary,.lms-ui-icon-total{font-size:125%}}.lms-ui-icon-operator:before,.lms-ui-icon-sum:before,.lms-ui-icon-summary:before,.lms-ui-icon-total:before{content:"\f1ec"}.lms-ui-icon-account-number{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-account-number.fa-pull-left{margin-right:.3em}.lms-ui-icon-account-number.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-account-number{font-size:125%}}.lms-ui-icon-account-number:before{content:"\f09d"}.lms-ui-icon-customer-status-connected{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-customer-status-connected.fa-pull-left{margin-right:.3em}.lms-ui-icon-customer-status-connected.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-customer-status-connected{font-size:125%}}.lms-ui-icon-customer-status-connected:before{content:"\f4fc"}.lms-ui-icon-customer-status-awaiting{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-customer-status-awaiting.fa-pull-left{margin-right:.3em}.lms-ui-icon-customer-status-awaiting.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-customer-status-awaiting{font-size:125%}}.lms-ui-icon-customer-status-awaiting:before{color:green;content:"\f4fd"}.lms-ui-icon-customer-status-interested{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-customer-status-interested.fa-pull-left{margin-right:.3em}.lms-ui-icon-customer-status-interested.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-customer-status-interested{font-size:125%}}.lms-ui-icon-customer-status-interested:before{content:"\f234"}.lms-ui-icon-customer-status-disconnected{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-customer-status-disconnected.fa-pull-left{margin-right:.3em}.lms-ui-icon-customer-status-disconnected.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-customer-status-disconnected{font-size:125%}}.lms-ui-icon-customer-status-disconnected:before{content:"\f235"}.lms-ui-icon-customer-status-debtcollection{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-customer-status-debtcollection.fa-pull-left{margin-right:.3em}.lms-ui-icon-customer-status-debtcollection.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-customer-status-debtcollection{font-size:125%}}.lms-ui-icon-customer-status-debtcollection:before{color:red;content:"\f4fa"}.lms-ui-icon-redo,.lms-ui-icon-resend{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-redo.fa-pull-left,.lms-ui-icon-resend.fa-pull-left{margin-right:.3em}.lms-ui-icon-redo.fa-pull-right,.lms-ui-icon-resend.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-redo,.lms-ui-icon-resend{font-size:125%}}.lms-ui-icon-redo:before,.lms-ui-icon-resend:before{content:"\f01e"}.lms-ui-icon-additional-selection,.lms-ui-icon-secondary-selection{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-additional-selection.fa-pull-left,.lms-ui-icon-secondary-selection.fa-pull-left{margin-right:.3em}.lms-ui-icon-additional-selection.fa-pull-right,.lms-ui-icon-secondary-selection.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-additional-selection,.lms-ui-icon-secondary-selection{font-size:125%}}.lms-ui-icon-additional-selection:before,.lms-ui-icon-secondary-selection:before{content:"\f142"}.lms-ui-icon-menu{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-menu.fa-pull-left{margin-right:.3em}.lms-ui-icon-menu.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-menu{font-size:125%}}.lms-ui-icon-menu:before{content:"\f0c9"}.lms-ui-icon-routed,.lms-ui-icon-routing{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-routed.fa-pull-left,.lms-ui-icon-routing.fa-pull-left{margin-right:.3em}.lms-ui-icon-routed.fa-pull-right,.lms-ui-icon-routing.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-routed,.lms-ui-icon-routing{font-size:125%}}.lms-ui-icon-routed:before,.lms-ui-icon-routing:before{content:"\f4d7"}.lms-ui-icon-finger-up{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-finger-up.fa-pull-left{margin-right:.3em}.lms-ui-icon-finger-up.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-finger-up{font-size:125%}}.lms-ui-icon-finger-up:before{content:"\f0a6"}.lms-ui-icon-finger-down{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-finger-down.fa-pull-left{margin-right:.3em}.lms-ui-icon-finger-down.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-finger-down{font-size:125%}}.lms-ui-icon-finger-down:before{content:"\f0a7"}.lms-ui-icon-karma,.lms-ui-icon-star{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-karma.fa-pull-left,.lms-ui-icon-star.fa-pull-left{margin-right:.3em}.lms-ui-icon-karma.fa-pull-right,.lms-ui-icon-star.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-karma,.lms-ui-icon-star{font-size:125%}}.lms-ui-icon-karma:before,.lms-ui-icon-star:before{content:"\f005"}.lms-ui-icon-bell,.lms-ui-icon-notification,.lms-ui-icon-notifications,.lms-ui-icon-notify{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-bell.fa-pull-left,.lms-ui-icon-notification.fa-pull-left,.lms-ui-icon-notifications.fa-pull-left,.lms-ui-icon-notify.fa-pull-left{margin-right:.3em}.lms-ui-icon-bell.fa-pull-right,.lms-ui-icon-notification.fa-pull-right,.lms-ui-icon-notifications.fa-pull-right,.lms-ui-icon-notify.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-bell,.lms-ui-icon-notification,.lms-ui-icon-notifications,.lms-ui-icon-notify{font-size:125%}}.lms-ui-icon-bell:before,.lms-ui-icon-notification:before,.lms-ui-icon-notifications:before,.lms-ui-icon-notify:before{content:"\f0f3"}.lms-ui-icon-color,.lms-ui-icon-colour,.lms-ui-icon-palette{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-color.fa-pull-left,.lms-ui-icon-colour.fa-pull-left,.lms-ui-icon-palette.fa-pull-left{margin-right:.3em}.lms-ui-icon-color.fa-pull-right,.lms-ui-icon-colour.fa-pull-right,.lms-ui-icon-palette.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-color,.lms-ui-icon-colour,.lms-ui-icon-palette{font-size:125%}}.lms-ui-icon-color:before,.lms-ui-icon-colour:before,.lms-ui-icon-palette:before{content:"\f53f"}.lms-ui-icon-csv{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-csv.fa-pull-left{margin-right:.3em}.lms-ui-icon-csv.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-csv{font-size:125%}}.lms-ui-icon-csv:before{content:"\f6dd"}.lms-ui-icon-reward{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-reward.fa-pull-left{margin-right:.3em}.lms-ui-icon-reward.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-reward{font-size:125%}}.lms-ui-icon-reward:before{content:"\f091"}.lms-ui-icon-penalty{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-penalty.fa-pull-left{margin-right:.3em}.lms-ui-icon-penalty.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-penalty{font-size:125%}}.lms-ui-icon-penalty:before{content:"\f714"}.lms-ui-icon-hardware,.lms-ui-icon-mac,.lms-ui-icon-model,.lms-ui-icon-producer{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-hardware.fa-pull-left,.lms-ui-icon-mac.fa-pull-left,.lms-ui-icon-model.fa-pull-left,.lms-ui-icon-producer.fa-pull-left{margin-right:.3em}.lms-ui-icon-hardware.fa-pull-right,.lms-ui-icon-mac.fa-pull-right,.lms-ui-icon-model.fa-pull-right,.lms-ui-icon-producer.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-hardware,.lms-ui-icon-mac,.lms-ui-icon-model,.lms-ui-icon-producer{font-size:125%}}.lms-ui-icon-hardware:before,.lms-ui-icon-mac:before,.lms-ui-icon-model:before,.lms-ui-icon-producer:before{content:"\f2db"}.lms-ui-icon-accounting,.lms-ui-icon-period{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-accounting.fa-pull-left,.lms-ui-icon-period.fa-pull-left{margin-right:.3em}.lms-ui-icon-accounting.fa-pull-right,.lms-ui-icon-period.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-accounting,.lms-ui-icon-period{font-size:125%}}.lms-ui-icon-accounting:before,.lms-ui-icon-period:before{content:"\f017"}.lms-ui-icon-recipient{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-recipient.fa-pull-left{margin-right:.3em}.lms-ui-icon-recipient.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-recipient{font-size:125%}}.lms-ui-icon-recipient:before{content:"\f2c1"}.lms-ui-icon-discount{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-discount.fa-pull-left{margin-right:.3em}.lms-ui-icon-discount.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-discount{font-size:125%}}.lms-ui-icon-discount:before{content:"\f295"}.lms-ui-icon-quantity{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-quantity.fa-pull-left{margin-right:.3em}.lms-ui-icon-quantity.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-quantity{font-size:125%}}.lms-ui-icon-quantity:before{content:"\f58d"}.lms-ui-icon-template{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-template.fa-pull-left{margin-right:.3em}.lms-ui-icon-template.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-template{font-size:125%}}.lms-ui-icon-template:before{content:"\f5bf"}.lms-ui-icon-permissions{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-permissions.fa-pull-left{margin-right:.3em}.lms-ui-icon-permissions.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-permissions{font-size:125%}}.lms-ui-icon-permissions:before{content:"\f502"}.lms-ui-icon-filter{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-filter.fa-pull-left{margin-right:.3em}.lms-ui-icon-filter.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-filter{font-size:125%}}.lms-ui-icon-filter:before{content:"\f0b0"}.lms-ui-icon-fiber,.lms-ui-icon-fibre{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Brands';font-weight:400;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-fiber.fa-pull-left,.lms-ui-icon-fibre.fa-pull-left{margin-right:.3em}.lms-ui-icon-fiber.fa-pull-right,.lms-ui-icon-fibre.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-fiber,.lms-ui-icon-fibre{font-size:125%}}.lms-ui-icon-fiber:before,.lms-ui-icon-fibre:before{content:"\f391"}.lms-ui-icon-tax,.lms-ui-icon-taxrate{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-tax.fa-pull-left,.lms-ui-icon-taxrate.fa-pull-left{margin-right:.3em}.lms-ui-icon-tax.fa-pull-right,.lms-ui-icon-taxrate.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-tax,.lms-ui-icon-taxrate{font-size:125%}}.lms-ui-icon-tax:before,.lms-ui-icon-taxrate:before{content:"\f0f2"}.lms-ui-icon-execute,.lms-ui-icon-launch,.lms-ui-icon-run{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-execute.fa-pull-left,.lms-ui-icon-launch.fa-pull-left,.lms-ui-icon-run.fa-pull-left{margin-right:.3em}.lms-ui-icon-execute.fa-pull-right,.lms-ui-icon-launch.fa-pull-right,.lms-ui-icon-run.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-execute,.lms-ui-icon-launch,.lms-ui-icon-run{font-size:125%}}.lms-ui-icon-execute:before,.lms-ui-icon-launch:before,.lms-ui-icon-run:before{content:"\f120"}.lms-ui-icon-area{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-area.fa-pull-left{margin-right:.3em}.lms-ui-icon-area.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-area{font-size:125%}}.lms-ui-icon-area:before{content:"\f0c8"}.lms-ui-icon-antenna{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-antenna.fa-pull-left{margin-right:.3em}.lms-ui-icon-antenna.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-antenna{font-size:125%}}.lms-ui-icon-antenna:before{content:"\f519"}.lms-ui-icon-share{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-share.fa-pull-left{margin-right:.3em}.lms-ui-icon-share.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-share{font-size:125%}}.lms-ui-icon-share:before{content:"\f1e0"}.lms-ui-icon-map{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-map.fa-pull-left{margin-right:.3em}.lms-ui-icon-map.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-map{font-size:125%}}.lms-ui-icon-map:before{content:"\f5a0"}.lms-ui-icon-mic,.lms-ui-icon-microphone{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-mic.fa-pull-left,.lms-ui-icon-microphone.fa-pull-left{margin-right:.3em}.lms-ui-icon-mic.fa-pull-right,.lms-ui-icon-microphone.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-mic,.lms-ui-icon-microphone{font-size:125%}}.lms-ui-icon-mic:before,.lms-ui-icon-microphone:before{content:"\f130"}@keyframes fa-beat{0%{transform:scale(1)}5%{transform:scale(1.25)}10%{transform:scale(1.5)}15%{transform:scale(1.25)}20%{transform:scale(1)}30%{transform:scale(1.25)}35%{transform:scale(1.5)}40%{transform:scale(1.25)}45%{transform:scale(1)}55%{transform:scale(1.25)}60%{transform:scale(1.5)}65%{transform:scale(1.25)}70%{transform:scale(1)}75%{transform:scale(1.25)}80%{transform:scale(1.5)}85%{transform:scale(1.25)}90%{transform:scale(1)}}.fa-beat{animation:fa-beat 5s ease infinite}.lms-ui-icon-barcode{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-barcode.fa-pull-left{margin-right:.3em}.lms-ui-icon-barcode.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-barcode{font-size:125%}}.lms-ui-icon-barcode:before{content:"\f02a"}.lms-ui-icon-fiber-optic,.lms-ui-icon-fiberoptic,.lms-ui-icon-fibre-optic{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-fiber-optic.fa-pull-left,.lms-ui-icon-fiberoptic.fa-pull-left,.lms-ui-icon-fibre-optic.fa-pull-left{margin-right:.3em}.lms-ui-icon-fiber-optic.fa-pull-right,.lms-ui-icon-fiberoptic.fa-pull-right,.lms-ui-icon-fibre-optic.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-fiber-optic,.lms-ui-icon-fiberoptic,.lms-ui-icon-fibre-optic{font-size:125%}}.lms-ui-icon-fiber-optic:before,.lms-ui-icon-fiberoptic:before,.lms-ui-icon-fibre-optic:before{content:"\f0eb"}.lms-ui-icon-tv{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-tv.fa-pull-left{margin-right:.3em}.lms-ui-icon-tv.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-tv{font-size:125%}}.lms-ui-icon-tv:before{content:"\f26c"}.lms-ui-icon-ignore,.lms-ui-icon-ignored{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:400;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-ignore.fa-pull-left,.lms-ui-icon-ignored.fa-pull-left{margin-right:.3em}.lms-ui-icon-ignore.fa-pull-right,.lms-ui-icon-ignored.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-ignore,.lms-ui-icon-ignored{font-size:125%}}.lms-ui-icon-ignore:before,.lms-ui-icon-ignored:before{content:"\f28d"}.lms-ui-icon-netrange-theoretical{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-netrange-theoretical.fa-pull-left{margin-right:.3em}.lms-ui-icon-netrange-theoretical.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-netrange-theoretical{font-size:125%}}.lms-ui-icon-netrange-theoretical:before{content:"\f059"}.lms-ui-icon-netrange-real{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-netrange-real.fa-pull-left{margin-right:.3em}.lms-ui-icon-netrange-real.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-netrange-real{font-size:125%}}.lms-ui-icon-netrange-real:before{content:"\f058"}.lms-ui-icon-transfer{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-transfer.fa-pull-left{margin-right:.3em}.lms-ui-icon-transfer.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-transfer{font-size:125%}}.lms-ui-icon-transfer:before{content:"\f079"}.dataTables_wrapper{margin-bottom:4px;position:static}.dataTables_wrapper .dataTables_processing{font-weight:700}.dataTables_wrapper .top{display:flex;justify-content:space-around;flex-wrap:wrap}.dataTables_wrapper div.lms-ui-datatable-toolbar{display:flex;justify-content:space-between}.dataTables_wrapper .dataTables_length{padding-left:4px;padding-top:5px;white-space:nowrap}.dataTables_wrapper div.lms-ui-datatable-clear-settings{float:left;padding-left:4px;padding-top:4px;cursor:pointer}.dataTables_wrapper div.lms-ui-datatable-column-toggle{float:left;padding-left:3px;padding-top:4px}.dataTables_wrapper .dataTables_paginate{float:left;text-align:center;padding-top:2px}.dataTables_wrapper .dataTables_filter{padding-right:4px;padding-top:5px}.dataTables_wrapper .dataTables_info{float:none;text-align:center;padding-top:3px;padding-bottom:3px;font-weight:700}.dataTables_wrapper .top{border:1px solid #000;border-bottom:0}.dataTables_wrapper .bottom{border:1px solid #000;border-top:0}#lms-ui-spinner{position:fixed;left:0;top:0;width:100%;height:100%;display:flex;justify-content:center;align-items:center}.lms-ui-sk-fading-circle{margin:100px 10px;width:80px;height:80px;position:relative}.lms-ui-sk-fading-circle .lms-ui-sk-circle{width:100%;height:100%;position:absolute;left:0;top:0}.lms-ui-sk-fading-circle .lms-ui-sk-circle:before{content:'';display:block;margin:0 auto;width:15%;height:15%;background-color:#333;border-radius:100%;-webkit-animation:lms-ui-sk-circleFadeDelay 1.2s infinite ease-in-out both;animation:lms-ui-sk-circleFadeDelay 1.2s infinite ease-in-out both}.lms-ui-sk-fading-circle .lms-ui-sk-circle2{-webkit-transform:rotate(30deg);-ms-transform:rotate(30deg);transform:rotate(30deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle3{-webkit-transform:rotate(60deg);-ms-transform:rotate(60deg);transform:rotate(60deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle4{-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle5{-webkit-transform:rotate(120deg);-ms-transform:rotate(120deg);transform:rotate(120deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle6{-webkit-transform:rotate(150deg);-ms-transform:rotate(150deg);transform:rotate(150deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle7{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle8{-webkit-transform:rotate(210deg);-ms-transform:rotate(210deg);transform:rotate(210deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle9{-webkit-transform:rotate(240deg);-ms-transform:rotate(240deg);transform:rotate(240deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle10{-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle11{-webkit-transform:rotate(300deg);-ms-transform:rotate(300deg);transform:rotate(300deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle12{-webkit-transform:rotate(330deg);-ms-transform:rotate(330deg);transform:rotate(330deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle2:before{-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.lms-ui-sk-fading-circle .lms-ui-sk-circle3:before{-webkit-animation-delay:-1s;animation-delay:-1s}.lms-ui-sk-fading-circle .lms-ui-sk-circle4:before{-webkit-animation-delay:-.9s;animation-delay:-.9s}.lms-ui-sk-fading-circle .lms-ui-sk-circle5:before{-webkit-animation-delay:-.8s;animation-delay:-.8s}.lms-ui-sk-fading-circle .lms-ui-sk-circle6:before{-webkit-animation-delay:-.7s;animation-delay:-.7s}.lms-ui-sk-fading-circle .lms-ui-sk-circle7:before{-webkit-animation-delay:-.6s;animation-delay:-.6s}.lms-ui-sk-fading-circle .lms-ui-sk-circle8:before{-webkit-animation-delay:-.5s;animation-delay:-.5s}.lms-ui-sk-fading-circle .lms-ui-sk-circle9:before{-webkit-animation-delay:-.4s;animation-delay:-.4s}.lms-ui-sk-fading-circle .lms-ui-sk-circle10:before{-webkit-animation-delay:-.3s;animation-delay:-.3s}.lms-ui-sk-fading-circle .lms-ui-sk-circle11:before{-webkit-animation-delay:-.2s;animation-delay:-.2s}.lms-ui-sk-fading-circle .lms-ui-sk-circle12:before{-webkit-animation-delay:-.1s;animation-delay:-.1s}@-webkit-keyframes lms-ui-sk-circleFadeDelay{0%,100%,39%{opacity:0}40%{opacity:1}}@keyframes lms-ui-sk-circleFadeDelay{0%,100%,39%{opacity:0}40%{opacity:1}}.lms-ui-list-container{display:flex;align-items:flex-start!important}.lms-ui-list-container ul{display:inline;list-style:none;padding:0;margin-block-start:0;margin-block-end:0}.lms-ui-list-container li .lms-ui-list-unlink{visibility:hidden;margin-top:.1em;padding-right:.4em}.lms-ui-list-container li:hover .lms-ui-list-unlink{visibility:visible;cursor:pointer}.lms-ui-list-container.disabled{cursor:default!important;color:#888!important}.lms-ui-list-container.disabled a{cursor:default!important}.lms-ui-list-container.disabled i::before{color:#888!important}.lms-ui-list-container .lms-ui-item-suggestion-button{margin:0}.lms-ui-list-suggestion-container .lms-ui-list-suggestion-button{cursor:pointer}.lms-ui-list-suggestion-container .lms-ui-list-suggestion:not(:focus){display:none}button{font-size:10pt}@media screen and (max-width:1920px){button{font-size:9pt}}@media screen and (max-width:1200px){button{font-size:8pt}}button.lms-ui-button{display:inline-flex;align-items:center}button.lms-ui-link-button{display:inline-block}a.lms-ui-link-button{vertical-align:top;display:inline-flex;align-items:center}a.lms-ui-link-button,button.lms-ui-button{box-sizing:border-box;padding:.33em;padding-top:.15em;padding-bottom:.15em;margin-top:.25em;margin-bottom:.25em;min-height:2.5em;border:1px solid #615847;color:#000!important;text-decoration:none;background-color:#DFD5BD;background-repeat:no-repeat;background-position:3px 3px;outline:0}a.lms-ui-link-button.lms-ui-button-icon,button.lms-ui-button.lms-ui-button-icon{padding-left:25px}a.lms-ui-link-button:hover,button.lms-ui-button:hover{text-decoration:none}a.lms-ui-link-button:not([disabled]):active,button.lms-ui-button:not([disabled]):active{background-color:#CEBD9B;box-shadow:inset 1px 1px 4px 0 rgba(0,0,0,.4)}a.lms-ui-link-button:not([disabled]):focus,button.lms-ui-button:not([disabled]):focus{box-shadow:0 0 1px 1px #000}a.lms-ui-link-button:not([disabled]):hover,button.lms-ui-button:not([disabled]):hover{box-shadow:0 0 3px 1px #000}a.lms-ui-link-button:not([disabled]):hover.alert,a.lms-ui-link-button:not([disabled]):hover.lms-ui-error,button.lms-ui-button:not([disabled]):hover.alert,button.lms-ui-button:not([disabled]):hover.lms-ui-error{box-shadow:0 0 3px 1px red}a.lms-ui-link-button:not([disabled]):hover.lms-ui-warning,button.lms-ui-button:not([disabled]):hover.lms-ui-warning{box-shadow:0 0 3px 1px Orange}a.lms-ui-link-button[disabled],button.lms-ui-button[disabled]{color:#888!important;cursor:no-drop}a.lms-ui-link-button[disabled]:before,button.lms-ui-button[disabled]:before{color:#888!important}a.lms-ui-link-button.alert,a.lms-ui-link-button.lms-ui-error,button.lms-ui-button.alert,button.lms-ui-button.lms-ui-error{box-shadow:0 0 3px 1px red}a.lms-ui-link-button.alert:focus,a.lms-ui-link-button.lms-ui-error:focus,button.lms-ui-button.alert:focus,button.lms-ui-button.lms-ui-error:focus{border:1px solid #a32828;box-shadow:0 0 1px 1px #a32828}a.lms-ui-link-button.lms-ui-warning,button.lms-ui-button.lms-ui-warning{box-shadow:0 0 3px 1px Orange}a.lms-ui-link-button.lms-ui-warning:focus,button.lms-ui-button.lms-ui-warning:focus{border:1px solid Orange;box-shadow:0 0 1px 1px Orange}a.lms-ui-link-button .lms-ui-label,button.lms-ui-button .lms-ui-label{font-weight:700;vertical-align:middle}a.lms-ui-link-button i+.lms-ui-label,button.lms-ui-button i+.lms-ui-label{padding-left:.5em}a.lms-ui-button i+.lms-ui-label{padding-left:.5em}a.lms-ui-button:not(.lms-ui-link-button){border:1px solid transparent;display:inline-block}a.lms-ui-button:not(.lms-ui-link-button)>i:before{color:#000}a.lms-ui-button:not(.lms-ui-link-button)>i{text-align:center;padding:0 .1em}a.lms-ui-button:not(.lms-ui-link-button):hover{cursor:pointer;border:1px solid #615847;border-radius:3px;display:inline-block;text-decoration:none}a.lms-ui-button:not(.lms-ui-link-button)[disabled]{color:#888!important;cursor:no-drop}a.lms-ui-button:not(.lms-ui-link-button)[disabled]:before{color:#888!important}a.lms-ui-button:not(.lms-ui-link-button)[disabled]>i:before{color:#888!important}a.lms-ui-link-button+button.lms-ui-button{margin-left:.33em}.lms-ui-responsive-buttons{display:inline-block}.lms-ui-responsive-buttons>*{padding-left:.1em;padding-right:.1em}.lms-ui-responsive-buttons .lms-ui-dropdown-toggle{display:none!important;cursor:pointer}.lms-ui-responsive-buttons .lms-ui-dropdown-toggle.secondary{display:inline!important}@media screen and (max-width:800px){.lms-ui-responsive-buttons .lms-ui-dropdown-toggle{font-size:1.33333333em;line-height:.75em;vertical-align:-.0667em;line-height:normal}}.lms-ui-responsive-buttons .lms-ui-dropdown-buttons{display:inline}.lms-ui-responsive-buttons .lms-ui-dropdown-buttons .lms-ui-button.secondary{display:none}@media screen and (max-width:1200px){.lms-ui-responsive-buttons .lms-ui-dropdown-toggle{display:inline-flex!important}.lms-ui-responsive-buttons .lms-ui-dropdown-toggle.secondary{display:none!important}.lms-ui-responsive-buttons .lms-ui-dropdown-buttons{display:none;padding:.2em;position:absolute;background-color:#DFD5BD;border:1px solid #000;box-shadow:0 8px 16px 0 rgba(0,0,0,.2);z-index:1}.lms-ui-responsive-buttons .lms-ui-dropdown-buttons.show{display:flex}.lms-ui-responsive-buttons .lms-ui-dropdown-buttons .lms-ui-button{display:none}}td>button:last-child{margin-right:.5em}i.lms-ui-button-clipboard:hover{cursor:pointer}i.lms-ui-button-clipboard:hover:not(.lms-ui-static){font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}i.lms-ui-button-clipboard:hover:not(.lms-ui-static).fa-pull-left{margin-right:.3em}i.lms-ui-button-clipboard:hover:not(.lms-ui-static).fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){i.lms-ui-button-clipboard:hover:not(.lms-ui-static){font-size:125%}}i.lms-ui-button-clipboard:hover:not(.lms-ui-static):before{content:"\f0c5"}a.lms-ui-button:not(.lms-ui-link-button).lms-ui-button-speech-recognition.active{animation:fa-beat 5s ease infinite}a.lms-ui-button:not(.lms-ui-link-button).lms-ui-button-speech-recognition.active>i:before{color:red}.lms-ui-util-buttons{display:flex;flex-direction:column}.ui-widget.ui-widget-content{border:1px solid #615847}.ui-tabs .ui-tabs-nav{border-top:0;border-right:0;border-bottom:1px dotted grey;border-bottom-right-radius:0;margin-right:.4em}.ui-tabs.ui-widget.ui-widget-content{border:0}.ui-tabs.ui-widget-content{background-color:transparent}.ui-tabs .ui-widget-header{background-color:transparent;padding:0}.ui-tabs .ui-tabs-panel{border:1px dotted grey;border-top:none;border-top-left-radius:0}.ui-tabs .ui-tab .alert,.ui-tabs .ui-tab.lms-ui-error,.ui-tabs .ui-tab:invalid{box-shadow:0 0 3px 1px red!important}.ui-tabs .ui-tab .alert:focus,.ui-tabs .ui-tab.lms-ui-error:focus,.ui-tabs .ui-tab:invalid:focus{box-shadow:0 0 1px 1px #a32828!important}.ui-tabs .ui-tab.lms-ui-warning{box-shadow:0 0 3px 1px Orange!important}.ui-tabs .ui-tab.lms-ui-warning:focus{box-shadow:0 0 1px 1px Orange!important}.ui-tabs .ui-tab.ui-tabs-tab{background-color:#CEBD9B;box-shadow:none;margin-left:-.1em}.ui-tabs .ui-tab.ui-tabs-active .ui-tabs-anchor{color:#000;font-weight:700;outline:0}.ui-tabs .ui-tab.ui-tabs-active.ui-tabs-tab{background-color:#DFD5BD;border:1px dotted grey;border-bottom:none;box-shadow:unset}.ui-tabs .ui-tab.ui-tabs-active:focus{border:1px solid #615847;border-bottom:none}.ui-widget-overlay{opacity:.5}.ui-button,.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default,html .ui-button.ui-state-disabled:active,html .ui-button.ui-state-disabled:hover{padding:0 1em;border:1px solid #615847;background-color:#DFD5BD}.ui-state-default,.ui-widget-content .ui-state-default{padding:0;text-align:center}.ui-button:focus,.ui-button:hover,.ui-state-focus,.ui-state-hover,.ui-widget-content .ui-state-focus,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-focus,.ui-widget-header .ui-state-hover{box-shadow:inset 1px 1px 3px 0 rgba(0,0,0,.6);background-color:#DFD5BD;border:1px solid #615847;outline:0;color:#000}.ui-selectmenu-text{padding-top:2px}.ui-selectmenu-button.ui-button{min-width:20em;width:auto}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{background-color:#fffa90}.ui-button.ui-state-active:hover,.ui-button:active,.ui-button:focus,.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{box-shadow:inset 1px 1px 4px 0 rgba(0,0,0,.4);background:#CEBD9B;border:1px solid #615847}.ui-dialog{background-color:#CEBD9B}.ui-dialog .ui-dialog-content{background-color:#CEBD9B}.ui-dialog .ui-dialog-buttonpane{background-color:#CEBD9B;border-top:0;padding-right:6px}.ui-dialog-content{background-color:#CEBD9B}.ui-dialog-titlebar{background-color:#B6A688;border:1px solid #B6A688;color:#333}.ui-dialog-buttonpane .ui-dialog-buttonset{width:100%;text-align:center}.ui-tooltip{background-color:#DFD5BD}.ui-tooltip.lms-ui-error{color:red}.ui-tooltip.lms-ui-warning{color:Sienna}.ui-datepicker{background-color:#B6A688}.ui-datepicker-header{background-color:#CEBD9B;border:1px solid #CEBD9B}.ui-datepicker-calendar{background-color:#CEBD9B}.ui-datepicker .ui-datepicker-buttonpane{border-top:1px solid #000;margin-top:0}.ui-datepicker-trigger{border:none;background:0 0;margin-left:.3em;padding:0}input[disabled]+.ui-datepicker-trigger{color:#888!important;cursor:no-drop}input[disabled]+.ui-datepicker-trigger:before{color:#888!important}.ui-tooltip.customerassignmentinfo,.ui-tooltip.customerinfo,.ui-tooltip.docnumber,.ui-tooltip.documentview,.ui-tooltip.ewxnodelist,.ui-tooltip.invoiceinfo,.ui-tooltip.netdevlist,.ui-tooltip.nodegroupinfo,.ui-tooltip.nodelist,.ui-tooltip.rtticketinfo,.ui-tooltip.voipaccountinfo{padding:0}.ui-dialog.documentviewdialog{min-width:200px;min-height:35px;position:absolute}.ui-dialog-content.documentviewdialog{padding:0!important;min-width:200px;min-height:35px}.fileupload-progress-dialog .ui-dialog-titlebar{display:none}.ui-progressbar{position:relative!important;background-color:#DFD5BD}.ui-progressbar .ui-progressbar-value{background-color:#B6A688;border-color:#B6A688}.ui-selected{background-color:#CFC}.ui-slider.ui-widget-content{background-color:#EBE4D6}.ui-slider-range{background-color:#CEBD9B;text-align:center;overflow:hidden;cursor:default}.ui-slider-handle.ui-state-default{background-color:#B6A688;margin-top:2px}.ui-slider-horizontal{height:1em}.ui-selectmenu-optgroup{background-color:#ebe4d6!important}.ui-menu-item{background-color:#ebe4d6!important}.ui-menu-item .ui-state-active,.ui-menu-item .ui-state-active:hover{color:#fff;background-color:#4a90d9!important}.ui-menu-item [class*=lms-ui-icon]{padding-right:.5em}.ui-sortable-handle{cursor:grab}.lms-ui-gallery-container{display:none}.lms-ui-gallery-container .lms-ui-gallery-overlay{position:fixed;left:0;top:0;width:100%;height:100%;z-index:52;opacity:.3;background-color:#000}.lms-ui-gallery-container .lms-ui-gallery{position:fixed;top:5em;bottom:5em;left:5em;right:5em;height:calc(100% - 10em);z-index:53}.lms-ui-gallery-container .lms-ui-gallery .galleria-info{width:auto}.lms-ui-gallery-container .lms-ui-gallery .galleria-buttons{position:absolute;top:.3em;right:.5em;z-index:10;color:#fff}.lms-ui-gallery-container .lms-ui-gallery .galleria-buttons i{cursor:pointer;font-size:2em}.lms-ui-gallery-container .lms-ui-gallery .galleria-buttons i:not(:last-child){margin-right:.3em}#lms-ui-popup-menu{display:none;z-index:80;flex-direction:column;position:absolute;max-width:25em;max-height:50vh;background-color:#DFD5BD;box-shadow:0 8px 16px 0 rgba(0,0,0,.2);padding:1em;font-weight:700}#lms-ui-popup-menu.open{display:flex}@media screen and (min-width:801px){#lms-ui-popup-menu{border:1px solid #000}}#lms-ui-popup-menu #lms-ui-popup-menu-titlebar{display:flex;justify-content:space-between;align-items:center;padding-bottom:.5em;margin-bottom:.5em;border-bottom:1px dotted grey}#lms-ui-popup-menu #lms-ui-popup-menu-titlebar i{margin-left:1.5em;cursor:pointer}#lms-ui-popup-menu #lms-ui-popup-menu-content{overflow-y:auto;max-height:calc(100% - 2.2em)}#lms-ui-popup-menu ul{list-style-type:none;display:inline-block;margin-block-start:0;margin-block-end:0;padding-inline-start:0;width:100%}#lms-ui-popup-menu ul li{padding-top:.25em;padding-bottom:.25em;padding-left:2.5em;padding-right:.5em;text-indent:-1.7em}@media screen and (max-width:800px){#lms-ui-popup-menu ul li:not(:last-child){border-bottom:1px dotted grey}}#lms-ui-popup-menu ul li:hover{background-color:#CFC;cursor:pointer}@media screen and (max-width:800px){#lms-ui-popup-menu{max-width:unset;max-height:unset;position:fixed;left:0;top:2em;right:0;bottom:0;font-size:200%}}.lms-ui-multiselect-container{display:inline-block;vertical-align:middle;min-height:1.8em}.lms-ui-multiselect-container .lms-ui-multiselect-label-workaround,.lms-ui-multiselect-container select{display:none}.lms-ui-multiselect-container .lms-ui-multiselect-launcher.lms-ui-error{border:1px solid red;box-shadow:0 0 3px 1px red}.lms-ui-multiselect-container .lms-ui-multiselect-launcher.lms-ui-error:focus{border:1px solid #a32828;box-shadow:0 0 1px 1px #a32828;outline:0}.lms-ui-multiselect-container.lms-ui-error{color:unset!important}.lms-ui-multiselect-container.lms-ui-error .lms-ui-multiselect-launcher{border:1px solid red;box-shadow:0 0 3px 1px red}.lms-ui-multiselect-container.lms-ui-error .lms-ui-multiselect-launcher:focus{border:1px solid #a32828;box-shadow:0 0 1px 1px #a32828;outline:0}.lms-ui-multiselect-container.lms-ui-distinguished,.lms-ui-multiselect-container.lms-ui-warning{color:unset!important}.lms-ui-multiselect-container.lms-ui-distinguished .lms-ui-multiselect-launcher,.lms-ui-multiselect-container.lms-ui-warning .lms-ui-multiselect-launcher{border:1px solid Orange;box-shadow:0 0 3px 1px Orange}.lms-ui-multiselect-container.lms-ui-distinguished .lms-ui-multiselect-launcher:focus,.lms-ui-multiselect-container.lms-ui-warning .lms-ui-multiselect-launcher:focus{border:1px solid Orange;box-shadow:0 0 1px 1px Orange;outline:0}.lms-ui-multiselect-container .lms-ui-multiselect-launcher{vertical-align:middle;background-color:#EBE4D6;border:1px solid #a9a9a9;min-height:1.6em;box-sizing:border-box;display:flex;flex-direction:row-reverse;align-items:center}.lms-ui-multiselect-container .lms-ui-multiselect-launcher .lms-ui-multiselect-launcher-label{font-size:10pt;font-family:Arial,Helvetica,Verdana;vertical-align:middle;cursor:default;padding:0 0 0 4px;max-width:200px;white-space:pre-wrap;min-width:200px;display:block}@media screen and (max-width:1920px){.lms-ui-multiselect-container .lms-ui-multiselect-launcher .lms-ui-multiselect-launcher-label{font-size:9pt}}@media screen and (max-width:1200px){.lms-ui-multiselect-container .lms-ui-multiselect-launcher .lms-ui-multiselect-launcher-label{font-size:8pt}}.lms-ui-multiselect-container .lms-ui-multiselect-launcher .lms-ui-multiselect-launcher-label.lms-ui-multiselect-filter{min-width:100px}.lms-ui-multiselect-container .lms-ui-multiselect-launcher .lms-ui-multiselect-launcher-toggle{float:right;margin-right:.2em;display:block;font-size:120%}.lms-ui-multiselect-container .lms-ui-multiselect-launcher .lms-ui-multiselect-clear-button{float:right;margin-right:.3em;margin-left:.3em;display:block;opacity:.4;font-size:100%;cursor:pointer;margin-top:.12em}.lms-ui-multiselect-container.tiny .lms-ui-multiselect-launcher{overflow:hidden;vertical-align:middle;cursor:pointer;display:flex;align-items:center;border-color:transparent;background-color:transparent;min-height:unset;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.lms-ui-multiselect-container .lms-ui-multiselect-popup{display:none;position:absolute;width:350px;border:solid 1px #888;background-color:#DFD5BD;z-index:65;overflow:hidden;box-shadow:0 8px 16px 0 rgba(0,0,0,.2);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media screen and (max-width:800px){.lms-ui-multiselect-container .lms-ui-multiselect-popup{position:fixed;width:auto;left:0;top:2em;right:0;bottom:0;padding:.5em;font-size:200%;border:0}}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list{list-style:none;cursor:default;padding:0;margin:0;border-bottom:solid 1px #888;max-height:200px;max-width:350px;text-align:left;overflow-x:hidden;overflow-y:auto}@media screen and (max-width:800px){.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list{max-height:80%;max-width:unset;border:solid 1px #888}}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list li{white-space:normal;padding:0;margin:0;background-color:#EBE4D6;padding-left:2em;text-indent:-2em}@media screen and (max-width:800px){.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list li{padding-left:1.2em;text-indent:-1.1em}}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list li:not(:last-child){border-bottom:1px dotted grey}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list li input{border:none;margin:3px 3px 3px 4px}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list li.selected{background-color:#CEBD9B}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list li.active{background-color:#B6A688}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list li:not(.visible){display:none}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list li.exclusive{font-weight:700}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list span{padding-left:3px}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-titlebar{display:none;justify-content:space-between;align-items:center;padding-bottom:.5em;margin-bottom:.5em;border-bottom:1px dotted grey}@media screen and (max-width:800px){.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-titlebar{display:flex}}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-titlebar .lms-ui-multiselect-popup-title{font-weight:700}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-titlebar i{margin-left:1.5em;cursor:pointer}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-checkall{width:100%}@media screen and (max-width:800px){.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-checkall{margin-top:.5em;border-top:1px dotted grey;padding-top:.5em}}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-checkall input{margin-right:.9em}@media screen and (min-width:801px){body.main-menu-visible{margin-left:17em}body.main-menu-visible #lms-ui-menu-panel{width:16em}body.main-menu-visible #lms-ui-tool-panels{margin-left:17em}}@media screen and (min-width:801px) and print{body.main-menu-visible{margin-left:0}}#lms-ui-menu-panel{z-index:2;background-color:#CEBD9B;overflow:hidden;border:1px solid #000;display:flex;flex-direction:column;justify-content:flex-start;align-items:stretch;position:fixed;left:0;top:0;height:100vh}@media screen and (min-width:801px){#lms-ui-menu-panel{box-shadow:1em 0 .9em #EBE4D6}}@media screen and (max-width:800px){#lms-ui-menu-panel{display:none;overflow-y:auto;border:0;font-size:200%;position:fixed;left:0;right:0;bottom:0;top:2em;z-index:50}#lms-ui-menu-panel.fullscreen-popup{display:unset}}#lms-ui-menu-panel #lms-ui-menu-panel-container{overflow-x:hidden;overflow-y:auto;margin-right:0;display:flex;flex-direction:column;justify-content:flex-start;align-items:center}#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-logo{margin-top:.3em;display:flex;justify-content:center;align-self:stretch}@media screen and (max-width:800px){#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-logo{display:none}}#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-logo :not(:first-child){margin-left:.3em;font-weight:700;align-self:flex-end}#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-logo a{color:initial}#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-logo a:hover{text-decoration:initial}#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-main-menu{margin-top:.5em;align-self:stretch}#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-session-expire{font-weight:700;color:#8b0000;align-self:stretch;text-align:center;margin-bottom:.5em}#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-division{align-self:stretch;text-align:center;margin-bottom:.5em;margin-left:.5em}#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-division>select{width:90%}@media screen and (max-width:801px){#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-division>select{font-size:80%;flex-grow:1}}#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-copyrights{font-weight:700;align-self:stretch;text-align:center;margin-bottom:.5em}@media screen and (max-width:801px){#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-copyrights{display:none}}#lms-ui-menu-panel-toggle{position:fixed;left:.15em;top:.15em;background-size:cover;width:.8em;height:.8em;cursor:pointer;z-index:3}@media screen and (max-width:800px){#lms-ui-menu-panel-toggle{display:none}}#lms-ui-menu-panel-toggle:not(.visible){background-color:#B6A688;padding:.1em 0 .3em .1em;border:1px solid #000;border-radius:0 0 .5em 0}@media screen and (min-width:801px){#lms-ui-menu-panel-toggle:not(.visible)~#lms-ui-contents #lms-ui-quicksearch-indicators-panel{padding-left:.5em}}#lms-ui-mobile-menu-container{position:fixed;left:0;right:0;top:0;height:2em;box-shadow:0 .7em .6em #EBE4D6;z-index:40;background-color:#EBE4D6;font-size:200%}@media screen and (min-width:801px){#lms-ui-mobile-menu-container{display:none}}#lms-ui-mobile-menu-container #lms-ui-mobile-menu-panel{border-bottom:1px solid #000;background-color:#CEBD9B;height:auto;width:100%}@media screen and (max-width:800px){#lms-ui-mobile-menu-container #lms-ui-mobile-menu-panel .lms-ui-button{margin-top:.2em;margin-bottom:.2em;border-radius:unset;border:0;border-right:1px solid #000}#lms-ui-mobile-menu-container #lms-ui-mobile-menu-panel .lms-ui-button:hover{border-radius:unset}}#lms-ui-modal-dialog ol{list-style:none;padding-left:0;width:90%}#lms-ui-modal-dialog ol li.message{font-weight:700}@media screen and (max-width:800px){.lms-ui-modal-dialog-wrapper{font-size:200%;position:fixed;left:0;right:0;top:0}.lms-ui-modal-dialog-wrapper .ui-dialog-titlebar-close{text-indent:unset;border:0!important;background-color:transparent!important;box-shadow:unset!important;right:.5em!important;top:40%!important}.lms-ui-modal-dialog-wrapper .ui-dialog-titlebar-close .lms-ui-icon-hide{position:absolute;text-indent:unset;width:0;height:0;left:0;top:0}}.chosen-container{text-align:left;min-width:250px;font-size:10pt;font-weight:initial}@media screen and (max-width:1920px){.chosen-container{font-size:9pt}}@media screen and (max-width:1200px){.chosen-container{font-size:8pt}}.chosen-container .chosen-results{color:#000}.chosen-container .chosen-results li.no-results{color:#000;background:#DFD5BD}.chosen-container .chosen-results li{padding:1px 6px}.chosen-container .chosen-results li em{background-color:#CEBD9B;font-weight:700;text-decoration:none}.chosen-container .chosen-results li.disabled-result{color:#888}.chosen-container.lms-ui-customer-address-select .chosen-single span{padding-top:1px;padding-bottom:1px}.chosen-container.lms-ui-customer-address-select .chosen-results li{padding:3px 6px}.chosen-container .chosen-drop{display:none;background-color:#EBE4D6;width:auto;min-width:15em}.chosen-container .chosen-drop li{white-space:nowrap}.chosen-container-active.chosen-with-drop .chosen-single{background-image:none}.chosen-container-active.chosen-with-drop .chosen-single div b{background-position-x:-12px;background-position-y:-2px}.chosen-with-drop .chosen-drop{display:block}.chosen-container-single.chosen-with-drop .chosen-single{border:1px solid #a9a9a9}.chosen-container-single .chosen-single{color:#000;background-color:#EBE4D6;background-image:none;line-height:normal;border-radius:unset;min-height:1.6em;height:unset;display:flex;align-items:center}.chosen-container-single .chosen-single div b{background-position-x:6px;background-position-y:-2px}.chosen-container-single.alert .chosen-single,.chosen-container-single.lms-ui-error .chosen-single,.chosen-container-single:invalid .chosen-single{border:1px solid red;box-shadow:0 0 3px 1px red}.chosen-container-single.alert .chosen-single:focus,.chosen-container-single.lms-ui-error .chosen-single:focus,.chosen-container-single:invalid .chosen-single:focus{border:1px solid #a32828;box-shadow:0 0 1px 1px #a32828;outline:0}.chosen-container-single.lms-ui-warning .chosen-single{border:1px solid Orange;background-color:Khaki;box-shadow:0 0 3px 1px Orange}.chosen-container-single.lms-ui-warning .chosen-single:focus{border:1px solid Orange;background-color:Khaki;box-shadow:0 0 1px 1px Orange}.chosen-container-single.lms-ui-distinguished .chosen-single{border:1px solid Orange;box-shadow:0 0 3px 1px Orange}.chosen-container-single.lms-ui-distinguished .chosen-single:focus{border:1px solid Orange;box-shadow:0 0 1px 1px Orange}.chosen-container-single .chosen-drop{border-radius:unset}.chosen-container-single .chosen-single-with-deselect span{margin-right:2em}.chosen-container-single .chosen-single abbr{top:2px;right:12px}.chosen-container-single .chosen-single div{width:18px}.chosen-container-multi .chosen-choices{color:#000;background-color:#EBE4D6;background-image:none;line-height:normal;border-radius:unset}.chosen-container-multi .chosen-choices div b{background-position-x:6px;background-position-y:-2px}.chosen-container-multi .chosen-choices li.search-choice{background-color:#DFD5BD;background-image:none;font-weight:700;border:1px solid #615847}.chosen-container-multi.alert .chosen-choices,.chosen-container-multi.lms-ui-error .chosen-choices,.chosen-container-multi:invalid .chosen-choices{border:1px solid red;box-shadow:0 0 3px 1px red}.chosen-container-multi.alert .chosen-choices:focus,.chosen-container-multi.lms-ui-error .chosen-choices:focus,.chosen-container-multi:invalid .chosen-choices:focus{border:1px solid #a32828;box-shadow:0 0 1px 1px #a32828;outline:0}.chosen-container-multi.lms-ui-warning .chosen-choices{border:1px solid Orange;background-color:Khaki;box-shadow:0 0 3px 1px Orange}.chosen-container-multi.lms-ui-warning .chosen-choices:focus{border:1px solid Orange;background-color:Khaki;box-shadow:0 0 1px 1px Orange}.chosen-container-multi.lms-ui-distinguished .chosen-choices{border:1px solid Orange;box-shadow:0 0 3px 1px Orange}.chosen-container-multi.lms-ui-distinguished .chosen-choices:focus{border:1px solid Orange;box-shadow:0 0 1px 1px Orange}.chosen-container-multi .chosen-drop .result-selected{color:#888}.scombobox{display:inline-block;margin:0}.scombobox-disabled .scombobox-display{cursor:no-drop}.scombobox-dropdown-background{background-color:transparent;border:unset}.scombobox-display{border-radius:unset;padding:0 19px 0 4px;min-height:1.6em}.scombobox-display.alert,.scombobox-display.lms-ui-error,.scombobox-display:invalid{border:1px solid red;box-shadow:0 0 3px 1px red}.scombobox-display.alert:focus,.scombobox-display.lms-ui-error:focus,.scombobox-display:invalid:focus{border:1px solid #a32828;box-shadow:0 0 1px 1px #a32828;outline:0}.scombobox-display.lms-ui-warning{border:1px solid Orange;background-color:Khaki;box-shadow:0 0 3px 1px Orange}.scombobox-display.lms-ui-warning:focus{border:1px solid Orange;background-color:Khaki;box-shadow:0 0 1px 1px Orange}.scombobox-list{border:1px solid #a9a9a9;box-shadow:0 8px 16px 0 rgba(0,0,0,.2);background-color:#EBE4D6;border-radius:unset}.scombobox-list p{padding:1px}.scombobox-list p:hover{background-color:#B6A688;color:#fff}.scombobox-list p.scombobox-hovered{background-color:#CEBD9B}.scombobox-list p.scombobox-hovered:hover{background-color:#B6A688;color:#fff}label>.lms-ui-customer-select-container{margin-left:.4em}.lms-ui-customer-select-container{display:flex;flex-wrap:wrap;align-items:center}.lms-ui-customer-select-container select{margin-right:.5em;max-width:35em}.lms-ui-customer-select-container .lms-ui-customer-select{display:inline-block;white-space:nowrap}.lms-ui-customer-select-container .lms-ui-customer-select>span{padding-right:.5em}.lms-ui-customer-select-container .lms-ui-customer-select .lms-ui-customer-select-customerid,.lms-ui-customer-select-container .lms-ui-customer-select .lms-ui-customer-select-suggestion-input{box-sizing:border-box;width:7em;margin-top:.5em;margin-bottom:.5em;padding-right:0}.lms-ui-customer-select-container .lms-ui-customer-select .lms-ui-customer-select-customerid:focus,.lms-ui-customer-select-container .lms-ui-customer-select .lms-ui-customer-select-suggestion-input:focus{padding-right:1.4em}.lms-ui-customer-select-container .lms-ui-customer-select .lms-ui-customer-select-customerid:focus+.lms-ui-customer-function-button,.lms-ui-customer-select-container .lms-ui-customer-select .lms-ui-customer-select-suggestion-input:focus+.lms-ui-customer-function-button{visibility:visible}.lms-ui-customer-select-container .lms-ui-customer-select .lms-ui-customer-function-button{display:inline-block;margin-left:-2.3em;vertical-align:middle;cursor:pointer;visibility:hidden}.lms-ui-customer-select-container .lms-ui-customer-select:hover .lms-ui-customer-select-customerid,.lms-ui-customer-select-container .lms-ui-customer-select:hover .lms-ui-customer-select-suggestion-input{padding-right:1.4em}.lms-ui-customer-select-container .lms-ui-customer-select:hover .lms-ui-customer-select-customerid+.lms-ui-customer-function-button,.lms-ui-customer-select-container .lms-ui-customer-select:hover .lms-ui-customer-select-suggestion-input+.lms-ui-customer-function-button{visibility:visible}.lms-ui-customer-select-container .lms-ui-customer-select-name{white-space:normal;padding-left:.8em;padding-right:.5em;flex-grow:1}.lms-ui-customer-select-container[data-version="2"] .lms-ui-customer-select .lms-ui-customer-select-customerid,.lms-ui-customer-select-container[data-version="2"] .lms-ui-customer-select .lms-ui-customer-select-suggestion-container{display:none}.lms-ui-customer-select-container[data-version="2"] .lms-ui-customer-select .lms-ui-customer-select-suggestion-input{min-width:10em}.lms-ui-customer-select-container[data-version="2"] .lms-ui-customer-select .lms-ui-customer-select-customerid[required]:invalid+.lms-ui-customer-select-suggestion-input{border:1px solid red;box-shadow:0 0 3px 1px red}.lms-ui-customer-select-container[data-version="2"] .lms-ui-customer-select .lms-ui-customer-select-customerid[required]:invalid+.lms-ui-customer-select-suggestion-input:focus{border:1px solid #a32828;box-shadow:0 0 1px 1px #a32828;outline:0}.lms-ui-customer-select-container.lms-ui-distinguished select{border:1px solid Orange;box-shadow:0 0 3px 1px Orange}.lms-ui-customer-select-container.lms-ui-distinguished select:focus{border:1px solid Orange;box-shadow:0 0 1px 1px Orange}.lms-ui-customer-select-container.lms-ui-distinguished .lms-ui-customer-select-name{border:1px solid Orange;box-shadow:0 0 3px 1px Orange}.lms-ui-hint-rollover:not(.ui-tooltip),.lms-ui-hint-toggle:not(.ui-tooltip){cursor:pointer}.lms-ui-hint-rollover .lms-ui-hint-titlebar,.lms-ui-hint-toggle .lms-ui-hint-titlebar{display:none;justify-content:flex-end}.lms-ui-hint-rollover .lms-ui-hint-titlebar .close-button,.lms-ui-hint-toggle .lms-ui-hint-titlebar .close-button{cursor:pointer}.lms-ui-hint-rollover.ui-tooltip,.lms-ui-hint-toggle.ui-tooltip{max-width:50vw}.lms-ui-hint-rollover.ui-tooltip .lms-ui-hint-titlebar,.lms-ui-hint-toggle.ui-tooltip .lms-ui-hint-titlebar{padding-bottom:.5em}.lms-ui-hint-rollover.ui-tooltip .lms-ui-hint-content,.lms-ui-hint-toggle.ui-tooltip .lms-ui-hint-content{max-height:90vh;overflow-y:auto;overflow-x:visible;padding-right:1em}@media screen and (max-width:800px){.lms-ui-hint-rollover.ui-tooltip,.lms-ui-hint-toggle.ui-tooltip{padding:0;font-size:200%}.lms-ui-hint-rollover.ui-tooltip,.lms-ui-hint-toggle.ui-tooltip{max-width:fit-content}.lms-ui-hint-rollover .ui-tooltip-content,.lms-ui-hint-toggle .ui-tooltip-content{padding:1em}.lms-ui-hint-rollover.ui-widget.ui-widget-content,.lms-ui-hint-toggle.ui-widget.ui-widget-content{border:0;position:fixed;left:0;top:0;width:100vw;height:100vh;max-width:unset;max-height:unset}.lms-ui-hint-rollover.ui-widget.ui-widget-content.ui-widget-shadow,.lms-ui-hint-toggle.ui-widget.ui-widget-content.ui-widget-shadow{box-shadow:unset}.lms-ui-hint-rollover .lms-ui-hint-titlebar,.lms-ui-hint-toggle .lms-ui-hint-titlebar{display:flex}}html{height:100%}html.fullscreen-popup{overflow:hidden}@media print{html{overflow:visible}}body{font-size:10pt;font-family:Arial,Helvetica,Verdana;background-color:#EBE4D6;margin:0;padding:0;margin-left:.5em}@media screen and (max-width:1920px){body{font-size:9pt}}@media screen and (max-width:1200px){body{font-size:8pt}}body.lms-ui-main-document{overflow:auto}body.fullscreen-popup{overflow:hidden}body.fullscreen-popup #lms-ui-contents{overflow:hidden}body.fullscreen-popup #lms-ui-module-view{overflow:hidden}body.fullscreen-popup #lms-ui-back-to-top{display:none;z-index:0}@media screen and (max-width:800px){body:not(.lms-ui-popup):not(.lms-ui-login-form){margin-top:4em}}body.lms-ui-popup{margin-left:0}body #lms-ui-tool-panels{margin-left:1.2em}@media screen and (max-width:800px){body #lms-ui-tool-panels{margin-left:0;top:4em;z-index:70;display:none}body #lms-ui-tool-panels.fullscreen-popup{display:block}body #lms-ui-tool-panels.fullscreen-popup .lms-ui-tool-panel:not(:first-child){display:none}}body.lms-ui-popup{display:block;height:auto;overflow:auto}TABLE{border-collapse:collapse;border-color:#000}#lms-ui-back-to-top{margin:.3em;position:fixed;opacity:.8;right:1.8em;bottom:.6em;z-index:60;transform:translateX(120px);transition:transform .4s .3s;will-change:transform}#lms-ui-back-to-top:hover{transform:translateX(10px)!important}@media screen and (max-width:800px){#lms-ui-back-to-top{font-size:130%}}#lms-ui-contents{overflow:visible;display:flex;flex-direction:column;justify-content:flex-start;align-items:flex-start;flex:1 1 auto;margin-bottom:.85em;padding:.43em}#lms-ui-contents>p{align-self:center}@media print{#lms-ui-contents{height:auto}}.lms-ui-tool-panel{flex:0 0 auto;display:flex;justify-content:flex-start;align-items:center;border-bottom:1px solid #000;padding-bottom:.3em;width:100%}.lms-ui-tool-panel:nth-child(n+2){padding-top:.3em}@media screen and (max-width:800px){.lms-ui-tool-panel{padding-bottom:0}}.lms-ui-indicator:hover{text-decoration:none}.lms-ui-indicator-counter{font-size:120%}#lms-ui-toolbar{display:flex;justify-content:space-between;flex:0 0 auto}#lms-ui-toolbar{justify-content:flex-start;flex-wrap:wrap;margin-top:-.5em}#lms-ui-toolbar .lms-ui-toolbar-shortcut{display:flex;justify-content:flex-start;margin-top:.5em}#lms-ui-toolbar .lms-ui-toolbar-shortcut:last-child{margin-left:auto;margin-right:.5em;display:flex;justify-content:flex-start}#lms-ui-toolbar .lms-ui-toolbar-shortcut-separator{padding-right:1.2em}#lms-ui-module-view{width:100%;overflow:visible}#lms-ui-module-view h1{margin-block-start:.4em;margin-block-end:.7em}#lms-ui-generation-time{text-align:center;color:#888}#lms-ui-dberrors{background-color:#F4F0EC;border:1px solid #000;padding:.3em;margin-top:.5em}#lms-ui-tool-panels{position:fixed;left:0;top:0;background-size:100% 100%;background-color:#EBE4D6;right:0;padding-top:.5em;box-shadow:0 1em .9em #EBE4D6;z-index:50}@media screen and (max-width:800px){#lms-ui-tool-panels{padding-top:0}}#lms-ui-quicksearch-indicators-panel{display:flex;justify-content:space-between;flex-wrap:wrap}@media screen and (max-width:800px){#lms-ui-quicksearch-indicators-panel{background-color:#CEBD9B}}.lms-ui-quick-search{display:flex;justify-content:flex-start;align-items:center;flex-wrap:wrap}@media screen and (max-width:800px){.lms-ui-quick-search{width:100%}.lms-ui-quick-search .lms-ui-quick-search-selector .lms-ui-multiselect-launcher{display:none}}.lms-ui-quick-search #lms-ui-quick-search-field-clear{font-size:200%;margin-right:.5em}@media screen and (min-width:801px){.lms-ui-quick-search #lms-ui-quick-search-field-clear{display:none}}@media screen and (max-width:800px){form.lms-ui-quick-search{flex-wrap:nowrap}}.lms-ui-quick-search-field{display:none;align-items:center;margin-left:.3em}.lms-ui-quick-search-field.visible{display:flex}@media screen and (max-width:800px){.lms-ui-quick-search-field.visible{display:none}}.lms-ui-quick-search-field .lms-ui-quick-search-icon,.lms-ui-quick-search-field img{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media screen and (max-width:800px){.lms-ui-quick-search-field{font-size:200%;display:none;flex-grow:1;margin:.5em;width:auto}.lms-ui-quick-search-field.lms-ui-quick-search-active{display:flex}.lms-ui-quick-search-field .lms-ui-multiselect-popup{font-size:inherit}}.lms-ui-quick-search-field>input{padding-right:1.2em;padding-top:.3em;padding-bottom:.3em;padding-left:.3em;margin-left:.3em;display:inline-block}.lms-ui-quick-search-field>input:last-child{padding-right:.3em;width:2.95em}.lms-ui-quick-search-field>input:not(:last-child){width:1.7em}@media screen and (max-width:800px){.lms-ui-quick-search-field>input{font-size:inherit;margin-left:.7em;width:100%;border-color:#000!important}}.lms-ui-quick-search-field>input.lms-ui-quick-search-active{width:8.4em}@media screen and (max-width:800px){.lms-ui-quick-search-field>input.lms-ui-quick-search-active{width:100%}}.lms-ui-quick-search-field>input.lms-ui-quick-search-input{min-width:3em}@media screen and (min-width:801px){.lms-ui-quick-search-field>input.lms-ui-quick-search-input{min-height:2.2em}}.lms-ui-quick-search-field>input.lms-ui-quick-search-input+div{margin-left:-1.8em;visibility:hidden}@media screen and (max-width:800px){.lms-ui-quick-search-field>input.lms-ui-quick-search-input+div{margin-left:-2em}}.lms-ui-quick-search-field>input.lms-ui-quick-search-input+div.open{visibility:visible}.lms-ui-quick-search-field>input:focus{padding-right:1.2em}.lms-ui-quick-search-field>input:focus:last-child{padding-right:.3em}.lms-ui-quick-search-field>input:focus+div{visibility:visible}.lms-ui-quick-search-field:hover input{padding-right:1.2em}.lms-ui-quick-search-field:hover input:last-child{padding-right:.3em}.lms-ui-quick-search-field:hover input+div{visibility:visible}.lms-ui-quick-search-field .fab,.lms-ui-quick-search-field .fal,.lms-ui-quick-search-field .far,.lms-ui-quick-search-field .fas{font-size:1.5em}.lms-ui-quick-search-selector{margin-left:.45em;cursor:pointer}#lms-ui-indicators{margin-left:auto;margin-right:1em}@media screen and (max-width:800px){#lms-ui-indicators{display:none}}#lms-ui-welcome-boxes{width:100%;display:flex;flex-direction:column;justify-content:stretch;align-items:stretch}#lms-ui-welcome-main-panels{width:100%;display:flex;justify-content:stretch;align-items:stretch;flex-wrap:wrap}.lms-ui-welcome-main-panel{padding:.17em;flex:1 1 auto}.lms-ui-welcome-main-panel.empty{flex:0 0 auto;min-width:2em;min-height:30%}.lms-ui-welcome-box-placeholder{min-width:20em;min-height:20em;margin:0 1em 1em 0;border:1px solid #000}#lms-ui-welcome-extra-panel{align-self:stretch}#lms-ui-welcome-bottom-panel{align-self:stretch}.bottomline{border-bottom-style:solid;border-bottom-width:1px;border-bottom-color:#CEBD9B}TD{font-size:10pt;font-family:Arial,Helvetica,Verdana;vertical-align:middle;border-color:#000}@media screen and (max-width:1920px){TD{font-size:9pt}}@media screen and (max-width:1200px){TD{font-size:8pt}}td[onclick]{cursor:pointer}.fleft{border-left-width:1pt;border-left-style:solid}.fright{border-right-width:1pt;border-right-style:solid}.ftop{border-top-width:1pt;border-top-style:solid}.fbottom{border-bottom-width:1pt;border-bottom-style:solid}.fleftu{border-top-width:1pt;border-top-style:solid;border-bottom-width:1pt;border-bottom-style:solid;border-left-width:1pt;border-left-style:solid}.frightu{border-top-width:1pt;border-top-style:solid;border-bottom-width:1pt;border-bottom-style:solid;border-right-width:1pt;border-right-style:solid}.ftopu{border-top-width:1pt;border-top-style:solid;border-left-width:1pt;border-left-style:solid;border-right-width:1pt;border-right-style:solid}.fbottomu{border-bottom-width:1pt;border-bottom-style:solid;border-left-width:1pt;border-left-style:solid;border-right-width:1pt;border-right-style:solid}.fall{border-width:1pt;border-style:solid}.fbt{border-bottom-width:1pt;border-bottom-style:solid;border-top-width:1pt;border-top-style:solid}.fbl{border-bottom-width:1pt;border-bottom-style:solid;border-left-width:1pt;border-left-style:solid}.fbr{border-bottom-width:1pt;border-bottom-style:solid;border-right-width:1pt;border-right-style:solid}.ftl{border-top-width:1pt;border-top-style:solid;border-left-width:1pt;border-left-style:solid}.ftr{border-top-width:1pt;border-top-style:solid;border-right-width:1pt;border-right-style:solid}.flr{border-left-width:1pt;border-left-style:solid;border-right-width:1pt;border-right-style:solid}.loginform{border-width:1pt;border-style:solid;border-color:#888}.hand{cursor:pointer}.container{padding:0}FORM{display:inline}label{cursor:pointer;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}label>input[type=checkbox]{margin-right:.6em}label>.lms-ui-multiselect-container,label>input[type=text],label>select{margin-left:.4em}A{text-decoration:none;vertical-align:baseline}A:link{color:maroon}A:active{color:#360}A:visited{color:maroon}A.blend{color:#888}A:hover{text-decoration:underline;color:#360;cursor:pointer}A.disabled{color:#888!important;cursor:no-drop}A.disabled:hover{text-decoration:none}A[href^="mailto:"]{font-family:'Fira Code',monospace}.lms-ui-tab-table-row.blend A,TR.blend A{color:#888}.lms-ui-tab-table-row.alertblend A,TR.alertblend A{color:salmon}.lms-ui-tab-table-row.suspended A,TR.suspended A{color:#30B6C6}P{font-size:10pt;font-family:Arial,Helvetica,Verdana}@media screen and (max-width:1920px){P{font-size:9pt}}@media screen and (max-width:1200px){P{font-size:8pt}}@media screen and (max-width:800px){P{font-size:8pt}}P.nor{font-size:10pt;font-family:Arial,Helvetica,Verdana}@media screen and (max-width:1920px){P.nor{font-size:9pt}}@media screen and (max-width:1200px){P.nor{font-size:8pt}}P.txt{font-size:10pt;font-family:Arial,Helvetica,Verdana;text-align:justify}@media screen and (max-width:1920px){P.txt{font-size:9pt}}@media screen and (max-width:1200px){P.txt{font-size:8pt}}P.separated{font-size:10pt;font-family:Arial,Helvetica,Verdana;margin-top:5px;margin-bottom:5px}@media screen and (max-width:1920px){P.separated{font-size:9pt}}@media screen and (max-width:1200px){P.separated{font-size:8pt}}H1{font-size:14pt;font-family:Arial,Helvetica,Verdana}H2{font-size:12pt;font-family:Arial,Helvetica,Verdana}H3{font-size:10pt;font-family:Arial,Helvetica,Verdana}HR{border:0;height:1px;color:#000;background-color:#000}input[type=text],input[type=email],input[type=search],input[type=number],input[type=tel],input[type=password],input[type=submit],input[type=button]{border:1px solid #a9a9a9;background-color:#EBE4D6;min-height:1.4em;padding:.1em;padding-left:.4em;box-sizing:border-box}input[type=text][disabled]{border:1px dashed grey;background-color:transparent}input[type=text][disabled]+label{color:#888}input[type=checkbox][disabled]{background-color:transparent}input[type=checkbox][disabled]+label{color:#888}input[type=radio][disabled]{background-color:transparent}input[type=radio][disabled]+label{color:#888}select[disabled]+label{color:#888}input[type=radio]{vertical-align:text-bottom}.lms-ui-disabled{color:#888}.lms-ui-disabled *{color:inherit}input[type=checkbox][disabled]+.lms-ui-label,input[type=radio][disabled]+.lms-ui-label{color:#888}input{font-size:10pt;font-family:Arial,Helvetica,Verdana;vertical-align:middle}@media screen and (max-width:1920px){input{font-size:9pt}}@media screen and (max-width:1200px){input{font-size:8pt}}input.alert,input.lms-ui-error,input:invalid{border:1px solid red;box-shadow:0 0 3px 1px red}input.alert:focus,input.lms-ui-error:focus,input:invalid:focus{border:1px solid #a32828;box-shadow:0 0 1px 1px #a32828;outline:0}input.lms-ui-warning{border:1px solid Orange;background-color:Khaki;box-shadow:0 0 3px 1px Orange}input.lms-ui-warning:focus{border:1px solid Orange;background-color:Khaki;box-shadow:0 0 1px 1px Orange}input.lms-ui-distinguished{border:1px solid Orange;box-shadow:0 0 3px 1px Orange}input.lms-ui-distinguished:focus{border:1px solid Orange;box-shadow:0 0 1px 1px Orange}input[type=checkbox].alert,input[type=checkbox].lms-ui-error,input[type=checkbox]:invalid,input[type=radio].alert,input[type=radio].lms-ui-error,input[type=radio]:invalid{outline:0;box-shadow:0 0 3px 2px red}input[type=checkbox].alert:focus,input[type=checkbox].lms-ui-error:focus,input[type=checkbox]:invalid:focus,input[type=radio].alert:focus,input[type=radio].lms-ui-error:focus,input[type=radio]:invalid:focus{box-shadow:0 0 2px 2px #a32828}input[type=checkbox].lms-ui-distinguished,input[type=checkbox].lms-ui-warning,input[type=radio].lms-ui-distinguished,input[type=radio].lms-ui-warning{outline:0;box-shadow:0 0 3px 2px Orange}input[type=checkbox].lms-ui-distinguished:focus,input[type=checkbox].lms-ui-warning:focus,input[type=radio].lms-ui-distinguished:focus,input[type=radio].lms-ui-warning:focus{box-shadow:0 0 2px 2px Orange}input.hiddenbtn{display:none!important}input.blend{border-style:solid;border-color:silver;border-width:1px;vertical-align:middle;color:#000}input.scroller{border-style:solid;border-color:grey;border-width:1px;vertical-align:middle;background-color:#DFD5BD}input[readonly]{color:#888!important;cursor:no-drop}input[readonly]:hover{text-decoration:none}textarea{font-size:10pt;font-family:Arial,Helvetica,Verdana;border:1px solid #a9a9a9;background-color:#EBE4D6;vertical-align:middle}@media screen and (max-width:1920px){textarea{font-size:9pt}}@media screen and (max-width:1200px){textarea{font-size:8pt}}textarea[disabled]{border:1px dashed grey;background-color:transparent}textarea.alert,textarea.lms-ui-error,textarea:invalid{border:1px solid red;box-shadow:0 0 3px 1px red}textarea.alert:focus,textarea.lms-ui-error:focus,textarea:invalid:focus{border:1px solid #a32828;box-shadow:0 0 1px 1px #a32828;outline:0}textarea.lms-ui-distinguished,textarea.lms-ui-warning{border:1px solid Orange;box-shadow:0 0 3px 1px Orange;background-color:Khaki}textarea.lms-ui-distinguished:focus,textarea.lms-ui-warning:focus{border:1px solid Orange;box-shadow:0 0 1px 1px Orange;outline:0}select{font-size:10pt;min-height:1.6em;font-family:Arial,Helvetica,Verdana;background-color:#EBE4D6;vertical-align:middle;-moz-appearance:none;-webkit-appearance:none;appearance:none;background-image:url(../img/1.png);background-repeat:no-repeat;background-position:right center;padding-right:16px;padding-left:3px;border:1px solid #a9a9a9}@media screen and (max-width:1920px){select{font-size:9pt}}@media screen and (max-width:1200px){select{font-size:8pt}}select.alert,select.lms-ui-error,select:invalid{border:1px solid red;box-shadow:0 0 3px 1px red}select.alert:focus,select.lms-ui-error:focus,select:invalid:focus{border:1px solid #a32828;box-shadow:0 0 1px 1px #a32828;outline:0}select.lms-ui-warning{border:1px solid Orange;box-shadow:0 0 3px 1px Orange;background-color:Khaki}select.lms-ui-warning:focus{border:1px solid Orange;box-shadow:0 0 1px 1px Orange;outline:0}select.lms-ui-distinguished{border:1px solid Orange;box-shadow:0 0 3px 1px Orange}select.lms-ui-distinguished:focus{border:1px solid Orange;box-shadow:0 0 1px 1px Orange;outline:0}IMG{vertical-align:middle;border:0}.lms-ui-cell-flex{display:inline-flex;align-items:center}.lms-ui-cell-flex>:not(:last-child){margin-right:.3em}.click-menu{padding:0 0;margin-top:0;margin-bottom:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.click-menu i{text-align:center}.click-menu i.fab,.click-menu i.fal,.click-menu i.far,.click-menu i.fas{font-size:1.5em;width:1.5em}.click-menu .box1{background-color:#CEBD9B;color:#000;font-weight:700;padding:.45em .45em;cursor:default;position:relative;white-space:nowrap}@media screen and (max-width:800px){.click-menu .box1{border-bottom:1px dotted grey}}.click-menu .box1-hover{background-color:#CFC;color:maroon;font-weight:700;padding:.45em .45em;cursor:default;position:relative;white-space:nowrap}@media screen and (max-width:800px){.click-menu .box1-hover{border-bottom:1px dotted grey}}.click-menu .box1-open{background-color:#DACAB2;color:maroon;font-weight:700;padding:.45em .45em;cursor:default;position:relative;white-space:nowrap}.click-menu .box1-open-hover{background-color:#CFC;color:maroon;font-weight:700;padding:.45em .45em;cursor:default;position:relative;white-space:nowrap}.click-menu .section{background-color:#EBE4D6;line-height:1.25em;padding:0;display:none}.click-menu .section a{color:maroon;text-decoration:none;white-space:nowrap}.click-menu .section a:hover{color:#360;text-decoration:none;white-space:nowrap}.click-menu .section .active,.click-menu .section .active:hover{color:#ff0}@media screen and (max-width:800px){.click-menu .box2{border-bottom:1px dotted grey}}.click-menu .box2-hover{background-color:#CFC;font-weight:400}.click-menu .box2 a,.click-menu .box2-hover a{display:block;padding-left:1.85em;font-weight:400;padding-top:.08em;padding-bottom:.08em}.dark{background-color:#CEBD9B}.superdark{background-color:#B6A688}.light{background-color:#DFD5BD}.lucid{background-color:#EBE4D6}.superlight{background-color:#F4F0EC}.highlight:hover{background-color:#CFC}.blendbg{background-color:#888}.blend{color:#888}.teal{color:teal}.transformed .comment{text-decoration:line-through}.green{color:green}.red{color:red}.brown{color:brown}.white{color:#FFF}.tox-tinymce.invalid,.tox-tinymce.lms-ui-error{box-shadow:0 0 4px 2px red}.tox-tinymce.lms-ui-warning,.tox-tinymce:invalid{box-shadow:0 0 4px 2px Orange}.alert{color:red!important}.lms-ui-warning{color:Sienna!important}.lms-ui-alert{color:red!important}.alertblend{color:salmon}.suspended{color:#30B6C6}.bold{font-weight:700}.crossed{text-decoration:line-through}.lms-ui-crossed{text-decoration:line-through;text-decoration-color:rgba(0,0,0,.2);text-decoration-thickness:.2em}.pre{font-size:10pt;font-family:Courier,Courier New}@media screen and (max-width:1920px){.pre{font-size:9pt}}@media screen and (max-width:1200px){.pre{font-size:8pt}}.lms-ui-suggestion-container{background-color:#EBE4D6;border:1px solid;padding:0;min-width:350px;position:absolute;display:none;box-shadow:0 8px 16px 0 rgba(0,0,0,.2)}@media screen and (max-width:800px){.lms-ui-suggestion-container{position:static;font-size:150%;border:0;width:100%;border-top:1px solid #000}.lms-ui-suggestion-container .lms-ui-suggestion-item{flex-direction:column;align-items:unset!important}.lms-ui-suggestion-container .lms-ui-suggestion-item .lms-ui-suggestion-name{font-size:inherit}.lms-ui-suggestion-container .lms-ui-suggestion-item .lms-ui-suggestion-name i{padding:.3em}.lms-ui-suggestion-container .lms-ui-suggestion-item .lms-ui-suggestion-description{padding-top:.4em;font-size:90%}}@media screen and (min-width:801px){.lms-ui-suggestion-container{z-index:55}}.lms-ui-suggestion-container:hover{cursor:pointer}.lms-ui-suggestion-container .lms-ui-suggestion-list{list-style-type:none;padding:0;margin:0;padding-top:.5em;padding-bottom:.5em}@media screen and (max-width:800px){.lms-ui-suggestion-container .lms-ui-suggestion-list{overflow:auto;max-height:calc(100vh - 11em)}}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item{display:flex;justify-content:space-between;align-items:center;padding-top:.2em;padding-bottom:.2em;padding-left:.5em;padding-right:.5em}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item:not(:last-child){border-bottom:#CEBD9B dotted 1px}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item.selected{background-color:#CFC}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item.selected a{color:#000}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item a{text-decoration:none;padding-left:2px;color:#000}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-icon{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name{padding-top:2px;color:#000}@media screen and (min-width:801px){.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name{font-size:12px}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name i{font-size:100%;padding:.3em}}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.blend{color:#888}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.red{color:red}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-customer-status-awaiting::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/wait.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-customer-status-interested::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/unk.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-customer-status-disconnected::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/node_off.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-customer-status-debtcollection::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/money.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-node-status-unknown::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/node_unk.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-node-status-online::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/node_on.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-node-status-offline::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/node_off.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-netdevice::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/netdev.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-wireless::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/wireless.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-wireless-uni{color:teal}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-wireless-uni::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/wireless.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-wireless-nni{color:brown}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-wireless-nni::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/wireless.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-network::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/network.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-netnode::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/netnode.png)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-customer-status-connected::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/customer.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-ticket-state-new{color:red}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-ticket-state-new::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/new.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-ticket-state-open::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/open.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-ticket-state-resolved{color:#888}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-ticket-state-resolved::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/resolved.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-ticket-state-dead::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/dead.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-ticket-state-scheduled::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/calendar.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-ticket-state-waiting::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/calendar.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-ticket-state-verified::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/verifier.png)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-phone::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/phone.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-description{margin-right:2px;color:brown;padding-left:20px;text-align:right}@media screen and (min-width:801px){.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-description{font-size:10px}}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-description>a{color:brown}.lms-ui-customer-status-connected{color:#000}.lms-ui-customer-status-awaiting{color:green}.lms-ui-customer-status-interested{color:#000}.lms-ui-customer-status-disconnected{text-decoration-line:line-through}.lms-ui-customer-status-debt-collection{color:red}.lms-ui-assignment-not-commited{text-decoration:line-through;text-decoration-color:rgba(0,0,0,.2);text-decoration-thickness:.2em}.lms-ui-document-closed .lms-ui-tab-table-column:not(.buttons),.lms-ui-document-closed>td:not(:last-child){color:#888}.lms-ui-document-archived .lms-ui-tab-table-column:not(.buttons),.lms-ui-document-archived>td:not(:last-child){text-decoration:line-through}.acl{list-style-type:square}.overlib{min-width:10px;font-family:Arial,Helvetica,Verdana;background-color:#F4F0EC;padding:2px 4px;border:1px solid #333;border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px;box-shadow:#333 1px 1px 12px;-moz-box-shadow:1px 1px 12px #333;-webkit-box-shadow:#333 1px 1px 12px;behavior:url(img/pie.htc)}@media print{.no-print,.no-print *,.ui-tooltip{display:none!important}}.lms-ui-button{color:maroon;border-radius:3px;white-space:nowrap}.lms-ui-button:hover{color:#360;cursor:pointer;text-decoration:underline}.lms-ui-important-box{border:1px #000 solid;background-color:red;color:#fff;font-weight:700;padding:2px 7px 3px 7px}.lms-ui-fileupload{display:inline-flex;flex-direction:column;justify-content:center}.lms-ui-fileupload .lms-ui-button-fileupload.lms-ui-fileupload-dropzone{box-shadow:0 0 10px 1px #000}.lms-ui-fileupload .fileupload-files{display:flex;flex-direction:column}.lms-ui-fileupload .fileupload-files>div{margin-top:.3em;margin-bottom:.3em}.lms-ui-fileupload .fileupload-files .fileupload-file{display:flex;flex-direction:column;width:fit-content}.lms-ui-fileupload .fileupload-files .fileupload-file-info{display:flex;align-items:center}.lms-ui-fileupload .fileupload-files .fileupload-file-info .file-delete{margin-right:.7em}.lms-ui-fileupload .fileupload-files .fileupload-file-options{display:flex;align-items:center;margin-top:.5em;justify-content:space-between}.lms-ui-fileupload .fileupload-files .fileupload-file-options input[type=text]{margin-left:1em;flex-grow:1;min-width:17em}.lms-ui-rtmessage-current,.lms-ui-rtsystemmessage-current{box-shadow:0 0 .3em .3em brown}.lms-ui-multi-check-all{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}table.lmsbox{margin:0 2px 4px 0}table.lmsbox,table.lmsbox-inner,table.lmsbox-innerbox{width:100%}table.lmsbox td,table.lmsbox-inner td,table.lmsbox-innerbox td{padding:.3em;padding-left:.5em}table.lmsbox td.lms-ui-box-buttons,table.lmsbox-inner td.lms-ui-box-buttons,table.lmsbox-innerbox td.lms-ui-box-buttons{background-image:linear-gradient(to right,#000 33%,rgba(255,255,255,0) 0);background-position:left .5em;background-size:3px 1px;background-repeat:repeat-x;padding:1em .5em .5em .5em}table.lmsbox td.lms-ui-box-buttons>:not(:first-child),table.lmsbox-inner td.lms-ui-box-buttons>:not(:first-child),table.lmsbox-innerbox td.lms-ui-box-buttons>:not(:first-child){margin-left:.3em}table.lmsbox td.lms-ui-box-buttons .lms-ui-box-button-container,table.lmsbox-inner td.lms-ui-box-buttons .lms-ui-box-button-container,table.lmsbox-innerbox td.lms-ui-box-buttons .lms-ui-box-button-container{display:flex;flex-wrap:wrap;align-items:center}table.lmsbox td.lms-ui-box-buttons .lms-ui-box-button-container>:not(:first-child),table.lmsbox-inner td.lms-ui-box-buttons .lms-ui-box-button-container>:not(:first-child),table.lmsbox-innerbox td.lms-ui-box-buttons .lms-ui-box-button-container>:not(:first-child){margin-left:.3em}table.lmsbox td.empty-table,table.lmsbox-inner td.empty-table,table.lmsbox-innerbox td.empty-table{text-align:center;font-weight:700;padding:2.5em}table.lmsbox-inner>thead,table.lmsbox-innerbox>thead,table.lmsbox>thead{background-color:#CEBD9B}table.lmsbox-inner>tbody,table.lmsbox>tbody{background-color:#DFD5BD}table.lmsbox-innerbox>tfoot,table.lmsbox-innerbox>thead,table.lmsbox>tbody,table.lmsbox>tfoot,table.lmsbox>thead{border-width:1px;border-style:solid;border-color:#000}table.lmsbox-inner>tfoot{border-top:1px solid #000}table.lmsbox-inner td{border-spacing:0}table.lmsbox-inner>thead,table.lmsbox-innerbox>tfoot,table.lmsbox-innerbox>thead{background-color:#CEBD9B}table.lmsbox>tfoot>tr,table.lmsbox>thead>tr:not(:first-child){border-top:1px solid #000}table.lmsbox tr.lms-ui-button-panel,table.lmsbox-inner tr.lms-ui-button-panel{background-color:#CEBD9B}table.lmsbox tr.lms-ui-button-panel>td,table.lmsbox-inner tr.lms-ui-button-panel>td{border-top:1px solid #000}table.lmsbox tr.lms-ui-header-panel>td,table.lmsbox-inner tr.lms-ui-header-panel>td{border-bottom:1px solid #000}table.lmsbox.lms-ui-tab-container{margin-top:.7em}table.lmsbox.lms-ui-tab-container>thead{background-color:#B6A688}table.lmsbox.lms-ui-tab-container>thead>.lmsbox-titlebar :not(.lms-ui-button)>i{width:1.3em;text-align:center;margin-right:.5em}table.lmsbox.lms-ui-tab-container>thead>.lmsbox-titlebar .lms-ui-karma-container i{width:auto;margin-right:0}table.lmsbox.lms-ui-tab-container>thead>.lmsbox-titlebar>td:last-child{padding-right:.5em}table.lmsbox>thead{text-align:left}table.lmsbox-inner>tfoot,table.lmsbox>tfoot{background-color:#DFD5BD}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr.lms-ui-distinguished-row,table.lmsbox.lms-ui-background-cycle>tbody>tr.lms-ui-distinguished-row{font-weight:700;background-color:#CEBD9B!important;border-top-width:1pt;border-top-style:solid;border-bottom-width:1pt!important;border-bottom-style:solid!important}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr.highlight:hover,table.lmsbox.lms-ui-background-cycle>tbody>tr.highlight:hover{background-color:#CFC!important}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(even),table.lmsbox.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(even){background-color:#DFD5BD}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(even).cancel,table.lmsbox.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(even).cancel{background-color:#ffb1b1}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(odd),table.lmsbox.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(odd){background-color:#EBE4D6}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(odd).cancel,table.lmsbox.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(odd).cancel{background-color:#fccdcd}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):not(:last-child),table.lmsbox.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):not(:last-child){border-bottom:1px dotted grey}table.lmsbox.lms-ui-background-cycle>tbody>tr.highlight:hover{background-color:#CFC!important}table.lmsbox.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(even):not(.ui-selected){background-color:#DFD5BD}table.lmsbox.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(even):not(.ui-selected).cancel{background-color:#ffb1b1}table.lmsbox.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(odd):not(.ui-selected){background-color:#EBE4D6}table.lmsbox.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(odd):not(.ui-selected).cancel{background-color:#fccdcd}table.lmsbox.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):not(:last-child){border-bottom:1px dotted grey}table.lmsbox-inner.dataTable>thead{background-color:#CEBD9B}table.lmsbox-inner:not(.dataTable)>thead{background-color:#DFD5BD}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr,table.lmsbox.lms-ui-background-cycle>tbody>tr{border-bottom:1px dotted grey}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr.lms-ui-resource-deleted:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(even),table.lmsbox.lms-ui-background-cycle>tbody>tr.lms-ui-resource-deleted:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(even){background-color:#ffb1b1}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr.lms-ui-resource-deleted:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(odd),table.lmsbox.lms-ui-background-cycle>tbody>tr.lms-ui-resource-deleted:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(odd){background-color:#fccdcd}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr.lms-ui-resource-deleted:not(.lms-ui-button-panel):not(.lms-ui-header-panel).highlight:hover,table.lmsbox.lms-ui-background-cycle>tbody>tr.lms-ui-resource-deleted:not(.lms-ui-button-panel):not(.lms-ui-header-panel).highlight:hover{background-color:#CFC}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr.lms-ui-resource-partly-deleted:nth-child(even),table.lmsbox.lms-ui-background-cycle>tbody>tr.lms-ui-resource-partly-deleted:nth-child(even){background-image:repeating-linear-gradient(145deg,transparent,transparent 10px,#ffb1b1 10px,#ffb1b1 20px)}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr.lms-ui-resource-partly-deleted:nth-child(odd),table.lmsbox.lms-ui-background-cycle>tbody>tr.lms-ui-resource-partly-deleted:nth-child(odd){background-image:repeating-linear-gradient(145deg,transparent,transparent 10px,#fccdcd 10px,#fccdcd 20px)}table.lmsbox .lmsbox-panels{width:100%;display:flex;flex-direction:row;justify-content:flex-start;align-items:flex-start;flex-wrap:wrap}table.lmsbox .lmsbox-panels>.lmsbox-panel{flex-grow:1}table.lmsbox .lmsbox-panels>.lmsbox-panel:last-child{margin-right:2em}@media screen and (min-width:470px){table.lmsbox .lmsbox-panels>.lmsbox-panel:last-child{margin-right:7em}}.lms-ui-rtmessage-deleted.light{background-color:#ffb1b1}.lms-ui-rtmessage-deleted.lucid{background-color:#fccdcd}table.lms-ui-datatable>tbody tr:nth-child(even):not(.ui-selected){background-color:#DFD5BD}table.lms-ui-datatable>tbody tr:nth-child(odd):not(.ui-selected){background-color:#EBE4D6}table.lms-ui-datatable>tbody tr:not(:last-child):not(.highlight) td{border-bottom:1px dotted grey}table.lms-ui-datatable>tbody tr.parent:not(.highlight):nth-child(4n+1){background-color:#DFD5BD}table.lms-ui-datatable>tbody tr.parent:not(.highlight):nth-child(4n+3){background-color:#EBE4D6}table.lms-ui-datatable>tbody tr.parent:not(.highlight) td{border-bottom:0}table.lms-ui-datatable>tbody tr.child:nth-child(4n+2){background-color:#DFD5BD}table.lms-ui-datatable>tbody tr.child:nth-child(4n+4){background-color:#EBE4D6}table.lms-ui-datatable>tbody tr.child:not(:last-child){border-bottom:1px dotted grey}table.lms-ui-datatable>tbody tr.parent.highlight{background-color:#CFC!important}table.lms-ui-datatable>tbody tr:hover{background-color:#CFC!important}table.lms-ui-datatable>tbody tr:hover.child,table.lms-ui-datatable>tbody tr:hover.parent+.child{background-color:#CFC!important}table.dataTable>tbody>tr.child ul.dtr-details>li{border-bottom:0;padding:0}table.dataTable>tbody>tr.child ul.dtr-details>li:last-child span.dtr-title{display:none}tr.space_row>td{padding-top:20px}.summary{text-align:right;font-weight:700}.buttons{text-align:right}.navigation{text-align:center;white-space:nowrap;background-color:#CEBD9B}.lms-ui-pagination{background-color:#CEBD9B;text-align:center}.lms-ui-pagination>span{display:inline-flex;flex-wrap:wrap;align-items:center}.lms-ui-pagination>span>*{padding-left:.2em;padding-right:.2em}td.empty-table{background-color:#EBE4D6;text-align:center;font-weight:700;padding:2.5em}td.multiselect{min-width:230px}td.multiselect select{min-width:200px}.lms-ui-selectable-draggable-active{box-shadow:0 0 15px 0 rgba(0,0,0,.75)}.lms-ui-selectable-draggable-active.lms-ui-selectable-draggable-hover{box-shadow:0 0 25px 0 rgba(0,0,0,.75)}.lms-inline-list{display:inline;list-style:none;padding:0}.lms-inline-list li{display:inline}.lms-inline-list li:after{content:', '}.lms-inline-list li:last-child:after{content:''}.nobr{white-space:nowrap}.line-break{white-space:normal!important}.text-right{text-align:right}.text-left{text-align:left}.text-center{text-align:center}.font-normal{font-weight:400!important}.lighter{font-weight:lighter}.valign-top{vertical-align:top}div.valign-top{display:inline-flex;align-items:flex-start}div.valign-top>:not(:last-child){margin-right:.5em}div.valign-middle{display:inline-flex;align-items:center}div.valign-middle>:not(:last-child){margin-right:.5em}.valign-bottom{vertical-align:bottom}div.valign-bottom{display:inline-flex;align-items:flex-end}div.valign-bottom>:not(:last-child){margin-right:.5em}.cf:after,.cf:before{content:" ";display:table}.cf:after{clear:both}.lf{float:left}.rf{float:right}.wf{width:100%}.wh{width:50%}.wq{width:25%}.cancel{background:#ff6c6c}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-o-transform:rotate(90deg);writing-mode:lr-tb}.lms-ui-selectmenu-button .ui-selectmenu-text{padding-top:0}.lms-ui-selectmenu-button .ui-selectmenu-icon{height:15px}.ui-selectmenu-menu .ui-widget-content{background-color:#EBE4D6!important}.ui-selectmenu-menu .ui-widget-content .ui-menu-divider{margin:0}.fileupload-progress-label{position:absolute;left:48%;top:4px;font-weight:700;text-shadow:1px 1px 0 #fff}.xdsoft_datetimepicker{background-color:#DFD5BD;border:1px solid #B6A688}.xdsoft_datetimepicker .xdsoft_label{background-color:#DFD5BD}.xdsoft_datetimepicker .xdsoft_label>.xdsoft_select>div>.xdsoft_option{background-color:#F4F0EC}table.dataTable tbody tr.odd:not(.ui-selected){background-color:#EBE4D6}table.dataTable tbody tr.even:not(.ui-selected){background-color:#DFD5BD}table.dataTable tbody tr.ui-selected{background-color:#CEBD9B}table.dataTable tbody tr.highlight{background-color:#CFC}table.dataTable tbody td,table.dataTable tbody th{padding:2px}table.dataTable tbody td.dataTables_empty{padding:2em;font-weight:700}table.dataTable thead .sorting_asc{background-image:url(../img/asc_order.gif)}table.dataTable thead .sorting_desc{background-image:url(../img/desc_order.gif)}table.dataTable thead .sorting{background-image:none}table.dataTable thead td,table.dataTable thead th{padding-top:2px;padding-bottom:2px;padding-left:10px;padding-right:10px}table.dataTable thead tr th{border:none}table.dataTable thead tr:last-child th{border-bottom:1px solid #000}.dataTables_wrapper .dataTables_paginate .paginate_button.current,.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover{background:linear-gradient(to bottom,#CEBD9B 0,#B6A688 100%)}.dataTables_wrapper .dataTables_processing{background:linear-gradient(to right,rgba(174,157,123,0) 0,rgba(174,157,123,.9) 25%,rgba(174,157,123,.9) 75%,rgba(174,157,123,0) 100%)}.dataTables_wrapper .lmsbox.lms-ui-datatable{width:100%!important;border:1px solid #000;border-top:0;margin-bottom:0}.dataTables_wrapper .lmsbox.lms-ui-datatable table{width:100%!important}.dataTables_wrapper .top{background-color:#CEBD9B}.dataTables_wrapper .bottom{background-color:#CEBD9B}.lms-ui-tab-contents .dataTables_wrapper,.lmsbox .dataTables_wrapper{margin-bottom:0}.lms-ui-tab-contents .dataTables_wrapper .bottom,.lms-ui-tab-contents .dataTables_wrapper .top,.lmsbox .dataTables_wrapper .bottom,.lmsbox .dataTables_wrapper .top{border:0}.location-box-expandable{padding-top:2px}.address-full{display:inline-block;height:13px}.address-full:hover{cursor:pointer}.lms-ui-address-select{padding-left:4px;padding-right:4px;border:1px solid #a9a9a9!important;background-color:#EBE4D6!important;box-shadow:none!important;border-radius:0!important;color:#000!important}.lms-ui-address-select:hover{cursor:default}.lms-ui-address-select .ui-selectmenu-icon.ui-icon{background:url(../img/1.png)!important}.lms-ui-address-select.alert,.lms-ui-address-select.lms-ui-error{border:1px solid red!important;box-shadow:0 0 3px 1px red!important}.lms-ui-address-select.alert:focus,.lms-ui-address-select.lms-ui-error:focus{border:1px solid #a32828!important;box-shadow:0 0 1px 1px #a32828!important;outline:0}.lms-ui-address-select.lms-ui-warning{border:1px solid Orange!important;background-color:Khaki!important;box-shadow:0 0 3px 1px Orange!important}.lms-ui-address-select.lms-ui-warning:focus{border:1px solid Orange!important;background-color:Khaki!important;box-shadow:0 0 1px 1px Orange!important}.lms-ui-address-select.lms-ui-distinguished{border:1px solid Orange!important;box-shadow:0 0 3px 1px Orange!important}.lms-ui-address-select.lms-ui-distinguished:focus{border:1px solid Orange!important;box-shadow:0 0 1px 1px Orange!important}.lms-ui-menu-item-icon{width:1.5em;text-align:center;font-size:1.6em;vertical-align:middle;cursor:grab}.lms-ui-quick-search-icon{font-size:1.4em}.lms-ui-indicator-icon{font-size:1.5em;vertical-align:middle}.ui-tooltip.lms-ui-tooltip-eventinfoshort,.ui-tooltip.lms-ui-tooltip-nodelist{max-width:initial}.lms-ui-cursor-pointer:hover{cursor:pointer}.lms-ui-visibility-hidden{visibility:hidden!important}div.lms-ui-filter-container{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap}div.lms-ui-filter-container div.lms-ui-filter-definition{display:flex;flex-wrap:wrap;align-items:center;white-space:normal;max-width:80%}div.lms-ui-filter-container div.lms-ui-filter-definition>:not(script),div.lms-ui-filter-container div.lms-ui-filter-definition>form>:not(script){margin:.2em;display:inline-flex;flex-wrap:wrap;align-items:center}div.lms-ui-persistent-filter{display:flex;justify-content:flex-end;align-items:center}div.lms-ui-persistent-filter>*{margin:2px}div.lms-ui-persistent-filter .lms-ui-filter-name{display:none}.lms-ui-matched-text{background-color:#B6A688;font-weight:700}div.lms-ui-wysiwyg-editor{display:inline-flex;flex-direction:column;justify-content:flex-start;align-items:flex-start}div.lms-ui-wysiwyg-editor>label{padding-bottom:.5em}.lms-ui-dragslider-slave{box-shadow:0 0 10px 1px #000}.lms-ui-event-time-container{display:flex;flex-direction:column;width:90%;flex-grow:1}.lms-ui-event-time-container .lms-ui-event-time-top-panel{display:flex;flex-direction:row;flex-wrap:wrap}.lms-ui-event-time-container .lms-ui-event-time-top-panel .lms-ui-event-time-period{display:flex;flex-direction:column;flex-grow:1}.lms-ui-event-time-container .lms-ui-event-time-top-panel .lms-ui-event-time-period .lms-ui-event-time-date{display:flex;justify-content:flex-end}.lms-ui-event-time-container .lms-ui-event-time-top-panel .lms-ui-event-time-period .lms-ui-event-time-date:not(:first-child){margin-top:.5em}.lms-ui-event-time-container .lms-ui-event-time-top-panel .lms-ui-event-time-period .lms-ui-event-time-date>*{margin-left:.3em}.lms-ui-event-time-container .lms-ui-event-time-top-panel .lms-ui-event-whole-days{display:inline-flex;flex-direction:row;justify-content:flex-start;align-items:center;flex-grow:1;margin-left:1em}.lms-ui-event-time-container .lms-ui-event-time-bottom-panel{display:flex;flex-direction:column}.lms-ui-event-time-container .lms-ui-event-time-bottom-panel .lms-ui-event-time-legend{margin-top:1em;margin-left:-1.5em;height:2em;width:25em;transform:scale(.85);display:flex;flex-direction:row;white-space:nowrap}.lms-ui-event-time-container .lms-ui-event-time-bottom-panel .lms-ui-event-time-legend .lms-ui-event-time-legend-label{margin-left:-1.62em;transform:rotate(90deg) translateX(.3em) translateY(-.38em)}.lms-ui-event-time-container .lms-ui-event-time-bottom-panel .lms-ui-event-time-legend .lms-ui-event-time-legend-scale{transform:rotate(90deg) translateX(1.8em) translateY(.3em)}.lms-ui-event-time-container .lms-ui-event-time-bottom-panel .lms-ui-event-time-slider{width:25em;margin-left:1em;margin-top:.7em}.lms-ui-box-container{display:flex;flex-direction:column;justify-content:flex-start;align-items:flex-start;border:1px solid #000;background-color:#DFD5BD;margin-top:.2em;margin-bottom:.2em}.lms-ui-box-container .lms-ui-box-header{display:flex;flex-direction:row;justify-content:flex-start;align-items:center;align-self:stretch;padding:.25em;background-color:#CEBD9B;font-weight:700}.lms-ui-box-container .lms-ui-box-header>*{margin:.25em}.lms-ui-box-container>.lms-ui-box-header{border-bottom:1px solid #000}.lms-ui-box-container>.lms-ui-box-header-multi-row{display:flex;flex-direction:column;justify-content:flex-start;align-items:center;align-self:stretch;background-color:#CEBD9B;border-bottom:1px solid #000;padding:.25em}.lms-ui-box-container>.lms-ui-box-header-multi-row .lms-ui-box-header{padding:0}.lms-ui-box-container .lms-ui-box-contents{display:flex;flex-direction:row;justify-content:flex-start;align-items:flex-start;flex-wrap:wrap}.lms-ui-box-container .lms-ui-box-contents .lms-ui-box-panel{margin:.25em;display:inline-flex;flex-direction:column;justify-content:flex-start;align-items:flex-start}.lms-ui-box-container .lms-ui-box-contents .lms-ui-box-panel:not(:last-child){margin-right:10em}.lms-ui-box-container .lms-ui-box-contents .lms-ui-box-panel .lms-ui-box-row{display:flex;justify-content:flex-start;align-items:center}.lms-ui-box-container .lms-ui-box-contents .lms-ui-box-panel .lms-ui-box-row>*{margin:.25em}.lms-ui-box-container .lms-ui-box-contents .lms-ui-box-panel .lms-ui-box-row .lms-ui-box-row-label{font-weight:700}.lms-ui-box-container .lms-ui-box-contents .lms-ui-box-panel .lms-ui-box-row .lms-ui-box-row-field{display:flex;flex-direction:row;justify-content:flex-start;align-items:center}.lms-ui-box-container .lms-ui-box-contents .lms-ui-box-panel .lms-ui-box-row .lms-ui-box-row-field>*{margin-right:.3em}.lms-ui-box-container .lms-ui-box-contents .lms-ui-box-panel .lms-ui-box-row .lms-ui-box-row-field input{padding-left:.2em}.lms-ui-box-container .lms-ui-box-buttons{background-image:linear-gradient(to right,#000 33%,rgba(255,255,255,0) 0);background-position:left .5em;background-size:3px 1px;background-repeat:repeat-x;padding:1em .5em .5em .5em;align-self:stretch;flex-direction:row;justify-content:flex-end;align-items:center}.lms-ui-box-container .lms-ui-box-buttons>:not(:first-child){margin-left:.3em}div.lms-ui-tab-container{display:flex;flex-direction:column;justify-items:flex-start;border:1px solid #000;margin-top:.7em}div.lms-ui-tab-container:not(:last-child){margin-bottom:.3em}div.lms-ui-tab-container .lms-ui-tab-header{display:flex;flex-direction:row;justify-content:space-between;background-color:#B6A688;padding:.2em;cursor:pointer}div.lms-ui-tab-container .lms-ui-tab-header .lms-ui-tab-header-cell{display:flex;flex-direction:row;justify-content:flex-start;align-items:center;flex-wrap:wrap}div.lms-ui-tab-container .lms-ui-tab-header .lms-ui-tab-header-cell>:nth-child(n+2){margin-left:.2em}div.lms-ui-tab-container .lms-ui-tab-header .lms-ui-tab-header-cell>i{text-align:center;width:1.25em;margin-right:.5em}div.lms-ui-tab-container .lms-ui-tab-header .lms-ui-tab-header-cell:last-child{justify-content:flex-end}div.lms-ui-tab-container .lms-ui-tab-header .lms-ui-tab-header-cell:first-child{justify-content:flex-start}@media all and (max-width:768px){div.lms-ui-tab-container .lms-ui-tab-header .lms-ui-tab-header-cell:not(:first-child){flex-direction:column;align-items:flex-start}div.lms-ui-tab-container .lms-ui-tab-header .lms-ui-tab-header-cell>:nth-child(n+2){margin-left:0}}@media all and (max-width:768px){div.lms-ui-tab-container .lms-ui-tab-header{flex-direction:column}}div.lms-ui-tab-container .lms-ui-tab-contents{display:flex;flex-direction:column;justify-content:flex-start;border-top:1px solid #000}div.lms-ui-tab-container .lms-ui-tab-contents .lms-ui-tab-button-panel{display:flex;flex-direction:row;justify-content:space-between;padding:.2em;border-top:1px solid #000;background-color:#CEBD9B}div.lms-ui-tab-container .lms-ui-tab-contents .lms-ui-tab-button-panel>:nth-child(n+2){margin-left:.5em}div.lms-ui-tab-container .lms-ui-tab-contents .lms-ui-tab-button-panel .lms-ui-tab-buttons{display:flex;flex-direction:row;justify-content:flex-start;align-items:center;flex-wrap:wrap}div.lms-ui-tab-container .lms-ui-tab-contents .lms-ui-tab-button-panel .lms-ui-tab-buttons>:nth-child(n+2){margin-left:.5em}div.lms-ui-tab-container .lms-ui-tab-table-row{display:flex;flex-direction:row;flex-wrap:nowrap;width:100%}div.lms-ui-tab-container .lms-ui-tab-table-row:nth-child(even){background-color:#EBE4D6}div.lms-ui-tab-container .lms-ui-tab-table-row:nth-child(odd){background-color:#DFD5BD}div.lms-ui-tab-container .lms-ui-tab-table-row.lucid{background-color:#EBE4D6}div.lms-ui-tab-container .lms-ui-tab-table-row.light{background-color:#DFD5BD}div.lms-ui-tab-container .lms-ui-tab-table-row.header{background-color:#DFD5BD;border-bottom:1px solid #000}div.lms-ui-tab-container .lms-ui-tab-table-row.footer{padding-top:.2em;padding-bottom:.2em;background-color:#CEBD9B;border-top:1px solid #000}div.lms-ui-tab-container .lms-ui-tab-table-row.footer>:nth-child(n+2){margin-left:.5em}div.lms-ui-tab-container .lms-ui-tab-table-row:not(.header):not(.footer):not(:last-child){border-bottom:1px dotted grey}div.lms-ui-tab-container .lms-ui-tab-table-row:not(.header):not(.footer):hover{background-color:#CFC}div.lms-ui-tab-container .lms-ui-tab-table-row .buttons>:last-child{margin-right:.4em}@media all and (max-width:768px){div.lms-ui-tab-container .lms-ui-tab-table-row .buttons{flex-direction:column!important;justify-content:flex-start!important;width:2em!important}div.lms-ui-tab-container .lms-ui-tab-table-row .buttons>*{margin-right:.5em;margin-top:.2em}}div.lms-ui-tab-container .lms-ui-tab-table-row .lms-ui-tab-table-wrapper{display:flex;flex-direction:row;flex-grow:0}div.lms-ui-tab-container .lms-ui-tab-table-row .lms-ui-tab-table-wrapper .lms-ui-tab-table-column,div.lms-ui-tab-container .lms-ui-tab-table-row .lms-ui-tab-table-wrapper [class*=col-],div.lms-ui-tab-container .lms-ui-tab-table-row .lms-ui-tab-table-wrapper.lms-ui-tab-table-column,div.lms-ui-tab-container .lms-ui-tab-table-row .lms-ui-tab-table-wrapper[class*=col-]{flex-grow:1;padding-top:.1em}div.lms-ui-tab-container .lms-ui-tab-table-row.footer .lms-ui-tab-table-wrapper{padding-top:0}div.lms-ui-tab-container .lms-ui-tab-table-row.footer .lms-ui-tab-table-wrapper .lms-ui-tab-table-column,div.lms-ui-tab-container .lms-ui-tab-table-row.footer .lms-ui-tab-table-wrapper [class*=col-],div.lms-ui-tab-container .lms-ui-tab-table-row.footer .lms-ui-tab-table-wrapper.lms-ui-tab-table-column,div.lms-ui-tab-container .lms-ui-tab-table-row.footer .lms-ui-tab-table-wrapper[class*=col-]{padding-top:0}div.lms-ui-tab-container .lms-ui-tab-table-column{padding-left:.5em;text-overflow:ellipsis}div.lms-ui-tab-container .lms-ui-tab-table-column.buttons{text-align:right;display:flex;flex-wrap:nowrap;justify-content:flex-end;align-items:center}div.lms-ui-tab-container .lms-ui-tab-table-column.buttons>:not(first-child){margin-left:.3em}div.lms-ui-tab-container div.lms-ui-tab-table .lms-ui-tab-empty-table{width:100%;text-align:center;font-weight:700;padding-top:3em;padding-bottom:3em}div.lms-ui-tab-container div.lms-ui-tab-table .lms-ui-tab-hourglass{width:100%;text-align:center;font-weight:700;padding-top:1em;padding-bottom:1em}div.lms-ui-tab-container div.lms-ui-tab-table .lms-ui-tab-hourglass>i{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%;animation:fa-spin 2s infinite linear;-webkit-animation:fa-spin .75s infinite linear!important;animation:fa-spin .75s infinite linear!important}div.lms-ui-tab-container div.lms-ui-tab-table .lms-ui-tab-hourglass>i.fa-pull-left{margin-right:.3em}div.lms-ui-tab-container div.lms-ui-tab-table .lms-ui-tab-hourglass>i.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){div.lms-ui-tab-container div.lms-ui-tab-table .lms-ui-tab-hourglass>i{font-size:125%}}div.lms-ui-tab-container div.lms-ui-tab-table .lms-ui-tab-hourglass>i:before{content:"\f2f1"}div.lms-ui-tab-container div.lms-ui-tab-table .lms-ui-tab-hourglass>i:before{color:#000}div.lms-ui-tab-container div.lms-ui-tab-table .lms-ui-tab-hourglass-template{display:none}i.lms-ui-hourglass{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%;animation:fa-spin 2s infinite linear;-webkit-animation:fa-spin .75s infinite linear!important;animation:fa-spin .75s infinite linear!important}i.lms-ui-hourglass.fa-pull-left{margin-right:.3em}i.lms-ui-hourglass.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){i.lms-ui-hourglass{font-size:125%}}i.lms-ui-hourglass:before{content:"\f2f1"}i.lms-ui-hourglass:before{color:#000}td.lms-ui-mac-address-selection{padding:0!important}table.lms-ui-mac-address-selection .mac td .remove-mac{visibility:hidden;margin-left:-2em;margin-top:.1em}table.lms-ui-mac-address-selection .mac:hover td .remove-mac{visibility:visible;cursor:pointer}table.lms-ui-mac-address-selection .mac .mac-selector{margin-left:.4em}.lms-ui-address-box [readonly]{border:none;background-color:transparent}.lms-ui-address-box .lms-ui-address-box-container{display:flex;align-items:center}.lms-ui-address-box .lms-ui-address-box-container .lms-ui-address-box-buttons{display:flex;flex-direction:column;margin-left:.5em}.lms-ui-address-box .lms-ui-address-box-container .lms-ui-address-box-buttons button:not(:first-child){margin-top:.2em}.lms-ui-location-add-button{margin-top:.3em;margin-bottom:.3em}.lms-ui-message-quote{color:#B6A688;border-left:3px solid #B6A688;border-right:3px solid #B6A688;background-color:#fff;margin:.2em 0;padding:0 .4em;overflow:hidden;text-overflow:ellipsis}fieldset{display:inline;border-radius:5px;border-width:1px;border-style:dotted;border-color:grey}.lms-ui-separated-rows tr:not(:first-child){border-top:1px dotted grey}.lms-ui-date-container,.lms-ui-datetime-container{display:inline-flex}.lms-ui-category-label{box-shadow:0 .1em .1em #888;border:1px solid #a9a9a9;background-color:#fff;color:#000;padding:.35em;text-decoration:none;border-radius:.45em;display:inline-block}#lms-ui-resource-tab-selector-container{display:none;margin-top:1em}#lms-ui-resource-tab-selector-container>div:first-child{font-weight:700;display:inline-block}.lms-ui-date-period-container{white-space:nowrap}.lms-ui-date-period-container>:not(:last-child){padding-right:.3em}.lms-ui-date-period-wrapper{display:inline}.lms-ui-date-period-wrapper .lms-ui-button.lms-ui-button-date-period{margin-top:0}@media screen and (min-width:801px){.lms-ui-date-period-wrapper .lms-ui-button.lms-ui-button-date-period{min-height:1.8em}}.lms-ui-day-selection-wrapper{display:inline}.lms-ui-day-selection-wrapper .lms-ui-button.lms-ui-button-day-selection{margin-top:0}@media screen and (min-width:801px){.lms-ui-day-selection-wrapper .lms-ui-button.lms-ui-button-day-selection{min-height:1.8em}}.lms-ui-karma-container{display:inline-block}.lms-ui-karma-container .lms-ui-karma-button{vertical-align:middle;cursor:pointer}.lms-ui-karma-container .lms-ui-karma-button.disabled{color:#888;cursor:no-drop}.lms-ui-deadline-selection{display:inline}.lms-ui-deadline-selection .scombobox{width:5em;display:inline-block}.lms-ui-fileview-dialog .ui-dialog-content{display:flex}.lms-ui-fileview-dialog .ui-dialog-content img,.lms-ui-fileview-dialog .ui-dialog-content object{width:100%;height:100%}.lms-ui-message-new{color:inherit}.lms-ui-message-delivered{color:green}.lms-ui-message-sent{color:#888}.lms-ui-message-cancelled{color:Sienna}.lms-ui-message-bounced,.lms-ui-message-error{color:red}.lms-ui-font-smaller{font-size:80%}span.division-context{margin-left:.5em}.lms-ui-route-type{margin-block-start:0;margin-block-end:0;text-indent:-3.5em;margin-left:3.5em}.lms-ui-dotted-line-top{border-top:1px dotted grey} \ No newline at end of file + */@font-face{font-family:'Font Awesome 5 Free';font-style:normal;font-weight:400;font-display:block;src:url(fontawesome/webfonts/fa-regular-400.eot);src:url(fontawesome/webfonts/fa-regular-400.eot?#iefix) format('embedded-opentype'),url(fontawesome/webfonts/fa-regular-400.woff2) format('woff2'),url(fontawesome/webfonts/fa-regular-400.woff) format('woff'),url(fontawesome/webfonts/fa-regular-400.ttf) format('truetype'),url(fontawesome/webfonts/fa-regular-400.svg#fontawesome) format('svg')}.far{font-family:'Font Awesome 5 Free';font-weight:400}.lms-ui-icon{line-height:unset;vertical-align:unset;font-size:130%}@media screen and (max-width:800px){.lms-ui-icon{font-size:125%}}.lms-ui-icon-fixed-width{width:1.5em;text-align:center}.lms-ui-icon-spacer{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-spacer.fa-pull-left{margin-right:.3em}.lms-ui-icon-spacer.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-spacer{font-size:125%}}.lms-ui-icon-spacer:before{content:"\f111";color:transparent}.lms-ui-icon-start-watch,.lms-ui-icon-watch,.lms-ui-icon-watch-start{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-start-watch.fa-pull-left,.lms-ui-icon-watch-start.fa-pull-left,.lms-ui-icon-watch.fa-pull-left{margin-right:.3em}.lms-ui-icon-start-watch.fa-pull-right,.lms-ui-icon-watch-start.fa-pull-right,.lms-ui-icon-watch.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-start-watch,.lms-ui-icon-watch,.lms-ui-icon-watch-start{font-size:125%}}.lms-ui-icon-start-watch:before,.lms-ui-icon-watch-start:before,.lms-ui-icon-watch:before{content:"\f06e"}.lms-ui-icon-stop-watch,.lms-ui-icon-unwatch,.lms-ui-icon-watch-stop{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-stop-watch.fa-pull-left,.lms-ui-icon-unwatch.fa-pull-left,.lms-ui-icon-watch-stop.fa-pull-left{margin-right:.3em}.lms-ui-icon-stop-watch.fa-pull-right,.lms-ui-icon-unwatch.fa-pull-right,.lms-ui-icon-watch-stop.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-stop-watch,.lms-ui-icon-unwatch,.lms-ui-icon-watch-stop{font-size:125%}}.lms-ui-icon-stop-watch:before,.lms-ui-icon-unwatch:before,.lms-ui-icon-watch-stop:before{content:"\f070"}.lms-ui-icon-tariff-limit{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-tariff-limit.fa-pull-left{margin-right:.3em}.lms-ui-icon-tariff-limit.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-tariff-limit{font-size:125%}}.lms-ui-icon-tariff-limit:before{content:"\f252"}.lms-ui-icon-map-pin{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-map-pin.fa-pull-left{margin-right:.3em}.lms-ui-icon-map-pin.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-map-pin{font-size:125%}}.lms-ui-icon-map-pin:before{content:"\f276"}.lms-ui-icon-customer-location{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%;color:red}.lms-ui-icon-customer-location.fa-pull-left{margin-right:.3em}.lms-ui-icon-customer-location.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-customer-location{font-size:125%}}.lms-ui-icon-customer-location:before{content:"\f276"}.lms-ui-icon-default-customer-location{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%;color:#00f}.lms-ui-icon-default-customer-location.fa-pull-left{margin-right:.3em}.lms-ui-icon-default-customer-location.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-default-customer-location{font-size:125%}}.lms-ui-icon-default-customer-location:before{content:"\f276"}.lms-ui-icon-memo,.lms-ui-icon-sticky-note{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-memo.fa-pull-left,.lms-ui-icon-sticky-note.fa-pull-left{margin-right:.3em}.lms-ui-icon-memo.fa-pull-right,.lms-ui-icon-sticky-note.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-memo,.lms-ui-icon-sticky-note{font-size:125%}}.lms-ui-icon-memo:before,.lms-ui-icon-sticky-note:before{content:"\f249"}.lms-ui-icon-quick-send{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-quick-send.fa-pull-left{margin-right:.3em}.lms-ui-icon-quick-send.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-quick-send{font-size:125%}}.lms-ui-icon-quick-send:before{content:"\f2f6"}.lms-ui-icon-nodesession,.lms-ui-icon-session{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%;-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=1)";transform:rotate(90deg)}.lms-ui-icon-nodesession.fa-pull-left,.lms-ui-icon-session.fa-pull-left{margin-right:.3em}.lms-ui-icon-nodesession.fa-pull-right,.lms-ui-icon-session.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-nodesession,.lms-ui-icon-session{font-size:125%}}.lms-ui-icon-nodesession:before,.lms-ui-icon-session:before{content:"\f362"}.lms-ui-icon-change-format{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-change-format.fa-pull-left{margin-right:.3em}.lms-ui-icon-change-format.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-change-format{font-size:125%}}.lms-ui-icon-change-format:before{content:"\f362"}.lms-ui-icon-lock,.lms-ui-icon-nodelock{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-lock.fa-pull-left,.lms-ui-icon-nodelock.fa-pull-left{margin-right:.3em}.lms-ui-icon-lock.fa-pull-right,.lms-ui-icon-nodelock.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-lock,.lms-ui-icon-nodelock{font-size:125%}}.lms-ui-icon-lock:before,.lms-ui-icon-nodelock:before{content:"\f023"}.lms-ui-icon-convert,.lms-ui-icon-transform{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-convert.fa-pull-left,.lms-ui-icon-transform.fa-pull-left{margin-right:.3em}.lms-ui-icon-convert.fa-pull-right,.lms-ui-icon-transform.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-convert,.lms-ui-icon-transform{font-size:125%}}.lms-ui-icon-convert:before,.lms-ui-icon-transform:before{content:"\f362"}.lms-ui-icon-correct,.lms-ui-icon-correction{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-correct.fa-pull-left,.lms-ui-icon-correction.fa-pull-left{margin-right:.3em}.lms-ui-icon-correct.fa-pull-right,.lms-ui-icon-correction.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-correct,.lms-ui-icon-correction{font-size:125%}}.lms-ui-icon-correct:before,.lms-ui-icon-correction:before{content:"\f0ad"}.lms-ui-icon-cashsource,.lms-ui-icon-importsource,.lms-ui-icon-isource{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-cashsource.fa-pull-left,.lms-ui-icon-importsource.fa-pull-left,.lms-ui-icon-isource.fa-pull-left{margin-right:.3em}.lms-ui-icon-cashsource.fa-pull-right,.lms-ui-icon-importsource.fa-pull-right,.lms-ui-icon-isource.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-cashsource,.lms-ui-icon-importsource,.lms-ui-icon-isource{font-size:125%}}.lms-ui-icon-cashsource:before,.lms-ui-icon-importsource:before,.lms-ui-icon-isource:before{content:"\f570"}.lms-ui-icon-import{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-import.fa-pull-left{margin-right:.3em}.lms-ui-icon-import.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-import{font-size:125%}}.lms-ui-icon-import:before{content:"\f56f"}.lms-ui-icon-debitnote,.lms-ui-icon-dnote{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-debitnote.fa-pull-left,.lms-ui-icon-dnote.fa-pull-left{margin-right:.3em}.lms-ui-icon-debitnote.fa-pull-right,.lms-ui-icon-dnote.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-debitnote,.lms-ui-icon-dnote{font-size:125%}}.lms-ui-icon-debitnote:before,.lms-ui-icon-dnote:before{content:"\f571"}.lms-ui-icon-cash,.lms-ui-icon-money,.lms-ui-icon-paytype{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-cash.fa-pull-left,.lms-ui-icon-money.fa-pull-left,.lms-ui-icon-paytype.fa-pull-left{margin-right:.3em}.lms-ui-icon-cash.fa-pull-right,.lms-ui-icon-money.fa-pull-right,.lms-ui-icon-paytype.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-cash,.lms-ui-icon-money,.lms-ui-icon-paytype{font-size:125%}}.lms-ui-icon-cash:before,.lms-ui-icon-money:before,.lms-ui-icon-paytype:before{content:"\f0d6"}.lms-ui-icon-settle,.lms-ui-icon-value{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-settle.fa-pull-left,.lms-ui-icon-value.fa-pull-left{margin-right:.3em}.lms-ui-icon-settle.fa-pull-right,.lms-ui-icon-value.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-settle,.lms-ui-icon-value{font-size:125%}}.lms-ui-icon-settle:before,.lms-ui-icon-value:before{content:"\f51e"}.lms-ui-icon-signout{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-signout.fa-pull-left{margin-right:.3em}.lms-ui-icon-signout.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-signout{font-size:125%}}.lms-ui-icon-signout:before{content:"\f127"}.lms-ui-icon-hourglass,.lms-ui-icon-wait{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:400;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-hourglass.fa-pull-left,.lms-ui-icon-wait.fa-pull-left{margin-right:.3em}.lms-ui-icon-hourglass.fa-pull-right,.lms-ui-icon-wait.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-hourglass,.lms-ui-icon-wait{font-size:125%}}.lms-ui-icon-hourglass:before,.lms-ui-icon-wait:before{content:"\f254"}.lms-ui-icon-option,.lms-ui-icon-options{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-option.fa-pull-left,.lms-ui-icon-options.fa-pull-left{margin-right:.3em}.lms-ui-icon-option.fa-pull-right,.lms-ui-icon-options.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-option,.lms-ui-icon-options{font-size:125%}}.lms-ui-icon-option:before,.lms-ui-icon-options:before{content:"\f0ce"}.lms-ui-icon-consent,.lms-ui-icon-sign,.lms-ui-icon-signature{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-consent.fa-pull-left,.lms-ui-icon-sign.fa-pull-left,.lms-ui-icon-signature.fa-pull-left{margin-right:.3em}.lms-ui-icon-consent.fa-pull-right,.lms-ui-icon-sign.fa-pull-right,.lms-ui-icon-signature.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-consent,.lms-ui-icon-sign,.lms-ui-icon-signature{font-size:125%}}.lms-ui-icon-consent:before,.lms-ui-icon-sign:before,.lms-ui-icon-signature:before{content:"\f5b7"}.lms-ui-icon-assign,.lms-ui-icon-assignment{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-assign.fa-pull-left,.lms-ui-icon-assignment.fa-pull-left{margin-right:.3em}.lms-ui-icon-assign.fa-pull-right,.lms-ui-icon-assignment.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-assign,.lms-ui-icon-assignment{font-size:125%}}.lms-ui-icon-assign:before,.lms-ui-icon-assignment:before{content:"\f53d"}.lms-ui-icon-save,.lms-ui-icon-submit{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-save.fa-pull-left,.lms-ui-icon-submit.fa-pull-left{margin-right:.3em}.lms-ui-icon-save.fa-pull-right,.lms-ui-icon-submit.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-save,.lms-ui-icon-submit{font-size:125%}}.lms-ui-icon-save:before,.lms-ui-icon-submit:before{content:"\f0c7"}.lms-ui-icon-cancel{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-cancel.fa-pull-left{margin-right:.3em}.lms-ui-icon-cancel.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-cancel{font-size:125%}}.lms-ui-icon-cancel:before{content:"\f55a"}.lms-ui-icon-location{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-location.fa-pull-left{margin-right:.3em}.lms-ui-icon-location.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-location{font-size:125%}}.lms-ui-icon-location:before{content:"\f3c5"}.lms-ui-icon-location-netstork{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-location-netstork.fa-pull-left{margin-right:.3em}.lms-ui-icon-location-netstork.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-location-netstork{font-size:125%}}.lms-ui-icon-location-netstork:before{content:"\f124"}.lms-ui-icon-location-geoportal{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-location-geoportal.fa-pull-left{margin-right:.3em}.lms-ui-icon-location-geoportal.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-location-geoportal{font-size:125%}}.lms-ui-icon-location-geoportal:before{content:"\f1b2"}.lms-ui-icon-location-sidusis{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-location-sidusis.fa-pull-left{margin-right:.3em}.lms-ui-icon-location-sidusis.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-location-sidusis{font-size:125%}}.lms-ui-icon-location-sidusis:before{content:"\f279"}.lms-ui-icon-search{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-search.fa-pull-left{margin-right:.3em}.lms-ui-icon-search.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-search{font-size:125%}}.lms-ui-icon-search:before{content:"\f002"}.lms-ui-icon-next{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-next.fa-pull-left{margin-right:.3em}.lms-ui-icon-next.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-next{font-size:125%}}.lms-ui-icon-next:before{content:"\f101"}.lms-ui-icon-fast-next{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-fast-next.fa-pull-left{margin-right:.3em}.lms-ui-icon-fast-next.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-fast-next{font-size:125%}}.lms-ui-icon-fast-next:before{content:"\f050"}.lms-ui-icon-previous{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-previous.fa-pull-left{margin-right:.3em}.lms-ui-icon-previous.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-previous{font-size:125%}}.lms-ui-icon-previous:before{content:"\f100"}.lms-ui-icon-fast-previous{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-fast-previous.fa-pull-left{margin-right:.3em}.lms-ui-icon-fast-previous.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-fast-previous{font-size:125%}}.lms-ui-icon-fast-previous:before{content:"\f049"}.lms-ui-icon-current-year{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-current-year.fa-pull-left{margin-right:.3em}.lms-ui-icon-current-year.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-current-year{font-size:125%}}.lms-ui-icon-current-year:before{content:"\f102"}.lms-ui-icon-clone,.lms-ui-icon-copy{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-clone.fa-pull-left,.lms-ui-icon-copy.fa-pull-left{margin-right:.3em}.lms-ui-icon-clone.fa-pull-right,.lms-ui-icon-copy.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-clone,.lms-ui-icon-copy{font-size:125%}}.lms-ui-icon-clone:before,.lms-ui-icon-copy:before{content:"\f0c5"}.lms-ui-icon-clean,.lms-ui-icon-clear{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-clean.fa-pull-left,.lms-ui-icon-clear.fa-pull-left{margin-right:.3em}.lms-ui-icon-clean.fa-pull-right,.lms-ui-icon-clear.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-clean,.lms-ui-icon-clear{font-size:125%}}.lms-ui-icon-clean:before,.lms-ui-icon-clear:before{content:"\f12d"}.lms-ui-icon-delete,.lms-ui-icon-remove,.lms-ui-icon-trash{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-delete.fa-pull-left,.lms-ui-icon-remove.fa-pull-left,.lms-ui-icon-trash.fa-pull-left{margin-right:.3em}.lms-ui-icon-delete.fa-pull-right,.lms-ui-icon-remove.fa-pull-right,.lms-ui-icon-trash.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-delete,.lms-ui-icon-remove,.lms-ui-icon-trash{font-size:125%}}.lms-ui-icon-delete:before,.lms-ui-icon-remove:before,.lms-ui-icon-trash:before{content:"\f1f8"}.lms-ui-icon-change,.lms-ui-icon-edit,.lms-ui-icon-modify{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-change.fa-pull-left,.lms-ui-icon-edit.fa-pull-left,.lms-ui-icon-modify.fa-pull-left{margin-right:.3em}.lms-ui-icon-change.fa-pull-right,.lms-ui-icon-edit.fa-pull-right,.lms-ui-icon-modify.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-change,.lms-ui-icon-edit,.lms-ui-icon-modify{font-size:125%}}.lms-ui-icon-change:before,.lms-ui-icon-edit:before,.lms-ui-icon-modify:before{content:"\f044"}.lms-ui-icon-attachment,.lms-ui-icon-fileupload{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-attachment.fa-pull-left,.lms-ui-icon-fileupload.fa-pull-left{margin-right:.3em}.lms-ui-icon-attachment.fa-pull-right,.lms-ui-icon-fileupload.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-attachment,.lms-ui-icon-fileupload{font-size:125%}}.lms-ui-icon-attachment:before,.lms-ui-icon-fileupload:before{content:"\f0c6"}.lms-ui-icon-download{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-download.fa-pull-left{margin-right:.3em}.lms-ui-icon-download.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-download{font-size:125%}}.lms-ui-icon-download:before{content:"\f019"}.lms-ui-icon-upload{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-upload.fa-pull-left{margin-right:.3em}.lms-ui-icon-upload.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-upload{font-size:125%}}.lms-ui-icon-upload:before{content:"\f093"}.lms-ui-icon-back,.lms-ui-icon-return{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-back.fa-pull-left,.lms-ui-icon-return.fa-pull-left{margin-right:.3em}.lms-ui-icon-back.fa-pull-right,.lms-ui-icon-return.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-back,.lms-ui-icon-return{font-size:125%}}.lms-ui-icon-back:before,.lms-ui-icon-return:before{content:"\f151"}.lms-ui-icon-expired{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-expired.fa-pull-left{margin-right:.3em}.lms-ui-icon-expired.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-expired{font-size:125%}}.lms-ui-icon-expired:before{content:"\f06a"}.lms-ui-icon-add,.lms-ui-icon-append,.lms-ui-icon-new{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-add.fa-pull-left,.lms-ui-icon-append.fa-pull-left,.lms-ui-icon-new.fa-pull-left{margin-right:.3em}.lms-ui-icon-add.fa-pull-right,.lms-ui-icon-append.fa-pull-right,.lms-ui-icon-new.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-add,.lms-ui-icon-append,.lms-ui-icon-new{font-size:125%}}.lms-ui-icon-add:before,.lms-ui-icon-append:before,.lms-ui-icon-new:before{content:"\f0fe"}.lms-ui-icon-print{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-print.fa-pull-left{margin-right:.3em}.lms-ui-icon-print.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-print{font-size:125%}}.lms-ui-icon-print:before{content:"\f02f"}.lms-ui-icon-descending{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-descending.fa-pull-left{margin-right:.3em}.lms-ui-icon-descending.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-descending{font-size:125%}}.lms-ui-icon-descending:before{content:"\f0dd"}.lms-ui-icon-sorting{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-sorting.fa-pull-left{margin-right:.3em}.lms-ui-icon-sorting.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-sorting{font-size:125%}}.lms-ui-icon-sorting:before{content:"\f0dc"}.lms-ui-icon-ascending{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-ascending.fa-pull-left{margin-right:.3em}.lms-ui-icon-ascending.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-ascending{font-size:125%}}.lms-ui-icon-ascending:before{content:"\f0de"}.lms-ui-icon-apply,.lms-ui-icon-confirm{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-apply.fa-pull-left,.lms-ui-icon-confirm.fa-pull-left{margin-right:.3em}.lms-ui-icon-apply.fa-pull-right,.lms-ui-icon-confirm.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-apply,.lms-ui-icon-confirm{font-size:125%}}.lms-ui-icon-apply:before,.lms-ui-icon-confirm:before{content:"\f560"}.lms-ui-icon-mail{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-mail.fa-pull-left{margin-right:.3em}.lms-ui-icon-mail.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-mail{font-size:125%}}.lms-ui-icon-mail:before{content:"\f1fa"}.lms-ui-icon-send{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-send.fa-pull-left{margin-right:.3em}.lms-ui-icon-send.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-send{font-size:125%}}.lms-ui-icon-send:before{content:"\f0e0"}.lms-ui-icon-call,.lms-ui-icon-phone{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-call.fa-pull-left,.lms-ui-icon-phone.fa-pull-left{margin-right:.3em}.lms-ui-icon-call.fa-pull-right,.lms-ui-icon-phone.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-call,.lms-ui-icon-phone{font-size:125%}}.lms-ui-icon-call:before,.lms-ui-icon-phone:before{content:"\f095"}.lms-ui-icon-phone-call{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-phone-call.fa-pull-left{margin-right:.3em}.lms-ui-icon-phone-call.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-phone-call{font-size:125%}}.lms-ui-icon-phone-call:before{content:"\f2a0"}.lms-ui-icon-mobile,.lms-ui-icon-sms{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-mobile.fa-pull-left,.lms-ui-icon-sms.fa-pull-left{margin-right:.3em}.lms-ui-icon-mobile.fa-pull-right,.lms-ui-icon-sms.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-mobile,.lms-ui-icon-sms{font-size:125%}}.lms-ui-icon-mobile:before,.lms-ui-icon-sms:before{content:"\f3cd"}.lms-ui-icon-web,.lms-ui-icon-www{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Brands';font-weight:400;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-web.fa-pull-left,.lms-ui-icon-www.fa-pull-left{margin-right:.3em}.lms-ui-icon-web.fa-pull-right,.lms-ui-icon-www.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-web,.lms-ui-icon-www{font-size:125%}}.lms-ui-icon-web:before,.lms-ui-icon-www:before{content:"\f268"}.lms-ui-icon-panel,.lms-ui-icon-userpanel{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-panel.fa-pull-left,.lms-ui-icon-userpanel.fa-pull-left{margin-right:.3em}.lms-ui-icon-panel.fa-pull-right,.lms-ui-icon-userpanel.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-panel,.lms-ui-icon-userpanel{font-size:125%}}.lms-ui-icon-panel:before,.lms-ui-icon-userpanel:before{content:"\f0c0"}.lms-ui-icon-clipboard,.lms-ui-icon-notes{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-clipboard.fa-pull-left,.lms-ui-icon-notes.fa-pull-left{margin-right:.3em}.lms-ui-icon-clipboard.fa-pull-right,.lms-ui-icon-notes.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-clipboard,.lms-ui-icon-notes{font-size:125%}}.lms-ui-icon-clipboard:before,.lms-ui-icon-notes:before{content:"\f0ea"}.lms-ui-icon-view{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-view.fa-pull-left{margin-right:.3em}.lms-ui-icon-view.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-view{font-size:125%}}.lms-ui-icon-view:before{content:"\f06e"}.lms-ui-icon-view.pdf:before{content:"\f1c1"}.lms-ui-icon-view.xls:before{content:"\f1c3"}.lms-ui-icon-details,.lms-ui-icon-info{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-details.fa-pull-left,.lms-ui-icon-info.fa-pull-left{margin-right:.3em}.lms-ui-icon-details.fa-pull-right,.lms-ui-icon-info.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-details,.lms-ui-icon-info{font-size:125%}}.lms-ui-icon-details:before,.lms-ui-icon-info:before{content:"\f129"}.lms-ui-icon-help,.lms-ui-icon-hint{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:400;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-help.fa-pull-left,.lms-ui-icon-hint.fa-pull-left{margin-right:.3em}.lms-ui-icon-help.fa-pull-right,.lms-ui-icon-hint.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-help,.lms-ui-icon-hint{font-size:125%}}.lms-ui-icon-help:before,.lms-ui-icon-hint:before{content:"\f059"}.lms-ui-icon-open{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-open.fa-pull-left{margin-right:.3em}.lms-ui-icon-open.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-open{font-size:125%}}.lms-ui-icon-open:before{content:"\f518"}.lms-ui-icon-close{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-close.fa-pull-left{margin-right:.3em}.lms-ui-icon-close.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-close{font-size:125%}}.lms-ui-icon-close:before{content:"\f02d"}.lms-ui-icon-unread{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-unread.fa-pull-left{margin-right:.3em}.lms-ui-icon-unread.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-unread{font-size:125%}}.lms-ui-icon-unread:before{content:"\f02d";color:#4169e1}.lms-ui-icon-read{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-read.fa-pull-left{margin-right:.3em}.lms-ui-icon-read.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-read{font-size:125%}}.lms-ui-icon-read:before{content:"\f518"}.lms-ui-icon-urgent{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-urgent.fa-pull-left{margin-right:.3em}.lms-ui-icon-urgent.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-urgent{font-size:125%}}.lms-ui-icon-urgent:before{content:"\f0f3";color:#ff8c00}.lms-ui-icon-critical{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-critical.fa-pull-left{margin-right:.3em}.lms-ui-icon-critical.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-critical{font-size:125%}}.lms-ui-icon-critical:before{content:"\f0f3";color:red}.lms-ui-icon-ng,.lms-ui-icon-ngroup,.lms-ui-icon-nodegroup{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-ng.fa-pull-left,.lms-ui-icon-ngroup.fa-pull-left,.lms-ui-icon-nodegroup.fa-pull-left{margin-right:.3em}.lms-ui-icon-ng.fa-pull-right,.lms-ui-icon-ngroup.fa-pull-right,.lms-ui-icon-nodegroup.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-ng,.lms-ui-icon-ngroup,.lms-ui-icon-nodegroup{font-size:125%}}.lms-ui-icon-ng:before,.lms-ui-icon-ngroup:before,.lms-ui-icon-nodegroup:before{content:"\f5fd"}.lms-ui-icon-cg,.lms-ui-icon-cgroup,.lms-ui-icon-customergroup{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-cg.fa-pull-left,.lms-ui-icon-cgroup.fa-pull-left,.lms-ui-icon-customergroup.fa-pull-left{margin-right:.3em}.lms-ui-icon-cg.fa-pull-right,.lms-ui-icon-cgroup.fa-pull-right,.lms-ui-icon-customergroup.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-cg,.lms-ui-icon-cgroup,.lms-ui-icon-customergroup{font-size:125%}}.lms-ui-icon-cg:before,.lms-ui-icon-cgroup:before,.lms-ui-icon-customergroup:before{content:"\f0c0"}.lms-ui-icon-tag,.lms-ui-icon-ug,.lms-ui-icon-ugroup,.lms-ui-icon-usergroup{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-tag.fa-pull-left,.lms-ui-icon-ug.fa-pull-left,.lms-ui-icon-ugroup.fa-pull-left,.lms-ui-icon-usergroup.fa-pull-left{margin-right:.3em}.lms-ui-icon-tag.fa-pull-right,.lms-ui-icon-ug.fa-pull-right,.lms-ui-icon-ugroup.fa-pull-right,.lms-ui-icon-usergroup.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-tag,.lms-ui-icon-ug,.lms-ui-icon-ugroup,.lms-ui-icon-usergroup{font-size:125%}}.lms-ui-icon-tag:before,.lms-ui-icon-ug:before,.lms-ui-icon-ugroup:before,.lms-ui-icon-usergroup:before{content:"\f507"}.lms-ui-icon-lock,.lms-ui-icon-suspend{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-lock.fa-pull-left,.lms-ui-icon-suspend.fa-pull-left{margin-right:.3em}.lms-ui-icon-lock.fa-pull-right,.lms-ui-icon-suspend.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-lock,.lms-ui-icon-suspend{font-size:125%}}.lms-ui-icon-lock:before,.lms-ui-icon-suspend:before{content:"\f023"}.lms-ui-icon-unlock{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-unlock.fa-pull-left{margin-right:.3em}.lms-ui-icon-unlock.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-unlock{font-size:125%}}.lms-ui-icon-unlock:before{content:"\f09c"}.lms-ui-icon-warn,.lms-ui-icon-warning,.lms-ui-icon-warnoff{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-warn.fa-pull-left,.lms-ui-icon-warning.fa-pull-left,.lms-ui-icon-warnoff.fa-pull-left{margin-right:.3em}.lms-ui-icon-warn.fa-pull-right,.lms-ui-icon-warning.fa-pull-right,.lms-ui-icon-warnoff.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-warn,.lms-ui-icon-warning,.lms-ui-icon-warnoff{font-size:125%}}.lms-ui-icon-warn:before,.lms-ui-icon-warning:before,.lms-ui-icon-warnoff:before{content:"\f071"}.lms-ui-icon-warnoff:before{color:#000!important}.lms-ui-icon-warnmix{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-warnmix.fa-pull-left{margin-right:.3em}.lms-ui-icon-warnmix.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-warnmix{font-size:125%}}.lms-ui-icon-warnmix:before{content:"\f071"}.lms-ui-icon-warnmix:before{color:#deb887!important;text-stroke-width:1px;text-stroke-color:#000;-webkit-text-stroke-width:1px;-webkit-text-stroke-color:#000}.lms-ui-icon-warnon{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-warnon.fa-pull-left{margin-right:.3em}.lms-ui-icon-warnon.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-warnon{font-size:125%}}.lms-ui-icon-warnon:before{content:"\f071"}.lms-ui-icon-warnon:before{color:gold!important;text-stroke-width:1px;text-stroke-color:#000;-webkit-text-stroke-width:1px;-webkit-text-stroke-color:#000}.lms-ui-icon-connect{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-connect.fa-pull-left{margin-right:.3em}.lms-ui-icon-connect.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-connect{font-size:125%}}.lms-ui-icon-connect:before{content:"\f205"}.lms-ui-icon-plug{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-plug.fa-pull-left{margin-right:.3em}.lms-ui-icon-plug.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-plug{font-size:125%}}.lms-ui-icon-plug:before{content:"\f1e6"}.lms-ui-icon-connected{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-connected.fa-pull-left{margin-right:.3em}.lms-ui-icon-connected.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-connected{font-size:125%}}.lms-ui-icon-connected:before{content:"\f205"}.lms-ui-icon-connected:before{color:gold!important;text-stroke-width:1px;text-stroke-color:#000;-webkit-text-stroke-width:1px;-webkit-text-stroke-color:#000}.lms-ui-icon-mixconnected{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-mixconnected.fa-pull-left{margin-right:.3em}.lms-ui-icon-mixconnected.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-mixconnected{font-size:125%}}.lms-ui-icon-mixconnected:before{content:"\f205"}.lms-ui-icon-mixconnected:before{color:#deb887!important;text-stroke-width:1px;text-stroke-color:#000;-webkit-text-stroke-width:1px;-webkit-text-stroke-color:#000}.lms-ui-icon-disconnected{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%;-ms-filter:"progid:DXImageTransform.Microsoft.BasicImage(rotation=0, mirror=1)";transform:scale(-1,1)}.lms-ui-icon-disconnected.fa-pull-left{margin-right:.3em}.lms-ui-icon-disconnected.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-disconnected{font-size:125%}}.lms-ui-icon-disconnected:before{content:"\f205";color:#000!important}.lms-ui-icon-vlan{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-vlan.fa-pull-left{margin-right:.3em}.lms-ui-icon-vlan.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-vlan{font-size:125%}}.lms-ui-icon-vlan:before{content:"\f542"}.lms-ui-icon-id,.lms-ui-icon-serial,.lms-ui-icon-serialnumber,.lms-ui-icon-sn{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-id.fa-pull-left,.lms-ui-icon-serial.fa-pull-left,.lms-ui-icon-serialnumber.fa-pull-left,.lms-ui-icon-sn.fa-pull-left{margin-right:.3em}.lms-ui-icon-id.fa-pull-right,.lms-ui-icon-serial.fa-pull-right,.lms-ui-icon-serialnumber.fa-pull-right,.lms-ui-icon-sn.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-id,.lms-ui-icon-serial,.lms-ui-icon-serialnumber,.lms-ui-icon-sn{font-size:125%}}.lms-ui-icon-id:before,.lms-ui-icon-serial:before,.lms-ui-icon-serialnumber:before,.lms-ui-icon-sn:before{content:"\f0cb"}.lms-ui-icon-window-close{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-window-close.fa-pull-left{margin-right:.3em}.lms-ui-icon-window-close.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-window-close{font-size:125%}}.lms-ui-icon-window-close:before{content:"\f410"}.lms-ui-icon-node{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-node.fa-pull-left{margin-right:.3em}.lms-ui-icon-node.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-node{font-size:125%}}.lms-ui-icon-node:before{content:"\f108"}.lms-ui-icon-verifier{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-verifier.fa-pull-left{margin-right:.3em}.lms-ui-icon-verifier.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-verifier{font-size:125%}}.lms-ui-icon-verifier:before{content:"\f51c"}.lms-ui-icon-deadline{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-deadline.fa-pull-left{margin-right:.3em}.lms-ui-icon-deadline.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-deadline{font-size:125%}}.lms-ui-icon-deadline:before{content:"\f253"}.lms-ui-icon-actions{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-actions.fa-pull-left{margin-right:.3em}.lms-ui-icon-actions.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-actions{font-size:125%}}.lms-ui-icon-actions:before{content:"\f085"}.lms-ui-icon-time,.lms-ui-icon-uptime{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-time.fa-pull-left,.lms-ui-icon-uptime.fa-pull-left{margin-right:.3em}.lms-ui-icon-time.fa-pull-right,.lms-ui-icon-uptime.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-time,.lms-ui-icon-uptime{font-size:125%}}.lms-ui-icon-time:before,.lms-ui-icon-uptime:before{content:"\f017"}.lms-ui-icon-categories{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-categories.fa-pull-left{margin-right:.3em}.lms-ui-icon-categories.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-categories{font-size:125%}}.lms-ui-icon-categories:before{content:"\f14a"}.lms-ui-icon-check,.lms-ui-icon-checked{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-check.fa-pull-left,.lms-ui-icon-checked.fa-pull-left{margin-right:.3em}.lms-ui-icon-check.fa-pull-right,.lms-ui-icon-checked.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-check,.lms-ui-icon-checked{font-size:125%}}.lms-ui-icon-check:before,.lms-ui-icon-checked:before{content:"\f00c"}.lms-ui-icon-restore{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-restore.fa-pull-left{margin-right:.3em}.lms-ui-icon-restore.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-restore{font-size:125%}}.lms-ui-icon-restore:before{content:"\f2ea"}.lms-ui-icon-recover{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-recover.fa-pull-left{margin-right:.3em}.lms-ui-icon-recover.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-recover{font-size:125%}}.lms-ui-icon-recover:before{content:"\f829"}.lms-ui-icon-description{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-description.fa-pull-left{margin-right:.3em}.lms-ui-icon-description.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-description{font-size:125%}}.lms-ui-icon-description:before{content:"\f29e"}.lms-ui-icon-nodeoff{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-nodeoff.fa-pull-left{margin-right:.3em}.lms-ui-icon-nodeoff.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-nodeoff{font-size:125%}}.lms-ui-icon-nodeoff:before{content:"\f108"}.lms-ui-icon-nodeoff.fa-pull-left{margin-right:.3em}.lms-ui-icon-nodeoff.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-nodeoff{font-size:125%}}.lms-ui-icon-nodeoff:before{content:"\f108"}.lms-ui-icon-nodeon{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%;text-stroke-width:1px;text-stroke-color:#32cd32;-webkit-text-stroke-width:1px;-webkit-text-stroke-color:#32cd32}.lms-ui-icon-nodeon.fa-pull-left{margin-right:.3em}.lms-ui-icon-nodeon.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-nodeon{font-size:125%}}.lms-ui-icon-nodeon:before{content:"\f108"}.lms-ui-icon-nodeon.fa-pull-left{margin-right:.3em}.lms-ui-icon-nodeon.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-nodeon{font-size:125%}}.lms-ui-icon-nodeon:before{content:"\f108"}.lms-ui-icon-nodeunk{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%;text-stroke-width:1px;text-stroke-color:red;-webkit-text-stroke-width:1px;-webkit-text-stroke-color:red}.lms-ui-icon-nodeunk.fa-pull-left{margin-right:.3em}.lms-ui-icon-nodeunk.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-nodeunk{font-size:125%}}.lms-ui-icon-nodeunk:before{content:"\f108"}.lms-ui-icon-nodeunk.fa-pull-left{margin-right:.3em}.lms-ui-icon-nodeunk.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-nodeunk{font-size:125%}}.lms-ui-icon-nodeunk:before{content:"\f108"}.lms-ui-icon-device,.lms-ui-icon-netdevice{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-device.fa-pull-left,.lms-ui-icon-netdevice.fa-pull-left{margin-right:.3em}.lms-ui-icon-device.fa-pull-right,.lms-ui-icon-netdevice.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-device,.lms-ui-icon-netdevice{font-size:125%}}.lms-ui-icon-device:before,.lms-ui-icon-netdevice:before{content:"\f0a0"}.lms-ui-icon-netdev{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-netdev.fa-pull-left{margin-right:.3em}.lms-ui-icon-netdev.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-netdev{font-size:125%}}.lms-ui-icon-netdev:before{content:"\f0a0"}.lms-ui-icon-netdevoff{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-netdevoff.fa-pull-left{margin-right:.3em}.lms-ui-icon-netdevoff.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-netdevoff{font-size:125%}}.lms-ui-icon-netdevoff:before{content:"\f0a0"}.lms-ui-icon-netdevon{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%;text-stroke-width:1px;text-stroke-color:#32cd32;-webkit-text-stroke-width:1px;-webkit-text-stroke-color:#32cd32}.lms-ui-icon-netdevon.fa-pull-left{margin-right:.3em}.lms-ui-icon-netdevon.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-netdevon{font-size:125%}}.lms-ui-icon-netdevon:before{content:"\f0a0"}.lms-ui-icon-netdevunk{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%;text-stroke-width:1px;text-stroke-color:red;-webkit-text-stroke-width:1px;-webkit-text-stroke-color:red}.lms-ui-icon-netdevunk.fa-pull-left{margin-right:.3em}.lms-ui-icon-netdevunk.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-netdevunk{font-size:125%}}.lms-ui-icon-netdevunk:before{content:"\f0a0"}.lms-ui-icon-mailsent{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-mailsent.fa-pull-left{margin-right:.3em}.lms-ui-icon-mailsent.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-mailsent{font-size:125%}}.lms-ui-icon-mailsent:before{content:"\f1fa"}.lms-ui-icon-mailsent:before{color:#888!important}.lms-ui-icon-customer{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-customer.fa-pull-left{margin-right:.3em}.lms-ui-icon-customer.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-customer{font-size:125%}}.lms-ui-icon-customer:before{content:"\f007"}.lms-ui-icon-phone{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-phone.fa-pull-left{margin-right:.3em}.lms-ui-icon-phone.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-phone{font-size:125%}}.lms-ui-icon-phone:before{content:"\f095"}.lms-ui-icon-node{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-node.fa-pull-left{margin-right:.3em}.lms-ui-icon-node.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-node{font-size:125%}}.lms-ui-icon-node:before{content:"\f108"}.lms-ui-icon-ipnetwork,.lms-ui-icon-network,.lms-ui-icon-networks{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-ipnetwork.fa-pull-left,.lms-ui-icon-network.fa-pull-left,.lms-ui-icon-networks.fa-pull-left{margin-right:.3em}.lms-ui-icon-ipnetwork.fa-pull-right,.lms-ui-icon-network.fa-pull-right,.lms-ui-icon-networks.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-ipnetwork,.lms-ui-icon-network,.lms-ui-icon-networks{font-size:125%}}.lms-ui-icon-ipnetwork:before,.lms-ui-icon-network:before,.lms-ui-icon-networks:before{content:"\f0ac"}.lms-ui-icon-subject{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-subject.fa-pull-left{margin-right:.3em}.lms-ui-icon-subject.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-subject{font-size:125%}}.lms-ui-icon-subject:before{content:"\f64a"}.lms-ui-icon-user{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-user.fa-pull-left{margin-right:.3em}.lms-ui-icon-user.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-user{font-size:125%}}.lms-ui-icon-user:before{content:"\f007"}.lms-ui-icon-owner{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-owner.fa-pull-left{margin-right:.3em}.lms-ui-icon-owner.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-owner{font-size:125%}}.lms-ui-icon-owner:before{content:"\f2bd"}.lms-ui-icon-queue{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-queue.fa-pull-left{margin-right:.3em}.lms-ui-icon-queue.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-queue{font-size:125%}}.lms-ui-icon-queue:before{content:"\f0ae"}.lms-ui-icon-netnode{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-netnode.fa-pull-left{margin-right:.3em}.lms-ui-icon-netnode.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-netnode{font-size:125%}}.lms-ui-icon-netnode:before{content:"\f5fd"}.lms-ui-icon-service{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-service.fa-pull-left{margin-right:.3em}.lms-ui-icon-service.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-service{font-size:125%}}.lms-ui-icon-service:before{content:"\f013"}.lms-ui-icon-type{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-type.fa-pull-left{margin-right:.3em}.lms-ui-icon-type.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-type{font-size:125%}}.lms-ui-icon-type:before{content:"\f3ff"}.lms-ui-icon-event-type{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-event-type.fa-pull-left{margin-right:.3em}.lms-ui-icon-event-type.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-event-type{font-size:125%}}.lms-ui-icon-event-type:before{content:"\f133"}.lms-ui-icon-requestor{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-requestor.fa-pull-left{margin-right:.3em}.lms-ui-icon-requestor.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-requestor{font-size:125%}}.lms-ui-icon-requestor:before{content:"\f183"}.lms-ui-icon-helpdesk{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-helpdesk.fa-pull-left{margin-right:.3em}.lms-ui-icon-helpdesk.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-helpdesk{font-size:125%}}.lms-ui-icon-helpdesk:before{content:"\f0ae"}.lms-ui-icon-billing,.lms-ui-icon-calendar,.lms-ui-icon-timetable{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-billing.fa-pull-left,.lms-ui-icon-calendar.fa-pull-left,.lms-ui-icon-timetable.fa-pull-left{margin-right:.3em}.lms-ui-icon-billing.fa-pull-right,.lms-ui-icon-calendar.fa-pull-right,.lms-ui-icon-timetable.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-billing,.lms-ui-icon-calendar,.lms-ui-icon-timetable{font-size:125%}}.lms-ui-icon-billing:before,.lms-ui-icon-calendar:before,.lms-ui-icon-timetable:before{content:"\f073"}.lms-ui-icon-administration{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-administration.fa-pull-left{margin-right:.3em}.lms-ui-icon-administration.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-administration{font-size:125%}}.lms-ui-icon-administration:before{content:"\f54a"}.lms-ui-icon-dropdown2{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-dropdown2.fa-pull-left{margin-right:.3em}.lms-ui-icon-dropdown2.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-dropdown2{font-size:125%}}.lms-ui-icon-dropdown2:before{content:"\f141"}.lms-ui-icon-factory-reset,.lms-ui-icon-reload{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-factory-reset.fa-pull-left,.lms-ui-icon-reload.fa-pull-left{margin-right:.3em}.lms-ui-icon-factory-reset.fa-pull-right,.lms-ui-icon-reload.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-factory-reset,.lms-ui-icon-reload{font-size:125%}}.lms-ui-icon-factory-reset:before,.lms-ui-icon-reload:before{content:"\f2f1"}.lms-ui-icon-relatedticket{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-relatedticket.fa-pull-left{margin-right:.3em}.lms-ui-icon-relatedticket.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-relatedticket{font-size:125%}}.lms-ui-icon-relatedticket:before{content:"\f31e"}.lms-ui-icon-childticket{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-childticket.fa-pull-left{margin-right:.3em}.lms-ui-icon-childticket.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-childticket{font-size:125%}}.lms-ui-icon-childticket:before{content:"\f0ab"}.lms-ui-icon-net-to-gross{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-net-to-gross.fa-pull-left{margin-right:.3em}.lms-ui-icon-net-to-gross.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-net-to-gross{font-size:125%}}.lms-ui-icon-net-to-gross:before{color:gold;text-stroke-width:1px;text-stroke-color:#000;-webkit-text-stroke-width:1px;-webkit-text-stroke-color:#000;content:"\f35a"}.lms-ui-icon-gross-to-net{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-gross-to-net.fa-pull-left{margin-right:.3em}.lms-ui-icon-gross-to-net.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-gross-to-net{font-size:125%}}.lms-ui-icon-gross-to-net:before{content:"\f359"}.lms-ui-icon-parentticket{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-parentticket.fa-pull-left{margin-right:.3em}.lms-ui-icon-parentticket.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-parentticket{font-size:125%}}.lms-ui-icon-parentticket:before{content:"\f122"}.lms-ui-icon-source{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-source.fa-pull-left{margin-right:.3em}.lms-ui-icon-source.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-source{font-size:125%}}.lms-ui-icon-source:before{content:"\f00a"}.lms-ui-icon-priority{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-priority.fa-pull-left{margin-right:.3em}.lms-ui-icon-priority.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-priority{font-size:125%}}.lms-ui-icon-priority:before{content:"\f2cb"}.lms-ui-icon-cause{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-cause.fa-pull-left{margin-right:.3em}.lms-ui-icon-cause.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-cause{font-size:125%}}.lms-ui-icon-cause:before{content:"\f069"}.lms-ui-icon-logout{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-logout.fa-pull-left{margin-right:.3em}.lms-ui-icon-logout.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-logout{font-size:125%}}.lms-ui-icon-logout:before{content:"\f011"}.lms-ui-icon-login{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-login.fa-pull-left{margin-right:.3em}.lms-ui-icon-login.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-login{font-size:125%}}.lms-ui-icon-login:before{content:"\f2f6"}.lms-ui-icon-configuration{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-configuration.fa-pull-left{margin-right:.3em}.lms-ui-icon-configuration.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-configuration{font-size:125%}}.lms-ui-icon-configuration:before{content:"\f0ad"}.lms-ui-icon-archive,.lms-ui-icon-archiveview,.lms-ui-icon-history,.lms-ui-icon-log,.lms-ui-icon-logging,.lms-ui-icon-transaction,.lms-ui-icon-transactions{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-archive.fa-pull-left,.lms-ui-icon-archiveview.fa-pull-left,.lms-ui-icon-history.fa-pull-left,.lms-ui-icon-log.fa-pull-left,.lms-ui-icon-logging.fa-pull-left,.lms-ui-icon-transaction.fa-pull-left,.lms-ui-icon-transactions.fa-pull-left{margin-right:.3em}.lms-ui-icon-archive.fa-pull-right,.lms-ui-icon-archiveview.fa-pull-right,.lms-ui-icon-history.fa-pull-right,.lms-ui-icon-log.fa-pull-right,.lms-ui-icon-logging.fa-pull-right,.lms-ui-icon-transaction.fa-pull-right,.lms-ui-icon-transactions.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-archive,.lms-ui-icon-archiveview,.lms-ui-icon-history,.lms-ui-icon-log,.lms-ui-icon-logging,.lms-ui-icon-transaction,.lms-ui-icon-transactions{font-size:125%}}.lms-ui-icon-archive:before,.lms-ui-icon-archiveview:before,.lms-ui-icon-history:before,.lms-ui-icon-log:before,.lms-ui-icon-logging:before,.lms-ui-icon-transaction:before,.lms-ui-icon-transactions:before{content:"\f1da"}.lms-ui-icon-finances{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-finances.fa-pull-left{margin-right:.3em}.lms-ui-icon-finances.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-finances{font-size:125%}}.lms-ui-icon-finances:before{content:"\f0d6"}.lms-ui-icon-invproject{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-invproject.fa-pull-left{margin-right:.3em}.lms-ui-icon-invproject.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-invproject{font-size:125%}}.lms-ui-icon-invproject:before{content:"\f0d6"}.lms-ui-icon-status{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-status.fa-pull-left{margin-right:.3em}.lms-ui-icon-status.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-status{font-size:125%}}.lms-ui-icon-status:before{color:#6495ed;content:"\f02d"}.lms-ui-icon-status-resolved{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-status-resolved.fa-pull-left{margin-right:.3em}.lms-ui-icon-status-resolved.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-status-resolved{font-size:125%}}.lms-ui-icon-status-resolved:before{color:#696969;content:"\f02d"}.lms-ui-icon-wireless{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-wireless.fa-pull-left{margin-right:.3em}.lms-ui-icon-wireless.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-wireless{font-size:125%}}.lms-ui-icon-wireless:before{content:"\f1eb"}.lms-ui-icon-port,.lms-ui-icon-wired{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-port.fa-pull-left,.lms-ui-icon-wired.fa-pull-left{margin-right:.3em}.lms-ui-icon-port.fa-pull-right,.lms-ui-icon-wired.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-port,.lms-ui-icon-wired{font-size:125%}}.lms-ui-icon-port:before,.lms-ui-icon-wired:before{content:"\f796"}.lms-ui-icon-port-connected,.lms-ui-icon-port-taken{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-port-connected.fa-pull-left,.lms-ui-icon-port-taken.fa-pull-left{margin-right:.3em}.lms-ui-icon-port-connected.fa-pull-right,.lms-ui-icon-port-taken.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-port-connected,.lms-ui-icon-port-taken{font-size:125%}}.lms-ui-icon-port-connected:before,.lms-ui-icon-port-taken:before{content:"\f796"}.lms-ui-icon-port-connected:before,.lms-ui-icon-port-taken:before{color:gold!important;text-stroke-width:1px;text-stroke-color:#000;-webkit-text-stroke-width:1px;-webkit-text-stroke-color:#000}.lms-ui-icon-hosting,.lms-ui-icon-radius{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-hosting.fa-pull-left,.lms-ui-icon-radius.fa-pull-left{margin-right:.3em}.lms-ui-icon-hosting.fa-pull-right,.lms-ui-icon-radius.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-hosting,.lms-ui-icon-radius{font-size:125%}}.lms-ui-icon-hosting:before,.lms-ui-icon-radius:before{content:"\f233"}.lms-ui-icon-document{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-document.fa-pull-left{margin-right:.3em}.lms-ui-icon-document.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-document{font-size:125%}}.lms-ui-icon-document:before{content:"\f15c"}.lms-ui-icon-stats{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-stats.fa-pull-left{margin-right:.3em}.lms-ui-icon-stats.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-stats{font-size:125%}}.lms-ui-icon-stats:before{content:"\f201"}.lms-ui-icon-externalid{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-externalid.fa-pull-left{margin-right:.3em}.lms-ui-icon-externalid.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-externalid{font-size:125%}}.lms-ui-icon-externalid:before{content:"\f1c0"}.lms-ui-icon-external,.lms-ui-icon-popup{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-external.fa-pull-left,.lms-ui-icon-popup.fa-pull-left{margin-right:.3em}.lms-ui-icon-external.fa-pull-right,.lms-ui-icon-popup.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-external,.lms-ui-icon-popup{font-size:125%}}.lms-ui-icon-external:before,.lms-ui-icon-popup:before{content:"\f35d"}.lms-ui-icon-message{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-message.fa-pull-left{margin-right:.3em}.lms-ui-icon-message.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-message{font-size:125%}}.lms-ui-icon-message:before{content:"\f0e0"}.lms-ui-icon-note{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-note.fa-pull-left{margin-right:.3em}.lms-ui-icon-note.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-note{font-size:125%}}.lms-ui-icon-note:before{content:"\f304"}.lms-ui-icon-documentation{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-documentation.fa-pull-left{margin-right:.3em}.lms-ui-icon-documentation.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-documentation{font-size:125%}}.lms-ui-icon-documentation:before{content:"\f02d"}.lms-ui-icon-lastloggedin .lms-ui-icon-key,.lms-ui-icon-password,.lms-ui-icon-sensible,.lms-ui-icon-sensible-data{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-lastloggedin .lms-ui-icon-key.fa-pull-left,.lms-ui-icon-password.fa-pull-left,.lms-ui-icon-sensible-data.fa-pull-left,.lms-ui-icon-sensible.fa-pull-left{margin-right:.3em}.lms-ui-icon-lastloggedin .lms-ui-icon-key.fa-pull-right,.lms-ui-icon-password.fa-pull-right,.lms-ui-icon-sensible-data.fa-pull-right,.lms-ui-icon-sensible.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-lastloggedin .lms-ui-icon-key,.lms-ui-icon-password,.lms-ui-icon-sensible,.lms-ui-icon-sensible-data{font-size:125%}}.lms-ui-icon-lastloggedin .lms-ui-icon-key:before,.lms-ui-icon-password:before,.lms-ui-icon-sensible-data:before,.lms-ui-icon-sensible:before{content:"\f084"}.lms-ui-icon-reply,.lms-ui-icon-reply-all{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-reply-all.fa-pull-left,.lms-ui-icon-reply.fa-pull-left{margin-right:.3em}.lms-ui-icon-reply-all.fa-pull-right,.lms-ui-icon-reply.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-reply,.lms-ui-icon-reply-all{font-size:125%}}.lms-ui-icon-reply-all:before,.lms-ui-icon-reply:before{content:"\f122"}.lms-ui-icon-citing,.lms-ui-icon-quote{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-citing.fa-pull-left,.lms-ui-icon-quote.fa-pull-left{margin-right:.3em}.lms-ui-icon-citing.fa-pull-right,.lms-ui-icon-quote.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-citing,.lms-ui-icon-quote{font-size:125%}}.lms-ui-icon-citing:before,.lms-ui-icon-quote:before{content:"\f10e"}.lms-ui-icon-chat,.lms-ui-icon-comment,.lms-ui-icon-comments{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-chat.fa-pull-left,.lms-ui-icon-comment.fa-pull-left,.lms-ui-icon-comments.fa-pull-left{margin-right:.3em}.lms-ui-icon-chat.fa-pull-right,.lms-ui-icon-comment.fa-pull-right,.lms-ui-icon-comments.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-chat,.lms-ui-icon-comment,.lms-ui-icon-comments{font-size:125%}}.lms-ui-icon-chat:before,.lms-ui-icon-comment:before,.lms-ui-icon-comments:before{content:"\f086"}.lms-ui-icon-home{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-home.fa-pull-left{margin-right:.3em}.lms-ui-icon-home.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-home{font-size:125%}}.lms-ui-icon-home:before{content:"\f015"}.lms-ui-icon-link,.lms-ui-icon-url{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-link.fa-pull-left,.lms-ui-icon-url.fa-pull-left{margin-right:.3em}.lms-ui-icon-link.fa-pull-right,.lms-ui-icon-url.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-link,.lms-ui-icon-url{font-size:125%}}.lms-ui-icon-link:before,.lms-ui-icon-url:before{content:"\f0c1"}.lms-ui-icon-handshake,.lms-ui-icon-trust,.lms-ui-icon-warranty{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-handshake.fa-pull-left,.lms-ui-icon-trust.fa-pull-left,.lms-ui-icon-warranty.fa-pull-left{margin-right:.3em}.lms-ui-icon-handshake.fa-pull-right,.lms-ui-icon-trust.fa-pull-right,.lms-ui-icon-warranty.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-handshake,.lms-ui-icon-trust,.lms-ui-icon-warranty{font-size:125%}}.lms-ui-icon-handshake:before,.lms-ui-icon-trust:before,.lms-ui-icon-warranty:before{content:"\f2b5"}.lms-ui-icon-list{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-list.fa-pull-left{margin-right:.3em}.lms-ui-icon-list.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-list{font-size:125%}}.lms-ui-icon-list:before{content:"\f03a"}.lms-ui-icon-label,.lms-ui-icon-tags{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-label.fa-pull-left,.lms-ui-icon-tags.fa-pull-left{margin-right:.3em}.lms-ui-icon-label.fa-pull-right,.lms-ui-icon-tags.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-label,.lms-ui-icon-tags{font-size:125%}}.lms-ui-icon-label:before,.lms-ui-icon-tags:before{content:"\f02c"}.lms-ui-icon-fullscreen-on{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-fullscreen-on.fa-pull-left{margin-right:.3em}.lms-ui-icon-fullscreen-on.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-fullscreen-on{font-size:125%}}.lms-ui-icon-fullscreen-on:before{content:"\f0b2"}.lms-ui-icon-fullscreen-off{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-fullscreen-off.fa-pull-left{margin-right:.3em}.lms-ui-icon-fullscreen-off.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-fullscreen-off{font-size:125%}}.lms-ui-icon-fullscreen-off:before{content:"\f78c"}.lms-ui-icon-hide{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-hide.fa-pull-left{margin-right:.3em}.lms-ui-icon-hide.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-hide{font-size:125%}}.lms-ui-icon-hide:before{content:"\f00d"}.lms-ui-icon-gallery{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:400;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-gallery.fa-pull-left{margin-right:.3em}.lms-ui-icon-gallery.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-gallery{font-size:125%}}.lms-ui-icon-gallery:before{content:"\f302"}.lms-ui-icon-customisation{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-customisation.fa-pull-left{margin-right:.3em}.lms-ui-icon-customisation.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-customisation{font-size:125%}}.lms-ui-icon-customisation:before{content:"\f0d7"}.lms-ui-icon-optional-info{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-optional-info.fa-pull-left{margin-right:.3em}.lms-ui-icon-optional-info.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-optional-info{font-size:125%}}.lms-ui-icon-optional-info:before{content:"\f05a"}.lms-ui-icon-modified-date{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-modified-date.fa-pull-left{margin-right:.3em}.lms-ui-icon-modified-date.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-modified-date{font-size:125%}}.lms-ui-icon-modified-date:before{content:"\f4fd"}.lms-ui-icon-legal-personality{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-legal-personality.fa-pull-left{margin-right:.3em}.lms-ui-icon-legal-personality.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-legal-personality{font-size:125%}}.lms-ui-icon-legal-personality:before{content:"\f0b1"}.lms-ui-icon-division{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-division.fa-pull-left{margin-right:.3em}.lms-ui-icon-division.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-division{font-size:125%}}.lms-ui-icon-division:before{content:"\f1ad"}.lms-ui-icon-customer-pin-code{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-customer-pin-code.fa-pull-left{margin-right:.3em}.lms-ui-icon-customer-pin-code.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-customer-pin-code{font-size:125%}}.lms-ui-icon-customer-pin-code:before{content:"\f141"}.lms-ui-icon-more{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-more.fa-pull-left{margin-right:.3em}.lms-ui-icon-more.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-more{font-size:125%}}.lms-ui-icon-more:before{content:"\f103"}.lms-ui-icon-less{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-less.fa-pull-left{margin-right:.3em}.lms-ui-icon-less.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-less{font-size:125%}}.lms-ui-icon-less:before{content:"\f102"}.lms-ui-icon-user-id-number{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-user-id-number.fa-pull-left{margin-right:.3em}.lms-ui-icon-user-id-number.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-user-id-number{font-size:125%}}.lms-ui-icon-user-id-number:before{content:"\f2c2"}.lms-ui-icon-operator,.lms-ui-icon-sum,.lms-ui-icon-summary,.lms-ui-icon-total{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-operator.fa-pull-left,.lms-ui-icon-sum.fa-pull-left,.lms-ui-icon-summary.fa-pull-left,.lms-ui-icon-total.fa-pull-left{margin-right:.3em}.lms-ui-icon-operator.fa-pull-right,.lms-ui-icon-sum.fa-pull-right,.lms-ui-icon-summary.fa-pull-right,.lms-ui-icon-total.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-operator,.lms-ui-icon-sum,.lms-ui-icon-summary,.lms-ui-icon-total{font-size:125%}}.lms-ui-icon-operator:before,.lms-ui-icon-sum:before,.lms-ui-icon-summary:before,.lms-ui-icon-total:before{content:"\f1ec"}.lms-ui-icon-account-number{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-account-number.fa-pull-left{margin-right:.3em}.lms-ui-icon-account-number.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-account-number{font-size:125%}}.lms-ui-icon-account-number:before{content:"\f09d"}.lms-ui-icon-customer-status-connected{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-customer-status-connected.fa-pull-left{margin-right:.3em}.lms-ui-icon-customer-status-connected.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-customer-status-connected{font-size:125%}}.lms-ui-icon-customer-status-connected:before{content:"\f4fc"}.lms-ui-icon-customer-status-awaiting{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-customer-status-awaiting.fa-pull-left{margin-right:.3em}.lms-ui-icon-customer-status-awaiting.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-customer-status-awaiting{font-size:125%}}.lms-ui-icon-customer-status-awaiting:before{color:green;content:"\f4fd"}.lms-ui-icon-customer-status-interested{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-customer-status-interested.fa-pull-left{margin-right:.3em}.lms-ui-icon-customer-status-interested.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-customer-status-interested{font-size:125%}}.lms-ui-icon-customer-status-interested:before{content:"\f234"}.lms-ui-icon-customer-status-disconnected{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-customer-status-disconnected.fa-pull-left{margin-right:.3em}.lms-ui-icon-customer-status-disconnected.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-customer-status-disconnected{font-size:125%}}.lms-ui-icon-customer-status-disconnected:before{content:"\f235"}.lms-ui-icon-customer-status-debtcollection{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-customer-status-debtcollection.fa-pull-left{margin-right:.3em}.lms-ui-icon-customer-status-debtcollection.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-customer-status-debtcollection{font-size:125%}}.lms-ui-icon-customer-status-debtcollection:before{color:red;content:"\f4fa"}.lms-ui-icon-redo,.lms-ui-icon-resend{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-redo.fa-pull-left,.lms-ui-icon-resend.fa-pull-left{margin-right:.3em}.lms-ui-icon-redo.fa-pull-right,.lms-ui-icon-resend.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-redo,.lms-ui-icon-resend{font-size:125%}}.lms-ui-icon-redo:before,.lms-ui-icon-resend:before{content:"\f01e"}.lms-ui-icon-additional-selection,.lms-ui-icon-secondary-selection{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-additional-selection.fa-pull-left,.lms-ui-icon-secondary-selection.fa-pull-left{margin-right:.3em}.lms-ui-icon-additional-selection.fa-pull-right,.lms-ui-icon-secondary-selection.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-additional-selection,.lms-ui-icon-secondary-selection{font-size:125%}}.lms-ui-icon-additional-selection:before,.lms-ui-icon-secondary-selection:before{content:"\f142"}.lms-ui-icon-menu{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-menu.fa-pull-left{margin-right:.3em}.lms-ui-icon-menu.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-menu{font-size:125%}}.lms-ui-icon-menu:before{content:"\f0c9"}.lms-ui-icon-routed,.lms-ui-icon-routing{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-routed.fa-pull-left,.lms-ui-icon-routing.fa-pull-left{margin-right:.3em}.lms-ui-icon-routed.fa-pull-right,.lms-ui-icon-routing.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-routed,.lms-ui-icon-routing{font-size:125%}}.lms-ui-icon-routed:before,.lms-ui-icon-routing:before{content:"\f4d7"}.lms-ui-icon-finger-up{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-finger-up.fa-pull-left{margin-right:.3em}.lms-ui-icon-finger-up.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-finger-up{font-size:125%}}.lms-ui-icon-finger-up:before{content:"\f0a6"}.lms-ui-icon-finger-down{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-finger-down.fa-pull-left{margin-right:.3em}.lms-ui-icon-finger-down.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-finger-down{font-size:125%}}.lms-ui-icon-finger-down:before{content:"\f0a7"}.lms-ui-icon-karma,.lms-ui-icon-star{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-karma.fa-pull-left,.lms-ui-icon-star.fa-pull-left{margin-right:.3em}.lms-ui-icon-karma.fa-pull-right,.lms-ui-icon-star.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-karma,.lms-ui-icon-star{font-size:125%}}.lms-ui-icon-karma:before,.lms-ui-icon-star:before{content:"\f005"}.lms-ui-icon-bell,.lms-ui-icon-notification,.lms-ui-icon-notifications,.lms-ui-icon-notify{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-bell.fa-pull-left,.lms-ui-icon-notification.fa-pull-left,.lms-ui-icon-notifications.fa-pull-left,.lms-ui-icon-notify.fa-pull-left{margin-right:.3em}.lms-ui-icon-bell.fa-pull-right,.lms-ui-icon-notification.fa-pull-right,.lms-ui-icon-notifications.fa-pull-right,.lms-ui-icon-notify.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-bell,.lms-ui-icon-notification,.lms-ui-icon-notifications,.lms-ui-icon-notify{font-size:125%}}.lms-ui-icon-bell:before,.lms-ui-icon-notification:before,.lms-ui-icon-notifications:before,.lms-ui-icon-notify:before{content:"\f0f3"}.lms-ui-icon-color,.lms-ui-icon-colour,.lms-ui-icon-palette{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-color.fa-pull-left,.lms-ui-icon-colour.fa-pull-left,.lms-ui-icon-palette.fa-pull-left{margin-right:.3em}.lms-ui-icon-color.fa-pull-right,.lms-ui-icon-colour.fa-pull-right,.lms-ui-icon-palette.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-color,.lms-ui-icon-colour,.lms-ui-icon-palette{font-size:125%}}.lms-ui-icon-color:before,.lms-ui-icon-colour:before,.lms-ui-icon-palette:before{content:"\f53f"}.lms-ui-icon-csv{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-csv.fa-pull-left{margin-right:.3em}.lms-ui-icon-csv.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-csv{font-size:125%}}.lms-ui-icon-csv:before{content:"\f6dd"}.lms-ui-icon-reward{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-reward.fa-pull-left{margin-right:.3em}.lms-ui-icon-reward.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-reward{font-size:125%}}.lms-ui-icon-reward:before{content:"\f091"}.lms-ui-icon-penalty{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-penalty.fa-pull-left{margin-right:.3em}.lms-ui-icon-penalty.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-penalty{font-size:125%}}.lms-ui-icon-penalty:before{content:"\f714"}.lms-ui-icon-hardware,.lms-ui-icon-mac,.lms-ui-icon-model,.lms-ui-icon-producer{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-hardware.fa-pull-left,.lms-ui-icon-mac.fa-pull-left,.lms-ui-icon-model.fa-pull-left,.lms-ui-icon-producer.fa-pull-left{margin-right:.3em}.lms-ui-icon-hardware.fa-pull-right,.lms-ui-icon-mac.fa-pull-right,.lms-ui-icon-model.fa-pull-right,.lms-ui-icon-producer.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-hardware,.lms-ui-icon-mac,.lms-ui-icon-model,.lms-ui-icon-producer{font-size:125%}}.lms-ui-icon-hardware:before,.lms-ui-icon-mac:before,.lms-ui-icon-model:before,.lms-ui-icon-producer:before{content:"\f2db"}.lms-ui-icon-accounting,.lms-ui-icon-period{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-accounting.fa-pull-left,.lms-ui-icon-period.fa-pull-left{margin-right:.3em}.lms-ui-icon-accounting.fa-pull-right,.lms-ui-icon-period.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-accounting,.lms-ui-icon-period{font-size:125%}}.lms-ui-icon-accounting:before,.lms-ui-icon-period:before{content:"\f017"}.lms-ui-icon-recipient{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-recipient.fa-pull-left{margin-right:.3em}.lms-ui-icon-recipient.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-recipient{font-size:125%}}.lms-ui-icon-recipient:before{content:"\f2c1"}.lms-ui-icon-discount{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-discount.fa-pull-left{margin-right:.3em}.lms-ui-icon-discount.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-discount{font-size:125%}}.lms-ui-icon-discount:before{content:"\f295"}.lms-ui-icon-quantity{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-quantity.fa-pull-left{margin-right:.3em}.lms-ui-icon-quantity.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-quantity{font-size:125%}}.lms-ui-icon-quantity:before{content:"\f58d"}.lms-ui-icon-template{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-template.fa-pull-left{margin-right:.3em}.lms-ui-icon-template.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-template{font-size:125%}}.lms-ui-icon-template:before{content:"\f5bf"}.lms-ui-icon-permissions{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-permissions.fa-pull-left{margin-right:.3em}.lms-ui-icon-permissions.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-permissions{font-size:125%}}.lms-ui-icon-permissions:before{content:"\f502"}.lms-ui-icon-filter{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-filter.fa-pull-left{margin-right:.3em}.lms-ui-icon-filter.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-filter{font-size:125%}}.lms-ui-icon-filter:before{content:"\f0b0"}.lms-ui-icon-fiber,.lms-ui-icon-fibre{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Brands';font-weight:400;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-fiber.fa-pull-left,.lms-ui-icon-fibre.fa-pull-left{margin-right:.3em}.lms-ui-icon-fiber.fa-pull-right,.lms-ui-icon-fibre.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-fiber,.lms-ui-icon-fibre{font-size:125%}}.lms-ui-icon-fiber:before,.lms-ui-icon-fibre:before{content:"\f391"}.lms-ui-icon-tax,.lms-ui-icon-taxrate{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-tax.fa-pull-left,.lms-ui-icon-taxrate.fa-pull-left{margin-right:.3em}.lms-ui-icon-tax.fa-pull-right,.lms-ui-icon-taxrate.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-tax,.lms-ui-icon-taxrate{font-size:125%}}.lms-ui-icon-tax:before,.lms-ui-icon-taxrate:before{content:"\f0f2"}.lms-ui-icon-execute,.lms-ui-icon-launch,.lms-ui-icon-run{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-execute.fa-pull-left,.lms-ui-icon-launch.fa-pull-left,.lms-ui-icon-run.fa-pull-left{margin-right:.3em}.lms-ui-icon-execute.fa-pull-right,.lms-ui-icon-launch.fa-pull-right,.lms-ui-icon-run.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-execute,.lms-ui-icon-launch,.lms-ui-icon-run{font-size:125%}}.lms-ui-icon-execute:before,.lms-ui-icon-launch:before,.lms-ui-icon-run:before{content:"\f120"}.lms-ui-icon-area{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-area.fa-pull-left{margin-right:.3em}.lms-ui-icon-area.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-area{font-size:125%}}.lms-ui-icon-area:before{content:"\f0c8"}.lms-ui-icon-antenna{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-antenna.fa-pull-left{margin-right:.3em}.lms-ui-icon-antenna.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-antenna{font-size:125%}}.lms-ui-icon-antenna:before{content:"\f519"}.lms-ui-icon-share{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-share.fa-pull-left{margin-right:.3em}.lms-ui-icon-share.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-share{font-size:125%}}.lms-ui-icon-share:before{content:"\f1e0"}.lms-ui-icon-map{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-map.fa-pull-left{margin-right:.3em}.lms-ui-icon-map.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-map{font-size:125%}}.lms-ui-icon-map:before{content:"\f5a0"}.lms-ui-icon-mic,.lms-ui-icon-microphone{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-mic.fa-pull-left,.lms-ui-icon-microphone.fa-pull-left{margin-right:.3em}.lms-ui-icon-mic.fa-pull-right,.lms-ui-icon-microphone.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-mic,.lms-ui-icon-microphone{font-size:125%}}.lms-ui-icon-mic:before,.lms-ui-icon-microphone:before{content:"\f130"}@keyframes fa-beat{0%{transform:scale(1)}5%{transform:scale(1.25)}10%{transform:scale(1.5)}15%{transform:scale(1.25)}20%{transform:scale(1)}30%{transform:scale(1.25)}35%{transform:scale(1.5)}40%{transform:scale(1.25)}45%{transform:scale(1)}55%{transform:scale(1.25)}60%{transform:scale(1.5)}65%{transform:scale(1.25)}70%{transform:scale(1)}75%{transform:scale(1.25)}80%{transform:scale(1.5)}85%{transform:scale(1.25)}90%{transform:scale(1)}}.fa-beat{animation:fa-beat 5s ease infinite}.lms-ui-icon-barcode{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-barcode.fa-pull-left{margin-right:.3em}.lms-ui-icon-barcode.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-barcode{font-size:125%}}.lms-ui-icon-barcode:before{content:"\f02a"}.lms-ui-icon-fiber-optic,.lms-ui-icon-fiberoptic,.lms-ui-icon-fibre-optic{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-fiber-optic.fa-pull-left,.lms-ui-icon-fiberoptic.fa-pull-left,.lms-ui-icon-fibre-optic.fa-pull-left{margin-right:.3em}.lms-ui-icon-fiber-optic.fa-pull-right,.lms-ui-icon-fiberoptic.fa-pull-right,.lms-ui-icon-fibre-optic.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-fiber-optic,.lms-ui-icon-fiberoptic,.lms-ui-icon-fibre-optic{font-size:125%}}.lms-ui-icon-fiber-optic:before,.lms-ui-icon-fiberoptic:before,.lms-ui-icon-fibre-optic:before{content:"\f0eb"}.lms-ui-icon-tv{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-tv.fa-pull-left{margin-right:.3em}.lms-ui-icon-tv.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-tv{font-size:125%}}.lms-ui-icon-tv:before{content:"\f26c"}.lms-ui-icon-ignore,.lms-ui-icon-ignored{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:400;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-ignore.fa-pull-left,.lms-ui-icon-ignored.fa-pull-left{margin-right:.3em}.lms-ui-icon-ignore.fa-pull-right,.lms-ui-icon-ignored.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-ignore,.lms-ui-icon-ignored{font-size:125%}}.lms-ui-icon-ignore:before,.lms-ui-icon-ignored:before{content:"\f28d"}.lms-ui-icon-netrange-theoretical{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-netrange-theoretical.fa-pull-left{margin-right:.3em}.lms-ui-icon-netrange-theoretical.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-netrange-theoretical{font-size:125%}}.lms-ui-icon-netrange-theoretical:before{content:"\f059"}.lms-ui-icon-netrange-real{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-netrange-real.fa-pull-left{margin-right:.3em}.lms-ui-icon-netrange-real.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-netrange-real{font-size:125%}}.lms-ui-icon-netrange-real:before{content:"\f058"}.lms-ui-icon-transfer{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}.lms-ui-icon-transfer.fa-pull-left{margin-right:.3em}.lms-ui-icon-transfer.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){.lms-ui-icon-transfer{font-size:125%}}.lms-ui-icon-transfer:before{content:"\f079"}.dataTables_wrapper{margin-bottom:4px;position:static}.dataTables_wrapper .dataTables_processing{font-weight:700}.dataTables_wrapper .top{display:flex;justify-content:space-around;flex-wrap:wrap}.dataTables_wrapper div.lms-ui-datatable-toolbar{display:flex;justify-content:space-between}.dataTables_wrapper .dataTables_length{padding-left:4px;padding-top:5px;white-space:nowrap}.dataTables_wrapper div.lms-ui-datatable-clear-settings{float:left;padding-left:4px;padding-top:4px;cursor:pointer}.dataTables_wrapper div.lms-ui-datatable-column-toggle{float:left;padding-left:3px;padding-top:4px}.dataTables_wrapper .dataTables_paginate{float:left;text-align:center;padding-top:2px}.dataTables_wrapper .dataTables_filter{padding-right:4px;padding-top:5px}.dataTables_wrapper .dataTables_info{float:none;text-align:center;padding-top:3px;padding-bottom:3px;font-weight:700}.dataTables_wrapper .top{border:1px solid #000;border-bottom:0}.dataTables_wrapper .bottom{border:1px solid #000;border-top:0}#lms-ui-spinner{position:fixed;left:0;top:0;width:100%;height:100%;display:flex;justify-content:center;align-items:center}.lms-ui-sk-fading-circle{margin:100px 10px;width:80px;height:80px;position:relative}.lms-ui-sk-fading-circle .lms-ui-sk-circle{width:100%;height:100%;position:absolute;left:0;top:0}.lms-ui-sk-fading-circle .lms-ui-sk-circle:before{content:'';display:block;margin:0 auto;width:15%;height:15%;background-color:#333;border-radius:100%;-webkit-animation:lms-ui-sk-circleFadeDelay 1.2s infinite ease-in-out both;animation:lms-ui-sk-circleFadeDelay 1.2s infinite ease-in-out both}.lms-ui-sk-fading-circle .lms-ui-sk-circle2{-webkit-transform:rotate(30deg);-ms-transform:rotate(30deg);transform:rotate(30deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle3{-webkit-transform:rotate(60deg);-ms-transform:rotate(60deg);transform:rotate(60deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle4{-webkit-transform:rotate(90deg);-ms-transform:rotate(90deg);transform:rotate(90deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle5{-webkit-transform:rotate(120deg);-ms-transform:rotate(120deg);transform:rotate(120deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle6{-webkit-transform:rotate(150deg);-ms-transform:rotate(150deg);transform:rotate(150deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle7{-webkit-transform:rotate(180deg);-ms-transform:rotate(180deg);transform:rotate(180deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle8{-webkit-transform:rotate(210deg);-ms-transform:rotate(210deg);transform:rotate(210deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle9{-webkit-transform:rotate(240deg);-ms-transform:rotate(240deg);transform:rotate(240deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle10{-webkit-transform:rotate(270deg);-ms-transform:rotate(270deg);transform:rotate(270deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle11{-webkit-transform:rotate(300deg);-ms-transform:rotate(300deg);transform:rotate(300deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle12{-webkit-transform:rotate(330deg);-ms-transform:rotate(330deg);transform:rotate(330deg)}.lms-ui-sk-fading-circle .lms-ui-sk-circle2:before{-webkit-animation-delay:-1.1s;animation-delay:-1.1s}.lms-ui-sk-fading-circle .lms-ui-sk-circle3:before{-webkit-animation-delay:-1s;animation-delay:-1s}.lms-ui-sk-fading-circle .lms-ui-sk-circle4:before{-webkit-animation-delay:-.9s;animation-delay:-.9s}.lms-ui-sk-fading-circle .lms-ui-sk-circle5:before{-webkit-animation-delay:-.8s;animation-delay:-.8s}.lms-ui-sk-fading-circle .lms-ui-sk-circle6:before{-webkit-animation-delay:-.7s;animation-delay:-.7s}.lms-ui-sk-fading-circle .lms-ui-sk-circle7:before{-webkit-animation-delay:-.6s;animation-delay:-.6s}.lms-ui-sk-fading-circle .lms-ui-sk-circle8:before{-webkit-animation-delay:-.5s;animation-delay:-.5s}.lms-ui-sk-fading-circle .lms-ui-sk-circle9:before{-webkit-animation-delay:-.4s;animation-delay:-.4s}.lms-ui-sk-fading-circle .lms-ui-sk-circle10:before{-webkit-animation-delay:-.3s;animation-delay:-.3s}.lms-ui-sk-fading-circle .lms-ui-sk-circle11:before{-webkit-animation-delay:-.2s;animation-delay:-.2s}.lms-ui-sk-fading-circle .lms-ui-sk-circle12:before{-webkit-animation-delay:-.1s;animation-delay:-.1s}@-webkit-keyframes lms-ui-sk-circleFadeDelay{0%,100%,39%{opacity:0}40%{opacity:1}}@keyframes lms-ui-sk-circleFadeDelay{0%,100%,39%{opacity:0}40%{opacity:1}}.lms-ui-list-container{display:flex;align-items:flex-start!important}.lms-ui-list-container ul{display:inline;list-style:none;padding:0;margin-block-start:0;margin-block-end:0}.lms-ui-list-container li .lms-ui-list-unlink{visibility:hidden;margin-top:.1em;padding-right:.4em}.lms-ui-list-container li:hover .lms-ui-list-unlink{visibility:visible;cursor:pointer}.lms-ui-list-container.disabled{cursor:default!important;color:#888!important}.lms-ui-list-container.disabled a{cursor:default!important}.lms-ui-list-container.disabled i::before{color:#888!important}.lms-ui-list-container .lms-ui-item-suggestion-button{margin:0}.lms-ui-list-suggestion-container .lms-ui-list-suggestion-button{cursor:pointer}.lms-ui-list-suggestion-container .lms-ui-list-suggestion:not(:focus){display:none}button{font-size:10pt}@media screen and (max-width:1920px){button{font-size:9pt}}@media screen and (max-width:1200px){button{font-size:8pt}}button.lms-ui-button{display:inline-flex;align-items:center}button.lms-ui-link-button{display:inline-block}a.lms-ui-link-button{vertical-align:top;display:inline-flex;align-items:center}a.lms-ui-link-button,button.lms-ui-button{box-sizing:border-box;padding:.33em;padding-top:.15em;padding-bottom:.15em;margin-top:.25em;margin-bottom:.25em;min-height:2.5em;border:1px solid #615847;color:#000!important;text-decoration:none;background-color:#DFD5BD;background-repeat:no-repeat;background-position:3px 3px;outline:0}a.lms-ui-link-button.lms-ui-button-icon,button.lms-ui-button.lms-ui-button-icon{padding-left:25px}a.lms-ui-link-button:hover,button.lms-ui-button:hover{text-decoration:none}a.lms-ui-link-button:not([disabled]):active,button.lms-ui-button:not([disabled]):active{background-color:#CEBD9B;box-shadow:inset 1px 1px 4px 0 rgba(0,0,0,.4)}a.lms-ui-link-button:not([disabled]):focus,button.lms-ui-button:not([disabled]):focus{box-shadow:0 0 1px 1px #000}a.lms-ui-link-button:not([disabled]):hover,button.lms-ui-button:not([disabled]):hover{box-shadow:0 0 3px 1px #000}a.lms-ui-link-button:not([disabled]):hover.alert,a.lms-ui-link-button:not([disabled]):hover.lms-ui-error,button.lms-ui-button:not([disabled]):hover.alert,button.lms-ui-button:not([disabled]):hover.lms-ui-error{box-shadow:0 0 3px 1px red}a.lms-ui-link-button:not([disabled]):hover.lms-ui-warning,button.lms-ui-button:not([disabled]):hover.lms-ui-warning{box-shadow:0 0 3px 1px Orange}a.lms-ui-link-button[disabled],button.lms-ui-button[disabled]{color:#888!important;cursor:no-drop}a.lms-ui-link-button[disabled]:before,button.lms-ui-button[disabled]:before{color:#888!important}a.lms-ui-link-button.alert,a.lms-ui-link-button.lms-ui-error,button.lms-ui-button.alert,button.lms-ui-button.lms-ui-error{box-shadow:0 0 3px 1px red}a.lms-ui-link-button.alert:focus,a.lms-ui-link-button.lms-ui-error:focus,button.lms-ui-button.alert:focus,button.lms-ui-button.lms-ui-error:focus{border:1px solid #a32828;box-shadow:0 0 1px 1px #a32828}a.lms-ui-link-button.lms-ui-warning,button.lms-ui-button.lms-ui-warning{box-shadow:0 0 3px 1px Orange}a.lms-ui-link-button.lms-ui-warning:focus,button.lms-ui-button.lms-ui-warning:focus{border:1px solid Orange;box-shadow:0 0 1px 1px Orange}a.lms-ui-link-button .lms-ui-label,button.lms-ui-button .lms-ui-label{font-weight:700;vertical-align:middle}a.lms-ui-link-button i+.lms-ui-label,button.lms-ui-button i+.lms-ui-label{padding-left:.5em}a.lms-ui-button i+.lms-ui-label{padding-left:.5em}a.lms-ui-button:not(.lms-ui-link-button){border:1px solid transparent;display:inline-block}a.lms-ui-button:not(.lms-ui-link-button)>i:before{color:#000}a.lms-ui-button:not(.lms-ui-link-button)>i{text-align:center;padding:0 .1em}a.lms-ui-button:not(.lms-ui-link-button):hover{cursor:pointer;border:1px solid #615847;border-radius:3px;display:inline-block;text-decoration:none}a.lms-ui-button:not(.lms-ui-link-button)[disabled]{color:#888!important;cursor:no-drop}a.lms-ui-button:not(.lms-ui-link-button)[disabled]:before{color:#888!important}a.lms-ui-button:not(.lms-ui-link-button)[disabled]>i:before{color:#888!important}a.lms-ui-link-button+button.lms-ui-button{margin-left:.33em}.lms-ui-responsive-buttons{display:inline-block}.lms-ui-responsive-buttons>*{padding-left:.1em;padding-right:.1em}.lms-ui-responsive-buttons .lms-ui-dropdown-toggle{display:none!important;cursor:pointer}.lms-ui-responsive-buttons .lms-ui-dropdown-toggle.secondary{display:inline!important}@media screen and (max-width:800px){.lms-ui-responsive-buttons .lms-ui-dropdown-toggle{font-size:1.33333333em;line-height:.75em;vertical-align:-.0667em;line-height:normal}}.lms-ui-responsive-buttons .lms-ui-dropdown-buttons{display:inline}.lms-ui-responsive-buttons .lms-ui-dropdown-buttons .lms-ui-button.secondary{display:none}@media screen and (max-width:1200px){.lms-ui-responsive-buttons .lms-ui-dropdown-toggle{display:inline-flex!important}.lms-ui-responsive-buttons .lms-ui-dropdown-toggle.secondary{display:none!important}.lms-ui-responsive-buttons .lms-ui-dropdown-buttons{display:none;padding:.2em;position:absolute;background-color:#DFD5BD;border:1px solid #000;box-shadow:0 8px 16px 0 rgba(0,0,0,.2);z-index:1}.lms-ui-responsive-buttons .lms-ui-dropdown-buttons.show{display:flex}.lms-ui-responsive-buttons .lms-ui-dropdown-buttons .lms-ui-button{display:none}}td>button:last-child{margin-right:.5em}i.lms-ui-button-clipboard:hover{cursor:pointer}i.lms-ui-button-clipboard:hover:not(.lms-ui-static){font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%}i.lms-ui-button-clipboard:hover:not(.lms-ui-static).fa-pull-left{margin-right:.3em}i.lms-ui-button-clipboard:hover:not(.lms-ui-static).fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){i.lms-ui-button-clipboard:hover:not(.lms-ui-static){font-size:125%}}i.lms-ui-button-clipboard:hover:not(.lms-ui-static):before{content:"\f0c5"}a.lms-ui-button:not(.lms-ui-link-button).lms-ui-button-speech-recognition.active{animation:fa-beat 5s ease infinite}a.lms-ui-button:not(.lms-ui-link-button).lms-ui-button-speech-recognition.active>i:before{color:red}.lms-ui-util-buttons{display:flex;flex-direction:column}.ui-widget.ui-widget-content{border:1px solid #615847}.ui-tabs .ui-tabs-nav{border-top:0;border-right:0;border-bottom:1px dotted grey;border-bottom-right-radius:0;margin-right:.4em}.ui-tabs.ui-widget.ui-widget-content{border:0}.ui-tabs.ui-widget-content{background-color:transparent}.ui-tabs .ui-widget-header{background-color:transparent;padding:0}.ui-tabs .ui-tabs-panel{border:1px dotted grey;border-top:none;border-top-left-radius:0}.ui-tabs .ui-tab .alert,.ui-tabs .ui-tab.lms-ui-error,.ui-tabs .ui-tab:invalid{box-shadow:0 0 3px 1px red!important}.ui-tabs .ui-tab .alert:focus,.ui-tabs .ui-tab.lms-ui-error:focus,.ui-tabs .ui-tab:invalid:focus{box-shadow:0 0 1px 1px #a32828!important}.ui-tabs .ui-tab.lms-ui-warning{box-shadow:0 0 3px 1px Orange!important}.ui-tabs .ui-tab.lms-ui-warning:focus{box-shadow:0 0 1px 1px Orange!important}.ui-tabs .ui-tab.ui-tabs-tab{background-color:#CEBD9B;box-shadow:none;margin-left:-.1em}.ui-tabs .ui-tab.ui-tabs-active .ui-tabs-anchor{color:#000;font-weight:700;outline:0}.ui-tabs .ui-tab.ui-tabs-active.ui-tabs-tab{background-color:#DFD5BD;border:1px dotted grey;border-bottom:none;box-shadow:unset}.ui-tabs .ui-tab.ui-tabs-active:focus{border:1px solid #615847;border-bottom:none}.ui-widget-overlay{opacity:.5}.ui-button,.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default,html .ui-button.ui-state-disabled:active,html .ui-button.ui-state-disabled:hover{padding:0 1em;border:1px solid #615847;background-color:#DFD5BD}.ui-state-default,.ui-widget-content .ui-state-default{padding:0;text-align:center}.ui-button:focus,.ui-button:hover,.ui-state-focus,.ui-state-hover,.ui-widget-content .ui-state-focus,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-focus,.ui-widget-header .ui-state-hover{box-shadow:inset 1px 1px 3px 0 rgba(0,0,0,.6);background-color:#DFD5BD;border:1px solid #615847;outline:0;color:#000}.ui-selectmenu-text{padding-top:2px}.ui-selectmenu-button.ui-button{min-width:20em;width:auto}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{background-color:#fffa90}.ui-button.ui-state-active:hover,.ui-button:active,.ui-button:focus,.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{box-shadow:inset 1px 1px 4px 0 rgba(0,0,0,.4);background:#CEBD9B;border:1px solid #615847}.ui-dialog{background-color:#CEBD9B}.ui-dialog .ui-dialog-content{background-color:#CEBD9B}.ui-dialog .ui-dialog-buttonpane{background-color:#CEBD9B;border-top:0;padding-right:6px}.ui-dialog-content{background-color:#CEBD9B}.ui-dialog-titlebar{background-color:#B6A688;border:1px solid #B6A688;color:#333}.ui-dialog-buttonpane .ui-dialog-buttonset{width:100%;text-align:center}.ui-tooltip{background-color:#DFD5BD}.ui-tooltip.lms-ui-error{color:red}.ui-tooltip.lms-ui-warning{color:Sienna}.ui-datepicker{background-color:#B6A688}.ui-datepicker-header{background-color:#CEBD9B;border:1px solid #CEBD9B}.ui-datepicker-calendar{background-color:#CEBD9B}.ui-datepicker .ui-datepicker-buttonpane{border-top:1px solid #000;margin-top:0}.ui-datepicker-trigger{border:none;background:0 0;margin-left:.3em;padding:0}input[disabled]+.ui-datepicker-trigger{color:#888!important;cursor:no-drop}input[disabled]+.ui-datepicker-trigger:before{color:#888!important}.ui-tooltip.customerassignmentinfo,.ui-tooltip.customerinfo,.ui-tooltip.docnumber,.ui-tooltip.documentview,.ui-tooltip.ewxnodelist,.ui-tooltip.invoiceinfo,.ui-tooltip.netdevlist,.ui-tooltip.nodegroupinfo,.ui-tooltip.nodelist,.ui-tooltip.rtticketinfo,.ui-tooltip.voipaccountinfo{padding:0}.ui-dialog.documentviewdialog{min-width:200px;min-height:35px;position:absolute}.ui-dialog-content.documentviewdialog{padding:0!important;min-width:200px;min-height:35px}.fileupload-progress-dialog .ui-dialog-titlebar{display:none}.ui-progressbar{position:relative!important;background-color:#DFD5BD}.ui-progressbar .ui-progressbar-value{background-color:#B6A688;border-color:#B6A688}.ui-selected{background-color:#CFC}.ui-slider.ui-widget-content{background-color:#EBE4D6}.ui-slider-range{background-color:#CEBD9B;text-align:center;overflow:hidden;cursor:default}.ui-slider-handle.ui-state-default{background-color:#B6A688;margin-top:2px}.ui-slider-horizontal{height:1em}.ui-selectmenu-optgroup{background-color:#ebe4d6!important}.ui-menu-item{background-color:#ebe4d6!important}.ui-menu-item .ui-state-active,.ui-menu-item .ui-state-active:hover{color:#fff;background-color:#4a90d9!important}.ui-menu-item [class*=lms-ui-icon]{padding-right:.5em}.ui-sortable-handle{cursor:grab}.lms-ui-gallery-container{display:none}.lms-ui-gallery-container .lms-ui-gallery-overlay{position:fixed;left:0;top:0;width:100%;height:100%;z-index:52;opacity:.3;background-color:#000}.lms-ui-gallery-container .lms-ui-gallery{position:fixed;top:5em;bottom:5em;left:5em;right:5em;height:calc(100% - 10em);z-index:53}.lms-ui-gallery-container .lms-ui-gallery .galleria-info{width:auto}.lms-ui-gallery-container .lms-ui-gallery .galleria-buttons{position:absolute;top:.3em;right:.5em;z-index:10;color:#fff}.lms-ui-gallery-container .lms-ui-gallery .galleria-buttons i{cursor:pointer;font-size:2em}.lms-ui-gallery-container .lms-ui-gallery .galleria-buttons i:not(:last-child){margin-right:.3em}#lms-ui-popup-menu{display:none;z-index:80;flex-direction:column;position:absolute;max-width:25em;max-height:50vh;background-color:#DFD5BD;box-shadow:0 8px 16px 0 rgba(0,0,0,.2);padding:1em;font-weight:700}#lms-ui-popup-menu.open{display:flex}@media screen and (min-width:801px){#lms-ui-popup-menu{border:1px solid #000}}#lms-ui-popup-menu #lms-ui-popup-menu-titlebar{display:flex;justify-content:space-between;align-items:center;padding-bottom:.5em;margin-bottom:.5em;border-bottom:1px dotted grey}#lms-ui-popup-menu #lms-ui-popup-menu-titlebar i{margin-left:1.5em;cursor:pointer}#lms-ui-popup-menu #lms-ui-popup-menu-content{overflow-y:auto;max-height:calc(100% - 2.2em)}#lms-ui-popup-menu ul{list-style-type:none;display:inline-block;margin-block-start:0;margin-block-end:0;padding-inline-start:0;width:100%}#lms-ui-popup-menu ul li{padding-top:.25em;padding-bottom:.25em;padding-left:2.5em;padding-right:.5em;text-indent:-1.7em}@media screen and (max-width:800px){#lms-ui-popup-menu ul li:not(:last-child){border-bottom:1px dotted grey}}#lms-ui-popup-menu ul li:hover{background-color:#CFC;cursor:pointer}@media screen and (max-width:800px){#lms-ui-popup-menu{max-width:unset;max-height:unset;position:fixed;left:0;top:2em;right:0;bottom:0;font-size:200%}}.lms-ui-multiselect-container{display:inline-block;vertical-align:middle;min-height:1.8em}.lms-ui-multiselect-container .lms-ui-multiselect-label-workaround,.lms-ui-multiselect-container select{display:none}.lms-ui-multiselect-container .lms-ui-multiselect-launcher.lms-ui-error{border:1px solid red;box-shadow:0 0 3px 1px red}.lms-ui-multiselect-container .lms-ui-multiselect-launcher.lms-ui-error:focus{border:1px solid #a32828;box-shadow:0 0 1px 1px #a32828;outline:0}.lms-ui-multiselect-container.lms-ui-error{color:unset!important}.lms-ui-multiselect-container.lms-ui-error .lms-ui-multiselect-launcher{border:1px solid red;box-shadow:0 0 3px 1px red}.lms-ui-multiselect-container.lms-ui-error .lms-ui-multiselect-launcher:focus{border:1px solid #a32828;box-shadow:0 0 1px 1px #a32828;outline:0}.lms-ui-multiselect-container.lms-ui-distinguished,.lms-ui-multiselect-container.lms-ui-warning{color:unset!important}.lms-ui-multiselect-container.lms-ui-distinguished .lms-ui-multiselect-launcher,.lms-ui-multiselect-container.lms-ui-warning .lms-ui-multiselect-launcher{border:1px solid Orange;box-shadow:0 0 3px 1px Orange}.lms-ui-multiselect-container.lms-ui-distinguished .lms-ui-multiselect-launcher:focus,.lms-ui-multiselect-container.lms-ui-warning .lms-ui-multiselect-launcher:focus{border:1px solid Orange;box-shadow:0 0 1px 1px Orange;outline:0}.lms-ui-multiselect-container .lms-ui-multiselect-launcher{vertical-align:middle;background-color:#EBE4D6;border:1px solid #a9a9a9;min-height:1.6em;box-sizing:border-box;display:flex;flex-direction:row-reverse;align-items:center}.lms-ui-multiselect-container .lms-ui-multiselect-launcher .lms-ui-multiselect-launcher-label{font-size:10pt;font-family:Arial,Helvetica,Verdana;vertical-align:middle;cursor:default;padding:0 0 0 4px;max-width:200px;white-space:pre-wrap;min-width:200px;display:block}@media screen and (max-width:1920px){.lms-ui-multiselect-container .lms-ui-multiselect-launcher .lms-ui-multiselect-launcher-label{font-size:9pt}}@media screen and (max-width:1200px){.lms-ui-multiselect-container .lms-ui-multiselect-launcher .lms-ui-multiselect-launcher-label{font-size:8pt}}.lms-ui-multiselect-container .lms-ui-multiselect-launcher .lms-ui-multiselect-launcher-label.lms-ui-multiselect-filter{min-width:100px}.lms-ui-multiselect-container .lms-ui-multiselect-launcher .lms-ui-multiselect-launcher-toggle{float:right;margin-right:.2em;display:block;font-size:120%}.lms-ui-multiselect-container .lms-ui-multiselect-launcher .lms-ui-multiselect-clear-button{float:right;margin-right:.3em;margin-left:.3em;display:block;opacity:.4;font-size:100%;cursor:pointer;margin-top:.12em}.lms-ui-multiselect-container.tiny .lms-ui-multiselect-launcher{overflow:hidden;vertical-align:middle;cursor:pointer;display:flex;align-items:center;border-color:transparent;background-color:transparent;min-height:unset;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.lms-ui-multiselect-container .lms-ui-multiselect-popup{display:none;position:absolute;width:350px;border:solid 1px #888;background-color:#DFD5BD;z-index:65;overflow:hidden;box-shadow:0 8px 16px 0 rgba(0,0,0,.2);-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media screen and (max-width:800px){.lms-ui-multiselect-container .lms-ui-multiselect-popup{position:fixed;width:auto;left:0;top:2em;right:0;bottom:0;padding:.5em;font-size:200%;border:0}}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list{list-style:none;cursor:default;padding:0;margin:0;border-bottom:solid 1px #888;max-height:200px;max-width:350px;text-align:left;overflow-x:hidden;overflow-y:auto}@media screen and (max-width:800px){.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list{max-height:80%;max-width:unset;border:solid 1px #888}}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list li{white-space:normal;padding:0;margin:0;background-color:#EBE4D6;padding-left:2em;text-indent:-2em}@media screen and (max-width:800px){.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list li{padding-left:1.2em;text-indent:-1.1em}}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list li:not(:last-child){border-bottom:1px dotted grey}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list li input{border:none;margin:3px 3px 3px 4px}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list li.selected{background-color:#CEBD9B}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list li.active{background-color:#B6A688}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list li:not(.visible){display:none}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list li.exclusive{font-weight:700}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-list span{padding-left:3px}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-titlebar{display:none;justify-content:space-between;align-items:center;padding-bottom:.5em;margin-bottom:.5em;border-bottom:1px dotted grey}@media screen and (max-width:800px){.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-titlebar{display:flex}}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-titlebar .lms-ui-multiselect-popup-title{font-weight:700}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-titlebar i{margin-left:1.5em;cursor:pointer}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-checkall{width:100%}@media screen and (max-width:800px){.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-checkall{margin-top:.5em;border-top:1px dotted grey;padding-top:.5em}}.lms-ui-multiselect-container .lms-ui-multiselect-popup .lms-ui-multiselect-popup-checkall input{margin-right:.9em}@media screen and (min-width:801px){body.main-menu-visible{margin-left:17em}body.main-menu-visible #lms-ui-menu-panel{width:16em}body.main-menu-visible #lms-ui-tool-panels{margin-left:17em}}@media screen and (min-width:801px) and print{body.main-menu-visible{margin-left:0}}#lms-ui-menu-panel{z-index:2;background-color:#CEBD9B;overflow:hidden;border:1px solid #000;display:flex;flex-direction:column;justify-content:flex-start;align-items:stretch;position:fixed;left:0;top:0;height:100vh}@media screen and (min-width:801px){#lms-ui-menu-panel{box-shadow:1em 0 .9em #EBE4D6}}@media screen and (max-width:800px){#lms-ui-menu-panel{display:none;overflow-y:auto;border:0;font-size:200%;position:fixed;left:0;right:0;bottom:0;top:2em;z-index:50}#lms-ui-menu-panel.fullscreen-popup{display:unset}}#lms-ui-menu-panel #lms-ui-menu-panel-container{overflow-x:hidden;overflow-y:auto;margin-right:0;display:flex;flex-direction:column;justify-content:flex-start;align-items:center}#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-logo{margin-top:.3em;display:flex;justify-content:center;align-self:stretch}@media screen and (max-width:800px){#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-logo{display:none}}#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-logo :not(:first-child){margin-left:.3em;font-weight:700;align-self:flex-end}#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-logo a{color:initial}#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-logo a:hover{text-decoration:initial}#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-main-menu{margin-top:.5em;align-self:stretch}#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-session-expire{font-weight:700;color:#8b0000;align-self:stretch;text-align:center;margin-bottom:.5em}#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-division{align-self:stretch;text-align:center;margin-bottom:.5em;margin-left:.5em}#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-division>select{width:90%}@media screen and (max-width:801px){#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-division>select{font-size:80%;flex-grow:1}}#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-copyrights{font-weight:700;align-self:stretch;text-align:center;margin-bottom:.5em}@media screen and (max-width:801px){#lms-ui-menu-panel #lms-ui-menu-panel-container #lms-ui-copyrights{display:none}}#lms-ui-menu-panel-toggle{position:fixed;left:.15em;top:.15em;background-size:cover;width:.8em;height:.8em;cursor:pointer;z-index:3}@media screen and (max-width:800px){#lms-ui-menu-panel-toggle{display:none}}#lms-ui-menu-panel-toggle:not(.visible){background-color:#B6A688;padding:.1em 0 .3em .1em;border:1px solid #000;border-radius:0 0 .5em 0}@media screen and (min-width:801px){#lms-ui-menu-panel-toggle:not(.visible)~#lms-ui-contents #lms-ui-quicksearch-indicators-panel{padding-left:.5em}}#lms-ui-mobile-menu-container{position:fixed;left:0;right:0;top:0;height:2em;box-shadow:0 .7em .6em #EBE4D6;z-index:40;background-color:#EBE4D6;font-size:200%}@media screen and (min-width:801px){#lms-ui-mobile-menu-container{display:none}}#lms-ui-mobile-menu-container #lms-ui-mobile-menu-panel{border-bottom:1px solid #000;background-color:#CEBD9B;height:auto;width:100%}@media screen and (max-width:800px){#lms-ui-mobile-menu-container #lms-ui-mobile-menu-panel .lms-ui-button{margin-top:.2em;margin-bottom:.2em;border-radius:unset;border:0;border-right:1px solid #000}#lms-ui-mobile-menu-container #lms-ui-mobile-menu-panel .lms-ui-button:hover{border-radius:unset}}#lms-ui-modal-dialog ol{list-style:none;padding-left:0;width:90%}#lms-ui-modal-dialog ol li.message{font-weight:700}@media screen and (max-width:800px){.lms-ui-modal-dialog-wrapper{font-size:200%;position:fixed;left:0;right:0;top:0}.lms-ui-modal-dialog-wrapper .ui-dialog-titlebar-close{text-indent:unset;border:0!important;background-color:transparent!important;box-shadow:unset!important;right:.5em!important;top:40%!important}.lms-ui-modal-dialog-wrapper .ui-dialog-titlebar-close .lms-ui-icon-hide{position:absolute;text-indent:unset;width:0;height:0;left:0;top:0}}.chosen-container{text-align:left;min-width:250px;font-size:10pt;font-weight:initial}@media screen and (max-width:1920px){.chosen-container{font-size:9pt}}@media screen and (max-width:1200px){.chosen-container{font-size:8pt}}.chosen-container .chosen-results{color:#000}.chosen-container .chosen-results li.no-results{color:#000;background:#DFD5BD}.chosen-container .chosen-results li{padding:1px 6px}.chosen-container .chosen-results li em{background-color:#CEBD9B;font-weight:700;text-decoration:none}.chosen-container .chosen-results li.disabled-result{color:#888}.chosen-container.lms-ui-customer-address-select .chosen-single span{padding-top:1px;padding-bottom:1px}.chosen-container.lms-ui-customer-address-select .chosen-results li{padding:3px 6px}.chosen-container .chosen-drop{display:none;background-color:#EBE4D6;width:auto;min-width:15em}.chosen-container .chosen-drop li{white-space:nowrap}.chosen-container-active.chosen-with-drop .chosen-single{background-image:none}.chosen-container-active.chosen-with-drop .chosen-single div b{background-position-x:-12px;background-position-y:-2px}.chosen-with-drop .chosen-drop{display:block}.chosen-container-single.chosen-with-drop .chosen-single{border:1px solid #a9a9a9}.chosen-container-single .chosen-single{color:#000;background-color:#EBE4D6;background-image:none;line-height:normal;border-radius:unset;min-height:1.6em;height:unset;display:flex;align-items:center}.chosen-container-single .chosen-single div b{background-position-x:6px;background-position-y:-2px}.chosen-container-single.alert .chosen-single,.chosen-container-single.lms-ui-error .chosen-single,.chosen-container-single:invalid .chosen-single{border:1px solid red;box-shadow:0 0 3px 1px red}.chosen-container-single.alert .chosen-single:focus,.chosen-container-single.lms-ui-error .chosen-single:focus,.chosen-container-single:invalid .chosen-single:focus{border:1px solid #a32828;box-shadow:0 0 1px 1px #a32828;outline:0}.chosen-container-single.lms-ui-warning .chosen-single{border:1px solid Orange;background-color:Khaki;box-shadow:0 0 3px 1px Orange}.chosen-container-single.lms-ui-warning .chosen-single:focus{border:1px solid Orange;background-color:Khaki;box-shadow:0 0 1px 1px Orange}.chosen-container-single.lms-ui-distinguished .chosen-single{border:1px solid Orange;box-shadow:0 0 3px 1px Orange}.chosen-container-single.lms-ui-distinguished .chosen-single:focus{border:1px solid Orange;box-shadow:0 0 1px 1px Orange}.chosen-container-single .chosen-drop{border-radius:unset}.chosen-container-single .chosen-single-with-deselect span{margin-right:2em}.chosen-container-single .chosen-single abbr{top:2px;right:12px}.chosen-container-single .chosen-single div{width:18px}.chosen-container-multi .chosen-choices{color:#000;background-color:#EBE4D6;background-image:none;line-height:normal;border-radius:unset}.chosen-container-multi .chosen-choices div b{background-position-x:6px;background-position-y:-2px}.chosen-container-multi .chosen-choices li.search-choice{background-color:#DFD5BD;background-image:none;font-weight:700;border:1px solid #615847}.chosen-container-multi.alert .chosen-choices,.chosen-container-multi.lms-ui-error .chosen-choices,.chosen-container-multi:invalid .chosen-choices{border:1px solid red;box-shadow:0 0 3px 1px red}.chosen-container-multi.alert .chosen-choices:focus,.chosen-container-multi.lms-ui-error .chosen-choices:focus,.chosen-container-multi:invalid .chosen-choices:focus{border:1px solid #a32828;box-shadow:0 0 1px 1px #a32828;outline:0}.chosen-container-multi.lms-ui-warning .chosen-choices{border:1px solid Orange;background-color:Khaki;box-shadow:0 0 3px 1px Orange}.chosen-container-multi.lms-ui-warning .chosen-choices:focus{border:1px solid Orange;background-color:Khaki;box-shadow:0 0 1px 1px Orange}.chosen-container-multi.lms-ui-distinguished .chosen-choices{border:1px solid Orange;box-shadow:0 0 3px 1px Orange}.chosen-container-multi.lms-ui-distinguished .chosen-choices:focus{border:1px solid Orange;box-shadow:0 0 1px 1px Orange}.chosen-container-multi .chosen-drop .result-selected{color:#888}.scombobox{display:inline-block;margin:0}.scombobox-disabled .scombobox-display{cursor:no-drop}.scombobox-dropdown-background{background-color:transparent;border:unset}.scombobox-display{border-radius:unset;padding:0 19px 0 4px;min-height:1.6em}.scombobox-display.alert,.scombobox-display.lms-ui-error,.scombobox-display:invalid{border:1px solid red;box-shadow:0 0 3px 1px red}.scombobox-display.alert:focus,.scombobox-display.lms-ui-error:focus,.scombobox-display:invalid:focus{border:1px solid #a32828;box-shadow:0 0 1px 1px #a32828;outline:0}.scombobox-display.lms-ui-warning{border:1px solid Orange;background-color:Khaki;box-shadow:0 0 3px 1px Orange}.scombobox-display.lms-ui-warning:focus{border:1px solid Orange;background-color:Khaki;box-shadow:0 0 1px 1px Orange}.scombobox-list{border:1px solid #a9a9a9;box-shadow:0 8px 16px 0 rgba(0,0,0,.2);background-color:#EBE4D6;border-radius:unset}.scombobox-list p{padding:1px}.scombobox-list p:hover{background-color:#B6A688;color:#fff}.scombobox-list p.scombobox-hovered{background-color:#CEBD9B}.scombobox-list p.scombobox-hovered:hover{background-color:#B6A688;color:#fff}label>.lms-ui-customer-select-container{margin-left:.4em}.lms-ui-customer-select-container{display:flex;flex-wrap:wrap;align-items:center}.lms-ui-customer-select-container select{margin-right:.5em;max-width:35em}.lms-ui-customer-select-container .lms-ui-customer-select{display:inline-block;white-space:nowrap}.lms-ui-customer-select-container .lms-ui-customer-select>span{padding-right:.5em}.lms-ui-customer-select-container .lms-ui-customer-select .lms-ui-customer-select-customerid,.lms-ui-customer-select-container .lms-ui-customer-select .lms-ui-customer-select-suggestion-input{box-sizing:border-box;width:7em;margin-top:.5em;margin-bottom:.5em;padding-right:0}.lms-ui-customer-select-container .lms-ui-customer-select .lms-ui-customer-select-customerid:focus,.lms-ui-customer-select-container .lms-ui-customer-select .lms-ui-customer-select-suggestion-input:focus{padding-right:1.4em}.lms-ui-customer-select-container .lms-ui-customer-select .lms-ui-customer-select-customerid:focus+.lms-ui-customer-function-button,.lms-ui-customer-select-container .lms-ui-customer-select .lms-ui-customer-select-suggestion-input:focus+.lms-ui-customer-function-button{visibility:visible}.lms-ui-customer-select-container .lms-ui-customer-select .lms-ui-customer-function-button{display:inline-block;margin-left:-2.3em;vertical-align:middle;cursor:pointer;visibility:hidden}.lms-ui-customer-select-container .lms-ui-customer-select:hover .lms-ui-customer-select-customerid,.lms-ui-customer-select-container .lms-ui-customer-select:hover .lms-ui-customer-select-suggestion-input{padding-right:1.4em}.lms-ui-customer-select-container .lms-ui-customer-select:hover .lms-ui-customer-select-customerid+.lms-ui-customer-function-button,.lms-ui-customer-select-container .lms-ui-customer-select:hover .lms-ui-customer-select-suggestion-input+.lms-ui-customer-function-button{visibility:visible}.lms-ui-customer-select-container .lms-ui-customer-select-name{white-space:normal;padding-left:.8em;padding-right:.5em;flex-grow:1}.lms-ui-customer-select-container[data-version="2"] .lms-ui-customer-select .lms-ui-customer-select-customerid,.lms-ui-customer-select-container[data-version="2"] .lms-ui-customer-select .lms-ui-customer-select-suggestion-container{display:none}.lms-ui-customer-select-container[data-version="2"] .lms-ui-customer-select .lms-ui-customer-select-suggestion-input{min-width:10em}.lms-ui-customer-select-container[data-version="2"] .lms-ui-customer-select .lms-ui-customer-select-customerid[required]:invalid+.lms-ui-customer-select-suggestion-input{border:1px solid red;box-shadow:0 0 3px 1px red}.lms-ui-customer-select-container[data-version="2"] .lms-ui-customer-select .lms-ui-customer-select-customerid[required]:invalid+.lms-ui-customer-select-suggestion-input:focus{border:1px solid #a32828;box-shadow:0 0 1px 1px #a32828;outline:0}.lms-ui-customer-select-container.lms-ui-distinguished select{border:1px solid Orange;box-shadow:0 0 3px 1px Orange}.lms-ui-customer-select-container.lms-ui-distinguished select:focus{border:1px solid Orange;box-shadow:0 0 1px 1px Orange}.lms-ui-customer-select-container.lms-ui-distinguished .lms-ui-customer-select-name{border:1px solid Orange;box-shadow:0 0 3px 1px Orange}.lms-ui-hint-rollover:not(.ui-tooltip),.lms-ui-hint-toggle:not(.ui-tooltip){cursor:pointer}.lms-ui-hint-rollover .lms-ui-hint-titlebar,.lms-ui-hint-toggle .lms-ui-hint-titlebar{display:none;justify-content:flex-end}.lms-ui-hint-rollover .lms-ui-hint-titlebar .close-button,.lms-ui-hint-toggle .lms-ui-hint-titlebar .close-button{cursor:pointer}.lms-ui-hint-rollover.ui-tooltip,.lms-ui-hint-toggle.ui-tooltip{max-width:50vw}.lms-ui-hint-rollover.ui-tooltip .lms-ui-hint-titlebar,.lms-ui-hint-toggle.ui-tooltip .lms-ui-hint-titlebar{padding-bottom:.5em}.lms-ui-hint-rollover.ui-tooltip .lms-ui-hint-content,.lms-ui-hint-toggle.ui-tooltip .lms-ui-hint-content{max-height:90vh;overflow-y:auto;overflow-x:visible;padding-right:1em}@media screen and (max-width:800px){.lms-ui-hint-rollover.ui-tooltip,.lms-ui-hint-toggle.ui-tooltip{padding:0;font-size:200%}.lms-ui-hint-rollover.ui-tooltip,.lms-ui-hint-toggle.ui-tooltip{max-width:fit-content}.lms-ui-hint-rollover .ui-tooltip-content,.lms-ui-hint-toggle .ui-tooltip-content{padding:1em}.lms-ui-hint-rollover.ui-widget.ui-widget-content,.lms-ui-hint-toggle.ui-widget.ui-widget-content{border:0;position:fixed;left:0;top:0;width:100vw;height:100vh;max-width:unset;max-height:unset}.lms-ui-hint-rollover.ui-widget.ui-widget-content.ui-widget-shadow,.lms-ui-hint-toggle.ui-widget.ui-widget-content.ui-widget-shadow{box-shadow:unset}.lms-ui-hint-rollover .lms-ui-hint-titlebar,.lms-ui-hint-toggle .lms-ui-hint-titlebar{display:flex}}html{height:100%}html.fullscreen-popup{overflow:hidden}@media print{html{overflow:visible}}body{font-size:10pt;font-family:Arial,Helvetica,Verdana;background-color:#EBE4D6;margin:0;padding:0;margin-left:.5em}@media screen and (max-width:1920px){body{font-size:9pt}}@media screen and (max-width:1200px){body{font-size:8pt}}body.lms-ui-main-document{overflow:auto}body.fullscreen-popup{overflow:hidden}body.fullscreen-popup #lms-ui-contents{overflow:hidden}body.fullscreen-popup #lms-ui-module-view{overflow:hidden}body.fullscreen-popup #lms-ui-back-to-top{display:none;z-index:0}@media screen and (max-width:800px){body:not(.lms-ui-popup):not(.lms-ui-login-form){margin-top:4em}}body.lms-ui-popup{margin-left:0}body #lms-ui-tool-panels{margin-left:1.2em}@media screen and (max-width:800px){body #lms-ui-tool-panels{margin-left:0;top:4em;z-index:70;display:none}body #lms-ui-tool-panels.fullscreen-popup{display:block}body #lms-ui-tool-panels.fullscreen-popup .lms-ui-tool-panel:not(:first-child){display:none}}body.lms-ui-popup{display:block;height:auto;overflow:auto}TABLE{border-collapse:collapse;border-color:#000}#lms-ui-back-to-top{margin:.3em;position:fixed;opacity:.8;right:1.8em;bottom:.6em;z-index:60;transform:translateX(120px);transition:transform .4s .3s;will-change:transform}#lms-ui-back-to-top:hover{transform:translateX(10px)!important}@media screen and (max-width:800px){#lms-ui-back-to-top{font-size:130%}}#lms-ui-contents{overflow:visible;display:flex;flex-direction:column;justify-content:flex-start;align-items:flex-start;flex:1 1 auto;margin-bottom:.85em;padding:.43em}#lms-ui-contents>p{align-self:center}@media print{#lms-ui-contents{height:auto}}.lms-ui-tool-panel{flex:0 0 auto;display:flex;justify-content:flex-start;align-items:center;border-bottom:1px solid #000;padding-bottom:.3em;width:100%}.lms-ui-tool-panel:nth-child(n+2){padding-top:.3em}@media screen and (max-width:800px){.lms-ui-tool-panel{padding-bottom:0}}.lms-ui-indicator:hover{text-decoration:none}.lms-ui-indicator-counter{font-size:120%}#lms-ui-toolbar{display:flex;justify-content:space-between;flex:0 0 auto}#lms-ui-toolbar{justify-content:flex-start;flex-wrap:wrap;margin-top:-.5em}#lms-ui-toolbar .lms-ui-toolbar-shortcut{display:flex;justify-content:flex-start;margin-top:.5em}#lms-ui-toolbar .lms-ui-toolbar-shortcut:last-child{margin-left:auto;margin-right:.5em;display:flex;justify-content:flex-start}#lms-ui-toolbar .lms-ui-toolbar-shortcut-separator{padding-right:1.2em}#lms-ui-module-view{width:100%;overflow:visible}#lms-ui-module-view h1{margin-block-start:.4em;margin-block-end:.7em}#lms-ui-generation-time{text-align:center;color:#888}#lms-ui-dberrors{background-color:#F4F0EC;border:1px solid #000;padding:.3em;margin-top:.5em}#lms-ui-tool-panels{position:fixed;left:0;top:0;background-size:100% 100%;background-color:#EBE4D6;right:0;padding-top:.5em;box-shadow:0 1em .9em #EBE4D6;z-index:50}@media screen and (max-width:800px){#lms-ui-tool-panels{padding-top:0}}#lms-ui-quicksearch-indicators-panel{display:flex;justify-content:space-between;flex-wrap:wrap}@media screen and (max-width:800px){#lms-ui-quicksearch-indicators-panel{background-color:#CEBD9B}}.lms-ui-quick-search{display:flex;justify-content:flex-start;align-items:center;flex-wrap:wrap}@media screen and (max-width:800px){.lms-ui-quick-search{width:100%}.lms-ui-quick-search .lms-ui-quick-search-selector .lms-ui-multiselect-launcher{display:none}}.lms-ui-quick-search #lms-ui-quick-search-field-clear{font-size:200%;margin-right:.5em}@media screen and (min-width:801px){.lms-ui-quick-search #lms-ui-quick-search-field-clear{display:none}}@media screen and (max-width:800px){form.lms-ui-quick-search{flex-wrap:nowrap}}.lms-ui-quick-search-field{display:none;align-items:center;margin-left:.3em}.lms-ui-quick-search-field.visible{display:flex}@media screen and (max-width:800px){.lms-ui-quick-search-field.visible{display:none}}.lms-ui-quick-search-field .lms-ui-quick-search-icon,.lms-ui-quick-search-field img{cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}@media screen and (max-width:800px){.lms-ui-quick-search-field{font-size:200%;display:none;flex-grow:1;margin:.5em;width:auto}.lms-ui-quick-search-field.lms-ui-quick-search-active{display:flex}.lms-ui-quick-search-field .lms-ui-multiselect-popup{font-size:inherit}}.lms-ui-quick-search-field>input{padding-right:1.2em;padding-top:.3em;padding-bottom:.3em;padding-left:.3em;margin-left:.3em;display:inline-block}.lms-ui-quick-search-field>input:last-child{padding-right:.3em;width:2.95em}.lms-ui-quick-search-field>input:not(:last-child){width:1.7em}@media screen and (max-width:800px){.lms-ui-quick-search-field>input{font-size:inherit;margin-left:.7em;width:100%;border-color:#000!important}}.lms-ui-quick-search-field>input.lms-ui-quick-search-active{width:8.4em}@media screen and (max-width:800px){.lms-ui-quick-search-field>input.lms-ui-quick-search-active{width:100%}}.lms-ui-quick-search-field>input.lms-ui-quick-search-input{min-width:3em}@media screen and (min-width:801px){.lms-ui-quick-search-field>input.lms-ui-quick-search-input{min-height:2.2em}}.lms-ui-quick-search-field>input.lms-ui-quick-search-input+div{margin-left:-1.8em;visibility:hidden}@media screen and (max-width:800px){.lms-ui-quick-search-field>input.lms-ui-quick-search-input+div{margin-left:-2em}}.lms-ui-quick-search-field>input.lms-ui-quick-search-input+div.open{visibility:visible}.lms-ui-quick-search-field>input:focus{padding-right:1.2em}.lms-ui-quick-search-field>input:focus:last-child{padding-right:.3em}.lms-ui-quick-search-field>input:focus+div{visibility:visible}.lms-ui-quick-search-field:hover input{padding-right:1.2em}.lms-ui-quick-search-field:hover input:last-child{padding-right:.3em}.lms-ui-quick-search-field:hover input+div{visibility:visible}.lms-ui-quick-search-field .fab,.lms-ui-quick-search-field .fal,.lms-ui-quick-search-field .far,.lms-ui-quick-search-field .fas{font-size:1.5em}.lms-ui-quick-search-selector{margin-left:.45em;cursor:pointer}#lms-ui-indicators{margin-left:auto;margin-right:1em}@media screen and (max-width:800px){#lms-ui-indicators{display:none}}#lms-ui-welcome-boxes{width:100%;display:flex;flex-direction:column;justify-content:stretch;align-items:stretch}#lms-ui-welcome-main-panels{width:100%;display:flex;justify-content:stretch;align-items:stretch;flex-wrap:wrap}.lms-ui-welcome-main-panel{padding:.17em;flex:1 1 auto}.lms-ui-welcome-main-panel.empty{flex:0 0 auto;min-width:2em;min-height:30%}.lms-ui-welcome-box-placeholder{min-width:20em;min-height:20em;margin:0 1em 1em 0;border:1px solid #000}#lms-ui-welcome-extra-panel{align-self:stretch}#lms-ui-welcome-bottom-panel{align-self:stretch}.bottomline{border-bottom-style:solid;border-bottom-width:1px;border-bottom-color:#CEBD9B}TD{font-size:10pt;font-family:Arial,Helvetica,Verdana;vertical-align:middle;border-color:#000}@media screen and (max-width:1920px){TD{font-size:9pt}}@media screen and (max-width:1200px){TD{font-size:8pt}}td[onclick]{cursor:pointer}.fleft{border-left-width:1pt;border-left-style:solid}.fright{border-right-width:1pt;border-right-style:solid}.ftop{border-top-width:1pt;border-top-style:solid}.fbottom{border-bottom-width:1pt;border-bottom-style:solid}.fleftu{border-top-width:1pt;border-top-style:solid;border-bottom-width:1pt;border-bottom-style:solid;border-left-width:1pt;border-left-style:solid}.frightu{border-top-width:1pt;border-top-style:solid;border-bottom-width:1pt;border-bottom-style:solid;border-right-width:1pt;border-right-style:solid}.ftopu{border-top-width:1pt;border-top-style:solid;border-left-width:1pt;border-left-style:solid;border-right-width:1pt;border-right-style:solid}.fbottomu{border-bottom-width:1pt;border-bottom-style:solid;border-left-width:1pt;border-left-style:solid;border-right-width:1pt;border-right-style:solid}.fall{border-width:1pt;border-style:solid}.fbt{border-bottom-width:1pt;border-bottom-style:solid;border-top-width:1pt;border-top-style:solid}.fbl{border-bottom-width:1pt;border-bottom-style:solid;border-left-width:1pt;border-left-style:solid}.fbr{border-bottom-width:1pt;border-bottom-style:solid;border-right-width:1pt;border-right-style:solid}.ftl{border-top-width:1pt;border-top-style:solid;border-left-width:1pt;border-left-style:solid}.ftr{border-top-width:1pt;border-top-style:solid;border-right-width:1pt;border-right-style:solid}.flr{border-left-width:1pt;border-left-style:solid;border-right-width:1pt;border-right-style:solid}.loginform{border-width:1pt;border-style:solid;border-color:#888}.hand{cursor:pointer}.container{padding:0}FORM{display:inline}label{cursor:pointer;white-space:nowrap;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}label>input[type=checkbox]{margin-right:.6em}label>.lms-ui-multiselect-container,label>input[type=text],label>select{margin-left:.4em}A{text-decoration:none;vertical-align:baseline}A:link{color:maroon}A:active{color:#360}A:visited{color:maroon}A.blend{color:#888}A:hover{text-decoration:underline;color:#360;cursor:pointer}A.disabled{color:#888!important;cursor:no-drop}A.disabled:hover{text-decoration:none}A[href^="mailto:"]{font-family:'Fira Code',monospace}.lms-ui-tab-table-row.blend A,TR.blend A{color:#888}.lms-ui-tab-table-row.alertblend A,TR.alertblend A{color:salmon}.lms-ui-tab-table-row.suspended A,TR.suspended A{color:#30B6C6}P{font-size:10pt;font-family:Arial,Helvetica,Verdana}@media screen and (max-width:1920px){P{font-size:9pt}}@media screen and (max-width:1200px){P{font-size:8pt}}@media screen and (max-width:800px){P{font-size:8pt}}P.nor{font-size:10pt;font-family:Arial,Helvetica,Verdana}@media screen and (max-width:1920px){P.nor{font-size:9pt}}@media screen and (max-width:1200px){P.nor{font-size:8pt}}P.txt{font-size:10pt;font-family:Arial,Helvetica,Verdana;text-align:justify}@media screen and (max-width:1920px){P.txt{font-size:9pt}}@media screen and (max-width:1200px){P.txt{font-size:8pt}}P.separated{font-size:10pt;font-family:Arial,Helvetica,Verdana;margin-top:5px;margin-bottom:5px}@media screen and (max-width:1920px){P.separated{font-size:9pt}}@media screen and (max-width:1200px){P.separated{font-size:8pt}}H1{font-size:14pt;font-family:Arial,Helvetica,Verdana}H2{font-size:12pt;font-family:Arial,Helvetica,Verdana}H3{font-size:10pt;font-family:Arial,Helvetica,Verdana}HR{border:0;height:1px;color:#000;background-color:#000}input[type=text],input[type=email],input[type=search],input[type=number],input[type=tel],input[type=password],input[type=submit],input[type=button]{border:1px solid #a9a9a9;background-color:#EBE4D6;min-height:1.4em;padding:.1em;padding-left:.4em;box-sizing:border-box}input[type=text][disabled]{border:1px dashed grey;background-color:transparent}input[type=text][disabled]+label{color:#888}input[type=checkbox][disabled]{background-color:transparent}input[type=checkbox][disabled]+label{color:#888}input[type=radio][disabled]{background-color:transparent}input[type=radio][disabled]+label{color:#888}select[disabled]+label{color:#888}input[type=radio]{vertical-align:text-bottom}.lms-ui-disabled{color:#888}.lms-ui-disabled *{color:inherit}input[type=checkbox][disabled]+.lms-ui-label,input[type=radio][disabled]+.lms-ui-label{color:#888}input{font-size:10pt;font-family:Arial,Helvetica,Verdana;vertical-align:middle}@media screen and (max-width:1920px){input{font-size:9pt}}@media screen and (max-width:1200px){input{font-size:8pt}}input.alert,input.lms-ui-error,input:invalid{border:1px solid red;box-shadow:0 0 3px 1px red}input.alert:focus,input.lms-ui-error:focus,input:invalid:focus{border:1px solid #a32828;box-shadow:0 0 1px 1px #a32828;outline:0}input.lms-ui-warning{border:1px solid Orange;background-color:Khaki;box-shadow:0 0 3px 1px Orange}input.lms-ui-warning:focus{border:1px solid Orange;background-color:Khaki;box-shadow:0 0 1px 1px Orange}input.lms-ui-distinguished{border:1px solid Orange;box-shadow:0 0 3px 1px Orange}input.lms-ui-distinguished:focus{border:1px solid Orange;box-shadow:0 0 1px 1px Orange}input[type=checkbox].alert,input[type=checkbox].lms-ui-error,input[type=checkbox]:invalid,input[type=radio].alert,input[type=radio].lms-ui-error,input[type=radio]:invalid{outline:0;box-shadow:0 0 3px 2px red}input[type=checkbox].alert:focus,input[type=checkbox].lms-ui-error:focus,input[type=checkbox]:invalid:focus,input[type=radio].alert:focus,input[type=radio].lms-ui-error:focus,input[type=radio]:invalid:focus{box-shadow:0 0 2px 2px #a32828}input[type=checkbox].lms-ui-distinguished,input[type=checkbox].lms-ui-warning,input[type=radio].lms-ui-distinguished,input[type=radio].lms-ui-warning{outline:0;box-shadow:0 0 3px 2px Orange}input[type=checkbox].lms-ui-distinguished:focus,input[type=checkbox].lms-ui-warning:focus,input[type=radio].lms-ui-distinguished:focus,input[type=radio].lms-ui-warning:focus{box-shadow:0 0 2px 2px Orange}input.hiddenbtn{display:none!important}input.blend{border-style:solid;border-color:silver;border-width:1px;vertical-align:middle;color:#000}input.scroller{border-style:solid;border-color:grey;border-width:1px;vertical-align:middle;background-color:#DFD5BD}input[readonly]{color:#888!important;cursor:no-drop}input[readonly]:hover{text-decoration:none}textarea{font-size:10pt;font-family:Arial,Helvetica,Verdana;border:1px solid #a9a9a9;background-color:#EBE4D6;vertical-align:middle}@media screen and (max-width:1920px){textarea{font-size:9pt}}@media screen and (max-width:1200px){textarea{font-size:8pt}}textarea[disabled]{border:1px dashed grey;background-color:transparent}textarea.alert,textarea.lms-ui-error,textarea:invalid{border:1px solid red;box-shadow:0 0 3px 1px red}textarea.alert:focus,textarea.lms-ui-error:focus,textarea:invalid:focus{border:1px solid #a32828;box-shadow:0 0 1px 1px #a32828;outline:0}textarea.lms-ui-distinguished,textarea.lms-ui-warning{border:1px solid Orange;box-shadow:0 0 3px 1px Orange;background-color:Khaki}textarea.lms-ui-distinguished:focus,textarea.lms-ui-warning:focus{border:1px solid Orange;box-shadow:0 0 1px 1px Orange;outline:0}select{font-size:10pt;min-height:1.6em;font-family:Arial,Helvetica,Verdana;background-color:#EBE4D6;vertical-align:middle;-moz-appearance:none;-webkit-appearance:none;appearance:none;background-image:url(../img/1.png);background-repeat:no-repeat;background-position:right center;padding-right:16px;padding-left:3px;border:1px solid #a9a9a9}@media screen and (max-width:1920px){select{font-size:9pt}}@media screen and (max-width:1200px){select{font-size:8pt}}select.alert,select.lms-ui-error,select:invalid{border:1px solid red;box-shadow:0 0 3px 1px red}select.alert:focus,select.lms-ui-error:focus,select:invalid:focus{border:1px solid #a32828;box-shadow:0 0 1px 1px #a32828;outline:0}select.lms-ui-warning{border:1px solid Orange;box-shadow:0 0 3px 1px Orange;background-color:Khaki}select.lms-ui-warning:focus{border:1px solid Orange;box-shadow:0 0 1px 1px Orange;outline:0}select.lms-ui-distinguished{border:1px solid Orange;box-shadow:0 0 3px 1px Orange}select.lms-ui-distinguished:focus{border:1px solid Orange;box-shadow:0 0 1px 1px Orange;outline:0}IMG{vertical-align:middle;border:0}.lms-ui-cell-flex{display:inline-flex;align-items:center}.lms-ui-cell-flex>:not(:last-child){margin-right:.3em}.click-menu{padding:0 0;margin-top:0;margin-bottom:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.click-menu i{text-align:center}.click-menu i.fab,.click-menu i.fal,.click-menu i.far,.click-menu i.fas{font-size:1.5em;width:1.5em}.click-menu .box1{background-color:#CEBD9B;color:#000;font-weight:700;padding:.45em .45em;cursor:default;position:relative;white-space:nowrap}@media screen and (max-width:800px){.click-menu .box1{border-bottom:1px dotted grey}}.click-menu .box1-hover{background-color:#CFC;color:maroon;font-weight:700;padding:.45em .45em;cursor:default;position:relative;white-space:nowrap}@media screen and (max-width:800px){.click-menu .box1-hover{border-bottom:1px dotted grey}}.click-menu .box1-open{background-color:#DACAB2;color:maroon;font-weight:700;padding:.45em .45em;cursor:default;position:relative;white-space:nowrap}.click-menu .box1-open-hover{background-color:#CFC;color:maroon;font-weight:700;padding:.45em .45em;cursor:default;position:relative;white-space:nowrap}.click-menu .section{background-color:#EBE4D6;line-height:1.25em;padding:0;display:none}.click-menu .section a{color:maroon;text-decoration:none;white-space:nowrap}.click-menu .section a:hover{color:#360;text-decoration:none;white-space:nowrap}.click-menu .section .active,.click-menu .section .active:hover{color:#ff0}@media screen and (max-width:800px){.click-menu .box2{border-bottom:1px dotted grey}}.click-menu .box2-hover{background-color:#CFC;font-weight:400}.click-menu .box2 a,.click-menu .box2-hover a{display:block;padding-left:1.85em;font-weight:400;padding-top:.08em;padding-bottom:.08em}.dark{background-color:#CEBD9B}.superdark{background-color:#B6A688}.light{background-color:#DFD5BD}.lucid{background-color:#EBE4D6}.superlight{background-color:#F4F0EC}.highlight:hover{background-color:#CFC}.blendbg{background-color:#888}.blend{color:#888}.teal{color:teal}.transformed .comment{text-decoration:line-through}.green{color:green}.red{color:red}.brown{color:brown}.white{color:#FFF}.tox-tinymce.invalid,.tox-tinymce.lms-ui-error{box-shadow:0 0 4px 2px red}.tox-tinymce.lms-ui-warning,.tox-tinymce:invalid{box-shadow:0 0 4px 2px Orange}.alert{color:red!important}.lms-ui-warning{color:Sienna!important}.lms-ui-alert{color:red!important}.alertblend{color:salmon}.suspended{color:#30B6C6}.bold{font-weight:700}.crossed{text-decoration:line-through}.lms-ui-crossed{text-decoration:line-through;text-decoration-color:rgba(0,0,0,.2);text-decoration-thickness:.2em}.pre{font-size:10pt;font-family:Courier,Courier New}@media screen and (max-width:1920px){.pre{font-size:9pt}}@media screen and (max-width:1200px){.pre{font-size:8pt}}.lms-ui-suggestion-container{background-color:#EBE4D6;border:1px solid;padding:0;min-width:350px;position:absolute;display:none;box-shadow:0 8px 16px 0 rgba(0,0,0,.2)}@media screen and (max-width:800px){.lms-ui-suggestion-container{position:static;font-size:150%;border:0;width:100%;border-top:1px solid #000}.lms-ui-suggestion-container .lms-ui-suggestion-item{flex-direction:column;align-items:unset!important}.lms-ui-suggestion-container .lms-ui-suggestion-item .lms-ui-suggestion-name{font-size:inherit}.lms-ui-suggestion-container .lms-ui-suggestion-item .lms-ui-suggestion-name i{padding:.3em}.lms-ui-suggestion-container .lms-ui-suggestion-item .lms-ui-suggestion-description{padding-top:.4em;font-size:90%}}@media screen and (min-width:801px){.lms-ui-suggestion-container{z-index:55}}.lms-ui-suggestion-container:hover{cursor:pointer}.lms-ui-suggestion-container .lms-ui-suggestion-list{list-style-type:none;padding:0;margin:0;padding-top:.5em;padding-bottom:.5em}@media screen and (max-width:800px){.lms-ui-suggestion-container .lms-ui-suggestion-list{overflow:auto;max-height:calc(100vh - 11em)}}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item{display:flex;justify-content:space-between;align-items:center;padding-top:.2em;padding-bottom:.2em;padding-left:.5em;padding-right:.5em}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item:not(:last-child){border-bottom:#CEBD9B dotted 1px}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item.selected{background-color:#CFC}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item.selected a{color:#000}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item a{text-decoration:none;padding-left:2px;color:#000}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-icon{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name{padding-top:2px;color:#000}@media screen and (min-width:801px){.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name{font-size:12px}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name i{font-size:100%;padding:.3em}}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.blend{color:#888}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.red{color:red}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-customer-status-awaiting::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/wait.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-customer-status-interested::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/unk.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-customer-status-disconnected::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/node_off.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-customer-status-debtcollection::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/money.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-node-status-unknown::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/node_unk.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-node-status-online::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/node_on.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-node-status-offline::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/node_off.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-netdevice::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/netdev.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-wireless::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/wireless.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-wireless-uni{color:teal}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-wireless-uni::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/wireless.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-wireless-nni{color:brown}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-wireless-nni::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/wireless.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-network::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/network.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-netnode::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/netnode.png)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-customer-status-connected::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/customer.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-ticket-state-new{color:red}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-ticket-state-new::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/new.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-ticket-state-open::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/open.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-ticket-state-resolved{color:#888}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-ticket-state-resolved::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/resolved.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-ticket-state-dead::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/dead.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-ticket-state-scheduled::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/calendar.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-ticket-state-waiting::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/calendar.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-ticket-state-verified::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/verifier.png)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-name.lms-ui-suggestion-phone::before{content:"";padding-right:17px;background-size:contain;background-repeat:no-repeat;background-image:url(../img/phone.gif)}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-description{margin-right:2px;color:brown;padding-left:20px;text-align:right}@media screen and (min-width:801px){.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-description{font-size:10px}}.lms-ui-suggestion-container .lms-ui-suggestion-list .lms-ui-suggestion-item .lms-ui-suggestion-description>a{color:brown}.lms-ui-customer-status-connected{color:#000}.lms-ui-customer-status-awaiting{color:green}.lms-ui-customer-status-interested{color:#000}.lms-ui-customer-status-disconnected{text-decoration-line:line-through}.lms-ui-customer-status-debt-collection{color:red}.lms-ui-assignment-not-commited{text-decoration:line-through;text-decoration-color:rgba(0,0,0,.2);text-decoration-thickness:.2em}.lms-ui-document-closed .lms-ui-tab-table-column:not(.buttons),.lms-ui-document-closed>td:not(:last-child){color:#888}.lms-ui-document-archived .lms-ui-tab-table-column:not(.buttons),.lms-ui-document-archived>td:not(:last-child){text-decoration:line-through}.acl{list-style-type:square}.overlib{min-width:10px;font-family:Arial,Helvetica,Verdana;background-color:#F4F0EC;padding:2px 4px;border:1px solid #333;border-radius:3px;-moz-border-radius:3px;-webkit-border-radius:3px;box-shadow:#333 1px 1px 12px;-moz-box-shadow:1px 1px 12px #333;-webkit-box-shadow:#333 1px 1px 12px;behavior:url(img/pie.htc)}@media print{.no-print,.no-print *,.ui-tooltip{display:none!important}}.lms-ui-button{color:maroon;border-radius:3px;white-space:nowrap}.lms-ui-button:hover{color:#360;cursor:pointer;text-decoration:underline}.lms-ui-important-box{border:1px #000 solid;background-color:red;color:#fff;font-weight:700;padding:2px 7px 3px 7px}.lms-ui-fileupload{display:inline-flex;flex-direction:column;justify-content:center}.lms-ui-fileupload .lms-ui-button-fileupload.lms-ui-fileupload-dropzone{box-shadow:0 0 10px 1px #000}.lms-ui-fileupload .fileupload-files{display:flex;flex-direction:column}.lms-ui-fileupload .fileupload-files>div{margin-top:.3em;margin-bottom:.3em}.lms-ui-fileupload .fileupload-files .fileupload-file{display:flex;flex-direction:column;width:fit-content}.lms-ui-fileupload .fileupload-files .fileupload-file-info{display:flex;align-items:center}.lms-ui-fileupload .fileupload-files .fileupload-file-info .file-delete{margin-right:.7em}.lms-ui-fileupload .fileupload-files .fileupload-file-options{display:flex;align-items:center;margin-top:.5em;justify-content:space-between}.lms-ui-fileupload .fileupload-files .fileupload-file-options input[type=text]{margin-left:1em;flex-grow:1;min-width:17em}.lms-ui-rtmessage-current,.lms-ui-rtsystemmessage-current{box-shadow:0 0 .3em .3em brown}.lms-ui-multi-check-all{-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}table.lmsbox{margin:0 2px 4px 0}table.lmsbox,table.lmsbox-inner,table.lmsbox-innerbox{width:100%}table.lmsbox td,table.lmsbox-inner td,table.lmsbox-innerbox td{padding:.3em;padding-left:.5em}table.lmsbox td.lms-ui-box-buttons,table.lmsbox-inner td.lms-ui-box-buttons,table.lmsbox-innerbox td.lms-ui-box-buttons{background-image:linear-gradient(to right,#000 33%,rgba(255,255,255,0) 0);background-position:left .5em;background-size:3px 1px;background-repeat:repeat-x;padding:1em .5em .5em .5em}table.lmsbox td.lms-ui-box-buttons>:not(:first-child),table.lmsbox-inner td.lms-ui-box-buttons>:not(:first-child),table.lmsbox-innerbox td.lms-ui-box-buttons>:not(:first-child){margin-left:.3em}table.lmsbox td.lms-ui-box-buttons .lms-ui-box-button-container,table.lmsbox-inner td.lms-ui-box-buttons .lms-ui-box-button-container,table.lmsbox-innerbox td.lms-ui-box-buttons .lms-ui-box-button-container{display:flex;flex-wrap:wrap;align-items:center}table.lmsbox td.lms-ui-box-buttons .lms-ui-box-button-container>:not(:first-child),table.lmsbox-inner td.lms-ui-box-buttons .lms-ui-box-button-container>:not(:first-child),table.lmsbox-innerbox td.lms-ui-box-buttons .lms-ui-box-button-container>:not(:first-child){margin-left:.3em}table.lmsbox td.empty-table,table.lmsbox-inner td.empty-table,table.lmsbox-innerbox td.empty-table{text-align:center;font-weight:700;padding:2.5em}table.lmsbox-inner>thead,table.lmsbox-innerbox>thead,table.lmsbox>thead{background-color:#CEBD9B}table.lmsbox-inner>tbody,table.lmsbox>tbody{background-color:#DFD5BD}table.lmsbox-innerbox>tfoot,table.lmsbox-innerbox>thead,table.lmsbox>tbody,table.lmsbox>tfoot,table.lmsbox>thead{border-width:1px;border-style:solid;border-color:#000}table.lmsbox-inner>tfoot{border-top:1px solid #000}table.lmsbox-inner td{border-spacing:0}table.lmsbox-inner>thead,table.lmsbox-innerbox>tfoot,table.lmsbox-innerbox>thead{background-color:#CEBD9B}table.lmsbox>tfoot>tr,table.lmsbox>thead>tr:not(:first-child){border-top:1px solid #000}table.lmsbox tr.lms-ui-button-panel,table.lmsbox-inner tr.lms-ui-button-panel{background-color:#CEBD9B}table.lmsbox tr.lms-ui-button-panel>td,table.lmsbox-inner tr.lms-ui-button-panel>td{border-top:1px solid #000}table.lmsbox tr.lms-ui-header-panel>td,table.lmsbox-inner tr.lms-ui-header-panel>td{border-bottom:1px solid #000}table.lmsbox.lms-ui-tab-container{margin-top:.7em}table.lmsbox.lms-ui-tab-container>thead{background-color:#B6A688}table.lmsbox.lms-ui-tab-container>thead>.lmsbox-titlebar :not(.lms-ui-button)>i{width:1.3em;text-align:center;margin-right:.5em}table.lmsbox.lms-ui-tab-container>thead>.lmsbox-titlebar .lms-ui-karma-container i{width:auto;margin-right:0}table.lmsbox.lms-ui-tab-container>thead>.lmsbox-titlebar>td:last-child{padding-right:.5em}table.lmsbox>thead{text-align:left}table.lmsbox-inner>tfoot,table.lmsbox>tfoot{background-color:#DFD5BD}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr.lms-ui-distinguished-row,table.lmsbox.lms-ui-background-cycle>tbody>tr.lms-ui-distinguished-row{font-weight:700;background-color:#CEBD9B!important;border-top-width:1pt;border-top-style:solid;border-bottom-width:1pt!important;border-bottom-style:solid!important}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr.highlight:hover,table.lmsbox.lms-ui-background-cycle>tbody>tr.highlight:hover{background-color:#CFC!important}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(even),table.lmsbox.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(even){background-color:#DFD5BD}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(even).cancel,table.lmsbox.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(even).cancel{background-color:#ffb1b1}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(odd),table.lmsbox.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(odd){background-color:#EBE4D6}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(odd).cancel,table.lmsbox.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(odd).cancel{background-color:#fccdcd}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):not(:last-child),table.lmsbox.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):not(:last-child){border-bottom:1px dotted grey}table.lmsbox.lms-ui-background-cycle>tbody>tr.highlight:hover{background-color:#CFC!important}table.lmsbox.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(even):not(.ui-selected){background-color:#DFD5BD}table.lmsbox.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(even):not(.ui-selected).cancel{background-color:#ffb1b1}table.lmsbox.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(odd):not(.ui-selected){background-color:#EBE4D6}table.lmsbox.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(odd):not(.ui-selected).cancel{background-color:#fccdcd}table.lmsbox.lms-ui-background-cycle>tbody>tr:not(.lms-ui-button-panel):not(.lms-ui-header-panel):not(:last-child){border-bottom:1px dotted grey}table.lmsbox-inner.dataTable>thead{background-color:#CEBD9B}table.lmsbox-inner:not(.dataTable)>thead{background-color:#DFD5BD}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr,table.lmsbox.lms-ui-background-cycle>tbody>tr{border-bottom:1px dotted grey}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr.lms-ui-resource-deleted:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(even),table.lmsbox.lms-ui-background-cycle>tbody>tr.lms-ui-resource-deleted:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(even){background-color:#ffb1b1}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr.lms-ui-resource-deleted:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(odd),table.lmsbox.lms-ui-background-cycle>tbody>tr.lms-ui-resource-deleted:not(.lms-ui-button-panel):not(.lms-ui-header-panel):nth-child(odd){background-color:#fccdcd}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr.lms-ui-resource-deleted:not(.lms-ui-button-panel):not(.lms-ui-header-panel).highlight:hover,table.lmsbox.lms-ui-background-cycle>tbody>tr.lms-ui-resource-deleted:not(.lms-ui-button-panel):not(.lms-ui-header-panel).highlight:hover{background-color:#CFC}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr.lms-ui-resource-partly-deleted:nth-child(even),table.lmsbox.lms-ui-background-cycle>tbody>tr.lms-ui-resource-partly-deleted:nth-child(even){background-image:repeating-linear-gradient(145deg,transparent,transparent 10px,#ffb1b1 10px,#ffb1b1 20px)}table.lmsbox-inner.lms-ui-background-cycle>tbody>tr.lms-ui-resource-partly-deleted:nth-child(odd),table.lmsbox.lms-ui-background-cycle>tbody>tr.lms-ui-resource-partly-deleted:nth-child(odd){background-image:repeating-linear-gradient(145deg,transparent,transparent 10px,#fccdcd 10px,#fccdcd 20px)}table.lmsbox .lmsbox-panels{width:100%;display:flex;flex-direction:row;justify-content:flex-start;align-items:flex-start;flex-wrap:wrap}table.lmsbox .lmsbox-panels>.lmsbox-panel{flex-grow:1}table.lmsbox .lmsbox-panels>.lmsbox-panel:last-child{margin-right:2em}@media screen and (min-width:470px){table.lmsbox .lmsbox-panels>.lmsbox-panel:last-child{margin-right:7em}}.lms-ui-rtmessage-deleted.light{background-color:#ffb1b1}.lms-ui-rtmessage-deleted.lucid{background-color:#fccdcd}table.lms-ui-datatable>tbody tr:nth-child(even):not(.ui-selected){background-color:#DFD5BD}table.lms-ui-datatable>tbody tr:nth-child(odd):not(.ui-selected){background-color:#EBE4D6}table.lms-ui-datatable>tbody tr:not(:last-child):not(.highlight) td{border-bottom:1px dotted grey}table.lms-ui-datatable>tbody tr.parent:not(.highlight):nth-child(4n+1){background-color:#DFD5BD}table.lms-ui-datatable>tbody tr.parent:not(.highlight):nth-child(4n+3){background-color:#EBE4D6}table.lms-ui-datatable>tbody tr.parent:not(.highlight) td{border-bottom:0}table.lms-ui-datatable>tbody tr.child:nth-child(4n+2){background-color:#DFD5BD}table.lms-ui-datatable>tbody tr.child:nth-child(4n+4){background-color:#EBE4D6}table.lms-ui-datatable>tbody tr.child:not(:last-child){border-bottom:1px dotted grey}table.lms-ui-datatable>tbody tr.parent.highlight{background-color:#CFC!important}table.lms-ui-datatable>tbody tr:hover{background-color:#CFC!important}table.lms-ui-datatable>tbody tr:hover.child,table.lms-ui-datatable>tbody tr:hover.parent+.child{background-color:#CFC!important}table.dataTable>tbody>tr.child ul.dtr-details>li{border-bottom:0;padding:0}table.dataTable>tbody>tr.child ul.dtr-details>li:last-child span.dtr-title{display:none}tr.space_row>td{padding-top:20px}.summary{text-align:right;font-weight:700}.buttons{text-align:right}.navigation{text-align:center;white-space:nowrap;background-color:#CEBD9B}.lms-ui-pagination{background-color:#CEBD9B;text-align:center}.lms-ui-pagination>span{display:inline-flex;flex-wrap:wrap;align-items:center}.lms-ui-pagination>span>*{padding-left:.2em;padding-right:.2em}td.empty-table{background-color:#EBE4D6;text-align:center;font-weight:700;padding:2.5em}td.multiselect{min-width:230px}td.multiselect select{min-width:200px}.lms-ui-selectable-draggable-active{box-shadow:0 0 15px 0 rgba(0,0,0,.75)}.lms-ui-selectable-draggable-active.lms-ui-selectable-draggable-hover{box-shadow:0 0 25px 0 rgba(0,0,0,.75)}.lms-inline-list{display:inline;list-style:none;padding:0}.lms-inline-list li{display:inline}.lms-inline-list li:after{content:', '}.lms-inline-list li:last-child:after{content:''}.nobr{white-space:nowrap}.line-break{white-space:normal!important}.text-right{text-align:right}.text-left{text-align:left}.text-center{text-align:center}.font-normal{font-weight:400!important}.lighter{font-weight:lighter}.valign-top{vertical-align:top}div.valign-top{display:inline-flex;align-items:flex-start}div.valign-top>:not(:last-child){margin-right:.5em}div.valign-middle{display:inline-flex;align-items:center}div.valign-middle>:not(:last-child){margin-right:.5em}.valign-bottom{vertical-align:bottom}div.valign-bottom{display:inline-flex;align-items:flex-end}div.valign-bottom>:not(:last-child){margin-right:.5em}.cf:after,.cf:before{content:" ";display:table}.cf:after{clear:both}.lf{float:left}.rf{float:right}.wf{width:100%}.wh{width:50%}.wq{width:25%}.cancel{background:#ff6c6c}.rotate-90{-webkit-transform:rotate(90deg);-moz-transform:rotate(90deg);-o-transform:rotate(90deg);writing-mode:lr-tb}.lms-ui-selectmenu-button .ui-selectmenu-text{padding-top:0}.lms-ui-selectmenu-button .ui-selectmenu-icon{height:15px}.ui-selectmenu-menu .ui-widget-content{background-color:#EBE4D6!important}.ui-selectmenu-menu .ui-widget-content .ui-menu-divider{margin:0}.fileupload-progress-label{position:absolute;left:48%;top:4px;font-weight:700;text-shadow:1px 1px 0 #fff}.xdsoft_datetimepicker{background-color:#DFD5BD;border:1px solid #B6A688}.xdsoft_datetimepicker .xdsoft_label{background-color:#DFD5BD}.xdsoft_datetimepicker .xdsoft_label>.xdsoft_select>div>.xdsoft_option{background-color:#F4F0EC}table.dataTable tbody tr.odd:not(.ui-selected){background-color:#EBE4D6}table.dataTable tbody tr.even:not(.ui-selected){background-color:#DFD5BD}table.dataTable tbody tr.ui-selected{background-color:#CEBD9B}table.dataTable tbody tr.highlight{background-color:#CFC}table.dataTable tbody td,table.dataTable tbody th{padding:2px}table.dataTable tbody td.dataTables_empty{padding:2em;font-weight:700}table.dataTable thead .sorting_asc{background-image:url(../img/asc_order.gif)}table.dataTable thead .sorting_desc{background-image:url(../img/desc_order.gif)}table.dataTable thead .sorting{background-image:none}table.dataTable thead td,table.dataTable thead th{padding-top:2px;padding-bottom:2px;padding-left:10px;padding-right:10px}table.dataTable thead tr th{border:none}table.dataTable thead tr:last-child th{border-bottom:1px solid #000}.dataTables_wrapper .dataTables_paginate .paginate_button.current,.dataTables_wrapper .dataTables_paginate .paginate_button.current:hover{background:linear-gradient(to bottom,#CEBD9B 0,#B6A688 100%)}.dataTables_wrapper .dataTables_processing{background:linear-gradient(to right,rgba(174,157,123,0) 0,rgba(174,157,123,.9) 25%,rgba(174,157,123,.9) 75%,rgba(174,157,123,0) 100%)}.dataTables_wrapper .lmsbox.lms-ui-datatable{width:100%!important;border:1px solid #000;border-top:0;margin-bottom:0}.dataTables_wrapper .lmsbox.lms-ui-datatable table{width:100%!important}.dataTables_wrapper .top{background-color:#CEBD9B}.dataTables_wrapper .bottom{background-color:#CEBD9B}.lms-ui-tab-contents .dataTables_wrapper,.lmsbox .dataTables_wrapper{margin-bottom:0}.lms-ui-tab-contents .dataTables_wrapper .bottom,.lms-ui-tab-contents .dataTables_wrapper .top,.lmsbox .dataTables_wrapper .bottom,.lmsbox .dataTables_wrapper .top{border:0}.location-box-expandable{padding-top:2px}.address-full{display:inline-block;height:13px}.address-full:hover{cursor:pointer}.lms-ui-address-select{padding-left:4px;padding-right:4px;border:1px solid #a9a9a9!important;background-color:#EBE4D6!important;box-shadow:none!important;border-radius:0!important;color:#000!important}.lms-ui-address-select:hover{cursor:default}.lms-ui-address-select .ui-selectmenu-icon.ui-icon{background:url(../img/1.png)!important}.lms-ui-address-select.alert,.lms-ui-address-select.lms-ui-error{border:1px solid red!important;box-shadow:0 0 3px 1px red!important}.lms-ui-address-select.alert:focus,.lms-ui-address-select.lms-ui-error:focus{border:1px solid #a32828!important;box-shadow:0 0 1px 1px #a32828!important;outline:0}.lms-ui-address-select.lms-ui-warning{border:1px solid Orange!important;background-color:Khaki!important;box-shadow:0 0 3px 1px Orange!important}.lms-ui-address-select.lms-ui-warning:focus{border:1px solid Orange!important;background-color:Khaki!important;box-shadow:0 0 1px 1px Orange!important}.lms-ui-address-select.lms-ui-distinguished{border:1px solid Orange!important;box-shadow:0 0 3px 1px Orange!important}.lms-ui-address-select.lms-ui-distinguished:focus{border:1px solid Orange!important;box-shadow:0 0 1px 1px Orange!important}.lms-ui-menu-item-icon{width:1.5em;text-align:center;font-size:1.6em;vertical-align:middle;cursor:grab}.lms-ui-quick-search-icon{font-size:1.4em}.lms-ui-indicator-icon{font-size:1.5em;vertical-align:middle}.ui-tooltip.lms-ui-tooltip-eventinfoshort,.ui-tooltip.lms-ui-tooltip-nodelist{max-width:initial}.lms-ui-cursor-pointer:hover{cursor:pointer}.lms-ui-visibility-hidden{visibility:hidden!important}div.lms-ui-filter-container{display:flex;justify-content:space-between;align-items:center;flex-wrap:wrap}div.lms-ui-filter-container div.lms-ui-filter-definition{display:flex;flex-wrap:wrap;align-items:center;white-space:normal;max-width:80%}div.lms-ui-filter-container div.lms-ui-filter-definition>:not(script),div.lms-ui-filter-container div.lms-ui-filter-definition>form>:not(script){margin:.2em;display:inline-flex;flex-wrap:wrap;align-items:center}div.lms-ui-persistent-filter{display:flex;justify-content:flex-end;align-items:center}div.lms-ui-persistent-filter>*{margin:2px}div.lms-ui-persistent-filter .lms-ui-filter-name{display:none}.lms-ui-matched-text{background-color:#B6A688;font-weight:700}div.lms-ui-wysiwyg-editor{display:inline-flex;flex-direction:column;justify-content:flex-start;align-items:flex-start}div.lms-ui-wysiwyg-editor>label{padding-bottom:.5em}.lms-ui-dragslider-slave{box-shadow:0 0 10px 1px #000}.lms-ui-event-time-container{display:flex;flex-direction:column;width:90%;flex-grow:1}.lms-ui-event-time-container .lms-ui-event-time-top-panel{display:flex;flex-direction:row;flex-wrap:wrap}.lms-ui-event-time-container .lms-ui-event-time-top-panel .lms-ui-event-time-period{display:flex;flex-direction:column;flex-grow:1}.lms-ui-event-time-container .lms-ui-event-time-top-panel .lms-ui-event-time-period .lms-ui-event-time-date{display:flex;justify-content:flex-end}.lms-ui-event-time-container .lms-ui-event-time-top-panel .lms-ui-event-time-period .lms-ui-event-time-date:not(:first-child){margin-top:.5em}.lms-ui-event-time-container .lms-ui-event-time-top-panel .lms-ui-event-time-period .lms-ui-event-time-date>*{margin-left:.3em}.lms-ui-event-time-container .lms-ui-event-time-top-panel .lms-ui-event-whole-days{display:inline-flex;flex-direction:row;justify-content:flex-start;align-items:center;flex-grow:1;margin-left:1em}.lms-ui-event-time-container .lms-ui-event-time-bottom-panel{display:flex;flex-direction:column}.lms-ui-event-time-container .lms-ui-event-time-bottom-panel .lms-ui-event-time-legend{margin-top:1em;margin-left:-1.5em;height:2em;width:25em;transform:scale(.85);display:flex;flex-direction:row;white-space:nowrap}.lms-ui-event-time-container .lms-ui-event-time-bottom-panel .lms-ui-event-time-legend .lms-ui-event-time-legend-label{margin-left:-1.62em;transform:rotate(90deg) translateX(.3em) translateY(-.38em)}.lms-ui-event-time-container .lms-ui-event-time-bottom-panel .lms-ui-event-time-legend .lms-ui-event-time-legend-scale{transform:rotate(90deg) translateX(1.8em) translateY(.3em)}.lms-ui-event-time-container .lms-ui-event-time-bottom-panel .lms-ui-event-time-slider{width:25em;margin-left:1em;margin-top:.7em}.lms-ui-box-container{display:flex;flex-direction:column;justify-content:flex-start;align-items:flex-start;border:1px solid #000;background-color:#DFD5BD;margin-top:.2em;margin-bottom:.2em}.lms-ui-box-container .lms-ui-box-header{display:flex;flex-direction:row;justify-content:flex-start;align-items:center;align-self:stretch;padding:.25em;background-color:#CEBD9B;font-weight:700}.lms-ui-box-container .lms-ui-box-header>*{margin:.25em}.lms-ui-box-container>.lms-ui-box-header{border-bottom:1px solid #000}.lms-ui-box-container>.lms-ui-box-header-multi-row{display:flex;flex-direction:column;justify-content:flex-start;align-items:center;align-self:stretch;background-color:#CEBD9B;border-bottom:1px solid #000;padding:.25em}.lms-ui-box-container>.lms-ui-box-header-multi-row .lms-ui-box-header{padding:0}.lms-ui-box-container .lms-ui-box-contents{display:flex;flex-direction:row;justify-content:flex-start;align-items:flex-start;flex-wrap:wrap}.lms-ui-box-container .lms-ui-box-contents .lms-ui-box-panel{margin:.25em;display:inline-flex;flex-direction:column;justify-content:flex-start;align-items:flex-start}.lms-ui-box-container .lms-ui-box-contents .lms-ui-box-panel:not(:last-child){margin-right:10em}.lms-ui-box-container .lms-ui-box-contents .lms-ui-box-panel .lms-ui-box-row{display:flex;justify-content:flex-start;align-items:center}.lms-ui-box-container .lms-ui-box-contents .lms-ui-box-panel .lms-ui-box-row>*{margin:.25em}.lms-ui-box-container .lms-ui-box-contents .lms-ui-box-panel .lms-ui-box-row .lms-ui-box-row-label{font-weight:700}.lms-ui-box-container .lms-ui-box-contents .lms-ui-box-panel .lms-ui-box-row .lms-ui-box-row-field{display:flex;flex-direction:row;justify-content:flex-start;align-items:center}.lms-ui-box-container .lms-ui-box-contents .lms-ui-box-panel .lms-ui-box-row .lms-ui-box-row-field>*{margin-right:.3em}.lms-ui-box-container .lms-ui-box-contents .lms-ui-box-panel .lms-ui-box-row .lms-ui-box-row-field input{padding-left:.2em}.lms-ui-box-container .lms-ui-box-buttons{background-image:linear-gradient(to right,#000 33%,rgba(255,255,255,0) 0);background-position:left .5em;background-size:3px 1px;background-repeat:repeat-x;padding:1em .5em .5em .5em;align-self:stretch;flex-direction:row;justify-content:flex-end;align-items:center}.lms-ui-box-container .lms-ui-box-buttons>:not(:first-child){margin-left:.3em}div.lms-ui-tab-container{display:flex;flex-direction:column;justify-items:flex-start;border:1px solid #000;margin-top:.7em}div.lms-ui-tab-container:not(:last-child){margin-bottom:.3em}div.lms-ui-tab-container .lms-ui-tab-header{display:flex;flex-direction:row;justify-content:space-between;background-color:#B6A688;padding:.2em;cursor:pointer}div.lms-ui-tab-container .lms-ui-tab-header .lms-ui-tab-header-cell{display:flex;flex-direction:row;justify-content:flex-start;align-items:center;flex-wrap:wrap}div.lms-ui-tab-container .lms-ui-tab-header .lms-ui-tab-header-cell>:nth-child(n+2){margin-left:.2em}div.lms-ui-tab-container .lms-ui-tab-header .lms-ui-tab-header-cell>i{text-align:center;width:1.25em;margin-right:.5em}div.lms-ui-tab-container .lms-ui-tab-header .lms-ui-tab-header-cell:last-child{justify-content:flex-end}div.lms-ui-tab-container .lms-ui-tab-header .lms-ui-tab-header-cell:first-child{justify-content:flex-start}@media all and (max-width:768px){div.lms-ui-tab-container .lms-ui-tab-header .lms-ui-tab-header-cell:not(:first-child){flex-direction:column;align-items:flex-start}div.lms-ui-tab-container .lms-ui-tab-header .lms-ui-tab-header-cell>:nth-child(n+2){margin-left:0}}@media all and (max-width:768px){div.lms-ui-tab-container .lms-ui-tab-header{flex-direction:column}}div.lms-ui-tab-container .lms-ui-tab-header-suspensions{display:flex;flex-direction:row;justify-content:space-between;background-color:#CEBD9B;border-top:1px dotted grey;padding:.2em;cursor:pointer}div.lms-ui-tab-container .lms-ui-tab-contents{display:flex;flex-direction:column;justify-content:flex-start;border-top:1px solid #000}div.lms-ui-tab-container .lms-ui-tab-contents .lms-ui-tab-button-panel{display:flex;flex-direction:row;justify-content:space-between;padding:.2em;border-top:1px solid #000;background-color:#CEBD9B}div.lms-ui-tab-container .lms-ui-tab-contents .lms-ui-tab-button-panel>:nth-child(n+2){margin-left:.5em}div.lms-ui-tab-container .lms-ui-tab-contents .lms-ui-tab-button-panel .lms-ui-tab-buttons{display:flex;flex-direction:row;justify-content:flex-start;align-items:center;flex-wrap:wrap}div.lms-ui-tab-container .lms-ui-tab-contents .lms-ui-tab-button-panel .lms-ui-tab-buttons>:nth-child(n+2){margin-left:.5em}div.lms-ui-tab-container .lms-ui-tab-table-row{display:flex;flex-direction:row;flex-wrap:nowrap;width:100%}div.lms-ui-tab-container .lms-ui-tab-table-row:nth-child(even){background-color:#EBE4D6}div.lms-ui-tab-container .lms-ui-tab-table-row:nth-child(odd){background-color:#DFD5BD}div.lms-ui-tab-container .lms-ui-tab-table-row.lucid{background-color:#EBE4D6}div.lms-ui-tab-container .lms-ui-tab-table-row.light{background-color:#DFD5BD}div.lms-ui-tab-container .lms-ui-tab-table-row.header{background-color:#DFD5BD;border-bottom:1px solid #000}div.lms-ui-tab-container .lms-ui-tab-table-row.suspensions{background-color:#DFD5BD;border-bottom:1px solid #000}div.lms-ui-tab-container .lms-ui-tab-table-row.footer{padding-top:.2em;padding-bottom:.2em;background-color:#CEBD9B;border-top:1px solid #000}div.lms-ui-tab-container .lms-ui-tab-table-row.footer>:nth-child(n+2){margin-left:.5em}div.lms-ui-tab-container .lms-ui-tab-table-row:not(.header):not(.footer):not(:last-child){border-bottom:1px dotted grey}div.lms-ui-tab-container .lms-ui-tab-table-row:not(.header):not(.footer):hover{background-color:#CFC}div.lms-ui-tab-container .lms-ui-tab-table-row .buttons>:last-child{margin-right:.4em}@media all and (max-width:768px){div.lms-ui-tab-container .lms-ui-tab-table-row .buttons{flex-direction:column!important;justify-content:flex-start!important;width:2em!important}div.lms-ui-tab-container .lms-ui-tab-table-row .buttons>*{margin-right:.5em;margin-top:.2em}}div.lms-ui-tab-container .lms-ui-tab-table-row .lms-ui-tab-table-wrapper{display:flex;flex-direction:row;flex-grow:0}div.lms-ui-tab-container .lms-ui-tab-table-row .lms-ui-tab-table-wrapper .lms-ui-tab-table-column,div.lms-ui-tab-container .lms-ui-tab-table-row .lms-ui-tab-table-wrapper [class*=col-],div.lms-ui-tab-container .lms-ui-tab-table-row .lms-ui-tab-table-wrapper.lms-ui-tab-table-column,div.lms-ui-tab-container .lms-ui-tab-table-row .lms-ui-tab-table-wrapper[class*=col-]{flex-grow:1;padding-top:.1em}div.lms-ui-tab-container .lms-ui-tab-table-row.footer .lms-ui-tab-table-wrapper{padding-top:0}div.lms-ui-tab-container .lms-ui-tab-table-row.footer .lms-ui-tab-table-wrapper .lms-ui-tab-table-column,div.lms-ui-tab-container .lms-ui-tab-table-row.footer .lms-ui-tab-table-wrapper [class*=col-],div.lms-ui-tab-container .lms-ui-tab-table-row.footer .lms-ui-tab-table-wrapper.lms-ui-tab-table-column,div.lms-ui-tab-container .lms-ui-tab-table-row.footer .lms-ui-tab-table-wrapper[class*=col-]{padding-top:0}div.lms-ui-tab-container .lms-ui-tab-table-column{padding-left:.5em;text-overflow:ellipsis}div.lms-ui-tab-container .lms-ui-tab-table-column.buttons{text-align:right;display:flex;flex-wrap:nowrap;justify-content:flex-end;align-items:center}div.lms-ui-tab-container .lms-ui-tab-table-column.buttons>:not(first-child){margin-left:.3em}div.lms-ui-tab-container div.lms-ui-tab-table .lms-ui-tab-empty-table{width:100%;text-align:center;font-weight:700;padding-top:3em;padding-bottom:3em}div.lms-ui-tab-container div.lms-ui-tab-table .lms-ui-tab-hourglass{width:100%;text-align:center;font-weight:700;padding-top:1em;padding-bottom:1em}div.lms-ui-tab-container div.lms-ui-tab-table .lms-ui-tab-hourglass>i{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%;animation:fa-spin 2s infinite linear;-webkit-animation:fa-spin .75s infinite linear!important;animation:fa-spin .75s infinite linear!important}div.lms-ui-tab-container div.lms-ui-tab-table .lms-ui-tab-hourglass>i.fa-pull-left{margin-right:.3em}div.lms-ui-tab-container div.lms-ui-tab-table .lms-ui-tab-hourglass>i.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){div.lms-ui-tab-container div.lms-ui-tab-table .lms-ui-tab-hourglass>i{font-size:125%}}div.lms-ui-tab-container div.lms-ui-tab-table .lms-ui-tab-hourglass>i:before{content:"\f2f1"}div.lms-ui-tab-container div.lms-ui-tab-table .lms-ui-tab-hourglass>i:before{color:#000}div.lms-ui-tab-container div.lms-ui-tab-table .lms-ui-tab-hourglass-template{display:none}i.lms-ui-hourglass{font-weight:400;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block;font-style:normal;font-variant:normal;text-rendering:auto;line-height:1;font-family:'Font Awesome 5 Free';font-weight:900;line-height:unset;vertical-align:unset;font-size:130%;animation:fa-spin 2s infinite linear;-webkit-animation:fa-spin .75s infinite linear!important;animation:fa-spin .75s infinite linear!important}i.lms-ui-hourglass.fa-pull-left{margin-right:.3em}i.lms-ui-hourglass.fa-pull-right{margin-left:.3em}@media screen and (max-width:800px){i.lms-ui-hourglass{font-size:125%}}i.lms-ui-hourglass:before{content:"\f2f1"}i.lms-ui-hourglass:before{color:#000}td.lms-ui-mac-address-selection{padding:0!important}table.lms-ui-mac-address-selection .mac td .remove-mac{visibility:hidden;margin-left:-2em;margin-top:.1em}table.lms-ui-mac-address-selection .mac:hover td .remove-mac{visibility:visible;cursor:pointer}table.lms-ui-mac-address-selection .mac .mac-selector{margin-left:.4em}.lms-ui-address-box [readonly]{border:none;background-color:transparent}.lms-ui-address-box .lms-ui-address-box-container{display:flex;align-items:center}.lms-ui-address-box .lms-ui-address-box-container .lms-ui-address-box-buttons{display:flex;flex-direction:column;margin-left:.5em}.lms-ui-address-box .lms-ui-address-box-container .lms-ui-address-box-buttons button:not(:first-child){margin-top:.2em}.lms-ui-location-add-button{margin-top:.3em;margin-bottom:.3em}.lms-ui-message-quote{color:#B6A688;border-left:3px solid #B6A688;border-right:3px solid #B6A688;background-color:#fff;margin:.2em 0;padding:0 .4em;overflow:hidden;text-overflow:ellipsis}fieldset{display:inline;border-radius:5px;border-width:1px;border-style:dotted;border-color:grey}.lms-ui-separated-rows tr:not(:first-child){border-top:1px dotted grey}.lms-ui-date-container,.lms-ui-datetime-container{display:inline-flex}.lms-ui-category-label{box-shadow:0 .1em .1em #888;border:1px solid #a9a9a9;background-color:#fff;color:#000;padding:.35em;text-decoration:none;border-radius:.45em;display:inline-block}#lms-ui-resource-tab-selector-container{display:none;margin-top:1em}#lms-ui-resource-tab-selector-container>div:first-child{font-weight:700;display:inline-block}.lms-ui-date-period-container{white-space:nowrap}.lms-ui-date-period-container>:not(:last-child){padding-right:.3em}.lms-ui-date-period-wrapper{display:inline}.lms-ui-date-period-wrapper .lms-ui-button.lms-ui-button-date-period{margin-top:0}@media screen and (min-width:801px){.lms-ui-date-period-wrapper .lms-ui-button.lms-ui-button-date-period{min-height:1.8em}}.lms-ui-day-selection-wrapper{display:inline}.lms-ui-day-selection-wrapper .lms-ui-button.lms-ui-button-day-selection{margin-top:0}@media screen and (min-width:801px){.lms-ui-day-selection-wrapper .lms-ui-button.lms-ui-button-day-selection{min-height:1.8em}}.lms-ui-karma-container{display:inline-block}.lms-ui-karma-container .lms-ui-karma-button{vertical-align:middle;cursor:pointer}.lms-ui-karma-container .lms-ui-karma-button.disabled{color:#888;cursor:no-drop}.lms-ui-deadline-selection{display:inline}.lms-ui-deadline-selection .scombobox{width:5em;display:inline-block}.lms-ui-fileview-dialog .ui-dialog-content{display:flex}.lms-ui-fileview-dialog .ui-dialog-content img,.lms-ui-fileview-dialog .ui-dialog-content object{width:100%;height:100%}.lms-ui-message-new{color:inherit}.lms-ui-message-delivered{color:green}.lms-ui-message-sent{color:#888}.lms-ui-message-cancelled{color:Sienna}.lms-ui-message-bounced,.lms-ui-message-error{color:red}.lms-ui-font-smaller{font-size:80%}span.division-context{margin-left:.5em}.lms-ui-route-type{margin-block-start:0;margin-block-end:0;text-indent:-3.5em;margin-left:3.5em}.lms-ui-dotted-line-top{border-top:1px dotted grey} \ No newline at end of file diff --git a/css/style.less b/css/style.less index 5494bbd9f1..aa519c5460 100644 --- a/css/style.less +++ b/css/style.less @@ -2405,6 +2405,15 @@ div.lms-ui-tab-container { flex-direction: column; } } + .lms-ui-tab-header-suspensions { + display: flex; + flex-direction: row; + justify-content: space-between; + background-color: @dark; + border-top: @dotted-line; + padding: 0.2em; + cursor: pointer; + } .lms-ui-tab-contents { display: flex; @@ -2459,6 +2468,10 @@ div.lms-ui-tab-container { background-color: @light; border-bottom: @frame; } + &.suspensions { + background-color: @light; + border-bottom: @frame; + } &.footer { padding-top: 0.2em; padding-bottom: 0.2em; diff --git a/css/templates/customer/customerassignments.css b/css/templates/customer/customerassignments.css index 3394afe2e8..8a9a373f8f 100644 --- a/css/templates/customer/customerassignments.css +++ b/css/templates/customer/customerassignments.css @@ -1 +1 @@ -.assignmentpanel .lms-ui-tab-table .footer .liability{text-align:right}.assignmentpanel .lms-ui-tab-button-panel{border-top:0!important;height:.1em!important;position:relative}.assignmentpanel .lms-ui-tab-button-panel .lms-ui-tab-buttons:nth-child(2){position:absolute;bottom:0;right:0;margin-bottom:.5em;flex-wrap:initial}.assignmentpanel .lms-ui-tab-button-panel .lms-ui-tab-buttons:nth-child(2) button.suspend-assignments{margin-bottom:0}.assignmentpanel .lms-ui-tab-button-panel .lms-ui-tab-buttons:nth-child(2) button.delete-assignments{margin-bottom:0}.assignmentpanel .lms-ui-tab-table-row.footer{min-height:2.5em}.assignmentpanel .lms-ui-tab-table .footer .liability{text-align:left}.assignmentpanel .liability{width:25em}.assignmentpanel .base_value{width:4em}.assignmentpanel .ptu_quantity{width:2em}.assignmentpanel .discount{width:4em}.assignmentpanel .price{width:4em}.assignmentpanel .total{width:4em}.assignmentpanel .downceil_upceil{width:8em}.assignmentpanel .accounting-period{width:14em}.assignmentpanel .buttons{width:4em}@media all and (max-width:1500px){.assignmentpanel .col-4:first-child .liability{width:20em}.assignmentpanel .col-4:first-child .col-2{flex-direction:column!important;width:8em!important}.assignmentpanel .col-4:first-child .col-2 div{flex-grow:0!important;width:100%!important}.assignmentpanel .col-4:nth-child(2) .col-2:first-child{flex-direction:column!important;width:8em!important}.assignmentpanel .col-4:nth-child(2) .col-2:first-child div{flex-grow:0!important;width:100%!important}.assignmentpanel .col-4:nth-child(2) .col-2:nth-child(2){flex-direction:column!important;width:14em!important}.assignmentpanel .col-4:nth-child(2) .col-2:nth-child(2) div{flex-grow:0!important;width:100%!important}}@media all and (max-width:1100px){.assignmentpanel .col-4:first-child{flex-direction:column!important;width:15em!important}.assignmentpanel .col-4:first-child div{flex-grow:0!important;width:100%!important}.assignmentpanel .col-4:nth-child(2){flex-direction:column!important;width:11em!important}.assignmentpanel .col-4:nth-child(2) div{flex-grow:0!important;width:100%!important}}@media all and (max-width:768px){.assignmentpanel .lms-ui-tab-table .footer .liability{text-align:left}.assignmentpanel .col-8{flex-direction:column!important;width:17em!important}.assignmentpanel .col-8 div{flex-grow:0!important;width:100%!important}}.assignmentpanel .delete-assignments,.assignmentpanel .suspend-assignments{margin-top:-.7em;margin-right:.5em}.reward-flags{margin-block-start:.5em;margin-block-end:.5em;padding-inline-start:1.5em} \ No newline at end of file +.assignmentpanel .lms-ui-tab-button-panel{border-top:0!important;height:.1em!important;position:relative}.assignmentpanel .lms-ui-tab-button-panel .lms-ui-tab-buttons:nth-child(2){position:absolute;bottom:0;right:0;margin-bottom:.5em;flex-wrap:initial}.assignmentpanel .lms-ui-tab-button-panel .lms-ui-tab-buttons:nth-child(2) button.suspend-assignments{margin-bottom:0}.assignmentpanel .lms-ui-tab-button-panel .lms-ui-tab-buttons:nth-child(2) button.delete-assignments{margin-bottom:0}.assignmentpanel .lms-ui-tab-table-row.footer{min-height:2.5em}.assignmentpanel .lms-ui-tab-table .footer .liability{text-align:left}.assignmentpanel .liability{width:25em}.assignmentpanel .base_price{width:4em}.assignmentpanel .ptu_quantity{width:2em}.assignmentpanel .discount{width:8em}.assignmentpanel .price{width:4em}.assignmentpanel .total{width:4em}.assignmentpanel .downceil_upceil{width:6em}.assignmentpanel .accounting-period{width:16em}.assignmentpanel .buttons{width:4em}@media all and (max-width:1500px){.assignmentpanel .col-4:first-child .liability{width:20em}.assignmentpanel .col-4:first-child .col-2{flex-direction:column!important;width:8em!important}.assignmentpanel .col-4:first-child .col-2 div{flex-grow:0!important;width:100%!important}.assignmentpanel .col-4:nth-child(2) .col-2:first-child{flex-direction:column!important;width:8em!important}.assignmentpanel .col-4:nth-child(2) .col-2:first-child div{flex-grow:0!important;width:100%!important}.assignmentpanel .col-4:nth-child(2) .col-2:nth-child(2){flex-direction:column!important;width:14em!important}.assignmentpanel .col-4:nth-child(2) .col-2:nth-child(2) div{flex-grow:0!important;width:100%!important}}@media all and (max-width:1100px){.assignmentpanel .col-4:first-child{flex-direction:column!important;width:15em!important}.assignmentpanel .col-4:first-child div{flex-grow:0!important;width:100%!important}.assignmentpanel .col-4:nth-child(2){flex-direction:column!important;width:11em!important}.assignmentpanel .col-4:nth-child(2) div{flex-grow:0!important;width:100%!important}}@media all and (max-width:768px){.assignmentpanel .lms-ui-tab-table .footer .liability{text-align:left}.assignmentpanel .col-8{flex-direction:column!important;width:17em!important}.assignmentpanel .col-8 div{flex-grow:0!important;width:100%!important}}.assignmentpanel .delete-assignments,.assignmentpanel .suspend-assignments{margin-top:-.7em;margin-right:.5em}.assignmentpanel .suspensions-panel .suspension{width:10em!important}.assignmentpanel .suspensions-panel .liabilities{width:22em!important}.assignmentpanel .suspensions-panel .ptu-value{width:6em!important}.assignmentpanel .suspensions-panel .calculation-charge{width:30em!important}.assignmentpanel .suspensions-panel .total{width:8em!important}.assignmentpanel .suspensions-panel .accounting-period{width:8em!important}.reward-flags{margin-block-start:.5em;margin-block-end:.5em;padding-inline-start:1.5em} \ No newline at end of file diff --git a/css/templates/customer/customerassignments.less b/css/templates/customer/customerassignments.less index 146fefa1ff..13fa2cce2c 100644 --- a/css/templates/customer/customerassignments.less +++ b/css/templates/customer/customerassignments.less @@ -23,9 +23,6 @@ */ .assignmentpanel { - .lms-ui-tab-table .footer .liability { - text-align: right; - } .lms-ui-tab-button-panel { border-top: 0 !important; height: 0.1em !important; @@ -59,14 +56,14 @@ .liability { width: 25em; } - .base_value { + .base_price { width: 4em; } .ptu_quantity { width: 2em; } .discount { - width: 4em; + width: 8em; } .price { width: 4em; @@ -75,10 +72,10 @@ width: 4em; } .downceil_upceil { - width: 8em; + width: 6em; } .accounting-period { - width: 14em; + width: 16em; } .buttons { width: 4em; @@ -155,6 +152,27 @@ margin-top: -0.7em; margin-right: 0.5em; } + + .suspensions-panel { + .suspension { + width: 10em !important; + } + .liabilities { + width: 22em !important; + } + .ptu-value { + width: 6em !important; + } + .calculation-charge { + width: 30em !important; + } + .total { + width: 8em !important; + } + .accounting-period { + width: 8em !important; + } + } } .reward-flags { diff --git a/css/templates/customer/customerassignmentssuspend.css b/css/templates/customer/customerassignmentssuspend.css new file mode 100644 index 0000000000..4d6735077e --- /dev/null +++ b/css/templates/customer/customerassignmentssuspend.css @@ -0,0 +1 @@ +#customerassignmentssuspensions{margin-top:0;max-width:60em}.assignmentssuspensionspanel .lms-ui-tab-table .footer .liability{text-align:right}.assignmentssuspensionspanel .lms-ui-tab-button-panel{border-top:0!important;height:.1em!important;position:relative}.assignmentssuspensionspanel .lms-ui-tab-button-panel .lms-ui-tab-buttons:nth-child(2){position:absolute;bottom:0;right:0;margin-bottom:.5em;flex-wrap:initial}.assignmentssuspensionspanel .lms-ui-tab-table-row.footer{min-height:2.5em}.assignmentssuspensionspanel .lms-ui-tab-table .footer .suspensions-liability{text-align:left}.assignmentssuspensionspanel .suspensions-liability{width:20em}.assignmentssuspensionspanel .suspensions-accounting{width:17em;white-space:nowrap}.assignmentssuspensionspanel .suspensions-accounting-period{width:13em;white-space:nowrap}.assignmentssuspensionspanel .suspensions-buttons{width:4em}@media all and (max-width:1500px){.assignmentssuspensionspanel .col-4:first-child .suspensions-liability{width:20em}.assignmentssuspensionspanel .col-4:first-child .col-2{flex-direction:column!important;width:8em!important}.assignmentssuspensionspanel .col-4:first-child .col-2 div{flex-grow:0!important;width:100%!important}.assignmentssuspensionspanel .col-4:nth-child(2) .col-2:first-child{flex-direction:column!important;width:8em!important}.assignmentssuspensionspanel .col-4:nth-child(2) .col-2:first-child div{flex-grow:0!important;width:100%!important}.assignmentssuspensionspanel .col-4:nth-child(2) .col-2:nth-child(2){flex-direction:column!important;width:14em!important}.assignmentssuspensionspanel .col-4:nth-child(2) .col-2:nth-child(2) div{flex-grow:0!important;width:100%!important}}@media all and (max-width:1100px){.assignmentssuspensionspanel .col-4:first-child{flex-direction:column!important;width:15em!important}.assignmentssuspensionspanel .col-4:first-child div{flex-grow:0!important;width:100%!important}.assignmentssuspensionspanel .col-4:nth-child(2){flex-direction:column!important;width:11em!important}.assignmentssuspensionspanel .col-4:nth-child(2) div{flex-grow:0!important;width:100%!important}}@media all and (max-width:768px){.assignmentssuspensionspanel .lms-ui-tab-table .footer .liability{text-align:left}} \ No newline at end of file diff --git a/css/templates/customer/customerassignmentssuspend.less b/css/templates/customer/customerassignmentssuspend.less new file mode 100644 index 0000000000..623176170e --- /dev/null +++ b/css/templates/customer/customerassignmentssuspend.less @@ -0,0 +1,123 @@ +/* + * LMS version 1.11-git + * + * (C) Copyright 2001-2020 LMS Developers + * + * Please, see the doc/AUTHORS for more information about authors! + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License Version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + * + * $Id$ + */ + +#customerassignmentssuspensions { + margin-top: 0em; + max-width: 60em; +} +.assignmentssuspensionspanel { + .lms-ui-tab-table .footer .liability { + text-align: right; + } + .lms-ui-tab-button-panel { + border-top: 0 !important; + height: 0.1em !important; + position: relative; + + .lms-ui-tab-buttons:nth-child(2) { + position: absolute; + bottom: 0; + right: 0; + margin-bottom: 0.5em; + flex-wrap: initial; + } + } + .lms-ui-tab-table-row.footer { + min-height: 2.5em; + } + .lms-ui-tab-table .footer .suspensions-liability { + text-align: left; + } + .suspensions-liability { + width: 20em; + } + .suspensions-accounting { + width: 17em; + white-space: nowrap; + } + .suspensions-accounting-period { + width: 13em; + white-space: nowrap; + } + .suspensions-buttons { + width: 4em; + } + + @media all and (max-width: 1500px) { + .col-4:first-child { + .suspensions-liability { + width: 20em; + } + .col-2 { + flex-direction: column !important; + width: 8em !important; + div { + flex-grow: 0 !important; + width: 100% !important; + } + } + } + .col-4:nth-child(2) { + .col-2:first-child { + flex-direction: column !important; + width: 8em !important; + div { + flex-grow: 0 !important; + width: 100% !important; + } + } + .col-2:nth-child(2) { + flex-direction: column !important; + width: 14em !important; + div { + flex-grow: 0 !important; + width: 100% !important; + } + } + } + } + @media all and (max-width: 1100px) { + .col-4:first-child { + flex-direction: column !important; + width: 15em !important; + div { + flex-grow: 0 !important; + width: 100% !important; + } + } + .col-4:nth-child(2) { + flex-direction: column !important; + width: 11em !important; + div { + flex-grow: 0 !important; + width: 100% !important; + } + } + } + @media all and (max-width: 768px) { + .lms-ui-tab-table .footer .liability { + text-align: left; + } + } +} diff --git a/doc/lms.mysql b/doc/lms.mysql index 44f761353a..fba0846a0d 100644 --- a/doc/lms.mysql +++ b/doc/lms.mysql @@ -26,7 +26,6 @@ DROP VIEW IF EXISTS vusers; DROP VIEW IF EXISTS vinvoicecontents; DROP VIEW IF EXISTS vallusers; DROP VIEW IF EXISTS vdivisions; -DROP VIEW IF EXISTS vnodetariffs_allsuspended; DROP VIEW IF EXISTS vnodetariffs_tariffs; DROP VIEW IF EXISTS vnodetariffs; DROP VIEW IF EXISTS vnodealltariffs_nodes; @@ -34,6 +33,9 @@ DROP VIEW IF EXISTS vnodealltariffs_tariffs; DROP VIEW IF EXISTS vnodealltariffs; DROP VIEW IF EXISTS customerconsentview; DROP VIEW IF EXISTS vcustomerassignments; +DROP VIEW IF EXISTS vassignmentsuspensions; +DROP VIEW IF EXISTS vassignmentssuspensionsgroupcounts; +DROP VIEW IF EXISTS vassignmentssuspensionsvalues; DROP TABLE IF EXISTS up_sessions; DROP TABLE IF EXISTS up_info_changes; @@ -186,6 +188,8 @@ DROP TABLE IF EXISTS customerbalances; DROP TABLE IF EXISTS comments; DROP TABLE IF EXISTS cryptokeys; DROP TABLE IF EXISTS tsigkeys; +DROP TABLE IF EXISTS assignmentsuspensions; +DROP TABLE IF EXISTS suspensions; SET FOREIGN_KEY_CHECKS = 1; SET SESSION sql_mode = ''; @@ -1249,7 +1253,6 @@ CREATE TABLE assignments ( datefrom int(11) NOT NULL DEFAULT '0', dateto int(11) NOT NULL DEFAULT '0', invoice tinyint(1) NOT NULL DEFAULT '0', - suspended tinyint(1) NOT NULL DEFAULT '0', settlement tinyint(1) NOT NULL DEFAULT '0', pdiscount decimal(5,2) NOT NULL DEFAULT '0', vdiscount decimal(9,3) NOT NULL DEFAULT '0', @@ -3232,6 +3235,47 @@ CREATE TABLE up_sessions ( FOREIGN KEY (customerid) REFERENCES customers (id) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB; +# -------------------------------------------------------- +# +# Structure of table suspensions +# +CREATE TABLE suspensions( + id int(11) NOT NULL auto_increment, + at int(11) DEFAULT NULL, + datefrom int(11) DEFAULT 0 NOT NULL, + dateto int(11) DEFAULT 0 NOT NULL, + chargemethod smallint NOT NULL, + calculationmethod smallint NOT NULL, + value numeric(9, 3) DEFAULT NULL, + percentage numeric(3, 2) DEFAULT NULL, + netflag smallint DEFAULT NULL, + currency varchar(3) DEFAULT NULL, + note text DEFAULT NULL, + customerid int(11) DEFAULT NULL, + taxid int(11) DEFAULT NULL, + PRIMARY KEY(id), + CONSTRAINT suspensions_customerid_fkey + FOREIGN KEY (customerid) REFERENCES customers(id) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT suspensions_taxid_fkey + FOREIGN KEY (taxid) REFERENCES taxes(id) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB; + +# -------------------------------------------------------- +# +# Structure of table assignmentsuspensions +# +CREATE TABLE assignmentsuspensions( + id int(11) NOT NULL auto_increment, + suspensionid int(11) NOT NULL, + assignmentid int(11) NOT NULL, + PRIMARY KEY(id), + CONSTRAINT suspensions_suspensionid_fkey + FOREIGN KEY (suspensionid) REFERENCES suspensions(id) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT assignments_assignmentid_fkey + FOREIGN KEY (assignmentid) REFERENCES assignments(id) ON DELETE CASCADE ON UPDATE CASCADE, + UNIQUE KEY assignmentsuspensions_assignmentid_suspensionid_ukey (assignmentid, suspensionid) +) ENGINE=InnoDB; + # -------------------------------------------------------- # # Functions and Views @@ -3302,13 +3346,6 @@ CREATE VIEW vnodes AS LEFT JOIN vaddresses a ON n.address_id = a.id WHERE n.ipaddr <> 0 OR n.ipaddr_pub <> 0; -CREATE VIEW vnodetariffs_allsuspended AS - SELECT customerid, COUNT(id) AS allsuspended FROM assignments - WHERE tariffid IS NULL AND liabilityid IS NULL - AND datefrom <= UNIX_TIMESTAMP() - AND (dateto = 0 OR dateto > UNIX_TIMESTAMP()) - GROUP BY customerid; - CREATE VIEW vnodetariffs_tariffs AS SELECT n.id AS nodeid, ROUND(SUM(t.downrate * a.count)) AS downrate, @@ -3335,8 +3372,12 @@ CREATE VIEW vnodetariffs_tariffs AS JOIN nodeassignments na ON na.nodeid = n.id JOIN assignments a ON a.id = na.assignmentid JOIN tariffs t ON t.id = a.tariffid - LEFT JOIN vnodetariffs_allsuspended s ON s.customerid = n.ownerid - WHERE s.allsuspended IS NULL AND a.suspended = 0 AND a.commited = 1 + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= UNIX_TIMESTAMP() + AND (vas.suspension_dateto >= UNIX_TIMESTAMP() OR vas.suspension_dateto = 0) + AND a.datefrom <= UNIX_TIMESTAMP() + AND (a.dateto > UNIX_TIMESTAMP() OR a.dateto = 0) + WHERE vas.suspended IS NULL AND a.commited = 1 AND a.datefrom <= UNIX_TIMESTAMP() AND (a.dateto = 0 OR a.dateto >= UNIX_TIMESTAMP()) AND (t.downrate > 0 OR t.downceil > 0 OR t.uprate > 0 OR t.upceil > 0) @@ -3398,8 +3439,12 @@ CREATE VIEW vnodealltariffs_tariffs AS FROM assignments a JOIN tariffs t ON t.id = a.tariffid JOIN vnodealltariffs_nodes n ON n.ownerid = a.customerid - LEFT JOIN vnodetariffs_allsuspended s ON s.customerid = a.customerid - WHERE s.allsuspended IS NULL AND a.suspended = 0 AND a.commited = 1 + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= UNIX_TIMESTAMP() + AND (vas.suspension_dateto >= UNIX_TIMESTAMP() OR vas.suspension_dateto = 0) + AND a.datefrom <= UNIX_TIMESTAMP() + AND (a.dateto > UNIX_TIMESTAMP() OR a.dateto = 0) + WHERE vas.suspended IS NULL AND a.commited = 1 AND a.datefrom <= UNIX_TIMESTAMP() AND (a.dateto = 0 OR a.dateto >= UNIX_TIMESTAMP()) AND (t.downrate > 0 OR t.downceil > 0 OR t.uprate > 0 OR t.upceil > 0) @@ -3773,6 +3818,310 @@ CREATE TRIGGER cash_customerbalances_delete_trigger AFTER DELETE ON cash END $$ DELIMITER ; +CREATE VIEW vassignmentssuspensionsgroupcounts AS + SELECT COUNT(vasg.suspension_assignment_id) AS suspensiongroup_assignments_count, + vasg.suspension_id AS suspensiongroup_suspension_id + FROM (SELECT + (CASE WHEN suspensions.assignment_id IS NOT NULL + THEN suspensions.assignment_id + ELSE a.id + END) AS suspension_assignment_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.suspension_id + ELSE suspensions_all.suspension_id + END) AS suspension_id + FROM assignments a + LEFT JOIN ( + SELECT + assignmentsuspensions.assignmentid AS assignment_id, + assignmentsuspensions.suspensionid AS suspension_id, + suspensions1.id AS id + FROM assignmentsuspensions + JOIN suspensions AS suspensions1 ON suspensions1.id = assignmentsuspensions.suspensionid + LEFT JOIN taxes ON taxes.id = suspensions1.taxid + ) suspensions ON suspensions.assignment_id = a.id + LEFT JOIN ( + SELECT + suspensions2.id AS suspension_id, + suspensions2.customerid, + (CASE WHEN suspensions2.customerid IS NULL THEN 0 ELSE 1 END) AS suspend_all + FROM suspensions AS suspensions2 + ) AS suspensions_all ON suspensions_all.customerid = a.customerid + WHERE suspensions.suspension_id IS NOT NULL OR suspensions_all.suspend_all = 1 + ) AS vasg + GROUP BY vasg.suspension_id; + +CREATE VIEW vassignmentssuspensionsvalues AS + SELECT + suspension_assignment_id AS suspensionvalues_assignment_id, + suspension_id AS suspensionvalues_suspension_id, + assignment_base_price AS suspensionvalues_assignment_base_price, + assignment_tpv_price AS suspensionvalues_assignment_tpv_price, + assignment_price AS suspensionvalues_assignment_price, + suspensiongroup_assignments_count AS suspensionvalues_assignments_count + FROM ( + SELECT + (CASE WHEN suspensions.assignment_id IS NOT NULL + THEN suspensions.assignment_id + ELSE a.id + END) AS suspension_assignment_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.suspension_id + ELSE suspensions_all.suspension_id + END) AS suspension_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.suspensiongroup_assignments_count + ELSE suspensions_all.suspensiongroup_assignments_count + END) AS suspensiongroup_assignments_count, + ROUND(((((100 - a.pdiscount) * (CASE WHEN a.liabilityid IS NULL THEN tvalue ELSE lvalue END)) / 100) - a.vdiscount), 3) AS assignment_base_price, + assignments_tpvariants.tpvprice AS assignment_tpv_price, + (CASE WHEN assignments_tpvariants.tpvprice IS NULL + THEN ROUND(((((100 - a.pdiscount) * (CASE WHEN a.liabilityid IS NULL THEN tvalue ELSE lvalue END)) / 100) - a.vdiscount), 3) + ELSE assignments_tpvariants.tpvprice + END) AS assignment_price + FROM assignments a + LEFT JOIN ( + SELECT + tariffs.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN tariffs.flags & 16 > 0 THEN tariffs.netvalue ELSE tariffs.value END) AS tvalue + FROM tariffs + JOIN taxes ON taxes.id = tariffs.taxid + ) t ON a.tariffid = t.id + LEFT JOIN ( + SELECT + liabilities.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN liabilities.flags & 16 > 0 THEN liabilities.netvalue ELSE liabilities.value END) AS lvalue + FROM liabilities + JOIN taxes ON taxes.id = liabilities.taxid + ) l ON a.liabilityid = l.id + LEFT JOIN ( + SELECT + assignmentsuspensions.assignmentid AS assignment_id, + assignmentsuspensions.suspensionid AS suspension_id, + suspensions1.id AS id, + vasg.suspensiongroup_assignments_count AS suspensiongroup_assignments_count + FROM assignmentsuspensions + JOIN suspensions AS suspensions1 ON suspensions1.id = assignmentsuspensions.suspensionid + JOIN vassignmentssuspensionsgroupcounts vasg ON vasg.suspensiongroup_suspension_id = suspensions1.id + LEFT JOIN taxes ON taxes.id = suspensions1.taxid + ) suspensions ON suspensions.assignment_id = a.id + LEFT JOIN ( + SELECT + suspensions2.id AS suspension_id, + suspensions2.customerid, + (CASE WHEN suspensions2.customerid IS NULL THEN 0 ELSE 1 END) AS suspend_all, + vasg.suspensiongroup_assignments_count AS suspensiongroup_assignments_count + FROM suspensions AS suspensions2 + JOIN vassignmentssuspensionsgroupcounts vasg ON vasg.suspensiongroup_suspension_id = suspensions2.id + ) AS suspensions_all ON suspensions_all.customerid = a.customerid + LEFT JOIN ( + SELECT + tpv.* + FROM assignments a + JOIN ( + SELECT + tariffpricevariants.quantity_threshold AS tpv_quantity_threshold, tariffs.id AS tpv_tariffid, + (CASE WHEN tariffs.flags & 16 > 0 THEN tariffpricevariants.net_price ELSE tariffpricevariants.gross_price END) AS tpvprice + FROM tariffs + JOIN tariffpricevariants ON tariffs.id = tariffpricevariants.tariffid + ) tpv ON a.tariffid = tpv.tpv_tariffid AND tpv.tpv_quantity_threshold <= a.count AND tpv.tpv_tariffid = a.tariffid + ORDER BY tpv.tpv_quantity_threshold DESC LIMIT 1 + ) AS assignments_tpvariants ON a.tariffid = assignments_tpvariants.tpv_tariffid + WHERE suspensions.suspension_id IS NOT NULL OR suspensions_all.suspend_all = 1 + ) AS vasv; + +CREATE VIEW vassignmentsuspensions AS + SELECT + (CASE WHEN suspensions.assignment_id IS NOT NULL + THEN suspensions.assignment_id + ELSE a.id + END) AS suspension_assignment_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL OR suspensions_all.suspend_all = 1 THEN 1 ELSE 0 END) AS suspended, + (CASE WHEN suspensions.suspension_id IS NULL AND suspensions_all.suspend_all = 1 THEN 1 ELSE 0 END) AS suspension_suspend_all, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.suspension_id + ELSE suspensions_all.suspension_id + END) AS suspension_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.at + ELSE suspensions_all.at + END) AS suspension_at, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.datefrom + ELSE suspensions_all.datefrom + END) AS suspension_datefrom, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.dateto + ELSE suspensions_all.dateto + END) AS suspension_dateto, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.chargemethod + ELSE suspensions_all.chargemethod + END) AS suspension_charge_method, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.calculationmethod + ELSE suspensions_all.calculationmethod + END) AS suspension_calculation_method, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.value + ELSE suspensions_all.value + END) AS suspension_value, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.percentage + ELSE suspensions_all.percentage + END) AS suspension_percentage, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.netflag + ELSE suspensions_all.netflag + END) AS suspension_netflag, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.currency + ELSE suspensions_all.currency + END) AS suspension_currency, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.taxid + ELSE suspensions_all.taxid + END) AS suspension_tax_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.note + ELSE suspensions_all.note + END) AS suspension_note, + (CASE WHEN suspensions.customerid IS NOT NULL + THEN suspensions_all.customerid + ELSE a.customerid + END) AS suspension_customer_id, + (CASE WHEN suspensions.taxrate IS NOT NULL + THEN suspensions.taxrate + ELSE suspensions_all.taxrate + END) AS suspension_taxrate, + (CASE WHEN suspensions.taxlabel IS NOT NULL + THEN suspensions.taxlabel + ELSE suspensions_all.taxlabel + END) AS suspension_taxlabel, + vasv.suspensionvalues_assignment_base_price, + vasv.suspensionvalues_assignment_tpv_price, + vasv.suspensionvalues_assignment_price, + vasv.suspensionvalues_assignments_count, + (CASE + WHEN suspensions.chargemethod = 3 OR suspensions.chargemethod = 2 + OR suspensions_all.chargemethod = 3 OR suspensions_all.chargemethod = 2 + THEN (CASE + WHEN suspensions.calculationmethod = 1 + THEN vasv.suspensionvalues_assignment_price * + (CASE + WHEN suspensions.percentage IS NOT NULL + THEN ROUND(suspensions.percentage / 100, 2) + ELSE + ROUND((SELECT CAST(uiconfig.value AS numeric) + FROM uiconfig + WHERE uiconfig.section = 'suspensions' + AND uiconfig.var = 'default_percentage' + AND uiconfig.configid IS NULL + LIMIT 1) / 100, 2) + END) + WHEN suspensions_all.calculationmethod = 1 + THEN vasv.suspensionvalues_assignment_price * + (CASE + WHEN suspensions_all.percentage IS NOT NULL + THEN ROUND(suspensions_all.percentage / 100, 2) + ELSE + ROUND((SELECT CAST(uiconfig.value AS numeric) + FROM uiconfig + WHERE uiconfig.section = 'suspensions' + AND uiconfig.var = 'default_percentage' + AND uiconfig.configid IS NULL + LIMIT 1) / 100, 2) + END) + WHEN suspensions.calculationmethod = 2 + THEN + (CASE + WHEN suspensions.value IS NOT NULL + THEN ROUND(suspensions.value / vasv.suspensionvalues_assignments_count, 2) + ELSE + ROUND((SELECT CAST(uiconfig.value AS numeric) + FROM uiconfig + WHERE uiconfig.section = 'suspensions' + AND uiconfig.var = 'default_percentage' + AND uiconfig.configid IS NULL + LIMIT 1) / 100, 2) + END) + WHEN suspensions_all.calculationmethod = 2 + THEN + (CASE + WHEN suspensions_all.value IS NOT NULL + THEN ROUND(suspensions_all.value / vasv.suspensionvalues_assignments_count, 2) + ELSE + ROUND((SELECT CAST(uiconfig.value AS numeric) + FROM uiconfig + WHERE uiconfig.section = 'suspensions' + AND uiconfig.var = 'default_percentage' + AND uiconfig.configid IS NULL + LIMIT 1) / 100, 2) + END) + END) + WHEN suspensions.chargemethod = 1 OR suspensions_all.chargemethod = 1 + THEN 0 + END) AS suspension_price + FROM assignments a + LEFT JOIN ( + SELECT + tariffs.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN tariffs.flags & 16 > 0 THEN tariffs.netvalue ELSE tariffs.value END) AS tvalue + FROM tariffs + JOIN taxes ON taxes.id = tariffs.taxid + ) t ON a.tariffid = t.id + LEFT JOIN ( + SELECT + tpv.* + FROM assignments a + JOIN ( + SELECT + tariffpricevariants.quantity_threshold AS tpv_quantity_threshold, + tariffs.id AS tpv_tariffid, + (CASE WHEN tariffs.flags & 16 > 0 THEN tariffpricevariants.net_price ELSE tariffpricevariants.gross_price END) AS tpvprice + FROM tariffs + JOIN tariffpricevariants ON tariffs.id = tariffpricevariants.tariffid + ) tpv ON a.tariffid = tpv.tpv_tariffid AND tpv.tpv_quantity_threshold <= a.count AND tpv.tpv_tariffid = a.tariffid + ORDER BY tpv.tpv_quantity_threshold DESC LIMIT 1 + ) AS assignments_tpvariants ON a.tariffid = assignments_tpvariants.tpv_tariffid + LEFT JOIN ( + SELECT + liabilities.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN liabilities.flags & 16 > 0 THEN liabilities.netvalue ELSE liabilities.value END) AS lvalue + FROM liabilities + JOIN taxes ON taxes.id = liabilities.taxid + ) l ON a.liabilityid = l.id + LEFT JOIN ( + SELECT + assignmentsuspensions.id AS assignmentsuspension_id, + assignmentsuspensions.assignmentid AS assignment_id, + assignmentsuspensions.suspensionid AS suspension_id, + suspensions1.id AS id, + suspensions1.at, suspensions1.datefrom, suspensions1.dateto, suspensions1.chargemethod, suspensions1.calculationmethod, + suspensions1.value, suspensions1.percentage, suspensions1.netflag, suspensions1.currency, suspensions1.note, suspensions1.taxid, + suspensions1.customerid, + taxes.value AS taxrate, taxes.label AS taxlabel + FROM assignmentsuspensions + JOIN suspensions AS suspensions1 ON suspensions1.id = assignmentsuspensions.suspensionid + LEFT JOIN taxes ON taxes.id = suspensions1.taxid + ) suspensions ON suspensions.assignment_id = a.id + LEFT JOIN ( + SELECT suspensions2.id AS suspension_id, suspensions2.at, suspensions2.datefrom, suspensions2.dateto, + suspensions2.chargemethod, suspensions2.calculationmethod, + suspensions2.value, suspensions2.percentage, suspensions2.netflag, suspensions2.currency, suspensions2.note, suspensions2.taxid, + suspensions2.customerid, + (CASE WHEN suspensions2.customerid IS NULL THEN 0 ELSE 1 END) AS suspend_all, + taxes.value AS taxrate, taxes.label AS taxlabel + FROM suspensions AS suspensions2 + LEFT JOIN taxes ON taxes.id = suspensions2.taxid + ) AS suspensions_all ON suspensions_all.customerid = a.customerid + LEFT JOIN vassignmentssuspensionsvalues vasv ON vasv.suspensionvalues_assignment_id = a.id + WHERE suspensions.suspension_id IS NOT NULL OR suspensions_all.suspend_all = 1; + INSERT INTO rtcategories (name, description, style) VALUES ('default', 'default category', 'background-color:#ffffff;color:#000000'); @@ -3925,7 +4274,11 @@ URL: %url ('receipts','content_type','text/html','',0), ('receipts','type','html','',0), ('receipts','attachment_name','','',0), -('payments','suspension_percentage','0','',0), +('suspensions','default_percentage','0','',0), +('suspensions','default_value','0','',0), +('suspensions', 'default_netflag','0','',0), +('suspensions', 'default_charge_method','2','[1-none|2-once|3-periodically]',0), +('suspensions', 'default_calculation_method','1','[1-percent|2-value]',0), ('mail','debug_email','','',0), ('mail','smtp_host','127.0.0.1','',0), ('mail','smtp_port','25','',0), @@ -4369,4 +4722,4 @@ INSERT INTO netdevicemodels (name, alternative_name, netdeviceproducerid) VALUES ('XR7', 'XR7 MINI PCI PCBA', 2), ('XR9', 'MINI PCI 600MW 900MHZ', 2); -INSERT INTO dbinfo (keytype, keyvalue) VALUES ('dbversion', '2024050700'); +INSERT INTO dbinfo (keytype, keyvalue) VALUES ('dbversion', '2024052400'); diff --git a/doc/lms.pgsql b/doc/lms.pgsql index fa7bc8f6bd..2afd408446 100644 --- a/doc/lms.pgsql +++ b/doc/lms.pgsql @@ -1105,7 +1105,6 @@ CREATE TABLE assignments ( datefrom integer DEFAULT 0 NOT NULL, dateto integer DEFAULT 0 NOT NULL, invoice smallint DEFAULT 0 NOT NULL, - suspended smallint DEFAULT 0 NOT NULL, settlement smallint DEFAULT 0 NOT NULL, pdiscount numeric(5,2) DEFAULT 0 NOT NULL, vdiscount numeric(9,3) DEFAULT 0 NOT NULL, @@ -3150,6 +3149,49 @@ CREATE TABLE up_sessions ( PRIMARY KEY (id) ); +/* -------------------------------------------------------- + Structure of table "suspensions" +-------------------------------------------------------- */ +DROP SEQUENCE IF EXISTS suspensions_id_seq; +CREATE SEQUENCE suspensions_id_seq; +DROP TABLE IF EXISTS suspensions CASCADE; +CREATE TABLE suspensions ( + id integer DEFAULT nextval('suspensions_id_seq'::text) NOT NULL, + at integer DEFAULT NULL, + datefrom integer DEFAULT 0 NOT NULL, + dateto integer DEFAULT 0 NOT NULL, + chargemethod smallint NOT NULL, + calculationmethod smallint NOT NULL, + value numeric(9, 3) DEFAULT NULL, + percentage numeric(3, 2) DEFAULT NULL, + netflag smallint DEFAULT NULL, + currency varchar(3) DEFAULT NULL, + note text DEFAULT NULL, + customerid integer DEFAULT NULL + CONSTRAINT suspensions_customerid_fkey REFERENCES customers (id) ON DELETE CASCADE ON UPDATE CASCADE, + taxid integer DEFAULT NULL + CONSTRAINT suspensions_taxid_fkey REFERENCES taxes (id) ON DELETE CASCADE ON UPDATE CASCADE, + PRIMARY KEY (id) +); + + +/* -------------------------------------------------------- + Structure of table "assignmentsuspensions" +-------------------------------------------------------- */ +DROP SEQUENCE IF EXISTS assignmentsuspensions_id_seq; +CREATE SEQUENCE assignmentsuspensions_id_seq; +DROP TABLE IF EXISTS assignmentsuspensions CASCADE; +CREATE TABLE assignmentsuspensions ( + id integer DEFAULT nextval('assignmentsuspensions_id_seq'::text) NOT NULL, + suspensionid integer NOT NULL + CONSTRAINT suspensions_suspensionid_fkey REFERENCES suspensions (id) ON DELETE CASCADE ON UPDATE CASCADE, + assignmentid integer NOT NULL + CONSTRAINT assignments_assignmentid_fkey REFERENCES assignments (id) ON DELETE CASCADE ON UPDATE CASCADE, + PRIMARY KEY (id), + CONSTRAINT assignmentsuspensions_assignmentid_suspensionid_ukey UNIQUE (assignmentid, suspensionid) +); + + /* --------------------------------------------------- Functions and Views ------------------------------------------------------*/ @@ -3397,14 +3439,12 @@ CREATE VIEW vnodetariffs AS JOIN nodeassignments na ON na.nodeid = n.id JOIN assignments a ON a.id = na.assignmentid JOIN tariffs t ON t.id = a.tariffid - LEFT JOIN ( - SELECT customerid, COUNT(id) AS allsuspended FROM assignments - WHERE tariffid IS NULL AND liabilityid IS NULL - AND datefrom <= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer - AND (dateto = 0 OR dateto > EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer) - GROUP BY customerid - ) s ON s.customerid = n.ownerid - WHERE s.allsuspended IS NULL AND a.suspended = 0 AND a.commited = 1 + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer + AND (vas.suspension_dateto >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer OR vas.suspension_dateto = 0) + AND a.datefrom <= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer + AND (a.dateto > EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer OR a.dateto = 0) + WHERE vas.suspended IS NULL AND a.commited = 1 AND a.datefrom <= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer AND (a.dateto = 0 OR a.dateto >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer) AND (t.downrate > 0 OR t.downceil > 0 OR t.uprate > 0 OR t.upceil > 0) @@ -3497,14 +3537,12 @@ CREATE VIEW vnodealltariffs AS JOIN nodeassignments na ON na.assignmentid = a.id JOIN nodes n ON n.id = na.nodeid JOIN tariffs t ON t.id = a.tariffid - LEFT JOIN ( - SELECT customerid, COUNT(id) AS allsuspended FROM assignments - WHERE tariffid IS NULL AND liabilityid IS NULL - AND datefrom <= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer - AND (dateto = 0 OR dateto > EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer) - GROUP BY customerid - ) s ON s.customerid = n.ownerid - WHERE s.allsuspended IS NULL AND a.suspended = 0 AND a.commited = 1 + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer + AND (vas.suspension_dateto >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer OR vas.suspension_dateto = 0) + AND a.datefrom <= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer + AND (a.dateto > EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer OR a.dateto = 0) + WHERE vas.suspended IS NULL AND a.commited = 1 AND a.datefrom <= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer AND (a.dateto = 0 OR a.dateto >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer) AND (t.downrate > 0 OR t.downceil > 0 OR t.uprate > 0 OR t.upceil > 0) @@ -3567,14 +3605,12 @@ CREATE VIEW vnodealltariffs AS WHERE (vn.ownerid IS NOT NULL AND nd.id IS NULL) OR (vn.ownerid IS NULL AND nd.id IS NOT NULL) ) n ON n.ownerid = a.customerid - LEFT JOIN ( - SELECT customerid, COUNT(id) AS allsuspended FROM assignments - WHERE tariffid IS NULL AND liabilityid IS NULL - AND datefrom <= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer - AND (dateto = 0 OR dateto > EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer) - GROUP BY customerid - ) s ON s.customerid = a.customerid - WHERE s.allsuspended IS NULL AND a.suspended = 0 AND a.commited = 1 + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer + AND (vas.suspension_dateto >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer OR vas.suspension_dateto = 0) + AND a.datefrom <= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer + AND (a.dateto > EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer OR a.dateto = 0) + WHERE vas.suspended IS NULL AND a.commited = 1 AND a.datefrom <= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer AND (a.dateto = 0 OR a.dateto >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer) AND (t.downrate > 0 OR t.downceil > 0 OR t.uprate > 0 OR t.upceil > 0) @@ -3818,6 +3854,311 @@ CREATE TRIGGER cash_customerbalances_update_trigger AFTER INSERT OR UPDATE OR DE CREATE TRIGGER cash_customerbalances_truncate_trigger AFTER TRUNCATE ON cash EXECUTE PROCEDURE customerbalances_update(); +CREATE VIEW vassignmentssuspensionsgroupcounts AS + SELECT COUNT(vasg.suspension_assignment_id) AS suspensiongroup_assignments_count, + vasg.suspension_id AS suspensiongroup_suspension_id + FROM (SELECT + (CASE WHEN suspensions.assignment_id IS NOT NULL + THEN suspensions.assignment_id + ELSE a.id + END) AS suspension_assignment_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.suspension_id + ELSE suspensions_all.suspension_id + END) AS suspension_id + FROM assignments a + LEFT JOIN ( + SELECT + assignmentsuspensions.assignmentid AS assignment_id, + assignmentsuspensions.suspensionid AS suspension_id, + suspensions1.id AS id + FROM assignmentsuspensions + JOIN suspensions AS suspensions1 ON suspensions1.id = assignmentsuspensions.suspensionid + LEFT JOIN taxes ON taxes.id = suspensions1.taxid + ) suspensions ON suspensions.assignment_id = a.id + LEFT JOIN ( + SELECT + suspensions2.id AS suspension_id, + suspensions2.customerid, + (CASE WHEN suspensions2.customerid IS NULL THEN 0 ELSE 1 END) AS suspend_all + FROM suspensions AS suspensions2 + ) AS suspensions_all ON suspensions_all.customerid = a.customerid + WHERE suspensions.suspension_id IS NOT NULL OR suspensions_all.suspend_all = 1 + ) AS vasg + GROUP BY vasg.suspension_id; + +CREATE VIEW vassignmentssuspensionsvalues AS + SELECT + suspension_assignment_id AS suspensionvalues_assignment_id, + suspension_id AS suspensionvalues_suspension_id, + assignment_base_price AS suspensionvalues_assignment_base_price, + assignment_tpv_price AS suspensionvalues_assignment_tpv_price, + assignment_price AS suspensionvalues_assignment_price, + suspensiongroup_assignments_count AS suspensionvalues_assignments_count + FROM ( + SELECT + (CASE WHEN suspensions.assignment_id IS NOT NULL + THEN suspensions.assignment_id + ELSE a.id + END) AS suspension_assignment_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.suspension_id + ELSE suspensions_all.suspension_id + END) AS suspension_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.suspensiongroup_assignments_count + ELSE suspensions_all.suspensiongroup_assignments_count + END) AS suspensiongroup_assignments_count, + ROUND(((((100 - a.pdiscount) * (CASE WHEN a.liabilityid IS NULL THEN tvalue ELSE lvalue END)) / 100) - a.vdiscount), 3) AS assignment_base_price, + assignments_tpvariants.tpvprice AS assignment_tpv_price, + (CASE WHEN assignments_tpvariants.tpvprice IS NULL + THEN ROUND(((((100 - a.pdiscount) * (CASE WHEN a.liabilityid IS NULL THEN tvalue ELSE lvalue END)) / 100) - a.vdiscount), 3) + ELSE assignments_tpvariants.tpvprice + END) AS assignment_price + FROM assignments a + LEFT JOIN ( + SELECT + tariffs.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN tariffs.flags & 16 > 0 THEN tariffs.netvalue ELSE tariffs.value END) AS tvalue + FROM tariffs + JOIN taxes ON taxes.id = tariffs.taxid + ) t ON a.tariffid = t.id + LEFT JOIN ( + SELECT + liabilities.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN liabilities.flags & 16 > 0 THEN liabilities.netvalue ELSE liabilities.value END) AS lvalue + FROM liabilities + JOIN taxes ON taxes.id = liabilities.taxid + ) l ON a.liabilityid = l.id + LEFT JOIN ( + SELECT + assignmentsuspensions.assignmentid AS assignment_id, + assignmentsuspensions.suspensionid AS suspension_id, + suspensions1.id AS id, + vasg.suspensiongroup_assignments_count AS suspensiongroup_assignments_count + FROM assignmentsuspensions + JOIN suspensions AS suspensions1 ON suspensions1.id = assignmentsuspensions.suspensionid + JOIN vassignmentssuspensionsgroupcounts vasg ON vasg.suspensiongroup_suspension_id = suspensions1.id + LEFT JOIN taxes ON taxes.id = suspensions1.taxid + ) suspensions ON suspensions.assignment_id = a.id + LEFT JOIN ( + SELECT + suspensions2.id AS suspension_id, + suspensions2.customerid, + (CASE WHEN suspensions2.customerid IS NULL THEN 0 ELSE 1 END) AS suspend_all, + vasg.suspensiongroup_assignments_count AS suspensiongroup_assignments_count + FROM suspensions AS suspensions2 + JOIN vassignmentssuspensionsgroupcounts vasg ON vasg.suspensiongroup_suspension_id = suspensions2.id + ) AS suspensions_all ON suspensions_all.customerid = a.customerid + LEFT JOIN ( + SELECT + tpv.* + FROM assignments a + JOIN ( + SELECT + tariffpricevariants.quantity_threshold AS tpv_quantity_threshold, tariffs.id AS tpv_tariffid, + (CASE WHEN tariffs.flags & 16 > 0 THEN tariffpricevariants.net_price ELSE tariffpricevariants.gross_price END) AS tpvprice + FROM tariffs + JOIN tariffpricevariants ON tariffs.id = tariffpricevariants.tariffid + ) tpv ON a.tariffid = tpv.tpv_tariffid AND tpv.tpv_quantity_threshold <= a.count AND tpv.tpv_tariffid = a.tariffid + ORDER BY tpv.tpv_quantity_threshold DESC LIMIT 1 + ) AS assignments_tpvariants ON a.tariffid = assignments_tpvariants.tpv_tariffid + WHERE suspensions.suspension_id IS NOT NULL OR suspensions_all.suspend_all = 1 + ) AS vasv +; + +CREATE VIEW vassignmentsuspensions AS + SELECT + (CASE WHEN suspensions.assignment_id IS NOT NULL + THEN suspensions.assignment_id + ELSE a.id + END) AS suspension_assignment_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL OR suspensions_all.suspend_all = 1 THEN 1 ELSE 0 END) AS suspended, + (CASE WHEN suspensions.suspension_id IS NULL AND suspensions_all.suspend_all = 1 THEN 1 ELSE 0 END) AS suspension_suspend_all, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.suspension_id + ELSE suspensions_all.suspension_id + END) AS suspension_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.at + ELSE suspensions_all.at + END) AS suspension_at, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.datefrom + ELSE suspensions_all.datefrom + END) AS suspension_datefrom, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.dateto + ELSE suspensions_all.dateto + END) AS suspension_dateto, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.chargemethod + ELSE suspensions_all.chargemethod + END) AS suspension_charge_method, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.calculationmethod + ELSE suspensions_all.calculationmethod + END) AS suspension_calculation_method, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.value + ELSE suspensions_all.value + END) AS suspension_value, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.percentage + ELSE suspensions_all.percentage + END) AS suspension_percentage, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.netflag + ELSE suspensions_all.netflag + END) AS suspension_netflag, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.currency + ELSE suspensions_all.currency + END) AS suspension_currency, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.taxid + ELSE suspensions_all.taxid + END) AS suspension_tax_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.note + ELSE suspensions_all.note + END) AS suspension_note, + (CASE WHEN suspensions.customerid IS NOT NULL + THEN suspensions_all.customerid + ELSE a.customerid + END) AS suspension_customer_id, + (CASE WHEN suspensions.taxrate IS NOT NULL + THEN suspensions.taxrate + ELSE suspensions_all.taxrate + END) AS suspension_taxrate, + (CASE WHEN suspensions.taxlabel IS NOT NULL + THEN suspensions.taxlabel + ELSE suspensions_all.taxlabel + END) AS suspension_taxlabel, + vasv.suspensionvalues_assignment_base_price, + vasv.suspensionvalues_assignment_tpv_price, + vasv.suspensionvalues_assignment_price, + vasv.suspensionvalues_assignments_count, + (CASE + WHEN suspensions.chargemethod = 3 OR suspensions.chargemethod = 2 + OR suspensions_all.chargemethod = 3 OR suspensions_all.chargemethod = 2 + THEN (CASE + WHEN suspensions.calculationmethod = 1 + THEN vasv.suspensionvalues_assignment_price * + (CASE + WHEN suspensions.percentage IS NOT NULL + THEN ROUND(suspensions.percentage / 100, 2) + ELSE + ROUND((SELECT CAST(uiconfig.value AS numeric) + FROM uiconfig + WHERE uiconfig.section = 'suspensions' + AND uiconfig.var = 'default_percentage' + AND uiconfig.configid IS NULL + LIMIT 1) / 100, 2) + END) + WHEN suspensions_all.calculationmethod = 1 + THEN vasv.suspensionvalues_assignment_price * + (CASE + WHEN suspensions_all.percentage IS NOT NULL + THEN ROUND(suspensions_all.percentage / 100, 2) + ELSE + ROUND((SELECT CAST(uiconfig.value AS numeric) + FROM uiconfig + WHERE uiconfig.section = 'suspensions' + AND uiconfig.var = 'default_percentage' + AND uiconfig.configid IS NULL + LIMIT 1) / 100, 2) + END) + WHEN suspensions.calculationmethod = 2 + THEN + (CASE + WHEN suspensions.value IS NOT NULL + THEN ROUND(suspensions.value / vasv.suspensionvalues_assignments_count, 2) + ELSE + ROUND((SELECT CAST(uiconfig.value AS numeric) + FROM uiconfig + WHERE uiconfig.section = 'suspensions' + AND uiconfig.var = 'default_percentage' + AND uiconfig.configid IS NULL + LIMIT 1) / 100, 2) + END) + WHEN suspensions_all.calculationmethod = 2 + THEN + (CASE + WHEN suspensions_all.value IS NOT NULL + THEN ROUND(suspensions_all.value / vasv.suspensionvalues_assignments_count, 2) + ELSE + ROUND((SELECT CAST(uiconfig.value AS numeric) + FROM uiconfig + WHERE uiconfig.section = 'suspensions' + AND uiconfig.var = 'default_percentage' + AND uiconfig.configid IS NULL + LIMIT 1) / 100, 2) + END) + END) + WHEN suspensions.chargemethod = 1 OR suspensions_all.chargemethod = 1 + THEN 0 + END) AS suspension_price + FROM assignments a + LEFT JOIN ( + SELECT + tariffs.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN tariffs.flags & 16 > 0 THEN tariffs.netvalue ELSE tariffs.value END) AS tvalue + FROM tariffs + JOIN taxes ON taxes.id = tariffs.taxid + ) t ON a.tariffid = t.id + LEFT JOIN ( + SELECT + tpv.* + FROM assignments a + JOIN ( + SELECT + tariffpricevariants.quantity_threshold AS tpv_quantity_threshold, + tariffs.id AS tpv_tariffid, + (CASE WHEN tariffs.flags & 16 > 0 THEN tariffpricevariants.net_price ELSE tariffpricevariants.gross_price END) AS tpvprice + FROM tariffs + JOIN tariffpricevariants ON tariffs.id = tariffpricevariants.tariffid + ) tpv ON a.tariffid = tpv.tpv_tariffid AND tpv.tpv_quantity_threshold <= a.count AND tpv.tpv_tariffid = a.tariffid + ORDER BY tpv.tpv_quantity_threshold DESC LIMIT 1 + ) AS assignments_tpvariants ON a.tariffid = assignments_tpvariants.tpv_tariffid + LEFT JOIN ( + SELECT + liabilities.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN liabilities.flags & 16 > 0 THEN liabilities.netvalue ELSE liabilities.value END) AS lvalue + FROM liabilities + JOIN taxes ON taxes.id = liabilities.taxid + ) l ON a.liabilityid = l.id + LEFT JOIN ( + SELECT + assignmentsuspensions.id AS assignmentsuspension_id, + assignmentsuspensions.assignmentid AS assignment_id, + assignmentsuspensions.suspensionid AS suspension_id, + suspensions1.id AS id, + suspensions1.at, suspensions1.datefrom, suspensions1.dateto, suspensions1.chargemethod, suspensions1.calculationmethod, + suspensions1.value, suspensions1.percentage, suspensions1.netflag, suspensions1.currency, suspensions1.note, suspensions1.taxid, + suspensions1.customerid, + taxes.value AS taxrate, taxes.label AS taxlabel + FROM assignmentsuspensions + JOIN suspensions AS suspensions1 ON suspensions1.id = assignmentsuspensions.suspensionid + LEFT JOIN taxes ON taxes.id = suspensions1.taxid + ) suspensions ON suspensions.assignment_id = a.id + LEFT JOIN ( + SELECT suspensions2.id AS suspension_id, suspensions2.at, suspensions2.datefrom, suspensions2.dateto, + suspensions2.chargemethod, suspensions2.calculationmethod, + suspensions2.value, suspensions2.percentage, suspensions2.netflag, suspensions2.currency, suspensions2.note, suspensions2.taxid, + suspensions2.customerid, + (CASE WHEN suspensions2.customerid IS NULL THEN 0 ELSE 1 END) AS suspend_all, + taxes.value AS taxrate, taxes.label AS taxlabel + FROM suspensions AS suspensions2 + LEFT JOIN taxes ON taxes.id = suspensions2.taxid + ) AS suspensions_all ON suspensions_all.customerid = a.customerid + LEFT JOIN vassignmentssuspensionsvalues vasv ON vasv.suspensionvalues_assignment_id = a.id + WHERE suspensions.suspension_id IS NOT NULL OR suspensions_all.suspend_all = 1; + /* --------------------------------------------------- Data records ------------------------------------------------------*/ @@ -3972,7 +4313,11 @@ URL: %url ('receipts', 'content_type', 'text/html', '', 0), ('receipts', 'type', 'html', '', 0), ('receipts', 'attachment_name', '', '', 0), -('payments', 'suspension_percentage', '0', '', 0), +('suspensions', 'default_percentage', '0', '', 0), +('suspensions', 'default_value', '0', '', 0), +('suspensions', 'default_netflag', '0', '', 0), +('suspensions', 'default_charge_method', '2', '[1-none|2-once|3-periodically]', 0), +('suspensions', 'default_calculation_method', '1', '[1-percent|2-value]', 0), ('mail', 'debug_email', '', '', 0), ('mail', 'smtp_host', '127.0.0.1', '', 0), ('mail', 'smtp_port', '25', '', 0), @@ -4416,6 +4761,6 @@ INSERT INTO netdevicemodels (name, alternative_name, netdeviceproducerid) VALUES ('XR7', 'XR7 MINI PCI PCBA', 2), ('XR9', 'MINI PCI 600MW 900MHZ', 2); -INSERT INTO dbinfo (keytype, keyvalue) VALUES ('dbversion', '2024050700'); +INSERT INTO dbinfo (keytype, keyvalue) VALUES ('dbversion', '2024052400'); COMMIT; diff --git a/js/customerassignmenthelper.js b/js/customerassignmenthelper.js index 050c8f2362..a42004dc66 100644 --- a/js/customerassignmenthelper.js +++ b/js/customerassignmenthelper.js @@ -4,6 +4,14 @@ const netPriceElem = $("#netprice"); const grossPriceElem = $("#grossprice"); const invoiceElem = $("#invoice"); +const suspensionNetflagElem = $("#suspension_netflag"); +const suspensionNetValueElem = $("#suspension_net_value"); +const suspensionGrossValueElem = $("#suspension_gross_value"); +const suspensionChargeMethodElem = $("#suspension_charge_method"); +const suspensionCalculationMethodElem = $('#suspension_calculation_method'); +const suspensionPercentageElem = $('#suspension_percentage'); +const suspensionCurrencyElem = $('#currency'); + function CustomerAssignmentHelper(options) { var helper = this; @@ -624,12 +632,19 @@ function tariffSelectionHandler() { } $('#a_promotions,#a_align_periods').toggle(val == -2); + $('#a_assignments_suspensions, #a_suspension_charge_method, #a_suspension_type,' + + '#a_suspension_calculation_method, #a_suspension_value, #a_suspension_percentage,' + + '#a_currency') + .toggle(val == -3); + + $('[data-lmsbox-content="customerassignmentsuspensionspanel"]').off('click'); + $('#assignment-period').find('option').prop('disabled', false); $('#last-settlement').prop('disabled', $('#align-periods').prop('checked') && val == -2) .closest('label').toggleClass('lms-ui-disabled', $('#align-periods').prop('checked') && val == -2); - $('#netflag, #tax, #taxcategory, #splitpayment').prop('disabled', false); - $('#a_tax, #a_taxcategory, #a_splitpayment').removeClass('lms-ui-disabled'); + $('#netflag, #tax, #taxcategory, #splitpayment, #currency').prop('disabled', false); + $('#a_tax, #a_taxcategory, #a_splitpayment, #a_currency').removeClass('lms-ui-disabled'); if (val == '') { $('#a_tax,#a_type,#a_price,#a_currency,#a_splitpayment,#a_taxcategory,#a_productid,#a_name').show(); @@ -705,10 +720,11 @@ function tariffSelectionHandler() { $('#tax').val(tariffTaxId).prop('disabled', true); - if (val == -1) { - $('#tax').val(tariffDefaultTaxId).prop('disabled', false); + if (val == -3){ + $('#a_type,#a_price,#a_splitpayment,#a_taxcategory,#a_productid,#a_name,#a_attribute').hide(); + $('#a_currency').show(); - $('#a_tax,#a_type,#a_price,#a_currency,#a_splitpayment,#a_taxcategory,#a_productid,#a_name,#a_attribute').hide(); + suspensionFieldsHandler(suspensionChargeMethodElem, suspensionCalculationMethodElem); } else if (val == -2){ $('#tax').val(tariffDefaultTaxId).prop('disabled', false); @@ -721,7 +737,7 @@ function tariffSelectionHandler() { } } - if (val == -1) { + if (val == -3) { $('#a_numberplan,#a_paytime,#a_paytype,#a_address,#a_day,#a_options,#a_existingassignments').hide(); $('#a_properties').show(); } else { @@ -739,7 +755,7 @@ function tariffSelectionHandler() { $('#a_netdevnodes').hide(); } else { $('#a_phones').hide(); - if (val == -1 || val == -2) { + if (val == -2 || val == -3) { $('#a_nodes,#a_netdevnodes,#a_checkall').hide(); } else { $('#a_nodes,#a_netdevnodes,#a_checkall').show(); @@ -747,7 +763,7 @@ function tariffSelectionHandler() { } if (!assignment_settings.hideFinances) { - if (val <= -1) { + if (val <= -2) { $('.a_discount').hide(); } else { $('.a_discount').show(); @@ -771,21 +787,21 @@ function tariffSelectionHandler() { $('#tariff-select').change(tariffSelectionHandler); -function claculatePriceFromGross() { - let grossPriceElemVal = grossPriceElem.val(); +function claculateNetFromGross(netPriceElem, grossPriceElem, precision = 3, grossPriceVal = null) { + let grossPriceElemVal = (grossPriceVal == null ? grossPriceElem.val() : grossPriceVal); grossPriceElemVal = parseFloat(grossPriceElemVal.replace(/[\,]+/, '.')); if (!isNaN(grossPriceElemVal)) { let selectedTaxId = $("#tax").find('option:selected').val(); let tax = $('#tax' + selectedTaxId).val(); - let grossPrice = financeDecimals.round(grossPriceElemVal, 3); - let netPrice = financeDecimals.round(grossPrice / (tax / 100 + 1), 3); + let grossPrice = financeDecimals.round(grossPriceElemVal, precision); + let netPrice = financeDecimals.round(grossPrice / (tax / 100 + 1), precision); - netPrice = netPrice.toFixed(3).replace(/[\.]+/, ','); + netPrice = netPrice.toFixed(precision).replace(/[\.]+/, ','); netPriceElem.val(netPrice); - grossPrice = grossPrice.toFixed(3).replace(/[\.]+/, ','); + grossPrice = grossPrice.toFixed(precision).replace(/[\.]+/, ','); grossPriceElem.val(grossPrice); } else { netPriceElem.val(''); @@ -793,21 +809,21 @@ function claculatePriceFromGross() { } } -function claculatePriceFromNet() { - let netPriceElemVal = netPriceElem.val(); +function claculateGrossFromNet(netPriceElem, grossPriceElem, precision = 3, netPriceVal = null) { + let netPriceElemVal = (netPriceVal == null ? netPriceElem.val() : netPriceVal); netPriceElemVal = parseFloat(netPriceElemVal.replace(/[\,]+/, '.')) if (!isNaN(netPriceElemVal)) { let selectedTaxId = $("#tax").find('option:selected').val(); let tax = $('#tax' + selectedTaxId).val(); - let netPrice = financeDecimals.round(netPriceElemVal, 3); - let grossPrice = financeDecimals.round(netPrice * (tax / 100 + 1), 3); + let netPrice = financeDecimals.round(netPriceElemVal, precision); + let grossPrice = financeDecimals.round(netPrice * (tax / 100 + 1), precision); - grossPrice = grossPrice.toFixed(3).replace(/[\.]+/, ','); + grossPrice = grossPrice.toFixed(precision).replace(/[\.]+/, ','); grossPriceElem.val(grossPrice); - netPrice = netPrice.toFixed(3).replace(/[\.]+/, ','); + netPrice = netPrice.toFixed(precision).replace(/[\.]+/, ','); netPriceElem.val(netPrice); } else { grossPriceElem.val(''); @@ -815,11 +831,154 @@ function claculatePriceFromNet() { } } +function suspendAllFieldsHandler(suspenAllElem) { + let suspensionsElem = $('#customerassignmentssuspensions'); + let suspensions = suspensionsElem.find('.lms-ui-tab-table-row').not( ".header,.footer"); + + if (suspenAllElem.is(':checked')) { + suspensionsElem.addClass('lms-ui-disabled'); + suspensions.each(function (index) { + let rowData = $(this).data(); + if (rowData.class !== 'blend') { + $(this).removeClass('suspended alertblend lms-ui-assignment-not-commited'); + $(this).addClass('blend'); + } + $(this).find('input').prop('disabled', true); + }); + $('#check-all-assignments-suspend').prop('disabled', true); + } else { + suspensionsElem.removeClass('lms-ui-disabled'); + suspensions.each(function (index) { + $(this).removeClass('blend'); + $(this).find('input').prop('disabled', false); + let rowData = $(this).data(); + let rowCheckElem = $(this).find('input'); + if (rowData.suspended == 1) { + $(this).removeClass('suspended alertblend lms-ui-assignment-not-commited'); + $(this).addClass('blend'); + rowCheckElem.prop('disabled', !rowCheckElem.is(':checked')); + } else if (rowData.class) { + $(this).addClass(rowData.class); + rowCheckElem.prop('disabled', rowData.class == 'blend' || rowData.class == 'suspended' || rowData.class == 'lms-ui-assignment-not-commited'); + } + }); + $('#check-all-assignments-suspend').prop('disabled', false); + } +} +$('#suspend_all').on('change', function () { + suspendAllFieldsHandler($(this)); +}); + +function suspensionFieldsHandler(suspensionChargeMethodElem, suspensionCalculationMethodElem) { + suspendAllFieldsHandler($('#suspend_all')); + + if (suspensionChargeMethodElem.val()) { + suspensionChargeMethod = suspensionChargeMethodElem.val(); + } else if (suspensionChargeMethod == '') { + suspensionChargeMethod = suspensionDefaultChargeMethod; + } + let chargeMethod = suspensionChargeMethod; + + if (suspensionCalculationMethodElem.val()) { + suspensionCalculationMethod = suspensionCalculationMethodElem.val(); + } else if (suspensionCalculationMethod == '') { + suspensionCalculationMethod = suspensionDefaultCalculationMethod; + } + let calculationMethod = suspensionCalculationMethod; + + $('#a_suspension_calculation_method, #a_suspension_percentage, #a_suspension_value, #a_currency, #a_tax').addClass('lms-ui-disabled'); + $('#suspension_calculation_method, #suspension_percentage, #suspension_gross_value, #suspension_net_value, #suspension_netflag, #currency, #tax').prop('disabled', true); + $('#suspension_percentage, #suspension_gross_value, #suspension_net_value').val('').attr('placeholder', ''); + + if (chargeMethod == 1) { + $('#suspension_calculation_method').val(''); + } else { + $('#a_suspension_calculation_method').removeClass('lms-ui-disabled'); + $('#suspension_calculation_method').prop('disabled', false); + + + suspensionCalculationMethodElem.val(calculationMethod); + + if (calculationMethod == 1) { + $('#a_suspension_value, #a_currency, #a_tax').addClass('lms-ui-disabled'); + $('#suspension_gross_value, #suspension_net_value, #suspension_netflag, #currency, #tax').prop('disabled', true); + $('#suspension_gross_value, #suspension_net_value').val('').attr('placeholder', ''); + $('#tax').prop('disabled', true); + $('#a_suspension_percentage').removeClass('lms-ui-disabled'); + suspensionPercentageElem.prop('disabled', false); + + $('#tax').val('').prop('disabled', true); + suspensionCurrencyElem.val(''); + + if (suspensionPercentageElem.val() == '') { + suspensionPercentageElem.attr('placeholder', suspensionDefaultPlaceholder.concat(" ", suspensionDefaultPercentage, " %")); + } + } else if (calculationMethod == 2) { + $('#a_suspension_percentage').addClass('lms-ui-disabled'); + suspensionPercentageElem.prop('disabled', true).val('').attr('placeholder', ''); + $('#a_suspension_value, #a_currency, #a_tax').removeClass('lms-ui-disabled'); + $('#suspension_gross_value, #suspension_net_value, #suspension_netflag, #currency, #tax').prop('disabled', false); + $('#tax').prop('disabled', false); + + if (!$('#tax').val()) { + $('#tax').val(tariffDefaultTaxId); + } + + if (!suspensionCurrencyElem.val()) { + suspensionCurrencyElem.val(suspensionDefaultCurrency); + } + + if (suspensionNetflag == '') { + suspensionNetflag = suspensionDefaultNetFlag; + } + + if (suspensionNetflag && parseInt(suspensionNetflag) != 0) { + suspensionNetflagElem.prop({checked: true, disabled: false}); + suspensionGrossValueElem.prop('disabled', true); + suspensionNetValueElem.prop('disabled', false); + + if (suspensionNetValue != '') { + suspensionNetValueElem.val(suspensionNetValue); + claculateGrossFromNet(suspensionNetValueElem, suspensionGrossValueElem, 2); + } else { + suspensionNetValueElem.val(suspensionDefaultValue); + claculateGrossFromNet(suspensionNetValueElem, suspensionGrossValueElem, 2, suspensionDefaultValue); + suspensionNetValueElem.val('').attr('placeholder', suspensionDefaultPlaceholder.concat(" ", suspensionDefaultValue)); + suspensionGrossValueElem.attr('placeholder', suspensionDefaultPlaceholder.concat(" ", suspensionGrossValueElem.val())); + suspensionGrossValueElem.val(''); + } + } else { + suspensionNetflagElem.prop({checked: false, disabled: false}); + suspensionGrossValueElem.prop('disabled', false); + suspensionNetValueElem.prop('disabled', true); + + if (suspensionGrossValue != '') { + suspensionGrossValueElem.val(suspensionGrossValue); + claculateNetFromGross(suspensionNetValueElem, suspensionGrossValueElem, 2); + } else { + suspensionGrossValueElem.val(suspensionDefaultValue); + claculateNetFromGross(suspensionNetValueElem, suspensionGrossValueElem, 2, suspensionDefaultValue); + suspensionGrossValueElem.val('').attr('placeholder', suspensionDefaultPlaceholder.concat(" ", suspensionDefaultValue)); + suspensionNetValueElem.attr('placeholder', suspensionDefaultPlaceholder.concat(" ", suspensionNetValueElem.val())); + suspensionNetValueElem.val(''); + } + } + } + } +} +suspensionChargeMethodElem.on('change', function () { + suspensionFieldsHandler(suspensionChargeMethodElem, suspensionCalculationMethodElem); +}); + +suspensionCalculationMethodElem.on('change', function () { + suspensionFieldsHandler(suspensionChargeMethodElem, suspensionCalculationMethodElem); +}); + $('#netflag').on('change', function () { if (netFlagElem.is(':checked')) { grossPriceElem.prop('disabled', true); netPriceElem.prop('disabled', false); - claculatePriceFromNet(); + claculateGrossFromNet(netPriceElem, grossPriceElem); invoiceElem.prop('required', true); if (invoiceElem.val() === assignment_settings.DOC_DNOTE) { invoiceElem.val(''); @@ -828,30 +987,84 @@ $('#netflag').on('change', function () { } else { grossPriceElem.prop('disabled', false); netPriceElem.prop('disabled', true); - claculatePriceFromGross(); + claculateNetFromGross(netPriceElem, grossPriceElem); invoiceElem.prop('required', false).removeClass('lms-ui-error'); invoiceElem.find('option[value="' + assignment_settings.DOC_DNOTE + '"]').prop('disabled', false); } }); +$('#suspension_netflag').on('change', function () { + if (suspensionNetflagElem.is(':checked')) { + if (suspensionNetValueElem.val() != '') { + suspensionNetValueElem.val(suspensionNetValue); + claculateGrossFromNet(suspensionNetValueElem, suspensionGrossValueElem, 2); + } else { + suspensionNetValueElem.val(suspensionDefaultValue); + claculateGrossFromNet(suspensionNetValueElem, suspensionGrossValueElem, 2, suspensionDefaultValue); + suspensionNetValueElem.val('').attr('placeholder', suspensionDefaultPlaceholder.concat(" ", suspensionDefaultValue)); + suspensionGrossValueElem.attr('placeholder', suspensionDefaultPlaceholder.concat(" ", suspensionGrossValueElem.val())); + suspensionGrossValueElem.val(''); + } + } else { + if (suspensionGrossValueElem.val() != '') { + suspensionGrossValueElem.val(suspensionGrossValue); + claculateNetFromGross(suspensionNetValueElem, suspensionGrossValueElem, 2); + } else { + suspensionGrossValueElem.val(suspensionDefaultValue); + claculateNetFromGross(suspensionNetValueElem, suspensionGrossValueElem, 2, suspensionDefaultValue); + suspensionGrossValueElem.val('').attr('placeholder', suspensionDefaultPlaceholder.concat(" ", suspensionDefaultValue)); + suspensionNetValueElem.attr('placeholder', suspensionDefaultPlaceholder.concat(" ", suspensionNetValueElem.val())); + suspensionNetValueElem.val(''); + } + } +}); + $("#tax").on('change', function () { if (netFlagElem.is(':checked')) { - claculatePriceFromNet(); + claculateGrossFromNet(netPriceElem, grossPriceElem); + claculateGrossFromNet(suspensionNetValueElem, suspensionGrossValueElem, 2); } else { - claculatePriceFromGross(); + claculateNetFromGross(netPriceElem, grossPriceElem); + claculateNetFromGross(suspensionNetValueElem, suspensionGrossValueElem, 2); } }); -$("#grossprice").change(function () { - claculatePriceFromGross(); +$("#grossprice").on('change', function () { + claculateNetFromGross(netPriceElem, grossPriceElem); $("#target_price").change(); }); -$("#netprice").change(function () { - claculatePriceFromNet(); +$("#netprice").on('change', function () { + claculateGrossFromNet(netPriceElem, grossPriceElem); $("#target_price").change(); }); +$("#suspension_gross_value").on('change', function () { + if ($(this).val() != '') { + suspensionNetValueElem.val(suspensionNetValue); + claculateGrossFromNet(suspensionNetValueElem, suspensionGrossValueElem, 2); + } else { + suspensionNetValueElem.val(suspensionDefaultValue); + claculateGrossFromNet(suspensionNetValueElem, suspensionGrossValueElem, 2, suspensionDefaultValue); + suspensionNetValueElem.val('').attr('placeholder', suspensionDefaultPlaceholder.concat(" ", suspensionDefaultValue)); + suspensionGrossValueElem.attr('placeholder', suspensionDefaultPlaceholder.concat(" ", suspensionGrossValueElem.val())); + suspensionGrossValueElem.val(''); + } +}); + +$("#suspension_net_value").on('change', function () { + if ($(this).val() != '') { + suspensionGrossValueElem.val(suspensionGrossValue); + claculateGrossFromNet(suspensionNetValueElem, suspensionGrossValueElem, 2); + } else { + suspensionGrossValueElem.val(suspensionDefaultValue); + claculateNetFromGross(suspensionNetValueElem, suspensionGrossValueElem, 2, suspensionDefaultValue); + suspensionGrossValueElem.val('').attr('placeholder', suspensionDefaultPlaceholder.concat(" ", suspensionDefaultValue)); + suspensionNetValueElem.attr('placeholder', suspensionDefaultPlaceholder.concat(" ", suspensionNetValueElem.val())); + suspensionNetValueElem.val(''); + } +}); + $(".format-3f").on('change', function () { if ($(this).val()) { let roundedValue = financeRound($(this).val().replaceAll(' ', ''), 3); diff --git a/lib/LMS.class.php b/lib/LMS.class.php index 9e908a87d9..e7cb565e69 100644 --- a/lib/LMS.class.php +++ b/lib/LMS.class.php @@ -1461,10 +1461,28 @@ public function GetCustomerAssignmentValue($id) return $manager->GetCustomerAssignmentValue($id); } - public function GetCustomerAssignments($id, $show_expired = false, $show_approved = true) + public function getCustomerAssignments($customer_id, $params = array()) { $manager = $this->getFinanceManager(); - return $manager->GetCustomerAssignments($id, $show_expired, $show_approved); + return $manager->getCustomerAssignments($customer_id, $params); + } + + public function getAssignments($params = array()) + { + $manager = $this->getFinanceManager(); + return $manager->getAssignments($params); + } + + public function getAssignment($assignment_id) + { + $manager = $this->getFinanceManager(); + return $manager->getAssignment($assignment_id); + } + + public function getSuspensions($params = array()) + { + $manager = $this->getFinanceManager(); + return $manager->getSuspensions($params); } public function GetCustomerServiceSummary($id) @@ -1491,6 +1509,12 @@ public function ValidateAssignment($data) return $manager->ValidateAssignment($data); } + public function ValidateSuspension($params = array()) + { + $manager = $this->getFinanceManager(); + return $manager->ValidateSuspension($params); + } + public function CheckSchemaModifiedValues(&$data) { $manager = $this->getFinanceManager(); @@ -1503,10 +1527,45 @@ public function UpdateExistingAssignments($data) return $manager->UpdateExistingAssignments($data); } - public function SuspendAssignment($id, $suspend = true) + public function addSuspension($params = array()) + { + $manager = $this->getFinanceManager(); + return $manager->addSuspension($params); + } + + public function updateSuspension($params = array()) + { + $manager = $this->getFinanceManager(); + return $manager->updateSuspension($params); + } + + public function addAssignmentSuspension($params = array()) + { + $manager = $this->getFinanceManager(); + return $manager->addAssignmentSuspension($params); + } + + public function deleteSuspension($suspension_id) + { + $manager = $this->getFinanceManager(); + return $manager->deleteSuspension($suspension_id); + } + + public function deleteAssignmentSuspension($params = array()) + { + $manager = $this->getFinanceManager(); + return $manager->deleteAssignmentSuspension($params); + } + +// public function SuspendAssignment($id, $suspend = true, $suspensionid = null) +// { +// $manager = $this->getFinanceManager(); +// return $manager->SuspendAssignment($id, $suspend, $suspensionid); +// } + public function suspendAssignment($assignment_id) { $manager = $this->getFinanceManager(); - return $manager->SuspendAssignment($id, $suspend); + return $manager->suspendAssignment($assignment_id); } public function toggleAssignmentSuspension($id) diff --git a/lib/LMSDB_common.class.php b/lib/LMSDB_common.class.php index edf816fe65..46b8356ac5 100644 --- a/lib/LMSDB_common.class.php +++ b/lib/LMSDB_common.class.php @@ -25,7 +25,7 @@ */ // here should be always the newest version of database! -define('DBVERSION', '2024050700'); +define('DBVERSION', '2024052400'); /** * diff --git a/lib/LMSManagers/LMSCustomerManager.php b/lib/LMSManagers/LMSCustomerManager.php index e116b72140..e59f2a789b 100644 --- a/lib/LMSManagers/LMSCustomerManager.php +++ b/lib/LMSManagers/LMSCustomerManager.php @@ -983,15 +983,20 @@ public function getCustomerList($params = array()) AND (tariffid IS NOT NULL OR liabilityid IS NOT NULL))'; break; case 56: - $state_conditions[] = 'EXISTS (SELECT 1 FROM assignments a - WHERE a.customerid = c.id AND ( - (tariffid IS NULL AND liabilityid IS NULL - AND datefrom <= ?NOW? - AND (dateto >= ?NOW? OR dateto = 0)) - OR (datefrom <= ?NOW? - AND (dateto >= ?NOW? OR dateto = 0) - AND suspended = 1 AND commited = 1) - ))'; + $state_conditions[] = 'EXISTS (SELECT 1 + FROM assignments a + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) + WHERE a.customerid = c.id + AND ( + (vas.suspension_suspend_all = 1) + OR (vas.suspended IS NOT NULL + AND vas.suspension_suspend_all = 0 + AND commited = 1) + ) + )'; break; case 57: $state_conditions[] = 'b.balance < -t.value'; @@ -1141,35 +1146,78 @@ public function getCustomerList($params = array()) FROM assignments a LEFT JOIN tariffs t ON t.id = a.tariffid LEFT JOIN liabilities l ON (l.id = a.liabilityid AND a.period <> 0) - WHERE a.suspended = 0 + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.dateto = 0 + WHERE vas.suspended IS NULL AND a.commited = 1 AND a.dateto = 0 AND (t.type = ' . intval($search['tarifftype']) . ' OR l.type = ' . intval($search['tarifftype']) . ')'; } else { - $assignment = 'SELECT DISTINCT(a.customerid) FROM assignments a WHERE a.suspended = 0 AND a.commited = 1 AND a.dateto = 0'; + $assignment = 'SELECT DISTINCT(a.customerid) + FROM assignments a + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.dateto = 0 + WHERE vas.suspended IS NULL + AND a.commited = 1 + AND a.dateto = 0'; } break; case -2: - $assignment = 'SELECT DISTINCT(a.customerid) FROM assignments a WHERE a.suspended = 0 AND a.commited = 1 ' - . 'AND (a.dateto = 0 OR a.dateto > ?NOW?) AND ((a.at + 86400) > ?NOW? OR a.period <> 0)'; + $assignment = 'SELECT DISTINCT(a.customerid) + FROM assignments a + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND (a.dateto = 0 OR a.dateto > ?NOW?) AND ((a.at + 86400) > ?NOW? OR a.period <> 0) + WHERE vas.suspended IS NULL AND a.commited = 1 + AND (a.dateto = 0 OR a.dateto > ?NOW?) AND ((a.at + 86400) > ?NOW? OR a.period <> 0)'; break; case -3: - $assignment = 'SELECT DISTINCT(a.customerid) FROM assignments a WHERE a.invoice = ' . DOC_INVOICE - . ' AND a.suspended = 0 AND a.commited = 1 + $assignment = 'SELECT DISTINCT(a.customerid) + FROM assignments a + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND (a.dateto = 0 OR a.dateto > ?NOW?) AND (a.period <> ' . DISPOSABLE . ' OR (a.at + 86400) > ?NOW?) + WHERE a.invoice = ' . DOC_INVOICE + . ' AND vas.suspended IS NULL + AND a.commited = 1 AND (a.dateto = 0 OR a.dateto > ?NOW?) AND (a.period <> ' . DISPOSABLE . ' OR (a.at + 86400) > ?NOW?)'; break; case -4: - $assignment = 'SELECT DISTINCT(a.customerid) FROM assignments a WHERE a.suspended <> 0'; + $assignment = 'SELECT DISTINCT(a.customerid) + FROM assignments a + JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + WHERE vas.suspended IS NOT NULL AND vas.suspension_suspend_all = 0'; break; case -5: - $assignment = 'SELECT DISTINCT(a.customerid) FROM assignments a WHERE a.invoice = ' . DOC_INVOICE_PRO - . ' AND a.suspended = 0 AND a.commited = 1 + $assignment = 'SELECT DISTINCT(a.customerid) + FROM assignments a + JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND (a.dateto = 0 OR a.dateto > ?NOW?) AND ((a.at + 86400) > ?NOW? or a.period != 0) + WHERE a.invoice = ' . DOC_INVOICE_PRO + . ' AND vas.suspended IS NOT NULL + AND a.commited = 1 AND (a.dateto = 0 OR a.dateto > ?NOW?) AND ((a.at + 86400) > ?NOW? or a.period != 0)'; break; case -6: - $assignment = 'SELECT DISTINCT(a.customerid) FROM assignments a + $assignment = 'SELECT DISTINCT(a.customerid) + FROM assignments a LEFT JOIN documents d ON d.id = a.docid - WHERE a.suspended = 0 AND a.commited = 1 + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND (a.dateto = 0 OR a.dateto > ?NOW?) AND a.period <> 0 + WHERE vas.suspended IS NULL + AND a.commited = 1 AND (a.dateto = 0 OR a.dateto > ?NOW?) AND a.period <> 0 GROUP BY a.customerid, d.id HAVING MIN(a.datefrom) > ?NOW?'; @@ -1177,7 +1225,12 @@ public function getCustomerList($params = array()) case -7: $assignment = 'SELECT DISTINCT(a.customerid) FROM assignments a - WHERE a.suspended = 0 AND a.commited = 1 + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND (a.dateto = 0 OR a.dateto > ?NOW?) AND ((a.at + 86400) > ?NOW? OR a.period <> 0) + WHERE vas.suspended IS NULL + AND a.commited = 1 AND (a.dateto = 0 OR a.dateto > ?NOW?) AND ((a.at + 86400) > ?NOW? OR a.period <> 0) AND NOT EXISTS (SELECT 1 FROM nodeassignments WHERE assignmentid = a.id)'; break; @@ -1185,7 +1238,12 @@ public function getCustomerList($params = array()) $assignment = 'SELECT DISTINCT(a.customerid) FROM assignments a LEFT JOIN documents d ON d.id = a.docid - WHERE a.suspended = 0 AND a.commited = 1 + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND (a.dateto = 0 OR a.dateto > ?NOW?) AND a.period <> 0 + WHERE vas.suspended IS NULL + AND a.commited = 1 AND (a.dateto = 0 OR a.dateto > ?NOW?) AND a.period <> 0 AND NOT EXISTS (SELECT 1 FROM nodeassignments WHERE assignmentid = a.id) GROUP BY a.customerid, d.id @@ -1194,12 +1252,24 @@ public function getCustomerList($params = array()) case -9: $assignment = 'SELECT DISTINCT(a.customerid) FROM assignments a - WHERE a.commited = 1 AND tariffid IS NULL AND liabilityid IS NULL - AND datefrom <= ?NOW? - AND (dateto >= ?NOW? OR dateto = 0)'; + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) + WHERE a.commited = 1 + AND vas.suspension_suspend_all = 1 + AND datefrom <= ?NOW? AND (dateto >= ?NOW? OR dateto = 0)'; break; case -10: - $assignment = 'SELECT DISTINCT(a.customerid) FROM assignments a WHERE a.suspended = 0 AND a.commited = 1 AND a.datefrom = 0'; + $assignment = 'SELECT DISTINCT(a.customerid) + FROM assignments a + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom = 0) + WHERE vas.suspended IS NULL + AND a.commited = 1 + AND a.datefrom = 0'; break; case -11: $assignment = 'SELECT DISTINCT(a.customerid) FROM assignments a WHERE a.commited = 1'; @@ -1208,15 +1278,29 @@ public function getCustomerList($params = array()) $assignment = 'SELECT DISTINCT(a.customerid) FROM assignments a WHERE a.commited = 0'; break; case -13: - $assignment = 'SELECT DISTINCT(a.customerid) FROM assignments a WHERE a.invoice = 0 - AND a.suspended = 0 AND a.commited = 1 - AND (a.dateto = 0 OR a.dateto > ?NOW?) AND (a.period <> ' . DISPOSABLE . ' OR (a.at + 86400) > ?NOW?)'; + $assignment = 'SELECT DISTINCT(a.customerid) + FROM assignments a + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND (a.dateto = 0 OR a.dateto > ?NOW?) AND (a.period <> ' . DISPOSABLE . ' OR (a.at + 86400) > ?NOW?) + WHERE a.invoice = 0 + AND vas.suspended IS NULL + AND a.commited = 1 + AND (a.dateto = 0 OR a.dateto > ?NOW?) AND (a.period <> ' . DISPOSABLE . ' OR (a.at + 86400) > ?NOW?)'; break; default: if ($as > 0) { - $assignment = 'SELECT DISTINCT(a.customerid) FROM assignments a WHERE - a.suspended = 0 AND a.commited = 1 AND a.dateto > ' . time() . ' AND a.dateto <= ' . (time() + ($as * 86400)) - . ' AND NOT EXISTS (SELECT 1 FROM assignments aa WHERE aa.customerid = a.customerid AND aa.datefrom > a.dateto LIMIT 1)'; + $assignment = 'SELECT DISTINCT(a.customerid) + FROM assignments a + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.dateto > ' . time() . ' AND a.dateto <= ' . (time() + ($as * 86400)). ' + WHERE vas.suspended IS NULL + AND a.commited = 1 + AND a.dateto > ' . time() . ' AND a.dateto <= ' . (time() + ($as * 86400)). ' + AND NOT EXISTS (SELECT 1 FROM assignments aa WHERE aa.customerid = a.customerid AND aa.datefrom > a.dateto LIMIT 1)'; } else { $assignment = null; } @@ -1544,8 +1628,6 @@ public function getCustomerList($params = array()) $sqlsarg = implode(' ' . $sqlskey . ' ', $searchargs); } - $suspension_percentage = f_round(ConfigHelper::getConfig('payments.suspension_percentage', ConfigHelper::getConfig('finances.suspension_percentage', 0))); - $sql = ''; if ($count) { @@ -1616,50 +1698,50 @@ public function getCustomerList($params = array()) SELECT a.customerid, SUM( - ( - ( - (100 - a.pdiscount) - * (CASE WHEN ca.netflag = 1 - THEN ca.netvalue - ELSE ca.value - END) - / 100 - ) - a.vdiscount - ) - * a.count - * (CASE WHEN ca.netflag = 1 - THEN (100 + ca.taxrate) / 100 - ELSE 1 - END) - * (CASE WHEN a.suspended = 0 - THEN 1 - ELSE ' . $suspension_percentage . ' / 100 + (CASE + WHEN vas.suspended IS NULL + THEN ( + ( + (100 - a.pdiscount) + * (CASE WHEN ca.netflag = 1 + THEN ca.netvalue + ELSE ca.value + END) + / 100 + ) - a.vdiscount + ) + * (CASE WHEN ca.netflag = 1 + THEN (100 + ca.taxrate) / 100 + ELSE 1 + END) + ELSE vas.suspension_price END) + * a.count * ( - CASE WHEN a.period = ' . DISPOSABLE . ' THEN 0 - ELSE ( - CASE WHEN a.period <> ' . DISPOSABLE . ' AND ca.period > 0 AND ca.period <> a.period - THEN ( - CASE ca.period - WHEN ' . YEARLY . ' THEN 1/12.0 - WHEN ' . HALFYEARLY . ' THEN 1/6.0 - WHEN ' . QUARTERLY . ' THEN 1/3.0 - ELSE 1 - END - ) ELSE ( - CASE a.period - WHEN ' . YEARLY . ' THEN 1/12.0 - WHEN ' . HALFYEARLY . ' THEN 1/6.0 - WHEN ' . QUARTERLY . ' THEN 1/3.0 - WHEN ' . WEEKLY . ' THEN 4.0 - WHEN ' . DAILY . ' THEN 30.0 - ELSE 1 - END - ) + CASE WHEN a.period = ' . DISPOSABLE . ' THEN 0 + ELSE ( + CASE WHEN a.period <> ' . DISPOSABLE . ' AND ca.period > 0 AND ca.period <> a.period + THEN ( + CASE ca.period + WHEN ' . YEARLY . ' THEN 1/12.0 + WHEN ' . HALFYEARLY . ' THEN 1/6.0 + WHEN ' . QUARTERLY . ' THEN 1/3.0 + ELSE 1 + END + ) ELSE ( + CASE a.period + WHEN ' . YEARLY . ' THEN 1/12.0 + WHEN ' . HALFYEARLY . ' THEN 1/6.0 + WHEN ' . QUARTERLY . ' THEN 1/3.0 + WHEN ' . WEEKLY . ' THEN 4.0 + WHEN ' . DAILY . ' THEN 30.0 + ELSE 1 + END + ) + END + ) END - ) - END - ) + ) ) AS value FROM assignments a JOIN ( @@ -1693,6 +1775,10 @@ public function getCustomerList($params = array()) AND a2.datefrom <= ?NOW? AND (a2.dateto > ?NOW? OR a2.dateto = 0) ) ca ON ca.id = a.id + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) GROUP BY a.customerid ) t ON (t.customerid = c.id) LEFT JOIN (SELECT ownerid, diff --git a/lib/LMSManagers/LMSFinanceManager.php b/lib/LMSManagers/LMSFinanceManager.php index 097ba0af5d..eec1f0ee98 100644 --- a/lib/LMSManagers/LMSFinanceManager.php +++ b/lib/LMSManagers/LMSFinanceManager.php @@ -48,22 +48,28 @@ public function GetPromotionNameByID($id) public function GetCustomerTariffsValue($id) { - return $this->db->GetAllByKey('SELECT SUM(tariffs.value * a.count) AS value, tariffs.currency - FROM assignments a, tariffs - WHERE tariffid = tariffs.id AND customerid = ? AND suspended = 0 AND commited = 1 - AND a.datefrom <= ?NOW? AND (a.dateto > ?NOW? OR a.dateto = 0) - GROUP BY tariffs.currency', 'currency', array($id)); + return $this->db->GetAllByKey( + 'SELECT SUM(tariffs.value * a.count) AS value, tariffs.currency + FROM assignments a, tariffs + WHERE tariffid = tariffs.id AND customerid = ? AND suspended = 0 AND commited = 1 + AND a.datefrom <= ?NOW? AND (a.dateto > ?NOW? OR a.dateto = 0) + GROUP BY tariffs.currency', + 'currency', + array($id) + ); } public function GetCustomerAssignmentValue($id) { - $suspension_percentage = f_round(ConfigHelper::getConfig('payments.suspension_percentage', ConfigHelper::getConfig('finances.suspension_percentage', 0))); - - return $this->db->GetAllByKey('SELECT SUM(sum), currency FROM - (SELECT SUM((CASE a.suspended - WHEN 0 THEN (((100 - a.pdiscount) * (CASE WHEN t.value IS null THEN l.value ELSE t.value END) / 100) - a.vdiscount) - ELSE ((((100 - a.pdiscount) * (CASE WHEN t.value IS null THEN l.value ELSE t.value END) / 100) - a.vdiscount) * ' . $suspension_percentage . ' / 100) END) - * (CASE t.period + return $this->db->GetAllByKey( + 'SELECT SUM(ca.sum), ca.acurrency AS scurrency FROM + (SELECT SUM(ROUND( + (CASE + WHEN vas.suspended IS NULL + THEN ROUND(((((100 - a.pdiscount) * (CASE WHEN a.liabilityid IS NULL THEN t.value ELSE l.value END)) / 100) - a.vdiscount), 3) + ELSE vas.suspension_price + END) * + (CASE t.period WHEN ' . MONTHLY . ' THEN 1 WHEN ' . YEARLY . ' THEN 1/12.0 WHEN ' . HALFYEARLY . ' THEN 1/6.0 @@ -74,16 +80,26 @@ public function GetCustomerAssignmentValue($id) WHEN ' . HALFYEARLY . ' THEN 1/6.0 WHEN ' . QUARTERLY . ' THEN 1/3.0 ELSE 0 END) - END) * a.count) AS sum, - (CASE WHEN t.currency IS NULL THEN l.currency ELSE t.currency END) AS currency - FROM assignments a + END) * + a.count, 2)) AS sum, + (CASE WHEN a.liabilityid IS NULL THEN t.currency ELSE l.currency END) AS acurrency + FROM assignments a LEFT JOIN tariffs t ON t.id = a.tariffid LEFT JOIN liabilities l ON l.id = a.liabilityid - WHERE customerid = ? AND suspended = 0 AND commited = 1 AND a.period <> ' . DISPOSABLE . ' - AND a.datefrom <= ?NOW? AND (a.dateto > ?NOW? OR a.dateto = 0) - GROUP BY t.currency, l.currency + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) + WHERE a.customerid = ? + AND a.datefrom <= ?NOW? AND (a.dateto > ?NOW? OR a.dateto = 0) + GROUP BY acurrency ) as ca - GROUP BY ca.currency', 'currency', array($id)); + GROUP BY scurrency', + 'scurrency', + array( + $id + ) + ); } private function getAssignmentPresentation($tariff) @@ -114,275 +130,998 @@ private function getAssignmentPresentation($tariff) ); } - public function GetCustomerAssignments($id, $show_expired = false, $show_approved = true) + /** + * @param $params + * @return mixed + */ + public function getAssignments($params = array()) { - $now = mktime(0, 0, 0, date('n'), date('d'), date('Y')); - $suspension_percentage = f_round(ConfigHelper::getConfig('payments.suspension_percentage', ConfigHelper::getConfig('finances.suspension_percentage', 0))); - - $assignments = $this->db->GetAll( - 'SELECT a.id AS id, a.tariffid, a.customerid, a.period AS periodvalue, a.backwardperiod, a.note, - a.at, a.suspended, a.invoice, a.settlement, a.recipient_address_id, - a.datefrom, a.dateto, a.pdiscount, - a.vdiscount AS unitary_vdiscount, - (a.vdiscount * a.count) AS vdiscount, - a.attribute, a.liabilityid, - a.separatedocument, a.separateitem, - (CASE WHEN t.flags IS NULL - THEN - (CASE WHEN (l.flags & ' . LIABILITY_FLAG_SPLIT_PAYMENT . ') > 0 THEN 1 ELSE 0 END) + if (empty($params['reportdate'])) { + $currtime = time(); + $today = strtotime('today'); + } else { + $today = $currtime = strtotime($params['reportdate']); + } + + [$year, $month, $dom] = explode('/', date('Y/n/j', $currtime)); + $weekday = date('N', $currtime); + $yearday = date('z', $currtime) + 1; + $last_dom = date('j', mktime(0, 0, 0, $month + 1, 0, $year)) == date('j', $currtime); + if (is_leap_year($year) && $yearday > 31 + 28) { + $yearday -= 1; + } + if ($month == 1 || $month == 4 || $month == 7 || $month == 10) { + $quarter = $dom; + } elseif ($month == 2 || $month == 5 || $month == 8 || $month == 11) { + $quarter = $dom + 100; + } else { + $quarter = $dom + 200; + } + if ($month > 6) { + $halfyear = $dom + ($month - 7) * 100; + } else { + $halfyear = $dom + ($month - 1) * 100; + } + + $query = 'SELECT ' + . $this->db->Concat('UPPER(c.lastname)', "' '", 'c.name') . ' AS customername, ' + . $this->db->Concat('c.city', "' '", 'c.address') . ' AS address, + c.ten, + a.id, + a.id AS assignmentid, + a.at, + a.tariffid, + a.liabilityid, + a.customerid, + a.period, + a.period as periodvalue, + a.count AS count, + a.datefrom, + a.dateto, + a.pdiscount, + a.vdiscount, + (CASE WHEN a.liabilityid IS NULL + THEN (CASE WHEN t.flags & ? > 0 THEN 1 ELSE 0 END) + ELSE (CASE WHEN l.flags & ? > 0 THEN 1 ELSE 0 END) + END) AS netflag, + t.period AS t_period, + (CASE WHEN price_variants.tpv_price IS NULL + THEN + (CASE WHEN a.liabilityid IS NULL THEN tvalue ELSE lvalue END) ELSE - (CASE WHEN (t.flags & ' . TARIFF_FLAG_SPLIT_PAYMENT . ') > 0 THEN 1 ELSE 0 END) - END) AS splitpayment, - (CASE WHEN t.flags IS NULL - THEN - (CASE WHEN (l.flags & ' . LIABILITY_FLAG_NET_ACCOUT . ') > 0 THEN 1 ELSE 0 END) + price_variants.tpv_price + END) AS base_price, + (CASE WHEN price_variants.tpv_price IS NULL + THEN + ROUND(((((100 - a.pdiscount) * (CASE WHEN a.liabilityid IS NULL THEN tvalue ELSE lvalue END)) / 100) - a.vdiscount), 3) ELSE - (CASE WHEN (t.flags & ' . TARIFF_FLAG_NET_ACCOUNT . ') > 0 THEN 1 ELSE 0 END) - END) AS netflag, - (CASE WHEN t.taxcategory IS NULL THEN l.taxcategory ELSE t.taxcategory END) AS taxcategory, - ROUND(t.uprate * a.count) AS uprate, + ROUND(((((100 - a.pdiscount) * price_variants.tpv_price) / 100) - a.vdiscount), 3) + END) AS price, + (CASE WHEN a.liabilityid IS NULL THEN t.taxid ELSE l.taxid END) AS taxid, + (CASE WHEN a.liabilityid IS NULL THEN t.taxrate ELSE l.taxrate END) AS taxrate, + (CASE WHEN a.liabilityid IS NULL THEN t.taxlabel ELSE l.taxlabel END) AS taxlabel, + (CASE WHEN a.liabilityid IS NULL THEN t.currency ELSE l.currency END) AS currency, + vas.*, + (CASE + WHEN vas.suspended IS NOT NULL + AND + ( + ( + vas.suspension_charge_method = ? AND vas.suspension_at = ? + ) + OR + ( + ( + vas.suspension_charge_method = ? + OR + (vas.suspension_charge_method = ? AND vas.suspension_at IN ?) + ) + AND vas.suspension_datefrom <= ? + AND (vas.suspension_dateto > ? OR vas.suspension_dateto = 0) + ) + ) + THEN 1 + ELSE 0 + END) AS charge_suspension + FROM assignments a + JOIN customerview c ON (a.customerid = c.id) + LEFT JOIN ( + SELECT tariffs.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN tariffs.flags & ? > 0 THEN tariffs.netvalue ELSE tariffs.value END) AS tvalue + FROM tariffs + JOIN taxes ON taxes.id = tariffs.taxid + ) t ON a.tariffid = t.id + LEFT JOIN ( + SELECT liabilities.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN liabilities.flags & ? > 0 THEN liabilities.netvalue ELSE liabilities.value END) AS lvalue + FROM liabilities + JOIN taxes ON taxes.id = liabilities.taxid + ) l ON a.liabilityid = l.id + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ? + AND (vas.suspension_dateto > ? OR vas.suspension_dateto = 0) + LEFT JOIN ( + SELECT + tpv.* + FROM assignments a + JOIN ( + SELECT + tariffpricevariants.quantity_threshold AS tpv_quantity_threshold, tariffs.id AS tpv_tariffid, + (CASE WHEN tariffs.flags & ? > 0 THEN tariffpricevariants.net_price ELSE tariffpricevariants.gross_price END) AS tpv_price + FROM tariffs + JOIN tariffpricevariants ON tariffs.id = tariffpricevariants.tariffid + ) tpv ON a.tariffid = tpv.tpv_tariffid AND tpv.tpv_quantity_threshold <= a.count AND tpv.tpv_tariffid = a.tariffid + ORDER BY tpv.tpv_quantity_threshold DESC LIMIT 1 + ) AS price_variants ON a.tariffid = price_variants.tpv_tariffid + WHERE a.commited = 1 + AND ( + (a.period = ? AND at = ?) + OR ( + ( + a.period = ? + OR (a.period = ? AND at = ?) + OR (a.period = ? AND at IN ?) + OR (a.period = ? AND at = ?) + OR (a.period = ? AND at = ?) + OR (a.period = ? AND at = ?) + ) + AND a.datefrom <= ? AND (a.dateto > ? OR a.dateto = 0) + ) + OR ( + (vas.suspension_charge_method = ? AND vas.suspension_at = ?) + OR ( + ( + vas.suspension_charge_method = ? + OR + (vas.suspension_charge_method = ? AND vas.suspension_at IN ?) + ) + AND vas.suspension_datefrom <= ? + AND (vas.suspension_dateto >= ? OR vas.suspension_dateto = 0) + AND a.datefrom <= ? AND (a.dateto > ? OR a.dateto = 0) + ) + ) + )' + . (!empty($params['customer_id']) ? ' AND c.id = ' . $params['customer_id'] : '') + . (!empty($params['division_id']) ? ' AND c.divisionid = ' . $params['division_id'] : '') + .' ORDER BY customername, address, a.id'; + + $doms = array($dom); + + if ($last_dom) { + $doms[] = 0; + } + + return $this->db->GetAllByKey( + $query, + 'id', + array( + TARIFF_FLAG_NET_ACCOUNT, + LIABILITY_FLAG_NET_ACCOUT, + SUSPENSION_CHARGE_METHOD_ONCE, $today, + SUSPENSION_CHARGE_METHOD_NONE, + SUSPENSION_CHARGE_METHOD_PERIODICALLY, $doms, + $currtime, $currtime, + TARIFF_FLAG_NET_ACCOUNT, + LIABILITY_FLAG_NET_ACCOUT, + $currtime, $currtime, + TARIFF_FLAG_NET_ACCOUNT, + DISPOSABLE, $today, DAILY, WEEKLY, $weekday, MONTHLY, $doms, QUARTERLY, $quarter, HALFYEARLY, $halfyear, YEARLY, $yearday, + $currtime, $currtime, + SUSPENSION_CHARGE_METHOD_ONCE, $today, + SUSPENSION_CHARGE_METHOD_NONE, + SUSPENSION_CHARGE_METHOD_PERIODICALLY, $doms, + $currtime, $currtime, + $currtime, $currtime, + ) + ); + } + + /** + * @param $customer_id + * @param array $params + * @return mixed + */ + public function getCustomerAssignments($customer_id, $params = array()) + { + $result = array(); + $currtime = time(); + $today = strtotime('today'); + + $query = 'SELECT a.id AS id, + a.tariffid, + a.liabilityid, + a.customerid, + a.recipient_address_id, + a.period, + a.period as periodvalue, + a.backwardperiod, + a.at, + a.settlement, + a.datefrom, + a.dateto, + a.pdiscount, + a.vdiscount, + a.attribute, + a.invoice, + a.separatedocument, + a.separateitem, + a.commited, + a.count AS count, + a.id AS assignmentid, + a.paytime AS a_paytime, + a.paytype AS a_paytype, + a.numberplanid, + a.attribute, + c.type AS customertype, + c.divisionid, + c.paytime, + c.paytype, + c.flags AS customerflags, + d.number AS docnumber, + d.type AS doctype, + d.cdate, + d.fullnumber, + np.template, + p.name AS promotion_name, + ps.name AS promotion_schema_name, + ps.length AS promotion_schema_length, + t.description AS description, + t.period AS t_period, uprate AS unitary_uprate, - ROUND(t.upceil * a.count) AS upceil, + ROUND(t.uprate * a.count) AS total_uprate, upceil AS unitary_upceil, - ROUND(t.downceil * a.count) AS downceil, + ROUND(t.upceil * a.count) AS total_upceil, downceil AS unitary_downceil, - ROUND(t.downrate * a.count) AS downrate, + ROUND(t.downceil * a.count) AS total_downceil, downrate AS unitary_downrate, + ROUND(t.downrate * a.count) AS total_downrate, + (CASE WHEN a.period = ? THEN ? ELSE ? END) AS assignment_charge_method, + vas.*, + (CASE WHEN c.type = ? THEN 0 ELSE (CASE WHEN a.liabilityid IS NULL + THEN (CASE WHEN t.flags & ? > 0 THEN 1 ELSE 0 END) + ELSE (CASE WHEN l.flags & ? > 0 THEN 1 ELSE 0 END) + END) END) AS splitpayment, + (CASE WHEN a.liabilityid IS NULL + THEN (CASE WHEN t.flags & ? > 0 THEN 1 ELSE 0 END) + ELSE (CASE WHEN l.flags & ? > 0 THEN 1 ELSE 0 END) + END) AS netflag, + (CASE WHEN a.liabilityid IS NULL THEN t.taxcategory ELSE l.taxcategory END) AS taxcategory, + (CASE WHEN a.tariffid IS NULL THEN l.type ELSE t.type END) AS tarifftype, + (CASE WHEN a.liabilityid IS NULL THEN t.name ELSE l.name END) AS name, + (CASE WHEN a.liabilityid IS NULL THEN t.taxid ELSE l.taxid END) AS taxid, + (CASE WHEN a.liabilityid IS NULL THEN t.prodid ELSE l.prodid END) AS prodid, + price_variants.tpv_price AS price_variant, + (CASE WHEN price_variants.tpv_price IS NULL + THEN + (CASE WHEN a.liabilityid IS NULL THEN tvalue ELSE lvalue END) + ELSE + price_variants.tpv_price + END) AS base_price, + (CASE WHEN price_variants.tpv_price IS NULL + THEN + ROUND(((((100 - a.pdiscount) * (CASE WHEN a.liabilityid IS NULL THEN tvalue ELSE lvalue END)) / 100) - a.vdiscount), 3) + ELSE + ROUND(((((100 - a.pdiscount) * price_variants.tpv_price) / 100) - a.vdiscount), 3) + END) AS price, + (CASE WHEN a.liabilityid IS NULL THEN t.taxrate ELSE l.taxrate END) AS taxrate, + (CASE WHEN a.liabilityid IS NULL THEN t.taxlabel ELSE l.taxlabel END) AS taxlabel, + (CASE WHEN a.liabilityid IS NULL THEN t.currency ELSE l.currency END) AS currency, (CASE WHEN t.flags IS NULL THEN l.flags ELSE t.flags END) AS flags, - tax.value AS tax_value, tax.label AS tax_label, - taxl.value AS taxl_value, taxl.label AS taxl_label, - (CASE WHEN t.type IS NULL THEN l.type ELSE t.type END) AS tarifftype, - (CASE WHEN t.value IS NULL THEN l.value ELSE t.value END) AS unitary_value, - (CASE WHEN t.netvalue IS NULL THEN l.netvalue ELSE t.netvalue END) AS unitary_netvalue, - a.count, - (CASE WHEN t.value IS NULL THEN l.value ELSE t.value END) * a.count AS value, - (CASE WHEN t.netvalue IS NULL THEN l.netvalue ELSE t.netvalue END) * a.count AS netvalue, - (CASE WHEN t.currency IS NULL THEN l.currency ELSE t.currency END) AS currency, - (CASE WHEN t.name IS NULL THEN l.name ELSE t.name END) AS name, - p.name AS promotion_name, ps.name AS promotion_schema_name, ps.length AS promotion_schema_length, - d.number AS docnumber, d.type AS doctype, d.cdate, np.template, - d.fullnumber, - (CASE WHEN - ((a.period <> ' . DISPOSABLE . ' OR (a.tariffid IS NULL AND a.liabilityid IS NULL)) AND (a.dateto > ' . $now . ' OR a.dateto = 0) AND (a.at >= ' . $now . ' OR a.at < 531)) - OR (a.period = ' . DISPOSABLE . ' AND a.at >= ' . $now . ') + (CASE WHEN (a.period <> ? AND (a.dateto > ? OR a.dateto = 0) AND (a.at >= ? OR a.at < 531)) + OR (a.period = ? AND a.at >= ?) THEN 0 ELSE 1 END) AS expired, - commited - FROM - assignments a - LEFT JOIN tariffs t ON (a.tariffid = t.id) - LEFT JOIN liabilities l ON (a.liabilityid = l.id) - LEFT JOIN taxes tax ON (tax.id = t.taxid) - LEFT JOIN taxes taxl ON (taxl.id = l.taxid) + (CASE WHEN (a.period <> ? AND a.datefrom > ?) OR (a.period = ? AND a.at >= ?) + THEN 1 + ELSE 0 + END) AS future + FROM assignments a + JOIN customers c ON (a.customerid = c.id) + LEFT JOIN ( + SELECT tariffs.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN tariffs.flags & ? > 0 THEN tariffs.netvalue ELSE tariffs.value END) AS tvalue + FROM tariffs + JOIN taxes ON taxes.id = tariffs.taxid + ) t ON a.tariffid = t.id + LEFT JOIN ( + SELECT liabilities.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN liabilities.flags & ? > 0 THEN liabilities.netvalue ELSE liabilities.value END) AS lvalue + FROM liabilities + JOIN taxes ON taxes.id = liabilities.taxid + ) l ON a.liabilityid = l.id LEFT JOIN promotionschemas ps ON ps.id = a.promotionschemaid LEFT JOIN promotions p ON p.id = ps.promotionid LEFT JOIN documents d ON d.id = a.docid LEFT JOIN numberplans np ON np.id = d.numberplanid - WHERE a.customerid=? ' . ($show_approved ? 'AND a.commited = 1 ' : '') - . (!$show_expired ? 'AND ((a.period <> ' . DISPOSABLE . ' AND (a.dateto > ' . $now . ' OR a.dateto = 0) AND (a.at >= ' . $now . ' OR a.at < 531)) - OR (a.period = ' . DISPOSABLE . ' AND a.at > ' . $now . '))' : '') . ' - ORDER BY - a.datefrom, t.name, value', - array($id) + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + LEFT JOIN ( + SELECT + tpv.* + FROM assignments a + JOIN ( + SELECT + tariffpricevariants.quantity_threshold AS tpv_quantity_threshold, tariffs.id AS tpv_tariffid, + (CASE WHEN tariffs.flags & ? > 0 THEN tariffpricevariants.net_price ELSE tariffpricevariants.gross_price END) AS tpv_price + FROM tariffs + JOIN tariffpricevariants ON tariffs.id = tariffpricevariants.tariffid + ) tpv ON a.tariffid = tpv.tpv_tariffid AND tpv.tpv_quantity_threshold <= a.count AND tpv.tpv_tariffid = a.tariffid + ORDER BY tpv.tpv_quantity_threshold DESC LIMIT 1 + ) AS price_variants ON a.tariffid = price_variants.tpv_tariffid + WHERE a.customerid = ?' + . (!empty($params['show_approved']) ? ' AND a.commited = 1' : '') + . (empty($params['show_expired']) ? ' AND ((a.period <> ' . DISPOSABLE . ' AND (a.dateto > ' . $currtime . ' OR a.dateto = 0) AND (a.at >= ' . $currtime . ' OR a.at < 531)) + OR (a.period = ' . DISPOSABLE . ' AND a.at > ' . $currtime . '))' : '') + . (!empty($params['not_suspended']) ? ' AND vas.suspension_id IS NULL' : '') + . (!empty($params['suspended']) ? ' AND vas.suspended != 0' : '') + . (!empty($params['suspend_group']) ? ' AND vas.suspension_id IS NOT NULL AND vas.suspension_suspend_all = 0' : '') + . (!empty($params['suspend_all']) ? ' AND vas.suspension_suspend_all = 1' : '') + . (!empty($params['suspension_id']) ? ' AND vas.suspension_id = ' . $params['suspension_id'] : '') + . (!empty($params['assignments']) ? ' AND a.id IN (' . $params['assignments'] . ')' : '') + . ' ORDER BY t.name, a.datefrom'; + + $assignments = $this->db->GetAllByKey( + $query, + 'id', + array( + DISPOSABLE, + SUSPENSION_CHARGE_METHOD_ONCE, + SUSPENSION_CHARGE_METHOD_PERIODICALLY, + CTYPES_PRIVATE, + TARIFF_FLAG_SPLIT_PAYMENT, + LIABILITY_FLAG_SPLIT_PAYMENT, + TARIFF_FLAG_NET_ACCOUNT, + LIABILITY_FLAG_NET_ACCOUT, + DISPOSABLE, + $currtime, + $currtime, + DISPOSABLE, + $currtime, + DISPOSABLE, + $currtime, + DISPOSABLE, + $currtime, + TARIFF_FLAG_NET_ACCOUNT, + LIABILITY_FLAG_NET_ACCOUT, + TARIFF_FLAG_NET_ACCOUNT, + $customer_id + ) ); - if ($assignments) { - foreach ($assignments as $idx => $row) { + $suspensionsByCurrency = array(); + $suspensionsById = array(); + + if (!empty($assignments)) { + $lms = LMS::getInstance(); + + //region Suspensions defaults + $defaultSuspensionPercentage = ConfigHelper::getConfig( + 'suspensions.default_percentage', + ConfigHelper::getConfig('payments.suspension_percentage', ConfigHelper::getConfig('finances.suspension_percentage', 0)) + ); + $defaultSuspensionPercentage = f_round($defaultSuspensionPercentage); + $defaultSuspensionValue = f_round(ConfigHelper::getConfig('suspensions.default_value', 0)); + //endregion + + foreach ($assignments as $idx => &$row) { + $row['name'] = $this->getAssignmentPresentation($row); + $recipient_address = !empty($row['recipient_address_id']) ? $lms->GetAddress($row['recipient_address_id']) : null; + $row['recipient_location'] = $recipient_address ? $recipient_address['location'] : null; + + $row['docnumber'] = docnumber(array( + 'number' => $row['docnumber'], + 'template' => $row['numtemplate'] ?? null, + 'cdate' => $row['cdate'], + 'customerid' => $customer_id, + )); + switch ($row['periodvalue']) { case DISPOSABLE: $row['payday'] = date('Y/m/d', $row['at']); - $row['period'] = trans('disposable'); break; case DAILY: - $row['period'] = trans('daily'); $row['payday'] = trans('daily'); break; case WEEKLY: $row['at'] = date('D', mktime(0, 0, 0, 0, $row['at'] + 5, 0)); $row['payday'] = trans('weekly ($a)', $row['at']); - $row['period'] = trans('weekly'); break; case MONTHLY: $row['payday'] = trans('monthly ($a)', $row['at'] ?: trans('last day')); - $row['period'] = trans('monthly'); break; case QUARTERLY: $row['at'] = sprintf('%02d/%02d', $row['at'] % 100, $row['at'] / 100 + 1); $row['payday'] = trans('quarterly ($a)', $row['at']); - $row['period'] = trans('quarterly'); break; case HALFYEARLY: $row['at'] = sprintf('%02d/%02d', $row['at'] % 100, $row['at'] / 100 + 1); $row['payday'] = trans('half-yearly ($a)', $row['at']); - $row['period'] = trans('half-yearly'); break; case YEARLY: $row['at'] = date('d/m', ($row['at'] - 1) * 86400); $row['payday'] = trans('yearly ($a)', $row['at']); - $row['period'] = trans('yearly'); break; } - $row['name'] = $this->getAssignmentPresentation($row); - $lms = LMS::getInstance(); - $recipient_address = !empty($row['recipient_address_id']) ? $lms->GetAddress($row['recipient_address_id']) : null; - $row['recipient_location'] = $recipient_address ? $recipient_address['location'] : null; + if ($row['t_period'] && $row['period'] != DISPOSABLE + && $row['t_period'] != $row['period']) { + if ($row['t_period'] == YEARLY) { + $row['base_price'] = $row['base_price'] / 12.0; + $row['price'] = $row['price'] / 12.0; + } elseif ($row['t_period'] == HALFYEARLY) { + $row['base_price'] = $row['base_price'] / 6.0; + $row['price'] = $row['price'] / 6.0; + } elseif ($row['t_period'] == QUARTERLY) { + $row['base_price'] = $row['base_price'] / 3.0; + $row['price'] = $row['price'] / 3.0; + } - $row['docnumber'] = docnumber(array( - 'number' => $row['docnumber'], - 'template' => $row['numtemplate'] ?? null, - 'cdate' => $row['cdate'], - 'customerid' => $id, - )); + if ($row['period'] == YEARLY) { + $row['base_price'] = $row['base_price'] * 12.0; + $row['price'] = $row['price'] * 12.0; + } elseif ($row['period'] == HALFYEARLY) { + $row['base_price'] = $row['base_price'] * 6.0; + $row['price'] = $row['price'] * 6.0; + } elseif ($row['period'] == QUARTERLY) { + $row['base_price'] = $row['base_price'] * 3.0; + $row['price'] = $row['price'] * 3.0; + } elseif ($row['period'] == WEEKLY) { + $row['base_price'] = $row['base_price'] / 4.0; + $row['price'] = $row['price'] / 4.0; + } elseif ($row['period'] == DAILY) { + $row['base_price'] = $row['base_price'] / 30.0; + $row['price'] = $row['price'] / 30.0; + } + } - $assignments[$idx] = $row; + // + if (!empty($row['netflag'])) { + $row['base_net_price'] = $row['base_price']; + $row['base_net_value'] = f_round($row['base_net_price'] * $row['count']); + $row['base_gross_price'] = f_round($row['base_net_price'] * ($row['taxrate'] / 100 + 1), 3); + $row['base_tax_value'] = f_round($row['base_net_value'] * ($row['taxrate'] / 100)); + $row['base_gross_value'] = f_round($row['base_net_value'] + $row['base_tax_value']); + + $row['net_price'] = $row['price']; // price is discounted in sql already + + $row['net_price_discount'] = f_round($row['base_net_price'] - $row['net_price'], 3); + $row['net_value'] = f_round($row['net_price'] * $row['count']); + $row['gross_price'] = f_round($row['net_price'] * ($row['taxrate'] / 100 + 1), 3); + $row['gross_price_discount'] = f_round($row['net_price_discount'] * ($row['taxrate'] / 100 + 1), 3); + $row['tax_value'] = f_round($row['net_value'] * ($row['taxrate'] / 100)); + $row['gross_value'] = f_round($row['net_value'] + $row['tax_value']); + } else { + $row['base_gross_price'] = $row['base_price']; + $row['base_gross_value'] = f_round($row['base_gross_price'] * $row['count']); + $row['base_net_price'] = f_round($row['base_gross_price'] / ($row['taxrate'] / 100 + 1), 3); + $row['base_tax_value'] = f_round(($row['base_gross_value'] * $row['taxrate']) / (100 + $row['taxrate'])); + $row['base_net_value'] = f_round($row['base_gross_value'] - $row['base_tax_value']); + + $row['gross_price'] = $row['price']; // price is discounted in sql already + + $row['gross_price_discount'] = f_round($row['base_gross_price'] - $row['gross_price'], 3); + $row['gross_value'] = f_round($row['gross_price'] * $row['count']); + $row['net_price'] = f_round($row['gross_price'] / ($row['taxrate'] / 100 + 1), 3); + $row['net_price_discount'] = f_round($row['gross_price_discount'] / ($row['taxrate'] / 100 + 1), 3); + $row['tax_value'] = f_round(($row['gross_value'] * $row['taxrate']) / (100 + $row['taxrate'])); + $row['net_value'] = f_round(($row['gross_value'] - $row['tax_value'])); + } - // assigned nodes - $assignments[$idx]['nodes'] = $this->db->GetAll('SELECT vn.name, vn.id, vn.location, vn.ownerid, - nd.id AS netdev_id, nd.name AS netdev_name, - nd.ownerid AS netdev_ownerid - FROM - nodeassignments, vnodes vn - LEFT JOIN netdevices nd ON vn.netdev = nd.id - WHERE - nodeid = vn.id AND - assignmentid = ?', array($row['id'])); - - $assignments[$idx]['phones'] = $this->db->GetAllByKey('SELECT vn.phone - FROM - voip_number_assignments vna - LEFT JOIN voip_numbers vn ON vna.number_id = vn.id - WHERE - assignment_id = ?', 'phone', array($row['id'])); - - if (!empty($row['tariffid'])) { - $priceVariant = $lms->getTariffPriceVariantByQuantityThreshold($row['tariffid'], $row['count']); - if (!empty($priceVariant)) { - $row['netvalue'] = $priceVariant['net_price'] * $row['count']; - $row['value'] = $priceVariant['gross_price'] * $row['count']; - $row['unitary_netvalue'] = $priceVariant['net_price']; - $row['unitary_value'] = $priceVariant['gross_price']; - $assignments[$idx]['unitary_netvalue'] = $priceVariant['net_price']; - $assignments[$idx]['unitary_value'] = $priceVariant['gross_price']; - $assignments[$idx]['netvalue'] = $priceVariant['net_price'] * $row['count']; - $assignments[$idx]['value'] = $priceVariant['gross_price'] * $row['count']; - } + $row['net_value_discount'] = f_round($row['base_net_value'] - $row['net_value']); + $row['gross_value_discount'] = f_round($row['base_gross_value'] - $row['gross_value']); + + if (empty($row['expired']) && empty($row['future']) && !empty($row['commited'])) { + $row['current_base_net_value'] = $row['base_net_value']; + $row['current_base_gross_value'] = $row['base_gross_value']; + $row['current_net_value'] = $row['net_value']; + $row['current_gross_value'] = $row['gross_value']; + $row['current_net_value_discount'] = $row['net_value_discount']; + $row['current_gross_value_discount'] = $row['gross_value_discount']; + $row['current_gross_value_discount'] = $row['gross_value_discount']; + $row['current_downrate'] = $row['total_downrate']; + $row['current_downceil'] = $row['total_downceil']; + $row['current_uprate'] = $row['total_uprate']; + $row['current_upceil'] = $row['total_upceil']; } + // + + if (!empty($row['suspended'])) { + if ($row['suspension_charge_method'] != SUSPENSION_CHARGE_METHOD_NONE) { + switch ($row['suspension_calculation_method']) { + case SUSPENSION_CALCULATION_METHOD_PERCENTAGE: + if (!isset($suspensionsByCurrency[$row['currency']][$row['taxid']][$row['suspension_id']])) { + $suspensionsByCurrency[$row['currency']][$row['taxid']][$row['suspension_id']] = array( + 'name' => !empty($row['suspension_suspend_all']) ? trans("Suspension of all") : trans("Suspension"), + 'taxid' => $row['taxid'], + 'currency' => $row['currency'], + 'customerid' => $row['customerid'], + 'suspensionid' => $row['suspension_id'], + 'taxid' => $row['taxid'], + 'taxlabel' => $row['taxlabel'], + 'taxrate' => $row['taxrate'], + 'note' => $row['suspension_note'], + 'at' => $row['suspension_at'], + 'datefrom' => $row['suspension_datefrom'], + 'dateto' => $row['suspension_dateto'], + 'charge_method' => $row['suspension_charge_method'], + 'calculation_method' => $row['suspension_calculation_method'], + 'suspension_percentage' => !is_null($row['suspension_percentage']) ? $row['suspension_percentage'] : $defaultSuspensionPercentage, + 'default_suspension_percentage' => is_null($row['suspension_percentage']), + 'netflag' => $row['netflag'], + 'currency' => $row['currency'], + 'total_net_value' => 0, + 'total_gross_value' => 0, + 'total_tax_value' => 0, + 'current_total_net_value' => 0, + 'current_total_gross_value' => 0, + 'current_total_tax_value' => 0, + ); + } + if (!isset($suspensionsById[$row['suspension_id']])) { + $suspensionsById[$row['suspension_id']]['suspension_id'] = $row['suspension_id']; + } - if ($assignments[$idx]['netflag']) { - $assignments[$idx]['discounted_netprice'] = f_round(($row['unitary_netvalue'] - $row['unitary_netvalue'] * $row['pdiscount'] / 100) - ($row['unitary_vdiscount']), 3); - if ($row['suspended'] == 1) { - $assignments[$idx]['discounted_netprice'] = $assignments[$idx]['discounted_netprice'] * $suspension_percentage / 100; - } - $assignments[$idx]['discounted_netvalue'] = f_round($assignments[$idx]['discounted_netprice'] * $row['count']); - $assignments[$idx]['unitary_netdiscount'] = f_round($row['unitary_netvalue'] - $assignments[$idx]['discounted_netprice'], 3); + $suspension = $suspensionsByCurrency[$row['currency']][$row['taxid']][$row['suspension_id']]; + $suspension['suspend_assignments'][$idx]['assignment_id'] = $idx; + + //region set 'at' + switch ($row['suspension_charge_method']) { + case SUSPENSION_CHARGE_METHOD_ONCE: + $suspension['payday'] = date('Y/m/d', $row['suspension_at']); + break; + case SUSPENSION_CHARGE_METHOD_PERIODICALLY: + $suspension['payday'] = trans('monthly ($a)', $row['suspension_at'] ?: trans('last day')); + break; + } + //endregion + + $suspensionPercentage = !is_null($row['suspension_percentage']) ? f_round($row['suspension_percentage']) : $defaultSuspensionPercentage; + if (!empty($row['netflag'])) { + $suspension['net_price'] = f_round($row['net_price'] * ($suspensionPercentage / 100), 3); + if ($row['suspension_charge_method'] == SUSPENSION_CHARGE_METHOD_PERIODICALLY) { + if ($row['period'] == YEARLY) { + $suspension['net_price'] = $suspension['net_price'] / 12; + } elseif ($row['period'] == HALFYEARLY) { + $suspension['net_price'] = $suspension['net_price'] / 6; + } elseif ($row['period'] == QUARTERLY) { + $suspension['net_price'] = $suspension['net_price'] / 3; + } elseif ($row['period'] == WEEKLY) { + $suspension['net_price'] = $suspension['net_price'] * 4; + } elseif ($row['period'] == DAILY) { + $suspension['net_price'] = $suspension['net_price'] * 30; + } + } + $suspension['net_value'] = f_round($suspension['net_price'] * $row['count']); + $suspension['gross_price'] = f_round($suspension['net_price'] * ($row['taxrate'] / 100 + 1), 3); + $suspension['tax_value'] = f_round($suspension['net_value'] * ($row['taxrate'] / 100)); + $suspension['gross_value'] = f_round($suspension['net_value'] + $suspension['tax_value']); + } else { + $suspension['gross_price'] = f_round($row['gross_price'] * ($suspensionPercentage / 100), 3); + if ($row['suspension_charge_method'] == SUSPENSION_CHARGE_METHOD_PERIODICALLY) { + if ($row['period'] == YEARLY) { + $suspension['gross_price'] = $suspension['gross_price'] / 12; + } elseif ($row['period'] == HALFYEARLY) { + $suspension['gross_price'] = $suspension['gross_price'] / 6; + } elseif ($row['period'] == QUARTERLY) { + $suspension['gross_price'] = $suspension['gross_price'] / 3; + } elseif ($row['period'] == WEEKLY) { + $suspension['gross_price'] = $suspension['gross_price'] * 4; + } elseif ($row['period'] == DAILY) { + $suspension['gross_price'] = $suspension['gross_price'] * 30; + } + } + $suspension['gross_value'] = f_round($suspension['gross_price'] * $row['count']); + $suspension['net_price'] = f_round($suspension['gross_price'] / ($row['taxrate'] / 100 + 1), 3); + $suspension['tax_value'] = f_round(($suspension['gross_value'] * $row['taxrate']) / (100 + $row['taxrate'])); + $suspension['net_value'] = f_round(($suspension['gross_value'] - $suspension['tax_value'])); + } - if (!empty($assignments[$idx]['tax_value'])) { - $assignments[$idx]['discounted_price'] = f_round($assignments[$idx]['discounted_netprice'] * ($assignments[$idx]['tax_value'] / 100 + 1), 3); + $suspension['total_net_value'] += $suspension['net_value']; + $suspension['total_tax_value'] += $suspension['tax_value']; + $suspension['total_gross_value'] += $suspension['gross_value']; - $assignments[$idx]['tax_from_discounted_value'] = f_round($assignments[$idx]['discounted_netvalue'] * ($assignments[$idx]['tax_value'] / 100)); - } elseif (!empty($assignments[$idx]['taxl_value'])) { - $assignments[$idx]['discounted_price'] = f_round($assignments[$idx]['discounted_netprice'] * ($assignments[$idx]['taxl_value'] / 100 + 1), 3); + if (empty($row['expired']) && empty($row['future']) && !empty($row['commited'])) { + $suspension['current_total_net_value'] += $suspension['net_value']; + $suspension['current_total_tax_value'] += $suspension['tax_value']; + $suspension['current_total_gross_value'] += $suspension['gross_value']; + } - $assignments[$idx]['tax_from_discounted_value'] = f_round($assignments[$idx]['discounted_netvalue'] * ($assignments[$idx]['taxl_value'] / 100)); - } else { - $assignments[$idx]['discounted_price'] = 0; - $assignments[$idx]['tax_from_discounted_value'] = 0; - } - $assignments[$idx]['discounted_value'] = f_round(($assignments[$idx]['discounted_netvalue'] + $assignments[$idx]['tax_from_discounted_value'])); - $assignments[$idx]['unitary_discount'] = f_round($row['unitary_value'] - $assignments[$idx]['discounted_price'], 3); - } else { - $assignments[$idx]['discounted_price'] = f_round(($row['unitary_value'] - $row['unitary_value'] * $row['pdiscount'] / 100) - ($row['unitary_vdiscount']), 3); - if ($row['suspended'] == 1) { - $assignments[$idx]['discounted_price'] = $assignments[$idx]['discounted_price'] * $suspension_percentage / 100; - } - $assignments[$idx]['discounted_value'] = f_round($assignments[$idx]['discounted_price'] * $row['count']); - $assignments[$idx]['unitary_discount'] = f_round($row['unitary_value'] - $assignments[$idx]['discounted_price'], 3); + $suspensionsByCurrency[$row['currency']][$row['taxid']][$row['suspension_id']] = $suspension; + break; + + case SUSPENSION_CALCULATION_METHOD_VALUE: + // account only once for all assignemnts having this suspension + if (!isset($suspensionsByCurrency[$row['suspension_currency']][$row['suspension_tax_id']][$row['suspension_id']]) + && !isset($suspensionsById[$row['suspension_id']])) { + $suspensionsByCurrency[$row['suspension_currency']][$row['suspension_tax_id']][$row['suspension_id']] = array( + 'name' => !empty($row['suspension_suspend_all']) ? trans("Suspension of all") : trans("Suspension"), + 'customerid' => $row['suspension_customer_id'], + 'suspensionid' => $row['suspension_id'], + 'taxid' => $row['suspension_tax_id'], + 'taxlabel' => $row['suspension_taxlabel'], + 'taxrate' => $row['suspension_taxrate'], + 'note' => $row['suspension_note'], + 'datefrom' => $row['suspension_datefrom'], + 'dateto' => $row['suspension_dateto'], + 'charge_method' => $row['suspension_charge_method'], + 'calculation_method' => $row['suspension_calculation_method'], + 'value' => !is_null($row['suspension_value']) ? $row['suspension_value'] : $defaultSuspensionValue, + 'suspension_value' => !is_null($row['suspension_value']) ? $row['suspension_value'] : $defaultSuspensionValue, + 'default_suspension_value' => is_null($row['suspension_value']), + 'netflag' => $row['suspension_netflag'], + 'currency' => $row['suspension_currency'], + 'total_net_value' => 0, + 'total_gross_value' => 0, + 'total_tax_value' => 0, + 'current_total_net_value' => 0, + 'current_total_gross_value' => 0, + 'current_total_tax_value' => 0, + ); + + $suspensionsById[$row['suspension_id']]['suspension_id'] = $row['suspension_id']; + + $suspension = $suspensionsByCurrency[$row['suspension_currency']][$row['suspension_tax_id']][$row['suspension_id']]; + $suspension['suspend_assignments'][$idx]['assignment_id'] = $idx; + + switch ($row['suspension_charge_method']) { + case SUSPENSION_CHARGE_METHOD_ONCE: + $suspension['payday'] = date('Y/m/d', $row['suspension_at']); + break; + case SUSPENSION_CHARGE_METHOD_PERIODICALLY: + $suspension['payday'] = trans('monthly ($a)', $row['suspension_at'] ?: trans('last day')); + break; + } - if (!empty($assignments[$idx]['tax_value'])) { - $assignments[$idx]['discounted_netprice'] = f_round($assignments[$idx]['discounted_price'] / ($assignments[$idx]['tax_value'] / 100 + 1), 3); + if (!empty($row['suspension_netflag'])) { + $suspension['net_value'] = f_round($suspension['value']); + if ($row['suspension_charge_method'] == SUSPENSION_CHARGE_METHOD_PERIODICALLY) { + if ($row['period'] == YEARLY) { + $suspension['net_value'] = $suspension['net_value'] / 12; + } elseif ($row['period'] == HALFYEARLY) { + $suspension['net_value'] = $suspension['net_value'] / 6; + } elseif ($row['period'] == QUARTERLY) { + $suspension['net_value'] = $suspension['net_value'] / 3; + } elseif ($row['period'] == WEEKLY) { + $suspension['net_value'] = $suspension['net_value'] * 4; + } elseif ($row['period'] == DAILY) { + $suspension['net_value'] = $suspension['net_value'] * 30; + } + } + $suspension['tax_value'] = f_round($suspension['net_value'] * ($row['suspension_taxrate'] / 100)); + $suspension['gross_value'] = f_round($suspension['net_value'] + $suspension['tax_value']); + } else { + $suspension['gross_value'] = f_round($suspension['value']); + if ($row['suspension_charge_method'] == SUSPENSION_CHARGE_METHOD_PERIODICALLY) { + if ($row['period'] == YEARLY) { + $suspension['gross_value'] = $suspension['gross_value'] / 12; + } elseif ($row['period'] == HALFYEARLY) { + $suspension['gross_value'] = $suspension['gross_value'] / 6; + } elseif ($row['period'] == QUARTERLY) { + $suspension['gross_value'] = $suspension['gross_value'] / 3; + } elseif ($row['period'] == WEEKLY) { + $suspension['gross_value'] = $suspension['gross_value'] * 4; + } elseif ($row['period'] == DAILY) { + $suspension['gross_value'] = $suspension['gross_value'] * 30; + } + } + $suspension['tax_value'] = f_round(($suspension['gross_value'] * $row['suspension_taxrate']) / (100 + $row['suspension_taxrate'])); + $suspension['net_value'] = f_round(($suspension['gross_value'] - $suspension['tax_value'])); + } + + $suspension['total_net_value'] = $suspension['net_value']; + $suspension['total_gross_value'] = $suspension['gross_value']; + $suspension['total_tax_value'] = $suspension['tax_value']; + + if (empty($row['expired']) && empty($row['future']) && !empty($row['commited'])) { + $suspension['current_total_net_value'] = $suspension['net_value']; + $suspension['current_total_tax_value'] = $suspension['tax_value']; + $suspension['current_total_gross_value'] = $suspension['gross_value']; + } - $assignments[$idx]['tax_from_discounted_value'] = f_round(($assignments[$idx]['discounted_value'] * $assignments[$idx]['tax_value']) - / (100 + $assignments[$idx]['tax_value'])); - } elseif (!empty($assignments[$idx]['taxl_value'])) { - $assignments[$idx]['discounted_netprice'] = f_round($assignments[$idx]['discounted_price'] / ($assignments[$idx]['taxl_value'] / 100 + 1), 3); + $suspensionsByCurrency[$row['suspension_currency']][$row['suspension_tax_id']][$row['suspension_id']] = $suspension; + } - $assignments[$idx]['tax_from_discounted_value'] = f_round(($assignments[$idx]['discounted_value'] * $assignments[$idx]['taxl_value']) - / (100 + $assignments[$idx]['taxl_value'])); + $suspensionsByCurrency[$row['suspension_currency']][$row['suspension_tax_id']][$row['suspension_id']]['suspend_assignments'][$idx]['assignment_id'] = $idx; + break; + } } else { - $assignments[$idx]['discounted_netprice'] = 0; - $assignments[$idx]['tax_from_discounted_value'] = 0; + switch ($row['suspension_calculation_method']) { + case SUSPENSION_CALCULATION_METHOD_PERCENTAGE: + if (!isset($suspensionsByCurrency[$row['currency']][$row['taxid']][$row['suspension_id']])) { + $suspensionsByCurrency[$row['currency']][$row['taxid']][$row['suspension_id']] = array( + 'name' => !empty($row['suspension_suspend_all']) ? trans("Suspension of all") : trans("Suspension"), + 'taxid' => $row['taxid'], + 'currency' => $row['currency'], + 'customerid' => $row['customerid'], + 'suspensionid' => $row['suspension_id'], + 'taxid' => $row['taxid'], + 'taxlabel' => $row['taxlabel'], + 'taxrate' => $row['taxrate'], + 'note' => $row['suspension_note'], + 'datefrom' => $row['suspension_datefrom'], + 'dateto' => $row['suspension_dateto'], + 'charge_method' => $row['suspension_charge_method'], + 'calculation_method' => $row['suspension_calculation_method'], + 'netflag' => $row['netflag'], + 'currency' => $row['currency'], + 'total_net_value' => 0, + 'total_gross_value' => 0, + 'total_tax_value' => 0, + 'current_total_net_value' => 0, + 'current_total_gross_value' => 0, + 'current_total_tax_value' => 0, + ); + } + if (!isset($suspensionsById[$row['suspension_id']])) { + $suspensionsById[$row['suspension_id']]['suspension_id'] = $row['suspension_id']; + } + + $suspension = $suspensionsByCurrency[$row['currency']][$row['taxid']][$row['suspension_id']]; + $suspension['suspend_assignments'][$idx]['assignment_id'] = $idx; + + $suspension['net_price'] = 0; + $suspension['net_value'] = 0; + $suspension['gross_price'] = 0; + $suspension['tax_value'] = 0; + $suspension['gross_value'] = 0; + + $suspension['total_net_value'] = 0; + $suspension['total_tax_value'] = 0; + $suspension['total_gross_value'] = 0; + + $suspension['current_total_net_value'] = 0; + $suspension['current_total_tax_value'] = 0; + $suspension['current_total_gross_value'] = 0; + $suspension['payday'] = null; + + $suspensionsByCurrency[$row['currency']][$row['taxid']][$row['suspension_id']] = $suspension; + break; + + case SUSPENSION_CALCULATION_METHOD_VALUE: + // account only once for all assignemnts having this suspension + if (!isset($suspensionsByCurrency[$row['suspension_currency']][$row['suspension_tax_id']][$row['suspension_id']]) + && !isset($suspensionsById[$row['suspension_id']])) { + $suspensionsByCurrency[$row['suspension_currency']][$row['suspension_tax_id']][$row['suspension_id']] = array( + 'name' => !empty($row['suspension_suspend_all']) ? trans("Suspension of all") : trans("Suspension"), + 'customerid' => $row['suspension_customer_id'], + 'suspensionid' => $row['suspension_id'], + 'taxid' => '', + 'taxlabel' => '', + 'taxrate' => '', + 'note' => $row['suspension_note'], + 'datefrom' => $row['suspension_datefrom'], + 'dateto' => $row['suspension_dateto'], + 'charge_method' => $row['suspension_charge_method'], + 'calculation_method' => $row['suspension_calculation_method'], + 'value' => is_null($row['suspension_value']) ? $defaultSuspensionValue : $row['suspension_value'], + 'netflag' => $row['suspension_netflag'], + 'currency' => $row['suspension_currency'], + 'total_net_value' => 0, + 'total_gross_value' => 0, + 'total_tax_value' => 0, + 'current_total_net_value' => 0, + 'current_total_gross_value' => 0, + 'current_total_tax_value' => 0, + ); + + $suspensionsById[$row['suspension_id']]['suspension_id'] = $row['suspension_id']; + + $suspension = $suspensionsByCurrency[$row['suspension_currency']][$row['suspension_tax_id']][$row['suspension_id']]; + $suspension['suspend_assignments'][$idx]['assignment_id'] = $idx; + + $suspension['net_price'] = 0; + $suspension['net_value'] = 0; + $suspension['gross_price'] = 0; + $suspension['tax_value'] = 0; + $suspension['gross_value'] = 0; + + $suspension['total_net_value'] = 0; + $suspension['total_tax_value'] = 0; + $suspension['total_gross_value'] = 0; + + $suspension['current_total_net_value'] = 0; + $suspension['current_total_tax_value'] = 0; + $suspension['current_total_gross_value'] = 0; + $suspension['payday'] = null; + + $suspensionsByCurrency[$row['suspension_currency']][$row['suspension_tax_id']][$row['suspension_id']] = $suspension; + } + + $suspensionsByCurrency[$row['suspension_currency']][$row['suspension_tax_id']][$row['suspension_id']]['suspend_assignments'][$idx]['assignment_id'] = $idx; + + break; + } } - $assignments[$idx]['discounted_netvalue'] = f_round(($assignments[$idx]['discounted_value'] - $assignments[$idx]['tax_from_discounted_value'])); - $assignments[$idx]['unitary_netdiscount'] = f_round($row['unitary_netvalue'] - $assignments[$idx]['discounted_netprice'], 3); } - $now = time(); - - if ($row['suspended'] == 0 && - (($row['datefrom'] == 0 || $row['datefrom'] < $now) && - ($row['dateto'] == 0 || $row['dateto'] > $now))) { - // for proper summary - $assignments[$idx]['real_unitary_price'] = $assignments[$idx]['discounted_price']; - $assignments[$idx]['real_unitary_netprice'] = $assignments[$idx]['discounted_netprice']; - $assignments[$idx]['real_count'] = $row['count']; - $assignments[$idx]['real_value'] = $row['value']; - $assignments[$idx]['real_netvalue'] = $row['netvalue']; - $assignments[$idx]['real_unitary_discount'] = $assignments[$idx]['unitary_discount']; - $assignments[$idx]['real_unitary_netdiscount'] = $assignments[$idx]['unitary_netdiscount']; - $assignments[$idx]['real_discount'] = round($assignments[$idx]['real_unitary_discount'] * $row['count'], 3); - $assignments[$idx]['real_netdiscount'] = round($assignments[$idx]['real_unitary_netdiscount'] * $row['count'], 3); - $assignments[$idx]['real_disc_value'] = $assignments[$idx]['discounted_value']; - $assignments[$idx]['real_disc_netvalue'] = $assignments[$idx]['discounted_netvalue']; - $assignments[$idx]['real_unitary_downrate'] = $row['unitary_downrate']; - $assignments[$idx]['real_downrate'] = $row['downrate']; - $assignments[$idx]['real_unitary_downceil'] = $row['unitary_downceil']; - $assignments[$idx]['real_downceil'] = $row['downceil']; - $assignments[$idx]['real_unitary_uprate'] = $row['unitary_uprate']; - $assignments[$idx]['real_uprate'] = $row['uprate']; - $assignments[$idx]['real_unitary_upceil'] = $row['unitary_upceil']; - $assignments[$idx]['real_upceil'] = $row['upceil']; + // assigned nodes + $row['nodes'] = $this->db->GetAll( + 'SELECT vn.name, vn.id, vn.location, vn.ownerid, nd.id AS netdev_id, nd.name AS netdev_name, + nd.ownerid AS netdev_ownerid + FROM nodeassignments, vnodes vn + LEFT JOIN netdevices nd ON vn.netdev = nd.id + WHERE nodeid = vn.id + AND assignmentid = ?', + array($row['id']) + ); + + $row['phones'] = $this->db->GetAllByKey( + 'SELECT vn.phone + FROM voip_number_assignments vna + LEFT JOIN voip_numbers vn ON vna.number_id = vn.id + WHERE assignment_id = ?', + 'phone', + array($row['id']) + ); + } + unset($row, $suspension); + + $suspensions = $suspensionsByCurrency; + if (!empty($params['with_suspensions'])) { + $result['suspensions'] = $suspensions; + $result['assignments'] = $assignments; + } elseif (!empty($params['suspensions'])) { + $result = $suspensions; + } else { + $result = $assignments; + } + } + + return $result; + } + + public function getAssignment($assignment_id) + { + return $this->db->GetRow( + 'SELECT + a.id AS id, + a.at, + a.datefrom, + a.dateto, + a.period, + a.tariffid, + a.liabilityid, + a.customerid, + (CASE WHEN a.period = ? THEN ? ELSE ? END) AS assignment_charge_method, + (CASE WHEN a.liabilityid IS NULL THEN tvalue ELSE lvalue END) AS base_price, + ROUND(((((100 - a.pdiscount) * (CASE WHEN a.liabilityid IS NULL THEN tvalue ELSE lvalue END)) / 100) - a.vdiscount), 3) AS price, + (CASE WHEN a.liabilityid IS NULL THEN t.currency ELSE l.currency END) AS currency, + (CASE WHEN a.liabilityid IS NULL THEN t.taxid ELSE l.taxid END) AS taxid, + (CASE WHEN a.liabilityid IS NULL + THEN (CASE WHEN t.flags & ? > 0 THEN 1 ELSE 0 END) + ELSE (CASE WHEN l.flags & ? > 0 THEN 1 ELSE 0 END) + END) AS netflag, + vas.* + FROM assignments a + LEFT JOIN ( + SELECT tariffs.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN tariffs.flags & ? > 0 THEN tariffs.netvalue ELSE tariffs.value END) AS tvalue + FROM tariffs + JOIN taxes ON taxes.id = tariffs.taxid + ) t ON a.tariffid = t.id + LEFT JOIN ( + SELECT liabilities.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN liabilities.flags & ? > 0 THEN liabilities.netvalue ELSE liabilities.value END) AS lvalue + FROM liabilities + JOIN taxes ON taxes.id = liabilities.taxid + ) l ON a.liabilityid = l.id + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + WHERE a.id = ?', + array( + DISPOSABLE, + SUSPENSION_CHARGE_METHOD_ONCE, + SUSPENSION_CHARGE_METHOD_PERIODICALLY, + TARIFF_FLAG_NET_ACCOUNT, + LIABILITY_FLAG_NET_ACCOUT, + TARIFF_FLAG_NET_ACCOUNT, + LIABILITY_FLAG_NET_ACCOUT, + $assignment_id + ) + ); + } + + public function getSuspensions($params = array()) + { + $result = array(); + if (!empty($params)) { + $suspensions = $this->db->GetAll( + 'SELECT * + FROM vassignmentsuspensions + WHERE 1=1' + . (!empty($params['suspension_id']) ? ' AND suspension_id = ' . $params['suspension_id'] : '') + . (!empty($params['customer_id']) ? ' AND suspension_customer_id = ' . $params['suspension_id'] : ''), + ); + + if (!empty($suspensions)) { + if (!empty($params['by_suspension_id'])) { + $suspensionsBySuspensionId = array(); + foreach ($suspensions as $suspension) { + if (!isset($suspensionsBySuspensionId[$suspension['suspension_id']])) { + $suspensionsBySuspensionId[$suspension['suspension_id']] = $suspension; + } + if (!isset($suspensionsBySuspensionId[$suspension['suspension_id']]['suspended_assignments'][$suspension['suspension_assignment_id']])) { + $suspensionsBySuspensionId[$suspension['suspension_id']]['suspended_assignments'][$suspension['suspension_assignment_id']]['assignemnt_id'] = $suspension['suspension_assignment_id']; + } + } + + $result = $suspensionsBySuspensionId; + } elseif (!empty($params['by_customer_id'])) { + $suspensionsByCustomerId = array(); + foreach ($suspensions as $suspension) { + if (!isset($suspensionsByCustomerId[$suspension['suspension_customer_id']])) { + $suspensionsByCustomerId[$suspension['suspension_customer_id']]['customer_id'] = $suspension['suspension_customer_id']; + } + + if (!isset($suspensionsByCustomerId[$suspension['suspension_customer_id']][$suspension['suspension_id']])) { + $suspensionsByCustomerId[$suspension['suspension_customer_id']][$suspension['suspension_id']] = $suspension; + } + if (!isset($suspensionsByCustomerId[$suspension['suspension_customer_id']][$suspension['suspension_id']]['suspended_assignments'][$suspension['suspension_assignment_id']])) { + $suspensionsByCustomerId[$suspension['suspension_customer_id']][$suspension['suspension_id']]['suspended_assignments'][$suspension['suspension_assignment_id']]['assignemnt_id'] = $suspension['suspension_assignment_id']; + } + } + $result = $suspensionsByCustomerId; } } } - return $assignments; + return $result; } public function GetCustomerServiceSummary($id) { global $SERVICETYPES; - $now = mktime(0, 0, 0, date('n'), date('d'), date('Y')); - $suspension_percentage = f_round(ConfigHelper::getConfig('payments.suspension_percentage', ConfigHelper::getConfig('finances.suspension_percentage', 0))); + $now = strtotime('today'); - $servicesassignments = $this->db->GetAll('SELECT - t.type AS tarifftype, - ROUND(SUM((CASE a.suspended - WHEN 0 THEN (((100 - a.pdiscount) * (CASE WHEN t.value IS null THEN l.value ELSE t.value END) / 100) - a.vdiscount) - ELSE ((((100 - a.pdiscount) * (CASE WHEN t.value IS null THEN l.value ELSE t.value END) / 100) - a.vdiscount) * ' . $suspension_percentage . ' / 100) END) - * (CASE t.period + $servicesassignments = $this->db->GetAll( + 'SELECT SUM(ROUND( + (CASE + WHEN vas.suspended IS NULL + THEN ROUND(((((100 - a.pdiscount) * (CASE WHEN a.liabilityid IS NULL THEN t.value ELSE l.value END)) / 100) - a.vdiscount), 3) + ELSE vas.suspension_price + END) * + (CASE t.period + WHEN ' . MONTHLY . ' THEN 1 + WHEN ' . YEARLY . ' THEN 1/12.0 + WHEN ' . HALFYEARLY . ' THEN 1/6.0 + WHEN ' . QUARTERLY . ' THEN 1/3.0 + ELSE (CASE a.period WHEN ' . MONTHLY . ' THEN 1 WHEN ' . YEARLY . ' THEN 1/12.0 WHEN ' . HALFYEARLY . ' THEN 1/6.0 WHEN ' . QUARTERLY . ' THEN 1/3.0 - ELSE (CASE a.period - WHEN ' . MONTHLY . ' THEN 1 - WHEN ' . YEARLY . ' THEN 1/12.0 - WHEN ' . HALFYEARLY . ' THEN 1/6.0 - WHEN ' . QUARTERLY . ' THEN 1/3.0 - ELSE 0 END) - END) * a.count), 2) AS sumvalue - FROM - assignments a - LEFT JOIN tariffs t ON a.tariffid = t.id - LEFT JOIN liabilities l ON a.liabilityid = l.id - WHERE a.customerid= ? + ELSE 0 END) + END) * + a.count, 2)) AS sumvalue, + t.type AS tarifftype + FROM assignments a + LEFT JOIN tariffs t ON t.id = a.tariffid + LEFT JOIN liabilities l ON l.id = a.liabilityid + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ? + AND (vas.suspension_dateto >= ? OR vas.suspension_dateto = 0) + AND a.datefrom <= ? AND (a.dateto >= ? OR a.dateto = 0) + WHERE a.customerid = ? AND a.commited = 1 AND a.period <> ' . DISPOSABLE . ' - AND a.datefrom <= ' . $now . ' AND (a.dateto > ' . $now . ' OR a.dateto = 0) - GROUP BY tarifftype', array($id)); + AND a.datefrom <= ? AND (a.dateto > ? OR a.dateto = 0) + GROUP BY tarifftype', + array( + $now, + $now, + $now, + $now, + $id, + $now, + $now + ) + ); if ($servicesassignments) { $total_value = 0; @@ -1300,6 +2039,152 @@ private function insertAssignment($args) return $id; } + /** + * Add suspension. + * + * @params array suspension data + * @return void Inserted suspension ID + */ + public function addSuspension($params = array()) + { + if (!empty($params)) { + $args = $params; + $this->db->Execute( + 'INSERT INTO suspensions (at, datefrom, dateto, chargemethod, calculationmethod, + value, percentage, netflag, currency, taxid, note, customerid) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', + array_values($args) + ); + + $suspensionId = $this->db->GetLastInsertID('suspensions'); + + if (!empty($suspensionId)) { + if ($this->syslog) { + $args = array( + SYSLOG::RES_SUSPENSION => $suspensionId, + ); + $this->syslog->AddMessage(SYSLOG::RES_SUSPENSION, SYSLOG::OPER_ADD, $args); + } + + return $suspensionId; + } + } + } + + /** + * Update suspension. + * + * @params array suspension data + * @return void + */ + public function updateSuspension($params = array()) + { + if (!empty($params)) { + $args = $params; + $this->db->Execute( + 'UPDATE suspensions SET at = ?, datefrom = ?, dateto = ?, chargemethod = ?, calculationmethod = ?, + value = ?, percentage = ?, netflag = ?, currency = ?, taxid = ?, note = ?, customerid = ? + WHERE id = ?', + array_values($args) + ); + } + + if ($this->syslog) { + $args = array( + SYSLOG::RES_SUSPENSION => $params['id'], + ); + $this->syslog->AddMessage(SYSLOG::RES_SUSPENSION, SYSLOG::OPER_UPDATE, $args); + } + } + + /** + * Add assignment suspension. + * + * @params array suspension data + * @return void Inserted assignment suspension ID + */ + public function addAssignmentSuspension($params = array()) + { + if (!empty($params)) { + if (!empty($params['suspension_id']) && !empty($params['assignment_id'])) { + $this->db->Execute( + 'INSERT INTO assignmentsuspensions (suspensionid, assignmentid) + VALUES (?, ?)', + array( + $params['suspension_id'], + $params['assignment_id'], + ) + ); + + $assignemntSuspensionId = $this->db->GetLastInsertID('assignmentsuspensions'); + + if (!empty($assignemntSuspensionId) && $this->syslog) { + $args = array( + SYSLOG::RES_ASSIGN => $params['assignment_id'], + SYSLOG::RES_CUST => $params['customerid'], + 'suspend' => 1, + ); + $this->syslog->AddMessage(SYSLOG::RES_ASSIGN, SYSLOG::OPER_UPDATE, $args); + } + } + } + } + + /** + * Delete suspension. + * + * @params int suspension ID + * @return void + */ + public function deleteSuspension($suspension_id) + { + if (!empty($suspension_id)) { + $this->db->Execute('DELETE FROM assignmentsuspensions WHERE suspensionid = ?', array($suspension_id)); + $this->db->Execute('DELETE FROM suspensions WHERE id = ?', array($suspension_id)); + } + } + + /** + * Delete assignment suspension. + * + * @params array assignment suspension data + * @return void + */ + public function deleteAssignmentSuspension($params = array()) + { + if (!empty($params)) { + $suspensionsGroupCount = $this->db->GetOne( + 'SELECT COUNT(id) + FROM assignmentsuspensions + WHERE suspensionid = ?', + array($params['suspension_id']) + ); + + if ($suspensionsGroupCount == 1) { + $this->db->Execute('DELETE FROM suspensions WHERE id = ?', array($params['suspension_id'])); + } + + $this->db->Execute( + 'DELETE FROM assignmentsuspensions + WHERE suspensionid = ? + AND assignmentid = ?', + array( + $params['suspension_id'], + $params['assignment_id'], + ) + ); + + if ($this->syslog) { + $args = array( + SYSLOG::RES_ASSIGN => $params['assignment_id'], + SYSLOG::RES_CUST => $params['customerid'], + 'suspend' => 0, + ); + $this->syslog->AddMessage(SYSLOG::RES_ASSIGN, SYSLOG::OPER_UPDATE, $args); + } + } + } + private function insertNodeAssignments($args) { if (!empty($args['nodes'])) { @@ -1653,6 +2538,114 @@ public function ValidateAssignment($data) return $result; } + public function ValidateSuspension($params = array()) + { + $error = array(); + $suspension = r_trim($params); + + //region charging validation + $suspensionChargeMethod = $suspension['suspension_charge_method']; + if (!isset($GLOBALS['SUSPENSION_CHARGE_METHODS'][$suspensionChargeMethod])) { + $error['suspension_charge_method'] = trans('Incorrect value!'); + } + + $suspensionCalculationMethod = $suspension['suspension_calculation_method']; + if (!isset($GLOBALS['SUSPENSION_CALCULATION_METHODS'][$suspensionCalculationMethod])) { + $error['suspension_calculation_method'] = trans('Incorrect value!'); + } + //endregion + + if (empty($error)) { + //region charging validation + if ($suspensionChargeMethod != SUSPENSION_CHARGE_METHOD_NONE) { + if ($suspensionCalculationMethod == SUSPENSION_CALCULATION_METHOD_VALUE) { + if (!empty($suspension['suspension_netflag'])) { + if (!empty($suspension['suspension_net_value'])) { + if (!preg_match('/^[0-9\.,]+$/', $suspension['suspension_net_value'])) { + $error['suspension_net_value'] = trans('Incorrect value!'); + } + } else { + if (!preg_match('/^[0-9\.,]+$/', ConfigHelper::getConfig('suspensions.default_value', 0))) { + $error['suspension_net_value'] = trans('Incorrect value!'); + } + } + } else { + if (!empty($suspension['suspension_gross_value'])) { + if (!preg_match('/^[0-9\.,]+$/', $suspension['suspension_gross_value'])) { + $error['suspension_gross_value'] = trans('Incorrect value!'); + } + } else { + if (!preg_match('/^[0-9\.,]+$/', ConfigHelper::getConfig('suspensions.default_value', 0))) { + $error['suspension_gross_value'] = trans('Incorrect value!'); + } + } + } + + if (!isset($GLOBALS['CURRENCIES'][$suspension['currency']])) { + $error['currency'] = trans('Invalid currency selection!'); + } + } + if ($suspensionCalculationMethod == SUSPENSION_CALCULATION_METHOD_PERCENTAGE) { + if (!empty($suspension['suspension_percentage'])) { + if (!preg_match('/^[0-9\.,]+$/', $suspension['suspension_percentage'])) { + $error['suspension_percentage'] = trans('Incorrect value!'); + } + } else { + if (!preg_match('/^[0-9\.,]+$/', ConfigHelper::getConfig('suspensions.default_percentage', 0))) { + $error['suspension_percentage'] = trans('Incorrect value!'); + } + } + } + } + //endregion + + if (empty($error)) { + //region Dates Validation + if (empty($suspension['datefrom'])) { + if ($suspensionChargeMethod == SUSPENSION_CHARGE_METHOD_ONCE) { + $error['datefrom'] = trans('Date from is required!'); + } else { + $from = 0; + } + } elseif (preg_match('/^[0-9]+$/', $suspension['datefrom'])) { + $from = $suspension['datefrom']; + } else { + $error['datefrom'] = trans('Incorrect date format! Enter date in YYYY/MM/DD format!'); + } + if (empty($suspension['dateto'])) { + $to = 0; + } elseif (preg_match('/^[0-9]+$/', $suspension['dateto'])) { + $to = strtotime('+ 1 day', $suspension['dateto']) - 1; + } else { + $error['dateto'] = trans('Incorrect date format! Enter date in YYYY/MM/DD format!'); + } + if (isset($from) && isset($to)) { + if ($to < $from && $to != 0 && $from != 0) { + $error['dateto'] = trans('Start date can\'t be greater than end date!'); + } + } + //endregion + + if (empty($error)) { + if (!empty($suspension['existing_suspend_all'])) { + $error['suspend_all'] = trans('This suspension exists already!'); + } + + if (!empty($suspension['existing_suspensions'])) { + foreach ($suspension['suspended_assignments'] as $skey => $asuspension) { + if (isset($suspension['existing_suspensions'][$skey])) { + $error['suspensions'] = trans('Assignment is suspended already!'); + break; + } + } + } + } + } + } + + return $error; + } + public function CheckSchemaModifiedValues(&$data) { $schemaid = $data['schemaid']; @@ -1751,7 +2744,7 @@ public function UpdateExistingAssignments($data) if ($data['existing_assignments']['operation'] == EXISTINGASSIGNMENT_DELETE) { $this->DeleteAssignment($aid); } else { - $this->SuspendAssignment($aid); + $this->suspendAssignment($aid); } } } @@ -1814,36 +2807,158 @@ public function UpdateExistingAssignments($data) } } - public function SuspendAssignment($id, $suspend = true) + public function suspendAssignment($assignment_id) { - if ($this->syslog) { - $assign = $this->db->GetRow('SELECT id, tariffid, liabilityid, customerid FROM assignments WHERE id = ?', array($id)); - $args = array( - SYSLOG::RES_ASSIGN => $assign['id'], - SYSLOG::RES_TARIFF => $assign['tariffid'], - SYSLOG::RES_LIAB => $assign['liabilityid'], - SYSLOG::RES_CUST => $assign['customerid'], - 'suspend' => ($suspend ? 1 : 0) - ); - $this->syslog->AddMessage(SYSLOG::RES_ASSIGN, SYSLOG::OPER_UPDATE, $args); + $assignmentId = !empty($assignment_id) && is_numeric($assignment_id) ? intval($assignment_id) : null; + + if (!empty($assignmentId) && $assignmentId == $assignment_id) { + $this->db->BeginTrans(); + $this->db->LockTables(array('suspensions', 'assignmentsuspensions')); + + $assignment = $this->getAssignment($assignmentId); + + if (empty($assignment['suspension_suspend_all'])) { + if (empty($assignment['suspended'])) { + $args = array( + 'at' => $assignment['at'], + 'datefrom' => $assignment['datefrom'], + 'dateto' => $assignment['dateto'], + 'chargemethod' => $assignment['assignment_charge_method'], + 'calculationmethod' => null, + 'value' => null, + 'percentage' => null, + 'netflag' => $assignment['netflag'], + 'currency' => $assignment['currency'], + 'taxid' => $assignment['taxid'], + 'note' => null, + 'customerid' => null, + ); + + $suspensionId = $this->addSuspension($args); + + if (!empty($suspensionId)) { + $args = array( + 'suspension_id' => $suspensionId, + 'assignment_id' => $assignmentId, + 'customerid' => $assignment['customerid'], + ); + + $this->addAssignmentSuspension($args); + } + } + } + + $this->db->UnLockTables(); + $this->db->CommitTrans(); } - return $this->db->Execute('UPDATE assignments SET suspended=? WHERE id=?', array($suspend ? 1 : 0, $id)); } public function toggleAssignmentSuspension($id) { - if ($this->syslog) { - $assign = $this->db->GetRow('SELECT id, tariffid, liabilityid, customerid, suspended FROM assignments WHERE id = ?', array($id)); - $args = array( - SYSLOG::RES_ASSIGN => $assign['id'], - SYSLOG::RES_TARIFF => $assign['tariffid'], - SYSLOG::RES_LIAB => $assign['liabilityid'], - SYSLOG::RES_CUST => $assign['customerid'], - 'suspend' => empty($assign['suspend']) ? 1 : 0, - ); - $this->syslog->AddMessage(SYSLOG::RES_ASSIGN, SYSLOG::OPER_UPDATE, $args); + $assignmentId = !empty($id) && is_numeric($id) ? intval($id) : null; + + if (!empty($assignmentId) && $assignmentId == $id) { + $today = strtotime('today'); + + $this->db->BeginTrans(); + $this->db->LockTables(array('suspensions', 'assignmentsuspensions')); + + $assignment = $this->getAssignment($assignmentId); + $defaultSuspensionCalculationMethod = ConfigHelper::getConfig('suspensions.default_calculation_method', SUSPENSION_CALCULATION_METHOD_PERCENTAGE); + + if (empty($assignment['suspension_suspend_all'])) { + if (empty($assignment['suspended'])) { + [$year, $month, $dom] = explode('/', date('Y/n/j', $today)); + $at = null; + $netflag = null; + $currency = null; + $taxid = null; + + switch ($assignment['period']) { + case DISPOSABLE: + $charge_method = SUSPENSION_CHARGE_METHOD_ONCE; + $at = $assignment['at']; + break; + case DAILY: + $charge_method = SUSPENSION_CHARGE_METHOD_PERIODICALLY; + $at = $dom; + break; + case WEEKLY: + $charge_method = SUSPENSION_CHARGE_METHOD_PERIODICALLY; + $atdate = date('Y/n/j', mktime(0, 0, 0, 0, $assignment['at'] + 5, 0)); + [$wyear, $wmonth, $wdom] = explode('/', date('Y/n/j', $atdate)); + $at = $wdom; + break; + case MONTHLY: + $charge_method = SUSPENSION_CHARGE_METHOD_PERIODICALLY; + $at = $assignment['at']; + break; + case QUARTERLY: + $charge_method = SUSPENSION_CHARGE_METHOD_PERIODICALLY; + $atdate = sprintf('%02d/%02d', $assignment['at'] % 100, $assignment['at'] / 100 + 1); + [$qday, $qmonth] = explode('/', $atdate); + $at = $qday; + break; + case HALFYEARLY: + $charge_method = SUSPENSION_CHARGE_METHOD_PERIODICALLY; + $atdate = sprintf('%02d/%02d', $assignment['at'] % 100, $assignment['at'] / 100 + 1); + [$hday, $hmonth] = explode('/', $atdate); + $at = $hday; + break; + case YEARLY: + $charge_method = SUSPENSION_CHARGE_METHOD_PERIODICALLY; + $atdate = date('d/m', ($assignment['at'] - 1) * 86400); + [$yday, $tmonth] = explode('/', $atdate); + $at = $yday; + break; + } + + if ($defaultSuspensionCalculationMethod == SUSPENSION_CALCULATION_METHOD_VALUE) { + $netflag = intval($assignment['netflag']); + $currency = $assignment['currency']; + $taxid = intval($assignment['taxid']); + } + + $args = array( + 'at' => $at, + 'datefrom' => $assignment['datefrom'], + 'dateto' => $assignment['dateto'], + 'chargemethod' => $charge_method, + 'calculationmethod' => $defaultSuspensionCalculationMethod, + 'value' => null, + 'percentage' => null, + 'netflag' => $netflag, + 'currency' => $currency, + 'taxid' => $taxid, + 'note' => null, + 'customerid' => null, + ); + + $suspensionId = $this->addSuspension($args); + + if (!empty($suspensionId)) { + $args = array( + 'suspension_id' => $suspensionId, + 'assignment_id' => $assignmentId, + 'customerid' => $assignment['customerid'], + ); + + $this->addAssignmentSuspension($args); + } + } else { + $args = array( + 'suspension_id' => $assignment['suspension_id'], + 'assignment_id' => $assignmentId, + 'customerid' => $assignment['customerid'], + ); + + $this->deleteAssignmentSuspension($args); + } + } + + $this->db->UnLockTables(); + $this->db->CommitTrans(); } - return $this->db->Execute('UPDATE assignments SET suspended = (suspended + 1) % 2 WHERE id = ?', array($id)); } public function GetTradeDocumentArchiveStats($ids) @@ -3360,14 +4475,24 @@ public function GetTariff($id, $network = null) ); $result['customers'] = $this->db->GetAll('SELECT c.id AS id, COUNT(c.id) AS cnt, - COUNT(CASE WHEN s.customerid IS NULL AND commited = 1 AND suspended = 0 AND datefrom < ?NOW? AND (dateto = 0 OR dateto > ?NOW?) THEN 1 ELSE NULL END) AS active, ' + COUNT(CASE WHEN s.customerid IS NULL AND commited = 1 AND vas1.suspended IS NULL AND datefrom < ?NOW? AND (dateto = 0 OR dateto > ?NOW?) THEN 1 ELSE NULL END) AS active, ' . $this->db->Concat('c.lastname', "' '", 'c.name') . ' AS customername ' . ($network ? ', COUNT(vnodes.id) AS nodescount ' : '') - . 'FROM assignments, customerview c + . ' + FROM assignments + LEFT JOIN vassignmentsuspensions vas1 ON vas1.suspension_assignment_id = assignments.id + AND vas1.suspension_datefrom <= ?NOW? + AND (vas1.suspension_dateto >= ?NOW? OR vas1.suspension_dateto = 0) + AND assignments.datefrom <= ?NOW? AND (assignments.dateto >= ?NOW? OR assignments.dateto = 0), + customerview c LEFT JOIN ( SELECT DISTINCT a.customerid FROM assignments a - WHERE a.tariffid IS NULL AND a.liabilityid IS NULL + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) + WHERE vas.suspension_suspend_all = 1 AND a.datefrom < ?NOW? AND (a.dateto = 0 OR a.dateto > ?NOW?) ) s ON s.customerid = c.id ' . ($network ? 'LEFT JOIN vnodes ON (c.id = vnodes.ownerid) ' : '') @@ -3412,18 +4537,12 @@ public function GetTariff($id, $network = null) t.currency FROM assignments a JOIN tariffs t ON (t.id = a.tariffid) - WHERE t.id = ? AND a.commited = 1 AND ( - a.suspended = 1 - OR a.datefrom > ?NOW? - OR (a.dateto <= ?NOW? AND a.dateto != 0) - OR EXISTS ( - SELECT 1 FROM assignments b - WHERE b.customerid = a.customerid - AND liabilityid IS NULL AND tariffid IS NULL - AND b.datefrom <= ?NOW? AND (b.dateto > ?NOW? OR b.dateto = 0) - ) - ) - GROUP BY t.currency', 'currency', array($id)); + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) + WHERE t.id = ? AND a.commited = 1 AND vas.suspended IS NOT NULL + GROUP BY t.currency', 'currency', array($id)); $all = $this->db->GetAllByKey('SELECT COUNT(*) AS count, SUM( @@ -5309,7 +6428,11 @@ public function isTariffEditable($id) LEFT JOIN ( SELECT DISTINCT a.customerid FROM assignments a - WHERE a.tariffid IS NULL AND a.liabilityid IS NULL + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) + WHERE vas.suspension_suspend_all = 1 AND a.datefrom < ?NOW? AND (a.dateto = 0 OR a.dateto > ?NOW?) ) s ON s.customerid = assignments.customerid WHERE tariffid = ?', diff --git a/lib/LMSManagers/LMSFinanceManagerInterface.php b/lib/LMSManagers/LMSFinanceManagerInterface.php index 654c425ad0..a7aaafc1db 100644 --- a/lib/LMSManagers/LMSFinanceManagerInterface.php +++ b/lib/LMSManagers/LMSFinanceManagerInterface.php @@ -36,7 +36,13 @@ public function GetPromotionNameByID($id); public function GetCustomerTariffsValue($id); - public function GetCustomerAssignments($id, $show_expired = false, $show_approved = true); + public function getCustomerAssignments($customer_id, $params = array()); + + public function getAssignments($params = array()); + + public function getAssignment($assignment_id); + + public function getSuspensions($params = array()); public function GetCustomerServiceSummary($id); @@ -46,11 +52,23 @@ public function AddAssignment($data); public function ValidateAssignment($data); + public function ValidateSuspension($params = array()); + public function CheckSchemaModifiedValues(&$data); public function UpdateExistingAssignments($data); - public function SuspendAssignment($id, $suspend = true); + public function addSuspension($params = array()); + + public function updateSuspension($params = array()); + + public function addAssignmentSuspension($params = array()); + + public function deleteSuspension($suspension_id); + + public function deleteAssignmentSuspension($params = array()); + + public function suspendAssignment($assignment_id); public function toggleAssignmentSuspension($id); diff --git a/lib/LMSManagers/LMSNodeManager.php b/lib/LMSManagers/LMSNodeManager.php index f15cee2d71..c9f049015f 100644 --- a/lib/LMSManagers/LMSNodeManager.php +++ b/lib/LMSManagers/LMSNodeManager.php @@ -615,7 +615,13 @@ public function GetNodeList(array $params = array()) . ($status == 4 ? ' AND n.id NOT IN ( SELECT DISTINCT nodeid FROM nodeassignments na JOIN assignments a ON a.id = na.assignmentid - WHERE a.suspended = 0 AND a.commited = 1 AND a.period IN (' . implode(',', array(YEARLY, HALFYEARLY, QUARTERLY, MONTHLY, DISPOSABLE)) . ') + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) + WHERE vas.suspended IS NULL + AND a.commited = 1 + AND a.period IN (' . implode(',', array(YEARLY, HALFYEARLY, QUARTERLY, MONTHLY, DISPOSABLE)) . ') AND a.datefrom <= ?NOW? AND (a.dateto = 0 OR a.dateto >= ?NOW?) )' : '') . ($status == 5 ? ' AND n.location_city IS NULL' : '') diff --git a/lib/SYSLOG.class.php b/lib/SYSLOG.class.php index 48510bb26f..6ee749b519 100644 --- a/lib/SYSLOG.class.php +++ b/lib/SYSLOG.class.php @@ -97,6 +97,8 @@ class SYSLOG public const RES_TICKET_MESSAGE = 69; public const RES_QUEUE = 70; + public const RES_SUSPENSION = 71; + public const OPER_ADD = 1; public const OPER_DELETE = 2; public const OPER_UPDATE = 3; @@ -113,6 +115,7 @@ class SYSLOG private static $resources = array( self::RES_USER => 'user', self::RES_ASSIGN => 'assignment', + self::RES_SUSPENSION => 'suspension', self::RES_LIAB => 'liability', self::RES_NODEASSIGN => 'node assignment', self::RES_NODE => 'node', @@ -185,6 +188,7 @@ class SYSLOG private static $resource_keys = array( self::RES_USER => 'userid', self::RES_ASSIGN => 'assignmentid', + self::RES_SUSPENSION => 'suspensionid', self::RES_LIAB => 'liabilityid', self::RES_NODEASSIGN => 'nodeassignmentid', self::RES_NODE => 'nodeid', diff --git a/lib/SmartyPlugins/block.tab_header.php b/lib/SmartyPlugins/block.tab_header.php index a3bd6ec97a..b1f3c809f7 100644 --- a/lib/SmartyPlugins/block.tab_header.php +++ b/lib/SmartyPlugins/block.tab_header.php @@ -28,9 +28,10 @@ function smarty_block_tab_header($params, $content, $template, $repeat) { if (!$repeat) { $content_id = $params['content_id'] ?? null; + $suspensions_content_id = $params['suspensions_content_id'] ?? null; return ' -
' . $content . ' diff --git a/lib/common.php b/lib/common.php index 79c0ebe105..c4f8dd042e 100644 --- a/lib/common.php +++ b/lib/common.php @@ -495,7 +495,7 @@ function r_trim($array) foreach ($array as $key => $value) { if (is_array($value)) { $array[$key] = r_trim($value); - } else { + } elseif (!is_null($value)) { $array[$key] = trim($value); } } diff --git a/lib/config.php b/lib/config.php index c0025ea25a..ad5aa13cd4 100644 --- a/lib/config.php +++ b/lib/config.php @@ -123,8 +123,12 @@ 'paytime' => 14, 'paytype' => 1, // cash ), - 'finances' => array( - 'suspension_percentage' => 0, + 'suspensions' => array( + 'default_charge_method' => 2, + 'default_calculation_method' => 1, + 'default_percentage' => 0, + 'default_value' => 0, + 'default_netflag' => 0, ), 'receipts' => array( 'template_file' => 'receipt.html', diff --git a/lib/definitions.php b/lib/definitions.php index 0033c3922b..b38f837ca9 100644 --- a/lib/definitions.php +++ b/lib/definitions.php @@ -1666,6 +1666,25 @@ function ($link_technology) { 5 => 'permanent residence card', ); +// assignment suspensions +const SUSPENSION_CHARGE_METHOD_NONE = 1, +SUSPENSION_CHARGE_METHOD_ONCE = 2, +SUSPENSION_CHARGE_METHOD_PERIODICALLY = 3; + +$SUSPENSION_CHARGE_METHODS = array( + SUSPENSION_CHARGE_METHOD_NONE => trans('None'), + SUSPENSION_CHARGE_METHOD_ONCE => trans('Once'), + SUSPENSION_CHARGE_METHOD_PERIODICALLY => trans('Periodically'), +); + +const SUSPENSION_CALCULATION_METHOD_PERCENTAGE = 1, +SUSPENSION_CALCULATION_METHOD_VALUE = 2; + +$SUSPENSION_CALCULATION_METHODS = array( + SUSPENSION_CALCULATION_METHOD_PERCENTAGE => trans('Percentage calculated on each liability'), + SUSPENSION_CALCULATION_METHOD_VALUE => trans('Amount calculated on all liabilities'), +); + if (isset($SMARTY)) { $SMARTY->assign( array( @@ -1711,6 +1730,8 @@ function ($link_technology) { '_CURRENCIES' => $CURRENCIES, '_TAX_CATEGORIES' => $TAX_CATEGORIES, '_IDENTITY_TYPES' => $IDENTITY_TYPES, + '_SUSPENSION_CHARGE_METHODS' => $SUSPENSION_CHARGE_METHODS, + '_SUSPENSION_CALCULATION_METHODS' => $SUSPENSION_CALCULATION_METHODS, ) ); $SMARTY->assignByRef('_EVENTTYPES', $EVENTTYPES); diff --git a/lib/locale/pl_PL/strings.php b/lib/locale/pl_PL/strings.php index 2ef152f263..4f72bb0bb5 100644 --- a/lib/locale/pl_PL/strings.php +++ b/lib/locale/pl_PL/strings.php @@ -24,6 +24,37 @@ * $Id$ */ +$_LANG['Suspension'] = 'Zawieszenie'; +$_LANG['Suspension of all'] = 'Zawieszenie wszystkich'; +$_LANG['Suspension value'] = 'Wartość zawieszenia'; +$_LANG['All customer liabilities are suspended'] = 'Wszystkie zobowiązania klienta są zawieszone'; +$_LANG['Suspentions of the customer liabilities'] = 'Zawieszenia zobowiązań klienta'; +$_LANG['Suspended liabilities'] = 'Zawieszone zobowiązania'; +$_LANG['No assignment has been selected!'] = 'Nie zostało wybrane żadne zobowiązanie!'; +$_LANG['Suspended assignments period'] = 'Okres zawieszanych zobowiązań'; +$_LANG['Current suspensions total'] = 'Bieżące zawieszenia razem'; +$_LANG['Amount'] = 'Kwota'; +$_LANG['Percentage'] = 'Procent'; +$_LANG['Charge method'] = 'Metoda naliczania'; +$_LANG['Calcullation method'] = 'Metoda obliczania'; +$_LANG['Accounting'] = 'Rozliczenie'; +$_LANG['Default'] = 'Domyślnie'; +$_LANG['None'] = 'Bez naliczania'; +$_LANG['Once'] = 'Jednorazowo'; +$_LANG['Periodically'] = 'Okresowo'; +$_LANG['Assignment suspension'] = 'Zawieszenie zobowiązania'; +$_LANG['Liabilities'] = 'Zobowiązania'; +$_LANG['— selected liabilities suspending —'] = '— zawieszenie wybranych zobowiązań —'; +$_LANG['Suspended'] = 'Zawieszone'; +$_LANG['Suspensions'] = 'Zawieszenia'; +$_LANG['Percentage calculated on each liability'] = 'Procent liczony od każdego zobowiązania'; +$_LANG['Amount calculated on all liabilities'] = 'Kwota liczona od wszystkich zobowiązań'; +$_LANG['Are you sure, you want to delete this suspension?'] = 'Jesteś pewien, że chcesz usunąć to zawieszenie?'; +$_LANG['Date from is required!'] = 'Data od jest wymagana!'; +$_LANG['Delete suspension'] = 'Usuń zawieszenie'; +$_LANG['Edit suspension'] = 'Edytuj zawieszenie'; +$_LANG['suspension'] = 'zawieszenie'; + $_LANG['Check in PESEL Reservation Registry'] = 'Sprawdź w Rejestrze Zastrzeżeń PESEL'; $_LANG['Empty PESEL Reservation Registry API secret key!'] = 'Pusty klucz API Rejestru Zastrzeżeń PESEL!'; $_LANG['Incorrect PESEL format!'] = 'Błędny format PESEL!'; @@ -1828,6 +1859,9 @@ $_LANG['Period'] = 'Okres'; $_LANG['Allow nodes addition with duplicated MAC address (not checking that some computer have that MAC yet). Default: 0 (off).'] = 'Zezwolenie na dodawanie komputerów ze zduplikowanymi adresami MAC (LMS nie sprawdza, czy inny komputer nie ma już przypisanego danego adresu MAC). Domyślnie: 0 (wyłączone).'; $_LANG['Percentage of suspended liabilities. Default: 0'] = 'Wartość procentowa zawieszonych zobowiązań. Domyślnie: 0'; +$_LANG['Amount of suspended liabilities. Default: 0'] = 'Kwota zawieszonych zobowiązań. Domyślnie: 0'; +$_LANG['Charge method for assignment suspension. Default: none'] = 'Metoda naliczania zawieszenia zobowiązań. Domyślnie: brak'; +$_LANG['Calculation method for assignment suspension. Default: percent'] = 'Metoda obliczania zawieszenia zobowiązań. Domyślnie: procent'; $_LANG['Permissions:'] = 'Prawa:'; $_LANG['Permissions'] = 'Uprawnienia'; $_LANG['Phone'] = 'Telefon'; diff --git a/lib/upgradedb/mysql.2024052400.php b/lib/upgradedb/mysql.2024052400.php new file mode 100644 index 0000000000..13dcb58d72 --- /dev/null +++ b/lib/upgradedb/mysql.2024052400.php @@ -0,0 +1,883 @@ +BeginTrans(); + +//region Suspension configs +if (!$this->GetOne( + 'SELECT 1 FROM uiconfig WHERE section = ? AND var = ?', + array( + 'suspensions', + 'default_percentage', + ) +)) { + $this->Execute( + 'INSERT INTO uiconfig (section, var, value, disabled) VALUES (?, ?, ?, ?)', + array( + 'suspensions', + 'default_percentage', + '0', + 0, + ) + ); +} + +if (!$this->GetOne( + 'SELECT 1 FROM uiconfig WHERE section = ? AND var = ?', + array( + 'suspensions', + 'default_value', + ) +)) { + $this->Execute( + 'INSERT INTO uiconfig (section, var, value, disabled) VALUES (?, ?, ?, ?)', + array( + 'suspensions', + 'default_value', + '0', + 0, + ) + ); +} + +if (!$this->GetOne( + 'SELECT 1 FROM uiconfig WHERE section = ? AND var = ?', + array( + 'suspensions', + 'default_netflag', + ) +)) { + $this->Execute( + 'INSERT INTO uiconfig (section, var, value, disabled) VALUES (?, ?, ?, ?)', + array( + 'suspensions', + 'default_netflag', + '0', + 0, + ) + ); +} + +if (!$this->GetOne( + 'SELECT 1 FROM uiconfig WHERE section = ? AND var = ?', + array( + 'suspensions', + 'default_charge_method', + ) +)) { + $this->Execute( + 'INSERT INTO uiconfig (section, var, value, description, disabled) VALUES (?, ?, ?, ?, ?)', + array( + 'suspensions', + 'default_charge_method', + '2', + '[1-none|2-once|3-periodically]', + 0, + ) + ); +} + +if (!$this->GetOne( + 'SELECT 1 FROM uiconfig WHERE section = ? AND var = ?', + array( + 'suspensions', + 'default_calculation_method', + ) +)) { + $this->Execute( + 'INSERT INTO uiconfig (section, var, value, description, disabled) VALUES (?, ?, ?, ?, ?)', + array( + 'suspensions', + 'default_calculation_method', + '1', + '[1-percentage|2-value]', + 0, + ) + ); +} +//endregion + +/* -------------------------------------------------------- + Structure of table "suspensions" +-------------------------------------------------------- */ +if (!$this->ResourceExists('suspensions', LMSDB::RESOURCE_TYPE_TABLE)) { + $this->Execute( + "CREATE TABLE suspensions( + id int(11) NOT NULL auto_increment, + at int(11) DEFAULT NULL, + datefrom int(11) DEFAULT 0 NOT NULL, + dateto int(11) DEFAULT 0 NOT NULL, + chargemethod smallint NOT NULL, + calculationmethod smallint NOT NULL, + value numeric(9, 3) DEFAULT NULL, + percentage numeric(3, 2) DEFAULT NULL, + netflag smallint DEFAULT NULL, + currency varchar(3) DEFAULT NULL, + note text DEFAULT NULL, + customerid int(11) DEFAULT NULL, + taxid int(11) DEFAULT NULL, + PRIMARY KEY(id), + CONSTRAINT suspensions_customerid_fkey + FOREIGN KEY (customerid) REFERENCES customers(id) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT suspensions_taxid_fkey + FOREIGN KEY (taxid) REFERENCES taxes(id) ON DELETE CASCADE ON UPDATE CASCADE + )" + ); +} + +/* -------------------------------------------------------- + Structure of table "assignmentsuspensions" +-------------------------------------------------------- */ +if (!$this->ResourceExists('assignmentsuspensions', LMSDB::RESOURCE_TYPE_TABLE)) { + $this->Execute( + "CREATE TABLE assignmentsuspensions( + id int(11) NOT NULL auto_increment, + suspensionid int(11) NOT NULL, + assignmentid int(11) NOT NULL, + PRIMARY KEY(id), + CONSTRAINT suspensions_suspensionid_fkey + FOREIGN KEY (suspensionid) REFERENCES suspensions(id) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT assignments_assignmentid_fkey + FOREIGN KEY (assignmentid) REFERENCES assignments(id) ON DELETE CASCADE ON UPDATE CASCADE, + UNIQUE KEY assignmentsuspensions_assignmentid_suspensionid_ukey (assignmentid, suspensionid) + )" + ); +} + +//transform old assignment suspensions to new ones +define('DISPOSABLE', 0); +define('DAILY', 1); +define('WEEKLY', 2); +define('MONTHLY', 3); +define('QUARTERLY', 4); +define('HALFYEARLY', 7); +define('YEARLY', 5); +define('SUSPENSION_CHARGE_METHOD_ONCE', 2); +define('SUSPENSION_CHARGE_METHOD_PERIODICALLY', 3); +define('TARIFF_FLAG_NET_ACCOUNT', 16); +define('LIABILITY_FLAG_NET_ACCOUT', 16); +define('SUSPENSION_CALCULATION_METHOD_PERCENTAGE', 1); + +$allSuspendedAssignments = $this->GetAll( + 'SELECT + a.id, + a.at, + a.datefrom, + a.dateto, + a.period, + a.customerid, + (CASE WHEN a.period = ? THEN ? ELSE ? END) AS assignment_charge_method + FROM assignments a + WHERE + a.tariffid IS NULL AND a.liabilityid IS NULL + ORDER BY a.id DESC', + array( + DISPOSABLE, + SUSPENSION_CHARGE_METHOD_ONCE, + SUSPENSION_CHARGE_METHOD_PERIODICALLY, + TARIFF_FLAG_NET_ACCOUNT, + LIABILITY_FLAG_NET_ACCOUT, + TARIFF_FLAG_NET_ACCOUNT, + LIABILITY_FLAG_NET_ACCOUT, + ) +); + +if (!empty($allSuspendedAssignments)) { + $today = strtotime('today'); + foreach ($allSuspendedAssignments as $allSuspendedAssignment) { + $suspensionExist = $this->getOne('SELECT customerid FROM suspensions WHERE customerid = ?', array($allSuspendedAssignment['customerid'])); + if (empty($suspensionExist)) { + $assignments = $this->getAll( + 'SELECT + a.id, + a.at, + a.datefrom, + a.dateto, + a.period, + a.customerid, + (CASE WHEN a.period = ? THEN ? ELSE ? END) AS assignment_charge_method + FROM assignments a + WHERE + a.suspended = 0 + AND a.tariffid IS NOT NULL OR a.liabilityid IS NOT NULL + AND a.customerid = ?', + array( + DISPOSABLE, + SUSPENSION_CHARGE_METHOD_ONCE, + SUSPENSION_CHARGE_METHOD_PERIODICALLY, + $allSuspendedAssignment['customerid'] + ) + ); + + if (!empty($assignments)) { + foreach ($assignments as $row) { + switch ($row['assignment_charge_method']) { + case SUSPENSION_CHARGE_METHOD_ONCE: + $startdate = $row['datefrom'] > $today ? $row['datefrom'] : $today; + [$year, $month, $dom] = explode('/', date('Y/n/j', $startdate)); + $commingPayDate = 0; + $commingPayTimestamp = 0; + + switch ($row['period']) { + case DISPOSABLE: + $commingPayTimestamp = $row['at']; + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + case MONTHLY: + $commingPayTimestamp = mktime(0, 0, 0, $month, $row['at'], $year); + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + case QUARTERLY: + [$d, $m] = explode('/', $row['at']); + $quarterlyDate1 = mktime(0, 0, 0, $m, $d, $year); + $quarterlyDate2 = strtotime('+3 months', $quarterlyDate1); + $quarterlyDate3 = strtotime('+6 months', $quarterlyDate1); + $quarterlyDate4 = strtotime('+9 months', $quarterlyDate1); + + if ($quarterlyDate1 <= $row['datefrom']) { + if ($quarterlyDate2 <= $row['datefrom']) { + if ($quarterlyDate3 <= $row['datefrom']) { + if ($quarterlyDate4 <= $row['datefrom']) { + $commingPayTimestamp = strtotime('+3 months', $quarterlyDate4); + } else { + $commingPayTimestamp = $quarterlyDate3; + } + } else { + $commingPayTimestamp = $quarterlyDate3; + } + } else { + $commingPayTimestamp = $quarterlyDate2; + } + } else { + $commingPayTimestamp = $quarterlyDate1; + } + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + case HALFYEARLY: + [$d, $m] = explode('/', $row['at']); + $halfyearlyDate1 = mktime(0, 0, 0, $m, $d, $year); + $halfyearlyDate2 = strtotime('+6 months', $halfyearlyDate1); + + if ($halfyearlyDate1 <= $row['datefrom']) { + if ($halfyearlyDate2 <= $row['datefrom']) { + $commingPayTimestamp = strtotime('+6 months', $halfyearlyDate2); + } else { + $commingPayTimestamp = $halfyearlyDate2; + } + } else { + $commingPayTimestamp = $halfyearlyDate1; + } + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + case YEARLY: + [$d, $m] = explode('/', $row['at']); + $yearlyDate = mktime(0, 0, 0, $m, $d, $year); + if ($yearlyDate <= $row['datefrom']) { + $commingPayTimestamp = strtotime('+1 year', $yearlyDate); + } else { + $commingPayTimestamp = $yearlyDate; + } + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + } + + if (!isset($suspension_at) || $commingPayTimestamp < $suspension_at) { + $suspension_at = $commingPayTimestamp; + } + break; + case SUSPENSION_CHARGE_METHOD_PERIODICALLY: + $startdate = $row['datefrom'] > $today ? $row['datefrom'] : $today; + $dom = date('j', $startdate); + $commingPayDay = 0; + + switch ($row['period']) { + case DISPOSABLE: + $commingPayDay = date('j', $row['at']); + break; + case MONTHLY: + $commingPayDay = $row['at']; + break; + case QUARTERLY: + case HALFYEARLY: + case YEARLY: + [$d, $m] = explode('/', $row['at']); + $commingPayDay = $d; + break; + } + + if (!isset($suspension_at) || $commingPayDay < $suspension_at) { + $suspension_at = $commingPayDay; + } + break; + } + } + } + + $args = array( + 'at' => $suspension_at, + 'datefrom' => $allSuspendedAssignment['datefrom'], + 'dateto' => $allSuspendedAssignment['dateto'], + 'chargemethod' => SUSPENSION_CHARGE_METHOD_PERIODICALLY, + 'calculationmethod' => SUSPENSION_CALCULATION_METHOD_PERCENTAGE, + 'customerid' => $allSuspendedAssignment['customerid'] + ); + + $this->Execute( + "INSERT INTO suspensions (at, datefrom, dateto, chargemethod, calculationmethod, customerid) + VALUES (?, ?, ?, ?, ?, ?)", + array_values($args) + ); + + $this->Execute("DELETE FROM assignments WHERE id = ?", array($allSuspendedAssignment['id'])); + } + } +} + +$suspendedAssignments = $this->GetAll( + 'SELECT + a.id, + a.at, + a.datefrom, + a.dateto, + a.period, + (CASE WHEN a.liabilityid IS NULL THEN t.currency ELSE l.currency END) AS currency, + (CASE WHEN a.liabilityid IS NULL THEN t.taxid ELSE l.taxid END) AS taxid, + (CASE WHEN a.liabilityid IS NULL + THEN (CASE WHEN t.flags & ? > 0 THEN 1 ELSE 0 END) + ELSE (CASE WHEN l.flags & ? > 0 THEN 1 ELSE 0 END) + END) AS netflag, + (CASE WHEN a.tariffid IS NULL AND a.liabilityid IS NULL THEN 1 ELSE 0 END) AS allsuspended + FROM assignments a + LEFT JOIN ( + SELECT tariffs.*, + taxes.value AS taxrate, + (CASE WHEN tariffs.flags & ? > 0 THEN tariffs.netvalue ELSE tariffs.value END) AS tvalue + FROM tariffs + JOIN taxes ON taxes.id = tariffs.taxid + ) t ON a.tariffid = t.id + LEFT JOIN ( + SELECT liabilities.*, + taxes.value AS taxrate, + (CASE WHEN liabilities.flags & ? > 0 THEN liabilities.netvalue ELSE liabilities.value END) AS lvalue + FROM liabilities + JOIN taxes ON taxes.id = liabilities.taxid + ) l ON a.liabilityid = l.id + WHERE suspended = 1', + array( + TARIFF_FLAG_NET_ACCOUNT, + LIABILITY_FLAG_NET_ACCOUT, + TARIFF_FLAG_NET_ACCOUNT, + LIABILITY_FLAG_NET_ACCOUT, + ) +); + +if (!empty($suspendedAssignments)) { + $today = strtotime('today'); + [$year, $month, $dom] = explode('/', date('Y/n/j', $today)); + foreach ($suspendedAssignments as $suspendedAssignment) { + $at = null; + switch ($suspendedAssignment['period']) { + case DISPOSABLE: + $charge_method = SUSPENSION_CHARGE_METHOD_ONCE; + $at = $suspendedAssignment['at']; + break; + case DAILY: + $charge_method = SUSPENSION_CHARGE_METHOD_PERIODICALLY; + $at = $dom; + break; + case WEEKLY: + $charge_method = SUSPENSION_CHARGE_METHOD_PERIODICALLY; + $atdate = date('Y/n/j', mktime(0, 0, 0, 0, $suspendedAssignment['at'] + 5, 0)); + [$wyear, $wmonth, $wdom] = explode('/', date('Y/n/j', $atdate)); + $at = $wdom; + break; + case MONTHLY: + $charge_method = SUSPENSION_CHARGE_METHOD_PERIODICALLY; + $at = $suspendedAssignment['at']; + break; + case QUARTERLY: + $charge_method = SUSPENSION_CHARGE_METHOD_PERIODICALLY; + $atdate = sprintf('%02d/%02d', $suspendedAssignment['at'] % 100, $suspendedAssignment['at'] / 100 + 1); + [$qday, $qmonth] = explode('/', $atdate); + $at = $qday; + break; + case HALFYEARLY: + $charge_method = SUSPENSION_CHARGE_METHOD_PERIODICALLY; + $atdate = sprintf('%02d/%02d', $suspendedAssignment['at'] % 100, $suspendedAssignment['at'] / 100 + 1); + [$hday, $hmonth] = explode('/', $atdate); + $at = $hday; + break; + case YEARLY: + $charge_method = SUSPENSION_CHARGE_METHOD_PERIODICALLY; + $atdate = date('d/m', ($suspendedAssignment['at'] - 1) * 86400); + [$yday, $tmonth] = explode('/', $atdate); + $at = $yday; + break; + } + + $args = array( + 'at' => $at, + 'datefrom' => $suspendedAssignment['datefrom'], + 'dateto' => $suspendedAssignment['dateto'], + 'chargemethod' => $charge_method, + 'calculationmethod' => SUSPENSION_CALCULATION_METHOD_PERCENTAGE, + ); + + $this->Execute( + "INSERT INTO suspensions (at, datefrom, dateto, chargemethod, calculationmethod) + VALUES (?, ?, ?, ?, ?)", + array_values($args) + ); + + $suspensionId = $this->GetLastInsertID('suspensions'); + + $this->Execute( + "INSERT INTO assignmentsuspensions (suspensionid, assignmentid) + VALUES (?, ?)", + array( + $suspensionId, + $suspendedAssignment['id'], + ) + ); + + $this->Execute( + "UPDATE assignments SET suspended = 0 + WHERE id = ?", + array( + $suspendedAssignment['id'] + ) + ); + } +} + +$this->Execute("DROP VIEW vnodealltariffs_tariffs"); +$this->Execute("DROP VIEW vnodetariffs_tariffs"); +$this->Execute("DROP VIEW vnodetariffs_allsuspended"); +$this->Execute("DROP VIEW vassignmentsuspensions"); +$this->Execute("DROP VIEW vassignmentssuspensionsvalues"); +$this->Execute("DROP VIEW vassignmentssuspensionsgroupcounts"); + +/* -------------------------------------------------------- + Structure of view "vassignmentssuspensionsgroupcounts" +-------------------------------------------------------- */ +$this->Execute(" +CREATE VIEW vassignmentssuspensionsgroupcounts AS + SELECT COUNT(vasg.suspension_assignment_id) AS suspensiongroup_assignments_count, + vasg.suspension_id AS suspensiongroup_suspension_id + FROM (SELECT + (CASE WHEN suspensions.assignment_id IS NOT NULL + THEN suspensions.assignment_id + ELSE a.id + END) AS suspension_assignment_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.suspension_id + ELSE suspensions_all.suspension_id + END) AS suspension_id + FROM assignments a + LEFT JOIN ( + SELECT + assignmentsuspensions.assignmentid AS assignment_id, + assignmentsuspensions.suspensionid AS suspension_id, + suspensions1.id AS id + FROM assignmentsuspensions + JOIN suspensions AS suspensions1 ON suspensions1.id = assignmentsuspensions.suspensionid + LEFT JOIN taxes ON taxes.id = suspensions1.taxid + ) suspensions ON suspensions.assignment_id = a.id + LEFT JOIN ( + SELECT + suspensions2.id AS suspension_id, + suspensions2.customerid, + (CASE WHEN suspensions2.customerid IS NULL THEN 0 ELSE 1 END) AS suspend_all + FROM suspensions AS suspensions2 + ) AS suspensions_all ON suspensions_all.customerid = a.customerid + WHERE suspensions.suspension_id IS NOT NULL OR suspensions_all.suspend_all = 1 + ) AS vasg + GROUP BY vasg.suspension_id +"); + +/* -------------------------------------------------------- + Structure of view "vassignmentssuspensionsvalues" +-------------------------------------------------------- */ +$this->Execute(" +CREATE VIEW vassignmentssuspensionsvalues AS + SELECT + suspension_assignment_id AS suspensionvalues_assignment_id, + suspension_id AS suspensionvalues_suspension_id, + assignment_base_price AS suspensionvalues_assignment_base_price, + assignment_tpv_price AS suspensionvalues_assignment_tpv_price, + assignment_price AS suspensionvalues_assignment_price, + suspensiongroup_assignments_count AS suspensionvalues_assignments_count + FROM ( + SELECT + (CASE WHEN suspensions.assignment_id IS NOT NULL + THEN suspensions.assignment_id + ELSE a.id + END) AS suspension_assignment_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.suspension_id + ELSE suspensions_all.suspension_id + END) AS suspension_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.suspensiongroup_assignments_count + ELSE suspensions_all.suspensiongroup_assignments_count + END) AS suspensiongroup_assignments_count, + ROUND(((((100 - a.pdiscount) * (CASE WHEN a.liabilityid IS NULL THEN tvalue ELSE lvalue END)) / 100) - a.vdiscount), 3) AS assignment_base_price, + assignments_tpvariants.tpvprice AS assignment_tpv_price, + (CASE WHEN assignments_tpvariants.tpvprice IS NULL + THEN ROUND(((((100 - a.pdiscount) * (CASE WHEN a.liabilityid IS NULL THEN tvalue ELSE lvalue END)) / 100) - a.vdiscount), 3) + ELSE assignments_tpvariants.tpvprice + END) AS assignment_price + FROM assignments a + LEFT JOIN ( + SELECT + tariffs.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN tariffs.flags & 16 > 0 THEN tariffs.netvalue ELSE tariffs.value END) AS tvalue + FROM tariffs + JOIN taxes ON taxes.id = tariffs.taxid + ) t ON a.tariffid = t.id + LEFT JOIN ( + SELECT + liabilities.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN liabilities.flags & 16 > 0 THEN liabilities.netvalue ELSE liabilities.value END) AS lvalue + FROM liabilities + JOIN taxes ON taxes.id = liabilities.taxid + ) l ON a.liabilityid = l.id + LEFT JOIN ( + SELECT + assignmentsuspensions.assignmentid AS assignment_id, + assignmentsuspensions.suspensionid AS suspension_id, + suspensions1.id AS id, + vasg.suspensiongroup_assignments_count AS suspensiongroup_assignments_count + FROM assignmentsuspensions + JOIN suspensions AS suspensions1 ON suspensions1.id = assignmentsuspensions.suspensionid + JOIN vassignmentssuspensionsgroupcounts vasg ON vasg.suspensiongroup_suspension_id = suspensions1.id + LEFT JOIN taxes ON taxes.id = suspensions1.taxid + ) suspensions ON suspensions.assignment_id = a.id + LEFT JOIN ( + SELECT + suspensions2.id AS suspension_id, + suspensions2.customerid, + (CASE WHEN suspensions2.customerid IS NULL THEN 0 ELSE 1 END) AS suspend_all, + vasg.suspensiongroup_assignments_count AS suspensiongroup_assignments_count + FROM suspensions AS suspensions2 + JOIN vassignmentssuspensionsgroupcounts vasg ON vasg.suspensiongroup_suspension_id = suspensions2.id + ) AS suspensions_all ON suspensions_all.customerid = a.customerid + LEFT JOIN ( + SELECT + tpv.* + FROM assignments a + JOIN ( + SELECT + tariffpricevariants.quantity_threshold AS tpv_quantity_threshold, tariffs.id AS tpv_tariffid, + (CASE WHEN tariffs.flags & 16 > 0 THEN tariffpricevariants.net_price ELSE tariffpricevariants.gross_price END) AS tpvprice + FROM tariffs + JOIN tariffpricevariants ON tariffs.id = tariffpricevariants.tariffid + ) tpv ON a.tariffid = tpv.tpv_tariffid AND tpv.tpv_quantity_threshold <= a.count AND tpv.tpv_tariffid = a.tariffid + ORDER BY tpv.tpv_quantity_threshold DESC LIMIT 1 + ) AS assignments_tpvariants ON a.tariffid = assignments_tpvariants.tpv_tariffid + WHERE suspensions.suspension_id IS NOT NULL OR suspensions_all.suspend_all = 1 + ) AS vasv +"); + +/* -------------------------------------------------------- + Structure of view "vassignmentsuspensions" +-------------------------------------------------------- */ + +$this->Execute(" +CREATE VIEW vassignmentsuspensions AS + SELECT + (CASE WHEN suspensions.assignment_id IS NOT NULL + THEN suspensions.assignment_id + ELSE a.id + END) AS suspension_assignment_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL OR suspensions_all.suspend_all = 1 THEN 1 ELSE 0 END) AS suspended, + (CASE WHEN suspensions.suspension_id IS NULL AND suspensions_all.suspend_all = 1 THEN 1 ELSE 0 END) AS suspension_suspend_all, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.suspension_id + ELSE suspensions_all.suspension_id + END) AS suspension_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.at + ELSE suspensions_all.at + END) AS suspension_at, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.datefrom + ELSE suspensions_all.datefrom + END) AS suspension_datefrom, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.dateto + ELSE suspensions_all.dateto + END) AS suspension_dateto, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.chargemethod + ELSE suspensions_all.chargemethod + END) AS suspension_charge_method, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.calculationmethod + ELSE suspensions_all.calculationmethod + END) AS suspension_calculation_method, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.value + ELSE suspensions_all.value + END) AS suspension_value, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.percentage + ELSE suspensions_all.percentage + END) AS suspension_percentage, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.netflag + ELSE suspensions_all.netflag + END) AS suspension_netflag, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.currency + ELSE suspensions_all.currency + END) AS suspension_currency, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.taxid + ELSE suspensions_all.taxid + END) AS suspension_tax_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.note + ELSE suspensions_all.note + END) AS suspension_note, + (CASE WHEN suspensions.customerid IS NOT NULL + THEN suspensions_all.customerid + ELSE a.customerid + END) AS suspension_customer_id, + (CASE WHEN suspensions.taxrate IS NOT NULL + THEN suspensions.taxrate + ELSE suspensions_all.taxrate + END) AS suspension_taxrate, + (CASE WHEN suspensions.taxlabel IS NOT NULL + THEN suspensions.taxlabel + ELSE suspensions_all.taxlabel + END) AS suspension_taxlabel, + vasv.suspensionvalues_assignment_base_price, + vasv.suspensionvalues_assignment_tpv_price, + vasv.suspensionvalues_assignment_price, + vasv.suspensionvalues_assignments_count, + (CASE + WHEN suspensions.chargemethod = 3 OR suspensions.chargemethod = 2 + OR suspensions_all.chargemethod = 3 OR suspensions_all.chargemethod = 2 + THEN (CASE + WHEN suspensions.calculationmethod = 1 + THEN vasv.suspensionvalues_assignment_price * + (CASE + WHEN suspensions.percentage IS NOT NULL + THEN ROUND(suspensions.percentage / 100, 2) + ELSE + ROUND((SELECT CAST(uiconfig.value AS numeric) + FROM uiconfig + WHERE uiconfig.section = 'suspensions' + AND uiconfig.var = 'default_percentage' + AND uiconfig.configid IS NULL + LIMIT 1) / 100, 2) + END) + WHEN suspensions_all.calculationmethod = 1 + THEN vasv.suspensionvalues_assignment_price * + (CASE + WHEN suspensions_all.percentage IS NOT NULL + THEN ROUND(suspensions_all.percentage / 100, 2) + ELSE + ROUND((SELECT CAST(uiconfig.value AS numeric) + FROM uiconfig + WHERE uiconfig.section = 'suspensions' + AND uiconfig.var = 'default_percentage' + AND uiconfig.configid IS NULL + LIMIT 1) / 100, 2) + END) + WHEN suspensions.calculationmethod = 2 + THEN + (CASE + WHEN suspensions.value IS NOT NULL + THEN ROUND(suspensions.value / vasv.suspensionvalues_assignments_count, 2) + ELSE + ROUND((SELECT CAST(uiconfig.value AS numeric) + FROM uiconfig + WHERE uiconfig.section = 'suspensions' + AND uiconfig.var = 'default_percentage' + AND uiconfig.configid IS NULL + LIMIT 1) / 100, 2) + END) + WHEN suspensions_all.calculationmethod = 2 + THEN + (CASE + WHEN suspensions_all.value IS NOT NULL + THEN ROUND(suspensions_all.value / vasv.suspensionvalues_assignments_count, 2) + ELSE + ROUND((SELECT CAST(uiconfig.value AS numeric) + FROM uiconfig + WHERE uiconfig.section = 'suspensions' + AND uiconfig.var = 'default_percentage' + AND uiconfig.configid IS NULL + LIMIT 1) / 100, 2) + END) + END) + WHEN suspensions.chargemethod = 1 OR suspensions_all.chargemethod = 1 + THEN 0 + END) AS suspension_price + FROM assignments a + LEFT JOIN ( + SELECT + tariffs.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN tariffs.flags & 16 > 0 THEN tariffs.netvalue ELSE tariffs.value END) AS tvalue + FROM tariffs + JOIN taxes ON taxes.id = tariffs.taxid + ) t ON a.tariffid = t.id + LEFT JOIN ( + SELECT + tpv.* + FROM assignments a + JOIN ( + SELECT + tariffpricevariants.quantity_threshold AS tpv_quantity_threshold, + tariffs.id AS tpv_tariffid, + (CASE WHEN tariffs.flags & 16 > 0 THEN tariffpricevariants.net_price ELSE tariffpricevariants.gross_price END) AS tpvprice + FROM tariffs + JOIN tariffpricevariants ON tariffs.id = tariffpricevariants.tariffid + ) tpv ON a.tariffid = tpv.tpv_tariffid AND tpv.tpv_quantity_threshold <= a.count AND tpv.tpv_tariffid = a.tariffid + ORDER BY tpv.tpv_quantity_threshold DESC LIMIT 1 + ) AS assignments_tpvariants ON a.tariffid = assignments_tpvariants.tpv_tariffid + LEFT JOIN ( + SELECT + liabilities.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN liabilities.flags & 16 > 0 THEN liabilities.netvalue ELSE liabilities.value END) AS lvalue + FROM liabilities + JOIN taxes ON taxes.id = liabilities.taxid + ) l ON a.liabilityid = l.id + LEFT JOIN ( + SELECT + assignmentsuspensions.id AS assignmentsuspension_id, + assignmentsuspensions.assignmentid AS assignment_id, + assignmentsuspensions.suspensionid AS suspension_id, + suspensions1.id AS id, + suspensions1.at, suspensions1.datefrom, suspensions1.dateto, suspensions1.chargemethod, suspensions1.calculationmethod, + suspensions1.value, suspensions1.percentage, suspensions1.netflag, suspensions1.currency, suspensions1.note, suspensions1.taxid, + suspensions1.customerid, + taxes.value AS taxrate, taxes.label AS taxlabel + FROM assignmentsuspensions + JOIN suspensions AS suspensions1 ON suspensions1.id = assignmentsuspensions.suspensionid + LEFT JOIN taxes ON taxes.id = suspensions1.taxid + ) suspensions ON suspensions.assignment_id = a.id + LEFT JOIN ( + SELECT suspensions2.id AS suspension_id, suspensions2.at, suspensions2.datefrom, suspensions2.dateto, + suspensions2.chargemethod, suspensions2.calculationmethod, + suspensions2.value, suspensions2.percentage, suspensions2.netflag, suspensions2.currency, suspensions2.note, suspensions2.taxid, + suspensions2.customerid, + (CASE WHEN suspensions2.customerid IS NULL THEN 0 ELSE 1 END) AS suspend_all, + taxes.value AS taxrate, taxes.label AS taxlabel + FROM suspensions AS suspensions2 + LEFT JOIN taxes ON taxes.id = suspensions2.taxid + ) AS suspensions_all ON suspensions_all.customerid = a.customerid + LEFT JOIN vassignmentssuspensionsvalues vasv ON vasv.suspensionvalues_assignment_id = a.id + WHERE suspensions.suspension_id IS NOT NULL OR suspensions_all.suspend_all = 1 +"); + +$this->Execute(" +CREATE VIEW vnodetariffs_tariffs AS + SELECT n.id AS nodeid, + ROUND(SUM(t.downrate * a.count)) AS downrate, + ROUND(SUM(t.downceil * a.count)) AS downceil, + SUM(t.down_burst_time) AS down_burst_time, + SUM(t.down_burst_threshold) AS down_burst_threshold, + SUM(t.down_burst_limit) AS down_burst_limit, + ROUND(SUM(t.uprate * a.count)) AS uprate, + ROUND(SUM(t.upceil * a.count)) AS upceil, + SUM(t.up_burst_time) AS up_burst_time, + SUM(t.up_burst_threshold) AS up_burst_threshold, + SUM(t.up_burst_limit) AS up_burst_limit, + ROUND(SUM(COALESCE(t.downrate_n, t.downrate) * a.count)) AS downrate_n, + ROUND(SUM(COALESCE(t.downceil_n, t.downceil) * a.count)) AS downceil_n, + SUM(COALESCE(t.down_burst_time_n, t.down_burst_time)) AS down_burst_time_n, + SUM(COALESCE(t.down_burst_threshold_n, t.down_burst_threshold)) AS down_burst_threshold_n, + SUM(COALESCE(t.down_burst_limit_n, t.down_burst_limit)) AS down_burst_limit_n, + ROUND(SUM(COALESCE(t.uprate_n, t.uprate) * a.count)) AS uprate_n, + ROUND(SUM(COALESCE(t.upceil_n, t.upceil) * a.count)) AS upceil_n, + SUM(COALESCE(t.up_burst_time_n, t.up_burst_time)) AS up_burst_time_n, + SUM(COALESCE(t.up_burst_threshold_n, t.up_burst_threshold)) AS up_burst_threshold_n, + SUM(COALESCE(t.up_burst_limit_n, t.up_burst_limit)) AS up_burst_limit_n + FROM nodes n + JOIN nodeassignments na ON na.nodeid = n.id + JOIN assignments a ON a.id = na.assignmentid + JOIN tariffs t ON t.id = a.tariffid + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= UNIX_TIMESTAMP() + AND (vas.suspension_dateto >= UNIX_TIMESTAMP() OR vas.suspension_dateto = 0) + AND a.datefrom <= UNIX_TIMESTAMP() + AND (a.dateto > UNIX_TIMESTAMP() OR a.dateto = 0) + WHERE vas.suspended IS NULL AND a.commited = 1 + AND a.datefrom <= UNIX_TIMESTAMP() + AND (a.dateto = 0 OR a.dateto >= UNIX_TIMESTAMP()) + AND (t.downrate > 0 OR t.downceil > 0 OR t.uprate > 0 OR t.upceil > 0) + GROUP BY n.id +"); + +$this->Execute(" +CREATE VIEW vnodealltariffs_tariffs AS + SELECT n.id AS nodeid, + ROUND(SUM(t.downrate * a.count)) AS downrate, + ROUND(SUM(t.downceil * a.count)) AS downceil, + SUM(t.down_burst_time) AS down_burst_time, + SUM(t.down_burst_threshold) AS down_burst_threshold, + SUM(t.down_burst_limit) AS down_burst_limit, + ROUND(SUM(t.uprate * a.count)) AS uprate, + ROUND(SUM(t.upceil * a.count)) AS upceil, + SUM(t.up_burst_time) AS up_burst_time, + SUM(t.up_burst_threshold) AS up_burst_threshold, + SUM(t.up_burst_limit) AS up_burst_limit, + ROUND(SUM(COALESCE(t.downrate_n, t.downrate) * a.count)) AS downrate_n, + ROUND(SUM(COALESCE(t.downceil_n, t.downceil) * a.count)) AS downceil_n, + SUM(COALESCE(t.down_burst_time_n, t.down_burst_time)) AS down_burst_time_n, + SUM(COALESCE(t.down_burst_threshold_n, t.down_burst_threshold)) AS down_burst_threshold_n, + SUM(COALESCE(t.down_burst_limit_n, t.down_burst_limit)) AS down_burst_limit_n, + ROUND(SUM(COALESCE(t.uprate_n, t.uprate) * a.count)) AS uprate_n, + ROUND(SUM(COALESCE(t.upceil_n, t.upceil) * a.count)) AS upceil_n, + SUM(COALESCE(t.up_burst_time_n, t.up_burst_time)) AS up_burst_time_n, + SUM(COALESCE(t.up_burst_threshold_n, t.up_burst_threshold)) AS up_burst_threshold_n, + SUM(COALESCE(t.up_burst_limit_n, t.up_burst_limit)) AS up_burst_limit_n + FROM assignments a + JOIN tariffs t ON t.id = a.tariffid + JOIN vnodealltariffs_nodes n ON n.ownerid = a.customerid + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= UNIX_TIMESTAMP() + AND (vas.suspension_dateto >= UNIX_TIMESTAMP() OR vas.suspension_dateto = 0) + AND a.datefrom <= UNIX_TIMESTAMP() + AND (a.dateto > UNIX_TIMESTAMP() OR a.dateto = 0) + WHERE vas.suspended IS NULL AND a.commited = 1 + AND a.datefrom <= UNIX_TIMESTAMP() + AND (a.dateto = 0 OR a.dateto >= UNIX_TIMESTAMP()) + AND (t.downrate > 0 OR t.downceil > 0 OR t.uprate > 0 OR t.upceil > 0) + AND n.id NOT IN (SELECT nodeid FROM nodeassignments) + AND a.id NOT IN (SELECT assignmentid FROM nodeassignments) + GROUP BY n.id +"); + +$this->Execute("ALTER TABLE assignments DROP COLUMN suspended"); + +$this->Execute("UPDATE dbinfo SET keyvalue = ? WHERE keytype = ?", array('2024052400', 'dbversion')); + +$this->CommitTrans(); diff --git a/lib/upgradedb/postgres.2024052400.php b/lib/upgradedb/postgres.2024052400.php new file mode 100644 index 0000000000..cab520be0d --- /dev/null +++ b/lib/upgradedb/postgres.2024052400.php @@ -0,0 +1,1033 @@ +BeginTrans(); + +//region Suspension configs +if (!$this->GetOne( + 'SELECT 1 FROM uiconfig WHERE section = ? AND var = ?', + array( + 'suspensions', + 'default_percentage', + ) +)) { + $this->Execute( + 'INSERT INTO uiconfig (section, var, value, disabled) VALUES (?, ?, ?, ?)', + array( + 'suspensions', + 'default_percentage', + '0', + 0, + ) + ); +} + +if (!$this->GetOne( + 'SELECT 1 FROM uiconfig WHERE section = ? AND var = ?', + array( + 'suspensions', + 'default_value', + ) +)) { + $this->Execute( + 'INSERT INTO uiconfig (section, var, value, disabled) VALUES (?, ?, ?, ?)', + array( + 'suspensions', + 'default_value', + '0', + 0, + ) + ); +} + +if (!$this->GetOne( + 'SELECT 1 FROM uiconfig WHERE section = ? AND var = ?', + array( + 'suspensions', + 'default_netflag', + ) +)) { + $this->Execute( + 'INSERT INTO uiconfig (section, var, value, disabled) VALUES (?, ?, ?, ?)', + array( + 'suspensions', + 'default_netflag', + '0', + 0, + ) + ); +} + +if (!$this->GetOne( + 'SELECT 1 FROM uiconfig WHERE section = ? AND var = ?', + array( + 'suspensions', + 'default_charge_method', + ) +)) { + $this->Execute( + 'INSERT INTO uiconfig (section, var, value, description, disabled) VALUES (?, ?, ?, ?, ?)', + array( + 'suspensions', + 'default_charge_method', + '2', + '[1-none|2-once|3-periodically]', + 0, + ) + ); +} + +if (!$this->GetOne( + 'SELECT 1 FROM uiconfig WHERE section = ? AND var = ?', + array( + 'suspensions', + 'default_calculation_method', + ) +)) { + $this->Execute( + 'INSERT INTO uiconfig (section, var, value, description, disabled) VALUES (?, ?, ?, ?, ?)', + array( + 'suspensions', + 'default_calculation_method', + '1', + '[1-percentage|2-value]', + 0, + ) + ); +} +//endregion + +/* -------------------------------------------------------- + Structure of table "suspensions" +-------------------------------------------------------- */ +if (!$this->ResourceExists('suspensions', LMSDB::RESOURCE_TYPE_TABLE)) { + $this->Execute("CREATE SEQUENCE suspensions_id_seq"); + $this->Execute( + "CREATE TABLE suspensions( + id integer DEFAULT nextval('suspensions_id_seq'::text) NOT NULL, + at integer DEFAULT NULL, + datefrom integer DEFAULT 0 NOT NULL, + dateto integer DEFAULT 0 NOT NULL, + chargemethod smallint NOT NULL, + calculationmethod smallint NOT NULL, + value numeric(9, 3) DEFAULT NULL, + percentage numeric(3, 2) DEFAULT NULL, + netflag smallint DEFAULT NULL, + currency varchar(3) DEFAULT NULL, + note text DEFAULT NULL, + customerid integer DEFAULT NULL + CONSTRAINT suspensions_customerid_fkey REFERENCES customers(id) ON DELETE CASCADE ON UPDATE CASCADE, + taxid integer DEFAULT NULL + CONSTRAINT suspensions_taxid_fkey REFERENCES taxes(id) ON DELETE CASCADE ON UPDATE CASCADE, + PRIMARY KEY(id) + )" + ); +} + +/* -------------------------------------------------------- + Structure of table "assignmentsuspensions" +-------------------------------------------------------- */ +if (!$this->ResourceExists('assignmentsuspensions', LMSDB::RESOURCE_TYPE_TABLE)) { + $this->Execute("CREATE SEQUENCE assignmentsuspensions_id_seq"); + $this->Execute( + "CREATE TABLE assignmentsuspensions( + id integer DEFAULT nextval('assignmentsuspensions_id_seq'::text) NOT NULL, + suspensionid integer NOT NULL + CONSTRAINT suspensions_suspensionid_fkey REFERENCES suspensions(id) ON DELETE CASCADE ON UPDATE CASCADE, + assignmentid integer NOT NULL + CONSTRAINT assignments_assignmentid_fkey REFERENCES assignments(id) ON DELETE CASCADE ON UPDATE CASCADE, + PRIMARY KEY(id), + CONSTRAINT assignmentsuspensions_assignmentid_suspensionid_ukey UNIQUE(assignmentid, suspensionid) + )" + ); +} + +//transform old assignment suspensions to new ones +define('DISPOSABLE', 0); +define('DAILY', 1); +define('WEEKLY', 2); +define('MONTHLY', 3); +define('QUARTERLY', 4); +define('HALFYEARLY', 7); +define('YEARLY', 5); +define('SUSPENSION_CHARGE_METHOD_ONCE', 2); +define('SUSPENSION_CHARGE_METHOD_PERIODICALLY', 3); +define('TARIFF_FLAG_NET_ACCOUNT', 16); +define('LIABILITY_FLAG_NET_ACCOUT', 16); +define('SUSPENSION_CALCULATION_METHOD_PERCENTAGE', 1); + +$allSuspendedAssignments = $this->GetAll( + 'SELECT + a.id, + a.at, + a.datefrom, + a.dateto, + a.period, + a.customerid, + (CASE WHEN a.period = ? THEN ? ELSE ? END) AS assignment_charge_method + FROM assignments a + WHERE + a.tariffid IS NULL AND a.liabilityid IS NULL + ORDER BY a.id DESC', + array( + DISPOSABLE, + SUSPENSION_CHARGE_METHOD_ONCE, + SUSPENSION_CHARGE_METHOD_PERIODICALLY, + TARIFF_FLAG_NET_ACCOUNT, + LIABILITY_FLAG_NET_ACCOUT, + TARIFF_FLAG_NET_ACCOUNT, + LIABILITY_FLAG_NET_ACCOUT, + ) +); + +if (!empty($allSuspendedAssignments)) { + $today = strtotime('today'); + foreach ($allSuspendedAssignments as $allSuspendedAssignment) { + $suspensionExist = $this->getOne('SELECT customerid FROM suspensions WHERE customerid = ?', array($allSuspendedAssignment['customerid'])); + if (empty($suspensionExist)) { + $assignments = $this->getAll( + 'SELECT + a.id, + a.at, + a.datefrom, + a.dateto, + a.period, + a.customerid, + (CASE WHEN a.period = ? THEN ? ELSE ? END) AS assignment_charge_method + FROM assignments a + WHERE + a.suspended = 0 + AND a.tariffid IS NOT NULL OR a.liabilityid IS NOT NULL + AND a.customerid = ?', + array( + DISPOSABLE, + SUSPENSION_CHARGE_METHOD_ONCE, + SUSPENSION_CHARGE_METHOD_PERIODICALLY, + $allSuspendedAssignment['customerid'] + ) + ); + + if (!empty($assignments)) { + foreach ($assignments as $row) { + switch ($row['assignment_charge_method']) { + case SUSPENSION_CHARGE_METHOD_ONCE: + $startdate = $row['datefrom'] > $today ? $row['datefrom'] : $today; + [$year, $month, $dom] = explode('/', date('Y/n/j', $startdate)); + $commingPayDate = 0; + $commingPayTimestamp = 0; + + switch ($row['period']) { + case DISPOSABLE: + $commingPayTimestamp = $row['at']; + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + case MONTHLY: + $commingPayTimestamp = mktime(0, 0, 0, $month, $row['at'], $year); + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + case QUARTERLY: + [$d, $m] = explode('/', $row['at']); + $quarterlyDate1 = mktime(0, 0, 0, $m, $d, $year); + $quarterlyDate2 = strtotime('+3 months', $quarterlyDate1); + $quarterlyDate3 = strtotime('+6 months', $quarterlyDate1); + $quarterlyDate4 = strtotime('+9 months', $quarterlyDate1); + + if ($quarterlyDate1 <= $row['datefrom']) { + if ($quarterlyDate2 <= $row['datefrom']) { + if ($quarterlyDate3 <= $row['datefrom']) { + if ($quarterlyDate4 <= $row['datefrom']) { + $commingPayTimestamp = strtotime('+3 months', $quarterlyDate4); + } else { + $commingPayTimestamp = $quarterlyDate3; + } + } else { + $commingPayTimestamp = $quarterlyDate3; + } + } else { + $commingPayTimestamp = $quarterlyDate2; + } + } else { + $commingPayTimestamp = $quarterlyDate1; + } + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + case HALFYEARLY: + [$d, $m] = explode('/', $row['at']); + $halfyearlyDate1 = mktime(0, 0, 0, $m, $d, $year); + $halfyearlyDate2 = strtotime('+6 months', $halfyearlyDate1); + + if ($halfyearlyDate1 <= $row['datefrom']) { + if ($halfyearlyDate2 <= $row['datefrom']) { + $commingPayTimestamp = strtotime('+6 months', $halfyearlyDate2); + } else { + $commingPayTimestamp = $halfyearlyDate2; + } + } else { + $commingPayTimestamp = $halfyearlyDate1; + } + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + case YEARLY: + [$d, $m] = explode('/', $row['at']); + $yearlyDate = mktime(0, 0, 0, $m, $d, $year); + if ($yearlyDate <= $row['datefrom']) { + $commingPayTimestamp = strtotime('+1 year', $yearlyDate); + } else { + $commingPayTimestamp = $yearlyDate; + } + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + } + + if (!isset($suspension_at) || $commingPayTimestamp < $suspension_at) { + $suspension_at = $commingPayTimestamp; + } + break; + case SUSPENSION_CHARGE_METHOD_PERIODICALLY: + $startdate = $row['datefrom'] > $today ? $row['datefrom'] : $today; + $dom = date('j', $startdate); + $commingPayDay = 0; + + switch ($row['period']) { + case DISPOSABLE: + $commingPayDay = date('j', $row['at']); + break; + case MONTHLY: + $commingPayDay = $row['at']; + break; + case QUARTERLY: + case HALFYEARLY: + case YEARLY: + [$d, $m] = explode('/', $row['at']); + $commingPayDay = $d; + break; + } + + if (!isset($suspension_at) || $commingPayDay < $suspension_at) { + $suspension_at = $commingPayDay; + } + break; + } + } + } + + $args = array( + 'at' => $suspension_at, + 'datefrom' => $allSuspendedAssignment['datefrom'], + 'dateto' => $allSuspendedAssignment['dateto'], + 'chargemethod' => SUSPENSION_CHARGE_METHOD_PERIODICALLY, + 'calculationmethod' => SUSPENSION_CALCULATION_METHOD_PERCENTAGE, + 'customerid' => $allSuspendedAssignment['customerid'] + ); + + $this->Execute( + "INSERT INTO suspensions (at, datefrom, dateto, chargemethod, calculationmethod, customerid) + VALUES (?, ?, ?, ?, ?, ?)", + array_values($args) + ); + + $this->Execute("DELETE FROM assignments WHERE id = ?", array($allSuspendedAssignment['id'])); + } + } +} + +$suspendedAssignments = $this->GetAll( + 'SELECT + a.id, + a.at, + a.datefrom, + a.dateto, + a.period, + (CASE WHEN a.liabilityid IS NULL THEN t.currency ELSE l.currency END) AS currency, + (CASE WHEN a.liabilityid IS NULL THEN t.taxid ELSE l.taxid END) AS taxid, + (CASE WHEN a.liabilityid IS NULL + THEN (CASE WHEN t.flags & ? > 0 THEN 1 ELSE 0 END) + ELSE (CASE WHEN l.flags & ? > 0 THEN 1 ELSE 0 END) + END) AS netflag, + (CASE WHEN a.tariffid IS NULL AND a.liabilityid IS NULL THEN 1 ELSE 0 END) AS allsuspended + FROM assignments a + LEFT JOIN ( + SELECT tariffs.*, + taxes.value AS taxrate, + (CASE WHEN tariffs.flags & ? > 0 THEN tariffs.netvalue ELSE tariffs.value END) AS tvalue + FROM tariffs + JOIN taxes ON taxes.id = tariffs.taxid + ) t ON a.tariffid = t.id + LEFT JOIN ( + SELECT liabilities.*, + taxes.value AS taxrate, + (CASE WHEN liabilities.flags & ? > 0 THEN liabilities.netvalue ELSE liabilities.value END) AS lvalue + FROM liabilities + JOIN taxes ON taxes.id = liabilities.taxid + ) l ON a.liabilityid = l.id + WHERE suspended = 1', + array( + TARIFF_FLAG_NET_ACCOUNT, + LIABILITY_FLAG_NET_ACCOUT, + TARIFF_FLAG_NET_ACCOUNT, + LIABILITY_FLAG_NET_ACCOUT, + ) +); + +if (!empty($suspendedAssignments)) { + $today = strtotime('today'); + [$year, $month, $dom] = explode('/', date('Y/n/j', $today)); + foreach ($suspendedAssignments as $suspendedAssignment) { + $at = null; + switch ($suspendedAssignment['period']) { + case DISPOSABLE: + $charge_method = SUSPENSION_CHARGE_METHOD_ONCE; + $at = $suspendedAssignment['at']; + break; + case DAILY: + $charge_method = SUSPENSION_CHARGE_METHOD_PERIODICALLY; + $at = $dom; + break; + case WEEKLY: + $charge_method = SUSPENSION_CHARGE_METHOD_PERIODICALLY; + $atdate = date('Y/n/j', mktime(0, 0, 0, 0, $suspendedAssignment['at'] + 5, 0)); + [$wyear, $wmonth, $wdom] = explode('/', date('Y/n/j', $atdate)); + $at = $wdom; + break; + case MONTHLY: + $charge_method = SUSPENSION_CHARGE_METHOD_PERIODICALLY; + $at = $suspendedAssignment['at']; + break; + case QUARTERLY: + $charge_method = SUSPENSION_CHARGE_METHOD_PERIODICALLY; + $atdate = sprintf('%02d/%02d', $suspendedAssignment['at'] % 100, $suspendedAssignment['at'] / 100 + 1); + [$qday, $qmonth] = explode('/', $atdate); + $at = $qday; + break; + case HALFYEARLY: + $charge_method = SUSPENSION_CHARGE_METHOD_PERIODICALLY; + $atdate = sprintf('%02d/%02d', $suspendedAssignment['at'] % 100, $suspendedAssignment['at'] / 100 + 1); + [$hday, $hmonth] = explode('/', $atdate); + $at = $hday; + break; + case YEARLY: + $charge_method = SUSPENSION_CHARGE_METHOD_PERIODICALLY; + $atdate = date('d/m', ($suspendedAssignment['at'] - 1) * 86400); + [$yday, $tmonth] = explode('/', $atdate); + $at = $yday; + break; + } + + $args = array( + 'at' => $at, + 'datefrom' => $suspendedAssignment['datefrom'], + 'dateto' => $suspendedAssignment['dateto'], + 'chargemethod' => $charge_method, + 'calculationmethod' => SUSPENSION_CALCULATION_METHOD_PERCENTAGE, + ); + + $this->Execute( + "INSERT INTO suspensions (at, datefrom, dateto, chargemethod, calculationmethod) + VALUES (?, ?, ?, ?, ?)", + array_values($args) + ); + + $suspensionId = $this->GetLastInsertID('suspensions'); + + $this->Execute( + "INSERT INTO assignmentsuspensions (suspensionid, assignmentid) + VALUES (?, ?)", + array( + $suspensionId, + $suspendedAssignment['id'], + ) + ); + + $this->Execute( + "UPDATE assignments SET suspended = 0 + WHERE id = ?", + array( + $suspendedAssignment['id'] + ) + ); + } +} + +$this->Execute("DROP VIEW IF EXISTS vnodetariffs"); +$this->Execute("DROP VIEW IF EXISTS vnodealltariffs"); +$this->Execute("DROP VIEW IF EXISTS vassignmentsuspensions"); +$this->Execute("DROP VIEW IF EXISTS vassignmentssuspensionsvalues"); +$this->Execute("DROP VIEW IF EXISTS vassignmentssuspensionsgroupcounts"); + +/* -------------------------------------------------------- + Structure of view "vassignmentssuspensionsgroupcounts" +-------------------------------------------------------- */ +$this->Execute(" +CREATE VIEW vassignmentssuspensionsgroupcounts AS + SELECT COUNT(vasg.suspension_assignment_id) AS suspensiongroup_assignments_count, + vasg.suspension_id AS suspensiongroup_suspension_id + FROM (SELECT + (CASE WHEN suspensions.assignment_id IS NOT NULL + THEN suspensions.assignment_id + ELSE a.id + END) AS suspension_assignment_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.suspension_id + ELSE suspensions_all.suspension_id + END) AS suspension_id + FROM assignments a + LEFT JOIN ( + SELECT + assignmentsuspensions.assignmentid AS assignment_id, + assignmentsuspensions.suspensionid AS suspension_id, + suspensions1.id AS id + FROM assignmentsuspensions + JOIN suspensions AS suspensions1 ON suspensions1.id = assignmentsuspensions.suspensionid + LEFT JOIN taxes ON taxes.id = suspensions1.taxid + ) suspensions ON suspensions.assignment_id = a.id + LEFT JOIN ( + SELECT + suspensions2.id AS suspension_id, + suspensions2.customerid, + (CASE WHEN suspensions2.customerid IS NULL THEN 0 ELSE 1 END) AS suspend_all + FROM suspensions AS suspensions2 + ) AS suspensions_all ON suspensions_all.customerid = a.customerid + WHERE suspensions.suspension_id IS NOT NULL OR suspensions_all.suspend_all = 1 + ) AS vasg + GROUP BY vasg.suspension_id +"); + +/* -------------------------------------------------------- + Structure of view "vassignmentssuspensionsvalues" +-------------------------------------------------------- */ +$this->Execute(" +CREATE VIEW vassignmentssuspensionsvalues AS + SELECT + suspension_assignment_id AS suspensionvalues_assignment_id, + suspension_id AS suspensionvalues_suspension_id, + assignment_base_price AS suspensionvalues_assignment_base_price, + assignment_tpv_price AS suspensionvalues_assignment_tpv_price, + assignment_price AS suspensionvalues_assignment_price, + suspensiongroup_assignments_count AS suspensionvalues_assignments_count + FROM ( + SELECT + (CASE WHEN suspensions.assignment_id IS NOT NULL + THEN suspensions.assignment_id + ELSE a.id + END) AS suspension_assignment_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.suspension_id + ELSE suspensions_all.suspension_id + END) AS suspension_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.suspensiongroup_assignments_count + ELSE suspensions_all.suspensiongroup_assignments_count + END) AS suspensiongroup_assignments_count, + ROUND(((((100 - a.pdiscount) * (CASE WHEN a.liabilityid IS NULL THEN tvalue ELSE lvalue END)) / 100) - a.vdiscount), 3) AS assignment_base_price, + assignments_tpvariants.tpvprice AS assignment_tpv_price, + (CASE WHEN assignments_tpvariants.tpvprice IS NULL + THEN ROUND(((((100 - a.pdiscount) * (CASE WHEN a.liabilityid IS NULL THEN tvalue ELSE lvalue END)) / 100) - a.vdiscount), 3) + ELSE assignments_tpvariants.tpvprice + END) AS assignment_price + FROM assignments a + LEFT JOIN ( + SELECT + tariffs.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN tariffs.flags & 16 > 0 THEN tariffs.netvalue ELSE tariffs.value END) AS tvalue + FROM tariffs + JOIN taxes ON taxes.id = tariffs.taxid + ) t ON a.tariffid = t.id + LEFT JOIN ( + SELECT + liabilities.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN liabilities.flags & 16 > 0 THEN liabilities.netvalue ELSE liabilities.value END) AS lvalue + FROM liabilities + JOIN taxes ON taxes.id = liabilities.taxid + ) l ON a.liabilityid = l.id + LEFT JOIN ( + SELECT + assignmentsuspensions.assignmentid AS assignment_id, + assignmentsuspensions.suspensionid AS suspension_id, + suspensions1.id AS id, + vasg.suspensiongroup_assignments_count AS suspensiongroup_assignments_count + FROM assignmentsuspensions + JOIN suspensions AS suspensions1 ON suspensions1.id = assignmentsuspensions.suspensionid + JOIN vassignmentssuspensionsgroupcounts vasg ON vasg.suspensiongroup_suspension_id = suspensions1.id + LEFT JOIN taxes ON taxes.id = suspensions1.taxid + ) suspensions ON suspensions.assignment_id = a.id + LEFT JOIN ( + SELECT + suspensions2.id AS suspension_id, + suspensions2.customerid, + (CASE WHEN suspensions2.customerid IS NULL THEN 0 ELSE 1 END) AS suspend_all, + vasg.suspensiongroup_assignments_count AS suspensiongroup_assignments_count + FROM suspensions AS suspensions2 + JOIN vassignmentssuspensionsgroupcounts vasg ON vasg.suspensiongroup_suspension_id = suspensions2.id + ) AS suspensions_all ON suspensions_all.customerid = a.customerid + LEFT JOIN ( + SELECT + tpv.* + FROM assignments a + JOIN ( + SELECT + tariffpricevariants.quantity_threshold AS tpv_quantity_threshold, tariffs.id AS tpv_tariffid, + (CASE WHEN tariffs.flags & 16 > 0 THEN tariffpricevariants.net_price ELSE tariffpricevariants.gross_price END) AS tpvprice + FROM tariffs + JOIN tariffpricevariants ON tariffs.id = tariffpricevariants.tariffid + ) tpv ON a.tariffid = tpv.tpv_tariffid AND tpv.tpv_quantity_threshold <= a.count AND tpv.tpv_tariffid = a.tariffid + ORDER BY tpv.tpv_quantity_threshold DESC LIMIT 1 + ) AS assignments_tpvariants ON a.tariffid = assignments_tpvariants.tpv_tariffid + WHERE suspensions.suspension_id IS NOT NULL OR suspensions_all.suspend_all = 1 + ) AS vasv +"); + +/* -------------------------------------------------------- + Structure of view "vassignmentsuspensions" +-------------------------------------------------------- */ + +$this->Execute(" +CREATE VIEW vassignmentsuspensions AS + SELECT + (CASE WHEN suspensions.assignment_id IS NOT NULL + THEN suspensions.assignment_id + ELSE a.id + END) AS suspension_assignment_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL OR suspensions_all.suspend_all = 1 THEN 1 ELSE 0 END) AS suspended, + (CASE WHEN suspensions.suspension_id IS NULL AND suspensions_all.suspend_all = 1 THEN 1 ELSE 0 END) AS suspension_suspend_all, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.suspension_id + ELSE suspensions_all.suspension_id + END) AS suspension_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.at + ELSE suspensions_all.at + END) AS suspension_at, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.datefrom + ELSE suspensions_all.datefrom + END) AS suspension_datefrom, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.dateto + ELSE suspensions_all.dateto + END) AS suspension_dateto, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.chargemethod + ELSE suspensions_all.chargemethod + END) AS suspension_charge_method, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.calculationmethod + ELSE suspensions_all.calculationmethod + END) AS suspension_calculation_method, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.value + ELSE suspensions_all.value + END) AS suspension_value, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.percentage + ELSE suspensions_all.percentage + END) AS suspension_percentage, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.netflag + ELSE suspensions_all.netflag + END) AS suspension_netflag, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.currency + ELSE suspensions_all.currency + END) AS suspension_currency, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.taxid + ELSE suspensions_all.taxid + END) AS suspension_tax_id, + (CASE WHEN suspensions.suspension_id IS NOT NULL + THEN suspensions.note + ELSE suspensions_all.note + END) AS suspension_note, + (CASE WHEN suspensions.customerid IS NOT NULL + THEN suspensions_all.customerid + ELSE a.customerid + END) AS suspension_customer_id, + (CASE WHEN suspensions.taxrate IS NOT NULL + THEN suspensions.taxrate + ELSE suspensions_all.taxrate + END) AS suspension_taxrate, + (CASE WHEN suspensions.taxlabel IS NOT NULL + THEN suspensions.taxlabel + ELSE suspensions_all.taxlabel + END) AS suspension_taxlabel, + vasv.suspensionvalues_assignment_base_price, + vasv.suspensionvalues_assignment_tpv_price, + vasv.suspensionvalues_assignment_price, + vasv.suspensionvalues_assignments_count, + (CASE + WHEN suspensions.chargemethod = 3 OR suspensions.chargemethod = 2 + OR suspensions_all.chargemethod = 3 OR suspensions_all.chargemethod = 2 + THEN (CASE + WHEN suspensions.calculationmethod = 1 + THEN vasv.suspensionvalues_assignment_price * + (CASE + WHEN suspensions.percentage IS NOT NULL + THEN ROUND(suspensions.percentage / 100, 2) + ELSE + ROUND((SELECT CAST(uiconfig.value AS numeric) + FROM uiconfig + WHERE uiconfig.section = 'suspensions' + AND uiconfig.var = 'default_percentage' + AND uiconfig.configid IS NULL + LIMIT 1) / 100, 2) + END) + WHEN suspensions_all.calculationmethod = 1 + THEN vasv.suspensionvalues_assignment_price * + (CASE + WHEN suspensions_all.percentage IS NOT NULL + THEN ROUND(suspensions_all.percentage / 100, 2) + ELSE + ROUND((SELECT CAST(uiconfig.value AS numeric) + FROM uiconfig + WHERE uiconfig.section = 'suspensions' + AND uiconfig.var = 'default_percentage' + AND uiconfig.configid IS NULL + LIMIT 1) / 100, 2) + END) + WHEN suspensions.calculationmethod = 2 + THEN + (CASE + WHEN suspensions.value IS NOT NULL + THEN ROUND(suspensions.value / vasv.suspensionvalues_assignments_count, 2) + ELSE + ROUND((SELECT CAST(uiconfig.value AS numeric) + FROM uiconfig + WHERE uiconfig.section = 'suspensions' + AND uiconfig.var = 'default_percentage' + AND uiconfig.configid IS NULL + LIMIT 1) / 100, 2) + END) + WHEN suspensions_all.calculationmethod = 2 + THEN + (CASE + WHEN suspensions_all.value IS NOT NULL + THEN ROUND(suspensions_all.value / vasv.suspensionvalues_assignments_count, 2) + ELSE + ROUND((SELECT CAST(uiconfig.value AS numeric) + FROM uiconfig + WHERE uiconfig.section = 'suspensions' + AND uiconfig.var = 'default_percentage' + AND uiconfig.configid IS NULL + LIMIT 1) / 100, 2) + END) + END) + WHEN suspensions.chargemethod = 1 OR suspensions_all.chargemethod = 1 + THEN 0 + END) AS suspension_price + FROM assignments a + LEFT JOIN ( + SELECT + tariffs.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN tariffs.flags & 16 > 0 THEN tariffs.netvalue ELSE tariffs.value END) AS tvalue + FROM tariffs + JOIN taxes ON taxes.id = tariffs.taxid + ) t ON a.tariffid = t.id + LEFT JOIN ( + SELECT + tpv.* + FROM assignments a + JOIN ( + SELECT + tariffpricevariants.quantity_threshold AS tpv_quantity_threshold, + tariffs.id AS tpv_tariffid, + (CASE WHEN tariffs.flags & 16 > 0 THEN tariffpricevariants.net_price ELSE tariffpricevariants.gross_price END) AS tpvprice + FROM tariffs + JOIN tariffpricevariants ON tariffs.id = tariffpricevariants.tariffid + ) tpv ON a.tariffid = tpv.tpv_tariffid AND tpv.tpv_quantity_threshold <= a.count AND tpv.tpv_tariffid = a.tariffid + ORDER BY tpv.tpv_quantity_threshold DESC LIMIT 1 + ) AS assignments_tpvariants ON a.tariffid = assignments_tpvariants.tpv_tariffid + LEFT JOIN ( + SELECT + liabilities.*, + taxes.value AS taxrate, taxes.label AS taxlabel, + (CASE WHEN liabilities.flags & 16 > 0 THEN liabilities.netvalue ELSE liabilities.value END) AS lvalue + FROM liabilities + JOIN taxes ON taxes.id = liabilities.taxid + ) l ON a.liabilityid = l.id + LEFT JOIN ( + SELECT + assignmentsuspensions.id AS assignmentsuspension_id, + assignmentsuspensions.assignmentid AS assignment_id, + assignmentsuspensions.suspensionid AS suspension_id, + suspensions1.id AS id, + suspensions1.at, suspensions1.datefrom, suspensions1.dateto, suspensions1.chargemethod, suspensions1.calculationmethod, + suspensions1.value, suspensions1.percentage, suspensions1.netflag, suspensions1.currency, suspensions1.note, suspensions1.taxid, + suspensions1.customerid, + taxes.value AS taxrate, taxes.label AS taxlabel + FROM assignmentsuspensions + JOIN suspensions AS suspensions1 ON suspensions1.id = assignmentsuspensions.suspensionid + LEFT JOIN taxes ON taxes.id = suspensions1.taxid + ) suspensions ON suspensions.assignment_id = a.id + LEFT JOIN ( + SELECT suspensions2.id AS suspension_id, suspensions2.at, suspensions2.datefrom, suspensions2.dateto, + suspensions2.chargemethod, suspensions2.calculationmethod, + suspensions2.value, suspensions2.percentage, suspensions2.netflag, suspensions2.currency, suspensions2.note, suspensions2.taxid, + suspensions2.customerid, + (CASE WHEN suspensions2.customerid IS NULL THEN 0 ELSE 1 END) AS suspend_all, + taxes.value AS taxrate, taxes.label AS taxlabel + FROM suspensions AS suspensions2 + LEFT JOIN taxes ON taxes.id = suspensions2.taxid + ) AS suspensions_all ON suspensions_all.customerid = a.customerid + LEFT JOIN vassignmentssuspensionsvalues vasv ON vasv.suspensionvalues_assignment_id = a.id + WHERE suspensions.suspension_id IS NOT NULL OR suspensions_all.suspend_all = 1 +"); + +$this->Execute(" +CREATE VIEW vnodetariffs AS + SELECT n.*, + t.downrate, t.downceil, + t.uprate, t.upceil, + t.downrate_n, t.downceil_n, + t.uprate_n, t.upceil_n, + net.mask, net.gateway, net.dns, net.dns2, + m.mac, + a.ccode, + a.city_id as location_city, a.street_id as location_street, + a.house as location_house, a.flat as location_flat, + a.location + FROM nodes n + JOIN networks net ON net.id = n.netid + LEFT JOIN (SELECT nodeid, array_to_string(array_agg(mac), ',') AS mac FROM macs GROUP BY nodeid) m ON (n.id = m.nodeid) + LEFT JOIN vaddresses a ON n.address_id = a.id + JOIN ( + SELECT n.id AS nodeid, + ROUND(SUM(t.downrate * a.count)) AS downrate, + ROUND(SUM(t.downceil * a.count)) AS downceil, + SUM(t.down_burst_time) AS down_burst_time, + SUM(t.down_burst_threshold) AS down_burst_threshold, + SUM(t.down_burst_limit) AS down_burst_limit, + ROUND(SUM(t.uprate * a.count)) AS uprate, + ROUND(SUM(t.upceil * a.count)) AS upceil, + SUM(t.up_burst_time) AS up_burst_time, + SUM(t.up_burst_threshold) AS up_burst_threshold, + SUM(t.up_burst_limit) AS up_burst_limit, + ROUND(SUM(COALESCE(t.downrate_n, t.downrate) * a.count)) AS downrate_n, + ROUND(SUM(COALESCE(t.downceil_n, t.downceil) * a.count)) AS downceil_n, + SUM(COALESCE(t.down_burst_time_n, t.down_burst_time)) AS down_burst_time_n, + SUM(COALESCE(t.down_burst_threshold_n, t.down_burst_threshold)) AS down_burst_threshold_n, + SUM(COALESCE(t.down_burst_limit_n, t.down_burst_limit)) AS down_burst_limit_n, + ROUND(SUM(COALESCE(t.uprate_n, t.uprate) * a.count)) AS uprate_n, + ROUND(SUM(COALESCE(t.upceil_n, t.upceil) * a.count)) AS upceil_n, + SUM(COALESCE(t.up_burst_time_n, t.up_burst_time)) AS up_burst_time_n, + SUM(COALESCE(t.up_burst_threshold_n, t.up_burst_threshold)) AS up_burst_threshold_n, + SUM(COALESCE(t.up_burst_limit_n, t.up_burst_limit)) AS up_burst_limit_n + FROM nodes n + JOIN nodeassignments na ON na.nodeid = n.id + JOIN assignments a ON a.id = na.assignmentid + JOIN tariffs t ON t.id = a.tariffid + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer + AND (vas.suspension_dateto >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer OR vas.suspension_dateto = 0) + AND a.datefrom <= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer + AND (a.dateto > EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer OR a.dateto = 0) + WHERE vas.suspended IS NULL AND a.commited = 1 + AND a.datefrom <= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer + AND (a.dateto = 0 OR a.dateto >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer) + AND (t.downrate > 0 OR t.downceil > 0 OR t.uprate > 0 OR t.upceil > 0) + GROUP BY n.id + ) t ON t.nodeid = n.id + WHERE n.ipaddr <> 0 OR n.ipaddr_pub <> 0 +"); + +$this->Execute(" +CREATE VIEW vnodealltariffs AS + SELECT n.*, + COALESCE(t1.downrate, t2.downrate, 0) AS downrate, + COALESCE(t1.downceil, t2.downceil, 0) AS downceil, + COALESCE(t1.down_burst_time, t2.down_burst_time, 0) AS down_burst_time, + COALESCE(t1.down_burst_threshold, t2.down_burst_threshold, 0) AS down_burst_threshold, + COALESCE(t1.down_burst_limit, t2.down_burst_limit, 0) AS down_burst_limit, + COALESCE(t1.uprate, t2.uprate, 0) AS uprate, + COALESCE(t1.upceil, t2.upceil, 0) AS upceil, + COALESCE(t1.up_burst_time, t2.up_burst_time, 0) AS up_burst_time, + COALESCE(t1.up_burst_threshold, t2.up_burst_threshold, 0) AS up_burst_threshold, + COALESCE(t1.up_burst_limit, t2.up_burst_limit, 0) AS up_burst_limit, + COALESCE(t1.downrate_n, t2.downrate_n, 0) AS downrate_n, + COALESCE(t1.downceil_n, t2.downceil_n, 0) AS downceil_n, + COALESCE(t1.down_burst_time_n, t2.down_burst_time_n, 0) AS down_burst_time_n, + COALESCE(t1.down_burst_threshold_n, t2.down_burst_threshold_n, 0) AS down_burst_threshold_n, + COALESCE(t1.down_burst_limit_n, t2.down_burst_limit_n, 0) AS down_burst_limit_n, + COALESCE(t1.uprate_n, t2.uprate_n, 0) AS uprate_n, + COALESCE(t1.upceil_n, t2.upceil_n, 0) AS upceil_n, + COALESCE(t1.up_burst_time_n, t2.up_burst_time_n, 0) AS up_burst_time_n, + COALESCE(t1.up_burst_threshold_n, t2.up_burst_threshold_n, 0) AS up_burst_threshold_n, + COALESCE(t1.up_burst_limit_n, t2.up_burst_limit_n, 0) AS up_burst_limit_n, + net.mask, net.gateway, net.dns, net.dns2, + m.mac, + a.ccode, + a.city_id as location_city, a.street_id as location_street, + a.house as location_house, a.flat as location_flat, + a.location + FROM nodes n + JOIN networks net ON net.id = n.netid + LEFT JOIN ( + SELECT nodeid, array_to_string(array_agg(mac), ',') AS mac + FROM macs + GROUP BY nodeid + ) m ON n.id = m.nodeid + LEFT JOIN vaddresses a ON a.id = n.address_id + LEFT JOIN ( + SELECT n.id AS nodeid, + SUM(a.downrate) AS downrate, + SUM(a.downceil) AS downceil, + SUM(a.down_burst_time) AS down_burst_time, + SUM(a.down_burst_threshold) AS down_burst_threshold, + SUM(a.down_burst_limit) AS down_burst_limit, + SUM(a.uprate) AS uprate, + SUM(a.upceil) AS upceil, + SUM(a.up_burst_time) AS up_burst_time, + SUM(a.up_burst_threshold) AS up_burst_threshold, + SUM(a.up_burst_limit) AS up_burst_limit, + SUM(a.downrate_n) AS downrate_n, + SUM(a.downceil_n) AS downceil_n, + SUM(a.down_burst_time_n) AS down_burst_time_n, + SUM(a.down_burst_threshold_n) AS down_burst_threshold_n, + SUM(a.down_burst_limit_n) AS down_burst_limit_n, + SUM(a.uprate_n) AS uprate_n, + SUM(a.upceil_n) AS upceil_n, + SUM(a.up_burst_time_n) AS up_burst_time_n, + SUM(a.up_burst_threshold_n) AS up_burst_threshold_n, + SUM(a.up_burst_limit_n) AS up_burst_limit_n + FROM nodes n + JOIN ( + SELECT n.id, + ROUND(SUM(t.downrate * a.count)) AS downrate, + ROUND(SUM(t.downceil * a.count)) AS downceil, + SUM(t.down_burst_time) AS down_burst_time, + SUM(t.down_burst_threshold) AS down_burst_threshold, + SUM(t.down_burst_limit) AS down_burst_limit, + ROUND(SUM(t.uprate * a.count)) AS uprate, + ROUND(SUM(t.upceil * a.count)) AS upceil, + SUM(t.up_burst_time) AS up_burst_time, + SUM(t.up_burst_threshold) AS up_burst_threshold, + SUM(t.up_burst_limit) AS up_burst_limit, + ROUND(SUM(COALESCE(t.downrate_n, t.downrate)) * a.count) AS downrate_n, + ROUND(SUM(COALESCE(t.downceil_n, t.downceil)) * a.count) AS downceil_n, + SUM(COALESCE(t.down_burst_time_n, t.down_burst_time)) AS down_burst_time_n, + SUM(COALESCE(t.down_burst_threshold_n, t.down_burst_threshold)) AS down_burst_threshold_n, + SUM(COALESCE(t.down_burst_limit_n, t.down_burst_limit)) AS down_burst_limit_n, + ROUND(SUM(COALESCE(t.uprate_n, t.uprate)) * a.count) AS uprate_n, + ROUND(SUM(COALESCE(t.upceil_n, t.upceil)) * a.count) AS upceil_n, + SUM(COALESCE(t.up_burst_time_n, t.up_burst_time)) AS up_burst_time_n, + SUM(COALESCE(t.up_burst_threshold_n, t.up_burst_threshold)) AS up_burst_threshold_n, + SUM(COALESCE(t.up_burst_limit_n, t.up_burst_limit)) AS up_burst_limit_n + FROM assignments a + JOIN nodeassignments na ON na.assignmentid = a.id + JOIN nodes n ON n.id = na.nodeid + JOIN tariffs t ON t.id = a.tariffid + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer + AND (vas.suspension_dateto >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer OR vas.suspension_dateto = 0) + AND a.datefrom <= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer + AND (a.dateto > EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer OR a.dateto = 0) + WHERE vas.suspended IS NULL AND a.commited = 1 + AND a.datefrom <= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer + AND (a.dateto = 0 OR a.dateto >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer) + AND (t.downrate > 0 OR t.downceil > 0 OR t.uprate > 0 OR t.upceil > 0) + GROUP BY n.id, a.count + ) a ON a.id = n.id + GROUP BY n.id + ) t1 ON t1.nodeid = n.id + LEFT JOIN ( + SELECT n.id AS nodeid, + SUM(a.downrate) AS downrate, + SUM(a.downceil) AS downceil, + SUM(a.down_burst_time) AS down_burst_time, + SUM(a.down_burst_threshold) AS down_burst_threshold, + SUM(a.down_burst_limit) AS down_burst_limit, + SUM(a.uprate) AS uprate, + SUM(a.upceil) AS upceil, + SUM(a.up_burst_time) AS up_burst_time, + SUM(a.up_burst_threshold) AS up_burst_threshold, + SUM(a.up_burst_limit) AS up_burst_limit, + SUM(a.downrate_n) AS downrate_n, + SUM(a.downceil_n) AS downceil_n, + SUM(a.down_burst_time_n) AS down_burst_time_n, + SUM(a.down_burst_threshold_n) AS down_burst_threshold_n, + SUM(a.down_burst_limit_n) AS down_burst_limit_n, + SUM(a.uprate_n) AS uprate_n, + SUM(a.upceil_n) AS upceil_n, + SUM(a.up_burst_time_n) AS up_burst_time_n, + SUM(a.up_burst_threshold_n) AS up_burst_threshold_n, + SUM(a.up_burst_limit_n) AS up_burst_limit_n + FROM nodes n + JOIN ( + SELECT n.id AS nodeid, + ROUND(SUM(t.downrate * a.count)) AS downrate, + ROUND(SUM(t.downceil * a.count)) AS downceil, + SUM(t.down_burst_time) AS down_burst_time, + SUM(t.down_burst_threshold) AS down_burst_threshold, + SUM(t.down_burst_limit) AS down_burst_limit, + ROUND(SUM(t.uprate * a.count)) AS uprate, + ROUND(SUM(t.upceil * a.count)) AS upceil, + SUM(t.up_burst_time) AS up_burst_time, + SUM(t.up_burst_threshold) AS up_burst_threshold, + SUM(t.up_burst_limit) AS up_burst_limit, + ROUND(SUM((CASE WHEN t.downrate_n IS NOT NULL THEN t.downrate_n ELSE t.downrate END) * a.count)) AS downrate_n, + ROUND(SUM((CASE WHEN t.downceil_n IS NOT NULL THEN t.downceil_n ELSE t.downceil END) * a.count)) AS downceil_n, + SUM(CASE WHEN t.down_burst_time_n IS NOT NULL THEN t.down_burst_time_n ELSE t.down_burst_time END) AS down_burst_time_n, + SUM(CASE WHEN t.down_burst_threshold_n IS NOT NULL THEN t.down_burst_threshold_n ELSE t.down_burst_threshold END) AS down_burst_threshold_n, + SUM(CASE WHEN t.down_burst_limit_n IS NOT NULL THEN t.down_burst_limit_n ELSE t.down_burst_limit END) AS down_burst_limit_n, + ROUND(SUM((CASE WHEN t.uprate_n IS NOT NULL THEN t.uprate_n ELSE t.uprate END) * a.count)) AS uprate_n, + ROUND(SUM((CASE WHEN t.upceil_n IS NOT NULL THEN t.upceil_n ELSE t.upceil END) * a.count)) AS upceil_n, + SUM(CASE WHEN t.up_burst_time_n IS NOT NULL THEN t.up_burst_time_n ELSE t.up_burst_time END) AS up_burst_time_n, + SUM(CASE WHEN t.up_burst_threshold_n IS NOT NULL THEN t.up_burst_threshold_n ELSE t.up_burst_threshold END) AS up_burst_threshold_n, + SUM(CASE WHEN t.up_burst_limit_n IS NOT NULL THEN t.up_burst_limit_n ELSE t.up_burst_limit END) AS up_burst_limit_n + FROM assignments a + JOIN tariffs t ON t.id = a.tariffid + JOIN ( + SELECT vn.id, + (CASE WHEN nd.id IS NULL THEN vn.ownerid ELSE nd.ownerid END) AS ownerid + FROM vnodes vn + LEFT JOIN netdevices nd ON nd.id = vn.netdev AND vn.ownerid IS NULL AND nd.ownerid IS NOT NULL + WHERE (vn.ownerid IS NOT NULL AND nd.id IS NULL) + OR (vn.ownerid IS NULL AND nd.id IS NOT NULL) + ) n ON n.ownerid = a.customerid + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer + AND (vas.suspension_dateto >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer OR vas.suspension_dateto = 0) + AND a.datefrom <= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer + AND (a.dateto > EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer OR a.dateto = 0) + WHERE vas.suspended IS NULL AND a.commited = 1 + AND a.datefrom <= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer + AND (a.dateto = 0 OR a.dateto >= EXTRACT(EPOCH FROM CURRENT_TIMESTAMP(0))::integer) + AND (t.downrate > 0 OR t.downceil > 0 OR t.uprate > 0 OR t.upceil > 0) + AND n.id NOT IN (SELECT nodeid FROM nodeassignments) + AND a.id NOT IN (SELECT assignmentid FROM nodeassignments) + GROUP BY n.id, a.count + ) a ON a.nodeid = n.id + GROUP BY n.id + ) t2 ON t2.nodeid = n.id + WHERE (n.ipaddr <> 0 OR n.ipaddr_pub <> 0) + AND ((t1.nodeid IS NOT NULL AND t2.nodeid IS NULL) + OR (t1.nodeid IS NULL AND t2.nodeid IS NOT NULL) + OR (t1.nodeid IS NULL AND t2.nodeid IS NULL)) +"); + +$this->Execute("ALTER TABLE assignments DROP COLUMN suspended"); + +$this->Execute("UPDATE dbinfo SET keyvalue = ? WHERE keytype = ?", array('2024052400', 'dbversion')); + +$this->CommitTrans(); diff --git a/modules/configlist.php b/modules/configlist.php index 53ab9fc5d6..1e62d88ac1 100644 --- a/modules/configlist.php +++ b/modules/configlist.php @@ -109,7 +109,13 @@ function GetConfigList() 'payments' => array( 'date_format' => 'Define date format for variable: %period, %aligned_period, %current_month used in payments.comment and payments.settlement_comment', 'default_unit_name' => 'Unit name on invoice, default: "pcs."', - 'suspension_percentage' => 'Percentage of suspended liabilities. Default: 0', + ), + 'suspensions' => array( + 'default_percentage' => 'Default suspension percentage. Default: 0', + 'default_value' => 'Default suspension value. Default: 0', + 'default_netflag' => 'Default suspension netflag. Default: 0', + 'default_charge_method' => 'Default suspension charge method. Default: 2', + 'default_calculation_method' => 'Default suspension calculation method. Default: 1', ), 'finances' => array( 'cashimport_checkinvoices' => 'Check invoices as accounted when importing cash operations. Default: false', diff --git a/modules/customer.inc.php b/modules/customer.inc.php index 99b40fe0c1..b80e193860 100644 --- a/modules/customer.inc.php +++ b/modules/customer.inc.php @@ -79,7 +79,11 @@ } else { $period = null; } - $assignments = $LMS->GetCustomerAssignments($customerid, true, false); + $assignmentsWithSuspensions = $LMS->getCustomerAssignments($customerid, array('show_expired' => true, 'show_approved' => false, 'with_suspensions' => true)); + if (!empty($assignmentsWithSuspensions)) { + $assignments = !empty($assignmentsWithSuspensions['assignments']) ? $assignmentsWithSuspensions['assignments'] : array(); + $suspensions = !empty($assignmentsWithSuspensions['suspensions']) ? $assignmentsWithSuspensions['suspensions'] : array(); + } } if (!isset($resource_tabs['customergroups']) || $resource_tabs['customergroups']) { $customergroups = $LMS->CustomergroupGetForCustomer($customerid); @@ -286,6 +290,7 @@ $SMARTY->assignByRef('customernetnodes', $customernetnodes); $SMARTY->assignByRef('customerstats', $customerstats); $SMARTY->assignByRef('assignments', $assignments); +$SMARTY->assignByRef('suspensions', $suspensions); $SMARTY->assignByRef('nodeassignments', $nodeassignments); $SMARTY->assignByRef('customergroups', $customergroups); $SMARTY->assignByRef('othercustomergroups', $othercustomergroups); diff --git a/modules/customerassignmentadd.php b/modules/customerassignmentadd.php index a00d5d9aa5..aac91f3b2c 100644 --- a/modules/customerassignmentadd.php +++ b/modules/customerassignmentadd.php @@ -34,106 +34,432 @@ } if (isset($_POST['assignment'])) { - $a = $_POST['assignment']; + $a = r_trim($_POST['assignment']); - $result = $LMS->ValidateAssignment($a); - extract($result); - if (empty($a['taxid'])) { - $error['taxid'] = trans('— no tax rates defined —'); - } - - if (isset($schemaid) && !$LMS->CheckSchemaModifiedValues($a)) { - $error['promotion-select'] = trans('Illegal promotion schema period value modification!'); - } - - // try to restrict node assignment sharing - if ($a['tariffid'] > 0 && !empty($a['nodes'])) { - $restricted_nodes = $LMS->CheckNodeTariffRestrictions($a['id'] ?? null, $a['nodes'], $from, $to); - $node_multi_tariff_restriction = ConfigHelper::getConfig( - 'phpui.node_multi_tariff_restriction', - '', - true - ); - if (preg_match('/^(error|warning)$/', $node_multi_tariff_restriction) && !empty($restricted_nodes)) { - foreach ($restricted_nodes as $nodeid) { - if ($node_multi_tariff_restriction == 'error') { - $error['assignment[nodes][' . $nodeid . ']'] = trans('This item is already bound with another assignment!'); - } else { - if (!isset($a['node_warns'][$nodeid])) { + if (!isset($a['suspended_assignments']) && !isset($a['suspend_all'])) { + $result = $LMS->ValidateAssignment($a); + extract($result); + if (empty($a['taxid'])) { + $error['taxid'] = trans('— no tax rates defined —'); + } + if (isset($schemaid) && !$LMS->CheckSchemaModifiedValues($a)) { + $error['promotion-select'] = trans('Illegal promotion schema period value modification!'); + }// try to restrict node assignment sharing + if ($a['tariffid'] > 0 && !empty($a['nodes'])) { + $restricted_nodes = $LMS->CheckNodeTariffRestrictions($a['id'] ?? null, $a['nodes'], $from, $to); + $node_multi_tariff_restriction = ConfigHelper::getConfig( + 'phpui.node_multi_tariff_restriction', + '', + true + ); + if (preg_match('/^(error|warning)$/', $node_multi_tariff_restriction) && !empty($restricted_nodes)) { + foreach ($restricted_nodes as $nodeid) { + if ($node_multi_tariff_restriction == 'error') { $error['assignment[nodes][' . $nodeid . ']'] = trans('This item is already bound with another assignment!'); + } else { + if (!isset($a['node_warns'][$nodeid])) { + $error['assignment[nodes][' . $nodeid . ']'] = trans('This item is already bound with another assignment!'); + } + $a['node_warns'][$nodeid] = $nodeid; } - $a['node_warns'][$nodeid] = $nodeid; } } } - } + $hook_data = $LMS->executeHook( + 'customerassignmentadd_validation_before_submit', + array( + 'a' => $a, + 'error' => $error + ) + ); + $a = $hook_data['a']; + $error = $hook_data['error']; + if (!$error) { + $a['customerid'] = $customer['id']; + $a['period'] = $period; + $a['at'] = $at; + $a['datefrom'] = $from; + $a['dateto'] = $to; + $a['count'] = $count; + $a['paytime'] = $paytime; + + $DB->BeginTrans(); + + $LMS->UpdateExistingAssignments($a); + + if (isset($a['sassignmentid'][$schemaid]) && is_array($a['sassignmentid'][$schemaid])) { + $modifiedvalues = $a['values'][$schemaid] ?? array(); + $counts = $a['counts'][$schemaid]; + $backwardperiods = $a['backwardperiods'][$schemaid]; + $copy_a = $a; + $snodes = $a['snodes'][$schemaid] ?? array(); + $sphones = $a['sphones'][$schemaid] ?? array(); + + foreach ($a['sassignmentid'][$schemaid] as $label => $v) { + if (!$v) { + continue; + } - $hook_data = $LMS->executeHook( - 'customerassignmentadd_validation_before_submit', - array( - 'a' => $a, - 'error' => $error - ) - ); - $a = $hook_data['a']; - $error = $hook_data['error']; - - if (!$error) { - $a['customerid'] = $customer['id']; - $a['period'] = $period; - $a['at'] = $at; - $a['datefrom'] = $from; - $a['dateto'] = $to; - $a['count'] = $count; - $a['paytime'] = $paytime; - - $DB->BeginTrans(); - - $LMS->UpdateExistingAssignments($a); - - if (isset($a['sassignmentid'][$schemaid]) && is_array($a['sassignmentid'][$schemaid])) { - $modifiedvalues = $a['values'][$schemaid] ?? array(); - $counts = $a['counts'][$schemaid]; - $backwardperiods = $a['backwardperiods'][$schemaid]; - $copy_a = $a; - $snodes = $a['snodes'][$schemaid] ?? array(); - $sphones = $a['sphones'][$schemaid] ?? array(); - - foreach ($a['sassignmentid'][$schemaid] as $label => $v) { - if (!$v) { - continue; + $copy_a['promotionassignmentid'] = $v; + $copy_a['modifiedvalues'] = $modifiedvalues[$label][$v] ?? array(); + $copy_a['count'] = $counts[$label]; + $copy_a['backwardperiod'] = $backwardperiods[$label][$v]; + $copy_a['nodes'] = $snodes[$label] ?? array(); + $copy_a['phones'] = $sphones[$label] ?? array(); + $tariffid = $LMS->AddAssignment($copy_a); } + } else { + $a['taxvalue'] = $DB->GetOne('SELECT value FROM taxes WHERE id = ?', array($a['taxid'])); + $tariffid = $LMS->AddAssignment($a); + } - $copy_a['promotionassignmentid'] = $v; - $copy_a['modifiedvalues'] = $modifiedvalues[$label][$v] ?? array(); - $copy_a['count'] = $counts[$label]; - $copy_a['backwardperiod'] = $backwardperiods[$label][$v]; - $copy_a['nodes'] = $snodes[$label] ?? array(); - $copy_a['phones'] = $sphones[$label] ?? array(); - $tariffid = $LMS->AddAssignment($copy_a); + if ($a['tarifftype'] == SERVICE_PHONE && !empty($a['phones'])) { + $tariffid = $tariffid[0]; } - } else { - $a['taxvalue'] = $DB->GetOne('SELECT value FROM taxes WHERE id = ?', array($a['taxid'])); - $tariffid = $LMS->AddAssignment($a); + + $DB->CommitTrans(); + + $LMS->executeHook( + 'customerassignmentadd_after_submit', + array( + 'assignment' => $a, + ) + ); + + $SESSION->redirect_to_history_entry(); } - if ($a['tarifftype'] == SERVICE_PHONE && !empty($a['phones'])) { - $tariffid = $tariffid[0]; + $a['alltariffs'] = isset($a['alltariffs']); + } else { + //region suspension common part + $suspension = $a; + $defaultTaxIds = $LMS->GetTaxes(null, null, true); + + if (is_array($defaultTaxIds)) { + $defaultTaxId = reset($defaultTaxIds); + $defaultTaxId = $defaultTaxId['id']; + } else { + $defaultTaxId = 0; } - $DB->CommitTrans(); + $today = strtotime('today'); + $suspensionValue = null; + $suspensionPercentage = null; + $suspension_at = null; + $suspension_netflag = null; + $suspension_currency = null; + $suspension_taxid = null; + + if ($suspension['suspension_charge_method'] != SUSPENSION_CHARGE_METHOD_NONE) { + if ($suspension['suspension_calculation_method'] == SUSPENSION_CALCULATION_METHOD_VALUE) { + $suspension_netflag = isset($suspension['suspension_netflag']) ? 1 : 0; + if ($suspension_netflag) { + if (!empty($suspension['suspension_net_value']) && f_round($suspension['suspension_net_value']) != 0) { + $suspensionValue = str_replace(',', '.', f_round($suspension['suspension_net_value'])); + } elseif ($suspension['suspension_net_value'] == '') { + $suspensionValue = null; + } elseif (isset($suspension['suspension_net_value']) && f_round($suspension['suspension_net_value']) == 0) { + $suspensionValue = 0; + } + } else { + if (!empty($suspension['suspension_gross_value']) && f_round($suspension['suspension_gross_value']) != 0) { + $suspensionValue = str_replace(',', '.', f_round($suspension['suspension_gross_value'])); + } elseif ($suspension['suspension_gross_value'] == '') { + $suspensionValue = null; + } elseif (isset($suspension['suspension_gross_value']) && f_round($suspension['suspension_gross_value']) == 0) { + $suspensionValue = 0; + } + } - $LMS->executeHook( - 'customerassignmentadd_after_submit', - array( - 'assignment' => $a, - ) + $suspension_currency = $suspension['currency']; + $suspension_taxid = $suspension['taxid']; + } elseif ($suspension['suspension_calculation_method'] == SUSPENSION_CALCULATION_METHOD_PERCENTAGE) { + if (!empty($suspension['suspension_percentage']) && f_round($suspension['suspension_percentage']) != 0) { + $suspensionPercentage = str_replace(',', '.', f_round($suspension['suspension_percentage'])); + } elseif ($suspension['suspension_percentage'] == '') { + $suspensionPercentage = null; + } elseif (isset($suspension['suspension_percentage']) && f_round($suspension['suspension_percentage']) == 0) { + $suspensionPercentage = 0; + } + } + } else { + $suspension['suspension_calculation_method'] = SUSPENSION_CALCULATION_METHOD_PERCENTAGE; + $suspensionPercentage = 0; + } + + $suspensionArgs = array( + 'at' => $suspension_at, + 'datefrom' => !empty($suspension['datefrom']) ? $suspension['datefrom'] : 0, + 'dateto' => !empty($suspension['dateto']) ? (strtotime('+ 1 day', $suspension['dateto']) - 1) : 0, + 'chargemethod' => $suspension['suspension_charge_method'], + 'calculationmethod' => $suspension['suspension_calculation_method'], + 'value' => $suspensionValue, + 'percentage' => $suspensionPercentage, + 'netflag' => $suspension_netflag, + 'currency' => $suspension_currency, + 'taxid' => $suspension_taxid, + 'note' => !empty($suspension['note']) ? Utils::removeInsecureHtml($suspension['note']) : null, ); + //endregion + + if (isset($suspension['suspend_all'])) { + // suspend all + $suspension['existing_suspend_all'] = $LMS->getCustomerAssignments($customer['id'], array('suspend_all' => true)); + $error = $LMS->ValidateSuspension($suspension); + if (empty($error)) { + $assignments = $LMS->getCustomerAssignments($customer['id'], array('not_suspended' => true)); + if (!empty($assignments)) { + foreach ($assignments as $row) { + switch ($row['assignment_charge_method']) { + case SUSPENSION_CHARGE_METHOD_ONCE: + $startdate = $row['datefrom'] > $today ? $row['datefrom'] : $today; + [$year, $month, $dom] = explode('/', date('Y/n/j', $startdate)); + $commingPayDate = 0; + $commingPayTimestamp = 0; + + switch ($row['periodvalue']) { + case DISPOSABLE: + $commingPayTimestamp = $row['at']; + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + case MONTHLY: + $commingPayTimestamp = mktime(0, 0, 0, $month, $row['at'], $year); + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + case QUARTERLY: + [$d, $m] = explode('/', $row['at']); + $quarterlyDate1 = mktime(0, 0, 0, $m, $d, $year); + $quarterlyDate2 = strtotime('+3 months', $quarterlyDate1); + $quarterlyDate3 = strtotime('+6 months', $quarterlyDate1); + $quarterlyDate4 = strtotime('+9 months', $quarterlyDate1); + + if ($quarterlyDate1 <= $row['datefrom']) { + if ($quarterlyDate2 <= $row['datefrom']) { + if ($quarterlyDate3 <= $row['datefrom']) { + if ($quarterlyDate4 <= $row['datefrom']) { + $commingPayTimestamp = strtotime('+3 months', $quarterlyDate4); + } else { + $commingPayTimestamp = $quarterlyDate3; + } + } else { + $commingPayTimestamp = $quarterlyDate3; + } + } else { + $commingPayTimestamp = $quarterlyDate2; + } + } else { + $commingPayTimestamp = $quarterlyDate1; + } + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + case HALFYEARLY: + [$d, $m] = explode('/', $row['at']); + $halfyearlyDate1 = mktime(0, 0, 0, $m, $d, $year); + $halfyearlyDate2 = strtotime('+6 months', $halfyearlyDate1); + + if ($halfyearlyDate1 <= $row['datefrom']) { + if ($halfyearlyDate2 <= $row['datefrom']) { + $commingPayTimestamp = strtotime('+6 months', $halfyearlyDate2); + } else { + $commingPayTimestamp = $halfyearlyDate2; + } + } else { + $commingPayTimestamp = $halfyearlyDate1; + } + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + case YEARLY: + [$d, $m] = explode('/', $row['at']); + $yearlyDate = mktime(0, 0, 0, $m, $d, $year); + if ($yearlyDate <= $row['datefrom']) { + $commingPayTimestamp = strtotime('+1 year', $yearlyDate); + } else { + $commingPayTimestamp = $yearlyDate; + } + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + } + + if (!isset($suspension_at) || $commingPayTimestamp < $suspension_at) { + $suspension_at = $commingPayTimestamp; + } + break; + case SUSPENSION_CHARGE_METHOD_PERIODICALLY: + $startdate = $row['datefrom'] > $today ? $row['datefrom'] : $today; + $dom = date('j', $startdate); + $commingPayDay = 0; + + switch ($row['periodvalue']) { + case DISPOSABLE: + $commingPayDay = date('j', $row['at']); + break; + case MONTHLY: + $commingPayDay = $row['at']; + break; + case QUARTERLY: + case HALFYEARLY: + case YEARLY: + [$d, $m] = explode('/', $row['at']); + $commingPayDay = $d; + break; + } + + if (!isset($suspension_at) || $commingPayDay < $suspension_at) { + $suspension_at = $commingPayDay; + } + break; + } + } + } + + $suspensionArgs['at'] = $suspension_at; + $suspensionArgs['customerid'] = $customer['id']; + + $DB->BeginTrans(); + $DB->LockTables(array('suspensions', 'assignmentsuspensions')); + + $LMS->addSuspension($suspensionArgs); + + $DB->UnLockTables(); + $DB->CommitTrans(); + $SESSION->redirect_to_history_entry(); + } + } elseif (!empty($suspension['suspended_assignments'])) { + // suspend group + $suspension['existing_suspensions'] = $LMS->getCustomerAssignments($customer['id'], array('suspended' => true)); + $error = $LMS->ValidateSuspension($suspension); + if (empty($error)) { + $suspendedAssignemnts = implode(',', array_keys($suspension['suspended_assignments'])); + $assignments = $LMS->getCustomerAssignments($customer['id'], array('assignments' => $suspendedAssignemnts)); + if (!empty($assignments)) { + foreach ($assignments as $row) { + switch ($row['assignment_charge_method']) { + case SUSPENSION_CHARGE_METHOD_ONCE: + $startdate = $row['datefrom'] > $today ? $row['datefrom'] : $today; + [$year, $month, $dom] = explode('/', date('Y/n/j', $startdate)); + $commingPayDate = 0; + $commingPayTimestamp = 0; + + switch ($row['periodvalue']) { + case DISPOSABLE: + $commingPayTimestamp = $row['at']; + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + case MONTHLY: + $commingPayTimestamp = mktime(0, 0, 0, $month, $row['at'], $year); + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + case QUARTERLY: + [$d, $m] = explode('/', $row['at']); + $quarterlyDate1 = mktime(0, 0, 0, $m, $d, $year); + $quarterlyDate2 = strtotime('+3 months', $quarterlyDate1); + $quarterlyDate3 = strtotime('+6 months', $quarterlyDate1); + $quarterlyDate4 = strtotime('+9 months', $quarterlyDate1); + + if ($quarterlyDate1 <= $row['datefrom']) { + if ($quarterlyDate2 <= $row['datefrom']) { + if ($quarterlyDate3 <= $row['datefrom']) { + if ($quarterlyDate4 <= $row['datefrom']) { + $commingPayTimestamp = strtotime('+3 months', $quarterlyDate4); + } else { + $commingPayTimestamp = $quarterlyDate3; + } + } else { + $commingPayTimestamp = $quarterlyDate3; + } + } else { + $commingPayTimestamp = $quarterlyDate2; + } + } else { + $commingPayTimestamp = $quarterlyDate1; + } + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + case HALFYEARLY: + [$d, $m] = explode('/', $row['at']); + $halfyearlyDate1 = mktime(0, 0, 0, $m, $d, $year); + $halfyearlyDate2 = strtotime('+6 months', $halfyearlyDate1); + + if ($halfyearlyDate1 <= $row['datefrom']) { + if ($halfyearlyDate2 <= $row['datefrom']) { + $commingPayTimestamp = strtotime('+6 months', $halfyearlyDate2); + } else { + $commingPayTimestamp = $halfyearlyDate2; + } + } else { + $commingPayTimestamp = $halfyearlyDate1; + } + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + case YEARLY: + [$d, $m] = explode('/', $row['at']); + $yearlyDate = mktime(0, 0, 0, $m, $d, $year); + if ($yearlyDate <= $row['datefrom']) { + $commingPayTimestamp = strtotime('+1 year', $yearlyDate); + } else { + $commingPayTimestamp = $yearlyDate; + } + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + } + + if (!isset($suspension_at) || $commingPayTimestamp < $suspension_at) { + $suspension_at = $commingPayTimestamp; + } + break; + case SUSPENSION_CHARGE_METHOD_PERIODICALLY: + $startdate = $row['datefrom'] > $today ? $row['datefrom'] : $today; + $dom = date('j', $startdate); + $commingPayDay = 0; + + switch ($row['periodvalue']) { + case DISPOSABLE: + $commingPayDay = date('j', $row['at']); + break; + case MONTHLY: + $commingPayDay = $row['at']; + break; + case QUARTERLY: + case HALFYEARLY: + case YEARLY: + [$d, $m] = explode('/', $row['at']); + $commingPayDay = $d; + break; + } + + if (!isset($suspension_at) || $commingPayDay < $suspension_at) { + $suspension_at = $commingPayDay; + } + break; + } + } + } + + $suspensionArgs['at'] = $suspension_at; + $suspensionArgs['customerid'] = null; + + $DB->BeginTrans(); + $DB->LockTables(array('suspensions', 'assignmentsuspensions')); + + $suspensionId = $LMS->addSuspension($suspensionArgs); + + foreach ($suspension['suspended_assignments'] as $akey => $a) { + $args = array( + 'suspension_id' => $suspensionId, + 'assignment_id' => $akey, + 'customerid' => $customer['id'], + ); + $LMS->addAssignmentSuspension($args); + } - $SESSION->redirect_to_history_entry(); - } - $a['alltariffs'] = isset($a['alltariffs']); + $DB->UnLockTables(); + $DB->CommitTrans(); + + $SESSION->redirect_to_history_entry(); + } + } + } $SMARTY->assign('error', $error); } else { @@ -227,7 +553,7 @@ $a['currency'] = Localisation::getDefaultCurrency(); } -$layout['pagetitle'] = trans('New Liability: $a', ''.$customer['name'].''); +$layout['pagetitle'] = trans('New Liability: $a', ''.$customer['name'].''); $SESSION->add_history_entry(); @@ -265,7 +591,14 @@ $defaultTaxId = 0; } $SMARTY->assign('defaultTaxId', $defaultTaxId); -$SMARTY->assign('assignments', $LMS->GetCustomerAssignments($customer['id'], true, false)); + +$assignmentsWithSuspensions = $LMS->getCustomerAssignments($customer['id'], array('show_expired' => true, 'show_approved' => false, 'with_suspensions' => true)); +if (!empty($assignmentsWithSuspensions)) { + $assignments = !empty($assignmentsWithSuspensions['assignments']) ? $assignmentsWithSuspensions['assignments'] : array(); + $suspensions = !empty($assignmentsWithSuspensions['suspensions']) ? $assignmentsWithSuspensions['suspensions'] : array(); +} +$SMARTY->assign('assignments', $assignments); +$SMARTY->assign('suspensions', $suspensions); $SMARTY->assign('customerinfo', $customer); $SMARTY->display('customer/customerassignmentsedit.html'); diff --git a/modules/customerassignmentedit.php b/modules/customerassignmentedit.php index 6999b3873f..2c77a84093 100644 --- a/modules/customerassignmentedit.php +++ b/modules/customerassignmentedit.php @@ -3,7 +3,7 @@ /* * LMS version 1.11-git * - * (C) Copyright 2001-2022 LMS Developers + * (C) Copyright 2001-2024 LMS Developers * * Please, see the doc/AUTHORS for more information about authors! * @@ -24,592 +24,858 @@ * $Id$ */ -// get customer name and check privileges using customerview -$aids = $_POST['customerassignments'] ?? array($_GET['id']); -$aids = Utils::filterIntegers($aids); -if (empty($aids)) { - $SESSION->redirect_to_history_entry(); -} - -if (count($aids) == 1) { - $aid = reset($aids); - $customer = $DB->GetRow( - 'SELECT a.customerid AS id, c.divisionid, ' - . $DB->Concat('c.lastname', "' '", 'c.name') . ' AS name - FROM assignments a - JOIN customerview c ON (c.id = a.customerid) - WHERE a.id = ?', - array($aid) - ); - if (!$customer) { +if (isset($_GET['action']) && $_GET['action'] == 'edit_suspension') { + $sid = isset($_GET['sid']) ? intval($_GET['sid']) : null; + $cid = isset($_GET['cid']) ? intval($_GET['cid']) : null; + $suspensionId = null; + $customerid = null; + if (!empty($sid)) { + $suspensionId = $DB->GetOne('SELECT id FROM suspensions WHERE id = ?', array($sid)); + } + if (!empty($cid)) { + $customer = $DB->GetRow( + 'SELECT c.id AS id, c.divisionid, ' + . $DB->Concat('c.lastname', "' '", 'c.name') . ' AS name + FROM customerview c + WHERE c.id = ?', + array($cid) + ); + if (!empty($customer)) { + $customerId = $customer['id']; + } + } + if (empty($suspensionId) || empty($customerId)) { $SESSION->redirect_to_history_entry(); } + + if (isset($_POST['assignment'])) { + $suspension = r_trim($_POST['assignment']); + $origSuspension = $LMS->getSuspensions(array('suspension_id' => $suspensionId, 'by_suspension_id' => true)); + + $defaultTaxIds = $LMS->GetTaxes(null, null, true); + if (is_array($defaultTaxIds)) { + $defaultTaxId = reset($defaultTaxIds); + $defaultTaxId = $defaultTaxId['id']; + } else { + $defaultTaxId = 0; + } + + $today = strtotime('today'); + $suspensionValue = null; + $suspensionPercentage = null; + $suspension_at = null; + $suspension_netflag = null; + $suspension_currency = null; + $suspension_taxid = null; + + if ($suspension['suspension_charge_method'] != SUSPENSION_CHARGE_METHOD_NONE) { + if ($suspension['suspension_calculation_method'] == SUSPENSION_CALCULATION_METHOD_VALUE) { + $suspension_netflag = isset($suspension['suspension_netflag']) ? 1 : 0; + + if ($suspension_netflag) { + if (!empty($suspension['suspension_net_value']) && f_round($suspension['suspension_net_value']) != 0) { + $suspensionValue = str_replace(',', '.', f_round($suspension['suspension_net_value'])); + } elseif ($suspension['suspension_net_value'] == '') { + $suspensionValue = null; + } elseif (isset($suspension['suspension_net_value']) && f_round($suspension['suspension_net_value']) == 0) { + $suspensionValue = 0; + } + } else { + if (!empty($suspension['suspension_gross_value']) && f_round($suspension['suspension_gross_value']) != 0) { + $suspensionValue = str_replace(',', '.', f_round($suspension['suspension_gross_value'])); + } elseif ($suspension['suspension_gross_value'] == '') { + $suspensionValue = null; + } elseif (isset($suspension['suspension_gross_value']) && f_round($suspension['suspension_gross_value']) == 0) { + $suspensionValue = 0; + } + } + + $suspension_currency = $suspension['currency']; + $suspension_taxid = $suspension['taxid']; + } elseif ($suspension['suspension_calculation_method'] == SUSPENSION_CALCULATION_METHOD_PERCENTAGE) { + if (!empty($suspension['suspension_percentage']) && f_round($suspension['suspension_percentage']) != 0) { + $suspensionPercentage = str_replace(',', '.', f_round($suspension['suspension_percentage'])); + } elseif ($suspension['suspension_percentage'] == '') { + $suspensionPercentage = null; + } elseif (isset($suspension['suspension_percentage']) && f_round($suspension['suspension_percentage']) == 0) { + $suspensionPercentage = 0; + } + } + } else { + $suspension['suspension_calculation_method'] = SUSPENSION_CALCULATION_METHOD_PERCENTAGE; + $suspensionPercentage = 0; + } + + $error = $LMS->ValidateSuspension($suspension); + if (empty($error)) { + $DB->BeginTrans(); + $DB->LockTables(array('suspensions', 'assignmentsuspensions')); + + if (!empty($suspension['suspended_assignments'])) { + $origSuspension = $LMS->getSuspensions(array('suspension_id' => $suspensionId, 'by_suspension_id' => true)); + $allSuspenedAssignemnts = $LMS->getCustomerAssignments($customerId, array('show_expired' => false, 'suspended' => true)); + + if (isset($origSuspension[$suspensionId])) { + foreach ($origSuspension[$suspensionId]['suspended_assignments'] as $akey => $sassignment) { + if (!isset($suspension['suspended_assignments'][$akey])) { + $DB->Execute( + 'DELETE FROM assignmentsuspensions WHERE suspensionid = ? AND assignmentid = ?', + array( + $suspensionId, + $akey) + ); + } + } + + foreach ($suspension['suspended_assignments'] as $akey => $sassignment) { + if (!isset($origSuspension[$suspensionId]['suspended_assignments'][$akey]) && !isset($allSuspenedAssignemnts[$akey])) { + $args = array( + 'suspension_id' => $suspensionId, + 'assignment_id' => $akey, + 'customerid' => $customerId, + ); + $LMS->addAssignmentSuspension($args); + } + } + + $assignments = $LMS->getCustomerAssignments($customerId, array('suspension_id' => $suspensionId)); + if (!empty($assignments)) { + foreach ($assignments as $row) { + switch ($suspension['suspension_charge_method']) { + case SUSPENSION_CHARGE_METHOD_ONCE: + $startdate = $row['datefrom'] > $today ? $row['datefrom'] : $today; + [$year, $month, $dom] = explode('/', date('Y/n/j', $startdate)); + $commingPayDate = 0; + $commingPayTimestamp = 0; + switch ($row['periodvalue']) { + case DISPOSABLE: + $commingPayTimestamp = $row['at']; + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + case MONTHLY: + if ($row['at'] == 0) { + $commingPayTimestamp = mktime(0, 0, 0, $month + 1, $row['at'], $year); + } else { + $commingPayTimestamp = mktime(0, 0, 0, $month, $row['at'], $year); + } + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + case QUARTERLY: + [$d, $m] = explode('/', $row['at']); + $quarterlyDate1 = mktime(0, 0, 0, $m, $d, $year); + $quarterlyDate2 = strtotime('+3 months', $quarterlyDate1); + $quarterlyDate3 = strtotime('+6 months', $quarterlyDate1); + $quarterlyDate4 = strtotime('+9 months', $quarterlyDate1); + + if ($quarterlyDate1 <= $row['datefrom']) { + if ($quarterlyDate2 <= $row['datefrom']) { + if ($quarterlyDate3 <= $row['datefrom']) { + if ($quarterlyDate4 <= $row['datefrom']) { + $commingPayTimestamp = strtotime('+3 months', $quarterlyDate4); + } else { + $commingPayTimestamp = $quarterlyDate3; + } + } else { + $commingPayTimestamp = $quarterlyDate3; + } + } else { + $commingPayTimestamp = $quarterlyDate2; + } + } else { + $commingPayTimestamp = $quarterlyDate1; + } + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + case HALFYEARLY: + [$d, $m] = explode('/', $row['at']); + $halfyearlyDate1 = mktime(0, 0, 0, $m, $d, $year); + $halfyearlyDate2 = strtotime('+6 months', $halfyearlyDate1); + + if ($halfyearlyDate1 <= $row['datefrom']) { + if ($halfyearlyDate2 <= $row['datefrom']) { + $commingPayTimestamp = strtotime('+6 months', $halfyearlyDate2); + } else { + $commingPayTimestamp = $halfyearlyDate2; + } + } else { + $commingPayTimestamp = $halfyearlyDate1; + } + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + case YEARLY: + [$d, $m] = explode('/', $row['at']); + $yearlyDate = mktime(0, 0, 0, $m, $d, $year); + if ($yearlyDate <= $row['datefrom']) { + $commingPayTimestamp = strtotime('+1 year', $yearlyDate); + } else { + $commingPayTimestamp = $yearlyDate; + } + $commingPayDate = date('Y-m-d', $commingPayTimestamp); + break; + } + + if (!isset($suspension_at) || $commingPayTimestamp < $suspension_at) { + $suspension_at = $commingPayTimestamp; + } + break; + case SUSPENSION_CHARGE_METHOD_PERIODICALLY: + $startdate = $row['datefrom'] > $today ? $row['datefrom'] : $today; + [$year, $month, $dom] = explode('/', date('Y/n/j', $startdate)); + $commingPayDay = 0; + $commingPayTimestamp = 0; + switch ($row['periodvalue']) { + case DISPOSABLE: + $commingPayTimestamp = $row['at']; + $commingPayDay = date('j', $row['at']); + break; + case MONTHLY: + $commingPayTimestamp = mktime(0, 0, 0, $month, $row['at'], $year); + $commingPayDay = $row['at']; + break; + case QUARTERLY: + case HALFYEARLY: + case YEARLY: + [$d, $m] = explode('/', $row['at']); + $commingPayTimestamp = mktime(0, 0, 0, $month, $d, $year); + $commingPayDay = $d; + break; + } + + if (!isset($suspension_at) || $commingPayDay < $suspension_at) { + $suspension_at = $commingPayDay; + } + break; + } + } + } + } + } + + $suspensionArgs = array( + 'at' => $suspension_at, + 'datefrom' => !empty($suspension['datefrom']) ? $suspension['datefrom'] : 0, + 'dateto' => !empty($suspension['dateto']) ? (strtotime('+ 1 day', $suspension['dateto']) - 1) : 0, + 'chargemethod' => $suspension['suspension_charge_method'], + 'calculationmethod' => $suspension['suspension_calculation_method'], + 'value' => $suspensionValue, + 'percentage' => $suspensionPercentage, + 'netflag' => $suspension_netflag, + 'currency' => $suspension_currency, + 'taxid' => $suspension_taxid, + 'note' => !empty($suspension['note']) ? Utils::removeInsecureHtml($suspension['note']) : null, + 'customerid' => isset($suspension['suspend_all']) ? $customerId : null, + 'id' => $suspensionId, + ); + + $LMS->updateSuspension($suspensionArgs); + + $DB->UnLockTables(); + $DB->CommitTrans(); + $SESSION->redirect_to_history_entry(); + } + } else { + $suspension = $LMS->getSuspensions(array('suspension_id' => $suspensionId, 'by_suspension_id' => true)); + $a = $suspension[$suspensionId]; + $a['tariffid'] = -3; + $a['customer_id'] = $customerId; + $a['suspension_id'] = $suspensionId; + $a['datefrom'] = $a['suspension_datefrom']; + $a['dateto'] = $a['suspension_dateto']; + $a['netflag'] = $a['suspension_netflag']; + $a['suspension_gross_value'] = $a['suspension_value']; + $a['suspension_net_value'] = $a['suspension_value']; + $a['suspend_all'] = $a['suspension_suspend_all']; + $a['currency'] = !empty($a['suspension_currency']) ? $a['suspension_currency'] : Localisation::getDefaultCurrency(); + $a['taxid'] = $a['suspension_tax_id']; + } } else { - if ($DB->GetOne( - 'SELECT COUNT(a.id) - FROM assignments a - JOIN customerview c ON c.id = a.customerid - WHERE a.id IN ?', - array($aids) - ) != count($aids)) { + // get customer name and check privileges using customerview + $aids = $_POST['customerassignments'] ?? array($_GET['id']); + $aids = Utils::filterIntegers($aids); + if (empty($aids)) { $SESSION->redirect_to_history_entry(); } -} -if (isset($_GET['action']) && $_GET['action'] == 'suspend') { - foreach ($aids as $aid) { - $LMS->toggleAssignmentSuspension($aid); + if (count($aids) == 1) { + $aid = reset($aids); + $customer = $DB->GetRow( + 'SELECT a.customerid AS id, c.divisionid, ' + . $DB->Concat('c.lastname', "' '", 'c.name') . ' AS name + FROM assignments a + JOIN customerview c ON (c.id = a.customerid) + WHERE a.id = ?', + array($aid) + ); + if (!$customer) { + $SESSION->redirect_to_history_entry(); + } + } else { + if ($DB->GetOne( + 'SELECT COUNT(a.id) + FROM assignments a + JOIN customerview c ON c.id = a.customerid + WHERE a.id IN ?', + array($aids) + ) != count($aids)) { + $SESSION->redirect_to_history_entry(); + } } - $SESSION->redirect_to_history_entry(); -} -if (isset($_POST['assignment'])) { - $a = $_POST['assignment']; - - foreach ($a as $key => $val) { - if (!is_array($val)) { - $a[$key] = trim($val); + if (isset($_GET['action']) && $_GET['action'] == 'toggle_suspension') { + foreach ($aids as $aid) { + $LMS->toggleAssignmentSuspension($aid); } + $SESSION->redirect_to_history_entry(); } - $a['id'] = $_GET['id']; - $a['customerid'] = $customer['id']; - $a['liabilityid'] = $_GET['lid'] ?? null; + if (isset($_POST['assignment'])) { + $a = $_POST['assignment']; - $period = sprintf('%d', $a['period']); + foreach ($a as $key => $val) { + if (!is_array($val)) { + $a[$key] = trim($val); + } + } - switch ($period) { - case DAILY: - $at = 0; - break; + $a['id'] = $_GET['id']; + $a['customerid'] = $customer['id']; + $a['liabilityid'] = $_GET['lid'] ?? null; - case WEEKLY: - $at = sprintf('%d', $a['at']); + $period = sprintf('%d', $a['period']); - if (ConfigHelper::checkConfig('phpui.use_current_payday') && $at == 0) { - $at = date('N', time()); - } + switch ($period) { + case DAILY: + $at = 0; + break; - if ($at < 1 || $at > 7) { - $error['at'] = trans('Incorrect day of week (1-7)!'); - } - break; - - case MONTHLY: - if ($a['at'] == '') { - if (ConfigHelper::checkConfig('phpui.use_current_payday')) { - $at = date('j', time()); - } elseif (!ConfigHelper::checkConfig('phpui.use_current_payday') - && ConfigHelper::getConfig('phpui.default_monthly_payday') > 0) { - $at = ConfigHelper::getConfig('phpui.default_monthly_payday'); - } else { - $at = -1; + case WEEKLY: + $at = sprintf('%d', $a['at']); + + if (ConfigHelper::checkConfig('phpui.use_current_payday') && $at == 0) { + $at = date('N', time()); } - } else { - $at = intval($a['at']); - } - if ($at > 28 || $at < 0) { - $error['at'] = trans('Incorrect day of month (1-28)!'); - } else { - $a['at'] = $at; - } + if ($at < 1 || $at > 7) { + $error['at'] = trans('Incorrect day of week (1-7)!'); + } + break; + + case MONTHLY: + if ($a['at'] == '') { + if (ConfigHelper::checkConfig('phpui.use_current_payday')) { + $at = date('j', time()); + } elseif (!ConfigHelper::checkConfig('phpui.use_current_payday') + && ConfigHelper::getConfig('phpui.default_monthly_payday') > 0) { + $at = ConfigHelper::getConfig('phpui.default_monthly_payday'); + } else { + $at = -1; + } + } else { + $at = intval($a['at']); + } - break; + if ($at > 28 || $at < 0) { + $error['at'] = trans('Incorrect day of month (1-28)!'); + } else { + $a['at'] = $at; + } - case QUARTERLY: - if (ConfigHelper::checkConfig('phpui.use_current_payday') && !$a['at']) { - $d = date('j', time()); - $m = date('n', time()); - $a['at'] = $d.'/'.$m; - } elseif (!preg_match('/^[0-9]{2}\/[0-9]{2}$/', $a['at'])) { - $error['at'] = trans('Incorrect date format! Enter date in DD/MM format!'); - } else { - [$d, $m] = explode('/', $a['at']); - } + break; - if (!$error) { - if ($d>30 || $d<1 || ($d>28 && $m==2)) { - $error['at'] = trans('This month doesn\'t contain specified number of days'); - } - if ($m>3 || $m<1) { - $error['at'] = trans('Incorrect month number (max.3)!'); + case QUARTERLY: + if (ConfigHelper::checkConfig('phpui.use_current_payday') && !$a['at']) { + $d = date('j', time()); + $m = date('n', time()); + $a['at'] = $d.'/'.$m; + } elseif (!preg_match('/^[0-9]{2}\/[0-9]{2}$/', $a['at'])) { + $error['at'] = trans('Incorrect date format! Enter date in DD/MM format!'); + } else { + [$d, $m] = explode('/', $a['at']); } - $at = ($m-1) * 100 + $d; - } - break; - - case HALFYEARLY: - if (!preg_match('/^[0-9]{2}\/[0-9]{2}$/', $a['at']) && $a['at']) { - $error['at'] = trans('Incorrect date format! Enter date in DD/MM format!'); - } elseif (ConfigHelper::checkConfig('phpui.use_current_payday') && !$a['at']) { - $d = date('j', time()); - $m = date('n', time()); - $a['at'] = $d.'/'.$m; - } else { - [$d, $m] = explode('/', $a['at']); - } + if (!$error) { + if ($d>30 || $d<1 || ($d>28 && $m==2)) { + $error['at'] = trans('This month doesn\'t contain specified number of days'); + } + if ($m>3 || $m<1) { + $error['at'] = trans('Incorrect month number (max.3)!'); + } - if (!$error) { - if ($d>30 || $d<1 || ($d>28 && $m==2)) { - $error['at'] = trans('This month doesn\'t contain specified number of days'); + $at = ($m-1) * 100 + $d; } - if ($m>6 || $m<1) { - $error['at'] = trans('Incorrect month number (max.6)!'); + break; + + case HALFYEARLY: + if (!preg_match('/^[0-9]{2}\/[0-9]{2}$/', $a['at']) && $a['at']) { + $error['at'] = trans('Incorrect date format! Enter date in DD/MM format!'); + } elseif (ConfigHelper::checkConfig('phpui.use_current_payday') && !$a['at']) { + $d = date('j', time()); + $m = date('n', time()); + $a['at'] = $d.'/'.$m; + } else { + [$d, $m] = explode('/', $a['at']); } - $at = ($m-1) * 100 + $d; - } - break; - - case YEARLY: - if (ConfigHelper::checkConfig('phpui.use_current_payday') && !$a['at']) { - $d = date('j', time()); - $m = date('n', time()); - $a['at'] = $d.'/'.$m; - } elseif (!preg_match('/^[0-9]{2}\/[0-9]{2}$/', $a['at'])) { - $error['at'] = trans('Incorrect date format! Enter date in DD/MM format!'); - } else { - [$d, $m] = explode('/', $a['at']); - } + if (!$error) { + if ($d>30 || $d<1 || ($d>28 && $m==2)) { + $error['at'] = trans('This month doesn\'t contain specified number of days'); + } + if ($m>6 || $m<1) { + $error['at'] = trans('Incorrect month number (max.6)!'); + } - if (!$error) { - if ($d>30 || $d<1 || ($d>28 && $m==2)) { - $error['at'] = trans('This month doesn\'t contain specified number of days'); + $at = ($m-1) * 100 + $d; } - if ($m>12 || $m<1) { - $error['at'] = trans('Incorrect month number'); + break; + + case YEARLY: + if (ConfigHelper::checkConfig('phpui.use_current_payday') && !$a['at']) { + $d = date('j', time()); + $m = date('n', time()); + $a['at'] = $d.'/'.$m; + } elseif (!preg_match('/^[0-9]{2}\/[0-9]{2}$/', $a['at'])) { + $error['at'] = trans('Incorrect date format! Enter date in DD/MM format!'); + } else { + [$d, $m] = explode('/', $a['at']); } - $ttime = mktime(12, 0, 0, $m, $d, 1990); - $at = date('z', $ttime) + 1; - } - break; - - default: // DISPOSABLE - $period = DISPOSABLE; - - if (preg_match('/^[0-9]{4}\/[0-9]{2}\/[0-9]{2}$/', $a['at'])) { - [$y, $m, $d] = explode('/', $a['at']); - if (checkdate($m, $d, $y)) { - $at = mktime(0, 0, 0, $m, $d, $y); - if (empty($a['atwarning']) && $at < mktime(0, 0, 0)) { - $a['atwarning'] = true; - $error['at'] = trans('Incorrect date!'); + if (!$error) { + if ($d>30 || $d<1 || ($d>28 && $m==2)) { + $error['at'] = trans('This month doesn\'t contain specified number of days'); + } + if ($m>12 || $m<1) { + $error['at'] = trans('Incorrect month number'); + } + + $ttime = mktime(12, 0, 0, $m, $d, 1990); + $at = date('z', $ttime) + 1; + } + break; + + default: // DISPOSABLE + $period = DISPOSABLE; + + if (preg_match('/^[0-9]{4}\/[0-9]{2}\/[0-9]{2}$/', $a['at'])) { + [$y, $m, $d] = explode('/', $a['at']); + if (checkdate($m, $d, $y)) { + $at = mktime(0, 0, 0, $m, $d, $y); + if (empty($a['atwarning']) && $at < mktime(0, 0, 0)) { + $a['atwarning'] = true; + $error['at'] = trans('Incorrect date!'); + } + } else { + $error['at'] = trans('Incorrect date format! Enter date in YYYY/MM/DD format!'); } } else { $error['at'] = trans('Incorrect date format! Enter date in YYYY/MM/DD format!'); } + break; + } + + if (isset($a['count'])) { + if ($a['count'] == '') { + $count = 1; + } elseif (preg_match('/^[0-9]+(\.[0-9]+)?$/', $a['count'])) { + $count = floatval($a['count']); } else { - $error['at'] = trans('Incorrect date format! Enter date in YYYY/MM/DD format!'); + $error['count'] = trans('Incorrect count format! Numeric value required!'); } - break; - } - - if (isset($a['count'])) { - if ($a['count'] == '') { - $count = 1; - } elseif (preg_match('/^[0-9]+(\.[0-9]+)?$/', $a['count'])) { - $count = floatval($a['count']); - } else { - $error['count'] = trans('Incorrect count format! Numeric value required!'); } - } - if (isset($a['paytime'])) { - if (empty($a['paytime'])) { - $paytime = 0; - } elseif (preg_match('/^[\-]?[0-9]+$/', $a['paytime'])) { - $paytime = intval($a['paytime']); - if ($paytime == -1) { - $paytime = null; + if (isset($a['paytime'])) { + if (empty($a['paytime'])) { + $paytime = 0; + } elseif (preg_match('/^[\-]?[0-9]+$/', $a['paytime'])) { + $paytime = intval($a['paytime']); + if ($paytime == -1) { + $paytime = null; + } + } else { + $error['paytime'] = trans('Invalid deadline format!'); } - } else { - $error['paytime'] = trans('Invalid deadline format!'); } - } - - if (empty($a['datefrom'])) { - $from = 0; - } elseif (!preg_match('/^[0-9]+$/', $a['datefrom'])) { - $error['datefrom'] = trans('Incorrect date format! Enter date in YYYY/MM/DD format!'); - } else { - $from = $a['datefrom']; - } - if (empty($a['dateto'])) { - $to = 0; - } elseif (!preg_match('/^[0-9]+$/', $a['dateto'])) { - $error['dateto'] = trans('Incorrect date format! Enter date in YYYY/MM/DD format!'); - } else { - $to = strtotime('+ 1 day', $a['dateto']) - 1; - } + if (empty($a['datefrom'])) { + $from = 0; + } elseif (!preg_match('/^[0-9]+$/', $a['datefrom'])) { + $error['datefrom'] = trans('Incorrect date format! Enter date in YYYY/MM/DD format!'); + } else { + $from = $a['datefrom']; + } - if ($to < $from && $to != 0 && $from != 0) { - $error['dateto'] = trans('Incorrect date range!'); - } + if (empty($a['dateto'])) { + $to = 0; + } elseif (!preg_match('/^[0-9]+$/', $a['dateto'])) { + $error['dateto'] = trans('Incorrect date format! Enter date in YYYY/MM/DD format!'); + } else { + $to = strtotime('+ 1 day', $a['dateto']) - 1; + } - $a['discount'] = str_replace(',', '.', $a['discount']); - $a['pdiscount'] = 0.0; - $a['vdiscount'] = 0.0; - if (preg_match('/^[0-9]+(\.[0-9]+)*$/', $a['discount'])) { - $a['pdiscount'] = ($a['discount_type'] == DISCOUNT_PERCENTAGE ? floatval($a['discount']) : 0); - $a['vdiscount'] = ($a['discount_type'] == DISCOUNT_AMOUNT ? floatval($a['discount']) : 0); - } - if ($a['pdiscount'] < 0 || $a['pdiscount'] > 100) { - $error['discount'] = trans('Wrong discount value!'); - } + if ($to < $from && $to != 0 && $from != 0) { + $error['dateto'] = trans('Incorrect date range!'); + } - if ($a['tariffid'] == -1) { - unset($error['at']); - $at = 0; - } elseif (!$a['tariffid']) { - if ($a['name'] == '') { - $error['name'] = trans('Liability name is required!'); + $a['discount'] = str_replace(',', '.', $a['discount']); + $a['pdiscount'] = 0.0; + $a['vdiscount'] = 0.0; + if (preg_match('/^[0-9]+(\.[0-9]+)*$/', $a['discount'])) { + $a['pdiscount'] = ($a['discount_type'] == DISCOUNT_PERCENTAGE ? floatval($a['discount']) : 0); + $a['vdiscount'] = ($a['discount_type'] == DISCOUNT_AMOUNT ? floatval($a['discount']) : 0); } - if (!$a['value'] && empty($a['netflag'])) { - $error['value'] = trans('Liability value is required!'); - } elseif (!$a['netvalue'] && !empty($a['netflag'])) { - $error['netvalue'] = trans('Liability value is required!'); - } elseif (!preg_match('/^[-]?[0-9.,]+$/', $a['value']) && empty($a['netflag'])) { - $error['value'] = trans('Incorrect value!'); - } elseif (!preg_match('/^[-]?[0-9.,]+$/', $a['netvalue']) && !empty($a['netflag'])) { - $error['netvalue'] = trans('Incorrect value!'); - } elseif ($a['discount_type'] == 2 && $a['discount'] && $a['value'] - $a['discount'] < 0) { - $error['value'] = trans('Value less than discount are not allowed!'); - $error['discount'] = trans('Value less than discount are not allowed!'); + if ($a['pdiscount'] < 0 || $a['pdiscount'] > 100) { + $error['discount'] = trans('Wrong discount value!'); } - } else { - if ($a['discount_type'] == DISCOUNT_AMOUNT && $a['discount'] - && $DB->GetOne('SELECT value FROM tariffs WHERE id = ?', array($a['tariffid'])) - $a['discount'] < 0) { - $error['value'] = trans('Value less than discount are not allowed!'); - $error['discount'] = trans('Value less than discount are not allowed!'); + + if ($a['tariffid'] == -1) { + unset($error['at']); + $at = 0; + } elseif (!$a['tariffid']) { + if ($a['name'] == '') { + $error['name'] = trans('Liability name is required!'); + } + if (!$a['value'] && empty($a['netflag'])) { + $error['value'] = trans('Liability value is required!'); + } elseif (!$a['netvalue'] && !empty($a['netflag'])) { + $error['netvalue'] = trans('Liability value is required!'); + } elseif (!preg_match('/^[-]?[0-9.,]+$/', $a['value']) && empty($a['netflag'])) { + $error['value'] = trans('Incorrect value!'); + } elseif (!preg_match('/^[-]?[0-9.,]+$/', $a['netvalue']) && !empty($a['netflag'])) { + $error['netvalue'] = trans('Incorrect value!'); + } elseif ($a['discount_type'] == 2 && $a['discount'] && $a['value'] - $a['discount'] < 0) { + $error['value'] = trans('Value less than discount are not allowed!'); + $error['discount'] = trans('Value less than discount are not allowed!'); + } + } else { + if ($a['discount_type'] == DISCOUNT_AMOUNT && $a['discount'] + && $DB->GetOne('SELECT value FROM tariffs WHERE id = ?', array($a['tariffid'])) - $a['discount'] < 0) { + $error['value'] = trans('Value less than discount are not allowed!'); + $error['discount'] = trans('Value less than discount are not allowed!'); + } } - } - if ($a['tarifftype'] != SERVICE_PHONE) { - unset($a['phones']); - } + if ($a['tarifftype'] != SERVICE_PHONE) { + unset($a['phones']); + } - // try to restrict node assignment sharing - if ($a['tariffid'] > 0 && !empty($a['nodes'])) { - $restricted_nodes = $LMS->CheckNodeTariffRestrictions($a['id'], $a['nodes'], $from, $to); - $node_multi_tariff_restriction = ConfigHelper::getConfig( - 'phpui.node_multi_tariff_restriction', - '', - true - ); - if (preg_match('/^(error|warning)$/', $node_multi_tariff_restriction) && !empty($restricted_nodes)) { - foreach ($restricted_nodes as $nodeid) { - if ($node_multi_tariff_restriction == 'error') { - $error['assignment[nodes][' . $nodeid . ']'] = trans('This item is already bound with another assignment!'); - } else { - if (!isset($a['node_warns'][$nodeid])) { + // try to restrict node assignment sharing + if ($a['tariffid'] > 0 && !empty($a['nodes'])) { + $restricted_nodes = $LMS->CheckNodeTariffRestrictions($a['id'], $a['nodes'], $from, $to); + $node_multi_tariff_restriction = ConfigHelper::getConfig( + 'phpui.node_multi_tariff_restriction', + '', + true + ); + if (preg_match('/^(error|warning)$/', $node_multi_tariff_restriction) && !empty($restricted_nodes)) { + foreach ($restricted_nodes as $nodeid) { + if ($node_multi_tariff_restriction == 'error') { $error['assignment[nodes][' . $nodeid . ']'] = trans('This item is already bound with another assignment!'); + } else { + if (!isset($a['node_warns'][$nodeid])) { + $error['assignment[nodes][' . $nodeid . ']'] = trans('This item is already bound with another assignment!'); + } + $a['node_warns'][$nodeid] = $nodeid; } - $a['node_warns'][$nodeid] = $nodeid; } } } - } - if (!isset($CURRENCIES[$a['currency']])) { - $error['currency'] = trans('Invalid currency selection!'); - } + if (!isset($CURRENCIES[$a['currency']])) { + $error['currency'] = trans('Invalid currency selection!'); + } - $hook_data = $LMS->executeHook( - 'customerassignmentedit_validation_before_submit', - array( - 'a' => $a, - 'error' => $error - ) - ); + $hook_data = $LMS->executeHook( + 'customerassignmentedit_validation_before_submit', + array( + 'a' => $a, + 'error' => $error + ) + ); - $a = $hook_data['a']; - $error = $hook_data['error']; + $a = $hook_data['a']; + $error = $hook_data['error']; - if (!$error) { - $DB->BeginTrans(); + if (!$error) { + $DB->BeginTrans(); - if ($a['liabilityid']) { - if ($a['tariffid'] > 0) { - $DB->Execute( - 'UPDATE assignments SET tariffid = ?, liabilityid = NULL WHERE id = ?', - array($a['tariffid'], $a['id']) - ); - $DB->Execute('DELETE FROM liabilities WHERE id=?', array($a['liabilityid'])); - if ($SYSLOG) { + if ($a['liabilityid']) { + if ($a['tariffid'] > 0) { + $DB->Execute( + 'UPDATE assignments SET tariffid = ?, liabilityid = NULL WHERE id = ?', + array($a['tariffid'], $a['id']) + ); + $DB->Execute('DELETE FROM liabilities WHERE id=?', array($a['liabilityid'])); + if ($SYSLOG) { + $args = array( + SYSLOG::RES_LIAB => $a['liabilityid'], + SYSLOG::RES_CUST => $customer['id']); + $SYSLOG->AddMessage(SYSLOG::RES_LIAB, SYSLOG::OPER_DELETE, $args); + } + $a['liabilityid'] = null; + } else { $args = array( - SYSLOG::RES_LIAB => $a['liabilityid'], - SYSLOG::RES_CUST => $customer['id']); - $SYSLOG->AddMessage(SYSLOG::RES_LIAB, SYSLOG::OPER_DELETE, $args); + 'value' => str_replace(',', '.', $a['value']), + 'flags' => (isset($a['splitpayment']) ? LIABILITY_FLAG_SPLIT_PAYMENT : 0) + + (isset($a['netflag']) ? LIABILITY_FLAG_NET_ACCOUT : 0), + 'taxcategory' => $a['taxcategory'], + 'currency' => $a['currency'], + 'name' => $a['name'], + SYSLOG::RES_TAX => intval($a['taxid']), + 'prodid' => $a['prodid'], + 'type' => $a['type'], + 'netvalue' => str_replace(',', '.', $a['netvalue']), + 'note' => htmlspecialchars($a['note']), + SYSLOG::RES_LIAB => $a['liabilityid'] + ); + $DB->Execute( + 'UPDATE liabilities SET value = ?, flags = ?, taxcategory = ?, currency = ?, name = ?, + taxid = ?, prodid = ?, type = ?, netvalue = ?, note = ? + WHERE id = ?', + array_values($args) + ); + if ($SYSLOG) { + $args[SYSLOG::RES_CUST] = $customer['id']; + $SYSLOG->AddMessage(SYSLOG::RES_LIAB, SYSLOG::OPER_UPDATE, $args); + } } - $a['liabilityid'] = null; - } else { + } else if (!$a['tariffid']) { $args = array( - 'value' => str_replace(',', '.', $a['value']), + 'name' => $a['name'], + 'value' => $a['value'], 'flags' => (isset($a['splitpayment']) ? LIABILITY_FLAG_SPLIT_PAYMENT : 0) + (isset($a['netflag']) ? LIABILITY_FLAG_NET_ACCOUT : 0), 'taxcategory' => $a['taxcategory'], 'currency' => $a['currency'], - 'name' => $a['name'], SYSLOG::RES_TAX => intval($a['taxid']), 'prodid' => $a['prodid'], 'type' => $a['type'], 'netvalue' => str_replace(',', '.', $a['netvalue']), 'note' => htmlspecialchars($a['note']), - SYSLOG::RES_LIAB => $a['liabilityid'] ); $DB->Execute( - 'UPDATE liabilities SET value = ?, flags = ?, taxcategory = ?, currency = ?, name = ?, - taxid = ?, prodid = ?, type = ?, netvalue = ?, note = ? - WHERE id = ?', + 'INSERT INTO liabilities (name, value, flags, taxcategory, currency, taxid, prodid, type, netvalue, note) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', array_values($args) ); + + $a['liabilityid'] = $DB->GetLastInsertID('liabilities'); + if ($SYSLOG) { + $args[SYSLOG::RES_LIAB] = $a['liabilityid']; $args[SYSLOG::RES_CUST] = $customer['id']; - $SYSLOG->AddMessage(SYSLOG::RES_LIAB, SYSLOG::OPER_UPDATE, $args); + $SYSLOG->AddMessage(SYSLOG::RES_LIAB, SYSLOG::OPER_ADD, $args); } } - } else if (!$a['tariffid']) { + + if ($a['tariffid'] == -1) { + $a['tariffid'] = 0; + $a['discount'] = 0; + $a['pdiscount'] = 0; + $a['vdiscount'] = 0; + unset($a['invoice']); + unset($a['settlement']); + } + $args = array( - 'name' => $a['name'], - 'value' => $a['value'], - 'flags' => (isset($a['splitpayment']) ? LIABILITY_FLAG_SPLIT_PAYMENT : 0) - + (isset($a['netflag']) ? LIABILITY_FLAG_NET_ACCOUT : 0), - 'taxcategory' => $a['taxcategory'], - 'currency' => $a['currency'], - SYSLOG::RES_TAX => intval($a['taxid']), - 'prodid' => $a['prodid'], - 'type' => $a['type'], - 'netvalue' => str_replace(',', '.', $a['netvalue']), + SYSLOG::RES_TARIFF => empty($a['tariffid']) ? null : intval($a['tariffid']), + SYSLOG::RES_CUST => $customer['id'], + 'attribute' => !empty($a['attribute']) ? $a['attribute'] : null, + 'period' => $period, + 'backwardperiod' => isset($a['backwardperiod']) ? 1 : 0, + 'at' => $at, + 'count' => $count, 'note' => htmlspecialchars($a['note']), + 'invoice' => isset($a['invoice']) ? intval($a['invoice']) : 0, + 'separatedocument' => empty($a['separatedocument']) ? 0 : 1, + 'separateitem' => empty($a['separateitem']) ? 0 : 1, + 'settlement' => empty($a['settlement']) ? 0 : 1, + 'datefrom' => $from, + 'dateto' => $to, + 'pdiscount' => str_replace(',', '.', $a['pdiscount']), + 'vdiscount' => str_replace(',', '.', $a['vdiscount']), + SYSLOG::RES_LIAB => $a['liabilityid'], + SYSLOG::RES_NUMPLAN => !empty($a['numberplanid']) ? $a['numberplanid'] : null, + 'paytime' => $paytime ?? null, + 'paytype' => !empty($a['paytype']) ? $a['paytype'] : null, + 'recipient_address_id' => ($a['recipient_address_id'] >= 0) ? $a['recipient_address_id'] : null, + SYSLOG::RES_ASSIGN => $a['id'] ); - $DB->Execute( - 'INSERT INTO liabilities (name, value, flags, taxcategory, currency, taxid, prodid, type, netvalue, note) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', - array_values($args) - ); - - $a['liabilityid'] = $DB->GetLastInsertID('liabilities'); + $DB->Execute('UPDATE assignments SET tariffid=?, customerid=?, attribute=?, period=?, + backwardperiod=?, at=?, count=?, note=?, + invoice=?, separatedocument=?, separateitem = ?, settlement=?, datefrom=?, dateto=?, pdiscount=?, vdiscount=?, + liabilityid=?, numberplanid=?, paytime = ?, paytype=?, recipient_address_id=? + WHERE id=?', array_values($args)); if ($SYSLOG) { - $args[SYSLOG::RES_LIAB] = $a['liabilityid']; - $args[SYSLOG::RES_CUST] = $customer['id']; - $SYSLOG->AddMessage(SYSLOG::RES_LIAB, SYSLOG::OPER_ADD, $args); - } - } - - if ($a['tariffid'] == -1) { - $a['tariffid'] = 0; - $a['discount'] = 0; - $a['pdiscount'] = 0; - $a['vdiscount'] = 0; - unset($a['invoice']); - unset($a['settlement']); - } - - $args = array( - SYSLOG::RES_TARIFF => empty($a['tariffid']) ? null : intval($a['tariffid']), - SYSLOG::RES_CUST => $customer['id'], - 'attribute' => !empty($a['attribute']) ? $a['attribute'] : null, - 'period' => $period, - 'backwardperiod' => isset($a['backwardperiod']) ? 1 : 0, - 'at' => $at, - 'count' => $count, - 'note' => htmlspecialchars($a['note']), - 'invoice' => isset($a['invoice']) ? intval($a['invoice']) : 0, - 'separatedocument' => empty($a['separatedocument']) ? 0 : 1, - 'separateitem' => empty($a['separateitem']) ? 0 : 1, - 'settlement' => empty($a['settlement']) ? 0 : 1, - 'datefrom' => $from, - 'dateto' => $to, - 'pdiscount' => str_replace(',', '.', $a['pdiscount']), - 'vdiscount' => str_replace(',', '.', $a['vdiscount']), - SYSLOG::RES_LIAB => $a['liabilityid'], - SYSLOG::RES_NUMPLAN => !empty($a['numberplanid']) ? $a['numberplanid'] : null, - 'paytime' => $paytime ?? null, - 'paytype' => !empty($a['paytype']) ? $a['paytype'] : null, - 'recipient_address_id' => ($a['recipient_address_id'] >= 0) ? $a['recipient_address_id'] : null, - SYSLOG::RES_ASSIGN => $a['id'] - ); + $SYSLOG->AddMessage(SYSLOG::RES_ASSIGN, SYSLOG::OPER_UPDATE, $args); - $DB->Execute('UPDATE assignments SET tariffid=?, customerid=?, attribute=?, period=?, - backwardperiod=?, at=?, count=?, note=?, - invoice=?, separatedocument=?, separateitem = ?, settlement=?, datefrom=?, dateto=?, pdiscount=?, vdiscount=?, - liabilityid=?, numberplanid=?, paytime = ?, paytype=?, recipient_address_id=? - WHERE id=?', array_values($args)); - if ($SYSLOG) { - $SYSLOG->AddMessage(SYSLOG::RES_ASSIGN, SYSLOG::OPER_UPDATE, $args); - - $nodeassigns = $DB->GetAll('SELECT id, nodeid FROM nodeassignments WHERE assignmentid=?', array($a['id'])); - if (!empty($nodeassigns)) { - foreach ($nodeassigns as $nodeassign) { - $args = array( - SYSLOG::RES_NODEASSIGN => $nodeassign['id'], - SYSLOG::RES_CUST => $customer['id'], - SYSLOG::RES_NODE => $nodeassign['nodeid'], - SYSLOG::RES_ASSIGN => $a['id'] - ); - $SYSLOG->AddMessage(SYSLOG::RES_NODEASSIGN, SYSLOG::OPER_DELETE, $args); + $nodeassigns = $DB->GetAll('SELECT id, nodeid FROM nodeassignments WHERE assignmentid=?', array($a['id'])); + if (!empty($nodeassigns)) { + foreach ($nodeassigns as $nodeassign) { + $args = array( + SYSLOG::RES_NODEASSIGN => $nodeassign['id'], + SYSLOG::RES_CUST => $customer['id'], + SYSLOG::RES_NODE => $nodeassign['nodeid'], + SYSLOG::RES_ASSIGN => $a['id'] + ); + $SYSLOG->AddMessage(SYSLOG::RES_NODEASSIGN, SYSLOG::OPER_DELETE, $args); + } } } - } - $DB->Execute('DELETE FROM nodeassignments WHERE assignmentid=?', array($a['id'])); - $DB->Execute('DELETE FROM voip_number_assignments WHERE assignment_id = ?', array($a['id'])); + $DB->Execute('DELETE FROM nodeassignments WHERE assignmentid=?', array($a['id'])); + $DB->Execute('DELETE FROM voip_number_assignments WHERE assignment_id = ?', array($a['id'])); - if (!empty($a['nodes'])) { - foreach ($a['nodes'] as $nodeid) { - $DB->Execute( - 'INSERT INTO nodeassignments (nodeid, assignmentid) VALUES (?,?)', - array($nodeid, $a['id']) - ); - if ($SYSLOG) { - $nodeaid = $DB->GetOne( - 'SELECT id FROM nodeassignments WHERE nodeid = ? AND assignmentid = ?', + if (!empty($a['nodes'])) { + foreach ($a['nodes'] as $nodeid) { + $DB->Execute( + 'INSERT INTO nodeassignments (nodeid, assignmentid) VALUES (?,?)', array($nodeid, $a['id']) ); - $args = array( - SYSLOG::RES_NODEASSIGN => $nodeaid, - SYSLOG::RES_CUST => $customer['id'], - SYSLOG::RES_NODE => $nodeid, - SYSLOG::RES_ASSIGN => $a['id'] - ); - $SYSLOG->AddMessage(SYSLOG::RES_NODEASSIGN, SYSLOG::OPER_ADD, $args); + if ($SYSLOG) { + $nodeaid = $DB->GetOne( + 'SELECT id FROM nodeassignments WHERE nodeid = ? AND assignmentid = ?', + array($nodeid, $a['id']) + ); + $args = array( + SYSLOG::RES_NODEASSIGN => $nodeaid, + SYSLOG::RES_CUST => $customer['id'], + SYSLOG::RES_NODE => $nodeid, + SYSLOG::RES_ASSIGN => $a['id'] + ); + $SYSLOG->AddMessage(SYSLOG::RES_NODEASSIGN, SYSLOG::OPER_ADD, $args); + } } } - } - if (!empty($a['phones'])) { - foreach ($a['phones'] as $p) { - $DB->Execute( - 'INSERT INTO voip_number_assignments (number_id, assignment_id) VALUES (?,?)', - array($p, $a['id']) - ); + if (!empty($a['phones'])) { + foreach ($a['phones'] as $p) { + $DB->Execute( + 'INSERT INTO voip_number_assignments (number_id, assignment_id) VALUES (?,?)', + array($p, $a['id']) + ); + } } - } - $LMS->executeHook( - 'customerassignmentedit_after_submit', - array('a' => $a) - ); + $LMS->executeHook( + 'customerassignmentedit_after_submit', + array('a' => $a) + ); - $DB->CommitTrans(); + $DB->CommitTrans(); - $SESSION->redirect_to_history_entry(); - } + $SESSION->redirect_to_history_entry(); + } - $a['alltariffs'] = isset($a['alltariffs']); + $a['alltariffs'] = isset($a['alltariffs']); - $SMARTY->assign('error', $error); -} else { - $a = $DB->GetRow( - 'SELECT a.id AS id, a.customerid, a.tariffid, a.period, a.backwardperiod, - a.at, a.count, a.datefrom, a.dateto, a.numberplanid, a.paytime, a.paytype, - a.invoice, - a.separatedocument, a.separateitem, - a.note, - liabilities.type, - (CASE WHEN liabilityid IS NULL - THEN (CASE WHEN tariffs.flags & ? > 0 THEN 1 ELSE 0 END) - ELSE (CASE WHEN liabilities.flags & ? > 0 THEN 1 ELSE 0 END) - END) AS splitpayment, - (CASE WHEN liabilityid IS NULL - THEN (CASE WHEN tariffs.flags & ? > 0 THEN 1 ELSE 0 END) - ELSE (CASE WHEN liabilities.flags & ? > 0 THEN 1 ELSE 0 END) - END) AS netflag, - (CASE WHEN liabilityid IS NULL THEN tariffs.taxcategory ELSE liabilities.taxcategory END) AS taxcategory, - a.settlement, a.pdiscount, a.vdiscount, a.attribute, a.liabilityid, - (CASE WHEN liabilityid IS NULL THEN tariffs.name ELSE liabilities.name END) AS name, - liabilities.value AS value, liabilities.currency AS currency, - liabilities.netvalue AS netvalue, - liabilities.prodid AS prodid, liabilities.taxid AS taxid, - recipient_address_id - FROM assignments a - LEFT JOIN tariffs ON (tariffs.id = a.tariffid) - LEFT JOIN liabilities ON (liabilities.id = a.liabilityid) - WHERE a.id = ?', - array( - TARIFF_FLAG_SPLIT_PAYMENT, - LIABILITY_FLAG_SPLIT_PAYMENT, - TARIFF_FLAG_NET_ACCOUNT, - LIABILITY_FLAG_NET_ACCOUT, - $_GET['id'] - ) - ); + $SMARTY->assign('error', $error); + } else { + $a = $DB->GetRow( + 'SELECT a.id AS id, a.customerid, a.tariffid, a.period, a.backwardperiod, + a.at, a.count, a.datefrom, a.dateto, a.numberplanid, a.paytime, a.paytype, + a.invoice, + a.separatedocument, a.separateitem, + a.note, + liabilities.type, + (CASE WHEN liabilityid IS NULL + THEN (CASE WHEN tariffs.flags & ? > 0 THEN 1 ELSE 0 END) + ELSE (CASE WHEN liabilities.flags & ? > 0 THEN 1 ELSE 0 END) + END) AS splitpayment, + (CASE WHEN liabilityid IS NULL + THEN (CASE WHEN tariffs.flags & ? > 0 THEN 1 ELSE 0 END) + ELSE (CASE WHEN liabilities.flags & ? > 0 THEN 1 ELSE 0 END) + END) AS netflag, + (CASE WHEN liabilityid IS NULL THEN tariffs.taxcategory ELSE liabilities.taxcategory END) AS taxcategory, + a.settlement, a.pdiscount, a.vdiscount, a.attribute, a.liabilityid, + (CASE WHEN liabilityid IS NULL THEN tariffs.name ELSE liabilities.name END) AS name, + liabilities.value AS value, liabilities.currency AS currency, + liabilities.netvalue AS netvalue, + liabilities.prodid AS prodid, liabilities.taxid AS taxid, + recipient_address_id + FROM assignments a + LEFT JOIN tariffs ON (tariffs.id = a.tariffid) + LEFT JOIN liabilities ON (liabilities.id = a.liabilityid) + WHERE a.id = ?', + array( + TARIFF_FLAG_SPLIT_PAYMENT, + LIABILITY_FLAG_SPLIT_PAYMENT, + TARIFF_FLAG_NET_ACCOUNT, + LIABILITY_FLAG_NET_ACCOUT, + $_GET['id'] + ) + ); - $a['pdiscount'] = floatval($a['pdiscount']); - $a['vdiscount'] = floatval($a['vdiscount']); - if (!empty($a['pdiscount'])) { - $a['discount'] = $a['pdiscount']; - $a['discount_type'] = DISCOUNT_PERCENTAGE; - } elseif (!empty($a['vdiscount'])) { - $a['discount'] = $a['vdiscount']; - $a['discount_type'] = DISCOUNT_AMOUNT; - } + $a['pdiscount'] = floatval($a['pdiscount']); + $a['vdiscount'] = floatval($a['vdiscount']); + if (!empty($a['pdiscount'])) { + $a['discount'] = $a['pdiscount']; + $a['discount_type'] = DISCOUNT_PERCENTAGE; + } elseif (!empty($a['vdiscount'])) { + $a['discount'] = $a['vdiscount']; + $a['discount_type'] = DISCOUNT_AMOUNT; + } - switch ($a['period']) { - case HALFYEARLY: - case QUARTERLY: - $a['at'] = sprintf('%02d/%02d', $a['at']%100, $a['at']/100+1); - break; - case YEARLY: - $a['at'] = date('d/m', ($a['at']-1)*86400); - break; - case DISPOSABLE: - if ($a['at']) { - $a['at'] = date('Y/m/d', $a['at']); - } - break; - } + switch ($a['period']) { + case HALFYEARLY: + case QUARTERLY: + $a['at'] = sprintf('%02d/%02d', $a['at']%100, $a['at']/100+1); + break; + case YEARLY: + $a['at'] = date('d/m', ($a['at']-1)*86400); + break; + case DISPOSABLE: + if ($a['at']) { + $a['at'] = date('Y/m/d', $a['at']); + } + break; + } - $a['count'] = floatval($a['count']); + $a['count'] = floatval($a['count']); - if (!$a['tariffid'] && !$a['liabilityid']) { - $a['tariffid'] = -1; - } + if (!$a['tariffid'] && !$a['liabilityid']) { + $a['tariffid'] = -1; + } - // tariff price variants - if (!empty($a['tariffid'])) { - $a['tariff_price_variants'] = $LMS->getTariffPriceVariants($a['tariffid']); - } + // tariff price variants + if (!empty($a['tariffid'])) { + $a['tariff_price_variants'] = $LMS->getTariffPriceVariants($a['tariffid']); + } - // nodes assignments - $a['nodes'] = $DB->GetCol('SELECT nodeid FROM nodeassignments WHERE assignmentid=?', array($a['id'])); + // nodes assignments + $a['nodes'] = $DB->GetCol('SELECT nodeid FROM nodeassignments WHERE assignmentid=?', array($a['id'])); - // phone numbers assignments - $a['phones'] = $DB->GetCol('SELECT number_id FROM voip_number_assignments WHERE assignment_id=?', array($a['id'])); + // phone numbers assignments + $a['phones'] = $DB->GetCol('SELECT number_id FROM voip_number_assignments WHERE assignment_id=?', array($a['id'])); - if (empty($a['currency'])) { - $a['currency'] = Localisation::getDefaultCurrency(); - } + if (empty($a['currency'])) { + $a['currency'] = Localisation::getDefaultCurrency(); + } - if (empty($a['pdiscount']) && empty($a['vdiscount'])) { - $default_assignment_discount_type = ConfigHelper::getConfig( - 'assignments.default_discount_type', - ConfigHelper::getConfig('phpui.default_assignment_discount_type', 'percentage') - ); - $a['discount_type'] = $default_assignment_discount_type == 'percentage' ? DISCOUNT_PERCENTAGE : DISCOUNT_AMOUNT; - } + if (empty($a['pdiscount']) && empty($a['vdiscount'])) { + $default_assignment_discount_type = ConfigHelper::getConfig( + 'assignments.default_discount_type', + ConfigHelper::getConfig('phpui.default_assignment_discount_type', 'percentage') + ); + $a['discount_type'] = $default_assignment_discount_type == 'percentage' ? DISCOUNT_PERCENTAGE : DISCOUNT_AMOUNT; + } - if (!empty($a['tariffid'])) { - $a['netflag'] = ConfigHelper::checkConfig('assignments.default_net_account'); + if (!empty($a['tariffid'])) { + $a['netflag'] = ConfigHelper::checkConfig('assignments.default_net_account'); + } } -} -$layout['pagetitle'] = trans('Liability Edit: $a', ''.$customer['name'].''); -$SESSION->add_history_entry(); + $SESSION->add_history_entry(); -$LMS->executeHook( - 'customerassignmentedit_before_display', - array( - 'a' => $a, - 'smarty' => $SMARTY, - ) -); + $LMS->executeHook( + 'customerassignmentedit_before_display', + array( + 'a' => $a, + 'smarty' => $SMARTY, + ) + ); +} +$layout['pagetitle'] = trans('Liability Edit: $a', ''.$customer['name'].''); $SMARTY->assign('customernodes', $LMS->GetCustomerNodes($customer['id'])); $SMARTY->assign('customernetdevnodes', $LMS->getCustomerNetDevNodes($customer['id'])); $SMARTY->assign('voipaccounts', $LMS->GetCustomerVoipAccounts($customer['id'])); @@ -620,11 +886,7 @@ 'division' => $customer['divisionid'], 'next' => false, ))); - -// ----- - $SMARTY->assign('tags', $LMS->TarifftagGetAll()); - $SMARTY->assign('tariffs', $LMS->GetTariffs($a['tariffid'])); $SMARTY->assign('taxeslist', $LMS->GetTaxes()); $defaultTaxIds = $LMS->GetTaxes(null, null, true); @@ -639,6 +901,12 @@ $a['nodes'] = array_flip($a['nodes']); } $SMARTY->assign('assignment', $a); -$SMARTY->assign('assignments', $LMS->GetCustomerAssignments($customer['id'], true, false)); +$assignmentsWithSuspensions = $LMS->getCustomerAssignments($customer['id'], array('show_expired' => true, 'show_approved' => false, 'with_suspensions' => true)); +if (!empty($assignmentsWithSuspensions)) { + $assignments = !empty($assignmentsWithSuspensions['assignments']) ? $assignmentsWithSuspensions['assignments'] : array(); + $suspensions = !empty($assignmentsWithSuspensions['suspensions']) ? $assignmentsWithSuspensions['suspensions'] : array(); +} +$SMARTY->assign('assignments', $assignments); +$SMARTY->assign('suspensions', $suspensions); $SMARTY->assign('customerinfo', $customer); $SMARTY->display('customer/customerassignmentsedit.html'); diff --git a/modules/messageadd.php b/modules/messageadd.php index 714ca8d6c4..cbe690fee3 100644 --- a/modules/messageadd.php +++ b/modules/messageadd.php @@ -215,7 +215,11 @@ function GetRecipients($filter, $type = MSG_MAIL) $tarifftable = 'JOIN ( SELECT DISTINCT a.customerid FROM assignments a JOIN tariffs t ON t.id = a.tariffid - WHERE a.suspended = 0 + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) + WHERE vas.suspended IS NULL AND (a.datefrom = 0 OR a.datefrom < ?NOW?) AND (a.dateto = 0 OR a.dateto > ?NOW?) AND t.type = ' . $tarifftype . ' @@ -231,8 +235,6 @@ function GetRecipients($filter, $type = MSG_MAIL) ) nd ON nd.ownerid = c.id '; } - $suspension_percentage = f_round(ConfigHelper::getConfig('payments.suspension_percentage', ConfigHelper::getConfig('finances.suspension_percentage', 0))); - $recipients = $LMS->DB->GetAll( 'SELECT c.id, pin, c.divisionid, ' . ($type == MSG_MAIL ? 'cc.email, ' : '') @@ -274,9 +276,10 @@ function GetRecipients($filter, $type = MSG_MAIL) ) b2 ON b2.customerid = c.id LEFT JOIN (SELECT a.customerid, SUM( - (CASE a.suspended - WHEN 0 THEN (((100 - a.pdiscount) * (CASE WHEN t.value IS null THEN l.value ELSE t.value END) / 100) - a.vdiscount) - ELSE ((((100 - a.pdiscount) * (CASE WHEN t.value IS null THEN l.value ELSE t.value END) / 100) - a.vdiscount) * ' . $suspension_percentage . ' / 100) END) + (CASE WHEN vas.suspended IS NULL + THEN (((100 - a.pdiscount) * (CASE WHEN t.value IS null THEN l.value ELSE t.value END) / 100) - a.vdiscount) + ELSE vas.suspension_price + END) * (CASE t.period WHEN ' . MONTHLY . ' THEN 1 WHEN ' . YEARLY . ' THEN 1/12.0 @@ -294,6 +297,10 @@ function GetRecipients($filter, $type = MSG_MAIL) FROM assignments a LEFT JOIN tariffs t ON (t.id = a.tariffid) LEFT JOIN liabilities l ON (l.id = a.liabilityid AND a.period != ' . DISPOSABLE . ') + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) WHERE a.datefrom <= ?NOW? AND (a.dateto > ?NOW? OR a.dateto = 0) GROUP BY a.customerid ) t ON (t.customerid = c.id) ' @@ -381,8 +388,13 @@ function GetRecipients($filter, $type = MSG_MAIL) . ($unapproved_documents ? ' AND c.id IN (SELECT DISTINCT customerid FROM documents WHERE documents.closed = 0 AND documents.type < 0)' : '') - . ($tarifftype ? ' AND NOT EXISTS (SELECT id FROM assignments - WHERE customerid = c.id AND tariffid IS NULL AND liabilityid IS NULL + . ($tarifftype ? ' AND NOT EXISTS (SELECT id + FROM assignments + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) + WHERE customerid = c.id AND vas.suspension_suspen_all = 1 AND (datefrom = 0 OR datefrom < ?NOW?) AND (dateto = 0 OR dateto > ?NOW?))' : '') .' ORDER BY c.divisionid, customername', diff --git a/modules/netdevedit.php b/modules/netdevedit.php index d7de4528f7..35193596c7 100644 --- a/modules/netdevedit.php +++ b/modules/netdevedit.php @@ -883,7 +883,7 @@ $netdev['id'] = $id; if (!empty($netdev['ownerid'])) { - $assignments = $LMS->GetCustomerAssignments($netdev['ownerid'], true, false); + $assignments = $LMS->getCustomerAssignments($netdev['ownerid'], array('show_expired' => true, 'show_approved' => false)); $assignments = $LMS->GetNetDevCustomerAssignments($id, $assignments); $SMARTY->assign(array( 'assignments' => $assignments, diff --git a/modules/netdevinfo.php b/modules/netdevinfo.php index a1ff36f3cf..50adf6c1df 100644 --- a/modules/netdevinfo.php +++ b/modules/netdevinfo.php @@ -37,7 +37,7 @@ if (!isset($_POST['xjxfun'])) { // xajax was called and handled by netdevxajax.inc.php $netdev = $LMS->GetNetDev($id); if (!empty($netdev['ownerid'])) { - $assignments = $LMS->GetCustomerAssignments($netdev['ownerid'], true, false); + $assignments = $LMS->getCustomerAssignments($netdev['ownerid'], array('show_expired' => true, 'show_approved' => false)); $assignments = $LMS->GetNetDevCustomerAssignments($id, $assignments); $SMARTY->assign(array( 'assignments' => $assignments, diff --git a/modules/nodeservicelist.php b/modules/nodeservicelist.php index 12c823ac77..e12265d033 100644 --- a/modules/nodeservicelist.php +++ b/modules/nodeservicelist.php @@ -55,14 +55,11 @@ SELECT na.nodeid, t.type FROM nodeassignments na JOIN assignments a ON a.id = na.assignmentid JOIN tariffs t ON t.id = a.tariffid - LEFT JOIN ( - SELECT customerid, COUNT(id) AS allsuspended FROM assignments - WHERE tariffid IS NULL AND liabilityid IS NULL - AND datefrom <= ?NOW? - AND (dateto = 0 OR dateto > ?NOW?) - GROUP BY customerid - ) s ON s.customerid = a.customerid - WHERE s.allsuspended IS NULL AND a.suspended = 0 AND a.commited = 1 + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) + WHERE vas.suspended IS NULL AND a.commited = 1 AND a.datefrom <= ?NOW? AND (a.dateto = 0 OR a.dateto >= ?NOW?) AND t.type IN (?, ?, ?) diff --git a/modules/print.php b/modules/print.php index b3e69791e6..45cce11574 100644 --- a/modules/print.php +++ b/modules/print.php @@ -574,222 +574,465 @@ if (!ConfigHelper::checkConfig('privileges.superuser') && !ConfigHelper::checkConfig('privileges.finances_management')) { access_denied(); } - - if (isset($_POST['day']) && $_POST['day']) { - [$year, $month, $day] = explode('/', $_POST['day']); - $reportday = mktime(0, 0, 0, $month, $day, $year); - $today = $reportday; - } else { - $reportday = time(); - $today = mktime(0, 0, 0); - } - - if (isset($_POST['period']) && $_POST['period'] != '') { - $period = intval($_POST['period']); - } - - $layout['pagetitle'] = trans('Liability Report on $a', date('Y/m/d', $reportday)); - + $reportlist = array(); + $total = array(); $order = $_POST['order']; $direction = $_POST['direction']; $divisionid = (isset($_POST['division']) ? intval($_POST['division']) : 0); $customerid = (isset($_POST['customer']) ? intval($_POST['customer']) : 0); + $reportdate = !empty($_POST['day']) ? $_POST['day'] : null; - $year = date('Y', $reportday); - $yearday = date('z', $reportday) + 1; - $month = date('n', $reportday); - $monthday = date('j', $reportday); - $weekday = date('w', $reportday); - - switch ($month) { - case 1: - case 4: - case 7: - case 10: - $quarterday = $monthday; - break; - case 2: - case 5: - case 8: - case 11: - $quarterday = $monthday + 100; - break; - default: - $quarterday = $monthday + 200; - break; - } - - if ($month > 6) { - $halfyear = $monthday + ($month - 7) * 100; + //region get taxes + if (empty($reportdate)) { + $currtime = time(); + $today = strtotime('today'); } else { - $halfyear = $monthday + ($month - 1) * 100; + $today = $currtime = strtotime($reportdate); } + $taxes = $LMS->GetTaxes($currtime, $currtime); + //endregion - if (is_leap_year($year) && $yearday > 31 + 28) { - $yearday -= 1; - } + $args = array( + 'customer_id' => isset($_POST['customer']) ? intval($_POST['customer']) : null, + 'division_id' => isset($_POST['division']) ? intval($_POST['division']) : null, + 'reportdate' => $reportdate, + ); - $suspension_percentage = ConfigHelper::getConfig('payments.suspension_percentage', ConfigHelper::getConfig('finances.suspension_percentage', 0)); + $assignments = $LMS->getAssignments($args); - $reportlist = array(); - if ($taxes = $LMS->GetTaxes($reportday, $reportday)) { - $total = array(); - - foreach ($taxes as $taxidx => $tax) { - $list1 = $DB->GetAllByKey( - 'SELECT a.customerid AS id, '.$DB->Concat('UPPER(lastname)', "' '", 'c.name').' AS customername, ' - .$DB->Concat('city', "' '", 'address').' AS address, ten, - SUM((((((100 - a.pdiscount) * t.value) / 100) - a.vdiscount) * - ((CASE WHEN a.suspended = 0 AND allsuspended.suspended IS NULL THEN 100.0 ELSE '.$suspension_percentage.' END) / 100)) - * (CASE a.period - WHEN '.YEARLY.' THEN 12 - WHEN '.HALFYEARLY.' THEN 6 - WHEN '.QUARTERLY.' THEN 3 - WHEN '.WEEKLY.' THEN 1.0/4 - WHEN '.DAILY.' THEN 1.0/30 - ELSE 1 END) - * (CASE t.period - WHEN '.YEARLY.' THEN 1.0/12 - WHEN '.HALFYEARLY.' THEN 1.0/6 - WHEN '.QUARTERLY.' THEN 1.0/3 - ELSE 1 END) - ) AS value, t.currency - FROM assignments a - LEFT JOIN tariffs t ON t.id = a.tariffid - LEFT JOIN customerview c ON c.id = a.customerid - LEFT JOIN ( - SELECT COUNT(id) AS suspended, customerid FROM assignments - WHERE tariffid IS NULL AND liabilityid IS NULL - AND datefrom <= ? AND (dateto >= ? OR dateto = 0) - GROUP BY customerid - ) allsuspended ON allsuspended.customerid = a.customerid - WHERE c.status = ? - AND t.taxid=? - AND c.deleted=0 - AND a.datefrom <= ? AND (a.dateto >= ? OR a.dateto = 0) - ' . (isset($period) ? ' AND a.period = ' . $period : '') . ' - AND ((a.period='.DISPOSABLE.' AND a.at=?) - OR (a.period='.WEEKLY.'. AND a.at=?) - OR (a.period='.MONTHLY.' AND a.at=?) - OR (a.period='.QUARTERLY.' AND a.at=?) - OR (a.period='.HALFYEARLY.' AND a.at=?) - OR (a.period='.YEARLY.' AND a.at=?)) ' - . ($customerid ? ' AND a.customerid=' . $customerid : '') - . ($divisionid ? ' AND c.divisionid=' . $divisionid : '') - . ' GROUP BY a.customerid, lastname, c.name, city, address, ten, t.currency', - 'id', - array($reportday, $reportday, CSTATUS_CONNECTED, $tax['id'], $reportday, $reportday, $today, $weekday, $monthday, $quarterday, $halfyear, $yearday) - ); - - $list2 = $DB->GetAllByKey( - 'SELECT a.customerid AS id, '.$DB->Concat('UPPER(lastname)', "' '", 'c.name').' AS customername, ' - .$DB->Concat('city', "' '", 'address').' AS address, ten, - SUM(((((100 - a.pdiscount) * l.value) / 100) - a.vdiscount) * - ((CASE WHEN a.suspended = 0 AND allsuspended.customerid IS NULL THEN 100.0 ELSE '.$suspension_percentage.' END) / 100)) AS value, - l.currency - FROM assignments a - LEFT JOIN liabilities l ON l.id = a.liabilityid - LEFT JOIN customerview c ON c.id = a.customerid - LEFT JOIN ( - SELECT COUNT(id) AS suspended, customerid FROM assignments - WHERE tariffid IS NULL AND liabilityid IS NULL - AND datefrom <= ? AND (dateto >= ? OR dateto = 0) - GROUP BY customerid - ) allsuspended ON allsuspended.customerid = a.customerid - WHERE c.status = ? - AND l.taxid=? - AND c.deleted=0 - AND a.datefrom <= ? AND (a.dateto>=? OR a.dateto=0) - ' . (isset($period) ? ' AND a.period = ' . $period : '') . ' - AND ((a.period='.DISPOSABLE.' AND a.at=?) - OR (a.period='.WEEKLY.'. AND a.at=?) - OR (a.period='.MONTHLY.' AND a.at=?) - OR (a.period='.QUARTERLY.' AND a.at=?) - OR (a.period='.HALFYEARLY.' AND a.at=?) - OR (a.period='.YEARLY.' AND a.at=?)) ' - .($customerid ? 'AND a.customerid='.$customerid : ''). - ' GROUP BY a.customerid, lastname, c.name, city, address, ten, l.currency', - 'id', - array($reportday, $reportday, CSTATUS_CONNECTED, $tax['id'], $reportday, $reportday, $today, $weekday, $monthday, $quarterday, $halfyear, $yearday) - ); - - if (empty($list1) && empty($list2)) { - unset($taxes[$taxidx]); + //region Suspensions defaults + $defaultSuspensionPercentage = ConfigHelper::getConfig( + 'suspensions.default_percentage', + ConfigHelper::getConfig('payments.suspension_percentage', ConfigHelper::getConfig('finances.suspension_percentage', 0)) + ); + $defaultSuspensionPercentage = f_round($defaultSuspensionPercentage); + $defaultSuspensionValue = f_round(ConfigHelper::getConfig('suspensions.default_value', 0)); + //endregion + + if (!empty($assignments)) { + $suspensionsByCurrency = array(); + $suspensionsById = array(); + + foreach ($assignments as $idx => &$row) { + if ($row['t_period'] && $row['period'] != DISPOSABLE + && $row['t_period'] != $row['period']) { + if ($row['t_period'] == YEARLY) { + $row['base_price'] = $row['base_price'] / 12.0; + $row['price'] = $row['price'] / 12.0; + } elseif ($row['t_period'] == HALFYEARLY) { + $row['base_price'] = $row['base_price'] / 6.0; + $row['price'] = $row['price'] / 6.0; + } elseif ($row['t_period'] == QUARTERLY) { + $row['base_price'] = $row['base_price'] / 3.0; + $row['price'] = $row['price'] / 3.0; + } + + if ($row['period'] == YEARLY) { + $row['base_price'] = $row['base_price'] * 12.0; + $row['price'] = $row['price'] * 12.0; + } elseif ($row['period'] == HALFYEARLY) { + $row['base_price'] = $row['base_price'] * 6.0; + $row['price'] = $row['price'] * 6.0; + } elseif ($row['period'] == QUARTERLY) { + $row['base_price'] = $row['base_price'] * 3.0; + $row['price'] = $row['price'] * 3.0; + } elseif ($row['period'] == WEEKLY) { + $row['base_price'] = $row['base_price'] / 4.0; + $row['price'] = $row['price'] / 4.0; + } elseif ($row['period'] == DAILY) { + $row['base_price'] = $row['base_price'] / 30.0; + $row['price'] = $row['price'] / 30.0; + } } - $list = array_merge((array) $list1, (array) $list2); - - if ($list) { - foreach ($list as $row) { - $idx = $row['id']; - if (!isset($reportlist[$idx])) { - $reportlist[$idx]['id'] = $row['id']; - $reportlist[$idx]['customername'] = $row['customername']; - $reportlist[$idx]['address'] = $row['address']; - $reportlist[$idx]['ten'] = $row['ten']; - $reportlist[$idx]['values'] = array(); - } - if (!isset($reportlist[$idx]['values'][$row['currency']])) { - $reportlist[$idx]['values'][$row['currency']] = array( - 'value' => 0, - 'taxsum' => 0, - ); + // + if (!empty($row['netflag'])) { + $row['base_net_price'] = $row['base_price']; + $row['base_net_value'] = f_round($row['base_net_price'] * $row['count']); + $row['base_gross_price'] = f_round($row['base_net_price'] * ($row['taxrate'] / 100 + 1), 3); + $row['base_tax_value'] = f_round($row['base_net_value'] * ($row['taxrate'] / 100)); + $row['base_gross_value'] = f_round($row['base_net_value'] + $row['base_tax_value']); + + $row['net_price'] = $row['price']; // price is discounted in sql already + + $row['net_price_discount'] = f_round($row['base_net_price'] - $row['net_price'], 3); + $row['net_value'] = f_round($row['net_price'] * $row['count']); + $row['gross_price'] = f_round($row['net_price'] * ($row['taxrate'] / 100 + 1), 3); + $row['gross_price_discount'] = f_round($row['net_price_discount'] * ($row['taxrate'] / 100 + 1), 3); + $row['tax_value'] = f_round($row['net_value'] * ($row['taxrate'] / 100)); + $row['gross_value'] = f_round($row['net_value'] + $row['tax_value']); + } else { + $row['base_gross_price'] = $row['base_price']; + $row['base_gross_value'] = f_round($row['base_gross_price'] * $row['count']); + $row['base_net_price'] = f_round($row['base_gross_price'] / ($row['taxrate'] / 100 + 1), 3); + $row['base_tax_value'] = f_round(($row['base_gross_value'] * $row['taxrate']) / (100 + $row['taxrate'])); + $row['base_net_value'] = f_round($row['base_gross_value'] - $row['base_tax_value']); + + $row['gross_price'] = $row['price']; // price is discounted in sql already + + $row['gross_price_discount'] = f_round($row['base_gross_price'] - $row['gross_price'], 3); + $row['gross_value'] = f_round($row['gross_price'] * $row['count']); + $row['net_price'] = f_round($row['gross_price'] / ($row['taxrate'] / 100 + 1), 3); + $row['net_price_discount'] = f_round($row['gross_price_discount'] / ($row['taxrate'] / 100 + 1), 3); + $row['tax_value'] = f_round(($row['gross_value'] * $row['taxrate']) / (100 + $row['taxrate'])); + $row['net_value'] = f_round(($row['gross_value'] - $row['tax_value'])); + } + + $row['net_value_discount'] = f_round($row['base_net_value'] - $row['net_value']); + $row['gross_value_discount'] = f_round($row['base_gross_value'] - $row['gross_value']); + // + + if (!empty($row['suspended'])) { + if (!empty($row['charge_suspension'])) { + if ($row['suspension_charge_method'] != SUSPENSION_CHARGE_METHOD_NONE) { + switch ($row['suspension_calculation_method']) { + case SUSPENSION_CALCULATION_METHOD_PERCENTAGE: + if (!isset($suspensionsByCurrency[$row['currency']][$row['taxid']][$row['suspension_id']])) { + $suspensionsByCurrency[$row['currency']][$row['taxid']][$row['suspension_id']] = array( + 'name' => trans("Suspension"), + 'taxid' => $row['taxid'], + 'currency' => $row['currency'], + 'customerid' => $row['customerid'], + 'suspensionid' => $row['suspension_id'], + 'customername' => $row['customername'], + 'address' => $row['address'], + 'ten' => $row['ten'], + 'total_net_value' => 0, + 'total_gross_value' => 0, + 'total_tax_value' => 0, + ); + } + if (!isset($suspensionsById[$row['suspension_id']])) { + $suspensionsById[$row['suspension_id']]['suspension_id'] = $row['suspension_id']; + } + + $suspension = $suspensionsByCurrency[$row['currency']][$row['taxid']][$row['suspension_id']]; + $suspension['suspend_assignments'][$idx]['assignment_id'] = $idx; + + $suspensionPercentage = !is_null($row['suspension_percentage']) ? f_round($row['suspension_percentage']) : $defaultSuspensionPercentage; + if (!empty($row['netflag'])) { + $suspension['net_price'] = f_round($row['net_price'] * ($suspensionPercentage / 100), 3); + if ($row['suspension_charge_method'] == SUSPENSION_CHARGE_METHOD_PERIODICALLY) { + if ($row['period'] == YEARLY) { + $suspension['net_price'] = $suspension['net_price'] / 12; + } elseif ($row['period'] == HALFYEARLY) { + $suspension['net_price'] = $suspension['net_price'] / 6; + } elseif ($row['period'] == QUARTERLY) { + $suspension['net_price'] = $suspension['net_price'] / 3; + } elseif ($row['period'] == WEEKLY) { + $suspension['net_price'] = $suspension['net_price'] * 4; + } elseif ($row['period'] == DAILY) { + $suspension['net_price'] = $suspension['net_price'] * 30; + } + } + $suspension['net_value'] = f_round($suspension['net_price'] * $row['count']); + $suspension['gross_price'] = f_round($suspension['net_price'] * ($row['taxrate'] / 100 + 1), 3); + $suspension['tax_value'] = f_round($suspension['net_value'] * ($row['taxrate'] / 100)); + $suspension['gross_value'] = f_round($suspension['net_value'] + $suspension['tax_value']); + } else { + $suspension['gross_price'] = f_round($row['gross_price'] * ($suspensionPercentage / 100), 3); + if ($row['suspension_charge_method'] == SUSPENSION_CHARGE_METHOD_PERIODICALLY) { + if ($row['period'] == YEARLY) { + $suspension['gross_price'] = $suspension['gross_price'] / 12; + } elseif ($row['period'] == HALFYEARLY) { + $suspension['gross_price'] = $suspension['gross_price'] / 6; + } elseif ($row['period'] == QUARTERLY) { + $suspension['gross_price'] = $suspension['gross_price'] / 3; + } elseif ($row['period'] == WEEKLY) { + $suspension['gross_price'] = $suspension['gross_price'] * 4; + } elseif ($row['period'] == DAILY) { + $suspension['gross_price'] = $suspension['gross_price'] * 30; + } + } + $suspension['gross_value'] = f_round($suspension['gross_price'] * $row['count']); + $suspension['net_price'] = f_round($suspension['gross_price'] / ($row['taxrate'] / 100 + 1), 3); + $suspension['tax_value'] = f_round(($suspension['gross_value'] * $row['taxrate']) / (100 + $row['taxrate'])); + $suspension['net_value'] = f_round(($suspension['gross_value'] - $suspension['tax_value'])); + } + + $suspension['total_net_value'] += $suspension['net_value']; + $suspension['total_tax_value'] += $suspension['tax_value']; + $suspension['total_gross_value'] += $suspension['gross_value']; + + $suspensionsByCurrency[$row['currency']][$row['taxid']][$row['suspension_id']] = $suspension; + break; + case SUSPENSION_CALCULATION_METHOD_VALUE: + // account only once for all assignemnts having this suspension + if (!isset($suspensionsByCurrency[$row['suspension_currency']][$row['suspension_tax_id']][$row['suspension_id']]) + && !isset($suspensionsById[$row['suspension_id']])) { + $suspensionsByCurrency[$row['suspension_currency']][$row['suspension_tax_id']][$row['suspension_id']] = array( + 'name' => trans("Suspension"), + 'customerid' => $row['suspension_customer_id'], + 'suspensionid' => $row['suspension_id'], + 'customername' => $row['customername'], + 'address' => $row['address'], + 'ten' => $row['ten'], + 'taxid' => $row['suspension_tax_id'], + 'taxlabel' => $row['suspension_taxlabel'], + 'taxrate' => $row['suspension_taxrate'], + 'note' => $row['suspension_note'], + 'datefrom' => $row['suspension_datefrom'], + 'dateto' => $row['suspension_dateto'], + 'charge_method' => $row['suspension_charge_method'], + 'calculation_method' => $row['suspension_calculation_method'], + 'value' => !is_null($row['suspension_value']) ? $row['suspension_value'] : $defaultSuspensionValue, + 'netflag' => $row['suspension_netflag'], + 'currency' => $row['suspension_currency'], + 'total_net_value' => 0, + 'total_gross_value' => 0, + 'total_tax_value' => 0, + ); + + $suspensionsById[$row['suspension_id']]['suspension_id'] = $row['suspension_id']; + + $suspension = $suspensionsByCurrency[$row['suspension_currency']][$row['suspension_tax_id']][$row['suspension_id']]; + $suspension['suspend_assignments'][$idx]['assignment_id'] = $idx; + + if (!empty($row['suspension_netflag'])) { + $suspension['net_value'] = f_round($suspension['value']); + if ($row['suspension_charge_method'] == SUSPENSION_CHARGE_METHOD_PERIODICALLY) { + if ($row['period'] == YEARLY) { + $suspension['net_value'] = $suspension['net_value'] / 12; + } elseif ($row['period'] == HALFYEARLY) { + $suspension['net_value'] = $suspension['net_value'] / 6; + } elseif ($row['period'] == QUARTERLY) { + $suspension['net_value'] = $suspension['net_value'] / 3; + } elseif ($row['period'] == WEEKLY) { + $suspension['net_value'] = $suspension['net_value'] * 4; + } elseif ($row['period'] == DAILY) { + $suspension['net_value'] = $suspension['net_value'] * 30; + } + } + $suspension['tax_value'] = f_round($suspension['net_value'] * ($row['suspension_taxrate'] / 100)); + $suspension['gross_value'] = f_round($suspension['net_value'] + $suspension['tax_value']); + } else { + $suspension['gross_value'] = f_round($suspension['value']); + if ($row['suspension_charge_method'] == SUSPENSION_CHARGE_METHOD_PERIODICALLY) { + if ($row['period'] == YEARLY) { + $suspension['gross_value'] = $suspension['gross_value'] / 12; + } elseif ($row['period'] == HALFYEARLY) { + $suspension['gross_value'] = $suspension['gross_value'] / 6; + } elseif ($row['period'] == QUARTERLY) { + $suspension['gross_value'] = $suspension['gross_value'] / 3; + } elseif ($row['period'] == WEEKLY) { + $suspension['gross_value'] = $suspension['gross_value'] * 4; + } elseif ($row['period'] == DAILY) { + $suspension['gross_value'] = $suspension['gross_value'] * 30; + } + } + $suspension['tax_value'] = f_round(($suspension['gross_value'] * $row['suspension_taxrate']) / (100 + $row['suspension_taxrate'])); + $suspension['net_value'] = f_round(($suspension['gross_value'] - $suspension['tax_value'])); + } + + $suspension['total_net_value'] = $suspension['net_value']; + $suspension['total_gross_value'] = $suspension['gross_value']; + $suspension['total_tax_value'] = $suspension['tax_value']; + + $suspensionsByCurrency[$row['suspension_currency']][$row['suspension_tax_id']][$row['suspension_id']] = $suspension; + } + $suspensionsByCurrency[$row['suspension_currency']][$row['suspension_tax_id']][$row['suspension_id']]['suspend_assignments'][$idx]['assignment_id'] = $idx; + + break; + } + } else { + switch ($row['suspension_calculation_method']) { + case SUSPENSION_CALCULATION_METHOD_PERCENTAGE: + if (!isset($suspensionsByCurrency[$row['currency']][$row['taxid']][$row['suspension_id']])) { + $suspensionsByCurrency[$row['currency']][$row['taxid']][$row['suspension_id']] = array( + 'name' => trans("Suspension"), + 'taxid' => $row['taxid'], + 'currency' => $row['currency'], + 'customerid' => $row['customerid'], + 'suspensionid' => $row['suspension_id'], + 'customername' => $row['customername'], + 'address' => $row['address'], + 'ten' => $row['ten'], + 'total_net_value' => 0, + 'total_gross_value' => 0, + 'total_tax_value' => 0, + ); + } + if (!isset($suspensionsById[$row['suspension_id']])) { + $suspensionsById[$row['suspension_id']]['suspension_id'] = $row['suspension_id']; + } + + $suspension = $suspensionsByCurrency[$row['currency']][$row['taxid']][$row['suspension_id']]; + $suspension['suspend_assignments'][$idx]['assignment_id'] = $idx; + + $suspension['net_price'] = 0; + $suspension['net_value'] = 0; + $suspension['gross_price'] = 0; + $suspension['tax_value'] = 0; + $suspension['gross_value'] = 0; + + $suspension['total_net_value'] = 0; + $suspension['total_tax_value'] = 0; + $suspension['total_gross_value'] = 0; + + $suspensionsByCurrency[$row['currency']][$row['taxid']][$row['suspension_id']] = $suspension; + break; + case SUSPENSION_CALCULATION_METHOD_VALUE: + // account only once for all assignemnts having this suspension + if (!isset($suspensionsByCurrency[$row['suspension_currency']][$row['suspension_tax_id']][$row['suspension_id']]) + && !isset($suspensionsById[$row['suspension_id']])) { + $suspensionsByCurrency[$row['suspension_currency']][$row['suspension_tax_id']][$row['suspension_id']] = array( + 'name' => trans("Suspension"), + 'customerid' => $row['suspension_customer_id'], + 'suspensionid' => $row['suspension_id'], + 'customername' => $row['customername'], + 'address' => $row['address'], + 'ten' => $row['ten'], + 'taxid' => $row['suspension_tax_id'], + 'taxlabel' => $row['suspension_taxlabel'], + 'taxrate' => $row['suspension_taxrate'], + 'note' => $row['suspension_note'], + 'datefrom' => $row['suspension_datefrom'], + 'dateto' => $row['suspension_dateto'], + 'charge_method' => $row['suspension_charge_method'], + 'calculation_method' => $row['suspension_calculation_method'], + 'value' => !is_null($row['suspension_value']) ? $row['suspension_value'] : $defaultSuspensionValue, + 'netflag' => $row['suspension_netflag'], + 'currency' => $row['suspension_currency'], + 'total_net_value' => 0, + 'total_gross_value' => 0, + 'total_tax_value' => 0, + ); + + $suspensionsById[$row['suspension_id']]['suspension_id'] = $row['suspension_id']; + + $suspension = $suspensionsByCurrency[$row['suspension_currency']][$row['suspension_tax_id']][$row['suspension_id']]; + $suspension['suspend_assignments'][$idx]['assignment_id'] = $idx; + + $suspension['net_value'] = 0; + $suspension['tax_value'] = 0; + $suspension['gross_value'] = 0; + + $suspension['total_net_value'] = 0; + $suspension['total_gross_value'] = 0; + $suspension['total_tax_value'] = 0; + + $suspensionsByCurrency[$row['suspension_currency']][$row['suspension_tax_id']][$row['suspension_id']] = $suspension; + } + + $suspensionsByCurrency[$row['suspension_currency']][$row['suspension_tax_id']][$row['suspension_id']]['suspend_assignments'][$idx]['assignment_id'] = $idx; + + break; + } } - $reportlist[$idx]['values'][$row['currency']]['value'] += $row['value']; - $reportlist[$idx]['values'][$row['currency']][$tax['id']]['netto'] = - round($row['value']/($tax['value']+100)*100, 2); - $reportlist[$idx]['values'][$row['currency']][$tax['id']]['tax'] = - $row['value'] - $reportlist[$idx]['values'][$row['currency']][$tax['id']]['netto']; - $reportlist[$idx]['values'][$row['currency']]['taxsum'] += - $reportlist[$idx]['values'][$row['currency']][$tax['id']]['tax']; - if (!isset($total['netto'][$row['currency']][$tax['id']])) { - $total['netto'][$row['currency']][$tax['id']] = 0; - $total['tax'][$row['currency']][$tax['id']] = 0; + } + unset($assignments[$idx]); + } + } + unset($row, $suspension); + + if (!empty($suspensionsByCurrency)) { + $suspensions = array(); + foreach ($suspensionsByCurrency as $currency => $currencySuspensions) { + foreach ($currencySuspensions as $taxid => $currencyTaxesSuspensions) { + foreach ($currencyTaxesSuspensions as $sid => $currencyTaxSuspension) { + if ($currencyTaxSuspension['total_net_value'] != 0) { + $suspensions[] = array( + 'currency' => $currencyTaxSuspension['currency'], + 'taxid' => $currencyTaxSuspension['taxid'], + 'gross_value' => $currencyTaxSuspension['total_gross_value'], + 'net_value' => $currencyTaxSuspension['total_net_value'], + 'tax_value' => $currencyTaxSuspension['total_tax_value'], + 'customerid' => $currencyTaxSuspension['customerid'], + 'customername' => $currencyTaxSuspension['customername'], + 'address' => $currencyTaxSuspension['address'], + 'ten' => $currencyTaxSuspension['ten'], + ); + } } - $total['netto'][$row['currency']][$tax['id']] += - $reportlist[$idx]['values'][$row['currency']][$tax['id']]['netto']; - $total['tax'][$row['currency']][$tax['id']] += - $reportlist[$idx]['values'][$row['currency']][$tax['id']]['tax']; } } } - switch ($order) { - case 'customername': - $table = array(); - foreach ($reportlist as $idx => $row) { - $table['idx'][] = $idx; - $table['customername'][] = $row['customername']; - } - if (!empty($table)) { - array_multisort($table['customername'], ($direction == 'desc' ? SORT_DESC : SORT_ASC), $table['idx']); - foreach ($table['idx'] as $idx) { - $tmplist[] = $reportlist[$idx]; + if (!empty($suspensions)) { + $assignments = array_values($assignments); + $assignments = array_merge($assignments, $suspensions); + } + + // + $assignmentsByTax = array(); + foreach ($assignments as $row) { + if (!isset($assignmentsByTax[$row['customerid']])) { + $assignmentsByTax[$row['customerid']] = array( + 'id' => $row['customerid'], + 'customername' => $row['customername'], + 'address' => $row['address'], + 'ten' => $row['ten'], + 'values' => array(), + ); + } + + if (!isset($assignmentsByTax[$row['customerid']]['values'][$row['currency']])) { + $assignmentsByTax[$row['customerid']]['values'][$row['currency']] = array( + 'value' => 0, + 'taxsum' => 0, + ); + } + + if (!isset($assignmentsByTax[$row['customerid']]['values'][$row['currency']][$row['taxid']])) { + $assignmentsByTax[$row['customerid']]['values'][$row['currency']][$row['taxid']]['netto'] = 0; + $assignmentsByTax[$row['customerid']]['values'][$row['currency']][$row['taxid']]['tax'] = 0; + } + + $assignmentsByTax[$row['customerid']]['values'][$row['currency']]['value'] += $row['gross_value']; + $assignmentsByTax[$row['customerid']]['values'][$row['currency']][$row['taxid']]['netto'] += $row['net_value']; + $assignmentsByTax[$row['customerid']]['values'][$row['currency']][$row['taxid']]['tax'] += $row['tax_value']; + $assignmentsByTax[$row['customerid']]['values'][$row['currency']]['taxsum'] += $row['tax_value']; + + if (!isset($total['netto'][$row['currency']][$row['taxid']])) { + $total['netto'][$row['currency']][$row['taxid']] = 0; + $total['tax'][$row['currency']][$row['taxid']] = 0; + } + + $total['netto'][$row['currency']][$row['taxid']] += $assignmentsByTax[$row['customerid']]['values'][$row['currency']][$row['taxid']]['netto']; + $total['tax'][$row['currency']][$row['taxid']] += $assignmentsByTax[$row['customerid']]['values'][$row['currency']][$row['taxid']]['tax']; + } + // + + $reportlist = $assignmentsByTax; + if (!empty($reportlist)) { + $table = array(); + $tmplist = array(); + switch ($order) { + case 'customername': + foreach ($reportlist as $idx => $row) { + $table['idx'][] = $idx; + $table['customername'][] = $row['customername']; } - } - $reportlist = empty($tmplist) ? array() : $tmplist; - break; - default: - foreach ($reportlist as $idx => $row) { - $table['idx'][] = $idx; - $table['value'][] = $row['value']; - } - if (is_array($table)) { - array_multisort($table['value'], ($direction == 'desc' ? SORT_DESC : SORT_ASC), $table['idx']); - foreach ($table['idx'] as $idx) { - $tmplist[] = $reportlist[$idx]; + if (!empty($table)) { + array_multisort($table['customername'], ($direction == 'desc' ? SORT_DESC : SORT_ASC), $table['idx']); + foreach ($table['idx'] as $idx) { + $tmplist[] = $reportlist[$idx]; + } } - } - $reportlist = $tmplist; - break; + $reportlist = empty($tmplist) ? array() : $tmplist; + break; + default: + foreach ($reportlist as $idx => $row) { + $table['idx'][] = $idx; + $table['value'][] = $row['value']; + } + if (is_array($table)) { + array_multisort($table['value'], ($direction == 'desc' ? SORT_DESC : SORT_ASC), $table['idx']); + foreach ($table['idx'] as $idx) { + $tmplist[] = $reportlist[$idx]; + } + } + $reportlist = $tmplist; + break; + } } - - $SMARTY->assign('reportlist', $reportlist); - $SMARTY->assign('total', $total); - $SMARTY->assign('taxes', $taxes); - $SMARTY->assign('taxescount', count($taxes)); } + $SMARTY->assign('reportlist', $reportlist); + $SMARTY->assign('total', $total); + $SMARTY->assign('taxes', $taxes); + $SMARTY->assign('taxescount', count($taxes)); + if (strtolower($report_type) == 'pdf') { $output = $SMARTY->fetch('print/printliabilityreport.html'); html2pdf($output, trans('Reports'), $layout['pagetitle']); diff --git a/modules/suspensiondel.php b/modules/suspensiondel.php new file mode 100644 index 0000000000..cdf6de4ada --- /dev/null +++ b/modules/suspensiondel.php @@ -0,0 +1,52 @@ +GetOne('SELECT id FROM customerview WHERE id = ?', array($cid)); + } + if (!$customerId) { + $SESSION->redirect_to_history_entry(); + } + + $DB->BeginTrans(); + $DB->LockTables(array('suspensions', 'assignmentsuspensions')); + + $LMS->deleteSuspension($suspensionId); + + $DB->UnLockTables(); + $DB->CommitTrans(); + + $backto = $SESSION->get_history_entry(); + // infinite loop prevention + if (preg_match('/customerassignmentedit/', $backto)) { + $backto = 'm=customerinfo&id=' . $customer; + } + $SESSION->redirect('?' . $backto); +} diff --git a/modules/tarifflist.php b/modules/tarifflist.php index a38c40198f..157e194caf 100644 --- a/modules/tarifflist.php +++ b/modules/tarifflist.php @@ -146,20 +146,14 @@ function GetTariffList($order = 'name,asc', $type = null, $access = 0, $customer FROM ( SELECT a.tariffid, a.count, t.period, a.period AS aperiod, a.pdiscount, a.vdiscount, t.value FROM assignments a - JOIN tariffs t ON (t.id = a.tariffid)' + JOIN tariffs t ON (t.id = a.tariffid) + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0)' . ($customergroupid ? ' JOIN vcustomerassignments cc ON (cc.customerid = a.customerid)' : '') . ($tax ? ' JOIN taxes ON (t.taxid = taxes.id)' : '') - . ' WHERE a.commited = 1 AND ( - a.suspended = 1 - OR a.datefrom > ?NOW? - OR (a.dateto <= ?NOW? AND a.dateto != 0) - OR EXISTS ( - SELECT 1 FROM assignments b - WHERE b.customerid = a.customerid - AND liabilityid IS NULL AND tariffid IS NULL - AND b.datefrom <= ?NOW? AND (b.dateto > ?NOW? OR b.dateto = 0) - ) - )' + . ' WHERE a.commited = 1 AND vas.suspended IS NOT NULL' . ($type ? ' AND t.type = '.intval($type) : '') . ($netflag == 1 ? ' AND t.flags & ' . TARIFF_FLAG_NET_ACCOUNT . ' > 0' : '') . ($netflag == 2 ? ' AND t.flags & ' . TARIFF_FLAG_NET_ACCOUNT . ' = 0' : '') diff --git a/modules/ukepit.php b/modules/ukepit.php index fc44613828..69ab377983 100644 --- a/modules/ukepit.php +++ b/modules/ukepit.php @@ -685,20 +685,27 @@ function find_nodes_for_netdev($customerid, $netdevid, &$customer_nodes, &$custo AND EXISTS ( SELECT na.id FROM nodeassignments na JOIN assignments a ON a.id = na.assignmentid + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) WHERE na.nodeid = n.id AND a.commited = 1 - AND a.suspended = 0 + AND vas.suspended IS NULL AND a.period IN ? AND a.datefrom < ?NOW? AND (a.dateto = 0 OR a.dateto > ?NOW?) ) AND NOT EXISTS ( SELECT id FROM assignments aa + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = aa.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND (aa.dateto = 0 OR aa.dateto > ?NOW?) WHERE aa.customerid = (CASE WHEN n.ownerid IS NULL THEN nd.ownerid ELSE n.ownerid END) AND aa.commited = 1 AND aa.tariffid IS NULL - AND aa.liabilityid IS NULL - AND aa.datefrom < ?NOW? + AND vas.suspension_suspend_all = 1 AND (aa.dateto = 0 OR aa.dateto > ?NOW?) ) GROUP BY customerid_netdev", @@ -815,19 +822,27 @@ function find_nodes_for_netdev($customerid, $netdevid, &$customer_nodes, &$custo AND EXISTS ( SELECT na.id FROM nodeassignments na JOIN assignments a ON a.id = na.assignmentid + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) WHERE na.nodeid = n.id AND a.commited = 1 - AND a.suspended = 0 + AND vas.suspended IS NULL AND a.period IN ? AND a.datefrom < ?NOW? AND (a.dateto = 0 OR a.dateto > ?NOW?) ) AND NOT EXISTS ( - SELECT id FROM assignments aa + SELECT id + FROM assignments aa + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = aa.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND (aa.dateto > ?NOW? OR aa.dateto = 0) WHERE aa.customerid = c.id AND aa.commited = 1 - AND aa.tariffid IS NULL - AND aa.liabilityid IS NULL + AND vas.suspension_suspend_all = 1 AND aa.datefrom < ?NOW? AND (aa.dateto > ?NOW? OR aa.dateto = 0) ) @@ -1298,17 +1313,10 @@ function find_nodes_for_netdev($customerid, $netdevid, &$customer_nodes, &$custo JOIN customers c ON c.id = n.ownerid JOIN assignments a ON a.id = na.assignmentid JOIN tariffs t ON t.id = a.tariffid - LEFT JOIN ( - SELECT - aa.customerid AS cid, - COUNT(id) AS total - FROM assignments aa - WHERE aa.tariffid IS NULL - AND aa.liabilityid IS NULL - AND aa.datefrom < ?NOW? - AND (aa.dateto > ?NOW? OR aa.dateto = 0) - GROUP BY aa.customerid - ) allsuspended ON allsuspended.cid = a.customerid + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) WHERE n.ownerid IS NOT NULL AND n.netdev IS NOT NULL " . ($division ? ' AND c.divisionid = ' . $division : '') . " @@ -1320,11 +1328,10 @@ function find_nodes_for_netdev($customerid, $netdevid, &$customer_nodes, &$custo AND (addr.street_id = ? OR addr.street_id IS NULL) AND addr.house = ? AND a.commited = 1 - AND a.suspended = 0 AND a.period IN ? AND a.datefrom < ?NOW? AND (a.dateto = 0 OR a.dateto > ?NOW?) - AND allsuspended.total IS NULL + AND vas.suspended IS NULL GROUP BY na.nodeid, n.name, n.longitude, n.latitude, n.linktype, n.linktechnology, n.address_id", array( $netnode['netdevices'], @@ -1364,28 +1371,19 @@ function find_nodes_for_netdev($customerid, $netdevid, &$customer_nodes, &$custo JOIN nodes n ON n.id = na.nodeid JOIN assignments a ON a.id = na.assignmentid JOIN tariffs t ON t.id = a.tariffid - LEFT JOIN ( - SELECT - aa.customerid AS cid, - COUNT(id) AS total - FROM assignments aa - WHERE aa.commited = 1 - AND aa.tariffid IS NULL - AND aa.liabilityid IS NULL - AND aa.datefrom < ?NOW? - AND (aa.dateto > ?NOW? OR aa.dateto = 0) - GROUP BY aa.customerid - ) allsuspended ON allsuspended.cid = a.customerid + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) JOIN netdevices nd ON nd.id = n.netdev JOIN customers c ON c.id = nd.ownerid WHERE n.id IN ? " . ($division ? ' AND c.divisionid = ' . $division : '') . " AND a.commited = 1 - AND a.suspended = 0 AND a.period IN ? AND a.datefrom < ?NOW? AND (a.dateto = 0 OR a.dateto > ?NOW?) - AND allsuspended.total IS NULL + AND vas.suspended IS NULL GROUP BY na.nodeid, n.name, n.linktype, n.linktechnology, n.address_id", array( $uni_link['nodes'], @@ -1632,26 +1630,18 @@ function ($value, $key) { : '') . " JOIN assignments a ON a.id = na.assignmentid JOIN tariffs t ON t.id = a.tariffid - LEFT JOIN ( - SELECT - aa.customerid AS cid, - COUNT(id) AS total - FROM assignments aa - WHERE aa.tariffid IS NULL - AND aa.liabilityid IS NULL - AND aa.datefrom < ?NOW? - AND (aa.dateto > ?NOW? OR aa.dateto = 0) - GROUP BY aa.customerid - ) allsuspended ON allsuspended.cid = a.customerid + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) WHERE n.ownerid IS NOT NULL " . ($division ? ' AND c.divisionid = ' . $division : '') . " AND n.access = 1 AND a.commited = 1 - AND a.suspended = 0 AND a.period IN ? AND a.datefrom < ?NOW? AND (a.dateto = 0 OR a.dateto > ?NOW?) - AND allsuspended.total IS NULL + AND vas.suspended IS NULL GROUP BY na.nodeid, n.name, n.linktype, diff --git a/modules/ukesiis.php b/modules/ukesiis.php index 0a93044067..0b7c0014a7 100644 --- a/modules/ukesiis.php +++ b/modules/ukesiis.php @@ -450,17 +450,15 @@ function find_nodes_for_netdev($customerid, $netdevid, &$customer_nodes, &$custo AND EXISTS ( SELECT na.id FROM nodeassignments na JOIN assignments a ON a.id = na.assignmentid - WHERE na.nodeid = n.id AND a.suspended = 0 + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) + WHERE na.nodeid = n.id + AND vas.suspended IS NULL AND a.period IN (" . implode(',', array(YEARLY, HALFYEARLY, QUARTERLY, MONTHLY, DISPOSABLE)) . ") AND a.datefrom < ?NOW? AND (a.dateto = 0 OR a.dateto > ?NOW?) ) - AND NOT EXISTS ( - SELECT id FROM assignments aa - WHERE aa.customerid = (CASE WHEN n.ownerid IS NULL THEN nd.ownerid ELSE n.ownerid END) - AND aa.tariffid IS NULL AND aa.liabilityid IS NULL - AND aa.datefrom < ?NOW? - AND (aa.dateto > ?NOW? OR aa.dateto = 0) - ) GROUP BY customerid_netdev", 'customerid_netdev' ); @@ -581,14 +579,15 @@ function find_nodes_for_netdev($customerid, $netdevid, &$customer_nodes, &$custo AND EXISTS (SELECT na.id FROM nodeassignments na JOIN assignments a ON a.id = na.assignmentid - WHERE na.nodeid = n.id AND a.suspended = 0 + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) + WHERE na.nodeid = n.id + AND vas.suspended IS NULL AND a.period IN (" . implode(',', array(YEARLY, HALFYEARLY, QUARTERLY, MONTHLY, DISPOSABLE)) . ") AND (a.datefrom = 0 OR a.datefrom < ?NOW?) AND (a.dateto = 0 OR a.dateto > ?NOW?)) - AND NOT EXISTS - (SELECT id FROM assignments aa - WHERE aa.customerid = c.id AND aa.tariffid IS NULL AND aa.liabilityid IS NULL - AND (aa.datefrom < ?NOW? OR aa.datefrom = 0) - AND (aa.dateto > ?NOW? OR aa.dateto = 0)) + ) GROUP BY linktype, linktechnology, linkspeed, rs.frequency, c.type ORDER BY c.type", array($netdevice['id'])); @@ -1447,17 +1446,16 @@ function find_nodes_for_netdev($customerid, $netdevid, &$customer_nodes, &$custo JOIN assignments a ON a.id = na.assignmentid JOIN tariffs t ON t.id = a.tariffid JOIN customers c ON c.id = n.ownerid - LEFT JOIN (SELECT aa.customerid AS cid, COUNT(id) AS total FROM assignments aa - WHERE aa.tariffid IS NULL AND aa.liabilityid IS NULL - AND aa.datefrom < ?NOW? - AND (aa.dateto > ?NOW? OR aa.dateto = 0) GROUP BY aa.customerid) - AS allsuspended ON allsuspended.cid = c.id + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) JOIN netdevices nd ON nd.id = n.netdev WHERE n.ownerid IS NOT NULL AND n.netdev IS NOT NULL AND n.linktype = ? AND n.linktechnology = ? AND addr.city_id = ? AND (addr.street_id = ? OR addr.street_id IS NULL) AND addr.house = ? - AND a.suspended = 0 AND a.period IN (".implode(',', array(YEARLY, HALFYEARLY, QUARTERLY, MONTHLY, DISPOSABLE)).") + AND a.period IN (".implode(',', array(YEARLY, HALFYEARLY, QUARTERLY, MONTHLY, DISPOSABLE)).") AND (a.datefrom = 0 OR a.datefrom < ?NOW?) AND (a.dateto = 0 OR a.dateto > ?NOW?) - AND allsuspended.total IS NULL + AND vas.suspended IS NULL GROUP BY na.nodeid, c.type, n.invprojectid, nd.id, nd.status", array($range['linktype'], $range['linktechnology'], $range['location_city'], $range['location_street'], $range['location_house']) ); @@ -1482,16 +1480,15 @@ function find_nodes_for_netdev($customerid, $netdevid, &$customer_nodes, &$custo JOIN assignments a ON a.id = na.assignmentid JOIN tariffs t ON t.id = a.tariffid JOIN customers c ON c.id = n.ownerid - LEFT JOIN (SELECT aa.customerid AS cid, COUNT(id) AS total FROM assignments aa - WHERE aa.tariffid IS NULL AND aa.liabilityid IS NULL - AND aa.datefrom < ?NOW? - AND (aa.dateto > ?NOW? OR aa.dateto = 0) GROUP BY aa.customerid) - AS allsuspended ON allsuspended.cid = c.id + LEFT JOIN vassignmentsuspensions vas ON vas.suspension_assignment_id = a.id + AND vas.suspension_datefrom <= ?NOW? + AND (vas.suspension_dateto >= ?NOW? OR vas.suspension_dateto = 0) + AND a.datefrom <= ?NOW? AND (a.dateto >= ?NOW? OR a.dateto = 0) JOIN netdevices nd ON nd.id = n.netdev WHERE n.id IN (" . implode(',', $uni_link['nodes']) . ") - AND a.suspended = 0 AND a.period IN (".implode(',', array(YEARLY, HALFYEARLY, QUARTERLY, MONTHLY, DISPOSABLE)).") + AND a.period IN (".implode(',', array(YEARLY, HALFYEARLY, QUARTERLY, MONTHLY, DISPOSABLE)).") AND a.datefrom < ?NOW? AND (a.dateto = 0 OR a.dateto > ?NOW?) - AND allsuspended.total IS NULL + AND vas.suspended IS NULL GROUP BY na.nodeid, c.type", array() ); diff --git a/templates/default/customer/customerassignmenthelper.html b/templates/default/customer/customerassignmenthelper.html index 812e8cb054..80802ad3f0 100644 --- a/templates/default/customer/customerassignmenthelper.html +++ b/templates/default/customer/customerassignmenthelper.html @@ -1,5 +1,14 @@ {$promotion_show_period_values = ConfigHelper::checkConfig('promotions.show_period_values', ConfigHelper::checkConfig('phpui.promotion_show_period_values'))} {$promotion_schema_name_limit = intval(ConfigHelper::getConfig('promotions.schema_name_limit', ConfigHelper::getConfig('phpui.promotion_schema_name_limit', 40)))} +{$defaultSuspensionChargeMethod = ConfigHelper::getConfig('suspensions.default_charge_method', $smarty.const.SUSPENSION_CHARGE_METHOD_PERIODICALLY)} +{$defaultSuspensionCalculationMethod = ConfigHelper::getConfig('suspensions.default_calculation_method', $smarty.const.SUSPENSION_CALCULATION_METHOD_PERCENTAGE)} +{$defaultSuspensionPercentage = ConfigHelper::getConfig('suspensions.default_percentage', + ConfigHelper::getConfig('payments.suspension_percentage', + ConfigHelper::getConfig('finances.suspension_percentage', 0) + ) +)} +{$defaultSuspensionValue = ConfigHelper::getConfig('suspensions.default_value', 0)} +{$defaultSuspensionNetflag = ConfigHelper::getConfig('suspensions.default_netflag', 0)}