26

(7 replies, posted in Reporting)

got you. Will try that. First I got to deal with the validation things with source_ref and check no. in Banking and General Ledger.

I believe with everyone's contributions for different parts of the world, FA will certain be the number Accounting software.

Cheers

27

(7 replies, posted in Reporting)

tom.horton wrote:

To "spell out" the number entered, you could always use this PHP function:

$f = new NumberFormatter("en", NumberFormatter::SPELLOUT);
$f->setTextAttribute(NumberFormatter::DEFAULT_RULESET, "%spellout-numbering-verbose");
echo $f->format($total_amount);

You can see there is the option for the script to pickup a default language as well ("en", NumberFormatter::SPELLOUT) so if FA has the same "standard" letters set as PHP for language settings, it will write the wording in that language.

Hope this helps.

Where do you insert this piece of code? Is it in gl_payment_view.php or somewhere else? I like the idea.

28

(2 replies, posted in Installation)

dLoPRod wrote:

Hello,

I'm the admin for an FA installation, but I havn't logged in for a while and missplaced my password.

How can I reset the password, I'm locked out

Thanks in advance for all your help

Edit:

I have access to the server and database, the only password I lost is the web app password itself

Edit 2:
Figured out it is an md5 hash, just replaced the value in database for my new password's hash.
Thanks anyway!! Have a good day all!

Good thing you have access to the database, you can visit this site

https://md5decrypt.net/en/

copy paste your password hash it will decrypt your password. or you could also copy another user's md5 hash and replace on your user password, login with that then change. Also the other user must change theirs to since you know it. cheers

tom.horton wrote:

I think I have this right now...

Firstly, make sure the Ajax libraries are included in your file.

For your main PHP file, you need to have the following javascript/Ajax included:

<script>
        function add_source_reference()
        {
            $.ajax({
                type: "POST",
                data: {
                    source_ref: $('#source_ref').val(),
                },
                url: "gl_validation_checks.php",
                success: function(data)
                {
                    if(data === 'SOURCEREF_EXISTS')
                    {
                        $('#sourceref_res')
                            .css('color', 'red')
                            .html("This reference already exists");
                    }
                }
            })              
        }
</script>

You need to add an OnExit command to a text field (the "source_ref" field), where this equals "add_source_reference()"

Create a new PHP file called gl_validation_checks.php for example:

<?php
    $source_ref = mysql_real_escape_string($_POST['source_ref']);
    $sql = "SELECT source_ref FROM bank_trans WHERE source_ref='".$source_ref."'";
    $query = mysql_query($sql);
    if(mysql_num_rows($query) == 0)
    {
        echo('NO_SOURCEREF');
    }
    else
    {
        echo('SOURCEREF_EXISTS');
    }
?>

I believe there is already a file for validation check  /includes/data_checks.inc    , isn't it possible to just include the script in that file?

tom.horton wrote:

For your SQL error you are missing a number of fields. These are as follows:

INSERT INTO bank_trans 
(type, trans_no, bank_act, ref, check_no, source_ref, trans_date, amount, person_type_id, person_id) 
VALUES
(0, 1348, '5', '080/2021', '<check_no>', '<source_ref>', '2021-01-18','-400','<person_type_id>', '<person_id>')

I have marked them with "<>" either side. I have also corrected fields that were showing the wrong format etc.

As for checking for duplicated source_ref data, that could possibly be done by Ajax. It would require a JS file to execute a PHP file to run a MySQL query when you update a text field.

Now, that's the thing, journal entry is used not only for bank transactions, but also for other says, I am getting money from CASH ON HAND To Fuel Expense, without necessarily getting money from the bank, which means there is no check involved. This is where i am complicating my life now lol... The Check no field in this case will be empty, which will throw that database error.

I am also getting another error when I deal with journal entry, since we changed the fields for banks_trans, now journal entry gives me this error

Undefined offset: 1 in file: /var/www/html/ced/includes/date_functions.inc at line 386Undefined offset: 2 in file: /var/www/html/ced/includes/date_functions.inc at line 386DATABASE ERROR : The bank transaction could not be inserted
error code : 1366
error message : Incorrect integer value: 'ETB' for column 'person_type_id' at row 1
sql that failed was : INSERT INTO bank_trans (type, trans_no, bank_act, ref, check_no, source_ref, trans_date, amount, person_type_id, person_id) VALUES (0, 1348, '5', '080/2021', '01/18/2021','-400','0000-00-00', '0', 'ETB', 'Cannot insert a destination bank transaction')

I have only managed with php to prevent empty field for source_ref

if (strlen($_POST['source_ref']) == 0 || $_POST['source_ref'] == "") // new line validation added on sunday november 21 2020
    {
        display_error(_("The source reference field must be entered.")); // new line validation
         if (get_post('currency') != get_company_pref('curr_default'))
        set_focus('source_ref'); if (isset($_POST['_ex_rate']) && !check_num('_ex_rate', 0.000001))
        return false; {
    }                  display_error(_("The exchange rate must be numeric and greater than zero."));
                set_focus('_ex_rate');
            $input_error = 1;
        }

@tom.horton

I have not succeeded in preventing same source_ref data to be duplicated. When I use the sql UNIQUE constraint, even NULL values will not be accepted. Do you have a better idea to prevent duplication of source_ref values?

Thanks

Will do that,
Also you can update your view to display check and source reference on <b>gl_payment_view.php</b>

start_row();
label_cells(_("From Bank Account"), $from_trans['bank_account_name'], "class='tableheader2'");
if ($show_currencies)
    label_cells(_("Currency"), $from_trans['bank_curr_code'], "class='tableheader2'");
label_cells(_("Amount"), number_format2(-$from_trans['amount'], user_price_dec()), "class='tableheader2'", "align=right");
label_cells(_("Date"), sql2date($from_trans['trans_date']), "class='tableheader2'");
end_row();
start_row();
label_cells(_("Pay To"), get_counterparty_name(ST_BANKPAYMENT, $from_trans['trans_no']), "class='tableheader2'", "colspan=$colspan1");
if ($show_currencies)
{
    label_cells(_("Settle currency"), $from_trans['settle_curr'], "class='tableheader2'");
    label_cells(_("Settled amount"), number_format2($from_trans['settled_amount'], user_price_dec()), "class='tableheader2'");
}
label_cells(_("Payment Type"), $bank_transfer_types[$from_trans['account_type']], "class='tableheader2'");
end_row();
start_row();
label_cells(_("Reference"),   $from_trans['ref'], "class='tableheader2'");
label_cells(_("voucher No"),  $from_trans['source_ref'], "class='tableheader2'", "align=right");
label_cells(_("Check No"),    $from_trans['check_no'], "class='tableheader2'");
end_row();

something like this on journal entry

if (strlen($_POST['source_ref']) == 0 || $_POST['source_ref'] == "") // new line validation added on sunday november 21 2020
    {
        display_error(_("The source reference field must be entered.")); // new line validation
         if (get_post('currency') != get_company_pref('curr_default'))
        set_focus('source_ref'); if (isset($_POST['_ex_rate']) && !check_num('_ex_rate', 0.000001))
        return false; {
    }                  display_error(_("The exchange rate must be numeric and greater than zero."));
                set_focus('_ex_rate');
            $input_error = 1;
        }

Yeah I messed somewhere, I wanted the source ref on journal entry to be unique, to throw error to the user that the source ref is either empty or already used.

`journal` (
  `type` smallint(6) NOT NULL DEFAULT '0',
  `trans_no` int(11) NOT NULL DEFAULT '0',
  `reference` varchar(60) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  `source_ref` varchar(60) COLLATE utf8_unicode_ci DEFAULT '',
  `event_date` date DEFAULT '0000-00-00',
  `doc_date` date NOT NULL DEFAULT '0000-00-00',
  `currency` char(3) COLLATE utf8_unicode_ci NOT NULL DEFAULT '',
  `amount` double NOT NULL DEFAULT '0',
  `rate` double NOT NULL DEFAULT '1'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

tom.horton wrote:

Good news!

We have succeeded in doing what i wanted to do for Bank payments,
Now, I found the first bug in admin/void_transaction.php? after fixing this I will share the code

DATABASE ERROR : Error reading record set
error code : 1054
error message : Unknown column 't.tran_date' in 'field list'
sql that failed was : SELECT COUNT(*) FROM (SELECT t.trans_no as trans_no ,t.reference as ref ,t.tran_date as trans_date, t.type as type FROM journal t LEFT JOIN voided v ON t.trans_no=v.id AND v.type='0' WHERE ISNULL(v.`memo_`) AND t.trans_no >= '1' AND t.trans_no <= '999999' AND t.`type` = '0' GROUP BY t.type, t.trans_no ORDER BY t.trans_no DESC) tmp_count

right right, i corrected that and it pretty much worked.

I see data inserted in the database. So let me check the code again and again make sure it ok and didn't affect any other things in the all system
then I will share for those that may also need it.

if it happens to be useful to others maybe it can be added to the core FA in future updates

I had seen already when you posted the code. you switched the date position which was to come after source_ref.

ALTER TABLE `bank_trans` ADD `check_no` VARCHAR(60) NOT NULL AFTER `ref`, ADD `source_ref` VARCHAR(60) NOT NULL AFTER `check_no`, ADD UNIQUE (`check_no`), ADD UNIQUE (`source_ref`); 


All I am trying to do is add two extra columns to bank_trans so that I can record cheque no and cash voucher no.
also I want them to be unique so that their is no duplicate of the same check with different transaction?

Writing a cheque no on MEMO IS not the proper way to record payment according to me.
Dealing with banks we all know that, you make payment either bank Cheque, Transfer Note, so where do you record the cheques that you have processed..

Would you try it and let me know if it works for you!

I made some changes, now i am getting a different error

DATABASE ERROR : Cannot insert a source bank transaction
error code : 1064
error message : You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '', '-500', '0', 'Gregory')' at line 2
sql that failed was : INSERT INTO bank_trans (type, trans_no, bank_act, ref,check_no, source_ref, trans_date, amount, person_type_id, person_id) VALUES (1, 130, '3', '001/2021', 'CHEK 001','CV 001-2021',2021-01-17', '-500', '0', 'Gregory')

this is what I tried to do to modify my GL Payment transactions
1. I added two extra columns to bank_trans table to save cheques and voucher no

ALTER TABLE `bank_trans` ADD `check_no` VARCHAR(60) NOT NULL AFTER `ref`, ADD `source_ref` VARCHAR(60) NOT NULL AFTER `check_no`, ADD UNIQUE (`check_no`), ADD UNIQUE (`source_ref`);  

2. gl_bank.php file I added the following codes :

function create_cart($type, $trans_no)
{
    global $Refs;

    if (isset($_SESSION['pay_items']))
    {
        unset ($_SESSION['pay_items']);
    }

    $cart = new items_cart($type);
        $cart->order_id = $trans_no;

    if ($trans_no) {

        $bank_trans = db_fetch(get_bank_trans($type, $trans_no));
        $_POST['bank_account'] = $bank_trans["bank_act"];
        $_POST['PayType']      = $bank_trans["person_type_id"];
        $cart->reference       = $bank_trans["ref"];
        $_POST['check_no']     = $bank_trans["check_no"];  // New field for table check no

        if ($bank_trans["person_type_id"] == PT_CUSTOMER)
        {
            $trans = get_customer_trans($trans_no, $type);    
            $_POST['person_id'] = $trans["debtor_no"];
            $_POST['PersonDetailID'] = $trans["branch_code"];
        }
        elseif ($bank_trans["person_type_id"] == PT_SUPPLIER)
        {
            $trans = get_supp_trans($trans_no, $type);
            $_POST['person_id'] = $trans["supplier_id"];
        }
        elseif ($bank_trans["person_type_id"] == PT_MISC)
            $_POST['person_id'] = $bank_trans["person_id"];
        elseif ($bank_trans["person_type_id"] == PT_QUICKENTRY)
            $_POST['person_id'] = $bank_trans["person_id"];
        else 
            $_POST['person_id'] = $bank_trans["person_id"];

        $cart->memo_     = get_comments_string($type, $trans_no);
        $cart->tran_date = sql2date($bank_trans['trans_date']);

        $cart->original_amount = $bank_trans['amount'];
        $result = get_gl_trans($type, $trans_no);
        if ($result) {
            while ($row = db_fetch($result)) {
                if (is_bank_account($row['account'])) {
                    // date exchange rate is currenly not stored in bank transaction,
                    // so we have to restore it from original gl amounts
                    $ex_rate = $bank_trans['amount']/$row['amount'];
                } else {
                    $cart->add_gl_item( $row['account'], $row['dimension_id'],
                        $row['dimension2_id'], $row['amount'], $row['memo_']);
                }
            }
        }

        // apply exchange rate
        foreach($cart->gl_items as $line_no => $line)
            $cart->gl_items[$line_no]->amount *= $ex_rate;

    } else {
        $cart->reference = $Refs->get_next($cart->trans_type, null, $cart->tran_date);
        $cart->tran_date = new_doc_date();
        if (!is_date_in_fiscalyear($cart->tran_date))
            $cart->tran_date = end_fiscalyear();
    }

    $_POST['memo_']      = $cart->memo_;
    $_POST['ref']        = $cart->reference;
    $_POST['check_no']   = $cart->check_no; // Check no
    $_POST['source_ref'] = $cart->source_ref;  // voucher no
    $_POST['date_']      = $cart->tran_date;

    $_SESSION['pay_items'] = &$cart;
}

step 3 : gl_db_bank_trans.inc:

//-----------------------------------------------------------------------------------------------
// add a bank transaction
// $amount is in $currency
// $date_ is display date (non-sql)

function add_bank_trans($type, $trans_no, $bank_act, $ref, $check_no, $source_ref,$date_,
    $amount, $person_type_id, $person_id, $currency="", $err_msg="", $rate=0)
{
    $sqlDate = date2sql($date_);

    // convert $amount to the bank's currency
    if ($currency != "")
    {
        $bank_account_currency = get_bank_account_currency($bank_act);
        if ($rate == 0)
            $to_bank_currency = get_exchange_rate_from_to($currency, $bank_account_currency, $date_);
        else
            $to_bank_currency = 1 / $rate;
        $amount_bank = ($amount / $to_bank_currency);
    }
    else
        $amount_bank = $amount;
    $amount_bank = round2($amount_bank, user_price_dec());    

    $sql = "INSERT INTO ".TB_PREF."bank_trans (type, trans_no, bank_act, ref,check_no, source_ref,
        trans_date, amount, person_type_id, person_id) ";

    //$sql .= "VALUES ($type, $trans_no, '$bank_act', ".db_escape($ref).", $check_no, $source_ref, '$sqlDate',
    //    ".db_escape($amount_bank).", ".db_escape($person_type_id)
//        .", ". db_escape($person_id).")";

    $sql .= "VALUES ($type, $trans_no, '$bank_act', ".db_escape($ref).", ".db_escape($check_no).",".db_escape($source_ref).",$sqlDate',
        ".db_escape($amount_bank).", ".db_escape($person_type_id)
        .", ". db_escape($person_id).")";


    if ($err_msg == "")
        $err_msg = "The bank transaction could not be inserted";

    db_query($sql, $err_msg);
}

STEP 4:  gl_db_banking.inc:

//----------------------------------------------------------------------------------------

function write_bank_transaction($trans_type, $trans_no, $from_account, $items, $date_,
    $person_type_id, $person_id, $person_detail_id,    $ref, $check_no, $source_ref , $memo_ , $use_transaction=true, $settled_amount=null)
{
    global $Refs, $SysPrefs;

    // we can only handle type 1 (payment)and type 2 (deposit)
    if ($trans_type != ST_BANKPAYMENT && $trans_type != ST_BANKDEPOSIT)
        display_db_error("Invalid type ($trans_type) sent to add_bank_transaction");

    $do_exchange_variance = false;
    $exchanged = false;
    if ($use_transaction)
        begin_transaction();

    $args = func_get_args(); if (count($args) < 13) $args[] = true;
    $args = (object)array_combine(array('trans_type', 'trans_no', 'from_account', 'items', 'date_',
        'person_type_id', 'person_id', 'person_detail_id', 'ref','check_no','source_ref', 'memo_', 'use_transaction', 'settled_amount'),
        $args);
    hook_db_prewrite($args, $trans_type);

    $aid = 0;
    if ($trans_no) {
        $old_trans = $trans_no;
        $Refs->restore_last($trans_type, $trans_no);
        $aid = has_attachment($trans_type, $trans_no);
    } else
        $old_trans = false;

    $currency = get_bank_account_currency($from_account);
    $bank_gl_account = get_bank_gl_account($from_account);

    // the gl items are already inversed/negated for type 2 (deposit)
    $total_amount = $items->gl_items_total();

    if ($person_type_id == PT_CUSTOMER)
    {
        // we need to add a customer transaction record
        // convert to customer currency
        if (!isset($settled_amount)) // leaved for backward/ext compatibility 
            $cust_amount = exchange_from_to(abs($total_amount), $currency, get_customer_currency($person_id), $date_);
        else
            $cust_amount = $settled_amount;

        if ($trans_type == ST_BANKPAYMENT)
            $cust_amount = -$cust_amount;

        $trans_no = write_customer_trans($trans_type, 0, $person_id, $person_detail_id, $date_,
            $ref,$check_no,$source_ref, $cust_amount);
        if ($old_trans)
            move_trans_attachments($trans_type, $old_trans, $trans_no);
    }
    elseif ($person_type_id == PT_SUPPLIER)
    {
        // we need to add a supplier transaction record
        // convert to supp currency
        if (!isset($settled_amount)) // leaved for for backward/ext compatibility 
            $supp_amount = exchange_from_to(abs($total_amount), $currency, get_supplier_currency($person_id), $date_);
        else
            $supp_amount = $settled_amount;

        if ($trans_type == ST_BANKPAYMENT)
            $supp_amount = -$supp_amount;

        $trans_no = write_supp_trans($trans_type, 0, $person_id, $date_, '',
            $ref, "", $supp_amount, 0, 0);
        if ($old_trans)
            move_trans_attachments($trans_type, $old_trans, $trans_no);
    }
    else
    {
           $trans_no = get_next_trans_no($trans_type);
        $do_exchange_variance = $SysPrefs->auto_currency_revaluation();
        if ($do_exchange_variance)
            $trans_no1 = get_next_trans_no(ST_JOURNAL);
    }
    if ($aid != 0)
    {
        $row = get_attachment($aid);
        update_attachment($aid, $row['type_no'], $trans_no, $row['description'],
            $row['filename'], $row['unique_name'], $row['filesize'], $row['filetype']);
    }
    // do the source account postings

    add_bank_trans($trans_type, $trans_no, $from_account, $ref, $check_no, $source_ref,
        $date_, -$total_amount,
        $person_type_id, $person_id,
        $currency,
        "Cannot insert a source bank transaction");
    $total = 0;
    foreach ($items->gl_items as $gl_item)
    {
        $is_bank_to = is_bank_account($gl_item->code_id);

        if ($trans_type == ST_BANKPAYMENT AND $is_bank_to)
        {
            // we don't allow payments to go to a bank account. use transfer for this !
            display_db_error("invalid payment entered. Cannot pay to another bank account", "");
        }

        // do the destination account postings
        $total += add_gl_trans($trans_type, $trans_no, $date_, $gl_item->code_id,
            $gl_item->dimension_id, $gl_item->dimension2_id, $gl_item->reference,
            $gl_item->amount, $currency, $person_type_id, $person_id);

        if ($is_bank_to)
        {
            add_bank_trans($trans_type, $trans_no, $is_bank_to, $ref, $check_no,$source_ref,
                $date_, $gl_item->amount,
                $person_type_id, $person_id, $currency,
                "Cannot insert a destination bank transaction");
            if ($do_exchange_variance)
            {
                add_exchange_variation($trans_no1, $date_, $is_bank_to, $gl_item->code_id, 
                    $currency, $person_type_id, $person_id);
            }
        }
        // store tax details if the gl account is a tax account

        $amount = $gl_item->amount;
        $ex_rate = get_exchange_rate_from_home_currency($currency, $date_);

        add_gl_tax_details($gl_item->code_id, $trans_type, $trans_no, -$amount,
            $ex_rate, $date_, $memo_);
    }

    // do the source account postings
    add_gl_trans($trans_type, $trans_no, $date_, $bank_gl_account, 0, 0, $memo_,
        -$total, null, $person_type_id, $person_id);

    if ($do_exchange_variance)
    {
        if ($exchanged || add_exchange_variation($trans_no1, $date_, $from_account, $bank_gl_account, 
            $currency, $person_type_id, $person_id))
        {
               $ref1 = $Refs->get_next(ST_JOURNAL, null, $date_);
            $Refs->save(ST_JOURNAL, $trans_no1, $ref1);
            add_audit_trail(ST_JOURNAL, $trans_no1, $date_);
        }
    }

    add_comments($trans_type, $trans_no, $date_, $memo_);

    $Refs->save($trans_type, $trans_no, $ref, $check_no);
    add_audit_trail($trans_type, $trans_no, $date_);

    // old transaction can be voided only after new transaction is entered,
    //  otherwise the operation could fail for cash accounts due to temporary negative balance
    if ($old_trans) 
    {
        $msg = void_transaction($trans_type, $old_trans, Today(), _("Document reentered."));
        if ($msg)
        {
            display_error($msg);
            return false;
        }
    }


    $args->trans_no = $trans_no;
    hook_db_postwrite($args, $trans_type);
    if ($use_transaction)
        commit_transaction();

    return array($trans_type, $trans_no);
}

STEP 5 : gl_bank_ui.inc:

function display_bank_header(&$order)
{
    global $Ajax;
    $payment = $order->trans_type == ST_BANKPAYMENT;

    $customer_error = false;
    div_start('pmt_header');

    start_outer_table(TABLESTYLE2, "width='90%'"); // outer table

    table_section(1);
    
         date_row(_("Date:"), 'date_', '', true, 0, 0, 0, null, true);

    ref_row(_("Reference:"), 'ref', '', $order->reference, false, $order->trans_type, get_post('date_')); 
   // text_row(_("check No:"), 'check_no', $_POST['check_no'], 16, 40);
    text_row(_("Check No:"),  'check_no', $_POST['check_no'], 16, 40); // Newly Added
   
    table_section(2, "33%");

    if (!isset($_POST['PayType']))
    {
        if (isset($_GET['PayType']))
            $_POST['PayType'] = $_GET['PayType'];
        else
            $_POST['PayType'] = "";
    }
    if (!isset($_POST['person_id']))
    {
        if (isset($_GET['PayPerson']))
            $_POST['person_id'] = $_GET['PayPerson'];
        else
            $_POST['person_id'] = "";
    }
    if (isset($_POST['_PayType_update'])) {
        $_POST['person_id'] = '';
        $Ajax->activate('pmt_header');
        $Ajax->activate('code_id');
        $Ajax->activate('pagehelp');
        $Ajax->activate('editors');
        $Ajax->activate('footer');
    }
    payment_person_types_list_row( $payment ? _("Pay To:"):_("From:"),
         'PayType', $_POST['PayType'], true);
    switch ($_POST['PayType'])
    {
        case PT_MISC :
            text_row_ex($payment ?_("To the Order of:"):_("Name:"),
                 'person_id', 20, 50);
           text_row(_("Voucher No:"), 'source_ref', null, 20, 50);    // Newly Added
            break;
        case PT_SUPPLIER :
            supplier_list_row(_("Supplier:"), 'person_id', null, false, true, false, true);
            text_row(_("Voucher No:"), 'source_ref', null, 20, 50);     // Newly added
            break;
        case PT_CUSTOMER :
            customer_list_row(_("Customer:"), 'person_id', null, false, true, false, true);
            text_row(_("Voucher No:"), 'source_ref', null, 20, 50);    //New Line

            if (db_customer_has_branches($_POST['person_id']))
            {
                customer_branches_list_row(_("Branch:"), $_POST['person_id'], 
                    'PersonDetailID', null, false, true, true, true);
            }
            else
            {
                $_POST['PersonDetailID'] = ANY_NUMERIC;
                hidden('PersonDetailID');
            }
            $trans = get_customer_habit($_POST['person_id']); // take care of customers on hold
            if ($trans['dissallow_invoices'] != 0)
            {
                if ($payment)
                {
                    $customer_error = true;
                    display_error(_("This customer account is on hold."));
                }
                else
                    display_warning(_("This customer account is on hold."));
            }
            break;

        case PT_QUICKENTRY :
            quick_entries_list_row(_("Type").":", 'person_id', null, ($payment ? QE_PAYMENT : QE_DEPOSIT), true);
            $qid = get_quick_entry(get_post('person_id'));

            if (list_updated('person_id')) {
                unset($_POST['totamount']); // enable default
                $Ajax->activate('footer');
                $Ajax->activate('totamount');
            }
            amount_row($qid['base_desc'].":", 'totamount', price_format($qid['base_amount']),
                 null, "&nbsp;&nbsp;".submit('go', _("Go"), false, false, true));
            text_row(_("Voucher No:"), 'source_ref', null, 20, 50);    // New Line
            break;

    }

    table_section(3, "33%");

    if (!$order->order_id && !get_post('bank_account'))
    {
        if ($_POST['PayType'] == PT_CUSTOMER)
            $_POST['bank_account'] = get_default_customer_bank_account($_POST['person_id']);
        elseif ($_POST['PayType'] == PT_SUPPLIER)    
            $_POST['bank_account'] = get_default_supplier_bank_account($_POST['person_id']);
        else
            unset($_POST['bank_account']);
    }        
    
    bank_accounts_list_row( $payment ? _("From:") : _("Into:"), 'bank_account', null, true);
    if ($payment)
        bank_balance_row($_POST['bank_account']);

    $bank_currency = get_bank_account_currency($_POST['bank_account']);

    exchange_rate_display(get_company_currency(), $bank_currency, $_POST['date_']);

    end_outer_table(1); // outer table

    div_end();
    if ($customer_error)
    {
        end_form();
        end_page();
        exit;
    }
}
//---------------------------------------------------------------------------------
tom.horton wrote:

that didn't work this is the error i am getting now.


DATABASE ERROR : Cannot insert a source bank transaction
error code : 1064
error message : You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '', '-500', '0', 'ethan')' at line 2
sql that failed was : INSERT INTO bank_trans (type, trans_no, bank_act, ref,check_no, source_ref, trans_date, amount, person_type_id, person_id) VALUES (1, 130, '3', '001/2021', 'CHK 1011','jv 2424',2021-01-17', '-500', '0', 'ethan')

//----------------------------------------------------------------------------------
//    Add bank payment or deposit to database.
//
//    $from_account - bank account id
//  $items - transaction cart (line amounts in bank account's currency); negative for deposit
//  $person_type_id - defines type of $person_id identifiers
//  $person_id    - supplier/customer/other id
//  $person_detail_id - customer branch id or not used
//  $settled_amount - settled amount in AR/AP (if applicable) in customer/supplier currency (always non-negative number)
//
// returns an array of (inserted trans type, trans no)
//
// FIXME -revise code for update case
//
function write_bank_transaction($trans_type, $trans_no, $from_account, $items, $date_,
    $person_type_id, $person_id, $person_detail_id,    $ref, $check_no, $source_ref , $memo_ , $use_transaction=true, $settled_amount=null)
{
    global $Refs, $SysPrefs;

    // we can only handle type 1 (payment)and type 2 (deposit)
    if ($trans_type != ST_BANKPAYMENT && $trans_type != ST_BANKDEPOSIT)
        display_db_error("Invalid type ($trans_type) sent to add_bank_transaction");

    $do_exchange_variance = false;
    $exchanged = false;
    if ($use_transaction)
        begin_transaction();

    $args = func_get_args(); if (count($args) < 13) $args[] = true;
    $args = (object)array_combine(array('trans_type', 'trans_no', 'from_account', 'items', 'date_',
        'person_type_id', 'person_id', 'person_detail_id', 'ref','check_no','source_ref', 'memo_', 'use_transaction', 'settled_amount'),
        $args);
    hook_db_prewrite($args, $trans_type);

    $aid = 0;
    if ($trans_no) {
        $old_trans = $trans_no;
        $Refs->restore_last($trans_type, $trans_no);
        $aid = has_attachment($trans_type, $trans_no);
    } else
        $old_trans = false;

    $currency = get_bank_account_currency($from_account);
    $bank_gl_account = get_bank_gl_account($from_account);

    // the gl items are already inversed/negated for type 2 (deposit)
    $total_amount = $items->gl_items_total();

    if ($person_type_id == PT_CUSTOMER)
    {
        // we need to add a customer transaction record
        // convert to customer currency
        if (!isset($settled_amount)) // leaved for backward/ext compatibility
            $cust_amount = exchange_from_to(abs($total_amount), $currency, get_customer_currency($person_id), $date_);
        else
            $cust_amount = $settled_amount;

        if ($trans_type == ST_BANKPAYMENT)
            $cust_amount = -$cust_amount;

        $trans_no = write_customer_trans($trans_type, 0, $person_id, $person_detail_id, $date_,
            $ref,$check_no,$source_ref, $cust_amount);
        if ($old_trans)
            move_trans_attachments($trans_type, $old_trans, $trans_no);
    }
    elseif ($person_type_id == PT_SUPPLIER)
    {
        // we need to add a supplier transaction record
        // convert to supp currency
        if (!isset($settled_amount)) // leaved for for backward/ext compatibility
            $supp_amount = exchange_from_to(abs($total_amount), $currency, get_supplier_currency($person_id), $date_);
        else
            $supp_amount = $settled_amount;

        if ($trans_type == ST_BANKPAYMENT)
            $supp_amount = -$supp_amount;

        $trans_no = write_supp_trans($trans_type, 0, $person_id, $date_, '',
            $ref, "", $supp_amount, 0, 0);
        if ($old_trans)
            move_trans_attachments($trans_type, $old_trans, $trans_no);
    }
    else
    {
           $trans_no = get_next_trans_no($trans_type);
        $do_exchange_variance = $SysPrefs->auto_currency_revaluation();
        if ($do_exchange_variance)
            $trans_no1 = get_next_trans_no(ST_JOURNAL);
    }
    if ($aid != 0)
    {
        $row = get_attachment($aid);
        update_attachment($aid, $row['type_no'], $trans_no, $row['description'],
            $row['filename'], $row['unique_name'], $row['filesize'], $row['filetype']);
    }
    // do the source account postings

    add_bank_trans($trans_type, $trans_no, $from_account, $ref, $check_no, $source_ref,
        $date_, -$total_amount,
        $person_type_id, $person_id,
        $currency,
        "Cannot insert a source bank transaction");
    $total = 0;
    foreach ($items->gl_items as $gl_item)
    {
        $is_bank_to = is_bank_account($gl_item->code_id);

        if ($trans_type == ST_BANKPAYMENT AND $is_bank_to)
        {
            // we don't allow payments to go to a bank account. use transfer for this !
            display_db_error("invalid payment entered. Cannot pay to another bank account", "");
        }

        // do the destination account postings
        $total += add_gl_trans($trans_type, $trans_no, $date_, $gl_item->code_id,
            $gl_item->dimension_id, $gl_item->dimension2_id, $gl_item->reference,
            $gl_item->amount, $currency, $person_type_id, $person_id);

        if ($is_bank_to)
        {
            add_bank_trans($trans_type, $trans_no, $is_bank_to, $ref, $check_no,$source_ref,
                $date_, $gl_item->amount,
                $person_type_id, $person_id, $currency,
                "Cannot insert a destination bank transaction");
            if ($do_exchange_variance)
            {
                add_exchange_variation($trans_no1, $date_, $is_bank_to, $gl_item->code_id,
                    $currency, $person_type_id, $person_id);
            }
        }
        // store tax details if the gl account is a tax account

        $amount = $gl_item->amount;
        $ex_rate = get_exchange_rate_from_home_currency($currency, $date_);

        add_gl_tax_details($gl_item->code_id, $trans_type, $trans_no, -$amount,
            $ex_rate, $date_, $memo_);
    }

    // do the source account postings
    add_gl_trans($trans_type, $trans_no, $date_, $bank_gl_account, 0, 0, $memo_,
        -$total, null, $person_type_id, $person_id);

    if ($do_exchange_variance)
    {
        if ($exchanged || add_exchange_variation($trans_no1, $date_, $from_account, $bank_gl_account,
            $currency, $person_type_id, $person_id))
        {
               $ref1 = $Refs->get_next(ST_JOURNAL, null, $date_);
            $Refs->save(ST_JOURNAL, $trans_no1, $ref1);
            add_audit_trail(ST_JOURNAL, $trans_no1, $date_);
        }
    }

    add_comments($trans_type, $trans_no, $date_, $memo_);

    $Refs->save($trans_type, $trans_no, $ref, $check_no);
    add_audit_trail($trans_type, $trans_no, $date_);

    // old transaction can be voided only after new transaction is entered,
    //  otherwise the operation could fail for cash accounts due to temporary negative balance
    if ($old_trans)
    {
        $msg = void_transaction($trans_type, $old_trans, Today(), _("Document reentered."));
        if ($msg)
        {
            display_error($msg);
            return false;
        }
    }


    $args->trans_no = $trans_no;
    hook_db_postwrite($args, $trans_type);
    if ($use_transaction)
        commit_transaction();

    return array($trans_type, $trans_no);
}

// this is for     gl_bank_ui.inc

function display_bank_header(&$order)
{
    global $Ajax;
    $payment = $order->trans_type == ST_BANKPAYMENT;

    $customer_error = false;
    div_start('pmt_header');

    start_outer_table(TABLESTYLE2, "width='90%'"); // outer table

    table_section(1);
   
         date_row(_("Date:"), 'date_', '', true, 0, 0, 0, null, true);

    ref_row(_("Reference:"), 'ref', '', $order->reference, false, $order->trans_type, get_post('date_'));
   // text_row(_("check No:"), 'check_no', $_POST['check_no'], 16, 40);
    text_row(_("Check No:"),  'check_no', $_POST['check_no'], 16, 40); // Newly Added
   
    table_section(2, "33%");

    if (!isset($_POST['PayType']))
    {
        if (isset($_GET['PayType']))
            $_POST['PayType'] = $_GET['PayType'];
        else
            $_POST['PayType'] = "";
    }
    if (!isset($_POST['person_id']))
    {
        if (isset($_GET['PayPerson']))
            $_POST['person_id'] = $_GET['PayPerson'];
        else
            $_POST['person_id'] = "";
    }
    if (isset($_POST['_PayType_update'])) {
        $_POST['person_id'] = '';
        $Ajax->activate('pmt_header');
        $Ajax->activate('code_id');
        $Ajax->activate('pagehelp');
        $Ajax->activate('editors');
        $Ajax->activate('footer');
    }
    payment_person_types_list_row( $payment ? _("Pay To:"):_("From:"),
         'PayType', $_POST['PayType'], true);
    switch ($_POST['PayType'])
    {
        case PT_MISC :
            text_row_ex($payment ?_("To the Order of:"):_("Name:"),
                 'person_id', 20, 50);
           text_row(_("Voucher No:"), 'source_ref', null, 20, 50);    // Newly Added
            break;
        case PT_SUPPLIER :
            supplier_list_row(_("Supplier:"), 'person_id', null, false, true, false, true);
            text_row(_("Voucher No:"), 'source_ref', null, 20, 50);     // Newly added
            break;
        case PT_CUSTOMER :
            customer_list_row(_("Customer:"), 'person_id', null, false, true, false, true);
            text_row(_("Voucher No:"), 'source_ref', null, 20, 50);    //New Line

            if (db_customer_has_branches($_POST['person_id']))
            {
                customer_branches_list_row(_("Branch:"), $_POST['person_id'],
                    'PersonDetailID', null, false, true, true, true);
            }
            else
            {
                $_POST['PersonDetailID'] = ANY_NUMERIC;
                hidden('PersonDetailID');
            }
            $trans = get_customer_habit($_POST['person_id']); // take care of customers on hold
            if ($trans['dissallow_invoices'] != 0)
            {
                if ($payment)
                {
                    $customer_error = true;
                    display_error(_("This customer account is on hold."));
                }
                else
                    display_warning(_("This customer account is on hold."));
            }
            break;

        case PT_QUICKENTRY :
            quick_entries_list_row(_("Type").":", 'person_id', null, ($payment ? QE_PAYMENT : QE_DEPOSIT), true);
            $qid = get_quick_entry(get_post('person_id'));

            if (list_updated('person_id')) {
                unset($_POST['totamount']); // enable default
                $Ajax->activate('footer');
                $Ajax->activate('totamount');
            }
            amount_row($qid['base_desc'].":", 'totamount', price_format($qid['base_amount']),
                 null, "&nbsp;&nbsp;".submit('go', _("Go"), false, false, true));
            text_row(_("Voucher No:"), 'source_ref', null, 20, 50);    // New Line
            break;

    }

    table_section(3, "33%");

    if (!$order->order_id && !get_post('bank_account'))
    {
        if ($_POST['PayType'] == PT_CUSTOMER)
            $_POST['bank_account'] = get_default_customer_bank_account($_POST['person_id']);
        elseif ($_POST['PayType'] == PT_SUPPLIER)   
            $_POST['bank_account'] = get_default_supplier_bank_account($_POST['person_id']);
        else
            unset($_POST['bank_account']);
    }       
   
    bank_accounts_list_row( $payment ? _("From:") : _("Into:"), 'bank_account', null, true);
    if ($payment)
        bank_balance_row($_POST['bank_account']);

    $bank_currency = get_bank_account_currency($_POST['bank_account']);

    exchange_rate_display(get_company_currency(), $bank_currency, $_POST['date_']);

    end_outer_table(1); // outer table

    div_end();
    if ($customer_error)
    {
        end_form();
        end_page();
        exit;
    }
}

Code under gl_banking.php

function create_cart($type, $trans_no)
{
    global $Refs;

    if (isset($_SESSION['pay_items']))
    {
        unset ($_SESSION['pay_items']);
    }

    $cart = new items_cart($type);
    $cart->order_id = $trans_no;

    if ($trans_no) {

        $bank_trans = db_fetch(get_bank_trans($type, $trans_no));
        $_POST['bank_account'] = $bank_trans["bank_act"];
        $_POST['PayType']      = $bank_trans["person_type_id"];
        $cart->reference       = $bank_trans["ref"];
        $_POST['check_no']     = $bank_trans["check_no"];

        if ($bank_trans["person_type_id"] == PT_CUSTOMER)
        {
            $trans = get_customer_trans($trans_no, $type);   
            $_POST['person_id'] = $trans["debtor_no"];
            $_POST['PersonDetailID'] = $trans["branch_code"];
        }
        elseif ($bank_trans["person_type_id"] == PT_SUPPLIER)
        {
            $trans = get_supp_trans($trans_no, $type);
            $_POST['person_id'] = $trans["supplier_id"];
        }
        elseif ($bank_trans["person_type_id"] == PT_MISC)
            $_POST['person_id'] = $bank_trans["person_id"];
        elseif ($bank_trans["person_type_id"] == PT_QUICKENTRY)
            $_POST['person_id'] = $bank_trans["person_id"];
        else
            $_POST['person_id'] = $bank_trans["person_id"];

        $cart->memo_     = get_comments_string($type, $trans_no);
        $cart->tran_date = sql2date($bank_trans['trans_date']);

        $cart->original_amount = $bank_trans['amount'];
        $result = get_gl_trans($type, $trans_no);
        if ($result) {
            while ($row = db_fetch($result)) {
                if (is_bank_account($row['account'])) {
                    // date exchange rate is currenly not stored in bank transaction,
                    // so we have to restore it from original gl amounts
                    $ex_rate = $bank_trans['amount']/$row['amount'];
                } else {
                    $cart->add_gl_item( $row['account'], $row['dimension_id'],
                        $row['dimension2_id'], $row['amount'], $row['memo_']);
                }
            }
        }

        // apply exchange rate
        foreach($cart->gl_items as $line_no => $line)
            $cart->gl_items[$line_no]->amount *= $ex_rate;

    } else {
        $cart->reference = $Refs->get_next($cart->trans_type, null, $cart->tran_date);
        $cart->tran_date = new_doc_date();
        if (!is_date_in_fiscalyear($cart->tran_date))
            $cart->tran_date = end_fiscalyear();
    }

    $_POST['memo_']      = $cart->memo_;
    $_POST['ref']        = $cart->reference;
    $_POST['check_no']   = $cart->check_no;
    $_POST['source_ref'] = $cart->source_ref;
    $_POST['date_']      = $cart->tran_date;

    $_SESSION['pay_items'] = &$cart;
}

Yeah it is in a string format.
its should pick it right?

But this error tells that the number of data to be inserted is not equal with the value

array_combine(): Both parameters should have an equal number of element

48

(6 replies, posted in Setup)

@rafat  I know this is not a place for this post to be but I hope somebody can give a answer.

I have alter my payment table to add 2 extra column, check_no, source_ref to process my bank payments as all my bank payment require a checks, and cash payment voucher(source_ref). Now when I want to process a payment I get this error below:

What I understand is that the number of data being sent in the database does not correspond to the field required. Would you please tell me where I should add the 2 columns from UI?  I also wanted to put validation to check if a check no is already inserted to refuse duplicates.

Great Thanks!

array_combine(): Both parameters should have an equal number of elements in file: /var/www/html/fms/gl/includes/db/gl_db_banking.inc at line 394DATABASE ERROR : Cannot insert a source bank transaction
error code : 1064
error message : You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'for computer services, 1, '2021-01-07', '-10500', '0', 'Cedrick ')' at line 2
sql that failed was : INSERT INTO bank_trans (type, trans_no, bank_act, ref,check_no, source_ref, trans_date, amount, person_type_id, person_id) VALUES (1, 130, '3', '001/2021', payment for computer services, 1, '2021-01-07', '-10500', '0', 'Cedrick ')

great, i think we figure it out together well.

Hope this will help others to be careful when the register assets. a little tiny detail could make everything wrong.

I appreciate your time Boss!

Bless Up!

Wait a minute, does it matter if the depreciation starting date and the purchase date are different?
I didn't get to check that closely.

What i mean is for example:

I create create asset class, category and insert asset depreciation date as well. say 2017.
Now when i am purchasing the asset, i put purchase date 2018, will that bring confusion to the system?
Could that be the issue? Though I am not sure if that's what I did.