Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IDEMPIERE-5836 Adding support for stocked expense product #2039

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions migration/iD11/oracle/202309291327_IDEMPIERE-5836.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
SELECT register_migration_script('202309291327_IDEMPIERE-5836.sql') FROM dual;
SET SQLBLANKLINES ON
SET DEFINE OFF

-- I forgot to set the DICTIONARY_ID_COMMENTS System Configurator
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment on line 5 is wrong "I forgot to set the DICTIONARY_ID_COMMENTS System Configurator" better to delete it or make it correct

-- Aug 8, 2023, 1:27:56 PM IST
UPDATE AD_Field SET DisplayLogic='@IsSummary@=''N'' & @ProductType@=I | @ProductType@=E', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2023-08-08 13:27:56','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=1026
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic here is wrong, is showing the Stocked flag when the product is marked as Summary and Expense.

You need to add parenthesis on the OR condition, or reorder it to check the IsSummary at the end

;

-- Aug 8, 2023, 1:29:13 PM IST
UPDATE AD_Column SET ReadOnlyLogic='@ProductType@=R | @ProductType@=O',Updated=TO_DATE('2023-08-08 13:29:13','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=1761
;

-- Oct 2, 2023, 3:38:33 PM IST
UPDATE AD_Column SET Callout='org.compiere.model.CalloutProduct.productType',Updated=TO_TIMESTAMP('2023-10-02 15:38:33','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=7795
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The CalloutProduct class is missing on the pull request

;
13 changes: 13 additions & 0 deletions migration/iD11/postgresql/202309291327_IDEMPIERE-5836.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
SELECT register_migration_script('202309291327_IDEMPIERE-5836.sql') FROM dual;
-- I forgot to set the DICTIONARY_ID_COMMENTS System Configurator
-- Aug 8, 2023, 1:27:56 PM IST
UPDATE AD_Field SET DisplayLogic='@IsSummary@=''N'' & @ProductType@=I | @ProductType@=E', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2023-08-08 13:27:56','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=1026
;

-- Aug 8, 2023, 1:29:13 PM IST
UPDATE AD_Column SET ReadOnlyLogic='@ProductType@=R | @ProductType@=O',Updated=TO_TIMESTAMP('2023-08-08 13:29:13','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=1761
;

-- Oct 2, 2023, 3:38:33 PM IST
UPDATE AD_Column SET Callout='org.compiere.model.CalloutProduct.productType',Updated=TO_TIMESTAMP('2023-10-02 15:38:33','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=7795
;
10 changes: 10 additions & 0 deletions org.adempiere.base/src/org/compiere/acct/Doc_InOut.java
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,11 @@ public ArrayList<Fact> createFacts (MAcctSchema as)
Map<String, BigDecimal> batchLotCostMap = null;
DocLine_InOut line = (DocLine_InOut) p_lines[i];
MProduct product = line.getProduct();
//If expense type stocked product, no impact on COGS as it not deducting inventory
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when doing a manual material receipt - is complaining with "No Costs for ..." - if the expense product is not to be posted, then the posting must not throw error

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We were creating cost. now creating new PR which has no cost created at all and so it will not throw any error.

if(MProduct.PRODUCTTYPE_ExpenseType.equals(product.getProductType()) && product.isStocked()) {
continue;
}

BigDecimal costs = null;
if (!isReversal(line))
{
Expand Down Expand Up @@ -430,6 +435,11 @@ else if ( getDocumentType().equals(DOCTYPE_MatReceipt) && isSOTrx() )
{
DocLine_InOut line = (DocLine_InOut) p_lines[i];
MProduct product = line.getProduct();
//If expense type stocked product, no impact on COGS as it not deducting inventory
if(MProduct.PRODUCTTYPE_ExpenseType.equals(product.getProductType()) && product.isStocked()) {
continue;
}

BigDecimal costs = null;
Map<String, BigDecimal> batchLotCostMap = null;
if (!isReversal(line))
Expand Down
5 changes: 5 additions & 0 deletions org.adempiere.base/src/org/compiere/acct/Doc_Inventory.java
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,11 @@ else if (MAcctSchema.COSTINGLEVEL_BatchLot.equals(costingLevel))
}
else
{
//if product type expense and stocked, then no needs to do posting
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Posting an Internal Use Inventory is throwing this error:
15:42:49.073===========> Doc_Inventory.post: [371]
java.lang.NullPointerException: Cannot invoke "org.compiere.model.MProduct.getProductType()" because "product" is null
at org.compiere.acct.Doc_Inventory.createFacts(Doc_Inventory.java:249)
at org.compiere.acct.Doc.postLogic(Doc.java:741)
at org.compiere.acct.Doc.post(Doc.java:625)

if(MProduct.PRODUCTTYPE_ExpenseType.equals(product.getProductType()) && product.isStocked()) {
continue;
}

if (!isReversal(line))
{
product = line.getProduct();
Expand Down
9 changes: 7 additions & 2 deletions org.adempiere.base/src/org/compiere/acct/Doc_Movement.java
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,15 @@ public ArrayList<Fact> createFacts (MAcctSchema as)
{
DocLine line = p_lines[i];
BigDecimal costs = null;

MProduct product = (MProduct) line.getProduct();

//If expense type stocked product, no accounting impacted
if(MProduct.PRODUCTTYPE_ExpenseType.equals(product.getProductType()) && product.isStocked()) {
continue;
}

if (!isReversal(line))
{
MProduct product = (MProduct) line.getProduct();
String costingLevel = product.getCostingLevel(as);
if (MAcctSchema.COSTINGLEVEL_BatchLot.equals(costingLevel) )
{
Expand Down
13 changes: 9 additions & 4 deletions org.adempiere.base/src/org/compiere/acct/Doc_Production.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.Map;
import java.util.logging.Level;

import org.compiere.model.MAccount;
import org.compiere.model.MAcctSchema;
import org.compiere.model.MCostDetail;
import org.compiere.model.MProduct;
Expand Down Expand Up @@ -375,9 +376,11 @@ public ArrayList<Fact> createFacts (MAcctSchema as)

if (MAcctSchema.COSTINGLEVEL_BatchLot.equals(CostingLevel))
{
MAccount assets = line.getAccount(ProductCost.ACCTTYPE_P_Asset, as);
if (product.isService())
assets = line.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
//post roll-up
fl = fact.createLine(line,
line.getAccount(ProductCost.ACCTTYPE_P_Asset, as),
fl = fact.createLine(line, assets,
as.getC_Currency_ID(), bomCost.negate().setScale(stdPrecision, RoundingMode.HALF_UP));
if (fl == null)
{
Expand Down Expand Up @@ -415,8 +418,10 @@ else if (MAcctSchema.COSTINGMETHOD_StandardCosting.equals(costingMethod))
{
factLineAmt = bomCost.negate();
}
fl = fact.createLine(line,
line.getAccount(ProductCost.ACCTTYPE_P_Asset, as),
MAccount assets = line.getAccount(ProductCost.ACCTTYPE_P_Asset, as);
if (product.isService())
assets = line.getAccount(ProductCost.ACCTTYPE_P_Expense, as);
fl = fact.createLine(line, assets,
as.getC_Currency_ID(), factLineAmt.setScale(stdPrecision, RoundingMode.HALF_UP));
if (fl == null)
{
Expand Down
4 changes: 2 additions & 2 deletions org.adempiere.base/src/org/compiere/model/MProduct.java
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ public boolean isItem()
@Override
public boolean isStocked ()
{
return super.isStocked() && isItem();
return super.isStocked() && (isItem() || PRODUCTTYPE_ExpenseType.equals(getProductType()));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please change the javadoc accordingly

} // isStocked

/**
Expand Down Expand Up @@ -698,7 +698,7 @@ protected boolean beforeSave (boolean newRecord)

// Reset Stocked if not Item
//AZ Goodwill: Bug Fix isStocked always return false
if (!PRODUCTTYPE_Item.equals(getProductType()))
if (!PRODUCTTYPE_Item.equals(getProductType()) && !PRODUCTTYPE_ExpenseType.equals(getProductType()))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please change the comment too.

Also, please check line 666 of MProduct, there is a validation and storage managing code when changing from Item to not-Item, not sure about the effect, probably changing from Item to Expense doesn't matter now if the Stocked flag is maintained.

Line 918 (beforeDelete) has also a validation about storage

setIsStocked(false);

// UOM reset
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ public String createTransactions(Timestamp date, boolean mustBeStocked) {
MProduct prod = new MProduct(getCtx(), getM_Product_ID(), get_TrxName());
if (log.isLoggable(Level.FINE))log.log(Level.FINE,"Loaded Product " + prod.toString());

if ( !prod.isStocked() || prod.getProductType().compareTo(MProduct.PRODUCTTYPE_Item ) != 0 ) {
if ( !prod.isStocked()) {
// no need to do any movements
if (log.isLoggable(Level.FINE))log.log(Level.FINE, "Production Line " + getLine() + " does not require stock movement");
return "";
Expand Down