From 7d32b0de0f0767b0cb04436ea2f9d72e400cb4cc Mon Sep 17 00:00:00 2001 From: Heng Sin Low Date: Thu, 13 Feb 2014 22:05:15 +0800 Subject: [PATCH] IDEMPIERE-1750 Restore backward compatibility for M_ProductionPlan. --- .../oracle/201402121237_IDEMPIERE-1750.sql | 151 +++++++++ .../201402121237_IDEMPIERE-1750.sql | 149 +++++++++ .../compiere/process/ProductionCreate.java | 59 +++- .../compiere/process/ProductionProcess.java | 109 +++--- .../org/compiere/model/I_M_Production.java | 9 + .../src/org/compiere/model/MProduction.java | 13 + .../org/compiere/model/MProductionLine.java | 155 +++++---- .../org/compiere/model/MProductionPlan.java | 313 ++++++++++++++++++ .../org/compiere/model/X_M_Production.java | 25 +- 9 files changed, 865 insertions(+), 118 deletions(-) create mode 100644 migration/i2.0/oracle/201402121237_IDEMPIERE-1750.sql create mode 100644 migration/i2.0/postgresql/201402121237_IDEMPIERE-1750.sql create mode 100644 org.adempiere.base/src/org/compiere/model/MProductionPlan.java diff --git a/migration/i2.0/oracle/201402121237_IDEMPIERE-1750.sql b/migration/i2.0/oracle/201402121237_IDEMPIERE-1750.sql new file mode 100644 index 0000000000..ea69b6db92 --- /dev/null +++ b/migration/i2.0/oracle/201402121237_IDEMPIERE-1750.sql @@ -0,0 +1,151 @@ +SET SQLBLANKLINES ON +SET DEFINE OFF + +-- Feb 12, 2014 2:30:48 PM MYT +-- IDEMPIERE-1750 Restore M_ProductionPlan backward compatibility +INSERT INTO AD_Element (AD_Client_ID,AD_Element_ID,AD_Element_UU,AD_Org_ID,ColumnName,Created,CreatedBy,EntityType,IsActive,Name,PrintName,Updated,UpdatedBy) VALUES (0,202669,'5bdb1aeb-6657-4477-b9e3-ca967fe6fec7',0,'IsUseProductionPlan',TO_DATE('2014-02-12 14:30:32','YYYY-MM-DD HH24:MI:SS'),100,'D','Y','Use Production Plan','Use Production Plan',TO_DATE('2014-02-12 14:30:32','YYYY-MM-DD HH24:MI:SS'),100) +; + +-- Feb 12, 2014 2:31:42 PM MYT +INSERT INTO AD_Column (SeqNoSelection,IsAlwaysUpdateable,IsSyncDatabase,AD_Client_ID,EntityType,IsSecure,IsEncrypted,AD_Column_ID,IsParent,IsMandatory,IsIdentifier,SeqNo,Version,FieldLength,IsKey,IsTranslated,IsUpdateable,IsAutocomplete,IsAllowLogging,IsAllowCopy,ColumnName,Name,DefaultValue,IsSelectionColumn,AD_Column_UU,AD_Org_ID,CreatedBy,Updated,Created,IsActive,UpdatedBy,IsToolbarButton,FKConstraintType,AD_Element_ID,AD_Reference_ID,AD_Table_ID) VALUES (0,'N','N',0,'D','N','N',210981,'N','Y','N',0,0,1,'N','N','Y','N','Y','Y','IsUseProductionPlan','Use Production Plan','N','N','46c42278-5188-4e22-9564-44954437f3f8',0,100,TO_DATE('2014-02-12 14:31:35','YYYY-MM-DD HH24:MI:SS'),TO_DATE('2014-02-12 14:31:35','YYYY-MM-DD HH24:MI:SS'),'Y',100,'N','N',202669,20,325) +; + +-- Feb 12, 2014 2:31:51 PM MYT +ALTER TABLE M_Production ADD IsUseProductionPlan CHAR(1) DEFAULT 'N' CHECK (IsUseProductionPlan IN ('Y','N')) NOT NULL +; + +-- Feb 12, 2014 2:34:02 PM MYT +UPDATE AD_Tab SET WhereClause='M_Production.IsUseProductionPlan=''Y''',Updated=TO_DATE('2014-02-12 14:34:02','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tab_ID=319 +; + +-- Feb 12, 2014 2:35:04 PM MYT +INSERT INTO AD_Field (ColumnSpan,NumLines,IsQuickEntry,AD_Client_ID,IsHeading,AD_Field_ID,IsDisplayed,IsFieldOnly,AD_Tab_ID,IsSameLine,IsDisplayedGrid,SeqNoGrid,SeqNo,IsReadOnly,IsCentrallyMaintained,DefaultValue,EntityType,Name,SortNo,IsEncrypted,DisplayLength,CreatedBy,Created,AD_Org_ID,Updated,UpdatedBy,AD_Field_UU,IsActive,XPosition,IsAdvancedField,IsDefaultFocus,AD_Column_ID) VALUES (1,1,'N',0,'N',202628,'N','N',319,'N','N',210,210,'N','Y','Y','D','Use Production Plan',0,'N',0,100,TO_DATE('2014-02-12 14:35:02','YYYY-MM-DD HH24:MI:SS'),0,TO_DATE('2014-02-12 14:35:02','YYYY-MM-DD HH24:MI:SS'),100,'e4845d93-6a9e-41d6-a044-0619e27c2065','Y',1,'N','N',210981) +; + +-- Feb 12, 2014 2:37:21 PM MYT +UPDATE AD_Tab SET WhereClause='M_Production.IsUseProductionPlan=''N''',Updated=TO_DATE('2014-02-12 14:37:21','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tab_ID=53344 +; + +-- Feb 12, 2014 2:38:29 PM MYT +INSERT INTO AD_Field (ColumnSpan,NumLines,IsQuickEntry,AD_Client_ID,IsHeading,AD_Field_ID,IsDisplayed,IsFieldOnly,AD_Tab_ID,IsSameLine,IsDisplayedGrid,SeqNoGrid,SeqNo,IsReadOnly,IsCentrallyMaintained,DefaultValue,EntityType,Name,SortNo,IsEncrypted,DisplayLength,CreatedBy,Created,AD_Org_ID,Updated,UpdatedBy,AD_Field_UU,IsActive,XPosition,IsAdvancedField,IsDefaultFocus,AD_Column_ID) VALUES (1,1,'N',0,'N',202629,'N','N',53344,'N','N',210,250,'N','Y','N','D','Use Production Plan',0,'N',0,100,TO_DATE('2014-02-12 14:38:23','YYYY-MM-DD HH24:MI:SS'),0,TO_DATE('2014-02-12 14:38:23','YYYY-MM-DD HH24:MI:SS'),100,'b1b2a592-9681-420c-bdfa-c164c8ca51f8','Y',1,'N','N',210981) +; + +-- Feb 12, 2014 5:06:14 PM MYT +-- IDEMPIERE-1750 Restore M_ProductionPlan backward compatibility +INSERT INTO AD_Field (ColumnSpan,NumLines,IsQuickEntry,AD_Client_ID,IsHeading,AD_Field_ID,IsDisplayed,IsFieldOnly,AD_Tab_ID,IsSameLine,IsDisplayedGrid,SeqNoGrid,SeqNo,IsReadOnly,IsCentrallyMaintained,EntityType,Name,SortNo,IsEncrypted,DisplayLength,DisplayLogic,CreatedBy,Created,AD_Org_ID,Updated,UpdatedBy,AD_Field_UU,IsActive,XPosition,IsAdvancedField,IsDefaultFocus,AD_Column_ID) VALUES (2,1,'N',0,'N',202630,'Y','N',321,'N','Y',130,140,'N','Y','D','Quantity Used',0,'N',0,'@IsEndProduct@=N',100,TO_DATE('2014-02-12 17:06:11','YYYY-MM-DD HH24:MI:SS'),0,TO_DATE('2014-02-12 17:06:11','YYYY-MM-DD HH24:MI:SS'),100,'70e099b3-284b-4617-8e3b-684e541bc1af','Y',1,'N','N',61944) +; + +-- Feb 12, 2014 5:06:50 PM MYT +UPDATE AD_Field SET DisplayLogic='@IsEndProduct@=Y',Updated=TO_DATE('2014-02-12 17:06:50','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=3807 +; + +-- Feb 12, 2014 5:07:57 PM MYT +INSERT INTO AD_Field (ColumnSpan,NumLines,IsQuickEntry,AD_Client_ID,IsHeading,AD_Field_ID,IsDisplayed,IsFieldOnly,AD_Tab_ID,IsSameLine,IsDisplayedGrid,SeqNoGrid,SeqNo,IsReadOnly,IsCentrallyMaintained,EntityType,Name,Description,SortNo,IsEncrypted,DisplayLength,CreatedBy,Created,AD_Org_ID,Updated,UpdatedBy,AD_Field_UU,IsActive,XPosition,IsAdvancedField,IsDefaultFocus,AD_Column_ID) VALUES (2,1,'N',0,'N',202631,'Y','N',321,'N','Y',140,150,'N','Y','D','End Product','End Product of production',0,'N',0,100,TO_DATE('2014-02-12 17:07:56','YYYY-MM-DD HH24:MI:SS'),0,TO_DATE('2014-02-12 17:07:56','YYYY-MM-DD HH24:MI:SS'),100,'c879fc0d-d134-41a5-81fd-565b22118d66','Y',1,'N','N',61945) +; + +-- Feb 12, 2014 5:09:09 PM MYT +UPDATE AD_Field SET SeqNo=0,IsDisplayed='N' WHERE AD_Field_ID=202335 +; + +-- Feb 12, 2014 5:09:09 PM MYT +UPDATE AD_Field SET SeqNo=0,IsDisplayed='N' WHERE AD_Field_ID=10338 +; + +-- Feb 12, 2014 5:09:10 PM MYT +UPDATE AD_Field SET SeqNo=0,IsDisplayed='N' WHERE AD_Field_ID=3801 +; + +-- Feb 12, 2014 5:09:10 PM MYT +UPDATE AD_Field SET SeqNo=10,IsDisplayed='Y' WHERE AD_Field_ID=3802 +; + +-- Feb 12, 2014 5:09:10 PM MYT +UPDATE AD_Field SET SeqNo=20,IsDisplayed='Y' WHERE AD_Field_ID=3803 +; + +-- Feb 12, 2014 5:09:10 PM MYT +UPDATE AD_Field SET SeqNo=30,IsDisplayed='Y' WHERE AD_Field_ID=3809 +; + +-- Feb 12, 2014 5:09:10 PM MYT +UPDATE AD_Field SET SeqNo=40,IsDisplayed='Y' WHERE AD_Field_ID=3811 +; + +-- Feb 12, 2014 5:09:10 PM MYT +UPDATE AD_Field SET SeqNo=50,IsDisplayed='Y' WHERE AD_Field_ID=3806 +; + +-- Feb 12, 2014 5:09:10 PM MYT +UPDATE AD_Field SET SeqNo=60,IsDisplayed='Y' WHERE AD_Field_ID=202631 +; + +-- Feb 12, 2014 5:09:10 PM MYT +UPDATE AD_Field SET SeqNo=70,IsDisplayed='Y' WHERE AD_Field_ID=6556 +; + +-- Feb 12, 2014 5:09:10 PM MYT +UPDATE AD_Field SET SeqNo=80,IsDisplayed='Y' WHERE AD_Field_ID=3804 +; + +-- Feb 12, 2014 5:09:10 PM MYT +UPDATE AD_Field SET SeqNo=90,IsDisplayed='Y' WHERE AD_Field_ID=202630 +; + +-- Feb 12, 2014 5:10:09 PM MYT +UPDATE AD_Field SET XPosition=2,Updated=TO_DATE('2014-02-12 17:10:09','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202631 +; +-- Feb 12, 2014 8:30:35 PM MYT +-- IDEMPIERE-1750 Restore M_ProductionPlan backward compatibility +UPDATE AD_Field SET SeqNo=60,IsDisplayed='Y' WHERE AD_Field_ID=6556 +; + +-- Feb 12, 2014 8:30:35 PM MYT +UPDATE AD_Field SET SeqNo=70,IsDisplayed='Y' WHERE AD_Field_ID=202631 +; + +-- Feb 12, 2014 8:31:19 PM MYT +UPDATE AD_Tab SET AD_Column_ID=4753,Updated=TO_DATE('2014-02-12 20:31:19','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tab_ID=321 +; + +UPDATE M_Production +SET IsUseProductionPlan='Y' +WHERE M_Product_ID IS NULL +; + +UPDATE M_ProductionLine +SET QtyUsed = 0 WHERE QtyUsed IS NULL +; + +UPDATE M_ProductionLine +SET QtyUsed = MovementQty * -1 +WHERE QtyUsed = 0 AND MovementQty <> 0 +AND M_ProductionPlan_ID IN +( SELECT M_ProductionPlan_ID FROM M_ProductionPlan + WHERE M_ProductionPlan.M_ProductionPlan_ID=M_ProductionLine.M_ProductionPlan_ID + AND M_ProductionPlan.M_Product_ID != M_ProductionLine.M_Product_ID) +; + +UPDATE M_ProductionLine +SET IsEndProduct='Y' +WHERE M_ProductionPlan_ID IN +( SELECT M_ProductionPlan_ID FROM M_ProductionPlan + WHERE M_ProductionPlan.M_ProductionPlan_ID=M_ProductionLine.M_ProductionPlan_ID + AND M_ProductionPlan.M_Product_ID = M_ProductionLine.M_Product_ID) +; + +UPDATE M_ProductionLine +SET IsEndProduct='N' +WHERE M_ProductionPlan_ID IN +( SELECT M_ProductionPlan_ID FROM M_ProductionPlan + WHERE M_ProductionPlan.M_ProductionPlan_ID=M_ProductionLine.M_ProductionPlan_ID + AND M_ProductionPlan.M_Product_ID != M_ProductionLine.M_Product_ID) +; + +-- Feb 12, 2014 9:14:39 PM MYT +-- IDEMPIERE-1750 Restore M_ProductionPlan backward compatibility +UPDATE AD_Process_Para SET DisplayLogic='@IsUseProductionPlan@=N', IsCentrallyMaintained='N',Updated=TO_DATE('2014-02-12 21:14:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=53517 +; + +SELECT register_migration_script('201402121237_IDEMPIERE-1750.sql') FROM dual +; + diff --git a/migration/i2.0/postgresql/201402121237_IDEMPIERE-1750.sql b/migration/i2.0/postgresql/201402121237_IDEMPIERE-1750.sql new file mode 100644 index 0000000000..6c9a541262 --- /dev/null +++ b/migration/i2.0/postgresql/201402121237_IDEMPIERE-1750.sql @@ -0,0 +1,149 @@ +-- Feb 12, 2014 2:30:48 PM MYT +-- IDEMPIERE-1750 Restore M_ProductionPlan backward compatibility +INSERT INTO AD_Element (AD_Client_ID,AD_Element_ID,AD_Element_UU,AD_Org_ID,ColumnName,Created,CreatedBy,EntityType,IsActive,Name,PrintName,Updated,UpdatedBy) VALUES (0,202669,'5bdb1aeb-6657-4477-b9e3-ca967fe6fec7',0,'IsUseProductionPlan',TO_TIMESTAMP('2014-02-12 14:30:32','YYYY-MM-DD HH24:MI:SS'),100,'D','Y','Use Production Plan','Use Production Plan',TO_TIMESTAMP('2014-02-12 14:30:32','YYYY-MM-DD HH24:MI:SS'),100) +; + +-- Feb 12, 2014 2:31:42 PM MYT +INSERT INTO AD_Column (SeqNoSelection,IsAlwaysUpdateable,IsSyncDatabase,AD_Client_ID,EntityType,IsSecure,IsEncrypted,AD_Column_ID,IsParent,IsMandatory,IsIdentifier,SeqNo,Version,FieldLength,IsKey,IsTranslated,IsUpdateable,IsAutocomplete,IsAllowLogging,IsAllowCopy,ColumnName,Name,DefaultValue,IsSelectionColumn,AD_Column_UU,AD_Org_ID,CreatedBy,Updated,Created,IsActive,UpdatedBy,IsToolbarButton,FKConstraintType,AD_Element_ID,AD_Reference_ID,AD_Table_ID) VALUES (0,'N','N',0,'D','N','N',210981,'N','Y','N',0,0,1,'N','N','Y','N','Y','Y','IsUseProductionPlan','Use Production Plan','N','N','46c42278-5188-4e22-9564-44954437f3f8',0,100,TO_TIMESTAMP('2014-02-12 14:31:35','YYYY-MM-DD HH24:MI:SS'),TO_TIMESTAMP('2014-02-12 14:31:35','YYYY-MM-DD HH24:MI:SS'),'Y',100,'N','N',202669,20,325) +; + +-- Feb 12, 2014 2:31:51 PM MYT +ALTER TABLE M_Production ADD COLUMN IsUseProductionPlan CHAR(1) DEFAULT 'N' CHECK (IsUseProductionPlan IN ('Y','N')) NOT NULL +; + +-- Feb 12, 2014 2:34:02 PM MYT +UPDATE AD_Tab SET WhereClause='M_Production.IsUseProductionPlan=''Y''',Updated=TO_TIMESTAMP('2014-02-12 14:34:02','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tab_ID=319 +; + +-- Feb 12, 2014 2:35:04 PM MYT +INSERT INTO AD_Field (ColumnSpan,NumLines,IsQuickEntry,AD_Client_ID,IsHeading,AD_Field_ID,IsDisplayed,IsFieldOnly,AD_Tab_ID,IsSameLine,IsDisplayedGrid,SeqNoGrid,SeqNo,IsReadOnly,IsCentrallyMaintained,DefaultValue,EntityType,Name,SortNo,IsEncrypted,DisplayLength,CreatedBy,Created,AD_Org_ID,Updated,UpdatedBy,AD_Field_UU,IsActive,XPosition,IsAdvancedField,IsDefaultFocus,AD_Column_ID) VALUES (1,1,'N',0,'N',202628,'N','N',319,'N','N',210,210,'N','Y','Y','D','Use Production Plan',0,'N',0,100,TO_TIMESTAMP('2014-02-12 14:35:02','YYYY-MM-DD HH24:MI:SS'),0,TO_TIMESTAMP('2014-02-12 14:35:02','YYYY-MM-DD HH24:MI:SS'),100,'e4845d93-6a9e-41d6-a044-0619e27c2065','Y',1,'N','N',210981) +; + +-- Feb 12, 2014 2:37:21 PM MYT +UPDATE AD_Tab SET WhereClause='M_Production.IsUseProductionPlan=''N''',Updated=TO_TIMESTAMP('2014-02-12 14:37:21','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tab_ID=53344 +; + +-- Feb 12, 2014 2:38:29 PM MYT +INSERT INTO AD_Field (ColumnSpan,NumLines,IsQuickEntry,AD_Client_ID,IsHeading,AD_Field_ID,IsDisplayed,IsFieldOnly,AD_Tab_ID,IsSameLine,IsDisplayedGrid,SeqNoGrid,SeqNo,IsReadOnly,IsCentrallyMaintained,DefaultValue,EntityType,Name,SortNo,IsEncrypted,DisplayLength,CreatedBy,Created,AD_Org_ID,Updated,UpdatedBy,AD_Field_UU,IsActive,XPosition,IsAdvancedField,IsDefaultFocus,AD_Column_ID) VALUES (1,1,'N',0,'N',202629,'N','N',53344,'N','N',210,250,'N','Y','N','D','Use Production Plan',0,'N',0,100,TO_TIMESTAMP('2014-02-12 14:38:23','YYYY-MM-DD HH24:MI:SS'),0,TO_TIMESTAMP('2014-02-12 14:38:23','YYYY-MM-DD HH24:MI:SS'),100,'b1b2a592-9681-420c-bdfa-c164c8ca51f8','Y',1,'N','N',210981) +; + +-- Feb 12, 2014 5:06:14 PM MYT +-- IDEMPIERE-1750 Restore M_ProductionPlan backward compatibility +INSERT INTO AD_Field (ColumnSpan,NumLines,IsQuickEntry,AD_Client_ID,IsHeading,AD_Field_ID,IsDisplayed,IsFieldOnly,AD_Tab_ID,IsSameLine,IsDisplayedGrid,SeqNoGrid,SeqNo,IsReadOnly,IsCentrallyMaintained,EntityType,Name,SortNo,IsEncrypted,DisplayLength,DisplayLogic,CreatedBy,Created,AD_Org_ID,Updated,UpdatedBy,AD_Field_UU,IsActive,XPosition,IsAdvancedField,IsDefaultFocus,AD_Column_ID) VALUES (2,1,'N',0,'N',202630,'Y','N',321,'N','Y',130,140,'N','Y','D','Quantity Used',0,'N',0,'@IsEndProduct@=N',100,TO_TIMESTAMP('2014-02-12 17:06:11','YYYY-MM-DD HH24:MI:SS'),0,TO_TIMESTAMP('2014-02-12 17:06:11','YYYY-MM-DD HH24:MI:SS'),100,'70e099b3-284b-4617-8e3b-684e541bc1af','Y',1,'N','N',61944) +; + +-- Feb 12, 2014 5:06:50 PM MYT +UPDATE AD_Field SET DisplayLogic='@IsEndProduct@=Y',Updated=TO_TIMESTAMP('2014-02-12 17:06:50','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=3807 +; + +-- Feb 12, 2014 5:07:57 PM MYT +INSERT INTO AD_Field (ColumnSpan,NumLines,IsQuickEntry,AD_Client_ID,IsHeading,AD_Field_ID,IsDisplayed,IsFieldOnly,AD_Tab_ID,IsSameLine,IsDisplayedGrid,SeqNoGrid,SeqNo,IsReadOnly,IsCentrallyMaintained,EntityType,Name,Description,SortNo,IsEncrypted,DisplayLength,CreatedBy,Created,AD_Org_ID,Updated,UpdatedBy,AD_Field_UU,IsActive,XPosition,IsAdvancedField,IsDefaultFocus,AD_Column_ID) VALUES (2,1,'N',0,'N',202631,'Y','N',321,'N','Y',140,150,'N','Y','D','End Product','End Product of production',0,'N',0,100,TO_TIMESTAMP('2014-02-12 17:07:56','YYYY-MM-DD HH24:MI:SS'),0,TO_TIMESTAMP('2014-02-12 17:07:56','YYYY-MM-DD HH24:MI:SS'),100,'c879fc0d-d134-41a5-81fd-565b22118d66','Y',1,'N','N',61945) +; + +-- Feb 12, 2014 5:09:09 PM MYT +UPDATE AD_Field SET SeqNo=0,IsDisplayed='N' WHERE AD_Field_ID=202335 +; + +-- Feb 12, 2014 5:09:09 PM MYT +UPDATE AD_Field SET SeqNo=0,IsDisplayed='N' WHERE AD_Field_ID=10338 +; + +-- Feb 12, 2014 5:09:10 PM MYT +UPDATE AD_Field SET SeqNo=0,IsDisplayed='N' WHERE AD_Field_ID=3801 +; + +-- Feb 12, 2014 5:09:10 PM MYT +UPDATE AD_Field SET SeqNo=10,IsDisplayed='Y' WHERE AD_Field_ID=3802 +; + +-- Feb 12, 2014 5:09:10 PM MYT +UPDATE AD_Field SET SeqNo=20,IsDisplayed='Y' WHERE AD_Field_ID=3803 +; + +-- Feb 12, 2014 5:09:10 PM MYT +UPDATE AD_Field SET SeqNo=30,IsDisplayed='Y' WHERE AD_Field_ID=3809 +; + +-- Feb 12, 2014 5:09:10 PM MYT +UPDATE AD_Field SET SeqNo=40,IsDisplayed='Y' WHERE AD_Field_ID=3811 +; + +-- Feb 12, 2014 5:09:10 PM MYT +UPDATE AD_Field SET SeqNo=50,IsDisplayed='Y' WHERE AD_Field_ID=3806 +; + +-- Feb 12, 2014 5:09:10 PM MYT +UPDATE AD_Field SET SeqNo=60,IsDisplayed='Y' WHERE AD_Field_ID=202631 +; + +-- Feb 12, 2014 5:09:10 PM MYT +UPDATE AD_Field SET SeqNo=70,IsDisplayed='Y' WHERE AD_Field_ID=6556 +; + +-- Feb 12, 2014 5:09:10 PM MYT +UPDATE AD_Field SET SeqNo=80,IsDisplayed='Y' WHERE AD_Field_ID=3804 +; + +-- Feb 12, 2014 5:09:10 PM MYT +UPDATE AD_Field SET SeqNo=90,IsDisplayed='Y' WHERE AD_Field_ID=202630 +; + +-- Feb 12, 2014 5:10:09 PM MYT +UPDATE AD_Field SET XPosition=2,Updated=TO_TIMESTAMP('2014-02-12 17:10:09','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=202631 +; + +-- Feb 12, 2014 8:30:35 PM MYT +-- IDEMPIERE-1750 Restore M_ProductionPlan backward compatibility +UPDATE AD_Field SET SeqNo=60,IsDisplayed='Y' WHERE AD_Field_ID=6556 +; + +-- Feb 12, 2014 8:30:35 PM MYT +UPDATE AD_Field SET SeqNo=70,IsDisplayed='Y' WHERE AD_Field_ID=202631 +; + +-- Feb 12, 2014 8:31:19 PM MYT +UPDATE AD_Tab SET AD_Column_ID=4753,Updated=TO_TIMESTAMP('2014-02-12 20:31:19','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Tab_ID=321 +; + +UPDATE M_Production +SET IsUseProductionPlan='Y' +WHERE M_Product_ID IS NULL +; + +UPDATE M_ProductionLine +SET QtyUsed = 0 WHERE QtyUsed IS NULL +; + +UPDATE M_ProductionLine +SET QtyUsed = MovementQty * -1 +WHERE QtyUsed = 0 AND MovementQty <> 0 +AND M_ProductionPlan_ID IN +( SELECT M_ProductionPlan_ID FROM M_ProductionPlan + WHERE M_ProductionPlan.M_ProductionPlan_ID=M_ProductionLine.M_ProductionPlan_ID + AND M_ProductionPlan.M_Product_ID != M_ProductionLine.M_Product_ID) +; + +UPDATE M_ProductionLine +SET IsEndProduct='Y' +WHERE M_ProductionPlan_ID IN +( SELECT M_ProductionPlan_ID FROM M_ProductionPlan + WHERE M_ProductionPlan.M_ProductionPlan_ID=M_ProductionLine.M_ProductionPlan_ID + AND M_ProductionPlan.M_Product_ID = M_ProductionLine.M_Product_ID) +; + +UPDATE M_ProductionLine +SET IsEndProduct='N' +WHERE M_ProductionPlan_ID IN +( SELECT M_ProductionPlan_ID FROM M_ProductionPlan + WHERE M_ProductionPlan.M_ProductionPlan_ID=M_ProductionLine.M_ProductionPlan_ID + AND M_ProductionPlan.M_Product_ID != M_ProductionLine.M_Product_ID) +; + +-- Feb 12, 2014 9:14:39 PM MYT +-- IDEMPIERE-1750 Restore M_ProductionPlan backward compatibility +UPDATE AD_Process_Para SET DisplayLogic='@IsUseProductionPlan@=N', IsCentrallyMaintained='N',Updated=TO_TIMESTAMP('2014-02-12 21:14:39','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_Para_ID=53517 +; + +SELECT register_migration_script('201402121237_IDEMPIERE-1750.sql') FROM dual +; + diff --git a/org.adempiere.base.process/src/org/compiere/process/ProductionCreate.java b/org.adempiere.base.process/src/org/compiere/process/ProductionCreate.java index 2ff78d2986..353e739b8e 100644 --- a/org.adempiere.base.process/src/org/compiere/process/ProductionCreate.java +++ b/org.adempiere.base.process/src/org/compiere/process/ProductionCreate.java @@ -1,10 +1,14 @@ package org.compiere.process; import java.math.BigDecimal; +import java.util.List; import java.util.logging.Level; +import org.compiere.model.I_M_ProductionPlan; import org.compiere.model.MProduction; +import org.compiere.model.MProductionPlan; import org.compiere.model.MSysConfig; +import org.compiere.model.Query; import org.compiere.util.AdempiereUserError; import org.compiere.util.DB; import org.compiere.util.Env; @@ -95,25 +99,33 @@ public class ProductionCreate extends SvrProcess { protected String createLines() throws Exception { int created = 0; - isBom(m_production.getM_Product_ID()); - - if (!costsOK(m_production.getM_Product_ID())) { - String msg = "Excessive difference in standard costs"; - if (MSysConfig.getBooleanValue("MFG_ValidateCostsDifferenceOnCreate", false, getAD_Client_ID())) { - throw new AdempiereUserError("Excessive difference in standard costs"); - } else { - log.warning(msg); + if (!m_production.isUseProductionPlan()) { + validateEndProduct(m_production.getM_Product_ID()); + + if (!recreate && "Y".equalsIgnoreCase(m_production.getIsCreated())) + throw new AdempiereUserError("Production already created."); + + if (newQty != null ) + m_production.setProductionQty(newQty); + + m_production.deleteLines(get_TrxName()); + created = m_production.createLines(mustBeStocked); + } else { + Query planQuery = new Query(getCtx(), I_M_ProductionPlan.Table_Name, "M_ProductionPlan.M_Production_ID=?", get_TrxName()); + List plans = planQuery.setParameters(m_production.getM_Production_ID()).list(); + for(MProductionPlan plan : plans) { + validateEndProduct(plan.getM_Product_ID()); + + if (!recreate && "Y".equalsIgnoreCase(m_production.getIsCreated())) + throw new AdempiereUserError("Production already created."); + + plan.deleteLines(get_TrxName()); + int n = plan.createLines(mustBeStocked); + if ( n == 0 ) + {return "Failed to create production lines"; } + created = created + n; } } - - if (!recreate && "Y".equalsIgnoreCase(m_production.getIsCreated())) - throw new AdempiereUserError("Production already created."); - - if (newQty != null ) - m_production.setProductionQty(newQty); - - m_production.deleteLines(get_TrxName()); - created = m_production.createLines(mustBeStocked); if ( created == 0 ) {return "Failed to create production lines"; } @@ -123,6 +135,19 @@ public class ProductionCreate extends SvrProcess { StringBuilder msgreturn = new StringBuilder().append(created).append(" production lines were created"); return msgreturn.toString(); } + + private void validateEndProduct(int M_Product_ID) throws Exception { + isBom(M_Product_ID); + + if (!costsOK(M_Product_ID)) { + String msg = "Excessive difference in standard costs"; + if (MSysConfig.getBooleanValue("MFG_ValidateCostsDifferenceOnCreate", false, getAD_Client_ID())) { + throw new AdempiereUserError("Excessive difference in standard costs"); + } else { + log.warning(msg); + } + } + } protected void isBom(int M_Product_ID) throws Exception { diff --git a/org.adempiere.base.process/src/org/compiere/process/ProductionProcess.java b/org.adempiere.base.process/src/org/compiere/process/ProductionProcess.java index b0b731c04d..a1e5f95974 100644 --- a/org.adempiere.base.process/src/org/compiere/process/ProductionProcess.java +++ b/org.adempiere.base.process/src/org/compiere/process/ProductionProcess.java @@ -1,13 +1,19 @@ package org.compiere.process; import java.sql.Timestamp; +import java.util.List; import java.util.logging.Level; +import org.adempiere.exceptions.AdempiereException; +import org.compiere.model.I_M_ProductionPlan; import org.compiere.model.MClient; import org.compiere.model.MProduction; import org.compiere.model.MProductionLine; -import org.compiere.util.AdempiereSystemError; +import org.compiere.model.MProductionPlan; +import org.compiere.model.Query; import org.compiere.util.AdempiereUserError; +import org.compiere.util.Env; +import org.compiere.util.Util; /** @@ -41,60 +47,87 @@ public class ProductionProcess extends SvrProcess { } p_M_Production_ID = getRecord_ID(); - m_production = new MProduction(getCtx(), p_M_Production_ID, get_TrxName()); + if (p_M_Production_ID > 0) + m_production = new MProduction(getCtx(), p_M_Production_ID, get_TrxName()); } //prepare @Override protected String doIt() throws Exception { - - - if ( m_production.get_ID() == 0 ) + if ( m_production == null || m_production.get_ID() == 0 ) throw new AdempiereUserError("Could not load production header"); - if ( m_production.getIsCreated().equals("N") ) - return "Not created"; - - if ( m_production.isProcessed() ) - return "Already processed"; - - - return processLines(); - + try { + int processed = ProductionProcess.procesProduction(m_production, p_MovementDate, mustBeStocked); + StringBuilder msgreturn = new StringBuilder("@Processed@ #").append(processed); + return msgreturn.toString(); + } catch (Exception e) { + log.log(Level.SEVERE, e.getLocalizedMessage(), e); + return e.getMessage(); + } } - protected String processLines() throws Exception { + public static int procesProduction(MProduction production, Timestamp movementDate, boolean mustBeStocked) { + if ( production.getIsCreated().equals("N") ) + throw new AdempiereUserError("Not created"); - int processed = 0; - m_production.setMovementDate(p_MovementDate); - MProductionLine[] lines = m_production.getLines(); + if ( production.isProcessed() ) + throw new AdempiereUserError("Already processed"); + + if (movementDate != null) + production.setMovementDate(movementDate); StringBuilder errors = new StringBuilder(); - for ( int i = 0; i 0) { + throw new AdempiereException(errors.toString()); + } + processed = processed + lines.length; + } else { + Query planQuery = new Query(Env.getCtx(), I_M_ProductionPlan.Table_Name, "M_ProductionPlan.M_Production_ID=?", production.get_TrxName()); + List plans = planQuery.setParameters(production.getM_Production_ID()).list(); + for(MProductionPlan plan : plans) { + MProductionLine[] lines = plan.getLines(); + if (lines.length > 0) { + errors.append(processLines(production, lines, mustBeStocked)); + if (errors.length() > 0) { + throw new AdempiereException(errors.toString()); + } + processed = processed + lines.length; + } + plan.setProcessed(true); + plan.saveEx(); + } } - if ( errors.toString().compareTo("") != 0 ) { - log.log(Level.WARNING, errors.toString() ); - throw new AdempiereSystemError(errors.toString()); - } + production.setProcessed(true); + production.saveEx(); - m_production.setProcessed(true); - - m_production.saveEx(get_TrxName()); - /* Immediate accounting */ if (MClient.isClientAccountingImmediate()) { @SuppressWarnings("unused") - String ignoreError = DocumentEngine.postImmediate(getCtx(), getAD_Client_ID(), m_production.get_Table_ID(), m_production.get_ID(), true, get_TrxName()); + String ignoreError = DocumentEngine.postImmediate(Env.getCtx(), production.getAD_Client_ID(), production.get_Table_ID(), production.get_ID(), true, production.get_TrxName()); } - - StringBuilder msgreturn = new StringBuilder("@Processed@ #").append(processed); - return msgreturn.toString(); + + return processed; + } + + protected static String processLines(MProduction production, MProductionLine[] lines, boolean mustBeStocked) { + + StringBuilder errors = new StringBuilder(); + for ( int i = 0; i 0) { + if (isUseProductionPlan()) { + setIsUseProductionPlan(false); + } + } else { + if (!isUseProductionPlan()) { + setIsUseProductionPlan(true); + } + } + return true; + } } diff --git a/org.adempiere.base/src/org/compiere/model/MProductionLine.java b/org.adempiere.base/src/org/compiere/model/MProductionLine.java index 27f41ff514..93d27de4f9 100644 --- a/org.adempiere.base/src/org/compiere/model/MProductionLine.java +++ b/org.adempiere.base/src/org/compiere/model/MProductionLine.java @@ -18,7 +18,7 @@ public class MProductionLine extends X_M_ProductionLine { */ private static final long serialVersionUID = 5939914729719167512L; - private MProduction parent; + private MProduction productionParent; /** @@ -57,9 +57,15 @@ public class MProductionLine extends X_M_ProductionLine { setM_Production_ID( header.get_ID()); setAD_Client_ID(header.getAD_Client_ID()); setAD_Org_ID(header.getAD_Org_ID()); - parent = header; + productionParent = header; } + public MProductionLine( MProductionPlan header ) { + super( header.getCtx(), 0, header.get_TrxName() ); + setM_ProductionPlan_ID( header.get_ID()); + setAD_Client_ID(header.getAD_Client_ID()); + setAD_Org_ID(header.getAD_Org_ID()); + } /** @@ -89,7 +95,7 @@ public class MProductionLine extends X_M_ProductionLine { if (log.isLoggable(Level.FINEST)) log.log(Level.FINEST, "asi Description is: " + asiString); // create transactions for finished goods - if ( getMovementQty().compareTo(Env.ZERO) > 0 ) { + if ( getM_Product_ID() == getEndProduct_ID()) { Timestamp dateMPolicy = date; if(getM_AttributeSetInstance_ID()>0){ @@ -132,66 +138,68 @@ public class MProductionLine extends X_M_ProductionLine { MTransaction matTrx = null; BigDecimal qtyToMove = getMovementQty().negate(); - for (int sl = 0; sl < storages.length; sl++) { - - BigDecimal lineQty = storages[sl].getQtyOnHand(); - - if (log.isLoggable(Level.FINE))log.log(Level.FINE, "QtyAvailable " + lineQty ); - if (lineQty.signum() > 0) - { - if (lineQty.compareTo(qtyToMove ) > 0) - lineQty = qtyToMove; - - MAttributeSetInstance slASI = new MAttributeSetInstance(getCtx(), - storages[sl].getM_AttributeSetInstance_ID(),get_TrxName()); - String slASIString = slASI.getDescription(); - if (slASIString == null) - slASIString = ""; + if (qtyToMove.signum() > 0) { + for (int sl = 0; sl < storages.length; sl++) { + + BigDecimal lineQty = storages[sl].getQtyOnHand(); - if (log.isLoggable(Level.FINEST))log.log(Level.FINEST,"slASI-Description =" + slASIString); - - if ( slASIString.compareTo(asiString) == 0 - || asi.getM_AttributeSet_ID() == 0 ) - //storage matches specified ASI or is a costing asi (inc. 0) - // This process will move negative stock on hand quantities + if (log.isLoggable(Level.FINE))log.log(Level.FINE, "QtyAvailable " + lineQty ); + if (lineQty.signum() > 0) { - lineMA = MProductionLineMA.get(this,storages[sl].getM_AttributeSetInstance_ID(),storages[sl].getDateMaterialPolicy()); - lineMA.setMovementQty(lineMA.getMovementQty().add(lineQty.negate())); - if ( !lineMA.save(get_TrxName()) ) { - log.log(Level.SEVERE, "Could not save MA for " + toString()); - errorString.append("Could not save MA for " + toString() + "\n" ); - } else { - if (log.isLoggable(Level.FINE))log.log(Level.FINE, "Saved MA for " + toString()); + if (lineQty.compareTo(qtyToMove ) > 0) + lineQty = qtyToMove; + + MAttributeSetInstance slASI = new MAttributeSetInstance(getCtx(), + storages[sl].getM_AttributeSetInstance_ID(),get_TrxName()); + String slASIString = slASI.getDescription(); + if (slASIString == null) + slASIString = ""; + + if (log.isLoggable(Level.FINEST))log.log(Level.FINEST,"slASI-Description =" + slASIString); + + if ( slASIString.compareTo(asiString) == 0 + || asi.getM_AttributeSet_ID() == 0 ) + //storage matches specified ASI or is a costing asi (inc. 0) + // This process will move negative stock on hand quantities + { + lineMA = MProductionLineMA.get(this,storages[sl].getM_AttributeSetInstance_ID(),storages[sl].getDateMaterialPolicy()); + lineMA.setMovementQty(lineMA.getMovementQty().add(lineQty.negate())); + if ( !lineMA.save(get_TrxName()) ) { + log.log(Level.SEVERE, "Could not save MA for " + toString()); + errorString.append("Could not save MA for " + toString() + "\n" ); + } else { + if (log.isLoggable(Level.FINE))log.log(Level.FINE, "Saved MA for " + toString()); + } + matTrx = new MTransaction (getCtx(), getAD_Org_ID(), + "P-", + getM_Locator_ID(), getM_Product_ID(), asi.get_ID(), + lineQty.negate(), date, get_TrxName()); + matTrx.setM_ProductionLine_ID(get_ID()); + if ( !matTrx.save(get_TrxName()) ) { + log.log(Level.SEVERE, "Could not save transaction for " + toString()); + errorString.append("Could not save transaction for " + toString() + "\n"); + } else { + if (log.isLoggable(Level.FINE))log.log(Level.FINE, "Saved transaction for " + toString()); + } + storages[sl].changeQtyOnHand(lineQty, false); + if ( !storages[sl].save(get_TrxName()) ) { + log.log(Level.SEVERE, "Could not update storage for " + toString()); + errorString.append("Could not update storage for " + toString() + "\n"); + } + qtyToMove = qtyToMove.subtract(lineQty); + if (log.isLoggable(Level.FINE))log.log(Level.FINE, getLine() + " Qty moved = " + lineQty + ", Remaining = " + qtyToMove ); } - matTrx = new MTransaction (getCtx(), getAD_Org_ID(), - "P-", - getM_Locator_ID(), getM_Product_ID(), asi.get_ID(), - lineQty.negate(), date, get_TrxName()); - matTrx.setM_ProductionLine_ID(get_ID()); - if ( !matTrx.save(get_TrxName()) ) { - log.log(Level.SEVERE, "Could not save transaction for " + toString()); - errorString.append("Could not save transaction for " + toString() + "\n"); - } else { - if (log.isLoggable(Level.FINE))log.log(Level.FINE, "Saved transaction for " + toString()); - } - storages[sl].changeQtyOnHand(lineQty, false); - if ( !storages[sl].save(get_TrxName()) ) { - log.log(Level.SEVERE, "Could not update storage for " + toString()); - errorString.append("Could not update storage for " + toString() + "\n"); - } - qtyToMove = qtyToMove.subtract(lineQty); - if (log.isLoggable(Level.FINE))log.log(Level.FINE, getLine() + " Qty moved = " + lineQty + ", Remaining = " + qtyToMove ); } - } - - if ( qtyToMove.signum() == 0 ) - break; - - } // for available storages + + if ( qtyToMove.signum() == 0 ) + break; + + } // for available storages + } if ( !( qtyToMove.signum() == 0) ) { - if (mustBeStocked) + if (mustBeStocked && qtyToMove.signum() > 0) { MLocator loc = new MLocator(getCtx(), getM_Locator_ID(), get_TrxName()); errorString.append( "Insufficient qty on hand of " + prod.toString() + " at " @@ -252,6 +260,16 @@ public class MProductionLine extends X_M_ProductionLine { } + private int getEndProduct_ID() { + if (productionParent != null) { + return productionParent.getM_Product_ID(); + } else if (getM_Production_ID() > 0) { + return getM_Production().getM_Product_ID(); + } else { + return getM_ProductionPlan().getM_Product_ID(); + } + } + private int deleteMA() { String sql = "DELETE FROM M_ProductionLineMA WHERE M_ProductionLine_ID = " + get_ID(); int count = DB.executeUpdateEx( sql, get_TrxName() ); @@ -266,14 +284,26 @@ public class MProductionLine extends X_M_ProductionLine { } @Override - protected boolean beforeSave(boolean newRecord) { - if (parent == null ) - parent = new MProduction(getCtx(), getM_Production_ID(), get_TrxName()); + protected boolean beforeSave(boolean newRecord) + { + if (productionParent == null && getM_Production_ID() > 0) + productionParent = new MProduction(getCtx(), getM_Production_ID(), get_TrxName()); - if ( parent.getM_Product_ID() == getM_Product_ID() && parent.getProductionQty().signum() == getMovementQty().signum()) - setIsEndProduct(true); + if (getM_Production_ID() > 0) + { + if ( productionParent.getM_Product_ID() == getM_Product_ID() && productionParent.getProductionQty().signum() == getMovementQty().signum()) + setIsEndProduct(true); + else + setIsEndProduct(false); + } else - setIsEndProduct(false); + { + I_M_ProductionPlan plan = getM_ProductionPlan(); + if (plan.getM_Product_ID() == getM_Product_ID() && plan.getProductionQty().signum() == getMovementQty().signum()) + setIsEndProduct(true); + else + setIsEndProduct(false); + } if ( isEndProduct() && getM_AttributeSetInstance_ID() != 0 ) { @@ -295,6 +325,7 @@ public class MProductionLine extends X_M_ProductionLine { { setMovementQty(getQtyUsed().negate()); } + return true; } diff --git a/org.adempiere.base/src/org/compiere/model/MProductionPlan.java b/org.adempiere.base/src/org/compiere/model/MProductionPlan.java new file mode 100644 index 0000000000..00f3a48bf9 --- /dev/null +++ b/org.adempiere.base/src/org/compiere/model/MProductionPlan.java @@ -0,0 +1,313 @@ +/** + * + */ +package org.compiere.model; + +import java.math.BigDecimal; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Properties; + +import org.adempiere.exceptions.AdempiereException; +import org.compiere.util.AdempiereUserError; +import org.compiere.util.DB; +import org.compiere.util.Env; + +/** + * @author hengsin + * + */ +public class MProductionPlan extends X_M_ProductionPlan { + + /** + * generated serial id + */ + private static final long serialVersionUID = -8189507724698695756L; + + /** + * @param ctx + * @param M_ProductionPlan_ID + * @param trxName + */ + public MProductionPlan(Properties ctx, int M_ProductionPlan_ID, + String trxName) { + super(ctx, M_ProductionPlan_ID, trxName); + } + + /** + * @param ctx + * @param rs + * @param trxName + */ + public MProductionPlan(Properties ctx, ResultSet rs, String trxName) { + super(ctx, rs, trxName); + } + + public MProductionLine[] getLines() { + ArrayList list = new ArrayList(); + + String sql = "SELECT pl.M_ProductionLine_ID " + + "FROM M_ProductionLine pl " + + "WHERE pl.M_ProductionPlan_ID = ?"; + + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, get_ID()); + rs = pstmt.executeQuery(); + while (rs.next()) + list.add( new MProductionLine( getCtx(), rs.getInt(1), get_TrxName() ) ); + } + catch (SQLException ex) + { + throw new AdempiereException("Unable to load production lines", ex); + } + finally + { + DB.close(rs, pstmt); + rs = null; + pstmt = null; + } + + MProductionLine[] retValue = new MProductionLine[list.size()]; + list.toArray(retValue); + return retValue; + } + + public void deleteLines(String trxName) { + + for (MProductionLine line : getLines()) + { + line.deleteEx(true); + } + + }// deleteLines + + public int createLines(boolean mustBeStocked) { + + int lineno = 100; + + int count = 0; + + // product to be produced + MProduct finishedProduct = new MProduct(getCtx(), getM_Product_ID(), get_TrxName()); + + + MProductionLine line = new MProductionLine( this ); + line.setLine( lineno ); + line.setM_Product_ID( finishedProduct.get_ID() ); + line.setM_Locator_ID( getM_Locator_ID() ); + line.setMovementQty( getProductionQty()); + line.setPlannedQty(getProductionQty()); + + line.saveEx(); + count++; + + count = count + createLines(mustBeStocked, finishedProduct, getProductionQty(), lineno); + + return count; + } + + private int createLines(boolean mustBeStocked, MProduct finishedProduct, BigDecimal requiredQty, int lineno) { + + int count = 0; + int defaultLocator = 0; + + MLocator finishedLocator = MLocator.get(getCtx(), getM_Locator_ID()); + + int M_Warehouse_ID = finishedLocator.getM_Warehouse_ID(); + + int asi = 0; + + // products used in production + String sql = "SELECT M_ProductBom_ID, BOMQty" + " FROM M_Product_BOM" + + " WHERE M_Product_ID=" + finishedProduct.getM_Product_ID() + " ORDER BY Line"; + + PreparedStatement pstmt = null; + ResultSet rs = null; + + try { + pstmt = DB.prepareStatement(sql, get_TrxName()); + + rs = pstmt.executeQuery(); + while (rs.next()) { + + lineno = lineno + 10; + int BOMProduct_ID = rs.getInt(1); + BigDecimal BOMQty = rs.getBigDecimal(2); + BigDecimal BOMMovementQty = BOMQty.multiply(requiredQty); + + MProduct bomproduct = new MProduct(Env.getCtx(), BOMProduct_ID, get_TrxName()); + + + if ( bomproduct.isBOM() && bomproduct.isPhantom() ) + { + count = count + createLines(mustBeStocked, bomproduct, BOMMovementQty, lineno); + } + else + { + + defaultLocator = bomproduct.getM_Locator_ID(); + if ( defaultLocator == 0 ) + defaultLocator = getM_Locator_ID(); + + if (!bomproduct.isStocked()) + { + MProductionLine BOMLine = null; + BOMLine = new MProductionLine( this ); + BOMLine.setLine( lineno ); + BOMLine.setM_Product_ID( BOMProduct_ID ); + BOMLine.setM_Locator_ID( defaultLocator ); + BOMLine.setQtyUsed(BOMMovementQty ); + BOMLine.setPlannedQty( BOMMovementQty ); + BOMLine.saveEx(get_TrxName()); + + lineno = lineno + 10; + count++; + } + else if (BOMMovementQty.signum() == 0) + { + MProductionLine BOMLine = null; + BOMLine = new MProductionLine( this ); + BOMLine.setLine( lineno ); + BOMLine.setM_Product_ID( BOMProduct_ID ); + BOMLine.setM_Locator_ID( defaultLocator ); + BOMLine.setQtyUsed( BOMMovementQty ); + BOMLine.setPlannedQty( BOMMovementQty ); + BOMLine.saveEx(get_TrxName()); + + lineno = lineno + 10; + count++; + } + else + { + + // BOM stock info + MStorageOnHand[] storages = null; + MProduct usedProduct = MProduct.get(getCtx(), BOMProduct_ID); + defaultLocator = usedProduct.getM_Locator_ID(); + if ( defaultLocator == 0 ) + defaultLocator = getM_Locator_ID(); + if (usedProduct == null || usedProduct.get_ID() == 0) + return 0; + + MClient client = MClient.get(getCtx()); + MProductCategory pc = MProductCategory.get(getCtx(), + usedProduct.getM_Product_Category_ID()); + String MMPolicy = pc.getMMPolicy(); + if (MMPolicy == null || MMPolicy.length() == 0) + { + MMPolicy = client.getMMPolicy(); + } + + storages = MStorageOnHand.getWarehouse(getCtx(), M_Warehouse_ID, BOMProduct_ID, 0, null, + MProductCategory.MMPOLICY_FiFo.equals(MMPolicy), true, 0, get_TrxName()); + + MProductionLine BOMLine = null; + int prevLoc = -1; + int previousAttribSet = -1; + // Create lines from storage until qty is reached + for (int sl = 0; sl < storages.length; sl++) { + + BigDecimal lineQty = storages[sl].getQtyOnHand(); + if (lineQty.signum() != 0) { + if (lineQty.compareTo(BOMMovementQty) > 0) + lineQty = BOMMovementQty; + + + int loc = storages[sl].getM_Locator_ID(); + int slASI = storages[sl].getM_AttributeSetInstance_ID(); + int locAttribSet = new MAttributeSetInstance(getCtx(), asi, + get_TrxName()).getM_AttributeSet_ID(); + + // roll up costing attributes if in the same locator + if (locAttribSet == 0 && previousAttribSet == 0 + && prevLoc == loc) { + BOMLine.setQtyUsed(BOMLine.getQtyUsed() + .add(lineQty)); + BOMLine.setPlannedQty(BOMLine.getQtyUsed()); + BOMLine.saveEx(get_TrxName()); + + } + // otherwise create new line + else { + BOMLine = new MProductionLine( this ); + BOMLine.setLine( lineno ); + BOMLine.setM_Product_ID( BOMProduct_ID ); + BOMLine.setM_Locator_ID( loc ); + BOMLine.setQtyUsed( lineQty); + BOMLine.setPlannedQty( lineQty); + if ( slASI != 0 && locAttribSet != 0 ) // ie non costing attribute + BOMLine.setM_AttributeSetInstance_ID(slASI); + BOMLine.saveEx(get_TrxName()); + + lineno = lineno + 10; + count++; + } + prevLoc = loc; + previousAttribSet = locAttribSet; + // enough ? + BOMMovementQty = BOMMovementQty.subtract(lineQty); + if (BOMMovementQty.signum() == 0) + break; + } + } // for available storages + + // fallback + if (BOMMovementQty.signum() != 0 ) { + if (!mustBeStocked) + { + + // roll up costing attributes if in the same locator + if ( previousAttribSet == 0 + && prevLoc == defaultLocator) { + BOMLine.setQtyUsed(BOMLine.getQtyUsed() + .add(BOMMovementQty)); + BOMLine.setPlannedQty(BOMLine.getQtyUsed()); + BOMLine.saveEx(get_TrxName()); + + } + // otherwise create new line + else { + + BOMLine = new MProductionLine( this ); + BOMLine.setLine( lineno ); + BOMLine.setM_Product_ID( BOMProduct_ID ); + BOMLine.setM_Locator_ID( defaultLocator ); + BOMLine.setQtyUsed( BOMMovementQty); + BOMLine.setPlannedQty( BOMMovementQty); + BOMLine.saveEx(get_TrxName()); + + lineno = lineno + 10; + count++; + } + + } + else + { + throw new AdempiereUserError("Not enough stock of " + BOMProduct_ID); + } + } + } + } + } // for all bom products + } catch (Exception e) { + throw new AdempiereException("Failed to create production lines", e); + } + finally { + DB.close(rs, pstmt); + } + + return count; + } + + @Override + protected boolean beforeDelete() { + deleteLines(get_TrxName()); + return true; + } +} diff --git a/org.adempiere.base/src/org/compiere/model/X_M_Production.java b/org.adempiere.base/src/org/compiere/model/X_M_Production.java index 6571b12e96..3f909d69a6 100644 --- a/org.adempiere.base/src/org/compiere/model/X_M_Production.java +++ b/org.adempiere.base/src/org/compiere/model/X_M_Production.java @@ -33,7 +33,7 @@ public class X_M_Production extends PO implements I_M_Production, I_Persistent /** * */ - private static final long serialVersionUID = 20131031L; + private static final long serialVersionUID = 20140212L; /** Standard Constructor */ public X_M_Production (Properties ctx, int M_Production_ID, String trxName) @@ -43,6 +43,8 @@ public class X_M_Production extends PO implements I_M_Production, I_Persistent { setDocumentNo (null); setIsCreated (null); +// N + setIsUseProductionPlan (false); // N setM_Locator_ID (0); setMovementDate (new Timestamp( System.currentTimeMillis() )); @@ -361,6 +363,27 @@ public class X_M_Production extends PO implements I_M_Production, I_Persistent return (String)get_Value(COLUMNNAME_IsCreated); } + /** Set Use Production Plan. + @param IsUseProductionPlan Use Production Plan */ + public void setIsUseProductionPlan (boolean IsUseProductionPlan) + { + set_Value (COLUMNNAME_IsUseProductionPlan, Boolean.valueOf(IsUseProductionPlan)); + } + + /** Get Use Production Plan. + @return Use Production Plan */ + public boolean isUseProductionPlan () + { + Object oo = get_Value(COLUMNNAME_IsUseProductionPlan); + if (oo != null) + { + if (oo instanceof Boolean) + return ((Boolean)oo).booleanValue(); + return "Y".equals(oo); + } + return false; + } + public I_M_Locator getM_Locator() throws RuntimeException { return (I_M_Locator)MTable.get(getCtx(), I_M_Locator.Table_Name)