diff --git a/migration/360lts-release/oracle/826_IDEMPIERE-118.sql b/migration/360lts-release/oracle/826_IDEMPIERE-118.sql new file mode 100644 index 0000000000..6c6ca7599c --- /dev/null +++ b/migration/360lts-release/oracle/826_IDEMPIERE-118.sql @@ -0,0 +1,12 @@ +-- Mar 19, 2012 8:33:59 PM MYT +-- IDEMPIERE-118 Average Costing: Negative Inventory +UPDATE AD_Column SET ReadOnlyLogic=NULL,Updated=TO_DATE('2012-03-19 20:33:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=13455 +; + +UPDATE AD_System + SET LastMigrationScriptApplied='826_IDEMPIERE-118.sql' +WHERE LastMigrationScriptApplied<'826_IDEMPIERE-118.sql' + OR LastMigrationScriptApplied IS NULL +; + + diff --git a/migration/360lts-release/postgresql/826_IDEMPIERE-118.sql b/migration/360lts-release/postgresql/826_IDEMPIERE-118.sql new file mode 100644 index 0000000000..0585a803c5 --- /dev/null +++ b/migration/360lts-release/postgresql/826_IDEMPIERE-118.sql @@ -0,0 +1,10 @@ +-- Mar 19, 2012 8:33:59 PM MYT +-- IDEMPIERE-118 Average Costing: Negative Inventory +UPDATE AD_Column SET ReadOnlyLogic=NULL,Updated=TO_DATE('2012-03-19 20:33:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=13455 +; + +UPDATE AD_System + SET LastMigrationScriptApplied='826_IDEMPIERE-118.sql' +WHERE LastMigrationScriptApplied<'826_IDEMPIERE-118.sql' + OR LastMigrationScriptApplied IS NULL +; diff --git a/org.adempiere.base/src/org/compiere/acct/DocManager.java b/org.adempiere.base/src/org/compiere/acct/DocManager.java index 26c6801bab..76af3bfd98 100644 --- a/org.adempiere.base/src/org/compiere/acct/DocManager.java +++ b/org.adempiere.base/src/org/compiere/acct/DocManager.java @@ -19,6 +19,7 @@ package org.compiere.acct; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Savepoint; import java.util.ArrayList; import java.util.List; @@ -282,7 +283,8 @@ public class DocManager { localTrxName = Trx.createTrxName("Post"); trxName = localTrxName; } - + + Trx trx = Trx.get(trxName, true); String error = null; try { @@ -292,10 +294,20 @@ public class DocManager { Doc doc = Doc.get (as, AD_Table_ID, rs, trxName); if (doc != null) { + Savepoint savepoint = trx.setSavepoint(null); error = doc.post (force, repost); // repost status = doc.getPostStatus(); if (error != null && error.trim().length() > 0) + { + trx.rollback(savepoint); break; + } + else + { + try { + trx.releaseSavepoint(savepoint); + } catch (Exception e) {} + } } else { @@ -311,7 +323,6 @@ public class DocManager { ValueNamePair dbError = CLogger.retrieveError(); // log.log(Level.SEVERE, "(doc not saved) ... rolling back"); if (localTrxName != null) { - Trx trx = Trx.get(localTrxName, false); if (trx != null) trx.rollback(); } @@ -321,7 +332,6 @@ public class DocManager { error = "SaveError"; } if (localTrxName != null) { - Trx trx = Trx.get(localTrxName, false); if (trx != null) trx.commit(); } @@ -329,7 +339,6 @@ public class DocManager { catch (Exception e) { if (localTrxName != null) { - Trx trx = Trx.get(localTrxName, false); if (trx != null) trx.rollback(); } @@ -342,7 +351,6 @@ public class DocManager { { if (localTrxName != null) { - Trx trx = Trx.get(localTrxName, false); if (trx != null) trx.close(); } diff --git a/org.adempiere.base/src/org/compiere/model/MCost.java b/org.adempiere.base/src/org/compiere/model/MCost.java index 5c524ba763..e01ff10958 100644 --- a/org.adempiere.base/src/org/compiere/model/MCost.java +++ b/org.adempiere.base/src/org/compiere/model/MCost.java @@ -1441,6 +1441,15 @@ public class MCost extends X_M_Cost */ public void add (BigDecimal amt, BigDecimal qty) { + MCostElement costElement = (MCostElement) getM_CostElement(); + if (costElement.isAveragePO() || costElement.isAverageInvoice()) + { + if (getCurrentQty().add(qty).signum() < 0) + { + throw new AverageCostingNegativeQtyException("Product(ID)="+getM_Product_ID()+", Current Qty="+getCurrentQty()+", Trx Qty="+qty + + ", CostElement="+costElement.getName()+", Schema="+getC_AcctSchema().getName()); + } + } setCumulatedAmt(getCumulatedAmt().add(amt)); setCumulatedQty(getCumulatedQty().add(qty)); setCurrentQty(getCurrentQty().add(qty)); @@ -1462,7 +1471,8 @@ public class MCost extends X_M_Cost if (getCurrentQty().add(qty).signum() < 0) { - throw new AverageCostingNegativeQtyException("Product(ID)="+getM_Product_ID()+", Current Qty="+getCurrentQty()+", Trx Qty="+qty); + throw new AverageCostingNegativeQtyException("Product(ID)="+getM_Product_ID()+", Current Qty="+getCurrentQty()+", Trx Qty="+qty + +", CostElement="+getM_CostElement().getName()+", Schema="+getC_AcctSchema().getName()); } BigDecimal oldSum = getCurrentCostPrice().multiply(getCurrentQty()); @@ -1616,6 +1626,17 @@ public class MCost extends X_M_Cost if (getCumulatedQty().signum() != 0) setCumulatedQty(Env.ZERO); } + + //-ve current qty will break moving average costing + if ((ce.isAveragePO() || ce.isAverageInvoice()) && is_ValueChanged(COLUMNNAME_CurrentQty)) + { + if (getCurrentQty().signum() < 0) + { + throw new AverageCostingNegativeQtyException("Product(ID)="+getM_Product_ID()+", Current Qty="+getCurrentQty() + +", CostElement="+getM_CostElement().getName()+", Schema="+getC_AcctSchema().getName()); + } + } + return true; } // beforeSave @@ -1630,6 +1651,20 @@ public class MCost extends X_M_Cost } // beforeDelete + @Override + public void setCurrentQty(BigDecimal CurrentQty) { + MCostElement ce = (MCostElement)getM_CostElement(); + if (ce.isAveragePO() || ce.isAverageInvoice()) + { + if (CurrentQty.signum() < 0) + { + throw new AverageCostingNegativeQtyException("Product(ID)="+getM_Product_ID()+", Current Qty="+getCurrentQty()+", New Current Qty="+CurrentQty + +", CostElement="+ce.getName()+", Schema="+getC_AcctSchema().getName()); + } + } + super.setCurrentQty(CurrentQty); + } + /** * Test * @param args ignored