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:
parent
3bd5a42659
commit
5a5f24f179
|
@ -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[")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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@";
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue