2 /**********************************************************************
3 Copyright (C) FrontAccounting, LLC.
4 Released under the terms of the GNU General Public License, GPL,
5 as published by the Free Software Foundation, either version 3
6 of the License, or (at your option) any later version.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10 See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
11 ***********************************************************************/
13 function add_wo_costing($workorder_id, $cost_type, $trans_type, $trans_no, $factor=1)
15 $sql = "INSERT INTO ".TB_PREF."wo_costing (workorder_id, cost_type, trans_type, trans_no, factor)
16 VALUES (".db_escape($workorder_id).","
17 .db_escape($cost_type).",".db_escape($trans_type).","
18 .db_escape($trans_no).",".db_escape($factor).")";
20 db_query($sql, "could not add work order costing");
24 function get_wo_costing($workorder_id)
27 FROM ".TB_PREF."wo_costing cost,
30 cost.trans_type=gl.type AND cost.trans_no=gl.trans_no
31 AND workorder_id=".db_escape($workorder_id);
33 return db_query($sql, "could not get work order costing");
36 function delete_wo_costing($trans_type, $trans_no)
38 $sql="DELETE FROM ".TB_PREF."wo_costing WHERE trans_type=".db_escape($trans_type)
39 ." AND trans_no=".db_escape($trans_no);
41 db_query($sql, "could not delete work order costing");
45 Updates average material cost for item.
47 function update_material_cost($stock_id, $qty, $unit_cost, $date)
51 $product = get_item($stock_id);
52 $avg_cost = $product['material_cost'];
54 $qoh = get_qoh_on_date($stock_id, null, $date);
56 // unit_cost*qty is already posted on inventory GL
61 $qty_done = max(-$qoh, $qty);
66 $qty_done = max($qoh+$qty, 0);
70 $qty_delayed = $qty-$qty_done;
74 $qty_delayed = min(-$qoh, $qty);
78 $qty_new = $qty - $qty_delayed;
80 if ($qty_delayed > 0 && ($unit_cost != $avg_cost))
82 // post $qty_delayed*($avg_cost-$unit_cost)
83 $diff = $qty_delayed*($unit_cost-$avg_cost);
84 $stock_gl_code = get_item($stock_id);
86 $dec = user_price_dec();
87 $old_cost = -round2($avg_cost, $dec);
88 $new_cost = -round2($unit_cost, $dec);
90 $cart = new items_cart(ST_COSTUPDATE);
91 $cart->tran_date = $cart->doc_date = $cart->event_date = $date;
93 if (!is_date_in_fiscalyear($cart->tran_date))
94 $cart->tran_date = end_fiscalyear();
96 $cart->reference = $Refs->get_next(ST_COSTUPDATE, null, $cart->tran_date, $date);
98 $cart->memo_ = sprintf(_("COGS changed from %s to %s for %d %s of '%s'"), $avg_cost, $unit_cost, $qty_delayed, $item['units'], $stock_id);
100 $cart->add_gl_item($item["cogs_account"], $item["dimension_id"], $item["dimension2_id"], -$diff);
101 $cart->add_gl_item($item["inventory_account"], 0, 0, $diff);
103 write_journal_entries($cart);
106 if ($qty > 0 && ($qoh != -$qty))
107 $avg_cost = ($avg_cost*($qoh+$qty_delayed)+$unit_cost*$qty_new)/($qoh+$qty);
109 $sql = "UPDATE ".TB_PREF."stock_master SET material_cost=".db_escape($avg_cost)."
110 WHERE stock_id=".db_escape($stock_id);
111 db_query($sql,"The cost details for the inventory item could not be updated");
114 function add_issue_cost($stock_id, $qty, $date_, $costs, $adj_only=false)
118 $sql = "SELECT material_cost FROM ".TB_PREF."stock_master WHERE stock_id = "
119 .db_escape($stock_id);
120 $result = db_query($sql);
121 $myrow = db_fetch($result);
122 $material_cost = $myrow['material_cost'];
123 $qoh = get_qoh_on_date($stock_id);
129 $material_cost = ($qoh * $material_cost + $costs) / $qoh;
130 else // Journal Entry if QOH is 0/negative
134 $id = get_next_trans_no(ST_JOURNAL);
135 $ref = $Refs->get_next(ST_JOURNAL, null, $date_);
136 add_journal(ST_JOURNAL, $id, $costs, $date_, get_company_currency(), $ref);
138 $stock_gl_code = get_stock_gl_code($stock_id);
139 $memo = "WO Issue settlement JV for zero/negative respository of ".$stock_id;
140 //Reverse the inventory effect if $qoh <=0
141 add_gl_trans_std_cost(ST_JOURNAL, $id, $date_,
142 $stock_gl_code["inventory_account"],
143 $stock_gl_code['dimension_id'], $stock_gl_code['dimension2_id'], $memo,
145 //GL Posting to inventory adjustment account
146 add_gl_trans_std_cost(ST_JOURNAL, $id, $date_,
147 $stock_gl_code["assembly_account"],
148 $stock_gl_code['dimension_id'], $stock_gl_code['dimension2_id'], $memo,
151 add_audit_trail(ST_JOURNAL, $id, $date_);
152 add_comments(ST_JOURNAL, $id, $date_, $memo);
153 $Refs->save(ST_JOURNAL, $id, $ref);
155 $material_cost = $costs / $qty;
160 if ($qoh + $qty != 0)
161 $material_cost = ($qoh * $material_cost + $qty * $costs) / ($qoh + $qty);
163 $sql = "UPDATE ".TB_PREF."stock_master SET material_cost=material_cost+"
164 .db_escape($material_cost)
165 ." WHERE stock_id=".db_escape($stock_id);
166 db_query($sql,"The cost details for the inventory item could not be updated");
170 Create journal entry for WO related costs.
172 function add_wo_costs_journal($wo_id, $amount, $cost_type, $cr_acc, $db_acc, $date, $dim1=0, $dim2=0, $memo = null, $ref= null)
174 //-------- this should be done by single call to write_journal_entries() using items_cart()
176 global $Refs, $wo_cost_types;
180 $journal_id = get_next_trans_no(ST_JOURNAL);
182 if (!$ref) $ref = $Refs->get_next(ST_JOURNAL, null, $date);
184 add_gl_trans_std_cost(ST_JOURNAL, $journal_id, $date, $cr_acc,
185 0, 0, $wo_cost_types[$cost_type], -$amount);
186 $is_bank_to = is_bank_account($cr_acc);
189 add_bank_trans(ST_JOURNAL, $journal_id, $is_bank_to, "",
190 $date, -$amount, PT_WORKORDER, $wo_id, get_company_currency(),
191 "Cannot insert a destination bank transaction");
193 add_journal(ST_JOURNAL, $journal_id, $amount, $date, get_company_currency(), $ref);
195 add_gl_trans_std_cost(ST_JOURNAL, $journal_id, $date, $db_acc,
196 $dim1, $dim2, $wo_cost_types[$cost_type], $amount);
198 $wo = get_work_order($wo_id);
199 $wip = $wo['assembly_account'];
203 add_gl_trans_std_cost(ST_JOURNAL, $journal_id, $date, $db_acc,
204 0, 0, $wo_cost_types[$cost_type], -$amount);
206 add_gl_trans_std_cost(ST_JOURNAL, $journal_id, $date, $wip,
207 0, 0, $wo_cost_types[$cost_type], $amount);
210 $Refs->save(ST_JOURNAL, $journal_id, $ref);
212 add_wo_costing($wo_id, $cost_type, ST_JOURNAL, $journal_id);
214 add_comments(ST_JOURNAL, $journal_id, $date, $memo);
215 add_audit_trail(ST_JOURNAL, $journal_id, $date);
217 commit_transaction();
221 Process component usage: generate and post stock move, update average component cost.
223 function work_order_production_gl($woid, $stock_id, $quantity, $date_, $rcv_no)
225 $result = get_wo_requirements($woid);
227 // credit all the components
229 while ($bom_item = db_fetch($result))
232 update_wo_requirement_issued($bom_item['id'], $bom_item["units_req"] * $quantity, $bom_item["ComponentCost"]);
234 // insert a -ve stock move for each item
235 add_stock_move(ST_MANURECEIVE, $bom_item["stock_id"], $rcv_no,
236 $bom_item["loc_code"], $date_, "", -$bom_item["units_req"] * $quantity, $bom_item["ComponentCost"], 0);
238 if (!is_service($bom_item["mb_flag"]))
239 $ivaccount = $bom_item["inventory_account"];
241 $ivaccount = $bom_item["cogs_account"];
243 $memo = $date_.": ".$bom_item["units_req"] ." * ".$bom_item["description"];
245 $total_cost += add_gl_trans_std_cost(ST_MANURECEIVE, $rcv_no, $date_, $ivaccount, 0, 0,
246 $memo, -$bom_item["ComponentCost"] * $bom_item["units_req"] * $quantity);
249 $wo = get_work_order($woid);
250 add_gl_trans_std_cost(ST_MANURECEIVE, $rcv_no, $date_, $wo['assembly_account'],
251 0, 0, $memo, -$total_cost);
254 function void_wo_costing($wo_id)
256 $res = get_wo_costing($wo_id);
258 while($row = db_fetch($res))
260 // void any related gl trans
261 void_gl_trans($row['trans_type'], $row['trans_no'], true);
264 $sql = "DELETE FROM ".TB_PREF."wo_costing WHERE workorder_id=".db_escape($wo_id);
265 db_query($sql, "could not delete work order costing");