Merging version 2.1 RC to main trunk.
[fa-stable.git] / manufacturing / work_order_entry.php
1 <?php
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 $page_security = 10;
13 $path_to_root="..";
14
15 include_once($path_to_root . "/includes/session.inc");
16
17 include_once($path_to_root . "/includes/date_functions.inc");
18 include_once($path_to_root . "/includes/manufacturing.inc");
19 include_once($path_to_root . "/includes/data_checks.inc");
20
21 include_once($path_to_root . "/manufacturing/includes/manufacturing_db.inc");
22 include_once($path_to_root . "/manufacturing/includes/manufacturing_ui.inc");
23
24 $js = "";
25 if ($use_date_picker)
26         $js .= get_js_date_picker();
27 page(_("Work Order Entry"), false, false, "", $js);
28
29
30 check_db_has_manufacturable_items(_("There are no manufacturable items defined in the system."));
31
32 check_db_has_locations(("There are no inventory locations defined in the system."));
33
34 //---------------------------------------------------------------------------------------
35
36 if (isset($_GET['trans_no']))
37 {
38         $selected_id = $_GET['trans_no'];
39 }
40 elseif(isset($_POST['selected_id']))
41 {
42         $selected_id = $_POST['selected_id'];
43 }
44
45 //---------------------------------------------------------------------------------------
46
47 if (isset($_GET['AddedID']))
48 {
49         $id = $_GET['AddedID'];
50
51         display_notification_centered(_("The work order been added."));
52
53         safe_exit();
54 }
55
56 //---------------------------------------------------------------------------------------
57
58 if (isset($_GET['UpdatedID']))
59 {
60         $id = $_GET['UpdatedID'];
61
62         display_notification_centered(_("The work order been updated."));
63         safe_exit();
64 }
65
66 //---------------------------------------------------------------------------------------
67
68 if (isset($_GET['DeletedID']))
69 {
70         $id = $_GET['DeletedID'];
71
72         display_notification_centered(_("Work order has been deleted."));
73         safe_exit();
74 }
75
76 //---------------------------------------------------------------------------------------
77
78 if (isset($_GET['ClosedID']))
79 {
80         $id = $_GET['ClosedID'];
81
82         display_notification_centered(_("This work order has been closed. There can be no more issues against it.") . " #$id");
83         safe_exit();
84 }
85
86 //---------------------------------------------------------------------------------------
87
88 function safe_exit()
89 {
90         global $path_to_root;
91
92         hyperlink_no_params("", _("Enter a new work order"));
93         hyperlink_no_params("search_work_orders.php", _("Select an existing work order"));
94         echo "<br>";
95         end_form();
96         end_page();
97         exit;
98 }
99
100 //-------------------------------------------------------------------------------------
101 if (!isset($_POST['date_']))
102 {
103         $_POST['date_'] = Today();
104         if (!is_date_in_fiscalyear($_POST['date_']))
105                 $_POST['date_'] = end_fiscalyear();
106 }
107
108 function can_process()
109 {
110         global $selected_id;
111
112         if (!isset($selected_id))
113         {
114         if (!references::is_valid($_POST['wo_ref']))
115         {
116                 display_error(_("You must enter a reference."));
117                 set_focus('wo_ref');
118                 return false;
119         }
120
121         if (!is_new_reference($_POST['wo_ref'], systypes::work_order()))
122         {
123                 display_error(_("The entered reference is already in use."));
124                 set_focus('wo_ref');
125                 return false;
126         }
127         }
128
129         if (!check_num('quantity', 0))
130         {
131                 display_error( _("The quantity entered is invalid or less than zero."));
132                 set_focus('quantity');
133                 return false;
134         }
135
136         if (!is_date($_POST['date_']))
137         {
138                 display_error( _("The date entered is in an invalid format."));
139                 set_focus('date_');
140                 return false;
141         }
142         elseif (!is_date_in_fiscalyear($_POST['date_']))
143         {
144                 display_error(_("The entered date is not in fiscal year."));
145                 set_focus('date_');
146                 return false;
147         }
148         // only check bom and quantites if quick assembly
149         if (!($_POST['type'] == wo_types::advanced()))
150         {
151         if (!has_bom($_POST['stock_id']))
152         {
153                 display_error(_("The selected item to manufacture does not have a bom."));
154                 set_focus('stock_id');
155                 return false;
156         }
157
158                 if ($_POST['Costs'] == "")
159                         $_POST['Costs'] = price_format(0);
160         if (!check_num('Costs', 0))
161         {
162                 display_error( _("The cost entered is invalid or less than zero."));
163                 set_focus('Costs');
164                 return false;
165         }
166
167         if (!sys_prefs::allow_negative_stock())
168         {
169                 if ($_POST['type'] == wo_types::assemble())
170                 {
171                         // check bom if assembling
172                 $result = get_bom($_POST['stock_id']);
173
174                 while ($bom_item = db_fetch($result))
175                 {
176
177                         if (has_stock_holding($bom_item["ResourceType"]))
178                         {
179
180                                 $quantity = $bom_item["quantity"] * input_num('quantity');
181
182                         $qoh = get_qoh_on_date($bom_item["component"], $bom_item["loc_code"], $_POST['date_']);
183                                 if (-$quantity + $qoh < 0)
184                                 {
185                                         display_error(_("The work order cannot be processed because there is an insufficient quantity for component:") .
186                                                 " " . $bom_item["component"] . " - " .  $bom_item["description"] . ".  " . _("Location:") . " " . $bom_item["location_name"]);
187                                                 set_focus('quantity');
188                                                 return false;
189                                 }
190                         }
191                 }
192                 }
193                 elseif ($_POST['type'] == wo_types::unassemble())
194                 {
195                         // if unassembling, check item to unassemble
196                                 $qoh = get_qoh_on_date($_POST['stock_id'], $_POST['StockLocation'], $_POST['date_']);
197                         if (-input_num('quantity') + $qoh < 0)
198                         {
199                                 display_error(_("The selected item cannot be unassembled because there is insufficient stock."));
200                                         return false;
201                         }
202                 }
203         }
204      }
205      else
206      {
207         if (!is_date($_POST['RequDate']))
208         {
209                 set_focus('RequDate');
210                 display_error( _("The date entered is in an invalid format."));
211                 return false;
212                 }
213                 //elseif (!is_date_in_fiscalyear($_POST['RequDate']))
214                 //{
215                 //      display_error(_("The entered date is not in fiscal year."));
216                 //      return false;
217                 //}
218         if (isset($selected_id))
219         {
220                 $myrow = get_work_order($selected_id, true);
221
222                 if ($_POST['units_issued'] > input_num('quantity'))
223                 {
224                         set_focus('quantity');
225                         display_error(_("The quantity cannot be changed to be less than the quantity already manufactured for this order."));
226                         return false;
227                 }
228         }
229         }
230
231         return true;
232 }
233
234 //-------------------------------------------------------------------------------------
235
236 if (isset($_POST['ADD_ITEM']) && can_process())
237 {
238
239         $id = add_work_order($_POST['wo_ref'], $_POST['StockLocation'], input_num('quantity'),
240                 $_POST['stock_id'],  $_POST['type'], $_POST['date_'],
241                 $_POST['RequDate'], input_num('Costs'), $_POST['memo_']);
242
243         meta_forward($_SERVER['PHP_SELF'], "AddedID=$id");
244 }
245
246 //-------------------------------------------------------------------------------------
247
248 if (isset($_POST['UPDATE_ITEM']) && can_process())
249 {
250
251         update_work_order($selected_id, $_POST['StockLocation'], input_num('quantity'),
252                 $_POST['stock_id'],  $_POST['date_'], $_POST['RequDate'], $_POST['memo_']);
253
254         meta_forward($_SERVER['PHP_SELF'], "UpdatedID=$selected_id");
255 }
256
257 //--------------------------------------------------------------------------------------
258
259 if (isset($_POST['delete']))
260 {
261         //the link to delete a selected record was clicked instead of the submit button
262
263         $cancel_delete = false;
264
265         // can't delete it there are productions or issues
266         if (work_order_has_productions($selected_id) ||
267                 work_order_has_issues($selected_id)     ||
268                 work_order_has_payments($selected_id))
269         {
270                 display_error(_("This work order cannot be deleted because it has already been processed."));
271                 $cancel_delete = true;
272         }
273
274         if ($cancel_delete == false)
275         { //ie not cancelled the delete as a result of above tests
276
277                 // delete the actual work order
278                 delete_work_order($selected_id);
279                 meta_forward($_SERVER['PHP_SELF'], "DeletedID=$selected_id");
280         }
281 }
282
283 //-------------------------------------------------------------------------------------
284
285 if (isset($_POST['close']))
286 {
287
288         // update the closed flag in the work order
289         close_work_order($selected_id);
290         meta_forward($_SERVER['PHP_SELF'], "ClosedID=$selected_id");
291 }
292
293 //-------------------------------------------------------------------------------------
294 if (get_post('_type_update')) 
295 {
296   $Ajax->activate('_page_body');
297 }
298 //-------------------------------------------------------------------------------------
299
300 start_form();
301
302 start_table($table_style2);
303
304 $existing_comments = "";
305
306 $dec = 0;
307 if (isset($selected_id))
308 {
309         $myrow = get_work_order($selected_id);
310
311         if (strlen($myrow[0]) == 0)
312         {
313                 echo _("The order number sent is not valid.");
314                 safe_exit();
315         }
316
317         // if it's a closed work order can't edit it
318         if ($myrow["closed"] == 1)
319         {
320                 echo "<center>";
321                 display_error(_("This work order is closed and cannot be edited."));
322                 safe_exit();
323         }
324
325         $_POST['wo_ref'] = $myrow["wo_ref"];
326         $_POST['stock_id'] = $myrow["stock_id"];
327         $_POST['quantity'] = qty_format($myrow["units_reqd"], $_POST['stock_id'], $dec);
328         $_POST['StockLocation'] = $myrow["loc_code"];
329         $_POST['released'] = $myrow["released"];
330         $_POST['closed'] = $myrow["closed"];
331         $_POST['type'] = $myrow["type"];
332         $_POST['date_'] = sql2date($myrow["date_"]);
333         $_POST['RequDate'] = sql2date($myrow["required_by"]);
334         $_POST['released_date'] = sql2date($myrow["released_date"]);
335         $_POST['memo_'] = "";
336         $_POST['units_issued'] = $myrow["units_issued"];
337         $_POST['Costs'] = price_format($myrow["additional_costs"]);
338
339         $_POST['memo_'] = get_comments_string(systypes::work_order(), $selected_id);
340
341         hidden('wo_ref', $_POST['wo_ref']);
342         hidden('units_issued', $_POST['units_issued']);
343         hidden('released', $_POST['released']);
344         hidden('released_date', $_POST['released_date']);
345         hidden('selected_id',  $selected_id);
346         hidden('old_qty', $myrow["units_reqd"]);
347         hidden('old_stk_id', $myrow["stock_id"]);
348
349         label_row(_("Reference:"), $_POST['wo_ref']);
350         label_row(_("Type:"), wo_types::name($_POST['type']));
351         hidden('type', $myrow["type"]);
352 }
353 else
354 {
355         $_POST['units_issued'] = $_POST['released'] = 0;
356         ref_row(_("Reference:"), 'wo_ref', '', references::get_next(systypes::work_order()));
357
358         wo_types_list_row(_("Type:"), 'type', null);
359 }
360
361 if ($_POST['released'] == true)
362 {
363         hidden('stock_id', $_POST['stock_id']);
364         hidden('StockLocation', $_POST['StockLocation']);
365         hidden('type', $_POST['type']);
366
367         label_row(_("Item:"), $myrow["StockItemName"]);
368         label_row(_("Destination Location:"), $myrow["location_name"]);
369 }
370 else
371 {
372         stock_manufactured_items_list_row(_("Item:"), 'stock_id', null);
373
374         locations_list_row(_("Destination Location:"), 'StockLocation', null);
375 }
376
377 if (!isset($_POST['quantity']))
378         $_POST['quantity'] = qty_format(1, $_POST['stock_id'], $dec);
379
380 if (get_post('type') == wo_types::advanced())
381 {
382     qty_row(_("Quantity Required:"), 'quantity', null, null, null, $dec);
383     if ($_POST['released'])
384         label_row(_("Quantity Manufactured:"), number_format($_POST['units_issued'], get_qty_dec($_POST['stock_id'])));
385     date_row(_("Date") . ":", 'date_');
386         date_row(_("Date Required By") . ":", 'RequDate', '', null, sys_prefs::default_wo_required_by());
387 }
388 else
389 {
390     qty_row(_("Quantity:"), 'quantity', null, null, null, $dec);
391     date_row(_("Date") . ":", 'date_');
392         hidden('RequDate', '');
393
394         if (!isset($_POST['Costs']))
395                 $_POST['Costs'] = price_format(0);
396
397         amount_row(_("Total Additional Costs:"), 'Costs');
398 }
399
400 if ($_POST['released'])
401         label_row(_("Released On:"),$_POST['released_date']);
402
403 textarea_row(_("Memo:"), 'memo_', null, 40, 5);
404
405 end_table(1);
406
407 if (isset($selected_id))
408 {
409         echo "<table align=center><tr>";
410
411         submit_cells('UPDATE_ITEM', _("Update"), '', _('Save changes to work order'), true);
412         if (isset($_POST['released']))
413         {
414                 submit_cells('close', _("Close This Work Order"),'','',true);
415         }
416         submit_cells('delete', _("Delete This Work Order"),'','',true);
417
418         echo "</tr></table>";
419 }
420 else
421 {
422         submit_center('ADD_ITEM', _("Add Workorder"), true, '', true);
423 }
424
425 end_form();
426 end_page();
427
428 ?>