From 46ef36ced9981cf756eeee6b689c1d6630de4831 Mon Sep 17 00:00:00 2001 From: Steve Ireland Date: Sat, 27 Feb 2021 18:25:18 -0500 Subject: [PATCH] Add support for customer balance due tracking. --- application/controllers/Customers.php | 3 ++ application/controllers/Reports.php | 13 ++++++- application/language/en-GB/customers_lang.php | 1 + application/language/en-GB/reports_lang.php | 1 + application/language/en-US/customers_lang.php | 1 + application/language/en-US/reports_lang.php | 1 + .../20210224100000_customerduetracking.php | 20 ++++++++++ application/models/Customer.php | 2 + application/models/Sale.php | 2 +- application/models/reports/Detailed_sales.php | 13 +++++++ .../models/reports/Summary_payments.php | 12 ++++-- application/models/reports/Summary_taxes.php | 37 +++++++++++++++--- application/views/customers/form.php | 38 ++++++++++++++++++- 13 files changed, 132 insertions(+), 12 deletions(-) create mode 100644 application/migrations/20210224100000_customerduetracking.php diff --git a/application/controllers/Customers.php b/application/controllers/Customers.php index 5f446da76..394960aee 100644 --- a/application/controllers/Customers.php +++ b/application/controllers/Customers.php @@ -38,6 +38,7 @@ class Customers extends Persons //create object with empty properties. $stats = new stdClass; $stats->total = 0; + $stats->balance_due = 0; $stats->min = 0; $stats->max = 0; $stats->average = 0; @@ -74,6 +75,7 @@ class Customers extends Persons //create object with empty properties. $stats = new stdClass; $stats->total = 0; + $stats->balance_due = 0; $stats->min = 0; $stats->max = 0; $stats->average = 0; @@ -260,6 +262,7 @@ class Customers extends Persons 'company_name' => $this->input->post('company_name') == '' ? NULL : $this->input->post('company_name'), 'discount' => $this->input->post('discount') == '' ? 0.00 : $this->input->post('discount'), 'discount_type' => $this->input->post('discount_type') == NULL ? PERCENT : $this->input->post('discount_type'), + 'credit_limit' => $this->input->post('credit_limit') == '' ? 0.00 : $this->input->post('credit_limit'), 'package_id' => $this->input->post('package_id') == '' ? NULL : $this->input->post('package_id'), 'taxable' => $this->input->post('taxable') != NULL, 'date' => $date_formatter->format('Y-m-d H:i:s'), diff --git a/application/controllers/Reports.php b/application/controllers/Reports.php index d7001e8b0..2eec83746 100644 --- a/application/controllers/Reports.php +++ b/application/controllers/Reports.php @@ -1347,6 +1347,7 @@ class Reports extends Secure_Controller } $sale_type_options['canceled'] = $this->lang->line('reports_canceled'); $sale_type_options['returns'] = $this->lang->line('reports_returns'); + $sale_type_options['due'] = $this->lang->line('reports_balance_due'); return $sale_type_options; } @@ -1387,6 +1388,16 @@ class Reports extends Secure_Controller $button_label = $this->lang->line('common_delete'); } + $payments = $row['payment_type']; + if($row['due'] > 0) + { + if($row['payment_type'] != "") + { + $payments .= ', '; + } + $payments .= 'Balance ' . to_currency($row['due']); + } + $summary_data[] = $this->xss_clean(array( 'id' => $row['sale_id'], 'type_code' => $row['type_code'], @@ -1399,7 +1410,7 @@ class Reports extends Secure_Controller 'total' => to_currency($row['total']), 'cost' => to_currency($row['cost']), 'profit' => to_currency($row['profit']), - 'payment_type' => $row['payment_type'], + 'payment_type' => $payments, 'comment' => $row['comment'], 'edit' => anchor('sales/edit/'.$row['sale_id'], '', array('class' => 'modal-dlg print_hide', $button_key => $button_label, 'data-btn-submit' => $this->lang->line('common_submit'), 'title' => $this->lang->line('sales_update'))) diff --git a/application/language/en-GB/customers_lang.php b/application/language/en-GB/customers_lang.php index db5f072d4..1c467f879 100644 --- a/application/language/en-GB/customers_lang.php +++ b/application/language/en-GB/customers_lang.php @@ -12,6 +12,7 @@ $lang["customers_confirm_delete"] = "Are you sure you want to delete the selecte $lang["customers_confirm_restore"] = "Are you sure you want to restore the selected Customers(s)?"; $lang["customers_consent"] = "Registration consent"; $lang["customers_consent_required"] = "Registration consent is a required field"; +$lang["customers_credit_limit"] = "Credit Limit"; $lang["customers_csv_import_failed"] = "The csv import failed"; $lang["customers_csv_import_nodata_wrongformat"] = "The uploaded file has no data or is incorrectly formatted"; $lang["customers_csv_import_partially_failed"] = "Customer import successful with some failures:"; diff --git a/application/language/en-GB/reports_lang.php b/application/language/en-GB/reports_lang.php index 98309c6ca..f60d2c125 100644 --- a/application/language/en-GB/reports_lang.php +++ b/application/language/en-GB/reports_lang.php @@ -2,6 +2,7 @@ $lang["reports_all"] = "All"; $lang["reports_authority"] = "Authority"; +$lang["reports_balance_due"] = "Balance Due"; $lang["reports_canceled"] = "Cancelled"; $lang["reports_categories"] = "Categories"; $lang["reports_categories_summary_report"] = "Categories Summary Report"; diff --git a/application/language/en-US/customers_lang.php b/application/language/en-US/customers_lang.php index 9eddd5b3c..21fe87e18 100644 --- a/application/language/en-US/customers_lang.php +++ b/application/language/en-US/customers_lang.php @@ -12,6 +12,7 @@ $lang["customers_confirm_delete"] = "Are you sure you want to delete the selecte $lang["customers_confirm_restore"] = "Are you sure you want to restore selected customers(s)?"; $lang["customers_consent"] = "Registration consent"; $lang["customers_consent_required"] = "Registration consent is a required field."; +$lang["customers_credit_limit"] = "Credit Limit"; $lang["customers_csv_import_failed"] = "CSV import failed"; $lang["customers_csv_import_nodata_wrongformat"] = "The uploaded file has no data or is incorrectly formatted."; $lang["customers_csv_import_partially_failed"] = "Customer import successful with some failures:"; diff --git a/application/language/en-US/reports_lang.php b/application/language/en-US/reports_lang.php index a14631001..a46db97f9 100644 --- a/application/language/en-US/reports_lang.php +++ b/application/language/en-US/reports_lang.php @@ -2,6 +2,7 @@ $lang["reports_all"] = "All"; $lang["reports_authority"] = "Authority"; +$lang["reports_balance_due"] = "Balance Due"; $lang["reports_canceled"] = "Canceled"; $lang["reports_categories"] = "Categories"; $lang["reports_categories_summary_report"] = "Categories Summary Report"; diff --git a/application/migrations/20210224100000_customerduetracking.php b/application/migrations/20210224100000_customerduetracking.php new file mode 100644 index 000000000..b8553ab79 --- /dev/null +++ b/application/migrations/20210224100000_customerduetracking.php @@ -0,0 +1,20 @@ +db->query('ALTER TABLE ' . $this->db->dbprefix('customers') . ' ADD COLUMN `credit_limit` decimal(15,2) NOT NULL DEFAULT 0 AFTER `discount_type`'); + } + + public function down() + { + $this->db->query('ALTER TABLE ' . $this->db->dbprefix('customers') . ' DROP COLUMN `credit_limit`'); + } +} +?> diff --git a/application/models/Customer.php b/application/models/Customer.php index d5b812718..d88b98251 100644 --- a/application/models/Customer.php +++ b/application/models/Customer.php @@ -98,6 +98,7 @@ class Customer extends Person */ public function get_stats($customer_id) { + // TODO Rework this // create a temporary table to contain all the sum and average of items $this->db->query('CREATE TEMPORARY TABLE IF NOT EXISTS ' . $this->db->dbprefix('sales_items_temp') . ' (INDEX(sale_id)) ENGINE=MEMORY @@ -255,6 +256,7 @@ class Customer extends Person 'taxable' => 0, 'discount' => 0.00, 'discount_type' => 0, + 'credit_limit' => 0, 'package_id' => NULL, 'points' => NULL, 'sales_tax_code_id' => NULL, diff --git a/application/models/Sale.php b/application/models/Sale.php index a58abc5d1..906d028a6 100644 --- a/application/models/Sale.php +++ b/application/models/Sale.php @@ -1115,7 +1115,7 @@ class Sale extends CI_Model } /** - * Creates sales temporary dimentional table + * Creates sales temporary dimensional table * We create a temp table that allows us to do easy report/sales queries */ public function create_temp_table(array $inputs) diff --git a/application/models/reports/Detailed_sales.php b/application/models/reports/Detailed_sales.php index f49dd556c..61a5e3b70 100644 --- a/application/models/reports/Detailed_sales.php +++ b/application/models/reports/Detailed_sales.php @@ -86,6 +86,7 @@ class Detailed_sales extends Report SUM(subtotal) AS subtotal, SUM(tax) AS tax, SUM(total) AS total, + SUM(CASE WHEN (total - sale_payment_amount) > 0 THEN (total - sale_payment_amount) ELSE 0 END) AS due, SUM(cost) AS cost, SUM(profit) AS profit, MAX(payment_type) AS payment_type, @@ -114,6 +115,14 @@ class Detailed_sales extends Report $this->db->or_where('sale_type', SALE_TYPE_INVOICE); $this->db->group_end(); } + elseif($inputs['sale_type'] == 'due') + { + $this->db->where('sale_status', COMPLETED); + $this->db->group_start(); + $this->db->where('sale_type', SALE_TYPE_POS); + $this->db->or_where('sale_type', SALE_TYPE_INVOICE); + $this->db->group_end(); + } elseif($inputs['sale_type'] == 'quotes') { $this->db->where('sale_status', SUSPENDED); @@ -135,6 +144,10 @@ class Detailed_sales extends Report } $this->db->group_by('sale_id'); + if($inputs['sale_type'] == 'due') + { + $this->db->having('due > 0'); + } $this->db->order_by('MAX(sale_date)'); $data = array(); diff --git a/application/models/reports/Summary_payments.php b/application/models/reports/Summary_payments.php index b2eda838b..2df4a95a2 100644 --- a/application/models/reports/Summary_payments.php +++ b/application/models/reports/Summary_payments.php @@ -121,9 +121,15 @@ class Summary_payments extends Summary_report { $decimals = totals_decimals(); - $trans_amount = 'ROUND(SUM(CASE WHEN sales_items.discount_type = ' . PERCENT - . ' THEN sales_items.item_unit_price * sales_items.quantity_purchased * (1 - sales_items.discount / 100) ' - . 'ELSE sales_items.item_unit_price * sales_items.quantity_purchased - sales_items.discount END), ' . $decimals . ') AS trans_amount'; +// Replace the following +// $trans_amount = 'ROUND(SUM(CASE WHEN sales_items.discount_type = ' . PERCENT +// . ' THEN sales_items.item_unit_price * sales_items.quantity_purchased * (1 - sales_items.discount / 100) ' +// . 'ELSE sales_items.item_unit_price * sales_items.quantity_purchased - sales_items.discount END), ' . $decimals . ') AS trans_amount'; +// With the following + $trans_amount = 'SUM(CASE WHEN sales_items.discount_type = ' . PERCENT + . " THEN sales_items.quantity_purchased * sales_items.item_unit_price - ROUND(sales_items.quantity_purchased * sales_items.item_unit_price * sales_items.discount / 100, $decimals) " + . 'ELSE sales_items.quantity_purchased * (sales_items.item_unit_price - sales_items.discount) END) AS trans_amount'; + $this->db->query('CREATE TEMPORARY TABLE IF NOT EXISTS ' . $this->db->dbprefix('sumpay_taxes_temp') . ' (INDEX(sale_id)) ENGINE=MEMORY diff --git a/application/models/reports/Summary_taxes.php b/application/models/reports/Summary_taxes.php index 9ae838306..c6d78c8bc 100644 --- a/application/models/reports/Summary_taxes.php +++ b/application/models/reports/Summary_taxes.php @@ -40,19 +40,44 @@ class Summary_taxes extends Summary_report { $where .= 'AND sale_time BETWEEN ' . $this->db->escape(rawurldecode($inputs['start_date'])) . ' AND ' . $this->db->escape(rawurldecode($inputs['end_date'])); } +// Replace the following +// if($this->config->item('tax_included')) +// { +// $sale_total = '(CASE WHEN sales_items.discount_type = ' . PERCENT . ' THEN sales_items.item_unit_price * sales_items.quantity_purchased * (1 - sales_items.discount / 100) ELSE sales_items.item_unit_price * sales_items.quantity_purchased - sales_items.discount END)'; +// $sale_subtotal = '(CASE WHEN sales_items.discount_type = ' . PERCENT . ' THEN sales_items.item_unit_price * sales_items.quantity_purchased * (1 - sales_items.discount / 100) ELSE sales_items.item_unit_price * sales_items.quantity_purchased - sales_items.discount END * (100 / (100 + sales_items_taxes.percent)))'; +// } +// else +// { +// $sale_total = '(CASE WHEN sales_items.discount_type = ' . PERCENT . ' THEN sales_items.item_unit_price * sales_items.quantity_purchased * (1 - sales_items.discount / 100) ELSE sales_items.item_unit_price * sales_items.quantity_purchased - sales_items.discount END * (1 + (sales_items_taxes.percent / 100)))'; +// $sale_subtotal = '(CASE WHEN sales_items.discount_type = ' . PERCENT . ' THEN sales_items.item_unit_price * sales_items.quantity_purchased * (1 - sales_items.discount / 100) ELSE sales_items.item_unit_price * sales_items.quantity_purchased - sales_items.discount END)'; +// } +// +// $decimals = totals_decimals(); +// With the following + $decimals = totals_decimals(); if($this->config->item('tax_included')) { - $sale_total = '(CASE WHEN sales_items.discount_type = ' . PERCENT . ' THEN sales_items.item_unit_price * sales_items.quantity_purchased * (1 - sales_items.discount / 100) ELSE sales_items.item_unit_price * sales_items.quantity_purchased - sales_items.discount END)'; - $sale_subtotal = '(CASE WHEN sales_items.discount_type = ' . PERCENT . ' THEN sales_items.item_unit_price * sales_items.quantity_purchased * (1 - sales_items.discount / 100) ELSE sales_items.item_unit_price * sales_items.quantity_purchased - sales_items.discount END * (100 / (100 + sales_items_taxes.percent)))'; + $sale_total = '(CASE WHEN sales_items.discount_type = ' . PERCENT + . " THEN sales_items.quantity_purchased * sales_items.item_unit_price - ROUND(sales_items.quantity_purchased * sales_items.item_unit_price * sales_items.discount / 100, $decimals) " + . 'ELSE sales_items.quantity_purchased * (sales_items.item_unit_price - sales_items.discount) END)'; + + $sale_subtotal = '(CASE WHEN sales_items.discount_type = ' . PERCENT + . " THEN sales_items.quantity_purchased * sales_items.item_unit_price - ROUND(sales_items.quantity_purchased * sales_items.item_unit_price * sales_items.discount / 100, $decimals) " + . 'ELSE sales_items.quantity_purchased * (sales_items.item_unit_price - sales_items.discount) END * (100 / (100 + sales_items_taxes.percent)))'; + } else { - $sale_total = '(CASE WHEN sales_items.discount_type = ' . PERCENT . ' THEN sales_items.item_unit_price * sales_items.quantity_purchased * (1 - sales_items.discount / 100) ELSE sales_items.item_unit_price * sales_items.quantity_purchased - sales_items.discount END * (1 + (sales_items_taxes.percent / 100)))'; - $sale_subtotal = '(CASE WHEN sales_items.discount_type = ' . PERCENT . ' THEN sales_items.item_unit_price * sales_items.quantity_purchased * (1 - sales_items.discount / 100) ELSE sales_items.item_unit_price * sales_items.quantity_purchased - sales_items.discount END)'; - } + $sale_total = '(CASE WHEN sales_items.discount_type = ' . PERCENT + . " THEN sales_items.quantity_purchased * sales_items.item_unit_price - ROUND(sales_items.quantity_purchased * sales_items.item_unit_price * sales_items.discount / 100, $decimals) " + . 'ELSE sales_items.quantity_purchased * (sales_items.item_unit_price - sales_items.discount) END * (100 / (100 + sales_items_taxes.percent)) * (1 + (sales_items_taxes.percent / 100)))'; - $decimals = totals_decimals(); + $sale_subtotal = '(CASE WHEN sales_items.discount_type = ' . PERCENT + . " THEN sales_items.quantity_purchased * sales_items.item_unit_price - ROUND(sales_items.quantity_purchased * sales_items.item_unit_price * sales_items.discount / 100, $decimals) " + . 'ELSE sales_items.quantity_purchased * (sales_items.item_unit_price - sales_items.discount) END)'; + } +// End of "with the following" $query = $this->db->query("SELECT percent, count(*) AS count, ROUND(SUM(subtotal), $decimals) AS subtotal, ROUND(SUM(tax), $decimals) AS tax, ROUND(SUM(total), $decimals) AS total FROM ( diff --git a/application/views/customers/form.php b/application/views/customers/form.php index edf841977..d945af03f 100644 --- a/application/views/customers/form.php +++ b/application/views/customers/form.php @@ -80,6 +80,21 @@ +
+ lang->line('customers_credit_limit'), 'credit_limit', array('class' => 'control-label col-xs-3')); ?> +
+
+ 'credit_limit', + 'id'=>'credit_limit', + 'class'=>'form-control input-sm', + 'onClick'=>'this.select();', + 'value'=>$person_info->credit_limit) + ); ?> +
+
+
+
lang->line('customers_company_name'), 'company_name', array('class' => 'control-label col-xs-3')); ?>
@@ -227,7 +242,28 @@
- + +
+ lang->line('customers_balance_due'), 'total', array('class' => 'control-label col-xs-3')); ?> +
+
+ + config->item('currency_symbol'); ?> + + 'balance_due', + 'id'=>'balance_due', + 'class'=>'form-control input-sm', + 'value'=>to_currency_no_money($stats->balance_due), + 'disabled'=>'') + ); ?> + + config->item('currency_symbol'); ?> + +
+
+
+
lang->line('customers_max'), 'max', array('class' => 'control-label col-xs-3')); ?>