IDEMPIERE-1180 Cost Adjustment Document for Standard and Average Costing.
This commit is contained in:
parent
0cead2d7f9
commit
db5e974ab7
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -20,6 +20,11 @@
|
||||||
<arguments>
|
<arguments>
|
||||||
</arguments>
|
</arguments>
|
||||||
</buildCommand>
|
</buildCommand>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.pde.ds.core.builder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
</buildSpec>
|
</buildSpec>
|
||||||
<natures>
|
<natures>
|
||||||
<nature>org.eclipse.pde.PluginNature</nature>
|
<nature>org.eclipse.pde.PluginNature</nature>
|
||||||
|
|
|
@ -6,4 +6,6 @@ Bundle-Version: 1.0.0.qualifier
|
||||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
Bundle-RequiredExecutionEnvironment: JavaSE-1.6
|
||||||
Require-Bundle: org.adempiere.base;bundle-version="1.0.0"
|
Require-Bundle: org.adempiere.base;bundle-version="1.0.0"
|
||||||
Eclipse-RegisterBuddy: org.adempiere.base
|
Eclipse-RegisterBuddy: org.adempiere.base
|
||||||
|
Service-Component: OSGI-INF/costadjustmentcalloutfactory.xml
|
||||||
|
Bundle-ActivationPolicy: lazy
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.adempiere.base.callout.CostAdjustmentCalloutFactory">
|
||||||
|
<implementation class="org.adempiere.base.callout.CostAdjustmentCalloutFactory"/>
|
||||||
|
<service>
|
||||||
|
<provide interface="org.adempiere.base.IColumnCalloutFactory"/>
|
||||||
|
</service>
|
||||||
|
</scr:component>
|
|
@ -1,4 +1,6 @@
|
||||||
source.. = src/
|
|
||||||
output.. = bin/
|
output.. = bin/
|
||||||
bin.includes = META-INF/,\
|
bin.includes = META-INF/,\
|
||||||
.
|
.,\
|
||||||
|
OSGI-INF/costadjustmentcalloutfactory.xml,\
|
||||||
|
OSGI-INF/
|
||||||
|
source.. = src/
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Copyright (C) 2013 Heng Sin Low *
|
||||||
|
* Copyright (C) 2013 Trek Global *
|
||||||
|
* 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. *
|
||||||
|
*****************************************************************************/
|
||||||
|
package org.adempiere.base.callout;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.adempiere.base.IColumnCallout;
|
||||||
|
import org.adempiere.base.IColumnCalloutFactory;
|
||||||
|
import org.compiere.model.GridField;
|
||||||
|
import org.compiere.model.GridTab;
|
||||||
|
import org.compiere.model.I_M_InventoryLine;
|
||||||
|
import org.compiere.model.MAcctSchema;
|
||||||
|
import org.compiere.model.MClient;
|
||||||
|
import org.compiere.model.MCost;
|
||||||
|
import org.compiere.model.MCostElement;
|
||||||
|
import org.compiere.model.MDocType;
|
||||||
|
import org.compiere.model.MInventory;
|
||||||
|
import org.compiere.model.MProduct;
|
||||||
|
import org.compiere.util.Env;
|
||||||
|
import org.compiere.util.Msg;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class CostAdjustmentCalloutFactory implements IColumnCalloutFactory {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public CostAdjustmentCalloutFactory() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.adempiere.base.IColumnCalloutFactory#getColumnCallouts(java.lang.String, java.lang.String)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public IColumnCallout[] getColumnCallouts(String tableName,
|
||||||
|
String columnName) {
|
||||||
|
if (tableName.equalsIgnoreCase(I_M_InventoryLine.Table_Name)) {
|
||||||
|
if (columnName.equalsIgnoreCase(I_M_InventoryLine.COLUMNNAME_M_Product_ID))
|
||||||
|
return new IColumnCallout[]{new CostAdjustmentLineProduct()};
|
||||||
|
else if (columnName.equalsIgnoreCase(I_M_InventoryLine.COLUMNNAME_M_AttributeSetInstance_ID))
|
||||||
|
return new IColumnCallout[]{new CostAdjustmentLineASI()};
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* callout for m_product_id
|
||||||
|
*/
|
||||||
|
private static class CostAdjustmentLineProduct implements IColumnCallout {
|
||||||
|
@Override
|
||||||
|
public String start(Properties ctx, int WindowNo, GridTab mTab,
|
||||||
|
GridField mField, Object value, Object oldValue) {
|
||||||
|
MInventory inventory = MInventory.get(ctx, (Integer) mTab.getValue("M_Inventory_ID"));
|
||||||
|
if (MDocType.DOCSUBTYPEINV_CostAdjustment.equals(inventory.getC_DocType().getDocSubTypeInv())) {
|
||||||
|
String costingMethod = inventory.getCostingMethod();
|
||||||
|
if (value == null) {
|
||||||
|
mTab.setValue(I_M_InventoryLine.COLUMNNAME_CurrentCostPrice, BigDecimal.ZERO);
|
||||||
|
mTab.setValue(I_M_InventoryLine.COLUMNNAME_NewCostPrice, BigDecimal.ZERO);
|
||||||
|
} else {
|
||||||
|
MProduct product = MProduct.get(ctx, (Integer) value);
|
||||||
|
MClient client = MClient.get(ctx);
|
||||||
|
MAcctSchema as = client.getAcctSchema();
|
||||||
|
Object asiValue = mTab.getValue(I_M_InventoryLine.COLUMNNAME_M_AttributeSetInstance_ID);
|
||||||
|
int M_ASI_ID = asiValue != null ? (Integer)asiValue : 0;
|
||||||
|
int AD_Org_ID = inventory.getAD_Org_ID();
|
||||||
|
MCost cost = product.getCostingRecord(as, AD_Org_ID, M_ASI_ID, costingMethod);
|
||||||
|
if (cost == null) {
|
||||||
|
if (!MCostElement.COSTINGMETHOD_StandardCosting.equals(costingMethod)) {
|
||||||
|
mTab.setValue(mField, null);
|
||||||
|
return Msg.getMsg(Env.getCtx(), "NoCostingRecord");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mTab.setValue(I_M_InventoryLine.COLUMNNAME_CurrentCostPrice, cost.getCurrentCostPrice());
|
||||||
|
mTab.setValue(I_M_InventoryLine.COLUMNNAME_NewCostPrice, cost.getCurrentCostPrice());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* callout for m_attributesetinstance_id
|
||||||
|
*/
|
||||||
|
private class CostAdjustmentLineASI implements IColumnCallout {
|
||||||
|
@Override
|
||||||
|
public String start(Properties ctx, int WindowNo, GridTab mTab,
|
||||||
|
GridField mField, Object value, Object oldValue) {
|
||||||
|
MInventory inventory = MInventory.get(ctx, (Integer) mTab.getValue("M_Inventory_ID"));
|
||||||
|
if (MDocType.DOCSUBTYPEINV_CostAdjustment.equals(inventory.getC_DocType().getDocSubTypeInv())) {
|
||||||
|
String costingMethod = inventory.getCostingMethod();
|
||||||
|
Object productValue = mTab.getValue(I_M_InventoryLine.COLUMNNAME_M_Product_ID);
|
||||||
|
if (productValue == null || ((Integer)productValue).intValue() == 0) return null;
|
||||||
|
|
||||||
|
MProduct product = MProduct.get(ctx, (Integer)productValue);
|
||||||
|
int M_ASI_ID = value != null ? (Integer)value : 0;
|
||||||
|
int AD_Org_ID = inventory.getAD_Org_ID();
|
||||||
|
MClient client = MClient.get(ctx);
|
||||||
|
MAcctSchema as = client.getAcctSchema();
|
||||||
|
MCost cost = product.getCostingRecord(as, AD_Org_ID, M_ASI_ID, costingMethod);
|
||||||
|
if (cost != null) {
|
||||||
|
BigDecimal currentCost = (BigDecimal) mTab.getValue(I_M_InventoryLine.COLUMNNAME_CurrentCostPrice);
|
||||||
|
if (currentCost == null || currentCost.compareTo(cost.getCurrentCostPrice())==0) return null;
|
||||||
|
|
||||||
|
mTab.setValue(I_M_InventoryLine.COLUMNNAME_CurrentCostPrice, cost.getCurrentCostPrice());
|
||||||
|
mTab.setValue(I_M_InventoryLine.COLUMNNAME_NewCostPrice, cost.getCurrentCostPrice());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,17 +19,27 @@ package org.compiere.process;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.sql.PreparedStatement;
|
import java.sql.PreparedStatement;
|
||||||
import java.sql.ResultSet;
|
import java.sql.ResultSet;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.compiere.model.I_C_DocType;
|
||||||
|
import org.compiere.model.I_M_Inventory;
|
||||||
import org.compiere.model.MAcctSchema;
|
import org.compiere.model.MAcctSchema;
|
||||||
import org.compiere.model.MClient;
|
import org.compiere.model.MClient;
|
||||||
import org.compiere.model.MCost;
|
import org.compiere.model.MCost;
|
||||||
import org.compiere.model.MCostElement;
|
import org.compiere.model.MCostElement;
|
||||||
|
import org.compiere.model.MDocType;
|
||||||
|
import org.compiere.model.MInventory;
|
||||||
|
import org.compiere.model.MInventoryLine;
|
||||||
import org.compiere.model.MProduct;
|
import org.compiere.model.MProduct;
|
||||||
import org.compiere.util.AdempiereSystemError;
|
import org.compiere.util.AdempiereSystemError;
|
||||||
import org.compiere.util.AdempiereUserError;
|
import org.compiere.util.AdempiereUserError;
|
||||||
import org.compiere.util.DB;
|
import org.compiere.util.DB;
|
||||||
|
import org.compiere.util.Env;
|
||||||
|
import org.compiere.util.Msg;
|
||||||
|
import org.compiere.util.Util;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Standard Cost Update
|
* Standard Cost Update
|
||||||
|
@ -48,6 +58,8 @@ public class CostUpdate extends SvrProcess
|
||||||
/** PLV */
|
/** PLV */
|
||||||
private int p_M_PriceList_Version_ID = 0;
|
private int p_M_PriceList_Version_ID = 0;
|
||||||
|
|
||||||
|
private int p_C_DocType_ID = 0;
|
||||||
|
|
||||||
|
|
||||||
private static final String TO_AveragePO = "A";
|
private static final String TO_AveragePO = "A";
|
||||||
private static final String TO_AverageInvoiceHistory = "DI";
|
private static final String TO_AverageInvoiceHistory = "DI";
|
||||||
|
@ -67,6 +79,7 @@ public class CostUpdate extends SvrProcess
|
||||||
private MAcctSchema[] m_ass = null;
|
private MAcctSchema[] m_ass = null;
|
||||||
/** Map of Cost Elements */
|
/** Map of Cost Elements */
|
||||||
private HashMap<String,MCostElement> m_ces = new HashMap<String,MCostElement>();
|
private HashMap<String,MCostElement> m_ces = new HashMap<String,MCostElement>();
|
||||||
|
private MDocType m_docType = null;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -89,6 +102,8 @@ public class CostUpdate extends SvrProcess
|
||||||
p_SetStandardCostTo = (String)para[i].getParameter();
|
p_SetStandardCostTo = (String)para[i].getParameter();
|
||||||
else if (name.equals("M_PriceList_Version_ID"))
|
else if (name.equals("M_PriceList_Version_ID"))
|
||||||
p_M_PriceList_Version_ID = para[i].getParameterAsInt();
|
p_M_PriceList_Version_ID = para[i].getParameterAsInt();
|
||||||
|
else if (name.equals("C_DocType_ID"))
|
||||||
|
p_C_DocType_ID = para[i].getParameterAsInt();
|
||||||
else
|
else
|
||||||
log.log(Level.SEVERE, "Unknown Parameter: " + name);
|
log.log(Level.SEVERE, "Unknown Parameter: " + name);
|
||||||
}
|
}
|
||||||
|
@ -114,6 +129,13 @@ public class CostUpdate extends SvrProcess
|
||||||
{
|
{
|
||||||
return "-";
|
return "-";
|
||||||
}
|
}
|
||||||
|
if (!Util.isEmpty(p_SetStandardCostTo))
|
||||||
|
{
|
||||||
|
if (p_C_DocType_ID <= 0)
|
||||||
|
throw new AdempiereUserError ("@FillMandatory@ @C_DocType_ID@");
|
||||||
|
else
|
||||||
|
m_docType = MDocType.get(getCtx(), p_C_DocType_ID);
|
||||||
|
}
|
||||||
// PLV required
|
// PLV required
|
||||||
if (p_M_PriceList_Version_ID == 0
|
if (p_M_PriceList_Version_ID == 0
|
||||||
&& (p_SetFutureCostTo.equals(TO_PriceListLimit) || p_SetStandardCostTo.equals(TO_PriceListLimit)))
|
&& (p_SetFutureCostTo.equals(TO_PriceListLimit) || p_SetStandardCostTo.equals(TO_PriceListLimit)))
|
||||||
|
@ -253,6 +275,10 @@ public class CostUpdate extends SvrProcess
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
List<MInventoryLine> lines = new ArrayList<MInventoryLine>();
|
||||||
|
MClient client = MClient.get(getCtx());
|
||||||
|
MAcctSchema primarySchema = client.getAcctSchema();
|
||||||
|
MInventory inventoryDoc = null;
|
||||||
pstmt = DB.prepareStatement (sql, null);
|
pstmt = DB.prepareStatement (sql, null);
|
||||||
pstmt.setInt (1, m_ce.getM_CostElement_ID());
|
pstmt.setInt (1, m_ce.getM_CostElement_ID());
|
||||||
if (p_M_Product_Category_ID != 0)
|
if (p_M_Product_Category_ID != 0)
|
||||||
|
@ -267,15 +293,65 @@ public class CostUpdate extends SvrProcess
|
||||||
if (m_ass[i].getC_AcctSchema_ID() == cost.getC_AcctSchema_ID()
|
if (m_ass[i].getC_AcctSchema_ID() == cost.getC_AcctSchema_ID()
|
||||||
&& m_ass[i].getM_CostType_ID() == cost.getM_CostType_ID())
|
&& m_ass[i].getM_CostType_ID() == cost.getM_CostType_ID())
|
||||||
{
|
{
|
||||||
if (update (cost))
|
if (m_ass[i].getC_AcctSchema_ID() == primarySchema.getC_AcctSchema_ID())
|
||||||
|
{
|
||||||
|
if (update (cost, lines))
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (update (cost, null))
|
||||||
counter++;
|
counter++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (lines.size() > 0)
|
||||||
|
{
|
||||||
|
inventoryDoc = new MInventory(getCtx(), 0, get_TrxName());
|
||||||
|
inventoryDoc.setC_DocType_ID(p_C_DocType_ID);
|
||||||
|
inventoryDoc.setCostingMethod(MCostElement.COSTINGMETHOD_StandardCosting);
|
||||||
|
inventoryDoc.setDocAction(DocAction.ACTION_Complete);
|
||||||
|
inventoryDoc.saveEx();
|
||||||
|
|
||||||
|
for(MInventoryLine line : lines)
|
||||||
|
{
|
||||||
|
line.setM_Inventory_ID(inventoryDoc.getM_Inventory_ID());
|
||||||
|
line.saveEx();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!DocumentEngine.processIt(inventoryDoc, DocAction.ACTION_Complete))
|
||||||
|
{
|
||||||
|
StringBuilder msg = new StringBuilder();
|
||||||
|
msg.append(Msg.getMsg(getCtx(), "ProcessFailed")).append(": ");
|
||||||
|
if (Env.isBaseLanguage(getCtx(), I_C_DocType.Table_Name))
|
||||||
|
msg.append(m_docType.getName());
|
||||||
|
else
|
||||||
|
msg.append(m_docType.get_Translation(I_C_DocType.COLUMNNAME_Name));
|
||||||
|
throw new AdempiereUserError(msg.toString());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
inventoryDoc.saveEx();
|
||||||
|
StringBuilder msg = new StringBuilder();
|
||||||
|
if (Env.isBaseLanguage(getCtx(), I_C_DocType.Table_Name))
|
||||||
|
msg.append(m_docType.getName()).append(" ").append(inventoryDoc.getDocumentNo());
|
||||||
|
else
|
||||||
|
msg.append(m_docType.get_Translation(I_C_DocType.COLUMNNAME_Name)).append(" ").append(inventoryDoc.getDocumentNo());
|
||||||
|
addLog(getAD_PInstance_ID(), null, null, msg.toString(), I_M_Inventory.Table_ID, inventoryDoc.getM_Inventory_ID());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
log.log (Level.SEVERE, sql, e);
|
if (e instanceof RuntimeException)
|
||||||
|
{
|
||||||
|
throw (RuntimeException)e;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -291,10 +367,11 @@ public class CostUpdate extends SvrProcess
|
||||||
/**
|
/**
|
||||||
* Update Cost Records
|
* Update Cost Records
|
||||||
* @param cost cost
|
* @param cost cost
|
||||||
|
* @param inventoryDoc
|
||||||
* @return true if updated
|
* @return true if updated
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
private boolean update (MCost cost) throws Exception
|
private boolean update (MCost cost, List<MInventoryLine> lines) throws Exception
|
||||||
{
|
{
|
||||||
boolean updated = false;
|
boolean updated = false;
|
||||||
if (p_SetFutureCostTo.equals(p_SetStandardCostTo))
|
if (p_SetFutureCostTo.equals(p_SetStandardCostTo))
|
||||||
|
@ -303,21 +380,37 @@ public class CostUpdate extends SvrProcess
|
||||||
if (costs != null && costs.signum() != 0)
|
if (costs != null && costs.signum() != 0)
|
||||||
{
|
{
|
||||||
cost.setFutureCostPrice(costs);
|
cost.setFutureCostPrice(costs);
|
||||||
cost.setCurrentCostPrice(costs);
|
|
||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
|
if (lines != null)
|
||||||
|
{
|
||||||
|
MInventoryLine line = new MInventoryLine(getCtx(), 0, get_TrxName());
|
||||||
|
line.setM_Product_ID(cost.getM_Product_ID());
|
||||||
|
line.setCurrentCostPrice(cost.getCurrentCostPrice());
|
||||||
|
line.setNewCostPrice(costs);
|
||||||
|
line.setM_Locator_ID(0);
|
||||||
|
lines.add(line);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (p_SetStandardCostTo.length() > 0)
|
if (p_SetStandardCostTo.length() > 0)
|
||||||
|
{
|
||||||
|
if (lines != null)
|
||||||
{
|
{
|
||||||
BigDecimal costs = getCosts(cost, p_SetStandardCostTo);
|
BigDecimal costs = getCosts(cost, p_SetStandardCostTo);
|
||||||
if (costs != null && costs.signum() != 0)
|
if (costs != null && costs.signum() != 0)
|
||||||
{
|
{
|
||||||
cost.setCurrentCostPrice(costs);
|
MInventoryLine line = new MInventoryLine(getCtx(), 0, get_TrxName());
|
||||||
|
line.setM_Product_ID(cost.getM_Product_ID());
|
||||||
|
line.setCurrentCostPrice(cost.getCurrentCostPrice());
|
||||||
|
line.setNewCostPrice(costs);
|
||||||
|
line.setM_Locator_ID(0);
|
||||||
|
lines.add(line);
|
||||||
updated = true;
|
updated = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (p_SetFutureCostTo.length() > 0)
|
if (p_SetFutureCostTo.length() > 0)
|
||||||
{
|
{
|
||||||
BigDecimal costs = getCosts(cost, p_SetFutureCostTo);
|
BigDecimal costs = getCosts(cost, p_SetFutureCostTo);
|
||||||
|
|
|
@ -0,0 +1,66 @@
|
||||||
|
/******************************************************************************
|
||||||
|
* Copyright (C) 2013 Heng Sin Low *
|
||||||
|
* Copyright (C) 2013 Trek Global *
|
||||||
|
* 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. *
|
||||||
|
*****************************************************************************/
|
||||||
|
package org.idempiere.process;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
|
import org.compiere.model.MAcctSchema;
|
||||||
|
import org.compiere.model.MClient;
|
||||||
|
import org.compiere.model.MCost;
|
||||||
|
import org.compiere.model.MInventoryLine;
|
||||||
|
import org.compiere.model.MProduct;
|
||||||
|
import org.compiere.process.SvrProcess;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author hengsin
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class CostAdjustmentLineRefreshCost extends SvrProcess {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public CostAdjustmentLineRefreshCost() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.compiere.process.SvrProcess#prepare()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected void prepare() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.compiere.process.SvrProcess#doIt()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected String doIt() throws Exception {
|
||||||
|
MInventoryLine line = new MInventoryLine(getCtx(), getRecord_ID(), null);
|
||||||
|
MProduct product = line.getProduct();
|
||||||
|
MClient client = MClient.get(getCtx(), line.getAD_Client_ID());
|
||||||
|
MAcctSchema as = client.getAcctSchema();
|
||||||
|
MCost cost = product.getCostingRecord(as, line.getAD_Org_ID(), line.getM_AttributeSetInstance_ID(), line.getM_Inventory().getCostingMethod());
|
||||||
|
if (cost != null) {
|
||||||
|
line.setCurrentCostPrice(cost.getCurrentCostPrice());
|
||||||
|
line.setNewCostPrice(cost.getCurrentCostPrice());
|
||||||
|
line.saveEx();
|
||||||
|
} else {
|
||||||
|
line.setCurrentCostPrice(BigDecimal.ZERO);
|
||||||
|
line.setNewCostPrice(BigDecimal.ZERO);
|
||||||
|
line.saveEx();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "@Ok@";
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,11 +23,17 @@ import java.util.logging.Level;
|
||||||
|
|
||||||
import org.compiere.model.MAccount;
|
import org.compiere.model.MAccount;
|
||||||
import org.compiere.model.MAcctSchema;
|
import org.compiere.model.MAcctSchema;
|
||||||
|
import org.compiere.model.MClient;
|
||||||
|
import org.compiere.model.MConversionRate;
|
||||||
|
import org.compiere.model.MCost;
|
||||||
import org.compiere.model.MCostDetail;
|
import org.compiere.model.MCostDetail;
|
||||||
|
import org.compiere.model.MCostElement;
|
||||||
import org.compiere.model.MDocType;
|
import org.compiere.model.MDocType;
|
||||||
import org.compiere.model.MInventory;
|
import org.compiere.model.MInventory;
|
||||||
import org.compiere.model.MInventoryLine;
|
import org.compiere.model.MInventoryLine;
|
||||||
|
import org.compiere.model.MProduct;
|
||||||
import org.compiere.model.ProductCost;
|
import org.compiere.model.ProductCost;
|
||||||
|
import org.compiere.util.DB;
|
||||||
import org.compiere.util.Env;
|
import org.compiere.util.Env;
|
||||||
import org.compiere.util.Util;
|
import org.compiere.util.Util;
|
||||||
|
|
||||||
|
@ -49,6 +55,7 @@ public class Doc_Inventory extends Doc
|
||||||
private int m_Reversal_ID = 0;
|
private int m_Reversal_ID = 0;
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private String m_DocStatus = "";
|
private String m_DocStatus = "";
|
||||||
|
private String parentDocSubTypeInv;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
@ -67,12 +74,23 @@ public class Doc_Inventory extends Doc
|
||||||
*/
|
*/
|
||||||
protected String loadDocumentDetails()
|
protected String loadDocumentDetails()
|
||||||
{
|
{
|
||||||
setC_Currency_ID (NO_CURRENCY);
|
|
||||||
MInventory inventory = (MInventory)getPO();
|
MInventory inventory = (MInventory)getPO();
|
||||||
setDateDoc (inventory.getMovementDate());
|
setDateDoc (inventory.getMovementDate());
|
||||||
setDateAcct(inventory.getMovementDate());
|
setDateAcct(inventory.getMovementDate());
|
||||||
m_Reversal_ID = inventory.getReversal_ID();//store original (voided/reversed) document
|
m_Reversal_ID = inventory.getReversal_ID();//store original (voided/reversed) document
|
||||||
m_DocStatus = inventory.getDocStatus();
|
m_DocStatus = inventory.getDocStatus();
|
||||||
|
MDocType dt = MDocType.get(getCtx(), getC_DocType_ID());
|
||||||
|
parentDocSubTypeInv = dt.getDocSubTypeInv();
|
||||||
|
if (MDocType.DOCSUBTYPEINV_CostAdjustment.equals(parentDocSubTypeInv))
|
||||||
|
{
|
||||||
|
MClient client = MClient.get(getCtx(), inventory.getAD_Client_ID());
|
||||||
|
int C_Currency_ID = client.getAcctSchema().getC_Currency_ID();
|
||||||
|
setC_Currency_ID(C_Currency_ID);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
setC_Currency_ID (NO_CURRENCY);
|
||||||
|
}
|
||||||
// Contained Objects
|
// Contained Objects
|
||||||
p_lines = loadLines(inventory);
|
p_lines = loadLines(inventory);
|
||||||
if (log.isLoggable(Level.FINE)) log.fine("Lines=" + p_lines.length);
|
if (log.isLoggable(Level.FINE)) log.fine("Lines=" + p_lines.length);
|
||||||
|
@ -86,8 +104,6 @@ public class Doc_Inventory extends Doc
|
||||||
*/
|
*/
|
||||||
private DocLine[] loadLines(MInventory inventory)
|
private DocLine[] loadLines(MInventory inventory)
|
||||||
{
|
{
|
||||||
MDocType dt = MDocType.get(getCtx(), getC_DocType_ID());
|
|
||||||
String parentDocSubTypeInv = dt.getDocSubTypeInv();
|
|
||||||
ArrayList<DocLine> list = new ArrayList<DocLine>();
|
ArrayList<DocLine> list = new ArrayList<DocLine>();
|
||||||
MInventoryLine[] lines = inventory.getLines(false);
|
MInventoryLine[] lines = inventory.getLines(false);
|
||||||
for (int i = 0; i < lines.length; i++)
|
for (int i = 0; i < lines.length; i++)
|
||||||
|
@ -106,16 +122,23 @@ public class Doc_Inventory extends Doc
|
||||||
}
|
}
|
||||||
|
|
||||||
BigDecimal qtyDiff = Env.ZERO;
|
BigDecimal qtyDiff = Env.ZERO;
|
||||||
|
BigDecimal amtDiff = Env.ZERO;
|
||||||
if (MDocType.DOCSUBTYPEINV_InternalUseInventory.equals(docSubTypeInv))
|
if (MDocType.DOCSUBTYPEINV_InternalUseInventory.equals(docSubTypeInv))
|
||||||
qtyDiff = line.getQtyInternalUse().negate();
|
qtyDiff = line.getQtyInternalUse().negate();
|
||||||
else if (MDocType.DOCSUBTYPEINV_PhysicalInventory.equals(docSubTypeInv))
|
else if (MDocType.DOCSUBTYPEINV_PhysicalInventory.equals(docSubTypeInv))
|
||||||
qtyDiff = line.getQtyCount().subtract(line.getQtyBook());
|
qtyDiff = line.getQtyCount().subtract(line.getQtyBook());
|
||||||
|
else if (MDocType.DOCSUBTYPEINV_CostAdjustment.equals(docSubTypeInv))
|
||||||
|
amtDiff = line.getNewCostPrice().subtract(line.getCurrentCostPrice());
|
||||||
// nothing to post
|
// nothing to post
|
||||||
if (qtyDiff.signum() == 0)
|
if (qtyDiff.signum() == 0 && amtDiff.signum() == 0)
|
||||||
continue;
|
continue;
|
||||||
//
|
//
|
||||||
DocLine docLine = new DocLine (line, this);
|
DocLine docLine = new DocLine (line, this);
|
||||||
docLine.setQty (qtyDiff, false); // -5 => -5
|
docLine.setQty (qtyDiff, false); // -5 => -5
|
||||||
|
if (amtDiff.signum() != 0)
|
||||||
|
{
|
||||||
|
docLine.setAmount(amtDiff);
|
||||||
|
}
|
||||||
docLine.setReversalLine_ID(line.getReversalLine_ID());
|
docLine.setReversalLine_ID(line.getReversalLine_ID());
|
||||||
if (log.isLoggable(Level.FINE)) log.fine(docLine.toString());
|
if (log.isLoggable(Level.FINE)) log.fine(docLine.toString());
|
||||||
list.add (docLine);
|
list.add (docLine);
|
||||||
|
@ -158,10 +181,54 @@ public class Doc_Inventory extends Doc
|
||||||
FactLine dr = null;
|
FactLine dr = null;
|
||||||
FactLine cr = null;
|
FactLine cr = null;
|
||||||
|
|
||||||
|
MInventory inventory = (MInventory) getPO();
|
||||||
|
boolean costAdjustment = MDocType.DOCSUBTYPEINV_CostAdjustment.equals(parentDocSubTypeInv);
|
||||||
|
String docCostingMethod = inventory.getCostingMethod();
|
||||||
|
|
||||||
for (int i = 0; i < p_lines.length; i++)
|
for (int i = 0; i < p_lines.length; i++)
|
||||||
{
|
{
|
||||||
DocLine line = p_lines[i];
|
DocLine line = p_lines[i];
|
||||||
|
|
||||||
|
boolean doPosting = true;
|
||||||
|
String costingLevel = null;
|
||||||
|
MProduct product = null;
|
||||||
|
if (costAdjustment)
|
||||||
|
{
|
||||||
|
product = line.getProduct();
|
||||||
|
String productCostingMethod = product.getCostingMethod(as);
|
||||||
|
costingLevel = product.getCostingLevel(as);
|
||||||
|
if (!docCostingMethod.equals(productCostingMethod))
|
||||||
|
{
|
||||||
|
doPosting = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
BigDecimal costs = null;
|
BigDecimal costs = null;
|
||||||
|
BigDecimal adjustmentDiff = null;
|
||||||
|
if (costAdjustment)
|
||||||
|
{
|
||||||
|
costs = line.getAmtSource();
|
||||||
|
int orgId = line.getAD_Org_ID();
|
||||||
|
int asiId = line.getM_AttributeSetInstance_ID();
|
||||||
|
if (MAcctSchema.COSTINGLEVEL_Client.equals(costingLevel))
|
||||||
|
{
|
||||||
|
orgId = 0;
|
||||||
|
asiId = 0;
|
||||||
|
}
|
||||||
|
else if (MAcctSchema.COSTINGLEVEL_Organization.equals(costingLevel))
|
||||||
|
asiId = 0;
|
||||||
|
else if (MAcctSchema.COSTINGLEVEL_BatchLot.equals(costingLevel))
|
||||||
|
orgId = 0;
|
||||||
|
MCostElement ce = MCostElement.getMaterialCostElement(getCtx(), docCostingMethod, orgId);
|
||||||
|
MCost cost = MCost.get(product, asiId, as,
|
||||||
|
orgId, ce.getM_CostElement_ID(), getTrxName());
|
||||||
|
DB.getDatabase().forUpdate(cost, 120);
|
||||||
|
BigDecimal currentQty = cost.getCurrentQty();
|
||||||
|
adjustmentDiff = costs;
|
||||||
|
costs = costs.multiply(currentQty);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
if (!isReversal(line))
|
if (!isReversal(line))
|
||||||
{
|
{
|
||||||
// MZ Goodwill
|
// MZ Goodwill
|
||||||
|
@ -176,15 +243,21 @@ public class Doc_Inventory extends Doc
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
costs = BigDecimal.ZERO;
|
//updated below
|
||||||
|
costs = Env.ONE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doPosting)
|
||||||
|
{
|
||||||
|
int C_Currency_ID = getC_Currency_ID() > 0 ? getC_Currency_ID() : as.getC_Currency_ID();
|
||||||
// Inventory DR CR
|
// Inventory DR CR
|
||||||
dr = fact.createLine(line,
|
dr = fact.createLine(line,
|
||||||
line.getAccount(ProductCost.ACCTTYPE_P_Asset, as),
|
line.getAccount(ProductCost.ACCTTYPE_P_Asset, as),
|
||||||
as.getC_Currency_ID(), costs);
|
C_Currency_ID, costs);
|
||||||
// may be zero difference - no line created.
|
// may be zero difference - no line created.
|
||||||
if (dr == null)
|
if (dr != null)
|
||||||
continue;
|
{
|
||||||
dr.setM_Locator_ID(line.getM_Locator_ID());
|
dr.setM_Locator_ID(line.getM_Locator_ID());
|
||||||
if (isReversal(line))
|
if (isReversal(line))
|
||||||
{
|
{
|
||||||
|
@ -208,11 +281,20 @@ public class Doc_Inventory extends Doc
|
||||||
}
|
}
|
||||||
|
|
||||||
if (invDiff == null)
|
if (invDiff == null)
|
||||||
|
{
|
||||||
|
if (costAdjustment)
|
||||||
|
{
|
||||||
|
invDiff = line.getProductCost().getAccount(ProductCost.ACCTTYPE_P_CostAdjustment, as);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
invDiff = getAccount(Doc.ACCTTYPE_InvDifferences, as);
|
invDiff = getAccount(Doc.ACCTTYPE_InvDifferences, as);
|
||||||
|
}
|
||||||
|
}
|
||||||
cr = fact.createLine(line, invDiff,
|
cr = fact.createLine(line, invDiff,
|
||||||
as.getC_Currency_ID(), costs.negate());
|
C_Currency_ID, costs.negate());
|
||||||
if (cr == null)
|
if (cr != null)
|
||||||
continue;
|
{
|
||||||
cr.setM_Locator_ID(line.getM_Locator_ID());
|
cr.setM_Locator_ID(line.getM_Locator_ID());
|
||||||
cr.setQty(line.getQty().negate());
|
cr.setQty(line.getQty().negate());
|
||||||
if (line.getC_Charge_ID() != 0) // explicit overwrite for charge
|
if (line.getC_Charge_ID() != 0) // explicit overwrite for charge
|
||||||
|
@ -229,18 +311,31 @@ public class Doc_Inventory extends Doc
|
||||||
}
|
}
|
||||||
costs = cr.getAcctBalance(); //get original cost
|
costs = cr.getAcctBalance(); //get original cost
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doPosting || costAdjustment)
|
||||||
|
{
|
||||||
|
BigDecimal costDetailAmt = costAdjustment ? adjustmentDiff : costs;
|
||||||
|
if (costAdjustment && getC_Currency_ID() > 0 && getC_Currency_ID() != as.getC_Currency_ID())
|
||||||
|
{
|
||||||
|
costDetailAmt = MConversionRate.convert (getCtx(),
|
||||||
|
costDetailAmt, getC_Currency_ID(), as.getC_Currency_ID(),
|
||||||
|
getDateAcct(), 0, getAD_Client_ID(), getAD_Org_ID());
|
||||||
|
}
|
||||||
// Cost Detail
|
// Cost Detail
|
||||||
if (!MCostDetail.createInventory(as, line.getAD_Org_ID(),
|
if (!MCostDetail.createInventory(as, line.getAD_Org_ID(),
|
||||||
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
|
line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(),
|
||||||
line.get_ID(), 0,
|
line.get_ID(), 0,
|
||||||
costs, line.getQty(),
|
costDetailAmt, line.getQty(),
|
||||||
line.getDescription(), getTrxName()))
|
line.getDescription(), getTrxName()))
|
||||||
{
|
{
|
||||||
p_Error = "Failed to create cost detail record";
|
p_Error = "Failed to create cost detail record";
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
//
|
//
|
||||||
ArrayList<Fact> facts = new ArrayList<Fact>();
|
ArrayList<Fact> facts = new ArrayList<Fact>();
|
||||||
facts.add(fact);
|
facts.add(fact);
|
||||||
|
|
|
@ -133,6 +133,19 @@ public interface I_M_Inventory
|
||||||
|
|
||||||
public org.compiere.model.I_C_DocType getC_DocType() throws RuntimeException;
|
public org.compiere.model.I_C_DocType getC_DocType() throws RuntimeException;
|
||||||
|
|
||||||
|
/** Column name CostingMethod */
|
||||||
|
public static final String COLUMNNAME_CostingMethod = "CostingMethod";
|
||||||
|
|
||||||
|
/** Set Costing Method.
|
||||||
|
* Indicates how Costs will be calculated
|
||||||
|
*/
|
||||||
|
public void setCostingMethod (String CostingMethod);
|
||||||
|
|
||||||
|
/** Get Costing Method.
|
||||||
|
* Indicates how Costs will be calculated
|
||||||
|
*/
|
||||||
|
public String getCostingMethod();
|
||||||
|
|
||||||
/** Column name C_Project_ID */
|
/** Column name C_Project_ID */
|
||||||
public static final String COLUMNNAME_C_Project_ID = "C_Project_ID";
|
public static final String COLUMNNAME_C_Project_ID = "C_Project_ID";
|
||||||
|
|
||||||
|
|
|
@ -93,6 +93,19 @@ public interface I_M_InventoryLine
|
||||||
*/
|
*/
|
||||||
public int getCreatedBy();
|
public int getCreatedBy();
|
||||||
|
|
||||||
|
/** Column name CurrentCostPrice */
|
||||||
|
public static final String COLUMNNAME_CurrentCostPrice = "CurrentCostPrice";
|
||||||
|
|
||||||
|
/** Set Current Cost Price.
|
||||||
|
* The currently used cost price
|
||||||
|
*/
|
||||||
|
public void setCurrentCostPrice (BigDecimal CurrentCostPrice);
|
||||||
|
|
||||||
|
/** Get Current Cost Price.
|
||||||
|
* The currently used cost price
|
||||||
|
*/
|
||||||
|
public BigDecimal getCurrentCostPrice();
|
||||||
|
|
||||||
/** Column name Description */
|
/** Column name Description */
|
||||||
public static final String COLUMNNAME_Description = "Description";
|
public static final String COLUMNNAME_Description = "Description";
|
||||||
|
|
||||||
|
@ -227,6 +240,19 @@ public interface I_M_InventoryLine
|
||||||
|
|
||||||
public org.compiere.model.I_M_Product getM_Product() throws RuntimeException;
|
public org.compiere.model.I_M_Product getM_Product() throws RuntimeException;
|
||||||
|
|
||||||
|
/** Column name NewCostPrice */
|
||||||
|
public static final String COLUMNNAME_NewCostPrice = "NewCostPrice";
|
||||||
|
|
||||||
|
/** Set New Cost Price.
|
||||||
|
* New current cost price after processing of M_CostDetail
|
||||||
|
*/
|
||||||
|
public void setNewCostPrice (BigDecimal NewCostPrice);
|
||||||
|
|
||||||
|
/** Get New Cost Price.
|
||||||
|
* New current cost price after processing of M_CostDetail
|
||||||
|
*/
|
||||||
|
public BigDecimal getNewCostPrice();
|
||||||
|
|
||||||
/** Column name Processed */
|
/** Column name Processed */
|
||||||
public static final String COLUMNNAME_Processed = "Processed";
|
public static final String COLUMNNAME_Processed = "Processed";
|
||||||
|
|
||||||
|
|
|
@ -1037,13 +1037,22 @@ public class MCostDetail extends X_M_CostDetail
|
||||||
|| getPP_Cost_Collector_ID() != 0)
|
|| getPP_Cost_Collector_ID() != 0)
|
||||||
{
|
{
|
||||||
boolean addition = qty.signum() > 0;
|
boolean addition = qty.signum() > 0;
|
||||||
|
boolean adjustment = getM_InventoryLine_ID() > 0 && qty.signum() == 0 && amt.signum() != 0;
|
||||||
boolean isVendorRMA = isVendorRMA();
|
boolean isVendorRMA = isVendorRMA();
|
||||||
//
|
//
|
||||||
if (ce.isAverageInvoice())
|
if (ce.isAverageInvoice())
|
||||||
{
|
{
|
||||||
if (!isVendorRMA)
|
if (!isVendorRMA)
|
||||||
{
|
{
|
||||||
if (addition)
|
if (adjustment)
|
||||||
|
{
|
||||||
|
String costingMethod = getM_InventoryLine().getM_Inventory().getCostingMethod();
|
||||||
|
if (MCostElement.COSTINGMETHOD_AverageInvoice.equals(costingMethod))
|
||||||
|
{
|
||||||
|
cost.setWeightedAverage(amt.multiply(cost.getCurrentQty()), qty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (addition)
|
||||||
{
|
{
|
||||||
cost.setWeightedAverage(amt, qty);
|
cost.setWeightedAverage(amt, qty);
|
||||||
//shouldn't accumulate reversal of customer shipment qty and amt
|
//shouldn't accumulate reversal of customer shipment qty and amt
|
||||||
|
@ -1060,7 +1069,15 @@ public class MCostDetail extends X_M_CostDetail
|
||||||
}
|
}
|
||||||
else if (ce.isAveragePO())
|
else if (ce.isAveragePO())
|
||||||
{
|
{
|
||||||
if (addition)
|
if (adjustment)
|
||||||
|
{
|
||||||
|
String costingMethod = getM_InventoryLine().getM_Inventory().getCostingMethod();
|
||||||
|
if (MCostElement.COSTINGMETHOD_AveragePO.equals(costingMethod))
|
||||||
|
{
|
||||||
|
cost.setWeightedAverage(amt.multiply(cost.getCurrentQty()), qty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (addition)
|
||||||
{
|
{
|
||||||
cost.setWeightedAverage(amt, qty);
|
cost.setWeightedAverage(amt, qty);
|
||||||
//shouldn't accumulate reversal of customer shipment qty and amt
|
//shouldn't accumulate reversal of customer shipment qty and amt
|
||||||
|
@ -1085,7 +1102,7 @@ public class MCostDetail extends X_M_CostDetail
|
||||||
}
|
}
|
||||||
else if (ce.isFifo() || ce.isLifo())
|
else if (ce.isFifo() || ce.isLifo())
|
||||||
{
|
{
|
||||||
if (!isVendorRMA)
|
if (!isVendorRMA && !adjustment)
|
||||||
{
|
{
|
||||||
if (addition)
|
if (addition)
|
||||||
{
|
{
|
||||||
|
@ -1110,19 +1127,28 @@ public class MCostDetail extends X_M_CostDetail
|
||||||
if (log.isLoggable(Level.FINER)) log.finer("QtyAdjust - FiFo/Lifo - " + cost);
|
if (log.isLoggable(Level.FINER)) log.finer("QtyAdjust - FiFo/Lifo - " + cost);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (ce.isLastInvoice() && !isVendorRMA)
|
else if (ce.isLastInvoice() && !isVendorRMA && !adjustment)
|
||||||
{
|
{
|
||||||
cost.setCurrentQty(cost.getCurrentQty().add(qty));
|
cost.setCurrentQty(cost.getCurrentQty().add(qty));
|
||||||
if (log.isLoggable(Level.FINER)) log.finer("QtyAdjust - LastInv - " + cost);
|
if (log.isLoggable(Level.FINER)) log.finer("QtyAdjust - LastInv - " + cost);
|
||||||
}
|
}
|
||||||
else if (ce.isLastPOPrice() && !isVendorRMA)
|
else if (ce.isLastPOPrice() && !isVendorRMA && !adjustment)
|
||||||
{
|
{
|
||||||
cost.setCurrentQty(cost.getCurrentQty().add(qty));
|
cost.setCurrentQty(cost.getCurrentQty().add(qty));
|
||||||
if (log.isLoggable(Level.FINER)) log.finer("QtyAdjust - LastPO - " + cost);
|
if (log.isLoggable(Level.FINER)) log.finer("QtyAdjust - LastPO - " + cost);
|
||||||
}
|
}
|
||||||
else if (ce.isStandardCosting() && !isVendorRMA)
|
else if (ce.isStandardCosting() && !isVendorRMA)
|
||||||
{
|
{
|
||||||
if (addition)
|
if (adjustment)
|
||||||
|
{
|
||||||
|
String costingMethod = getM_InventoryLine().getM_Inventory().getCostingMethod();
|
||||||
|
if (MCostElement.COSTINGMETHOD_StandardCosting.equals(costingMethod))
|
||||||
|
{
|
||||||
|
cost.add(amt.multiply(cost.getCurrentQty()), qty);
|
||||||
|
cost.setCurrentCostPrice(cost.getCurrentCostPrice().add(amt));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (addition)
|
||||||
{
|
{
|
||||||
cost.add(amt, qty);
|
cost.add(amt, qty);
|
||||||
// Initial
|
// Initial
|
||||||
|
@ -1140,7 +1166,7 @@ public class MCostDetail extends X_M_CostDetail
|
||||||
}
|
}
|
||||||
if (log.isLoggable(Level.FINER)) log.finer("QtyAdjust - Standard - " + cost);
|
if (log.isLoggable(Level.FINER)) log.finer("QtyAdjust - Standard - " + cost);
|
||||||
}
|
}
|
||||||
else if (ce.isUserDefined() && !isVendorRMA)
|
else if (ce.isUserDefined() && !isVendorRMA && !adjustment)
|
||||||
{
|
{
|
||||||
// Interface
|
// Interface
|
||||||
if (addition)
|
if (addition)
|
||||||
|
|
|
@ -105,6 +105,27 @@ public class MCostElement extends X_M_CostElement
|
||||||
return retValue;
|
return retValue;
|
||||||
} // getMaterialCostElement
|
} // getMaterialCostElement
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get first Material Cost Element
|
||||||
|
* @param ctx context
|
||||||
|
* @param CostingMethod costing method
|
||||||
|
* @return Cost Element or null
|
||||||
|
*/
|
||||||
|
public static MCostElement getMaterialCostElement(Properties ctx, String CostingMethod, int AD_Org_ID)
|
||||||
|
{
|
||||||
|
final String whereClause = "AD_Client_ID=? AND CostingMethod=? AND CostElementType=? AND AD_Org_ID In (0, ?)";
|
||||||
|
List<MCostElement> list = new Query(ctx, I_M_CostElement.Table_Name, whereClause, null)
|
||||||
|
.setParameters(Env.getAD_Client_ID(ctx),CostingMethod,COSTELEMENTTYPE_Material,AD_Org_ID)
|
||||||
|
.setOrderBy(I_M_CostElement.COLUMNNAME_AD_Org_ID + " Desc")
|
||||||
|
.list();
|
||||||
|
MCostElement retValue = null;
|
||||||
|
if (list.size() > 0)
|
||||||
|
retValue = list.get(0);
|
||||||
|
if (list.size() > 1)
|
||||||
|
if (s_log.isLoggable(Level.INFO)) s_log.info("More then one Material Cost Element for CostingMethod=" + CostingMethod);
|
||||||
|
return retValue;
|
||||||
|
} // getMaterialCostElement
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get active Material Cost Element for client
|
* Get active Material Cost Element for client
|
||||||
* @param po parent
|
* @param po parent
|
||||||
|
|
|
@ -412,6 +412,21 @@ public class MInventory extends X_M_Inventory implements DocAction
|
||||||
qtyDiff = line.getQtyInternalUse().negate();
|
qtyDiff = line.getQtyInternalUse().negate();
|
||||||
else if (MDocType.DOCSUBTYPEINV_PhysicalInventory.equals(docSubTypeInv))
|
else if (MDocType.DOCSUBTYPEINV_PhysicalInventory.equals(docSubTypeInv))
|
||||||
qtyDiff = line.getQtyCount().subtract(line.getQtyBook());
|
qtyDiff = line.getQtyCount().subtract(line.getQtyBook());
|
||||||
|
else if (MDocType.DOCSUBTYPEINV_CostAdjustment.equals(docSubTypeInv))
|
||||||
|
{
|
||||||
|
if (!isReversal())
|
||||||
|
{
|
||||||
|
BigDecimal currentCost = line.getCurrentCostPrice();
|
||||||
|
MClient client = MClient.get(getCtx(), getAD_Client_ID());
|
||||||
|
MAcctSchema as = client.getAcctSchema();
|
||||||
|
MCost cost = product.getCostingRecord(as, getAD_Org_ID(), line.getM_AttributeSetInstance_ID(), getCostingMethod());
|
||||||
|
if (cost != null && cost.getCurrentCostPrice().compareTo(currentCost) != 0)
|
||||||
|
{
|
||||||
|
m_processMsg = "Current Cost for Line " + line.getLine() + " have changed.";
|
||||||
|
return DocAction.STATUS_Invalid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//If Quantity Count minus Quantity Book = Zero, then no change in Inventory
|
//If Quantity Count minus Quantity Book = Zero, then no change in Inventory
|
||||||
if (qtyDiff.signum() == 0)
|
if (qtyDiff.signum() == 0)
|
||||||
|
|
|
@ -346,7 +346,33 @@ public class MInventoryLine extends X_M_InventoryLine
|
||||||
log.saveError("Quantity", Msg.getElement(getCtx(), COLUMNNAME_QtyInternalUse));
|
log.saveError("Quantity", Msg.getElement(getCtx(), COLUMNNAME_QtyInternalUse));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
} else if (MDocType.DOCSUBTYPEINV_CostAdjustment.equals(docSubTypeInv)) {
|
||||||
|
if (getNewCostPrice().signum() == 0) {
|
||||||
|
log.saveError("FillMandatory", Msg.getElement(getCtx(), COLUMNNAME_NewCostPrice));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int M_ASI_ID = getM_AttributeSetInstance_ID();
|
||||||
|
MProduct product = getProduct();
|
||||||
|
MClient client = MClient.get(getCtx());
|
||||||
|
MAcctSchema as = client.getAcctSchema();
|
||||||
|
String costingLevel = product.getCostingLevel(as);
|
||||||
|
if (MAcctSchema.COSTINGLEVEL_BatchLot.equals(costingLevel)) {
|
||||||
|
if (M_ASI_ID == 0) {
|
||||||
|
log.saveError("FillMandatory", Msg.getElement(getCtx(), COLUMNNAME_M_AttributeSetInstance_ID));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String costingMethod = getParent().getCostingMethod();
|
||||||
|
int AD_Org_ID = getAD_Org_ID();
|
||||||
|
MCost cost = product.getCostingRecord(as, AD_Org_ID, M_ASI_ID, costingMethod);
|
||||||
|
if (cost == null) {
|
||||||
|
if (!MCostElement.COSTINGMETHOD_StandardCosting.equals(costingMethod)) {
|
||||||
|
log.saveError("NoCostingRecord", "");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
log.saveError("Error", "Document inventory subtype not configured, cannot complete");
|
log.saveError("Error", "Document inventory subtype not configured, cannot complete");
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -869,4 +869,34 @@ public class MProduct extends X_M_Product
|
||||||
}
|
}
|
||||||
return costingMethod;
|
return costingMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MCost getCostingRecord(MAcctSchema as, int AD_Org_ID, int M_ASI_ID)
|
||||||
|
{
|
||||||
|
return getCostingRecord(as, AD_Org_ID, M_ASI_ID, getCostingMethod(as));
|
||||||
|
}
|
||||||
|
|
||||||
|
public MCost getCostingRecord(MAcctSchema as, int AD_Org_ID, int M_ASI_ID, String costingMethod)
|
||||||
|
{
|
||||||
|
|
||||||
|
String costingLevel = getCostingLevel(as);
|
||||||
|
if (MAcctSchema.COSTINGLEVEL_Client.equals(costingLevel))
|
||||||
|
{
|
||||||
|
AD_Org_ID = 0;
|
||||||
|
M_ASI_ID = 0;
|
||||||
|
}
|
||||||
|
else if (MAcctSchema.COSTINGLEVEL_Organization.equals(costingLevel))
|
||||||
|
M_ASI_ID = 0;
|
||||||
|
else if (MAcctSchema.COSTINGLEVEL_BatchLot.equals(costingLevel))
|
||||||
|
{
|
||||||
|
AD_Org_ID = 0;
|
||||||
|
if (M_ASI_ID == 0)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
MCostElement ce = MCostElement.getMaterialCostElement(getCtx(), costingMethod, AD_Org_ID);
|
||||||
|
if (ce == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
MCost cost = MCost.get(this, M_ASI_ID, as, AD_Org_ID, ce.getM_CostElement_ID(), (String)null);
|
||||||
|
return cost.is_new() ? null : cost;
|
||||||
|
}
|
||||||
} // MProduct
|
} // MProduct
|
||||||
|
|
|
@ -683,11 +683,15 @@ public final class MSetup
|
||||||
createDocType("Material Movement", Msg.getElement(m_ctx, "M_Movement_ID", false),
|
createDocType("Material Movement", Msg.getElement(m_ctx, "M_Movement_ID", false),
|
||||||
MDocType.DOCBASETYPE_MaterialMovement, null, 0, 0, 610000, GL_MM, false);
|
MDocType.DOCBASETYPE_MaterialMovement, null, 0, 0, 610000, GL_MM, false);
|
||||||
createDocType("Physical Inventory", Msg.getElement(m_ctx, "M_Inventory_ID", false),
|
createDocType("Physical Inventory", Msg.getElement(m_ctx, "M_Inventory_ID", false),
|
||||||
MDocType.DOCBASETYPE_MaterialPhysicalInventory, null, 0, 0, 620000, GL_MM, false);
|
MDocType.DOCBASETYPE_MaterialPhysicalInventory, MDocType.DOCSUBTYPEINV_PhysicalInventory, 0, 0, 620000, GL_MM, false);
|
||||||
createDocType("Material Production", Msg.getElement(m_ctx, "M_Production_ID", false),
|
createDocType("Material Production", Msg.getElement(m_ctx, "M_Production_ID", false),
|
||||||
MDocType.DOCBASETYPE_MaterialProduction, null, 0, 0, 630000, GL_MM, false);
|
MDocType.DOCBASETYPE_MaterialProduction, null, 0, 0, 630000, GL_MM, false);
|
||||||
createDocType("Project Issue", Msg.getElement(m_ctx, "C_ProjectIssue_ID", false),
|
createDocType("Project Issue", Msg.getElement(m_ctx, "C_ProjectIssue_ID", false),
|
||||||
MDocType.DOCBASETYPE_ProjectIssue, null, 0, 0, 640000, GL_MM, false);
|
MDocType.DOCBASETYPE_ProjectIssue, null, 0, 0, 640000, GL_MM, false);
|
||||||
|
createDocType("Internal Use Inventory", "Internal Use Inventory",
|
||||||
|
MDocType.DOCBASETYPE_MaterialPhysicalInventory, MDocType.DOCSUBTYPEINV_InternalUseInventory, 0, 0, 650000, GL_MM, false);
|
||||||
|
createDocType("Cost Adjustment", "Cost Adjustment",
|
||||||
|
MDocType.DOCBASETYPE_MaterialPhysicalInventory, MDocType.DOCSUBTYPEINV_CostAdjustment, 0, 0, 660000, GL_MM, false);
|
||||||
|
|
||||||
// Order Entry
|
// Order Entry
|
||||||
createDocType("Binding offer", "Quotation",
|
createDocType("Binding offer", "Quotation",
|
||||||
|
@ -891,7 +895,16 @@ public final class MSetup
|
||||||
if (PrintName != null && PrintName.length() > 0)
|
if (PrintName != null && PrintName.length() > 0)
|
||||||
dt.setPrintName(PrintName); // Defaults to Name
|
dt.setPrintName(PrintName); // Defaults to Name
|
||||||
if (DocSubTypeSO != null)
|
if (DocSubTypeSO != null)
|
||||||
|
{
|
||||||
|
if (MDocType.DOCBASETYPE_MaterialPhysicalInventory.equals(DocBaseType))
|
||||||
|
{
|
||||||
|
dt.setDocSubTypeInv(DocSubTypeSO);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
dt.setDocSubTypeSO(DocSubTypeSO);
|
dt.setDocSubTypeSO(DocSubTypeSO);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (C_DocTypeShipment_ID != 0)
|
if (C_DocTypeShipment_ID != 0)
|
||||||
dt.setC_DocTypeShipment_ID(C_DocTypeShipment_ID);
|
dt.setC_DocTypeShipment_ID(C_DocTypeShipment_ID);
|
||||||
if (C_DocTypeInvoice_ID != 0)
|
if (C_DocTypeInvoice_ID != 0)
|
||||||
|
|
|
@ -30,7 +30,7 @@ public class X_C_DocType extends PO implements I_C_DocType, I_Persistent
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = 20130626L;
|
private static final long serialVersionUID = 20130717L;
|
||||||
|
|
||||||
/** Standard Constructor */
|
/** Standard Constructor */
|
||||||
public X_C_DocType (Properties ctx, int C_DocType_ID, String trxName)
|
public X_C_DocType (Properties ctx, int C_DocType_ID, String trxName)
|
||||||
|
@ -429,6 +429,8 @@ public class X_C_DocType extends PO implements I_C_DocType, I_Persistent
|
||||||
public static final String DOCSUBTYPEINV_PhysicalInventory = "PI";
|
public static final String DOCSUBTYPEINV_PhysicalInventory = "PI";
|
||||||
/** Internal Use Inventory = IU */
|
/** Internal Use Inventory = IU */
|
||||||
public static final String DOCSUBTYPEINV_InternalUseInventory = "IU";
|
public static final String DOCSUBTYPEINV_InternalUseInventory = "IU";
|
||||||
|
/** Cost Adjustment = CA */
|
||||||
|
public static final String DOCSUBTYPEINV_CostAdjustment = "CA";
|
||||||
/** Set Inv Sub Type.
|
/** Set Inv Sub Type.
|
||||||
@param DocSubTypeInv
|
@param DocSubTypeInv
|
||||||
Inventory Sub Type
|
Inventory Sub Type
|
||||||
|
|
|
@ -33,7 +33,7 @@ public class X_M_Inventory extends PO implements I_M_Inventory, I_Persistent
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = 20130626L;
|
private static final long serialVersionUID = 20130717L;
|
||||||
|
|
||||||
/** Standard Constructor */
|
/** Standard Constructor */
|
||||||
public X_M_Inventory (Properties ctx, int M_Inventory_ID, String trxName)
|
public X_M_Inventory (Properties ctx, int M_Inventory_ID, String trxName)
|
||||||
|
@ -212,6 +212,44 @@ public class X_M_Inventory extends PO implements I_M_Inventory, I_Persistent
|
||||||
return ii.intValue();
|
return ii.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** CostingMethod AD_Reference_ID=122 */
|
||||||
|
public static final int COSTINGMETHOD_AD_Reference_ID=122;
|
||||||
|
/** Standard Costing = S */
|
||||||
|
public static final String COSTINGMETHOD_StandardCosting = "S";
|
||||||
|
/** Average PO = A */
|
||||||
|
public static final String COSTINGMETHOD_AveragePO = "A";
|
||||||
|
/** Lifo = L */
|
||||||
|
public static final String COSTINGMETHOD_Lifo = "L";
|
||||||
|
/** Fifo = F */
|
||||||
|
public static final String COSTINGMETHOD_Fifo = "F";
|
||||||
|
/** Last PO Price = p */
|
||||||
|
public static final String COSTINGMETHOD_LastPOPrice = "p";
|
||||||
|
/** Average Invoice = I */
|
||||||
|
public static final String COSTINGMETHOD_AverageInvoice = "I";
|
||||||
|
/** Last Invoice = i */
|
||||||
|
public static final String COSTINGMETHOD_LastInvoice = "i";
|
||||||
|
/** User Defined = U */
|
||||||
|
public static final String COSTINGMETHOD_UserDefined = "U";
|
||||||
|
/** _ = x */
|
||||||
|
public static final String COSTINGMETHOD__ = "x";
|
||||||
|
/** Set Costing Method.
|
||||||
|
@param CostingMethod
|
||||||
|
Indicates how Costs will be calculated
|
||||||
|
*/
|
||||||
|
public void setCostingMethod (String CostingMethod)
|
||||||
|
{
|
||||||
|
|
||||||
|
set_Value (COLUMNNAME_CostingMethod, CostingMethod);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get Costing Method.
|
||||||
|
@return Indicates how Costs will be calculated
|
||||||
|
*/
|
||||||
|
public String getCostingMethod ()
|
||||||
|
{
|
||||||
|
return (String)get_Value(COLUMNNAME_CostingMethod);
|
||||||
|
}
|
||||||
|
|
||||||
public org.compiere.model.I_C_Project getC_Project() throws RuntimeException
|
public org.compiere.model.I_C_Project getC_Project() throws RuntimeException
|
||||||
{
|
{
|
||||||
return (org.compiere.model.I_C_Project)MTable.get(getCtx(), org.compiere.model.I_C_Project.Table_Name)
|
return (org.compiere.model.I_C_Project)MTable.get(getCtx(), org.compiere.model.I_C_Project.Table_Name)
|
||||||
|
|
|
@ -32,7 +32,7 @@ public class X_M_InventoryLine extends PO implements I_M_InventoryLine, I_Persis
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = 20130626L;
|
private static final long serialVersionUID = 20130717L;
|
||||||
|
|
||||||
/** Standard Constructor */
|
/** Standard Constructor */
|
||||||
public X_M_InventoryLine (Properties ctx, int M_InventoryLine_ID, String trxName)
|
public X_M_InventoryLine (Properties ctx, int M_InventoryLine_ID, String trxName)
|
||||||
|
@ -111,6 +111,26 @@ public class X_M_InventoryLine extends PO implements I_M_InventoryLine, I_Persis
|
||||||
return ii.intValue();
|
return ii.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Set Current Cost Price.
|
||||||
|
@param CurrentCostPrice
|
||||||
|
The currently used cost price
|
||||||
|
*/
|
||||||
|
public void setCurrentCostPrice (BigDecimal CurrentCostPrice)
|
||||||
|
{
|
||||||
|
set_ValueNoCheck (COLUMNNAME_CurrentCostPrice, CurrentCostPrice);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get Current Cost Price.
|
||||||
|
@return The currently used cost price
|
||||||
|
*/
|
||||||
|
public BigDecimal getCurrentCostPrice ()
|
||||||
|
{
|
||||||
|
BigDecimal bd = (BigDecimal)get_Value(COLUMNNAME_CurrentCostPrice);
|
||||||
|
if (bd == null)
|
||||||
|
return Env.ZERO;
|
||||||
|
return bd;
|
||||||
|
}
|
||||||
|
|
||||||
/** Set Description.
|
/** Set Description.
|
||||||
@param Description
|
@param Description
|
||||||
Optional short description of the record
|
Optional short description of the record
|
||||||
|
@ -329,6 +349,26 @@ public class X_M_InventoryLine extends PO implements I_M_InventoryLine, I_Persis
|
||||||
return ii.intValue();
|
return ii.intValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Set New Cost Price.
|
||||||
|
@param NewCostPrice
|
||||||
|
New current cost price after processing of M_CostDetail
|
||||||
|
*/
|
||||||
|
public void setNewCostPrice (BigDecimal NewCostPrice)
|
||||||
|
{
|
||||||
|
set_Value (COLUMNNAME_NewCostPrice, NewCostPrice);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Get New Cost Price.
|
||||||
|
@return New current cost price after processing of M_CostDetail
|
||||||
|
*/
|
||||||
|
public BigDecimal getNewCostPrice ()
|
||||||
|
{
|
||||||
|
BigDecimal bd = (BigDecimal)get_Value(COLUMNNAME_NewCostPrice);
|
||||||
|
if (bd == null)
|
||||||
|
return Env.ZERO;
|
||||||
|
return bd;
|
||||||
|
}
|
||||||
|
|
||||||
/** Set Processed.
|
/** Set Processed.
|
||||||
@param Processed
|
@param Processed
|
||||||
The document has been processed
|
The document has been processed
|
||||||
|
|
Loading…
Reference in New Issue