c7e7cb134d34699128aa109c21302f3673df1877
[fa-stable.git] / purchasing / po_receive_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 $page_security = 'SA_GRN';
13 $path_to_root = "..";
14 include_once($path_to_root . "/purchasing/includes/po_class.inc");
15
16 include_once($path_to_root . "/includes/session.inc");
17 include_once($path_to_root . "/purchasing/includes/purchasing_db.inc");
18 include_once($path_to_root . "/purchasing/includes/purchasing_ui.inc");
19
20 $js = "";
21 if ($use_popup_windows)
22         $js .= get_js_open_window(900, 500);
23 if ($use_date_picker)
24         $js .= get_js_date_picker();
25 page(_($help_context = "Receive Purchase Order Items"), false, false, "", $js);
26
27 //---------------------------------------------------------------------------------------------------------------
28
29 if (isset($_GET['AddedID']))
30 {
31         $grn = $_GET['AddedID'];
32         $trans_type = ST_SUPPRECEIVE;
33
34         display_notification_centered(_("Purchase Order Delivery has been processed"));
35
36         display_note(get_trans_view_str($trans_type, $grn, _("&View this Delivery")));
37
38         hyperlink_params("$path_to_root/purchasing/supplier_invoice.php", _("Entry purchase &invoice for this receival"), "New=1");
39
40         hyperlink_no_params("$path_to_root/purchasing/inquiry/po_search.php", _("Select a different &purchase order for receiving items against"));
41
42         display_footer_exit();
43 }
44
45 //--------------------------------------------------------------------------------------------------
46
47 if ((!isset($_GET['PONumber']) || $_GET['PONumber'] == 0) && !isset($_SESSION['PO']))
48 {
49         die (_("This page can only be opened if a purchase order has been selected. Please select a purchase order first."));
50 }
51
52 //--------------------------------------------------------------------------------------------------
53
54 function display_po_receive_items()
55 {
56         div_start('grn_items');
57     start_table(TABLESTYLE, "colspan=7 width=90%");
58     $th = array(_("Item Code"), _("Description"), _("Ordered"), _("Units"), _("Received"),
59         _("Outstanding"), _("This Delivery"), _("Price"), _("Total"));
60     table_header($th);
61
62     /*show the line items on the order with the quantity being received for modification */
63
64     $total = 0;
65     $k = 0; //row colour counter
66
67     if (count($_SESSION['PO']->line_items)> 0 )
68     {
69         foreach ($_SESSION['PO']->line_items as $ln_itm)
70         {
71
72                         alt_table_row_color($k);
73
74                 $qty_outstanding = $ln_itm->quantity - $ln_itm->qty_received;
75
76                         if (!isset($_POST['Update']) && !isset($_POST['ProcessGoodsReceived']) && $ln_itm->receive_qty == 0)
77                 {   //If no quantites yet input default the balance to be received
78                 $ln_itm->receive_qty = $qty_outstanding;
79                 }
80
81                 $line_total = ($ln_itm->receive_qty * $ln_itm->price);
82                 $total += $line_total;
83
84                         label_cell($ln_itm->stock_id);
85                         if ($qty_outstanding > 0)
86                                 text_cells(null, $ln_itm->stock_id . "Desc", $ln_itm->item_description, 30, 50);
87                         else
88                                 label_cell($ln_itm->item_description);
89                         $dec = get_qty_dec($ln_itm->stock_id);
90                         qty_cell($ln_itm->quantity, false, $dec);
91                         label_cell($ln_itm->units);
92                         qty_cell($ln_itm->qty_received, false, $dec);
93                         qty_cell($qty_outstanding, false, $dec);
94
95                         if ($qty_outstanding > 0)
96                                 qty_cells(null, $ln_itm->line_no, number_format2($ln_itm->receive_qty, $dec), "align=right", null, $dec);
97                         else
98                                 label_cell(number_format2($ln_itm->receive_qty, $dec), "align=right");
99
100                         amount_decimal_cell($ln_itm->price);
101                         amount_cell($line_total);
102                         end_row();
103         }
104     }
105
106         $colspan = count($th)-1;
107
108         $display_sub_total = price_format($total/* + input_num('freight_cost')*/);
109
110         label_row(_("Sub-total"), $display_sub_total, "colspan=$colspan align=right","align=right");
111         $taxes = $_SESSION['PO']->get_taxes(input_num('freight_cost'));
112         
113         $tax_total = display_edit_tax_items($taxes, $colspan, $_SESSION['PO']->tax_included);
114
115         $display_total = price_format(($total + input_num('freight_cost') + $tax_total));
116
117         start_row();
118         label_cells(_("Amount Total"), $display_total, "colspan=$colspan align='right'","align='right'");
119         end_row();
120     end_table();
121         div_end();
122 }
123
124 //--------------------------------------------------------------------------------------------------
125
126 function check_po_changed()
127 {
128         /*Now need to check that the order details are the same as they were when they were read
129         into the Items array. If they've changed then someone else must have altered them */
130         // Sherifoz 22.06.03 Compare against COMPLETED items only !!
131         // Otherwise if you try to fullfill item quantities separately will give error.
132         $result = get_po_items($_SESSION['PO']->order_no);
133
134         $line_no = 0;
135         while ($myrow = db_fetch($result))
136         {
137                 $ln_item = $_SESSION['PO']->line_items[$line_no];
138                 // only compare against items that are outstanding
139                 $qty_outstanding = $ln_item->quantity - $ln_item->qty_received;
140                 if ($qty_outstanding > 0)
141                 {
142                 if ($ln_item->qty_inv != $myrow["qty_invoiced"] ||
143                         $ln_item->stock_id != $myrow["item_code"] ||
144                         $ln_item->quantity != $myrow["quantity_ordered"] ||
145                         $ln_item->qty_received != $myrow["quantity_received"])
146                 {
147                         return true;
148                 }
149                 }
150                 $line_no++;
151         } /*loop through all line items of the order to ensure none have been invoiced */
152
153         return false;
154 }
155
156 //--------------------------------------------------------------------------------------------------
157
158 function can_process()
159 {
160         global $SysPrefs, $Refs;
161         
162         if (count($_SESSION['PO']->line_items) <= 0)
163         {
164         display_error(_("There is nothing to process. Please enter valid quantities greater than zero."));
165         return false;
166         }
167
168         if (!is_date($_POST['DefaultReceivedDate']))
169         {
170                 display_error(_("The entered date is invalid."));
171                 set_focus('DefaultReceivedDate');
172                 return false;
173         }
174
175     if (!$Refs->is_valid($_POST['ref']))
176     {
177                 display_error(_("You must enter a reference."));
178                 set_focus('ref');
179                 return false;
180         }
181
182         if (!is_new_reference($_POST['ref'], ST_SUPPRECEIVE))
183         {
184                 display_error(_("The entered reference is already in use."));
185                 set_focus('ref');
186                 return false;
187         }
188
189         $something_received = 0;
190         foreach ($_SESSION['PO']->line_items as $order_line)
191         {
192                 if ($order_line->receive_qty > 0)
193                 {
194                         $something_received = 1;
195                         break;
196                 }
197         }
198
199     // Check whether trying to deliver more items than are recorded on the actual purchase order (+ overreceive allowance)
200     $delivery_qty_too_large = 0;
201         foreach ($_SESSION['PO']->line_items as $order_line)
202         {
203                 if ($order_line->receive_qty+$order_line->qty_received >
204                         $order_line->quantity * (1+ ($SysPrefs->over_receive_allowance() / 100)))
205                 {
206                         $delivery_qty_too_large = 1;
207                         break;
208                 }
209         }
210
211     if ($something_received == 0)
212     {   /*Then dont bother proceeding cos nothing to do ! */
213         display_error(_("There is nothing to process. Please enter valid quantities greater than zero."));
214         return false;
215     }
216     elseif ($delivery_qty_too_large == 1)
217     {
218         display_error(_("Entered quantities cannot be greater than the quantity entered on the purchase order including the allowed over-receive percentage") . " (" . $SysPrefs->over_receive_allowance() ."%)."
219                 . "<br>" .
220                 _("Modify the ordered items on the purchase order if you wish to increase the quantities."));
221         return false;
222     }
223
224         return true;
225 }
226
227 //--------------------------------------------------------------------------------------------------
228
229 function process_receive_po()
230 {
231         global $path_to_root, $Ajax;
232
233         if (!can_process())
234                 return;
235
236         if (check_po_changed())
237         {
238                 display_error(_("This order has been changed or invoiced since this delivery was started to be actioned. Processing halted. To enter a delivery against this purchase order, it must be re-selected and re-read again to update the changes made by the other user."));
239
240                 hyperlink_no_params("$path_to_root/purchasing/inquiry/po_search.php",
241                  _("Select a different purchase order for receiving goods against"));
242
243                 hyperlink_params("$path_to_root/purchasing/po_receive_items.php", 
244                          _("Re-Read the updated purchase order for receiving goods against"),
245                          "PONumber=" . $_SESSION['PO']->order_no);
246
247                 unset($_SESSION['PO']->line_items);
248                 unset($_SESSION['PO']);
249                 unset($_POST['ProcessGoodsReceived']);
250                 $Ajax->activate('_page_body');
251                 display_footer_exit();
252         }
253         
254         $grn = &$_SESSION['PO'];
255         $grn->orig_order_date = $_POST['DefaultReceivedDate'];
256         $grn->reference = $_POST['ref'];
257         $grn->Location = $_POST['Location'];
258
259         $grn_no = add_grn($grn);
260
261         new_doc_date($_POST['DefaultReceivedDate']);
262         unset($_SESSION['PO']->line_items);
263         unset($_SESSION['PO']);
264
265         meta_forward($_SERVER['PHP_SELF'], "AddedID=$grn_no");
266 }
267
268 //--------------------------------------------------------------------------------------------------
269
270 if (isset($_GET['PONumber']) && $_GET['PONumber'] > 0 && !isset($_POST['Update']))
271 {
272         create_new_po(ST_PURCHORDER, $_GET['PONumber']);
273         $_SESSION['PO']->trans_type = ST_SUPPRECEIVE;
274         $_SESSION['PO']->reference = $Refs->get_next(ST_SUPPRECEIVE);
275         copy_from_cart();
276 }
277
278 //--------------------------------------------------------------------------------------------------
279
280 if (isset($_POST['Update']) || isset($_POST['ProcessGoodsReceived']))
281 {
282
283         /* if update quantities button is hit page has been called and ${$line->line_no} would have be
284         set from the post to the quantity to be received in this receival*/
285         foreach ($_SESSION['PO']->line_items as $line)
286         {
287          if( ($line->quantity - $line->qty_received)>0) {
288                 $_POST[$line->line_no] = max($_POST[$line->line_no], 0);
289                 if (!check_num($line->line_no))
290                         $_POST[$line->line_no] = number_format2(0, get_qty_dec($line->stock_id));
291
292                 if (!isset($_POST['DefaultReceivedDate']) || $_POST['DefaultReceivedDate'] == "")
293                         $_POST['DefaultReceivedDate'] = new_doc_date();
294
295                 $_SESSION['PO']->line_items[$line->line_no]->receive_qty = input_num($line->line_no);
296
297                 if (isset($_POST[$line->stock_id . "Desc"]) && strlen($_POST[$line->stock_id . "Desc"]) > 0)
298                 {
299                         $_SESSION['PO']->line_items[$line->line_no]->item_description = $_POST[$line->stock_id . "Desc"];
300                 }
301          }
302         }
303         $Ajax->activate('grn_items');
304 }
305
306 //--------------------------------------------------------------------------------------------------
307
308 if (isset($_POST['ProcessGoodsReceived']))
309 {
310         process_receive_po();
311 }
312
313 //--------------------------------------------------------------------------------------------------
314
315 start_form();
316
317 display_grn_summary($_SESSION['PO'], true);
318 display_heading(_("Items to Receive"));
319 display_po_receive_items();
320
321 echo '<br>';
322 submit_center_first('Update', _("Update"), '', true);
323 submit_center_last('ProcessGoodsReceived', _("Process Receive Items"), _("Clear all GL entry fields"), 'default');
324
325 end_form();
326
327 //--------------------------------------------------------------------------------------------------
328 end_page();
329 ?>
330