Ok so I copied all the persons for each branch and it still fails. There is something else going on here.

/sales/manage/customer_branches.php

will fail and hang on large numbers of branches for clients ( 745 branches)
fetch time for any client increases if more branches are made even for other clients. I think the issue might be is our same crm persons are listed on the other customer branches in crm contacts.

Example
Debtor (MHN Health Net Insurance)
Branch (MHN Patient Jim) -> Crm Person (Patient Jim)

Debtor (Anthem Blue Cross)
Branch (Anthem Patient Jim) -> Crm Person (Patient Jim)

Person is the same that both branches are referencing so they both point to the same ID.

SQL Called on page

SET sql_mode = 'STRICT_ALL_TABLES'
SELECT name, value FROM 0_sys_prefs
SELECT value FROM 0_sys_prefs WHERE name='version_id'
SELECT name, value FROM 0_sys_prefs
SELECT COUNT(*) FROM 0_debtors_master
SELECT COUNT(*) FROM 0_salesman
SELECT COUNT(*) FROM 0_areas
SELECT COUNT(*) FROM 0_shippers
SELECT COUNT(*) FROM 0_tax_groups
SELECT debtor_no, debtor_ref, curr_code, inactive FROM 0_debtors_master  ORDER BY debtor_ref
SELECT COUNT(*) FROM 0_cust_branch WHERE debtor_no='757'
SELECT COUNT(*) FROM (SELECT b.branch_code, b.branch_ref, b.br_name, p.name as contact_name, s.salesman_name, a.description, p.phone, p.fax, p.email, t.name AS tax_group_name, b.inactive
        FROM 0_cust_branch b LEFT JOIN 0_crm_contacts c
            ON c.entity_id=b.branch_code AND c.type='cust_branch' AND c.action='general'
            LEFT JOIN 0_crm_persons p on c.person_id=p.id,0_areas a, 0_salesman s, 0_tax_groups t
        WHERE b.tax_group_id=t.id
        AND b.area=a.area_code
        AND b.salesman=s.salesman_code
        AND b.debtor_no = '757' AND !b.inactive GROUP BY b.branch_code ORDER BY branch_ref) tmp_count
SELECT b.branch_code, b.branch_ref, b.br_name, p.name as contact_name, s.salesman_name, a.description, p.phone, p.fax, p.email, t.name AS tax_group_name, b.inactive
     FROM 0_cust_branch b LEFT JOIN 0_crm_contacts c
            ON c.entity_id=b.branch_code AND c.type='cust_branch' AND c.action='general'
            LEFT JOIN 0_crm_persons p on c.person_id=p.id,0_areas a, 0_salesman s, 0_tax_groups t
      WHERE (b.tax_group_id=t.id
        AND b.area=a.area_code
        AND b.salesman=s.salesman_code
        AND b.debtor_no = '757' AND !b.inactive) GROUP BY b.branch_code ORDER BY branch_ref LIMIT 0, 10
SELECT name, address, debtor_ref
        FROM 0_debtors_master WHERE debtor_no = '757'
SELECT salesman_code, salesman_name, inactive FROM 0_salesman ORDER BY salesman_name
SELECT area_code, description, inactive FROM 0_areas ORDER BY description
SELECT id, description, inactive FROM 0_groups ORDER BY description
SELECT loc_code, location_name, inactive FROM 0_locations WHERE fixed_asset=0 ORDER BY location_name
SELECT shipper_id, shipper_name, inactive FROM 0_shippers ORDER BY shipper_name
SELECT id, name, inactive FROM 0_tax_groups ORDER BY id
SELECT chart.account_code, chart.account_name, type.name, chart.inactive, type.id
            FROM 0_chart_master chart,0_chart_types type
            WHERE chart.account_type=type.id ORDER BY type.class_id,type.id,account_code
SELECT chart.account_code, chart.account_name, type.name, chart.inactive, type.id
            FROM 0_chart_master chart,0_chart_types type
            WHERE chart.account_type=type.id ORDER BY type.class_id,type.id,account_code
SELECT chart.account_code, chart.account_name, type.name, chart.inactive, type.id
            FROM (0_chart_master chart,0_chart_types type) LEFT JOIN 0_bank_accounts acc ON chart.account_code=acc.account_code
                WHERE acc.account_code  IS NULL
            AND chart.account_type=type.id ORDER BY type.class_id,type.id,account_code
SELECT chart.account_code, chart.account_name, type.name, chart.inactive, type.id
            FROM 0_chart_master chart,0_chart_types type
            WHERE chart.account_type=type.id ORDER BY type.class_id,type.id,account_code

Thanks for considering taking a look at this.
a though would be a branch select list with the first option for all branches then the other branches.

I can get it to output by branch by add this if statement to the loop

if ($_POST['BranchID'] == $myrow['branch_code']){
Blah blah do the table stuff here
}

but what is strange is the BranchID select box doesnt update any $_POST data?

only customer select and bank select appear to be working properly. To update $_POST['BranchID'] you have to select the branch then adjust the bank account to update it.

If you change the customer it will select the default first BranchID again so that works ok.

I have it outputting the Branch name in the table now. fairly easy

in
/includes/ui/allocation_cart.inc
in the function show_allocatable($show_totals)

add  Branch table header in the table loop pull the customer transaction data and add br name to the cell. This is how my function looks.

function show_allocatable($show_totals) {

    global $systypes_array;
    
    $k = $total_allocated = 0;

    $cart = $_SESSION['alloc'];
    $supp_ref = in_array($cart->type, array(ST_SUPPCREDIT, ST_SUPPAYMENT, ST_BANKPAYMENT));

    if (count($cart->allocs)) 
    {
        display_heading(sprintf(_("Allocated amounts in %s:"), $cart->person_curr));
        start_table(TABLESTYLE, "width='60%'");
           $th = array(_("Transaction Type"), _("#"), _("Branch"), $supp_ref ? _("Supplier Ref"): _("Ref"), _("Date"), _("Due Date"), _("Amount"),
               _("Other Allocations"), _("Left to Allocate"), _("This Allocation"),'',''); // added branch heading

           table_header($th);

        foreach ($cart->allocs as $id => $alloc_item)
        {
            if (floatcmp(abs($alloc_item->amount), $alloc_item->amount_allocated))
            {
                $myrow = get_customer_trans($alloc_item->type_no, ST_SALESINVOICE);// new to get trans data
                alt_table_row_color($k);
                label_cell($systypes_array[$alloc_item->type]);
                   label_cell(get_trans_view_str($alloc_item->type, $alloc_item->type_no), "nowrap align='right'");
                   label_cell($myrow['br_name'], "nowrap align='right'"); // to output branch
                   label_cell($alloc_item->ref);
                label_cell($alloc_item->date_, "align=right");
                label_cell($alloc_item->due_date, "align=right");
                amount_cell(abs($alloc_item->amount));
                amount_cell($alloc_item->amount_allocated);

                $_POST['amount' . $id] = price_format($alloc_item->current_allocated);

                $un_allocated = round((abs($alloc_item->amount) - $alloc_item->amount_allocated), 6);
                amount_cell($un_allocated, false,'', 'maxval'.$id);
                amount_cells(null, "amount" . $id);//, input_num('amount' . $id));
                label_cell("<a href='javascript:void(0)' name=Alloc$id onclick='allocate_all(this.name.substr(5));return true;'>"
                     . _("All") . "</a>");
                label_cell("<a href='javascript:void(0)' name=DeAll$id onclick='allocate_none(this.name.substr(5));return true;'>"
                     . _("None") . "</a>".hidden("un_allocated" . $id, 
                     price_format($un_allocated), false));
                end_row();

                   $total_allocated += input_num('amount' . $id);
               }
        }
        if ($show_totals) {
               label_row(_("Total Allocated"), price_format($total_allocated),
                "colspan=8 align=right", "align=right id='total_allocated'", 3);

            $amount = abs($cart->amount);

            if (floatcmp($amount, $total_allocated) < 0)
            {
                $font1 = "<font color=red>";
                $font2 = "</font>";
            }
            else
                $font1 = $font2 = "";
            $left_to_allocate = price_format($amount - $total_allocated);
            label_row(_("Left to Allocate"), $font1 . $left_to_allocate . $font2, 
                "colspan=8 align=right", "nowrap align=right id='left_to_allocate'",
                 3);
        }
        end_table(1);
    }
    hidden('TotalNumberOfAllocs', count($cart->allocs));
}

I will try to add logic to check the branch in the loop. if anyone good at this stuff can help lol
Thank you

Is it possible on the customer payments page show only the invoices by branch or at least have it show in the allocation table what branch the invoice belongs too. We have customers with over 800 branches and it is really difficult to find the correct invoice.

on this page
/sales/customer_payments.php

function in question
show_allocatable();
calls
class allocation
set_person()
read()

easy for invoices

reports_main.php                     (change the array)

$reports->addReport(RC_CUSTOMER, 107, _('Print &Invoices'),
    array(    //_('From') => 'INVOICE',       // removed for date
            //_('To') => 'INVOICE',         // removed for date  
            _('Start Date') => 'DATEBEGINM',    // added for date
            _('End Date') => 'DATEENDM',        // added for date
            _('Currency Filter') => 'CURRENCY',
            _('email Customers') => 'YES_NO',
            _('Payment Link') => 'PAYMENT_LINK',
            _('Comments') => 'TEXTBOX',
            _('Customer') => 'CUSTOMERS_NO_FILTER',
            _('Orientation') => 'ORIENTATION'
));

rep107.php         (change the function)

function get_invoice_range($from, $to, $currency=false)
{
    global $SysPrefs;
//--- new for date search instead of     
    $fromdate = date2sql($from);
    $todate = date2sql($to);
//---- End new stuff    


    $ref = ($SysPrefs->print_invoice_no() == 1 ? "trans_no" : "reference");

    $sql = "SELECT trans.trans_no, trans.reference";

//  if($currency !== false)
//        $sql .= ", cust.curr_code";

    $sql .= " FROM ".TB_PREF."debtor_trans trans 
            LEFT JOIN ".TB_PREF."voided voided ON trans.type=voided.type AND trans.trans_no=voided.id";

    if ($currency !== false)
        $sql .= " LEFT JOIN ".TB_PREF."debtors_master cust ON trans.debtor_no=cust.debtor_no";

    $sql .= " WHERE trans.type=".ST_SALESINVOICE
        ." AND ISNULL(voided.id)"
     //    ." AND trans.trans_no BETWEEN ".db_escape($from)." AND ".db_escape($to) //removed old
         ." AND trans.tran_date>='$fromdate'" // added this
        ." AND trans.tran_date<='$todate'";     //added this        

    if ($currency !== false)
        $sql .= " AND cust.curr_code=".db_escape($currency);

    $sql .= " ORDER BY trans.tran_date, trans.$ref";

    return db_query($sql, "Cant retrieve invoice range");
}

more difficult for deliveries

I find it hard to understand why the default reporting is by order created for invoices and delivery notes. Ok, maybe you go about your day entering some invoices then printing in batches. but couldn't you just click print right after creation if that is how you work?

Most people batch these things out by the day, most certainly deliveries. ie. You go about your work week or month scheduling deliveries to be efficient. then batch print all the delivery notes for the day. "Here you go Timmy here is your stops/deliveries for the day".

Then depending on what deliveries were completed you would invoice. so lets say Timmy comes back and didn't do some jobs. He gave you that reason about not feeling to good again. So you move the deliveries to a future date invoice the ones that were completed for the day and batch print or email them.

Maybe you mail invoices by date as well the whole month at once and make bills due on a date of the month. I can see many reasons why you would do date and not due order created.

What do you guys think?

33

(16 replies, posted in Wish List)

I agree with tm its what I did so you get the URL printed and the QR on the invoice

copy the library from here https://sourceforge.net/projects/phpqrc … t/download
to --> /reporting/includes/

in the file
/reporting/includes/doctext.inc

in the top

// add QR Support mod
    $path_to_root="..";
    include_once($path_to_root . "/reporting/includes/phpqrcode/qrlib.php");

    $tempDir = $path_to_root ."/company/1/pdf_files/"; // <--NOTE must be your temp location
// end

the if statement around line 270 should look like this

    if (@$this->formData['payment_service'])    //payment link
    {
        $amt = number_format($this->formData["ov_freight"] + $this->formData["ov_gst"] + $this->formData["ov_amount"], user_price_dec());
        $service = $this->formData['payment_service'];
        $url = payment_link($service, array(
            'company_email' => $this->company['email'],
            'amount' => $amt,
            'currency' => $this->formData['curr_code'],
            'comment' => $this->title . " " . $this->formData['reference'],
            'invoice' => $this->formData['document_number']
            ));
        $Footer[_("You can pay through"). " $service: "] = "$url";
// QR Mod
        $tempname = tempnam($tempDir,'QRcode');
        QRcode::png($url, $tempname.'.png', QR_ECLEVEL_L, 3);
        $this->Image($tempname.'.png',486,670,100,100);
// End
    }

Thank you, I ended up getting it working with the base fpdf built in function Image().
Now I just need to figure out where to put this thing. Haha it looks weird everywhere! I hate when things are not Symmetrical.

    if (@$this->formData['payment_service'])    //payment link
    {
        $amt = number_format($this->formData["ov_freight"] + $this->formData["ov_gst"] + $this->formData["ov_amount"], user_price_dec());
        $service = $this->formData['payment_service'];
        $url = payment_link($service, array(
            'company_email' => $this->company['email'],
            'amount' => $amt,
            'currency' => $this->formData['curr_code'],
            'comment' => $this->title . " " . $this->formData['reference'],
            'invoice' => $this->formData['reference']
            ));
        $Footer[_("You can pay through"). " $service: "] = "$url";
        QRcode::png($url, $tempDir.'030.png', QR_ECLEVEL_L, 3);
        $this->Image($tempDir.'030.png',35,540);
    }

I cant display a QR image in the Footer. I tried the $Footer[] array but I seams that It only displays text. I generate the QR from the URL in doctext.inc

 
    if (@$this->formData['payment_service'])    //payment link
    {
        $amt = number_format($this->formData["ov_freight"] + $this->formData["ov_gst"] + $this->formData["ov_amount"], user_price_dec());
        $service = $this->formData['payment_service'];
        $url = payment_link($service, array(
            'company_email' => $this->company['email'],
            'amount' => $amt,
            'currency' => $this->formData['curr_code'],
            'comment' => $this->title . " " . $this->formData['reference'],
            'invoice' => $this->formData['reference']
            ));
        $Footer[_("You can pay through"). " $service: "] = "$url";
        QRcode::png($url, $tempDir.'030.png', QR_ECLEVEL_L, 3);
    }

36

(1 replies, posted in Wish List)

We have an high interest bitcoin savings account that pays in bitcoin and have a few customers that pay in bitcoin. I would like to see better support for Bitcoin as a currency. As is the system works fine to account for as an asset (ie. capital gains or loss)

Bitcoin problems
1 The automatic get exchange rate does not function (but can be entered manually)
2 front accounting only supports one type of floating point number at a time. Can't have 2 decimal points "cents" for USD account and 8 decimal places for your BTC accounts. (That I know of) bit-cents are far to valueable already at 88 USD (My work around is to use the smallest value the Satoshis .00000001 BTC And disregarding the decimal place. Unfortunately, this could lead to many incorrect entries due to the strange nonstandard BTCformatting

Example .00432 BTC being entered as 432 Satoshi when it is 432000

BTC is gaining traction and I'm sure we will see much more in the coming years with the global recession.

Yes, unfortunately it shows voided invoices now Wished this could be removed and if you click the option to edit a voided it will throw a SQL error.

DATABASE ERROR : document version retreival
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 ')' at line 2
sql that failed was : SELECT trans_no, version FROM 2_debtor_trans WHERE type='13' AND ()

You  guys are awesome and that did work.

Just to let you know it still doesn't show the delivery notes in the 0.00 amount.

Thanks again, you guys are always the greatest

I just upgraded to 2.4.4 from 2.4.1 and it no longer shows sales invoices if they were for free i.e. 0.00

We create service invoices for 0.00 when work was guaranteed all the time and can no longer see the clients complete  work history.  The invoices can no longer be seen all types and I just noticed the delivery notes are missing as well.

Thank you

Sorry to delay on this response I've just been very busy.

I just wanted a question about the upgrade and this transaction.

Should I just do the update with the transaction how it is or should I void the transaction update then redo the transaction.

Basically, is it a problem how the transaction was written to the ledgers or just how it was interpreted / read from them.

Thank you.

Hello,

I have noticed if you debit a clients account receivables directly from a journal entry that there seems to be an error. when you check the client under Customer Transaction Inquiry all looks well but when creating a new invoice under Current Credit the calculation will be incorrect showing they have more credit available to them.

for Example

Sales Invoice    2/21/18 Debit 65.00
Sales Invoice  4/18/18 Debit 65.00
Customer Payment 4/20/18 Credit 65.00
Journal Entry 4/26/18 Debit 65.00 (Customer cheque was returned)

Client's balance should be 120.00 and it shows that in Customer Transaction Inquiry
but in enter direct invoice it shows 0.00 so it calculates the debit to A/R as a credit

42

(13 replies, posted in Reporting)

Ok here is a stock file with only the print invoice balance modifacations.

<?php
/**********************************************************************
    Copyright (C) FrontAccounting, LLC.
    Released under the terms of the GNU General Public License, GPL, 
    as published by the Free Software Foundation, either version 3 
    of the License, or (at your option) any later version.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
    See the License here <http://www.gnu.org/licenses/gpl-3.0.html>.
***********************************************************************/
$page_security = $_POST['PARAM_0'] == $_POST['PARAM_1'] ?
    'SA_SALESTRANSVIEW' : 'SA_SALESBULKREP';
// ----------------------------------------------------------------
// $ Revision:    2.0 $
// Creator:    Joe Hunt
// date_:    2005-05-19
// Title:    Print Invoices
// ----------------------------------------------------------------
$path_to_root="..";

include_once($path_to_root . "/includes/session.inc");
include_once($path_to_root . "/includes/date_functions.inc");
include_once($path_to_root . "/includes/data_checks.inc");
include_once($path_to_root . "/sales/includes/sales_db.inc");

//----------------------------------------------------------------------------------------------------
function get_invoice_range($from, $to)
{
    global $SysPrefs;

    $ref = ($SysPrefs->print_invoice_no() == 1 ? "trans_no" : "reference");

    $sql = "SELECT trans.trans_no, trans.reference
        FROM ".TB_PREF."debtor_trans trans 
            LEFT JOIN ".TB_PREF."voided voided ON trans.type=voided.type AND trans.trans_no=voided.id
        WHERE trans.type=".ST_SALESINVOICE
            ." AND ISNULL(voided.id)"
            ." AND trans.reference>=".db_escape(get_reference(ST_SALESINVOICE, $from))
            ." AND trans.reference<=".db_escape(get_reference(ST_SALESINVOICE, $to))
        ." ORDER BY trans.tran_date, trans.$ref";

    return db_query($sql, "Cant retrieve invoice range");
}

print_invoices();

//---------------------------------------------------------------------------------------------------- added from rep101 to get current balance


function get_open_balance($debtorno, $to)
{
    if($to)
        $to = date2sql($to);

     $sql = "SELECT SUM(IF(t.type = ".ST_SALESINVOICE." OR (t.type = ".ST_JOURNAL." AND t.ov_amount>0),
         -abs(t.ov_amount + t.ov_gst + t.ov_freight + t.ov_freight_tax + t.ov_discount), 0)) AS charges,";
     $sql .= "SUM(IF(t.type != ".ST_SALESINVOICE." AND NOT(t.type = ".ST_JOURNAL." AND t.ov_amount>0),
         abs(t.ov_amount + t.ov_gst + t.ov_freight + t.ov_freight_tax + t.ov_discount) * -1, 0)) AS credits,";
     $sql .= "SUM(IF(t.type != ".ST_SALESINVOICE." AND NOT(t.type = ".ST_JOURNAL." AND t.ov_amount>0), t.alloc * -1, t.alloc)) AS Allocated,";

     $sql .=    "SUM(IF(t.type = ".ST_SALESINVOICE.", 1, -1) *
             (abs(t.ov_amount + t.ov_gst + t.ov_freight + t.ov_freight_tax + t.ov_discount) - abs(t.alloc))) AS OutStanding
        FROM ".TB_PREF."debtor_trans t
        WHERE t.debtor_no = ".db_escape($debtorno)
        ." AND t.type <> ".ST_CUSTDELIVERY;
    if ($to)
        $sql .= " AND t.tran_date < '$to+1'"; // Has +1 to include any invoices created today in the balance
    $sql .= " GROUP BY debtor_no";

    $result = db_query($sql,"No transactions were returned");
    return db_fetch($result);
}


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

function print_invoices()
{
    global $path_to_root, $SysPrefs;
    
    $show_this_payment = true; // include payments invoiced here in summary

    include_once($path_to_root . "/reporting/includes/pdf_report.inc");

    $from = $_POST['PARAM_0'];
    $to = $_POST['PARAM_1'];
    $currency = $_POST['PARAM_2'];
    $email = $_POST['PARAM_3'];
    $pay_service = $_POST['PARAM_4'];
    $comments = $_POST['PARAM_5'];
    $customer = $_POST['PARAM_6'];
    $orientation = $_POST['PARAM_7'];

    if (!$from || !$to) return;

    $orientation = ($orientation ? 'L' : 'P');
    $dec = user_price_dec();

     $fno = explode("-", $from);
    $tno = explode("-", $to);
    $from = min($fno[0], $tno[0]);
    $to = max($fno[0], $tno[0]);

    //-------------code-Descr-Qty--uom--tax--prc--Disc-Tot--//
    $cols = array(4, 60, 225, 300, 325, 385, 450, 515);

    // $headers in doctext.inc
    $aligns = array('left',    'left',    'right', 'center', 'right', 'right', 'right');

    $params = array('comments' => $comments);

    $cur = get_company_Pref('curr_default');

    if ($email == 0)
        $rep = new FrontReport(_('INVOICE'), "InvoiceBulk", user_pagesize(), 9, $orientation);
    if ($orientation == 'L')
        recalculate_cols($cols);

    $range = get_invoice_range($from, $to);
    while($row = db_fetch($range))
    {
            if (!exists_customer_trans(ST_SALESINVOICE, $row['trans_no']))
                continue;
            $sign = 1;
            $myrow = get_customer_trans($row['trans_no'], ST_SALESINVOICE);

            if ($customer && $myrow['debtor_no'] != $customer) {
                continue;
            }
            if ($currency != ALL_TEXT && $myrow['curr_code'] != $currency) {
                continue;
            }
            $baccount = get_default_bank_account($myrow['curr_code']);
            $params['bankaccount'] = $baccount['id'];

            $branch = get_branch($myrow["branch_code"]);
            $sales_order = get_sales_order_header($myrow["order_"], ST_SALESORDER);
            if ($email == 1)
            {
                $rep = new FrontReport("", "", user_pagesize(), 9, $orientation);
                $rep->title = _('INVOICE');
                $rep->filename = "Invoice" . $myrow['reference'] . ".pdf";
            }    
            $rep->currency = $cur;
            $rep->Font();
            $rep->Info($params, $cols, null, $aligns);

            $contacts = get_branch_contacts($branch['branch_code'], 'invoice', $branch['debtor_no'], true);
            $baccount['payment_service'] = $pay_service;
            $rep->SetCommonData($myrow, $branch, $sales_order, $baccount, ST_SALESINVOICE, $contacts);
            $rep->SetHeaderType('Header2');
            $rep->NewPage();
            // calculate summary start row for later use
            $summary_start_row = $rep->bottomMargin + (15 * $rep->lineHeight);

            if ($rep->formData['prepaid'])
            {
                $result = get_sales_order_invoices($myrow['order_']);
                $prepayments = array();
                while($inv = db_fetch($result))
                {
                    $prepayments[] = $inv;
                    if ($inv['trans_no'] == $row['trans_no'])
                    break;
                }

                if (count($prepayments) > ($show_this_payment ? 0 : 1))
                    $summary_start_row += (count($prepayments)) * $rep->lineHeight;
                else
                    unset($prepayments);
            }

               $result = get_customer_trans_details(ST_SALESINVOICE, $row['trans_no']);
            $SubTotal = 0;
            while ($myrow2=db_fetch($result))
            {
                if ($myrow2["quantity"] == 0)
                    continue;

                $Net = round2($sign * ((1 - $myrow2["discount_percent"]) * $myrow2["unit_price"] * $myrow2["quantity"]),
                   user_price_dec());
                $SubTotal += $Net;
                $DisplayPrice = number_format2($myrow2["unit_price"],$dec);
                $DisplayQty = number_format2($sign*$myrow2["quantity"],get_qty_dec($myrow2['stock_id']));
                $DisplayNet = number_format2($Net,$dec);
                if ($myrow2["discount_percent"]==0)
                      $DisplayDiscount ="";
                else
                      $DisplayDiscount = number_format2($myrow2["discount_percent"]*100,user_percent_dec()) . "%";
                $c=0;
                $rep->TextCol($c++, $c,    $myrow2['stock_id'], -2);
                $oldrow = $rep->row;
                $rep->TextColLines($c++, $c, $myrow2['StockDescription'], -2);
                $newrow = $rep->row;
                $rep->row = $oldrow;
                if ($Net != 0.0 || !is_service($myrow2['mb_flag']) || !$SysPrefs->no_zero_lines_amount())
                {
                    $rep->TextCol($c++, $c,    $DisplayQty, -2);
                    $rep->TextCol($c++, $c,    $myrow2['units'], -2);
                    $rep->TextCol($c++, $c,    $DisplayPrice, -2);
                    $rep->TextCol($c++, $c,    $DisplayDiscount, -2);
                    $rep->TextCol($c++, $c,    $DisplayNet, -2);
                }
                $rep->row = $newrow;
                //$rep->NewLine(1);
                if ($rep->row < $summary_start_row)
                    $rep->NewPage();
            }

            $memo = get_comments_string(ST_SALESINVOICE, $row['trans_no']);
            if ($memo != "")
            {
                $rep->NewLine();
                $rep->TextColLines(1, 3, $memo, -2);
            }

               $DisplaySubTot = number_format2($SubTotal,$dec);

            // set to start of summary line:
            $rep->row = $summary_start_row;
            if (isset($prepayments))
            {
                // Partial invoices table
                $rep->TextCol(0, 3,_("Prepayments invoiced to this order up to day:"));
                $rep->TextCol(0, 3,    str_pad('', 150, '_'));
                $rep->cols[2] -= 20;
                $rep->aligns[2] = 'right';
                $rep->NewLine(); $c = 0; $tot_pym=0;
                $rep->TextCol(0, 3,    str_pad('', 150, '_'));
                $rep->TextCol($c++, $c, _("Date"));
                $rep->TextCol($c++, $c,    _("Invoice reference"));
                $rep->TextCol($c++, $c,    _("Amount"));

                foreach ($prepayments as $invoice)
                {
                    if ($show_this_payment || ($invoice['reference'] != $myrow['reference']))
                    {
                        $rep->NewLine();
                        $c = 0; $tot_pym += $invoice['prep_amount'];
                        $rep->TextCol($c++, $c,    sql2date($invoice['tran_date']));
                        $rep->TextCol($c++, $c,    $invoice['reference']);
                        $rep->TextCol($c++, $c, number_format2($invoice['prep_amount'], $dec));
                    }
                    if ($invoice['reference']==$myrow['reference']) break;
                }
                $rep->TextCol(0, 3,    str_pad('', 150, '_'));
                $rep->NewLine();
                $rep->TextCol(1, 2,    _("Total payments:"));
                $rep->TextCol(2, 3,    number_format2($tot_pym, $dec));
            }


            $doctype = ST_SALESINVOICE;
            $rep->row = $summary_start_row;
            $rep->cols[2] += 20;
            $rep->cols[3] += 20;
            $rep->aligns[3] = 'left';

            $rep->TextCol(3, 6, _("Sub-total"), -2);
            $rep->TextCol(6, 7,    $DisplaySubTot, -2);
            $rep->NewLine();
            if ($myrow['ov_freight'] != 0.0)
            {
                   $DisplayFreight = number_format2($sign*$myrow["ov_freight"],$dec);
                $rep->TextCol(3, 6, _("Shipping"), -2);
                $rep->TextCol(6, 7,    $DisplayFreight, -2);
                $rep->NewLine();
            }    
            $tax_items = get_trans_tax_details(ST_SALESINVOICE, $row['trans_no']);
            $first = true;
            while ($tax_item = db_fetch($tax_items))
            {
                if ($tax_item['amount'] == 0)
                    continue;
                $DisplayTax = number_format2($sign*$tax_item['amount'], $dec);

                if ($SysPrefs->suppress_tax_rates() == 1)
                    $tax_type_name = $tax_item['tax_type_name'];
                else
                    $tax_type_name = $tax_item['tax_type_name']." (".$tax_item['rate']."%) ";

                if ($myrow['tax_included'])
                {
                    if ($SysPrefs->alternative_tax_include_on_docs() == 1)
                    {
                        if ($first)
                        {
                            $rep->TextCol(3, 6, _("Total Tax Excluded"), -2);
                            $rep->TextCol(6, 7,    number_format2($sign*$tax_item['net_amount'], $dec), -2);
                            $rep->NewLine();
                        }
                        $rep->TextCol(3, 6, $tax_type_name, -2);
                        $rep->TextCol(6, 7,    $DisplayTax, -2);
                        $first = false;
                    }
                    else
                        $rep->TextCol(3, 6, _("Included") . " " . $tax_type_name . _("Amount") . ": " . $DisplayTax, -2);
                }
                else
                {
                    $rep->TextCol(3, 6, $tax_type_name, -2);
                    $rep->TextCol(6, 7,    $DisplayTax, -2);
                }
                $rep->NewLine();
            }

            $rep->NewLine();

//-----------------------------------------------------------added to fetch and calculate total balance
                $accumulate = 0;                    
                $bal = get_open_balance($myrow['debtor_no'],today()); 
                $init[0] = $init[1] = 0.0;
            $init[0] = round2(abs($bal['charges']), $dec);
            $init[1] = round2(Abs($bal['credits']), $dec);
            $init[2] = round2($bal['Allocated'], $dec);
            $init[3] = $init[0] - $init[1];
            $accumulate += $init[3];
//-----------------------------------------------------------End added to fetch and calculate total balance

            $DisplayTotal = number_format2($sign*($myrow["ov_freight"] + $myrow["ov_gst"] +
                $myrow["ov_amount"]+$myrow["ov_freight_tax"]),$dec);
            $rep->Font('bold');
            if (!$myrow['prepaid']) $rep->Font('bold');
                $rep->TextCol(3, 6, $rep->formData['prepaid'] ? _("TOTAL ORDER VAT INCL.") : _("TOTAL INVOICE"), - 2);
            $rep->TextCol(6, 7, $DisplayTotal, -2);

//-------------------------------------------- added to display total balance            
            $rep->NewLine(); 
            $rep->TextCol(3, 6, $rep->formData['prepaid'] ? _("TOTAL ORDER VAT INCL.") : _("TOTAL BALANCE"), - 2); 
            $DisplayGrand = number_format2($init[3],$dec);
            $rep->TextCol(6, 7, $DisplayGrand, -2); 
//-----------------------------------------------------------End added to display total balance    

            if ($rep->formData['prepaid'])
            {
                $rep->NewLine();
                $rep->Font('bold');
                $rep->TextCol(3, 6, $rep->formData['prepaid']=='final' ? _("THIS INVOICE") : _("TOTAL INVOICE"), - 2);
                $rep->TextCol(6, 7, number_format2($myrow['prep_amount'], $dec), -2);
            }
            $words = price_in_words($rep->formData['prepaid'] ? $myrow['prep_amount'] : $myrow['Total']
                , array( 'type' => ST_SALESINVOICE, 'currency' => $myrow['curr_code']));
            if ($words != "")
            {
                $rep->NewLine(1);
                $rep->TextCol(1, 7, $myrow['curr_code'] . ": " . $words, - 2);
            }
            $rep->Font();
            if ($email == 1)
            {
                $rep->End($email);
            }
    }
    if ($email == 0)
        $rep->End();
}

I was pretty busy with work.

Update, I have used it this way for a week with no problems. It works much better.

44

(13 replies, posted in Reporting)

@Apmuthu

Ok I got it working Thank You for the help. I'll send you some money on Pay Pal for your help on Monday (Waiting to verify the new Bank Account) I'll send it to the Email on you whois for the domain.

So, Here is the code for anyone that wants it. I am no coder so someone might want to clean it up, but it works.
It will print the clients current balance for all invoices up to the day it s printed. For example if today is 1/12/18 it will includeinvoices with dates from 1/5/18 and 1/12/18 but not an invoice made for the future 1/16/18.

add this funcion from rep101.php to the top of your /reporting/rep107.php where all the funcions are

function get_open_balance($debtorno, $to)
{
    if($to)
        $to = date2sql($to);

     $sql = "SELECT SUM(IF(t.type = ".ST_SALESINVOICE." OR (t.type = ".ST_JOURNAL." AND t.ov_amount>0),
         -abs(t.ov_amount + t.ov_gst + t.ov_freight + t.ov_freight_tax + t.ov_discount), 0)) AS charges,";
     $sql .= "SUM(IF(t.type != ".ST_SALESINVOICE." AND NOT(t.type = ".ST_JOURNAL." AND t.ov_amount>0),
         abs(t.ov_amount + t.ov_gst + t.ov_freight + t.ov_freight_tax + t.ov_discount) * -1, 0)) AS credits,";
     $sql .= "SUM(IF(t.type != ".ST_SALESINVOICE." AND NOT(t.type = ".ST_JOURNAL." AND t.ov_amount>0), t.alloc * -1, t.alloc)) AS Allocated,";

     $sql .=    "SUM(IF(t.type = ".ST_SALESINVOICE.", 1, -1) *
             (abs(t.ov_amount + t.ov_gst + t.ov_freight + t.ov_freight_tax + t.ov_discount) - abs(t.alloc))) AS OutStanding
        FROM ".TB_PREF."debtor_trans t
        WHERE t.debtor_no = ".db_escape($debtorno)
        ." AND t.type <> ".ST_CUSTDELIVERY;
    if ($to)
        $sql .= " AND t.tran_date < '$to+1'";
    $sql .= " GROUP BY debtor_no";

    $result = db_query($sql,"No transactions were returned");
    return db_fetch($result);
}

Then add this above

                        $accumulate = 0;                    
                $bal = get_open_balance($myrow['debtor_no'],today()); 
                $init[0] = $init[1] = 0.0;
            $init[0] = round2(abs($bal['charges']), $dec);
            $init[1] = round2(Abs($bal['credits']), $dec);
            $init[2] = round2($bal['Allocated'], $dec);
            $init[3] = $init[0] - $init[1];
            $accumulate += $init[3];

and this below

$rep->TextCol(6, 7, $DisplayTotal, -2);
            $rep->NewLine(); // added for total balance
            $rep->TextCol(3, 6, $rep->formData['prepaid'] ? _("TOTAL ORDER VAT INCL.") : _("TOTAL BALANCE"), - 2); 
            $DisplayGrand = number_format2($init[3],$dec);
            $rep->TextCol(6, 7, $DisplayGrand, -2); // added for total balance

This line of code

            $DisplayTotal = number_format2($sign*($myrow["ov_freight"] + $myrow["ov_gst"] +
                $myrow["ov_amount"]+$myrow["ov_freight_tax"]),$dec);
            $rep->Font('bold');
            if (!$myrow['prepaid']) $rep->Font('bold');
                $rep->TextCol(3, 6, $rep->formData['prepaid'] ? _("TOTAL ORDER VAT INCL.") : _("THIS INVOICE"), - 2);

45

(3 replies, posted in Report Bugs here)

Okay I was a complete fool it wasn't working because I was entering the payment in the bank charges section. Thats why I couldnt allocate because there was no balance left to allocate. There could be a if statement to prevent that. I feel like a fool. Ha

46

(3 replies, posted in Report Bugs here)

Okay I was able to fix the debit account to be undeposited funds that setting was actually under the bank account setting but I still can't allocate a payment to an invoice

47

(3 replies, posted in Report Bugs here)

Ok, I also get that error when allocating in the Customer Payment Entry ui as well.

I can see the amount was credited from accounts receivables and debited in 5690 Interest & Bank Charges???

shouldn't it go to a undeposited funds account in current assets???

Thanks

In sales_order_ui.inc the reference number input is placed in table_section(1) and I beleive workflow is better if it is placed at the end of table_section(4). Because...

When entering an invoice and tabbing through the fields with a keyboard. If you enter a custom reference in table_section(1) then tab through to table_section(4) and enter a date it will update the reference number to the next sequencial number causing you to go back to table_section(1) to replace the value again.

I suggest removing this line from line 361

ref_row(_("Reference").':', 'ref', _('Reference number unique for this document type'), null, '', $order->trans_type, array('date'=> @$_POST['OrderDate']));

and place it here around 458

    else
    {
        label_row($date_text, $order->document_date);
        hidden('OrderDate', $order->document_date);
    }
    
    ref_row(_("Reference").':', 'ref', _('Reference number unique for this document type'), null, '', $order->trans_type, array('date'=> @$_POST['OrderDate']));

    end_outer_table(1); // outer table

    if ($change_prices != 0) {
        foreach ($order->line_items as $line_no=>$item) {
            $line = &$order->line_items[$line_no];
            $line->price = get_kit_price($line->stock_id, $order->customer_currency,
                $order->sales_type, $order->price_factor, get_post('OrderDate'));
        }
        $Ajax->activate('items_table');
    }

Let me know if this will cause trouble that I am unaware I am trying it now.

49

(13 replies, posted in Reporting)

I have a service industry and am trying to create a "service ticket/invoice" with the total customer balance at the time of printing. I have imported the function get_open_balance from rep101 and am trying to use it but it returns an array. Maybe the array needs to be added up before displaying?

Here is the funcion I imported to the begining of my version of rep107
The parts with variable $to were disabled since it is not passed in an invoice

function get_open_balance($debtorno)
{
    #if($to) 
    #    $to = date2sql($to);

     $sql = "SELECT SUM(IF(t.type = ".ST_SALESINVOICE." OR (t.type = ".ST_JOURNAL." AND t.ov_amount>0),
         -abs(t.ov_amount + t.ov_gst + t.ov_freight + t.ov_freight_tax + t.ov_discount), 0)) AS charges,";
     $sql .= "SUM(IF(t.type != ".ST_SALESINVOICE." AND NOT(t.type = ".ST_JOURNAL." AND t.ov_amount>0),
         abs(t.ov_amount + t.ov_gst + t.ov_freight + t.ov_freight_tax + t.ov_discount) * -1, 0)) AS credits,";
     $sql .= "SUM(IF(t.type != ".ST_SALESINVOICE." AND NOT(t.type = ".ST_JOURNAL." AND t.ov_amount>0), t.alloc * -1, t.alloc)) AS Allocated,";

     $sql .=    "SUM(IF(t.type = ".ST_SALESINVOICE.", 1, -1) *
             (abs(t.ov_amount + t.ov_gst + t.ov_freight + t.ov_freight_tax + t.ov_discount) - abs(t.alloc))) AS OutStanding
        FROM ".TB_PREF."debtor_trans t
        WHERE t.debtor_no = ".db_escape($debtorno)
        ." AND t.type <> ".ST_CUSTDELIVERY;
    # if ($to)
    #    $sql .= " AND t.tran_date < '$to'";
    #$sql .= " GROUP BY debtor_no"; 

    $result = db_query($sql,"No transactions were returned");
    return db_fetch($result);
}

On the end of the invoice printing side I have this:
The lines are commented becuse it is broken.

$rep->NewLine();
                #$bal = get_open_balance($myrow['debtor_no']); // added for total balance not working function returns an array.
                #$DisplayCustTotal = number_format2($bal,$dec); // added for total balance
            $DisplayTotal = number_format2($sign*($myrow["ov_freight"] + $myrow["ov_gst"] +
                $myrow["ov_amount"]+$myrow["ov_freight_tax"]),$dec);
            $rep->Font('bold');
            if (!$myrow['prepaid']) $rep->Font('bold');
                $rep->TextCol(3, 6, $rep->formData['prepaid'] ? _("TOTAL ORDER VAT INCL.") : _("THIS INVOICE"), - 2);
            $rep->TextCol(6, 7, $DisplayTotal, -2);
            $rep->NewLine(); // added for total balance
            $rep->TextCol(3, 6, $rep->formData['prepaid'] ? _("TOTAL ORDER VAT INCL.") : _("TOTAL BALANCE"), - 2); // added for total balance
            #$rep->TextCol(6, 7, $DisplayCustTotal, -2); // added for total balance
            if ($rep->formData['prepaid'])
            {
                $rep->NewLine();
                $rep->Font('bold');
                $rep->TextCol(3, 6, $rep->formData['prepaid']=='final' ? _("THIS INVOICE") : _("TOTAL INVOICE"), - 2);
                $rep->TextCol(6, 7, number_format2($myrow['prep_amount'], $dec), -2);
            }
            $words = price_in_words($rep->formData['prepaid'] ? $myrow['prep_amount'] : $myrow['Total']
                , array( 'type' => ST_SALESINVOICE, 'currency' => $myrow['curr_code']));
            if ($words != "")
            {
                $rep->NewLine(1);
                $rep->TextCol(1, 7, $myrow['curr_code'] . ": " . $words, - 2);
            }
            $rep->Font();
            if ($email == 1)
            {
                $rep->End($email);
            }

I am not a very good programmer and I have no experience in PHP. Thank you in advance you guys are lifesavers.

When I enter a payment in the ui it never gives me the success screen. But when I check the Database and the Allocate customer payment screen it shows that the payments were entered but not allocated. When I try to allocate them in the allocate customer payment screen with the debug 2 flag set (in config.php) It gives me this error   

/home4/traffid0/public_html/books/sales/includes/db/cust_trans_db.inc:206:    display_backtrace()
/home4/traffid0/public_html/books/includes/ui/allocation_cart.inc:126:    get_customer_trans('1','12','190')
/home4/traffid0/public_html/books/includes/ui/allocation_cart.inc:42:    (allocation Object)->read('12','1','190','2')
/home4/traffid0/public_html/books/sales/allocations/customer_allocate.php:111:    (allocation Object)->allocation('12','1','190','2')

/home4/traffid0/public_html/books/includes/ui/ui_msgs.inc:14:    trigger_error('
/home4/traffid0/public_html/books/sales/includes/db/cust_trans_db.inc:206:    display_backtrace()
/home4/traffid0/public_html/books/includes/ui/allocation_cart.inc:126:    get_customer_trans('1','12','190')
/home4/traffid0/public_html/books/includes/ui/allocation_cart.inc:42:    (allocation Object)->read('12','1','190','2')
/home4/traffid0/public_html/books/sales/allocations/customer_allocate.php:111:    (allocation Object)->allocation('12','1','190','2')
','256')
/home4/traffid0/public_html/books/includes/ui/ui_view.inc:1484:    display_error('
/home4/traffid0/public_html/books/sales/includes/db/cust_trans_db.inc:206:    display_backtrace()
/home4/traffid0/public_html/books/includes/ui/allocation_cart.inc:126:    get_customer_trans('1','12','190')
/home4/traffid0/public_html/books/includes/ui/allocation_cart.inc:42:    (allocation Object)->read('12','1','190','2')
/home4/traffid0/public_html/books/sales/allocations/customer_allocate.php:111:    (allocation Object)->allocation('12','1','190','2')
')
/home4/traffid0/public_html/books/sales/includes/db/cust_trans_db.inc:206:    display_backtrace()
/home4/traffid0/public_html/books/includes/ui/allocation_cart.inc:126:    get_customer_trans('1','12','190')
/home4/traffid0/public_html/books/includes/ui/allocation_cart.inc:42:    (allocation Object)->read('12','1','190','2')
/home4/traffid0/public_html/books/sales/allocations/customer_allocate.php:111:    (allocation Object)->allocation('12','1','190','2')
DATABASE ERROR : no debtor trans found for given params
sql that failed was : SELECT trans.*,ov_amount+ov_gst+ov_freight+ov_freight_tax+ov_discount AS Total,cust.name AS DebtorName, cust.address, cust.curr_code, cust.tax_id, trans.prep_amount>0 as prepaid,com.memo_,bank_act,2_bank_accounts.bank_name, 2_bank_accounts.bank_account_name, 2_bank_accounts.account_type AS BankTransType, 2_bank_accounts.bank_curr_code, 2_bank_trans.amount as bank_amount FROM 2_debtor_trans trans LEFT JOIN 2_comments com ON trans.type=com.type AND trans.trans_no=com.id LEFT JOIN 2_shippers ON 2_shippers.shipper_id=trans.ship_via, 2_debtors_master cust, 2_bank_trans, 2_bank_accounts WHERE trans.trans_no='1' AND trans.type='12' AND trans.debtor_no=cust.debtor_no AND trans.debtor_no='190' AND 2_bank_trans.trans_no ='1' AND 2_bank_trans.type=12 AND 2_bank_trans.amount != 0 AND 2_bank_accounts.id=2_bank_trans.bank_act 



/home4/traffid0/public_html/books/includes/errors.inc:198:    trigger_error('DATABASE ERROR : no debtor trans found for given params
sql that failed was : SELECT trans.*,ov_amount+ov_gst+ov_freight+ov_freight_tax+ov_discount AS Total,cust.name AS DebtorName, cust.address, cust.curr_code, cust.tax_id, trans.prep_amount>0 as prepaid,com.memo_,bank_act,2_bank_accounts.bank_name, 2_bank_accounts.bank_account_name, 2_bank_accounts.account_type AS BankTransType, 2_bank_accounts.bank_curr_code, 2_bank_trans.amount as bank_amount FROM 2_debtor_trans trans LEFT JOIN 2_comments com ON trans.type=com.type AND trans.trans_no=com.id LEFT JOIN 2_shippers ON 2_shippers.shipper_id=trans.ship_via, 2_debtors_master cust, 2_bank_trans, 2_bank_accounts WHERE trans.trans_no='1' AND trans.type='12' AND trans.debtor_no=cust.debtor_no AND trans.debtor_no='190' AND 2_bank_trans.trans_no ='1' AND 2_bank_trans.type=12 AND 2_bank_trans.amount != 0 AND 2_bank_accounts.id=2_bank_trans.bank_act 


','256')
/home4/traffid0/public_html/books/sales/includes/db/cust_trans_db.inc:207:    display_db_error('no debtor trans found for given params','SELECT trans.*,ov_amount+ov_gst+ov_freight+ov_freight_tax+ov_discount AS Total,cust.name AS DebtorName, cust.address, cust.curr_code, cust.tax_id, trans.prep_amount>0 as prepaid,com.memo_,bank_act,&TB_PREF&bank_accounts.bank_name, &TB_PREF&bank_accounts.bank_account_name, &TB_PREF&bank_accounts.account_type AS BankTransType, &TB_PREF&bank_accounts.bank_curr_code, &TB_PREF&bank_trans.amount as bank_amount FROM &TB_PREF&debtor_trans trans LEFT JOIN &TB_PREF&comments com ON trans.type=com.type AND trans.trans_no=com.id LEFT JOIN &TB_PREF&shippers ON &TB_PREF&shippers.shipper_id=trans.ship_via, &TB_PREF&debtors_master cust, &TB_PREF&bank_trans, &TB_PREF&bank_accounts WHERE trans.trans_no='1' AND trans.type='12' AND trans.debtor_no=cust.debtor_no AND trans.debtor_no='190' AND &TB_PREF&bank_trans.trans_no ='1' AND &TB_PREF&bank_trans.type=12 AND &TB_PREF&bank_trans.amount != 0 AND &TB_PREF&bank_accounts.id=&TB_PREF&bank_trans.bank_act ','1')
/home4/traffid0/public_html/books/includes/ui/allocation_cart.inc:126:    get_customer_trans('1','12','190')
/home4/traffid0/public_html/books/includes/ui/allocation_cart.inc:42:    (allocation Object)->read('12','1','190','2')
/home4/traffid0/public_html/books/sales/allocations/customer_allocate.php:111:    (allocation Object)->allocation('12','1','190','2')


Thank You in advance