From eea7d897f2c6b2234d4fca235a5a2d30ac900b45 Mon Sep 17 00:00:00 2001 From: Janusz Dobrowolski Date: Mon, 15 Jul 2019 20:28:14 +0200 Subject: [PATCH] Cost handling in purchasing module fixed. --- gl/includes/db/gl_db_trans.inc | 10 +-- purchasing/includes/db/grn_db.inc | 60 ++++++++-------- purchasing/includes/db/invoice_db.inc | 89 ++++++++++-------------- purchasing/includes/db/po_db.inc | 2 +- purchasing/includes/po_class.inc | 12 ++-- purchasing/includes/purchasing_db.inc | 1 + purchasing/includes/supp_trans_class.inc | 6 +- purchasing/includes/ui/invoice_ui.inc | 6 -- purchasing/supplier_credit.php | 16 ++--- purchasing/supplier_invoice.php | 40 +++++++---- reporting/rep204.php | 7 +- reporting/rep305.php | 4 +- taxes/tax_calc.inc | 30 +++++--- taxes/tax_rules.inc | 1 - 14 files changed, 144 insertions(+), 140 deletions(-) diff --git a/gl/includes/db/gl_db_trans.inc b/gl/includes/db/gl_db_trans.inc index 229ba2d1..15e2c84a 100644 --- a/gl/includes/db/gl_db_trans.inc +++ b/gl/includes/db/gl_db_trans.inc @@ -483,13 +483,15 @@ function add_trans_tax_details($trans_type, $trans_no, $tax_id, $rate, $included function get_trans_tax_details($trans_type, $trans_no) { - $sql = "SELECT tax_details.*, tax_type.name AS tax_type_name, tax_type.rate AS rate - FROM ".TB_PREF."trans_tax_details tax_details INNER JOIN - ".TB_PREF."tax_types tax_type ON tax_type.id = tax_details.tax_type_id + $sql = "SELECT tax_details.*, SUM(tax_details.amount) amount, SUM(tax_details.net_amount) as net_amount, + tax_type.name AS tax_type_name, tax_type.rate AS rate + FROM ".TB_PREF."trans_tax_details tax_details + LEFT JOIN ".TB_PREF."tax_types tax_type ON tax_type.id = tax_details.tax_type_id WHERE trans_type = ".db_escape($trans_type)." AND trans_no = ".db_escape($trans_no)." - AND (net_amount != 0 OR amount != 0)"; + AND (net_amount != 0 OR amount != 0) + GROUP BY tax_type_id"; return db_query($sql, "The transaction tax details could not be retrieved"); } diff --git a/purchasing/includes/db/grn_db.inc b/purchasing/includes/db/grn_db.inc index 26b5bc7e..c303933f 100644 --- a/purchasing/includes/db/grn_db.inc +++ b/purchasing/includes/db/grn_db.inc @@ -121,43 +121,41 @@ function write_grn(&$po) { $stock_gl_code = get_stock_gl_code($order_line->stock_id); - /*Update sales_order_details for the new quantity received and the standard cost used for postings to GL - and recorded in the stock movements for FIFO/LIFO stocks valuations*/ + //------------------------------------------------------------------------------------------------------ + if ($order_line->qty_received == 0) + { + /* This must be the first receipt of goods against this PO line. */ + /* Store provisional cost used in GL posting - inventory is updated to actual cost later when invoice is received */ + $order_line->unit_cost = round2($order_line->taxfree_charge_value($po) / $po->ex_rate / $order_line->quantity, user_price_dec()); + } + //------------------- update average material cost and clearing account -------------------------------- if (is_inventory_item($order_line->stock_id)) { if ($clearing_act) - $total += add_gl_trans_supplier(ST_SUPPRECEIVE, $grn, $date_, $stock_gl_code["inventory_account"], - $stock_gl_code['dimension_id'], $stock_gl_code['dimension2_id'], - $order_line->taxfree_charge_value($po), $po->supplier_id, 0, $order_line->stock_id); + $total += add_gl_trans_std_cost(ST_SUPPRECEIVE, $grn, $date_, $stock_gl_code["inventory_account"], + $stock_gl_code['dimension_id'], $stock_gl_code['dimension2_id'], $order_line->stock_id, + $order_line->unit_cost*$order_line->quantity, PT_SUPPLIER, $po->supplier_id); + update_average_material_cost($po->supplier_id, $order_line->stock_id, $order_line->price, $order_line->quantity, $date_); } - //------------------------------------------------------------------------------------------------------ - if ($order_line->qty_received == 0) - { - /*This must be the first receipt of goods against this line */ - /*Need to get the standard cost as it is now so we can process GL jorunals later*/ - $order_line->unit_cost = get_unit_cost($order_line->stock_id); - } - // Update the purchase data table - add_or_update_purchase_data($po->supplier_id, $order_line->stock_id, $order_line->price, - $order_line->item_description); - /*Need to insert a grn item */ // also need to check for over-receive.(within allowance) + /* Need to insert a grn item */ // also need to check for over-receive.(within allowance) if ($order_line->quantity + $order_line->qty_received > $order_line->qty_ordered) $order_line->qty_ordered = $order_line->quantity + $order_line->qty_received; + /* Store line details and update po_line */ $grn_item = write_grn_item($grn, $order_line->po_item_id, - $order_line->stock_id, $order_line->item_description, $order_line->quantity, $order_line->grn_item_id); + $order_line->stock_id, $order_line->item_description, $order_line->quantity, $order_line->grn_item_id, $order_line->unit_cost); $po->line_items[$line_no]->grn_item_id = $grn_item; /* Update location stock records - NB a po cannot be entered for a service/kit parts done automatically */ add_stock_move(ST_SUPPRECEIVE, $order_line->stock_id, $grn, $po->Location, $date_, "", $order_line->quantity, $order_line->unit_cost, $order_line->taxfree_charge_value($po)/$order_line->quantity); - } /*quantity received is != 0 */ - } /*end of order_line loop */ + } /* quantity received is != 0 */ + } if ($clearing_act && $total != 0.0) { $accs = get_supplier_accounts($po->supplier_id); @@ -170,6 +168,7 @@ function write_grn(&$po) $po->trans_no = $grn; hook_db_postwrite($po, ST_SUPPRECEIVE); + commit_transaction(); return $grn; @@ -208,7 +207,7 @@ function update_grn_batch($grn, $reference, $location, $date_) } //------------------------------------------------------------------------------------------------------------- -function write_grn_item($grn_batch_id, $po_detail_item, $item_code, $description, $quantity_received, $grn_item_id) +function write_grn_item($grn_batch_id, $po_detail_item, $item_code, $description, $quantity_received, $grn_item_id, $unit_cost) { if ($grn_item_id) $sql = "UPDATE ".TB_PREF."grn_items SET qty_recd=".db_escape($quantity_received) @@ -223,7 +222,8 @@ function write_grn_item($grn_batch_id, $po_detail_item, $item_code, $description $sql = "UPDATE ".TB_PREF."purch_order_details po, (SELECT SUM(qty_recd) received FROM ".TB_PREF."grn_items grn WHERE po_detail_item=".db_escape($po_detail_item).") grn - SET po.quantity_received = grn.received + SET po.quantity_received = grn.received, + po.std_cost_unit =".db_escape($unit_cost)." WHERE po_detail_item = ".db_escape($po_detail_item); db_query($sql, "a purchase order details record could not be updated. This receipt of goods has not been processed "); @@ -262,24 +262,23 @@ function set_grn_item_credited(&$entered_grn, $supplier, $transno, $date) $myrow = db_fetch($result); $sql = "UPDATE ".TB_PREF."purch_order_details - SET quantity_received = quantity_received + " + SET quantity_received = quantity_received - " .db_escape($entered_grn->this_quantity_inv).", - quantity_ordered = quantity_ordered + " + quantity_ordered = quantity_ordered - " .db_escape($entered_grn->this_quantity_inv).", - qty_invoiced = qty_invoiced + ".db_escape($entered_grn->this_quantity_inv).", - std_cost_unit=".db_escape($mcost).", + qty_invoiced = qty_invoiced - ".db_escape($entered_grn->this_quantity_inv).", act_price=".db_escape($entered_grn->chg_price)." WHERE po_detail_item = ".$myrow["po_detail_item"]; db_query($sql, "a purchase order details record could not be updated. This receipt of goods has not been processed "); //$sql = "UPDATE ".TB_PREF."grn_items SET qty_recd=0, quantity_inv=0 WHERE id=$entered_grn->id"; - $sql = "UPDATE ".TB_PREF."grn_items SET qty_recd=qty_recd+".db_escape($entered_grn->this_quantity_inv) - .",quantity_inv=quantity_inv+".db_escape($entered_grn->this_quantity_inv) + $sql = "UPDATE ".TB_PREF."grn_items SET qty_recd=qty_recd-".db_escape($entered_grn->this_quantity_inv) + .",quantity_inv=quantity_inv-".db_escape($entered_grn->this_quantity_inv) ." WHERE id=".db_escape($entered_grn->id); db_query($sql); add_stock_move(ST_SUPPCREDIT, $entered_grn->item_code, $transno, $myrow['loc_code'], $date, "", - $entered_grn->this_quantity_inv, $mcost, $entered_grn->chg_price); + -$entered_grn->this_quantity_inv, $mcost, $entered_grn->chg_price); } function get_grn_items($grn_batch_id=0, $supplier_id="", $outstanding_only=false, @@ -338,7 +337,7 @@ function get_grn_items($grn_batch_id=0, $supplier_id="", $outstanding_only=false // get the details for a given grn item -function get_grn_item_detail($grn_item_no) +function get_grn_item($grn_item_no) { $sql = "SELECT grn.*, po.unit_price, grn.qty_recd - grn.quantity_inv AS QtyOstdg, po.std_cost_unit @@ -370,8 +369,7 @@ function read_grn_items_to_order($grn_batch, &$order) $order->add_to_order($myrow["item_code"], $myrow["qty_recd"],$myrow["description"], $myrow["unit_price"], sql2date($myrow["req_del_date"]), $myrow["quantity_inv"], - $myrow["quantity_received"], $myrow["quantity_ordered"], $myrow["id"], $myrow["po_detail_item"]); - + $myrow["quantity_received"], $myrow["quantity_ordered"], $myrow["id"], $myrow["po_detail_item"], $myrow["std_cost_unit"]); } /* line po from purchase order details */ } //end of checks on returned data set } diff --git a/purchasing/includes/db/invoice_db.inc b/purchasing/includes/db/invoice_db.inc index de085139..07e87eb0 100644 --- a/purchasing/includes/db/invoice_db.inc +++ b/purchasing/includes/db/invoice_db.inc @@ -175,11 +175,6 @@ function add_supp_invoice(&$supp_trans) //, $already_voided=false, $allocs=null $net_total = 0; foreach($supp_trans->grn_items as $item) { - if ($trans_type == ST_SUPPCREDIT) - { - $item->this_quantity_inv = -$item->this_quantity_inv; - set_grn_item_credited($item, $supp_trans->supplier_id, $invoice_id, $date_); - } $item_gl = $item->gl_amounts; $stock_gl_code = get_stock_gl_code($item->item_code); @@ -195,16 +190,14 @@ function add_supp_invoice(&$supp_trans) //, $already_voided=false, $allocs=null { if ($value['Deductible']) { // GL: VAT deductible - $gl_cart->add_gl_item($value['purchasing_gl_code'], 0, 0, $value['Deductible']+$value['Adjust'], //FIXME: 'Adjust' ? - $value['Payable'] ? sprintf(_('Internal invoice %s input tax'), $supp_trans->reference) : ''); + $gl_cart->add_gl_item($value['purchasing_gl_code'], 0, 0, $value['Deductible']+$value['Adjust']); // GL: VAT adjustment due to vat factor if ($value['Adjust']) $gl_cart->add_gl_item(get_company_pref('tax_adjustments_act'), 0, 0, -$value['Adjust']); } if ($value['Payable']) // reverse charge/intracommunity aquisition { - $gl_cart->add_gl_item($value['sales_gl_code'], 0, 0, -$value['Payable'], - sprintf(_('Internal invoice %s input tax'), $supp_trans->reference)); + $gl_cart->add_gl_item($value['sales_gl_code'], 0, 0, -$value['Payable']); } // GL: AP account (vat part) if ($value['Value']) @@ -220,62 +213,47 @@ function add_supp_invoice(&$supp_trans) //, $already_voided=false, $allocs=null $value['tax_type_id'], $value['rate'], $supp_trans->tax_included, $value['Value'], $item_gl['Net'], $supp_trans->ex_rate, $date_, $supp_trans->supp_reference, TR_INPUT, $supp_trans->tax_group_id, $vat_category); - // $value['Deductible'], ??? - - $tax_total += $value['Value']; - $line_tax += $value['Payable'] ? $value['Payable'] : $value['Value']; } } + // GL: AP account (net) $gl_cart->add_gl_item($supplier["payable_account"], 0, 0, -$item_gl['Net'], '', '', $supp_trans->supplier_id); + + $tax_total += $item_gl['Tax']; $net_total += $item_gl['Net']; // cost line value $taxfree_line = $item_gl['Cost']; - $old = update_supp_received_items_for_invoice($item->id, $item->po_detail_item, - $item->this_quantity_inv, $item->chg_price); - - // Since the standard cost is always calculated on basis of the po unit_price, - // this is also the price that should be the base of calculating the price diff. - // In cases where there is two different po invoices on the same delivery with different unit prices this will not work either - $old_price = $old[2]; - - /* - If statement is removed. Should always check for deliveries nomatter if there has been a price change. - */ - $old_date = sql2date($old[1]); - if (!is_inventory_item($item->item_code)) { - $gl_cart->add_gl_item($supplier["purchase_account"] ? $supplier["purchase_account"] : $stock_gl_code["cogs_account"], $dimension, $dimension2, $taxfree_line); - + $gl_cart->add_gl_item($supplier["purchase_account"] ? $supplier["purchase_account"] : $stock_gl_code["cogs_account"], $dimension, $dimension2, $taxfree_line); + + } elseif ($trans_type != ST_SUPPCREDIT) { + $gl_cart->add_gl_item($stock_gl_code["inventory_account"], $dimension, $dimension2, $taxfree_line, _('Return to supplier')); + // we must use invoice value here to preserve proper inventory valuation, + // but if the purchase changed average cost, and any item was sold between invoice and credit, + // the average will not return to the previous one. To fix this additional cost update should be made here to compensate cogs difference on items sold. + update_average_material_cost(null, $item->item_code, $item_gl['Cost']/$item->this_quantity_inv, -$item->this_quantity_inv, $date_); } else { - $val = split_item_price($item->item_code, $item->this_quantity_inv * $old_price, - $supp_trans->tax_group_id, $supp_trans->tax_included); - - $GRN_value = $val['Cost']; - - $diff = get_diff_in_home_currency($supp_trans->supplier_id, $old_date, $date_, $GRN_value, - $taxfree_line); + // calculate difference between clearing cost and actual cost + $diff = $item_gl['Cost'] - $item->std_cost_unit*$item->this_quantity_inv; - // update average cost with per item part of difference (between invoice value and value set on po/grn) update_average_material_cost(null, $item->item_code, - $diff/$item->this_quantity_inv, $item->this_quantity_inv, null, true, "add_supp_invoice $trans_type:$invoice_id"); + $diff/$item->this_quantity_inv, $item->this_quantity_inv, null, true); - if ($clearing_act) // no postings on GRN, so post full net value + if ($clearing_act) { - //Add GL transaction for GRN Provision in case of difference - // material was already posted due GRN; post differences in value - if ($diff != 0) + if ($diff != 0) // if value on invoice differs from those posted on GRN receive, post the difference { $gl_cart->add_gl_item($stock_gl_code["inventory_account"], // cart is in supplier currency, so need to fix by ex_rate here $dimension, $dimension2, $diff/$gl_cart->rate, _('GRN Provision')); // subject to rounding errors? + $gl_cart->add_gl_item($clearing_act, - $dimension, $dimension2, -$diff/$gl_cart->rate, _('GRN Provision')); + $dimension, $dimension2, -$diff/$gl_cart->rate); //Chaitanya //If QOH is 0 or negative then update_average_material_cost will be skipped @@ -308,7 +286,7 @@ function add_supp_invoice(&$supp_trans) //, $already_voided=false, $allocs=null } $gl_cart->add_gl_item($clearing_act, $dimension, $dimension2, $taxfree_line); } - else + else // no postings on GRN, so post full cost here $gl_cart->add_gl_item($stock_gl_code["inventory_account"], $dimension, $dimension2, $taxfree_line); } @@ -317,20 +295,25 @@ function add_supp_invoice(&$supp_trans) //, $already_voided=false, $allocs=null // add_actual_cost($item->order_price, $item->item_code); // } - add_or_update_purchase_data($supp_trans->supplier_id, $item->item_code, $item->chg_price); + if ($trans_type == ST_SUPPCREDIT) + set_grn_item_credited($item, $supp_trans->supplier_id, $invoice_id, $date_); + else { + add_or_update_purchase_data($supp_trans->supplier_id, $item->item_code, $item->chg_price); + update_supp_received_items_for_invoice($item->id, $item->po_detail_item, + $item->this_quantity_inv, $item->chg_price); + } + + $qty = ($trans_type==ST_SUPPCREDIT ? 1 : -1)*$item->this_quantity_inv; add_supp_invoice_item($trans_type, $invoice_id, $item->item_code, - $item->item_description, 0, $item->chg_price, $line_tax/$item->this_quantity_inv, - $item->this_quantity_inv, $item->id, $item->po_detail_item); + $item->item_description, 0, $item->chg_price, $line_tax/$qty, $qty, $item->id, $item->po_detail_item); } // grn_items + /*GL Items are straight forward - just do the debit postings to the GL accounts specified - the credit is to creditors control act */ foreach ($supp_trans->gl_codes as $entered_gl_code) { - if ($trans_type == ST_SUPPCREDIT) - $entered_gl_code->amount = -$entered_gl_code->amount; - $memo_ = $entered_gl_code->memo_; $index = is_tax_account($entered_gl_code->gl_code); @@ -338,8 +321,6 @@ function add_supp_invoice(&$supp_trans) //, $already_voided=false, $allocs=null { $gl_cart->add_gl_item($entered_gl_code->gl_code, $entered_gl_code->gl_dim, $entered_gl_code->gl_dim2, $entered_gl_code->amount); // store tax details if the gl account is a tax account - if ($trans_type == ST_SUPPCREDIT) - $entered_gl_code->amount = -$entered_gl_code->amount; add_gl_tax_details($entered_gl_code->gl_code, $trans_type, $invoice_id, $entered_gl_code->amount, $supp_trans->ex_rate, $date_, $supp_trans->supp_reference, $supp_trans->tax_included, null, $supp_trans->tax_group_id); @@ -355,6 +336,12 @@ function add_supp_invoice(&$supp_trans) //, $already_voided=false, $allocs=null $entered_gl_code->gl_dim, $entered_gl_code->gl_dim2); } + if ($trans_type == ST_SUPPCREDIT) { // reverse postings if this is credit note + foreach($gl_cart->gl_items as &$line) + $line->amount = -$line->amount; + $net_total = -$net_total; + $tax_total = -$tax_total; + } $gl_cart->reduce_gl(); // minimize GL lines $gl_cart->write_gl(false); // don't check balances here: we are working on two (maybe unbalanced) carts diff --git a/purchasing/includes/db/po_db.inc b/purchasing/includes/db/po_db.inc index f48621fa..e7257e00 100644 --- a/purchasing/includes/db/po_db.inc +++ b/purchasing/includes/db/po_db.inc @@ -238,7 +238,7 @@ function read_po_items($order_no, &$order, $open_items_only=false) $myrow["quantity_ordered"],$myrow["description"], $myrow["unit_price"], sql2date($myrow["delivery_date"]), $myrow["qty_invoiced"], $myrow["quantity_received"], - $myrow["quantity_ordered"], 0, $myrow["po_detail_item"]); + $myrow["quantity_ordered"], 0, $myrow["po_detail_item"], $myrow["std_cost_unit"]); } /* line po from purchase order details */ } //end of checks on returned data set } diff --git a/purchasing/includes/po_class.inc b/purchasing/includes/po_class.inc index 54ae5164..22a9274b 100644 --- a/purchasing/includes/po_class.inc +++ b/purchasing/includes/po_class.inc @@ -69,10 +69,10 @@ class purch_order $this->tax_area = $tax_area; } - function add_to_order($stock_id, $qty, $item_descr, $price, $req_del_date, $qty_inv, $qty_recd, $qty_ordered=0, $grn_item_id=0, $po_item_id=0) + function add_to_order($stock_id, $qty, $item_descr, $price, $req_del_date, $qty_inv, $qty_recd, $qty_ordered=0, $grn_item_id=0, $po_item_id=0, $unit_cost=0) { $this->line_items[] = new po_line_details($stock_id, $item_descr, $qty, $price, - $req_del_date, $qty_inv, $qty_recd, $qty_ordered, $grn_item_id, $po_item_id); + $req_del_date, $qty_inv, $qty_recd, $qty_ordered, $grn_item_id, $po_item_id, $unit_cost); } function update_order_item($line_no, $qty, $price, $req_del_date, $description="") @@ -207,7 +207,7 @@ class purch_order { $diff = $tax['Override'] - $tax['Value']; $this->line_items[$id]->gl_amounts[0]['Value'] += $diff; - if ($this->vat_category() != VC_NONDEDUCT) + if ($line->vat_category != VC_NONDEDUCT) $this->line_items[$id]->gl_amounts[0]['Deductible'] += $diff; else $this->line_items[$id]->gl_amounts['Cost'] += $diff; @@ -247,7 +247,7 @@ class po_line_details var $gl_amounts; // splited line value (after call to split_line_value method) function __construct($stock_item, $item_descr, $qty, $prc, $req_del_date, - $qty_inv, $qty_recd, $qty_ordered=0, $grn_item_id=0, $po_item_id=0) + $qty_inv, $qty_recd, $qty_ordered=0, $grn_item_id=0, $po_item_id=0, $unit_cost=0) { $this->stock_id = $stock_item; $item_row = get_item($stock_item); @@ -265,7 +265,7 @@ class po_line_details $this->units = $item_row["units"]; $this->qty_received = $qty_recd; $this->qty_inv = $qty_inv; - $this->unit_cost =0; + $this->unit_cost = $unit_cost; $this->grn_item_id = $grn_item_id; $this->vat_category = $item_row["vat_category"]; $this->qty_ordered = $qty_ordered; @@ -289,7 +289,7 @@ class po_line_details $vat_factor = 1; return $this->gl_amounts = split_item_price($this->stock_id, $this->price*$this->quantity, $cart->tax_group_id, $cart->tax_included, - ST_SUPPINVOICE, $vat_factor, $cart->tran_date); + ST_SUPPINVOICE, $vat_factor); } } diff --git a/purchasing/includes/purchasing_db.inc b/purchasing/includes/purchasing_db.inc index 53d73dbc..eb4a1ac4 100644 --- a/purchasing/includes/purchasing_db.inc +++ b/purchasing/includes/purchasing_db.inc @@ -194,6 +194,7 @@ function add_direct_supp_trans($cart) $inv->add_grn_to_trans($line->grn_item_id, $line->po_item_id, $line->stock_id, $line->item_description, $line->quantity, 0, $line->quantity, $line->price, $line->price, true, get_unit_cost($line->stock_id), ''); + $total += round2(($line->quantity * $line->price), user_price_dec()); } $inv->tax_overrides = $cart->tax_overrides; diff --git a/purchasing/includes/supp_trans_class.inc b/purchasing/includes/supp_trans_class.inc index 31b00b8a..59d0e5c2 100644 --- a/purchasing/includes/supp_trans_class.inc +++ b/purchasing/includes/supp_trans_class.inc @@ -213,11 +213,11 @@ class supp_trans if ($tax['Value'] != 0 && isset($tax['Override']) && ($tax['Value'] != $tax['Override'])) { foreach($this->grn_items as $id => $line) - if ($line->gl_amounts[0]['tax_type_id'] == $tax_id) // assumed single tax rate on item, so always gl_mount[0] is valid + if ($line->gl_amounts[0]['tax_type_id'] == $tax_id) // assumed single tax rate on item, so always gl_amounts[0] is valid { $diff = $tax['Override'] - $tax['Value']; $this->grn_items[$id]->gl_amounts[0]['Value'] += $diff; - if ($this->vat_category() != VC_NONDEDUCT) + if ($line->vat_category != VC_NONDEDUCT) $this->grn_items[$id]->gl_amounts[0]['Deductible'] += $diff; else $this->grn_items[$id]->gl_amounts['Cost'] += $diff; @@ -300,7 +300,7 @@ all the info to do the necessary entries without looking up ie additional querie $vat_factor = 1; return $this->gl_amounts = split_item_price($this->item_code, $this->chg_price*$this->this_quantity_inv, $cart->tax_group_id, $cart->tax_included, - ST_SUPPINVOICE, $vat_factor, $cart->tran_date); + ST_SUPPINVOICE, $vat_factor); } } diff --git a/purchasing/includes/ui/invoice_ui.inc b/purchasing/includes/ui/invoice_ui.inc index 8299aa0e..2e9520e7 100644 --- a/purchasing/includes/ui/invoice_ui.inc +++ b/purchasing/includes/ui/invoice_ui.inc @@ -386,12 +386,6 @@ function display_grn_items_for_selection(&$supp_trans, $k) $n = $myrow["id"]; label_cell(get_trans_view_str(ST_SUPPRECEIVE, $myrow["grn_batch_id"]), "nowrap align='right'"); - hidden('qty_recd'.$n, $myrow["qty_recd"]); - hidden('item_code'.$n, $myrow["item_code"]); - hidden('item_description'.$n, $myrow["description"]); - hidden('prev_quantity_inv'.$n, $myrow['quantity_inv']); - hidden('order_price'.$n, $myrow['unit_price']); - hidden('po_detail_item'.$n, $myrow['po_detail_item']); label_cell(get_trans_view_str(ST_PURCHORDER, $myrow["purch_order_no"]), "nowrap align='right'"); label_cell($myrow["item_code"]); label_cell($myrow["description"]); diff --git a/purchasing/supplier_credit.php b/purchasing/supplier_credit.php index 461c8044..cbb10a8d 100644 --- a/purchasing/supplier_credit.php +++ b/purchasing/supplier_credit.php @@ -236,10 +236,7 @@ function handle_commit_credit_note() if (!check_data()) return; - if (isset($_POST['invoice_no'])) - $invoice_no = add_supp_invoice($_SESSION['supp_trans'], $_POST['invoice_no']); - else - $invoice_no = add_supp_invoice($_SESSION['supp_trans']); + $invoice_no = add_supp_invoice($_SESSION['supp_trans']); $_SESSION['supp_trans']->clear_items(); unset($_SESSION['supp_trans']); @@ -270,7 +267,7 @@ function check_item_data($n) set_focus('ChgPrice'.$n); return false; } - + return true; } @@ -278,11 +275,12 @@ function commit_item_data($n) { if (check_item_data($n)) { + $item = get_grn_item($n); $_SESSION['supp_trans']->add_grn_to_trans($n, - $_POST['po_detail_item'.$n], $_POST['item_code'.$n], - $_POST['item_description'.$n], $_POST['qty_recd'.$n], - $_POST['prev_quantity_inv'.$n], input_num('This_QuantityCredited'.$n), - $_POST['order_price'.$n], input_num('ChgPrice'.$n)); + $item['po_detail_item'], $item['item_code'], + $item['description'], $item['qty_recd'], + $item['quantity_inv'], input_num('This_QuantityCredited'.$n), + $item['unit_price'], input_num('ChgPrice'.$n), $item['std_cost_unit']); reset_tax_input(); } } diff --git a/purchasing/supplier_invoice.php b/purchasing/supplier_invoice.php index e75ec45c..0ac3052d 100644 --- a/purchasing/supplier_invoice.php +++ b/purchasing/supplier_invoice.php @@ -246,6 +246,14 @@ function check_item_data($n) { global $SysPrefs; + $item = get_grn_item($n); + + if (!$item) + { + display_error( _("Invalid GRN item selected.")); + return false; + } + if (!check_num('this_quantity_inv'.$n, 0) || input_num('this_quantity_inv'.$n)==0) { display_error( _("The quantity to invoice must be numeric and greater than zero.")); @@ -263,10 +271,8 @@ function check_item_data($n) $margin = $SysPrefs->over_charge_allowance(); if ($SysPrefs->check_price_charged_vs_order_price == True) { - if ($_POST['order_price'.$n]!=input_num('ChgPrice'.$n)) { - if ($_POST['order_price'.$n]==0 || - input_num('ChgPrice'.$n)/$_POST['order_price'.$n] > - (1 + ($margin/ 100))) + if ($item['unit_price'] != input_num('ChgPrice'.$n)) { + if ($item['unit_price'] == 0 || input_num('ChgPrice'.$n)/$item['unit_price'] > (1 + ($margin/ 100))) { display_error(_("The price being invoiced is more than the purchase order price by more than the allowed over-charge percentage. The system is set up to prohibit this. See the system administrator to modify the set up parameters if necessary.") . _("The over-charge percentage allowance is :") . $margin . "%"); @@ -276,9 +282,9 @@ function check_item_data($n) } } - if ($SysPrefs->check_qty_charged_vs_del_qty == true && ($_POST['qty_recd'.$n] != $_POST['prev_quantity_inv'.$n])) + if ($SysPrefs->check_qty_charged_vs_del_qty == true && ($item['qty_recd'] != $item['quantity_inv'])) { - if (input_num('this_quantity_inv'.$n) / ($_POST['qty_recd'.$n] - $_POST['prev_quantity_inv'.$n]) > + if (input_num('this_quantity_inv'.$n) / ($item['qty_recd'] - $item['quantity_inv']) > (1+ ($margin / 100))) { display_error( _("The quantity being invoiced is more than the outstanding quantity by more than the allowed over-charge percentage. The system is set up to prohibit this. See the system administrator to modify the set up parameters if necessary.") @@ -288,17 +294,23 @@ function check_item_data($n) } } - return true; + $item['quantity'] = input_num('this_quantity_inv'.$n); + $item['chg_price'] = input_num('ChgPrice'.$n); + + return $item; } function commit_item_data($n) { - if (check_item_data($n)) + $item = check_item_data($n); + if ($item) { - $_SESSION['supp_trans']->add_grn_to_trans($n, $_POST['po_detail_item'.$n], - $_POST['item_code'.$n], $_POST['item_description'.$n], $_POST['qty_recd'.$n], - $_POST['prev_quantity_inv'.$n], input_num('this_quantity_inv'.$n), - $_POST['order_price'.$n], input_num('ChgPrice'.$n)); + $_SESSION['supp_trans']->add_grn_to_trans($n, + $item['po_detail_item'], $item['item_code'], + $item['description'], $item['qty_recd'], + $item['quantity_inv'], $item['quantity'], + $item['unit_price'], $item['chg_price'], $item['std_cost_unit']); + reset_tax_input(); } } @@ -315,9 +327,9 @@ if (isset($_POST['InvGRNAll'])) { foreach($_POST as $postkey=>$postval ) { - if (strpos($postkey, "qty_recd") === 0) + if (strpos($postkey, "this_quantity_inv") === 0) { - $id = substr($postkey, strlen("qty_recd")); + $id = substr($postkey, strlen("this_quantity_inv")); $id = (int)$id; commit_item_data($id); } diff --git a/reporting/rep204.php b/reporting/rep204.php index 51fbf012..cc8b5362 100644 --- a/reporting/rep204.php +++ b/reporting/rep204.php @@ -37,7 +37,6 @@ function getTransactions($fromsupp) item.description, qty_recd, quantity_inv, - std_cost_unit, act_price, unit_price FROM ".TB_PREF."grn_items item, @@ -102,7 +101,7 @@ function print_outstanding_GRN() $SuppTot_Val=0; $res = getTransactions($fromsupp); - While ($GRNs = db_fetch($res)) + while ($GRNs = db_fetch($res)) { $dec2 = get_qty_dec($GRNs['item_code']); if ($Supplier != $GRNs['supplier_id']) @@ -126,9 +125,9 @@ function print_outstanding_GRN() $rep->AmountCol(3, 4, $GRNs['qty_recd'], $dec2); $rep->AmountCol(4, 5, $GRNs['quantity_inv'], $dec2); $QtyOstg = $GRNs['qty_recd'] - $GRNs['quantity_inv']; - $Value = ($GRNs['qty_recd'] - $GRNs['quantity_inv']) * $GRNs['act_price']; + $Value = ($GRNs['qty_recd'] - $GRNs['quantity_inv']) * $GRNs['unit_price']; $rep->AmountCol(5, 6, $QtyOstg, $dec2); - $rep->AmountCol(6, 7, $GRNs['act_price'], $dec); + $rep->AmountCol(6, 7, $GRNs['unit_price'], $dec); $rep->AmountCol(7, 8, $Value, $dec); $Tot_Val += $Value; $SuppTot_Val += $Value; diff --git a/reporting/rep305.php b/reporting/rep305.php index a6f8a9bc..89b417e1 100644 --- a/reporting/rep305.php +++ b/reporting/rep305.php @@ -171,8 +171,8 @@ function print_grn_valuation() $trans['unit_price'] *= $rate; $rep->TextCol(4, 5, "--"); $rep->AmountCol(5, 6, $trans['qty_recd'] - $trans['quantity_inv'], $qdec); - $rep->AmountCol(7, 8, $trans['unit_price'], $dec); - $amt = round2(($trans['qty_recd'] - $trans['quantity_inv']) * $trans['unit_price'], $dec); + $rep->AmountCol(7, 8, $trans['std_cost_unit'], $dec); + $amt = round2(($trans['qty_recd'] - $trans['quantity_inv']) * $trans['std_cost_unit'], $dec); $rep->AmountCol(8, 9, $amt, $dec); $total += $amt; $qtotal += $trans['qty_recd'] - $trans['quantity_inv']; diff --git a/taxes/tax_calc.inc b/taxes/tax_calc.inc index 323f92e0..84aa9ce6 100644 --- a/taxes/tax_calc.inc +++ b/taxes/tax_calc.inc @@ -95,8 +95,8 @@ function get_base_taxdata($stock_id, $group_id) $amount - price/value to be splitted $tax_group - entity tax group $tax_included - whether value includes all taxes - $vat_factor - 0-1; tax deduction factor - $allow_reverse - option for invoice - whether to honour reverse charging + $vat_factor - 0-1; tax deduction factor (purchases, not used for now; depends on whthere it is related to exempt or taxed sales) + $allow_reverse - option for invoice - whether to honour reverse charging (depends on customer tax status) Returned array contains calculated values for GL postings and tax registration: 'Net' - value without tax, @@ -107,16 +107,26 @@ function get_base_taxdata($stock_id, $group_id) and (with numeric keys) detailed info for any applicable tax rate: 'tax_type_id' - tax type id 'Value' - charged tax value - 'Deductible' - tax deductible (can be lower than Value for special goods) + 'Deductible' - tax deductible (can be lower than Value for special goods or mixed sales structure) 'Payable' - tax payable - 'Adjust' - additional adjustemnt to deductible tax due to sales structure factor + 'Adjust' - additional adjustment to deductible tax due to sales structure factor 'rate' - tax rate 'sales_gl_code' - sales tax GL account 'purchasing_gl_code' - purchase tax GL account 'tax_type_name' - name of tax type + + Price value is splitted as follows: + Tax: sum of Value (for applicable taxes) + Net: amount - Tax + Cost: Net + sum(Payable-Deductible) + for every applicable tax rate: + Value: tax calculated or 0 + Deductible: vat_factor*Value or 0 + Adjust: Value-Deductible or 0 + Payable: 0 or Value */ function split_item_price($stock_id, $amount, $group_id, $tax_included=false, $trans_type=ST_SUPPINVOICE, $vat_factor = 1, - $allow_reverse=true, $date=null) + $allow_reverse=true) { global $TS; @@ -187,13 +197,17 @@ function split_item_price($stock_id, $amount, $group_id, $tax_included=false, $t if ($taxopt & TAX_DEDUCTIBLE) // tax is deductible { - $tax['Deductible'] = round2($vat_value*$factor, 2); // [4815] To avoid rounding issues if $dec > 2 decimal places + $tax['Deductible'] = round2($vat_value*$factor, 2); // avoid rounding issues if $dec > 2 decimal places $tax['Adjust'] = round2(-(1-$vat_factor)*$factor*$vat_value, $dec); // adjustment due to mixed taxed/exmpt sales activity } else { $tax['Deductible'] = 0; $tax['Adjust'] = 0; } - $ret_array['Cost'] += $tax['Value'] + ($tax['Payable'] - $tax['Deductible']);// - $tax['Adjust']; + + if ($tax['Payable']) + $ret_array['Cost'] += ($tax['Payable'] - $tax['Deductible']); + elseif ($tax['Deductible']) + $ret_array['Cost'] += $tax['Adjust']; $ret_array[] = $tax; $ret_array['Tax'] += $tax['Value']; @@ -227,7 +241,7 @@ function get_tax_for_items($trans_type, $items, $prices, $shipping_cost, $tax_gr foreach($items as $i => $stock_id) { $taxdata = split_item_price($stock_id, $prices[$i], $tax_group, $tax_included, $trans_type, - $vat_factors ? $vat_factors[$i] : 1, $allow_reverse, $date=null); // FIXME: $date + $vat_factors ? $vat_factors[$i] : 1, $allow_reverse); foreach ($taxdata as $key => $data) { diff --git a/taxes/tax_rules.inc b/taxes/tax_rules.inc index 73f30b64..9dd3519f 100644 --- a/taxes/tax_rules.inc +++ b/taxes/tax_rules.inc @@ -16,7 +16,6 @@ TODO: . changes in Sales module . change all tax related methods in supp_trans to use split_item_price instead of other functions like get_taxes_for_item - . all tax types selections in tax group table (beside domestic group) are currently ignored (see FIXME in split_item_price()) */ define('TAX_NONE', 0); // none option define('TQ_NONE', 0); // none option -- 2.30.2