IDEMPIERE-5139 BOM validation for Deactivation of Product (#1111)
This commit is contained in:
parent
57d4caa101
commit
55e9e87f0b
|
@ -0,0 +1,11 @@
|
|||
SET SQLBLANKLINES ON
|
||||
SET DEFINE OFF
|
||||
|
||||
-- IDEMPIERE-5139 BOM validation for Deactivation of Product
|
||||
-- Jan 4, 2022, 3:43:47 PM MYT
|
||||
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','This product is being used as a component in an active BOM. Please remove from BOM or inactivate BOM before marking this product as inactive.',0,0,'Y',TO_DATE('2022-01-04 15:43:42','YYYY-MM-DD HH24:MI:SS'),100,TO_DATE('2022-01-04 15:43:42','YYYY-MM-DD HH24:MI:SS'),100,200724,'DeActivateProductInActiveBOM','D','748a4e5b-95ec-4106-a949-ab700376a4a1')
|
||||
;
|
||||
|
||||
SELECT register_migration_script('202201040800_IDEMPIERE-5139.sql') FROM dual
|
||||
;
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
-- IDEMPIERE-5139 BOM validation for Deactivation of Product
|
||||
-- Jan 4, 2022, 3:43:47 PM MYT
|
||||
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('E','This product is being used as a component in an active BOM. Please remove from BOM or inactivate BOM before marking this product as inactive.',0,0,'Y',TO_TIMESTAMP('2022-01-04 15:43:42','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-01-04 15:43:42','YYYY-MM-DD HH24:MI:SS'),100,200724,'DeActivateProductInActiveBOM','D','748a4e5b-95ec-4106-a949-ab700376a4a1')
|
||||
;
|
||||
|
||||
SELECT register_migration_script('202201040800_IDEMPIERE-5139.sql') FROM dual
|
||||
;
|
||||
|
|
@ -28,6 +28,8 @@ import org.compiere.util.DB;
|
|||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Msg;
|
||||
import org.compiere.util.Util;
|
||||
import org.eevolution.model.MPPProductBOM;
|
||||
import org.eevolution.model.MPPProductBOMLine;
|
||||
import org.idempiere.cache.ImmutableIntPOCache;
|
||||
import org.idempiere.cache.ImmutablePOSupport;
|
||||
|
||||
|
@ -653,6 +655,17 @@ public class MProduct extends X_M_Product implements ImmutablePOSupport
|
|||
}
|
||||
|
||||
removeStorageRecords();
|
||||
|
||||
// check bom
|
||||
if (is_ValueChanged("IsActive") && !isActive())
|
||||
{
|
||||
errMsg = verifyBOM();
|
||||
if (! Util.isEmpty(errMsg))
|
||||
{
|
||||
log.saveError("Error", errMsg);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} // storage
|
||||
|
||||
// it checks if UOM has been changed , if so disallow the change if the condition is true.
|
||||
|
@ -753,6 +766,31 @@ public class MProduct extends X_M_Product implements ImmutablePOSupport
|
|||
}
|
||||
}
|
||||
|
||||
private String verifyBOM() {
|
||||
Query query = new Query(getCtx(), MPPProductBOMLine.Table_Name, MPPProductBOMLine.COLUMNNAME_M_Product_ID+"=?", get_TrxName());
|
||||
List<MPPProductBOMLine> list = query.setOnlyActiveRecords(true)
|
||||
.setClient_ID()
|
||||
.setParameters(getM_Product_ID())
|
||||
.list();
|
||||
for(MPPProductBOMLine line : list) {
|
||||
MPPProductBOM bom = line.getParent();
|
||||
if (bom.isActive()) {
|
||||
StringBuilder errMsg = new StringBuilder();
|
||||
errMsg.append(Msg.getMsg(Env.getCtx(), "DeActivateProductInActiveBOM"));
|
||||
String bomName = bom.getName();
|
||||
errMsg.append(" (BOM: ")
|
||||
.append(bomName);
|
||||
String parentValue = MProduct.get(bom.getM_Product_ID()).getValue();
|
||||
if (!parentValue.equals(bomName))
|
||||
errMsg.append(", ").append(parentValue);
|
||||
errMsg.append(")");
|
||||
return errMsg.toString();
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* HasInventoryOrCost
|
||||
* @return true if it has Inventory or Cost
|
||||
|
@ -822,6 +860,25 @@ public class MProduct extends X_M_Product implements ImmutablePOSupport
|
|||
if (newRecord || is_ValueChanged("M_Product_Category_ID"))
|
||||
MCost.create(this);
|
||||
|
||||
|
||||
if (!newRecord && success && is_ValueChanged(COLUMNNAME_IsActive))
|
||||
{
|
||||
if (!isActive() && isBOM())
|
||||
{
|
||||
StringBuilder where = new StringBuilder();
|
||||
where.append("AD_Client_ID=? ")
|
||||
.append("AND M_Product_ID=? ")
|
||||
.append("AND IsActive='Y'");
|
||||
Query query = new Query(Env.getCtx(), MPPProductBOM.Table_Name, where.toString(), get_TrxName());
|
||||
List<MPPProductBOM> boms = query.setParameters(getAD_Client_ID(), getM_Product_ID()).list();
|
||||
for(MPPProductBOM bom : boms)
|
||||
{
|
||||
bom.setIsActive(false);
|
||||
bom.saveEx();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
} // afterSave
|
||||
|
||||
|
|
|
@ -58,6 +58,8 @@ import org.compiere.util.DB;
|
|||
import org.compiere.util.Env;
|
||||
import org.compiere.util.TimeUtil;
|
||||
import org.compiere.wf.MWorkflow;
|
||||
import org.eevolution.model.MPPProductBOM;
|
||||
import org.eevolution.model.MPPProductBOMLine;
|
||||
import org.idempiere.test.AbstractTestCase;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
|
@ -241,4 +243,20 @@ public class MProductTest extends AbstractTestCase {
|
|||
count = query.setParameters(product.get_ID()).count();
|
||||
assertEquals(0, count, "Storage Reservation Record > 0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeactivateProductBOMValidation() {
|
||||
Query query = new Query(Env.getCtx(), MPPProductBOM.Table_Name, MPPProductBOM.COLUMNNAME_PP_Product_BOM_ID+"<1000000", getTrxName());
|
||||
MPPProductBOM bom = query.setClient_ID().setOnlyActiveRecords(true).first();
|
||||
MPPProductBOMLine[] lines = bom.getLines();
|
||||
final MProduct product = new MProduct(Env.getCtx(), lines[0].getM_Product_ID(), getTrxName());
|
||||
product.setIsActive(false);
|
||||
assertThrows(AdempiereException.class, () -> product.saveEx(), "No exception throw for deactivation of product in active BOM");
|
||||
|
||||
MProduct parent = new MProduct(Env.getCtx(), bom.getM_Product_ID(), getTrxName());
|
||||
parent.setIsActive(false);
|
||||
parent.saveEx();
|
||||
bom.load(getTrxName());
|
||||
assertFalse(bom.isActive(), "BOM not auto deactivated after deactivation of parent product");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue