<?php

/* * ********************************************
  Author: Andres Amaya
  Name: Sales Quotes API
  Free software under GNU GPL
 * ********************************************* */

$path_to_root = "../..";

include_once($path_to_root . "/sales/includes/cart_class.inc");
include_once($path_to_root . "/includes/date_functions.inc");
include_once($path_to_root . "/sales/includes/sales_ui.inc");
include_once($path_to_root . "/sales/includes/ui/sales_order_ui.inc");
include_once($path_to_root . "/sales/includes/db/cust_trans_details_db.inc");
include_once($path_to_root . "/sales/includes/sales_db.inc");
include_once($path_to_root . "/sales/includes/db/sales_types_db.inc");
include_once($path_to_root . "/admin/db/attachments_db.inc");
include_once($path_to_root . "/modules/external/stock/db.php");
include_once($path_to_root . "/modules/api/api_db.inc");

function sales_all($trans_type, $from = null) {
    if ($from == null)
        $from = 0;

    $info = array();
    $sale_index = 0;
    $length = RESULTS_PER_PAGE;

    $debtor_no = !isset($_GET['debtor_no']) ? "" : $_GET['debtor_no'];
    $from_date = !isset($_GET['start_date']) ? "" : $_GET['start_date'];
    $to_date = !isset($_GET['end_date']) ? "" : $_GET['end_date'];
    $dimension = !isset($_GET['dimension']) ? "" : $_GET['dimension'];
    $Outstanding = !isset($_GET['outstanding']) ? "" : $_GET['outstanding'];

    if ($trans_type == ST_SALESINVOICE || $trans_type == ST_CUSTCREDIT) {
        $sql = "SELECT trans_no, type FROM " . TB_PREF . "debtor_trans WHERE  type=" . db_escape($trans_type) . " ";
        if (!empty($debtor_no)) {
            $sql .= " AND debtor_no=" . db_escape($debtor_no);
        }
        if (!empty($from_date) && !empty($to_date)) {
            $sql .= " AND tran_date BETWEEN '" . date2sql($from_date) . "' AND '" . date2sql($to_date) . "' ";
        }
        if (!empty($dimension)) {
            $sql .= " AND dimension_id=" . db_escape($dimension);
        }

        $sql .= " AND (ov_amount + ov_gst + ov_freight + ov_freight_tax ) != 0 order by tran_date,trans_no DESC LIMIT " . $from . ", " . $length;
        $query = db_query($sql, "error");

        while ($sale = db_fetch($query, "error")) {
            try {
                $trans = get_customer_trans($sale['trans_no'], $sale['type']);
                if (($Outstanding == "1" && ($trans['Total'] - $trans['alloc']) > 0) || ($Outstanding == "0" || empty($Outstanding))) {
                    $trans_details = get_customer_trans_details($sale['type'], $trans['trans_no']);

                    $info[$sale_index]['trans_no'] = $trans['trans_no'];
                    $info[$sale_index]['trans_type'] = $trans['type'];
                    $info[$sale_index]['version'] = $trans['version'];
                    $info[$sale_index]['debtor_no'] = $trans['debtor_no'];
                    $info[$sale_index]['customer'] = get_api_customer($trans['debtor_no']);
                    $info[$sale_index]['debtor_name'] = $trans['DebtorName'];
                    $info[$sale_index]['branch_code'] = $trans['branch_code'];
                    $branch = get_api_branch($trans['branch_code']);
                    $info[$sale_index]['branch'] = $branch;
                    $info[$sale_index]['tran_date'] = $trans['tran_date'];
                    $info[$sale_index]['document_date'] = $trans['tran_date'];
                    $info[$sale_index]['due_date'] = $trans['due_date'];
                    $info[$sale_index]['reference'] = $trans['reference'];
                    $info[$sale_index]['tpe'] = $trans['tpe'];
                    $info[$sale_index]['order_'] = $trans['order_'];
                    $info[$sale_index]['ov_amount'] = $trans['ov_amount'];
                    $info[$sale_index]['ov_gst'] = $trans['ov_gst'];
                    $info[$sale_index]['ov_freight'] = $trans['ov_freight'];
                    $info[$sale_index]['ov_freight_tax'] = $trans['ov_freight_tax'];
                    $info[$sale_index]['ov_discount'] = $trans['ov_discount'];
                    $info[$sale_index]['Total'] = $trans['Total'];
                    $info[$sale_index]['display_total'] = $trans['Total'];
                    $info[$sale_index]['alloc'] = $trans['alloc'];
                    $info[$sale_index]['rate'] = $trans['rate'];
                    $info[$sale_index]['ship_via'] = $trans['ship_via'];
                    $dimesion = get_dimension($trans['dimension_id'], true);
                    $info[$sale_index]['dimension'] = $dimesion ? $dimesion : null;
                    $dimesion2 = get_dimension($trans['dimension2_id'], true);
                    $info[$sale_index]['dimension2'] = $dimesion2 ? $dimesion2 : null;
                    $info[$sale_index]['dimension_id'] = $trans['dimension_id'];
                    $info[$sale_index]['dimension2_id'] = $trans['dimension2_id'];
                    $payment_terms = get_payment_terms($trans['payment_terms']);
                    $info[$sale_index]['payment_terms'] = $payment_terms ? $payment_terms : null;
                    $sales_type = get_sales_type_by_name($trans['sales_type']);
                    $info[$sale_index]['sales_type'] = $sales_type;
                    //$info[$sale_index]['digital'] = $trans['digital'];

                    $item_index = 0;

                    if (db_num_rows($trans_details) > 0) {
                        while ($trans_item = db_fetch($trans_details)) {
                            $stock_item = get_api_item($trans_item['stock_id'], $branch['tax_group_id']);
                            $info[$sale_index]['line_items'][$item_index]['stock_item'] = $stock_item;
                            $info[$sale_index]['line_items'][$item_index]['id'] = $trans_item['id'];
                            $info[$sale_index]['line_items'][$item_index]['stock_id'] = $trans_item['stock_id'];
                            $info[$sale_index]['line_items'][$item_index]['qty'] = $trans_item['quantity'];
                            $info[$sale_index]['line_items'][$item_index]['qty_done'] = $trans_item['qty_done'];
                            $info[$sale_index]['line_items'][$item_index]['units'] = $trans_item['units'];
                            $info[$sale_index]['line_items'][$item_index]['price'] = $trans_item['unit_price'];
                            $info[$sale_index]['line_items'][$item_index]['discount_percent'] = $trans_item['discount_percent'];
                            $info[$sale_index]['line_items'][$item_index]['item_description'] = $trans_item['StockDescription'];
                            $item_index++;
                        }
                    }

                    $alloc_result = get_allocatable_from_cust_transactions($trans['debtor_no'], $sale['trans_no'], $sale['type']);
                    $info[$sale_index]['has_payments'] = TRUE;
                    if (!$alloc_result || db_num_rows($alloc_result) == 0) {
                        $info[$sale_index]['has_payments'] = FALSE;
                    } else {
                        $pay_index = 0;
                        while ($alloc_row = db_fetch($alloc_result)) {
                            if ($alloc_row['type'] == ST_CUSTPAYMENT) {
                                $bank_trans = db_fetch(get_bank_trans($alloc_row['type'], $alloc_row['trans_no']));
                                $bank = get_bank_account($bank_trans['bank_act']);
                                $info[$sale_index][$sale_index]['payments'][$pay_index]['Total'] = $alloc_row['Total'];
                                $info[$sale_index]['payments'][$pay_index]['amt'] = $alloc_row['amt'];
                                $info[$sale_index]['payments'][$pay_index]['date'] = $alloc_row['tran_date'];
                                $info[$sale_index]['payments'][$pay_index]['ref'] = $alloc_row['reference'];
                                //$info[$sale_index]['payments'][$pay_index]['bank_ref'] = $bank_trans['bank_ref'];
                                $info[$sale_index]['payments'][$pay_index]['bank_ref'] = "";
                                $info[$sale_index]['payments'][$pay_index]['bank'] = $bank;
                                $pay_index++;
                            }
                        }
                    }

                    $tax_amount = 0;
                    $tax_items = get_trans_tax_details($trans['type'], $trans['trans_no']);
                    while ($tax_item = db_fetch($tax_items)) {
                        $tax_amount += $tax_item['amount'];
                        $info[$sale_index]['included_in_price'] = $tax_item['included_in_price'];
                    }
                    $info[$sale_index]['tax_amount'] = $tax_amount;

                    $sale_index++;
                }
            } catch (Exception $e) {
                api_error(200, $e->getMessage());
            }
        }
    } else if ($trans_type == ST_SALESORDER || $trans_type == ST_SALESQUOTE || $trans_type == ST_CUSTDELIVERY) {
        $sql = "SELECT order_no, trans_type FROM " . TB_PREF . "sales_orders WHERE trans_type=" . db_escape($trans_type);
        if (!empty($debtor_no)) {
            $sql .= " AND debtor_no=" . db_escape($debtor_no);
        }
        if (!empty($from_date) && !empty($to_date)) {
            $sql .= " AND ord_date BETWEEN '" . date2sql($from_date) . "' AND '" . date2sql($to_date) . "' ";
        }
        $sql .= " ORDER BY ord_date,order_no DESC LIMIT " . $from . ", " . RESULTS_PER_PAGE;
        $query = db_query($sql, "error");

        while ($sale = db_fetch($query, "error")) {
            try {
                $cart = null;
                $cart = new Cart($sale['trans_type'], $sale['order_no']);
                $audit_trail = get_audit_trail_last($sale['trans_type'], $sale['order_no']);
                if(!$_SESSION["wa_current_user"]->can_access("SA_SALESTRANSVIEW") && $audit_trail['user'] != $_SESSION["wa_current_user"]->user)
                    continue;
                $info[$sale_index]['trans_no'] = $sale['order_no'];
                $info[$sale_index]['trans_type'] = $sale['trans_type'];
                $info[$sale_index]['reference'] = $cart->reference;
                $info[$sale_index]['comments'] = $cart->Comments;
                $info[$sale_index]['document_date'] = $cart->document_date;
                $info[$sale_index]['payment'] = $cart->payment;
                $info[$sale_index]['due_date'] = $cart->due_date;
                $info[$sale_index]['phone'] = $cart->phone;
                $info[$sale_index]['cust_ref'] = $cart->cust_ref;
                $info[$sale_index]['delivery_address'] = $cart->delivery_address;
                $info[$sale_index]['ship_via'] = $cart->ship_via;
                $info[$sale_index]['deliver_to'] = $cart->deliver_to;
                $info[$sale_index]['delivery_date'] = $cart->due_date;
                $info[$sale_index]['location'] = $cart->Location;
                $info[$sale_index]['freight_cost'] = $cart->freight_cost;
                $info[$sale_index]['email'] = $cart->email;
                $info[$sale_index]['customer_id'] = $cart->customer_id;
                $info[$sale_index]['branch_id'] = $cart->Branch;
                $sales_type = get_sales_type($cart->sales_type);
                $info[$sale_index]['sales_type'] = $sales_type;
                $info[$sale_index]['dimension_id'] = $cart->dimension_id;
                $info[$sale_index]['dimension2_id'] = $cart->dimension2_id;
                $dimesion = get_dimension($cart->dimension_id, true);
                $info[$sale_index]['dimension'] = $dimesion ? $dimesion : null;
                $dimesion2 = get_dimension($cart->dimension2_id, true);
                $info[$sale_index]['dimension2'] = $dimesion2 ? $dimesion2 : null;
                $branch = get_api_branch($cart->Branch);
                $info[$sale_index]['branch'] = $branch;
                $info[$sale_index]['customer'] = get_api_customer($cart->customer_id);
                $payment_terms = get_payment_terms($cart->payment_terms);
                $info[$sale_index]['payment_terms'] = $payment_terms ? $payment_terms : null;
                $info[$sale_index]['outstanding'] = false;

                $item_index = 0;

                foreach ($cart->line_items as $item) {
                    $stock_item = get_api_item($item->stock_id, $branch['tax_group_id']);
                    $info[$sale_index]['line_items'][$item_index]['stock_item'] = $stock_item;
                    $info[$sale_index]['line_items'][$item_index]['id'] = $item->id;
                    $info[$sale_index]['line_items'][$item_index]['stock_id'] = $item->stock_id;
                    $info[$sale_index]['line_items'][$item_index]['qty'] = $item->quantity;
                    $info[$sale_index]['line_items'][$item_index]['qty_done'] = $item->qty_done;
                    $info[$sale_index]['line_items'][$item_index]['units'] = $item->units;
                    $info[$sale_index]['line_items'][$item_index]['price'] = $item->price;
                    $info[$sale_index]['line_items'][$item_index]['discount_percent'] = $item->discount_percent;
                    $info[$sale_index]['line_items'][$item_index]['item_description'] = $item->item_description;
                    if ($item->qty_done < $item->quantity) {
                        $info[$sale_index]['outstanding'] = true;
                    }
                    $item_index++;
                }

                $tax_amount = 0;
                $tax_items = get_trans_tax_details($trans_type, $sale['order_no']);
                while ($tax_item = db_fetch($tax_items)) {
                    $tax_amount += $tax_item['amount'];
                    $info[$sale_index]['included_in_price'] = $tax_item['included_in_price'];
                }
                $info[$sale_index]['tax_amount'] = $tax_amount;

                $sub_total = $cart->get_items_total() + $cart->freight_cost;
                $display_sub_total = price_format($sub_total);
                $display_total = $cart->get_trans_total();

                $info[$sale_index]['sub_total'] = $sub_total;
                $info[$sale_index]['display_total'] = $display_total;

                if ($Outstanding == "1" && $info[$sale_index]['outstanding']) {
                    unset($info[$sale_index]);
                } else {
                    $sale_index++;
                }
            } catch (Exception $e) {
                //api_error(404, $e->getMessage());
            }
        }
    }

    $response['items'] = $info;
    $response['incomplete_results'] = FALSE;
    $response['total_count'] = $length;
    api_success_response(json_encode($response));
}

function payments_all($from = null) {
    if ($from == null)
        $from = 0;
    $info = array();
    $sale_index = 0;
    $length = RESULTS_PER_PAGE;

    $debtor_no = !isset($_GET['debtor_no']) ? "" : $_GET['debtor_no'];
    $from_date = !isset($_GET['start_date']) ? "" : $_GET['start_date'];
    $to_date = !isset($_GET['end_date']) ? "" : $_GET['end_date'];
    $dimension = !isset($_GET['dimension']) ? "" : $_GET['dimension'];
    $Outstanding = !isset($_GET['outstanding']) ? "" : $_GET['outstanding'];


    $sql = "SELECT trans_no, type FROM " . TB_PREF . "debtor_trans WHERE  type IN (" . ST_BANKDEPOSIT . "," . ST_CUSTPAYMENT . ") ";
    if (!empty($debtor_no)) {
        $sql .= " AND debtor_no=" . db_escape($debtor_no);
    }
    if (!empty($from_date) && !empty($to_date)) {
        $sql .= " AND tran_date BETWEEN '" . date2sql($from_date) . "' AND '" . date2sql($to_date) . "' ";
    }
    if (!empty($dimension)) {
        $sql .= " AND dimension_id=" . db_escape($dimension);
    }

    $sql .= " AND (ov_amount + ov_gst + ov_freight + ov_freight_tax ) != 0 order by tran_date,trans_no DESC LIMIT " . $from . ", " . $length;
    $query = db_query($sql, "error");
    //api_error(200, var_dump($query));
    while ($sale = db_fetch($query, "error")) {
        try {
            $trans = get_customer_trans($sale['trans_no'], $sale['type']);
            //if (($Outstanding == "1" && ($trans['Total'] - $trans['alloc']) > 0) || ($Outstanding == "0" || empty($Outstanding)) ) {
            if (true) {
                $info[$sale_index]['trans_no'] = $trans['trans_no'];
                $info[$sale_index]['trans_type'] = $trans['type'];
                $info[$sale_index]['version'] = $trans['version'];
                $info[$sale_index]['customer'] = get_api_customer($trans['debtor_no']);
                $branch = get_api_branch($trans['branch_code']);
                $info[$sale_index]['branch'] = $branch;
                $info[$sale_index]['tran_date'] = $trans['tran_date'];
                $info[$sale_index]['reference'] = $trans['reference'];
                $info[$sale_index]['ov_amount'] = $trans['ov_amount'];
                $info[$sale_index]['ov_discount'] = $trans['ov_discount'];
                $info[$sale_index]['Total'] = $trans['Total'];
                $info[$sale_index]['alloc'] = $trans['alloc'];
                $info[$sale_index]['memo_'] = '';
                $info[$sale_index]['outstanding'] = false;
                $bank = get_bank_account($trans['bank_act']);
                $info[$sale_index]['bank'] = $bank;
                $sale_index++;
            }
        } catch (Exception $e) {
            api_error(200, $e->getMessage());
        }
    }


    $response['items'] = $info;
    $response['incomplete_results'] = FALSE;
    $response['total_count'] = $length;
    api_success_response(json_encode($response));
}

function payment_get($trans_no, $trans_type) {
    //api_error(200, "WE ARE HERE");
    try {
        $cart = null;
        $cart = get_customer_trans($trans_no, $trans_type);
        $info['trans_no'] = $trans_no;
        $info['trans_type'] = $trans_type;
        $info['reference'] = $cart['reference'];
        $info['memo_'] = $cart['memo_'];
        $info['tran_date'] = $cart['tran_date'];
        $info['ov_amount'] = $cart['ov_amount'];
        $info['ov_discount'] = $cart['ov_discount'];
        $info['Total'] = $cart['Total'];
        $info['alloc'] = $cart['alloc'];
        $customer = get_api_customer($cart['debtor_no']);
        $info['customer'] = $customer;
        $branch = get_api_branch($cart['branch_code']);
        $info['branch'] = $branch;
        $bank = get_bank_account($cart['bank_act']);
        $info['bank'] = $bank;
        $info['outstanding'] = false;

        $alloc_result = get_allocatable_to_cust_transactions($cart['debtor_no'], $trans_no, $trans_type);
        $info['has_allocs'] = TRUE;
        if (!$alloc_result || db_num_rows($alloc_result) == 0) {
            $info['has_allocs'] = FALSE;
        } else {
            $pay_index = 0;
            while ($alloc_row = db_fetch($alloc_result)) {
                if ($alloc_row['type'] == ST_SALESINVOICE || $alloc_row['type'] == ST_SALESORDER) {
                    $info['allocs'][$pay_index]['Total'] = $alloc_row['Total'];
                    $info['allocs'][$pay_index]['trans_no'] = $alloc_row['trans_no'];
                    $info['allocs'][$pay_index]['type'] = $alloc_row['type'];
                    $info['allocs'][$pay_index]['ref'] = $alloc_row['reference'];
                    $info['allocs'][$pay_index]['alloc'] = $alloc_row['alloc'];
                    $info['allocs'][$pay_index]['tran_date'] = $alloc_row['tran_date'];
                    $pay_index++;
                }
            }
        }
    } catch (Exception $e) {
        api_error(200, $e->getMessage());
    }

    api_success_response(json_encode($info));
}

function mpesa_unallocated_payments() {
    try {
        $sale_index = 0;
        $info = array();
        $MpesaCustomer = get_company_pref('mpesa_api_default_customer');
        $MpesaBankAccount = get_company_pref('mpesa_api_bank_account');
        $sql = "SELECT * FROM " . TB_PREF . "debtor_trans t "
                . " LEFT JOIN ".TB_PREF."bank_trans b  on b.trans_no=t.trans_no AND b.type=t.type "
                . " where (t.alloc=0 or t.alloc IS NULL) and t.type=" . ST_BANKDEPOSIT ." and t.debtor_no=". db_escape($MpesaCustomer)." "
                . " AND b.amount!=0 AND b.bank_act=". db_escape($MpesaBankAccount);
        
        $result = db_query($sql);
        while ($payment = db_fetch($result)) {
            $trans = get_customer_trans($payment['trans_no'], $payment['type']);
            $info[$sale_index]['trans_no'] = $trans['trans_no'];
            $info[$sale_index]['trans_type'] = $trans['type'];
            $info[$sale_index]['version'] = $trans['version'];
            $info[$sale_index]['customer'] = get_api_customer($trans['debtor_no']);
            $branch = get_api_branch($trans['branch_code']);
            $info[$sale_index]['branch'] = $branch;
            $info[$sale_index]['tran_date'] = $trans['tran_date'];
            $info[$sale_index]['reference'] = $trans['reference'];
            $info[$sale_index]['ov_amount'] = $trans['ov_amount'];
            $info[$sale_index]['ov_discount'] = $trans['ov_discount'];
            $info[$sale_index]['Total'] = $trans['Total'];
            $info[$sale_index]['alloc'] = $trans['alloc'];
            $info[$sale_index]['memo_'] = '';
            $info[$sale_index]['outstanding'] = false;
            $bank = get_bank_account($trans['bank_act']);
            $info[$sale_index]['bank'] = $bank;
            $sale_index++;
        }
    } catch (Exception $e) {
        api_error(200, $e->getMessage());
    }

    $response['items'] = $info;
    $response['incomplete_results'] = FALSE;
    $response['total_count'] = 1000;
    api_success_response(json_encode($response));
}

function sales_get($trans_no, $trans_type) {
    //api_error(200, "WE ARE HERE");
    try {
        $cart = null;
        $cart = new Cart($trans_type, $trans_no);
        $info['trans_no'] = $trans_no;
        $info['trans_type'] = $trans_type;
        $info['reference'] = $cart->reference;
        $info['Comments'] = $cart->Comments;
        $info['document_date'] = $cart->document_date;
        $info['payment'] = $cart->payment;
        $payment_terms = get_payment_terms($cart->payment);
        $info['payment_terms'] = $payment_terms ? $payment_terms : null;
        $info['due_date'] = $cart->due_date;
        $info['phone'] = $cart->phone;
        $info['cust_ref'] = $cart->cust_ref;
        $info['delivery_address'] = $cart->delivery_address;
        $info['ship_via'] = $cart->ship_via;
        $info['deliver_to'] = $cart->deliver_to;
        $info['delivery_date'] = $cart->due_date;
        $location = get_inventory_location($cart->Location);
        $info['Location'] = $location ? $location : null;
        $info['freight_cost'] = $cart->freight_cost;
        $info['email'] = $cart->email;
        $customer = get_api_customer($cart->customer_id);
        $info['customer'] = $customer;
        $branch = get_api_branch($cart->Branch);
        $info['branch'] = $branch;
        $sales_type = get_sales_type($cart->sales_type);
        $info['sales_type'] = $sales_type ? $sales_type : null;
        $dimension_1 = get_dimension($cart->dimension_id, true);
        $info['dimension'] = $dimension_1 ? $dimension_1 : null;
        $dimension_2 = get_dimension($cart->dimension2_id, true);
        $info['dimension2'] = $dimension_2 ? $dimension_2 : null;
        $info['outstanding'] = false;

        $item_index = 0;
        foreach ($cart->line_items as $item) {
            $info['line_items'][$item_index]['stock_item'] = get_api_item($item->stock_id, $branch['tax_group_id']);
            $info['line_items'][$item_index]['id'] = $item->id;
            $info['line_items'][$item_index]['stock_id'] = $item->stock_id;
            $info['line_items'][$item_index]['qty'] = $item->quantity;
            $info['line_items'][$item_index]['qty_done'] = $item->qty_done;
            $info['line_items'][$item_index]['units'] = $item->units;
            $info['line_items'][$item_index]['price'] = $item->price;
            $info['line_items'][$item_index]['discount_percent'] = $item->discount_percent;
            $info['line_items'][$item_index]['item_description'] = $item->item_description;
            if ($item->qty_done < $item->quantity) {
                $info['outstanding'] = true;
            }
            $item_index++;
        }

        $alloc_result = get_allocatable_from_cust_transactions($cart->customer_id, $trans_no, $trans_type);
        $info['has_payments'] = TRUE;
        if (!$alloc_result || db_num_rows($alloc_result) == 0) {
            $info['has_payments'] = FALSE;
        } else {
            $pay_index = 0;
            while ($alloc_row = db_fetch($alloc_result)) {
                if ($alloc_row['type'] == ST_CUSTPAYMENT) {
                    $bank_trans = db_fetch(get_bank_trans($alloc_row['type'], $alloc_row['trans_no']));
                    $bank = get_bank_account($bank_trans['bank_act']);
                    $info['payments'][$pay_index]['Total'] = $alloc_row['Total'];
                    $info['payments'][$pay_index]['amt'] = $alloc_row['amt'];
                    $info['payments'][$pay_index]['date'] = $alloc_row['tran_date'];
                    $info['payments'][$pay_index]['ref'] = $alloc_row['reference'];
                    //$info['payments'][$pay_index]['bank_ref'] = $bank_trans['bank_ref'];
                    $info['payments'][$pay_index]['bank_ref'] = "";
                    $info['payments'][$pay_index]['bank'] = $bank;
                    $pay_index++;
                }
            }
        }
        $tax_amount = 0;
        $tax_items = get_trans_tax_details($trans_type, $trans_no);
        while ($tax_item = db_fetch($tax_items)) {
            $tax_amount += $tax_item['amount'];
            $info['included_in_price'] = $tax_item['included_in_price'];
        }
        $info['tax_amount'] = $tax_amount;

        $sub_total = $cart->get_items_total() + $cart->freight_cost;
        $display_sub_total = price_format($sub_total);
        $display_total = $cart->get_trans_total();

        $info['sub_total'] = $sub_total;
        $info['display_total'] = $display_total;
    } catch (Exception $e) {
        api_error(200, $e->getMessage());
    }

    api_success_response(json_encode($info));
}

function sales_add() {
    global $Refs;
    $app = \Slim\Slim::getInstance('SASYS');
    $req = $app->request();
    $info = $req->post();

    $trans_no = 0;
    if (!empty($info['trans_no'])) {
        $trans_no = $info['trans_no'];
    }
    $cart = new Cart($info['trans_type'], $trans_no);
    if ($trans_no == 0) {
        $ref = $Refs->get_next($info['trans_type'], null, array('date' => Today()));
        $cart->reference = $ref;
    }
    $info['reference'] = $cart->reference;
    $cart->Comments = $info['Comments'];
    $cart->document_date = $info['document_date'];

    $newpayment = false;
    if (isset($info['payment']) && ($cart->payment != $info['payment'])) {
        $cart->payment = $info['payment'];
        $cart->payment_terms = get_payment_terms($info['payment']);
        $newpayment = true;
    }

    if ($cart->payment_terms['cash_sale']) {
        if ($newpayment) {
            $cart->due_date = $cart->document_date;
            $cart->phone = $cart->cust_ref = $cart->delivery_address = '';
            $cart->ship_via = 0;
            $cart->deliver_to = '';
        }
    } else {
        $cart->due_date = $info['due_date'];
        $cart->cust_ref = $info['cust_ref'];
        $cart->deliver_to = $info['deliver_to'];
        $cart->delivery_address = $info['delivery_address'];
        $cart->phone = $info['phone'];
        $cart->ship_via = 0;
    }

    if ($trans_no == 0 || ($cart->trans_type != ST_SALESINVOICE)) {
        $cart->Location = $info['Location']['loc_code'];
    }
    $cart->freight_cost = input_num('freight_cost');

    if (isset($info['email'])) {
        $cart->email = $info['email'];
    } else {
        $cart->email = '';
    }

    $cart->customer_id = $info['customer']['debtor_no'];
    $cart->Branch = $info['branch']['branch_code'];
    $cart->sales_type = $info['sales_type']['id'];

    if ($cart->trans_type != ST_SALESORDER && $cart->trans_type != ST_SALESQUOTE) {
        $cart->dimension_id = !empty($info['dimension']['id']) ? $info['dimension']['id'] : "0";
        $cart->dimension2_id = !empty($info['dimension2']['id']) ? $info['dimension2']['id'] : "0";
    }

    $can_process = can_process_line_items($info);
    if ($can_process['passed'] == false) {
        api_error(200, $can_process['message']);
        return;
    }

    if (($cart->trans_type != ST_SALESINVOICE && $cart->trans_type != ST_CUSTDELIVERY) || $trans_no == 0) {
        $cart->line_items = array();
        foreach ($info['line_items'] as $item) {
            set_error_handler("cart_error_handler");
            add_to_order($cart, $item['stock_item']['stock_id'], $item['qty'], $item['price'], $item['discount_percent'], $item['item_description']);
            restore_error_handler();
        }
    }

    $can_process = can_process_order($info, $cart);

    if ($can_process['passed'] == false) {
        //trigger_error(var_export($can_process, true));
        api_error(200, $can_process['message']);
        return;
    }

    $result = $cart->write(1);

    if ($result == -1) {
        //return array("passed" => false, "message" => _("The entered reference is already in use."));
        api_error(200, 'Could Not Save to Database');
        return;
    }

    switch ($cart->trans_type) {
        case ST_SALESQUOTE:
            $feeback_response = (sprintf(_("Quotation # %d has been entered."), key($cart->trans_no)));
            break;
        case ST_SALESORDER:
            $feeback_response = (sprintf(_("Order # %d has been entered."), key($cart->trans_no)));
            break;
        case ST_SALESINVOICE:
            $feeback_response = sprintf(_("Invoice # %d has been entered."), key($cart->trans_no));
            break;
        case ST_CUSTCREDIT:
            $feeback_response = sprintf(_("Credit Note # %d has been processed."), key($cart->trans_no));
            break;
        case ST_CUSTDELIVERY:
            $feeback_response = (sprintf(_("Delivery # %d has been entered."), key($cart->trans_no)));
            break;
    }

    $response['msg'] = $feeback_response;
    $response['reference'] = $cart->reference;
    $response['type_no'] = $result;
    api_success_response(json_encode($response));
}

function order2invoice() {
    global $Refs;
    $app = \Slim\Slim::getInstance('SASYS');
    $req = $app->request();
    $info = $req->post();

    $trans_no = 0;
    if (!empty($info['trans_no'])) {
        $trans_no = $info['trans_no'];
    }
    $cart = new Cart(ST_SALESORDER, $trans_no, true);
    $cart->Comments = $info['Comments'];
    $cart->document_date = $info['document_date'];

    $newpayment = false;
    if (isset($info['payment']) && ($cart->payment != $info['payment'])) {
        $cart->payment = $info['payment'];
        $cart->payment_terms = get_payment_terms($info['payment']);
        $newpayment = true;
    }

    if ($cart->payment_terms['cash_sale']) {
        if ($newpayment) {
            $cart->due_date = $cart->document_date;
            $cart->phone = $cart->cust_ref = $cart->delivery_address = '';
            $cart->ship_via = 0;
            $cart->deliver_to = '';
        }
    } else {
        $cart->due_date = $info['due_date'];
        $cart->ship_via = 0;
    }

    $cart->update_payments();
    $cart->freight_cost = 0;
    $cart->dimension_id = isset($info['dimension']) ? $info['dimension']['id'] : 0;
    $cart->dimension2_id = isset($info['dimension2']) ? $info['dimension2']['id'] : 0;

    $can_process = check_quantities($cart, $info);
    if (!$can_process) {
        api_error(200, _("Selected quantity cannot be less than quantity credited nor more than quantity not invoiced yet."));
        return;
    }

    $can_process = check_data($cart);

    if ($can_process['passed'] == false) {
        //trigger_error(var_export($can_process, true));
        api_error(200, $can_process['message']);
        return;
    }

    $delivery = $cart->write();
    if ($delivery == -1) {
        api_error(200, 'Could Not Save to Database');
        return;
    }

    $inv_cart = new Cart(ST_CUSTDELIVERY, $delivery, true);
    $inv_cart->document_date = $cart->document_date;
    $inv_cart->update_payments();
    $invoice_no = $inv_cart->write();
    if ($invoice_no == -1) {
        api_error(200, 'Could Not Save to Database');
        return;
    }

    $feeback_response = sprintf(_("Invoice # %d has been entered."), key($cart->trans_no));
    $response['msg'] = $feeback_response;
    $response['reference'] = $inv_cart->reference;
    $response['type_no'] = $invoice_no;
    api_success_response(json_encode($response));
}

function pos_add() {
    global $Refs;
    $app = \Slim\Slim::getInstance('SASYS');
    $req = $app->request();
    $info = $req->post();

    $pos = get_sales_point($_SESSION["wa_current_user"]->pos);
    $ref = $Refs->get_next($info['trans_type'], null, array('date' => Today()));
    $info['ref'] = $ref;
    $info['delivery_date'] = $info['order_date'];
    $info['cust_ref'] = "";
    $info['location'] = $pos['pos_location'];

    $cart = null;
    $cart = new Cart($info['trans_type'], $info['trans_no']);
    $cart->reference = $info['ref'];
    $cart->Comments = $info['comments'];
    $cart->document_date = $info['order_date'];

    if (isset($info['payment']) && ($cart->payment != $info['payment'])) {
        $cart->payment = $info['payment'];
        $cart->payment_terms = get_payment_terms($info['payment']);
        $newpayment = true;
    }

    if ($cart->payment_terms['cash_sale']) {
        if ($newpayment) {
            $cart->due_date = $cart->document_date;
            $cart->phone = $cart->cust_ref = $cart->delivery_address = '';
            $cart->ship_via = 0;
            $cart->deliver_to = '';
        }
    } else {
        $cart->due_date = $info['delivery_date'];
        $cart->cust_ref = $info['cust_ref'];
        $cart->deliver_to = $info['deliver_to'];
        $cart->delivery_address = $info['delivery_address'];
        $cart->phone = $info['phone'];
        $cart->ship_via = $info['ship_via'];
    }

    $cart->Location = $pos['pos_location'];
    $cart->freight_cost = input_num('freight_cost');

    if (isset($info['email'])) {
        $cart->email = $info['email'];
    } else {
        $cart->email = '';
    }

    $cart->customer_id = $info['customer_id'];
    $cart->Branch = $info['branch_id'];
    $cart->sales_type = $info['sales_type'];

    if ($cart->trans_type != ST_SALESORDER && $cart->trans_type != ST_SALESQUOTE) { // 2008-11-12 Joe Hunt
        $cart->dimension_id = $info['dimension_id'];
        $cart->dimension2_id = $info['dimension2_id'];
    }

    $can_process = can_process_items($info);
    if ($can_process['passed'] == false) {
        //trigger_error(var_export($can_process, true));
        api_error(200, $can_process['message']);
        return;
    }

    foreach ($info['items'] as $item) {
        set_error_handler("cart_error_handler");
        add_to_order($cart, $item['stock_id'], $item['qty'], $item['price'], $item['discount'], $item['description'], $item['is_taxed']);
        restore_error_handler();
    }

    $can_process = can_process($info, $cart);
    if ($can_process['passed'] == false) {
        //trigger_error(var_export($can_process, true));
        api_error(200, $can_process['message']);
        return;
    }

    //void_sales_invoice($type, $type_no);
    //void_customer_trans_details($cart->trans_type, $cart->trans_no);
    $result = $cart->write(1);
    {
//        $invoice_no = $result;
//        $pmtno = write_customer_payment(0, $cart->customer_id, $cart->Branch, $info['bank'], $cart->document_date, $Refs->get_next(ST_CUSTPAYMENT, null, array('customer' => $cart->customer_id,
//                    'branch' => $cart->Branch, 'date' => $cart->document_date)), $cart->get_trans_total(),0, _('Termina invoice') . ' ' . $invoice_no);
//        add_cust_allocation($cart->get_trans_total(), ST_CUSTPAYMENT, $pmtno, ST_SALESINVOICE, $invoice_no, $cart->customer_id, $cart->document_date);
//
//        update_debtor_trans_allocation(ST_SALESINVOICE, $invoice_no, $cart->customer_id);
//        update_debtor_trans_allocation(ST_CUSTPAYMENT, $pmtno, $cart->customer_id);
    }


    if ($result == -1) {
        //return array("passed" => false, "message" => _("The entered reference is already in use."));
        api_error(200, 'Could Not Save to Database');
        return;
    }

    $feeback_response = sprintf(_("Invoice # %d has been entered."), key($cart->trans_no));
    $response['msg'] = $feeback_response;
    $response['reference'] = $cart->reference;
    $response['type_no'] = $result;
    api_success_response(json_encode($response));

    //api_success_response(_("Ok"));
}

function pos_pay() {
    global $Refs;
    $app = \Slim\Slim::getInstance('SASYS');
    $req = $app->request();
    $info = $req->post();

    $pos = get_sales_point($_SESSION["wa_current_user"]->pos);
    $ref = $Refs->get_next(ST_CUSTPAYMENT, null, array('date' => Today()));
    $cart = null;
    $cart = new Cart($info['trans_type'], 0);
    $cart->document_date = $info['order_date'];
    $cart->customer_id = $info['customer_id'];
    $cart->Branch = $info['branch_id'];

    $can_process = can_process_pay($info, $cart);
    if ($can_process['passed'] == false) {
        //trigger_error(var_export($can_process, true));
        api_error(200, $can_process['message']);
        return;
    } {
        $invoice_no = $info['type_no'];
        $pmtno = write_customer_payment(0, $cart->customer_id, $cart->Branch, $info['bank'], $cart->document_date, $Refs->get_next(ST_CUSTPAYMENT, null, array('customer' => $cart->customer_id,
                    'branch' => $cart->Branch, 'date' => $cart->document_date)), $info['payment_amount'], 0, _('Termina invoice') . ' ' . $invoice_no, 0, 0, 0);
        add_cust_allocation($info['payment_amount'], ST_CUSTPAYMENT, $pmtno, ST_SALESINVOICE, $invoice_no, $cart->customer_id, $cart->document_date);

        update_debtor_trans_allocation(ST_SALESINVOICE, $invoice_no, $cart->customer_id);
        update_debtor_trans_allocation(ST_CUSTPAYMENT, $pmtno, $cart->customer_id);
    }


    if ($pmtno == -1) {
        //return array("passed" => false, "message" => _("The entered reference is already in use."));
        api_error(200, 'Could Not Save to Database');
        return;
    }

    $feeback_response = sprintf(_("Payment # %d has been entered."), $pmtno);
    $response['msg'] = $feeback_response;
    $response['ref'] = $cart->reference;
    $response['type_no'] = $pmtno;
    api_success_response(json_encode($response));

    //api_success_response(_("Ok"));
}

function sales_edit($trans_no, $trans_type) {
    $app = \Slim\Slim::getInstance('SASYS');
    $req = $app->request();
    $info = $req->put();

    $cart = null;
    $cart = new Cart($trans_type, $trans_no);
    if (isset($info["ref"]))
        $cart->reference = $info['ref'];
    if (isset($info["comments"]))
        $cart->Comments = $info['comments'];
    if (isset($info["order_date"]))
        $cart->document_date = $info['order_date'];

    if (isset($info['payment']) && ($cart->payment != $info['payment'])) {
        if (isset($info["payment"]))
            $cart->payment = $info['payment'];
        if (isset($info["payment"]))
            $cart->payment_terms = get_payment_terms($info['payment']);
        //$newpayment						= true;
    }

    if ($cart->payment_terms['cash_sale']) {
        /* if ($newpayment) {
          $cart->due_date		= $cart->document_date;
          $cart->phone			= $cart->cust_ref = $cart->delivery_address = '';
          $cart->ship_via		= 0;
          $cart->deliver_to	= '';
          } */
    } else {
        if (isset($info["delivery_date"]))
            $cart->due_date = $info['delivery_date'];
        if (isset($info["cust_ref"]))
            $cart->cust_ref = $info['cust_ref'];
        if (isset($info["deliver_to"]))
            $cart->deliver_to = $info['deliver_to'];
        if (isset($info["delivery_address"]))
            $cart->delivery_address = $info['delivery_address'];
        if (isset($info["phone"]))
            $cart->phone = $info['phone'];
        if (isset($info["ship_via"]))
            $cart->ship_via = $info['ship_via'];
    }

    if (isset($info["location"]))
        $cart->Location = $info['location'];
    if (isset($info["freight_cost"]))
        $cart->freight_cost = input_num('freight_cost');

    if (isset($info['email'])) {
        $cart->email = $info['email'];
    } else {
        //$cart->email = '';
    }

    if (isset($info["customer_id"]))
        $cart->customer_id = $info['customer_id'];
    if (isset($info["branch_id"]))
        $cart->Branch = $info['branch_id'];
    if (isset($info["sales_type"]))
        $cart->sales_type = $info['sales_type'];

    if ($cart->trans_type != ST_SALESORDER && $cart->trans_type != ST_SALESQUOTE) { // 2008-11-12 Joe Hunt
        if (isset($info["dimension_id"]))
            $cart->dimension_id = $info['dimension_id'];
        if (isset($info["dimension2_id"]))
            $cart->dimension2_id = $info['dimension2_id'];
    }

    if (isset($info["items"])) {
        foreach ($info['items'] as $item) {
            add_to_order($cart, $item['stock_id'], $item['qty'], $item['price'], $item['discount'], $item['description'], $item['is_taxed']);
        }
    }

    $can_process = can_process($info, $cart);

    if ($can_process == false) {
        api_error(412, $can_process['message']);
    }

    $result = $cart->write(1);

    if ($result == -1) {
        //return array("passed" => false, "message" => _("The entered reference is already in use."));
        api_error(500, _('Could Not Save to Database'));
    }

    switch ($cart->trans_type) {
        case ST_SALESQUOTE:
            api_success_response(sprintf(_("Quotation # %d has been updated."), $cart->trans_no));
            return;
            break;
        case ST_SALESORDER:
            api_success_response(sprintf(_("Order # %d has been updated."), $cart->trans_no));
            return;
            break;
        case ST_SALESINVOICE:
            api_success_response(sprintf(_("Invoice # %d has been updated."), $cart->trans_no));
            return;
            break;
        case ST_CUSTCREDIT:
            api_success_response(sprintf(_("Credit # %d has been updated."), $cart->trans_no));
            return;
            break;
        case ST_CUSTDELIVERY:
            api_success_response(sprintf(_("Delivery # %d has been updated."), $cart->trans_no));
            return;
            break;
    }

    api_success_response(_("Ok"));
}

function sales_cancel($trans_type, $trans_no) {
    if ($trans_type == ST_CUSTDELIVERY && !exists_customer_trans($trans_type, $trans_no)) {
        api_error(200, "Sales delivery # " . $trans_no . " does not exist in the system.");
        return;
    } else if ($trans_type == ST_SALESINVOICE && !exists_customer_trans($trans_type, $trans_no)) {
        api_error(200, "Sales invoice # " . $trans_no . " does not exist in the system.");
        return;
    }

    $void_entry = get_voided_entry($trans_type, $trans_no);
    if ($void_entry != null) {
        api_error(200, _("The selected transaction has already been voided."));
        return;
    }

    if ($trans_type == ST_SALESQUOTE) {
        delete_sales_order($trans_no, $trans_type);
        $msg = false;
    } else if ($trans_type == ST_SALESORDER) {
        if (sales_order_has_deliveries($trans_no)) {
            close_sales_order($trans_no);
            $response['msg'] = _("Undelivered part of order has been cancelled as requested.");
            api_success_response(json_encode($response));
            return;
        } else {
            delete_sales_order($trans_no, $trans_type);
            $msg = false;
        }
    } else {
        $msg = void_transaction($trans_type, $trans_no, date('d/m/Y'), "API deleted");
    }

    if (!$msg) {
        $response['msg'] = "Transaction was voided successfully";
        api_success_response(json_encode($response));
    } else {
        api_error(200, $msg);
    }
}

function can_process_pay($info, $cart) {
    global $Refs;
    if (!$info['customer_id']) {
        return array("passed" => false, "message" => _("There is no customer selected."));
    }

    if (!$info['branch_id']) {
        return array("passed" => false, "message" => _("This customer has no branch defined."));
    }

    if (!is_date($info['order_date'])) {
        return array("passed" => false, "message" => _("The entered date is invalid."));
    }

    if (!is_numeric($info['payment_amount'])) {
        return array("passed" => false, "message" => _("The entered Amount is invalid."));
    }

    if (empty($info['bank'])) {
        return array("passed" => false, "message" => _("The entered Bank is invalid."));
    }

    if (empty($info['payment_mode'])) {
        //return array("passed" => false, "message" => _("The entered Payment mode is invalid."));
    }
    return array('passed' => true);
}

function can_process($info, $cart) {
    global $Refs;

    if (!$info['customer_id']) {
        return array("passed" => false, "message" => _("There is no customer selected."));
    }

    if (!$info['branch_id']) {
        return array("passed" => false, "message" => _("This customer has no branch defined."));
    }

    if (!is_date($info['order_date'])) {
        return array("passed" => false, "message" => _("The entered date is invalid."));
    }

    if ($cart->trans_type != ST_SALESORDER && $cart->trans_type != ST_SALESQUOTE && !is_date_in_fiscalyear($info['order_date'])) {
        return array("passed" => false, "message" => _("The entered date is not in fiscal year"));
    }

    if (count($cart->line_items) == 0) {
        return array("passed" => false, "message" => _("You must enter at least one non empty item line."));
    }

    if ($cart->payment_terms['cash_sale'] == 0) {
        if (strlen($info['deliver_to']) <= 1) {
            return array("passed" => false, "message" => _("You must enter the person or company to whom delivery should be made to."));
        }

        if ($cart->trans_type != ST_SALESQUOTE && strlen($info['delivery_address']) <= 1) {
            return array("passed" => false, "message" => _("You should enter the street address in the box provided. Orders cannot be accepted without a valid street address."));
        }

        if ($info['freight_cost'] == "") {
            $info['freight_cost'] = price_format(0);
        }

        /* if (!check_num('freight_cost', 0)) {
          return array("passed" => false, "message" => _("The shipping cost entered is expected to be numeric."));
          } */

        if (!is_date($info['delivery_date'])) {
            if ($cart->trans_type == ST_SALESQUOTE) {
                return array("passed" => false, "message" => _("The Valid date is invalid."));
            } else {
                return array("passed" => false, "message" => _("The delivery date is invalid."));
            }
        }

        if (date1_greater_date2($info['order_date'], $info['delivery_date'])) {
            if ($cart->trans_type == ST_SALESQUOTE) {
                return array("passed" => false, "message" => _("The requested valid date is before the date of the quotation."));
            } else {
                return array("passed" => false, "message" => _("The requested delivery date is before the date of the order."));
            }
        }
    } else {
        if (!db_has_cash_accounts()) {
            return array("passed" => false, "message" => _("You need to define a cash account for your Sales Point."));
        }
    }

    if (!$Refs->is_valid($info['ref'], $cart->trans_type)) {
        return array("passed" => false, "message" => _("You must enter a valid reference."));
    }

    if (!db_has_currency_rates($cart->customer_currency, $info['order_date'])) {
        return array("passed" => false, "message" => _("Currency rates are not defined for this date."));
        ;
    }

    if ($cart->get_items_total() < 0) {
        return array("passed" => false, "message" => _("Invoice total amount cannot be less than zero."));
    }

    return array('passed' => true);
}

function can_process_order($info, $cart) {
    global $Refs;

    if (!$info['customer']['debtor_no']) {
        return array("passed" => false, "message" => _("There is no customer selected."));
    }

    if (!$info['branch']['branch_code']) {
        return array("passed" => false, "message" => _("This customer has no branch defined."));
    }

    if (!is_date($info['document_date'])) {
        return array("passed" => false, "message" => _("The entered date is invalid."));
    }

    if ($cart->trans_type != ST_SALESORDER && $cart->trans_type != ST_SALESQUOTE && !is_date_in_fiscalyear($info['document_date'])) {
        return array("passed" => false, "message" => _("The entered date is not in fiscal year"));
    }

    if (count($cart->line_items) == 0) {
        return array("passed" => false, "message" => _("You must enter at least one non empty item line."));
    }

    if ($cart->payment_terms['cash_sale'] == 0) {
        if (strlen($info['deliver_to']) <= 1) {
            return array("passed" => false, "message" => _("You must enter the person or company to whom delivery should be made to."));
        }

        if ($cart->trans_type != ST_SALESQUOTE && strlen($info['delivery_address']) <= 1) {
            return array("passed" => false, "message" => _("You should enter the street address in the box provided. Orders cannot be accepted without a valid street address."));
        }

        if ($info['freight_cost'] == "") {
            $info['freight_cost'] = price_format(0);
        }

        /* if (!check_num('freight_cost', 0)) {
          return array("passed" => false, "message" => _("The shipping cost entered is expected to be numeric."));
          } */

        if (!is_date($info['due_date'])) {
            if ($cart->trans_type == ST_SALESQUOTE) {
                return array("passed" => false, "message" => _("The Valid date is invalid."));
            } else {
                return array("passed" => false, "message" => _("The delivery date is invalid."));
            }
        }

        if (date1_greater_date2($info['document_date'], $info['due_date'])) {
            if ($cart->trans_type == ST_SALESQUOTE) {
                return array("passed" => false, "message" => _("The requested valid date is before the date of the quotation."));
            } else {
                return array("passed" => false, "message" => _("The requested delivery date is before the date of the order."));
            }
        }
    } else {
        if (!db_has_cash_accounts()) {
            return array("passed" => false, "message" => _("You need to define a cash account for your Sales Point."));
        }
    }

    if (!$Refs->is_valid($info['reference'], $cart->trans_type) && empty($info['trans_no'])) {
        return array("passed" => false, "message" => _("You must enter a valid reference."));
    }

    if (!db_has_currency_rates($cart->customer_currency, $info['document_date'])) {
        return false;
    }

    if ($cart->get_items_total() < 0) {
        return array("passed" => false, "message" => _("Invoice total amount cannot be less than zero."));
    }

    return array('passed' => true);
}

function check_data($cart) {
    global $Refs;

    $prepaid = $cart->is_prepaid();

    if (!isset($cart->document_date) || !is_date($cart->document_date)) {
        return array("passed" => false, "message" => _("The entered invoice date is invalid."));
    }

    if (!is_date_in_fiscalyear($cart->document_date)) {
        return array("passed" => false, "message" => _("The entered date is out of fiscal year or is closed for further data entry."));
    }


    if (!$prepaid && (!isset($cart->due_date) || !is_date($cart->due_date))) {
        return array("passed" => false, "message" => _("The entered invoice due date is invalid."));
    }

    if ($cart->trans_no == 0) {
        if (!$Refs->is_valid($cart->reference, ST_SALESINVOICE)) {
            return array("passed" => false, "message" => _("You must enter a reference."));
        }
    }

    if (!$prepaid) {
        if ($cart->has_items_dispatch() == 0 && $cart->freight_cost == 0) {
            return array("passed" => false, "message" => _("There are no item quantities on this invoice."));
        }
    } else {
        if (($cart->payment_terms['days_before_due'] == -1) && !count($cart->prepayments)) {
            return array("passed" => false, "message" => _("There is no non-invoiced payments for this order. If you want to issue final invoice, select delayed or cash payment terms."));
        }
    }

    return array("passed" => true);
}

function can_process_items($info) {
    global $SysPrefs;
    $stock_ids = array();
    $duplicate_items = array();
    $negative_stocks = array();
    $test = true;
    foreach ($info['items'] as $item) {
        if (in_array($item['stock_id'], $stock_ids)) {
            $duplicate_items[] = $item['description'];
            $test = false;
        }

        //api_error(200, "sys:".var_dump($SysPrefs->allow_negative_stock())." -- ".$item['stock_id']." -- ".$item['qty']." -- ".$info['location']." -- ".$info['order_date']."  QOH : ".get_qoh_on_date($item['stock_id'], $info['location'], $info['order_date'])." check : ".  var_dump(check_negative_stock($item['stock_id'], $item['qty'], $info['location'], $info['order_date'])));
        if (!$SysPrefs->allow_negative_stock() && check_negative_stock($item['stock_id'], $item['qty'], $info['location'], $info['order_date'])) {
            $negative_stocks = $item['description'] . " Qty On Hand = " . get_qoh_on_date($item['stock_id'], $info['location'], $info['order_date']) . "  ";
            $test = false;
        }
        $stock_ids[] = $item['stock_id'];
    }

    $msg = "";
    if (count($duplicate_items)) {
        $msg .= "Please remove all duplicates for these items : " . join(" , ", $duplicate_items) . " ";
    }

    if (count($negative_stocks)) {
        $msg .= " Insuficient stock for these Items : " . join(" , ", $negative_stocks);
    }
    return array("passed" => $test, "message" => $msg);
}

function can_process_line_items($info) {
    global $SysPrefs;
    $stock_ids = array();
    $duplicate_items = array();
    $negative_stocks = array();
    $test = true;
    foreach ($info['line_items'] as $item) {
        if (in_array($item['stock_item']['stock_id'], $stock_ids)) {
            $duplicate_items[] = $item['item_description'];
            $test = false;
        }

        //api_error(200, "sys:".var_dump($SysPrefs->allow_negative_stock())." -- ".$item['stock_item']['stock_id']." -- ".$item['qty']." -- ".$info['Location']['loc_code']." -- ".$info['document_date']."  QOH : ".get_qoh_on_date($item['stock_item']['stock_id'], $info['Location']['loc_code'], $info['document_date'])." check : ".  var_dump(check_negative_stock($item['stock_item']['stock_id'], $item['qty'], $info['Location']['loc_code'], $info['document_date'])));
        if (!$SysPrefs->allow_negative_stock() && check_negative_stock($item['stock_item']['stock_id'], -$item['qty'], $info['Location']['loc_code'], $info['document_date'])) {
            $negative_stocks[] = $item['item_description'] . " Qty On Hand = " . get_qoh_on_date($item['stock_item']['stock_id'], $info['Location']['loc_code'], $info['document_date']) . "  ";
            $test = false;
        }
        $stock_ids[] = $item['stock_item']['stock_id'];
    }

    $msg = "";
    if (count($duplicate_items)) {
        $msg .= "Please remove all duplicates for these items : " . join(" , ", $duplicate_items) . " ";
    }

    if (count($negative_stocks)) {
        $msg .= " Insuficient stock for these Items : " . join(" , ", $negative_stocks);
    }
    return array("passed" => $test, "message" => $msg);
}

function check_quantities(&$cart, $info) {
    $ok = 1;
    foreach ($cart->line_items as $line_no => $itm) {
        $_POST['Line' . $line_no] = $info['line_items'][$line_no]['qty'];
        if (isset($_POST['Line' . $line_no])) {
            if ($cart->trans_no) {
                $min = $itm->qty_done;
                $max = $itm->quantity;
            } else {
                $min = 0;
                $max = $itm->quantity - $itm->qty_done;
            }
            if (check_num('Line' . $line_no, $min, $max)) {
                $cart->line_items[$line_no]->qty_dispatched = input_num('Line' . $line_no);
            } else {
                $ok = 0;
            }
        }

        if (isset($info['line_items'][$line_no]['item_description'])) {
            $line_desc = $info['line_items'][$line_no]['item_description'];
            if (strlen($line_desc) > 0) {
                $cart->line_items[$line_no]->item_description = $line_desc;
            }
        }
    }
    return $ok;
}

function cart_error_handler($errno, $errstr) {
    if ($errno != E_USER_WARNING) {
        die($errstr);
    }
}

?>