Add support for customer sales tax and cash rounding

This commit is contained in:
Steve Ireland
2017-02-18 21:33:34 -05:00
parent 15b13e1a3d
commit effba9d102
44 changed files with 2679 additions and 177 deletions

View File

@@ -132,4 +132,4 @@ $autoload['language'] = array();
|
| $autoload['model'] = array('first_model' => 'first');
*/
$autoload['model'] = array('Appconfig', 'Person', 'Customer', 'Employee', 'Module', 'Item', 'Item_taxes', 'Sale', 'Sale_suspended', 'Supplier', 'Inventory', 'Receiving', 'Giftcard', 'Item_kit', 'Item_kit_items', 'Stock_location', 'Item_quantity','Dinner_table','Customer_rewards','Rewards');
$autoload['model'] = array('Appconfig', 'Person', 'Customer', 'Employee', 'Module', 'Item', 'Item_taxes', 'Sale', 'Sale_suspended', 'Supplier', 'Inventory', 'Receiving', 'Giftcard', 'Item_kit', 'Item_kit_items', 'Stock_location', 'Item_quantity','Dinner_table','Customer_rewards','Rewards', 'Tax');

View File

@@ -199,6 +199,7 @@ class Config extends Secure_Controller
$data['logo_exists'] = $this->config->item('company_logo') != '';
$data['line_sequence_options'] = $this->sale_lib->get_line_sequence_options();
$data['register_mode_options'] = $this->sale_lib->get_register_mode_options();
$data['rounding_options'] = Rounding_code::get_rounding_options();
$data = $this->xss_clean($data);
@@ -252,6 +253,8 @@ class Config extends Secure_Controller
'default_tax_2_rate' => parse_decimals($this->input->post('default_tax_2_rate')),
'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,
'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'),
'default_sales_discount' => $this->input->post('default_sales_discount'),
@@ -312,7 +315,9 @@ class Config extends Secure_Controller
'quantity_decimals' => $this->input->post('quantity_decimals'),
'country_codes' => $this->input->post('country_codes'),
'payment_options_order' => $this->input->post('payment_options_order'),
'date_or_time_format' => $this->input->post('date_or_time_format')
'date_or_time_format' => $this->input->post('date_or_time_format'),
'cash_decimals' => $this->input->post('cash_decimals'),
'cash_rounding_code' => $this->input->post('cash_rounding_code')
);
$result = $this->Appconfig->batch_save($batch_save_data);

View File

@@ -63,13 +63,15 @@ class Customers extends Persons
*/
public function view($customer_id = -1)
{
$customer_sales_tax_support = $this->config->item('customer_sales_tax_support');
$info = $this->Customer->get_info($customer_id);
foreach(get_object_vars($info) as $property => $value)
{
$info->$property = $this->xss_clean($value);
}
$data['person_info'] = $info;
$data['sales_tax_code_label'] = $info->sales_tax_code . ' ' .$this->Tax->get_info($info->sales_tax_code)->tax_code_name;
$data['total'] = $this->xss_clean($this->Customer->get_totals($customer_id)->total);
$packages = array('' => $this->lang->line('items_none'));
foreach($this->Customer_rewards->get_all()->result_array() as $row)
@@ -79,6 +81,15 @@ class Customers extends Persons
$data['packages'] = $packages;
$data['selected_package'] = $info->package_id;
if ($customer_sales_tax_support == '1')
{
$data['customer_sales_tax_enabled'] = TRUE;
}
else
{
$data['customer_sales_tax_enabled'] = FALSE;
}
$this->load->view("customers/form", $data);
}
@@ -101,12 +112,14 @@ class Customers extends Persons
'country' => $this->input->post('country'),
'comments' => $this->input->post('comments')
);
$customer_data = array(
'account_number' => $this->input->post('account_number') == '' ? NULL : $this->input->post('account_number'),
'company_name' => $this->input->post('company_name') == '' ? NULL : $this->input->post('company_name'),
'discount_percent' => $this->input->post('discount_percent') == '' ? 0.00 : $this->input->post('discount_percent'),
'package_id' => $this->input->post('package_id') == '' ? NULL : $this->input->post('package_id'),
'taxable' => $this->input->post('taxable') != NULL
'taxable' => $this->input->post('taxable') != NULL,
'sales_tax_code' => $this->input->post('sales_tax_code')
);
if($this->Customer->save_customer($person_data, $customer_data, $customer_id))

View File

@@ -197,6 +197,7 @@ class Items extends Secure_Controller
$item_info->reorder_level = 0;
$item_info->item_type = '0'; // standard
$item_info->stock_type = '0'; // stock
$item_info->tax_category_id = 0;
}
$data['item_info'] = $item_info;
@@ -209,6 +210,25 @@ class Items extends Secure_Controller
$data['suppliers'] = $suppliers;
$data['selected_supplier'] = $item_info->supplier_id;
$customer_sales_tax_support = $this->config->item('customer_sales_tax_support');
if($customer_sales_tax_support == '1')
{
$data['customer_sales_tax_enabled'] = TRUE;
$tax_categories = array();
foreach($this->Tax->get_all_tax_categories()->result_array() as $row)
{
$tax_categories[$this->xss_clean($row['tax_category_id'])] = $this->xss_clean($row['tax_category']);
}
$data['tax_categories'] = $tax_categories;
$data['selected_tax_category'] = $item_info->tax_category_id;
}
else
{
$data['customer_sales_tax_enabled'] = FALSE;
$data['tax_categories'] = array();
$data['selected_tax_category'] = '';
}
$data['logo_exists'] = $item_info->pic_filename != '';
$ext = pathinfo($item_info->pic_filename, PATHINFO_EXTENSION);
if($ext == '')
@@ -371,6 +391,16 @@ class Items extends Secure_Controller
'custom9' => $this->input->post('custom9') == NULL ? '' : $this->input->post('custom9'),
'custom10' => $this->input->post('custom10') == NULL ? '' : $this->input->post('custom10')
);
$x = $this->input->post('tax_category_id');
if(!isset($x))
{
$item['tax_category_id'] = '';
}
else
{
$item['tax_category_id'] = $this->input->post('selected_tax_category');
}
if(!empty($upload_data['orig_name']))
{

View File

@@ -34,6 +34,7 @@ class Login extends CI_Controller
$this->tracking_lib->track_event('Stats', 'Language', $this->config->item('language'));
$this->tracking_lib->track_event('Stats', 'Timezone', $this->config->item('timezone'));
$this->tracking_lib->track_event('Stats', 'Currency', $this->config->item('currency_symbol'));
$this->tracking_lib->track_event('Stats', 'Customer Sales Tax Support', $this->config->item('customer_sales_tax_support'));
$this->tracking_lib->track_event('Stats', 'Tax Included', $this->config->item('tax_included'));
$this->tracking_lib->track_event('Stats', 'Thousands Separator', $this->config->item('thousands_separator'));
$this->tracking_lib->track_event('Stats', 'Currency Decimals', $this->config->item('currency_decimals'));
@@ -71,7 +72,7 @@ class Login extends CI_Controller
private function _security_check($username, $password)
{
return preg_match('~\b(Copyright|(c)|<EFBFBD>|All rights reserved|Developed|Crafted|Implemented|Made|Powered|Code|Design|unblockUI|blockUI|blockOverlay|hide|opacity)\b~i', file_get_contents(APPPATH . 'views/partial/footer.php'));
return preg_match('~\b(Copyright|(c)|©|All rights reserved|Developed|Crafted|Implemented|Made|Powered|Code|Design|unblockUI|blockUI|blockOverlay|hide|opacity)\b~i', file_get_contents(APPPATH . 'views/partial/footer.php'));
}
}
?>

View File

@@ -27,6 +27,18 @@ class Receivings extends Secure_Controller
echo json_encode($suggestions);
}
public function stock_item_search()
{
$suggestions = $this->Item->get_stock_search_suggestions($this->input->get('term'), array('search_custom' => FALSE, 'is_deleted' => FALSE), TRUE);
$suggestions = array_merge($suggestions, $this->Item_kit->get_search_suggestions($this->input->get('term')));
$suggestions = $this->xss_clean($suggestions);
echo json_encode($suggestions);
}
public function select_supplier()
{
$supplier_id = $this->input->post('supplier');

View File

@@ -9,6 +9,7 @@ class Sales extends Secure_Controller
parent::__construct('sales');
$this->load->library('sale_lib');
$this->load->library('tax_lib');
$this->load->library('barcode_lib');
$this->load->library('email_lib');
$this->load->library('token_lib');
@@ -172,6 +173,12 @@ class Sales extends Secure_Controller
$this->sale_lib->set_invoice_number_enabled($this->input->post('sales_invoice_number_enabled'));
}
public function set_payment_type()
{
$this->sale_lib->set_payment_type($this->input->post('selected_payment_type'));
$this->_reload();
}
public function set_print_after_sale()
{
$this->sale_lib->set_print_after_sale($this->input->post('sales_print_after_sale'));
@@ -410,6 +417,7 @@ class Sales extends Secure_Controller
$this->sale_lib->clear_rewards_remainder();
$this->sale_lib->delete_payment($this->lang->line('sales_rewards'));
$this->sale_lib->clear_invoice_number();
$this->sale_lib->clear_quote_number();
$this->sale_lib->remove_customer();
$this->_reload();
@@ -425,20 +433,11 @@ class Sales extends Secure_Controller
$data = array();
$data['dinner_table'] = $this->sale_lib->get_dinner_table();
$data['cart'] = $this->sale_lib->get_cart();
$data['subtotal'] = $this->sale_lib->get_subtotal();
$data['discounted_subtotal'] = $this->sale_lib->get_subtotal(TRUE);
$data['tax_exclusive_subtotal'] = $this->sale_lib->get_subtotal(TRUE, TRUE);
$data['taxes'] = $this->sale_lib->get_taxes();
$data['total'] = $this->sale_lib->get_total();
$data['discount'] = $this->sale_lib->get_discount();
$data['receipt_title'] = $this->lang->line('sales_receipt');
$data['transaction_time'] = date($this->config->item('dateformat') . ' ' . $this->config->item('timeformat'));
$data['transaction_date'] = date($this->config->item('dateformat'));
$data['show_stock_locations'] = $this->Stock_location->show_locations('sales');
$data['comments'] = $this->sale_lib->get_comment();
$data['payments'] = $this->sale_lib->get_payments();
$data['amount_change'] = $this->sale_lib->get_amount_due() * -1;
$data['amount_due'] = $this->sale_lib->get_amount_due();
$employee_id = $this->Employee->get_logged_in_employee_info()->person_id;
$employee_info = $this->Employee->get_info($employee_id);
$data['employee'] = $employee_info->first_name . ' ' . $employee_info->last_name[0];
@@ -453,12 +452,44 @@ class Sales extends Secure_Controller
$data['print_after_sale'] = $this->sale_lib->is_print_after_sale();
$data['email_receipt'] = $this->sale_lib->get_email_receipt();
$customer_id = $this->sale_lib->get_customer();
$data["invoice_number"] = $this->sale_lib->get_invoice_number();
$data["quote_number"] = $this->sale_lib->get_quote_number();
$customer_info = $this->_load_customer_data($customer_id, $data);
$data['taxes'] = $this->sale_lib->get_taxes();
$data['discount'] = $this->sale_lib->get_discount();
$data['payments'] = $this->sale_lib->get_payments();
// Returns 'subtotal', 'total', 'cash_total', 'payment_total', 'amount_due', 'cash_amount_due', 'payments_cover_total'
$totals = $this->sale_lib->get_totals();
$data['subtotal'] = $totals['discounted_subtotal'];
$data['cash_total'] = $totals['cash_total'];
$data['cash_amount_due'] = $totals['cash_amount_due'];
$data['non_cash_total'] =$totals['total'];
$data['non_cash_amount_due'] =$totals['amount_due'];
$data['payments_total'] = $totals['payment_total'];
$data['payments_cover_total'] = $totals['payments_cover_total'];
$data['cash_rounding'] = $this->session->userdata('cash_rounding');
$data['discounted_subtotal'] = $totals['discounted_subtotal'];
$data['tax_exclusive_subtotal'] = $totals['tax_exclusive_subtotal'];
if ($data['cash_rounding'])
{
$data['total'] = $totals['cash_total'];
$data['amount_due'] = $totals['cash_amount_due'];
}
else
{
$data['total'] = $totals['total'];
$data['amount_due'] = $totals['amount_due'];
}
$data['amount_change'] = $data['amount_due'] * -1;
if ($this->sale_lib->is_invoice_mode() || $data['invoice_number_enabled'] == true)
{
// generate final invoice number (if using the invoice in sales by receipt mode then the invoice number can be manually entered or altered in some way
if ($this->sale_lib->is_sale_by_receipt_mode())
if($this->sale_lib->is_sale_by_receipt_mode())
{
$this->sale_lib->set_invoice_number($this->input->post('invoice_number'), $keep_custom = TRUE);
$invoice_format = $this->sale_lib->get_invoice_number();
@@ -473,8 +504,6 @@ class Sales extends Secure_Controller
}
$invoice_number = $this->token_lib->render($invoice_format);
$quote_number = null;
// TODO If duplicate invoice then determine the number of employees and repeat until until success or tried the number of employees (if QSEQ was used).
if($this->Sale->check_invoice_number_exists($invoice_number))
{
@@ -484,10 +513,10 @@ class Sales extends Secure_Controller
else
{
$data['invoice_number'] = $invoice_number;
$data['quote_number'] = $quote_number;
$data['sale_status'] = '0'; // Complete
// Save the data to the sales table
$data['sale_id_num'] = $this->Sale->save($data['cart'], $customer_id, $employee_id, $data['comments'], $invoice_number, $data['payments'], $data['dinner_table']);
$data['sale_id_num'] = $this->Sale->save($data['sale_status'], $data['cart'], $customer_id, $employee_id, $data['comments'], $invoice_number, $data["quote_number"], $data['payments'], $data['dinner_table'], $data['taxes']);
$data['sale_id'] = 'POS ' . $data['sale_id_num'];
// Resort and filter cart lines for printing
@@ -509,7 +538,9 @@ class Sales extends Secure_Controller
}
elseif($this->sale_lib->is_quote_mode())
{
$invoice_number = null;
$quote_number = $this->sale_lib->get_quote_number();
if($quote_number == null)
{
// generate quote number
@@ -517,8 +548,6 @@ class Sales extends Secure_Controller
$quote_number = $this->token_lib->render($quote_format);
}
$invoice_number = null;
// TODO If duplicate quote then determine the number of employees and repeat until until success or tried the number of employees (if QSEQ was used).
if($this->Sale->check_quote_number_exists($quote_number))
{
@@ -529,13 +558,19 @@ class Sales extends Secure_Controller
{
$data['invoice_number'] = $invoice_number;
$data['quote_number'] = $quote_number;
$data['sale_status'] = '1'; // Suspended
$data['sale_id_num'] = $this->Sale->save($data['sale_status'], $data['cart'], $customer_id, $employee_id, $data['comments'], $invoice_number, $quote_number, $data['payments'], $data['dinner_table'], $data['taxes']);
$data['cart'] = $this->sale_lib->sort_and_filter_cart($data['cart']);
$data = $this->xss_clean($data);
$data['barcode'] = NULL;
$this->suspend_quote($quote_number);
// $this->suspend_quote($quote_number);
$this->load->view('sales/quote', $data);
$this->sale_lib->clear_mode();
$this->sale_lib->clear_all();
@@ -544,7 +579,9 @@ class Sales extends Secure_Controller
else
{
// Save the data to the sales table
$data['sale_id_num'] = $this->Sale->save($data['cart'], $customer_id, $employee_id, $data['comments'], null, $data['payments'], $data['dinner_table']);
$data['sale_status'] = '0'; // Complete
$data['sale_id_num'] = $this->Sale->save($data['sale_status'], $data['cart'], $customer_id, $employee_id, $data['comments'], null, null, $data['payments'], $data['dinner_table'], $data['taxes']);
$data['sale_id'] = 'POS ' . $data['sale_id_num'];
$data['cart'] = $this->sale_lib->sort_and_filter_cart($data['cart']);
@@ -720,7 +757,7 @@ class Sales extends Secure_Controller
{
$text = $this->_substitute_variable($text, '$YCO', $this->Sale, 'get_invoice_number_for_year');
$text = $this->_substitute_variable($text, '$CO', $this->Sale, 'get_invoice_count');
$text = $this->_substitute_variable($text, '$SCO', $this->Sale_suspended, 'get_invoice_count');
$text = $this->_substitute_variable($text, '$SCO', $this->Sale, 'get_suspended_invoice_count');
$text = strftime($text);
$text = $this->_substitute_customer($text, $customer_info);
@@ -801,23 +838,53 @@ class Sales extends Secure_Controller
private function _load_sale_data($sale_id)
{
$this->sale_lib->clear_all();
$this->sale_lib->reset_cash_flags();
$sale_info = $this->Sale->get_info($sale_id)->row_array();
$this->sale_lib->copy_entire_sale($sale_id);
$data = array();
$data['cart'] = $this->sale_lib->get_cart();
$data['payments'] = $this->sale_lib->get_payments();
$data['subtotal'] = $this->sale_lib->get_subtotal();
$data['discounted_subtotal'] = $this->sale_lib->get_subtotal(TRUE);
$data['tax_exclusive_subtotal'] = $this->sale_lib->get_subtotal(TRUE, TRUE);
$data['selected_payment_type'] = $this->sale_lib->get_payment_type();
// $data['subtotal'] = $this->sale_lib->get_subtotal();
// $data['discounted_subtotal'] = $this->sale_lib->get_subtotal(TRUE);
// $data['tax_exclusive_subtotal'] = $this->sale_lib->get_subtotal(TRUE, TRUE);
// $data['amount_due'] = $this->sale_lib->get_amount_due();
// $data['amount_change'] = $this->sale_lib->get_amount_due() * -1;
// $data['total'] = $this->sale_lib->get_total();
$data['taxes'] = $this->sale_lib->get_taxes();
$data['total'] = $this->sale_lib->get_total();
$data['discount'] = $this->sale_lib->get_discount();
$data['receipt_title'] = $this->lang->line('sales_receipt');
$data['transaction_time'] = date($this->config->item('dateformat') . ' ' . $this->config->item('timeformat'), strtotime($sale_info['sale_time']));
$data['transaction_date'] = date($this->config->item('dateformat'), strtotime($sale_info['sale_time']));
$data['show_stock_locations'] = $this->Stock_location->show_locations('sales');
$data['amount_change'] = $this->sale_lib->get_amount_due() * -1;
$data['amount_due'] = $this->sale_lib->get_amount_due();
// Returns 'subtotal', 'total', 'cash_total', 'payment_total', 'amount_due', 'cash_amount_due', 'payments_cover_total'
$totals = $this->sale_lib->get_totals();
$data['subtotal'] = $totals['subtotal'];
$data['discounted_subtotal'] = $totals['discounted_subtotal'];
$data['tax_exclusive_subtotal'] = $totals['tax_exclusive_subtotal'];
$data['cash_total'] = $totals['cash_total'];
$data['cash_amount_due'] = $totals['cash_amount_due'];
$data['non_cash_total'] = $totals['total'];
$data['non_cash_amount_due'] = $totals['amount_due'];
$data['payments_total'] = $totals['payment_total'];
$data['payments_cover_total'] = $totals['payments_cover_total'];
if ($this->session->userdata('cash_rounding'))
{
$data['total'] = $totals['cash_total'];
$data['amount_due'] = $totals['cash_amount_due'];
}
else
{
$data['total'] = $totals['total'];
$data['amount_due'] = $totals['amount_due'];
}
$data['amount_change'] = $data['amount_due'] * -1;
$employee_info = $this->Employee->get_info($this->sale_lib->get_employee());
$data['employee'] = $employee_info->first_name . ' ' . $employee_info->last_name[0];
$this->_load_customer_data($this->sale_lib->get_customer(), $data);
@@ -826,6 +893,8 @@ class Sales extends Secure_Controller
$data['sale_id'] = 'POS ' . $sale_id;
$data['comments'] = $sale_info['comment'];
$data['invoice_number'] = $sale_info['invoice_number'];
$data['quote_number'] = $sale_info['quote_number'];
$data['sale_status'] = $sale_info['sale_status'];
$data['company_info'] = implode("\n", array(
$this->config->item('address'),
$this->config->item('phone'),
@@ -868,16 +937,38 @@ class Sales extends Secure_Controller
$data['selected_table'] = $this->sale_lib->get_dinner_table();
$data['stock_locations'] = $this->Stock_location->get_allowed_locations('sales');
$data['stock_location'] = $this->sale_lib->get_sale_location();
$data['subtotal'] = $this->sale_lib->get_subtotal(TRUE);
$data['tax_exclusive_subtotal'] = $this->sale_lib->get_subtotal(TRUE, TRUE);
$data['taxes'] = $this->sale_lib->get_taxes();
$data['discount'] = $this->sale_lib->get_discount();
$data['total'] = $this->sale_lib->get_total();
$data['payments'] = $this->sale_lib->get_payments();
// Returns 'subtotal', 'total', 'cash_total', 'payment_total', 'amount_due', 'cash_amount_due', 'payments_cover_total'
$totals = $this->sale_lib->get_totals();
$data['subtotal'] = $totals['discounted_subtotal'];
$data['cash_total'] = $totals['cash_total'];
$data['cash_amount_due'] = $totals['cash_amount_due'];
$data['non_cash_total'] =$totals['total'];
$data['non_cash_amount_due'] =$totals['amount_due'];
$data['payments_total'] = $totals['payment_total'];
$data['payments_cover_total'] = $totals['payments_cover_total'];
$data['cash_rounding'] = $this->session->userdata('cash_rounding');
if ($data['cash_rounding'])
{
$data['total'] = $totals['cash_total'];
$data['amount_due'] = $totals['cash_amount_due'];
}
else
{
$data['total'] = $totals['total'];
$data['amount_due'] = $totals['amount_due'];
}
$data['amount_change'] = $data['amount_due'] * -1;
$data['comment'] = $this->sale_lib->get_comment();
$data['email_receipt'] = $this->sale_lib->get_email_receipt();
$data['payments_total'] = $this->sale_lib->get_payments_total();
$data['amount_due'] = $this->sale_lib->get_amount_due();
$data['payments'] = $this->sale_lib->get_payments();
$data['selected_payment_type'] = $this->sale_lib->get_payment_type();
if($customer_info && $this->config->item('customer_reward_enable') == TRUE)
$data['payment_options'] = $this->Sale->get_payment_options(TRUE,TRUE);
else
@@ -898,7 +989,6 @@ class Sales extends Secure_Controller
$data['invoice_number_enabled'] = $this->sale_lib->is_invoice_mode();
$data['print_after_sale'] = $this->sale_lib->is_print_after_sale();
$data['payments_cover_total'] = $this->sale_lib->is_payment_covering_total();
$data['quote_or_invoice_mode'] = $data['mode'] == 'sale_invoice' || $data['mode'] == 'sale_quote';
$data['sales_or_return_mode'] = $data['mode'] == 'sale' || $data['mode'] == 'return';
if($this->sale_lib->get_mode() == 'sale_invoice')
@@ -1050,7 +1140,7 @@ class Sales extends Secure_Controller
{
$suspended_id = $this->sale_lib->get_suspended_id();
$this->sale_lib->clear_all();
$this->Sale_suspended->delete($suspended_id);
$this->Sale->delete_suspended_sale($suspended_id);
$this->_reload();
}
@@ -1065,10 +1155,11 @@ class Sales extends Secure_Controller
$invoice_number = $this->_is_custom_invoice_number($customer_info) ? $this->sale_lib->get_invoice_number() : NULL;
$quote_number = $this->sale_lib->get_quote_number();
$comment = $this->sale_lib->get_comment();
$sale_status = '1';
//SAVE sale to database
$data = array();
if ($this->Sale_suspended->save($cart, $customer_id, $employee_id, $comment, $invoice_number, $quote_number, $payments, $dinner_table) == '-1')
$sales_taxes = array();
if ($this->Sale->save($sale_status, $cart, $customer_id, $employee_id, $comment, $invoice_number, $quote_number, $payments, $dinner_table, $sales_taxes) == '-1')
{
$data['error'] = $this->lang->line('sales_unsuccessfully_suspended_sale');
}
@@ -1088,14 +1179,14 @@ class Sales extends Secure_Controller
$employee_id = $this->Employee->get_logged_in_employee_info()->person_id;
$customer_id = $this->sale_lib->get_customer();
$customer_info = $this->Customer->get_info($customer_id);
$dinner_table = $this->sale_lib->get_dinner_table();
$invoice_number = $this->_is_custom_invoice_number($customer_info) ? $this->sale_lib->get_invoice_number() : NULL;
$comment = $this->sale_lib->get_comment();
$sale_status = '2'; // Suspend
//SAVE sale to database
$data = array();
$suspended_id = $this->Sale_suspended->save($cart, $customer_id, $employee_id, $comment, $invoice_number, $quote_number, $payments);
$this->sale_lib->set_suspended_id($suspended_id);
if ($suspended_id == '-1')
$sales_taxes = array();
if ($this->Sale->save($sale_status, $cart, $customer_id, $employee_id, $comment, $invoice_number, $quote_number, $payments, $dinner_table, $sales_taxes) == '-1')
{
$data['error'] = $this->lang->line('sales_unsuccessfully_suspended_sale');
}
@@ -1107,17 +1198,34 @@ class Sales extends Secure_Controller
public function suspended()
{
$customer_id = $this->sale_lib->get_customer();
$data = array();
$data['suspended_sales'] = $this->xss_clean($this->Sale_suspended->get_all()->result_array());
$data['suspended_sales'] = $this->xss_clean($this->Sale->get_all_suspended($customer_id));
$data['dinner_table_enable'] = $this->config->item('dinner_table_enable');
$this->load->view('sales/suspended', $data);
}
/*
* We will eventually drop the current set of "suspended" tables since suspended sales
* are now stored in the sales tables with a sale_status value of suspended.
*/
public function unsuspend()
{
$sale_id = $this->input->post('suspended_sale_id');
$this->sale_lib->clear_all();
$this->sale_lib->copy_entire_suspended_sale($sale_id);
$this->Sale_suspended->delete($sale_id);
if($sale_id > 0) {
$this->sale_lib->copy_entire_sale($sale_id);
$this->Sale->delete_suspended_sale($sale_id);
}
else
{
// This will unsuspended older suspended sales
$sale_id = $sale_id * -1;
$this->sale_lib->copy_entire_suspended_tables_sale($sale_id);
$this->Sale_suspended->delete($sale_id);
}
$this->_reload();
}

View File

@@ -0,0 +1,227 @@
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
require_once("Secure_Controller.php");
class Taxes extends Secure_Controller
{
public function __construct()
{
parent::__construct('taxes');
$this->load->model('enums/Rounding_code');
}
public function index()
{
$data['table_headers'] = $this->xss_clean(get_taxes_manage_table_headers());
$this->load->view('taxes/manage', $data);
}
/*
Returns tax_codes table data rows. This will be called with AJAX.
*/
public function search()
{
$search = $this->input->get('search');
$limit = $this->input->get('limit');
$offset = $this->input->get('offset');
$sort = $this->input->get('sort');
$order = $this->input->get('order');
$tax_codes = $this->Tax->search($search, $limit, $offset, $sort, $order);
$total_rows = $this->Tax->get_found_rows($search);
$data_rows = array();
foreach($tax_codes->result() as $tax_code_row)
{
$data_rows[] = get_tax_data_row($tax_code_row, $this);
}
$data_rows = $this->xss_clean($data_rows);
echo json_encode(array('total' => $total_rows, 'rows' => $data_rows));
}
/*
Gives search suggestions based on what is being searched for
*/
public function suggest_search()
{
$suggestions = $this->xss_clean($this->Tax->get_search_suggestions($this->input->post('term')));
echo json_encode($suggestions);
}
/*
Provides list of tax categories to select from
*/
public function suggest_tax_categories()
{
$suggestions = $this->xss_clean($this->Tax->get_tax_category_suggestions($this->input->post('term')));
echo json_encode($suggestions);
}
public function get_row($row_id)
{
$data_row = $this->xss_clean(get_tax_codes_data_row($this->Tax->get_info($row_id), $this));
echo json_encode($data_row);
}
public function view($tax_code = -1)
{
$tax_code_info = $this->Tax->get_info($tax_code);
$default_tax_category_id = 0; // Tax category id is always the default tax category
$default_tax_category = $this->Tax->get_tax_category($default_tax_category_id);
$tax_rate_info = $this->Tax->get_rate_info($tax_code, $default_tax_category_id);
$data['rounding_options'] = Rounding_code::get_rounding_options();
if ($tax_code == -1)
{
$data['tax_code'] = '';
$data['tax_code_name'] = '';
$data['tax_code_type'] = '0';
$data['city'] = '';
$data['state'] = '';
$data['tax_rate'] = '0.0000';
$data['rate_tax_code'] = '';
$data['rate_tax_category_id'] = '0';
$data['tax_category'] = '';
$data['add_tax_category'] = '';
$data['rounding_code'] = '0';
}
else
{
$data['tax_code'] = $tax_code;
$data['tax_code_name'] = $tax_code_info->tax_code_name;
$data['tax_code_type'] = $tax_code_info->tax_code_type;
$data['city'] = $tax_code_info->city;
$data['state'] = $tax_code_info->state;
$data['rate_tax_code'] = $tax_code_info->rate_tax_code;
$data['rate_tax_category_id'] = $tax_code_info->rate_tax_category_id;
$data['tax_category'] = $tax_code_info->tax_category;
$data['add_tax_category'] = '';
$data['tax_rate'] = $tax_rate_info->tax_rate;
$data['rounding_code'] = $tax_rate_info->rounding_code;
}
$data = $this->xss_clean($data);
$tax_code_rates = array();
foreach($this->Tax->get_tax_code_rate_exceptions($tax_code) as $tax_code_rate)
{
$tax_code_row = array();
$tax_code_row['rate_tax_category_id'] = $this->xss_clean($tax_code_rate['rate_tax_category_id']);
$tax_code_row['tax_category'] = $this->xss_clean($tax_code_rate['tax_category']);
$tax_code_row['tax_rate'] = $this->xss_clean($tax_code_rate['tax_rate']);
$tax_code_row['rounding_code'] = $this->xss_clean($tax_code_rate['rounding_code']);
$tax_code_rates[] = $tax_code_row;
}
$data['tax_code_rates'] = $tax_code_rates;
$this->load->view("taxes/form", $data);
}
public static function get_html_rounding_options()
{
return Rounding_code::get_html_rounding_options();
}
public function save($tax_code = -1)
{
$entered_tax_code = $this->xss_clean($this->input->post('tax_code'));
$tax_code_data = array(
'tax_code' => $this->input->post('tax_code'),
'tax_code_name' => $this->input->post('tax_code_name'),
'tax_code_type' => $this->input->post('tax_code_type'),
'city' => $this->input->post('city'),
'state' => $this->input->post('state'));
$tax_rate_data = array(
'rate_tax_code' => $this->input->post('tax_code'),
'rate_tax_category_id' => 0,
'tax_rate' => parse_decimals($this->input->post('tax_rate')),
'rounding_code' => parse_decimals($this->input->post('rounding_code'))
);
if($this->Tax->save($tax_code_data, $tax_rate_data, $tax_code))
{
$tax_code_rate_exceptions = array();
if(!empty($this->input->post('exception_tax_rate')))
{
foreach($this->input->post('exception_tax_rate') as $tax_category_id => $exception_tax_rate)
{
$exception_rounding_code = $this->input->post('exception_rounding_code[' . $tax_category_id . ']');
$tax_code_rate_exceptions[] = array(
'rate_tax_code' => $entered_tax_code,
'rate_tax_category_id' => $tax_category_id,
'tax_rate' => $exception_tax_rate,
'rounding_code' => $exception_rounding_code
);
}
}
if (!empty($tax_code_rate_exceptions))
{
$success = $this->Tax->save_tax_rate_exceptions($tax_code_rate_exceptions, $entered_tax_code);
}
$tax_code_data = $this->xss_clean($tax_code_data);
//New tax_code record
if($tax_code == -1)
{
echo json_encode(array('success' => TRUE, 'message' => $this->lang->line('taxes_tax_code_successfully_added') . ' ' . $entered_tax_code));
}
else //Existing tax_code
{
echo json_encode(array('success' => TRUE, 'message' => $this->lang->line('taxes_tax_code_successful_updated') . ' ' . $entered_tax_code));
}
}
else //failure
{
$tax_code_data = $this->xss_clean($tax_code_data);
echo json_encode(array('success' => FALSE, 'message' => $this->lang->line('taxes_tax_code_error_adding_updating') . ' ' .
$entered_tax_code));
}
}
public function delete()
{
$tax_codes_to_delete = $this->xss_clean($this->input->post('ids'));
if($this->Tax->delete_list($tax_codes_to_delete))
{
echo json_encode(array('success' => TRUE, 'message' => $this->lang->line('taxes_tax_code_successful_deleted')));
} else
{
echo json_encode(array('success' => FALSE, 'message' => $this->lang->line('taxes_tax_code_cannot_be_deleted')));
}
}
public function suggest_sales_tax_codes()
{
$suggestions = $this->xss_clean($this->Tax->get_sales_tax_codes_search_suggestions($this->input->post_get('term')));
echo json_encode($suggestions);
}
public function get_rounding_code_name($rounding_code)
{
return Rounding_code::get_rounding_code_name($rounding_code);
}
}
?>

View File

@@ -327,6 +327,23 @@ function get_giftcards_manage_table_headers()
return transform_headers($headers);
}
function get_taxes_manage_table_headers()
{
$CI =& get_instance();
$headers = array(
array('tax_code' => $CI->lang->line('taxes_tax_code')),
array('tax_code_name' => $CI->lang->line('taxes_tax_code_name')),
array('tax_code_type_name' => $CI->lang->line('taxes_tax_code_type')),
array('tax_rate' => $CI->lang->line('taxes_tax_rate')),
array('rounding_code_name' => $CI->lang->line('taxes_rounding_code')),
array('city' => $CI->lang->line('common_city')),
array('state' => $CI->lang->line('common_state'))
);
return transform_headers($headers);
}
function get_giftcard_data_row($giftcard, $controller)
{
$CI =& get_instance();
@@ -343,6 +360,26 @@ function get_giftcard_data_row($giftcard, $controller)
));
}
function get_tax_data_row($tax_code_row, $controller)
{
$CI =& get_instance();
$controller_name=strtolower(get_class($CI));
return array (
'tax_code' => $tax_code_row->tax_code,
'tax_code_name' => $tax_code_row->tax_code_name,
'tax_code_type' => $tax_code_row->tax_code_type,
'tax_rate' => $tax_code_row->tax_rate,
'rounding_code' =>$tax_code_row->rounding_code,
'tax_code_type_name' => $CI->Tax->get_tax_code_type_name($tax_code_row->tax_code_type),
'rounding_code_name' => $CI->get_rounding_code_name($tax_code_row->rounding_code),
'city' => $tax_code_row->city,
'state' => $tax_code_row->state,
'edit' => anchor($controller_name."/view/$tax_code_row->tax_code", '<span class="glyphicon glyphicon-edit"></span>',
array('class'=>'modal-dlg', 'data-btn-submit' => $CI->lang->line('common_submit'), 'title'=>$CI->lang->line($controller_name.'_update'))
));
}
function get_item_kits_manage_table_headers()
{
$CI =& get_instance();

View File

@@ -29,6 +29,9 @@ $lang["config_barcode_type"] = "Barcode Type";
$lang["config_barcode_width"] = "Width (px)";
$lang["config_bottom"] = "Bottom";
$lang["config_center"] = "Center";
$lang["config_cash_decimals"] = "Cash Decimals";
$lang["config_cash_decimals_tooltip"] = "If cash decimals and currency decimals are the same then no cash rounding will take place.";
$lang["config_cash_rounding"] = "Cash Rounding";
$lang["config_comma"] = "comma";
$lang["config_company"] = "Company Name";
$lang["config_company_change_image"] = "Change Image";
@@ -56,6 +59,7 @@ $lang["config_customer_reward_duplicate"] = "Please use an unique reward name";
$lang["config_customer_reward_enable"] = "Enable Customer Rewards";
$lang["config_customer_reward_invalid_chars"] = "The reward name can not contain '_'";
$lang["config_customer_reward_required"] = "Reward is a required field";
$lang["config_customer_sales_tax_support"] = "Customer Sales Tax Support";
$lang["config_date_or_time_format"] = "Date and Time filter";
$lang["config_datetimeformat"] = "Date and Time format";
$lang["config_decimal_point"] = "Decimal Point";
@@ -73,6 +77,7 @@ $lang["config_default_barcode_quality_number"] = "The default barcode quality mu
$lang["config_default_barcode_quality_required"] = "The default barcode quality is a required field";
$lang["config_default_barcode_width_number"] = "The default barcode width must be a number";
$lang["config_default_barcode_width_required"] = "The default barcode width is a required field";
$lang["config_default_origin_tax_code"] = "Default Origin Tax Code";
$lang["config_default_sales_discount"] = "Default Sales Discount %";
$lang["config_default_sales_discount_number"] = "The default sales discount must be a number";
$lang["config_default_sales_discount_required"] = "The default sales discount is a required field";

View File

@@ -20,6 +20,7 @@ $lang["customers_one_or_multiple"] = "customer(s)";
$lang["customers_successful_adding"] = "You have successfully added customer";
$lang["customers_successful_deleted"] = "You have successfully deleted";
$lang["customers_successful_updating"] = "You have successfully updated customer";
$lang["customers_tax_code"] = "Tax Code";
$lang["customers_taxable"] = "Taxable";
$lang["customers_total"] = "Total";
$lang["customers_update"] = "Update Customer";

View File

@@ -0,0 +1,9 @@
<?php
$lang["enum_half_down"] = "Half Down";
$lang["enum_half_five"] = "Half Five";
$lang["enum_half_even"] = "Half Even";
$lang["enum_half_odd"] = "Half Odd";
$lang["enum_half_up"] = "Half Up";
$lang["enum_round_up"] = "Round Up";
$lang["enum_round_down"] = "Round Down";

View File

@@ -23,3 +23,7 @@ $lang["module_sales"] = "Sales";
$lang["module_sales_desc"] = "Process sales and returns";
$lang["module_suppliers"] = "Suppliers";
$lang["module_suppliers_desc"] = "Add, Update, Delete, and Search suppliers";
$lang["module_taxes"] = "Taxes";
$lang["module_taxes_desc"] = "Configure sales taxes";
$lang["module_messages"] = "Messages";
$lang["module_messages_desc"] = "Send Messages to Customers, Suppliers, Employees et al.";

View File

@@ -105,6 +105,7 @@ $lang["sales_sale"] = "Sale";
$lang["sales_sale_by_invoice"] = "Sale by Invoice";
$lang["sales_sale_for_customer"] = "Customer:";
$lang["sales_sale_time"] = "Time";
$lang["sales_sales_tax"] = "Sales Tax";
$lang["sales_select_customer"] = "Select Customer (Optional)";
$lang["sales_send_invoice"] = "Send Invoice";
$lang["sales_send_quote"] = "Send Quote";

View File

@@ -0,0 +1,35 @@
<?php
$lang["taxes_default_tax_category"] = "Default Tax Category";
$lang["taxes_error_adding_updating"] = "Error adding/updating tax code";
$lang["taxes_new"] = "New Tax Code";
$lang["taxes_no_taxes_to_display"] = "No taxes code available to display";
$lang["taxes_rounding_code"] = "Rounding Code";
$lang["taxes_round_half_up"] = "Half Up";
$lang["taxes_round_half_down"] = "Half Down";
$lang["taxes_round_half_even"] = "Half Even";
$lang["taxes_round_half_odd"] = "Half Odd";
$lang["taxes_sales_tax"] = "Sales Tax";
$lang["taxes_sales_tax_by_invoice"] = "Sales Tax by Invoice";
$lang["taxes_successful_deleted"] = "You have successfully deleted";
$lang["taxes_tax_code"] = "Tax Code";
$lang["taxes_tax_code_name"] = "Tax Code Name";
$lang["taxes_tax_code_successful_deleted"] = "You have successfully deleted tax code";
$lang["taxes_tax_code_successful_updating"] = "You have successfully updated tax code";
$lang["taxes_tax_code_type"] = "Tax Code Type";
$lang["taxes_tax_rate"] = "Tax Rate";
$lang["taxes_tax_rate_numeric"] = "Tax rate must be a number";
$lang["taxes_tax_code_required"] = "Tax code is a required field";
$lang["taxes_tax_rate_required"] = "Tax rate is a required field";
$lang["taxes_vat_tax"] = "VAT Tax";
$lang["taxes_tax_category"] = "Tax Category";
$lang["taxes_tax_code_successfully_added"] = "You have successfully added";
$lang["taxes_tax_code_successful_deleted"] = "You have successfully deleted";
$lang["taxes_tax_code_cannot_be_deleted"] = "Could not delete selected tax code";
$lang["taxes_tax_code_successful_updated"] = "You have successfully updated";
$lang["taxes_confirm_delete"] = "Confirm deletion of tax code";
$lang["taxes_update"] = "Update Sales Category Tax";
$lang["taxes_add_exception"] = "Add Exception";

View File

@@ -7,6 +7,9 @@ class Sale_lib
public function __construct()
{
$this->CI =& get_instance();
$this->CI->load->library('tax_lib');
$this->CI->load->model('enums/Rounding_code');
}
public function get_line_sequence_options()
@@ -298,17 +301,112 @@ class Sale_lib
public function get_payments_total()
{
$subtotal = 0;
$this->reset_cash_flags();
foreach($this->get_payments() as $payments)
{
$subtotal = bcadd($payments['payment_amount'], $subtotal);
if($this->CI->session->userdata('cash_rounding') && $this->CI->lang->line('sales_cash') != $payments['payment_type'])
{
$this->CI->session->set_userdata('cash_rounding', 0);
}
}
return $subtotal;
}
public function get_cash_rounding()
{
}
/*
* Returns 'subtotal', 'total', 'cash_total', 'payment_total', 'amount_due', 'cash_amount_due', 'paid_in_full'
* 'subtotal', 'discounted_subtotal', 'tax_exclusive_subtotal'
*/
public function get_totals()
{
$cash_rounding = $this->CI->session->userdata('cash_rounding');
$totals = array();
$subtotal = 0;
$discounted_subtotal = 0;
$tax_exclusive_subtotal = 0;
foreach($this->get_cart() as $item)
{
$subtotal = bcadd($subtotal, $this->get_item_total($item['quantity'], $item['price'], $item['discount'], false));
$discounted_subtotal = bcadd($discounted_subtotal, $this->get_item_total($item['quantity'], $item['price'], $item['discount'], true));
if($this->CI->config->config['tax_included'])
{
$tax_exclusive_subtotal = bcadd($tax_exclusive_subtotal, $this->get_item_total_tax_exclusive($item['item_id'], $item['quantity'], $item['price'], $item['discount'], true));
}
}
$totals['subtotal'] = $subtotal;
$totals['discounted_subtotal'] = $discounted_subtotal;
$totals['tax_exclusive_subtotal'] = $tax_exclusive_subtotal;
$total = $discounted_subtotal;
if ($this->CI->config->config['tax_included'])
{
$totals['total'] = $total;
}
else
{
foreach($this->get_taxes() as $sales_tax)
{
$total = bcadd($total, $sales_tax['sale_tax_amount']);
}
$totals['total'] = $total;
}
if($cash_rounding)
{
$cash_total = $this->check_for_cash_rounding($total);
$totals['cash_total'] = $cash_total;
}
else
{
$cash_total = $total;
}
$totals['cash_total'] = $cash_total;
$payment_total = $this->get_payments_total();
$totals['payment_total'] = $payment_total;
$amount_due = bcsub($total, $payment_total);
$totals['amount_due'] = $amount_due;
$cash_amount_due = bcsub($cash_total, $payment_total);
$totals['cash_amount_due'] = $cash_amount_due;
if($cash_rounding)
{
$current_due = $cash_amount_due;
}
else
{
$current_due = $amount_due;
}
if($this->get_mode() == 'return')
{
$totals['payments_cover_total'] = $current_due >= 0;
}
else
{
$totals['payments_cover_total'] = $current_due <= 0;
}
return $totals;
}
// Multiple Payments
public function get_amount_due()
{
// Payment totals need to be identified first so that we know whether or not there is a non-cash payment involved
$payment_total = $this->get_payments_total();
$sales_total = $this->get_total();
$amount_due = bcsub($sales_total, $payment_total);
@@ -320,16 +418,14 @@ class Sale_lib
public function is_payment_covering_total()
{
// 0 decimal -> 1 / 2 = 0.5, 1 decimals -> 0.1 / 2 = 0.05, 2 decimals -> 0.01 / 2 = 0.005
$threshold = bcpow(10, -$this->CI->config->item('currency_decimals')) / 2;
if($this->get_mode() == 'return')
{
return ($this->get_amount_due() > -$threshold);
return $this->get_amount_due() >= 0;
}
else
{
return ($this->get_amount_due() < $threshold);
return $this->get_amount_due() <= 0;
}
}
@@ -437,6 +533,16 @@ class Sale_lib
$this->CI->session->set_userdata('sales_location', $location);
}
public function set_payment_type($payment_type)
{
$this->CI->session->set_userdata('payment_type', $payment_type);
}
public function get_payment_type()
{
return $this->CI->session->userdata('payment_type');
}
public function clear_sale_location()
{
$this->CI->session->unset_userdata('sales_location');
@@ -571,7 +677,8 @@ class Sale_lib
'total' => $total,
'discounted_total' => $discounted_total,
'print_option' => $print_option,
'stock_type' => $stock_type
'stock_type' => $stock_type,
'tax_category_id' => $item_info->tax_category_id
)
);
//add to existing array
@@ -778,6 +885,31 @@ class Sale_lib
$this->empty_cart();
$this->remove_customer();
foreach($this->CI->Sale->get_sale_items($sale_id)->result() as $row)
{
$this->add_item($row->item_id, $row->quantity_purchased, $row->item_location, $row->discount_percent, $row->item_unit_price,
$row->description, $row->serialnumber, TRUE, $row->print_option, $row->stock_type);
}
foreach($this->CI->Sale->get_sale_payments($sale_id)->result() as $row)
{
$this->add_payment($row->payment_type, $row->payment_amount);
}
$suspended_sale_info = $this->CI->Sale->get_info($sale_id)->row();
$this->set_customer($suspended_sale_info->person_id);
$this->set_comment($suspended_sale_info->comment);
$this->set_invoice_number($suspended_sale_info->invoice_number);
$this->set_quote_number($suspended_sale_info->quote_number);
$this->set_dinner_table($suspended_sale_info->dinner_table_id);
}
public function copy_entire_suspended_tables_sale($sale_id)
{
$this->empty_cart();
$this->remove_customer();
foreach($this->CI->Sale_suspended->get_sale_items($sale_id)->result() as $row)
{
$this->add_item($row->item_id, $row->quantity_purchased, $row->item_location, $row->discount_percent, $row->item_unit_price,
@@ -810,6 +942,37 @@ class Sale_lib
$this->clear_giftcard_remainder();
$this->empty_payments();
$this->remove_customer();
$this->clear_cash_flags();
}
public function clear_cash_flags()
{
$this->CI->session->unset_userdata('cash_rounding');
$this->CI->session->unset_userdata('cash_mode');
$this->CI->session->unset_userdata('payment_type');
}
public function reset_cash_flags()
{
if($this->CI->lang->line('payment_options_order') != 'cashdebitcredit')
{
$cash_mode = 1;
}
else
{
$cash_mode = 0;
}
$this->CI->session->set_userdata('cash_mode', $cash_mode);
if($this->CI->config->config['cash_decimals'] < $this->CI->config->config['currency_decimals'])
{
$cash_rounding = 1;
}
else
{
$cash_rounding = 0;
}
$this->CI->session->set_userdata('cash_rounding', $cash_rounding);
}
public function is_customer_taxable()
@@ -821,34 +984,68 @@ class Sale_lib
return $customer->taxable or $customer_id == -1;
}
/*
* This returns taxes for VAT taxes and for pre 3.1.0 sales taxes.
*/
public function get_taxes()
{
$taxes = array();
$register_mode = $this->CI->config->config['default_register_mode'];
$tax_decimals = $this->CI->config->config['tax_decimals'];
$customer_id = $this->get_customer();
$customer = $this->CI->Customer->get_info($customer_id);
$sales_taxes = array();
//Do not charge sales tax if we have a customer that is not taxable
if($this->is_customer_taxable())
if($customer->taxable or $customer_id == -1)
{
foreach($this->get_cart() as $line => $item)
{
$tax_info = $this->CI->Item_taxes->get_info($item['item_id']);
// Start of current VAT tax apply
$tax_info = $this->CI->Item_taxes->get_info($item['item_id']);
$tax_group_sequence = 0;
foreach($tax_info as $tax)
{
$name = to_tax_decimals($tax['percent']) . '% ' . $tax['name'];
$tax_amount = $this->get_item_tax($item['quantity'], $item['price'], $item['discount'], $tax['percent']);
// This computes tax for each line item and adds it to the tax type total
$tax_group = (float)$tax['percent'] . '% ' . $tax['name'];
$tax_type = Tax_lib::TAX_TYPE_VAT;
$tax_basis = $this->get_item_total($item['quantity'], $item['price'], $item['discount'], TRUE);
$tax_amount = 0;
if(!isset($taxes[$name]))
if($this->CI->config->config['tax_included'])
{
$taxes[$name] = 0;
$tax_amount = $this->get_item_tax($item['quantity'], $item['price'], $item['discount'], $tax['percent']);
}
elseif($this->CI->config->config['customer_sales_tax_support'] == '0')
{
$tax_amount = $this->CI->tax_lib->get_sales_tax_for_amount($tax_basis, $tax['percent'], '0', $tax_decimals);
}
$precision = $this->CI->config->item('currency_decimals');
$taxes[$name] = bcadd($taxes[$name], round($tax_amount, $precision, PHP_ROUND_HALF_EVEN));
if($tax_amount <> 0)
{
$this->CI->tax_lib->update_sales_taxes($sales_taxes, $tax_type, $tax_group, $tax['percent'], $tax_basis, $tax_amount, $tax_group_sequence, '0', -1);
$tax_group_sequence += 1;
}
}
$tax_category = '';
$tax_rate = '';
$rounding_code = Rounding_code::HALF_UP;
$tax_group_sequence = 0;
$tax_code = '';
if($this->CI->config->config['customer_sales_tax_support'] == '1')
{
// Now calculate what the sales taxes should be (storing them in the $sales_taxes array
$this->CI->tax_lib->apply_sales_tax($item, $customer->city, $customer->state, $customer->sales_tax_code, $register_mode, 0, $sales_taxes, $tax_category, $tax_rate, $rounding_code, $tax_group_sequence, $tax_code);
}
}
$this->CI->tax_lib->round_sales_taxes($sales_taxes);
}
return $taxes;
return $sales_taxes;
}
public function apply_customer_discount($discount_percent)
@@ -944,7 +1141,7 @@ class Sale_lib
return bcmul($price, $tax_fraction);
}
public function calculate_subtotal($include_discount = FALSE, $exclude_tax = FALSE)
public function calculate_subtotal($include_discount = FALSE, $exclude_tax = FALSE)
{
$subtotal = 0;
foreach($this->get_cart() as $item)
@@ -964,22 +1161,67 @@ class Sale_lib
public function get_total()
{
$total = $this->calculate_subtotal(TRUE);
if(!$this->CI->config->config['tax_included'])
$total = $this->calculate_subtotal(TRUE);
$cash_rounding = $this->CI->session->userdata('cash_rounding');
foreach($this->get_taxes() as $sales_tax)
{
foreach($this->get_taxes() as $tax)
{
$total = bcadd($total, $tax);
}
$total = bcadd($total, $sales_tax['sale_tax_amount']);
}
if($cash_rounding)
{
$rounded_total = $this->check_for_cash_rounding($total);
return $rounded_total;
}
return $total;
}
public function get_empty_tables()
public function get_empty_tables()
{
return $this->CI->Dinner_table->get_empty_tables();
}
public function check_for_cash_rounding($total)
{
$cash_decimals = $this->CI->config->config['cash_decimals'];
$cash_rounding_code = $this->CI->config->config['cash_rounding_code'];
$rounded_total = $total;
if($cash_rounding_code == Rounding_code::HALF_UP)
{
$rounded_total = round ( $total, $cash_decimals, PHP_ROUND_HALF_UP);
}
elseif($cash_rounding_code == Rounding_code::HALF_DOWN)
{
$rounded_total = round ( $total, $cash_decimals, PHP_ROUND_HALF_DOWN);
}
elseif($cash_rounding_code == Rounding_code::HALF_EVEN)
{
$rounded_total = round ( $total, $cash_decimals, PHP_ROUND_HALF_EVEN);
}
elseif($cash_rounding_code == Rounding_code::HALF_ODD)
{
$rounded_total = round ( $total, $cash_decimals, PHP_ROUND_HALF_UP);
}
elseif($cash_rounding_code == Rounding_code::ROUND_UP)
{
$fig = (int) str_pad('1', $cash_decimals, '0');
$rounded_total = (ceil($total * $fig) / $fig);
}
elseif($cash_rounding_code == Rounding_code::ROUND_DOWN)
{
$fig = (int) str_pad('1', $cash_decimals, '0');
$rounded_total = (floor($total * $fig) / $fig);
}
elseif($cash_rounding_code == Rounding_code::HALF_FIVE)
{
$rounded_total = round($total / 5) * 5;
}
return $rounded_total;
}
}
?>

View File

@@ -0,0 +1,320 @@
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
class Tax_lib
{
const TAX_TYPE_SALES = 1;
const TAX_TYPE_SALES_BY_INVOICE = 2;
const TAX_TYPE_VAT = 0;
private $CI;
public function __construct()
{
$this->CI =& get_instance();
$this->CI->load->library('sale_lib');
}
public function get_tax_types()
{
return array(
TAX_TYPE_SALES => $this->CI->lang->line('taxes_sales_tax'),
TAX_TYPE_SALES_BY_INVOICE => $this->CI->lang->line('taxes_sales_tax_by_invoice'),
TAX_TYPE_VAT => $this->CI->lang->line('taxes_vat_tax')
);
}
/*
* Compute the tax basis and returns the tax amount
*/
public function get_item_sales_tax($quantity, $price, $discount_percentage, $tax_percentage, $rounding_code)
{
$tax_decimals = $this->CI->config->config['tax_decimals'];
// The tax basis should be returned at the currency scale
$tax_basis = $this->CI->sale_lib->get_item_total($quantity, $price, $discount_percentage, TRUE);
return $this->get_sales_tax_for_amount($tax_basis, $tax_percentage, $rounding_code, $tax_decimals);
}
/*
* Computes the item level sales tax amount for a given tax basis
*/
public function get_sales_tax_for_amount($tax_basis, $tax_percentage, $rounding_code, $decimals)
{
$tax_fraction = bcdiv($tax_percentage, 100);
$tax_amount = bcmul($tax_basis, $tax_fraction);
$rounded_tax_amount = $tax_amount;
if($rounding_code == Rounding_code::HALF_UP)
{
$rounded_tax_amount = round ( $tax_amount, $decimals, PHP_ROUND_HALF_UP);
}
elseif($rounding_code == Rounding_code::HALF_DOWN)
{
$rounded_tax_amount = round ( $tax_amount, $decimals, PHP_ROUND_HALF_DOWN);
}
elseif($rounding_code == Rounding_code::HALF_EVEN)
{
$rounded_tax_amount = round ( $tax_amount, $decimals, PHP_ROUND_HALF_EVEN);
}
elseif($rounding_code == Rounding_code::HALF_ODD)
{
$rounded_tax_amount = round ( $tax_amount, $decimals, PHP_ROUND_HALF_UP);
}
elseif($rounding_code == Rounding_code::ROUND_UP) // ROUND_UP
{
$fig = (int) str_pad('1', $decimals, '0');
$rounded_tax_amount = (ceil($tax_amount * $fig) / $fig);
}
elseif($rounding_code == Rounding_code::ROUND_DOWN) // ROUND_DOWN
{
$fig = (int) str_pad('1', $decimals, '0');
$rounded_tax_amount = (floor($tax_amount * $fig) / $fig);
}
elseif($rounding_code == Rounding_code::HALF_FIVE)
{
$rounded_tax_amount = round($tax_amount / 5) * 5;
}
return $rounded_tax_amount;
}
/*
* Updates the sales_tax array which is later saved to the `sales_taxes` table and used for printing taxes on receipts and invoices
*/
public function update_sales_taxes(&$sales_taxes, $tax_type, $tax_group, $tax_rate, $tax_basis, $item_tax_amount, $tax_group_sequence, $rounding_code, $sale_id, $name='', $tax_code='')
{
$tax_group_index = $this->clean('X'.$tax_group);
if ($item_tax_amount != 0) {
if(!array_key_exists($tax_group_index, $sales_taxes))
{
$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
));
//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);
}
}
}
/*
* If invoice taxing (as opposed to invoice_item_taxing) rules apply then recalculate the sales tax after tax group totals are final
*/
public function apply_invoice_taxing(&$sales_taxes)
{
if(!empty($sales_taxes))
{
$sort = array();
foreach($sales_taxes as $k => $v)
{
$sort['print_sequence'][$k] = $v['print_sequence'];
}
array_multisort($sort['print_sequence'], SORT_ASC, $sales_taxes);
}
$currency_decimals = $this->CI->config->config['currency_decimals'];
foreach($sales_taxes as $row_number => $sales_tax)
{
$sales_tax['sale_tax_amount'] = get_sales_tax_for_amount($sales_tax['sale_tax_basis'], $sales_tax['sale_tax_rate'], $sales_tax['rounding_code'], $currency_decimals);
}
}
/*
* Apply rounding rules to the accumulated sales tax amounts
*/
public function round_sales_taxes(&$sales_taxes)
{
if (!empty($sales_taxes))
{
$sort = array();
foreach($sales_taxes as $k=>$v) {
$sort['print_sequence'][$k] = $v['print_sequence'];
}
array_multisort($sort['print_sequence'], SORT_ASC, $sales_taxes);
}
$currency_decimals = $this->CI->config->config['currency_decimals'];
foreach($sales_taxes as $row_number => $sales_tax)
{
$sale_tax_amount = $sales_tax['sale_tax_amount'];
$rounding_code = $sales_tax['rounding_code'];
$rounded_sale_tax_amount = $sale_tax_amount;
if ($rounding_code == Rounding_code::HALF_UP)
{
$rounded_sale_tax_amount = round ( $sale_tax_amount, $currency_decimals, PHP_ROUND_HALF_UP);
}
elseif($rounding_code == Rounding_code::HALF_DOWN)
{
$rounded_sale_tax_amount = round ( $sale_tax_amount, $currency_decimals, PHP_ROUND_HALF_DOWN);
}
elseif($rounding_code == Rounding_code::HALF_EVEN)
{
$rounded_sale_tax_amount = round ( $sale_tax_amount, $currency_decimals, PHP_ROUND_HALF_EVEN);
}
elseif($rounding_code == Rounding_code::HALF_ODD)
{
$rounded_sale_tax_amount = round ( $sale_tax_amount, $currency_decimals, PHP_ROUND_HALF_UP);
}
elseif($rounding_code == Rounding_code::ROUND_UP)
{
$fig = (int) str_pad('1', $currency_decimals, '0');
$rounded_sale_tax_amount = (ceil($sale_tax_amount * $fig) / $fig);
}
elseif($rounding_code == Rounding_code::ROUND_DOWN)
{
$fig = (int) str_pad('1', $currency_decimals, '0');
$rounded_sale_tax_amount = (floor($sale_tax_amount * $fig) / $fig);
}
elseif($rounding_code == Rounding_code::HALF_FIVE)
{
$rounded_sale_tax_amount = round($sale_tax_amount / 5) * 5;
}
$sales_taxes[$row_number]['sale_tax_amount'] = $rounded_sale_tax_amount;
}
}
/**
* Determine the applicable tax code and then determine the tax amount to be applied.
* If a tax amount was identified then accumulate into the sales_taxes array
*/
public function apply_sales_tax(&$item, &$city, &$state, &$sales_tax_code, $register_mode, $sale_id, &$sales_taxes)
{
$tax_code = $this->get_applicable_tax_mode($register_mode, $city, $state, $sales_tax_code);
// If tax code cannot be determined or the price is zero then skip this item
if($tax_code != '' && $item['price'] != 0)
{
$tax_rate = 0.0000;
$rounding_code = Rounding_code::HALF_UP;
$tax_code_obj = $this->CI->Tax->get_info($tax_code);
$tax_category_id = $item['tax_category_id'];
if($tax_category_id != 0)
{
$tax_rate_info = $this->CI->Tax->get_rate_info($tax_code, $tax_category_id);
if ($tax_rate_info)
{
$tax_rate = $tax_rate_info->tax_rate;
$rounding_code = $tax_rate_info->rounding_code;
}
else
{
$tax_rate = $tax_code_obj->tax_rate;
$rounding_code = $tax_code_obj->rounding_code;
}
}
if($tax_category_id != 0)
{
$tax_rate_info = $this->CI->Tax->get_rate_info($tax_code, $tax_category_id);
$tax_rate = $tax_rate_info->tax_rate;
$rounding_code = $tax_rate_info->rounding_code;
$tax_group_sequence = $tax_rate_info->tax_group_sequence;
$tax_category = $tax_rate_info->tax_category;
}
else
{
$tax_rate = $tax_code_obj->tax_rate;
$rounding_code = $tax_code_obj->rounding_code;
$tax_group_sequence = $tax_code_obj->tax_group_sequence;
$tax_category = $tax_code_obj->tax_category;
}
$tax_decimals = $this->CI->config->config['tax_decimals'];
// The tax basis should be returned at the currency scale
$tax_basis = $this->CI->sale_lib->get_item_total($item['quantity'], $item['price'], $item['discount'], TRUE);
$tax_amount = $this->get_sales_tax_for_amount($tax_basis, $tax_rate, $rounding_code, $tax_decimals);
$tax_group = (float)$tax_rate . '% ' . $tax_category;
$tax_type = Tax_lib::TAX_TYPE_SALES;
if($tax_amount != 0)
{
$this->update_sales_taxes($sales_taxes, $tax_type, $tax_group, $tax_rate, $tax_basis, $tax_amount, $tax_group_sequence, $rounding_code, $sale_id, $tax_category, $tax_code);
}
// input : register_mode
// input : city
// input : state
// input : sales_tax_code
// input : $item['price']
// input : $item['tax_category_id']
// input : $item['quantity']
// input : $item['price']
// input : $item['discount']
// both : $sales_taxes
// output : tax_details['tax_rate']
// output : tax_details['rounding_code']
// output : tax_details['tax_group_sequence']
// output : tax_details['tax_code']
$tax_details = array('item_tax_amount' => $tax_amount, 'tax_group' => $tax_group, 'tax_name' => $tax_category, 'tax_rate' => $tax_rate, 'rounding_code' => $rounding_code, 'tax_group_sequence' => $tax_group_sequence, 'tax_code' => $tax_code);
return $tax_details;
}
else
{
$tax_details = array('item_tax_amount' => 0.0000, 'tax_group' => '', 'tax_name' => '', 'tax_rate' => 0.0000, 'rounding_code' => '0', 'tax_group_sequence' => '0', 'tax_code' => '');
return $tax_details;
}
}
public function get_applicable_tax_mode($register_mode, $city, $state, $sales_tax_code)
{
if ($register_mode == "SALE")
{
$tax_code = $this->CI->config->config['default_origin_tax_code']; // overrides customer assigned code
}
else
{
if ($sales_tax_code == '')
{
$tax_code = $this->CI->Tax->get_sales_tax_code($city, $state);
}
else
{
// Use the customer assigned tax rate code
$tax_code = $sales_tax_code;
}
}
return $tax_code;
}
function clean($string) {
$string = str_replace(' ', '-', $string); // Replaces all spaces with hyphens.
return preg_replace('/[^A-Za-z0-9\-]/', '', $string); // Removes special chars.
}
}
?>

View File

@@ -8,12 +8,12 @@ class Token_suspended_invoice_count extends Token
{
parent::__construct();
$this->CI =& get_instance();
$this->CI->load->model('Sale_suspended');
$this->CI->load->model('Sale');
}
public function get_value()
{
return $this->CI->Sale_suspended->get_invoice_count();
return $this->CI->Sale->get_suspended_invoice_count();
}
}

View File

@@ -97,6 +97,7 @@ class Customer extends Person
$this->db->from('sales');
$this->db->join('sales_payments', 'sales.sale_id = sales_payments.sale_id');
$this->db->where('sales.customer_id', $customer_id);
$this->db->where('sale_status',0);
return $this->db->get()->row();
}
@@ -123,7 +124,7 @@ class Customer extends Person
//Run these queries as a transaction, we want to make sure we do all or nothing
$this->db->trans_start();
if(parent::save($person_data, $customer_id))
{
if(!$customer_id || !$this->exists($customer_id))
@@ -139,7 +140,7 @@ class Customer extends Person
}
$this->db->trans_complete();
$success &= $this->db->trans_status();
return $success;

View File

@@ -57,17 +57,17 @@ class Dinner_table extends CI_Model
public function get_name($dinner_table_id)
{
$this->db->from('dinner_tables');
$this->db->where('dinner_table_id', $dinner_table_id);
$row = $this->db->get()->row();
if(isset($row->name))
if($dinner_table_id == null || empty($dinner_table_id))
{
return $row->name;
return '';
}
else
{
$this->db->from('dinner_tables');
$this->db->where('dinner_table_id',$dinner_table_id);
return '';
return $this->db->get()->row()->name;
}
}
public function get_all()

View File

@@ -414,6 +414,7 @@ class Item extends CI_Model
$this->db->select('item_id, item_number');
$this->db->from('items');
$this->db->where('deleted', $filters['is_deleted']);
$this->db->where("item_type = '0'"); // standard, exclude kit items since kits will be picked up later
$this->db->like('item_number', $search);
$this->db->order_by('item_number', 'asc');
foreach($this->db->get()->result() as $row)
@@ -427,6 +428,7 @@ class Item extends CI_Model
$this->db->select('category');
$this->db->from('items');
$this->db->where('deleted', $filters['is_deleted']);
$this->db->where("item_type = '0'"); // standard, exclude kit items since kits will be picked up later
$this->db->distinct();
$this->db->like('category', $search);
$this->db->order_by('category', 'asc');
@@ -441,6 +443,7 @@ class Item extends CI_Model
$this->db->like('company_name', $search);
// restrict to non deleted companies only if is_deleted is FALSE
$this->db->where('deleted', $filters['is_deleted']);
$this->db->where("item_type = '0'"); // standard, exclude kit items since kits will be picked up later
$this->db->distinct();
$this->db->order_by('company_name', 'asc');
foreach($this->db->get()->result() as $row)
@@ -452,6 +455,7 @@ class Item extends CI_Model
$this->db->select('item_id, name, description');
$this->db->from('items');
$this->db->where('deleted', $filters['is_deleted']);
$this->db->where("item_type = '0'"); // standard, exclude kit items since kits will be picked up later
$this->db->like('description', $search);
$this->db->order_by('description', 'asc');
foreach($this->db->get()->result() as $row)
@@ -480,6 +484,7 @@ class Item extends CI_Model
$this->db->or_like('custom10', $search);
$this->db->group_end();
$this->db->where('deleted', $filters['is_deleted']);
$this->db->where("item_type = '0'"); // standard, exclude kit items since kits will be picked up later
foreach($this->db->get()->result() as $row)
{
$suggestions[] = array('value' => $row->item_id, 'label' => $row->name);
@@ -487,6 +492,118 @@ class Item extends CI_Model
}
}
//only return $limit suggestions
if(count($suggestions > $limit))
{
$suggestions = array_slice($suggestions, 0,$limit);
}
return $suggestions;
}
public function get_stock_search_suggestions($search, $filters = array('is_deleted' => FALSE, 'search_custom' => FALSE), $unique = FALSE, $limit = 25)
{
$suggestions = array();
$this->db->select('item_id, name');
$this->db->from('items');
$this->db->where('deleted', $filters['is_deleted']);
$this->db->where("item_type = '0'"); // standard, exclude kit items since kits will be picked up later
$this->db->where("stock_type = '0'"); // stocked items only
$this->db->like('name', $search);
$this->db->order_by('name', 'asc');
foreach($this->db->get()->result() as $row)
{
$suggestions[] = array('value' => $row->item_id, 'label' => $row->name);
}
$this->db->select('item_id, item_number');
$this->db->from('items');
$this->db->where('deleted', $filters['is_deleted']);
$this->db->where("item_type = '0'"); // standard, exclude kit items since kits will be picked up later
$this->db->where("stock_type = '0'"); // stocked items only
$this->db->like('item_number', $search);
$this->db->order_by('item_number', 'asc');
foreach($this->db->get()->result() as $row)
{
$suggestions[] = array('value' => $row->item_id, 'label' => $row->item_number);
}
if(!$unique)
{
//Search by category
$this->db->select('category');
$this->db->from('items');
$this->db->where('deleted', $filters['is_deleted']);
$this->db->where("item_type = '0'"); // standard, exclude kit items since kits will be picked up later
$this->db->where("stock_type = '0'"); // stocked items only
$this->db->distinct();
$this->db->like('category', $search);
$this->db->order_by('category', 'asc');
foreach($this->db->get()->result() as $row)
{
$suggestions[] = array('label' => $row->category);
}
//Search by supplier
$this->db->select('company_name');
$this->db->from('suppliers');
$this->db->like('company_name', $search);
// restrict to non deleted companies only if is_deleted is FALSE
$this->db->where('deleted', $filters['is_deleted']);
$this->db->distinct();
$this->db->order_by('company_name', 'asc');
foreach($this->db->get()->result() as $row)
{
$suggestions[] = array('label' => $row->company_name);
}
//Search by description
$this->db->select('item_id, name, description');
$this->db->from('items');
$this->db->where('deleted', $filters['is_deleted']);
$this->db->where("item_type = '0'"); // standard, exclude kit items since kits will be picked up later
$this->db->where("stock_type = '0'"); // stocked items only
$this->db->like('description', $search);
$this->db->order_by('description', 'asc');
foreach($this->db->get()->result() as $row)
{
$entry = array('value' => $row->item_id, 'label' => $row->name);
if(!array_walk($suggestions, function($value, $label) use ($entry) { return $entry['label'] != $label; } ))
{
$suggestions[] = $entry;
}
}
//Search by custom fields
if($filters['search_custom'] != FALSE)
{
$this->db->from('items');
$this->db->group_start();
$this->db->like('custom1', $search);
$this->db->or_like('custom2', $search);
$this->db->or_like('custom3', $search);
$this->db->or_like('custom4', $search);
$this->db->or_like('custom5', $search);
$this->db->or_like('custom6', $search);
$this->db->or_like('custom7', $search);
$this->db->or_like('custom8', $search);
$this->db->or_like('custom9', $search);
$this->db->or_like('custom10', $search);
$this->db->group_end();
$this->db->where("item_type = '0'"); // standard, exclude kit items since kits will be picked up later
$this->db->where("stock_type = '0'"); // stocked items only
$this->db->where('deleted', $filters['is_deleted']);
foreach($this->db->get()->result() as $row)
{
$suggestions[] = array('value' => $row->item_id, 'label' => $row->name);
}
}
}
//only return $limit suggestions
if(count($suggestions > $limit))
{

View File

@@ -42,6 +42,7 @@ class Sale extends CI_Model
'(
SELECT sales_items_taxes.sale_id AS sale_id,
sales_items_taxes.item_id AS item_id,
sales_items_taxes.line AS line,
' . "
IFNULL(ROUND($sale_tax, $decimals), 0) AS tax
" . '
@@ -51,7 +52,7 @@ class Sale extends CI_Model
INNER JOIN ' . $this->db->dbprefix('sales_items') . ' AS sales_items
ON sales_items.sale_id = sales_items_taxes.sale_id AND sales_items.line = sales_items_taxes.line
WHERE sales.sale_id = ' . $this->db->escape($sale_id) . '
GROUP BY sale_id, item_id
GROUP BY sale_id, item_id, line
)'
);
@@ -60,7 +61,9 @@ class Sale extends CI_Model
MAX(DATE(sales.sale_time)) AS sale_date,
MAX(sales.sale_time) AS sale_time,
MAX(sales.comment) AS comment,
MAX(sales.sale_status) AS sale_status,
MAX(sales.invoice_number) AS invoice_number,
MAX(sales.quote_number) AS quote_number,
MAX(sales.employee_id) AS employee_id,
MAX(sales.customer_id) AS customer_id,
MAX(CONCAT(customer_p.first_name, " ", customer_p.last_name)) AS customer_name,
@@ -81,7 +84,9 @@ class Sale extends CI_Model
$this->db->join('people AS customer_p', 'sales.customer_id = customer_p.person_id', 'left');
$this->db->join('customers AS customer', 'sales.customer_id = customer.person_id', 'left');
$this->db->join('sales_payments_temp AS payments', 'sales.sale_id = payments.sale_id', 'left outer');
$this->db->join('sales_items_taxes_temp AS sales_items_taxes', 'sales_items.sale_id = sales_items_taxes.sale_id AND sales_items.item_id = sales_items_taxes.item_id', 'left outer');
$this->db->join('sales_items_taxes_temp AS sales_items_taxes',
'sales_items.sale_id = sales_items_taxes.sale_id AND sales_items.item_id = sales_items_taxes.item_id AND sales_items.line = sales_items_taxes.line',
'left outer');
$this->db->where('sales.sale_id', $sale_id);
@@ -108,11 +113,11 @@ class Sale extends CI_Model
if (empty($this->config->item('date_or_time_format')))
{
$where .= 'DATE(sales.sale_time) BETWEEN ' . $this->db->escape($filters['start_date']) . ' AND ' . $this->db->escape($filters['end_date']) . ' ';
$where .= 'DATE(sales.sale_time) BETWEEN ' . $this->db->escape($filters['start_date']) . ' AND ' . $this->db->escape($filters['end_date']) . ' AND sales.sale_status = 0 ';
}
else
{
$where .= 'sales.sale_time BETWEEN ' . $this->db->escape(rawurldecode($filters['start_date'])) . ' AND ' . $this->db->escape(rawurldecode($filters['end_date'])) . ' ';
$where .= 'sales.sale_time BETWEEN ' . $this->db->escape(rawurldecode($filters['start_date'])) . ' AND ' . $this->db->escape(rawurldecode($filters['end_date'])) . ' AND sales.sale_status = 0 ';
}
// NOTE: temporary tables are created to speed up searches due to the fact that they are ortogonal to the main query
@@ -156,6 +161,7 @@ class Sale extends CI_Model
(
SELECT sales_items_taxes.sale_id AS sale_id,
sales_items_taxes.item_id AS item_id,
sales_items_taxes.line AS line,
' . "
IFNULL(ROUND($sale_tax, $decimals), 0) AS tax
" . '
@@ -165,7 +171,7 @@ class Sale extends CI_Model
INNER JOIN ' . $this->db->dbprefix('sales_items') . ' AS sales_items
ON sales_items.sale_id = sales_items_taxes.sale_id AND sales_items.line = sales_items_taxes.line
WHERE ' . $where . '
GROUP BY sale_id, item_id
GROUP BY sale_id, item_id, line
)'
);
@@ -174,6 +180,7 @@ class Sale extends CI_Model
MAX(DATE(sales.sale_time)) AS sale_date,
MAX(sales.sale_time) AS sale_time,
MAX(sales.invoice_number) AS invoice_number,
MAX(sales.quote_number) AS quote_number,
SUM(sales_items.quantity_purchased) AS items_purchased,
MAX(CONCAT(customer_p.first_name, " ", customer_p.last_name)) AS customer_name,
MAX(customer.company_name) AS company_name,
@@ -195,7 +202,9 @@ class Sale extends CI_Model
$this->db->join('people AS customer_p', 'sales.customer_id = customer_p.person_id', 'left');
$this->db->join('customers AS customer', 'sales.customer_id = customer.person_id', 'left');
$this->db->join('sales_payments_temp AS payments', 'sales.sale_id = payments.sale_id', 'left outer');
$this->db->join('sales_items_taxes_temp AS sales_items_taxes', 'sales_items.sale_id = sales_items_taxes.sale_id AND sales_items.item_id = sales_items_taxes.item_id', 'left outer');
$this->db->join('sales_items_taxes_temp AS sales_items_taxes',
'sales_items.sale_id = sales_items_taxes.sale_id AND sales_items.item_id = sales_items_taxes.item_id AND sales_items.line = sales_items_taxes.line',
'left outer');
$this->db->where($where);
@@ -486,8 +495,15 @@ class Sale extends CI_Model
return $success;
}
public function save($items, $customer_id, $employee_id, $comment, $invoice_number, $payments, $dinner_table, $sale_id = FALSE)
/*
* Save the sale information after the sales is complete but before the final document is printed
* The sales_taxes variable needs to be initialized to an empty array before calling
*/
public function save(&$sale_status, &$items, $customer_id, $employee_id, $comment, $invoice_number, $quote_number, $payments, $dinner_table, &$sales_taxes, $sale_id = FALSE)
{
$tax_decimals = $this->config->item('tax_decimals');
if(count($items) == 0)
{
return -1;
@@ -499,7 +515,9 @@ class Sale extends CI_Model
'employee_id' => $employee_id,
'comment' => $comment,
'invoice_number' => $invoice_number,
'dinner_table_id'=> $dinner_table
'quote_number' => $quote_number,
'dinner_table_id'=> $dinner_table,
'sale_status' => $sale_status
);
// Run these queries as a transaction, we want to make sure we do all or nothing
@@ -554,6 +572,10 @@ class Sale extends CI_Model
}
}
$customer = $this->Customer->get_info($customer_id);
$sales_taxes = array();
foreach($items as $line=>$item)
{
$cur_item_info = $this->Item->get_info($item['item_id']);
@@ -602,22 +624,82 @@ class Sale extends CI_Model
);
$this->Inventory->insert($inv_data);
$customer = $this->Customer->get_info($customer_id);
// Calculate taxes and save the tax information for the sale. Return the result for printing
if($customer_id == -1 || $customer->taxable)
{
if($this->config->item('tax_included'))
{
$tax_type = Tax_lib::TAX_TYPE_VAT;
}
else
{
$tax_type = Tax_lib::TAX_TYPE_SALES;
}
$rounding_code = Rounding_code::HALF_UP; // half adjust
$tax_group_sequence = 0;
$item_total = $this->sale_lib->get_item_total($item['quantity'], $item['price'], $item['discount'], TRUE);
$tax_basis = $item_total;
$item_tax_amount = 0;
foreach($this->Item_taxes->get_info($item['item_id']) as $row)
{
$this->db->insert('sales_items_taxes', array(
'sale_id' => $sale_id,
'item_id' => $item['item_id'],
'line' => $item['line'],
'name' => $row['name'],
'percent' => $row['percent']
));
$sales_items_taxes = array(
'sale_id' => $sale_id,
'item_id' => $item['item_id'],
'line' => $item['line'],
'name' => character_limiter($row['name'], 255),
'percent' => $row['percent'],
'tax_type' => $tax_type,
'rounding_code' => $rounding_code,
'cascade_tax' => 0,
'cascade_sequence' => 0,
'item_tax_amount' => 0
);
// This computes tax for each line item and adds it to the tax type total
$tax_group = (float)$row['percent'] . '% ' . $row['name'];
$tax_basis = $this->sale_lib->get_item_total($item['quantity'], $item['price'], $item['discount'], TRUE);
if($this->config->item('tax_included'))
{
$tax_type = Tax_lib::TAX_TYPE_VAT;
$item_tax_amount = $this->sale_lib->get_item_tax($item['quantity'], $item['price'], $item['discount'],$row['percent']);
}
elseif($this->config->item('customer_sales_tax_support') == '0')
{
$tax_type = Tax_lib::TAX_TYPE_SALES;
$item_tax_amount = $this->tax_lib->get_sales_tax_for_amount($tax_basis, $row['percent'], '0', $tax_decimals);
}
else
{
$tax_type = Tax_lib::TAX_TYPE_SALES;
}
$sales_items_taxes['item_tax_amount'] = $item_tax_amount;
if ($item_tax_amount != 0)
{
$this->db->insert('sales_items_taxes', $sales_items_taxes);
$this->tax_lib->update_sales_taxes($sales_taxes, $tax_type, $tax_group, $row['percent'], $tax_basis, $item_tax_amount, $tax_group_sequence, $rounding_code, $sale_id, $row['name'], '');
$tax_group_sequence += 1;
}
}
if($this->config->item('customer_sales_tax_support') == '1')
{
$this->save_sales_item_tax($customer, $sale_id, $item, $item_total, $sales_taxes, $sequence, $cur_item_info->tax_category_id);
}
}
}
if($customer_id == -1 || $customer->taxable)
{
$this->tax_lib->round_sales_taxes($sales_taxes);
$this->save_sales_tax($sales_taxes);
}
$this->db->trans_complete();
if($this->db->trans_status() === FALSE)
@@ -628,6 +710,47 @@ class Sale extends CI_Model
return $sale_id;
}
/**
* Apply customer sales tax if the customer sales tax is enabledl
* The original tax is still supported if the user configures it,
* but it won't make sense unless it's used exclusively for the purpose
* of VAT tax which becomes a price component. VAT taxes must still be reported
* as a separate tax entry on the invoice.
*/
public function save_sales_item_tax(&$customer, &$sale_id, &$item, $tax_basis, &$sales_taxes, &$sequence, $tax_category_id)
{
// if customer sales tax is enabled then update sales_items_taxes with the
if($this->config->item('customer_sales_tax_support') == '1')
{
$register_mode = $this->config->item('default_register_mode');
$tax_details = $this->tax_lib->apply_sales_tax($item, $customer->city, $customer->state, $customer->sales_tax_code, $register_mode, $sale_id, $sales_taxes);
$sales_items_taxes = array(
'sale_id' => $sale_id,
'item_id' => $item['item_id'],
'line' => $item['line'],
'name' => $tax_details['tax_name'],
'percent' => $tax_details['tax_rate'],
'tax_type' => Tax_lib::TAX_TYPE_SALES,
'rounding_code' => $tax_details['rounding_code'],
'cascade_tax' => 0,
'cascade_sequence' => 0,
'item_tax_amount' => $tax_details['item_tax_amount']
);
$this->db->insert('sales_items_taxes', $sales_items_taxes);
}
}
private function save_sales_tax(&$sales_taxes)
{
foreach($sales_taxes as $line=>$sales_tax)
{
$this->db->insert('sales_taxes', $sales_tax);
}
}
public function delete_list($sale_ids, $employee_id, $update_inventory = TRUE)
{
$result = TRUE;
@@ -815,8 +938,8 @@ class Sale extends CI_Model
// TODO change to use new quote_number field
public function check_quote_number_exists($quote_number, $sale_id = '')
{
$this->db->from('sales_suspended');
$this->db->where('invoice_number', $quote_number);
$this->db->from('sales');
$this->db->where('quote_number', $quote_number);
if(!empty($sale_id))
{
$this->db->where('sale_id !=', $sale_id);
@@ -894,6 +1017,7 @@ class Sale extends CI_Model
(
SELECT sales_items_taxes.sale_id AS sale_id,
sales_items_taxes.item_id AS item_id,
sales_items_taxes.line AS line,
' . "
IFNULL(ROUND($sale_tax, $decimals), 0) AS tax
" . '
@@ -902,8 +1026,8 @@ class Sale extends CI_Model
ON sales.sale_id = sales_items_taxes.sale_id
INNER JOIN ' . $this->db->dbprefix('sales_items') . ' AS sales_items
ON sales_items.sale_id = sales_items_taxes.sale_id AND sales_items.line = sales_items_taxes.line
WHERE ' . $where . '
GROUP BY sale_id, item_id
WHERE sales.sale_status = 0 AND ' . $where . '
GROUP BY sale_id, item_id, line
)'
);
@@ -917,7 +1041,7 @@ class Sale extends CI_Model
FROM ' . $this->db->dbprefix('sales_payments') . ' AS payments
INNER JOIN ' . $this->db->dbprefix('sales') . ' AS sales
ON sales.sale_id = payments.sale_id
WHERE ' . $where . '
WHERE sales.sale_status = 0 AND ' . $where . '
GROUP BY payments.sale_id
)'
);
@@ -931,6 +1055,7 @@ class Sale extends CI_Model
sales.sale_id AS sale_id,
MAX(sales.comment) AS comment,
MAX(sales.invoice_number) AS invoice_number,
MAX(sales.quote_number) AS quote_number,
MAX(sales.customer_id) AS customer_id,
MAX(CONCAT(customer_p.first_name, " ", customer_p.last_name)) AS customer_name,
MAX(customer_p.first_name) AS customer_first_name,
@@ -977,8 +1102,8 @@ class Sale extends CI_Model
LEFT OUTER JOIN ' . $this->db->dbprefix('people') . ' AS employee
ON sales.employee_id = employee.person_id
LEFT OUTER JOIN ' . $this->db->dbprefix('sales_items_taxes_temp') . ' AS sales_items_taxes
ON sales_items.sale_id = sales_items_taxes.sale_id AND sales_items.item_id = sales_items_taxes.item_id
WHERE ' . $where . '
ON sales_items.sale_id = sales_items_taxes.sale_id AND sales_items.item_id = sales_items_taxes.item_id AND sales_items.line = sales_items_taxes.line
WHERE sales.sale_status = 0 AND ' . $where . '
GROUP BY sale_id, item_id, line
)'
);
@@ -987,5 +1112,92 @@ class Sale extends CI_Model
$this->db->query('DROP TEMPORARY TABLE IF EXISTS ' . $this->db->dbprefix('sales_payments_temp'));
$this->db->query('DROP TEMPORARY TABLE IF EXISTS ' . $this->db->dbprefix('sales_items_taxes_temp'));
}
/*
* Retrieves all sales that are in a suspended state
*/
public function get_all_suspended($customer_id = NULL)
{
if ($customer_id == -1)
{
$query = $this->db->query('select sale_id, sale_id as suspended_sale_id, sale_status, sale_time, dinner_table_id, customer_id, comment from '
. $this->db->dbprefix('sales') . ' where sale_status = 1 '
. ' union select sale_id, sale_id*-1 as suspended_sale_id, 2 as sale_status, sale_time, dinner_table_id, customer_id, comment from '
. $this->db->dbprefix('sales_suspended'));
}
else
{
$query = $this->db->query('select sale_id, sale_id as suspended_sale_id, sale_status, sale_time, dinner_table_id, customer_id, comment from '
. $this->db->dbprefix('sales') . ' where sale_status = 1 and customer_id = ' . $customer_id
. ' union select sale_id, sale_id*-1 as suspended_sale_id, 2 as sale_status, sale_time, dinner_table_id, customer_id, comment from '
. $this->db->dbprefix('sales_suspended') . ' where customer_id = ' . $customer_id);
}
return $query->result_array();
}
/*
* get the dinner table for the selected sale
*/
public function get_dinner_table($sale_id)
{
$this->db->from('sales');
$this->db->where('sale_id', $sale_id);
return $this->db->get()->row()->dinner_table_id;
}
/*
* Gets total of suspended invoices rows
*/
public function get_suspended_invoice_count()
{
$this->db->from('sales');
$this->db->where('invoice_number IS NOT NULL');
$this->db->where('sale_status', '1');
return $this->db->count_all_results();
}
/*
* This will remove a selected sale from the sales table.
* This function should only be called for suspended sales that are being restored to the current cart
*/
public function delete_suspended_sale($sale_id)
{
//Run these queries as a transaction, we want to make sure we do all or nothing
$this->db->trans_start();
$dinner_table = $this->get_dinner_table($sale_id);
$dinner_table_data = array(
'status' => 0
);
$this->db->where('dinner_table_id',$dinner_table);
$this->db->update('dinner_tables', $dinner_table_data);
$this->db->delete('sales_payments', array('sale_id' => $sale_id));
$this->db->delete('sales_items_taxes', array('sale_id' => $sale_id));
$this->db->delete('sales_items', array('sale_id' => $sale_id));
$this->db->delete('sales_taxes', array('sale_id' => $sale_id));
$this->db->delete('sales', array('sale_id' => $sale_id));
$this->db->trans_complete();
return $this->db->trans_status();
}
public function get_suspended_sale_info($sale_id)
{
$this->db->from('sales');
$this->db->where('sale_id', $sale_id);
$this->db->join('people', 'people.person_id = sales_suspended.customer_id', 'LEFT');
return $this->db->get();
}
}
?>

375
application/models/Tax.php Normal file
View File

@@ -0,0 +1,375 @@
<?php
class Tax extends CI_Model
{
/*
Determines if a given tax_code is on file
*/
public function exists($tax_code)
{
$this->db->from('tax_codes');
$this->db->where('tax_code', $tax_code);
return ($this->db->get()->num_rows() == 1);
}
public function tax_rate_exists($tax_code, $tax_category_id)
{
$this->db->from('tax_code_rates');
$this->db->where('rate_tax_code', $tax_code);
$this->db->where('rate_tax_category_id', $tax_category_id);
return ($this->db->get()->num_rows() == 1);
}
/*
Gets total of rows
*/
public function get_total_rows()
{
$this->db->from('tax_codes');
return $this->db->count_all_results();
}
/*
Gets information about a particular tax_code
*/
public function get_info($tax_code)
{
$this->db->from('tax_codes');
$this->db->join('tax_code_rates',
'tax_code = rate_tax_code and rate_tax_category_id = 0', 'LEFT');
$this->db->join('tax_categories',
'rate_tax_category_id = tax_category_id');
$this->db->where('tax_code', $tax_code);
$query = $this->db->get();
if($query->num_rows() == 1)
{
return $query->row();
}
else
{
//Get empty base parent object
$tax_code_obj = new stdClass();
//Get all the fields from tax_codes table
foreach($this->db->list_fields('tax_codes') as $field)
{
$tax_code_obj->$field = '';
}
foreach($this->db->list_fields('tax_code_rates') as $field)
{
$tax_code_obj->$field = '';
}
return $tax_code_obj;
}
}
/*
Gets information about a particular tax_code
*/
public function get_rate_info($tax_code, $tax_category_id)
{
$this->db->from('tax_code_rates');
$this->db->join('tax_categories',
'rate_tax_category_id = tax_category_id');
$this->db->where('rate_tax_code', $tax_code);
$this->db->where('rate_tax_category_id', $tax_category_id);
$query = $this->db->get();
if($query->num_rows() == 1)
{
return $query->row();
}
else
{
//Get empty base parent object
$tax_rate_obj = new stdClass();
//Get all the fields from tax_codes table
foreach($this->db->list_fields('tax_code_rates') as $field)
{
$tax_rate_obj->$field = '';
}
//Get all the fields from tax_code_rates table
foreach($this->db->list_fields('tax_categories') as $field)
{
$tax_rate_obj->$field = '';
}
return $tax_rate_obj;
}
}
/*
* Gets the tax code to use for a given customer
*/
public function get_sales_tax_code($city = '', $state = '')
{
// if tax code using both city and state cannot be found then try again using just the state
// if the state tax code cannot be found then try again using blanks for both
$this->db->from('tax_codes');
$this->db->where('city', $city);
$this->db->where('state', $state);
$this->db->where('tax_code_type', '0'); // sales tax
$query = $this->db->get();
if($query->num_rows() == 1)
{
return $query->row()->tax_code;
}
else
{
$this->db->from('tax_codes');
$this->db->where('city', '');
$this->db->where('state', $state);
$this->db->where('tax_code_type', '0'); // sales tax
$query = $this->db->get();
if($query->num_rows() == 1)
{
return $query->row()->tax_code;
}
else
{
return $this->config->item('default_origin_tax_code');
}
}
return FALSE;
}
/*
Inserts or updates a tax_codes entry
*/
public function save(&$tax_code_data, $tax_rate_data, $tax_code = -1)
{
if(!$this->exists($tax_code))
{
if($this->db->insert('tax_codes', $tax_code_data))
{
$this->save_tax_rates($tax_rate_data, $tax_code);
return TRUE;
}
return FALSE;
}
$this->db->where('tax_code', $tax_code);
if ($this->db->update('tax_codes', $tax_code_data))
{
$this->save_tax_rates($tax_rate_data, $tax_code);
return TRUE;
}
else
{
return FALSE;
}
}
public function save_tax_rates(&$tax_rate_data, $tax_code)
{
if(!$this->tax_rate_exists($tax_code, $tax_rate_data['rate_tax_category_id']))
{
if($this->db->insert('tax_code_rates', $tax_rate_data))
{
return TRUE;
}
return FALSE;
}
$this->db->where('rate_tax_code', $tax_code);
$this->db->where('rate_tax_category_id', $tax_rate_data['rate_tax_category_id']);
return $this->db->update('tax_code_rates', $tax_rate_data);
}
/*
Inserts or updates an item kit's items
*/
public function save_tax_rate_exceptions(&$tax_rate_data, $tax_code)
{
$success = TRUE;
//Run these queries as a transaction, we want to make sure we do all or nothing
$this->db->trans_start();
// Delete all exceptions for the given tax_code
$this->delete_tax_rate_exceptions($tax_code);
if ($tax_rate_data != NULL) {
foreach ($tax_rate_data as $row) {
$row['rate_tax_code'] = $tax_code;
$success &= $this->db->insert('tax_code_rates', $row);
}
}
$this->db->trans_complete();
$success &= $this->db->trans_status();
return $success;
}
/*
Deletes one tax_codes entry
*/
public function delete($tax_code)
{
return $this->db->delete('tax_codes', array('tax_code' => $tax_code));
}
/*
Deletes a list of tax codes
*/
public function delete_list($tax_codes)
{
$this->db->where_in('tax_code', $tax_codes);
return $this->db->delete('tax_codes');
}
/*
Deletes all tax_rate_exceptions for given tax codes
*/
public function delete_tax_rate_exceptions($tax_code)
{
$this->db->where('rate_tax_code', $tax_code);
$this->db->where('rate_tax_category_id !=', 0);
return $this->db->delete('tax_code_rates');
}
/*
Performs a search on tax_codes
*/
public function search($search, $rows = 0, $limit_from = 0, $sort = 'tax_code', $order = 'asc')
{
$this->db->from('tax_codes');
$this->db->join('tax_code_rates',
'tax_code = rate_tax_code and rate_tax_category_id = 0', 'LEFT');
if (!empty($search)) {
$this->db->like('tax_code', $search);
$this->db->or_like('tax_code_name', $search);
}
$this->db->order_by($sort, $order);
if($rows > 0)
{
$this->db->limit($rows, $limit_from);
}
return $this->db->get();
}
/*
Gets tax_codes
*/
public function get_found_rows($search)
{
$this->db->from('tax_codes');
if (!empty($search)) {
$this->db->like('tax_code', $search);
$this->db->or_like('tax_code_name', $search);
}
return $this->db->get()->num_rows();
}
public function get_tax_code_type_name($tax_code_type) {
if ($tax_code_type == '0')
{
return $this->lang->line('taxes_sales_tax');
}
else
{
return $this->lang->line('taxes_vat_tax');
}
}
public function get_sales_tax_codes_search_suggestions($search, $limit = 25)
{
$suggestions = array();
$this->db->from('tax_codes');
if (!empty($search)) {
$this->db->like('tax_code', $search);
$this->db->or_like('tax_code_name', $search);
}
$this->db->order_by('tax_code_name', 'asc');
foreach($this->db->get()->result() as $row)
{
$suggestions[] = array('value' => $row->tax_code, 'label' => ($row->tax_code . ' ' . $row->tax_code_name));
}
//only return $limit suggestions
if(count($suggestions > $limit))
{
$suggestions = array_slice($suggestions, 0,$limit);
}
return $suggestions;
}
public function get_tax_category_suggestions($search)
{
$suggestions = array();
$this->db->from('tax_categories');
$this->db->where('tax_category_id !=', 0);
if (!empty($search)) {
$this->db->like('tax_category', '%'.$search.'%');
}
$this->db->order_by('tax_category', 'asc');
foreach($this->db->get()->result() as $row)
{
$suggestions[] = array('value' => $row->tax_category_id, 'label' => $row->tax_category);
}
return $suggestions;
}
public function get_tax_category($tax_category_id)
{
$this->db->select('tax_category');
$this->db->from('tax_categories');
$this->db->where('tax_category_id', $tax_category_id);
return $this->db->get()->row()->tax_category;
}
public function get_all_tax_categories()
{
$this->db->from('tax_categories');
$this->db->order_by('tax_category_id');
return $this->db->get();
}
public function get_tax_category_id($tax_category)
{
$this->db->select('tax_category_id');
$this->db->from('tax_categories');
return $this->db->get()->row()->tax_category_id;
}
public function get_tax_code_rate_exceptions($tax_code)
{
$this->db->from('tax_code_rates');
$this->db->join('tax_categories', 'rate_tax_category_id = tax_category_id');
$this->db->where('rate_tax_code', $tax_code);
$this->db->where('rate_tax_category_id !=', 0);
$this->db->order_by('tax_category', 'asc');
return $this->db->get()->result_array();
}
}
?>

View File

@@ -0,0 +1,80 @@
<?php
class Rounding_code
{
const HALF_UP = 0;
const HALF_DOWN = 1;
const HALF_EVEN = 2;
const HALF_ODD = 3;
const ROUND_UP = 4;
const ROUND_DOWN = 5;
const HALF_FIVE = 6;
public static function get_rounding_options()
{
$CI =& get_instance();
$CI->load->helper('language');
return array(
Rounding_code::HALF_UP => lang('enum_half_up'),
Rounding_code::HALF_DOWN => lang('enum_half_down'),
Rounding_code::HALF_EVEN => lang('enum_half_even'),
Rounding_code::HALF_ODD => lang('enum_half_odd'),
Rounding_code::ROUND_UP => lang('enum_round_up'),
Rounding_code::ROUND_DOWN => lang('enum_round_down'),
Rounding_code::HALF_FIVE => lang('enum_half_five')
);
}
public static function get_rounding_code_name($rounding_code)
{
$CI =& get_instance();
$CI->load->helper('language');
if($rounding_code == Rounding_code::HALF_UP)
{
return lang('enum_half_up');
}
elseif($rounding_code == Rounding_code::HALF_DOWN)
{
return lang('enum_half_down');
}
elseif($rounding_code == Rounding_code::HALF_EVEN)
{
return lang('enum_half_even');
}
elseif($rounding_code == Rounding_code::HALF_ODD)
{
return lang('enum_half_odd');
}
elseif($rounding_code == Rounding_code::ROUND_UP)
{
return lang('enum_round_up');
}
elseif($rounding_code == Rounding_code::ROUND_DOWN)
{
return lang('enum_round_down');
}
elseif($rounding_code == Rounding_code::HALF_FIVE)
{
return lang('enum_half_five');
}
else
{
return lang('common_unknown');
}
}
public static function get_html_rounding_options()
{
$CI =& get_instance();
$CI->load->helper('language');
$x = "<option value='0' selected='selected'>".lang('enum_half_up')."</option>" .
"<option value='1'>".lang('enum_half_down')."</option>" .
"<option value='2'>".lang('enum_half_even')."</option>" .
"<option value='3'>".lang('enum_half_odd')."</option>" .
"<option value='4'>".lang('enum_round_up')."</option>" .
"<option value='5'>".lang('enum_round_down')."</option>" .
"<option value='6'>".lang('enum_half_five')."</option>";
return $x;
}
}

View File

@@ -53,6 +53,7 @@ abstract class Summary_report extends Report
(
SELECT sales_items_taxes.sale_id AS sale_id,
sales_items_taxes.item_id AS item_id,
sales_items_taxes.line AS line,
' . "
IFNULL(ROUND($sale_tax, $decimals), 0) AS tax
" . '
@@ -61,8 +62,8 @@ abstract class Summary_report extends Report
ON sales.sale_id = sales_items_taxes.sale_id
INNER JOIN ' . $this->db->dbprefix('sales_items') . ' AS sales_items
ON sales_items.sale_id = sales_items_taxes.sale_id AND sales_items.line = sales_items_taxes.line
WHERE ' . $where . '
GROUP BY sale_id, item_id
WHERE sale_status = 0 AND ' . $where . '
GROUP BY sale_id, item_id, line
)'
);
@@ -79,7 +80,9 @@ abstract class Summary_report extends Report
{
$this->db->from('sales_items AS sales_items');
$this->db->join('sales AS sales', 'sales_items.sale_id = sales.sale_id', 'inner');
$this->db->join('sales_items_taxes_temp AS sales_items_taxes', 'sales_items.sale_id = sales_items_taxes.sale_id AND sales_items.item_id = sales_items_taxes.item_id', 'left outer');
$this->db->join('sales_items_taxes_temp AS sales_items_taxes',
'sales_items.sale_id = sales_items_taxes.sale_id AND sales_items.item_id = sales_items_taxes.item_id AND sales_items.line = sales_items_taxes.line',
'left outer');
}
private function _common_where(array $inputs)

View File

@@ -23,11 +23,11 @@ class Summary_taxes extends Summary_report
{
if(empty($this->config->item('date_or_time_format')))
{
$this->db->where('DATE(sales.sale_time) BETWEEN ' . $this->db->escape($inputs['start_date']) . ' AND ' . $this->db->escape($inputs['end_date']));
$this->db->where('sale_status = 0 AND DATE(sales.sale_time) BETWEEN ' . $this->db->escape($inputs['start_date']) . ' AND ' . $this->db->escape($inputs['end_date']));
}
else
{
$this->db->where('sales.sale_time BETWEEN ' . $this->db->escape(rawurldecode($inputs['start_date'])) . ' AND ' . $this->db->escape(rawurldecode($inputs['end_date'])));
$this->db->where('sale_status = 0 AND sales.sale_time BETWEEN ' . $this->db->escape(rawurldecode($inputs['start_date'])) . ' AND ' . $this->db->escape(rawurldecode($inputs['end_date'])));
}
}
@@ -37,11 +37,11 @@ class Summary_taxes extends Summary_report
if(empty($this->config->item('date_or_time_format')))
{
$where .= 'WHERE DATE(sale_time) BETWEEN ' . $this->db->escape($inputs['start_date']) . ' AND ' . $this->db->escape($inputs['end_date']);
$where .= 'WHERE sale_status = 0 AND DATE(sale_time) BETWEEN ' . $this->db->escape($inputs['start_date']) . ' AND ' . $this->db->escape($inputs['end_date']);
}
else
{
$where .= 'WHERE sale_time BETWEEN ' . $this->db->escape(rawurldecode($inputs['start_date'])) . ' AND ' . $this->db->escape(rawurldecode($inputs['end_date']));
$where .= 'WHERE sale_status = 0 AND sale_time BETWEEN ' . $this->db->escape(rawurldecode($inputs['start_date'])) . ' AND ' . $this->db->escape(rawurldecode($inputs['end_date']));
}
if($this->config->item('tax_included'))

View File

@@ -12,19 +12,19 @@
</div>
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('config_default_tax_rate_1'), 'default_tax_1_rate', array('class' => 'control-label col-xs-2 required')); ?>
<?php echo form_label($this->lang->line('config_default_tax_rate_1'), 'default_tax_1_rate', array('class' => 'control-label col-xs-2')); ?>
<div class='col-xs-2'>
<?php echo form_input(array(
'name' => 'default_tax_1_name',
'id' => 'default_tax_1_name',
'class' => 'form-control input-sm required',
'class' => 'form-control input-sm',
'value'=>$this->config->item('default_tax_1_name')!==FALSE ? $this->config->item('default_tax_1_name') : $this->lang->line('items_sales_tax_1'))); ?>
</div>
<div class="col-xs-1 input-group">
<?php echo form_input(array(
'name' => 'default_tax_1_rate',
'id' => 'default_tax_1_rate',
'class' => 'form-control input-sm required',
'class' => 'form-control input-sm',
'value'=>to_tax_decimals($this->config->item('default_tax_1_rate')))); ?>
<span class="input-group-addon input-sm">%</span>
</div>
@@ -60,7 +60,29 @@
</div>
</div>
<div class="form-group form-group-sm">
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('config_customer_sales_tax_support'), 'customer_sales_tax_support', array('class' => 'control-label col-xs-2')); ?>
<div class='col-xs-2'>
<?php echo form_checkbox(array(
'name' => 'customer_sales_tax_support',
'id' => 'customer_sales_tax_support',
'value' => 'customer_sales_tax_support',
'checked'=>$this->config->item('customer_sales_tax_support'))); ?>
</div>
</div>
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('config_default_origin_tax_code'), 'default_origin_tax_code', array('class' => 'control-label col-xs-2')); ?>
<div class='col-xs-2'>
<?php echo form_input(array(
'name' => 'default_origin_tax_code',
'id' => 'default_origin_tax_code',
'class' => 'form-control input-sm',
'value'=>$this->config->item('default_origin_tax_code'))); ?>
</div>
</div>
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('config_default_sales_discount'), 'default_sales_discount', array('class' => 'control-label col-xs-2 required')); ?>
<div class='col-xs-2'>
<div class="input-group">
@@ -283,10 +305,8 @@ $(document).ready(function()
{
default_tax_1_rate:
{
required: true,
remote: "<?php echo site_url($controller_name . '/check_numeric')?>"
},
default_tax_1_name: "required",
default_tax2_rate:
{
remote: "<?php echo site_url($controller_name . '/check_numeric')?>"
@@ -307,14 +327,8 @@ $(document).ready(function()
{
default_tax_1_rate:
{
required: "<?php echo $this->lang->line('config_default_tax_rate_required'); ?>",
number: "<?php echo $this->lang->line('config_default_tax_rate_number'); ?>"
},
default_tax_1_name:
{
required: "<?php echo $this->lang->line('config_default_tax_name_required'); ?>",
number: "<?php echo $this->lang->line('config_default_tax_name_number'); ?>"
},
default_sales_discount:
{
required: "<?php echo $this->lang->line('config_default_sales_discount_required'); ?>",

View File

@@ -65,7 +65,8 @@
'0' => '0',
'1' => '1',
'2' => '2',
'3' => '3'
'3' => '3',
'4' => '4'
),
$this->config->item('tax_decimals'), array('class' => 'form-control input-sm'));
?>
@@ -86,7 +87,31 @@
</div>
</div>
<div class="form-group form-group-sm">
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('config_cash_decimals'), 'cash_decimals', array('class' => 'control-label col-xs-2')); ?>
<div class='col-xs-2'>
<?php echo form_dropdown('cash_decimals', array(
'0' => '0',
'1' => '1',
'2' => '2'
),
$this->config->item('cash_decimals'), array('class' => 'form-control input-sm'));
?>
</div>
<div class='col-xs-1'>
<span class="glyphicon glyphicon-info-sign" data-toggle="tootltip" data-placement="right" title="<?php echo $this->lang->line('config_cash_decimals_tooltip'); ?>"></span>
</div>
</div>
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('config_cash_rounding'), 'cash_rounding_code', array('class' => 'control-label col-xs-2')); ?>
<div class='col-xs-4'>
<?php echo form_dropdown('cash_rounding_code', $rounding_options, $this->config->item('cash_rounding_code'), array('class' => 'form-control input-sm'));
?>
</div>
</div>
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('config_payment_options_order'), 'payment_options_order', array('class' => 'control-label col-xs-2')); ?>
<div class='col-xs-4'>
<?php echo form_dropdown('payment_options_order', array(

View File

@@ -91,6 +91,26 @@
<?php echo form_checkbox('taxable', '1', $person_info->taxable == '' ? TRUE : (boolean)$person_info->taxable);?>
</div>
</div>
<?php if ($customer_sales_tax_enabled) { ?>
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('customers_tax_code'), 'sales_tax_code_name', array('class'=>'control-label col-xs-3')); ?>
<div class='col-xs-8'>
<div class="input-group input-group-sm">
<?php echo form_input(array(
'name'=>'sales_tax_code_name',
'id'=>'sales_tax_code_name',
'class'=>'form-control input-sm',
'size'=>'50',
'value'=>$sales_tax_code_label)
); ?>
<?php echo form_hidden('sales_tax_code', $person_info->sales_tax_code);?>
</div>
</div>
</div>
<?php } ?>
</fieldset>
<?php echo form_close(); ?>
@@ -142,4 +162,27 @@ $(document).ready(function()
}
}, form_support.error));
});
$("input[name='sales_tax_code_name']").change(function() {
if( ! $("input[name='sales_tax_code_name']").val() ) {
$("input[name='sales_tax_code']").val('');
}
});
var fill_value = function(event, ui) {
event.preventDefault();
$("input[name='sales_tax_code']").val(ui.item.value);
$("input[name='sales_tax_code_name']").val(ui.item.label);
};
$("#sales_tax_code_name").autocomplete({
source: '<?php echo site_url("taxes/suggest_sales_tax_codes"); ?>',
minChars: 0,
delay: 15,
cacheLength: 1,
appendTo: '.modal-content',
select: fill_value,
focus: fill_value
});
</script>

View File

@@ -166,7 +166,7 @@
</div>
</div>
<div class="form-group form-group-sm">
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('items_tax_2'), 'tax_percent_2', array('class'=>'control-label col-xs-3')); ?>
<div class='col-xs-4'>
<?php echo form_input(array(
@@ -189,7 +189,16 @@
</div>
</div>
<?php
<?php if($customer_sales_tax_enabled) { ?>
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('taxes_tax_category'), 'tax_category', array('class'=>'control-label col-xs-3')); ?>
<div class='col-xs-8'>
<?php echo form_dropdown('tax_category_id', $tax_categories, $selected_tax_category, array('class'=>'form-control')); ?>
</div>
</div>
<?php } ?>
<?php
foreach($stock_locations as $key=>$location_detail)
{
?>

View File

@@ -408,7 +408,7 @@ $(document).ready(function()
{
$("#item").autocomplete(
{
source: '<?php echo site_url($controller_name."/item_search"); ?>',
source: '<?php echo site_url($controller_name."/stock_item_search"); ?>',
minChars:0,
delay:10,
autoFocus: false,

View File

@@ -123,16 +123,16 @@ $(document).ready(function()
<tr>
<td colspan="3" class="blank-bottom"> </td>
<td colspan="2" class="total-line"><textarea rows="5" cols="6"><?php echo $this->lang->line('sales_sub_total'); ?></textarea></td>
<td class="total-value"><textarea rows="5" cols="6" id="subtotal"><?php echo to_currency($tax_exclusive_subtotal); ?></textarea></td>
<td class="total-value"><textarea rows="5" cols="6" id="subtotal"><?php echo to_currency($subtotal); ?></textarea></td>
</tr>
<?php
foreach($taxes as $name=>$value)
foreach($taxes as $tax_group_index=>$sales_tax)
{
?>
<tr>
<td colspan="3" class="blank"> </td>
<td colspan="2" class="total-line"><textarea rows="5" cols="6"><?php echo $name; ?>:</textarea></td>
<td class="total-value"><textarea rows="5" cols="6" id="taxes"><?php echo to_currency($value); ?></textarea></td>
<td colspan="2" class="total-line"><textarea rows="5" cols="6"><?php echo $sales_tax['tax_group']; ?></textarea></td>
<td class="total-value"><textarea rows="5" cols="6" id="taxes"><?php echo to_currency($sales_tax['sale_tax_amount']); ?></textarea></td>
</tr>
<?php
}
@@ -142,6 +142,45 @@ $(document).ready(function()
<td colspan="2" class="total-line"><textarea rows="5" cols="6"><?php echo $this->lang->line('sales_total'); ?></textarea></td>
<td class="total-value"><textarea rows="5" cols="6" id="total"><?php echo to_currency($total); ?></textarea></td>
</tr>
<?php
$only_sale_check = FALSE;
$show_giftcard_remainder = FALSE;
foreach($payments as $payment_id=>$payment)
{
$only_sale_check |= $payment['payment_type'] == $this->lang->line('sales_check');
$splitpayment = explode(':', $payment['payment_type']);
$show_giftcard_remainder |= $splitpayment[0] == $this->lang->line('sales_giftcard');
?>
<tr>
<td colspan="3" class="blank"> </td>
<td colspan="2" class="total-line"><textarea rows="5" cols="6"><?php echo $splitpayment[0]; ?></textarea></td>
<td class="total-value"><textarea rows="5" cols="6" id="paid"><?php echo to_currency( $payment['payment_amount'] * -1 ); ?></textarea></td>
</tr>
<?php
}
if(isset($cur_giftcard_value) && $show_giftcard_remainder)
{
?>
<tr>
<td colspan="3" class="blank"> </td>
<td colspan="2" class="total-line"><textarea rows="5" cols="6"><?php echo $this->lang->line('sales_giftcard_balance'); ?></textarea></td>
<td class="total-value"><textarea rows="5" cols="6" id="giftcard"><?php echo to_currency($cur_giftcard_value); ?></textarea></td>
</tr>
<?php
}
if(!empty($payments))
{
?>
<tr>
<td colspan="3" class="blank"> </td>
<td colspan="2" class="total-line"> <textarea rows="5" cols="6"><?php echo $this->lang->line($amount_change >= 0 ? ($only_sale_check ? 'sales_check_balance' : 'sales_change_due') : 'sales_amount_due') ; ?></textarea></td>
<td class="total-value"><textarea rows="5" cols="6" id="change"><?php echo to_currency($amount_change); ?></textarea></td>
</tr>
<?php
}
?>
</table>
<div id="terms">

View File

@@ -126,13 +126,13 @@ if (isset($error_message))
<td class="total-value"><textarea rows="5" cols="6" id="subtotal"><?php echo to_currency($tax_exclusive_subtotal); ?></textarea></td>
</tr>
<?php
foreach($taxes as $name=>$value)
foreach($taxes as $tax_group_index=>$sales_tax)
{
?>
<tr>
<td colspan="3" class="blank"> </td>
<td colspan="2" class="total-line"><textarea rows="5" cols="6"><?php echo $name; ?>:</textarea></td>
<td class="total-value"><textarea rows="5" cols="6" id="taxes"><?php echo to_currency($value); ?></textarea></td>
<td colspan="2" class="total-line"><textarea rows="5" cols="6"><?php echo $sales_tax['tax_group']; ?></textarea></td>
<td class="total-value"><textarea rows="5" cols="6" id="taxes"><?php echo to_currency($sales_tax['sale_tax_amount']); ?></textarea></td>
</tr>
<?php
}

View File

@@ -115,12 +115,12 @@
<td style='text-align:right;border-top:2px solid #000000;'><?php echo to_currency($this->config->item('tax_included') ? $tax_exclusive_subtotal : $discounted_subtotal); ?></td>
</tr>
<?php
foreach($taxes as $name=>$value)
foreach($taxes as $tax_group_index=>$sales_tax)
{
?>
<tr>
<td colspan="3" class="total-value"><?php echo $name; ?>:</td>
<td class="total-value"><?php echo to_currency($value); ?></td>
<td colspan="3" class="total-value"><?php echo $sales_tax['tax_group']; ?>:</td>
<td class="total-value"><?php echo to_currency($sales_tax['sale_tax_amount']); ?></td>
</tr>
<?php
}

View File

@@ -116,12 +116,12 @@
<td style='text-align:right;border-top:2px solid #000000;'><?php echo to_currency($this->config->item('tax_included') ? $tax_exclusive_subtotal : $discounted_subtotal); ?></td>
</tr>
<?php
foreach($taxes as $name=>$value)
foreach($taxes as $tax_group_index=>$sales_tax)
{
?>
<tr>
<td colspan="2" class="total-value"><?php echo $name; ?>:</td>
<td class="total-value"><?php echo to_currency($value); ?></td>
<td colspan="2" class="total-value"><?php echo $sales_tax['tax_group']; ?>:</td>
<td class="total-value"><?php echo to_currency($sales_tax['sale_tax_amount']); ?></td>
</tr>
<?php
}

View File

@@ -343,12 +343,12 @@ if (isset($success))
</tr>
<?php
foreach($taxes as $name=>$value)
foreach($taxes as $tax_group_index=>$sales_tax)
{
?>
<tr>
<th style='width: 55%;'><?php echo $name; ?></th>
<th style="width: 45%; text-align: right;"><?php echo to_currency($value); ?></th>
<th style='width: 55%;'><?php echo $sales_tax['tax_group']; ?></th>
<th style="width: 45%; text-align: right;"><?php echo to_currency($sales_tax['sale_tax_amount']); ?></th>
</tr>
<?php
}
@@ -356,7 +356,7 @@ if (isset($success))
<tr>
<th style='width: 55%;'><?php echo $this->lang->line('sales_total'); ?></th>
<th style="width: 45%; text-align: right;"><?php echo to_currency($total); ?></th>
<th style="width: 45%; text-align: right;"><span id="sale_total"><?php echo to_currency($total); ?></span></th>
</tr>
</table>
@@ -372,7 +372,7 @@ if (isset($success))
</tr>
<tr>
<th style="width: 55%;"><?php echo $this->lang->line('sales_amount_due');?></th>
<th style="width: 45%; text-align: right;"><?php echo to_currency($amount_due); ?></th>
<th style="width: 45%; text-align: right;"><span id="sale_amount_due"><?php echo to_currency($amount_due); ?></span></th>
</tr>
</table>
@@ -387,7 +387,7 @@ if (isset($success))
<tr>
<td><?php echo $this->lang->line('sales_payment');?></td>
<td>
<?php echo form_dropdown('payment_type', $payment_options, array(), array('id'=>'payment_types', 'class'=>'selectpicker show-menu-arrow', 'data-style'=>'btn-default btn-sm', 'data-width'=>'auto', 'disabled'=>'disabled')); ?>
<?php echo form_dropdown('payment_type', $payment_options, $selected_payment_type, array('id'=>'payment_types', 'class'=>'selectpicker show-menu-arrow', 'data-style'=>'btn-default btn-sm', 'data-width'=>'auto', 'disabled'=>'disabled')); ?>
</td>
</tr>
<tr>
@@ -417,7 +417,7 @@ if (isset($success))
<tr>
<td><?php echo $this->lang->line('sales_payment');?></td>
<td>
<?php echo form_dropdown('payment_type', $payment_options, array(), array('id'=>'payment_types', 'class'=>'selectpicker show-menu-arrow', 'data-style'=>'btn-default btn-sm', 'data-width'=>'auto')); ?>
<?php echo form_dropdown('payment_type', $payment_options, $selected_payment_type, array('id'=>'payment_types', 'class'=>'selectpicker show-menu-arrow', 'data-style'=>'btn-default btn-sm', 'data-width'=>'fit')); ?>
</td>
</tr>
<tr>
@@ -693,7 +693,7 @@ $(document).ready(function()
$('#add_payment_form').submit();
});
$("#payment_types").change(check_payment_type_giftcard).ready(check_payment_type_giftcard);
$("#payment_types").change(check_payment_type).ready(check_payment_type);
$("#cart_contents input").keypress(function(event)
{
@@ -752,18 +752,31 @@ $(document).ready(function()
});
function check_payment_type_giftcard()
function check_payment_type()
{
if ($("#payment_types").val() == "<?php echo $this->lang->line('sales_giftcard'); ?>")
{
$("#amount_tendered_label").html("<?php echo $this->lang->line('sales_giftcard_number'); ?>");
$("#amount_tendered:enabled").val('').focus();
}
else
{
$("#amount_tendered_label").html("<?php echo $this->lang->line('sales_amount_tendered'); ?>");
$("#amount_tendered:enabled").val('<?php echo to_currency_no_money($amount_due); ?>');
}
var cash_rounding = <?php echo json_encode($cash_rounding); ?>;
if ($("#payment_types").val() == "<?php echo $this->lang->line('sales_giftcard'); ?>")
{
$("#sale_total").html("<?php echo to_currency($total); ?>");
$("#sale_amount_due").html("<?php echo to_currency($amount_due); ?>");
$("#amount_tendered_label").html("<?php echo $this->lang->line('sales_giftcard_number'); ?>");
$("#amount_tendered:enabled").val('').focus();
}
else if ($("#payment_types").val() == "<?php echo $this->lang->line('sales_cash'); ?>" && cash_rounding)
{
$("#sale_total").html("<?php echo to_currency($cash_total); ?>");
$("#sale_amount_due").html("<?php echo to_currency($cash_amount_due); ?>");
$("#amount_tendered_label").html("<?php echo $this->lang->line('sales_amount_tendered'); ?>");
$("#amount_tendered:enabled").val('<?php echo to_currency_no_money($cash_amount_due); ?>');
}
else
{
$("#sale_total").html("<?php echo to_currency($non_cash_total); ?>");
$("#sale_amount_due").html("<?php echo to_currency($non_cash_amount_due); ?>");
$("#amount_tendered_label").html("<?php echo $this->lang->line('sales_amount_tendered'); ?>");
$("#amount_tendered:enabled").val('<?php echo to_currency_no_money($non_cash_amount_due); ?>');
}
}
</script>

View File

@@ -50,7 +50,7 @@
<td><?php echo $suspended_sale['comment'];?></td>
<td>
<?php echo form_open('sales/unsuspend');
echo form_hidden('suspended_sale_id', $suspended_sale['sale_id']);
echo form_hidden('suspended_sale_id', $suspended_sale['suspended_sale_id']);
?>
<input type="submit" name="submit" value="<?php echo $this->lang->line('sales_unsuspend'); ?>" id="submit" class="btn btn-primary btn-xs pull-right">
<?php echo form_close(); ?>

View File

@@ -0,0 +1,212 @@
<div id="required_fields_message"><?php echo $this->lang->line('common_fields_required_message'); ?></div>
<ul id="error_message_box" class="error_message_box"></ul>
<?php echo form_open('taxes/save/'.$tax_code, array('id'=>'tax_code_form', 'class'=>'form-horizontal')); ?>
<fieldset id="tax_code_basic_info">
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('taxes_tax_code'), 'name', array('class'=>'required control-label col-xs-3')); ?>
<div class='col-xs-4'>
<?php echo form_input(array(
'name'=>'tax_code',
'id'=>'tax_code',
'class'=>'form-control input-sm',
'value'=>$tax_code)
);?>
</div>
</div>
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('taxes_tax_code_name'), 'name', array('class'=>'required control-label col-xs-3')); ?>
<div class='col-xs-9'>
<?php echo form_input(array(
'name'=>'tax_code_name',
'id'=>'tax_code_name',
'class'=>'form-control input-sm',
'value'=>$tax_code_name)
);?>
</div>
</div>
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('taxes_tax_code_type'), 'tax_code_type', !empty($basic_version) ? array('class'=>'required control-label col-xs-3') : array('class'=>'control-label col-xs-3')); ?>
<div class="col-xs-9">
<label class="radio-inline">
<?php echo form_radio(array(
'name'=>'tax_code_type',
'type'=>'radio',
'id'=>'tax_code_type',
'value'=>0,
'checked'=>$tax_code_type == '0')
); ?> <?php echo $this->lang->line('taxes_sales_tax'); ?>
</label>
<label class="radio-inline">
<?php echo form_radio(array(
'name'=>'tax_code_type',
'type'=>'radio',
'id'=>'tax_code_type',
'value'=>1,
'checked'=>$tax_code_type == '1')
); ?> <?php echo $this->lang->line('taxes_sales_tax_by_invoice'); ?>
</label>
<label class="radio-inline">
<?php echo form_radio(array(
'name'=>'tax_code_type',
'type'=>'radio',
'id'=>'tax_code_type',
'value'=>1,
'checked'=>$tax_code_type == '2')
); ?> <?php echo $this->lang->line('taxes_vat_tax'); ?>
</label>
</div>
</div>
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('common_city'), 'city', array('class'=>'control-label col-xs-3')); ?>
<div class='col-xs-8'>
<?php echo form_input(array(
'name'=>'city',
'id'=>'city',
'class'=>'form-control input-sm',
'value'=>$city)
);?>
</div>
</div>
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('common_state'), 'name', array('class'=>'control-label col-xs-3')); ?>
<div class='col-xs-8'>
<?php echo form_input(array(
'name'=>'state',
'id'=>'state',
'class'=>'form-control input-sm',
'value'=>$state)
);?>
</div>
</div>
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('taxes_tax_rate'), 'tax_rate', array('class' => 'required control-label col-xs-3')); ?>
<div class='col-xs-4'>
<div class="input-group input-group-sm">
<?php echo form_input(array(
'name'=>'tax_rate',
'id'=>'tax_rate',
'class'=>'form-control input-sm',
'value'=>$tax_rate)
);?>
<span class="input-group-addon input-sm"><b>%</b></span>
</div>
</div>
</div>
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('taxes_rounding_code'), 'rounding_code', array('class' => 'control-label col-xs-3')); ?>
<div class='col-xs-4'>
<?php echo form_dropdown('rounding_code', $rounding_options, $rounding_code, array('class' => 'form-control input-sm')); ?>
</div>
</div>
<div class="form-group form-group-sm">
<?php echo form_label($this->lang->line('taxes_add_exception'), 'add_tax_category', array('class'=>'control-label col-xs-3')); ?>
<div class='col-xs-8'>
<div class="input-group">
<span class="input-group-addon input-sm"><span class="glyphicon glyphicon-tag"></span></span>
<?php echo form_input(array(
'name'=>'add_tax_category',
'id'=>'add_tax_category',
'class'=>'form-control input-sm',
'value'=>$add_tax_category)
);?>
<?php echo form_hidden('rate_tax_category_id', $rate_tax_category_id);?>
</div>
</div>
</div>
<table id="tax_code_rates" class="table table-striped table-hover">
<thead>
<tr>
<th width="10%"><?php echo $this->lang->line('common_delete'); ?></th>
<th width="30%"><?php echo $this->lang->line('taxes_tax_category'); ?></th>
<th width="30%"><?php echo $this->lang->line('taxes_tax_rate'); ?></th>
<th width="30%"><?php echo $this->lang->line('taxes_rounding_code'); ?></th>
</tr>
</thead>
<tbody>
<?php
foreach($tax_code_rates as $tax_code_rate)
{
?>
<tr>
<td><a href='#' onclick='return delete_tax_code_rate_row(this);'><span class='glyphicon glyphicon-trash'></span></a></td>
<td><?php echo $tax_code_rate['tax_category']; ?></td>
<td><input class='form-control input-sm' id='exception_tax_rate_<?php echo $tax_code_rate['rate_tax_category_id'] ?>' name=exception_tax_rate[<?php echo $tax_code_rate['rate_tax_category_id'] ?>] value='<?php echo $tax_code_rate['tax_rate'] ?>'/></td>
<td><?php echo form_dropdown('exception_rounding_code['.$tax_code_rate['rate_tax_category_id'].']', $rounding_options, $tax_code_rate['rounding_code'], array('class' => 'form-control input-sm'));?></td>
</tr>
<?php
}
?>
</tbody>
</table>
</fieldset>
<?php echo form_close(); ?>
<script type="text/javascript">
//validation and submit handling
$(document).ready(function() {
$("#add_tax_category").autocomplete({
source: '<?php echo site_url("taxes/suggest_tax_categories"); ?>',
minChars: 0,
autoFocus: false,
delay: 10,
appendTo: ".modal-content",
select: function (e, ui) {
if ($("#tax_category_id" + ui.item.value).length == 1) {
$("#tax_category_id" + ui.item.value).val(parseFloat($("#tax_category_id" + ui.item.value).val()) + 1);
}
else {
$("#tax_code_rates").append("<tr>" +
"<td><a href='#' onclick='return delete_tax_code_rate_row(this);'><span class='glyphicon glyphicon-trash'></span></a></td>" +
"<td>" + ui.item.label + "</td>" +
"<td><input class='form-control input-sm' id='exception_tax_rate_" + ui.item.value + "' name=exception_tax_rate[" + ui.item.value + "] value=''/></td>" +
"<td><select id='exception_rounding_code_" + ui.item.value + "' class='form-control input-sm' name=exception_rounding_code[" + ui.item.value +
"] aria-invalid='false'><?php echo Taxes::get_html_rounding_options(); ?></select></td>" +
"</tr>");
}
$("#add_tax_category").val("");
return false;
}
});
$('#tax_code_form').validate($.extend({
submitHandler: function (form) {
$(form).ajaxSubmit({
success: function (response) {
dialog_support.hide();
table_support.handle_submit('<?php echo site_url('taxes'); ?>', response);
},
dataType: 'json'
});
},
rules: {
tax_code: "required",
tax_rate: "required"
},
messages: {
tax_code: "<?php echo $this->lang->line('taxes_tax_code_required'); ?>",
tax_rate: "<?php echo $this->lang->line('taxes_tax_rate_required'); ?>"
}
}, form_support.error));
});
function delete_tax_code_rate_row(link) {
$(link).parent().parent().remove();
return false;
}
</script>

View File

@@ -0,0 +1,34 @@
<?php $this->load->view("partial/header"); ?>
<script type="text/javascript">
$(document).ready(function()
{
<?php $this->load->view('partial/bootstrap_tables_locale'); ?>
table_support.init({
resource: '<?php echo site_url($controller_name);?>',
headers: <?php echo $table_headers; ?>,
pageSize: <?php echo $this->config->item('lines_per_page'); ?>,
uniqueId: 'tax_code'
});
});
</script>
<div id="title_bar" class="btn-toolbar">
<button class='btn btn-info btn-sm pull-right modal-dlg' data-btn-submit='<?php echo $this->lang->line('common_submit') ?>' data-href='<?php echo site_url($controller_name."/view"); ?>'
title='<?php echo $this->lang->line($controller_name.'_new'); ?>'>
<span class="glyphicon glyphicon-usd">&nbsp</span><?php echo $this->lang->line($controller_name . '_new'); ?>
</button>
</div>
<div id="toolbar">
<div class="pull-left btn-toolbar">
<button id="delete" class="btn btn-default btn-sm">
<span class="glyphicon glyphicon-trash">&nbsp</span><?php echo $this->lang->line("common_delete"); ?>
</button>
</div>
</div>
<div id="table_holder">
<table id="table"></table>
</div>
<?php $this->load->view("partial/footer"); ?>

View File

@@ -121,4 +121,86 @@ ADD COLUMN `points` int(11) DEFAULT NULL AFTER `package_id`;
-- add enabled reward points key into config
INSERT INTO `ospos_app_config` (`key`, `value`) VALUES
('customer_reward_enable','');
('customer_reward_enable','');
/* The following changes are in support of customer sales tax changes */
CREATE TABLE IF NOT EXISTS `ospos_tax_codes` (
`tax_code` varchar(32) NOT NULL,
`tax_code_name` varchar(255) NOT NULL DEFAULT '',
`tax_code_type` tinyint(2) NOT NULL DEFAULT 0,
`city` varchar(255) NOT NULL DEFAULT '',
`state` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`tax_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `ospos_tax_code_rates` (
`rate_tax_code` varchar(32) NOT NULL,
`rate_tax_category_id` int(10) NOT NULL,
`tax_rate` decimal(15,4) NOT NULL DEFAULT 0.0000,
`rounding_code` tinyint(2) NOT NULL DEFAULT 0,
PRIMARY KEY (`rate_tax_code`,`rate_tax_category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `ospos_sales_taxes` (
`sale_id` int(10) NOT NULL,
`tax_type` smallint(2) NOT NULL,
`tax_group` varchar(32) NOT NULL,
`sale_tax_basis` decimal(15,4) NOT NULL,
`sale_tax_amount` decimal(15,4) NOT NULL,
`print_sequence` tinyint(2) NOT NULL DEFAULT 0,
`name` varchar(255) NOT NULL,
`tax_rate` decimal(15,4) NOT NULL,
`sales_tax_code` varchar(32) NOT NULL DEFAULT '',
`rounding_code` tinyint(2) NOT NULL DEFAULT 0,
PRIMARY KEY (`sale_id`,`tax_type`,`tax_group`),
KEY `print_sequence` (`sale_id`,`print_sequence`,`tax_type`,`tax_group`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `ospos_tax_categories` (
`tax_category_id` int(10) NOT NULL,
`tax_category` varchar(32) NOT NULL,
`tax_group_sequence` tinyint(2) NOT NULL,
PRIMARY KEY (`tax_category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `ospos_tax_categories` ( `tax_category_id`,`tax_category`, `tax_group_sequence` ) VALUES
(0, 'Standard', 10),
(1, 'Service', 12),
(2, 'Alcohol', 11);
ALTER TABLE `ospos_items`
ADD COLUMN `tax_category_id` int(10) NOT NULL DEFAULT 0;
ALTER TABLE `ospos_sales`
ADD COLUMN `quote_number` varchar(32) DEFAULT NULL,
ADD COLUMN `sale_status` tinyint(2) NOT NULL DEFAULT 0;
ALTER TABLE `ospos_sales_items_taxes`
MODIFY COLUMN `percent` decimal(15,4) NOT NULL DEFAULT 0.0000,
ADD COLUMN `tax_type` tinyint(2) NOT NULL DEFAULT 0,
ADD COLUMN `rounding_code` tinyint(2) NOT NULL DEFAULT 0,
ADD COLUMN `cascade_tax` tinyint(2) NOT NULL DEFAULT 0,
ADD COLUMN `cascade_sequence` tinyint(2) NOT NULL DEFAULT 0,
ADD COLUMN `item_tax_amount` decimal(15,4) NOT NULL DEFAULT 0;
ALTER TABLE `ospos_customers`
ADD COLUMN `sales_tax_code` varchar(32) NOT NULL;
INSERT INTO `ospos_app_config` (`key`, `value`) VALUES
('customer_sales_tax_support', '0'),
('default_origin_tax_code', '');
INSERT INTO `ospos_modules` (`name_lang_key`, `desc_lang_key`, `sort`, `module_id`) VALUES
('module_taxes', 'module_taxes_desc', 105, 'taxes');
INSERT INTO `ospos_permissions` (`permission_id`, `module_id`) VALUES
('taxes', 'taxes');
/* End of customer sales tax changes */
/* Start of support for cash rounding */
INSERT INTO `ospos_app_config` (`key`, `value`) VALUES
('cash_decimals', '2');
/* End of support for cash rounding */

View File

@@ -85,11 +85,14 @@ INSERT INTO `ospos_app_config` (`key`, `value`) VALUES
('smtp_crypto', 'ssl'),
('receipt_template', 'receipt_default'),
('theme', 'flatly'),
('customer_sales_tax_support', '0'),
('default_origin_tax_code', ''),
('statistics', '1'),
('language', 'english'),
('language_code', 'en'),
('date_or_time_format',''),
('customer_reward_enable','');
('customer_reward_enable',''),
('cash_decimals', '2');
-- --------------------------------------------------------
@@ -103,6 +106,7 @@ CREATE TABLE `ospos_customers` (
`company_name` varchar(255) DEFAULT NULL,
`account_number` varchar(255) DEFAULT NULL,
`taxable` int(1) NOT NULL DEFAULT '1',
`sales_tax_code` varchar(32) NOT NULL DEFAULT '1',
`discount_percent` decimal(15,2) NOT NULL DEFAULT '0',
`package_id` int(11) DEFAULT NULL,
`points` int(11) DEFAULT NULL,
@@ -209,6 +213,7 @@ CREATE TABLE `ospos_items` (
`is_serialized` tinyint(1) NOT NULL,
`stock_type` TINYINT(2) NOT NULL DEFAULT 0,
`item_type` TINYINT(2) NOT NULL DEFAULT 0,
`tax_category_id` int(10) NOT NULL DEFAULT 0,
`deleted` int(1) NOT NULL DEFAULT '0',
`custom1` VARCHAR(25) NOT NULL,
`custom2` VARCHAR(25) NOT NULL,
@@ -335,7 +340,9 @@ INSERT INTO `ospos_modules` (`name_lang_key`, `desc_lang_key`, `sort`, `module_i
('module_receivings', 'module_receivings_desc', 60, 'receivings'),
('module_reports', 'module_reports_desc', 50, 'reports'),
('module_sales', 'module_sales_desc', 70, 'sales'),
('module_suppliers', 'module_suppliers_desc', 40, 'suppliers');
('module_suppliers', 'module_suppliers_desc', 40, 'suppliers'),
('module_taxes', 'module_taxes_desc', 105, 'taxes');
-- --------------------------------------------------------
@@ -407,13 +414,15 @@ INSERT INTO `ospos_permissions` (`permission_id`, `module_id`) VALUES
('reports', 'reports'),
('sales', 'sales'),
('config', 'config'),
('suppliers', 'suppliers');
('suppliers', 'suppliers'),
('taxes', 'taxes');
INSERT INTO `ospos_permissions` (`permission_id`, `module_id`, `location_id`) VALUES
('items_stock', 'items', 1),
('sales_stock', 'sales', 1),
('receivings_stock', 'receivings', 1);
-- --------------------------------------------------------
--
@@ -520,8 +529,10 @@ CREATE TABLE `ospos_sales` (
`employee_id` int(10) NOT NULL DEFAULT '0',
`comment` text NOT NULL,
`invoice_number` varchar(32) DEFAULT NULL,
`quote_number` varchar(32) DEFAULT NULL,
`sale_id` int(10) NOT NULL AUTO_INCREMENT,
`dinner_table_id` int(11) NULL,
`sale_status` tinyint(2) NOT NULL DEFAULT 0,
PRIMARY KEY (`sale_id`),
KEY `customer_id` (`customer_id`),
KEY `employee_id` (`employee_id`),
@@ -575,7 +586,12 @@ CREATE TABLE `ospos_sales_items_taxes` (
`item_id` int(10) NOT NULL,
`line` int(3) NOT NULL DEFAULT '0',
`name` varchar(255) NOT NULL,
`percent` decimal(15,3) NOT NULL,
`percent` decimal(15,4) NOT NULL,
`tax_type` tinyint(2) NOT NULL DEFAULT 0,
`rounding_code` tinyint(2) NOT NULL DEFAULT 0,
`cascade_tax` tinyint(2) NOT NULL DEFAULT 0,
`cascade_sequence` tinyint(2) NOT NULL DEFAULT 0,
`item_tax_amount` decimal(15,4) NOT NULL DEFAULT 0,
PRIMARY KEY (`sale_id`,`item_id`,`line`,`name`,`percent`),
KEY `sale_id` (`sale_id`),
KEY `item_id` (`item_id`)
@@ -604,6 +620,88 @@ CREATE TABLE `ospos_sales_payments` (
-- Dumping data for table `ospos_sales_payments`
--
-- --------------------------------------------------------
--
-- Table structure for table `ospos_sales_taxes`
--
CREATE TABLE `ospos_sales_taxes` (
`sale_id` int(10) NOT NULL,
`tax_type` smallint(2) NOT NULL,
`tax_group` varchar(32) NOT NULL,
`sale_tax_basis` decimal(15,4) NOT NULL,
`sale_tax_amount` decimal(15,4) NOT NULL,
`print_sequence` tinyint(2) NOT NULL DEFAULT 0,
`name` varchar(255) NOT NULL,
`tax_rate` decimal(15,4) NOT NULL,
`sales_tax_code` varchar(32) NOT NULL DEFAULT '',
`rounding_code` tinyint(2) NOT NULL DEFAULT 0,
PRIMARY KEY (`sale_id`,`tax_type`,`tax_group`),
KEY `print_sequence` (`sale_id`,`print_sequence`,`tax_type`,`tax_group`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `ospos_sales_taxes`
--
-- --------------------------------------------------------
--
-- Table structure for table `ospos_tax_categories`
--
CREATE TABLE IF NOT EXISTS `ospos_tax_categories` (
`tax_category_id` int(10) NOT NULL,
`tax_category` varchar(32) NOT NULL,
`tax_group_sequence` tinyint(2) NOT NULL,
PRIMARY KEY (`tax_category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `ospos_tax_categories`
--
INSERT INTO `ospos_tax_categories` ( `tax_category_id`,`tax_category`, `tax_group_sequence` ) VALUES
(0, 'Standard', 10),
(1, 'Service', 12),
(2, 'Alcohol', 11);
-- --------------------------------------------------------
--
-- Table structure for table `ospos_tax_codes`
--
CREATE TABLE IF NOT EXISTS `ospos_tax_codes` (
`tax_code` varchar(32) NOT NULL,
`tax_code_name` varchar(255) NOT NULL DEFAULT '',
`tax_code_type` tinyint(2) NOT NULL DEFAULT 0,
`city` varchar(255) NOT NULL DEFAULT '',
`state` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`tax_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `ospos_tax_codes`
--
-- --------------------------------------------------------
--
-- Table structure for table `ospos_tax_code_rates`
--
CREATE TABLE IF NOT EXISTS `ospos_tax_code_rates` (
`rate_tax_code` varchar(32) NOT NULL,
`rate_tax_category_id` int(10) NOT NULL,
`tax_rate` decimal(15,4) NOT NULL DEFAULT 0.0000,
`rounding_code` tinyint(2) NOT NULL DEFAULT 0,
PRIMARY KEY (`rate_tax_code`,`rate_tax_category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------

View File

@@ -18,6 +18,7 @@ INSERT INTO `ospos_app_config` (`key`, `value`) VALUES
('company', 'Open Source Point of Sale'),
('default_register_mode', 'sale'),
('default_tax_rate', '8'),
('default_tax_category', 'Standard'),
('email', 'changeme@example.com'),
('fax', ''),
('phone', '555-555-5555'),
@@ -85,11 +86,16 @@ INSERT INTO `ospos_app_config` (`key`, `value`) VALUES
('smtp_crypto', 'ssl'),
('receipt_template', 'receipt_default'),
('theme', 'flatly'),
('customer_sales_tax_support', '0'),
('statistics', '1'),
('language', 'english'),
('language_code', 'en'),
('date_or_time_format',''),
('customer_reward_enable','');
('customer_reward_enable',''),
('customer_sales_tax_support', '0'),
('default_origin_tax_code', ''),
('cash_decimals', '2');
-- --------------------------------------------------------
@@ -103,6 +109,7 @@ CREATE TABLE `ospos_customers` (
`company_name` varchar(255) DEFAULT NULL,
`account_number` varchar(255) DEFAULT NULL,
`taxable` int(1) NOT NULL DEFAULT '1',
`sales_tax_code` varchar(32) NOT NULL DEFAULT '',
`discount_percent` decimal(15,2) NOT NULL DEFAULT '0',
`package_id` int(11) DEFAULT NULL,
`points` int(11) DEFAULT NULL,
@@ -209,6 +216,7 @@ CREATE TABLE `ospos_items` (
`is_serialized` tinyint(1) NOT NULL,
`stock_type` TINYINT(2) NOT NULL DEFAULT 0,
`item_type` TINYINT(2) NOT NULL DEFAULT 0,
`tax_category_id` int(10) NOT NULL DEFAULT 0,
`deleted` int(1) NOT NULL DEFAULT '0',
`custom1` VARCHAR(25) NOT NULL,
`custom2` VARCHAR(25) NOT NULL,
@@ -335,7 +343,8 @@ INSERT INTO `ospos_modules` (`name_lang_key`, `desc_lang_key`, `sort`, `module_i
('module_receivings', 'module_receivings_desc', 60, 'receivings'),
('module_reports', 'module_reports_desc', 50, 'reports'),
('module_sales', 'module_sales_desc', 70, 'sales'),
('module_suppliers', 'module_suppliers_desc', 40, 'suppliers');
('module_suppliers', 'module_suppliers_desc', 40, 'suppliers'),
('module_taxes', 'module_taxes_desc', 105, 'taxes');
-- --------------------------------------------------------
@@ -407,7 +416,8 @@ INSERT INTO `ospos_permissions` (`permission_id`, `module_id`) VALUES
('reports', 'reports'),
('sales', 'sales'),
('config', 'config'),
('suppliers', 'suppliers');
('suppliers', 'suppliers'),
('taxes', 'taxes');
INSERT INTO `ospos_permissions` (`permission_id`, `module_id`, `location_id`) VALUES
('items_stock', 'items', 1),
@@ -520,7 +530,9 @@ CREATE TABLE `ospos_sales` (
`employee_id` int(10) NOT NULL DEFAULT '0',
`comment` text NOT NULL,
`invoice_number` varchar(32) DEFAULT NULL,
`quote_number` varchar(32) DEFAULT NULL,
`sale_id` int(10) NOT NULL AUTO_INCREMENT,
`sale_status` tinyint(2) DEFAULT 0,
`dinner_table_id` int(11) NULL,
PRIMARY KEY (`sale_id`),
KEY `customer_id` (`customer_id`),
@@ -575,7 +587,12 @@ CREATE TABLE `ospos_sales_items_taxes` (
`item_id` int(10) NOT NULL,
`line` int(3) NOT NULL DEFAULT '0',
`name` varchar(255) NOT NULL,
`percent` decimal(15,3) NOT NULL,
`percent` decimal(15,4) NOT NULL DEFAULT 0.0000,
`tax_type` tinyint(2) NOT NULL DEFAULT 0,
`rounding_code` tinyint(2) NOT NULL DEFAULT 0,
`cascade_tax` tinyint(2) NOT NULL DEFAULT 0,
`cascade_sequence` tinyint(2) NOT NULL DEFAULT 0,
`item_tax_amount` decimal(15,4) NOT NULL DEFAULT 0,
PRIMARY KEY (`sale_id`,`item_id`,`line`,`name`,`percent`),
KEY `sale_id` (`sale_id`),
KEY `item_id` (`item_id`)
@@ -604,6 +621,33 @@ CREATE TABLE `ospos_sales_payments` (
-- Dumping data for table `ospos_sales_payments`
--
-- --------------------------------------------------------
--
-- Table structure for table `ospos_sales_taxes`
--
CREATE TABLE `ospos_sales_taxes` (
`sale_id` int(10) NOT NULL,
`tax_type` smallint(2) NOT NULL,
`tax_group` varchar(32) NOT NULL,
`sale_tax_basis` decimal(15,4) NOT NULL,
`sale_tax_amount` decimal(15,4) NOT NULL,
`print_sequence` tinyint(2) NOT NULL DEFAULT 0,
`name` varchar(255) NOT NULL,
`tax_rate` decimal(15,4) NOT NULL,
`sales_tax_code` varchar(32) NOT NULL DEFAULT '',
`rounding_code` tinyint(2) NOT NULL DEFAULT 0,
PRIMARY KEY (`sale_id`,`tax_type`,`tax_group`),
KEY `print_sequence` (`sale_id`,`print_sequence`,`tax_type`,`tax_group`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `ospos_sales_taxes`
--
-- --------------------------------------------------------
@@ -736,7 +780,6 @@ CREATE TABLE `ospos_stock_locations` (
INSERT INTO `ospos_stock_locations` ( `deleted`, `location_name` ) VALUES ('0', 'stock');
-- --------------------------------------------------------
--
-- Table structure for table `ospos_suppliers`
--
@@ -751,12 +794,47 @@ CREATE TABLE `ospos_suppliers` (
KEY `person_id` (`person_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
-- --------------------------------------------------------
--
-- Dumping data for table `ospos_suppliers`
-- Table structure for table `ospos_tax_categories`
--
CREATE TABLE IF NOT EXISTS `ospos_tax_categories` (
`tax_category_id` int(10) NOT NULL,
`tax_category` varchar(32) NOT NULL,
`tax_group_sequence` tinyint(2) NOT NULL,
PRIMARY KEY (`tax_category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `ospos_stock_locations`
--
INSERT INTO `ospos_tax_categories` ( `tax_category_id`,`tax_category`, `tax_group_sequence` ) VALUES
(0, 'Standard', 10),
(1, 'Service', 12),
(2, 'Alcohol', 11);
-- --------------------------------------------------------
--
-- Table structure for table `ospos_tax_codes`
--
CREATE TABLE IF NOT EXISTS `ospos_tax_codes` (
`tax_code` varchar(32) NOT NULL,
`tax_code_name` varchar(255) NOT NULL DEFAULT '',
`tax_code_type` tinyint(2) NOT NULL DEFAULT 0,
`city` varchar(255) NOT NULL DEFAULT '',
`state` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`tax_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `ospos_tax_codes`
--
-- --------------------------------------------------------
--
-- Table structure for table `ospos_dinner_tables`
--
@@ -820,3 +898,20 @@ CREATE TABLE IF NOT EXISTS `ospos_sales_reward_points` (
`used` float NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
-- --------------------------------------------------------
--
-- Table structure for table `ospos_tax_code_rates`
--
CREATE TABLE IF NOT EXISTS `ospos_tax_code_rates` (
`rate_tax_code` varchar(32) NOT NULL,
`rate_tax_category_id` int(10) NOT NULL,
`tax_rate` decimal(15,4) NOT NULL DEFAULT 0.0000,
`rounding_code` tinyint(2) NOT NULL DEFAULT 0,
PRIMARY KEY (`rate_tax_code`,`rate_tax_category_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
--
-- Dumping data for table `ospos_tax_code_rates`
--

View File

@@ -63,23 +63,23 @@
font-size: 80%;
}
#item_kit_items, #items_count_details
#item_kit_items, #items_count_details, #tax_code_rates
{
width: 100%;
}
#item_kit_items thead tr, #items_count_details thead tr
#item_kit_items thead tr, #items_count_details thead tr, #tax_code_rates thead tr
{
background-color: #CCC;
}
#item_kit_items th, #items_count_details th
#item_kit_items th, #items_count_details th, #tax_code_rates th
{
text-align: center;
font-weight: bold;
}
#item_kit_items td, #items_count_details td
#item_kit_items td, #items_count_details td, #tax_code_rates td
{
text-align: center;
}

View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB