Annoyance 5683: Allow attachments from most needed post-creation option screens.
[fa-stable.git] / purchasing / po_entry_items.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 $path_to_root = "..";
13 $page_security = 'SA_PURCHASEORDER';
14 include_once($path_to_root . "/purchasing/includes/po_class.inc");
15 include_once($path_to_root . "/includes/session.inc");
16 include_once($path_to_root . "/purchasing/includes/purchasing_ui.inc");
17 include_once($path_to_root . "/purchasing/includes/db/suppliers_db.inc");
18 include_once($path_to_root . "/reporting/includes/reporting.inc");
19
20 set_page_security( @$_SESSION['PO']->trans_type,
21         array(  ST_PURCHORDER => 'SA_PURCHASEORDER',
22                         ST_SUPPRECEIVE => 'SA_GRN',
23                         ST_SUPPINVOICE => 'SA_SUPPLIERINVOICE'),
24         array(  'NewOrder' => 'SA_PURCHASEORDER',
25                         'ModifyOrderNumber' => 'SA_PURCHASEORDER',
26                         'AddedID' => 'SA_PURCHASEORDER',
27                         'NewGRN' => 'SA_GRN',
28                         'AddedGRN' => 'SA_GRN',
29                         'NewInvoice' => 'SA_SUPPLIERINVOICE',
30                         'AddedPI' => 'SA_SUPPLIERINVOICE')
31 );
32
33 $js = '';
34 if ($SysPrefs->use_popup_windows)
35         $js .= get_js_open_window(900, 500);
36 if (user_use_date_picker())
37         $js .= get_js_date_picker();
38
39 if (isset($_GET['ModifyOrderNumber']) && is_numeric($_GET['ModifyOrderNumber'])) {
40
41         $_SESSION['page_title'] = _($help_context = "Modify Purchase Order #") . $_GET['ModifyOrderNumber'];
42         create_new_po(ST_PURCHORDER, $_GET['ModifyOrderNumber']);
43         copy_from_cart();
44 } elseif (isset($_GET['NewOrder'])) {
45
46         $_SESSION['page_title'] = _($help_context = "Purchase Order Entry");
47         create_new_po(ST_PURCHORDER, 0);
48         copy_from_cart();
49 } elseif (isset($_GET['NewGRN'])) {
50
51         $_SESSION['page_title'] = _($help_context = "Direct GRN Entry");
52         create_new_po(ST_SUPPRECEIVE, 0);
53         copy_from_cart();
54 } elseif (isset($_GET['NewInvoice'])) {
55
56         create_new_po(ST_SUPPINVOICE, 0);
57         copy_from_cart();
58
59         if (isset($_GET['FixedAsset'])) {
60                 $_SESSION['page_title'] = _($help_context = "Fixed Asset Purchase Invoice Entry");
61                 $_SESSION['PO']->fixed_asset = true;
62         } else
63                 $_SESSION['page_title'] = _($help_context = "Direct Purchase Invoice Entry");
64 }
65
66 page($_SESSION['page_title'], false, false, "", $js);
67
68 if (isset($_GET['ModifyOrderNumber']))
69         check_is_editable(ST_PURCHORDER, $_GET['ModifyOrderNumber']);
70
71 //---------------------------------------------------------------------------------------------------
72
73 check_db_has_suppliers(_("There are no suppliers defined in the system."));
74
75 //---------------------------------------------------------------------------------------------------------------
76
77 if (isset($_GET['AddedID'])) 
78 {
79         $order_no = $_GET['AddedID'];
80         $trans_type = ST_PURCHORDER;    
81
82         if (!isset($_GET['Updated']))
83                 display_notification_centered(_("Purchase Order has been entered"));
84         else
85                 display_notification_centered(_("Purchase Order has been updated") . " #$order_no");
86         display_note(get_trans_view_str($trans_type, $order_no, _("&View this order")), 0, 1);
87
88         display_note(print_document_link($order_no, _("&Print This Order"), true, $trans_type), 0, 1);
89
90         display_note(print_document_link($order_no, _("&Email This Order"), true, $trans_type, false, "printlink", "", 1));
91
92         hyperlink_params($path_to_root . "/purchasing/po_receive_items.php", _("&Receive Items on this Purchase Order"), "PONumber=$order_no");
93
94   // TODO, for fixed asset
95         hyperlink_params($_SERVER['PHP_SELF'], _("Enter &Another Purchase Order"), "NewOrder=yes");
96         
97         hyperlink_no_params($path_to_root."/purchasing/inquiry/po_search.php", _("Select An &Outstanding Purchase Order"));
98         
99         hyperlink_params("$path_to_root/admin/attachments.php", _("Add an Attachment"), 
100                 "filterType=$trans_type&trans_no=$order_no");
101
102         display_footer_exit();  
103
104 } elseif (isset($_GET['AddedGRN'])) {
105
106         $trans_no = $_GET['AddedGRN'];
107         $trans_type = ST_SUPPRECEIVE;
108
109         display_notification_centered(_("Direct GRN has been entered"));
110
111         display_note(get_trans_view_str($trans_type, $trans_no, _("&View this GRN")), 0);
112
113     $clearing_act = get_company_pref('grn_clearing_act');
114         if ($clearing_act)      
115                 display_note(get_gl_view_str($trans_type, $trans_no, _("View the GL Journal Entries for this Delivery")), 1);
116
117         hyperlink_params("$path_to_root/purchasing/supplier_invoice.php",
118                 _("Entry purchase &invoice for this receival"), "New=1");
119
120         hyperlink_params($_SERVER['PHP_SELF'], _("Enter &Another GRN"), "NewGRN=Yes");
121         
122         hyperlink_params("$path_to_root/admin/attachments.php", _("Add an Attachment"), 
123                 "filterType=$trans_type&trans_no=$trans_no");
124
125         display_footer_exit();  
126
127 } elseif (isset($_GET['AddedPI'])) {
128
129         $trans_no = $_GET['AddedPI'];
130         $trans_type = ST_SUPPINVOICE;
131
132         display_notification_centered(_("Direct Purchase Invoice has been entered"));
133
134         display_note(get_trans_view_str($trans_type, $trans_no, _("&View this Invoice")), 0);
135
136         display_note(get_gl_view_str($trans_type, $trans_no, _("View the GL Journal Entries for this Invoice")), 1);
137
138         hyperlink_params("$path_to_root/purchasing/supplier_payment.php", _("Entry supplier &payment for this invoice"),
139                 "trans_type=$trans_type&PInvoice=".$trans_no);
140
141         hyperlink_params($_SERVER['PHP_SELF'], _("Enter &Another Direct Invoice"), "NewInvoice=Yes");
142         
143         hyperlink_params("$path_to_root/admin/attachments.php", _("Add an Attachment"), 
144                 "filterType=$trans_type&trans_no=$trans_no");
145
146         display_footer_exit();  
147 }
148
149 if ($_SESSION['PO']->fixed_asset)
150   check_db_has_purchasable_fixed_assets(_("There are no purchasable fixed assets defined in the system."));
151 else
152   check_db_has_purchasable_items(_("There are no purchasable inventory items defined in the system."));
153 //--------------------------------------------------------------------------------------------------
154
155 function line_start_focus() {
156   global        $Ajax;
157
158   $Ajax->activate('items_table');
159   set_focus('_stock_id_edit');
160 }
161 //--------------------------------------------------------------------------------------------------
162
163 function unset_form_variables() {
164         unset($_POST['stock_id']);
165     unset($_POST['qty']);
166     unset($_POST['price']);
167     unset($_POST['req_del_date']);
168 }
169
170 //---------------------------------------------------------------------------------------------------
171
172 function handle_delete_item($line_no)
173 {
174         if($_SESSION['PO']->some_already_received($line_no) == 0)
175         {
176                 $_SESSION['PO']->remove_from_order($line_no);
177                 unset_form_variables();
178         } 
179         else 
180         {
181                 display_error(_("This item cannot be deleted because some of it has already been received."));
182         }       
183     line_start_focus();
184 }
185
186 //---------------------------------------------------------------------------------------------------
187
188 function handle_cancel_po()
189 {
190         global $path_to_root;
191         
192         //need to check that not already dispatched or invoiced by the supplier
193         if(($_SESSION['PO']->order_no != 0) && 
194                 $_SESSION['PO']->any_already_received() == 1)
195         {
196                 display_error(_("This order cannot be cancelled because some of it has already been received.") 
197                         . "<br>" . _("The line item quantities may be modified to quantities more than already received. prices cannot be altered for lines that have already been received and quantities cannot be reduced below the quantity already received."));
198                 return;
199         }
200
201         $fixed_asset = $_SESSION['PO']->fixed_asset;
202
203         if($_SESSION['PO']->order_no != 0)
204                 delete_po($_SESSION['PO']->order_no);
205         else {
206                 unset($_SESSION['PO']);
207
208         if ($fixed_asset)
209                         meta_forward($path_to_root.'/index.php','application=assets');
210                 else
211                         meta_forward($path_to_root.'/index.php','application=AP');
212         }
213
214         $_SESSION['PO']->clear_items();
215         $_SESSION['PO'] = new purch_order;
216
217         display_notification(_("This purchase order has been cancelled."));
218
219         hyperlink_params($path_to_root . "/purchasing/po_entry_items.php", _("Enter a new purchase order"), "NewOrder=Yes");
220         echo "<br>";
221
222         end_page();
223         exit;
224 }
225
226 //---------------------------------------------------------------------------------------------------
227
228 function check_data()
229 {
230         if(!get_post('stock_id_text', true)) {
231                 display_error( _("Item description cannot be empty."));
232                 set_focus('stock_id_edit');
233                 return false;
234         }
235
236         $dec = get_qty_dec($_POST['stock_id']);
237         $min = 1 / pow(10, $dec);
238     if (!check_num('qty',$min))
239     {
240         $min = number_format2($min, $dec);
241                 display_error(_("The quantity of the order item must be numeric and not less than ").$min);
242                 set_focus('qty');
243                 return false;
244     }
245
246     if (!check_num('price', 0))
247     {
248                 display_error(_("The price entered must be numeric and not less than zero."));
249                 set_focus('price');
250                 return false;      
251     }
252     if ($_SESSION['PO']->trans_type == ST_PURCHORDER && !is_date($_POST['req_del_date'])){
253                 display_error(_("The date entered is in an invalid format."));
254                 set_focus('req_del_date');
255                 return false;            
256     }
257      
258     return true;        
259 }
260
261 //---------------------------------------------------------------------------------------------------
262
263 function handle_update_item()
264 {
265         $allow_update = check_data(); 
266
267         if ($allow_update)
268         {
269                 if ($_SESSION['PO']->line_items[$_POST['line_no']]->qty_inv > input_num('qty') ||
270                         $_SESSION['PO']->line_items[$_POST['line_no']]->qty_received > input_num('qty'))
271                 {
272                         display_error(_("You are attempting to make the quantity ordered a quantity less than has already been invoiced or received.  This is prohibited.") .
273                                 "<br>" . _("The quantity received can only be modified by entering a negative receipt and the quantity invoiced can only be reduced by entering a credit note against this item."));
274                         set_focus('qty');
275                         return;
276                 }
277         
278                 $_SESSION['PO']->update_order_item($_POST['line_no'], input_num('qty'), input_num('price'),
279                         @$_POST['req_del_date'], $_POST['item_description'] );
280                 unset_form_variables();
281         }       
282     line_start_focus();
283 }
284
285 //---------------------------------------------------------------------------------------------------
286
287 function handle_add_new_item()
288 {
289         $allow_update = check_data();
290         
291         if ($allow_update == true)
292         { 
293                 if (count($_SESSION['PO']->line_items) > 0)
294                 {
295                     foreach ($_SESSION['PO']->line_items as $order_item) 
296                     {
297                         /* do a loop round the items on the order to see that the item
298                         is not already on this order */
299                             if (($order_item->stock_id == $_POST['stock_id'])) 
300                             {
301                                         display_warning(_("The selected item is already on this order."));
302                             }
303                     } /* end of the foreach loop to look for pre-existing items of the same code */
304                 }
305
306                 if ($allow_update == true)
307                 {
308                         $result = get_short_info($_POST['stock_id']);
309
310                         if (db_num_rows($result) == 0)
311                         {
312                                 $allow_update = false;
313                         }
314
315                         if ($allow_update)
316                         {
317                                 $_SESSION['PO']->add_to_order (count($_SESSION['PO']->line_items), $_POST['stock_id'], input_num('qty'), 
318                                         get_post('stock_id_text'), //$myrow["description"], 
319                                         input_num('price'), '', // $myrow["units"], (retrived in cart)
320                                         $_SESSION['PO']->trans_type == ST_PURCHORDER ? $_POST['req_del_date'] : '', 0, 0);
321
322                                 unset_form_variables();
323                                 $_POST['stock_id']      = "";
324                         } 
325                         else 
326                         {
327                              display_error(_("The selected item does not exist or it is a kit part and therefore cannot be purchased."));
328                         }
329
330                 } /* end of if not already on the order and allow input was true*/
331     }
332         line_start_focus();
333 }
334
335 //---------------------------------------------------------------------------------------------------
336
337 function can_commit()
338 {
339         if (!get_post('supplier_id')) 
340         {
341                 display_error(_("There is no supplier selected."));
342                 set_focus('supplier_id');
343                 return false;
344         } 
345
346         if (!is_date($_POST['OrderDate'])) 
347         {
348                 display_error(_("The entered order date is invalid."));
349                 set_focus('OrderDate');
350                 return false;
351         } 
352         if (($_SESSION['PO']->trans_type == ST_SUPPRECEIVE || $_SESSION['PO']->trans_type == ST_SUPPINVOICE) 
353                 && !is_date_in_fiscalyear($_POST['OrderDate'])) {
354                 display_error(_("The entered date is out of fiscal year or is closed for further data entry."));
355                 set_focus('OrderDate');
356                 return false;
357         }
358
359         if (($_SESSION['PO']->trans_type==ST_SUPPINVOICE) && !is_date($_POST['due_date'])) 
360         {
361                 display_error(_("The entered due date is invalid."));
362                 set_focus('due_date');
363                 return false;
364         } 
365
366         if (!$_SESSION['PO']->order_no) 
367         {
368         if (!check_reference(get_post('ref'), $_SESSION['PO']->trans_type))
369         {
370                         set_focus('ref');
371                 return false;
372         }
373         }
374
375         if ($_SESSION['PO']->trans_type == ST_SUPPINVOICE && trim(get_post('supp_ref')) == false)
376         {
377                 display_error(_("You must enter a supplier's invoice reference."));
378                 set_focus('supp_ref');
379                 return false;
380         }
381         if ($_SESSION['PO']->trans_type==ST_SUPPINVOICE 
382                 && is_reference_already_there($_SESSION['PO']->supplier_id, get_post('supp_ref'), $_SESSION['PO']->order_no))
383         {
384                 display_error(_("This invoice number has already been entered. It cannot be entered again.") . " (" . get_post('supp_ref') . ")");
385                 set_focus('supp_ref');
386                 return false;
387         }
388         if ($_SESSION['PO']->trans_type == ST_PURCHORDER && get_post('delivery_address') == '')
389         {
390                 display_error(_("There is no delivery address specified."));
391                 set_focus('delivery_address');
392                 return false;
393         } 
394         if (get_post('StkLocation') == '')
395         {
396                 display_error(_("There is no location specified to move any items into."));
397                 set_focus('StkLocation');
398                 return false;
399         } 
400         if (!db_has_currency_rates($_SESSION['PO']->curr_code, $_POST['OrderDate'], true))
401                 return false;
402         if ($_SESSION['PO']->order_has_items() == false)
403         {
404         display_error (_("The order cannot be placed because there are no lines entered on this order."));
405         return false;
406         }
407         if (floatcmp(input_num('prep_amount'), $_SESSION['PO']->get_trans_total()) > 0)
408         {
409                 display_error(_("Required prepayment is greater than total invoice value."));
410                 set_focus('prep_amount');
411                 return false;
412         }
413
414         return true;
415 }
416
417 function handle_commit_order()
418 {
419         $cart = &$_SESSION['PO'];
420
421         if (can_commit()) {
422
423                 copy_to_cart();
424                 new_doc_date($cart->orig_order_date);
425                 if ($cart->order_no == 0) { // new po/grn/invoice
426                         $trans_no = add_direct_supp_trans($cart);
427                         if ($trans_no) {
428                                 unset($_SESSION['PO']);
429                                 if ($cart->trans_type == ST_PURCHORDER)
430                                         meta_forward($_SERVER['PHP_SELF'], "AddedID=$trans_no");
431                                 elseif ($cart->trans_type == ST_SUPPRECEIVE)
432                                         meta_forward($_SERVER['PHP_SELF'], "AddedGRN=$trans_no");
433                                 else
434                                         meta_forward($_SERVER['PHP_SELF'], "AddedPI=$trans_no");
435                         }
436                 } else { // order modification
437                         $order_no = update_po($cart);
438                         unset($_SESSION['PO']);
439                 meta_forward($_SERVER['PHP_SELF'], "AddedID=$order_no&Updated=1");      
440                 }
441         }
442 }
443 //---------------------------------------------------------------------------------------------------
444 if (isset($_POST['update'])) {
445         copy_to_cart();
446         $Ajax->activate('items_table');
447 }
448
449 $id = find_submit('Delete');
450 if ($id != -1)
451         handle_delete_item($id);
452
453 if (isset($_POST['Commit']))
454 {
455         handle_commit_order();
456 }
457 if (isset($_POST['UpdateLine']))
458         handle_update_item();
459
460 if (isset($_POST['EnterLine']))
461         handle_add_new_item();
462
463 if (isset($_POST['CancelOrder'])) 
464         handle_cancel_po();
465
466 if (isset($_POST['CancelUpdate']))
467         unset_form_variables();
468
469 if (isset($_POST['CancelUpdate']) || isset($_POST['UpdateLine'])) {
470         line_start_focus();
471 }
472
473 //---------------------------------------------------------------------------------------------------
474
475 start_form();
476
477 display_po_header($_SESSION['PO']);
478 echo "<br>";
479
480 display_po_items($_SESSION['PO']);
481
482 start_table(TABLESTYLE2);
483
484
485 if ($_SESSION['PO']->trans_type == ST_SUPPINVOICE) {
486         cash_accounts_list_row(_("Payment:"), 'cash_account', null, false, _('Delayed'));
487 }
488
489 textarea_row(_("Memo:"), 'Comments', null, 70, 4);
490
491 end_table(1);
492
493 div_start('controls', 'items_table');
494 $process_txt = _("Place Order");
495 $update_txt = _("Update Order");
496 $cancel_txt = _("Cancel Order");
497 if ($_SESSION['PO']->trans_type == ST_SUPPRECEIVE) {
498         $process_txt = _("Process GRN");
499         $update_txt = _("Update GRN");
500         $cancel_txt = _("Cancel GRN");
501 }       
502 elseif ($_SESSION['PO']->trans_type == ST_SUPPINVOICE) {
503         $process_txt = _("Process Invoice");
504         $update_txt = _("Update Invoice");
505         $cancel_txt = _("Cancel Invoice");
506 }       
507 if ($_SESSION['PO']->order_has_items()) 
508 {
509         if ($_SESSION['PO']->order_no)
510                 submit_center_first('Commit', $update_txt, '', 'default');
511         else
512                 submit_center_first('Commit', $process_txt, '', 'default');
513         submit_center_last('CancelOrder', $cancel_txt);         
514 }
515 else
516         submit_center('CancelOrder', $cancel_txt, true, false, 'cancel');
517 div_end();
518 //---------------------------------------------------------------------------------------------------
519
520 end_form();
521 end_page();