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