/** * Create Facts (the accounting logic) for PJI * * <pre> * Issue * ProjectWIP DR * Inventory CR * </pre> * * Project Account is either Asset or WIP depending on Project Type * * @param as accounting schema * @return Fact */ public ArrayList<Fact> createFacts(MAcctSchema as) { // create Fact Header Fact fact = new Fact(this, as, Fact.POST_Actual); setC_Currency_ID(as.getC_Currency_ID()); MProject project = new MProject(getCtx(), m_issue.getC_Project_ID(), getTrxName()); String ProjectCategory = project.getProjectCategory(); MProduct product = MProduct.get(getCtx(), m_issue.getM_Product_ID()); // Line pointers FactLine dr = null; FactLine cr = null; // Issue Cost BigDecimal costs = null; BigDecimal total = Env.ZERO; if (m_issue.getM_InOutLine_ID() != 0) costs = getPOCost(as); else if (m_issue.getS_TimeExpenseLine_ID() != 0) costs = getLaborCost(as); if (costs == null) // standard Product Costs { for (MCostDetail cost : m_line.getCostDetail(as)) { if (!MCostDetail.existsCost(cost)) continue; costs = MCostDetail.getTotalCost(cost, as); total = total.add(costs); } } if (total == null || total.signum() == 0) { p_Error = "Resubmit - No Costs for " + product.getName(); log.log(Level.WARNING, p_Error); return null; } // Project DR int acctType = ACCTTYPE_ProjectWIP; if (MProject.PROJECTCATEGORY_AssetProject.equals(ProjectCategory)) acctType = ACCTTYPE_ProjectAsset; dr = fact.createLine(m_line, getAccount(acctType, as), as.getC_Currency_ID(), costs, null); dr.setQty(m_line.getQty().negate()); // Inventory CR acctType = ProductCost.ACCTTYPE_P_Asset; if (product.isService()) acctType = ProductCost.ACCTTYPE_P_Expense; cr = fact.createLine( m_line, m_line.getAccount(acctType, as), as.getC_Currency_ID(), null, costs); cr.setM_Locator_ID(m_line.getM_Locator_ID()); cr.setLocationFromLocator(m_line.getM_Locator_ID(), true); // from Loc // ArrayList<Fact> facts = new ArrayList<Fact>(); facts.add(fact); return facts; } // createFact
/** * Load Document Details * * @return error message or null */ protected String loadDocumentDetails() { setC_Currency_ID(NO_CURRENCY); m_issue = (MProjectIssue) getPO(); setDateDoc(m_issue.getMovementDate()); setDateAcct(m_issue.getMovementDate()); // Pseudo Line m_line = new DocLine(m_issue, this); m_line.setQty(m_issue.getMovementQty(), true); // sets Trx and Storage Qty // Pseudo Line Check if (m_line.getM_Product_ID() == 0) log.warning(m_line.toString() + " - No Product"); log.fine(m_line.toString()); return null; } // loadDocumentDetails
/** * Load Invoice Line * * @param prod production * @return DoaLine Array */ private DocLine[] loadLines(X_M_Production prod) { ArrayList<DocLine> list = new ArrayList<DocLine>(); mQtyProduced = new HashMap<>(); String sqlPL = null; if (prod.isUseProductionPlan()) { // Production // -- ProductionLine - the real level sqlPL = "SELECT * FROM " + " M_ProductionLine pro_line INNER JOIN M_ProductionPlan plan ON pro_line.M_ProductionPlan_id = plan.M_ProductionPlan_id " + " INNER JOIN M_Production pro ON pro.M_Production_id = plan.M_Production_id " + " WHERE pro.M_Production_ID=? " + " ORDER BY plan.M_ProductionPlan_id, pro_line.Line"; } else { // Production // -- ProductionLine - the real level sqlPL = "SELECT * FROM M_ProductionLine pl " + "WHERE pl.M_Production_ID=? " + "ORDER BY pl.Line"; } PreparedStatement pstmtPL = null; ResultSet rsPL = null; try { pstmtPL = DB.prepareStatement(sqlPL, getTrxName()); pstmtPL.setInt(1, get_ID()); rsPL = pstmtPL.executeQuery(); while (rsPL.next()) { X_M_ProductionLine line = new X_M_ProductionLine(getCtx(), rsPL, getTrxName()); if (line.getMovementQty().signum() == 0) { if (log.isLoggable(Level.INFO)) log.info("LineQty=0 - " + line); continue; } DocLine docLine = new DocLine(line, this); docLine.setQty(line.getMovementQty(), false); // Identify finished BOM Product if (prod.isUseProductionPlan()) docLine.setProductionBOM( line.getM_Product_ID() == line.getM_ProductionPlan().getM_Product_ID()); else docLine.setProductionBOM(line.getM_Product_ID() == prod.getM_Product_ID()); if (docLine.isProductionBOM()) { manipulateQtyProduced( mQtyProduced, line, prod.isUseProductionPlan(), line.getMovementQty()); } // if (log.isLoggable(Level.FINE)) log.fine(docLine.toString()); list.add(docLine); } } catch (Exception ee) { log.log(Level.SEVERE, sqlPL, ee); } finally { DB.close(rsPL, pstmtPL); rsPL = null; pstmtPL = null; } DocLine[] dl = new DocLine[list.size()]; list.toArray(dl); return dl; } // loadLines
/** * Create Facts (the accounting logic) for MMP. * * <pre> * Production * Inventory DR CR * </pre> * * @param as account schema * @return Fact */ public ArrayList<Fact> createFacts(MAcctSchema as) { // create Fact Header Fact fact = new Fact(this, as, Fact.POST_Actual); setC_Currency_ID(as.getC_Currency_ID()); // Line pointer FactLine fl = null; X_M_Production prod = (X_M_Production) getPO(); for (int i = 0; i < p_lines.length; i++) { DocLine line = p_lines[i]; // Calculate Costs BigDecimal costs = null; // MZ Goodwill // if Production CostDetail exist then get Cost from Cost Detail MCostDetail cd = MCostDetail.get( as.getCtx(), "M_ProductionLine_ID=?", line.get_ID(), line.getM_AttributeSetInstance_ID(), as.getC_AcctSchema_ID(), getTrxName()); if (cd != null) { costs = cd.getAmt(); } else { costs = line.getProductCosts(as, line.getAD_Org_ID(), false); } if (line.isProductionBOM()) { X_M_ProductionLine endProLine = (X_M_ProductionLine) line.getPO(); Object parentEndPro = prod.isUseProductionPlan() ? endProLine.getM_ProductionPlan_ID() : endProLine.getM_Production_ID(); // Get BOM Cost - Sum of individual lines BigDecimal bomCost = Env.ZERO; for (int ii = 0; ii < p_lines.length; ii++) { DocLine line0 = p_lines[ii]; X_M_ProductionLine bomProLine = (X_M_ProductionLine) line0.getPO(); Object parentBomPro = prod.isUseProductionPlan() ? bomProLine.getM_ProductionPlan_ID() : bomProLine.getM_Production_ID(); if (!parentBomPro.equals(parentEndPro)) continue; if (!line0.isProductionBOM()) { // get cost of children MCostDetail cd0 = MCostDetail.get( as.getCtx(), "M_ProductionLine_ID=?", line0.get_ID(), line0.getM_AttributeSetInstance_ID(), as.getC_AcctSchema_ID(), getTrxName()); BigDecimal costs0; if (cd0 != null) { costs0 = cd0.getAmt(); } else { costs0 = line0.getProductCosts(as, line0.getAD_Org_ID(), false); } bomCost = bomCost.add(costs0.setScale(2, BigDecimal.ROUND_HALF_UP)); } } BigDecimal qtyProduced = manipulateQtyProduced(mQtyProduced, endProLine, prod.isUseProductionPlan(), null); if (line.getQty().compareTo(qtyProduced) != 0) { BigDecimal factor = line.getQty().divide(qtyProduced, 12, BigDecimal.ROUND_HALF_UP); bomCost = bomCost.multiply(factor).setScale(2, BigDecimal.ROUND_HALF_UP); } int precision = as.getStdPrecision(); BigDecimal variance = (costs.setScale(precision, BigDecimal.ROUND_HALF_UP)).subtract(bomCost.negate()); // only post variance if it's not zero if (variance.signum() != 0) { // post variance fl = fact.createLine( line, line.getAccount(ProductCost.ACCTTYPE_P_RateVariance, as), as.getC_Currency_ID(), variance.negate()); if (fl == null) { p_Error = "Couldn't post variance " + line.getLine() + " - " + line; return null; } fl.setQty(Env.ZERO); } // costs = bomCost.negate(); } // end MZ // Inventory DR CR fl = fact.createLine( line, line.getAccount(ProductCost.ACCTTYPE_P_Asset, as), as.getC_Currency_ID(), costs); if (fl == null) { p_Error = "No Costs for Line " + line.getLine() + " - " + line; return null; } fl.setM_Locator_ID(line.getM_Locator_ID()); fl.setQty(line.getQty()); // Cost Detail String description = line.getDescription(); if (description == null) description = ""; if (line.isProductionBOM()) description += "(*)"; if (!MCostDetail.createProduction( as, line.getAD_Org_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), line.get_ID(), 0, costs, line.getQty(), description, getTrxName())) { p_Error = "Failed to create cost detail record"; return null; } } // ArrayList<Fact> facts = new ArrayList<Fact>(); facts.add(fact); return facts; } // createFact