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