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