IDEMPIERE-5331 Create Production from Order (all Lines) (#1375)

* IDEMPIERE-5331 Create Production from Order (all Lines)

* Refactoring to remove redundant or unused code and parameters

* Clear the order line reference on production when voiding and reversing
This commit is contained in:
Carlos Ruiz 2022-06-30 04:05:33 +02:00 committed by GitHub
parent ddaf0d6af3
commit 7246c56266
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 219 additions and 41 deletions

View File

@ -0,0 +1,22 @@
-- IDEMPIERE-5331 Create Production from Order Lines
SELECT register_migration_script('202206271645_IDEMPIERE-5331.sql') FROM dual;
SET SQLBLANKLINES ON
SET DEFINE OFF
-- Jun 27, 2022, 4:45:47 PM CEST
UPDATE AD_Process SET Name='Create Production from Order Line', Description='Create Production for single ordered product',Updated=TO_TIMESTAMP('2022-06-27 16:45:47','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_ID=200006
;
-- Jun 27, 2022, 4:46:09 PM CEST
UPDATE AD_Process SET Name='Create Shipment from Order Line',Updated=TO_TIMESTAMP('2022-06-27 16:46:09','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_ID=200007
;
-- Jun 27, 2022, 4:46:53 PM CEST
INSERT INTO AD_Process (AD_Process_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,IsReport,Value,IsDirectPrint,Classname,AccessLevel,EntityType,Statistic_Count,Statistic_Seconds,IsBetaFunctionality,ShowHelp,CopyFromProcess,AD_Process_UU) VALUES (200138,0,0,'Y',TO_TIMESTAMP('2022-06-27 16:46:53','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-06-27 16:46:53','YYYY-MM-DD HH24:MI:SS'),100,'Create Production from Order','Create Production for BOM ordered products','N','C_Order_CreateProduction','N','org.compiere.process.OrderCreateProduction','3','D',0,0,'N','S','N','4d1322d4-df18-4cab-a280-82b1c14f35fd')
;
-- Jun 27, 2022, 4:51:04 PM CEST
INSERT INTO AD_ToolBarButton (AD_Client_ID,AD_Org_ID,Created,CreatedBy,ComponentName,IsActive,AD_ToolBarButton_ID,Name,Updated,UpdatedBy,IsCustomization,AD_ToolBarButton_UU,Action,AD_Tab_ID,AD_Process_ID,DisplayLogic,SeqNo,EntityType) VALUES (0,0,TO_TIMESTAMP('2022-06-27 16:51:04','YYYY-MM-DD HH24:MI:SS'),100,'C_Order_CreateProduction','Y',200122,'C_Order_CreateProduction',TO_TIMESTAMP('2022-06-27 16:51:04','YYYY-MM-DD HH24:MI:SS'),100,'N','9ffb3433-7c04-4d35-bd31-681fa70feb29','W',186,200138,'@SQL=SELECT 1 FROM C_OrderLine ol JOIN M_Product p ON (ol.M_Product_ID=p.M_Product_ID) WHERE ol.C_Order_ID=@C_Order_ID:0@ AND ol.Processed=''Y'' AND p.IsBOM=''Y''',10,'D')
;

View File

@ -0,0 +1,19 @@
-- IDEMPIERE-5331 Create Production from Order Lines
SELECT register_migration_script('202206271645_IDEMPIERE-5331.sql') FROM dual;
-- Jun 27, 2022, 4:45:47 PM CEST
UPDATE AD_Process SET Name='Create Production from Order Line', Description='Create Production for single ordered product',Updated=TO_TIMESTAMP('2022-06-27 16:45:47','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_ID=200006
;
-- Jun 27, 2022, 4:46:09 PM CEST
UPDATE AD_Process SET Name='Create Shipment from Order Line',Updated=TO_TIMESTAMP('2022-06-27 16:46:09','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Process_ID=200007
;
-- Jun 27, 2022, 4:46:53 PM CEST
INSERT INTO AD_Process (AD_Process_ID,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,Name,Description,IsReport,Value,IsDirectPrint,Classname,AccessLevel,EntityType,Statistic_Count,Statistic_Seconds,IsBetaFunctionality,ShowHelp,CopyFromProcess,AD_Process_UU) VALUES (200138,0,0,'Y',TO_TIMESTAMP('2022-06-27 16:46:53','YYYY-MM-DD HH24:MI:SS'),100,TO_TIMESTAMP('2022-06-27 16:46:53','YYYY-MM-DD HH24:MI:SS'),100,'Create Production from Order','Create Production for BOM ordered products','N','C_Order_CreateProduction','N','org.compiere.process.OrderCreateProduction','3','D',0,0,'N','S','N','4d1322d4-df18-4cab-a280-82b1c14f35fd')
;
-- Jun 27, 2022, 4:51:04 PM CEST
INSERT INTO AD_ToolBarButton (AD_Client_ID,AD_Org_ID,Created,CreatedBy,ComponentName,IsActive,AD_ToolBarButton_ID,Name,Updated,UpdatedBy,IsCustomization,AD_ToolBarButton_UU,"action",AD_Tab_ID,AD_Process_ID,DisplayLogic,SeqNo,EntityType) VALUES (0,0,TO_TIMESTAMP('2022-06-27 16:51:04','YYYY-MM-DD HH24:MI:SS'),100,'C_Order_CreateProduction','Y',200122,'C_Order_CreateProduction',TO_TIMESTAMP('2022-06-27 16:51:04','YYYY-MM-DD HH24:MI:SS'),100,'N','9ffb3433-7c04-4d35-bd31-681fa70feb29','W',186,200138,'@SQL=SELECT 1 FROM C_OrderLine ol JOIN M_Product p ON (ol.M_Product_ID=p.M_Product_ID) WHERE ol.C_Order_ID=@C_Order_ID:0@ AND ol.Processed=''Y'' AND p.IsBOM=''Y''',10,'D')
;

View File

@ -0,0 +1,162 @@
/***********************************************************************
* 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: *
* - Carlos Ruiz - globalqss - bxservice *
**********************************************************************/
package org.compiere.process;
import java.util.List;
import java.util.logging.Level;
import org.compiere.model.MDocType;
import org.compiere.model.MOrder;
import org.compiere.model.MOrderLine;
import org.compiere.model.MProduct;
import org.compiere.model.MProduction;
import org.compiere.model.MWarehouse;
import org.compiere.model.Query;
import org.compiere.util.Env;
import org.compiere.util.Msg;
/**
*
* @author Carlos Ruiz - globalqss - bxservice
*
*/
@org.adempiere.base.annotation.Process
public class OrderCreateProduction extends SvrProcess {
/** Order */
private int p_C_Order_ID = 0;
/**
* Prepare - e.g., get Parameters.
*/
protected void prepare() {
p_C_Order_ID = getRecord_ID();
} // prepare
/**
* Create Production for BOM products of an order
*
* @throws Exception
*/
protected String doIt() throws Exception {
if (log.isLoggable(Level.INFO))
log.info("C_Order_ID=" + p_C_Order_ID);
if (p_C_Order_ID == 0)
throw new IllegalArgumentException("No Order");
//
MOrder order = new MOrder(getCtx(), p_C_Order_ID, get_TrxName());
if (order.get_ID() == 0)
throw new IllegalArgumentException("Order not found");
if (!MOrder.DOCSTATUS_Completed.equals(order.getDocStatus()))
throw new IllegalArgumentException("Order not completed");
final String where = "C_OrderLine.C_Order_ID=?"
+ " AND C_OrderLine.Processed='Y'"
+ " AND p.IsBOM='Y'"
+ " AND p.IsVerified='Y'"
+ " AND NOT EXISTS (SELECT 1 FROM M_Production pr WHERE pr.C_OrderLine_ID=C_OrderLine.C_OrderLine_ID)";
List<MOrderLine> lines = new Query(getCtx(), MOrderLine.Table_Name, where, get_TrxName())
.addJoinClause("JOIN M_Product p ON (C_OrderLine.M_Product_ID=p.M_Product_ID)")
.setOnlyActiveRecords(true)
.setParameters(p_C_Order_ID)
.list();
MDocType doc = new MDocType(getCtx(), order.getC_DocType_ID(), get_TrxName());
int cnt = 0;
for (MOrderLine line : lines) {
if ((line.getQtyOrdered().subtract(line.getQtyDelivered())).compareTo(Env.ZERO) <= 0) {
if (!doc.getDocSubTypeSO().equals("ON")) { // Consignment and stock orders both have subtype of ON
continue;
}
}
MProduction production = new MProduction(line);
MProduct product = new MProduct(getCtx(), line.getM_Product_ID(), get_TrxName());
production.setM_Product_ID(line.getM_Product_ID());
production.setProductionQty(line.getQtyOrdered().subtract(line.getQtyDelivered()));
production.setDatePromised(line.getDatePromised());
production.setC_OrderLine_ID(line.getC_OrderLine_ID());
int locator = product.getM_Locator_ID();
if (locator == 0)
locator = MWarehouse.get(getCtx(), line.getM_Warehouse_ID()).getDefaultLocator().get_ID();
production.setM_Locator_ID(locator);
if (line.getC_BPartner_ID() > 0) {
production.setC_BPartner_ID(order.getC_BPartner_ID());
}
if (line.getC_Project_ID() > 0) {
production.setC_Project_ID(line.getC_Project_ID());
} else {
production.setC_Project_ID(order.getC_Project_ID());
}
if (line.getC_Campaign_ID() > 0) {
production.setC_Campaign_ID(line.getC_Campaign_ID());
} else {
production.setC_Campaign_ID(order.getC_Campaign_ID());
}
if (line.getC_Activity_ID() > 0) {
production.setC_Activity_ID(line.getC_Activity_ID());
} else {
production.setC_Activity_ID(order.getC_Activity_ID());
}
if (line.getUser1_ID() > 0) {
production.setUser1_ID(line.getUser1_ID());
} else {
production.setUser1_ID(order.getUser1_ID());
}
if (line.getUser2_ID() > 0) {
production.setUser2_ID(line.getUser2_ID());
} else {
production.setUser2_ID(order.getUser2_ID());
}
if (line.getAD_OrgTrx_ID() > 0) {
production.setAD_OrgTrx_ID(line.getAD_OrgTrx_ID());
} else {
production.setAD_OrgTrx_ID(order.getAD_OrgTrx_ID());
}
production.saveEx();
production.createLines(false);
production.setIsCreated("Y");
production.saveEx();
String msg = Msg.parseTranslation(getCtx(), "@M_Production_ID@ @Created@ " + production.getDocumentNo());
addBufferLog(production.getM_Production_ID(), null, null, msg, MProduction.Table_ID, production.getM_Production_ID());
cnt++;
}
return "@Created@ " + cnt;
}
} // OrderCreateShipment

View File

@ -16,7 +16,6 @@
*****************************************************************************/ *****************************************************************************/
package org.compiere.process; package org.compiere.process;
import java.sql.Timestamp;
import java.util.logging.Level; import java.util.logging.Level;
import org.compiere.model.MDocType; import org.compiere.model.MDocType;
@ -30,7 +29,7 @@ import org.compiere.util.Env;
import org.compiere.util.Msg; import org.compiere.util.Msg;
/** /**
* Create (Generate) Invoice from Shipment * Create (Generate) Production from OrderLine
* *
* @author Jorg Janke * @author Jorg Janke
* @version $Id: OrderLineCreateProduction.java,v 1.1 2007/07/23 05:34:35 mfuggle Exp $ * @version $Id: OrderLineCreateProduction.java,v 1.1 2007/07/23 05:34:35 mfuggle Exp $
@ -38,35 +37,14 @@ import org.compiere.util.Msg;
@org.adempiere.base.annotation.Process @org.adempiere.base.annotation.Process
public class OrderLineCreateProduction extends SvrProcess public class OrderLineCreateProduction extends SvrProcess
{ {
/** Shipment */ /** Order Line */
private int p_C_OrderLine_ID = 0; private int p_C_OrderLine_ID = 0;
private Timestamp p_MovementDate = null;
private boolean ignorePrevProduction = false;
/** /**
* Prepare - e.g., get Parameters. * Prepare - e.g., get Parameters.
*/ */
protected void prepare() protected void prepare()
{ {
ProcessInfoParameter[] para = getParameter();
for (int i = 0; i < para.length; i++)
{
String name = para[i].getParameterName();
if (para[i].getParameter() == null)
;
if (name.equals("MovementDate"))
p_MovementDate = (Timestamp) para[i].getParameter();
else if (name.equals("IgnorePrevProduction"))
ignorePrevProduction = "Y".equals(para[i].getParameter());
else
log.log(Level.SEVERE, "Unknown Parameter: " + name);
}
if (p_MovementDate == null)
p_MovementDate = Env.getContextAsDate(getCtx(), Env.DATE);
if ( p_MovementDate==null)
p_MovementDate = new Timestamp(System.currentTimeMillis());
p_C_OrderLine_ID = getRecord_ID(); p_C_OrderLine_ID = getRecord_ID();
} // prepare } // prepare
@ -97,11 +75,6 @@ public class OrderLineCreateProduction extends SvrProcess
} }
} }
// If we don't ignore previous production, and there has been a previous one,
//throw an exception
if (!ignorePrevProduction)
{
String docNo = DB.getSQLValueString(get_TrxName(), String docNo = DB.getSQLValueString(get_TrxName(),
"SELECT max(DocumentNo) " + "SELECT max(DocumentNo) " +
"FROM M_Production WHERE C_OrderLine_ID = ?", "FROM M_Production WHERE C_OrderLine_ID = ?",
@ -109,8 +82,6 @@ public class OrderLineCreateProduction extends SvrProcess
if (docNo != null) if (docNo != null)
{ {
throw new IllegalArgumentException(Msg.getMsg(Env.getCtx(), "ProductionHasAlreadyBeenCreated", new String[] {docNo})); throw new IllegalArgumentException(Msg.getMsg(Env.getCtx(), "ProductionHasAlreadyBeenCreated", new String[] {docNo}));
}
} }
MProduction production = new MProduction( line ); MProduction production = new MProduction( line );
@ -119,8 +90,6 @@ public class OrderLineCreateProduction extends SvrProcess
production.setM_Product_ID(line.getM_Product_ID()); production.setM_Product_ID(line.getM_Product_ID());
production.setProductionQty(line.getQtyOrdered().subtract(line.getQtyDelivered())); production.setProductionQty(line.getQtyOrdered().subtract(line.getQtyDelivered()));
production.setDatePromised(line.getDatePromised()); production.setDatePromised(line.getDatePromised());
if ( product.getM_Locator_ID() > 0 )
production.setM_Locator_ID(product.getM_Locator_ID());
production.setC_OrderLine_ID(p_C_OrderLine_ID); production.setC_OrderLine_ID(p_C_OrderLine_ID);
int locator = product.getM_Locator_ID(); int locator = product.getM_Locator_ID();
@ -177,6 +146,6 @@ public class OrderLineCreateProduction extends SvrProcess
String msg = Msg.parseTranslation(getCtx(), "@M_Production_ID@ @Created@ " + production.getDocumentNo()); String msg = Msg.parseTranslation(getCtx(), "@M_Production_ID@ @Created@ " + production.getDocumentNo());
addLog(production.getM_Production_ID(), null, null, msg, MProduction.Table_ID, production.getM_Production_ID()); addLog(production.getM_Production_ID(), null, null, msg, MProduction.Table_ID, production.getM_Production_ID());
return "@OK@"; return "@OK@";
} // OrderLineCreateShipment }
} // OrderLineCreateShipment } // OrderLineCreateShipment

View File

@ -659,6 +659,9 @@ public class MProduction extends X_M_Production implements DocAction {
return reverseCorrectIt(); return reverseCorrectIt();
} }
if (getC_OrderLine_ID() > 0)
setC_OrderLine_ID(0);
// After Void // After Void
m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_VOID); m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_VOID);
if (m_processMsg != null) if (m_processMsg != null)
@ -716,6 +719,9 @@ public class MProduction extends X_M_Production implements DocAction {
reversalDate = new Timestamp(System.currentTimeMillis()); reversalDate = new Timestamp(System.currentTimeMillis());
} }
if (getC_OrderLine_ID() > 0)
setC_OrderLine_ID(0);
MPeriod.testPeriodOpen(getCtx(), reversalDate, Doc.DOCTYPE_MatProduction, getAD_Org_ID()); MPeriod.testPeriodOpen(getCtx(), reversalDate, Doc.DOCTYPE_MatProduction, getAD_Org_ID());
MProduction reversal = null; MProduction reversal = null;
reversal = copyFrom (reversalDate); reversal = copyFrom (reversalDate);