From c710ec938f3aabafc53fa43ff6c9a592bbb8074c Mon Sep 17 00:00:00 2001 From: Steve Ireland Date: Sun, 30 Apr 2017 11:24:58 -0400 Subject: [PATCH] Sales tax history migration --- application/controllers/Config.php | 51 ++++++++++- application/language/en/config_lang.php | 4 + application/libraries/Tax_lib.php | 92 ++++++++++++++------ application/models/Sale.php | 65 +++++++++++++- application/views/configs/general_config.php | 26 +++++- database/3.0.2_to_3.1.0.sql | 5 ++ database/database.sql | 4 +- database/tables.sql | 5 +- 8 files changed, 215 insertions(+), 37 deletions(-) diff --git a/application/controllers/Config.php b/application/controllers/Config.php index 2544010b6..0dce618ae 100644 --- a/application/controllers/Config.php +++ b/application/controllers/Config.php @@ -10,6 +10,7 @@ class Config extends Secure_Controller $this->load->library('barcode_lib'); $this->load->library('sale_lib'); + $this->load->library('tax_lib'); } /* @@ -267,6 +268,9 @@ class Config extends Secure_Controller public function save_general() { + $migrate_sales_history = $this->input->post('migrate_sales_history') != NULL; + $migrate_sales_history_block = $this->input->post('migrate_sales_history_block'); + $batch_save_data = array( 'theme' => $this->input->post('theme'), 'default_tax_1_rate' => parse_decimals($this->input->post('default_tax_1_rate')), @@ -275,6 +279,8 @@ class Config extends Secure_Controller 'default_tax_2_name' => $this->input->post('default_tax_2_name'), 'tax_included' => $this->input->post('tax_included') != NULL, 'customer_sales_tax_support' => $this->input->post('customer_sales_tax_support') != NULL, + 'migrate_sales_history' => $migrate_sales_history, + 'migrate_sales_history_block' => $migrate_sales_history_block, 'default_origin_tax_code' => $this->input->post('default_origin_tax_code'), 'receiving_calculate_average_price' => $this->input->post('receiving_calculate_average_price') != NULL, 'lines_per_page' => $this->input->post('lines_per_page'), @@ -298,10 +304,47 @@ class Config extends Secure_Controller $result = $this->Appconfig->batch_save($batch_save_data); $success = $result ? TRUE : FALSE; - echo json_encode(array( - 'success' => $success, - 'message' => $this->lang->line('config_saved_' . ($success ? '' : 'un') . 'successfully') - )); + if($success && $migrate_sales_history) + { + $number_of_unmigrated = $this->Sale->get_count_of_unmigrated(); + if ($number_of_unmigrated > 0 && $migrate_sales_history_block > 0) + { + $unmigrated_invoices = $this->Sale->get_unmigrated($migrate_sales_history_block)->result_array(); + + foreach($unmigrated_invoices as $key=>$unmigrated_invoice) + { + $this->tax_lib->upgrade_tax_history_for_sale($unmigrated_invoice['sale_id']); + } + + if($migrate_sales_history_block > $number_of_unmigrated) + { + $migrate_sales_history_block = $number_of_unmigrated; + } + + $number_of_unmigrated = $this->Sale->get_count_of_unmigrated(); + + echo json_encode(array( + 'success' => $success, + 'message' => $this->lang->line('config_saved_with_migration').' '.$migrate_sales_history_block.' / '.$number_of_unmigrated.' '.$this->lang->line('config_migrate_remaining') + )); + + } + else + { + echo json_encode(array( + 'success' => $success, + 'message' => $this->lang->line('config_saved_' . ($success ? '' : 'un') . 'successfully') + )); + } + } + else + { + echo json_encode(array( + 'success' => $success, + 'message' => $this->lang->line('config_saved_' . ($success ? '' : 'un') . 'successfully') + )); + } + } public function check_number_locale() diff --git a/application/language/en/config_lang.php b/application/language/en/config_lang.php index d5e7a152e..0ff09c371 100644 --- a/application/language/en/config_lang.php +++ b/application/language/en/config_lang.php @@ -154,6 +154,10 @@ $lang["config_mailchimp_key_successfully"] = "Valid API Key"; $lang["config_mailchimp_key_unsuccessfully"] = "Invalid API Key"; $lang["config_message"] = "Message"; $lang["config_message_configuration"] = "Message Configuration"; +$lang["config_migrate_remaining"] = "remaining to be migrated"; +$lang["config_migrate_sales_history"] = "Migrate sales history on Save"; +$lang["config_migrate_sales_history_block"] = "Sales to migrate per Save"; +$lang["config_saved_with_migration"] = "Configuration saved and the number of sales migrated is "; $lang["config_msg_msg"] = "Saved Text Message"; $lang["config_msg_msg_placeholder"] = "If you wish to use a SMS template save your message here. Otherwise leave the box blank."; $lang["config_msg_pwd"] = "SMS-API Password"; diff --git a/application/libraries/Tax_lib.php b/application/libraries/Tax_lib.php index 0718dbb9d..e8ea75456 100644 --- a/application/libraries/Tax_lib.php +++ b/application/libraries/Tax_lib.php @@ -89,35 +89,32 @@ class Tax_lib $tax_group_index = $this->clean('X'.$tax_group); - if ($item_tax_amount != 0) + if(!array_key_exists($tax_group_index, $sales_taxes)) { - if(!array_key_exists($tax_group_index, $sales_taxes)) - { - $insertkey = $tax_group_index; + $insertkey = $tax_group_index; - $sales_tax = array($insertkey => array( - 'sale_id' => $sale_id, - 'tax_type' => $tax_type, - 'tax_group' => $tax_group, - 'sale_tax_basis' => $tax_basis, - 'sale_tax_amount' => $item_tax_amount, - 'print_sequence' => $tax_group_sequence, - 'name' => $name, - 'tax_rate' => $tax_rate, - 'sales_tax_code' => $tax_code, - 'rounding_code' => $rounding_code - )); + $sales_tax = array($insertkey => array( + 'sale_id' => $sale_id, + 'tax_type' => $tax_type, + 'tax_group' => $tax_group, + 'sale_tax_basis' => $tax_basis, + 'sale_tax_amount' => $item_tax_amount, + 'print_sequence' => $tax_group_sequence, + 'name' => $name, + 'tax_rate' => $tax_rate, + 'sales_tax_code' => $tax_code, + 'rounding_code' => $rounding_code + )); - //add to existing array - $sales_taxes += $sales_tax; - } - else - { - // Important ... the sales amounts are accumulated for the group at the maximum configurable scale value of 4 - // but the scale will in reality be the scale specified by the tax_decimal configuration value used for sales_items_taxes - $sales_taxes[$tax_group_index]['sale_tax_basis'] = bcadd($sales_taxes[$tax_group_index]['sale_tax_basis'], $tax_basis, 4); - $sales_taxes[$tax_group_index]['sale_tax_amount'] = bcadd($sales_taxes[$tax_group_index]['sale_tax_amount'], $item_tax_amount, 4); - } + //add to existing array + $sales_taxes += $sales_tax; + } + else + { + // Important ... the sales amounts are accumulated for the group at the maximum configurable scale value of 4 + // but the scale will in reality be the scale specified by the tax_decimal configuration value used for sales_items_taxes + $sales_taxes[$tax_group_index]['sale_tax_basis'] = bcadd($sales_taxes[$tax_group_index]['sale_tax_basis'], $tax_basis, 4); + $sales_taxes[$tax_group_index]['sale_tax_amount'] = bcadd($sales_taxes[$tax_group_index]['sale_tax_amount'], $item_tax_amount, 4); } } @@ -318,6 +315,45 @@ class Tax_lib return preg_replace('/[^A-Za-z0-9\-]/', '', $string); // Removes special chars. } -} -?> + function upgrade_tax_history_for_sale($sale_id) + { + $tax_decimals = $this->CI->config->config['tax_decimals']; + $tax_included = $this->CI->config->config['tax_included']; + + if($tax_included) + { + $tax_type = Tax_lib::TAX_TYPE_VAT; + } + else + { + $tax_type = Tax_lib::TAX_TYPE_SALES; + } + + $sales_taxes = array(); + $tax_group_sequence = 0; + + $items = $this->CI->Sale->get_sale_items_for_migration($sale_id)->result_array(); + foreach($items as $item) + { + // This computes tax for each line item and adds it to the tax type total + $tax_group = (float)$item['percent'] . '% ' . $item['name']; + $tax_basis = $this->CI->sale_lib->get_item_total($item['quantity_purchased'], $item['item_unit_price'], $item['discount_percent'], TRUE); + $item_tax_amount = 0; + + if($tax_included) + { + $item_tax_amount = $this->CI->sale_lib->get_item_tax($item['quantity_purchased'], $item['item_unit_price'], $item['discount_percent'], $item['percent']); + } + else + { + $item_tax_amount = $this->get_sales_tax_for_amount($tax_basis, $item['percent'], '0', $tax_decimals); + } + $this->CI->Sale->update_sales_items_taxes_amount($sale_id, $item['line'], $item['name'], $item['percent'], $tax_type, $item_tax_amount); + $this->update_sales_taxes($sales_taxes, $tax_type, $tax_group, $item['percent'], $tax_basis, $item_tax_amount, $tax_group_sequence, '0', $sale_id, $item['name']); + $tax_group_sequence += 1; + } + $this->CI->Sale->save_sales_tax($sales_taxes); + } +} +?> \ No newline at end of file diff --git a/application/models/Sale.php b/application/models/Sale.php index b361407cd..87f9d4f5a 100644 --- a/application/models/Sale.php +++ b/application/models/Sale.php @@ -752,11 +752,14 @@ class Sale extends CI_Model } } - private function save_sales_tax(&$sales_taxes) + public function save_sales_tax(&$sales_taxes) { + error_log('>>>Sale.save_sales_tax started'.print_r($sales_taxes, TRUE)); foreach($sales_taxes as $line=>$sales_tax) { + error_log('>>>Sale.save_sales_tax $sales_tax - '.print_r($sales_tax, TRUE)); $this->db->insert('sales_taxes', $sales_tax); + error_log('>>>Sale.save_sales_tax sales_tax written'); } } @@ -1205,5 +1208,63 @@ class Sale extends CI_Model return $this->db->get(); } + + public function get_sale_items_for_migration($sale_id) + { + + $this->db->select('sales_items.sale_id as sale_id'); + $this->db->select('sales_items.line as line'); + $this->db->select('item_unit_price'); + $this->db->select('discount_percent'); + $this->db->select('quantity_purchased'); + $this->db->select('percent'); + $this->db->select('name'); + $this->db->from('sales_items as sales_items'); + $this->db->join('sales_items_taxes as sales_items_taxes', 'sales_items.sale_id = sales_items_taxes.sale_id and sales_items.line = sales_items_taxes.line'); + $this->db->where('sales_items.sale_id', $sale_id); + + return $this->db->get(); + } + + public function get_count_of_unmigrated() + { + $result = $this->db->query('SELECT COUNT(*) FROM(SELECT SIT.sale_id, ST.sale_id as sales_taxes_sale_id FROM ' + . $this->db->dbprefix('sales_items_taxes') + . ' as SIT LEFT JOIN ' + . $this->db->dbprefix('sales_taxes') + . ' as ST ON SIT.sale_id = ST.sale_id WHERE ST.sale_id is null GROUP BY SIT.sale_id, ST.sale_id' + . ' ORDER BY SIT.sale_id) as US')->result_array(); + + return $result[0]['COUNT(*)']; + } + + public function get_unmigrated($block_count) + { + + $this->db->select('SIT.sale_id'); + $this->db->select('ST.sale_id as sales_taxes_sale_id'); + $this->db->from('sales_items_taxes as SIT'); + $this->db->join('sales_taxes as ST','SIT.sale_id = ST.sale_id', 'left'); + $this->db->where('ST.sale_id is null'); + $this->db->group_by('SIT.sale_id'); + $this->db->group_by('ST.sale_id'); + $this->db->order_by('SIT.sale_id'); + $this->db->limit($block_count); + $query = $this->db->get(); + + return $query; + + } + + public function update_sales_items_taxes_amount($sale_id, $line, $name, $percent, $tax_type, $item_tax_amount) + { + error_log('>>>Sale.update_sales_items_taxes_amount '.$sale_id.', '.$line.', '.$name.', '.$percent.', '.$tax_type.', '.$item_tax_amount); + $this->db->where('sale_id', $sale_id); + $this->db->where('line', $line); + $this->db->where('name', $name); + $this->db->where('percent', $percent); + $this->db->update('sales_items_taxes', array('tax_type' => $tax_type, 'item_tax_amount' => $item_tax_amount)); + } + } -?> +?> \ No newline at end of file diff --git a/application/views/configs/general_config.php b/application/views/configs/general_config.php index 0c4ad8c25..c30d3a803 100644 --- a/application/views/configs/general_config.php +++ b/application/views/configs/general_config.php @@ -82,7 +82,31 @@ -
+ +
+ lang->line('config_migrate_sales_history'), 'migrate_sales_history', array('class' => 'control-label col-xs-2')); ?> +
+ 'migrate_sales_history', + 'id' => 'migrate_sales_history', + 'value' => 'migrate_sales_history', + 'checked'=>$this->config->item('migrate_sales_history'))); ?> +
+
+ +
+ lang->line('config_migrate_sales_history_block'), 'migrate_sales_history_block', array('class' => 'control-label col-xs-2')); ?> +
+ 'migrate_sales_history_block', + 'id' => 'migrate_sales_history_block', + 'class' => 'form-control input-sm required', + 'type' => 'number', + 'value'=>$this->config->item('migrate_sales_history_block'))); ?> +
+
+ +
lang->line('config_default_sales_discount'), 'default_sales_discount', array('class' => 'control-label col-xs-2 required')); ?>
diff --git a/database/3.0.2_to_3.1.0.sql b/database/3.0.2_to_3.1.0.sql index d9d6cebfa..4cdee1979 100644 --- a/database/3.0.2_to_3.1.0.sql +++ b/database/3.0.2_to_3.1.0.sql @@ -228,3 +228,8 @@ INSERT INTO `ospos_app_config` (`key`, `value`) VALUES ('giftcard_number', 'seri -- add option to print company name in receipt INSERT INTO `ospos_app_config` (`key`, `value`) VALUES ('receipt_show_company_name', '1'); + +-- add options to support sales tax history migration + +INSERT INTO `ospos_app_config` (`key`, `value`) VALUES ('migrate_sales_history', '0'); +INSERT INTO `ospos_app_config` (`key`, `value`) VALUES ('migrate_sales_history_block', '0'); diff --git a/database/database.sql b/database/database.sql index 116f52a1b..2e50e49d2 100644 --- a/database/database.sql +++ b/database/database.sql @@ -96,7 +96,9 @@ INSERT INTO `ospos_app_config` (`key`, `value`) VALUES ('default_origin_tax_code', ''), ('cash_decimals', '2'), ('financial_year', '1'), -('giftcard_number', 'series'); +('giftcard_number', 'series'), +('migrate_sales_history', '0'), +('migrate_sales_history_block', '0'); -- -------------------------------------------------------- diff --git a/database/tables.sql b/database/tables.sql index 43fecdf00..69c1ede31 100644 --- a/database/tables.sql +++ b/database/tables.sql @@ -96,7 +96,10 @@ INSERT INTO `ospos_app_config` (`key`, `value`) VALUES ('default_origin_tax_code', ''), ('cash_decimals', '2'), ('financial_year', '1'), -('giftcard_number', 'series'); +('giftcard_number', 'series'), +('migrate_sales_history', '0'), +('migrate_sales_history_block', '0'); + -- --------------------------------------------------------