From 5824f78d5511eac751e18d2608bc6d3537d9a262 Mon Sep 17 00:00:00 2001 From: objecttothis Date: Mon, 6 May 2024 14:35:28 +0400 Subject: [PATCH] Convert raw query to querybuilder for security Signed-off-by: objecttothis --- app/Models/Reports/Summary_taxes.php | 120 ++++++++------------------- 1 file changed, 33 insertions(+), 87 deletions(-) diff --git a/app/Models/Reports/Summary_taxes.php b/app/Models/Reports/Summary_taxes.php index da5fc4773..c34a46a89 100644 --- a/app/Models/Reports/Summary_taxes.php +++ b/app/Models/Reports/Summary_taxes.php @@ -55,105 +55,51 @@ class Summary_taxes extends Summary_report */ public function getData(array $inputs): array { - $where = 'WHERE sale_status = ' . COMPLETED . ' '; //TODO: Duplicated code - - if(empty($this->config['date_or_time_format'])) //TODO: Ternary notation - { - $where .= 'AND DATE(sale_time) BETWEEN ' . $this->db->escape($inputs['start_date']) . ' AND ' . $this->db->escape($inputs['end_date']); - } - else - { - $where .= 'AND sale_time BETWEEN ' . $this->db->escape(rawurldecode($inputs['start_date'])) . ' AND ' . $this->db->escape(rawurldecode($inputs['end_date'])); - } $decimals = totals_decimals(); + $db_prefix = $this->db->getPrefix(); if($this->config['tax_included']) { - $sale_total = '(CASE WHEN sales_items.discount_type = ' . PERCENT - . " THEN sales_items.quantity_purchased * sales_items.item_unit_price - ROUND(sales_items.quantity_purchased * sales_items.item_unit_price * sales_items.discount / 100, $decimals)" - . ' ELSE sales_items.quantity_purchased * (sales_items.item_unit_price - sales_items.discount) END)'; + $sale_total = '(CASE WHEN ' . $db_prefix . 'sales_items.discount_type = ' . PERCENT + . " THEN " . $db_prefix . "sales_items.quantity_purchased * " . $db_prefix . "sales_items.item_unit_price - ROUND(" . $db_prefix . "sales_items.quantity_purchased * " . $db_prefix . "sales_items.item_unit_price * " . $db_prefix . "sales_items.discount / 100, $decimals)" + . ' ELSE ' . $db_prefix . 'sales_items.quantity_purchased * (' . $db_prefix . 'sales_items.item_unit_price - ' . $db_prefix . 'sales_items.discount) END)'; - $sale_subtotal = '(CASE WHEN sales_items.discount_type = ' . PERCENT - . " THEN sales_items.quantity_purchased * sales_items.item_unit_price - ROUND(sales_items.quantity_purchased * sales_items.item_unit_price * sales_items.discount / 100, $decimals) " - . 'ELSE sales_items.quantity_purchased * sales_items.item_unit_price - sales_items.discount END * (100 / (100 + sales_items_taxes.percent)))'; + $sale_subtotal = '(CASE WHEN ' . $db_prefix . 'sales_items.discount_type = ' . PERCENT + . " THEN " . $db_prefix . "sales_items.quantity_purchased * " . $db_prefix . "sales_items.item_unit_price - ROUND(" . $db_prefix . "sales_items.quantity_purchased * " . $db_prefix . "sales_items.item_unit_price * " . $db_prefix . "sales_items.discount / 100, $decimals) " + . 'ELSE ' . $db_prefix . 'sales_items.quantity_purchased * ' . $db_prefix . 'sales_items.item_unit_price - ' . $db_prefix . 'sales_items.discount END * (100 / (100 + ' . $db_prefix . 'sales_items_taxes.percent)))'; } else { - $sale_total = '(CASE WHEN sales_items.discount_type = ' . PERCENT - . " THEN sales_items.quantity_purchased * sales_items.item_unit_price - ROUND(sales_items.quantity_purchased * sales_items.item_unit_price * sales_items.discount / 100, $decimals)" - . ' ELSE sales_items.quantity_purchased * sales_items.item_unit_price - sales_items.discount END * (1 + (sales_items_taxes.percent / 100)))'; + $sale_total = '(CASE WHEN ' . $db_prefix . 'sales_items.discount_type = ' . PERCENT + . " THEN " . $db_prefix . "sales_items.quantity_purchased * " . $db_prefix . "sales_items.item_unit_price - ROUND(" . $db_prefix . "sales_items.quantity_purchased * " . $db_prefix . "sales_items.item_unit_price * " . $db_prefix . "sales_items.discount / 100, $decimals)" + . ' ELSE ' . $db_prefix . 'sales_items.quantity_purchased * ' . $db_prefix . 'sales_items.item_unit_price - ' . $db_prefix . 'sales_items.discount END * (1 + (' . $db_prefix . 'sales_items_taxes.percent / 100)))'; - $sale_subtotal = '(CASE WHEN sales_items.discount_type = ' . PERCENT - . " THEN sales_items.quantity_purchased * sales_items.item_unit_price - ROUND(sales_items.quantity_purchased * sales_items.item_unit_price * sales_items.discount / 100, $decimals)" - . ' ELSE sales_items.quantity_purchased * (sales_items.item_unit_price - sales_items.discount) END)'; + $sale_subtotal = '(CASE WHEN ' . $db_prefix . 'sales_items.discount_type = ' . PERCENT + . " THEN " . $db_prefix . "sales_items.quantity_purchased * " . $db_prefix . "sales_items.item_unit_price - ROUND(" . $db_prefix . "sales_items.quantity_purchased * " . $db_prefix . "sales_items.item_unit_price * " . $db_prefix . "sales_items.discount / 100, $decimals)" + . ' ELSE ' . $db_prefix . 'sales_items.quantity_purchased * (' . $db_prefix . 'sales_items.item_unit_price - ' . $db_prefix . 'sales_items.discount) END)'; } - $query = $this->db->query("SELECT name as name, percent, COUNT(DISTINCT sale_id) AS count, ROUND(SUM(subtotal), $decimals) AS subtotal, ROUND(SUM(tax), $decimals) AS tax, ROUND(SUM(total), $decimals) AS total - FROM ( - SELECT - name AS name, - CONCAT(IFNULL(ROUND(percent, $decimals), 0), '%') AS percent, - sales.sale_id AS sale_id, - $sale_subtotal AS subtotal, - IFNULL(sales_items_taxes.item_tax_amount, 0) AS tax, - IFNULL($sale_total, $sale_subtotal) AS total - FROM " . $this->db->prefixTable('sales_items') . ' AS sales_items - INNER JOIN ' . $this->db->prefixTable('sales') . ' AS sales - ON sales_items.sale_id = sales.sale_id - LEFT OUTER JOIN ' . $this->db->prefixTable('sales_items_taxes') . ' AS sales_items_taxes - 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 . ' - ) AS temp_taxes - GROUP BY percent, name' - ); + $subquery_builder = $this->db->table('sales_items'); + $subquery_builder->select("name AS name, CONCAT(IFNULL(ROUND(percent, $decimals), 0), '%') AS percent, sales.sale_id AS sale_id, $sale_subtotal AS subtotal, IFNULL($db_prefix"."sales_items_taxes.item_tax_amount, 0) AS tax, IFNULL($sale_total, $sale_subtotal) AS total"); - return $query->getResultArray(); + $subquery_builder->join('sales', 'sales_items.sale_id = sales.sale_id', 'inner'); + $subquery_builder->join('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'); -//TODO: Need to rework the above query into querybuilder. The problem is that QueryBuilder keeps prepending the table name prefix to the column name, not prepending it to the table name and escaping aliases when it shouldn't. -// $decimals = totals_decimals(); -// -// if($this->config['tax_included']) -// { -// $sale_total = '(CASE WHEN sales_items.discount_type = ' . PERCENT -// . " THEN sales_items.quantity_purchased * sales_items.item_unit_price - ROUND(sales_items.quantity_purchased * sales_items.item_unit_price * sales_items.discount / 100, $decimals)" -// . ' ELSE sales_items.quantity_purchased * (sales_items.item_unit_price - sales_items.discount) END)'; -// -// $sale_subtotal = '(CASE WHEN sales_items.discount_type = ' . PERCENT -// . " THEN sales_items.quantity_purchased * sales_items.item_unit_price - ROUND(sales_items.quantity_purchased * sales_items.item_unit_price * sales_items.discount / 100, $decimals) " -// . 'ELSE sales_items.quantity_purchased * sales_items.item_unit_price - sales_items.discount END * (100 / (100 + sales_items_taxes.percent)))'; -// } -// else -// { -// $sale_total = '(CASE WHEN sales_items.discount_type = ' . PERCENT -// . " THEN sales_items.quantity_purchased * sales_items.item_unit_price - ROUND(sales_items.quantity_purchased * sales_items.item_unit_price * sales_items.discount / 100, $decimals)" -// . ' ELSE sales_items.quantity_purchased * sales_items.item_unit_price - sales_items.discount END * (1 + (sales_items_taxes.percent / 100)))'; -// -// $sale_subtotal = '(CASE WHEN sales_items.discount_type = ' . PERCENT -// . " THEN sales_items.quantity_purchased * sales_items.item_unit_price - ROUND(sales_items.quantity_purchased * sales_items.item_unit_price * sales_items.discount / 100, $decimals)" -// . ' ELSE sales_items.quantity_purchased * (sales_items.item_unit_price - sales_items.discount) END)'; -// } -// -// $subquery_builder = $this->db->table('sales_items'); -// $subquery_builder->select("name, CONCAT(IFNULL(ROUND(percent, $decimals), 0), '%') AS percent, sales.sale_id AS sale_id, $sale_subtotal AS subtotal, IFNULL(sales_items_taxes.item_tax_amount, 0) AS tax, IFNULL($sale_total, $sale_subtotal) AS total"); -// -// $subquery_builder->join('sales', 'sales_items.sale_id = sales.sale_id', 'inner'); -// $subquery_builder->join('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'); -// -// if(empty($this->config['date_or_time_format'])) -// { -// $subquery_builder->where('DATE(sales.sale_time) BETWEEN ' . $inputs['start_date'] . ' AND ' . $inputs['end_date']); -// } -// else -// { -// $subquery_builder->where('sales.sale_time BETWEEN ' . rawurldecode($inputs['start_date']) . ' AND ' . rawurldecode($inputs['end_date'])); -// } -// -// $sub_query = $subquery_builder->getCompiledSelect(); -// -// $builder = $this->db->table("($sub_query) AS temp_taxes"); -// $builder->select("name, percent, COUNT(DISTINCT sale_id) AS count, ROUND(SUM(subtotal), $decimals) AS subtotal, ROUND(SUM(tax), $decimals) AS tax, ROUND(SUM(total), $decimals) AS total"); -// $builder->groupBy('percent, name'); -// -// return $builder->get()->getResultArray(); + $subquery_builder->where('sale_status', COMPLETED); + + if(empty($this->config['date_or_time_format'])) + { + $subquery_builder->where('DATE(' . $db_prefix . 'sales.sale_time) BETWEEN ' . $this->db->escape($inputs['start_date']) . ' AND ' . $this->db->escape($inputs['end_date'])); + } + else + { + $subquery_builder->where('sales.sale_time BETWEEN ' . $this->db->escape(rawurldecode($inputs['start_date'])) . ' AND ' . $this->db->escape(rawurldecode($inputs['end_date']))); + } + + $builder = $this->db->newQuery()->fromSubquery($subquery_builder, 'temp_taxes'); + $builder->select("name, percent, COUNT(DISTINCT sale_id) AS count, ROUND(SUM(subtotal), $decimals) AS subtotal, ROUND(SUM(tax), $decimals) AS tax, ROUND(SUM(total), $decimals) total"); + $builder->groupBy('percent, name'); + + return $builder->get()->getResultArray(); } }