Missing restriction on fiscal year in direct GRN and direct Supp Invoice
[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_PURCHORDER && !is_date_in_fiscalyear($_POST['OrderDate'])) 
339         {
340                 display_error(_("The entered date is not in fiscal year"));
341                 set_focus('OrderDate');
342                 return false;
343         }
344
345         if (($_SESSION['PO']->trans_type==ST_SUPPINVOICE) && !is_date($_POST['due_date'])) 
346         {
347                 display_error(_("The entered due date is invalid."));
348                 set_focus('due_date');
349                 return false;
350         } 
351         
352         if (!$_SESSION['PO']->order_no) 
353         {
354         if (!$Refs->is_valid(get_post('ref'))) 
355         {
356                 display_error(_("There is no reference entered for this purchase order."));
357                         set_focus('ref');
358                 return false;
359         } 
360         
361         if (!is_new_reference(get_post('ref'), $_SESSION['PO']->trans_type)) 
362         {
363                 display_error(_("The entered reference is already in use."));
364                         set_focus('ref');
365                 return false;
366         }
367         }
368         
369         if ($_SESSION['PO']->trans_type == ST_SUPPINVOICE && !$Refs->is_valid(get_post('supp_ref'))) 
370         {
371                 display_error(_("You must enter a supplier's invoice reference."));
372                 set_focus('supp_ref');
373                 return false;
374         }
375         if ($_SESSION['PO']->trans_type == ST_PURCHORDER && get_post('delivery_address') == '')
376         {
377                 display_error(_("There is no delivery address specified."));
378                 set_focus('delivery_address');
379                 return false;
380         } 
381         if (get_post('StkLocation') == '')
382         {
383                 display_error(_("There is no location specified to move any items into."));
384                 set_focus('StkLocation');
385                 return false;
386         } 
387         
388         if ($_SESSION['PO']->order_has_items() == false)
389         {
390         display_error (_("The order cannot be placed because there are no lines entered on this order."));
391         return false;
392         }
393                 
394         return true;
395 }
396
397 //---------------------------------------------------------------------------------------------------
398
399 function handle_commit_order()
400 {
401         $cart = &$_SESSION['PO'];
402
403         if (can_commit()) {
404
405                 copy_to_cart();
406                 if ($cart->trans_type != ST_PURCHORDER) {
407                         // for direct grn/invoice set same dates for lines as for whole document
408                         foreach ($cart->line_items as $line_no =>$line)
409                                 $cart->line_items[$line_no]->req_del_date = $cart->orig_order_date;
410                 }
411                 if ($cart->order_no == 0) { // new po/grn/invoice
412                         /*its a new order to be inserted */
413                         $ref = $cart->reference;
414                         if ($cart->trans_type != ST_PURCHORDER) {
415                                 $cart->reference = 'auto';
416                                 begin_transaction();    // all db changes as single transaction for direct document
417                         }
418                         $order_no = add_po($cart);
419                         new_doc_date($cart->orig_order_date); 
420                 $cart->order_no = $order_no;
421
422                         if ($cart->trans_type == ST_PURCHORDER) {
423                                 unset($_SESSION['PO']);
424                         meta_forward($_SERVER['PHP_SELF'], "AddedID=$order_no");
425                 }
426                         //Direct GRN
427                         if ($cart->trans_type == ST_SUPPRECEIVE)
428                                 $cart->reference = $ref;
429                         $cart->Comments = $cart->reference; //grn does not hold supp_ref
430                         foreach($cart->line_items as $key => $line)
431                                 $cart->line_items[$key]->receive_qty = $line->quantity;
432                         $grn_no = add_grn($cart);
433                         if ($cart->trans_type == ST_SUPPRECEIVE) {
434                                 commit_transaction(); // save PO+GRN
435                                 unset($_SESSION['PO']);
436                         meta_forward($_SERVER['PHP_SELF'], "AddedGRN=$grn_no");
437                         }
438 //                      Direct Purchase Invoice
439                         $inv = new supp_trans(ST_SUPPINVOICE);
440                         $inv->Comments = $cart->Comments;
441                         $inv->supplier_id = $cart->supplier_id;
442                         $inv->tran_date = $cart->orig_order_date;
443                         $inv->due_date = $cart->due_date;
444                         $inv->reference = $ref;
445                         $inv->supp_reference = $cart->supp_ref;
446                         $inv->tax_included = $cart->tax_included;
447                         $supp = get_supplier($cart->supplier_id);
448                         $inv->tax_group_id = $supp['tax_group_id'];
449 //                      $inv->ov_discount 'this isn't used at all'
450                         $inv->ov_amount = $inv->ov_gst = 0;
451                         
452                         foreach($cart->line_items as $key => $line) {
453                                 $inv->add_grn_to_trans($line->grn_item_id, $line->po_detail_rec, $line->stock_id,
454                                         $line->item_description, $line->receive_qty, 0, $line->receive_qty,
455                                         $line->price, $line->price, true, get_standard_cost($line->stock_id), '');
456                                 $inv->ov_amount += round2(($line->receive_qty * $line->price), user_price_dec());
457                         }
458                         $taxes = $inv->get_taxes($inv->tax_group_id, 0, false);
459                         foreach( $taxes as $taxitem) {
460                                 $inv->ov_gst += round2($taxitem['Value'], user_price_dec());
461                         }
462                         $inv_no = add_supp_invoice($inv);
463                         commit_transaction(); // save PO+GRN+PI
464                         // FIXME payment for cash terms. (Needs cash account selection)
465                         unset($_SESSION['PO']);
466                 meta_forward($_SERVER['PHP_SELF'], "AddedPI=$inv_no");
467                 }
468                 else { // order modification
469                 
470                         $order_no = update_po($cart);
471                         unset($_SESSION['PO']);
472                 meta_forward($_SERVER['PHP_SELF'], "AddedID=$order_no&Updated=1");      
473                 }
474         }
475 }
476 //---------------------------------------------------------------------------------------------------
477 $id = find_submit('Delete');
478 if ($id != -1)
479         handle_delete_item($id);
480
481 if (isset($_POST['Commit']))
482 {
483         handle_commit_order();
484 }
485 if (isset($_POST['UpdateLine']))
486         handle_update_item();
487
488 if (isset($_POST['EnterLine']))
489         handle_add_new_item();
490
491 if (isset($_POST['CancelOrder'])) 
492         handle_cancel_po();
493
494 if (isset($_POST['CancelUpdate']))
495         unset_form_variables();
496
497 if (isset($_POST['CancelUpdate']) || isset($_POST['UpdateLine'])) {
498         line_start_focus();
499 }
500
501 //---------------------------------------------------------------------------------------------------
502
503 start_form();
504
505 display_po_header($_SESSION['PO']);
506 echo "<br>";
507
508 display_po_items($_SESSION['PO']);
509
510 start_table(TABLESTYLE2);
511 textarea_row(_("Memo:"), 'Comments', null, 70, 4);
512
513 end_table(1);
514
515 div_start('controls', 'items_table');
516 $process_txt = _("Place Order");
517 $update_txt = _("Update Order");
518 $cancel_txt = _("Cancel Order");
519 if ($_SESSION['PO']->trans_type == ST_SUPPRECEIVE) {
520         $process_txt = _("Process GRN");
521         $update_txt = _("Update GRN");
522         $cancel_txt = _("Cancel GRN");
523 }       
524 elseif ($_SESSION['PO']->trans_type == ST_SUPPINVOICE) {
525         $process_txt = _("Process Invoice");
526         $update_txt = _("Update Invoice");
527         $cancel_txt = _("Cancel Invoice");
528 }       
529 if ($_SESSION['PO']->order_has_items()) 
530 {
531         if ($_SESSION['PO']->order_no)
532                 submit_center_first('Commit', $update_txt, '', 'default');
533         else
534                 submit_center_first('Commit', $process_txt, '', 'default');
535         submit_center_last('CancelOrder', $cancel_txt);         
536 }
537 else
538         submit_center('CancelOrder', $cancel_txt, true, false, 'cancel');
539 div_end();
540 //---------------------------------------------------------------------------------------------------
541
542 end_form();
543 end_page();
544 ?>