<?php
/*=======================================================\
|                 Point of Sales Module                  |
|--------------------------------------------------------|
|   Creator: Phương                                      |
|   Date :   18-Dec-2017                                 |
|   Description: ERP Point of Sales Extension            |
|   Website: http://notrinos.com                         |
|                                                        |
\=======================================================*/

include_once($path_to_root . '/sales/includes/cart_class.inc');

class PosCart extends Cart {

	function write($policy=0) {
		
		global $SysPrefs, $Refs;
		
		begin_transaction(); // prevents partial database changes in case of direct delivery/invoice
		if ($this->reference != 'auto' && $this->trans_no == 0 && !is_new_reference($this->reference, $this->trans_type))
		{
			if (!empty($SysPrefs->prefs['ref_no_auto_increase']))
				$this->reference = $Refs->get_next($this->trans_type, null, array('date' => Today()));
			else	
			{
				commit_transaction();
				return -1;
			}
		}
		if (count($this->src_docs) == 0 && ($this->trans_type == ST_SALESINVOICE || $this->trans_type == ST_CUSTDELIVERY) && !$this->is_prepaid()) {
			// this is direct document - first add parent
			$ref = $this->reference;
			$date = $this->document_date;
			$due_date = $this->due_date;
			$dimension_id = $this->dimension_id;
			$dimension2_id = $this->dimension2_id;
			$this->trans_type = get_parent_type($this->trans_type);

			$this->reference = 'auto'; 
			$trans_no = $this->write(1); 

			// re-read parent document converting it to child
			$this->read($this->trans_type, $trans_no, true); 
			$this->document_date = $date;
			$this->reference = $ref;
			$this->due_date = $due_date;
			$this->dimension_id = $dimension_id;
			$this->dimension2_id = $dimension2_id;
		}
		$this->reference = @html_entity_decode($this->reference, ENT_QUOTES);
		$this->Comments = @html_entity_decode($this->Comments, ENT_QUOTES);
		foreach($this->line_items as $lineno => $line) {
			$this->line_items[$lineno]->stock_id = @html_entity_decode($line->stock_id, ENT_QUOTES);
			$this->line_items[$lineno]->item_description = @html_entity_decode($line->item_description, ENT_QUOTES);
		}
		switch($this->trans_type) {
			case ST_SALESINVOICE:
				$ret = write_sales_invoice($this); break;
			case ST_CUSTCREDIT:
				$ret = write_credit_note($this, $policy); break;
			case ST_CUSTDELIVERY:
				$ret = write_sales_delivery($this, $policy); break;
			case ST_SALESORDER:
			case ST_SALESQUOTE:
				if ($this->trans_no==0) // new document
					$ret = pos_add_sales_order($this);
				else
					$ret = update_sales_order($this);
		}

		commit_transaction();

		return $ret;
	}
}

function pos_add_sales_order(&$order) {
	global $SysPrefs, $path_to_root, $Refs;

	begin_transaction();
	hook_db_prewrite($order, $order->trans_type);
	$order_no = get_next_trans_no($order->trans_type);
	$del_date = date2sql($order->due_date);
	$order_type = 0; // this is default on new order
	$total = $order->get_trans_total();
	
	if(!pos_add_order_record($order, $order_type, $order_no, $del_date, $total, 'could not add order record'))
		return 0;

	$order->trans_no = array($order_no=>0);

	if ($SysPrefs->loc_notification() == 1)
	{
		include_once($path_to_root . "/inventory/includes/inventory_db.inc");
		$st_ids = array();
		$st_names = array();
		$st_num = array();
		$st_reorder = array();
	}
	foreach ($order->line_items as $line)
	{
		if ($SysPrefs->loc_notification() == 1 && is_inventory_item($line->stock_id))
			$loc = calculate_reorder_level($order->Location, $line, $st_ids, $st_names, $st_num, $st_reorder); 

		$sql = "INSERT INTO ".TB_PREF."sales_order_details (order_no, trans_type, stk_code, description, unit_price, quantity, discount_percent) VALUES (";
		$sql .= $order_no . ",".$order->trans_type .
				",".db_escape($line->stock_id).", "
				.db_escape($line->item_description).", $line->price,
				$line->quantity,
				$line->discount_percent)";
		db_query($sql, "order Details Cannot be Added");

	// Now mark quotation line as processed
		if ($order->trans_type == ST_SALESORDER && $line->src_id)
			update_parent_line(ST_SALESORDER, $line->src_id, $line->qty_dispatched); // clear all the quote despite all or the part was ordered
	} /* inserted line items into sales order details */

	add_audit_trail($order->trans_type, $order_no, $order->document_date);
	$Refs->save($order->trans_type, $order_no, $order->reference, null, $order->fixed_asset);

	hook_db_postwrite($order, $order->trans_type);
	commit_transaction();

	if ($SysPrefs->loc_notification() == 1 && count($st_ids) > 0)
		send_reorder_email($loc, $st_ids, $st_names, $st_num, $st_reorder);
	return $order_no;
}

function pos_add_order_record(&$order, $order_type, $order_no, $del_date, $total, $err_msg=null) {
	global $db, $SysPrefs, $sql_queries, $Ajax,	$db_connections, $db_last_inserted_id;

	$sql = "INSERT INTO ".TB_PREF."sales_orders (order_no, type, debtor_no, trans_type, branch_code, customer_ref, reference, comments, ord_date,
		order_type, ship_via, deliver_to, delivery_address, contact_phone,
		freight_cost, from_stk_loc, delivery_date, payment_terms, total, prep_amount)
		VALUES (" .db_escape($order_no) . "," .db_escape($order_type) . "," . db_escape($order->customer_id) .
		 ", " .db_escape($order->trans_type) . "," .db_escape($order->Branch) . ", ".
			db_escape($order->cust_ref) .",". 
			db_escape($order->reference) .",". 
			db_escape($order->Comments) .",'" . 
			date2sql($order->document_date) . "', " .
			db_escape($order->sales_type) . ", " .
			db_escape($order->ship_via)."," . 
			db_escape($order->deliver_to) . "," .
			db_escape($order->delivery_address) . ", " .
			db_escape($order->phone) . ", " . 
			db_escape($order->freight_cost) .", " . 
			db_escape($order->Location) .", " .
			db_escape($del_date) . "," .
			db_escape($order->payment) . "," .
			db_escape($total) . "," .
			db_escape($order->prep_amount).")";

	// set current db prefix
	$comp = isset($_SESSION["wa_current_user"]->cur_con) ? $_SESSION["wa_current_user"]->cur_con : 0;
	$cur_prefix = $db_connections[$comp]['tbpref'];
	$sql = str_replace(TB_PREF, $cur_prefix, $sql);

	if ($SysPrefs->show_sql)
	{
		$Ajax->activate('footer_debug');
		$sql_queries .= "<pre>$sql</pre>\n<hr>";
	}

	db_profile(); // mysql profiling

	$retry = MAX_DEADLOCK_RETRY;
	do {
		$result = mysqli_query($db, $sql);
		if (mysqli_errno($db) == 1213)	{ // deadlock detected
			sleep(1); $retry--;
		}
		elseif(mysqli_errno($db) == 1062 || mysqli_errno($db) == 1366) {
			return false;
		}
		else
			$retry = 0;
	} while ($retry);

	db_profile($sql);

	if($SysPrefs->sql_trail) {
		$db_last_inserted_id = mysqli_insert_id($db);	// preserve in case trail insert is done
		if ($SysPrefs->select_trail || (strstr($sql, 'SELECT') === false)) {
			mysqli_query($db, "INSERT INTO ".$cur_prefix."sql_trail
				(`sql`, `result`, `msg`)
				VALUES(".db_escape($sql).",".($result ? 1 : 0).",
				".db_escape($err_msg).")");
		}
	}

	if ($err_msg != null || $SysPrefs->go_debug) {
		$exit = $err_msg != null;
		if (function_exists('xdebug_call_file'))
			$err_msg = '<br>At file '.xdebug_call_file().':'.xdebug_call_line().':<br>'.$err_msg;
		check_db_error($err_msg, $sql, $exit);
	}
	return $result;
}