/****************************************************************************** * Product: Adempiere ERP & CRM Smart Business Solution * * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it * * under the terms version 2 of the GNU General Public License as published * * by the Free Software Foundation. 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 GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * * with this program; if not, write to the Free Software Foundation, Inc., * * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. * * For the text or an alternative of this public license, you may reach us * * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * * or via info@compiere.org or http://www.compiere.org/license.html * *****************************************************************************/ package org.compiere.model; import java.math.BigDecimal; import java.math.RoundingMode; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.sql.Timestamp; import java.util.Properties; import java.util.logging.Level; import org.adempiere.base.Core; import org.adempiere.base.IProductPricing; import org.adempiere.model.GridTabWrapper; import org.compiere.util.CLogger; import org.compiere.util.DB; import org.compiere.util.DisplayType; import org.compiere.util.Env; /** * Invoice Callouts * * @author Jorg Janke * @version $Id: CalloutInvoice.java,v 1.4 2006/07/30 00:51:03 jjanke Exp $ */ public class CalloutInvoice extends CalloutEngine { /** * Invoice Header - DocType. * - PaymentRule * - temporary Document * Context: * - DocSubTypeSO * - HasCharges * - (re-sets Business Partner info of required) * @param ctx context * @param WindowNo window no * @param mTab tab * @param mField field * @param value value * @return null or error message */ public String docType (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) { Integer C_DocType_ID = (Integer)value; if (C_DocType_ID == null || C_DocType_ID.intValue() == 0) return ""; String sql = "SELECT d.HasCharges,d.IsDocNoControlled," // 1..2 + "d.DocBaseType, " // 3 + "s.AD_Sequence_ID " //4 + "FROM C_DocType d " + "LEFT OUTER JOIN AD_Sequence s ON (d.DocNoSequence_ID=s.AD_Sequence_ID) " + "WHERE C_DocType_ID=?"; // 1 PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = DB.prepareStatement(sql, null); pstmt.setInt(1, C_DocType_ID.intValue()); rs = pstmt.executeQuery(); if (rs.next()) { // Charges - Set Context Env.setContext(ctx, WindowNo, "HasCharges", rs.getString("HasCharges")); // DocumentNo if (rs.getString("IsDocNoControlled").equals("Y")) { int AD_Sequence_ID = rs.getInt("AD_Sequence_ID"); mTab.setValue("DocumentNo", MSequence.getPreliminaryNo(mTab, AD_Sequence_ID)); } // DocBaseType - Set Context String s = rs.getString("DocBaseType"); Env.setContext(ctx, WindowNo, "DocBaseType", s); // AP Check & AR Credit Memo if (s.startsWith("AP")) mTab.setValue("PaymentRule", X_C_Invoice.PAYMENTRULE_Check); else if (s.endsWith("C")) mTab.setValue("PaymentRule", X_C_Invoice.PAYMENTRULE_OnCredit); } } catch (SQLException e) { log.log(Level.SEVERE, sql, e); return e.getLocalizedMessage(); } finally { DB.close(rs, pstmt); rs = null; pstmt = null; } return ""; } // docType /** * Invoice Header- BPartner. * - M_PriceList_ID (+ Context) * - C_BPartner_Location_ID * - AD_User_ID * - POReference * - SO_Description * - IsDiscountPrinted * - PaymentRule * - C_PaymentTerm_ID * @param ctx context * @param WindowNo window no * @param mTab tab * @param mField field * @param value value * @return null or error message */ public String bPartner (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) { Integer C_BPartner_ID = (Integer)value; if (C_BPartner_ID == null || C_BPartner_ID.intValue() == 0) return ""; String sql = "SELECT p.AD_Language,p.C_PaymentTerm_ID," + " COALESCE(p.M_PriceList_ID,g.M_PriceList_ID) AS M_PriceList_ID, p.PaymentRule,p.POReference," + " p.SO_Description,p.IsDiscountPrinted," + " p.SO_CreditLimit, p.SO_CreditLimit-p.SO_CreditUsed AS CreditAvailable," + " (select max(lbill.C_BPartner_Location_ID) from C_BPartner_Location lbill where p.C_BPartner_ID=lbill.C_BPartner_ID AND lbill.IsBillTo='Y' AND lbill.IsActive='Y') AS C_BPartner_Location_ID," + " (select max(c.AD_User_ID) from AD_User c where p.C_BPartner_ID=c.C_BPartner_ID AND c.IsActive='Y') as AD_User_ID," + " (select max(c.AD_User_ID) from AD_User c where p.C_BPartner_ID=c.C_BPartner_ID AND c.IsActive='Y' AND IsBillTo='Y') as BillTo_User_ID," + " COALESCE(p.PO_PriceList_ID,g.PO_PriceList_ID) AS PO_PriceList_ID, p.PaymentRulePO,p.PO_PaymentTerm_ID, p.SalesRep_ID " + "FROM C_BPartner p" + " INNER JOIN C_BP_Group g ON (p.C_BP_Group_ID=g.C_BP_Group_ID)" + "WHERE p.C_BPartner_ID=? AND p.IsActive='Y'"; // #1 boolean IsSOTrx = Env.getContext(ctx, WindowNo, "IsSOTrx").equals("Y"); PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = DB.prepareStatement(sql, null); pstmt.setInt(1, C_BPartner_ID.intValue()); rs = pstmt.executeQuery(); // if (rs.next()) { // Sales Rep - If BP has a default SalesRep then default it Integer salesRep = rs.getInt("SalesRep_ID"); if (IsSOTrx && salesRep != 0 ) { mTab.setValue("SalesRep_ID", salesRep); } // PriceList & IsTaxIncluded & Currency Integer ii = Integer.valueOf(rs.getInt(IsSOTrx ? "M_PriceList_ID" : "PO_PriceList_ID")); if (!rs.wasNull()) mTab.setValue("M_PriceList_ID", ii); else { // get default PriceList int i = Env.getContextAsInt(ctx, Env.M_PRICELIST_ID); if (i != 0) { MPriceList pl = new MPriceList(ctx, i, null); if (IsSOTrx == pl.isSOPriceList()) mTab.setValue("M_PriceList_ID", Integer.valueOf(i)); else { String sql2 = "SELECT M_PriceList_ID FROM M_PriceList WHERE AD_Client_ID=? AND IsSOPriceList=? AND IsActive='Y' ORDER BY IsDefault DESC"; ii = DB.getSQLValue (null, sql2, Env.getAD_Client_ID(ctx), IsSOTrx); if (ii != 0) mTab.setValue("M_PriceList_ID", Integer.valueOf(ii)); } } } // PaymentRule String s = rs.getString(IsSOTrx ? "PaymentRule" : "PaymentRulePO"); if (s != null && s.length() != 0) mTab.setValue("PaymentRule", s); if (Env.getContext(ctx, WindowNo, "DocBaseType").endsWith("C")) // Credits are Payment Term s = X_C_Invoice.PAYMENTRULE_OnCredit; // Payment Term ii = Integer.valueOf(rs.getInt(IsSOTrx ? "C_PaymentTerm_ID" : "PO_PaymentTerm_ID")); if (!rs.wasNull()) mTab.setValue("C_PaymentTerm_ID", ii); // Location int locID = rs.getInt("C_BPartner_Location_ID"); // overwritten by InfoBP selection - works only if InfoWindow // was used otherwise creates error (uses last value, may belong to differnt BP) if (C_BPartner_ID.toString().equals(Env.getContext(ctx, WindowNo, Env.TAB_INFO, "C_BPartner_ID"))) { String loc = Env.getContext(ctx, WindowNo, Env.TAB_INFO, "C_BPartner_Location_ID"); if (loc.length() > 0) locID = Integer.parseInt(loc); } if (locID == 0) mTab.setValue("C_BPartner_Location_ID", null); else mTab.setValue("C_BPartner_Location_ID", Integer.valueOf(locID)); // Contact - overwritten by InfoBP selection int contID = rs.getInt("AD_User_ID"); if (C_BPartner_ID.toString().equals(Env.getContext(ctx, WindowNo, Env.TAB_INFO, "C_BPartner_ID"))) { String cont = Env.getContext(ctx, WindowNo, Env.TAB_INFO, "AD_User_ID"); if (cont.length() > 0) contID = Integer.parseInt(cont); } int BillTo_User_ID = rs.getInt("BillTo_User_ID"); if (contID == 0) mTab.setValue("AD_User_ID", null); else { Integer userID = BillTo_User_ID > 0 ? Integer.valueOf(BillTo_User_ID) : Integer.valueOf(contID); mTab.setValue("AD_User_ID", userID); } // CreditAvailable if (IsSOTrx) { double CreditLimit = rs.getDouble("SO_CreditLimit"); if (CreditLimit != 0) { double CreditAvailable = rs.getDouble("CreditAvailable"); if (!rs.wasNull() && CreditAvailable < 0) mTab.fireDataStatusEEvent("CreditLimitOver", DisplayType.getNumberFormat(DisplayType.Amount).format(CreditAvailable), false); } } // PO Reference s = rs.getString("POReference"); if (s != null && s.length() != 0) mTab.setValue("POReference", s); // SO Description s = rs.getString("SO_Description"); if (s != null && s.trim().length() != 0) mTab.setValue("Description", s); // IsDiscountPrinted s = rs.getString("IsDiscountPrinted"); if (s != null && s.length() != 0) mTab.setValue("IsDiscountPrinted", s); else mTab.setValue("IsDiscountPrinted", "N"); } } catch (SQLException e) { log.log(Level.SEVERE, "bPartner", e); return e.getLocalizedMessage(); } finally { DB.close(rs, pstmt); rs = null; pstmt = null; } return ""; } // bPartner /** * Set Payment Term. * Payment Term has changed * @param ctx context * @param WindowNo window no * @param mTab tab * @param mField field * @param value value * @return null or error message * @Deprecated - business logic moved to MInvoice.beforeSave - must not create/delete external records with callouts */ @Deprecated public String paymentTerm (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) { Integer C_PaymentTerm_ID = (Integer)value; int C_Invoice_ID = Env.getContextAsInt(ctx, WindowNo, "C_Invoice_ID"); if (C_PaymentTerm_ID == null || C_PaymentTerm_ID.intValue() == 0 || C_Invoice_ID == 0) // not saved yet return ""; // MPaymentTerm pt = new MPaymentTerm (ctx, C_PaymentTerm_ID.intValue(), null); if (pt.get_ID() == 0) return "PaymentTerm not found"; boolean valid = pt.apply (C_Invoice_ID); mTab.setValue("IsPayScheduleValid", valid ? "Y" : "N"); return ""; } // paymentTerm /************************************************************************** * Invoice Line - Product. * - reset C_Charge_ID / M_AttributeSetInstance_ID * - PriceList, PriceStd, PriceLimit, C_Currency_ID, EnforcePriceLimit * - UOM * Calls Tax * @param ctx context * @param WindowNo window no * @param mTab tab * @param mField field * @param value value * @return null or error message */ public String product (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) { Integer M_Product_ID = (Integer)value; if (M_Product_ID == null || M_Product_ID.intValue() == 0) return ""; mTab.setValue("C_Charge_ID", null); // Set Attribute if (Env.getContextAsInt(ctx, WindowNo, Env.TAB_INFO, "M_Product_ID") == M_Product_ID.intValue() && Env.getContextAsInt(ctx, WindowNo, Env.TAB_INFO, "M_AttributeSetInstance_ID") != 0) mTab.setValue("M_AttributeSetInstance_ID", Env.getContextAsInt(ctx, WindowNo, Env.TAB_INFO, "M_AttributeSetInstance_ID")); else mTab.setValue("M_AttributeSetInstance_ID", 0); /***** Price Calculation see also qty ****/ boolean IsSOTrx = Env.getContext(ctx, WindowNo, "IsSOTrx").equals("Y"); int C_BPartner_ID = Env.getContextAsInt(ctx, WindowNo, "C_BPartner_ID"); BigDecimal Qty = (BigDecimal)mTab.getValue("QtyInvoiced"); IProductPricing pp = Core.getProductPricing(); pp.setInitialValues(M_Product_ID.intValue(), C_BPartner_ID, Qty, IsSOTrx, null); Timestamp invoiceDate = Env.getContextAsDate(ctx, WindowNo, "DateInvoiced"); pp.setPriceDate(invoiceDate); I_C_InvoiceLine invoiceLine = GridTabWrapper.create(mTab, I_C_InvoiceLine.class); pp.setInvoiceLine(invoiceLine, null); // int M_PriceList_ID = Env.getContextAsInt(ctx, WindowNo, "M_PriceList_ID"); pp.setM_PriceList_ID(M_PriceList_ID); /** PLV is only accurate if PL selected in header */ int M_PriceList_Version_ID = Env.getContextAsInt(ctx, WindowNo, "M_PriceList_Version_ID"); if ( M_PriceList_Version_ID == 0 && M_PriceList_ID > 0) { String sql = "SELECT plv.M_PriceList_Version_ID " + "FROM M_PriceList_Version plv " + "WHERE plv.M_PriceList_ID=? " // 1 + " AND plv.ValidFrom <= ? " + "ORDER BY plv.ValidFrom DESC"; // Use newest price list - may not be future M_PriceList_Version_ID = DB.getSQLValueEx(null, sql, M_PriceList_ID, invoiceDate); if ( M_PriceList_Version_ID > 0 ) Env.setContext(ctx, WindowNo, "M_PriceList_Version_ID", M_PriceList_Version_ID ); } pp.setM_PriceList_Version_ID(M_PriceList_Version_ID); // mTab.setValue("PriceList", pp.getPriceList()); mTab.setValue("PriceLimit", pp.getPriceLimit()); mTab.setValue("PriceActual", pp.getPriceStd()); mTab.setValue("PriceEntered", pp.getPriceStd()); mTab.setValue("C_Currency_ID", Integer.valueOf(pp.getC_Currency_ID())); mTab.setValue("C_UOM_ID", Integer.valueOf(pp.getC_UOM_ID())); Env.setContext(ctx, WindowNo, "EnforcePriceLimit", pp.isEnforcePriceLimit() ? "Y" : "N"); Env.setContext(ctx, WindowNo, "DiscountSchema", pp.isDiscountSchema() ? "Y" : "N"); // return tax (ctx, WindowNo, mTab, mField, value); } // product /** * Invoice Line - Charge. * - updates PriceActual from Charge * - sets PriceLimit, PriceList to zero * Calles tax * @param ctx context * @param WindowNo window no * @param mTab tab * @param mField field * @param value value * @return null or error message */ public String charge (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) { Integer C_Charge_ID = (Integer)value; if (C_Charge_ID == null || C_Charge_ID.intValue() == 0) return ""; // No Product defined if (mTab.getValue("M_Product_ID") != null) { mTab.setValue("C_Charge_ID", null); return "ChargeExclusively"; } mTab.setValue("M_AttributeSetInstance_ID", null); mTab.setValue("S_ResourceAssignment_ID", null); mTab.setValue("C_UOM_ID", Integer.valueOf(SystemIDs.C_UOM_EACH)); // EA Env.setContext(ctx, WindowNo, "DiscountSchema", "N"); String sql = "SELECT ChargeAmt FROM C_Charge WHERE C_Charge_ID=?"; PreparedStatement pstmt = null; ResultSet rs = null; try { pstmt = DB.prepareStatement(sql, null); pstmt.setInt(1, C_Charge_ID.intValue()); rs = pstmt.executeQuery(); if (rs.next()) { mTab.setValue ("PriceEntered", rs.getBigDecimal (1)); mTab.setValue ("PriceActual", rs.getBigDecimal (1)); mTab.setValue ("PriceLimit", Env.ZERO); mTab.setValue ("PriceList", Env.ZERO); mTab.setValue ("Discount", Env.ZERO); } } catch (SQLException e) { log.log(Level.SEVERE, sql + e); return e.getLocalizedMessage(); } finally { DB.close(rs, pstmt); rs = null; pstmt = null; } // return tax (ctx, WindowNo, mTab, mField, value); } // charge /** * Invoice Line - Tax. * - basis: Product, Charge, BPartner Location * - sets C_Tax_ID * Calls Amount * @param ctx context * @param WindowNo window no * @param mTab tab * @param mField field * @param value value * @return null or error message */ public String tax (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) { String column = mField.getColumnName(); if (value == null) return ""; // Check Product int M_Product_ID = 0; if (column.equals("M_Product_ID")) M_Product_ID = ((Integer)value).intValue(); else M_Product_ID = Env.getContextAsInt(ctx, WindowNo, mTab.getTabNo(), "M_Product_ID"); int C_Charge_ID = 0; if (column.equals("C_Charge_ID")) C_Charge_ID = ((Integer)value).intValue(); else C_Charge_ID = Env.getContextAsInt(ctx, WindowNo, mTab.getTabNo(), "C_Charge_ID"); if (log.isLoggable(Level.FINE)) log.fine("Product=" + M_Product_ID + ", C_Charge_ID=" + C_Charge_ID); if (M_Product_ID == 0 && C_Charge_ID == 0) return amt (ctx, WindowNo, mTab, mField, value); // // Check Partner Location int shipC_BPartner_Location_ID = Env.getContextAsInt(ctx, WindowNo, "C_BPartner_Location_ID"); if (shipC_BPartner_Location_ID == 0) return amt (ctx, WindowNo, mTab, mField, value); // if (log.isLoggable(Level.FINE)) log.fine("Ship BP_Location=" + shipC_BPartner_Location_ID); int billC_BPartner_Location_ID = shipC_BPartner_Location_ID; if (log.isLoggable(Level.FINE)) log.fine("Bill BP_Location=" + billC_BPartner_Location_ID); // Dates Timestamp billDate = Env.getContextAsDate(ctx, WindowNo, "DateInvoiced"); if (log.isLoggable(Level.FINE)) log.fine("Bill Date=" + billDate); Timestamp shipDate = billDate; if (log.isLoggable(Level.FINE)) log.fine("Ship Date=" + shipDate); int AD_Org_ID = Env.getContextAsInt(ctx, WindowNo, "AD_Org_ID"); if (log.isLoggable(Level.FINE)) log.fine("Org=" + AD_Org_ID); int M_Warehouse_ID = Env.getContextAsInt(ctx, Env.M_WAREHOUSE_ID); if (log.isLoggable(Level.FINE)) log.fine("Warehouse=" + M_Warehouse_ID); // String deliveryViaRule = getLineDeliveryViaRule(ctx, WindowNo, mTab); int dropshipLocationId = getDropShipLocationId(ctx, WindowNo, mTab); int C_Tax_ID = Core.getTaxLookup().get(ctx, M_Product_ID, C_Charge_ID, billDate, shipDate, AD_Org_ID, M_Warehouse_ID, billC_BPartner_Location_ID, shipC_BPartner_Location_ID, dropshipLocationId, Env.getContext(ctx, WindowNo, "IsSOTrx").equals("Y"), deliveryViaRule, null); if (log.isLoggable(Level.INFO)) log.info("Tax ID=" + C_Tax_ID); // if (C_Tax_ID == 0) mTab.fireDataStatusEEvent(CLogger.retrieveError()); else mTab.setValue("C_Tax_ID", Integer.valueOf(C_Tax_ID)); // return amt (ctx, WindowNo, mTab, mField, value); } // tax /** * Get the delivery via rule from the related order * @param ctx * @param windowNo * @param mTab * @return */ private String getLineDeliveryViaRule(Properties ctx, int windowNo, GridTab mTab) { if (mTab.getValue("C_OrderLine_ID") != null) { int C_OrderLine_ID = (Integer) mTab.getValue("C_OrderLine_ID"); if (C_OrderLine_ID > 0) { MOrderLine orderLine = new MOrderLine(ctx, C_OrderLine_ID, null); return orderLine.getParent().getDeliveryViaRule(); } } if (mTab.getValue("M_InOutLine_ID") != null) { int M_InOutLine_ID = (Integer) mTab.getValue("M_InOutLine_ID"); if (M_InOutLine_ID > 0) { MInOutLine ioLine = new MInOutLine(ctx, M_InOutLine_ID, null); return ioLine.getParent().getDeliveryViaRule(); } } int C_Order_ID = Env.getContextAsInt(ctx, windowNo, "C_Order_ID", true); if (C_Order_ID > 0) { MOrder order = new MOrder(ctx, C_Order_ID, null); return order.getDeliveryViaRule(); } return null; } /** * Get the drop shipment location ID from the related order * @param ctx * @param windowNo * @param mTab * @return */ private int getDropShipLocationId(Properties ctx, int windowNo, GridTab mTab) { if (mTab.getValue("C_OrderLine_ID") != null) { int C_OrderLine_ID = (Integer) mTab.getValue("C_OrderLine_ID"); if (C_OrderLine_ID > 0) { MOrderLine orderLine = new MOrderLine(ctx, C_OrderLine_ID, null); return orderLine.getParent().getDropShip_Location_ID(); } } int C_Order_ID = Env.getContextAsInt(ctx, windowNo, "C_Order_ID", true); if (C_Order_ID > 0) { MOrder order = new MOrder(ctx, C_Order_ID, null); return order.getDropShip_Location_ID(); } return -1; } /** * Invoice - Amount. * - called from QtyInvoiced, PriceActual * - calculates LineNetAmt * @param ctx context * @param WindowNo window no * @param mTab tab * @param mField field * @param value value * @return null or error message */ public String amt (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) { if (isCalloutActive() || value == null) return ""; int C_UOM_To_ID = Env.getContextAsInt(ctx, WindowNo, mTab.getTabNo(), "C_UOM_ID"); int M_Product_ID = Env.getContextAsInt(ctx, WindowNo, mTab.getTabNo(), "M_Product_ID"); int M_PriceList_ID = Env.getContextAsInt(ctx, WindowNo, "M_PriceList_ID"); int StdPrecision = MPriceList.getStandardPrecision(ctx, M_PriceList_ID); MPriceList pl = new MPriceList(ctx, M_PriceList_ID, null); boolean isEnforcePriceLimit = pl.isEnforcePriceLimit(); BigDecimal QtyEntered, QtyInvoiced, PriceEntered, PriceActual, PriceLimit, Discount, PriceList; // get values QtyEntered = (BigDecimal)mTab.getValue("QtyEntered"); QtyInvoiced = (BigDecimal)mTab.getValue("QtyInvoiced"); if (log.isLoggable(Level.FINE)) log.fine("QtyEntered=" + QtyEntered + ", Invoiced=" + QtyInvoiced + ", UOM=" + C_UOM_To_ID); // PriceEntered = (BigDecimal)mTab.getValue("PriceEntered"); PriceActual = (BigDecimal)mTab.getValue("PriceActual"); PriceLimit = (BigDecimal)mTab.getValue("PriceLimit"); PriceList = (BigDecimal)mTab.getValue("PriceList"); if (log.isLoggable(Level.FINE)){ log.fine("PriceList=" + PriceList + ", Limit=" + PriceLimit + ", Precision=" + StdPrecision); log.fine("PriceEntered=" + PriceEntered + ", Actual=" + PriceActual);// + ", Discount=" + Discount); } // No Product if ( M_Product_ID == 0 ) { // if price change sync price actual and entered // else ignore if (mField.getColumnName().equals("PriceActual")) { PriceEntered = (BigDecimal) value; mTab.setValue("PriceEntered", value); } else if (mField.getColumnName().equals("PriceEntered")) { PriceActual = (BigDecimal) value; mTab.setValue("PriceActual", value); } } // Product Qty changed - recalc price else if ((mField.getColumnName().equals("QtyInvoiced") || mField.getColumnName().equals("QtyEntered") || mField.getColumnName().equals("C_UOM_ID") || mField.getColumnName().equals("M_Product_ID")) && !"N".equals(Env.getContext(ctx, WindowNo, "DiscountSchema"))) { int C_BPartner_ID = Env.getContextAsInt(ctx, WindowNo, "C_BPartner_ID"); if (mField.getColumnName().equals("QtyEntered")) QtyInvoiced = MUOMConversion.convertProductFrom (ctx, M_Product_ID, C_UOM_To_ID, QtyEntered); if (QtyInvoiced == null) QtyInvoiced = QtyEntered; boolean IsSOTrx = Env.getContext(ctx, WindowNo, "IsSOTrx").equals("Y"); IProductPricing pp = Core.getProductPricing(); pp.setInitialValues(M_Product_ID, C_BPartner_ID, QtyInvoiced, IsSOTrx, null); Timestamp date = (Timestamp)mTab.getValue("DateInvoiced"); pp.setPriceDate(date); I_C_InvoiceLine invoiceLine = GridTabWrapper.create(mTab, I_C_InvoiceLine.class); pp.setInvoiceLine(invoiceLine, null); pp.setM_PriceList_ID(M_PriceList_ID); int M_PriceList_Version_ID = Env.getContextAsInt(ctx, WindowNo, "M_PriceList_Version_ID"); pp.setM_PriceList_Version_ID(M_PriceList_Version_ID); // PriceEntered = MUOMConversion.convertProductFrom (ctx, M_Product_ID, C_UOM_To_ID, pp.getPriceStd(), 12); if (PriceEntered == null) PriceEntered = pp.getPriceStd(); // if (log.isLoggable(Level.FINE)) log.fine("amt - QtyChanged -> PriceActual=" + pp.getPriceStd() + ", PriceEntered=" + PriceEntered + ", Discount=" + pp.getDiscount()); PriceActual = pp.getPriceStd(); mTab.setValue("PriceActual", pp.getPriceStd()); mTab.setValue("PriceEntered", PriceEntered); Env.setContext(ctx, WindowNo, "DiscountSchema", pp.isDiscountSchema() ? "Y" : "N"); } else if (mField.getColumnName().equals("PriceActual")) { PriceActual = (BigDecimal)value; PriceEntered = MUOMConversion.convertProductFrom (ctx, M_Product_ID, C_UOM_To_ID, PriceActual, 12); if (PriceEntered == null) PriceEntered = PriceActual; // if (log.isLoggable(Level.FINE)) log.fine("amt - PriceActual=" + PriceActual + " -> PriceEntered=" + PriceEntered); mTab.setValue("PriceEntered", PriceEntered); } else if (mField.getColumnName().equals("PriceEntered")) { PriceEntered = (BigDecimal)value; PriceActual = MUOMConversion.convertProductTo (ctx, M_Product_ID, C_UOM_To_ID, PriceEntered, 12); if (PriceActual == null) PriceActual = PriceEntered; // if (log.isLoggable(Level.FINE)) log.fine("amt - PriceEntered=" + PriceEntered + " -> PriceActual=" + PriceActual); mTab.setValue("PriceActual", PriceActual); } // Check PriceLimit String epl = Env.getContext(ctx, WindowNo, "EnforcePriceLimit"); boolean enforce = Env.isSOTrx(ctx, WindowNo) && epl != null && !epl.equals("") ? epl.equals("Y") : isEnforcePriceLimit; if (enforce && MRole.getDefault().isOverwritePriceLimit()) enforce = false; // Check Price Limit? if (enforce && PriceLimit.doubleValue() != 0.0 && PriceActual.compareTo(PriceLimit) < 0) { PriceActual = PriceLimit; PriceEntered = MUOMConversion.convertProductFrom (ctx, M_Product_ID, C_UOM_To_ID, PriceLimit, 12); if (PriceEntered == null) PriceEntered = PriceLimit; if (log.isLoggable(Level.FINE)) log.fine("amt =(under) PriceEntered=" + PriceEntered + ", Actual" + PriceLimit); mTab.setValue ("PriceActual", PriceLimit); mTab.setValue ("PriceEntered", PriceEntered); mTab.fireDataStatusEEvent ("UnderLimitPrice", "", false); // Repeat Discount calc if (PriceList.compareTo(Env.ZERO) != 0) { Discount = BigDecimal.valueOf((PriceList.doubleValue () - PriceActual.doubleValue ()) / PriceList.doubleValue () * 100.0); if (Discount.scale () > 2) Discount = Discount.setScale (2, RoundingMode.HALF_UP); } } // Line Net Amt BigDecimal LineNetAmt = QtyEntered.multiply(PriceEntered); if (LineNetAmt.scale() > StdPrecision) LineNetAmt = LineNetAmt.setScale(StdPrecision, RoundingMode.HALF_UP); if (log.isLoggable(Level.INFO)) log.info("amt = LineNetAmt=" + LineNetAmt); mTab.setValue("LineNetAmt", LineNetAmt); // Calculate Tax Amount for PO boolean IsSOTrx = "Y".equals(Env.getContext(Env.getCtx(), WindowNo, "IsSOTrx")); if (!IsSOTrx) { BigDecimal TaxAmt = Env.ZERO; // teo_sarca: [ 1656829 ] Problem when there is not tax selected in vendor invoice if (mField.getColumnName().equals("TaxAmt")) { TaxAmt = (BigDecimal)mTab.getValue("TaxAmt"); } else { Integer taxID = (Integer)mTab.getValue("C_Tax_ID"); if (taxID != null) { int C_Tax_ID = taxID.intValue(); MTax tax = new MTax (ctx, C_Tax_ID, null); TaxAmt = tax.calculateTax(LineNetAmt, isTaxIncluded(WindowNo), StdPrecision); mTab.setValue("TaxAmt", TaxAmt); } } // Add it up mTab.setValue("LineTotalAmt", LineNetAmt.add(TaxAmt)); } return ""; } // amt /** * Is Tax Included * @param WindowNo window no * @return tax included (default: false) */ private boolean isTaxIncluded (int WindowNo) { String ss = Env.getContext(Env.getCtx(), WindowNo, "IsTaxIncluded"); // Not Set Yet if (ss.length() == 0) { int M_PriceList_ID = Env.getContextAsInt(Env.getCtx(), WindowNo, "M_PriceList_ID"); if (M_PriceList_ID == 0) return false; ss = DB.getSQLValueString(null, "SELECT IsTaxIncluded FROM M_PriceList WHERE M_PriceList_ID=?", M_PriceList_ID); if (ss == null) ss = "N"; Env.setContext(Env.getCtx(), WindowNo, "IsTaxIncluded", ss); } return "Y".equals(ss); } // isTaxIncluded /** * Invoice Line - Quantity. * - called from C_UOM_ID, QtyEntered, QtyInvoiced * - enforces qty UOM relationship * @param ctx context * @param WindowNo window no * @param mTab tab * @param mField field * @param value value * @return null or error message */ public String qty (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) { if (isCalloutActive() || value == null) return ""; int M_Product_ID = Env.getContextAsInt(ctx, WindowNo, mTab.getTabNo(), "M_Product_ID"); BigDecimal QtyInvoiced, QtyEntered, PriceActual, PriceEntered; // No Product if (M_Product_ID == 0) { QtyEntered = (BigDecimal)mTab.getValue("QtyEntered"); mTab.setValue("QtyInvoiced", QtyEntered); } // UOM Changed - convert from Entered -> Product else if (mField.getColumnName().equals("C_UOM_ID")) { int C_UOM_To_ID = ((Integer)value).intValue(); QtyEntered = (BigDecimal)mTab.getValue("QtyEntered"); BigDecimal QtyEntered1 = QtyEntered.setScale(MUOM.getPrecision(ctx, C_UOM_To_ID), RoundingMode.HALF_UP); if (QtyEntered.compareTo(QtyEntered1) != 0) { if (log.isLoggable(Level.FINE)) log.fine("Corrected QtyEntered Scale UOM=" + C_UOM_To_ID + "; QtyEntered=" + QtyEntered + "->" + QtyEntered1); QtyEntered = QtyEntered1; mTab.setValue("QtyEntered", QtyEntered); } QtyInvoiced = MUOMConversion.convertProductFrom (ctx, M_Product_ID, C_UOM_To_ID, QtyEntered); if (QtyInvoiced == null) QtyInvoiced = QtyEntered; boolean conversion = QtyEntered.compareTo(QtyInvoiced) != 0; PriceActual = (BigDecimal)mTab.getValue("PriceActual"); PriceEntered = MUOMConversion.convertProductFrom (ctx, M_Product_ID, C_UOM_To_ID, PriceActual, 12); if (PriceEntered == null) PriceEntered = PriceActual; if (log.isLoggable(Level.FINE)) log.fine("qty - UOM=" + C_UOM_To_ID + ", QtyEntered/PriceActual=" + QtyEntered + "/" + PriceActual + " -> " + conversion + " QtyInvoiced/PriceEntered=" + QtyInvoiced + "/" + PriceEntered); Env.setContext(ctx, WindowNo, "UOMConversion", conversion ? "Y" : "N"); mTab.setValue("QtyInvoiced", QtyInvoiced); mTab.setValue("PriceEntered", PriceEntered); } // QtyEntered changed - calculate QtyInvoiced else if (mField.getColumnName().equals("QtyEntered")) { int C_UOM_To_ID = Env.getContextAsInt(ctx, WindowNo, mTab.getTabNo(), "C_UOM_ID"); QtyEntered = (BigDecimal)value; BigDecimal QtyEntered1 = QtyEntered.setScale(MUOM.getPrecision(ctx, C_UOM_To_ID), RoundingMode.HALF_UP); if (QtyEntered.compareTo(QtyEntered1) != 0) { if (log.isLoggable(Level.FINE)) log.fine("Corrected QtyEntered Scale UOM=" + C_UOM_To_ID + "; QtyEntered=" + QtyEntered + "->" + QtyEntered1); QtyEntered = QtyEntered1; mTab.setValue("QtyEntered", QtyEntered); } QtyInvoiced = MUOMConversion.convertProductFrom (ctx, M_Product_ID, C_UOM_To_ID, QtyEntered); if (QtyInvoiced == null) QtyInvoiced = QtyEntered; boolean conversion = QtyEntered.compareTo(QtyInvoiced) != 0; if (log.isLoggable(Level.FINE)) log.fine("qty - UOM=" + C_UOM_To_ID + ", QtyEntered=" + QtyEntered + " -> " + conversion + " QtyInvoiced=" + QtyInvoiced); Env.setContext(ctx, WindowNo, "UOMConversion", conversion ? "Y" : "N"); mTab.setValue("QtyInvoiced", QtyInvoiced); } // QtyInvoiced changed - calculate QtyEntered (should not happen) else if (mField.getColumnName().equals("QtyInvoiced")) { int C_UOM_To_ID = Env.getContextAsInt(ctx, WindowNo, mTab.getTabNo(), "C_UOM_ID"); QtyInvoiced = (BigDecimal)value; int precision = MProduct.get(ctx, M_Product_ID).getUOMPrecision(); BigDecimal QtyInvoiced1 = QtyInvoiced.setScale(precision, RoundingMode.HALF_UP); if (QtyInvoiced.compareTo(QtyInvoiced1) != 0) { if (log.isLoggable(Level.FINE)) log.fine("Corrected QtyInvoiced Scale " + QtyInvoiced + "->" + QtyInvoiced1); QtyInvoiced = QtyInvoiced1; mTab.setValue("QtyInvoiced", QtyInvoiced); } QtyEntered = MUOMConversion.convertProductTo (ctx, M_Product_ID, C_UOM_To_ID, QtyInvoiced); if (QtyEntered == null) QtyEntered = QtyInvoiced; boolean conversion = QtyInvoiced.compareTo(QtyEntered) != 0; if (log.isLoggable(Level.FINE)) log.fine("qty - UOM=" + C_UOM_To_ID + ", QtyInvoiced=" + QtyInvoiced + " -> " + conversion + " QtyEntered=" + QtyEntered); Env.setContext(ctx, WindowNo, "UOMConversion", conversion ? "Y" : "N"); mTab.setValue("QtyEntered", QtyEntered); } // return ""; } // qty public String navigateInvoiceLine(Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value) { Integer M_Product_ID = Env.getContextAsInt(ctx, WindowNo, mTab.getTabNo(), "M_Product_ID"); if (M_Product_ID == null || M_Product_ID.intValue() == 0) { Env.setContext(ctx, WindowNo, "DiscountSchema", "N"); return ""; } /***** Price Calculation see also qty ****/ int C_BPartner_ID = Env.getContextAsInt(ctx, WindowNo, "C_BPartner_ID"); BigDecimal Qty = (BigDecimal)mTab.getValue("QtyOrdered"); boolean IsSOTrx = Env.getContext(ctx, WindowNo, "IsSOTrx").equals("Y"); IProductPricing pp = Core.getProductPricing(); pp.setInitialValues(M_Product_ID.intValue(), C_BPartner_ID, Qty, IsSOTrx, null); Timestamp orderDate = (Timestamp)mTab.getValue("DateOrdered"); pp.setPriceDate(orderDate); I_C_InvoiceLine invoiceLine = GridTabWrapper.create(mTab, I_C_InvoiceLine.class); pp.setInvoiceLine(invoiceLine, null); // int M_PriceList_ID = Env.getContextAsInt(ctx, WindowNo, "M_PriceList_ID"); pp.setM_PriceList_ID(M_PriceList_ID); /** PLV is only accurate if PL selected in header */ int M_PriceList_Version_ID = Env.getContextAsInt(ctx, WindowNo, "M_PriceList_Version_ID"); if ( M_PriceList_Version_ID == 0 && M_PriceList_ID > 0) { String sql = "SELECT plv.M_PriceList_Version_ID " + "FROM M_PriceList_Version plv " + "WHERE plv.M_PriceList_ID=? " // 1 + " AND plv.ValidFrom <= ? " + "ORDER BY plv.ValidFrom DESC"; // Use newest price list - may not be future M_PriceList_Version_ID = DB.getSQLValueEx(null, sql, M_PriceList_ID, orderDate); if ( M_PriceList_Version_ID > 0 ) Env.setContext(ctx, WindowNo, "M_PriceList_Version_ID", M_PriceList_Version_ID ); } pp.setM_PriceList_Version_ID(M_PriceList_Version_ID); // Env.setContext(ctx, WindowNo, "EnforcePriceLimit", pp.isEnforcePriceLimit() ? "Y" : "N"); Env.setContext(ctx, WindowNo, "DiscountSchema", pp.isDiscountSchema() ? "Y" : "N"); return ""; } } // CalloutInvoice