Workflow Cost Roll-UP do not work appropriately

https://sourceforge.net/tracker2/?func=detail&atid=879332&aid=2492987&group_id=176962
This commit is contained in:
vpj-cd 2009-01-08 00:09:31 +00:00
parent 3bd5a42659
commit 5a5f24f179
3 changed files with 136 additions and 103 deletions

View File

@ -16,11 +16,13 @@
*****************************************************************************/
package org.compiere.model;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.util.Properties;
import org.adempiere.exceptions.AdempiereException;
import org.compiere.util.CCache;
import org.compiere.util.DB;
/**
@ -161,6 +163,34 @@ public class MResource extends X_S_Resource
return success;
} // afterSave
/**
* Get Rate for this Resource
* @param CostElementType Cost Element Type (Labor and Overhead.)
* @param S_Resource_ID Resource
* @param AD_Org_ID Organization
* @return Rate for Resource
* @throws Exception if not successful
*/
public double getResouceRate(int C_AcctSchema_ID,int M_CostType_ID, String CostElementType , int AD_Org_ID)
{
final String sql = "SELECT SUM(c."+MCost.COLUMNNAME_CurrentCostPrice+")"
+" FROM M_Cost c, M_CostElement ce, M_Product p"
+" WHERE c.AD_Client_ID=? AND c.AD_Org_ID=?"
+" AND c."+MCost.COLUMNNAME_C_AcctSchema_ID+"=?"
+" AND c."+MCost.COLUMNNAME_M_CostType_ID+"=?"
// Cost Element Type
+" AND ce."+MCostElement.COLUMNNAME_M_CostElement_ID+"=c."+MCost.COLUMNNAME_M_CostElement_ID
+" AND ce."+MCostElement.COLUMNNAME_CostElementType+"=?"
// Product / Resource
+" AND p."+MProduct.COLUMNNAME_M_Product_ID+"=c."+MCost.COLUMNNAME_M_Product_ID
+" AND p."+MProduct.COLUMNNAME_S_Resource_ID+"=?"
;
BigDecimal rate = DB.getSQLValueBD(get_TrxName(), sql, getAD_Client_ID(), AD_Org_ID,
C_AcctSchema_ID, M_CostType_ID,
CostElementType, getS_Resource_ID());
return (rate != null ? rate.doubleValue() : 0);
}
public String toString()
{
StringBuffer sb = new StringBuffer ("MResource[")

View File

@ -26,7 +26,10 @@ import java.util.ArrayList;
import java.util.Properties;
import java.util.logging.Level;
import org.adempiere.exceptions.AdempiereException;
import org.compiere.model.MColumn;
import org.compiere.model.MResource;
import org.compiere.model.MUOM;
import org.compiere.model.X_AD_WF_Node;
import org.compiere.util.CCache;
import org.compiere.util.DB;
@ -651,4 +654,44 @@ public class MWFNode extends X_AD_WF_Node
return false;
return true;
}
/**
* Calculate the cost for this node using the Cost Element Type
* @param CostElementType Cost Element Type (Labor or Burden)
* @param C_AcctSchema_ID AcctSchema
* @param M_CostType_ID Cost Type
* @param AD_Org_ID Organization
* @param setuptime Setup Time
* @param duration Duration
* @return cost for this Cost Element Type (Labor or Burden)
* @throws Exception when the UOM do not is Hours
*/
public BigDecimal getCostForCostElementType(String CostElementType, int C_AcctSchema_ID,int M_CostType_ID,int AD_Org_ID,int setuptime, int duration)
{
MResource resource = (MResource) getS_Resource();
//get the rate and convert in second for this cost type element (Rsource, Burden)
MWorkflow workflow = getWorkflow();
double rate = resource.getResouceRate(C_AcctSchema_ID, M_CostType_ID,CostElementType, AD_Org_ID);
BigDecimal cost = Env.ZERO;
if (rate == 0)
{
return Env.ZERO;
}
int C_UOM_ID = DB.getSQLValue(get_TrxName(),"SELECT C_UOM_ID FROM M_Product WHERE S_Resource_ID = ? " , getS_Resource_ID());
MUOM uom = MUOM.get(getCtx(), C_UOM_ID);
if (uom.isHour())
{
double hours = (setuptime / workflow.getQtyBatchSize().doubleValue() + duration)
* workflow.getDurationBaseSec() / 3600;
double nodeCost = rate * hours;
cost = cost.add(new BigDecimal(nodeCost));
log.info("Node: " + getName() + " Resouce: " + resource.getName() +" CostElementType: " + CostElementType + " Time Base: "+workflow.getDurationUnit() +" Duration (H): " + hours + " Rate: " + rate + " Activity Cost: " + nodeCost +" =>Cost: "+cost);
}
else
{
throw new AdempiereException("@NotSupported@ @C_UOM_ID@="+uom.getName());
}
return cost;
}
} // M_WFNext

View File

@ -18,22 +18,18 @@
package org.eevolution.process;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import org.adempiere.exceptions.AdempiereException;
import org.compiere.model.MAcctSchema;
import org.compiere.model.MClient;
import org.compiere.model.MCost;
import org.compiere.model.MCostElement;
import org.compiere.model.MProduct;
import org.compiere.model.MUOM;
import org.compiere.model.Query;
import org.compiere.process.ProcessInfoParameter;
import org.compiere.process.SvrProcess;
import org.compiere.util.DB;
import org.compiere.util.Env;
import org.compiere.wf.MWFNode;
import org.compiere.wf.MWorkflow;
@ -134,112 +130,76 @@ public class RollupWorkflow extends SvrProcess
for (MProduct product : products)
{
MCost[] costs = MCost.getCosts(getCtx(), getAD_Client_ID(), p_AD_Org_ID, product.getM_Product_ID(), p_M_CostType_ID, p_C_AcctSchema_ID , get_TrxName());
for (MCost cost : costs)
MPPProductPlanning pp = MPPProductPlanning.find( getCtx(), p_AD_Org_ID , 0, 0, product.get_ID(), get_TrxName());
int AD_Workflow_ID = 0;
if (pp != null)
{
MCostElement element = cost.getCostElement();
// check if element cost is of type Labor
if (element.getCostElementType().equals(MCostElement.COSTELEMENTTYPE_Resource))
{
BigDecimal Labor = getCost(MCostElement.COSTELEMENTTYPE_Resource, p_AD_Org_ID, product);
log.info("Labor : " + Labor);
cost.setCurrentCostPrice(Labor);
cost.saveEx();
}
else if (element.getCostElementType().equals(MCostElement.COSTELEMENTTYPE_BurdenMOverhead))
{
BigDecimal Burden = getCost(MCostElement.COSTELEMENTTYPE_BurdenMOverhead, p_AD_Org_ID, product);
log.info("Burden : " + Burden);
cost.setCurrentCostPrice(Burden);
cost.saveEx();
}
AD_Workflow_ID = pp.getAD_Workflow_ID();
}
}
return "@OK@";
}
/**
* Calculate Cost
* @param CostElementType Cost Element Type (Labor and Overhead.)
* @param AD_Org_ID Organization
* @param MProduct product (BOM)
* @param M_CostType_ID Cost Type
* @param C_AcctSchema_ID Account Schema
* @return Cost for this Element
* @throws Exception if not successful
*/
private BigDecimal getCost(String CostElementType, int AD_Org_ID, MProduct product)
{
MPPProductPlanning pp = MPPProductPlanning.find(getCtx(), AD_Org_ID, 0, 0, product.get_ID(), get_TrxName());
int AD_Workflow_ID = 0;
if (pp != null)
{
AD_Workflow_ID = pp.getAD_Workflow_ID();
}
if (AD_Workflow_ID <= 0)
{
AD_Workflow_ID = MWorkflow.getWorkflowSearchKey(getCtx(), product);
}
if(AD_Workflow_ID <= 0)
{
return Env.ZERO;
}
BigDecimal cost = Env.ZERO;
MWorkflow workflow = MWorkflow.get(getCtx(), AD_Workflow_ID);
MWFNode[] nodes = workflow.getNodes(false, getAD_Client_ID());
for (MWFNode node : nodes)
{
BigDecimal rate = getResouceRate(CostElementType, node.getS_Resource_ID(), AD_Org_ID);
if (rate.signum() == 0)
if (AD_Workflow_ID <= 0)
{
AD_Workflow_ID = MWorkflow.getWorkflowSearchKey(getCtx(), product);
}
if(AD_Workflow_ID <= 0)
{
continue;
}
int C_UOM_ID = DB.getSQLValue(get_TrxName(),"SELECT C_UOM_ID FROM M_Product WHERE S_Resource_ID = ? " , node.getS_Resource_ID());
MUOM uom = MUOM.get(getCtx(), C_UOM_ID);
if (uom.isHour())
MWorkflow workflow = MWorkflow.get(getCtx(), AD_Workflow_ID);
workflow.setCost(Env.ZERO);
MWFNode[] nodes = workflow.getNodes(false, getAD_Client_ID());
for (MWFNode node : nodes)
{
double hours = (node.getSetupTime() / workflow.getQtyBatchSize().doubleValue() + node.getDuration())
* workflow.getDurationBaseSec() / 3600;
BigDecimal nodeCost = new BigDecimal(hours).multiply(rate).setScale(12, RoundingMode.HALF_UP);
cost = cost.add(nodeCost);
log.info("Node:" + node.getName() + " CostElementType:"+ CostElementType +" Duration(H):" + hours + " rate:" + rate + " NodeCost:" + nodeCost +" =>Cost:"+cost);
node.setCost(Env.ZERO);
}
else
{
throw new AdempiereException("@NotSupported@ @C_UOM_ID@="+uom.getName());
}
}
return cost;
}
BigDecimal m_cost = Env.ZERO;
MCost[] costs = MCost.getCosts(getCtx(), getAD_Client_ID(), p_AD_Org_ID, product.getM_Product_ID(), p_M_CostType_ID, p_C_AcctSchema_ID , get_TrxName());
for (MCost cost : costs)
{
MCostElement element = cost.getCostElement();
if(element.getCostElementType().equals(MCostElement.COSTELEMENTTYPE_Resource) || element.getCostElementType().equals(MCostElement.COSTELEMENTTYPE_BurdenMOverhead))
{
/**
* Get Rate for this Resource
* @param CostElementType Cost Element Type (Labor and Overhead.)
* @param S_Resource_ID Resource
* @param AD_Org_ID Organization
* @return Rate for Resource
* @throws Exception if not successful
*/
private BigDecimal getResouceRate(String CostElementType, int S_Resource_ID, int AD_Org_ID)
{
final String sql = "SELECT SUM(c."+MCost.COLUMNNAME_CurrentCostPrice+")"
+" FROM M_Cost c, M_CostElement ce, M_Product p"
+" WHERE c.AD_Client_ID=? AND c.AD_Org_ID=?"
+" AND c."+MCost.COLUMNNAME_C_AcctSchema_ID+"=?"
+" AND c."+MCost.COLUMNNAME_M_CostType_ID+"=?"
// Cost Element Type
+" AND ce."+MCostElement.COLUMNNAME_M_CostElement_ID+"=c."+MCost.COLUMNNAME_M_CostElement_ID
+" AND ce."+MCostElement.COLUMNNAME_CostElementType+"=?"
// Product / Resource
+" AND p."+MProduct.COLUMNNAME_M_Product_ID+"=c."+MCost.COLUMNNAME_M_Product_ID
+" AND p."+MProduct.COLUMNNAME_S_Resource_ID+"=?"
;
BigDecimal rate = DB.getSQLValueBD(get_TrxName(), sql, getAD_Client_ID(), AD_Org_ID,
p_C_AcctSchema_ID, p_M_CostType_ID,
CostElementType, S_Resource_ID);
return (rate != null ? rate : Env.ZERO);
}
for (MWFNode node : nodes)
{
BigDecimal nodeCost = Env.ZERO;
// check if element cost is of type Labor
if (element.getCostElementType().equals(MCostElement.COSTELEMENTTYPE_Resource))
{
nodeCost = node.getCostForCostElementType(MCostElement.COSTELEMENTTYPE_Resource ,p_C_AcctSchema_ID, p_M_CostType_ID, p_AD_Org_ID, node.getSetupTime(), node.getDuration());
m_cost = m_cost.add(nodeCost);
}
else if (element.getCostElementType().equals(MCostElement.COSTELEMENTTYPE_BurdenMOverhead))
{
nodeCost = node.getCostForCostElementType(MCostElement.COSTELEMENTTYPE_BurdenMOverhead ,p_C_AcctSchema_ID, p_M_CostType_ID, p_AD_Org_ID, node.getSetupTime(), node.getDuration());
m_cost = m_cost.add(nodeCost);
}
if(nodeCost.signum() != 0)
{
node.setCost(node.getCost().add(nodeCost));
node.saveEx();
}
}
// check if element cost is of type Labor
if (element.getCostElementType().equals(MCostElement.COSTELEMENTTYPE_Resource))
{
log.info("Product:"+product.getName()+" Labor: " + m_cost);
cost.setCurrentCostPrice(m_cost);
cost.saveEx();
}
else if (element.getCostElementType().equals(MCostElement.COSTELEMENTTYPE_BurdenMOverhead))
{
log.info("Product:"+product.getName()+" Burden: " + m_cost);
cost.setCurrentCostPrice(m_cost);
cost.saveEx();
}
}
}
workflow.setCost(workflow.getCost().add(m_cost));
}
return "@OK@";
}
}