diff --git a/bin/lms-maketcnew.php b/bin/lms-maketcnew.php index 40991b77bf..8c014fc897 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..d232835cf6 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..a91dca805c 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,25 +406,43 @@ 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.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) @@ -429,24 +452,6 @@ function get_period($period) 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, @@ -454,15 +459,37 @@ function get_period($period) (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 + (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 LEFT JOIN customerconsents cc1 ON cc1.customerid = c.id AND cc1.type = " . CCONSENT_EINVOICE . " @@ -490,28 +517,64 @@ function get_period($period) ) l ON a.liabilityid = l.id LEFT JOIN ( SELECT - vna.assignment_id, " . $DB->GroupConcat('vn.phone', ',') . " AS phones + 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 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,26 +597,43 @@ 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, + 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 @@ -565,128 +645,129 @@ function get_period($period) 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 + 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 - 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, ' : '') + " . ($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 ?: '') + 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..cac596db00 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 vassignmentsuspensiongroupcounts; +DROP VIEW IF EXISTS vassignmentsuspensionvalues; 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,300 @@ 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 vassignmentsuspensiongroupcounts 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 vassignmentsuspensionvalues 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 + COALESCE(suspensions.assignment_id, a.id) AS suspension_assignment_id, + COALESCE(suspensions.suspension_id, suspensions_all.suspension_id) 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 vassignmentsuspensiongroupcounts 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 vassignmentsuspensiongroupcounts 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, + COALESCE(suspensions.suspension_id, suspensions_all.suspension_id) 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.suspension_id IS NOT NULL + THEN suspensions.taxrate + ELSE suspensions_all.taxrate + END) AS suspension_taxrate, + (CASE WHEN suspensions.suspension_id 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 decimal) + 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 decimal) + 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 decimal) + 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 decimal) + 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 vassignmentsuspensionvalues vasv ON vasv.suspensionvalues_assignment_id = a.id + WHERE suspensions.suspension_id IS NOT NULL OR suspensions_all.suspend_all = 1; CREATE VIEW vnodetariffs_tariffs AS SELECT n.id AS nodeid, ROUND(SUM(t.downrate * a.count)) AS downrate, @@ -3335,8 +3666,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 +3733,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) @@ -3925,7 +4264,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 +4712,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..7b269a9a4a 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,293 @@ 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 vassignmentsuspensiongroupcounts AS + SELECT COUNT(vasg.suspension_assignment_id) AS suspensiongroup_assignments_count, + vasg.suspension_id AS suspensiongroup_suspension_id + FROM (SELECT + COALESCE(suspensions.assignment_id, a.id) AS suspension_assignment_id, + COALESCE(suspensions.suspension_id, suspensions_all.suspension_id) 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 vassignmentsuspensionvalues 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 + COALESCE(suspensions.assignment_id, a.id) AS suspension_assignment_id, + COALESCE(suspensions.suspension_id, suspensions_all.suspension_id) 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 vassignmentsuspensiongroupcounts 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 vassignmentsuspensiongroupcounts 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 + COALESCE(suspensions.assignment_id, a.id) 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, + COALESCE(suspensions.suspension_id, suspensions_all.suspension_id) 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.suspension_id IS NOT NULL + THEN suspensions.taxrate + ELSE suspensions_all.taxrate + END) AS suspension_taxrate, + (CASE WHEN suspensions.suspension_id 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 vassignmentsuspensionvalues 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 +4295,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 +4743,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..ab26bda1db 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,40 @@ 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($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..8b51b9afa3 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..09ba5a29ff 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 + 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 . ' + 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 t.currency, l.currency + 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,999 @@ 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) - 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) - 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, - uprate AS unitary_uprate, - ROUND(t.upceil * a.count) AS upceil, - upceil AS unitary_upceil, - ROUND(t.downceil * a.count) AS downceil, - downceil AS unitary_downceil, - ROUND(t.downrate * a.count) AS downrate, - downrate AS unitary_downrate, - (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 . ') - 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) + 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 + 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.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.uprate * a.count) AS total_uprate, + upceil AS unitary_upceil, + ROUND(t.upceil * a.count) AS total_upceil, + downceil AS unitary_downceil, + 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, + (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, + (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($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($assignments[$idx]['tax_value'])) { - $assignments[$idx]['discounted_netprice'] = f_round($assignments[$idx]['discounted_price'] / ($assignments[$idx]['tax_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_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 +2040,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 +2539,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 +2745,7 @@ public function UpdateExistingAssignments($data) if ($data['existing_assignments']['operation'] == EXISTINGASSIGNMENT_DELETE) { $this->DeleteAssignment($aid); } else { - $this->SuspendAssignment($aid); + $this->suspendAssignment($aid); } } } @@ -1814,36 +2808,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 +4476,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 +4538,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 +6429,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..8e25fa1794 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..04cc04f01a --- /dev/null +++ b/lib/upgradedb/mysql.2024052400.php @@ -0,0 +1,871 @@ +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 vassignmentsuspensionvalues"); +$this->Execute("DROP VIEW vassignmentsuspensiongroupcounts"); + +/* -------------------------------------------------------- + Structure of view "vassignmentsuspensiongroupcounts" +-------------------------------------------------------- */ +$this->Execute(" +CREATE VIEW vassignmentsuspensiongroupcounts 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 "vassignmentsuspensionvalues" +-------------------------------------------------------- */ +$this->Execute(" +CREATE VIEW vassignmentsuspensionvalues 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 + COALESCE(suspensions.assignment_id, a.id) AS suspension_assignment_id, + COALESCE(suspensions.suspension_id, suspensions_all.suspension_id) 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 vassignmentsuspensiongroupcounts 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 vassignmentsuspensiongroupcounts 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 + COALESCE(suspensions.assignment_id, a.id) 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, + COALESCE(suspensions.suspension_id, suspensions_all.suspension_id) 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.suspension_id IS NOT NULL + THEN suspensions.taxrate + ELSE suspensions_all.taxrate + END) AS suspension_taxrate, + (CASE WHEN suspensions.suspension_id 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 vassignmentsuspensionvalues 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..d46de2ade2 --- /dev/null +++ b/lib/upgradedb/postgres.2024052400.php @@ -0,0 +1,1021 @@ +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 vassignmentsuspensionvalues"); +$this->Execute("DROP VIEW IF EXISTS vassignmentsuspensiongroupcounts"); + +/* -------------------------------------------------------- + Structure of view "vassignmentsuspensiongroupcounts" +-------------------------------------------------------- */ +$this->Execute(" +CREATE VIEW vassignmentsuspensiongroupcounts 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 "vassignmentsuspensionvalues" +-------------------------------------------------------- */ +$this->Execute(" +CREATE VIEW vassignmentsuspensionvalues 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 + COALESCE(suspensions.assignment_id, a.id) AS suspension_assignment_id, + COALESCE(suspensions.suspension_id, suspensions_all.suspension_id) 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 vassignmentsuspensiongroupcounts 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 vassignmentsuspensiongroupcounts 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 + COALESCE(suspensions.assignment_id, a.id) 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, + COALESCE(suspensions.suspension_id, suspensions_all.suspension_id) 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.suspension_id IS NOT NULL + THEN suspensions.taxrate + ELSE suspensions_all.taxrate + END) AS suspension_taxrate, + (CASE WHEN suspensions.suspension_id 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 vassignmentsuspensionvalues 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..f3e08f1076 100644 --- a/modules/customerassignmentadd.php +++ b/modules/customerassignmentadd.php @@ -34,106 +34,433 @@ } 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; + } + } + } - $SESSION->redirect_to_history_entry(); - } + $suspensionArgs['at'] = $suspension_at; + $suspensionArgs['customerid'] = $customer['id']; + + $DB->BeginTrans(); + $DB->LockTables(array('suspensions', 'assignmentsuspensions')); + + $LMS->addSuspension($suspensionArgs); - $a['alltariffs'] = isset($a['alltariffs']); + $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); + } + + + $DB->UnLockTables(); + $DB->CommitTrans(); + + $SESSION->redirect_to_history_entry(); + } + } + } $SMARTY->assign('error', $error); } else { @@ -227,7 +554,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 +592,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..17b527df56 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']), - ); - $DB->Execute( - 'INSERT INTO liabilities (name, value, flags, taxcategory, currency, taxid, prodid, type, netvalue, note) - VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)', - array_values($args) + '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'] ); - $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); - } - } + $SYSLOG->AddMessage(SYSLOG::RES_ASSIGN, SYSLOG::OPER_UPDATE, $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'] - ); - - $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'])); @@ -621,8 +887,6 @@ 'next' => false, ))); -// ----- - $SMARTY->assign('tags', $LMS->TarifftagGetAll()); $SMARTY->assign('tariffs', $LMS->GetTariffs($a['tariffid'])); @@ -639,6 +903,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)}