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