diff --git a/config_api.php b/config_api.php index 105aa81..752e804 100644 --- a/config_api.php +++ b/config_api.php @@ -6,6 +6,6 @@ $rootPath = realpath(__DIR__ . '/../..'); } -define('API_ROOT', $rootPath . '/modules/api'); +define('API_ROOT', $rootPath . '/modules/FrontAccountingSimpleAPI'); //change to api if your api module directory name is api define('FA_ROOT', $rootPath); diff --git a/custom_sales_includes/db/extended_write_sales_invoice.inc b/custom_sales_includes/db/extended_write_sales_invoice.inc new file mode 100644 index 0000000..f578a50 --- /dev/null +++ b/custom_sales_includes/db/extended_write_sales_invoice.inc @@ -0,0 +1,224 @@ +trans_no; + if (is_array($trans_no)) + $trans_no = key($trans_no); + + $date_ = $invoice->document_date; + $charge_shipping =$invoice->freight_cost; + + begin_transaction(); + + hook_db_prewrite($invoice, ST_SALESINVOICE); + $company_data = get_company_prefs(); + + $branch_data = get_branch_accounts($invoice->Branch); + + $customer = get_customer($invoice->customer_id); + + add_new_exchange_rate($customer['curr_code'], $date_, $invoice->ex_rate); + + // offer price values without freight costs + $items_total = $invoice->get_items_total_dispatch(); + $freight_tax = $invoice->get_shipping_tax(); + + if (!$invoice->is_prepaid()) + update_customer_trans_version(get_parent_type(ST_SALESINVOICE), $invoice->src_docs); + elseif (count($invoice->prepayments)) { // partial invoice + $last_payment = end($invoice->prepayments); + $gl_date = sql2date($last_payment['tran_date']); + } else { // final invoice + $gl_date = $invoice->document_date; + } + + $ov_gst = 0; + $taxes = $invoice->get_taxes(); // all taxes with freight_tax + $dec = user_price_dec(); + foreach ($taxes as $taxitem) { + $taxitem['Value'] = round2($taxitem['Value'], $dec); + $ov_gst += $taxitem['Value']; + } + + if($invoice->tax_included==0) { + $items_added_tax = $ov_gst-$freight_tax; + $freight_added_tax = $freight_tax; + } else { + $items_added_tax = 0; + $freight_added_tax = 0; + } + + /* Insert/update the debtor_trans */ + $sales_order = $invoice->order_no; + if (is_array($sales_order)) + $sales_order = $sales_order[0]; // assume all crucial SO data are same for every delivery + + if ($trans_no) { + $allocs = get_payments_for($trans_no, ST_SALESINVOICE, $invoice->customer_id); + delete_comments(ST_SALESINVOICE, $trans_no); + void_gl_trans(ST_SALESINVOICE, $trans_no, true); + void_trans_tax_details(ST_SALESINVOICE, $trans_no); + } else + $allocs = get_payments_for($invoice->order_no, ST_SALESORDER, $invoice->customer_id); + + if ($invoice->is_prepaid()) // selected prepayment is already in cart + { + $allocs = $invoice->prepayments; + // values posted are reduced by prepaid_factor + $prepaid_factor = $invoice->prep_amount/$invoice->get_trans_total(); + } else { + $prepaid_factor = 1; + } + + // write_customer_trans have to be called after optional void_cust_allocations above + $invoice_no = write_customer_trans(ST_SALESINVOICE, $trans_no, $invoice->customer_id, + $invoice->Branch, $date_, $invoice->reference, $items_total, 0, + $items_added_tax, $invoice->freight_cost, $freight_added_tax, + $invoice->sales_type, $sales_order, $invoice->ship_via, + $invoice->due_date, 0, 0, $invoice->dimension_id, + $invoice->dimension2_id, $invoice->payment, $invoice->tax_included, $invoice->prep_amount); + + if ($trans_no == 0) { + $invoice->trans_no = array($invoice_no=>0); + } else + move_trans_attachments(ST_SALESINVOICE, $trans_no, $invoice_no); + + $total = 0; + // for prepayments use deferred income account if set + $sales_account = $invoice->is_prepaid() ? get_company_pref('deferred_income_act') : 0; + + foreach ($invoice->line_items as $line_no => $invoice_line) { + $qty = $invoice_line->qty_dispatched; + $line_taxfree_price = get_tax_free_price_for_item($invoice_line->stock_id, + $invoice_line->price * $qty, 0, $invoice->tax_included, + $invoice->tax_group_array); + + $line_tax = get_full_price_for_item($invoice_line->stock_id, + $invoice_line->price * $qty, 0, $invoice->tax_included, + $invoice->tax_group_array) - $line_taxfree_price; + + write_customer_trans_detail_item(ST_SALESINVOICE, $invoice_no, $invoice_line->stock_id, + $invoice_line->item_description, $invoice_line->qty_dispatched, + $invoice_line->line_price(), $qty ? $line_tax/$qty : 0, $invoice_line->discount_percent, + $invoice_line->standard_cost, $invoice_line->src_id, + $trans_no ? $invoice_line->id : 0); + + // Update delivery items for the quantity invoiced + if ($invoice_line->qty_old != $invoice_line->qty_dispatched) + { + if ($invoice->is_prepaid()) + update_prepaid_so_line($invoice_line->src_id, $invoice_line->qty_dispatched-$invoice_line->qty_old); + else + update_parent_line(ST_SALESINVOICE, $invoice_line->src_id, ($invoice_line->qty_dispatched-$invoice_line->qty_old)); + } + if ($invoice_line->qty_dispatched != 0) { + $stock_gl_code = get_stock_gl_code($invoice_line->stock_id); + + if ($invoice_line->line_price() != 0) { + //Post sales transaction to GL credit sales + + // If there is a Branch Sales Account, then override with this, + // else take the Item Sales Account + if (!$invoice->is_prepaid()) { + // by husnain 12-Dec-2023 + //to check whether or not to give item sale account priority on the basis of the $use_item_sale_account property + if($invoice->use_item_sale_account) { //If requested to use item sale account + $sales_account = ($stock_gl_code['sales_account'] != "" ? $stock_gl_code['sales_account']: $branch_data['sales_account']); + } + else{ + $sales_account = ($branch_data['sales_account'] != "" ? $branch_data['sales_account'] : $stock_gl_code['sales_account']); + } + } + // If there is a Customer Dimension, then override with this, + // else take the Item Dimension (if any) + $dim = ($invoice->dimension_id != $customer['dimension_id'] ? $invoice->dimension_id : + ($customer['dimension_id'] != 0 ? $customer["dimension_id"] : $stock_gl_code["dimension_id"])); + $dim2 = ($invoice->dimension2_id != $customer['dimension2_id'] ? $invoice->dimension2_id : + ($customer['dimension2_id'] != 0 ? $customer["dimension2_id"] : $stock_gl_code["dimension2_id"])); + $total += add_gl_trans_customer(ST_SALESINVOICE, $invoice_no, $date_, $sales_account, $dim, $dim2, + -$line_taxfree_price*$prepaid_factor, + $invoice->customer_id, "The sales price GL posting could not be inserted"); + + if ($invoice_line->discount_percent != 0) { + + $total += add_gl_trans_customer(ST_SALESINVOICE, $invoice_no, $date_, + $branch_data["sales_discount_account"], $dim, $dim2, + ($line_taxfree_price * $invoice_line->discount_percent)*$prepaid_factor, + $invoice->customer_id, "The sales discount GL posting could not be inserted"); + } /*end of if discount !=0 */ + } + } /*quantity dispatched is more than 0 */ + } /*end of delivery_line loop */ + + if (($items_total + $charge_shipping) != 0) { + $total += add_gl_trans_customer(ST_SALESINVOICE, $invoice_no, $date_, $branch_data["receivables_account"], $invoice->dimension_id, $invoice->dimension2_id, + ($items_total + $charge_shipping + $items_added_tax + $freight_added_tax)*$prepaid_factor, + $invoice->customer_id, "The total debtor GL posting could not be inserted"); + } + $to_allocate = ($items_total + $charge_shipping + $items_added_tax + $freight_added_tax); + + if ($charge_shipping != 0) { + $total += add_gl_trans_customer(ST_SALESINVOICE, $invoice_no, $date_, $company_data["freight_act"], $invoice->dimension_id, $invoice->dimension2_id, + -$invoice->get_tax_free_shipping()*$prepaid_factor, $invoice->customer_id, + "The freight GL posting could not be inserted"); + } + // post all taxes + foreach ($taxes as $taxitem) { + if ($taxitem['Net'] != 0) { + $ex_rate = get_exchange_rate_from_home_currency(get_customer_currency($invoice->customer_id), $date_); + add_trans_tax_details(ST_SALESINVOICE, $invoice_no, $taxitem['tax_type_id'], + $taxitem['rate'], $invoice->tax_included, $prepaid_factor*$taxitem['Value'], + $taxitem['Net'], $ex_rate, $date_, $invoice->reference, TR_OUTPUT); + if (isset($taxitem['sales_gl_code']) && !empty($taxitem['sales_gl_code']) && $taxitem['Value'] != 0) + $total += add_gl_trans_customer(ST_SALESINVOICE, $invoice_no, $date_, $taxitem['sales_gl_code'], $invoice->dimension_id, $invoice->dimension2_id, + (-$taxitem['Value'])*$prepaid_factor, $invoice->customer_id, + "A tax GL posting could not be inserted"); + } + } + + /*Post a balance post if $total != 0 */ + add_gl_balance(ST_SALESINVOICE, $invoice_no, $date_, -$total, PT_CUSTOMER, $invoice->customer_id); + + add_comments(ST_SALESINVOICE, $invoice_no, $date_, $invoice->Comments); + + if ($trans_no == 0) { + $Refs->save(ST_SALESINVOICE, $invoice_no, $invoice->reference, null, $invoice->fixed_asset); + if ($invoice->payment_terms['cash_sale'] && $invoice->pos['pos_account']) { + $amount = $items_total + $items_added_tax + $invoice->freight_cost + + $freight_added_tax; + if ($amount != 0) { + // to use debtors.pmt_discount on cash sale: + // extend invoice entry page with final amount after discount + // and change line below. + $discount = 0; // $invoice->cash_discount*$amount; + $payment_info = $invoice->pos['pos_name'].' #'.$invoice_no; + if (!empty($invoice->payment_info)) + $payment_info .= ' ' . $invoice->payment_info; + $pmtno = write_customer_payment(0, $invoice->customer_id, + $invoice->Branch, $invoice->pos['pos_account'], $date_, + $Refs->get_next(ST_CUSTPAYMENT, null, array('customer' => $invoice->customer_id, + 'branch' => $invoice->Branch, 'date' => $date_)), + $amount-$discount, $discount, $payment_info, + 0,0,0,$invoice->dimension_id, $invoice->dimension2_id); + add_cust_allocation($amount, ST_CUSTPAYMENT, $pmtno, ST_SALESINVOICE, $invoice_no, $invoice->customer_id, $date_); + + update_debtor_trans_allocation(ST_SALESINVOICE, $invoice_no, $invoice->customer_id); + update_debtor_trans_allocation(ST_CUSTPAYMENT, $pmtno, $invoice->customer_id); + } + } + } + reallocate_payments($invoice_no, ST_SALESINVOICE, $date_, $to_allocate, $allocs, $invoice->customer_id); + hook_db_postwrite($invoice, ST_SALESINVOICE); + + commit_transaction(); + + return $invoice_no; +} + +//-------------------------------------------------------------------------------------------------- \ No newline at end of file diff --git a/custom_sales_includes/extended_cart_class.inc b/custom_sales_includes/extended_cart_class.inc new file mode 100644 index 0000000..6acf608 --- /dev/null +++ b/custom_sales_includes/extended_cart_class.inc @@ -0,0 +1,87 @@ +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 = extended_write_sales_invoice($this); break; // by husnain 12-Dec-2023 extended sales invoice function to give item sales account priority if $use_item_sale_account is true + 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 = add_sales_order($this); + else + $ret = update_sales_order($this); + } + + commit_transaction(); + + return $ret; + } + +} \ No newline at end of file diff --git a/customerPayments.inc b/customerPayments.inc new file mode 100644 index 0000000..b44c673 --- /dev/null +++ b/customerPayments.inc @@ -0,0 +1,356 @@ + + */ +$page_security = 'ST_CUSTPAYMENT'; +$path_to_root = "../.."; +include_once($path_to_root . "/includes/ui/allocation_cart.inc"); +//include_once($path_to_root . "/includes/session.inc"); +include_once($path_to_root . "/includes/date_functions.inc"); +include_once($path_to_root . "/includes/ui.inc"); +include_once($path_to_root . "/includes/banking.inc"); +include_once($path_to_root . "/includes/data_checks.inc"); +include_once($path_to_root . "/sales/includes/sales_db.inc"); +include_once($path_to_root . "/reporting/includes/reporting.inc"); + + +//---------------------------------------------------------------------------------------------- + +function customerPayments_add() +{ + c_log('Step 1'); + if (can_process()) { + c_log('step can_process '); + new_doc_date($_POST['DateBanked']); + + $_SESSION['alloc'] = new allocation(ST_CUSTPAYMENT, 0, get_post('customer_id')); + + $payment_no = write_customer_payment($_SESSION['alloc']->trans_no, $_POST['customer_id'], $_POST['BranchID'], + $_POST['bank_account'], $_POST['DateBanked'], $_POST['ref'], + input_num('amount'), input_num('discount'), $_POST['memo_'], 0, input_num('charge'), input_num('bank_amount', input_num('amount')), $_POST['dimension_id'], $_POST['dimension2_id']); + + c_log('step $payment_no '); + + $_SESSION['alloc']->trans_no = $payment_no; + $_SESSION['alloc']->date_ = $_POST['DateBanked']; + $_SESSION['alloc']->write(); + + c_log('step AFTER write() '); + + unset($_SESSION['alloc']); + + if($payment_no){ + api_success_response(sprintf(_("Payment # %d has been entered."), $payment_no)); + }else{ + api_error(412, 'Failed to add Payment invoice.'); + } + + }else{ + c_log('step cannot process '); + api_error(500, 'Payment data is invalid.'); + } +} + +function can_process() +{ + global $Refs; + + if (!get_post('customer_id')) + { + display_error(_("There is no customer selected.")); + set_focus('customer_id'); + return false; + } + + if (!get_post('BranchID')) + { + display_error(_("This customer has no branch defined.")); + set_focus('BranchID'); + return false; + } + + if (!isset($_POST['DateBanked']) || !is_date($_POST['DateBanked'])) { + display_error(_("The entered date is invalid. Please enter a valid date for the payment.")); + set_focus('DateBanked'); + return false; + } elseif (!is_date_in_fiscalyear($_POST['DateBanked'])) { + display_error(_("The entered date is out of fiscal year or is closed for further data entry.")); + set_focus('DateBanked'); + return false; + } + + if (!check_reference($_POST['ref'], ST_CUSTPAYMENT, @$_POST['trans_no'])) { + set_focus('ref'); + return false; + } + + if (!check_num('amount', 0)) { + display_error(_("The entered amount is invalid or negative and cannot be processed.")); + set_focus('amount'); + return false; + } + + if (isset($_POST['charge']) && (!check_num('charge', 0) || $_POST['charge'] == $_POST['amount'])) { + display_error(_("The entered amount is invalid or negative and cannot be processed.")); + set_focus('charge'); + return false; + } + if (isset($_POST['charge']) && input_num('charge') > 0) { + $charge_acct = get_bank_charge_account($_POST['bank_account']); + if (get_gl_account($charge_acct) == false) { + display_error(_("The Bank Charge Account has not been set in System and General GL Setup.")); + set_focus('charge'); + return false; + } + } + + if (@$_POST['discount'] == "") + { + $_POST['discount'] = 0; + } + + if (!check_num('discount')) { + display_error(_("The entered discount is not a valid number.")); + set_focus('discount'); + return false; + } + + if (input_num('amount') <= 0) { + display_error(_("The balance of the amount and discount is zero or negative. Please enter valid amounts.")); + set_focus('discount'); + return false; + } + + if (isset($_POST['bank_amount']) && input_num('bank_amount')<=0) + { + display_error(_("The entered payment amount is zero or negative.")); + set_focus('bank_amount'); + return false; + } + + if (!db_has_currency_rates(get_customer_currency($_POST['customer_id']), $_POST['DateBanked'], true)) + return false; + + $_SESSION['alloc']->amount = input_num('amount'); + + if (isset($_POST["TotalNumberOfAllocs"])) + return check_allocations(); + else + return true; +} + + +function customerPayments_delete(){ + $resp=['status'=>true,'msg'=>'']; + try { + $_POST['filterType']=ST_CUSTPAYMENT; + if (check_valid_entries()==true) + { + $void_entry = get_voided_entry($_POST['filterType'], $_POST['trans_no']); + if ($void_entry != null) + { + $resp['status']=false; + $resp['error_code']=500; + $resp['msg']="The selected transaction has already been voided."; + + } else { + $msg = void_transaction($_POST['filterType'], $_POST['trans_no'], $_POST['date_'], $_POST['memo_']); + if (!$msg) { + $resp['status'] = true; + } else { + $resp['status'] = false; + $resp['error_code'] = 500; + $resp['msg'] = $msg; + } + } + } + } catch (Exception $e) { + error_log($e->getMessage(), 3, "/var/tmp/sales_cancel.log"); + $resp['msg']='Could not cancel invoice. '; + return; + } + if($resp['status']){ + api_success_response($resp); + }else{ + api_error($resp['error_code'], $resp['msg']); + } + +} + +function check_valid_entries() +{ + $check=array('status'=>true,'msg'); + + if (is_closed_trans($_POST['filterType'],$_POST['trans_no'])) + { + $check['msg'] = "The selected transaction was closed for edition and cannot be voided."; + $check['status'] = false; + } + if (!is_date($_POST['date_'])) + { + $check['msg'] = "The entered date is invalid."; + $check['status'] = false; + } + if (!is_date_in_fiscalyear($_POST['date_'])) + { + $check['msg'] ="The entered date is out of fiscal year or is closed for further data entry."; + $check['status'] = false; + } + + if (!is_numeric($_POST['trans_no']) OR $_POST['trans_no'] <= 0) + { + $check['msg'] ="The transaction number is expected to be numeric and greater than zero."; + $check['status'] = false; + } + + return $check; +} + + +function getAvailableCustomerPayments() +{ + $resp=['status'=>true,'msg'=>'success']; + try { + + $customer_id = $_POST['customer_id']; + + $sql = "SELECT + trans.type, + trans.trans_no, + trans.reference, + trans.tran_date, + debtor.name AS DebtorName, + debtor.curr_code, + ov_amount+ov_gst+ov_freight+ov_freight_tax+ov_discount AS Total, + trans.alloc, + trans.due_date, + debtor.address, + trans.version, + round(abs(ov_amount+ov_gst+ov_freight+ov_freight_tax+ov_discount-alloc),6) <= 0 AS settled, + trans.debtor_no + + FROM " + . TB_PREF . "debtor_trans as trans, " + . TB_PREF . "debtors_master as debtor" + . " WHERE trans.debtor_no=debtor.debtor_no + AND (((type=" . ST_CUSTPAYMENT . " OR type=" . ST_BANKDEPOSIT . ") AND (trans.ov_amount > 0)) + OR (type=" . ST_CUSTCREDIT . " AND (ov_amount+ov_gst+ov_freight+ov_freight_tax+ov_discount)>0) + OR (type=" . ST_JOURNAL . " AND (trans.ov_amount < 0)))"; + + + $sql .= " AND trans.debtor_no = " . db_escape($customer_id); + + $result = db_query($sql); + $resp['data'] = []; + + if ($result) { + while ($row = db_fetch_assoc($result)) { + $resp['data'][] = $row; + } + } + } catch (\Exception $e) { + $resp['status']=false; + $resp['msg']=$e->getMessage(); + } + + api_success_response(json_encode($resp)); + +} + +function getCustomerSalesForAllocate() +{ + $resp=['status'=>true,'msg'=>'success']; + try { + $allocation=new allocation($_POST['trans_type'],$_POST['trans_no']); + $resp['data']=$allocation->allocs; + } catch (\Exception $e) { + $resp['status']=false; + $resp['msg']=$e->getMessage(); + } + + api_success_response(json_encode($resp)); + +} + +function customerPayments_allocate() +{ + $resp=['status'=>true,'msg'=>'success']; + try { + $_SESSION['alloc']=new allocation($_POST['trans']['type'],$_POST['trans']['trans_no']); + $_POST=$_POST['alloc_data']; + $SysPrefs = new sys_prefs(); + + $total_allocated = 0; + + + for ($counter = 0; $counter < sizeof($_POST); $counter++) + { + if (!isset($_POST['amount'.$counter])) continue; + if (!check_num('amount' . $counter, 0)) + { + $resp['status']=false; + $resp['msg']="The entry for one or more amounts is invalid or negative. ( ".$_POST['amount'.$counter].""; + break; + } + + /* Now check to see that the AllocAmt is no greater than the + amount left to be allocated against the transaction under review; + skip check if no allocation is set to avoid deadlock on mistakenly overallocated transactions*/ + $allocated = input_num('amount' . $counter); + if ($allocated && ($allocated > input_num('un_allocated' . $counter))) + { + $resp['status']=false; + $resp['msg']="At least one transaction is overallocated. ( ".$_POST['amount'.$counter].""; + break; + } + + if ($_SESSION['alloc']->person_type == PT_CUSTOMER) { + if ($_SESSION['alloc']->allocs[$counter]->type == ST_SALESORDER) + $trans = get_sales_order_header($_SESSION['alloc']->allocs[$counter]->type_no, $_SESSION['alloc']->allocs[$counter]->type); + else + $trans = get_customer_trans($_SESSION['alloc']->allocs[$counter]->type_no, $_SESSION['alloc']->allocs[$counter]->type,$_SESSION['alloc']->person_id); + + if ($trans['debtor_no'] != $_SESSION['alloc']->person_id) { + $resp['status']=false; + $resp['msg']="Allocated transaction allocated is not related to company selected. ( ".$_POST['amount'.$counter].""; + break; + } + } elseif ($_SESSION['alloc']->person_type == PT_SUPPLIER) { + if ($_SESSION['alloc']->allocs[$counter]->type == ST_PURCHORDER) + $trans = get_po($_SESSION['alloc']->allocs[$counter]->type_no); + else + $trans = get_supp_trans($_SESSION['alloc']->allocs[$counter]->type_no, $_SESSION['alloc']->allocs[$counter]->type, $_SESSION['alloc']->person_id); + if ($trans['supplier_id'] != $_SESSION['alloc']->person_id) { + $resp['status']=false; + $resp['msg']="Allocated transaction allocated is not related to company selected. ( ".$_POST['amount'.$counter]." )"; + break; + } + } + + $_SESSION['alloc']->allocs[$counter]->current_allocated = input_num('amount' . $counter); + + $total_allocated += input_num('amount' . $counter); + } + + $amount = abs($_SESSION['alloc']->amount); + + if ($total_allocated - ($amount + input_num('discount')) > $SysPrefs->allocation_settled_allowance()) + { + $resp['status']=false; + $resp['msg']="These allocations cannot be processed because the amount allocated is more than the total amount left to allocate"; + } + + + if ($resp['status']) { + $_SESSION['alloc']->write(); + } + + + } catch (\Exception $e) { + $resp['status']=false; + $resp['msg']=$e->getMessage(); + } + + api_success_response(json_encode($resp)); + +} diff --git a/generalLedgerInquiry.inc b/generalLedgerInquiry.inc new file mode 100644 index 0000000..f0d7bdf --- /dev/null +++ b/generalLedgerInquiry.inc @@ -0,0 +1,309 @@ +true,'msg'=>'success','data_list'=>[]]; + global $path_to_root, $systypes_array; + + if (!isset($_POST["account"])) + $_POST["account"] = null; + + $act_name = $_POST["account"] ? get_gl_account_name($_POST["account"]) : ""; + $dim = get_company_pref('use_dimension'); + + /*Now get the transactions */ + if (!isset($_POST['Dimension'])) + $_POST['Dimension'] = 0; + if (!isset($_POST['Dimension2'])) + $_POST['Dimension2'] = 0; + $result = get_gl_transactions($_POST['TransFromDate'], $_POST['TransToDate'], -1, + $_POST["account"], $_POST['Dimension'], $_POST['Dimension2'], null, + input_num('amount_min'), input_num('amount_max'), null, null, $_POST['Memo']); + + $colspan = ($dim == 2 ? "7" : ($dim == 1 ? "6" : "5")); + + if ($_POST["account"] != null) + display_heading($_POST["account"]. "   ".$act_name); + + // Only show balances if an account is specified AND we're not filtering by amounts + $show_balances = $_POST["account"] != null && + input_num("amount_min") == 0 && + input_num("amount_max") == 0; + + start_table(TABLESTYLE); + + $first_cols = array(_("Type"), _("#"), _("Reference"), _("Date")); + + if ($_POST["account"] == null) + $account_col = array(_("Account")); + else + $account_col = array(); + + if ($dim == 2) + $dim_cols = array(_("Dimension")." 1", _("Dimension")." 2"); + elseif ($dim == 1) + $dim_cols = array(_("Dimension")); + else + $dim_cols = array(); + + if ($show_balances) + $remaining_cols = array(_("Person/Item"), _("Debit"), _("Credit"), _("Balance"), _("Memo"), ""); + else + $remaining_cols = array(_("Person/Item"), _("Debit"), _("Credit"), _("Memo"), ""); + + $th = array_merge($first_cols, $account_col, $dim_cols, $remaining_cols); + + table_header($th); + if ($_POST["account"] != null && is_account_balancesheet($_POST["account"])) + $begin = ""; + else + { + $begin = get_fiscalyear_begin_for_date($_POST['TransFromDate']); + if (date1_greater_date2($begin, $_POST['TransFromDate'])) + $begin = $_POST['TransFromDate']; + $begin = add_days($begin, -1); + } + + $bfw = 0; + if ($show_balances) { + $bfw = get_gl_balance_from_to($begin, $_POST['TransFromDate'], $_POST["account"], $_POST['Dimension'], $_POST['Dimension2']); + start_row("class='inquirybg'"); + label_cell(""._("Opening Balance")." - ".$_POST['TransFromDate']."", "colspan=$colspan"); + display_debit_or_credit_cells($bfw, true); + label_cell(""); + label_cell(""); + end_row(); + } + + $running_total = $bfw; + $j = 1; + $k = 0; //row colour counter + + while ($myrow = db_fetch($result)) + { + + alt_table_row_color($k); + + $running_total += $myrow["amount"]; + + $resp['data_list'][]=$myrow; + + $trandate = sql2date($myrow["tran_date"]); + + label_cell($systypes_array[$myrow["type"]]); + label_cell(get_gl_view_str($myrow["type"], $myrow["type_no"], $myrow["type_no"], true)); + label_cell(get_trans_view_str($myrow["type"],$myrow["type_no"],$myrow['reference'])); + label_cell($trandate); + + if ($_POST["account"] == null) + label_cell($myrow["account"] . ' ' . get_gl_account_name($myrow["account"])); + + if ($dim >= 1) + label_cell(get_dimension_string($myrow['dimension_id'], true)); + if ($dim > 1) + label_cell(get_dimension_string($myrow['dimension2_id'], true)); + label_cell(payment_person_name($myrow["person_type_id"],$myrow["person_id"])); + display_debit_or_credit_cells($myrow["amount"]); + if ($show_balances) + amount_cell($running_total); + if ($myrow['memo_'] == "") + $myrow['memo_'] = get_comments_string($myrow['type'], $myrow['type_no']); + label_cell($myrow['memo_']); + if ($myrow["type"] == ST_JOURNAL) + echo "" . trans_editor_link( $myrow["type"], $myrow["type_no"]) . ""; + else + label_cell(""); + end_row(); + + $j++; + if ($j == 12) + { + $j = 1; + table_header($th); + } + } + //end of while loop + + $resp['ending_balance']=$running_total; + + if ($show_balances) { + start_row("class='inquirybg'"); + label_cell("" . _("Ending Balance") ." - ".$_POST['TransToDate']. "", "colspan=$colspan"); + display_debit_or_credit_cells($running_total, true); + label_cell(""); + label_cell(""); + end_row(); + } + + end_table(2); + // if (db_num_rows($result) == 0) + // display_note(_("No general ledger transactions have been created for the specified criteria."), 0, 1); + + api_success_response(json_encode($resp)); +} + +function inquiry() +{ + $resp=['status'=>true,'msg'=>'success','data_list'=>[]]; + try { + + if (!isset($_POST["account"])) + $_POST["account"] = null; + if (!isset($_POST['Dimension'])) + $_POST['Dimension'] = 0; + if (!isset($_POST['Dimension2'])) + $_POST['Dimension2'] = 0; + + $result = get_gl_transactions($_POST['TransFromDate'], $_POST['TransToDate'], -1, + $_POST["account"], $_POST['Dimension'], $_POST['Dimension2'], null, + input_num('amount_min'), input_num('amount_max'), null, null, $_POST['Memo']); + + + // Only show balances if an account is specified AND we're not filtering by amounts + $show_balances = $_POST["account"] != null && + input_num("amount_min") == 0 && + input_num("amount_max") == 0; + + + if ($_POST["account"] != null && is_account_balancesheet($_POST["account"])) + $begin = ""; + else { + $begin = get_fiscalyear_begin_for_date($_POST['TransFromDate']); + if (date1_greater_date2($begin, $_POST['TransFromDate'])) + $begin = $_POST['TransFromDate']; + $begin = add_days($begin, -1); + } + + + $bfw = 0; + if ($show_balances) { + $bfw = get_gl_balance_from_to($begin, $_POST['TransFromDate'], $_POST["account"], $_POST['Dimension'], $_POST['Dimension2']); + } + + $running_total = $bfw; + + while ($myrow = db_fetch($result)) { + + $running_total += $myrow["amount"]; + + if ($_POST["account"] == null) + $myrow["account"] = get_gl_account_name($myrow["account"]); + + if(isset($_POST['list'])) + $resp['data_list'][]=$myrow; + } + + $resp['ending_balance']=round2($running_total, user_price_dec()); + + } catch (\Exception $e) { + $resp['status']=false; + $resp['msg']=$e->getMessage(); + } + + api_success_response(json_encode($resp)); +} + + +function inquiry__() +{ + $resp=['status'=>true,'msg'=>'success','data_list'=>[]]; + try { + + if (!isset($_POST["account"])) + $_POST["account"] = null; + + $act_name = $_POST["account"] ? get_gl_account_name($_POST["account"]) : ""; + + /*Now get the transactions */ + if (!isset($_POST['Dimension'])) + $_POST['Dimension'] = 0; + if (!isset($_POST['Dimension2'])) + $_POST['Dimension2'] = 0; + $result = get_gl_transactions($_POST['TransFromDate'], $_POST['TransToDate'], -1, + $_POST["account"], $_POST['Dimension'], $_POST['Dimension2'], null, + input_num('amount_min'), input_num('amount_max'), null, null, $_POST['Memo']); + + + if ($_POST["account"] != null) + $_POST["account"]=$_POST["account"]. "   ".$act_name; + + // Only show balances if an account is specified AND we're not filtering by amounts + $show_balances = $_POST["account"] != null && + input_num("amount_min") == 0 && + input_num("amount_max") == 0; + + + if ($_POST["account"] != null && is_account_balancesheet($_POST["account"])) + $begin = ""; + else + { + $begin = get_fiscalyear_begin_for_date($_POST['TransFromDate']); + if (date1_greater_date2($begin, $_POST['TransFromDate'])) + $begin = $_POST['TransFromDate']; + $begin = add_days($begin, -1); + } + + $bfw = 0; + if ($show_balances) { + $bfw = get_gl_balance_from_to($begin, $_POST['TransFromDate'], $_POST["account"], $_POST['Dimension'], $_POST['Dimension2']); + } + + $running_total = $bfw; + + while ($myrow = db_fetch($result)) + { + $running_total += $myrow["amount"]; + + if ($_POST["account"] == null) + $myrow["account"] = get_gl_account_name($myrow["account"]); + + if(isset($_POST['list'])) + $resp['data_list'][]=$myrow; + + + } + + /* if ($show_balances) { + $resp['ending_balance']=display_debit_or_credit_cells_($running_total); + }*/ + + $resp['ending_balance']=$running_total; + + + } catch (\Exception $e) { + $resp['status']=false; + $resp['msg']=$e->getMessage(); + } + + api_success_response(json_encode($resp)); + +} + +function display_debit_or_credit_cells_($value) +{ + $value = round2($value, user_price_dec()); + if ($value >= 0) + { + return $value; + } + elseif ($value < 0) + { + return abs($value); + } +} \ No newline at end of file diff --git a/index.php b/index.php index 2bb7b9f..51b0390 100755 --- a/index.php +++ b/index.php @@ -42,6 +42,19 @@ * ) */ +function c_log($log){ + // $file='../../tmp/logs.log'; + $file='logs.log'; + $myfile = fopen($file, file_exists($file)?'a':'w') or die("Unable to open file!"); + fwrite($myfile,"\n".date('Y-m-d H:i:s').' : '. (is_array($log)?print_r($log,true):$log)); + fclose($myfile); +} + + +ini_set('display_errors', 1); +ini_set('display_startup_errors', 1); +error_reporting(E_ALL); + ini_set('html_errors', false); ini_set('xdebug.show_exception_trace', 0); // ini_set('xdebug.auto_trace', 2); diff --git a/purchase.inc b/purchase.inc index 009f897..4b6fea2 100755 --- a/purchase.inc +++ b/purchase.inc @@ -133,6 +133,12 @@ function can_commit() return true; } + + +/** + * Author : Danish Naseem + * + */ function purchase_delete($branch_id,$uuid){ $resp=['status'=>true,'msg'=>'']; try { @@ -170,6 +176,11 @@ function purchase_delete($branch_id,$uuid){ } + +/** + * Author : Danish Naseem + * + */ function check_valid_entries() { if (is_closed_trans($_POST['filterType'],$_POST['trans_no'])) diff --git a/sales.inc b/sales.inc index 794ca2f..e8f000d 100755 --- a/sales.inc +++ b/sales.inc @@ -7,6 +7,7 @@ Free software under GNU GPL $path_to_root = "../.."; +include_once("custom_sales_includes/extended_cart_class.inc"); // by husnain 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"); @@ -251,8 +252,13 @@ function sales_add() { $req = $app->request(); $info = $req->post(); + c_log('in sales step 1'); + $cart = null; - $cart = new Cart($info['trans_type'], 0); + //$cart = new Cart($info['trans_type'], 0); // commented by husnain 12-dec-2023 to use extended class + $cart = new ExtendedCart($info['trans_type'], 0); // by husnain 12-dec-2023 extended cart class to give priority to item sales account if 'use_item_sale_account' param exist else use orginal + + $cart->reference = $info['ref']; $cart->Comments = $info['comments']; $cart->document_date = $info['order_date']; @@ -297,6 +303,10 @@ function sales_add() { $cart->dimension2_id = $info['dimension2_id']; } + if(isset($info['use_item_sale_account'])){ // 12-dec-2023 by husnain if want to give priority to use item sale account + $cart->use_item_sale_account=$info['use_item_sale_account']; + } + foreach($info['items'] as $item) { add_to_order($cart, $item['stock_id'], $item['qty'], $item['price'], $item['discount'], $item['description']); } diff --git a/src/CustomerPayments.php b/src/CustomerPayments.php index 676ce2e..c4d46e0 100644 --- a/src/CustomerPayments.php +++ b/src/CustomerPayments.php @@ -5,6 +5,8 @@ namespace FAAPI; + + class CustomerPayments { public function post($rest) @@ -18,4 +20,22 @@ public function delete($rest) include_once(API_ROOT . "/customerPayments.inc"); customerPayments_delete(); } + + public function getAvailableCustomerPayments($rest) + { + include_once(API_ROOT . "/customerPayments.inc"); + getAvailableCustomerPayments(); + } + + public function getCustomerSalesForAllocate($rest) + { + include_once(API_ROOT . "/customerPayments.inc"); + getCustomerSalesForAllocate(); + } + + public function allocateCustomerPayments($rest) + { + include_once(API_ROOT . "/customerPayments.inc"); + customerPayments_allocate(); + } } diff --git a/src/Customers.php b/src/Customers.php index 99f1f0f..f6709bb 100644 --- a/src/Customers.php +++ b/src/Customers.php @@ -107,11 +107,26 @@ public function post($rest) $info['email'] = ''; } + $dimension_id=0; + $dimension_id2=0; + + if(isset($info['dimension_id'])) + if(!is_numeric($info['dimension_id'])) + api_error(412, 'Dimension 1 should be numeric value [dimension_id]'); + else + $dimension_id=$info['dimension_id']; + + if(isset($info['dimension_id2'])) + if(!is_numeric($info['dimension_id2'])) + api_error(412, 'Dimension 2 should be numeric value [dimension_id2]'); + else + $dimension_id2=$info['dimension_id2']; + /* * $CustName, $debtor_ref, $address, $tax_id, $curr_code, $dimension_id, $dimension2_id, $credit_status, * $payment_terms, $discount, $pymt_discount, $credit_limit, $sales_type, $notes */ - add_customer($info['name'], $info['debtor_ref'], $info['address'], $info['tax_id'], $info['curr_code'], 0, 0, $info['credit_status'], $info['payment_terms'], $info['discount'], $info['pymt_discount'], $info['credit_limit'], $info['sales_type'], $info['notes']); + add_customer($info['name'], $info['debtor_ref'], $info['address'], $info['tax_id'], $info['curr_code'], $dimension_id, $dimension_id2, $info['credit_status'], $info['payment_terms'], $info['discount'], $info['pymt_discount'], $info['credit_limit'], $info['sales_type'], $info['notes']); $selected_id = db_insert_id(); $auto_create_branch = 1; @@ -137,6 +152,7 @@ public function post($rest) } // Edit Specific Item public function put($rest, $id) + { $req = $rest->request(); $info = $req->post(); @@ -188,11 +204,26 @@ public function put($rest, $id) $info['notes'] = ''; } + $dimension_id=0; + $dimension_id2=0; + + if(isset($info['dimension_id'])) + if(!is_numeric($info['dimension_id'])) + api_error(412, 'Dimension 1 should be numeric value [dimension_id]'); + else + $dimension_id=$info['dimension_id']; + + if(isset($info['dimension_id2'])) + if(!is_numeric($info['dimension_id2'])) + api_error(412, 'Dimension 2 should be numeric value [dimension_id2]'); + else + $dimension_id2=$info['dimension_id2']; + /* * $customer_id, $CustName, $debtor_ref, $address, $tax_id, $curr_code, $dimension_id, $dimension2_id, * $credit_status, $payment_terms, $discount, $pymt_discount, $credit_limit, $sales_type, $notes */ - update_customer($id, $info['name'], $info['debtor_ref'], $info['address'], $info['tax_id'], $info['curr_code'], 0, 0, $info['credit_status'], $info['payment_terms'], $info['discount'], $info['pymt_discount'], $info['credit_limit'], $info['sales_type'], $info['notes']); + update_customer($id, $info['name'], $info['debtor_ref'], $info['address'], $info['tax_id'], $info['curr_code'], $dimension_id, $dimension_id2, $info['credit_status'], $info['payment_terms'], $info['discount'], $info['pymt_discount'], $info['credit_limit'], $info['sales_type'], $info['notes']); api_success_response("Customer has been updated"); } diff --git a/src/Dimensions.php b/src/Dimensions.php index 4fda63f..24d0bc4 100644 --- a/src/Dimensions.php +++ b/src/Dimensions.php @@ -137,7 +137,8 @@ public function post($rest) \api_validate('name', $model); \api_check('memo', $model); // add_dimension($reference, $name, $type_, $date_, $due_date, $memo_) - $id = add_dimension($model['reference'], $model['name'], '', '', '', $model['memo']); + // $id = add_dimension($model['reference'], $model['name'], '', '', '', $model['memo']); + $id = add_dimension($model['reference'], $model['name'], $model['type_'],$model['date_'],$model['due_date'], $model['memo']); \api_create_response(array('id' => $id)); } diff --git a/src/GeneralLedgerInquiry.php b/src/GeneralLedgerInquiry.php new file mode 100644 index 0000000..7ac0a64 --- /dev/null +++ b/src/GeneralLedgerInquiry.php @@ -0,0 +1,16 @@ + + */ + +namespace FAAPI; + +class GeneralLedgerInquiry +{ + public function post($rest) + { + include_once(API_ROOT . "/generalLedgerInquiry.inc"); + inquiry(); + } + +} diff --git a/src/Journal.php b/src/Journal.php index e8c83f4..6b710bf 100644 --- a/src/Journal.php +++ b/src/Journal.php @@ -262,7 +262,15 @@ public function post($rest) $cart->reference = $model['reference'] ? $model['reference'] : $Refs->get_next(ST_JOURNAL, null, $cart->tran_date); // TODO check fiscal year foreach ($model['items'] as $item) { - $cart->add_gl_item($item['account_code'], '', '', $item['amount'], $item['memo']); + + /* Added by Danish Start*/ + $dimension_id=(isset($item['dimension_id'])?$item['dimension_id']:''); + $dimension2_id=(isset($item['dimension2_id'])?$item['dimension2_id']:''); + $person_id=(isset($item['person_id'])?$item['person_id']:''); + $cart->add_gl_item($item['account_code'], $dimension_id, $dimension2_id, $item['amount'], $item['memo'],'',$person_id); + /* Added by Danish end*/ + + // $cart->add_gl_item($item['account_code'], '', '', $item['amount'], $item['memo']); } $id = write_journal_entries($cart); diff --git a/src/Sales.php b/src/Sales.php index c2a6fa7..dc8046c 100644 --- a/src/Sales.php +++ b/src/Sales.php @@ -89,7 +89,7 @@ public function getById($rest, $trans_no, $trans_type) * description="successful operation", * @SWG\Schema( * type="object", - * ref="#/definitions/Sale" + * ref="#Ω/definitions/Sale" * ) * ), * deprecated=false diff --git a/src/Suppliers.php b/src/Suppliers.php index 1990f05..3692805 100644 --- a/src/Suppliers.php +++ b/src/Suppliers.php @@ -83,12 +83,27 @@ public function post($rest) $info['notes'] = ''; } + $dimension_id=0; + $dimension_id2=0; + + if(isset($info['dimension_id'])) + if(!is_numeric($info['dimension_id'])) + api_error(412, 'Dimension 1 should be numeric value [dimension_id]'); + else + $dimension_id=$info['dimension_id']; + + if(isset($info['dimension_id2'])) + if(!is_numeric($info['dimension_id2'])) + api_error(412, 'Dimension 2 should be numeric value [dimension_id2]'); + else + $dimension_id2=$info['dimension_id2']; + /* * $supp_name, $supp_ref, $address, $supp_address, $gst_no, $website, $supp_account_no, $bank_account, * $credit_limit, $dimension_id, $dimension2_id, $curr_code, $payment_terms, $payable_account, * $purchase_account, $payment_discount_account, $notes, $tax_group_id, $tax_included */ - add_supplier($info['supp_name'], $info['supp_ref'], $info['address'], $info['supp_address'], $info['gst_no'], $info['website'], $info['supp_account_no'], $info['bank_account'], $info['credit_limit'], 0, 0, $info['curr_code'], $info['payment_terms'], $info['payable_account'], $info['purchase_account'], $info['payment_discount_account'], $info['notes'], $info['tax_group_id'], $info['tax_included']); + add_supplier($info['supp_name'], $info['supp_ref'], $info['address'], $info['supp_address'], $info['gst_no'], $info['website'], $info['supp_account_no'], $info['bank_account'], $info['credit_limit'], $dimension_id, $dimension_id2, $info['curr_code'], $info['payment_terms'], $info['payable_account'], $info['purchase_account'], $info['payment_discount_account'], $info['notes'], $info['tax_group_id'], $info['tax_included']); $id = db_insert_id(); $sup = get_supplier($id); @@ -163,12 +178,27 @@ public function put($rest, $id) $info['notes'] = ''; } + $dimension_id=0; + $dimension_id2=0; + + if(isset($info['dimension_id'])) + if(!is_numeric($info['dimension_id'])) + api_error(412, 'Dimension 1 should be numeric value [dimension_id]'); + else + $dimension_id=$info['dimension_id']; + + if(isset($info['dimension_id2'])) + if(!is_numeric($info['dimension_id2'])) + api_error(412, 'Dimension 2 should be numeric value [dimension_id2]'); + else + $dimension_id2=$info['dimension_id2']; + /* * $supplier_id, $supp_name, $supp_ref, $address, $supp_address, $gst_no, $website, $supp_account_no, * $bank_account, $credit_limit, $dimension_id, $dimension2_id, $curr_code, $payment_terms, $payable_account, * $purchase_account, $payment_discount_account, $notes, $tax_group_id, $tax_included */ - update_supplier($id, $info['supp_name'], $info['supp_ref'], $info['address'], $info['supp_address'], $info['gst_no'], $info['website'], $info['supp_account_no'], $info['bank_account'], $info['credit_limit'], 0, 0, $info['curr_code'], $info['payment_terms'], $info['payable_account'], $info['purchase_account'], $info['payment_discount_account'], $info['notes'], $info['tax_group_id'], $info['tax_included']); + update_supplier($id, $info['supp_name'], $info['supp_ref'], $info['address'], $info['supp_address'], $info['gst_no'], $info['website'], $info['supp_account_no'], $info['bank_account'], $info['credit_limit'], $dimension_id, $dimension_id2, $info['curr_code'], $info['payment_terms'], $info['payable_account'], $info['purchase_account'], $info['payment_discount_account'], $info['notes'], $info['tax_group_id'], $info['tax_included']); api_success_response("Supplier has been updated"); }