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