Sistematika’s Journal

Diberkati untuk memberkati

Multi Accounting Schema #2

Posted by: Bayu Cahya P on: August 7, 2008

As per previous journal , we were facing to No Cost for Memory exception while trying to post Shipment (Customer) document.

Okay, it’s time to check what is happening behind the scene. As per our basic knowledge, posting document within Adempiere would be affected to accounting consequences. And because this Shipment (Customer) document using table M_InOut (how to know which table to be used for window), seems that java codes which handle this accounting generated is Doc_InOut.java. We can reach this files from org/compiere/acct folder.

Good, thanks to standardize which made me clear about how to find which codes affected with our problem.

Next, we directly jump to method createFacts(MAcctSchema as) , and this is a piece of codes which explained about where errors generated comes.

 

public ArrayList createFacts (MAcctSchema as)
        {
                //
                ArrayList facts = new ArrayList();
                //  create Fact Header
                Fact fact = new Fact(this, as, Fact.POST_Actual);
                setC_Currency_ID (as.getC_Currency_ID());

                //  Line pointers
                FactLine dr = null;
                FactLine cr = null;

                //  *** Sales - Shipment
                if (getDocumentType().equals(DOCTYPE_MatShipment) && isSOTrx())
                {
                        for (int i = 0; i < p_lines.length; i++)
                        {
                                DocLine line = p_lines[i];
                                // MZ Goodwill
                                // if Shipment CostDetail exist then get Cost from Cost Detail
                                BigDecimal costs = line.getProductCosts(as, line.getAD_Org_ID(), true, "M_InOutLine_ID=? AND M_AttributeSetInstance_ID=?");
                                // end MZ

                                if (costs == null || costs.signum() == 0)       //      zero costs OK
                                {
                                        MProduct product = line.getProduct();
                                        if (product.isStocked())
                                        {
                                                p_Error = "No Costs for " + line.getProduct().getName();
                                                log.log(Level.WARNING, p_Error);
                                                return null;
                                        }
                                        else    //      ignore service
                                                continue;
                                }

From this piece of codes, finally we were known about the value which taken from line.getProductCosts(as, line.getAD_Org_ID(), true, “M_InOutLine_ID=? AND M_AttributeSetInstance_ID=?”) give us null or zero costs.

Is it enough to know this? We have to dig more and more about what is line.getProductCosts actually doing. This methods actually read table M_CostDetail to got amount for specific M_InOutLine_ID and M_AttributeSetInstance_ID.

Strange, they don’t have cost detail records! Let us check within product cost window and goes to cost detail tab

missing-idr-product-cost

Figure 1. Product Cost Detail records

To be precisely, they don’t have value for IDR (first register) accounting schema.

As per Adempiere technical guidance, this cost detail records comes from M_CostDetail table, and within Adempiere, almost all of business process and table operation handled by their java model class. With their codification, we found MCostDetail.java within org/compiere/model folder.

Next question, which method to be executed within MCostDetail.java and with what kind of operation? Remember that, our problem rose while we tried to post Shipment (Customer) document. Before we post this document, actually we did complete document without fail. While we did this one, actually, Adempiere executed method completeIt() within M_InOut.java class. Reading this method, we found MCostDetail.createOrder() have been called.

This is complete listing of those method

public static boolean createOrder (MAcctSchema as, int AD_Org_ID,
                int M_Product_ID, int M_AttributeSetInstance_ID,
                int C_OrderLine_ID, int M_CostElement_ID,
                BigDecimal Amt, BigDecimal Qty,
                String Description, String trxName)
        {
                //      Delete Unprocessed zero Differences
                String sql = "DELETE M_CostDetail "
                        + "WHERE Processed='N' AND COALESCE(DeltaAmt,0)=0 AND COALESCE(DeltaQty,0)=0"
                        + " AND C_OrderLine_ID=" + C_OrderLine_ID
                        + " AND M_AttributeSetInstance_ID=" + M_AttributeSetInstance_ID
                        // Bayu add accounting schema as parameter
                        + " AND C_AcctSchema_ID =" + as.getC_AcctSchema_ID()
                        // Bayu end
                        ;
                int no = DB.executeUpdate(sql, trxName);
                if (no != 0)
                        s_log.config("Deleted #" + no);
                MCostDetail cd = get (as.getCtx(), "C_OrderLine_ID=? AND M_AttributeSetInstance_ID=?"
                                // Bayu add acc schema parameter
                                + " AND C_AcctSchema_ID=" + as.getC_AcctSchema_ID(),
                                // Bayu end
                        C_OrderLine_ID, M_AttributeSetInstance_ID, trxName);
                //
                if (cd == null)         //      createNew
                {
                        cd = new MCostDetail (as, AD_Org_ID,
                                M_Product_ID, M_AttributeSetInstance_ID,
                                M_CostElement_ID,
                                Amt, Qty, Description, trxName);
                        cd.setC_OrderLine_ID (C_OrderLine_ID);
                }
                else
                {
                        // MZ Goodwill
                        // set deltaAmt=Amt, deltaQty=       

                qty,      and set Cost Detail
                for Amt  and Qty cd.setDeltaAmt(Amt.subtract(cd.getAmt()));
                        cd.setDeltaQty(Qty.subtract(cd.getQty())); if (cd.isDelta()){ cd.setProcessed(false); cd.setAmt(Amt);cd.setQty(Qty); } //end
                        MZ else return true;// nothing to
                        do } boolean ok=
                           cd.save(); if (ok &&
                        !cd.isProcessed()) { MClient client =  MClient.get(as.getCtx(),
                        as.getAD_Client_ID()); if (client.isCostImmediate())
                        cd.process();
                } s_log.config("("  + ok
                + ") " +
                        cd); return ok; }
                // createOrder

While we have 2 accounting schema, this method will be executed twice (looping). The first one for IDR acc schema and the second one is USD acc schema. And finally we got where is the problem comes. While processing the second acc schema, the first record has been deleted with this piece of code

//      Delete Unprocessed zero Differences
                String sql = "DELETE M_CostDetail "
                        + "WHERE Processed='N' AND COALESCE(DeltaAmt,0)=0 AND COALESCE(DeltaQty,0)=0"
                        + " AND C_OrderLine_ID=" + C_OrderLine_ID
                        + " AND M_AttributeSetInstance_ID=" + M_AttributeSetInstance_ID;
                int no = DB.executeUpdate(sql, trxName);
                if (no != 0)
                        s_log.config("Deleted #" + no);

 

It doesn’t have accounting schema as parameter. We are trying to add accounting schema as parameter and this code becomes

 

//      Delete Unprocessed zero Differences
                String sql = "DELETE M_CostDetail "
                        + "WHERE Processed='N' AND COALESCE(DeltaAmt,0)=0 AND COALESCE(DeltaQty,0)=0"
                        + " AND C_OrderLine_ID=" + C_OrderLine_ID
                        + " AND M_AttributeSetInstance_ID=" + M_AttributeSetInstance_ID
                        // Bayu add accounting schema as parameter
                        + " AND C_AcctSchema_ID =" + as.getC_AcctSchema_ID()
                        // Bayu end
                        ;
                int no = DB.executeUpdate(sql, trxName);
                if (no != 0)
                        s_log.config("Deleted #" + no);

 

Compile this source and export as a customization and run silent setup then create new purchase order and finally this is cost detail records generated

 

idr-usd-product-cost

Figure 2. Product cost with 2 accounting schema

With this product cost details, this records would be calculated to product cost within your costing methods and this product cost will be used for our Shipment (Customer) accounting generated.

But, hey…… for USD accounting schema, Adempiere recorded 0.0089203 values. Is it okay or not? We are going to discuss this generated accounting values in the next journal .

Comment Form

SEO Powered by Platinum SEO from Techblissonline