📄 mcost.java
字号:
/******************************************************************************
* The contents of this file are subject to the Compiere License Version 1.1
* ("License"); You may not use this file except in compliance with the License
* You may obtain a copy of the License at http://www.compiere.org/license.html
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
* the specific language governing rights and limitations under the License.
* The Original Code is Compiere ERP & CRM Smart Business Solution. The Initial
* Developer of the Original Code is Jorg Janke. Portions created by Jorg Janke
* are Copyright (C) 1999-2005 Jorg Janke.
* All parts are Copyright (C) 1999-2005 ComPiere, Inc. All Rights Reserved.
* Contributor(s): ______________________________________.
*****************************************************************************/
package org.compiere.model;
import java.sql.*;
import java.math.*;
import java.util.*;
import java.util.logging.*;
import org.compiere.*;
import org.compiere.util.*;
/**
* Product Cost Model
*
* @author Jorg Janke
* @version $Id: MCost.java,v 1.20 2006/01/28 01:28:28 jjanke Exp $
*/
public class MCost extends X_M_Cost
{
/**
* Retrieve/Calculate Current Cost Price
* @param product product
* @param M_AttributeSetInstance_ID real asi
* @param as accounting schema
* @param AD_Org_ID real org
* @param costingMethod AcctSchema.COSTINGMETHOD_*
* @param qty qty
* @param C_OrderLine_ID optional order line
* @param zeroCostsOK zero/no costs are OK
* @return current cost price or null
*/
public static BigDecimal getCurrentCost (MProduct product,
int M_AttributeSetInstance_ID,
MAcctSchema as, int AD_Org_ID, String costingMethod,
BigDecimal qty, int C_OrderLine_ID,
boolean zeroCostsOK, String trxName)
{
String CostingLevel = as.getCostingLevel();
MProductCategoryAcct pca = MProductCategoryAcct.get (product.getCtx(),
product.getM_Product_Category_ID(), as.getC_AcctSchema_ID(), null);
if (pca == null)
throw new IllegalStateException("Cannot find Acct for M_Product_Category_ID="
+ product.getM_Product_Category_ID()
+ ", C_AcctSchema_ID=" + as.getC_AcctSchema_ID());
// Costing Level
if (pca.getCostingLevel() != null)
CostingLevel = pca.getCostingLevel();
if (MAcctSchema.COSTINGLEVEL_Client.equals(CostingLevel))
{
AD_Org_ID = 0;
M_AttributeSetInstance_ID = 0;
}
else if (MAcctSchema.COSTINGLEVEL_Organization.equals(CostingLevel))
M_AttributeSetInstance_ID = 0;
else if (MAcctSchema.COSTINGLEVEL_BatchLot.equals(CostingLevel))
AD_Org_ID = 0;
// Costing Method
if (costingMethod == null)
{
costingMethod = pca.getCostingMethod();
if (costingMethod == null)
{
costingMethod = as.getCostingMethod();
if (costingMethod == null)
throw new IllegalArgumentException("No Costing Method");
// costingMethod = MAcctSchema.COSTINGMETHOD_StandardCosting;
}
}
// Create/Update Costs
MCostDetail.processProduct (product, trxName);
return getCurrentCost (
product, M_AttributeSetInstance_ID,
as, AD_Org_ID, as.getM_CostType_ID(), costingMethod, qty,
C_OrderLine_ID, zeroCostsOK, trxName);
} // getCurrentCost
/**
* Get Current Cost Price for Costing Level
* @param product product
* @param M_ASI_ID costing level asi
* @param Org_ID costing level org
* @param M_CostType_ID cost type
* @param as AcctSchema
* @param costingMethod method
* @param qty quantity
* @param C_OrderLine_ID optional order line
* @param zeroCostsOK zero/no costs are OK
* @return cost price or null
*/
private static BigDecimal getCurrentCost (MProduct product, int M_ASI_ID,
MAcctSchema as, int Org_ID, int M_CostType_ID,
String costingMethod, BigDecimal qty, int C_OrderLine_ID,
boolean zeroCostsOK, String trxName)
{
BigDecimal currentCostPrice = null;
String costElementType = null;
int M_CostElement_ID = 0;
BigDecimal percent = null;
//
BigDecimal materialCostEach = Env.ZERO;
BigDecimal otherCostEach = Env.ZERO;
BigDecimal percentage = Env.ZERO;
int count = 0;
//
String sql = "SELECT SUM(c.CurrentCostPrice), ce.CostElementType, ce.CostingMethod,"
+ " c.Percent, c.M_CostElement_ID " // 4..5
+ "FROM M_Cost c"
+ " LEFT OUTER JOIN M_CostElement ce ON (c.M_CostElement_ID=ce.M_CostElement_ID) "
+ "WHERE c.AD_Client_ID=? AND c.AD_Org_ID=?" // #1/2
+ " AND c.M_Product_ID=?" // #3
+ " AND (c.M_AttributeSetInstance_ID=? OR c.M_AttributeSetInstance_ID=0)" // #4
+ " AND c.M_CostType_ID=? AND c.C_AcctSchema_ID=?" // #5/6
+ " AND (ce.CostingMethod IS NULL OR ce.CostingMethod=?) " // #7
+ "GROUP BY ce.CostElementType, ce.CostingMethod, c.Percent, c.M_CostElement_ID";
PreparedStatement pstmt = null;
try
{
pstmt = DB.prepareStatement (sql, trxName);
pstmt.setInt (1, product.getAD_Client_ID());
pstmt.setInt (2, Org_ID);
pstmt.setInt (3, product.getM_Product_ID());
pstmt.setInt (4, M_ASI_ID);
pstmt.setInt (5, M_CostType_ID);
pstmt.setInt (6, as.getC_AcctSchema_ID());
pstmt.setString (7, costingMethod);
ResultSet rs = pstmt.executeQuery ();
while (rs.next ())
{
currentCostPrice = rs.getBigDecimal(1);
costElementType = rs.getString(2);
String cm = rs.getString(3);
percent = rs.getBigDecimal(4);
// M_CostElement_ID = rs.getInt(5);
s_log.finest("CurrentCostPrice=" + currentCostPrice
+ ", CostElementType=" + costElementType
+ ", CostingMethod=" + cm
+ ", Percent=" + percent);
//
if (currentCostPrice != null && currentCostPrice.signum() != 0)
{
if (cm != null)
materialCostEach = materialCostEach.add(currentCostPrice);
else
otherCostEach = otherCostEach.add(currentCostPrice);
}
if (percent != null && percent.signum() != 0)
percentage = percentage.add(percent);
count++;
}
rs.close ();
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
s_log.log (Level.SEVERE, sql, e);
}
try
{
if (pstmt != null)
pstmt.close ();
pstmt = null;
}
catch (Exception e)
{
pstmt = null;
}
if (count > 1) // Print summary
s_log.finest("MaterialCost=" + materialCostEach
+ ", OtherCosts=" + otherCostEach
+ ", Percentage=" + percentage);
// Seed Initial Costs
if (materialCostEach.signum() == 0) // no costs
{
if (zeroCostsOK)
return Env.ZERO;
materialCostEach = getSeedCosts(product, M_ASI_ID,
as, Org_ID, costingMethod, C_OrderLine_ID);
}
if (materialCostEach == null)
return null;
// Material Costs
BigDecimal materialCost = materialCostEach.multiply(qty);
// Standard costs - just Material Costs
if (MCostElement.COSTINGMETHOD_StandardCosting.equals(costingMethod))
{
s_log.finer("MaterialCosts = " + materialCost);
return materialCost;
}
if (MCostElement.COSTINGMETHOD_Fifo.equals(costingMethod)
|| MCostElement.COSTINGMETHOD_Lifo.equals(costingMethod))
{
MCostElement ce = MCostElement.getMaterialCostElement(as, costingMethod);
materialCost = MCostQueue.getCosts(product, M_ASI_ID,
as, Org_ID, ce, qty, trxName);
}
// Other Costs
BigDecimal otherCost = otherCostEach.multiply(qty);
// Costs
BigDecimal costs = otherCost.add(materialCost);
if (costs.signum() == 0)
return null;
s_log.finer("Sum Costs = " + costs);
int precision = as.getCostingPrecision();
if (percentage.signum() == 0) // no percentages
{
if (costs.scale() > precision)
costs = costs.setScale(precision, BigDecimal.ROUND_HALF_UP);
return costs;
}
//
BigDecimal percentCost = costs.multiply(percentage);
percentCost = percentCost.divide(Env.ONEHUNDRED, precision, BigDecimal.ROUND_HALF_UP);
costs = costs.add(percentCost);
if (costs.scale() > precision)
costs = costs.setScale(precision, BigDecimal.ROUND_HALF_UP);
s_log.finer("Sum Costs = " + costs + " (Add=" + percentCost + ")");
return costs;
} // getCurrentCost
/**
* Get Seed Costs
* @param product product
* @param M_ASI_ID costing level asi
* @param as accounting schema
* @param Org_ID costing level org
* @param costingMethod costing method
* @param C_OrderLine_ID optional order line
* @return price or null
*/
public static BigDecimal getSeedCosts (MProduct product, int M_ASI_ID,
MAcctSchema as, int Org_ID, String costingMethod, int C_OrderLine_ID)
{
BigDecimal retValue = null;
// Direct Data
if (MCostElement.COSTINGMETHOD_AverageInvoice.equals(costingMethod))
retValue = calculateAverageInv(product, M_ASI_ID, as, Org_ID);
else if (MCostElement.COSTINGMETHOD_AveragePO.equals(costingMethod))
retValue = calculateAveragePO(product, M_ASI_ID, as, Org_ID);
else if (MCostElement.COSTINGMETHOD_Fifo.equals(costingMethod))
retValue = calculateFiFo(product, M_ASI_ID, as, Org_ID);
else if (MCostElement.COSTINGMETHOD_Lifo.equals(costingMethod))
retValue = calculateLiFo(product, M_ASI_ID, as, Org_ID);
else if (MCostElement.COSTINGMETHOD_LastInvoice.equals(costingMethod))
retValue = getLastInvoicePrice(product, M_ASI_ID, Org_ID, as.getC_Currency_ID());
else if (MCostElement.COSTINGMETHOD_LastPOPrice.equals(costingMethod))
{
if (C_OrderLine_ID != 0)
retValue = getPOPrice(product, C_OrderLine_ID, as.getC_Currency_ID());
if (retValue == null || retValue.signum() == 0)
retValue = getLastPOPrice(product, M_ASI_ID, Org_ID, as.getC_Currency_ID());
}
else if (MCostElement.COSTINGMETHOD_StandardCosting.equals(costingMethod))
{
// migrate old costs
MProductCosting pc = MProductCosting.get(product.getCtx(), product.getM_Product_ID(),
as.getC_AcctSchema_ID(), null);
if (pc != null)
retValue = pc.getCurrentCostPrice();
}
else if (MCostElement.COSTINGMETHOD_UserDefined.equals(costingMethod))
;
else
throw new IllegalArgumentException("Unknown Costing Method = " + costingMethod);
if (retValue != null && retValue.signum() != 0)
{
s_log.fine(product.getName() + ", CostingMethod=" + costingMethod + " - " + retValue);
return retValue;
}
// Look for exact Order Line
if (C_OrderLine_ID != 0)
{
retValue = getPOPrice(product, C_OrderLine_ID, as.getC_Currency_ID());
if (retValue != null && retValue.signum() != 0)
{
s_log.fine(product.getName() + ", PO - " + retValue);
return retValue;
}
}
// Look for Standard Costs first
if (!MCostElement.COSTINGMETHOD_StandardCosting.equals(costingMethod))
{
MCostElement ce = MCostElement.getMaterialCostElement(as, MCostElement.COSTINGMETHOD_StandardCosting);
MCost cost = get(product, M_ASI_ID, as, Org_ID, ce.getM_CostElement_ID());
if (cost != null && cost.getCurrentCostPrice().signum() != 0)
{
s_log.fine(product.getName() + ", Standard - " + retValue);
return cost.getCurrentCostPrice();
}
}
// We do not have a price
// PO first
if (MCostElement.COSTINGMETHOD_AveragePO.equals(costingMethod)
|| MCostElement.COSTINGMETHOD_LastPOPrice.equals(costingMethod)
|| MCostElement.COSTINGMETHOD_StandardCosting.equals(costingMethod))
{
// try Last PO
retValue = getLastPOPrice(product, M_ASI_ID, Org_ID, as.getC_Currency_ID());
if (Org_ID != 0 && (retValue == null || retValue.signum() == 0))
retValue = getLastPOPrice(product, M_ASI_ID, 0, as.getC_Currency_ID());
if (retValue != null && retValue.signum() != 0)
{
s_log.fine(product.getName() + ", LastPO = " + retValue);
return retValue;
}
}
else // Inv first
{
// try last Inv
retValue = getLastInvoicePrice(product, M_ASI_ID, Org_ID, as.getC_Currency_ID());
if (Org_ID != 0 && (retValue == null || retValue.signum() == 0))
retValue = getLastInvoicePrice(product, M_ASI_ID, 0, as.getC_Currency_ID());
if (retValue != null && retValue.signum() != 0)
{
s_log.fine(product.getName() + ", LastInv = " + retValue);
return retValue;
}
}
// Still Nothing
// Inv second
if (MCostElement.COSTINGMETHOD_AveragePO.equals(costingMethod)
|| MCostElement.COSTINGMETHOD_LastPOPrice.equals(costingMethod)
|| MCostElement.COSTINGMETHOD_StandardCosting.equals(costingMethod))
{
// try last Inv
retValue = getLastInvoicePrice(product, M_ASI_ID, Org_ID, as.getC_Currency_ID());
if (Org_ID != 0 && (retValue == null || retValue.signum() == 0))
retValue = getLastInvoicePrice(product, M_ASI_ID, 0, as.getC_Currency_ID());
if (retValue != null && retValue.signum() != 0)
{
s_log.fine(product.getName() + ", LastInv = " + retValue);
return retValue;
}
}
else // PO second
{
// try Last PO
retValue = getLastPOPrice(product, M_ASI_ID, Org_ID, as.getC_Currency_ID());
if (Org_ID != 0 && (retValue == null || retValue.signum() == 0))
retValue = getLastPOPrice(product, M_ASI_ID, 0, as.getC_Currency_ID());
if (retValue != null && retValue.signum() != 0)
{
s_log.fine(product.getName() + ", LastPO = " + retValue);
return retValue;
}
}
// Still nothing try ProductPO
MProductPO[] pos = MProductPO.getOfProduct(product.getCtx(), product.getM_Product_ID(), null);
for (int i = 0; i < pos.length; i++)
{
BigDecimal price = pos[i].getPricePO();
if (price == null || price.signum() == 0)
price = pos[0].getPriceList();
if (price != null && price.signum() != 0)
{
price = MConversionRate.convert(product.getCtx(), price,
pos[0].getC_Currency_ID(), as.getC_Currency_ID(),
as.getAD_Client_ID(), Org_ID);
if (price != null && price.signum() != 0)
{
retValue = price;
s_log.fine(product.getName() + ", Product_PO = " + retValue);
return retValue;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -