viernes, 24 de agosto de 2012

Form Running Totals


I can think of two use cases when applying running totals to a grid on a form. Taking the LedgerTransAccount form (Account Transactions) as an example:

Running totals by transaction date

Add a real field to the grid, with a 'XXX_RunningBalanceMST' DataMethdod with the 'LedgerTrans' DataSource.
Add the following method to the LedgerTrans table:
public AmountMST XXX_RunningBalanceMST()
{
    LedgerTrans     ledgerTrans;
    ;
    select sum(AmountMST) from ledgerTrans
            where ledgerTrans.AccountNum  == this.AccountNum
               && ( (ledgerTrans.TransDate < this.TransDate)
                 || (ledgerTrans.TransDate == this.TransDate && ledgerTrans.RecId <= this.RecId) );
    return ledgerTrans.AmountMST;
}

Add the cache method to the form datasource (LedgerTrans) init() method, after the super(); call.
    ledgerTrans_ds.cacheAddMethod(tablemethodstr(LedgerTrans, XXX_RunningBalanceMST));

Running totals by user defined filters, dynalinks and ordenations:

This time add a disply method directly to the datasource.
//BP Deviation Documented
display AmountMST XXX_runningBalanceMST2(LedgerTrans _ledgerTrans)
{
    QueryRun    qr = new QueryRun(ledgerTrans_qr.query());
    LedgerTrans localLedgerTrans;
    AmountMST   amountMST;
    ;
    while (qr.next())
    {
        localLedgerTrans    = qr.get(tablenum(LedgerTrans));
        amountMST           += localLedgerTrans.AmountMST;
        if (localLedgerTrans.RecId == _ledgerTrans.RecId)
        {
            break;
        }
    }
    return amountMST;
}

This is definately the slowest procedure.  I'd avoid applying this modification to be honest.
We would have to implement our own caching on the results, using a map, with RecId as our key and the result as the value.  Initialise/empty the map in the executeQuery() method and check if the _ledgerTrans.RecId key exists in the map before launching into the loop in the method.  The optimisation is undertaken here.

EDIT: Includes user filters on the form columns:-
//BP Deviation Documented
display AmountMST XXX_runningBalanceMST(LedgerTrans _trans)
{
    LedgerTrans localLedgerTrans;
    AmountMST   amountMST;
    ;
    localLedgerTrans    = this.getFirst();
    while (localLedgerTrans)
    {
        amountMST           += localLedgerTrans.AmountMST;
        if (localLedgerTrans.RecId == _trans.RecId)
        {
            break;
        }
        localLedgerTrans    = this.getNext();
    }
    return amountMST;
}
Thanks to Jan B. Kjeldsen for the heads-up.

No hay comentarios:

Publicar un comentario