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 ***********************************************************************/
12 //--------------------------------------------------------------------------------------
14 //Chaitanya : Added $advanced Parameter for Advanced Manufacturing
15 function add_material_cost($stock_id, $qty, $date_, $advanced=false)
18 $result = get_bom($stock_id);
19 while ($bom_item = db_fetch($result))
21 $standard_cost = get_standard_cost($bom_item['component']);
22 $m_cost += ($bom_item['quantity'] * $standard_cost);
26 //$dec = user_price_dec();
27 //price_decimal_format($m_cost, $dec);
28 $sql = "SELECT material_cost, labour_cost, overhead_cost FROM ".TB_PREF."stock_master WHERE stock_id = "
29 .db_escape($stock_id);
30 $result = db_query($sql);
31 $myrow = db_fetch($result);
32 $material_cost = $myrow['material_cost'];
34 //Chaitanya : Upating material cost without considering labour, overhead costs results in invalid costing
37 //reduce overhead_cost and labour_cost from price as those will remain as is
38 $m_cost = $m_cost - $myrow['labour_cost'] - $myrow['overhead_cost'];
41 //$qoh = get_qoh_on_date($stock_id, null, $date_);
42 $qoh = get_qoh_on_date($stock_id);
51 $material_cost = ($qoh * $material_cost + $qty * $m_cost) / ($qoh + $qty);
52 //$material_cost = round2($material_cost, $dec);
54 if ($advanced && $cost_adjust) // new 2010-02-10
55 adjust_deliveries($stock_id, $bom_cost, $date_);
57 $sql = "UPDATE ".TB_PREF."stock_master SET material_cost=".db_escape($material_cost)."
58 WHERE stock_id=".db_escape($stock_id);
59 db_query($sql,"The cost details for the inventory item could not be updated");
62 //Chaitanya : Added Adjustement Only Parameter
63 function add_overhead_cost($stock_id, $qty, $date_, $costs, $adj_only=false)
65 //$dec = user_price_dec();
66 //price_decimal_format($costs, $dec);
69 $sql = "SELECT overhead_cost FROM ".TB_PREF."stock_master WHERE stock_id = "
70 .db_escape($stock_id);
71 $result = db_query($sql);
72 $myrow = db_fetch($result);
73 $overhead_cost = $myrow['overhead_cost'];
74 //$qoh = get_qoh_on_date($stock_id, null, $date_);
75 $qoh = get_qoh_on_date($stock_id);
81 $costs = $qty * $costs;
83 $overhead_cost = ($qoh * $overhead_cost + $costs) / $qoh;
84 else //Chaitanya : Pass JV if qoh is 0/negative
88 $id = get_next_trans_no(ST_JOURNAL);
89 $ref = $Refs->get_next(ST_JOURNAL);
91 $stock_gl_code = get_stock_gl_code($stock_id);
92 $memo = "WO Overhead cost settlement JV for zero/negative respository of ".$stock_id;
93 //Reverse the inventory effect if $qoh <=0
94 add_gl_trans_std_cost(ST_JOURNAL, $id, $date_,
95 $stock_gl_code["inventory_account"],
96 $stock_gl_code['dimension_id'], $stock_gl_code['dimension2_id'], $memo,
98 //GL Posting to inventory adjustment account
99 add_gl_trans_std_cost(ST_JOURNAL, $id, $date_,
100 $stock_gl_code["adjustment_account"],
101 $stock_gl_code['dimension_id'], $stock_gl_code['dimension2_id'], $memo,
104 add_audit_trail(ST_JOURNAL, $id, $date_);
105 add_comments(ST_JOURNAL, $id, $date_, $memo);
106 $Refs->save(ST_JOURNAL, $id, $ref);
111 if ($qoh + $qty != 0)
112 $overhead_cost = ($qoh * $overhead_cost + $qty * $costs) / ($qoh + $qty);
114 //$overhead_cost = round2($overhead_cost, $dec);
115 $sql = "UPDATE ".TB_PREF."stock_master SET overhead_cost=".db_escape($overhead_cost)."
116 WHERE stock_id=".db_escape($stock_id);
117 db_query($sql,"The cost details for the inventory item could not be updated");
120 //Chaitanya : Added Adjustement Only Parameter
121 function add_labour_cost($stock_id, $qty, $date_, $costs, $adj_only=false)
123 //$dec = user_price_dec();
124 //price_decimal_format($costs, $dec);
127 $sql = "SELECT labour_cost FROM ".TB_PREF."stock_master WHERE stock_id = "
128 .db_escape($stock_id);
129 $result = db_query($sql);
130 $myrow = db_fetch($result);
131 $labour_cost = $myrow['labour_cost'];
132 //$qoh = get_qoh_on_date($stock_id, null, $date_);
133 $qoh = get_qoh_on_date($stock_id);
139 $costs = $qty * $costs;
141 $labour_cost = ($qoh * $labour_cost + $costs) / $qoh;
142 else //Chaitanya : Pass JV if qoh is 0/negative
146 $id = get_next_trans_no(ST_JOURNAL);
147 $ref = $Refs->get_next(ST_JOURNAL);
149 $stock_gl_code = get_stock_gl_code($stock_id);
150 $memo = "WO labour cost settlement JV for zero/negative respository of ".$stock_id;
151 //Reverse the inventory effect if $qoh <=0
152 add_gl_trans_std_cost(ST_JOURNAL, $id, $date_,
153 $stock_gl_code["inventory_account"],
154 $stock_gl_code['dimension_id'], $stock_gl_code['dimension2_id'], $memo,
156 //GL Posting to inventory adjustment account
157 add_gl_trans_std_cost(ST_JOURNAL, $id, $date_,
158 $stock_gl_code["adjustment_account"],
159 $stock_gl_code['dimension_id'], $stock_gl_code['dimension2_id'], $memo,
162 add_audit_trail(ST_JOURNAL, $id, $date_);
163 add_comments(ST_JOURNAL, $id, $date_, $memo);
164 $Refs->save(ST_JOURNAL, $id, $ref);
169 if ($qoh + $qty != 0)
170 $labour_cost = ($qoh * $labour_cost + $qty * $costs) / ($qoh + $qty);
172 //$labour_cost = round2($labour_cost, $dec);
173 $sql = "UPDATE ".TB_PREF."stock_master SET labour_cost=".db_escape($labour_cost)."
174 WHERE stock_id=".db_escape($stock_id);
175 db_query($sql,"The cost details for the inventory item could not be updated");
178 //Chaitanya : Added Adjustement Only Parameter
179 function add_issue_cost($stock_id, $qty, $date_, $costs, $adj_only=false)
183 $sql = "SELECT material_cost FROM ".TB_PREF."stock_master WHERE stock_id = "
184 .db_escape($stock_id);
185 $result = db_query($sql);
186 $myrow = db_fetch($result);
187 $material_cost = $myrow['material_cost'];
188 //$dec = user_price_dec();
189 //price_decimal_format($material_cost, $dec);
190 //$qoh = get_qoh_on_date($stock_id, null, $date_);
191 $qoh = get_qoh_on_date($stock_id);
197 $costs = $qty * $costs;
199 $material_cost = $costs / $qoh;
200 else //Chaitanya : Pass JV if qoh is 0/negative
204 $id = get_next_trans_no(ST_JOURNAL);
205 $ref = $Refs->get_next(ST_JOURNAL);
207 $stock_gl_code = get_stock_gl_code($stock_id);
208 $memo = "WO Issue settlement JV for zero/negative respository of ".$stock_id;
209 //Reverse the inventory effect if $qoh <=0
210 add_gl_trans_std_cost(ST_JOURNAL, $id, $date_,
211 $stock_gl_code["inventory_account"],
212 $stock_gl_code['dimension_id'], $stock_gl_code['dimension2_id'], $memo,
214 //GL Posting to inventory adjustment account
215 add_gl_trans_std_cost(ST_JOURNAL, $id, $date_,
216 $stock_gl_code["adjustment_account"],
217 $stock_gl_code['dimension_id'], $stock_gl_code['dimension2_id'], $memo,
220 add_audit_trail(ST_JOURNAL, $id, $date_);
221 add_comments(ST_JOURNAL, $id, $date_, $memo);
222 $Refs->save(ST_JOURNAL, $id, $ref);
227 if ($qoh + $qty != 0)
228 $material_cost = ($qty * $costs) / ($qoh + $qty);
230 //$material_cost = round2($material_cost, $dec);
231 $sql = "UPDATE ".TB_PREF."stock_master SET material_cost=material_cost+"
232 .db_escape($material_cost)
233 ." WHERE stock_id=".db_escape($stock_id);
234 db_query($sql,"The cost details for the inventory item could not be updated");
237 function add_work_order($wo_ref, $loc_code, $units_reqd, $stock_id,
238 $type, $date_, $required_by, $memo_, $costs, $cr_acc, $labour, $cr_lab_acc)
242 if (!($type == WO_ADVANCED))
243 return add_work_order_quick($wo_ref, $loc_code, $units_reqd, $stock_id, $type, $date_, $memo_, $costs, $cr_acc, $labour, $cr_lab_acc);
246 $args = func_get_args();
247 $args = (object)array_combine(array('wo_ref', 'loc_code', 'units_reqd', 'stock_id',
248 'type', 'date_', 'required_by', 'memo_', 'costs', 'cr_acc', 'labour', 'cr_lab_acc'), $args);
250 hook_db_prewrite($args, ST_WORKORDER);
252 //Chaitanya : Material cost should be added at time of production as per BOM at the time.
253 //add_material_cost($stock_id, $units_reqd, $date_);
255 $date = date2sql($date_);
256 $required = date2sql($required_by);
258 $sql = "INSERT INTO ".TB_PREF."workorders (wo_ref, loc_code, units_reqd, stock_id,
259 type, date_, required_by)
260 VALUES (".db_escape($wo_ref).", ".db_escape($loc_code).", "
261 .db_escape($units_reqd).", ".db_escape($stock_id).",
262 ".db_escape($type).", '$date', ".db_escape($required).")";
263 db_query($sql, "could not add work order");
265 $woid = db_insert_id();
267 add_comments(ST_WORKORDER, $woid, $required_by, $memo_);
269 $Refs->save(ST_WORKORDER, $woid, $wo_ref);
270 add_audit_trail(ST_WORKORDER, $woid, $date_);
273 hook_db_postwrite($args, ST_WORKORDER);
274 commit_transaction();
279 //--------------------------------------------------------------------------------------
281 function update_work_order($woid, $loc_code, $units_reqd, $stock_id,
282 $date_, $required_by, $memo_)
285 $args = func_get_args();
286 $args = (object)array_combine(array('woid', 'loc_code', 'units_reqd', 'stock_id',
287 'date_', 'required_by', 'memo_'), $args);
288 hook_db_prewrite($args, ST_WORKORDER);
290 //Chaitanya: Material Cost to be calculated at production
291 //add_material_cost($_POST['old_stk_id'], -$_POST['old_qty'], $date_);
292 //add_material_cost($stock_id, $units_reqd, $date_);
294 $date = date2sql($date_);
295 $required = date2sql($required_by);
297 $sql = "UPDATE ".TB_PREF."workorders SET loc_code=".db_escape($loc_code).",
298 units_reqd=".db_escape($units_reqd).", stock_id=".db_escape($stock_id).",
299 required_by=".db_escape($required).",
301 WHERE id = ".db_escape($woid);
303 db_query($sql, "could not update work order");
305 update_comments(ST_WORKORDER, $woid, null, $memo_);
306 add_audit_trail(ST_WORKORDER, $woid, $date_, _("Updated."));
308 hook_db_postwrite($args, ST_WORKORDER);
309 commit_transaction();
312 function delete_work_order($woid)
315 hook_db_prevoid(ST_WORKORDER, $woid);
317 //Chaitanya : Cost calculation are affected only at time of production
318 //add_material_cost($_POST['stock_id'], -$_POST['quantity'], $_POST['date_']);
320 // delete the work order requirements
321 delete_wo_requirements($woid);
323 // delete the actual work order
324 $sql = "DELETE FROM ".TB_PREF."workorders WHERE id=".db_escape($woid);
325 db_query($sql,"The work order could not be deleted");
327 delete_comments(ST_WORKORDER, $woid);
328 add_audit_trail(ST_WORKORDER, $woid, $_POST['date_'], _("Canceled."));
330 commit_transaction();
333 //--------------------------------------------------------------------------------------
335 function get_work_order($woid, $allow_null=false)
337 $sql = "SELECT wo.*,st.description As StockItemName,l.location_name,
338 l.delivery_address,l.email, l.contact
339 FROM ".TB_PREF."workorders wo, ".TB_PREF."stock_master st, ".TB_PREF."locations l
340 WHERE st.stock_id=wo.stock_id
341 AND l.loc_code=wo.loc_code
342 AND wo.id=".db_escape($woid)."
345 $result = db_query($sql, "The work order issues could not be retrieved");
347 if (!$allow_null && db_num_rows($result) == 0)
348 display_db_error("Could not find work order $woid", $sql);
350 return db_fetch($result);
353 //--------------------------------------------------------------------------------------
355 function work_order_has_productions($woid)
357 $sql = "SELECT COUNT(*) FROM ".TB_PREF."wo_manufacture WHERE workorder_id=".db_escape($woid);
358 $result = db_query($sql, "query work order for productions");
360 $myrow = db_fetch_row($result);
361 return ($myrow[0] > 0);
365 //--------------------------------------------------------------------------------------
367 function work_order_has_issues($woid)
369 $sql = "SELECT COUNT(*) FROM ".TB_PREF."wo_issues WHERE workorder_id=".db_escape($woid);
370 $result = db_query($sql, "query work order for issues");
372 $myrow = db_fetch_row($result);
373 return ($myrow[0] > 0);
376 //--------------------------------------------------------------------------------------
378 function work_order_has_payments($woid)
380 $result = get_gl_wo_cost_trans($woid);
382 return (db_num_rows($result) != 0);
385 //--------------------------------------------------------------------------------------
387 function release_work_order($woid, $releaseDate, $memo_)
391 $myrow = get_work_order($woid);
392 $stock_id = $myrow["stock_id"];
394 $date = date2sql($releaseDate);
396 $sql = "UPDATE ".TB_PREF."workorders SET released_date='$date',
397 released=1 WHERE id = ".db_escape($woid);
398 db_query($sql, "could not release work order");
400 // create Work Order Requirements based on the bom
401 create_wo_requirements($woid, $stock_id);
403 add_comments(ST_WORKORDER, $woid, $releaseDate, $memo_);
404 add_audit_trail(ST_WORKORDER, $woid, $releaseDate,_("Released."));
406 commit_transaction();
409 //--------------------------------------------------------------------------------------
411 function close_work_order($woid)
413 $sql = "UPDATE ".TB_PREF."workorders SET closed=1 WHERE id = ".db_escape($woid);
414 db_query($sql, "could not close work order");
417 //--------------------------------------------------------------------------------------
419 function work_order_is_closed($woid)
421 $sql = "SELECT closed FROM ".TB_PREF."workorders WHERE id = ".db_escape($woid);
422 $result = db_query($sql, "could not query work order");
423 $row = db_fetch_row($result);
424 return ($row[0] > 0);
427 //--------------------------------------------------------------------------------------
429 function work_order_update_finished_quantity($woid, $quantity, $force_close=0)
431 $sql = "UPDATE ".TB_PREF."workorders SET units_issued = units_issued + ".db_escape($quantity).",
432 closed = ((units_issued >= units_reqd) OR ".db_escape($force_close).")
433 WHERE id = ".db_escape($woid);
435 db_query($sql, "The work order issued quantity couldn't be updated");
438 //--------------------------------------------------------------------------------------
440 function void_work_order($woid)
443 hook_db_prevoid(ST_WORKORDER, $woid);
445 $work_order = get_work_order($woid);
446 if (!($work_order["type"] == WO_ADVANCED))
448 //Chaitanya : Removed WO costing from here. Handled in void_stock_move
449 //Reason - if BOM is changed since WO was executed then add_material_cost will result in incorrect costing as it is based on current BOM for material cost.
450 /*$date = sql2date($work_order['date_']);
451 $qty = $work_order['units_reqd'];
452 add_material_cost($work_order['stock_id'], -$qty, $date); // remove avg. cost for qty
453 $cost = get_gl_wo_cost($woid, WO_LABOUR); // get the labour cost and reduce avg cost
455 add_labour_cost($work_order['stock_id'], -$qty, $date, $cost);
456 $cost = get_gl_wo_cost($woid, WO_OVERHEAD); // get the overhead cost and reduce avg cost
458 add_overhead_cost($work_order['stock_id'], -$qty, $date, $cost);*/
460 $sql = "UPDATE ".TB_PREF."workorders SET closed=1,units_reqd=0,units_issued=0 WHERE id = "
462 db_query($sql, "The work order couldn't be voided");
464 // void all related stock moves
465 void_stock_move(ST_WORKORDER, $woid);
467 // void any related gl trans
468 void_gl_trans(ST_WORKORDER, $woid, true);
470 // clear the requirements units received
471 void_wo_requirements($woid);
475 // void everything inside the work order : issues, productions, payments
476 $date = sql2date($work_order['date_']);
478 //Chaitanya : Removed WO costing from here. Handled in void_stock_move
479 //Reason - if BOM is changed since WO was executed then add_material_cost will result in incorrect costing as it is based on current BOM for material cost.
480 //add_material_cost($work_order['stock_id'], -$work_order['units_reqd'], $date); // remove avg. cost for qty
482 $result = get_work_order_productions($woid); // check the produced quantity
484 while ($row = db_fetch($result))
486 //Chaitanya : Use native function for voiding
487 void_work_order_produce($row['id']);
489 //Post voided entry if not prevoided explicitly
490 $void_entry = get_voided_entry(ST_MANURECEIVE, $row['id']);
493 $memo_ = _("Voiding Work Order Trans # ").$woid;
494 add_audit_trail(ST_MANURECEIVE, $row['id'], today(), _("Voided.")."\n".$memo_);
495 add_voided_entry(ST_MANURECEIVE, $row['id'], today(), $memo_);
497 /*$qty += $row['quantity'];
498 // clear the production record
499 $sql = "UPDATE ".TB_PREF."wo_manufacture SET quantity=0 WHERE id=".$row['id'];
500 db_query($sql, "Cannot void a wo production");
502 void_stock_move(ST_MANURECEIVE, $row['id']); // and void the stock moves; */
504 //Chaitanya : Get all work order issues
505 //$result = get_additional_issues($woid); // check the issued quantities
506 $result = get_work_order_issues($woid);
509 while ($row = db_fetch($result))
511 //Chaitanya : Use native function for voiding
512 void_work_order_issue($row['issue_no']);
514 //Post voided entry if not prevoided explicitly
515 $void_entry = get_voided_entry(ST_MANUISSUE, $row['issue_no']);
518 $memo_ = _("Voiding Work Order Trans # ").$woid;
519 add_audit_trail(ST_MANUISSUE, $row['issue_no'], today(), _("Voided.")."\n".$memo_);
520 add_voided_entry(ST_MANUISSUE, $row['issue_no'], today(), $memo_);
522 /*$std_cost = get_standard_cost($row['stock_id']);
523 $icost = $std_cost * $row['qty_issued'];
526 $issue_no = $row['issue_no'];
527 // void the actual issue items and their quantities
528 $sql = "UPDATE ".TB_PREF."wo_issue_items SET qty_issued = 0 WHERE issue_id="
529 .db_escape($row['id']);
530 db_query($sql,"A work order issue item could not be voided");*/
533 //Chaitaya : Voiding each issue handles the
534 //if ($issue_no != 0)
535 //void_stock_move(ST_MANUISSUE, $issue_no); // and void the stock moves
537 //add_issue_cost($work_order['stock_id'], -$qty, $date, $cost);
539 //Chaitanya : Reverse the cost effects on $work_order['stock_id'] as adjustement
540 $cost = get_gl_wo_cost($woid, WO_LABOUR); // get the labour cost and reduce avg cost
542 //add_labour_cost($work_order['stock_id'], -$qty, $date, $cost);
543 add_labour_cost($work_order['stock_id'], 1, $date, -$cost, true);
544 $cost = get_gl_wo_cost($woid, WO_OVERHEAD); // get the overhead cost and reduce avg cost
546 //add_overhead_cost($work_order['stock_id'], -$qty, $date, $cost);
547 add_overhead_cost($work_order['stock_id'], 1, $date, -$cost, true);
549 $sql = "UPDATE ".TB_PREF."workorders SET closed=1,units_reqd=0,units_issued=0 WHERE id = "
551 db_query($sql, "The work order couldn't be voided");
553 // void all related stock moves
554 void_stock_move(ST_WORKORDER, $woid);
556 // void any related gl trans
557 void_gl_trans(ST_WORKORDER, $woid, true);
559 // clear the requirements units received
560 void_wo_requirements($woid);
562 commit_transaction();
565 function get_sql_for_work_orders($outstanding_only, $all_items)
571 location.location_name,
573 workorder.units_reqd,
574 workorder.units_issued,
576 workorder.required_by,
577 workorder.released_date,
582 FROM ".TB_PREF."workorders as workorder,"
583 .TB_PREF."stock_master as item,"
584 .TB_PREF."item_units as unit,"
585 .TB_PREF."locations as location
586 WHERE workorder.stock_id=item.stock_id
587 AND workorder.loc_code=location.loc_code
588 AND item.units=unit.abbr";
590 if (check_value('OpenOnly') || $outstanding_only != 0)
592 $sql .= " AND workorder.closed=0";
595 if (isset($_POST['StockLocation']) && $_POST['StockLocation'] != $all_items)
597 $sql .= " AND workorder.loc_code=".db_escape($_POST['StockLocation']);
600 if (isset($_POST['OrderNumber']) && $_POST['OrderNumber'] != "")
602 $sql .= " AND workorder.wo_ref LIKE ".db_escape('%'.$_POST['OrderNumber'].'%');
605 if (isset($_POST['SelectedStockItem']) && $_POST['SelectedStockItem'] != $all_items)
607 $sql .= " AND workorder.stock_id=".db_escape($_POST['SelectedStockItem']);
610 if (check_value('OverdueOnly'))
612 $Today = date2sql(Today());
614 $sql .= " AND workorder.required_by < '$Today' ";
619 function get_sql_for_where_used()
623 workcentre.name As WorkCentreName,
624 location.location_name,
627 FROM ".TB_PREF."bom as bom, "
628 .TB_PREF."stock_master as parent, "
629 .TB_PREF."workcentres as workcentre, "
630 .TB_PREF."locations as location
631 WHERE bom.parent = parent.stock_id
632 AND bom.workcentre_added = workcentre.id
633 AND bom.loc_code = location.loc_code
634 AND bom.component=".db_escape($_POST['stock_id']);
637 //--------------------------------------------------------------------------------------
638 function get_gl_wo_cost($woid, $cost_type)
641 $result = get_gl_wo_cost_trans($woid, $cost_type);
642 while ($row = db_fetch($result))
643 $cost += -$row['amount'];