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 Common entry procedure for all work order types
15 function add_work_order($wo_ref, $loc_code, $units_reqd, $stock_id,
16 $type, $date_, $required_by, $memo_, $costs, $cr_acc, $labour, $cr_lab_acc)
21 $args = func_get_args();
22 $args = (object)array_combine(array('wo_ref', 'loc_code', 'units_reqd', 'stock_id',
23 'type', 'date_', 'required_by', 'memo_', 'costs', 'cr_acc', 'labour', 'cr_lab_acc'), $args);
26 hook_db_prewrite($args, ST_WORKORDER);
28 if ($type != WO_ADVANCED)
29 $required_by = $date_;
31 $date = date2sql($date_);
32 $required = date2sql($required_by);
33 $sql = "INSERT INTO ".TB_PREF."workorders (wo_ref, loc_code, units_reqd, stock_id,
34 type, date_, required_by)
35 VALUES (".db_escape($wo_ref).", ".db_escape($loc_code).", "
36 .db_escape($units_reqd).", ".db_escape($stock_id).",
37 ".db_escape($type).", '$date', ".db_escape($required).")";
38 db_query($sql, "could not add work order");
40 $woid = db_insert_id();
42 add_comments(ST_WORKORDER, $woid, $required_by, $memo_);
44 $Refs->save(ST_WORKORDER, $woid, $wo_ref);
45 add_audit_trail(ST_WORKORDER, $woid, $date_);
48 hook_db_postwrite($args, ST_WORKORDER);
50 if ($type != WO_ADVANCED)
52 $stockitem = get_item($stock_id);
53 release_work_order($woid, $date_, '');
55 add_wo_costs_journal($woid, $costs, WO_OVERHEAD, $cr_acc, $stockitem["assembly_account"],
56 $date_, $stockitem["dimension_id"], $stockitem["dimension2_id"]);
58 add_wo_costs_journal($woid, $labour, WO_LABOUR, $cr_lab_acc, $stockitem["assembly_account"],
59 $date_, $stockitem["dimension_id"], $stockitem["dimension2_id"]);
61 if ($type == WO_UNASSEMBLY)
62 $units_reqd = -$units_reqd;
64 $ref = $Refs->get_next(ST_MANURECEIVE, null, $date_);
65 work_order_produce($woid, $ref, $units_reqd, $date_, '', true);
73 //--------------------------------------------------------------------------------------
75 function update_work_order($woid, $loc_code, $units_reqd, $stock_id,
76 $date_, $required_by, $memo_)
79 $args = func_get_args();
80 $args = (object)array_combine(array('woid', 'loc_code', 'units_reqd', 'stock_id',
81 'date_', 'required_by', 'memo_'), $args);
82 hook_db_prewrite($args, ST_WORKORDER);
84 $date = date2sql($date_);
85 $required = date2sql($required_by);
87 $sql = "UPDATE ".TB_PREF."workorders SET loc_code=".db_escape($loc_code).",
88 units_reqd=".db_escape($units_reqd).", stock_id=".db_escape($stock_id).",
89 required_by=".db_escape($required).",
91 WHERE id = ".db_escape($woid);
93 db_query($sql, "could not update work order");
95 update_comments(ST_WORKORDER, $woid, null, $memo_);
96 add_audit_trail(ST_WORKORDER, $woid, $date_, _("Updated."));
98 hook_db_postwrite($args, ST_WORKORDER);
102 function delete_work_order($woid, $stock_id, $qty, $date)
105 hook_db_prevoid(ST_WORKORDER, $woid);
107 // delete the work order requirements
108 delete_wo_requirements($woid);
110 // delete the actual work order
111 $sql = "DELETE FROM ".TB_PREF."workorders WHERE id=".db_escape($woid);
112 db_query($sql,"The work order could not be deleted");
114 delete_comments(ST_WORKORDER, $woid);
115 add_audit_trail(ST_WORKORDER, $woid, $date, _("Canceled."));
117 commit_transaction();
120 //--------------------------------------------------------------------------------------
122 function get_work_order($woid, $allow_null=false)
124 $sql = "SELECT wo.*,st.description As StockItemName,l.location_name,
125 l.delivery_address,l.email, l.contact, st.inventory_account, st.assembly_account
126 FROM ".TB_PREF."workorders wo, "
127 .TB_PREF."stock_master st, "
128 .TB_PREF."locations l
129 WHERE st.stock_id=wo.stock_id
130 AND l.loc_code=wo.loc_code
131 AND wo.id=".db_escape($woid)."
134 $result = db_query($sql, "The work order issues could not be retrieved");
136 if (!$allow_null && db_num_rows($result) == 0)
138 display_db_error("Could not find work order $woid", $sql);
142 return db_fetch($result);
145 //--------------------------------------------------------------------------------------
147 function work_order_has_productions($woid)
149 $sql = "SELECT COUNT(*) FROM ".TB_PREF."wo_manufacture WHERE workorder_id=".db_escape($woid);
150 $result = db_query($sql, "query work order for productions");
152 $myrow = db_fetch_row($result);
153 return ($myrow[0] > 0);
157 //--------------------------------------------------------------------------------------
159 function work_order_has_issues($woid)
161 $sql = "SELECT COUNT(*) FROM ".TB_PREF."wo_issues WHERE workorder_id=".db_escape($woid);
162 $result = db_query($sql, "query work order for issues");
164 $myrow = db_fetch_row($result);
165 return ($myrow[0] > 0);
168 //--------------------------------------------------------------------------------------
170 function work_order_has_payments($woid)
172 $result = get_gl_wo_cost_trans($woid);
174 return (db_num_rows($result) != 0);
177 //--------------------------------------------------------------------------------------
179 function release_work_order($woid, $releaseDate, $memo_)
183 $myrow = get_work_order($woid);
184 $stock_id = $myrow["stock_id"];
186 $date = date2sql($releaseDate);
188 $sql = "UPDATE ".TB_PREF."workorders SET released_date='$date',
189 released=1 WHERE id = ".db_escape($woid);
190 db_query($sql, "could not release work order");
192 // create wo_requirements records according to current BOM
193 create_wo_requirements($woid, $stock_id);
195 add_comments(ST_WORKORDER, $woid, $releaseDate, $memo_);
196 add_audit_trail(ST_WORKORDER, $woid, sql2date($myrow['date_']), _("Released."));
198 commit_transaction();
201 //--------------------------------------------------------------------------------------
203 function close_work_order($woid)
205 $sql = "UPDATE ".TB_PREF."workorders SET closed=1 WHERE id = ".db_escape($woid);
206 db_query($sql, "could not close work order");
209 //--------------------------------------------------------------------------------------
211 function work_order_is_closed($woid)
213 $sql = "SELECT closed FROM ".TB_PREF."workorders WHERE id = ".db_escape($woid);
214 $result = db_query($sql, "could not query work order");
215 $row = db_fetch_row($result);
216 return ($row[0] > 0);
219 //--------------------------------------------------------------------------------------
221 Update finished items quantity in work order, and close order either if all the order is produced,
222 or on user demand. Returns calculated unit cost on close, or null otherwise.
224 function work_order_update_finished_quantity($woid, $quantity, $date, $force_close=0)
227 $sql = "UPDATE ".TB_PREF."workorders SET units_issued = units_issued + ".db_escape($quantity)."
228 WHERE id = ".db_escape($woid). " AND !closed";
230 db_query($sql, "The work order issued quantity couldn't be updated");
232 $sql = "UPDATE ".TB_PREF."workorders SET closed = ((units_issued >= units_reqd) OR ".db_escape($force_close).")
233 WHERE id = ".db_escape($woid);
235 db_query($sql, "The work order couldn't be closed");
237 return db_num_affected_rows(); // returns 1 if WO has been closed
240 //--------------------------------------------------------------------------------------
242 function void_work_order($woid)
245 hook_db_prevoid(ST_WORKORDER, $woid);
247 $work_order = get_work_order($woid);
248 if (!($work_order["type"] == WO_ADVANCED))
250 // restore average product costs
251 $date = sql2date($work_order['date_']);
252 $qty = $work_order['units_reqd'];
254 // FIXME: update_material_cost
257 $sql = "UPDATE ".TB_PREF."workorders SET closed=1,units_reqd=0,units_issued=0 WHERE id = "
259 db_query($sql, "The work order couldn't be voided");
261 // void all related stock moves
262 void_stock_move(ST_WORKORDER, $woid);
264 // void any related costing records
265 void_wo_costing($woid);
267 // clear the requirements units received
268 void_wo_requirements($woid);
272 // void everything inside the work order : issues, productions, payments
273 $date = sql2date($work_order['date_']);
275 // FIXME: update_material_cost
277 $result = get_work_order_productions($woid); // check the produced quantity
279 while ($row = db_fetch($result))
281 $qty += $row['quantity'];
282 // clear the production record
283 $sql = "UPDATE ".TB_PREF."wo_manufacture SET quantity=0 WHERE id=".$row['id'];
284 db_query($sql, "Cannot void a wo production");
286 void_stock_move(ST_MANURECEIVE, $row['id']); // and void the stock moves;
288 $result = get_additional_issues($woid); // check the issued quantities
291 while ($row = db_fetch($result))
293 $unit_cost = get_unit_cost($row['stock_id']);
294 $icost = $unit_cost * $row['qty_issued'];
297 $issue_no = $row['issue_no'];
298 // void the actual issue items and their quantities
299 $sql = "UPDATE ".TB_PREF."wo_issue_items SET qty_issued = 0 WHERE issue_id="
300 .db_escape($row['id']);
301 db_query($sql,"A work order issue item could not be voided");
304 void_stock_move(ST_MANUISSUE, $issue_no); // and void the stock moves
307 add_issue_cost($work_order['stock_id'], -$qty, $date, $cost);
309 $sql = "UPDATE ".TB_PREF."workorders SET closed=1,units_reqd=0,units_issued=0 WHERE id = "
311 db_query($sql, "The work order couldn't be voided");
313 // void all related stock moves
314 void_stock_move(ST_WORKORDER, $woid);
316 // void any related bank/gl trans
317 void_wo_costing($woid);
319 // clear the requirements units received
320 void_wo_requirements($woid);
323 commit_transaction();
326 function get_sql_for_work_orders($outstanding_only, $stock_id, $location = ALL_TEXT, $order_no='', $order_ref = '', $overdue = false)
332 location.location_name,
334 workorder.units_reqd,
335 workorder.units_issued,
337 workorder.required_by,
338 workorder.released_date,
343 FROM ".TB_PREF."workorders as workorder,"
344 .TB_PREF."stock_master as item,"
345 .TB_PREF."item_units as unit,"
346 .TB_PREF."locations as location
347 WHERE workorder.stock_id=item.stock_id
348 AND workorder.loc_code=location.loc_code
349 AND item.units=unit.abbr";
351 if (check_value('OpenOnly') || $outstanding_only != 0)
353 $sql .= " AND workorder.closed=0";
356 if ($location != ALL_TEXT)
358 $sql .= " AND workorder.loc_code=".db_escape($location);
363 $sql .= " AND workorder.id LIKE ".db_escape('%'.$order_no.'%');
366 if ($order_ref != '')
368 $sql .= " AND workorder.wo_ref LIKE ".db_escape('%'.$order_ref.'%');
371 if ($stock_id != ALL_TEXT)
373 $sql .= " AND workorder.stock_id=".db_escape($stock_id);
378 $Today = date2sql(Today());
380 $sql .= " AND workorder.required_by < '$Today' ";
382 $sql .= " ORDER BY workorder.id DESC";
386 function get_sql_for_where_used($stock_id)
390 workcentre.name As WorkCentreName,
391 location.location_name,
394 FROM ".TB_PREF."bom as bom, "
395 .TB_PREF."stock_master as parent, "
396 .TB_PREF."workcentres as workcentre, "
397 .TB_PREF."locations as location
398 WHERE bom.parent = parent.stock_id
399 AND bom.workcentre_added = workcentre.id
400 AND bom.loc_code = location.loc_code
401 AND bom.component=".db_escape($stock_id);
404 //--------------------------------------------------------------------------------------
405 function get_gl_wo_cost($woid, $cost_type)
408 $result = get_gl_wo_cost_trans($woid, $cost_type);
409 while ($row = db_fetch($result))
410 $cost += -$row['amount'];