From 9e43a3686254f52d4680f8e410e45c1c57d01fdc Mon Sep 17 00:00:00 2001 From: hengsin Date: Thu, 12 May 2022 00:39:58 +0800 Subject: [PATCH] IDEMPIERE-5260 Enhance Discount Schema for Fixed Pricing (#1313) * IDEMPIERE-5260 Enhance Discount Schema for Fixed Pricing * IDEMPIERE-5260 Enhance Discount Schema for Fixed Pricing - Fix unit test error. --- .../oracle/202204280337_IDEMPIERE-5260.sql | 38 +++++ .../202204280337_IDEMPIERE-5260.sql | 35 +++++ .../model/I_M_DiscountSchemaBreak.java | 23 ++- .../org/compiere/model/MDiscountSchema.java | 77 +++++++++- .../compiere/model/MDiscountSchemaBreak.java | 5 + .../model/X_M_DiscountSchemaBreak.java | 23 ++- .../test/model/MDiscountSchemaTest.java | 145 ++++++++++++++++++ 7 files changed, 334 insertions(+), 12 deletions(-) create mode 100644 migration/iD10/oracle/202204280337_IDEMPIERE-5260.sql create mode 100644 migration/iD10/postgresql/202204280337_IDEMPIERE-5260.sql create mode 100644 org.idempiere.test/src/org/idempiere/test/model/MDiscountSchemaTest.java diff --git a/migration/iD10/oracle/202204280337_IDEMPIERE-5260.sql b/migration/iD10/oracle/202204280337_IDEMPIERE-5260.sql new file mode 100644 index 0000000000..22ed1460b9 --- /dev/null +++ b/migration/iD10/oracle/202204280337_IDEMPIERE-5260.sql @@ -0,0 +1,38 @@ +SELECT register_migration_script('202204280337_IDEMPIERE-5260.sql') FROM dual +; + +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- Apr 27, 2022 6:33:58 PM GMT+08:00 +INSERT INTO AD_Element (AD_Element_ID,ColumnName,Updated,Name,Description,PrintName,AD_Element_UU,IsActive,Created,AD_Org_ID,CreatedBy,UpdatedBy,AD_Client_ID,EntityType) VALUES (203079,'FixedPrice',TO_DATE('2022-04-27 18:33:57','YYYY-MM-DD HH24:MI:SS'),'Fixed Price','Fixed Price for Product','Fixed Price','9b4054b1-0202-4025-92a1-0778028c124e','Y',TO_DATE('2022-04-27 18:33:57','YYYY-MM-DD HH24:MI:SS'),0,100,100,0,'D') +; + +-- Apr 27, 2022 6:35:29 PM GMT+08:00 +INSERT INTO AD_Column (AD_Column_ID,SeqNoSelection,IsSyncDatabase,Version,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsParent,FieldLength,IsSelectionColumn,IsKey,IsAutocomplete,IsAllowLogging,AD_Column_UU,Updated,IsUpdateable,ColumnName,Description,Name,IsAllowCopy,IsActive,CreatedBy,UpdatedBy,IsAlwaysUpdateable,AD_Client_ID,AD_Org_ID,Created,EntityType,IsEncrypted,IsSecure,FKConstraintType,AD_Element_ID,AD_Table_ID,AD_Reference_ID,IsToolbarButton) VALUES (213025,0,'N',0,'N','N','N',0,'N',10,'N','N','N','Y','670c6edf-b9f2-4a6f-9dd4-4af4daea32ac',TO_DATE('2022-04-27 18:35:28','YYYY-MM-DD HH24:MI:SS'),'Y','FixedPrice','Fixed Price for Product','Fixed Price','Y','Y',100,100,'N',0,0,TO_DATE('2022-04-27 18:35:28','YYYY-MM-DD HH24:MI:SS'),'D','N','N','N',203079,476,37,'N') +; + +-- Apr 27, 2022 6:35:37 PM GMT+08:00 +ALTER TABLE M_DiscountSchemaBreak ADD FixedPrice NUMBER DEFAULT 0 +; + +-- Apr 27, 2022 6:37:03 PM GMT+08:00 +INSERT INTO AD_Field (SortNo,AD_Field_ID,IsEncrypted,DisplayLength,IsSameLine,IsHeading,SeqNo,IsCentrallyMaintained,IsReadOnly,AD_Org_ID,Updated,Description,Name,AD_Field_UU,IsDisplayed,IsFieldOnly,CreatedBy,UpdatedBy,IsActive,IsDisplayedGrid,SeqNoGrid,XPosition,IsQuickEntry,AD_Client_ID,Created,ColumnSpan,NumLines,IsAdvancedField,IsDefaultFocus,AD_Column_ID,EntityType,AD_Tab_ID) VALUES (0,204441,'N',0,'N','N',110,'Y','N',0,TO_DATE('2022-04-27 18:37:02','YYYY-MM-DD HH24:MI:SS'),'Fixed Price for Product','Fixed Price','d1c77e14-5d3d-4b0f-97f3-b800db7063b4','Y','N',100,100,'Y','Y',110,1,'N',0,TO_DATE('2022-04-27 18:37:02','YYYY-MM-DD HH24:MI:SS'),2,1,'N','N',213025,'D',406) +; + +-- Apr 27, 2022 6:37:59 PM GMT+08:00 +UPDATE AD_Field SET SeqNo=100, AD_Val_Rule_ID=NULL, IsDisplayed='Y', XPosition=1, AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2022-04-27 18:37:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=5279 +; + +-- Apr 27, 2022 6:39:22 PM GMT+08:00 +UPDATE AD_Field SET DisplayLogic='@IsBPartnerFlatDiscount@=N&@FixedPrice@=0', AD_Val_Rule_ID=NULL, AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2022-04-27 18:39:22','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=5279 +; + +-- Apr 27, 2022 6:40:12 PM GMT+08:00 +UPDATE AD_Field SET DisplayLogic='@IsBPartnerFlatDiscount@=N&@BreakDiscount@=0', AD_Val_Rule_ID=NULL, AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2022-04-27 18:40:12','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=204441 +; + +-- Apr 27, 2022 6:40:25 PM GMT+08:00 +UPDATE AD_Column SET DefaultValue='0',Updated=TO_DATE('2022-04-27 18:40:25','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=213025 +; + diff --git a/migration/iD10/postgresql/202204280337_IDEMPIERE-5260.sql b/migration/iD10/postgresql/202204280337_IDEMPIERE-5260.sql new file mode 100644 index 0000000000..ae17d55afc --- /dev/null +++ b/migration/iD10/postgresql/202204280337_IDEMPIERE-5260.sql @@ -0,0 +1,35 @@ +SELECT register_migration_script('202204280337_IDEMPIERE-5260.sql') FROM dual +; + +-- Apr 27, 2022 6:33:58 PM GMT+08:00 +INSERT INTO AD_Element (AD_Element_ID,ColumnName,Updated,Name,Description,PrintName,AD_Element_UU,IsActive,Created,AD_Org_ID,CreatedBy,UpdatedBy,AD_Client_ID,EntityType) VALUES (203079,'FixedPrice',TO_TIMESTAMP('2022-04-27 18:33:57','YYYY-MM-DD HH24:MI:SS'),'Fixed Price','Fixed Price for Product','Fixed Price','9b4054b1-0202-4025-92a1-0778028c124e','Y',TO_TIMESTAMP('2022-04-27 18:33:57','YYYY-MM-DD HH24:MI:SS'),0,100,100,0,'D') +; + +-- Apr 27, 2022 6:35:29 PM GMT+08:00 +INSERT INTO AD_Column (AD_Column_ID,SeqNoSelection,IsSyncDatabase,Version,IsMandatory,IsTranslated,IsIdentifier,SeqNo,IsParent,FieldLength,IsSelectionColumn,IsKey,IsAutocomplete,IsAllowLogging,AD_Column_UU,Updated,IsUpdateable,ColumnName,Description,Name,IsAllowCopy,IsActive,CreatedBy,UpdatedBy,IsAlwaysUpdateable,AD_Client_ID,AD_Org_ID,Created,EntityType,IsEncrypted,IsSecure,FKConstraintType,AD_Element_ID,AD_Table_ID,AD_Reference_ID,IsToolbarButton) VALUES (213025,0,'N',0,'N','N','N',0,'N',10,'N','N','N','Y','670c6edf-b9f2-4a6f-9dd4-4af4daea32ac',TO_TIMESTAMP('2022-04-27 18:35:28','YYYY-MM-DD HH24:MI:SS'),'Y','FixedPrice','Fixed Price for Product','Fixed Price','Y','Y',100,100,'N',0,0,TO_TIMESTAMP('2022-04-27 18:35:28','YYYY-MM-DD HH24:MI:SS'),'D','N','N','N',203079,476,37,'N') +; + +-- Apr 27, 2022 6:35:37 PM GMT+08:00 +ALTER TABLE M_DiscountSchemaBreak ADD COLUMN FixedPrice NUMERIC DEFAULT 0 +; + +-- Apr 27, 2022 6:37:03 PM GMT+08:00 +INSERT INTO AD_Field (SortNo,AD_Field_ID,IsEncrypted,DisplayLength,IsSameLine,IsHeading,SeqNo,IsCentrallyMaintained,IsReadOnly,AD_Org_ID,Updated,Description,Name,AD_Field_UU,IsDisplayed,IsFieldOnly,CreatedBy,UpdatedBy,IsActive,IsDisplayedGrid,SeqNoGrid,XPosition,IsQuickEntry,AD_Client_ID,Created,ColumnSpan,NumLines,IsAdvancedField,IsDefaultFocus,AD_Column_ID,EntityType,AD_Tab_ID) VALUES (0,204441,'N',0,'N','N',110,'Y','N',0,TO_TIMESTAMP('2022-04-27 18:37:02','YYYY-MM-DD HH24:MI:SS'),'Fixed Price for Product','Fixed Price','d1c77e14-5d3d-4b0f-97f3-b800db7063b4','Y','N',100,100,'Y','Y',110,1,'N',0,TO_TIMESTAMP('2022-04-27 18:37:02','YYYY-MM-DD HH24:MI:SS'),2,1,'N','N',213025,'D',406) +; + +-- Apr 27, 2022 6:37:59 PM GMT+08:00 +UPDATE AD_Field SET SeqNo=100, AD_Val_Rule_ID=NULL, IsDisplayed='Y', XPosition=1, AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2022-04-27 18:37:59','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=5279 +; + +-- Apr 27, 2022 6:39:22 PM GMT+08:00 +UPDATE AD_Field SET DisplayLogic='@IsBPartnerFlatDiscount@=N&@FixedPrice@=0', AD_Val_Rule_ID=NULL, AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2022-04-27 18:39:22','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=5279 +; + +-- Apr 27, 2022 6:40:12 PM GMT+08:00 +UPDATE AD_Field SET DisplayLogic='@IsBPartnerFlatDiscount@=N&@BreakDiscount@=0', AD_Val_Rule_ID=NULL, AD_Reference_Value_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2022-04-27 18:40:12','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=204441 +; + +-- Apr 27, 2022 6:40:25 PM GMT+08:00 +UPDATE AD_Column SET DefaultValue='0',Updated=TO_TIMESTAMP('2022-04-27 18:40:25','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Column_ID=213025 +; + diff --git a/org.adempiere.base/src/org/compiere/model/I_M_DiscountSchemaBreak.java b/org.adempiere.base/src/org/compiere/model/I_M_DiscountSchemaBreak.java index 42387dec1c..518f6604a2 100644 --- a/org.adempiere.base/src/org/compiere/model/I_M_DiscountSchemaBreak.java +++ b/org.adempiere.base/src/org/compiere/model/I_M_DiscountSchemaBreak.java @@ -22,7 +22,7 @@ import org.compiere.util.KeyNamePair; /** Generated Interface for M_DiscountSchemaBreak * @author iDempiere (generated) - * @version Release 9 + * @version Release 10 */ public interface I_M_DiscountSchemaBreak { @@ -44,8 +44,8 @@ public interface I_M_DiscountSchemaBreak /** Column name AD_Client_ID */ public static final String COLUMNNAME_AD_Client_ID = "AD_Client_ID"; - /** Get Client. - * Client/Tenant for this installation. + /** Get Tenant. + * Tenant for this installation. */ public int getAD_Client_ID(); @@ -53,12 +53,12 @@ public interface I_M_DiscountSchemaBreak public static final String COLUMNNAME_AD_Org_ID = "AD_Org_ID"; /** Set Organization. - * Organizational entity within client + * Organizational entity within tenant */ public void setAD_Org_ID (int AD_Org_ID); /** Get Organization. - * Organizational entity within client + * Organizational entity within tenant */ public int getAD_Org_ID(); @@ -104,6 +104,19 @@ public interface I_M_DiscountSchemaBreak */ public int getCreatedBy(); + /** Column name FixedPrice */ + public static final String COLUMNNAME_FixedPrice = "FixedPrice"; + + /** Set Fixed Price. + * Fixed Price for Product + */ + public void setFixedPrice (BigDecimal FixedPrice); + + /** Get Fixed Price. + * Fixed Price for Product + */ + public BigDecimal getFixedPrice(); + /** Column name IsActive */ public static final String COLUMNNAME_IsActive = "IsActive"; diff --git a/org.adempiere.base/src/org/compiere/model/MDiscountSchema.java b/org.adempiere.base/src/org/compiere/model/MDiscountSchema.java index 05e4fcb4b5..3ac42af83c 100644 --- a/org.adempiere.base/src/org/compiere/model/MDiscountSchema.java +++ b/org.adempiere.base/src/org/compiere/model/MDiscountSchema.java @@ -255,16 +255,33 @@ public class MDiscountSchema extends X_M_DiscountSchema implements ImmutablePOSu M_Product_ID, M_Product_Category_ID, BPartnerFlatDiscount); // nothing to calculate if (discount == null || discount.signum() == 0) - return Price; + { + BigDecimal fixedPrice = calculateFixedPrice(Qty, Price, M_Product_ID, M_Product_Category_ID); + if (fixedPrice != null) + return fixedPrice; + else + return Price; + } // - BigDecimal onehundred = Env.ONEHUNDRED; - BigDecimal multiplier = (onehundred).subtract(discount); - multiplier = multiplier.divide(onehundred, 6, RoundingMode.HALF_UP); - BigDecimal newPrice = Price.multiply(multiplier); + BigDecimal newPrice = calculateDiscountedPrice(Price, discount); if (log.isLoggable(Level.FINE)) log.fine("=>" + newPrice); return newPrice; } // calculatePrice + /** + * + * @param price input price + * @param discount discount percentage, for e.g 5.00 for 5% + * @return discounted price + */ + public static BigDecimal calculateDiscountedPrice(BigDecimal price, BigDecimal discount) { + BigDecimal onehundred = Env.ONEHUNDRED; + BigDecimal multiplier = (onehundred).subtract(discount); + multiplier = multiplier.divide(onehundred, 6, RoundingMode.HALF_UP); + BigDecimal newPrice = price.multiply(multiplier); + return newPrice; + } + /** * Calculate Discount Percentage * @param Qty quantity @@ -342,6 +359,56 @@ public class MDiscountSchema extends X_M_DiscountSchema implements ImmutablePOSu return Env.ZERO; } // calculateDiscount + /** + * Get fix discounted price + * @param Qty quantity + * @param Price price + * @param M_Product_ID product + * @param M_Product_Category_ID category + * @return fix discounted price or zero + */ + private BigDecimal calculateFixedPrice (BigDecimal Qty, BigDecimal Price, + int M_Product_ID, int M_Product_Category_ID) + { + if (DISCOUNTTYPE_FlatPercent.equals(getDiscountType()) || DISCOUNTTYPE_Formula.equals(getDiscountType()) + || DISCOUNTTYPE_Pricelist.equals(getDiscountType())) + { + return null; + } + + // Price Breaks + getBreaks(false); + BigDecimal Amt = Price.multiply(Qty); + for (int i = 0; i < m_breaks.length; i++) + { + MDiscountSchemaBreak br = m_breaks[i]; + if (!br.isActive()) + continue; + + if (isQuantityBased()) + { + if (!br.applies(Qty, M_Product_ID, M_Product_Category_ID)) + continue; + } + else + { + if (!br.applies(Amt, M_Product_ID, M_Product_Category_ID)) + continue; + } + + // Line applies + if (!br.isBPartnerFlatDiscount()) + { + if (br.getFixedPrice() != null && br.getFixedPrice().signum() > 0) + { + return br.getFixedPrice(); + } + } + return null; + } // for all breaks + + return null; + } // calculateDiscount /** * Before Save diff --git a/org.adempiere.base/src/org/compiere/model/MDiscountSchemaBreak.java b/org.adempiere.base/src/org/compiere/model/MDiscountSchemaBreak.java index 9da6854846..1d422f81cb 100644 --- a/org.adempiere.base/src/org/compiere/model/MDiscountSchemaBreak.java +++ b/org.adempiere.base/src/org/compiere/model/MDiscountSchemaBreak.java @@ -150,9 +150,14 @@ public class MDiscountSchemaBreak extends X_M_DiscountSchemaBreak implements Imm sb.append(",M_Product_ID=").append(getM_Product_ID()); sb.append(",Break=").append(getBreakValue()); if (isBPartnerFlatDiscount()) + { sb.append(",FlatDiscount"); + } else + { sb.append(",Discount=").append(getBreakDiscount()); + sb.append(",FixedPrice=").append(getFixedPrice()); + } sb.append ("]"); return sb.toString (); } // toString diff --git a/org.adempiere.base/src/org/compiere/model/X_M_DiscountSchemaBreak.java b/org.adempiere.base/src/org/compiere/model/X_M_DiscountSchemaBreak.java index 69c335f1e7..12cf6e5b7b 100644 --- a/org.adempiere.base/src/org/compiere/model/X_M_DiscountSchemaBreak.java +++ b/org.adempiere.base/src/org/compiere/model/X_M_DiscountSchemaBreak.java @@ -25,7 +25,7 @@ import org.compiere.util.KeyNamePair; /** Generated Model for M_DiscountSchemaBreak * @author iDempiere (generated) - * @version Release 9 - $Id$ */ + * @version Release 10 - $Id$ */ @org.adempiere.base.Model(table="M_DiscountSchemaBreak") public class X_M_DiscountSchemaBreak extends PO implements I_M_DiscountSchemaBreak, I_Persistent { @@ -33,7 +33,7 @@ public class X_M_DiscountSchemaBreak extends PO implements I_M_DiscountSchemaBre /** * */ - private static final long serialVersionUID = 20220116L; + private static final long serialVersionUID = 20220428L; /** Standard Constructor */ public X_M_DiscountSchemaBreak (Properties ctx, int M_DiscountSchemaBreak_ID, String trxName) @@ -135,6 +135,25 @@ public class X_M_DiscountSchemaBreak extends PO implements I_M_DiscountSchemaBre return bd; } + /** Set Fixed Price. + @param FixedPrice Fixed Price for Product + */ + public void setFixedPrice (BigDecimal FixedPrice) + { + set_Value (COLUMNNAME_FixedPrice, FixedPrice); + } + + /** Get Fixed Price. + @return Fixed Price for Product + */ + public BigDecimal getFixedPrice() + { + BigDecimal bd = (BigDecimal)get_Value(COLUMNNAME_FixedPrice); + if (bd == null) + return Env.ZERO; + return bd; + } + /** Set B.Partner Flat Discount. @param IsBPartnerFlatDiscount Use flat discount defined on Business Partner Level */ diff --git a/org.idempiere.test/src/org/idempiere/test/model/MDiscountSchemaTest.java b/org.idempiere.test/src/org/idempiere/test/model/MDiscountSchemaTest.java new file mode 100644 index 0000000000..e033442663 --- /dev/null +++ b/org.idempiere.test/src/org/idempiere/test/model/MDiscountSchemaTest.java @@ -0,0 +1,145 @@ +/*********************************************************************** + * This file is part of iDempiere ERP Open Source * + * http://www.idempiere.org * + * * + * Copyright (C) Contributors * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * 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., 51 Franklin Street, Fifth Floor, Boston, * + * MA 02110-1301, USA. * + * * + * Contributors: * + * - hengsin * + **********************************************************************/ +package org.idempiere.test.model; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.sql.Timestamp; + +import org.compiere.model.MBPartner; +import org.compiere.model.MDiscountSchema; +import org.compiere.model.MDiscountSchemaBreak; +import org.compiere.model.MOrder; +import org.compiere.model.MOrderLine; +import org.compiere.model.MPriceList; +import org.compiere.model.MPriceListVersion; +import org.compiere.model.MProduct; +import org.compiere.model.MProductPrice; +import org.compiere.process.DocAction; +import org.compiere.util.CacheMgt; +import org.compiere.util.Env; +import org.compiere.util.TimeUtil; +import org.idempiere.test.AbstractTestCase; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Test; + +/** + * + * @author hengsin + * + */ +public class MDiscountSchemaTest extends AbstractTestCase { + + private static final int FIVE_PERCENT_IF_100_ID=102; + private static final int PRODUCT_MULCH_ID = 137; + private static final int BP_JOE_BLOCK_ID = 118; + + public MDiscountSchemaTest() { + } + + @Test + @Order(1) + public void testPercentageDiscount() { + MOrder order = new MOrder(Env.getCtx(), 0, getTrxName()); + //Joe Block + order.setBPartner(MBPartner.get(Env.getCtx(), BP_JOE_BLOCK_ID)); + order.setC_DocTypeTarget_ID(MOrder.DocSubTypeSO_Standard); + order.setDeliveryRule(MOrder.DELIVERYRULE_CompleteOrder); + order.setDocStatus(DocAction.STATUS_Drafted); + order.setDocAction(DocAction.ACTION_Complete); + Timestamp today = TimeUtil.getDay(System.currentTimeMillis()); + order.setDatePromised(today); + order.saveEx(); + + MOrderLine line1 = new MOrderLine(order); + line1.setLine(10); + //Azalea Bush + line1.setProduct(MProduct.get(Env.getCtx(), PRODUCT_MULCH_ID)); + line1.setQty(new BigDecimal("100")); + line1.setDatePromised(today); + line1.saveEx(); + + MDiscountSchema schema = new MDiscountSchema(Env.getCtx(), FIVE_PERCENT_IF_100_ID, getTrxName()); + MDiscountSchemaBreak[] breaks = schema.getBreaks(false); + assertTrue(breaks.length > 0, "No discount schema breaks"); + + MPriceList priceList = MPriceList.get(order.getM_PriceList_ID()); + MPriceListVersion priceListVersion = priceList.getPriceListVersion(order.getDateOrdered()); + MProductPrice[] productPrice = priceListVersion.getProductPrice(" AND M_Product_ID="+PRODUCT_MULCH_ID); + assertEquals(1, productPrice.length, "Unexpected number of ProductPrice record"); + BigDecimal discounted = MDiscountSchema.calculateDiscountedPrice(productPrice[0].getPriceStd(), breaks[0].getBreakDiscount()); + assertEquals(discounted.setScale(2, RoundingMode.HALF_UP), line1.getPriceActual().setScale(2, RoundingMode.HALF_UP), "Unexpected Order Line price"); + } + + @Test + @Order(2) + public void testFixedPriceDiscount() { + BigDecimal fixedPrice = new BigDecimal("1.00"); + MDiscountSchema schema = new MDiscountSchema(Env.getCtx(), FIVE_PERCENT_IF_100_ID, getTrxName()); + MDiscountSchemaBreak discountBreak = null; + + try { + discountBreak = new MDiscountSchemaBreak(Env.getCtx(), 0, null); + discountBreak.setM_DiscountSchema_ID(schema.getM_DiscountSchema_ID()); + discountBreak.setBreakDiscount(new BigDecimal("0.00")); + discountBreak.setBreakValue(new BigDecimal("10")); + discountBreak.setFixedPrice(fixedPrice); + discountBreak.setM_Product_ID(PRODUCT_MULCH_ID); + discountBreak.setIsBPartnerFlatDiscount(false); + discountBreak.setIsActive(true); + discountBreak.setSeqNo(20); + discountBreak.saveEx(); + + CacheMgt.get().reset(MDiscountSchema.Table_Name, schema.get_ID()); + + MOrder order = new MOrder(Env.getCtx(), 0, getTrxName()); + //Joe Block + order.setBPartner(MBPartner.get(Env.getCtx(), BP_JOE_BLOCK_ID)); + order.setC_DocTypeTarget_ID(MOrder.DocSubTypeSO_Standard); + order.setDeliveryRule(MOrder.DELIVERYRULE_CompleteOrder); + order.setDocStatus(DocAction.STATUS_Drafted); + order.setDocAction(DocAction.ACTION_Complete); + Timestamp today = TimeUtil.getDay(System.currentTimeMillis()); + order.setDatePromised(today); + order.saveEx(); + + MOrderLine line1 = new MOrderLine(order); + line1.setLine(10); + //Azalea Bush + line1.setProduct(MProduct.get(Env.getCtx(), PRODUCT_MULCH_ID)); + line1.setQty(new BigDecimal("10")); + line1.setDatePromised(today); + line1.saveEx(); + + assertEquals(fixedPrice, line1.getPriceActual().setScale(2, RoundingMode.HALF_UP), "Unexpected Order Line price"); + } finally { + if (discountBreak != null && discountBreak.get_ID() > 0) + discountBreak.deleteEx(true); + } + } +}