diff --git a/migration/i1.0a-release/oracle/201303061816_TICKET-1002354.sql b/migration/i1.0a-release/oracle/201303061816_TICKET-1002354.sql new file mode 100644 index 0000000000..bdcf041bf7 --- /dev/null +++ b/migration/i1.0a-release/oracle/201303061816_TICKET-1002354.sql @@ -0,0 +1,22 @@ +-- Mar 6, 2013 5:52:10 PM SGT +-- Ticket 1002354: Price List Enhancement +INSERT INTO AD_Ref_List (AD_Client_ID,AD_Ref_List_ID,AD_Reference_ID,EntityType,Name,AD_Ref_List_UU,Value,CreatedBy,Created,Updated,UpdatedBy,IsActive,AD_Org_ID) VALUES (0,200134,194,'D','Product Cost','ee848c2c-1648-441e-a33a-c064e6fb0203','P',100,TO_DATE('2013-03-06 17:52:08','YYYY-MM-DD HH24:MI:SS'),TO_DATE('2013-03-06 17:52:08','YYYY-MM-DD HH24:MI:SS'),100,'Y',0) +; + +-- Mar 6, 2013 5:52:11 PM SGT +-- Ticket 1002354: Price List Enhancement +INSERT INTO AD_Ref_List_Trl (AD_Language,AD_Ref_List_ID, Description,Name, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy,AD_Ref_List_Trl_UU ) SELECT l.AD_Language,t.AD_Ref_List_ID, t.Description,t.Name, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy,Generate_UUID() FROM AD_Language l, AD_Ref_List t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Ref_List_ID=200134 AND NOT EXISTS (SELECT * FROM AD_Ref_List_Trl tt WHERE tt.AD_Language=l.AD_Language AND tt.AD_Ref_List_ID=t.AD_Ref_List_ID) +; + +-- Mar 6, 2013 7:08:02 PM SGT +-- Ticket 1002354: Price List Enhancement +INSERT INTO AD_ModelValidator (SeqNo,AD_ModelValidator_ID,Help,ModelValidationClass,EntityType,Description,Name,AD_ModelValidator_UU,AD_Client_ID,AD_Org_ID,Created,CreatedBy,Updated,UpdatedBy,IsActive) VALUES (0,200002,'Auto sync corresponding price list with the base price list','org.adempiere.model.ProductPriceValidator','D','Product Price','Model Validator to Product Price','cc9a0a8e-8749-45be-a38d-61e9e61aab3d',0,0,TO_DATE('2013-03-06 19:07:59','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2013-03-06 19:07:59','YYYY-MM-DD HH24:MI:SS'),100,'N') +; + +-- Mar 6, 2013 7:08:42 PM SGT +-- Ticket 1002354: Price List Enhancement +UPDATE AD_ModelValidator SET SeqNo=1,Updated=TO_DATE('2013-03-06 19:08:42','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_ModelValidator_ID=200002 +; + +SELECT register_migration_script('201303061816_TICKET-1002354.sql') FROM dual +; diff --git a/migration/i1.0a-release/oracle/201303071224_IDEMPIERE-704.sql b/migration/i1.0a-release/oracle/201303071224_IDEMPIERE-704.sql new file mode 100644 index 0000000000..a80072eaac --- /dev/null +++ b/migration/i1.0a-release/oracle/201303071224_IDEMPIERE-704.sql @@ -0,0 +1,23 @@ +-- Mar 7, 2013 8:21:59 PM MYT +-- IDEMPIERE-704 The Min. value and Max. value validation of column is not working +INSERT INTO AD_Message (MsgType,MsgText,AD_Message_ID,EntityType,AD_Message_UU,Value,IsActive,Updated,CreatedBy,UpdatedBy,AD_Client_ID,AD_Org_ID,Created) VALUES ('E','Entered value is more than the maximum ({0}) allowed',200150,'D','af92320e-f5a9-4dee-a1d4-3bfa8bbf3dbd','MoreThanMaxValue','Y',TO_DATE('2013-03-07 20:21:57','YYYY-MM-DD HH24:MI:SS'),100,100,0,0,TO_DATE('2013-03-07 20:21:57','YYYY-MM-DD HH24:MI:SS')) +; + +-- Mar 7, 2013 8:21:59 PM MYT +-- IDEMPIERE-704 The Min. value and Max. value validation of column is not working +INSERT INTO AD_Message_Trl (AD_Language,AD_Message_ID, MsgText,MsgTip, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy,AD_Message_Trl_UU ) SELECT l.AD_Language,t.AD_Message_ID, t.MsgText,t.MsgTip, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy,Generate_UUID() FROM AD_Language l, AD_Message t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Message_ID=200150 AND NOT EXISTS (SELECT * FROM AD_Message_Trl tt WHERE tt.AD_Language=l.AD_Language AND tt.AD_Message_ID=t.AD_Message_ID) +; + +-- Mar 7, 2013 8:22:22 PM MYT +-- IDEMPIERE-704 The Min. value and Max. value validation of column is not working +INSERT INTO AD_Message (MsgType,MsgText,AD_Message_ID,EntityType,AD_Message_UU,Value,IsActive,Updated,CreatedBy,UpdatedBy,AD_Client_ID,AD_Org_ID,Created) VALUES ('E','Entered value is less than the minimum ({0}) required',200151,'D','4402e2b3-803e-4bd2-b77c-86059fe10346','LessThanMinValue','Y',TO_DATE('2013-03-07 20:22:21','YYYY-MM-DD HH24:MI:SS'),100,100,0,0,TO_DATE('2013-03-07 20:22:21','YYYY-MM-DD HH24:MI:SS')) +; + +-- Mar 7, 2013 8:22:22 PM MYT +-- IDEMPIERE-704 The Min. value and Max. value validation of column is not working +INSERT INTO AD_Message_Trl (AD_Language,AD_Message_ID, MsgText,MsgTip, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy,AD_Message_Trl_UU ) SELECT l.AD_Language,t.AD_Message_ID, t.MsgText,t.MsgTip, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy,Generate_UUID() FROM AD_Language l, AD_Message t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Message_ID=200151 AND NOT EXISTS (SELECT * FROM AD_Message_Trl tt WHERE tt.AD_Language=l.AD_Language AND tt.AD_Message_ID=t.AD_Message_ID) +; + +SELECT register_migration_script('201303071224_IDEMPIERE-704.sql') FROM dual +; + diff --git a/migration/i1.0a-release/postgresql/201303061816_TICKET-1002354.sql b/migration/i1.0a-release/postgresql/201303061816_TICKET-1002354.sql new file mode 100644 index 0000000000..62bff2228a --- /dev/null +++ b/migration/i1.0a-release/postgresql/201303061816_TICKET-1002354.sql @@ -0,0 +1,22 @@ +-- Mar 6, 2013 5:52:10 PM SGT +-- Ticket 1002354: Price List Enhancement +INSERT INTO AD_Ref_List (AD_Client_ID,AD_Ref_List_ID,AD_Reference_ID,EntityType,Name,AD_Ref_List_UU,Value,CreatedBy,Created,Updated,UpdatedBy,IsActive,AD_Org_ID) VALUES (0,200134,194,'D','Product Cost','ee848c2c-1648-441e-a33a-c064e6fb0203','P',100,TO_TIMESTAMP('2013-03-06 17:52:08','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2013-03-06 17:52:08','YYYY-MM-DD HH24:MI:SS'),100,'Y',0) +; + +-- Mar 6, 2013 5:52:11 PM SGT +-- Ticket 1002354: Price List Enhancement +INSERT INTO AD_Ref_List_Trl (AD_Language,AD_Ref_List_ID, Description,Name, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy,AD_Ref_List_Trl_UU ) SELECT l.AD_Language,t.AD_Ref_List_ID, t.Description,t.Name, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy,Generate_UUID() FROM AD_Language l, AD_Ref_List t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Ref_List_ID=200134 AND NOT EXISTS (SELECT * FROM AD_Ref_List_Trl tt WHERE tt.AD_Language=l.AD_Language AND tt.AD_Ref_List_ID=t.AD_Ref_List_ID) +; + +-- Mar 6, 2013 7:08:02 PM SGT +-- Ticket 1002354: Price List Enhancement +INSERT INTO AD_ModelValidator (SeqNo,AD_ModelValidator_ID,Help,ModelValidationClass,EntityType,Description,Name,AD_ModelValidator_UU,AD_Client_ID,AD_Org_ID,Created,CreatedBy,Updated,UpdatedBy,IsActive) VALUES (0,200002,'Auto sync corresponding price list with the base price list','org.adempiere.model.ProductPriceValidator','D','Product Price','Model Validator to Product Price','cc9a0a8e-8749-45be-a38d-61e9e61aab3d',0,0,TO_TIMESTAMP('2013-03-06 19:07:59','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2013-03-06 19:07:59','YYYY-MM-DD HH24:MI:SS'),100,'N') +; + +-- Mar 6, 2013 7:08:42 PM SGT +-- Ticket 1002354: Price List Enhancement +UPDATE AD_ModelValidator SET SeqNo=1,Updated=TO_TIMESTAMP('2013-03-06 19:08:42','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_ModelValidator_ID=200002 +; + +SELECT register_migration_script('201303061816_TICKET-1002354.sql') FROM dual +; diff --git a/migration/i1.0a-release/postgresql/201303071224_IDEMPIERE-704.sql b/migration/i1.0a-release/postgresql/201303071224_IDEMPIERE-704.sql new file mode 100644 index 0000000000..e3ef0ddf91 --- /dev/null +++ b/migration/i1.0a-release/postgresql/201303071224_IDEMPIERE-704.sql @@ -0,0 +1,23 @@ +-- Mar 7, 2013 8:21:59 PM MYT +-- IDEMPIERE-704 The Min. value and Max. value validation of column is not working +INSERT INTO AD_Message (MsgType,MsgText,AD_Message_ID,EntityType,AD_Message_UU,Value,IsActive,Updated,CreatedBy,UpdatedBy,AD_Client_ID,AD_Org_ID,Created) VALUES ('E','Entered value is more than the maximum ({0}) allowed',200150,'D','af92320e-f5a9-4dee-a1d4-3bfa8bbf3dbd','MoreThanMaxValue','Y',TO_TIMESTAMP('2013-03-07 20:21:57','YYYY-MM-DD HH24:MI:SS'),100,100,0,0,TO_TIMESTAMP('2013-03-07 20:21:57','YYYY-MM-DD HH24:MI:SS')) +; + +-- Mar 7, 2013 8:21:59 PM MYT +-- IDEMPIERE-704 The Min. value and Max. value validation of column is not working +INSERT INTO AD_Message_Trl (AD_Language,AD_Message_ID, MsgText,MsgTip, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy,AD_Message_Trl_UU ) SELECT l.AD_Language,t.AD_Message_ID, t.MsgText,t.MsgTip, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy,Generate_UUID() FROM AD_Language l, AD_Message t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Message_ID=200150 AND NOT EXISTS (SELECT * FROM AD_Message_Trl tt WHERE tt.AD_Language=l.AD_Language AND tt.AD_Message_ID=t.AD_Message_ID) +; + +-- Mar 7, 2013 8:22:22 PM MYT +-- IDEMPIERE-704 The Min. value and Max. value validation of column is not working +INSERT INTO AD_Message (MsgType,MsgText,AD_Message_ID,EntityType,AD_Message_UU,Value,IsActive,Updated,CreatedBy,UpdatedBy,AD_Client_ID,AD_Org_ID,Created) VALUES ('E','Entered value is less than the minimum ({0}) required',200151,'D','4402e2b3-803e-4bd2-b77c-86059fe10346','LessThanMinValue','Y',TO_TIMESTAMP('2013-03-07 20:22:21','YYYY-MM-DD HH24:MI:SS'),100,100,0,0,TO_TIMESTAMP('2013-03-07 20:22:21','YYYY-MM-DD HH24:MI:SS')) +; + +-- Mar 7, 2013 8:22:22 PM MYT +-- IDEMPIERE-704 The Min. value and Max. value validation of column is not working +INSERT INTO AD_Message_Trl (AD_Language,AD_Message_ID, MsgText,MsgTip, IsTranslated,AD_Client_ID,AD_Org_ID,Created,Createdby,Updated,UpdatedBy,AD_Message_Trl_UU ) SELECT l.AD_Language,t.AD_Message_ID, t.MsgText,t.MsgTip, 'N',t.AD_Client_ID,t.AD_Org_ID,t.Created,t.Createdby,t.Updated,t.UpdatedBy,Generate_UUID() FROM AD_Language l, AD_Message t WHERE l.IsActive='Y' AND l.IsSystemLanguage='Y' AND l.IsBaseLanguage='N' AND t.AD_Message_ID=200151 AND NOT EXISTS (SELECT * FROM AD_Message_Trl tt WHERE tt.AD_Language=l.AD_Language AND tt.AD_Message_ID=t.AD_Message_ID) +; + +SELECT register_migration_script('201303071224_IDEMPIERE-704.sql') FROM dual +; + diff --git a/org.adempiere.base.process/src/org/compiere/process/M_PriceList_Create.java b/org.adempiere.base.process/src/org/compiere/process/M_PriceList_Create.java index 352bbb82da..422d5f8b4a 100644 --- a/org.adempiere.base.process/src/org/compiere/process/M_PriceList_Create.java +++ b/org.adempiere.base.process/src/org/compiere/process/M_PriceList_Create.java @@ -19,6 +19,7 @@ package org.compiere.process; +import java.math.BigDecimal; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -27,6 +28,12 @@ import java.util.Iterator; import java.util.Vector; import java.util.logging.Level; +import org.compiere.model.MAcctSchema; +import org.compiere.model.MClientInfo; +import org.compiere.model.MDiscountSchemaLine; +import org.compiere.model.MProduct; +import org.compiere.model.MProductPrice; +import org.compiere.model.ProductCost; import org.compiere.util.AdempiereSystemError; import org.compiere.util.AdempiereUserError; import org.compiere.util.CLogger; @@ -613,6 +620,75 @@ public class M_PriceList_Create extends SvrProcess { raiseError("Update M_ProductPrice ", sqlupd.toString()); totu += cntu; if (log.isLoggable(Level.FINE)) log.fine("Updated " + cntu); + + /** + * Product Cost overwrite + * Elaine 2009/12/24 + */ + if(rsDiscountLine.getString(MDiscountSchemaLine.COLUMNNAME_List_Base).equals(MDiscountSchemaLine.LIST_BASE_ProductCost) || + rsDiscountLine.getString(MDiscountSchemaLine.COLUMNNAME_Std_Base).equals(MDiscountSchemaLine.STD_BASE_ProductCost) || + rsDiscountLine.getString(MDiscountSchemaLine.COLUMNNAME_Limit_Base).equals(MDiscountSchemaLine.LIMIT_BASE_ProductCost)) + { + MClientInfo m_clientInfo = MClientInfo.get(getCtx(), rsCurgen.getInt("AD_Client_ID"), get_TrxName()); + MAcctSchema as = new MAcctSchema(getCtx(), m_clientInfo.getC_AcctSchema1_ID(), get_TrxName()); + + StringBuilder sqlpc = new StringBuilder("SELECT p.M_Product_ID "); + sqlpc.append(" FROM M_ProductPrice p"); + sqlpc.append(" WHERE M_PriceList_Version_ID=").append(p_PriceList_Version_ID); + sqlpc.append(" AND EXISTS (SELECT * FROM T_Selection s"); + sqlpc.append(" WHERE s.T_Selection_ID=p.M_Product_ID"); + sqlpc.append(" AND s.AD_PInstance_ID=").append(m_AD_PInstance_ID + ")"); + + PreparedStatement ps = DB.prepareStatement(sqlpc.toString(), get_TrxName()); + ResultSet rs = ps.executeQuery(); + while(rs.next()) + { + int M_Product_ID = rs.getInt(MProductPrice.COLUMNNAME_M_Product_ID); + ProductCost m_productCost = new ProductCost (getCtx(), M_Product_ID, 0, get_TrxName()); + m_productCost.setQty(BigDecimal.ONE); + BigDecimal costs = m_productCost.getProductCosts(as, rsCurgen.getInt("AD_Org_ID"), null, 0, false); + + if (costs == null || costs.signum() == 0) // zero costs OK + { + MProduct product = new MProduct(getCtx(), M_Product_ID, get_TrxName()); + if (product.isStocked()) + log.log(Level.WARNING, "No Costs for " + product.getName()); + } + else + { + sqlupd = new StringBuilder("UPDATE M_ProductPrice p "); + sqlupd.append(" SET PriceList = (DECODE('").append(rsDiscountLine.getString(MDiscountSchemaLine.COLUMNNAME_List_Base)).append("', 'P', ?, PriceList) + ?) * (1 - ?/100), "); + sqlupd.append(" PriceStd = (DECODE('").append(rsDiscountLine.getString(MDiscountSchemaLine.COLUMNNAME_Std_Base)).append("', 'P', ?, PriceStd) + ?) * (1 - ?/100),"); + sqlupd.append(" PriceLimit = (DECODE('").append(rsDiscountLine.getString(MDiscountSchemaLine.COLUMNNAME_Limit_Base)).append("', 'P', ?, PriceLimit) + ?) * (1 - ?/100)"); + sqlupd.append(" WHERE M_PriceList_Version_ID=").append(p_PriceList_Version_ID); + sqlupd.append(" AND M_Product_ID = ?"); + sqlupd.append(" AND EXISTS (SELECT * FROM T_Selection s"); + sqlupd.append(" WHERE s.T_Selection_ID=p.M_Product_ID"); + sqlupd.append(" AND s.AD_PInstance_ID=").append(m_AD_PInstance_ID + ")"); + + pstmu = DB.prepareStatement(sqlupd.toString(), + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.CONCUR_UPDATABLE, get_TrxName()); + + pstmu.setBigDecimal(1, costs); + pstmu.setDouble(2, rsDiscountLine.getDouble(MDiscountSchemaLine.COLUMNNAME_List_AddAmt)); + pstmu.setDouble(3, rsDiscountLine.getDouble(MDiscountSchemaLine.COLUMNNAME_List_Discount)); + pstmu.setBigDecimal(4, costs); + pstmu.setDouble(5, rsDiscountLine.getDouble(MDiscountSchemaLine.COLUMNNAME_Std_AddAmt)); + pstmu.setDouble(6, rsDiscountLine.getDouble(MDiscountSchemaLine.COLUMNNAME_Std_Discount)); + pstmu.setBigDecimal(7, costs); + pstmu.setDouble(8, rsDiscountLine.getDouble(MDiscountSchemaLine.COLUMNNAME_Limit_AddAmt)); + pstmu.setDouble(9, rsDiscountLine.getDouble(MDiscountSchemaLine.COLUMNNAME_Limit_Discount)); + pstmu.setInt(10, M_Product_ID); + + cntu = pstmu.executeUpdate(); + + if (cntu == -1) + raiseError("Update M_ProductPrice ", sqlupd.toString()); + if (log.isLoggable(Level.FINE)) log.fine("Updated " + cntu); + } + } + } // //Rounding (AD_Reference_ID=155) diff --git a/org.adempiere.base/src/org/adempiere/model/ProductPriceValidator.java b/org.adempiere.base/src/org/adempiere/model/ProductPriceValidator.java new file mode 100644 index 0000000000..fad0de8a46 --- /dev/null +++ b/org.adempiere.base/src/org/adempiere/model/ProductPriceValidator.java @@ -0,0 +1,140 @@ +/****************************************************************************** + * Copyright (C) 2013 Elaine Tan * + * 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.model; + +import java.math.BigDecimal; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.logging.Level; + +import org.compiere.model.MClient; +import org.compiere.model.MPriceListVersion; +import org.compiere.model.MProductPrice; +import org.compiere.model.ModelValidationEngine; +import org.compiere.model.ModelValidator; +import org.compiere.model.PO; +import org.compiere.util.CLogger; +import org.compiere.util.DB; +import org.compiere.util.Env; + +/** + * Auto sync corresponding price list with the price list schema and base price list. + * @author Elaine + * + */ +public class ProductPriceValidator implements ModelValidator { + + private static CLogger log = CLogger.getCLogger(ProductPriceValidator.class); + private int m_AD_Client_ID; + + public int getAD_Client_ID() { + return m_AD_Client_ID; + } + + public void initialize(ModelValidationEngine engine, MClient client) { + engine.addModelChange(MProductPrice.Table_Name, this); + if (client != null) + m_AD_Client_ID = client.getAD_Client_ID(); + } + + public String login(int AD_Org_ID, int AD_Role_ID, int AD_User_ID) { + return null; + } + + public String modelChange(PO po, int type) throws Exception { + if (po instanceof MProductPrice) { + if (type == TYPE_AFTER_CHANGE || type == TYPE_AFTER_NEW || type == TYPE_AFTER_DELETE) { + MProductPrice pp = (MProductPrice) po; + + int M_PriceList_Version_ID = pp.getM_PriceList_Version_ID(); + if(M_PriceList_Version_ID > 0) + { + MPriceListVersion plv = new MPriceListVersion(Env.getCtx(), M_PriceList_Version_ID, null); + int M_Pricelist_Version_Base_ID = plv.getM_Pricelist_Version_Base_ID(); + + if(M_Pricelist_Version_Base_ID > 0) // base price list + { + int M_Product_ID = pp.getM_Product_ID(); + BigDecimal priceLimit = pp.getPriceLimit(); + BigDecimal priceList = pp.getPriceList(); + BigDecimal priceStd = pp.getPriceStd(); + boolean isActive = pp.isActive(); + + StringBuilder sql = new StringBuilder(); + sql.append("SELECT * FROM M_PriceList_Version "); + sql.append("WHERE IsActive = 'Y' AND AD_Client_ID = ? "); + sql.append("AND M_DiscountSchema_ID = ? "); // match price list schema + sql.append("AND M_Pricelist_Version_Base_ID = ? "); // match base price list + sql.append("AND M_PriceList_Version_ID <> ? "); + + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement(sql.toString(), po.get_TrxName()); + int count = 1; + pstmt.setInt(count++, Env.getAD_Client_ID(Env.getCtx())); + pstmt.setInt(count++, plv.getM_DiscountSchema_ID()); + pstmt.setInt(count++, M_Pricelist_Version_Base_ID); + pstmt.setInt(count++, M_PriceList_Version_ID); + + rs = pstmt.executeQuery(); + while (rs.next()) + { + MPriceListVersion plv1 = new MPriceListVersion(Env.getCtx(), rs, po.get_TrxName()); + MProductPrice pp1 = MProductPrice.get(Env.getCtx(), plv1.getM_PriceList_Version_ID(), M_Product_ID, po.get_TrxName()); + + if (type == TYPE_AFTER_CHANGE || type == TYPE_AFTER_NEW) + { + if(pp1 == null) + pp1 = new MProductPrice(Env.getCtx(), plv1.getM_PriceList_Version_ID(), M_Product_ID, po.get_TrxName()); + + if(priceList.compareTo(pp1.getPriceList()) != 0 + || priceStd.compareTo(pp1.getPriceStd()) != 0 + || priceLimit.compareTo(pp1.getPriceLimit()) != 0 + || isActive != pp1.isActive()) + { + pp1.setPrices(priceList, priceStd, priceLimit); + pp1.setIsActive(isActive); + pp1.save(po.get_TrxName()); + } + } + else if (type == TYPE_AFTER_DELETE) + { + if(pp1 != null) + pp1.delete(false, po.get_TrxName()); + } + } + } + catch (SQLException ex) + { + log.log(Level.SEVERE, sql.toString(), ex); + } + finally + { + DB.close(rs, pstmt); + rs = null; pstmt = null; + } + } + } + } + } + return null; + } + + public String docValidate(PO po, int timing) { + return null; + } +} \ No newline at end of file diff --git a/org.adempiere.base/src/org/compiere/model/GridTable.java b/org.adempiere.base/src/org/compiere/model/GridTable.java index d9a752639f..1c3aa68d9c 100644 --- a/org.adempiere.base/src/org/compiere/model/GridTable.java +++ b/org.adempiere.base/src/org/compiere/model/GridTable.java @@ -2121,7 +2121,24 @@ public class GridTable extends AbstractTableModel || ((value != null && dbValue != null && value.getClass().equals(byte[].class) && dbValue.getClass().equals(byte[].class)) && Arrays.equals((byte[])oldValue, (byte[])dbValue)) ) { - po.set_ValueNoCheck (columnName, value); + if (!po.set_ValueNoCheck (columnName, value)) + { + ValueNamePair lastError = CLogger.retrieveError(); + if (lastError != null) { + String adMessage = lastError.getValue(); + String adMessageArgument = lastError.getName().trim(); + + StringBuilder info = new StringBuilder(adMessageArgument); + + if (!adMessageArgument.endsWith(";")) info.append(";"); + info.append(field.getHeader()); + + fireDataStatusEEvent(adMessage, info.toString(), true); + } else { + fireDataStatusEEvent("Set value failed", field.getHeader(), true); + } + return SAVE_ERROR; + } } // Original != DB else diff --git a/org.adempiere.base/src/org/compiere/model/PO.java b/org.adempiere.base/src/org/compiere/model/PO.java index e0920ae018..c9f6fc9ece 100644 --- a/org.adempiere.base/src/org/compiere/model/PO.java +++ b/org.adempiere.base/src/org/compiere/model/PO.java @@ -683,6 +683,18 @@ public abstract class PO * @return true if value set */ protected final boolean set_Value (String ColumnName, Object value) + { + return set_Value(ColumnName, value, true); + } + + /************************************************************************** + * Set Value + * @param ColumnName column name + * @param value value + * @param checkWritable + * @return true if value set + */ + protected final boolean set_Value (String ColumnName, Object value, boolean checkWritable) { if (value instanceof String && ColumnName.equals("WhereClause") && value.toString().toUpperCase().indexOf("=NULL") != -1) @@ -692,6 +704,7 @@ public abstract class PO if (index < 0) { log.log(Level.SEVERE, "Column not found - " + ColumnName); + log.saveError("ColumnNotFound", "Column not found - " + ColumnName); return false; } if (ColumnName.endsWith("_ID") && value instanceof String ) @@ -705,7 +718,7 @@ public abstract class PO } } - return set_Value (index, value); + return set_Value (index, value, checkWritable); } // setValue /** @@ -727,6 +740,19 @@ public abstract class PO * @return true if value set */ protected final boolean set_Value (int index, Object value) + { + return set_Value(index, value, true); + } + + /** + * Set Value if updateable and correct class. + * (and to NULL if not mandatory) + * @param index index + * @param value value + * @param checkWritable + * @return true if value set + */ + protected final boolean set_Value (int index, Object value, boolean checkWritable) { if (index < 0 || index >= get_ColumnCount()) { @@ -736,26 +762,32 @@ public abstract class PO String ColumnName = p_info.getColumnName(index); String colInfo = " - " + ColumnName; // - if (p_info.isVirtualColumn(index)) + if (checkWritable) { - log.log(Level.WARNING, "Virtual Column" + colInfo); - return false; - } - - // - // globalqss -- Bug 1618469 - is throwing not updateable even on new records - // if (!p_info.isColumnUpdateable(index)) - if ( ( ! p_info.isColumnUpdateable(index) ) && ( ! is_new() ) ) - { - colInfo += " - NewValue=" + value + " - OldValue=" + get_Value(index); - log.log(Level.WARNING, "Column not updateable" + colInfo); - return false; + if (p_info.isVirtualColumn(index)) + { + log.log(Level.WARNING, "Virtual Column" + colInfo); + log.saveError("VirtualColumn", "Virtual Column" + colInfo); + return false; + } + + // + // globalqss -- Bug 1618469 - is throwing not updateable even on new records + // if (!p_info.isColumnUpdateable(index)) + if ( ( ! p_info.isColumnUpdateable(index) ) && ( ! is_new() ) ) + { + colInfo += " - NewValue=" + value + " - OldValue=" + get_Value(index); + log.log(Level.WARNING, "Column not updateable" + colInfo); + log.saveError("ColumnReadonly", "Column not updateable" + colInfo); + return false; + } } // if (value == null) { if (p_info.isColumnMandatory(index)) { + log.saveError("FillMandatory", ColumnName + " is mandatory."); throw new IllegalArgumentException (ColumnName + " is mandatory."); } m_newValues[index] = Null.NULL; // correct @@ -793,6 +825,9 @@ public abstract class PO log.log(Level.SEVERE, ColumnName + " - Class invalid: " + value.getClass().toString() + ", Should be " + p_info.getColumnClass(index).toString() + ": " + value); + log.saveError("WrongDataType", ColumnName + + " - Class invalid: " + value.getClass().toString() + + ", Should be " + p_info.getColumnClass(index).toString() + ": " + value); return false; } else @@ -800,6 +835,9 @@ public abstract class PO log.log(Level.SEVERE, ColumnName + " - Class invalid: " + value.getClass().toString() + ", Should be " + p_info.getColumnClass(index).toString() + ": " + value); + log.saveError("WrongDataType", ColumnName + + " - Class invalid: " + value.getClass().toString() + + ", Should be " + p_info.getColumnClass(index).toString() + ": " + value); return false; } // Validate (Min/Max) @@ -807,6 +845,12 @@ public abstract class PO if (error != null) { log.log(Level.WARNING, ColumnName + "=" + value + " - " + error); + int separatorIndex = error.indexOf(";"); + if (separatorIndex > 0) { + log.saveError(error.substring(0,separatorIndex), error.substring(separatorIndex+1)); + } else { + log.saveError(error, ColumnName); + } return false; } // Length for String @@ -831,6 +875,8 @@ public abstract class PO StringBuilder validValues = new StringBuilder(); for (ValueNamePair vp : MRefList.getList(getCtx(), p_info.getColumn(index).AD_Reference_Value_ID, false)) validValues.append(" - ").append(vp.getValue()); + log.saveError("Validate", ColumnName + " Invalid value - " + + value + " - Reference_ID=" + p_info.getColumn(index).AD_Reference_Value_ID + validValues.toString()); throw new IllegalArgumentException(ColumnName + " Invalid value - " + value + " - Reference_ID=" + p_info.getColumn(index).AD_Reference_Value_ID + validValues.toString()); } @@ -878,75 +924,7 @@ public abstract class PO */ public final boolean set_ValueNoCheck (String ColumnName, Object value) { - int index = get_ColumnIndex(ColumnName); - if (index < 0) - { - log.log(Level.SEVERE, "Column not found - " + ColumnName); - return false; - } - if (value == null) - m_newValues[index] = Null.NULL; // write direct - else - { - // matching class or generic object - if (value.getClass().equals(p_info.getColumnClass(index)) - || p_info.getColumnClass(index) == Object.class) - m_newValues[index] = value; // correct - // Integer can be set as BigDecimal - else if (value.getClass() == BigDecimal.class - && p_info.getColumnClass(index) == Integer.class) - m_newValues[index] = new Integer (((BigDecimal)value).intValue()); - // Set Boolean - else if (p_info.getColumnClass(index) == Boolean.class - && ("Y".equals(value) || "N".equals(value)) ) - m_newValues[index] = new Boolean("Y".equals(value)); - else if (p_info.getColumnClass(index) == Integer.class - && value.getClass() == String.class) - { - try - { - int intValue = Integer.parseInt((String)value); - m_newValues[index] = Integer.valueOf(intValue); - } - catch (Exception e) - { - log.warning (ColumnName - + " - Class invalid: " + value.getClass().toString() - + ", Should be " + p_info.getColumnClass(index).toString() + ": " + value); - m_newValues[index] = null; - } - } - else - { - log.warning (ColumnName - + " - Class invalid: " + value.getClass().toString() - + ", Should be " + p_info.getColumnClass(index).toString() + ": " + value); - m_newValues[index] = value; // correct - } - // Validate (Min/Max) - String error = p_info.validate(index, value); - if (error != null) - log.warning(ColumnName + "=" + value + " - " + error); - // length for String - if (p_info.getColumnClass(index) == String.class) - { - String stringValue = value.toString(); - int length = p_info.getFieldLength(index); - if (stringValue.length() > length && length > 0) - { - log.warning(ColumnName + " - Value too long - truncated to length=" + length); - m_newValues[index] = stringValue.substring(0,length); - } - } - } - if (log.isLoggable(Level.FINEST)) log.finest(ColumnName + " = " + m_newValues[index] - + " (" + (m_newValues[index]==null ? "-" : m_newValues[index].getClass().getName()) + ")"); - set_Keys (ColumnName, m_newValues[index]); - - // FR 2962094 Fill ProcessedOn when the Processed column is changing from N to Y - setProcessedOn(ColumnName, value, m_oldValues[index]); - - return true; + return set_Value(ColumnName, value, false); } // set_ValueNoCheck /** diff --git a/org.adempiere.base/src/org/compiere/model/POInfo.java b/org.adempiere.base/src/org/compiere/model/POInfo.java index b644e3463f..5a96799af7 100644 --- a/org.adempiere.base/src/org/compiere/model/POInfo.java +++ b/org.adempiere.base/src/org/compiere/model/POInfo.java @@ -663,7 +663,7 @@ public class POInfo implements Serializable // Mandatory (i.e. not null if (m_columns[index].IsMandatory && value == null) { - return "IsMandatory"; + return "FillMandatory"; } if (value == null) return null; @@ -686,10 +686,7 @@ public class POInfo implements Serializable int comp = m_columns[index].ValueMin_BD.compareTo(value_BD); if (comp > 0) { - return "MinValue=" + m_columns[index].ValueMin_BD - + "(" + m_columns[index].ValueMin + ")" - + " - compared with Numeric Value=" + value_BD + "(" + value + ")" - + " - results in " + comp; + return "LessThanMinValue"+";"+m_columns[index].ValueMin_BD.toPlainString(); } } else // String @@ -697,9 +694,7 @@ public class POInfo implements Serializable int comp = m_columns[index].ValueMin.compareTo(value.toString()); if (comp > 0) { - return "MinValue=" + m_columns[index].ValueMin - + " - compared with String Value=" + value - + " - results in " + comp; + return "LessThanMinValue"+";"+m_columns[index].ValueMin; } } } @@ -718,9 +713,7 @@ public class POInfo implements Serializable int comp = m_columns[index].ValueMax_BD.compareTo(value_BD); if (comp < 0) { - return "MaxValue=" + m_columns[index].ValueMax_BD + "(" + m_columns[index].ValueMax + ")" - + " - compared with Numeric Value=" + value_BD + "(" + value + ")" - + " - results in " + comp; + return "MoreThanMaxValue"+";"+m_columns[index].ValueMax_BD.toPlainString(); } } else // String @@ -728,9 +721,7 @@ public class POInfo implements Serializable int comp = m_columns[index].ValueMax.compareTo(value.toString()); if (comp < 0) { - return "MaxValue=" + m_columns[index].ValueMax - + " - compared with String Value=" + value - + " - results in " + comp; + return "MoreThanMaxValue"+";"+m_columns[index].ValueMax; } } } diff --git a/org.adempiere.base/src/org/compiere/model/X_M_DiscountSchemaLine.java b/org.adempiere.base/src/org/compiere/model/X_M_DiscountSchemaLine.java index ce2fdaeaad..df91111f55 100644 --- a/org.adempiere.base/src/org/compiere/model/X_M_DiscountSchemaLine.java +++ b/org.adempiere.base/src/org/compiere/model/X_M_DiscountSchemaLine.java @@ -33,7 +33,7 @@ public class X_M_DiscountSchemaLine extends PO implements I_M_DiscountSchemaLine /** * */ - private static final long serialVersionUID = 20121031L; + private static final long serialVersionUID = 20130306L; /** Standard Constructor */ public X_M_DiscountSchemaLine (Properties ctx, int M_DiscountSchemaLine_ID, String trxName) @@ -251,6 +251,8 @@ public class X_M_DiscountSchemaLine extends PO implements I_M_DiscountSchemaLine public static final String LIMIT_BASE_LimitPOPrice = "X"; /** Fixed Price = F */ public static final String LIMIT_BASE_FixedPrice = "F"; + /** Product Cost = P */ + public static final String LIMIT_BASE_ProductCost = "P"; /** Set Limit price Base. @param Limit_Base Base price for calculation of the new price @@ -415,6 +417,8 @@ public class X_M_DiscountSchemaLine extends PO implements I_M_DiscountSchemaLine public static final String LIST_BASE_LimitPOPrice = "X"; /** Fixed Price = F */ public static final String LIST_BASE_FixedPrice = "F"; + /** Product Cost = P */ + public static final String LIST_BASE_ProductCost = "P"; /** Set List price Base. @param List_Base Price used as the basis for price list calculations @@ -728,6 +732,8 @@ public class X_M_DiscountSchemaLine extends PO implements I_M_DiscountSchemaLine public static final String STD_BASE_LimitPOPrice = "X"; /** Fixed Price = F */ public static final String STD_BASE_FixedPrice = "F"; + /** Product Cost = P */ + public static final String STD_BASE_ProductCost = "P"; /** Set Standard price Base. @param Std_Base Base price for calculating new standard price diff --git a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java index 34eb649924..5dda36f632 100644 --- a/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java +++ b/org.adempiere.ui.zk/WEB-INF/src/org/adempiere/webui/adwindow/AbstractADWindowContent.java @@ -20,6 +20,7 @@ package org.adempiere.webui.adwindow; import static org.compiere.model.SystemIDs.PROCESS_AD_CHANGELOG_REDO; import static org.compiere.model.SystemIDs.PROCESS_AD_CHANGELOG_UNDO; +import java.text.MessageFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Date; @@ -1268,16 +1269,46 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements { StringBuilder sb = new StringBuilder(); String msg = e.getMessage(); + StringBuilder adMessage = new StringBuilder(); if (msg != null && msg.length() > 0) { - sb.append(Msg.getMsg(Env.getCtx(), e.getAD_Message())); + adMessage.append(Msg.getMsg(Env.getCtx(), e.getAD_Message())); } String info = e.getInfo(); if (info != null && info.length() > 0) { - if (sb.length() > 0 && !sb.toString().trim().endsWith(":")) - sb.append(": "); - sb.append(info); + Object[] arguments = info.split("[;]"); + int index = 0; + while(index < arguments.length) + { + String expr = "{"+index+"}"; + if (adMessage.indexOf(expr) >= 0) + { + index++; + } + else + { + break; + } + } + if (index < arguments.length) + { + if (adMessage.length() > 0 && !adMessage.toString().trim().endsWith(":")) + adMessage.append(": "); + StringBuilder tail = new StringBuilder(); + while(index < arguments.length) + { + if (tail.length() > 0) tail.append(", "); + tail.append("{").append(index).append("}"); + index++; + } + adMessage.append(tail); + } + sb.append(MessageFormat.format(adMessage.toString(), arguments)); + } + else + { + sb.append(adMessage); } if (sb.length() > 0) {