diff --git a/base/src/org/compiere/model/MInOut.java b/base/src/org/compiere/model/MInOut.java index 0a98c9e6d3..4fde7bb972 100644 --- a/base/src/org/compiere/model/MInOut.java +++ b/base/src/org/compiere/model/MInOut.java @@ -1,480 +1,480 @@ -/****************************************************************************** - * Product: Adempiere ERP & CRM Smart Business Solution * - * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * - * 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. * - * For the text or an alternative of this public license, you may reach us * - * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * - * or via info@compiere.org or http://www.compiere.org/license.html * - *****************************************************************************/ -package org.compiere.model; - -import java.io.File; -import java.math.BigDecimal; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Timestamp; -import java.util.ArrayList; -import java.util.Properties; -import java.util.logging.Level; - -import org.compiere.print.ReportEngine; -import org.compiere.process.DocAction; -import org.compiere.process.DocumentEngine; -import org.compiere.util.CLogger; -import org.compiere.util.DB; -import org.compiere.util.Env; -import org.compiere.util.Msg; - -/** - * Shipment Model - * - * @author Jorg Janke - * @version $Id: MInOut.java,v 1.4 2006/07/30 00:51:03 jjanke Exp $ - * - * Modifications: Added the RMA functionality (Ashley Ramdass) - * @author Karsten Thiemann, Schaeffer AG - *
  • Bug [ 1759431 ] Problems with VCreateFrom - * @author victor.perez@e-evolution.com, e-Evolution http://www.e-evolution.com - *
  • FR [ 1948157 ] Is necessary the reference for document reverse - *
  • FR [ 2520591 ] Support multiples calendar for Org - * @see http://sourceforge.net/tracker2/?func=detail&atid=879335&aid=2520591&group_id=176962 - * @author Armen Rizal, Goodwill Consulting - *
  • BF [ 1745154 ] Cost in Reversing Material Related Docs - * @see http://sourceforge.net/tracker/?func=detail&atid=879335&aid=1948157&group_id=176962 - */ -public class MInOut extends X_M_InOut implements DocAction -{ - /** - * - */ - private static final long serialVersionUID = -1222763355238200128L; - - - /** - * Create Shipment From Order - * @param order order - * @param movementDate optional movement date - * @param forceDelivery ignore order delivery rule - * @param allAttributeInstances if true, all attribute set instances - * @param minGuaranteeDate optional minimum guarantee date if all attribute instances - * @param complete complete document (Process if false, Complete if true) - * @param trxName transaction - * @return Shipment or null - */ - public static MInOut createFrom (MOrder order, Timestamp movementDate, - boolean forceDelivery, boolean allAttributeInstances, Timestamp minGuaranteeDate, - boolean complete, String trxName) - { - if (order == null) - throw new IllegalArgumentException("No Order"); - // - if (!forceDelivery && DELIVERYRULE_CompleteLine.equals(order.getDeliveryRule())) - { - return null; - } - - // Create Meader - MInOut retValue = new MInOut (order, 0, movementDate); - retValue.setDocAction(complete ? DOCACTION_Complete : DOCACTION_Prepare); - - // Check if we can create the lines - MOrderLine[] oLines = order.getLines(true, "M_Product_ID"); - for (int i = 0; i < oLines.length; i++) - { - BigDecimal qty = oLines[i].getQtyOrdered().subtract(oLines[i].getQtyDelivered()); - // Nothing to deliver - if (qty.signum() == 0) - continue; - // Stock Info - MStorage[] storages = null; - MProduct product = oLines[i].getProduct(); - if (product != null && product.get_ID() != 0 && product.isStocked()) - { - String MMPolicy = product.getMMPolicy(); - storages = MStorage.getWarehouse (order.getCtx(), order.getM_Warehouse_ID(), - oLines[i].getM_Product_ID(), oLines[i].getM_AttributeSetInstance_ID(), - product.getM_AttributeSet_ID(), - allAttributeInstances, minGuaranteeDate, - MClient.MMPOLICY_FiFo.equals(MMPolicy), trxName); - } else { - continue; - } - - if (!forceDelivery) - { - BigDecimal maxQty = Env.ZERO; - for (int ll = 0; ll < storages.length; ll++) - maxQty = maxQty.add(storages[ll].getQtyOnHand()); - if (DELIVERYRULE_Availability.equals(order.getDeliveryRule())) - { - if (maxQty.compareTo(qty) < 0) - qty = maxQty; - } - else if (DELIVERYRULE_CompleteLine.equals(order.getDeliveryRule())) - { - if (maxQty.compareTo(qty) < 0) - continue; - } - } - // Create Line - if (retValue.get_ID() == 0) // not saved yet - retValue.save(trxName); - // Create a line until qty is reached - for (int ll = 0; ll < storages.length; ll++) - { - BigDecimal lineQty = storages[ll].getQtyOnHand(); - if (lineQty.compareTo(qty) > 0) - lineQty = qty; - MInOutLine line = new MInOutLine (retValue); - line.setOrderLine(oLines[i], storages[ll].getM_Locator_ID(), - order.isSOTrx() ? lineQty : Env.ZERO); - line.setQty(lineQty); // Correct UOM for QtyEntered - if (oLines[i].getQtyEntered().compareTo(oLines[i].getQtyOrdered()) != 0) - line.setQtyEntered(lineQty - .multiply(oLines[i].getQtyEntered()) - .divide(oLines[i].getQtyOrdered(), 12, BigDecimal.ROUND_HALF_UP)); - line.setC_Project_ID(oLines[i].getC_Project_ID()); - line.save(trxName); - // Delivered everything ? - qty = qty.subtract(lineQty); - // storage[ll].changeQtyOnHand(lineQty, !order.isSOTrx()); // Credit Memo not considered - // storage[ll].save(get_TrxName()); - if (qty.signum() == 0) - break; - } - } // for all order lines - - // No Lines saved - if (retValue.get_ID() == 0) - return null; - - return retValue; - } // createFrom - - /** - * Create new Shipment by copying - * @param from shipment - * @param dateDoc date of the document date - * @param C_DocType_ID doc type - * @param isSOTrx sales order - * @param counter create counter links - * @param trxName trx - * @param setOrder set the order link - * @return Shipment - */ - public static MInOut copyFrom (MInOut from, Timestamp dateDoc, - int C_DocType_ID, boolean isSOTrx, boolean counter, String trxName, boolean setOrder) - { - MInOut to = new MInOut (from.getCtx(), 0, null); - to.set_TrxName(trxName); - copyValues(from, to, from.getAD_Client_ID(), from.getAD_Org_ID()); - to.set_ValueNoCheck ("M_InOut_ID", I_ZERO); - to.set_ValueNoCheck ("DocumentNo", null); - // - to.setDocStatus (DOCSTATUS_Drafted); // Draft - to.setDocAction(DOCACTION_Complete); - // - to.setC_DocType_ID (C_DocType_ID); - to.setIsSOTrx(isSOTrx); - if (counter) - to.setMovementType (isSOTrx ? MOVEMENTTYPE_CustomerShipment : MOVEMENTTYPE_VendorReceipts); - // - to.setDateOrdered (dateDoc); - to.setDateAcct (dateDoc); - to.setMovementDate(dateDoc); - to.setDatePrinted(null); - to.setIsPrinted (false); - to.setDateReceived(null); - to.setNoPackages(0); - to.setShipDate(null); - to.setPickDate(null); - to.setIsInTransit(false); - // - to.setIsApproved (false); - to.setC_Invoice_ID(0); - to.setTrackingNo(null); - to.setIsInDispute(false); - // - to.setPosted (false); - to.setProcessed (false); - //[ 1633721 ] Reverse Documents- Processing=Y - to.setProcessing(false); - to.setC_Order_ID(0); // Overwritten by setOrder - to.setM_RMA_ID(0); // Overwritten by setOrder - if (counter) - { - to.setC_Order_ID(0); - to.setRef_InOut_ID(from.getM_InOut_ID()); - // Try to find Order/Invoice link - if (from.getC_Order_ID() != 0) - { - MOrder peer = new MOrder (from.getCtx(), from.getC_Order_ID(), from.get_TrxName()); - if (peer.getRef_Order_ID() != 0) - to.setC_Order_ID(peer.getRef_Order_ID()); - } - if (from.getC_Invoice_ID() != 0) - { - MInvoice peer = new MInvoice (from.getCtx(), from.getC_Invoice_ID(), from.get_TrxName()); - if (peer.getRef_Invoice_ID() != 0) - to.setC_Invoice_ID(peer.getRef_Invoice_ID()); - } - } - else - { - to.setRef_InOut_ID(0); - if (setOrder) - { - to.setC_Order_ID(from.getC_Order_ID()); - to.setM_RMA_ID(from.getM_RMA_ID()); // Copy also RMA - } - } - // - if (!to.save(trxName)) - throw new IllegalStateException("Could not create Shipment"); - if (counter) - from.setRef_InOut_ID(to.getM_InOut_ID()); - - if (to.copyLinesFrom(from, counter, setOrder) == 0) - throw new IllegalStateException("Could not create Shipment Lines"); - - return to; - } // copyFrom - - - /************************************************************************** - * Standard Constructor - * @param ctx context - * @param M_InOut_ID - * @param trxName rx name - */ - public MInOut (Properties ctx, int M_InOut_ID, String trxName) - { - super (ctx, M_InOut_ID, trxName); - if (M_InOut_ID == 0) - { - // setDocumentNo (null); - // setC_BPartner_ID (0); - // setC_BPartner_Location_ID (0); - // setM_Warehouse_ID (0); - // setC_DocType_ID (0); - setIsSOTrx (false); - setMovementDate (new Timestamp (System.currentTimeMillis ())); - setDateAcct (getMovementDate()); - // setMovementType (MOVEMENTTYPE_CustomerShipment); - setDeliveryRule (DELIVERYRULE_Availability); - setDeliveryViaRule (DELIVERYVIARULE_Pickup); - setFreightCostRule (FREIGHTCOSTRULE_FreightIncluded); - setDocStatus (DOCSTATUS_Drafted); - setDocAction (DOCACTION_Complete); - setPriorityRule (PRIORITYRULE_Medium); - setNoPackages(0); - setIsInTransit(false); - setIsPrinted (false); - setSendEMail (false); - setIsInDispute(false); - // - setIsApproved(false); - super.setProcessed (false); - setProcessing(false); - setPosted(false); - } - } // MInOut - - /** - * Load Constructor - * @param ctx context - * @param rs result set record - * @param trxName transaction - */ - public MInOut (Properties ctx, ResultSet rs, String trxName) - { - super(ctx, rs, trxName); - } // MInOut - - /** - * Order Constructor - create header only - * @param order order - * @param movementDate optional movement date (default today) - * @param C_DocTypeShipment_ID document type or 0 - */ - public MInOut (MOrder order, int C_DocTypeShipment_ID, Timestamp movementDate) - { - this (order.getCtx(), 0, order.get_TrxName()); - setClientOrg(order); - setC_BPartner_ID (order.getC_BPartner_ID()); - setC_BPartner_Location_ID (order.getC_BPartner_Location_ID()); // shipment address - setAD_User_ID(order.getAD_User_ID()); - // - setM_Warehouse_ID (order.getM_Warehouse_ID()); - setIsSOTrx (order.isSOTrx()); - setMovementType (order.isSOTrx() ? MOVEMENTTYPE_CustomerShipment : MOVEMENTTYPE_VendorReceipts); - if (C_DocTypeShipment_ID == 0) - C_DocTypeShipment_ID = DB.getSQLValue(null, - "SELECT C_DocTypeShipment_ID FROM C_DocType WHERE C_DocType_ID=?", - order.getC_DocType_ID()); - setC_DocType_ID (C_DocTypeShipment_ID); - - // Default - Today - if (movementDate != null) - setMovementDate (movementDate); - setDateAcct (getMovementDate()); - - // Copy from Order - setC_Order_ID(order.getC_Order_ID()); - setDeliveryRule (order.getDeliveryRule()); - setDeliveryViaRule (order.getDeliveryViaRule()); - setM_Shipper_ID(order.getM_Shipper_ID()); - setFreightCostRule (order.getFreightCostRule()); - setFreightAmt(order.getFreightAmt()); - setSalesRep_ID(order.getSalesRep_ID()); - // - setC_Activity_ID(order.getC_Activity_ID()); - setC_Campaign_ID(order.getC_Campaign_ID()); - setC_Charge_ID(order.getC_Charge_ID()); - setChargeAmt(order.getChargeAmt()); - // - setC_Project_ID(order.getC_Project_ID()); - setDateOrdered(order.getDateOrdered()); - setDescription(order.getDescription()); - setPOReference(order.getPOReference()); - setSalesRep_ID(order.getSalesRep_ID()); - setAD_OrgTrx_ID(order.getAD_OrgTrx_ID()); - setUser1_ID(order.getUser1_ID()); - setUser2_ID(order.getUser2_ID()); - setPriorityRule(order.getPriorityRule()); +/****************************************************************************** + * Product: Adempiere ERP & CRM Smart Business Solution * + * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * + * 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. * + * For the text or an alternative of this public license, you may reach us * + * ComPiere, Inc., 2620 Augustine Dr. #245, Santa Clara, CA 95054, USA * + * or via info@compiere.org or http://www.compiere.org/license.html * + *****************************************************************************/ +package org.compiere.model; + +import java.io.File; +import java.math.BigDecimal; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Properties; +import java.util.logging.Level; + +import org.compiere.print.ReportEngine; +import org.compiere.process.DocAction; +import org.compiere.process.DocumentEngine; +import org.compiere.util.CLogger; +import org.compiere.util.DB; +import org.compiere.util.Env; +import org.compiere.util.Msg; + +/** + * Shipment Model + * + * @author Jorg Janke + * @version $Id: MInOut.java,v 1.4 2006/07/30 00:51:03 jjanke Exp $ + * + * Modifications: Added the RMA functionality (Ashley Ramdass) + * @author Karsten Thiemann, Schaeffer AG + *
  • Bug [ 1759431 ] Problems with VCreateFrom + * @author victor.perez@e-evolution.com, e-Evolution http://www.e-evolution.com + *
  • FR [ 1948157 ] Is necessary the reference for document reverse + *
  • FR [ 2520591 ] Support multiples calendar for Org + * @see http://sourceforge.net/tracker2/?func=detail&atid=879335&aid=2520591&group_id=176962 + * @author Armen Rizal, Goodwill Consulting + *
  • BF [ 1745154 ] Cost in Reversing Material Related Docs + * @see http://sourceforge.net/tracker/?func=detail&atid=879335&aid=1948157&group_id=176962 + */ +public class MInOut extends X_M_InOut implements DocAction +{ + /** + * + */ + private static final long serialVersionUID = -1222763355238200128L; + + + /** + * Create Shipment From Order + * @param order order + * @param movementDate optional movement date + * @param forceDelivery ignore order delivery rule + * @param allAttributeInstances if true, all attribute set instances + * @param minGuaranteeDate optional minimum guarantee date if all attribute instances + * @param complete complete document (Process if false, Complete if true) + * @param trxName transaction + * @return Shipment or null + */ + public static MInOut createFrom (MOrder order, Timestamp movementDate, + boolean forceDelivery, boolean allAttributeInstances, Timestamp minGuaranteeDate, + boolean complete, String trxName) + { + if (order == null) + throw new IllegalArgumentException("No Order"); + // + if (!forceDelivery && DELIVERYRULE_CompleteLine.equals(order.getDeliveryRule())) + { + return null; + } + + // Create Meader + MInOut retValue = new MInOut (order, 0, movementDate); + retValue.setDocAction(complete ? DOCACTION_Complete : DOCACTION_Prepare); + + // Check if we can create the lines + MOrderLine[] oLines = order.getLines(true, "M_Product_ID"); + for (int i = 0; i < oLines.length; i++) + { + BigDecimal qty = oLines[i].getQtyOrdered().subtract(oLines[i].getQtyDelivered()); + // Nothing to deliver + if (qty.signum() == 0) + continue; + // Stock Info + MStorage[] storages = null; + MProduct product = oLines[i].getProduct(); + if (product != null && product.get_ID() != 0 && product.isStocked()) + { + String MMPolicy = product.getMMPolicy(); + storages = MStorage.getWarehouse (order.getCtx(), order.getM_Warehouse_ID(), + oLines[i].getM_Product_ID(), oLines[i].getM_AttributeSetInstance_ID(), + product.getM_AttributeSet_ID(), + allAttributeInstances, minGuaranteeDate, + MClient.MMPOLICY_FiFo.equals(MMPolicy), trxName); + } else { + continue; + } + + if (!forceDelivery) + { + BigDecimal maxQty = Env.ZERO; + for (int ll = 0; ll < storages.length; ll++) + maxQty = maxQty.add(storages[ll].getQtyOnHand()); + if (DELIVERYRULE_Availability.equals(order.getDeliveryRule())) + { + if (maxQty.compareTo(qty) < 0) + qty = maxQty; + } + else if (DELIVERYRULE_CompleteLine.equals(order.getDeliveryRule())) + { + if (maxQty.compareTo(qty) < 0) + continue; + } + } + // Create Line + if (retValue.get_ID() == 0) // not saved yet + retValue.save(trxName); + // Create a line until qty is reached + for (int ll = 0; ll < storages.length; ll++) + { + BigDecimal lineQty = storages[ll].getQtyOnHand(); + if (lineQty.compareTo(qty) > 0) + lineQty = qty; + MInOutLine line = new MInOutLine (retValue); + line.setOrderLine(oLines[i], storages[ll].getM_Locator_ID(), + order.isSOTrx() ? lineQty : Env.ZERO); + line.setQty(lineQty); // Correct UOM for QtyEntered + if (oLines[i].getQtyEntered().compareTo(oLines[i].getQtyOrdered()) != 0) + line.setQtyEntered(lineQty + .multiply(oLines[i].getQtyEntered()) + .divide(oLines[i].getQtyOrdered(), 12, BigDecimal.ROUND_HALF_UP)); + line.setC_Project_ID(oLines[i].getC_Project_ID()); + line.save(trxName); + // Delivered everything ? + qty = qty.subtract(lineQty); + // storage[ll].changeQtyOnHand(lineQty, !order.isSOTrx()); // Credit Memo not considered + // storage[ll].save(get_TrxName()); + if (qty.signum() == 0) + break; + } + } // for all order lines + + // No Lines saved + if (retValue.get_ID() == 0) + return null; + + return retValue; + } // createFrom + + /** + * Create new Shipment by copying + * @param from shipment + * @param dateDoc date of the document date + * @param C_DocType_ID doc type + * @param isSOTrx sales order + * @param counter create counter links + * @param trxName trx + * @param setOrder set the order link + * @return Shipment + */ + public static MInOut copyFrom (MInOut from, Timestamp dateDoc, + int C_DocType_ID, boolean isSOTrx, boolean counter, String trxName, boolean setOrder) + { + MInOut to = new MInOut (from.getCtx(), 0, null); + to.set_TrxName(trxName); + copyValues(from, to, from.getAD_Client_ID(), from.getAD_Org_ID()); + to.set_ValueNoCheck ("M_InOut_ID", I_ZERO); + to.set_ValueNoCheck ("DocumentNo", null); + // + to.setDocStatus (DOCSTATUS_Drafted); // Draft + to.setDocAction(DOCACTION_Complete); + // + to.setC_DocType_ID (C_DocType_ID); + to.setIsSOTrx(isSOTrx); + if (counter) + to.setMovementType (isSOTrx ? MOVEMENTTYPE_CustomerShipment : MOVEMENTTYPE_VendorReceipts); + // + to.setDateOrdered (dateDoc); + to.setDateAcct (dateDoc); + to.setMovementDate(dateDoc); + to.setDatePrinted(null); + to.setIsPrinted (false); + to.setDateReceived(null); + to.setNoPackages(0); + to.setShipDate(null); + to.setPickDate(null); + to.setIsInTransit(false); + // + to.setIsApproved (false); + to.setC_Invoice_ID(0); + to.setTrackingNo(null); + to.setIsInDispute(false); + // + to.setPosted (false); + to.setProcessed (false); + //[ 1633721 ] Reverse Documents- Processing=Y + to.setProcessing(false); + to.setC_Order_ID(0); // Overwritten by setOrder + to.setM_RMA_ID(0); // Overwritten by setOrder + if (counter) + { + to.setC_Order_ID(0); + to.setRef_InOut_ID(from.getM_InOut_ID()); + // Try to find Order/Invoice link + if (from.getC_Order_ID() != 0) + { + MOrder peer = new MOrder (from.getCtx(), from.getC_Order_ID(), from.get_TrxName()); + if (peer.getRef_Order_ID() != 0) + to.setC_Order_ID(peer.getRef_Order_ID()); + } + if (from.getC_Invoice_ID() != 0) + { + MInvoice peer = new MInvoice (from.getCtx(), from.getC_Invoice_ID(), from.get_TrxName()); + if (peer.getRef_Invoice_ID() != 0) + to.setC_Invoice_ID(peer.getRef_Invoice_ID()); + } + } + else + { + to.setRef_InOut_ID(0); + if (setOrder) + { + to.setC_Order_ID(from.getC_Order_ID()); + to.setM_RMA_ID(from.getM_RMA_ID()); // Copy also RMA + } + } + // + if (!to.save(trxName)) + throw new IllegalStateException("Could not create Shipment"); + if (counter) + from.setRef_InOut_ID(to.getM_InOut_ID()); + + if (to.copyLinesFrom(from, counter, setOrder) == 0) + throw new IllegalStateException("Could not create Shipment Lines"); + + return to; + } // copyFrom + + + /************************************************************************** + * Standard Constructor + * @param ctx context + * @param M_InOut_ID + * @param trxName rx name + */ + public MInOut (Properties ctx, int M_InOut_ID, String trxName) + { + super (ctx, M_InOut_ID, trxName); + if (M_InOut_ID == 0) + { + // setDocumentNo (null); + // setC_BPartner_ID (0); + // setC_BPartner_Location_ID (0); + // setM_Warehouse_ID (0); + // setC_DocType_ID (0); + setIsSOTrx (false); + setMovementDate (new Timestamp (System.currentTimeMillis ())); + setDateAcct (getMovementDate()); + // setMovementType (MOVEMENTTYPE_CustomerShipment); + setDeliveryRule (DELIVERYRULE_Availability); + setDeliveryViaRule (DELIVERYVIARULE_Pickup); + setFreightCostRule (FREIGHTCOSTRULE_FreightIncluded); + setDocStatus (DOCSTATUS_Drafted); + setDocAction (DOCACTION_Complete); + setPriorityRule (PRIORITYRULE_Medium); + setNoPackages(0); + setIsInTransit(false); + setIsPrinted (false); + setSendEMail (false); + setIsInDispute(false); + // + setIsApproved(false); + super.setProcessed (false); + setProcessing(false); + setPosted(false); + } + } // MInOut + + /** + * Load Constructor + * @param ctx context + * @param rs result set record + * @param trxName transaction + */ + public MInOut (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MInOut + + /** + * Order Constructor - create header only + * @param order order + * @param movementDate optional movement date (default today) + * @param C_DocTypeShipment_ID document type or 0 + */ + public MInOut (MOrder order, int C_DocTypeShipment_ID, Timestamp movementDate) + { + this (order.getCtx(), 0, order.get_TrxName()); + setClientOrg(order); + setC_BPartner_ID (order.getC_BPartner_ID()); + setC_BPartner_Location_ID (order.getC_BPartner_Location_ID()); // shipment address + setAD_User_ID(order.getAD_User_ID()); + // + setM_Warehouse_ID (order.getM_Warehouse_ID()); + setIsSOTrx (order.isSOTrx()); + setMovementType (order.isSOTrx() ? MOVEMENTTYPE_CustomerShipment : MOVEMENTTYPE_VendorReceipts); + if (C_DocTypeShipment_ID == 0) + C_DocTypeShipment_ID = DB.getSQLValue(null, + "SELECT C_DocTypeShipment_ID FROM C_DocType WHERE C_DocType_ID=?", + order.getC_DocType_ID()); + setC_DocType_ID (C_DocTypeShipment_ID); + + // Default - Today + if (movementDate != null) + setMovementDate (movementDate); + setDateAcct (getMovementDate()); + + // Copy from Order + setC_Order_ID(order.getC_Order_ID()); + setDeliveryRule (order.getDeliveryRule()); + setDeliveryViaRule (order.getDeliveryViaRule()); + setM_Shipper_ID(order.getM_Shipper_ID()); + setFreightCostRule (order.getFreightCostRule()); + setFreightAmt(order.getFreightAmt()); + setSalesRep_ID(order.getSalesRep_ID()); + // + setC_Activity_ID(order.getC_Activity_ID()); + setC_Campaign_ID(order.getC_Campaign_ID()); + setC_Charge_ID(order.getC_Charge_ID()); + setChargeAmt(order.getChargeAmt()); + // + setC_Project_ID(order.getC_Project_ID()); + setDateOrdered(order.getDateOrdered()); + setDescription(order.getDescription()); + setPOReference(order.getPOReference()); + setSalesRep_ID(order.getSalesRep_ID()); + setAD_OrgTrx_ID(order.getAD_OrgTrx_ID()); + setUser1_ID(order.getUser1_ID()); + setUser2_ID(order.getUser2_ID()); + setPriorityRule(order.getPriorityRule()); // Drop shipment setIsDropShip(order.isDropShip()); setDropShip_BPartner_ID(order.getDropShip_BPartner_ID()); setDropShip_Location_ID(order.getDropShip_Location_ID()); setDropShip_User_ID(order.getDropShip_User_ID()); - } // MInOut - - /** - * Invoice Constructor - create header only - * @param invoice invoice - * @param C_DocTypeShipment_ID document type or 0 - * @param movementDate optional movement date (default today) - * @param M_Warehouse_ID warehouse - */ - public MInOut (MInvoice invoice, int C_DocTypeShipment_ID, Timestamp movementDate, int M_Warehouse_ID) - { - this (invoice.getCtx(), 0, invoice.get_TrxName()); - setClientOrg(invoice); - setC_BPartner_ID (invoice.getC_BPartner_ID()); - setC_BPartner_Location_ID (invoice.getC_BPartner_Location_ID()); // shipment address - setAD_User_ID(invoice.getAD_User_ID()); - // - setM_Warehouse_ID (M_Warehouse_ID); - setIsSOTrx (invoice.isSOTrx()); - setMovementType (invoice.isSOTrx() ? MOVEMENTTYPE_CustomerShipment : MOVEMENTTYPE_VendorReceipts); - MOrder order = null; - if (invoice.getC_Order_ID() != 0) - order = new MOrder (invoice.getCtx(), invoice.getC_Order_ID(), invoice.get_TrxName()); - if (C_DocTypeShipment_ID == 0 && order != null) - C_DocTypeShipment_ID = DB.getSQLValue(null, - "SELECT C_DocTypeShipment_ID FROM C_DocType WHERE C_DocType_ID=?", - order.getC_DocType_ID()); - if (C_DocTypeShipment_ID != 0) - setC_DocType_ID (C_DocTypeShipment_ID); - else - setC_DocType_ID(); - - // Default - Today - if (movementDate != null) - setMovementDate (movementDate); - setDateAcct (getMovementDate()); - - // Copy from Invoice - setC_Order_ID(invoice.getC_Order_ID()); - setSalesRep_ID(invoice.getSalesRep_ID()); - // - setC_Activity_ID(invoice.getC_Activity_ID()); - setC_Campaign_ID(invoice.getC_Campaign_ID()); - setC_Charge_ID(invoice.getC_Charge_ID()); - setChargeAmt(invoice.getChargeAmt()); - // - setC_Project_ID(invoice.getC_Project_ID()); - setDateOrdered(invoice.getDateOrdered()); - setDescription(invoice.getDescription()); - setPOReference(invoice.getPOReference()); - setAD_OrgTrx_ID(invoice.getAD_OrgTrx_ID()); - setUser1_ID(invoice.getUser1_ID()); - setUser2_ID(invoice.getUser2_ID()); - - if (order != null) - { - setDeliveryRule (order.getDeliveryRule()); - setDeliveryViaRule (order.getDeliveryViaRule()); - setM_Shipper_ID(order.getM_Shipper_ID()); - setFreightCostRule (order.getFreightCostRule()); - setFreightAmt(order.getFreightAmt()); + } // MInOut + + /** + * Invoice Constructor - create header only + * @param invoice invoice + * @param C_DocTypeShipment_ID document type or 0 + * @param movementDate optional movement date (default today) + * @param M_Warehouse_ID warehouse + */ + public MInOut (MInvoice invoice, int C_DocTypeShipment_ID, Timestamp movementDate, int M_Warehouse_ID) + { + this (invoice.getCtx(), 0, invoice.get_TrxName()); + setClientOrg(invoice); + setC_BPartner_ID (invoice.getC_BPartner_ID()); + setC_BPartner_Location_ID (invoice.getC_BPartner_Location_ID()); // shipment address + setAD_User_ID(invoice.getAD_User_ID()); + // + setM_Warehouse_ID (M_Warehouse_ID); + setIsSOTrx (invoice.isSOTrx()); + setMovementType (invoice.isSOTrx() ? MOVEMENTTYPE_CustomerShipment : MOVEMENTTYPE_VendorReceipts); + MOrder order = null; + if (invoice.getC_Order_ID() != 0) + order = new MOrder (invoice.getCtx(), invoice.getC_Order_ID(), invoice.get_TrxName()); + if (C_DocTypeShipment_ID == 0 && order != null) + C_DocTypeShipment_ID = DB.getSQLValue(null, + "SELECT C_DocTypeShipment_ID FROM C_DocType WHERE C_DocType_ID=?", + order.getC_DocType_ID()); + if (C_DocTypeShipment_ID != 0) + setC_DocType_ID (C_DocTypeShipment_ID); + else + setC_DocType_ID(); + + // Default - Today + if (movementDate != null) + setMovementDate (movementDate); + setDateAcct (getMovementDate()); + + // Copy from Invoice + setC_Order_ID(invoice.getC_Order_ID()); + setSalesRep_ID(invoice.getSalesRep_ID()); + // + setC_Activity_ID(invoice.getC_Activity_ID()); + setC_Campaign_ID(invoice.getC_Campaign_ID()); + setC_Charge_ID(invoice.getC_Charge_ID()); + setChargeAmt(invoice.getChargeAmt()); + // + setC_Project_ID(invoice.getC_Project_ID()); + setDateOrdered(invoice.getDateOrdered()); + setDescription(invoice.getDescription()); + setPOReference(invoice.getPOReference()); + setAD_OrgTrx_ID(invoice.getAD_OrgTrx_ID()); + setUser1_ID(invoice.getUser1_ID()); + setUser2_ID(invoice.getUser2_ID()); + + if (order != null) + { + setDeliveryRule (order.getDeliveryRule()); + setDeliveryViaRule (order.getDeliveryViaRule()); + setM_Shipper_ID(order.getM_Shipper_ID()); + setFreightCostRule (order.getFreightCostRule()); + setFreightAmt(order.getFreightAmt()); // Drop Shipment setIsDropShip(order.isDropShip()); setDropShip_BPartner_ID(order.getDropShip_BPartner_ID()); setDropShip_Location_ID(order.getDropShip_Location_ID()); setDropShip_User_ID(order.getDropShip_User_ID()); - } - } // MInOut - - /** - * Copy Constructor - create header only - * @param original original - * @param movementDate optional movement date (default today) - * @param C_DocTypeShipment_ID document type or 0 - */ - public MInOut (MInOut original, int C_DocTypeShipment_ID, Timestamp movementDate) - { - this (original.getCtx(), 0, original.get_TrxName()); - setClientOrg(original); - setC_BPartner_ID (original.getC_BPartner_ID()); - setC_BPartner_Location_ID (original.getC_BPartner_Location_ID()); // shipment address - setAD_User_ID(original.getAD_User_ID()); - // - setM_Warehouse_ID (original.getM_Warehouse_ID()); - setIsSOTrx (original.isSOTrx()); - setMovementType (original.getMovementType()); - if (C_DocTypeShipment_ID == 0) - setC_DocType_ID(original.getC_DocType_ID()); - else - setC_DocType_ID (C_DocTypeShipment_ID); - - // Default - Today - if (movementDate != null) - setMovementDate (movementDate); - setDateAcct (getMovementDate()); - - // Copy from Order - setC_Order_ID(original.getC_Order_ID()); - setDeliveryRule (original.getDeliveryRule()); - setDeliveryViaRule (original.getDeliveryViaRule()); - setM_Shipper_ID(original.getM_Shipper_ID()); - setFreightCostRule (original.getFreightCostRule()); - setFreightAmt(original.getFreightAmt()); - setSalesRep_ID(original.getSalesRep_ID()); - // - setC_Activity_ID(original.getC_Activity_ID()); - setC_Campaign_ID(original.getC_Campaign_ID()); - setC_Charge_ID(original.getC_Charge_ID()); - setChargeAmt(original.getChargeAmt()); - // - setC_Project_ID(original.getC_Project_ID()); - setDateOrdered(original.getDateOrdered()); - setDescription(original.getDescription()); - setPOReference(original.getPOReference()); - setSalesRep_ID(original.getSalesRep_ID()); - setAD_OrgTrx_ID(original.getAD_OrgTrx_ID()); - setUser1_ID(original.getUser1_ID()); - setUser2_ID(original.getUser2_ID()); + } + } // MInOut + + /** + * Copy Constructor - create header only + * @param original original + * @param movementDate optional movement date (default today) + * @param C_DocTypeShipment_ID document type or 0 + */ + public MInOut (MInOut original, int C_DocTypeShipment_ID, Timestamp movementDate) + { + this (original.getCtx(), 0, original.get_TrxName()); + setClientOrg(original); + setC_BPartner_ID (original.getC_BPartner_ID()); + setC_BPartner_Location_ID (original.getC_BPartner_Location_ID()); // shipment address + setAD_User_ID(original.getAD_User_ID()); + // + setM_Warehouse_ID (original.getM_Warehouse_ID()); + setIsSOTrx (original.isSOTrx()); + setMovementType (original.getMovementType()); + if (C_DocTypeShipment_ID == 0) + setC_DocType_ID(original.getC_DocType_ID()); + else + setC_DocType_ID (C_DocTypeShipment_ID); + + // Default - Today + if (movementDate != null) + setMovementDate (movementDate); + setDateAcct (getMovementDate()); + + // Copy from Order + setC_Order_ID(original.getC_Order_ID()); + setDeliveryRule (original.getDeliveryRule()); + setDeliveryViaRule (original.getDeliveryViaRule()); + setM_Shipper_ID(original.getM_Shipper_ID()); + setFreightCostRule (original.getFreightCostRule()); + setFreightAmt(original.getFreightAmt()); + setSalesRep_ID(original.getSalesRep_ID()); + // + setC_Activity_ID(original.getC_Activity_ID()); + setC_Campaign_ID(original.getC_Campaign_ID()); + setC_Charge_ID(original.getC_Charge_ID()); + setChargeAmt(original.getChargeAmt()); + // + setC_Project_ID(original.getC_Project_ID()); + setDateOrdered(original.getDateOrdered()); + setDescription(original.getDescription()); + setPOReference(original.getPOReference()); + setSalesRep_ID(original.getSalesRep_ID()); + setAD_OrgTrx_ID(original.getAD_OrgTrx_ID()); + setUser1_ID(original.getUser1_ID()); + setUser2_ID(original.getUser2_ID()); // DropShipment setIsDropShip(original.isDropShip()); @@ -482,1076 +482,1076 @@ public class MInOut extends X_M_InOut implements DocAction setDropShip_Location_ID(original.getDropShip_Location_ID()); setDropShip_User_ID(original.getDropShip_User_ID()); - } // MInOut - - - /** Lines */ - private MInOutLine[] m_lines = null; - /** Confirmations */ - private MInOutConfirm[] m_confirms = null; - /** BPartner */ - private MBPartner m_partner = null; - - - /** - * Get Document Status - * @return Document Status Clear Text - */ - public String getDocStatusName() - { - return MRefList.getListName(getCtx(), 131, getDocStatus()); - } // getDocStatusName - - /** - * Add to Description - * @param description text - */ - public void addDescription (String description) - { - String desc = getDescription(); - if (desc == null) - setDescription(description); - else - setDescription(desc + " | " + description); - } // addDescription - - /** - * String representation - * @return info - */ - public String toString () - { - StringBuffer sb = new StringBuffer ("MInOut[") - .append (get_ID()).append("-").append(getDocumentNo()) - .append(",DocStatus=").append(getDocStatus()) - .append ("]"); - return sb.toString (); - } // toString - - /** - * Get Document Info - * @return document info (untranslated) - */ - public String getDocumentInfo() - { - MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); - return dt.getName() + " " + getDocumentNo(); - } // getDocumentInfo - - /** - * Create PDF - * @return File or null - */ - public File createPDF () - { - try - { - File temp = File.createTempFile(get_TableName()+get_ID()+"_", ".pdf"); - return createPDF (temp); - } - catch (Exception e) - { - log.severe("Could not create PDF - " + e.getMessage()); - } - return null; - } // getPDF - - /** - * Create PDF file - * @param file output file - * @return file if success - */ - public File createPDF (File file) - { - ReportEngine re = ReportEngine.get (getCtx(), ReportEngine.SHIPMENT, getM_InOut_ID(), get_TrxName()); - if (re == null) - return null; - return re.getPDF(file); - } // createPDF - - /** - * Get Lines of Shipment - * @param requery refresh from db - * @return lines - */ - public MInOutLine[] getLines (boolean requery) - { - if (m_lines != null && !requery) { - set_TrxName(m_lines, get_TrxName()); - return m_lines; - } - ArrayList list = new ArrayList(); - String sql = "SELECT * FROM M_InOutLine WHERE M_InOut_ID=? ORDER BY Line"; - PreparedStatement pstmt = null; - ResultSet rs = null; - try - { - pstmt = DB.prepareStatement(sql, get_TrxName()); - pstmt.setInt(1, getM_InOut_ID()); - rs = pstmt.executeQuery(); - while (rs.next()) - list.add(new MInOutLine(getCtx(), rs, get_TrxName())); - } - catch (SQLException ex) - { - log.log(Level.SEVERE, sql, ex); - list = null; - // throw new DBException(ex); - } - finally - { - DB.close(rs, pstmt); - rs = null; pstmt = null; - } - // - if (list == null) - return null; - // - m_lines = new MInOutLine[list.size()]; - list.toArray(m_lines); - return m_lines; - } // getMInOutLines - - /** - * Get Lines of Shipment - * @return lines - */ - public MInOutLine[] getLines() - { - return getLines(false); - } // getLines - - - /** - * Get Confirmations - * @param requery requery - * @return array of Confirmations - */ - public MInOutConfirm[] getConfirmations(boolean requery) - { - if (m_confirms != null && !requery) - return m_confirms; - - ArrayList list = new ArrayList (); - String sql = "SELECT * FROM M_InOutConfirm WHERE M_InOut_ID=?"; - PreparedStatement pstmt = null; - try - { - pstmt = DB.prepareStatement (sql, get_TrxName()); - pstmt.setInt (1, getM_InOut_ID()); - ResultSet rs = pstmt.executeQuery (); - while (rs.next ()) - list.add(new MInOutConfirm(getCtx(), rs, get_TrxName())); - rs.close (); - pstmt.close (); - pstmt = null; - } - catch (Exception e) - { - log.log(Level.SEVERE, sql, e); - } - try - { - if (pstmt != null) - pstmt.close (); - pstmt = null; - } - catch (Exception e) - { - pstmt = null; - } - - m_confirms = new MInOutConfirm[list.size ()]; - list.toArray (m_confirms); - return m_confirms; - } // getConfirmations - - - /** - * Copy Lines From other Shipment - * @param otherShipment shipment - * @param counter set counter info - * @param setOrder set order link - * @return number of lines copied - */ - public int copyLinesFrom (MInOut otherShipment, boolean counter, boolean setOrder) - { - if (isProcessed() || isPosted() || otherShipment == null) - return 0; - MInOutLine[] fromLines = otherShipment.getLines(false); - int count = 0; - for (int i = 0; i < fromLines.length; i++) - { - MInOutLine line = new MInOutLine (this); - MInOutLine fromLine = fromLines[i]; - line.set_TrxName(get_TrxName()); - if (counter) // header - PO.copyValues(fromLine, line, getAD_Client_ID(), getAD_Org_ID()); - else - PO.copyValues(fromLine, line, fromLine.getAD_Client_ID(), fromLine.getAD_Org_ID()); - line.setM_InOut_ID(getM_InOut_ID()); - line.set_ValueNoCheck ("M_InOutLine_ID", I_ZERO); // new - // Reset - if (!setOrder) - { - line.setC_OrderLine_ID(0); - line.setM_RMALine_ID(0); // Reset RMA Line - } - if (!counter) - line.setM_AttributeSetInstance_ID(0); - // line.setS_ResourceAssignment_ID(0); - line.setRef_InOutLine_ID(0); - line.setIsInvoiced(false); - // - line.setConfirmedQty(Env.ZERO); - line.setPickedQty(Env.ZERO); - line.setScrappedQty(Env.ZERO); - line.setTargetQty(Env.ZERO); - // Set Locator based on header Warehouse - if (getM_Warehouse_ID() != otherShipment.getM_Warehouse_ID()) - { - line.setM_Locator_ID(0); - line.setM_Locator_ID(Env.ZERO); - } - // - if (counter) - { - line.setRef_InOutLine_ID(fromLine.getM_InOutLine_ID()); - if (fromLine.getC_OrderLine_ID() != 0) - { - MOrderLine peer = new MOrderLine (getCtx(), fromLine.getC_OrderLine_ID(), get_TrxName()); - if (peer.getRef_OrderLine_ID() != 0) - line.setC_OrderLine_ID(peer.getRef_OrderLine_ID()); - } - } - // - line.setProcessed(false); - if (line.save(get_TrxName())) - count++; - // Cross Link - if (counter) - { - fromLine.setRef_InOutLine_ID(line.getM_InOutLine_ID()); - fromLine.save(get_TrxName()); - } - } - if (fromLines.length != count) - log.log(Level.SEVERE, "Line difference - From=" + fromLines.length + " <> Saved=" + count); - return count; - } // copyLinesFrom - - /** Reversal Flag */ - private boolean m_reversal = false; - - /** - * Set Reversal - * @param reversal reversal - */ - private void setReversal(boolean reversal) - { - m_reversal = reversal; - } // setReversal - /** - * Is Reversal - * @return reversal - */ - private boolean isReversal() - { - return m_reversal; - } // isReversal - - /** - * Set Processed. - * Propergate to Lines/Taxes - * @param processed processed - */ - public void setProcessed (boolean processed) - { - super.setProcessed (processed); - if (get_ID() == 0) - return; - String sql = "UPDATE M_InOutLine SET Processed='" - + (processed ? "Y" : "N") - + "' WHERE M_InOut_ID=" + getM_InOut_ID(); - int noLine = DB.executeUpdate(sql, get_TrxName()); - m_lines = null; - log.fine(processed + " - Lines=" + noLine); - } // setProcessed - - /** - * Get BPartner - * @return partner - */ - public MBPartner getBPartner() - { - if (m_partner == null) - m_partner = new MBPartner (getCtx(), getC_BPartner_ID(), get_TrxName()); - return m_partner; - } // getPartner - - /** - * Set Document Type - * @param DocBaseType doc type MDocType.DOCBASETYPE_ - */ - public void setC_DocType_ID (String DocBaseType) - { - String sql = "SELECT C_DocType_ID FROM C_DocType " - + "WHERE AD_Client_ID=? AND DocBaseType=?" - + " AND IsActive='Y'" - + " AND IsSOTrx='" + (isSOTrx() ? "Y" : "N") + "' " - + "ORDER BY IsDefault DESC"; - int C_DocType_ID = DB.getSQLValue(null, sql, getAD_Client_ID(), DocBaseType); - if (C_DocType_ID <= 0) - log.log(Level.SEVERE, "Not found for AC_Client_ID=" - + getAD_Client_ID() + " - " + DocBaseType); - else - { - log.fine("DocBaseType=" + DocBaseType + " - C_DocType_ID=" + C_DocType_ID); - setC_DocType_ID (C_DocType_ID); - boolean isSOTrx = MDocType.DOCBASETYPE_MaterialDelivery.equals(DocBaseType); - setIsSOTrx (isSOTrx); - } - } // setC_DocType_ID - - /** - * Set Default C_DocType_ID. - * Based on SO flag - */ - public void setC_DocType_ID() - { - if (isSOTrx()) - setC_DocType_ID(MDocType.DOCBASETYPE_MaterialDelivery); - else - setC_DocType_ID(MDocType.DOCBASETYPE_MaterialReceipt); - } // setC_DocType_ID - - /** - * Set Business Partner Defaults & Details - * @param bp business partner - */ - public void setBPartner (MBPartner bp) - { - if (bp == null) - return; - - setC_BPartner_ID(bp.getC_BPartner_ID()); - - // Set Locations - MBPartnerLocation[] locs = bp.getLocations(false); - if (locs != null) - { - for (int i = 0; i < locs.length; i++) - { - if (locs[i].isShipTo()) - setC_BPartner_Location_ID(locs[i].getC_BPartner_Location_ID()); - } - // set to first if not set - if (getC_BPartner_Location_ID() == 0 && locs.length > 0) - setC_BPartner_Location_ID(locs[0].getC_BPartner_Location_ID()); - } - if (getC_BPartner_Location_ID() == 0) - log.log(Level.SEVERE, "Has no To Address: " + bp); - - // Set Contact - MUser[] contacts = bp.getContacts(false); - if (contacts != null && contacts.length > 0) // get first User - setAD_User_ID(contacts[0].getAD_User_ID()); - } // setBPartner - - /** - * Create the missing next Confirmation - */ - public void createConfirmation() - { - MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); - boolean pick = dt.isPickQAConfirm(); - boolean ship = dt.isShipConfirm(); - // Nothing to do - if (!pick && !ship) - { - log.fine("No need"); - return; - } - - // Create Both .. after each other - if (pick && ship) - { - boolean havePick = false; - boolean haveShip = false; - MInOutConfirm[] confirmations = getConfirmations(false); - for (int i = 0; i < confirmations.length; i++) - { - MInOutConfirm confirm = confirmations[i]; - if (MInOutConfirm.CONFIRMTYPE_PickQAConfirm.equals(confirm.getConfirmType())) - { - if (!confirm.isProcessed()) // wait intil done - { - log.fine("Unprocessed: " + confirm); - return; - } - havePick = true; - } - else if (MInOutConfirm.CONFIRMTYPE_ShipReceiptConfirm.equals(confirm.getConfirmType())) - haveShip = true; - } - // Create Pick - if (!havePick) - { - MInOutConfirm.create (this, MInOutConfirm.CONFIRMTYPE_PickQAConfirm, false); - return; - } - // Create Ship - if (!haveShip) - { - MInOutConfirm.create (this, MInOutConfirm.CONFIRMTYPE_ShipReceiptConfirm, false); - return; - } - return; - } - // Create just one - if (pick) - MInOutConfirm.create (this, MInOutConfirm.CONFIRMTYPE_PickQAConfirm, true); - else if (ship) - MInOutConfirm.create (this, MInOutConfirm.CONFIRMTYPE_ShipReceiptConfirm, true); - } // createConfirmation - - - /** - * Set Warehouse and check/set Organization - * @param M_Warehouse_ID id - */ - public void setM_Warehouse_ID (int M_Warehouse_ID) - { - if (M_Warehouse_ID == 0) - { - log.severe("Ignored - Cannot set AD_Warehouse_ID to 0"); - return; - } - super.setM_Warehouse_ID (M_Warehouse_ID); - // - MWarehouse wh = MWarehouse.get(getCtx(), getM_Warehouse_ID()); - if (wh.getAD_Org_ID() != getAD_Org_ID()) - { - log.warning("M_Warehouse_ID=" + M_Warehouse_ID - + ", Overwritten AD_Org_ID=" + getAD_Org_ID() + "->" + wh.getAD_Org_ID()); - setAD_Org_ID(wh.getAD_Org_ID()); - } - } // setM_Warehouse_ID - - - /** - * Before Save - * @param newRecord new - * @return true or false - */ - protected boolean beforeSave (boolean newRecord) - { - // Warehouse Org - if (newRecord) - { - MWarehouse wh = MWarehouse.get(getCtx(), getM_Warehouse_ID()); - if (wh.getAD_Org_ID() != getAD_Org_ID()) - { - log.saveError("WarehouseOrgConflict", ""); - return false; - } - } - - // Shipment/Receipt can have either Order/RMA (For Movement type) - if (getC_Order_ID() != 0 && getM_RMA_ID() != 0) - { - log.saveError("OrderOrRMA", ""); - return false; - } - - // Shipment - Needs Order/RMA - if (!getMovementType().contentEquals(MInOut.MOVEMENTTYPE_CustomerReturns) && isSOTrx() && getC_Order_ID() == 0 && getM_RMA_ID() == 0) - { - log.saveError("FillMandatory", Msg.translate(getCtx(), "C_Order_ID")); - return false; - } - - if (isSOTrx() && getM_RMA_ID() != 0) - { - // Set Document and Movement type for this Receipt - MRMA rma = new MRMA(getCtx(), getM_RMA_ID(), get_TrxName()); - MDocType docType = MDocType.get(getCtx(), rma.getC_DocType_ID()); - setC_DocType_ID(docType.getC_DocTypeShipment_ID()); - } - - return true; - } // beforeSave - - /** - * After Save - * @param newRecord new - * @param success success - * @return success - */ - protected boolean afterSave (boolean newRecord, boolean success) - { - if (!success || newRecord) - return success; - - if (is_ValueChanged("AD_Org_ID")) - { - String sql = "UPDATE M_InOutLine ol" - + " SET AD_Org_ID =" - + "(SELECT AD_Org_ID" - + " FROM M_InOut o WHERE ol.M_InOut_ID=o.M_InOut_ID) " - + "WHERE M_InOut_ID=" + getC_Order_ID(); - int no = DB.executeUpdate(sql, get_TrxName()); - log.fine("Lines -> #" + no); - } - return true; - } // afterSave - - - /************************************************************************** - * Process document - * @param processAction document action - * @return true if performed - */ - public boolean processIt (String processAction) - { - m_processMsg = null; - DocumentEngine engine = new DocumentEngine (this, getDocStatus()); - return engine.processIt (processAction, getDocAction()); - } // process - - /** Process Message */ - private String m_processMsg = null; - /** Just Prepared Flag */ - private boolean m_justPrepared = false; - - /** - * Unlock Document. - * @return true if success - */ - public boolean unlockIt() - { - log.info(toString()); - setProcessing(false); - return true; - } // unlockIt - - /** - * Invalidate Document - * @return true if success - */ - public boolean invalidateIt() - { - log.info(toString()); - setDocAction(DOCACTION_Prepare); - return true; - } // invalidateIt - - /** - * Prepare Document - * @return new status (In Progress or Invalid) - */ - public String prepareIt() - { - log.info(toString()); - m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_BEFORE_PREPARE); - if (m_processMsg != null) - return DocAction.STATUS_Invalid; - - MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); - - // Order OR RMA can be processed on a shipment/receipt - if (getC_Order_ID() != 0 && getM_RMA_ID() != 0) - { - m_processMsg = "@OrderOrRMA@"; - return DocAction.STATUS_Invalid; - } - // Std Period open? - if (!MPeriod.isOpen(getCtx(), getDateAcct(), dt.getDocBaseType(), getAD_Org_ID())) - { - m_processMsg = "@PeriodClosed@"; - return DocAction.STATUS_Invalid; - } - - // Credit Check - if (isSOTrx() && !isReversal()) - { - MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), get_TrxName()); - if (MBPartner.SOCREDITSTATUS_CreditStop.equals(bp.getSOCreditStatus())) - { - m_processMsg = "@BPartnerCreditStop@ - @TotalOpenBalance@=" - + bp.getTotalOpenBalance() - + ", @SO_CreditLimit@=" + bp.getSO_CreditLimit(); - return DocAction.STATUS_Invalid; - } - if (MBPartner.SOCREDITSTATUS_CreditHold.equals(bp.getSOCreditStatus())) - { - m_processMsg = "@BPartnerCreditHold@ - @TotalOpenBalance@=" - + bp.getTotalOpenBalance() - + ", @SO_CreditLimit@=" + bp.getSO_CreditLimit(); - return DocAction.STATUS_Invalid; - } - BigDecimal notInvoicedAmt = MBPartner.getNotInvoicedAmt(getC_BPartner_ID()); - if (MBPartner.SOCREDITSTATUS_CreditHold.equals(bp.getSOCreditStatus(notInvoicedAmt))) - { - m_processMsg = "@BPartnerOverSCreditHold@ - @TotalOpenBalance@=" - + bp.getTotalOpenBalance() + ", @NotInvoicedAmt@=" + notInvoicedAmt - + ", @SO_CreditLimit@=" + bp.getSO_CreditLimit(); - return DocAction.STATUS_Invalid; - } - } - - // Lines - MInOutLine[] lines = getLines(true); - if (lines == null || lines.length == 0) - { - m_processMsg = "@NoLines@"; - return DocAction.STATUS_Invalid; - } - BigDecimal Volume = Env.ZERO; - BigDecimal Weight = Env.ZERO; - - // Mandatory Attributes - for (int i = 0; i < lines.length; i++) - { - MInOutLine line = lines[i]; - MProduct product = line.getProduct(); - if (product != null) - { - Volume = Volume.add(product.getVolume().multiply(line.getMovementQty())); - Weight = Weight.add(product.getWeight().multiply(line.getMovementQty())); - } - // - if (line.getM_AttributeSetInstance_ID() != 0) - continue; - if (product != null && product.isASIMandatory(isSOTrx())) - { - m_processMsg = "@M_AttributeSet_ID@ @IsMandatory@ (@Line@ #" + lines[i].getLine() + - ", @M_Product_ID@=" + product.getValue() + ")"; - return DocAction.STATUS_Invalid; - } - } - setVolume(Volume); - setWeight(Weight); - - if (!isReversal()) // don't change reversal - { - createConfirmation(); - } - - m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_PREPARE); - if (m_processMsg != null) - return DocAction.STATUS_Invalid; - - m_justPrepared = true; - if (!DOCACTION_Complete.equals(getDocAction())) - setDocAction(DOCACTION_Complete); - return DocAction.STATUS_InProgress; - } // prepareIt - - /** - * Approve Document - * @return true if success - */ - public boolean approveIt() - { - log.info(toString()); - setIsApproved(true); - return true; - } // approveIt - - /** - * Reject Approval - * @return true if success - */ - public boolean rejectIt() - { - log.info(toString()); - setIsApproved(false); - return true; - } // rejectIt - - /** - * Complete Document - * @return new status (Complete, In Progress, Invalid, Waiting ..) - */ - public String completeIt() - { - // Re-Check - if (!m_justPrepared) - { - String status = prepareIt(); - if (!DocAction.STATUS_InProgress.equals(status)) - return status; - } - - m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_BEFORE_COMPLETE); - if (m_processMsg != null) - return DocAction.STATUS_Invalid; - - // Outstanding (not processed) Incoming Confirmations ? - MInOutConfirm[] confirmations = getConfirmations(true); - for (int i = 0; i < confirmations.length; i++) - { - MInOutConfirm confirm = confirmations[i]; - if (!confirm.isProcessed()) - { - if (MInOutConfirm.CONFIRMTYPE_CustomerConfirmation.equals(confirm.getConfirmType())) - continue; - // - m_processMsg = "Open @M_InOutConfirm_ID@: " + - confirm.getConfirmTypeName() + " - " + confirm.getDocumentNo(); - return DocAction.STATUS_InProgress; - } - } - - - // Implicit Approval - if (!isApproved()) - approveIt(); - log.info(toString()); - StringBuffer info = new StringBuffer(); - - // For all lines - MInOutLine[] lines = getLines(false); - for (int lineIndex = 0; lineIndex < lines.length; lineIndex++) - { - MInOutLine sLine = lines[lineIndex]; - MProduct product = sLine.getProduct(); - - // Qty & Type - String MovementType = getMovementType(); - BigDecimal Qty = sLine.getMovementQty(); - if (MovementType.charAt(1) == '-') // C- Customer Shipment - V- Vendor Return - Qty = Qty.negate(); - BigDecimal QtySO = Env.ZERO; - BigDecimal QtyPO = Env.ZERO; - - // Update Order Line - MOrderLine oLine = null; - if (sLine.getC_OrderLine_ID() != 0) - { - oLine = new MOrderLine (getCtx(), sLine.getC_OrderLine_ID(), get_TrxName()); - log.fine("OrderLine - Reserved=" + oLine.getQtyReserved() - + ", Delivered=" + oLine.getQtyDelivered()); - if (isSOTrx()) - QtySO = sLine.getMovementQty(); - else - QtyPO = sLine.getMovementQty(); - } - - - // Load RMA Line - MRMALine rmaLine = null; - - if (sLine.getM_RMALine_ID() != 0) - { - rmaLine = new MRMALine(getCtx(), sLine.getM_RMALine_ID(), get_TrxName()); - } - - log.info("Line=" + sLine.getLine() + " - Qty=" + sLine.getMovementQty()); - - // Stock Movement - Counterpart MOrder.reserveStock - if (product != null - && product.isStocked() ) - { - //Ignore the Material Policy when is Reverse Correction - if(!isReversal()) - checkMaterialPolicy(sLine); - - log.fine("Material Transaction"); - MTransaction mtrx = null; - //same warehouse in order and receipt? - boolean sameWarehouse = true; - // Reservation ASI - assume none - int reservationAttributeSetInstance_ID = 0; // sLine.getM_AttributeSetInstance_ID(); - if (oLine != null) { - reservationAttributeSetInstance_ID = oLine.getM_AttributeSetInstance_ID(); - sameWarehouse = oLine.getM_Warehouse_ID()==getM_Warehouse_ID(); - } - // - if (sLine.getM_AttributeSetInstance_ID() == 0) - { - MInOutLineMA mas[] = MInOutLineMA.get(getCtx(), - sLine.getM_InOutLine_ID(), get_TrxName()); - for (int j = 0; j < mas.length; j++) - { - MInOutLineMA ma = mas[j]; - BigDecimal QtyMA = ma.getMovementQty(); - if (MovementType.charAt(1) == '-') // C- Customer Shipment - V- Vendor Return - QtyMA = QtyMA.negate(); - BigDecimal reservedDiff = Env.ZERO; - BigDecimal orderedDiff = Env.ZERO; - if (sLine.getC_OrderLine_ID() != 0) - { - if (isSOTrx()) - reservedDiff = ma.getMovementQty().negate(); - else - orderedDiff = ma.getMovementQty().negate(); - } - - - // Update Storage - see also VMatch.createMatchRecord - if (!MStorage.add(getCtx(), getM_Warehouse_ID(), - sLine.getM_Locator_ID(), - sLine.getM_Product_ID(), - ma.getM_AttributeSetInstance_ID(), reservationAttributeSetInstance_ID, - QtyMA, - sameWarehouse ? reservedDiff : Env.ZERO, - sameWarehouse ? orderedDiff : Env.ZERO, - get_TrxName())) - { - m_processMsg = "Cannot correct Inventory (MA)"; - return DocAction.STATUS_Invalid; - } - if (!sameWarehouse) { - //correct qtyOrdered in warehouse of order - MWarehouse wh = MWarehouse.get(getCtx(), oLine.getM_Warehouse_ID()); - if (!MStorage.add(getCtx(), oLine.getM_Warehouse_ID(), - wh.getDefaultLocator().getM_Locator_ID(), - sLine.getM_Product_ID(), - ma.getM_AttributeSetInstance_ID(), reservationAttributeSetInstance_ID, - Env.ZERO, reservedDiff, orderedDiff, get_TrxName())) - { - m_processMsg = "Cannot correct Inventory (MA) in order warehouse"; - return DocAction.STATUS_Invalid; - } - } - // Create Transaction - mtrx = new MTransaction (getCtx(), sLine.getAD_Org_ID(), - MovementType, sLine.getM_Locator_ID(), - sLine.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), - QtyMA, getMovementDate(), get_TrxName()); - mtrx.setM_InOutLine_ID(sLine.getM_InOutLine_ID()); - if (!mtrx.save()) - { - m_processMsg = "Could not create Material Transaction (MA)"; - return DocAction.STATUS_Invalid; - } - } - } - // sLine.getM_AttributeSetInstance_ID() != 0 - if (mtrx == null) - { - BigDecimal reservedDiff = sameWarehouse ? QtySO.negate() : Env.ZERO; - BigDecimal orderedDiff = sameWarehouse ? QtyPO.negate(): Env.ZERO; - - // Fallback: Update Storage - see also VMatch.createMatchRecord - if (!MStorage.add(getCtx(), getM_Warehouse_ID(), - sLine.getM_Locator_ID(), - sLine.getM_Product_ID(), - sLine.getM_AttributeSetInstance_ID(), reservationAttributeSetInstance_ID, - Qty, reservedDiff, orderedDiff, get_TrxName())) - { - m_processMsg = "Cannot correct Inventory"; - return DocAction.STATUS_Invalid; - } - if (!sameWarehouse) { - //correct qtyOrdered in warehouse of order - MWarehouse wh = MWarehouse.get(getCtx(), oLine.getM_Warehouse_ID()); - if (!MStorage.add(getCtx(), oLine.getM_Warehouse_ID(), - wh.getDefaultLocator().getM_Locator_ID(), - sLine.getM_Product_ID(), - sLine.getM_AttributeSetInstance_ID(), reservationAttributeSetInstance_ID, - Env.ZERO, QtySO.negate(), QtyPO.negate(), get_TrxName())) - { - m_processMsg = "Cannot correct Inventory"; - return DocAction.STATUS_Invalid; - } - } - // FallBack: Create Transaction - mtrx = new MTransaction (getCtx(), sLine.getAD_Org_ID(), - MovementType, sLine.getM_Locator_ID(), - sLine.getM_Product_ID(), sLine.getM_AttributeSetInstance_ID(), - Qty, getMovementDate(), get_TrxName()); - mtrx.setM_InOutLine_ID(sLine.getM_InOutLine_ID()); - if (!mtrx.save()) - { - m_processMsg = CLogger.retrieveErrorString("Could not create Material Transaction"); - return DocAction.STATUS_Invalid; - } - } - } // stock movement - - // Correct Order Line - if (product != null && oLine != null) // other in VMatch.createMatchRecord - oLine.setQtyReserved(oLine.getQtyReserved().subtract(sLine.getMovementQty())); - - // Update Sales Order Line - if (oLine != null) - { - if (isSOTrx() // PO is done by Matching - || sLine.getM_Product_ID() == 0) // PO Charges, empty lines - { - if (isSOTrx()) - oLine.setQtyDelivered(oLine.getQtyDelivered().subtract(Qty)); - else - oLine.setQtyDelivered(oLine.getQtyDelivered().add(Qty)); - oLine.setDateDelivered(getMovementDate()); // overwrite=last - } - if (!oLine.save()) - { - m_processMsg = "Could not update Order Line"; - return DocAction.STATUS_Invalid; - } - else - log.fine("OrderLine -> Reserved=" + oLine.getQtyReserved() - + ", Delivered=" + oLine.getQtyReserved()); - } - // Update RMA Line Qty Delivered - else if (rmaLine != null) - { - if (isSOTrx()) - { - rmaLine.setQtyDelivered(rmaLine.getQtyDelivered().add(Qty)); - } - else - { - rmaLine.setQtyDelivered(rmaLine.getQtyDelivered().subtract(Qty)); - } - if (!rmaLine.save()) - { - m_processMsg = "Could not update RMA Line"; - return DocAction.STATUS_Invalid; - } - } - - // Create Asset for SO - if (product != null - && isSOTrx() - && product.isCreateAsset() - && sLine.getMovementQty().signum() > 0 - && !isReversal()) - { - log.fine("Asset"); - info.append("@A_Asset_ID@: "); - int noAssets = sLine.getMovementQty().intValue(); - if (!product.isOneAssetPerUOM()) - noAssets = 1; - for (int i = 0; i < noAssets; i++) - { - if (i > 0) - info.append(" - "); - int deliveryCount = i+1; - if (!product.isOneAssetPerUOM()) - deliveryCount = 0; - MAsset asset = new MAsset (this, sLine, deliveryCount); - if (!asset.save(get_TrxName())) - { - m_processMsg = "Could not create Asset"; - return DocAction.STATUS_Invalid; - } - info.append(asset.getValue()); - } - } // Asset - - - // Matching - if (!isSOTrx() - && sLine.getM_Product_ID() != 0 - && !isReversal()) - { - BigDecimal matchQty = sLine.getMovementQty(); - // Invoice - Receipt Match (requires Product) - MInvoiceLine iLine = MInvoiceLine.getOfInOutLine (sLine); - if (iLine != null && iLine.getM_Product_ID() != 0) - { - if (matchQty.compareTo(iLine.getQtyInvoiced())>0) - matchQty = iLine.getQtyInvoiced(); - - MMatchInv[] matches = MMatchInv.get(getCtx(), - sLine.getM_InOutLine_ID(), iLine.getC_InvoiceLine_ID(), get_TrxName()); - if (matches == null || matches.length == 0) - { - MMatchInv inv = new MMatchInv (iLine, getMovementDate(), matchQty); - if (sLine.getM_AttributeSetInstance_ID() != iLine.getM_AttributeSetInstance_ID()) - { - iLine.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID()); - iLine.save(); // update matched invoice with ASI - inv.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID()); - } - if (!inv.save(get_TrxName())) - { - m_processMsg = CLogger.retrieveErrorString("Could not create Inv Matching"); - return DocAction.STATUS_Invalid; - } - } - } - - // Link to Order - if (sLine.getC_OrderLine_ID() != 0) - { - log.fine("PO Matching"); - // Ship - PO - MMatchPO po = MMatchPO.create (null, sLine, getMovementDate(), matchQty); - if (!po.save(get_TrxName())) - { - m_processMsg = "Could not create PO Matching"; - return DocAction.STATUS_Invalid; - } - // Update PO with ASI - if ( oLine != null && oLine.getM_AttributeSetInstance_ID() == 0 - && sLine.getMovementQty().compareTo(oLine.getQtyOrdered()) == 0) // just if full match [ 1876965 ] - { - oLine.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID()); - oLine.save(get_TrxName()); - } - } - else // No Order - Try finding links via Invoice - { - // Invoice has an Order Link - if (iLine != null && iLine.getC_OrderLine_ID() != 0) - { - // Invoice is created before Shipment - log.fine("PO(Inv) Matching"); - // Ship - Invoice - MMatchPO po = MMatchPO.create (iLine, sLine, - getMovementDate(), matchQty); - if (!po.save(get_TrxName())) - { - m_processMsg = "Could not create PO(Inv) Matching"; - return DocAction.STATUS_Invalid; - } - // Update PO with ASI - oLine = new MOrderLine (getCtx(), po.getC_OrderLine_ID(), get_TrxName()); - if ( oLine != null && oLine.getM_AttributeSetInstance_ID() == 0 - && sLine.getMovementQty().compareTo(oLine.getQtyOrdered()) == 0) // just if full match [ 1876965 ] - { - oLine.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID()); - oLine.save(get_TrxName()); - } - } - } // No Order - } // PO Matching - - } // for all lines - - // Counter Documents - MInOut counter = createCounterDoc(); - if (counter != null) - info.append(" - @CounterDoc@: @M_InOut_ID@=").append(counter.getDocumentNo()); + } // MInOut + + + /** Lines */ + private MInOutLine[] m_lines = null; + /** Confirmations */ + private MInOutConfirm[] m_confirms = null; + /** BPartner */ + private MBPartner m_partner = null; + + + /** + * Get Document Status + * @return Document Status Clear Text + */ + public String getDocStatusName() + { + return MRefList.getListName(getCtx(), 131, getDocStatus()); + } // getDocStatusName + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + + /** + * String representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MInOut[") + .append (get_ID()).append("-").append(getDocumentNo()) + .append(",DocStatus=").append(getDocStatus()) + .append ("]"); + return sb.toString (); + } // toString + + /** + * Get Document Info + * @return document info (untranslated) + */ + public String getDocumentInfo() + { + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + return dt.getName() + " " + getDocumentNo(); + } // getDocumentInfo + + /** + * Create PDF + * @return File or null + */ + public File createPDF () + { + try + { + File temp = File.createTempFile(get_TableName()+get_ID()+"_", ".pdf"); + return createPDF (temp); + } + catch (Exception e) + { + log.severe("Could not create PDF - " + e.getMessage()); + } + return null; + } // getPDF + + /** + * Create PDF file + * @param file output file + * @return file if success + */ + public File createPDF (File file) + { + ReportEngine re = ReportEngine.get (getCtx(), ReportEngine.SHIPMENT, getM_InOut_ID(), get_TrxName()); + if (re == null) + return null; + return re.getPDF(file); + } // createPDF + + /** + * Get Lines of Shipment + * @param requery refresh from db + * @return lines + */ + public MInOutLine[] getLines (boolean requery) + { + if (m_lines != null && !requery) { + set_TrxName(m_lines, get_TrxName()); + return m_lines; + } + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_InOutLine WHERE M_InOut_ID=? ORDER BY Line"; + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getM_InOut_ID()); + rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MInOutLine(getCtx(), rs, get_TrxName())); + } + catch (SQLException ex) + { + log.log(Level.SEVERE, sql, ex); + list = null; + // throw new DBException(ex); + } + finally + { + DB.close(rs, pstmt); + rs = null; pstmt = null; + } + // + if (list == null) + return null; + // + m_lines = new MInOutLine[list.size()]; + list.toArray(m_lines); + return m_lines; + } // getMInOutLines + + /** + * Get Lines of Shipment + * @return lines + */ + public MInOutLine[] getLines() + { + return getLines(false); + } // getLines + + + /** + * Get Confirmations + * @param requery requery + * @return array of Confirmations + */ + public MInOutConfirm[] getConfirmations(boolean requery) + { + if (m_confirms != null && !requery) + return m_confirms; + + ArrayList list = new ArrayList (); + String sql = "SELECT * FROM M_InOutConfirm WHERE M_InOut_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getM_InOut_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MInOutConfirm(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + m_confirms = new MInOutConfirm[list.size ()]; + list.toArray (m_confirms); + return m_confirms; + } // getConfirmations + + + /** + * Copy Lines From other Shipment + * @param otherShipment shipment + * @param counter set counter info + * @param setOrder set order link + * @return number of lines copied + */ + public int copyLinesFrom (MInOut otherShipment, boolean counter, boolean setOrder) + { + if (isProcessed() || isPosted() || otherShipment == null) + return 0; + MInOutLine[] fromLines = otherShipment.getLines(false); + int count = 0; + for (int i = 0; i < fromLines.length; i++) + { + MInOutLine line = new MInOutLine (this); + MInOutLine fromLine = fromLines[i]; + line.set_TrxName(get_TrxName()); + if (counter) // header + PO.copyValues(fromLine, line, getAD_Client_ID(), getAD_Org_ID()); + else + PO.copyValues(fromLine, line, fromLine.getAD_Client_ID(), fromLine.getAD_Org_ID()); + line.setM_InOut_ID(getM_InOut_ID()); + line.set_ValueNoCheck ("M_InOutLine_ID", I_ZERO); // new + // Reset + if (!setOrder) + { + line.setC_OrderLine_ID(0); + line.setM_RMALine_ID(0); // Reset RMA Line + } + if (!counter) + line.setM_AttributeSetInstance_ID(0); + // line.setS_ResourceAssignment_ID(0); + line.setRef_InOutLine_ID(0); + line.setIsInvoiced(false); + // + line.setConfirmedQty(Env.ZERO); + line.setPickedQty(Env.ZERO); + line.setScrappedQty(Env.ZERO); + line.setTargetQty(Env.ZERO); + // Set Locator based on header Warehouse + if (getM_Warehouse_ID() != otherShipment.getM_Warehouse_ID()) + { + line.setM_Locator_ID(0); + line.setM_Locator_ID(Env.ZERO); + } + // + if (counter) + { + line.setRef_InOutLine_ID(fromLine.getM_InOutLine_ID()); + if (fromLine.getC_OrderLine_ID() != 0) + { + MOrderLine peer = new MOrderLine (getCtx(), fromLine.getC_OrderLine_ID(), get_TrxName()); + if (peer.getRef_OrderLine_ID() != 0) + line.setC_OrderLine_ID(peer.getRef_OrderLine_ID()); + } + } + // + line.setProcessed(false); + if (line.save(get_TrxName())) + count++; + // Cross Link + if (counter) + { + fromLine.setRef_InOutLine_ID(line.getM_InOutLine_ID()); + fromLine.save(get_TrxName()); + } + } + if (fromLines.length != count) + log.log(Level.SEVERE, "Line difference - From=" + fromLines.length + " <> Saved=" + count); + return count; + } // copyLinesFrom + + /** Reversal Flag */ + private boolean m_reversal = false; + + /** + * Set Reversal + * @param reversal reversal + */ + private void setReversal(boolean reversal) + { + m_reversal = reversal; + } // setReversal + /** + * Is Reversal + * @return reversal + */ + private boolean isReversal() + { + return m_reversal; + } // isReversal + + /** + * Set Processed. + * Propergate to Lines/Taxes + * @param processed processed + */ + public void setProcessed (boolean processed) + { + super.setProcessed (processed); + if (get_ID() == 0) + return; + String sql = "UPDATE M_InOutLine SET Processed='" + + (processed ? "Y" : "N") + + "' WHERE M_InOut_ID=" + getM_InOut_ID(); + int noLine = DB.executeUpdate(sql, get_TrxName()); + m_lines = null; + log.fine(processed + " - Lines=" + noLine); + } // setProcessed + + /** + * Get BPartner + * @return partner + */ + public MBPartner getBPartner() + { + if (m_partner == null) + m_partner = new MBPartner (getCtx(), getC_BPartner_ID(), get_TrxName()); + return m_partner; + } // getPartner + + /** + * Set Document Type + * @param DocBaseType doc type MDocType.DOCBASETYPE_ + */ + public void setC_DocType_ID (String DocBaseType) + { + String sql = "SELECT C_DocType_ID FROM C_DocType " + + "WHERE AD_Client_ID=? AND DocBaseType=?" + + " AND IsActive='Y'" + + " AND IsSOTrx='" + (isSOTrx() ? "Y" : "N") + "' " + + "ORDER BY IsDefault DESC"; + int C_DocType_ID = DB.getSQLValue(null, sql, getAD_Client_ID(), DocBaseType); + if (C_DocType_ID <= 0) + log.log(Level.SEVERE, "Not found for AC_Client_ID=" + + getAD_Client_ID() + " - " + DocBaseType); + else + { + log.fine("DocBaseType=" + DocBaseType + " - C_DocType_ID=" + C_DocType_ID); + setC_DocType_ID (C_DocType_ID); + boolean isSOTrx = MDocType.DOCBASETYPE_MaterialDelivery.equals(DocBaseType); + setIsSOTrx (isSOTrx); + } + } // setC_DocType_ID + + /** + * Set Default C_DocType_ID. + * Based on SO flag + */ + public void setC_DocType_ID() + { + if (isSOTrx()) + setC_DocType_ID(MDocType.DOCBASETYPE_MaterialDelivery); + else + setC_DocType_ID(MDocType.DOCBASETYPE_MaterialReceipt); + } // setC_DocType_ID + + /** + * Set Business Partner Defaults & Details + * @param bp business partner + */ + public void setBPartner (MBPartner bp) + { + if (bp == null) + return; + + setC_BPartner_ID(bp.getC_BPartner_ID()); + + // Set Locations + MBPartnerLocation[] locs = bp.getLocations(false); + if (locs != null) + { + for (int i = 0; i < locs.length; i++) + { + if (locs[i].isShipTo()) + setC_BPartner_Location_ID(locs[i].getC_BPartner_Location_ID()); + } + // set to first if not set + if (getC_BPartner_Location_ID() == 0 && locs.length > 0) + setC_BPartner_Location_ID(locs[0].getC_BPartner_Location_ID()); + } + if (getC_BPartner_Location_ID() == 0) + log.log(Level.SEVERE, "Has no To Address: " + bp); + + // Set Contact + MUser[] contacts = bp.getContacts(false); + if (contacts != null && contacts.length > 0) // get first User + setAD_User_ID(contacts[0].getAD_User_ID()); + } // setBPartner + + /** + * Create the missing next Confirmation + */ + public void createConfirmation() + { + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + boolean pick = dt.isPickQAConfirm(); + boolean ship = dt.isShipConfirm(); + // Nothing to do + if (!pick && !ship) + { + log.fine("No need"); + return; + } + + // Create Both .. after each other + if (pick && ship) + { + boolean havePick = false; + boolean haveShip = false; + MInOutConfirm[] confirmations = getConfirmations(false); + for (int i = 0; i < confirmations.length; i++) + { + MInOutConfirm confirm = confirmations[i]; + if (MInOutConfirm.CONFIRMTYPE_PickQAConfirm.equals(confirm.getConfirmType())) + { + if (!confirm.isProcessed()) // wait intil done + { + log.fine("Unprocessed: " + confirm); + return; + } + havePick = true; + } + else if (MInOutConfirm.CONFIRMTYPE_ShipReceiptConfirm.equals(confirm.getConfirmType())) + haveShip = true; + } + // Create Pick + if (!havePick) + { + MInOutConfirm.create (this, MInOutConfirm.CONFIRMTYPE_PickQAConfirm, false); + return; + } + // Create Ship + if (!haveShip) + { + MInOutConfirm.create (this, MInOutConfirm.CONFIRMTYPE_ShipReceiptConfirm, false); + return; + } + return; + } + // Create just one + if (pick) + MInOutConfirm.create (this, MInOutConfirm.CONFIRMTYPE_PickQAConfirm, true); + else if (ship) + MInOutConfirm.create (this, MInOutConfirm.CONFIRMTYPE_ShipReceiptConfirm, true); + } // createConfirmation + + + /** + * Set Warehouse and check/set Organization + * @param M_Warehouse_ID id + */ + public void setM_Warehouse_ID (int M_Warehouse_ID) + { + if (M_Warehouse_ID == 0) + { + log.severe("Ignored - Cannot set AD_Warehouse_ID to 0"); + return; + } + super.setM_Warehouse_ID (M_Warehouse_ID); + // + MWarehouse wh = MWarehouse.get(getCtx(), getM_Warehouse_ID()); + if (wh.getAD_Org_ID() != getAD_Org_ID()) + { + log.warning("M_Warehouse_ID=" + M_Warehouse_ID + + ", Overwritten AD_Org_ID=" + getAD_Org_ID() + "->" + wh.getAD_Org_ID()); + setAD_Org_ID(wh.getAD_Org_ID()); + } + } // setM_Warehouse_ID + + + /** + * Before Save + * @param newRecord new + * @return true or false + */ + protected boolean beforeSave (boolean newRecord) + { + // Warehouse Org + if (newRecord) + { + MWarehouse wh = MWarehouse.get(getCtx(), getM_Warehouse_ID()); + if (wh.getAD_Org_ID() != getAD_Org_ID()) + { + log.saveError("WarehouseOrgConflict", ""); + return false; + } + } + + // Shipment/Receipt can have either Order/RMA (For Movement type) + if (getC_Order_ID() != 0 && getM_RMA_ID() != 0) + { + log.saveError("OrderOrRMA", ""); + return false; + } + + // Shipment - Needs Order/RMA + if (!getMovementType().contentEquals(MInOut.MOVEMENTTYPE_CustomerReturns) && isSOTrx() && getC_Order_ID() == 0 && getM_RMA_ID() == 0) + { + log.saveError("FillMandatory", Msg.translate(getCtx(), "C_Order_ID")); + return false; + } + + if (isSOTrx() && getM_RMA_ID() != 0) + { + // Set Document and Movement type for this Receipt + MRMA rma = new MRMA(getCtx(), getM_RMA_ID(), get_TrxName()); + MDocType docType = MDocType.get(getCtx(), rma.getC_DocType_ID()); + setC_DocType_ID(docType.getC_DocTypeShipment_ID()); + } + + return true; + } // beforeSave + + /** + * After Save + * @param newRecord new + * @param success success + * @return success + */ + protected boolean afterSave (boolean newRecord, boolean success) + { + if (!success || newRecord) + return success; + + if (is_ValueChanged("AD_Org_ID")) + { + String sql = "UPDATE M_InOutLine ol" + + " SET AD_Org_ID =" + + "(SELECT AD_Org_ID" + + " FROM M_InOut o WHERE ol.M_InOut_ID=o.M_InOut_ID) " + + "WHERE M_InOut_ID=" + getC_Order_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + log.fine("Lines -> #" + no); + } + return true; + } // afterSave + + + /************************************************************************** + * Process document + * @param processAction document action + * @return true if performed + */ + public boolean processIt (String processAction) + { + m_processMsg = null; + DocumentEngine engine = new DocumentEngine (this, getDocStatus()); + return engine.processIt (processAction, getDocAction()); + } // process + + /** Process Message */ + private String m_processMsg = null; + /** Just Prepared Flag */ + private boolean m_justPrepared = false; + + /** + * Unlock Document. + * @return true if success + */ + public boolean unlockIt() + { + log.info(toString()); + setProcessing(false); + return true; + } // unlockIt + + /** + * Invalidate Document + * @return true if success + */ + public boolean invalidateIt() + { + log.info(toString()); + setDocAction(DOCACTION_Prepare); + return true; + } // invalidateIt + + /** + * Prepare Document + * @return new status (In Progress or Invalid) + */ + public String prepareIt() + { + log.info(toString()); + m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_BEFORE_PREPARE); + if (m_processMsg != null) + return DocAction.STATUS_Invalid; + + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + + // Order OR RMA can be processed on a shipment/receipt + if (getC_Order_ID() != 0 && getM_RMA_ID() != 0) + { + m_processMsg = "@OrderOrRMA@"; + return DocAction.STATUS_Invalid; + } + // Std Period open? + if (!MPeriod.isOpen(getCtx(), getDateAcct(), dt.getDocBaseType(), getAD_Org_ID())) + { + m_processMsg = "@PeriodClosed@"; + return DocAction.STATUS_Invalid; + } + + // Credit Check + if (isSOTrx() && !isReversal()) + { + MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), get_TrxName()); + if (MBPartner.SOCREDITSTATUS_CreditStop.equals(bp.getSOCreditStatus())) + { + m_processMsg = "@BPartnerCreditStop@ - @TotalOpenBalance@=" + + bp.getTotalOpenBalance() + + ", @SO_CreditLimit@=" + bp.getSO_CreditLimit(); + return DocAction.STATUS_Invalid; + } + if (MBPartner.SOCREDITSTATUS_CreditHold.equals(bp.getSOCreditStatus())) + { + m_processMsg = "@BPartnerCreditHold@ - @TotalOpenBalance@=" + + bp.getTotalOpenBalance() + + ", @SO_CreditLimit@=" + bp.getSO_CreditLimit(); + return DocAction.STATUS_Invalid; + } + BigDecimal notInvoicedAmt = MBPartner.getNotInvoicedAmt(getC_BPartner_ID()); + if (MBPartner.SOCREDITSTATUS_CreditHold.equals(bp.getSOCreditStatus(notInvoicedAmt))) + { + m_processMsg = "@BPartnerOverSCreditHold@ - @TotalOpenBalance@=" + + bp.getTotalOpenBalance() + ", @NotInvoicedAmt@=" + notInvoicedAmt + + ", @SO_CreditLimit@=" + bp.getSO_CreditLimit(); + return DocAction.STATUS_Invalid; + } + } + + // Lines + MInOutLine[] lines = getLines(true); + if (lines == null || lines.length == 0) + { + m_processMsg = "@NoLines@"; + return DocAction.STATUS_Invalid; + } + BigDecimal Volume = Env.ZERO; + BigDecimal Weight = Env.ZERO; + + // Mandatory Attributes + for (int i = 0; i < lines.length; i++) + { + MInOutLine line = lines[i]; + MProduct product = line.getProduct(); + if (product != null) + { + Volume = Volume.add(product.getVolume().multiply(line.getMovementQty())); + Weight = Weight.add(product.getWeight().multiply(line.getMovementQty())); + } + // + if (line.getM_AttributeSetInstance_ID() != 0) + continue; + if (product != null && product.isASIMandatory(isSOTrx())) + { + m_processMsg = "@M_AttributeSet_ID@ @IsMandatory@ (@Line@ #" + lines[i].getLine() + + ", @M_Product_ID@=" + product.getValue() + ")"; + return DocAction.STATUS_Invalid; + } + } + setVolume(Volume); + setWeight(Weight); + + if (!isReversal()) // don't change reversal + { + createConfirmation(); + } + + m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_PREPARE); + if (m_processMsg != null) + return DocAction.STATUS_Invalid; + + m_justPrepared = true; + if (!DOCACTION_Complete.equals(getDocAction())) + setDocAction(DOCACTION_Complete); + return DocAction.STATUS_InProgress; + } // prepareIt + + /** + * Approve Document + * @return true if success + */ + public boolean approveIt() + { + log.info(toString()); + setIsApproved(true); + return true; + } // approveIt + + /** + * Reject Approval + * @return true if success + */ + public boolean rejectIt() + { + log.info(toString()); + setIsApproved(false); + return true; + } // rejectIt + + /** + * Complete Document + * @return new status (Complete, In Progress, Invalid, Waiting ..) + */ + public String completeIt() + { + // Re-Check + if (!m_justPrepared) + { + String status = prepareIt(); + if (!DocAction.STATUS_InProgress.equals(status)) + return status; + } + + m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_BEFORE_COMPLETE); + if (m_processMsg != null) + return DocAction.STATUS_Invalid; + + // Outstanding (not processed) Incoming Confirmations ? + MInOutConfirm[] confirmations = getConfirmations(true); + for (int i = 0; i < confirmations.length; i++) + { + MInOutConfirm confirm = confirmations[i]; + if (!confirm.isProcessed()) + { + if (MInOutConfirm.CONFIRMTYPE_CustomerConfirmation.equals(confirm.getConfirmType())) + continue; + // + m_processMsg = "Open @M_InOutConfirm_ID@: " + + confirm.getConfirmTypeName() + " - " + confirm.getDocumentNo(); + return DocAction.STATUS_InProgress; + } + } + + + // Implicit Approval + if (!isApproved()) + approveIt(); + log.info(toString()); + StringBuffer info = new StringBuffer(); + + // For all lines + MInOutLine[] lines = getLines(false); + for (int lineIndex = 0; lineIndex < lines.length; lineIndex++) + { + MInOutLine sLine = lines[lineIndex]; + MProduct product = sLine.getProduct(); + + // Qty & Type + String MovementType = getMovementType(); + BigDecimal Qty = sLine.getMovementQty(); + if (MovementType.charAt(1) == '-') // C- Customer Shipment - V- Vendor Return + Qty = Qty.negate(); + BigDecimal QtySO = Env.ZERO; + BigDecimal QtyPO = Env.ZERO; + + // Update Order Line + MOrderLine oLine = null; + if (sLine.getC_OrderLine_ID() != 0) + { + oLine = new MOrderLine (getCtx(), sLine.getC_OrderLine_ID(), get_TrxName()); + log.fine("OrderLine - Reserved=" + oLine.getQtyReserved() + + ", Delivered=" + oLine.getQtyDelivered()); + if (isSOTrx()) + QtySO = sLine.getMovementQty(); + else + QtyPO = sLine.getMovementQty(); + } + + + // Load RMA Line + MRMALine rmaLine = null; + + if (sLine.getM_RMALine_ID() != 0) + { + rmaLine = new MRMALine(getCtx(), sLine.getM_RMALine_ID(), get_TrxName()); + } + + log.info("Line=" + sLine.getLine() + " - Qty=" + sLine.getMovementQty()); + + // Stock Movement - Counterpart MOrder.reserveStock + if (product != null + && product.isStocked() ) + { + //Ignore the Material Policy when is Reverse Correction + if(!isReversal()) + checkMaterialPolicy(sLine); + + log.fine("Material Transaction"); + MTransaction mtrx = null; + //same warehouse in order and receipt? + boolean sameWarehouse = true; + // Reservation ASI - assume none + int reservationAttributeSetInstance_ID = 0; // sLine.getM_AttributeSetInstance_ID(); + if (oLine != null) { + reservationAttributeSetInstance_ID = oLine.getM_AttributeSetInstance_ID(); + sameWarehouse = oLine.getM_Warehouse_ID()==getM_Warehouse_ID(); + } + // + if (sLine.getM_AttributeSetInstance_ID() == 0) + { + MInOutLineMA mas[] = MInOutLineMA.get(getCtx(), + sLine.getM_InOutLine_ID(), get_TrxName()); + for (int j = 0; j < mas.length; j++) + { + MInOutLineMA ma = mas[j]; + BigDecimal QtyMA = ma.getMovementQty(); + if (MovementType.charAt(1) == '-') // C- Customer Shipment - V- Vendor Return + QtyMA = QtyMA.negate(); + BigDecimal reservedDiff = Env.ZERO; + BigDecimal orderedDiff = Env.ZERO; + if (sLine.getC_OrderLine_ID() != 0) + { + if (isSOTrx()) + reservedDiff = ma.getMovementQty().negate(); + else + orderedDiff = ma.getMovementQty().negate(); + } + + + // Update Storage - see also VMatch.createMatchRecord + if (!MStorage.add(getCtx(), getM_Warehouse_ID(), + sLine.getM_Locator_ID(), + sLine.getM_Product_ID(), + ma.getM_AttributeSetInstance_ID(), reservationAttributeSetInstance_ID, + QtyMA, + sameWarehouse ? reservedDiff : Env.ZERO, + sameWarehouse ? orderedDiff : Env.ZERO, + get_TrxName())) + { + m_processMsg = "Cannot correct Inventory (MA)"; + return DocAction.STATUS_Invalid; + } + if (!sameWarehouse) { + //correct qtyOrdered in warehouse of order + MWarehouse wh = MWarehouse.get(getCtx(), oLine.getM_Warehouse_ID()); + if (!MStorage.add(getCtx(), oLine.getM_Warehouse_ID(), + wh.getDefaultLocator().getM_Locator_ID(), + sLine.getM_Product_ID(), + ma.getM_AttributeSetInstance_ID(), reservationAttributeSetInstance_ID, + Env.ZERO, reservedDiff, orderedDiff, get_TrxName())) + { + m_processMsg = "Cannot correct Inventory (MA) in order warehouse"; + return DocAction.STATUS_Invalid; + } + } + // Create Transaction + mtrx = new MTransaction (getCtx(), sLine.getAD_Org_ID(), + MovementType, sLine.getM_Locator_ID(), + sLine.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), + QtyMA, getMovementDate(), get_TrxName()); + mtrx.setM_InOutLine_ID(sLine.getM_InOutLine_ID()); + if (!mtrx.save()) + { + m_processMsg = "Could not create Material Transaction (MA)"; + return DocAction.STATUS_Invalid; + } + } + } + // sLine.getM_AttributeSetInstance_ID() != 0 + if (mtrx == null) + { + BigDecimal reservedDiff = sameWarehouse ? QtySO.negate() : Env.ZERO; + BigDecimal orderedDiff = sameWarehouse ? QtyPO.negate(): Env.ZERO; + + // Fallback: Update Storage - see also VMatch.createMatchRecord + if (!MStorage.add(getCtx(), getM_Warehouse_ID(), + sLine.getM_Locator_ID(), + sLine.getM_Product_ID(), + sLine.getM_AttributeSetInstance_ID(), reservationAttributeSetInstance_ID, + Qty, reservedDiff, orderedDiff, get_TrxName())) + { + m_processMsg = "Cannot correct Inventory"; + return DocAction.STATUS_Invalid; + } + if (!sameWarehouse) { + //correct qtyOrdered in warehouse of order + MWarehouse wh = MWarehouse.get(getCtx(), oLine.getM_Warehouse_ID()); + if (!MStorage.add(getCtx(), oLine.getM_Warehouse_ID(), + wh.getDefaultLocator().getM_Locator_ID(), + sLine.getM_Product_ID(), + sLine.getM_AttributeSetInstance_ID(), reservationAttributeSetInstance_ID, + Env.ZERO, QtySO.negate(), QtyPO.negate(), get_TrxName())) + { + m_processMsg = "Cannot correct Inventory"; + return DocAction.STATUS_Invalid; + } + } + // FallBack: Create Transaction + mtrx = new MTransaction (getCtx(), sLine.getAD_Org_ID(), + MovementType, sLine.getM_Locator_ID(), + sLine.getM_Product_ID(), sLine.getM_AttributeSetInstance_ID(), + Qty, getMovementDate(), get_TrxName()); + mtrx.setM_InOutLine_ID(sLine.getM_InOutLine_ID()); + if (!mtrx.save()) + { + m_processMsg = CLogger.retrieveErrorString("Could not create Material Transaction"); + return DocAction.STATUS_Invalid; + } + } + } // stock movement + + // Correct Order Line + if (product != null && oLine != null) // other in VMatch.createMatchRecord + oLine.setQtyReserved(oLine.getQtyReserved().subtract(sLine.getMovementQty())); + + // Update Sales Order Line + if (oLine != null) + { + if (isSOTrx() // PO is done by Matching + || sLine.getM_Product_ID() == 0) // PO Charges, empty lines + { + if (isSOTrx()) + oLine.setQtyDelivered(oLine.getQtyDelivered().subtract(Qty)); + else + oLine.setQtyDelivered(oLine.getQtyDelivered().add(Qty)); + oLine.setDateDelivered(getMovementDate()); // overwrite=last + } + if (!oLine.save()) + { + m_processMsg = "Could not update Order Line"; + return DocAction.STATUS_Invalid; + } + else + log.fine("OrderLine -> Reserved=" + oLine.getQtyReserved() + + ", Delivered=" + oLine.getQtyReserved()); + } + // Update RMA Line Qty Delivered + else if (rmaLine != null) + { + if (isSOTrx()) + { + rmaLine.setQtyDelivered(rmaLine.getQtyDelivered().add(Qty)); + } + else + { + rmaLine.setQtyDelivered(rmaLine.getQtyDelivered().subtract(Qty)); + } + if (!rmaLine.save()) + { + m_processMsg = "Could not update RMA Line"; + return DocAction.STATUS_Invalid; + } + } + + // Create Asset for SO + if (product != null + && isSOTrx() + && product.isCreateAsset() + && sLine.getMovementQty().signum() > 0 + && !isReversal()) + { + log.fine("Asset"); + info.append("@A_Asset_ID@: "); + int noAssets = sLine.getMovementQty().intValue(); + if (!product.isOneAssetPerUOM()) + noAssets = 1; + for (int i = 0; i < noAssets; i++) + { + if (i > 0) + info.append(" - "); + int deliveryCount = i+1; + if (!product.isOneAssetPerUOM()) + deliveryCount = 0; + MAsset asset = new MAsset (this, sLine, deliveryCount); + if (!asset.save(get_TrxName())) + { + m_processMsg = "Could not create Asset"; + return DocAction.STATUS_Invalid; + } + info.append(asset.getValue()); + } + } // Asset + + + // Matching + if (!isSOTrx() + && sLine.getM_Product_ID() != 0 + && !isReversal()) + { + BigDecimal matchQty = sLine.getMovementQty(); + // Invoice - Receipt Match (requires Product) + MInvoiceLine iLine = MInvoiceLine.getOfInOutLine (sLine); + if (iLine != null && iLine.getM_Product_ID() != 0) + { + if (matchQty.compareTo(iLine.getQtyInvoiced())>0) + matchQty = iLine.getQtyInvoiced(); + + MMatchInv[] matches = MMatchInv.get(getCtx(), + sLine.getM_InOutLine_ID(), iLine.getC_InvoiceLine_ID(), get_TrxName()); + if (matches == null || matches.length == 0) + { + MMatchInv inv = new MMatchInv (iLine, getMovementDate(), matchQty); + if (sLine.getM_AttributeSetInstance_ID() != iLine.getM_AttributeSetInstance_ID()) + { + iLine.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID()); + iLine.save(); // update matched invoice with ASI + inv.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID()); + } + if (!inv.save(get_TrxName())) + { + m_processMsg = CLogger.retrieveErrorString("Could not create Inv Matching"); + return DocAction.STATUS_Invalid; + } + } + } + + // Link to Order + if (sLine.getC_OrderLine_ID() != 0) + { + log.fine("PO Matching"); + // Ship - PO + MMatchPO po = MMatchPO.create (null, sLine, getMovementDate(), matchQty); + if (!po.save(get_TrxName())) + { + m_processMsg = "Could not create PO Matching"; + return DocAction.STATUS_Invalid; + } + // Update PO with ASI + if ( oLine != null && oLine.getM_AttributeSetInstance_ID() == 0 + && sLine.getMovementQty().compareTo(oLine.getQtyOrdered()) == 0) // just if full match [ 1876965 ] + { + oLine.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID()); + oLine.save(get_TrxName()); + } + } + else // No Order - Try finding links via Invoice + { + // Invoice has an Order Link + if (iLine != null && iLine.getC_OrderLine_ID() != 0) + { + // Invoice is created before Shipment + log.fine("PO(Inv) Matching"); + // Ship - Invoice + MMatchPO po = MMatchPO.create (iLine, sLine, + getMovementDate(), matchQty); + if (!po.save(get_TrxName())) + { + m_processMsg = "Could not create PO(Inv) Matching"; + return DocAction.STATUS_Invalid; + } + // Update PO with ASI + oLine = new MOrderLine (getCtx(), po.getC_OrderLine_ID(), get_TrxName()); + if ( oLine != null && oLine.getM_AttributeSetInstance_ID() == 0 + && sLine.getMovementQty().compareTo(oLine.getQtyOrdered()) == 0) // just if full match [ 1876965 ] + { + oLine.setM_AttributeSetInstance_ID(sLine.getM_AttributeSetInstance_ID()); + oLine.save(get_TrxName()); + } + } + } // No Order + } // PO Matching + + } // for all lines + + // Counter Documents + MInOut counter = createCounterDoc(); + if (counter != null) + info.append(" - @CounterDoc@: @M_InOut_ID@=").append(counter.getDocumentNo()); // Drop Shipments MInOut dropShipment = createDropShipment(); if (dropShipment != null) info.append(" - @DropShipment@: @M_InOut_ID@=").append(dropShipment.getDocumentNo()); - // User Validation - String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE); - if (valid != null) - { - m_processMsg = valid; - return DocAction.STATUS_Invalid; - } - - // Set the definite document number after completed (if needed) - setDefiniteDocumentNo(); - - m_processMsg = info.toString(); - setProcessed(true); - setDocAction(DOCACTION_Close); - return DocAction.STATUS_Completed; - } // completeIt - - /** + // User Validation + String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE); + if (valid != null) + { + m_processMsg = valid; + return DocAction.STATUS_Invalid; + } + + // Set the definite document number after completed (if needed) + setDefiniteDocumentNo(); + + m_processMsg = info.toString(); + setProcessed(true); + setDocAction(DOCACTION_Close); + return DocAction.STATUS_Completed; + } // completeIt + + /** * Automatically creates a customer shipment for any * drop shipment material receipt * Based on createCounterDoc() by JJ @@ -1624,578 +1624,526 @@ public class MInOut extends X_M_InOut implements DocAction } /** - * Set the definite document number after completed - */ - private void setDefiniteDocumentNo() { - MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); - if (dt.isOverwriteDateOnComplete()) { - setMovementDate(new Timestamp (System.currentTimeMillis())); - } - if (dt.isOverwriteSeqOnComplete()) { - String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true, this); - if (value != null) - setDocumentNo(value); - } - } - - /** - * Check Material Policy - * Sets line ASI - */ - private void checkMaterialPolicy(MInOutLine line) - { - int no = MInOutLineMA.deleteInOutLineMA(line.getM_InOutLine_ID(), get_TrxName()); - if (no > 0) - log.config("Delete old #" + no); - - // Incoming Trx - String MovementType = getMovementType(); - boolean inTrx = MovementType.charAt(1) == '+'; // V+ Vendor Receipt - - - boolean needSave = false; - BigDecimal qtyASI = Env.ZERO ; - - MProduct product = line.getProduct(); - - // Need to have Location - if (product != null - && line.getM_Locator_ID() == 0) - { - //MWarehouse w = MWarehouse.get(getCtx(), getM_Warehouse_ID()); - line.setM_Warehouse_ID(getM_Warehouse_ID()); - line.setM_Locator_ID(inTrx ? Env.ZERO : line.getMovementQty()); // default Locator - needSave = true; - } - - // Attribute Set Instance - // Create an Attribute Set Instance to any receipt FIFO/LIFO - if (product != null && line.getM_AttributeSetInstance_ID() == 0) - { - //Validate Transaction - //if (inTrx) - if (getMovementType().compareTo(MInOut.MOVEMENTTYPE_CustomerReturns) == 0 || getMovementType().compareTo(MInOut.MOVEMENTTYPE_VendorReceipts) == 0 ) - { - MAttributeSetInstance asi = new MAttributeSetInstance(getCtx(), 0, get_TrxName()); - asi.setClientOrg(getAD_Client_ID(), 0); - asi.setM_AttributeSet_ID(product.getM_AttributeSet_ID()); - if (!asi.save()) - { - throw new IllegalStateException("Error try create ASI Reservation"); - } - if (asi.save()) - { - line.setM_AttributeSetInstance_ID(asi.getM_AttributeSetInstance_ID()); - log.config("New ASI=" + line); - needSave = true; - } - } - // Create consume the Attribute Set Instance using policy FIFO/LIFO - else if(getMovementType().compareTo(MInOut.MOVEMENTTYPE_VendorReturns) == 0 || getMovementType().compareTo(MInOut.MOVEMENTTYPE_CustomerShipment) == 0) - { - String MMPolicy = product.getMMPolicy(); - MStorage[] storages = MStorage.getAllWithASI(getCtx(), - line.getM_Product_ID(), line.getM_Locator_ID(), - MClient.MMPOLICY_FiFo.equals(MMPolicy), get_TrxName()); - BigDecimal qtyToDeliver = line.getMovementQty(); - /*for (int ii = 0; ii < storages.length; ii++) - { - MStorage storage = storages[ii]; - if (ii == 0) - { - if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0) - { - line.setM_AttributeSetInstance_ID(storage.getM_AttributeSetInstance_ID()); - needSave = true; - log.config("Direct - " + line); - qtyToDeliver = Env.ZERO; - } - else - { - log.config("Split - " + line); - MInOutLineMA ma = new MInOutLineMA (line, - storage.getM_AttributeSetInstance_ID(), - storage.getQtyOnHand()); - if (!ma.save()) - ; - qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand()); - log.fine("#" + ii + ": " + ma + ", QtyToDeliver=" + qtyToDeliver); - } - } - else // create addl material allocation - { - MInOutLineMA ma = new MInOutLineMA (line, - storage.getM_AttributeSetInstance_ID(), - qtyToDeliver); - if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0) - qtyToDeliver = Env.ZERO; - else - { - ma.setMovementQty(storage.getQtyOnHand()); - qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand()); - } - if (!ma.save()) - ; - log.fine("#" + ii + ": " + ma + ", QtyToDeliver=" + qtyToDeliver); - } - if (qtyToDeliver.signum() == 0) - break; - } // for all storages - */ - - for (MStorage storage: storages) - { - //consume ASI Zero - if (storage.getM_AttributeSetInstance_ID() == 0) - { - qtyASI = qtyASI.add(storage.getQtyOnHand()); - qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand()); - continue; - } - - if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0) - { - MInOutLineMA ma = new MInOutLineMA (line, - storage.getM_AttributeSetInstance_ID(), - qtyToDeliver); - if (!ma.save()) - { - throw new IllegalStateException("Error try create ASI Reservation"); - } - qtyToDeliver = Env.ZERO; - } - else - { - MInOutLineMA ma = new MInOutLineMA (line, - storage.getM_AttributeSetInstance_ID(), - storage.getQtyOnHand()); - if (!ma.save()) - { - throw new IllegalStateException("Error try create ASI Reservation"); - } - qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand()); - log.fine( ma + ", QtyToDeliver=" + qtyToDeliver); - } - } - - // No AttributeSetInstance found for remainder - if (qtyToDeliver.signum() != 0 || qtyASI.signum() != 0) - { - MInOutLineMA ma = new MInOutLineMA (line, 0, qtyToDeliver.add(qtyASI)); - if (!ma.save()) - ; - log.fine("##: " + ma); - } - } // outgoing Trx - } // attributeSetInstance - - if (needSave && !line.save()) - log.severe("NOT saved " + line); - } // checkMaterialPolicy - - - /************************************************************************** - * Create Counter Document - * @return InOut - */ - private MInOut createCounterDoc() - { - // Is this a counter doc ? - if (getRef_InOut_ID() != 0) - return null; - - // Org Must be linked to BPartner - MOrg org = MOrg.get(getCtx(), getAD_Org_ID()); - int counterC_BPartner_ID = org.getLinkedC_BPartner_ID(get_TrxName()); - if (counterC_BPartner_ID == 0) - return null; - // Business Partner needs to be linked to Org - MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), get_TrxName()); - int counterAD_Org_ID = bp.getAD_OrgBP_ID_Int(); - if (counterAD_Org_ID == 0) - return null; - - MBPartner counterBP = new MBPartner (getCtx(), counterC_BPartner_ID, null); - MOrgInfo counterOrgInfo = MOrgInfo.get(getCtx(), counterAD_Org_ID); - log.info("Counter BP=" + counterBP.getName()); - - // Document Type - int C_DocTypeTarget_ID = 0; - MDocTypeCounter counterDT = MDocTypeCounter.getCounterDocType(getCtx(), getC_DocType_ID()); - if (counterDT != null) - { - log.fine(counterDT.toString()); - if (!counterDT.isCreateCounter() || !counterDT.isValid()) - return null; - C_DocTypeTarget_ID = counterDT.getCounter_C_DocType_ID(); - } - else // indirect - { - C_DocTypeTarget_ID = MDocTypeCounter.getCounterDocType_ID(getCtx(), getC_DocType_ID()); - log.fine("Indirect C_DocTypeTarget_ID=" + C_DocTypeTarget_ID); - if (C_DocTypeTarget_ID <= 0) - return null; - } - - // Deep Copy - MInOut counter = copyFrom(this, getMovementDate(), - C_DocTypeTarget_ID, !isSOTrx(), true, get_TrxName(), true); - - // - counter.setAD_Org_ID(counterAD_Org_ID); - counter.setM_Warehouse_ID(counterOrgInfo.getM_Warehouse_ID()); - // - counter.setBPartner(counterBP); - - if ( isDropShip() ) - { - counter.setIsDropShip(true ); - counter.setDropShip_BPartner_ID(getDropShip_BPartner_ID()); - counter.setDropShip_Location_ID(getDropShip_Location_ID()); - counter.setDropShip_User_ID(getDropShip_User_ID()); - } - - // Refernces (Should not be required - counter.setSalesRep_ID(getSalesRep_ID()); - counter.save(get_TrxName()); - - String MovementType = counter.getMovementType(); - boolean inTrx = MovementType.charAt(1) == '+'; // V+ Vendor Receipt - - // Update copied lines - MInOutLine[] counterLines = counter.getLines(true); - for (int i = 0; i < counterLines.length; i++) - { - MInOutLine counterLine = counterLines[i]; - counterLine.setClientOrg(counter); - counterLine.setM_Warehouse_ID(counter.getM_Warehouse_ID()); - counterLine.setM_Locator_ID(0); - counterLine.setM_Locator_ID(inTrx ? Env.ZERO : counterLine.getMovementQty()); - // - counterLine.save(get_TrxName()); - } - - log.fine(counter.toString()); - - // Document Action - if (counterDT != null) - { - if (counterDT.getDocAction() != null) - { - counter.setDocAction(counterDT.getDocAction()); - counter.processIt(counterDT.getDocAction()); - counter.save(get_TrxName()); - } - } - return counter; - } // createCounterDoc - - /** - * Void Document. - * @return true if success - */ - public boolean voidIt() - { - log.info(toString()); - // Before Void - m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_BEFORE_VOID); - if (m_processMsg != null) - return false; - - if (DOCSTATUS_Closed.equals(getDocStatus()) - || DOCSTATUS_Reversed.equals(getDocStatus()) - || DOCSTATUS_Voided.equals(getDocStatus())) - { - m_processMsg = "Document Closed: " + getDocStatus(); - return false; - } - - // Not Processed - if (DOCSTATUS_Drafted.equals(getDocStatus()) - || DOCSTATUS_Invalid.equals(getDocStatus()) - || DOCSTATUS_InProgress.equals(getDocStatus()) - || DOCSTATUS_Approved.equals(getDocStatus()) - || DOCSTATUS_NotApproved.equals(getDocStatus()) ) - { - // Set lines to 0 - MInOutLine[] lines = getLines(false); - for (int i = 0; i < lines.length; i++) - { - MInOutLine line = lines[i]; - BigDecimal old = line.getMovementQty(); - if (old.signum() != 0) - { - line.setQty(Env.ZERO); - line.addDescription("Void (" + old + ")"); - line.save(get_TrxName()); - } - } - } - else - { - return reverseCorrectIt(); - } - - // After Void - m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_VOID); - if (m_processMsg != null) - return false; - - setProcessed(true); - setDocAction(DOCACTION_None); - return true; - } // voidIt - - /** - * Close Document. - * @return true if success - */ - public boolean closeIt() - { - log.info(toString()); - // Before Close - m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_BEFORE_CLOSE); - if (m_processMsg != null) - return false; - - // After Close - m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_CLOSE); - if (m_processMsg != null) - return false; - - setProcessed(true); - setDocAction(DOCACTION_None); - return true; - } // closeIt - - /** - * Reverse Correction - same date - * @return true if success - */ - public boolean reverseCorrectIt() - { - log.info(toString()); - // Before reverseCorrect - m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_BEFORE_REVERSECORRECT); - if (m_processMsg != null) - return false; - - MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); - if (!MPeriod.isOpen(getCtx(), getDateAcct(), dt.getDocBaseType(), getAD_Org_ID())) - { - m_processMsg = "@PeriodClosed@"; - return false; - } - - // Reverse/Delete Matching - if (!isSOTrx()) - { - MMatchInv[] mInv = MMatchInv.getInOut(getCtx(), getM_InOut_ID(), get_TrxName()); - for (int i = 0; i < mInv.length; i++) - mInv[i].delete(true); - MMatchPO[] mPO = MMatchPO.getInOut(getCtx(), getM_InOut_ID(), get_TrxName()); - for (int i = 0; i < mPO.length; i++) - { - if (mPO[i].getC_InvoiceLine_ID() == 0) - mPO[i].delete(true); - else - { - mPO[i].setM_InOutLine_ID(0); - mPO[i].save(); - - } - } - } - - // Deep Copy - MInOut reversal = copyFrom (this, getMovementDate(), - getC_DocType_ID(), isSOTrx(), false, get_TrxName(), true); - if (reversal == null) - { - m_processMsg = "Could not create Ship Reversal"; - return false; - } - reversal.setReversal(true); - - // Reverse Line Qty - MInOutLine[] sLines = getLines(false); - MInOutLine[] rLines = reversal.getLines(false); - for (int i = 0; i < rLines.length; i++) - { - MInOutLine rLine = rLines[i]; - rLine.setQtyEntered(rLine.getQtyEntered().negate()); - rLine.setMovementQty(rLine.getMovementQty().negate()); - rLine.setM_AttributeSetInstance_ID(sLines[i].getM_AttributeSetInstance_ID()); - // Goodwill: store original (voided/reversed) document line - rLine.setReversalLine_ID(sLines[i].getM_InOutLine_ID()); - if (!rLine.save(get_TrxName())) - { - m_processMsg = "Could not correct Ship Reversal Line"; - return false; - } - // We need to copy MA - if (rLine.getM_AttributeSetInstance_ID() == 0) - { - MInOutLineMA mas[] = MInOutLineMA.get(getCtx(), - sLines[i].getM_InOutLine_ID(), get_TrxName()); - for (int j = 0; j < mas.length; j++) - { - MInOutLineMA ma = new MInOutLineMA (rLine, - mas[j].getM_AttributeSetInstance_ID(), - mas[j].getMovementQty().negate()); - if (!ma.save()) - ; - } - } - // De-Activate Asset - MAsset asset = MAsset.getFromShipment(getCtx(), sLines[i].getM_InOutLine_ID(), get_TrxName()); - if (asset != null) - { - asset.setIsActive(false); - asset.addDescription("(" + reversal.getDocumentNo() + " #" + rLine.getLine() + "<-)"); - asset.save(); - } - } - reversal.setC_Order_ID(getC_Order_ID()); - // Set M_RMA_ID - reversal.setM_RMA_ID(getM_RMA_ID()); - reversal.addDescription("{->" + getDocumentNo() + ")"); - // - if (!reversal.processIt(DocAction.ACTION_Complete) - || !reversal.getDocStatus().equals(DocAction.STATUS_Completed)) - { - m_processMsg = "Reversal ERROR: " + reversal.getProcessMsg(); - return false; - } - reversal.closeIt(); - //FR1948157 - reversal.setReversal_ID(getM_InOut_ID()); - reversal.setProcessing (false); - reversal.setDocStatus(DOCSTATUS_Reversed); - reversal.setDocAction(DOCACTION_None); - reversal.save(get_TrxName()); - // - addDescription("(" + reversal.getDocumentNo() + "<-)"); - - // After reverseCorrect - m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_REVERSECORRECT); - if (m_processMsg != null) - return false; - - m_processMsg = reversal.getDocumentNo(); - //FR1948157 - this.setReversal_ID(reversal.getM_InOut_ID()); - setProcessed(true); - setDocStatus(DOCSTATUS_Reversed); // may come from void - setDocAction(DOCACTION_None); - return true; - } // reverseCorrectionIt - - /** - * Reverse Accrual - none - * @return false - */ - public boolean reverseAccrualIt() - { - log.info(toString()); - // Before reverseAccrual - m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_BEFORE_REVERSEACCRUAL); - if (m_processMsg != null) - return false; - - // After reverseAccrual - m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_REVERSEACCRUAL); - if (m_processMsg != null) - return false; - - return false; - } // reverseAccrualIt - - /** - * Re-activate - * @return false - */ - public boolean reActivateIt() - { - log.info(toString()); - // Before reActivate - m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_BEFORE_REACTIVATE); - if (m_processMsg != null) - return false; - - // After reActivate - m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_REACTIVATE); - if (m_processMsg != null) - return false; - - return false; - } // reActivateIt - - - /************************************************************************* - * Get Summary - * @return Summary of Document - */ - public String getSummary() - { - StringBuffer sb = new StringBuffer(); - sb.append(getDocumentNo()); - // : Total Lines = 123.00 (#1) - sb.append(":") - // .append(Msg.translate(getCtx(),"TotalLines")).append("=").append(getTotalLines()) - .append(" (#").append(getLines(false).length).append(")"); - // - Description - if (getDescription() != null && getDescription().length() > 0) - sb.append(" - ").append(getDescription()); - return sb.toString(); - } // getSummary - - /** - * Get Process Message - * @return clear text error message - */ - public String getProcessMsg() - { - return m_processMsg; - } // getProcessMsg - - /** - * Get Document Owner (Responsible) - * @return AD_User_ID - */ - public int getDoc_User_ID() - { - return getSalesRep_ID(); - } // getDoc_User_ID - - /** - * Get Document Approval Amount - * @return amount - */ - public BigDecimal getApprovalAmt() - { - return Env.ZERO; - } // getApprovalAmt - - /** - * Get C_Currency_ID - * @return Accounting Currency - */ - public int getC_Currency_ID () - { - return Env.getContextAsInt(getCtx(),"$C_Currency_ID"); - } // getC_Currency_ID - - /** - * Document Status is Complete or Closed - * @return true if CO, CL or RE - */ - public boolean isComplete() - { - String ds = getDocStatus(); - return DOCSTATUS_Completed.equals(ds) - || DOCSTATUS_Closed.equals(ds) - || DOCSTATUS_Reversed.equals(ds); - } // isComplete - -} // MInOut + * Set the definite document number after completed + */ + private void setDefiniteDocumentNo() { + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + if (dt.isOverwriteDateOnComplete()) { + setMovementDate(new Timestamp (System.currentTimeMillis())); + } + if (dt.isOverwriteSeqOnComplete()) { + String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true, this); + if (value != null) + setDocumentNo(value); + } + } + + /** + * Check Material Policy + * Sets line ASI + */ + private void checkMaterialPolicy(MInOutLine line) + { + int no = MInOutLineMA.deleteInOutLineMA(line.getM_InOutLine_ID(), get_TrxName()); + if (no > 0) + log.config("Delete old #" + no); + + // Incoming Trx + String MovementType = getMovementType(); + boolean inTrx = MovementType.charAt(1) == '+'; // V+ Vendor Receipt + + + boolean needSave = false; + + MProduct product = line.getProduct(); + + // Need to have Location + if (product != null + && line.getM_Locator_ID() == 0) + { + //MWarehouse w = MWarehouse.get(getCtx(), getM_Warehouse_ID()); + line.setM_Warehouse_ID(getM_Warehouse_ID()); + line.setM_Locator_ID(inTrx ? Env.ZERO : line.getMovementQty()); // default Locator + needSave = true; + } + + // Attribute Set Instance + // Create an Attribute Set Instance to any receipt FIFO/LIFO + if (product != null && line.getM_AttributeSetInstance_ID() == 0) + { + //Validate Transaction + //if (inTrx) + if (getMovementType().compareTo(MInOut.MOVEMENTTYPE_CustomerReturns) == 0 || getMovementType().compareTo(MInOut.MOVEMENTTYPE_VendorReceipts) == 0 ) + { + MAttributeSetInstance asi = new MAttributeSetInstance(getCtx(), 0, get_TrxName()); + asi.setClientOrg(getAD_Client_ID(), 0); + asi.setM_AttributeSet_ID(product.getM_AttributeSet_ID()); + if (!asi.save()) + { + throw new IllegalStateException("Error try create ASI Reservation"); + } + if (asi.save()) + { + line.setM_AttributeSetInstance_ID(asi.getM_AttributeSetInstance_ID()); + log.config("New ASI=" + line); + needSave = true; + } + } + // Create consume the Attribute Set Instance using policy FIFO/LIFO + else if(getMovementType().compareTo(MInOut.MOVEMENTTYPE_VendorReturns) == 0 || getMovementType().compareTo(MInOut.MOVEMENTTYPE_CustomerShipment) == 0) + { + String MMPolicy = product.getMMPolicy(); + Timestamp minGuaranteeDate = getMovementDate(); + MStorage[] storages = MStorage.getWarehouse(getCtx(), getM_Warehouse_ID(), line.getM_Product_ID(), + line.getM_AttributeSetInstance_ID(), + minGuaranteeDate, MClient.MMPOLICY_FiFo.equals(MMPolicy), true, line.getM_Locator_ID(), get_TrxName()); + BigDecimal qtyToDeliver = line.getMovementQty(); + BigDecimal qtyNegativeOnhand = Env.ZERO; + for (MStorage storage: storages) + { + if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0) + { + MInOutLineMA ma = new MInOutLineMA (line, + storage.getM_AttributeSetInstance_ID(), + qtyToDeliver); + if (!ma.save()) + { + throw new IllegalStateException("Error try create ASI Reservation"); + } + qtyToDeliver = Env.ZERO; + break; + } + else + { + MInOutLineMA ma = new MInOutLineMA (line, + storage.getM_AttributeSetInstance_ID(), + storage.getQtyOnHand()); + if (!ma.save()) + { + throw new IllegalStateException("Error try create ASI Reservation"); + } + qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand()); + log.fine( ma + ", QtyToDeliver=" + qtyToDeliver); + } + } + + if (qtyToDeliver.signum() != 0) + { + MInOutLineMA ma = new MInOutLineMA (line, 0, qtyToDeliver); + if (!ma.save()) + throw new IllegalStateException("Error try create ASI Reservation"); + log.fine("##: " + ma); + } + } // outgoing Trx + } // attributeSetInstance + + if (needSave && !line.save()) + log.severe("NOT saved " + line); + } // checkMaterialPolicy + + + /************************************************************************** + * Create Counter Document + * @return InOut + */ + private MInOut createCounterDoc() + { + // Is this a counter doc ? + if (getRef_InOut_ID() != 0) + return null; + + // Org Must be linked to BPartner + MOrg org = MOrg.get(getCtx(), getAD_Org_ID()); + int counterC_BPartner_ID = org.getLinkedC_BPartner_ID(get_TrxName()); + if (counterC_BPartner_ID == 0) + return null; + // Business Partner needs to be linked to Org + MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), get_TrxName()); + int counterAD_Org_ID = bp.getAD_OrgBP_ID_Int(); + if (counterAD_Org_ID == 0) + return null; + + MBPartner counterBP = new MBPartner (getCtx(), counterC_BPartner_ID, null); + MOrgInfo counterOrgInfo = MOrgInfo.get(getCtx(), counterAD_Org_ID); + log.info("Counter BP=" + counterBP.getName()); + + // Document Type + int C_DocTypeTarget_ID = 0; + MDocTypeCounter counterDT = MDocTypeCounter.getCounterDocType(getCtx(), getC_DocType_ID()); + if (counterDT != null) + { + log.fine(counterDT.toString()); + if (!counterDT.isCreateCounter() || !counterDT.isValid()) + return null; + C_DocTypeTarget_ID = counterDT.getCounter_C_DocType_ID(); + } + else // indirect + { + C_DocTypeTarget_ID = MDocTypeCounter.getCounterDocType_ID(getCtx(), getC_DocType_ID()); + log.fine("Indirect C_DocTypeTarget_ID=" + C_DocTypeTarget_ID); + if (C_DocTypeTarget_ID <= 0) + return null; + } + + // Deep Copy + MInOut counter = copyFrom(this, getMovementDate(), + C_DocTypeTarget_ID, !isSOTrx(), true, get_TrxName(), true); + + // + counter.setAD_Org_ID(counterAD_Org_ID); + counter.setM_Warehouse_ID(counterOrgInfo.getM_Warehouse_ID()); + // + counter.setBPartner(counterBP); + + if ( isDropShip() ) + { + counter.setIsDropShip(true ); + counter.setDropShip_BPartner_ID(getDropShip_BPartner_ID()); + counter.setDropShip_Location_ID(getDropShip_Location_ID()); + counter.setDropShip_User_ID(getDropShip_User_ID()); + } + + // Refernces (Should not be required + counter.setSalesRep_ID(getSalesRep_ID()); + counter.save(get_TrxName()); + + String MovementType = counter.getMovementType(); + boolean inTrx = MovementType.charAt(1) == '+'; // V+ Vendor Receipt + + // Update copied lines + MInOutLine[] counterLines = counter.getLines(true); + for (int i = 0; i < counterLines.length; i++) + { + MInOutLine counterLine = counterLines[i]; + counterLine.setClientOrg(counter); + counterLine.setM_Warehouse_ID(counter.getM_Warehouse_ID()); + counterLine.setM_Locator_ID(0); + counterLine.setM_Locator_ID(inTrx ? Env.ZERO : counterLine.getMovementQty()); + // + counterLine.save(get_TrxName()); + } + + log.fine(counter.toString()); + + // Document Action + if (counterDT != null) + { + if (counterDT.getDocAction() != null) + { + counter.setDocAction(counterDT.getDocAction()); + counter.processIt(counterDT.getDocAction()); + counter.save(get_TrxName()); + } + } + return counter; + } // createCounterDoc + + /** + * Void Document. + * @return true if success + */ + public boolean voidIt() + { + log.info(toString()); + // Before Void + m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_BEFORE_VOID); + if (m_processMsg != null) + return false; + + if (DOCSTATUS_Closed.equals(getDocStatus()) + || DOCSTATUS_Reversed.equals(getDocStatus()) + || DOCSTATUS_Voided.equals(getDocStatus())) + { + m_processMsg = "Document Closed: " + getDocStatus(); + return false; + } + + // Not Processed + if (DOCSTATUS_Drafted.equals(getDocStatus()) + || DOCSTATUS_Invalid.equals(getDocStatus()) + || DOCSTATUS_InProgress.equals(getDocStatus()) + || DOCSTATUS_Approved.equals(getDocStatus()) + || DOCSTATUS_NotApproved.equals(getDocStatus()) ) + { + // Set lines to 0 + MInOutLine[] lines = getLines(false); + for (int i = 0; i < lines.length; i++) + { + MInOutLine line = lines[i]; + BigDecimal old = line.getMovementQty(); + if (old.signum() != 0) + { + line.setQty(Env.ZERO); + line.addDescription("Void (" + old + ")"); + line.save(get_TrxName()); + } + } + } + else + { + return reverseCorrectIt(); + } + + // After Void + m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_VOID); + if (m_processMsg != null) + return false; + + setProcessed(true); + setDocAction(DOCACTION_None); + return true; + } // voidIt + + /** + * Close Document. + * @return true if success + */ + public boolean closeIt() + { + log.info(toString()); + // Before Close + m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_BEFORE_CLOSE); + if (m_processMsg != null) + return false; + + // After Close + m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_CLOSE); + if (m_processMsg != null) + return false; + + setProcessed(true); + setDocAction(DOCACTION_None); + return true; + } // closeIt + + /** + * Reverse Correction - same date + * @return true if success + */ + public boolean reverseCorrectIt() + { + log.info(toString()); + // Before reverseCorrect + m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_BEFORE_REVERSECORRECT); + if (m_processMsg != null) + return false; + + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + if (!MPeriod.isOpen(getCtx(), getDateAcct(), dt.getDocBaseType(), getAD_Org_ID())) + { + m_processMsg = "@PeriodClosed@"; + return false; + } + + // Reverse/Delete Matching + if (!isSOTrx()) + { + MMatchInv[] mInv = MMatchInv.getInOut(getCtx(), getM_InOut_ID(), get_TrxName()); + for (int i = 0; i < mInv.length; i++) + mInv[i].delete(true); + MMatchPO[] mPO = MMatchPO.getInOut(getCtx(), getM_InOut_ID(), get_TrxName()); + for (int i = 0; i < mPO.length; i++) + { + if (mPO[i].getC_InvoiceLine_ID() == 0) + mPO[i].delete(true); + else + { + mPO[i].setM_InOutLine_ID(0); + mPO[i].save(); + + } + } + } + + // Deep Copy + MInOut reversal = copyFrom (this, getMovementDate(), + getC_DocType_ID(), isSOTrx(), false, get_TrxName(), true); + if (reversal == null) + { + m_processMsg = "Could not create Ship Reversal"; + return false; + } + reversal.setReversal(true); + + // Reverse Line Qty + MInOutLine[] sLines = getLines(false); + MInOutLine[] rLines = reversal.getLines(false); + for (int i = 0; i < rLines.length; i++) + { + MInOutLine rLine = rLines[i]; + rLine.setQtyEntered(rLine.getQtyEntered().negate()); + rLine.setMovementQty(rLine.getMovementQty().negate()); + rLine.setM_AttributeSetInstance_ID(sLines[i].getM_AttributeSetInstance_ID()); + // Goodwill: store original (voided/reversed) document line + rLine.setReversalLine_ID(sLines[i].getM_InOutLine_ID()); + if (!rLine.save(get_TrxName())) + { + m_processMsg = "Could not correct Ship Reversal Line"; + return false; + } + // We need to copy MA + if (rLine.getM_AttributeSetInstance_ID() == 0) + { + MInOutLineMA mas[] = MInOutLineMA.get(getCtx(), + sLines[i].getM_InOutLine_ID(), get_TrxName()); + for (int j = 0; j < mas.length; j++) + { + MInOutLineMA ma = new MInOutLineMA (rLine, + mas[j].getM_AttributeSetInstance_ID(), + mas[j].getMovementQty().negate()); + if (!ma.save()) + ; + } + } + // De-Activate Asset + MAsset asset = MAsset.getFromShipment(getCtx(), sLines[i].getM_InOutLine_ID(), get_TrxName()); + if (asset != null) + { + asset.setIsActive(false); + asset.addDescription("(" + reversal.getDocumentNo() + " #" + rLine.getLine() + "<-)"); + asset.save(); + } + } + reversal.setC_Order_ID(getC_Order_ID()); + // Set M_RMA_ID + reversal.setM_RMA_ID(getM_RMA_ID()); + reversal.addDescription("{->" + getDocumentNo() + ")"); + // + if (!reversal.processIt(DocAction.ACTION_Complete) + || !reversal.getDocStatus().equals(DocAction.STATUS_Completed)) + { + m_processMsg = "Reversal ERROR: " + reversal.getProcessMsg(); + return false; + } + reversal.closeIt(); + //FR1948157 + reversal.setReversal_ID(getM_InOut_ID()); + reversal.setProcessing (false); + reversal.setDocStatus(DOCSTATUS_Reversed); + reversal.setDocAction(DOCACTION_None); + reversal.save(get_TrxName()); + // + addDescription("(" + reversal.getDocumentNo() + "<-)"); + + // After reverseCorrect + m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_REVERSECORRECT); + if (m_processMsg != null) + return false; + + m_processMsg = reversal.getDocumentNo(); + //FR1948157 + this.setReversal_ID(reversal.getM_InOut_ID()); + setProcessed(true); + setDocStatus(DOCSTATUS_Reversed); // may come from void + setDocAction(DOCACTION_None); + return true; + } // reverseCorrectionIt + + /** + * Reverse Accrual - none + * @return false + */ + public boolean reverseAccrualIt() + { + log.info(toString()); + // Before reverseAccrual + m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_BEFORE_REVERSEACCRUAL); + if (m_processMsg != null) + return false; + + // After reverseAccrual + m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_REVERSEACCRUAL); + if (m_processMsg != null) + return false; + + return false; + } // reverseAccrualIt + + /** + * Re-activate + * @return false + */ + public boolean reActivateIt() + { + log.info(toString()); + // Before reActivate + m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_BEFORE_REACTIVATE); + if (m_processMsg != null) + return false; + + // After reActivate + m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_REACTIVATE); + if (m_processMsg != null) + return false; + + return false; + } // reActivateIt + + + /************************************************************************* + * Get Summary + * @return Summary of Document + */ + public String getSummary() + { + StringBuffer sb = new StringBuffer(); + sb.append(getDocumentNo()); + // : Total Lines = 123.00 (#1) + sb.append(":") + // .append(Msg.translate(getCtx(),"TotalLines")).append("=").append(getTotalLines()) + .append(" (#").append(getLines(false).length).append(")"); + // - Description + if (getDescription() != null && getDescription().length() > 0) + sb.append(" - ").append(getDescription()); + return sb.toString(); + } // getSummary + + /** + * Get Process Message + * @return clear text error message + */ + public String getProcessMsg() + { + return m_processMsg; + } // getProcessMsg + + /** + * Get Document Owner (Responsible) + * @return AD_User_ID + */ + public int getDoc_User_ID() + { + return getSalesRep_ID(); + } // getDoc_User_ID + + /** + * Get Document Approval Amount + * @return amount + */ + public BigDecimal getApprovalAmt() + { + return Env.ZERO; + } // getApprovalAmt + + /** + * Get C_Currency_ID + * @return Accounting Currency + */ + public int getC_Currency_ID () + { + return Env.getContextAsInt(getCtx(),"$C_Currency_ID"); + } // getC_Currency_ID + + /** + * Document Status is Complete or Closed + * @return true if CO, CL or RE + */ + public boolean isComplete() + { + String ds = getDocStatus(); + return DOCSTATUS_Completed.equals(ds) + || DOCSTATUS_Closed.equals(ds) + || DOCSTATUS_Reversed.equals(ds); + } // isComplete + +} // MInOut diff --git a/base/src/org/compiere/model/MInventory.java b/base/src/org/compiere/model/MInventory.java index 7bc335ba1f..617fa46a4a 100644 --- a/base/src/org/compiere/model/MInventory.java +++ b/base/src/org/compiere/model/MInventory.java @@ -589,7 +589,6 @@ public class MInventory extends X_M_Inventory implements DocAction // Check Line boolean needSave = false; - BigDecimal qtyASI = Env.ZERO ; // Attribute Set Instance if (line.getM_AttributeSetInstance_ID() == 0) { @@ -612,21 +611,13 @@ public class MInventory extends X_M_Inventory implements DocAction else // Outgoing Trx { String MMPolicy = product.getMMPolicy(); - MStorage[] storages = MStorage.getAllWithASI(getCtx(), - line.getM_Product_ID(), line.getM_Locator_ID(), - MClient.MMPOLICY_FiFo.equals(MMPolicy), get_TrxName()); + MStorage[] storages = MStorage.getWarehouse(getCtx(), getM_Warehouse_ID(), line.getM_Product_ID(), 0, + null, MClient.MMPOLICY_FiFo.equals(MMPolicy), true, line.getM_Locator_ID(), get_TrxName()); + BigDecimal qtyToDeliver = qtyDiff.negate(); for (MStorage storage: storages) - { - //cosume ASI Zero - if (storage.getM_AttributeSetInstance_ID() == 0) - { - qtyASI = qtyASI.add(storage.getQtyOnHand()); - qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand()); - continue; - } - + { if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0) { MInventoryLineMA ma = new MInventoryLineMA (line, @@ -638,7 +629,7 @@ public class MInventory extends X_M_Inventory implements DocAction } qtyToDeliver = Env.ZERO; log.fine( ma + ", QtyToDeliver=" + qtyToDeliver); - //return; + break; } else { @@ -655,12 +646,12 @@ public class MInventory extends X_M_Inventory implements DocAction } // No AttributeSetInstance found for remainder - if (qtyToDeliver.signum() != 0 || qtyASI.signum() != 0) + if (qtyToDeliver.signum() != 0) { - MInventoryLineMA ma = new MInventoryLineMA (line, 0 , qtyToDeliver.add(qtyASI)); + MInventoryLineMA ma = new MInventoryLineMA (line, 0 , qtyToDeliver); if (!ma.save()) - ; + throw new IllegalStateException("Error try create ASI Reservation"); log.fine("##: " + ma); } } // outgoing Trx @@ -820,7 +811,7 @@ public class MInventory extends X_M_Inventory implements DocAction mas[j].getM_AttributeSetInstance_ID(), mas[j].getMovementQty().negate()); if (!ma.save()) - ; + throw new IllegalStateException("Error try create ASI Reservation"); } } } diff --git a/base/src/org/compiere/model/MMovement.java b/base/src/org/compiere/model/MMovement.java index 32bb132fab..5ce5f44e1d 100644 --- a/base/src/org/compiere/model/MMovement.java +++ b/base/src/org/compiere/model/MMovement.java @@ -658,81 +658,19 @@ public class MMovement extends X_M_Movement implements DocAction //{ // MMovementLine line = lines[i]; boolean needSave = false; - BigDecimal qtyASI = Env.ZERO ; // Attribute Set Instance if (line.getM_AttributeSetInstance_ID() == 0) { MProduct product = MProduct.get(getCtx(), line.getM_Product_ID()); String MMPolicy = product.getMMPolicy(); - MStorage[] storages = MStorage.getAllWithASI(getCtx(), - line.getM_Product_ID(), line.getM_Locator_ID(), - MClient.MMPOLICY_FiFo.equals(MMPolicy), get_TrxName()); + MStorage[] storages = MStorage.getWarehouse(getCtx(), 0, line.getM_Product_ID(), 0, + null, MClient.MMPOLICY_FiFo.equals(MMPolicy), true, line.getM_Locator_ID(), get_TrxName()); + BigDecimal qtyToDeliver = line.getMovementQty(); - - /*for (int ii = 0; ii < storages.length; ii++) - { - MStorage storage = storages[ii]; - if (ii == 0) - { - if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0) - { - line.setM_AttributeSetInstance_ID(storage.getM_AttributeSetInstance_ID()); - needSave = true; - log.config("Direct - " + line); - qtyToDeliver = Env.ZERO; - } - else - { - log.config("Split - " + line); - MMovementLineMA ma = new MMovementLineMA (line, - storage.getM_AttributeSetInstance_ID(), - storage.getQtyOnHand()); - if (!ma.save()) - ; - qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand()); - log.fine("#" + ii + ": " + ma + ", QtyToDeliver=" + qtyToDeliver); - } - } - else // create addl material allocation - { - MMovementLineMA ma = new MMovementLineMA (line, - storage.getM_AttributeSetInstance_ID(), - qtyToDeliver); - if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0) - qtyToDeliver = Env.ZERO; - else - { - ma.setMovementQty(storage.getQtyOnHand()); - qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand()); - } - if (!ma.save()) - ; - log.fine("#" + ii + ": " + ma + ", QtyToDeliver=" + qtyToDeliver); - } - if (qtyToDeliver.signum() == 0) - break; - } // for all storages - - // No AttributeSetInstance found for remainder - if (qtyToDeliver.signum() != 0) - { - MMovementLineMA ma = new MMovementLineMA (line, - 0, qtyToDeliver); - if (!ma.save()) - ; - log.fine("##: " + ma); - }*/ + for (MStorage storage: storages) { - //consume ASI Zero - if (storage.getM_AttributeSetInstance_ID() == 0) - { - qtyASI = qtyASI.add(storage.getQtyOnHand()); - qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand()); - continue; - } - if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0) { MMovementLineMA ma = new MMovementLineMA (line, @@ -744,7 +682,7 @@ public class MMovement extends X_M_Movement implements DocAction } qtyToDeliver = Env.ZERO; log.fine( ma + ", QtyToDeliver=" + qtyToDeliver); - //return; + break; } else { @@ -761,12 +699,12 @@ public class MMovement extends X_M_Movement implements DocAction } // No AttributeSetInstance found for remainder - if (qtyToDeliver.signum() != 0 || qtyASI.signum() != 0) + if (qtyToDeliver.signum() != 0) { - MMovementLineMA ma = new MMovementLineMA (line, 0 , qtyToDeliver.add(qtyASI)); + MMovementLineMA ma = new MMovementLineMA (line, 0 , qtyToDeliver); if (!ma.save()) - ; + throw new IllegalStateException("Error try create ASI Reservation"); log.fine("##: " + ma); } } // attributeSetInstance diff --git a/base/src/org/compiere/model/MStorage.java b/base/src/org/compiere/model/MStorage.java index 23589a8c45..193cd1fa01 100644 --- a/base/src/org/compiere/model/MStorage.java +++ b/base/src/org/compiere/model/MStorage.java @@ -78,7 +78,6 @@ public class MStorage extends X_M_Storage DB.close(rs, pstmt); rs = null; pstmt = null; } - pstmt = null; if (retValue == null) s_log.fine("Not Found - M_Locator_ID=" + M_Locator_ID + ", M_Product_ID=" + M_Product_ID + ", M_AttributeSetInstance_ID=" + M_AttributeSetInstance_ID); @@ -89,7 +88,7 @@ public class MStorage extends X_M_Storage } // get /** - * Get all Storages for Product with ASI and QtyOnHand > 0 + * Get all Storages for Product with ASI and QtyOnHand <> 0 * @param ctx context * @param M_Product_ID product * @param M_Locator_ID locator @@ -103,13 +102,9 @@ public class MStorage extends X_M_Storage ArrayList list = new ArrayList(); String sql = "SELECT * FROM M_Storage " + "WHERE M_Product_ID=? AND M_Locator_ID=?" - // Remove for management rightly FIFO/LIFO now you can consume a layer with ASI ID = zero and Qty onhand in negative - // + " AND M_AttributeSetInstance_ID > 0" - // + " AND QtyOnHand > 0 " - + " AND QtyOnHand <> 0 " + + " AND M_AttributeSetInstance_ID > 0 " + + " AND QtyOnHand <> 0 " + "ORDER BY M_AttributeSetInstance_ID"; - if (!FiFo) - sql += " DESC"; PreparedStatement pstmt = null; ResultSet rs = null; try @@ -130,14 +125,13 @@ public class MStorage extends X_M_Storage DB.close(rs, pstmt); rs = null; pstmt = null; } - pstmt = null; MStorage[] retValue = new MStorage[list.size()]; list.toArray(retValue); return retValue; } // getAllWithASI /** - * Get all Storages for Product + * Get all Storages for Product where QtyOnHand <> 0 * @param ctx context * @param M_Product_ID product * @param M_Locator_ID locator @@ -172,7 +166,6 @@ public class MStorage extends X_M_Storage DB.close(rs, pstmt); rs = null; pstmt = null; } - pstmt = null; MStorage[] retValue = new MStorage[list.size()]; list.toArray(retValue); return retValue; @@ -227,23 +220,41 @@ public class MStorage extends X_M_Storage * @param FiFo first in-first-out * @param trxName transaction * @return existing - ordered by location priority (desc) and/or guarantee date + * + * @deprecated */ public static MStorage[] getWarehouse (Properties ctx, int M_Warehouse_ID, int M_Product_ID, int M_AttributeSetInstance_ID, int M_AttributeSet_ID, boolean allAttributeInstances, Timestamp minGuaranteeDate, boolean FiFo, String trxName) { - if (M_Warehouse_ID == 0 || M_Product_ID == 0) + return getWarehouse(ctx, M_Warehouse_ID, M_Product_ID, M_AttributeSetInstance_ID, + minGuaranteeDate, FiFo, false, 0, trxName); + } + + /** + * Get Storage Info for Warehouse or locator + * @param ctx context + * @param M_Warehouse_ID ignore if M_Locator_ID > 0 + * @param M_Product_ID product + * @param M_AttributeSetInstance_ID instance id, 0 to retrieve all instance + * @param minGuaranteeDate optional minimum guarantee date if all attribute instances + * @param FiFo first in-first-out + * @param positiveOnly if true, only return storage records with qtyOnHand > 0 + * @param M_Locator_ID optional locator id + * @param trxName transaction + * @return existing - ordered by location priority (desc) and/or guarantee date + */ + public static MStorage[] getWarehouse (Properties ctx, int M_Warehouse_ID, + int M_Product_ID, int M_AttributeSetInstance_ID, Timestamp minGuaranteeDate, + boolean FiFo, boolean positiveOnly, int M_Locator_ID, String trxName) + { + if ((M_Warehouse_ID == 0 && M_Locator_ID == 0) || M_Product_ID == 0) return new MStorage[0]; - if (M_AttributeSet_ID == 0) - allAttributeInstances = true; - else - { - MAttributeSet mas = MAttributeSet.get(ctx, M_AttributeSet_ID); - if (!mas.isInstanceAttribute()) - allAttributeInstances = true; - } + boolean allAttributeInstances = false; + if (M_AttributeSetInstance_ID == 0) + allAttributeInstances = true; ArrayList list = new ArrayList(); // Specific Attribute Set Instance @@ -251,11 +262,18 @@ public class MStorage extends X_M_Storage + "s.AD_Client_ID,s.AD_Org_ID,s.IsActive,s.Created,s.CreatedBy,s.Updated,s.UpdatedBy," + "s.QtyOnHand,s.QtyReserved,s.QtyOrdered,s.DateLastInventory " + "FROM M_Storage s" - + " INNER JOIN M_Locator l ON (l.M_Locator_ID=s.M_Locator_ID) " - + "WHERE l.M_Warehouse_ID=?" - + " AND s.M_Product_ID=?" - + " AND COALESCE(s.M_AttributeSetInstance_ID,0)=? " - + "ORDER BY l.PriorityNo DESC, M_AttributeSetInstance_ID"; + + " INNER JOIN M_Locator l ON (l.M_Locator_ID=s.M_Locator_ID) "; + if (M_Locator_ID > 0) + sql += "WHERE l.M_Locator_ID = ?"; + else + sql += "WHERE l.M_Warehouse_ID=?"; + sql += " AND s.M_Product_ID=?" + + " AND COALESCE(s.M_AttributeSetInstance_ID,0)=? "; + if (positiveOnly) + { + sql += " AND s.QtyOnHand > 0 "; + } + sql += "ORDER BY l.PriorityNo DESC, M_AttributeSetInstance_ID"; if (!FiFo) sql += " DESC"; // All Attribute Set Instances @@ -266,19 +284,31 @@ public class MStorage extends X_M_Storage + "s.QtyOnHand,s.QtyReserved,s.QtyOrdered,s.DateLastInventory " + "FROM M_Storage s" + " INNER JOIN M_Locator l ON (l.M_Locator_ID=s.M_Locator_ID)" - + " LEFT OUTER JOIN M_AttributeSetInstance asi ON (s.M_AttributeSetInstance_ID=asi.M_AttributeSetInstance_ID) " - + "WHERE l.M_Warehouse_ID=?" - + " AND s.M_Product_ID=? "; + + " LEFT OUTER JOIN M_AttributeSetInstance asi ON (s.M_AttributeSetInstance_ID=asi.M_AttributeSetInstance_ID) "; + if (M_Locator_ID > 0) + sql += "WHERE l.M_Locator_ID = ?"; + else + sql += "WHERE l.M_Warehouse_ID=?"; + sql += " AND s.M_Product_ID=? "; if (minGuaranteeDate != null) { - sql += "AND (asi.GuaranteeDate IS NULL OR asi.GuaranteeDate>?) " - + "ORDER BY asi.GuaranteeDate, M_AttributeSetInstance_ID"; + sql += "AND (asi.GuaranteeDate IS NULL OR asi.GuaranteeDate>?) "; + if (positiveOnly) + { + sql += " AND s.QtyOnHand > 0 "; + } + sql += "ORDER BY l.PriorityNo DESC, " + + "asi.GuaranteeDate, M_AttributeSetInstance_ID"; if (!FiFo) sql += " DESC"; - sql += ", l.PriorityNo DESC, s.QtyOnHand DESC"; + sql += ", s.QtyOnHand DESC"; } else { + if (positiveOnly) + { + sql += " AND s.QtyOnHand > 0 "; + } sql += "ORDER BY l.PriorityNo DESC, l.M_Locator_ID, s.M_AttributeSetInstance_ID"; if (!FiFo) sql += " DESC"; @@ -290,15 +320,22 @@ public class MStorage extends X_M_Storage try { pstmt = DB.prepareStatement(sql, trxName); - pstmt.setInt(1, M_Warehouse_ID); + pstmt.setInt(1, M_Locator_ID > 0 ? M_Locator_ID : M_Warehouse_ID); pstmt.setInt(2, M_Product_ID); if (!allAttributeInstances) + { pstmt.setInt(3, M_AttributeSetInstance_ID); + } else if (minGuaranteeDate != null) + { pstmt.setTimestamp(3, minGuaranteeDate); + } rs = pstmt.executeQuery(); while (rs.next()) + { + if(rs.getBigDecimal(11).signum() != 0) list.add (new MStorage (ctx, rs, trxName)); + } } catch (Exception e) { diff --git a/base/src/org/compiere/process/InOutGenerate.java b/base/src/org/compiere/process/InOutGenerate.java index 8d1b95962b..855139ca1d 100644 --- a/base/src/org/compiere/process/InOutGenerate.java +++ b/base/src/org/compiere/process/InOutGenerate.java @@ -208,7 +208,7 @@ public class InOutGenerate extends SvrProcess */ private String generate (PreparedStatement pstmt) { - MClient client = MClient.get(getCtx()); + try { ResultSet rs = pstmt.executeQuery (); @@ -296,11 +296,10 @@ public class InOutGenerate extends SvrProcess // Stored Product String MMPolicy = product.getMMPolicy(); - MStorage[] storages = getStorages(line.getM_Warehouse_ID(), - line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), - product.getM_AttributeSet_ID(), - line.getM_AttributeSetInstance_ID()==0, minGuaranteeDate, - MClient.MMPOLICY_FiFo.equals(MMPolicy)); + + MStorage[] storages = getStorages(line.getM_Warehouse_ID(), + line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), + minGuaranteeDate, MClient.MMPOLICY_FiFo.equals(MMPolicy)); for (int j = 0; j < storages.length; j++) { @@ -382,9 +381,7 @@ public class InOutGenerate extends SvrProcess String MMPolicy = product.getMMPolicy(); storages = getStorages(line.getM_Warehouse_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), - product.getM_AttributeSet_ID(), - line.getM_AttributeSetInstance_ID()==0, minGuaranteeDate, - MClient.MMPOLICY_FiFo.equals(MMPolicy)); + minGuaranteeDate, MClient.MMPOLICY_FiFo.equals(MMPolicy)); } // createLine (order, line, toDeliver, storages, false); @@ -460,15 +457,7 @@ public class InOutGenerate extends SvrProcess return; } - // Product - MProduct product = orderLine.getProduct(); - boolean linePerASI = false; - if (product.getM_AttributeSet_ID() != 0) - { - MAttributeSet mas = MAttributeSet.get(getCtx(), product.getM_AttributeSet_ID()); - linePerASI = mas.isInstanceAttribute(); - } - + // Inventory Lines ArrayList list = new ArrayList(); BigDecimal toDeliver = qty; @@ -489,12 +478,12 @@ public class InOutGenerate extends SvrProcess int M_Locator_ID = storage.getM_Locator_ID(); // MInOutLine line = null; - if (!linePerASI) // find line with Locator + if (orderLine.getM_AttributeSetInstance_ID() == 0) // find line with Locator { for (int ll = 0; ll < list.size(); ll++) { MInOutLine test = (MInOutLine)list.get(ll); - if (test.getM_Locator_ID() == M_Locator_ID) + if (test.getM_Locator_ID() == M_Locator_ID && test.getM_AttributeSetInstance_ID() == 0) { line = test; break; @@ -514,20 +503,34 @@ public class InOutGenerate extends SvrProcess line.setQtyEntered(line.getMovementQty().multiply(orderLine.getQtyEntered()) .divide(orderLine.getQtyOrdered(), 12, BigDecimal.ROUND_HALF_UP)); line.setLine(m_line + orderLine.getLine()); - if (linePerASI) - line.setM_AttributeSetInstance_ID(storage.getM_AttributeSetInstance_ID()); if (!line.save()) throw new IllegalStateException("Could not create Shipment Line"); log.fine("ToDeliver=" + qty + "/" + deliver + " - " + line); toDeliver = toDeliver.subtract(deliver); - // Temp adjustment + // Temp adjustment, actual update happen in MInOut.completeIt storage.setQtyOnHand(storage.getQtyOnHand().subtract(deliver)); // if (toDeliver.signum() == 0) break; } if (toDeliver.signum() != 0) - throw new IllegalStateException("Not All Delivered - Remainder=" + toDeliver); + { + if (!force) + { + throw new IllegalStateException("Not All Delivered - Remainder=" + toDeliver); + } + else + { + + MInOutLine line = new MInOutLine (m_shipment); + line.setOrderLine(orderLine, 0, order.isSOTrx() ? toDeliver : Env.ZERO); + line.setQty(toDeliver); + if (!line.save()) + throw new IllegalStateException("Could not create Shipment Line"); + + + } + } } // createLine @@ -536,20 +539,17 @@ public class InOutGenerate extends SvrProcess * @param M_Warehouse_ID * @param M_Product_ID * @param M_AttributeSetInstance_ID - * @param M_AttributeSet_ID - * @param allAttributeInstances * @param minGuaranteeDate * @param FiFo * @return storages */ private MStorage[] getStorages(int M_Warehouse_ID, - int M_Product_ID, int M_AttributeSetInstance_ID, int M_AttributeSet_ID, - boolean allAttributeInstances, Timestamp minGuaranteeDate, - boolean FiFo) + int M_Product_ID, int M_AttributeSetInstance_ID, + Timestamp minGuaranteeDate, boolean FiFo) { m_lastPP = new SParameter(M_Warehouse_ID, - M_Product_ID, M_AttributeSetInstance_ID, M_AttributeSet_ID, - allAttributeInstances, minGuaranteeDate, FiFo); + M_Product_ID, M_AttributeSetInstance_ID, + minGuaranteeDate, FiFo); // m_lastStorages = m_map.get(m_lastPP); @@ -557,8 +557,7 @@ public class InOutGenerate extends SvrProcess { m_lastStorages = MStorage.getWarehouse(getCtx(), M_Warehouse_ID, M_Product_ID, M_AttributeSetInstance_ID, - M_AttributeSet_ID, allAttributeInstances, minGuaranteeDate, - FiFo, get_TrxName()); + minGuaranteeDate, FiFo,true, 0, get_TrxName()); m_map.put(m_lastPP, m_lastStorages); } return m_lastStorages; @@ -579,9 +578,11 @@ public class InOutGenerate extends SvrProcess // addLog(m_shipment.getM_InOut_ID(), m_shipment.getMovementDate(), null, m_shipment.getDocumentNo()); m_created++; + + //reset storage cache as MInOut.completeIt will update m_storage m_map = new HashMap(); - if (m_lastPP != null && m_lastStorages != null) - m_map.put(m_lastPP, m_lastStorages); + m_lastPP = null; + m_lastStorages = null; } m_shipment = null; m_line = 0; @@ -597,21 +598,16 @@ public class InOutGenerate extends SvrProcess * @param p_Warehouse_ID warehouse * @param p_Product_ID * @param p_AttributeSetInstance_ID - * @param p_AttributeSet_ID - * @param p_allAttributeInstances * @param p_minGuaranteeDate * @param p_FiFo */ protected SParameter (int p_Warehouse_ID, - int p_Product_ID, int p_AttributeSetInstance_ID, int p_AttributeSet_ID, - boolean p_allAttributeInstances, Timestamp p_minGuaranteeDate, - boolean p_FiFo) + int p_Product_ID, int p_AttributeSetInstance_ID, + Timestamp p_minGuaranteeDate,boolean p_FiFo) { this.M_Warehouse_ID = p_Warehouse_ID; this.M_Product_ID = p_Product_ID; this.M_AttributeSetInstance_ID = p_AttributeSetInstance_ID; - this.M_AttributeSet_ID = p_AttributeSet_ID; - this.allAttributeInstances = p_allAttributeInstances; this.minGuaranteeDate = p_minGuaranteeDate; this.FiFo = p_FiFo; }