mirror of
https://github.com/opensourcepos/opensourcepos.git
synced 2026-04-08 08:57:50 -04:00
Fix rounding issues in reports (#1336)
This commit is contained in:
@@ -17,23 +17,34 @@ function current_language()
|
||||
function currency_side()
|
||||
{
|
||||
$config = get_instance()->config;
|
||||
|
||||
$fmt = new \NumberFormatter($config->item('number_locale'), \NumberFormatter::CURRENCY);
|
||||
$fmt->setSymbol(\NumberFormatter::CURRENCY_SYMBOL, $config->item('currency_symbol'));
|
||||
|
||||
return !preg_match('/^¤/', $fmt->getPattern());
|
||||
}
|
||||
|
||||
function quantity_decimals()
|
||||
{
|
||||
$config = get_instance()->config;
|
||||
|
||||
return $config->item('quantity_decimals') ? $config->item('quantity_decimals') : 0;
|
||||
}
|
||||
|
||||
function totals_decimals()
|
||||
{
|
||||
$config = get_instance()->config;
|
||||
|
||||
return $config->item('currency_decimals') ? $config->item('currency_decimals') : 0;
|
||||
}
|
||||
|
||||
function tax_decimals()
|
||||
{
|
||||
$config = get_instance()->config;
|
||||
|
||||
return $config->item('tax_decimals') ? $config->item('tax_decimals') : 0;
|
||||
}
|
||||
|
||||
function to_currency($number)
|
||||
{
|
||||
return to_decimals($number, 'currency_decimals', \NumberFormatter::CURRENCY);
|
||||
@@ -74,11 +85,12 @@ function to_decimals($number, $decimals, $type=\NumberFormatter::DECIMAL)
|
||||
$fmt = new \NumberFormatter($config->item('number_locale'), $type);
|
||||
$fmt->setAttribute(\NumberFormatter::MIN_FRACTION_DIGITS, $config->item($decimals));
|
||||
$fmt->setAttribute(\NumberFormatter::MAX_FRACTION_DIGITS, $config->item($decimals));
|
||||
if (empty($config->item('thousands_separator')))
|
||||
if(empty($config->item('thousands_separator')))
|
||||
{
|
||||
$fmt->setAttribute(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL, '');
|
||||
}
|
||||
$fmt->setSymbol(\NumberFormatter::CURRENCY_SYMBOL, $config->item('currency_symbol'));
|
||||
|
||||
return $fmt->format($number);
|
||||
}
|
||||
|
||||
@@ -96,6 +108,7 @@ function parse_decimals($number)
|
||||
{
|
||||
$fmt->setAttribute(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL, '');
|
||||
}
|
||||
|
||||
return $fmt->parse($number);
|
||||
}
|
||||
|
||||
|
||||
@@ -328,7 +328,7 @@ class Sale_lib
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
/**
|
||||
* Returns 'subtotal', 'total', 'cash_total', 'payment_total', 'amount_due', 'cash_amount_due', 'paid_in_full'
|
||||
* 'subtotal', 'discounted_subtotal', 'tax_exclusive_subtotal'
|
||||
*/
|
||||
@@ -359,7 +359,7 @@ class Sale_lib
|
||||
}
|
||||
else
|
||||
{
|
||||
$subtotal =bcadd($subtotal, $extended_discounted_amount);
|
||||
$subtotal = bcadd($subtotal, $extended_discounted_amount);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,7 +367,7 @@ class Sale_lib
|
||||
$totals['total_discount'] = $total_discount;
|
||||
$totals['subtotal'] = $subtotal;
|
||||
|
||||
if ($this->CI->config->item('tax_included'))
|
||||
if($this->CI->config->item('tax_included'))
|
||||
{
|
||||
$totals['total'] = $total;
|
||||
}
|
||||
@@ -1137,6 +1137,7 @@ class Sale_lib
|
||||
|
||||
return $discounted_extended_amount;
|
||||
}
|
||||
|
||||
public function get_item_total($quantity, $price, $discount_percentage, $include_discount = FALSE)
|
||||
{
|
||||
$total = bcmul($quantity, $price);
|
||||
|
||||
@@ -30,23 +30,22 @@ class Sale extends CI_Model
|
||||
)'
|
||||
);
|
||||
|
||||
$decimals = totals_decimals();
|
||||
|
||||
$sale_price = 'sales_items.item_unit_price * sales_items.quantity_purchased * (1 - sales_items.discount_percent / 100)';
|
||||
$tax = 'ROUND(IFNULL(SUM(sales_items_taxes.tax), 0), ' . $decimals . ')';
|
||||
|
||||
if($this->config->item('tax_included'))
|
||||
{
|
||||
$sale_total = 'SUM(' . $sale_price . ')';
|
||||
$sale_subtotal = 'SUM(' . $sale_price . ' - sales_items_taxes.tax)';
|
||||
$sale_total = 'ROUND(SUM(' . $sale_price . '),' . $decimals . ')';
|
||||
$sale_subtotal = $sale_total . ' - ' . $tax;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sale_total = 'SUM(' . $sale_price . ' + sales_items_taxes.tax)';
|
||||
$sale_subtotal = 'SUM(' . $sale_price . ')';
|
||||
$sale_subtotal = 'ROUND(SUM(' . $sale_price . '),' . $decimals . ')';
|
||||
$sale_total = $sale_subtotal . ' + ' . $tax;
|
||||
}
|
||||
|
||||
$sale_cost = 'SUM(sales_items.item_cost_price * sales_items.quantity_purchased)';
|
||||
|
||||
$decimals = totals_decimals();
|
||||
|
||||
// create a temporary table to contain all the sum of taxes per sale item
|
||||
$this->db->query('CREATE TEMPORARY TABLE IF NOT EXISTS ' . $this->db->dbprefix('sales_items_taxes_temp') .
|
||||
'(
|
||||
@@ -80,9 +79,9 @@ class Sale extends CI_Model
|
||||
MAX(customer_p.email) AS email,
|
||||
MAX(customer_p.comments) AS comments,
|
||||
' . "
|
||||
IFNULL(ROUND($sale_total, $decimals), ROUND($sale_subtotal, $decimals)) AS amount_due,
|
||||
IFNULL($sale_total, $sale_subtotal) AS amount_due,
|
||||
MAX(payments.sale_payment_amount) AS amount_tendered,
|
||||
(MAX(payments.sale_payment_amount) - IFNULL(ROUND($sale_total, $decimals), ROUND($sale_subtotal, $decimals))) AS change_due,
|
||||
(MAX(payments.sale_payment_amount) - IFNULL($sale_total, $sale_subtotal)) AS change_due,
|
||||
" . '
|
||||
MAX(payments.payment_type) AS payment_type
|
||||
');
|
||||
@@ -144,23 +143,23 @@ class Sale extends CI_Model
|
||||
)'
|
||||
);
|
||||
|
||||
$decimals = totals_decimals();
|
||||
|
||||
$sale_price = 'sales_items.item_unit_price * sales_items.quantity_purchased * (1 - sales_items.discount_percent / 100)';
|
||||
$sale_cost = 'ROUND(SUM(sales_items.item_cost_price * sales_items.quantity_purchased), ' . $decimals . ')';
|
||||
$tax = 'ROUND(IFNULL(SUM(sales_items_taxes.tax), 0), ' . $decimals . ')';
|
||||
|
||||
if($this->config->item('tax_included'))
|
||||
{
|
||||
$sale_total = 'SUM(' . $sale_price . ')';
|
||||
$sale_subtotal = 'SUM(' . $sale_price . ' - sales_items_taxes.tax)';
|
||||
$sale_total = 'ROUND(SUM(' . $sale_price . '),' . $decimals . ')';
|
||||
$sale_subtotal = $sale_total . ' - ' . $tax;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sale_total = 'SUM(' . $sale_price . ' + sales_items_taxes.tax)';
|
||||
$sale_subtotal = 'SUM(' . $sale_price . ')';
|
||||
$sale_subtotal = 'ROUND(SUM(' . $sale_price . '),' . $decimals . ')';
|
||||
$sale_total = $sale_subtotal . ' + ' . $tax;
|
||||
}
|
||||
|
||||
$sale_cost = 'SUM(sales_items.item_cost_price * sales_items.quantity_purchased)';
|
||||
|
||||
$decimals = totals_decimals();
|
||||
|
||||
// create a temporary table to contain all the sum of taxes per sale item
|
||||
$this->db->query('CREATE TEMPORARY TABLE IF NOT EXISTS ' . $this->db->dbprefix('sales_items_taxes_temp') .
|
||||
' (INDEX(sale_id), INDEX(item_id))
|
||||
@@ -189,14 +188,14 @@ class Sale extends CI_Model
|
||||
MAX(CONCAT(customer_p.first_name, " ", customer_p.last_name)) AS customer_name,
|
||||
MAX(customer.company_name) AS company_name,
|
||||
' . "
|
||||
IFNULL(ROUND($sale_subtotal, $decimals), ROUND($sale_total - IFNULL(SUM(sales_items_taxes.tax), 0), $decimals)) AS subtotal,
|
||||
IFNULL(ROUND(SUM(sales_items_taxes.tax), $decimals), 0) AS tax,
|
||||
IFNULL(ROUND($sale_total, $decimals), ROUND($sale_subtotal, $decimals)) AS total,
|
||||
IFNULL(ROUND($sale_cost, $decimals), 0) AS cost,
|
||||
IFNULL(ROUND($sale_total - IFNULL(SUM(sales_items_taxes.tax), 0) - $sale_cost, $decimals), ROUND($sale_subtotal - $sale_cost, $decimals)) AS profit,
|
||||
IFNULL(ROUND($sale_total, $decimals), ROUND($sale_subtotal, $decimals)) AS amount_due,
|
||||
IFNULL($sale_subtotal, $sale_total) AS subtotal,
|
||||
$tax AS tax,
|
||||
IFNULL($sale_total, $sale_subtotal) AS total,
|
||||
$sale_cost AS cost,
|
||||
(IFNULL($sale_subtotal, $sale_total) - $sale_cost) AS profit,
|
||||
IFNULL($sale_total, $sale_subtotal) AS amount_due,
|
||||
MAX(payments.sale_payment_amount) AS amount_tendered,
|
||||
(MAX(payments.sale_payment_amount) - IFNULL(ROUND($sale_total, $decimals), ROUND($sale_subtotal, $decimals))) AS change_due,
|
||||
(MAX(payments.sale_payment_amount) - IFNULL($sale_total, $sale_subtotal)) AS change_due,
|
||||
" . '
|
||||
MAX(payments.payment_type) AS payment_type
|
||||
');
|
||||
@@ -1082,23 +1081,23 @@ class Sale extends CI_Model
|
||||
$where = 'sales.sale_id = ' . $this->db->escape($inputs['sale_id']);
|
||||
}
|
||||
|
||||
$decimals = totals_decimals();
|
||||
|
||||
$sale_price = 'sales_items.item_unit_price * sales_items.quantity_purchased * (1 - sales_items.discount_percent / 100)';
|
||||
$sale_cost = 'ROUND(IFNULL(SUM(sales_items.item_cost_price * sales_items.quantity_purchased), 0), ' . $decimals . ')';
|
||||
$tax = 'ROUND(IFNULL(SUM(sales_items_taxes.tax), 0), ' . $decimals . ')';
|
||||
|
||||
if($this->config->item('tax_included'))
|
||||
{
|
||||
$sale_total = 'SUM(' . $sale_price . ')';
|
||||
$sale_subtotal = 'SUM(' . $sale_price . ' - sales_items_taxes.tax)';
|
||||
$sale_total = 'ROUND(SUM(' . $sale_price . '),' . $decimals . ')';
|
||||
$sale_subtotal = $sale_total . ' - ' . $tax;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sale_total = 'SUM(' . $sale_price . ' + sales_items_taxes.tax)';
|
||||
$sale_subtotal = 'SUM(' . $sale_price . ')';
|
||||
$sale_subtotal = 'ROUND(SUM(' . $sale_price . '),' . $decimals . ')';
|
||||
$sale_total = $sale_subtotal . ' + ' . $tax;
|
||||
}
|
||||
|
||||
$sale_cost = 'SUM(sales_items.item_cost_price * sales_items.quantity_purchased)';
|
||||
|
||||
$decimals = totals_decimals();
|
||||
|
||||
// create a temporary table to contain all the sum of taxes per sale item
|
||||
$this->db->query('CREATE TEMPORARY TABLE IF NOT EXISTS ' . $this->db->dbprefix('sales_items_taxes_temp') .
|
||||
' (INDEX(sale_id), INDEX(item_id))
|
||||
@@ -1166,11 +1165,11 @@ class Sale extends CI_Model
|
||||
MAX(payments.payment_type) AS payment_type,
|
||||
MAX(payments.sale_payment_amount) AS sale_payment_amount,
|
||||
' . "
|
||||
IFNULL(ROUND($sale_subtotal, $decimals), ROUND($sale_total - IFNULL(SUM(sales_items_taxes.tax), 0), $decimals)) AS subtotal,
|
||||
IFNULL(ROUND(SUM(sales_items_taxes.tax), $decimals), 0) AS tax,
|
||||
IFNULL(ROUND($sale_total, $decimals), ROUND($sale_subtotal, $decimals)) AS total,
|
||||
IFNULL(ROUND($sale_cost, $decimals), 0) AS cost,
|
||||
IFNULL(ROUND($sale_total - IFNULL(SUM(sales_items_taxes.tax), 0) - $sale_cost, $decimals), ROUND($sale_subtotal - $sale_cost, $decimals)) AS profit
|
||||
IFNULL($sale_subtotal, $sale_total) AS subtotal,
|
||||
$tax AS tax,
|
||||
IFNULL($sale_total, $sale_subtotal) AS total,
|
||||
$sale_cost AS cost,
|
||||
(IFNULL($sale_subtotal, $sale_total) - $sale_cost) AS profit
|
||||
" . '
|
||||
FROM ' . $this->db->dbprefix('sales_items') . ' AS sales_items
|
||||
INNER JOIN ' . $this->db->dbprefix('sales') . ' AS sales
|
||||
|
||||
@@ -4,9 +4,9 @@ require_once("Report.php");
|
||||
|
||||
abstract class Summary_report extends Report
|
||||
{
|
||||
/*
|
||||
Private interface
|
||||
*/
|
||||
/**
|
||||
* Private interface
|
||||
*/
|
||||
|
||||
private function _common_select(array $inputs)
|
||||
{
|
||||
@@ -21,23 +21,23 @@ abstract class Summary_report extends Report
|
||||
$where .= 'sale_time BETWEEN ' . $this->db->escape(rawurldecode($inputs['start_date'])) . ' AND ' . $this->db->escape(rawurldecode($inputs['end_date']));
|
||||
}
|
||||
|
||||
$decimals = totals_decimals();
|
||||
|
||||
$sale_price = 'sales_items.item_unit_price * sales_items.quantity_purchased * (1 - sales_items.discount_percent / 100)';
|
||||
$sale_cost = 'ROUND(IFNULL(SUM(sales_items.item_cost_price * sales_items.quantity_purchased), 0), ' . $decimals . ')';
|
||||
$tax = 'ROUND(IFNULL(SUM(sales_items_taxes.tax), 0), ' . $decimals . ')';
|
||||
|
||||
if($this->config->item('tax_included'))
|
||||
{
|
||||
$sale_total = 'SUM(' . $sale_price . ')';
|
||||
$sale_subtotal = 'SUM(' . $sale_price . ' - sales_items_taxes.tax)';
|
||||
$sale_total = 'ROUND(SUM(' . $sale_price . '),' . $decimals . ')';
|
||||
$sale_subtotal = $sale_total . ' - ' . $tax;
|
||||
}
|
||||
else
|
||||
{
|
||||
$sale_total = 'SUM(' . $sale_price . ' + sales_items_taxes.tax)';
|
||||
$sale_subtotal = 'SUM(' . $sale_price . ')';
|
||||
$sale_subtotal = 'ROUND(SUM(' . $sale_price . '),' . $decimals . ')';
|
||||
$sale_total = $sale_subtotal . ' + ' . $tax;
|
||||
}
|
||||
|
||||
$sale_cost = 'SUM(sales_items.item_cost_price * sales_items.quantity_purchased)';
|
||||
|
||||
$decimals = totals_decimals();
|
||||
|
||||
// create a temporary table to contain all the sum of taxes per sale item
|
||||
$this->db->query('CREATE TEMPORARY TABLE IF NOT EXISTS ' . $this->db->dbprefix('sales_items_taxes_temp') .
|
||||
' (INDEX(sale_id), INDEX(item_id))
|
||||
@@ -57,11 +57,11 @@ abstract class Summary_report extends Report
|
||||
);
|
||||
|
||||
$this->db->select("
|
||||
IFNULL(ROUND($sale_subtotal, $decimals), ROUND($sale_total - IFNULL(SUM(sales_items_taxes.tax), 0), $decimals)) AS subtotal,
|
||||
IFNULL(ROUND(SUM(sales_items_taxes.tax), $decimals), 0) AS tax,
|
||||
IFNULL(ROUND($sale_total, $decimals), ROUND($sale_subtotal, $decimals)) AS total,
|
||||
IFNULL(ROUND($sale_cost, $decimals), 0) AS cost,
|
||||
IFNULL(ROUND($sale_total - IFNULL(SUM(sales_items_taxes.tax), 0) - $sale_cost, $decimals), ROUND($sale_subtotal - $sale_cost, $decimals)) AS profit
|
||||
IFNULL($sale_subtotal, $sale_total) AS subtotal,
|
||||
$tax AS tax,
|
||||
IFNULL($sale_total, $sale_subtotal) AS total,
|
||||
$sale_cost AS cost,
|
||||
(IFNULL($sale_subtotal, $sale_total) - $sale_cost) AS profit
|
||||
");
|
||||
}
|
||||
|
||||
@@ -100,11 +100,9 @@ abstract class Summary_report extends Report
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Protected class interface implemented by derived classes
|
||||
|
||||
*/
|
||||
/**
|
||||
* Protected class interface implemented by derived classes
|
||||
*/
|
||||
|
||||
abstract protected function _get_data_columns();
|
||||
|
||||
@@ -113,10 +111,8 @@ abstract class Summary_report extends Report
|
||||
protected function _where(array $inputs) { $this->_common_where($inputs); }
|
||||
protected function _group_order() {}
|
||||
|
||||
/*
|
||||
|
||||
Public interface implementing the base abstract class, in general it should not be extended unless there is a valid reason
|
||||
|
||||
/**
|
||||
* Public interface implementing the base abstract class, in general it should not be extended unless there is a valid reason
|
||||
*/
|
||||
|
||||
public function getDataColumns()
|
||||
|
||||
Reference in New Issue
Block a user