diff --git a/base/src/org/adempiere/pipo/handler/RoleElementHandler.java b/base/src/org/adempiere/pipo/handler/RoleElementHandler.java index 45ea17c24b..06609a3658 100644 --- a/base/src/org/adempiere/pipo/handler/RoleElementHandler.java +++ b/base/src/org/adempiere/pipo/handler/RoleElementHandler.java @@ -178,6 +178,9 @@ public class RoleElementHandler extends AbstractElementHandler { m_Role.setAllow_Info_Product(Boolean.valueOf(atts.getValue("AllowInfoProduct"))); m_Role.setAllow_Info_Resource(Boolean.valueOf(atts.getValue("AllowInfoResource"))); m_Role.setAllow_Info_Schedule(Boolean.valueOf(atts.getValue("AllowInfoSchedule"))); + m_Role.setAllow_Info_Schedule(Boolean.valueOf(atts.getValue("AllowInfoCRP"))); + m_Role.setAllow_Info_Schedule(Boolean.valueOf(atts.getValue("AllowInfoMRP"))); + if (m_Role.save(getTrxName(ctx)) == true) { @@ -504,6 +507,8 @@ public class RoleElementHandler extends AbstractElementHandler { atts.addAttribute("", "", "AllowInfoProduct", "CDATA", Boolean.toString(m_Role.isAllow_Info_Product())); atts.addAttribute("", "", "AllowInfoResource", "CDATA", Boolean.toString(m_Role.isAllow_Info_Resource())); atts.addAttribute("", "", "AllowInfoSchedule", "CDATA", Boolean.toString(m_Role.isAllow_Info_Schedule())); + atts.addAttribute("", "", "AllowInfoCRP", "CDATA", Boolean.toString(m_Role.isAllow_Info_CRP())); + atts.addAttribute("", "", "AllowInfoMRP", "CDATA", Boolean.toString(m_Role.isAllow_Info_MRP())); return atts; } diff --git a/base/src/org/compiere/model/MAllocationHdr.java b/base/src/org/compiere/model/MAllocationHdr.java index 3e51e03be7..f9583ecbb3 100644 --- a/base/src/org/compiere/model/MAllocationHdr.java +++ b/base/src/org/compiere/model/MAllocationHdr.java @@ -40,6 +40,7 @@ import org.compiere.util.Msg; * * @author Jorg Janke * @version $Id: MAllocationHdr.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + * @author victor.perez@e-evolution.com www.e-evolution.com FR [ 1866214 ] http://sourceforge.net/tracker/index.php?func=detail&aid=1866214&group_id=176962&atid=879335 */ public final class MAllocationHdr extends X_C_AllocationHdr implements DocAction { @@ -119,6 +120,54 @@ public final class MAllocationHdr extends X_C_AllocationHdr implements DocAction return retValue; } // getOfInvoice + //FR [ 1866214 ] + /** + * Get Allocations of Cash + * @param ctx context + * @param C_Cash_ID Cash ID + * @return allocations of payment + * @param trxName transaction + */ + public static MAllocationHdr[] getOfCash (Properties ctx, int C_Cash_ID, String trxName) + { + String sql = "SELECT a.C_AllocationHdr_ID FROM C_Cash c " + + " INNER JOIN C_Cashline cl ON (c.C_Cash_ID= cl.C_Cash_ID) " + + " INNER JOIN C_AllocationLine al ON (al.C_Cashline_ID=cl.C_Cashline_ID) " + + " INNER JOIN C_AllocationHdr a ON(al.C_AllocationHdr_ID=a.C_AllocationHdr_ID) " + + " WHERE c.C_Cash_ID=? GROUP BY a.C_AllocationHdr_ID"; + + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, trxName); + pstmt.setInt(1, C_Cash_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add (new MAllocationHdr(ctx, rs.getInt(1), trxName)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MAllocationHdr[] retValue = new MAllocationHdr[list.size()]; + list.toArray(retValue); + return retValue; + } // getOfInvoice + /** Logger */ private static CLogger s_log = CLogger.getCLogger(MAllocationHdr.class); diff --git a/base/src/org/compiere/model/MCash.java b/base/src/org/compiere/model/MCash.java index 1cc11b01bb..d2c08161db 100644 --- a/base/src/org/compiere/model/MCash.java +++ b/base/src/org/compiere/model/MCash.java @@ -1,5 +1,5 @@ /****************************************************************************** - * Product: Adempiere ERP & CRM Smart Business Solution * + * 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 * @@ -38,10 +38,10 @@ import org.compiere.util.TimeUtil; * Cash Journal Model * * @author Jorg Janke - * @version $Id: MCash.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ - * - * @author Teo Sarca, SC ARHIPAC SERVICE SRL - *
  • BF [ 1831997 ] Cash journal allocation reversed + * @version $Id: MCash.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ + * @author victor.perez@e-evolution.com www.e-evolution.com FR [ 1866214 ] http://sourceforge.net/tracker/index.php?func=detail&aid=1866214&group_id=176962&atid=879335 + * @author Teo Sarca, SC ARHIPAC SERVICE SRL + *
  • BF [ 1831997 ] Cash journal allocation reversed *
  • BF [ 1894524 ] Pay an reversed invoice */ public class MCash extends X_C_Cash implements DocAction @@ -567,6 +567,13 @@ public class MCash extends X_C_Cash implements DocAction m_processMsg = CLogger.retrieveErrorString("Could not create Payment"); return DocAction.STATUS_Invalid; } + + line.setC_Payment_ID(pay.getC_Payment_ID()); + if (!line.save()) + { + m_processMsg = "Could not update Cash Line"; + return DocAction.STATUS_Invalid; + } } } @@ -594,18 +601,108 @@ public class MCash extends X_C_Cash implements DocAction // Before Void m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_BEFORE_VOID); if (m_processMsg != null) - return false; - // After Void - m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_VOID); - if (m_processMsg != null) - return false; - setDocAction(DOCACTION_None); - return false; + return false; + + //FR [ 1866214 ] + boolean retValue = reverseIt(); + + if (retValue) { + // After Void + m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_VOID); + if (m_processMsg != null) + return false; + setDocAction(DOCACTION_None); + } + + return retValue; } // voidIt + //FR [ 1866214 ] + /************************************************************************** + * Reverse Cash + * Period needs to be open + * @return true if reversed + */ + private boolean reverseIt() + { + if (DOCSTATUS_Closed.equals(getDocStatus()) + || DOCSTATUS_Reversed.equals(getDocStatus()) + || DOCSTATUS_Voided.equals(getDocStatus())) + { + m_processMsg = "Document Closed: " + getDocStatus(); + setDocAction(DOCACTION_None); + return false; + } + + // Can we delete posting + if (!MPeriod.isOpen(getCtx(), this.getDateAcct(), MPeriodControl.DOCBASETYPE_CashJournal)) + throw new IllegalStateException("@PeriodClosed@"); + + // Reverse Allocations + MAllocationHdr[] allocations = MAllocationHdr.getOfCash(getCtx(), getC_Cash_ID(), get_TrxName()); + for(MAllocationHdr allocation : allocations) + { + allocation.reverseCorrectIt(); + if(!allocation.save()) + throw new IllegalStateException("Cannot reverse allocations"); + } + + MCashLine[] cashlines = getLines(true); + for (MCashLine cashline : cashlines ) + { + BigDecimal oldAmount = cashline.getAmount(); + BigDecimal oldDiscount = cashline.getDiscountAmt(); + BigDecimal oldWriteOff = cashline.getWriteOffAmt(); + cashline.setAmount(Env.ZERO); + cashline.setDiscountAmt(Env.ZERO); + cashline.setWriteOffAmt(Env.ZERO); + cashline.addDescription(Msg.getMsg(getCtx(), "Voided") + + " (Amount=" + oldAmount + ", Discount=" + oldDiscount + + ", WriteOff=" + oldWriteOff + ", )"); + if (MCashLine.CASHTYPE_BankAccountTransfer.equals(cashline.getCashType())) + { + if (cashline.getC_Payment_ID() == 0) + throw new IllegalStateException("Cannot reverse payment"); + + MPayment payment = new MPayment(getCtx(), cashline.getC_Payment_ID(),get_TrxName()); + payment.reverseCorrectIt(); + if (!payment.save()) + throw new IllegalStateException("Cannot reverse payment"); + } + } + + setName(getName()+"^"); + addDescription(Msg.getMsg(getCtx(), "Voided")); + setDocStatus(DOCSTATUS_Reversed); // for direct calls + setProcessed(true); + setDocAction(DOCACTION_None); + if (!save()) + throw new IllegalStateException("Cannot save journal cash"); + + // Delete Posting + String sql = "DELETE FROM Fact_Acct WHERE AD_Table_ID=" + MCash.Table_ID + + " AND Record_ID=" + getC_Cash_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + log.fine("Fact_Acct deleted #" + no); + return true; + } // reverse + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + /** * Close Document. - * Cancel not delivered Qunatities + * Cancel not delivered Quantities * @return true if success */ public boolean closeIt() @@ -636,12 +733,17 @@ public class MCash extends X_C_Cash implements DocAction if (m_processMsg != null) return false; - // After reverseCorrect - m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_REVERSECORRECT); - if (m_processMsg != null) - return false; + //FR [ 1866214 ] + boolean retValue = reverseIt(); - return false; + if (retValue) { + // After reverseCorrect + m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_REVERSECORRECT); + if (m_processMsg != null) + return false; + } + + return retValue; } // reverseCorrectionIt /** diff --git a/base/src/org/compiere/model/MInOut.java b/base/src/org/compiere/model/MInOut.java index 8bc4e6bfce..b40ff26b12 100644 --- a/base/src/org/compiere/model/MInOut.java +++ b/base/src/org/compiere/model/MInOut.java @@ -1,2034 +1,2090 @@ -/****************************************************************************** - * 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.*; -import java.math.*; -import java.sql.*; -import java.util.*; -import java.util.logging.*; -import org.compiere.print.*; -import org.compiere.process.*; -import org.compiere.util.*; - -/** - * 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 - */ -public class MInOut extends X_M_InOut implements DocAction -{ - /** - * 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()); - } // 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 - - /** - * 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 - - - /** 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())); - rs.close(); - rs = null; - pstmt.close(); - pstmt = null; - } - catch (SQLException ex) - { - log.log(Level.SEVERE, sql, ex); - list = null; - // throw new DBException(ex); - } - finally - { - try - { - if (rs != null) - rs.close(); - if (pstmt != null) - pstmt.close(); - } - catch (SQLException e) - { - } - } - pstmt = null; - rs = 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())) - { - 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()); - - checkMaterialPolicy(sLine); - // Stock Movement - Counterpart MOrder.reserveStock - if (product != null - && product.isStocked() ) - { - 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 QtySOMA = Env.ZERO; - BigDecimal QtyPOMA = Env.ZERO; - if (sLine.getC_OrderLine_ID() != 0) - { - if (isSOTrx()) - QtySOMA = ma.getMovementQty(); - else - QtyPOMA = ma.getMovementQty(); - } - BigDecimal diffQtyOrdered = QtyPOMA.negate(); - if (!sameWarehouse) { - diffQtyOrdered = Env.ZERO; - } - // 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, QtySOMA.negate(), diffQtyOrdered, 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, Env.ZERO, QtyPOMA.negate(), 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 diffQtyOrdered = QtyPO.negate(); - if (!sameWarehouse) { - diffQtyOrdered = 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, QtySO.negate(), diffQtyOrdered, 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, Env.ZERO, 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 = "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 = "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()); - // 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 - - /** - * 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) - { - line.setM_Warehouse_ID(getM_Warehouse_ID()); - line.setM_Locator_ID(inTrx ? Env.ZERO : line.getMovementQty()); // default Locator - needSave = true; - } - - // Attribute Set Instance - if (product != null - && line.getM_AttributeSetInstance_ID() == 0) - { - if (inTrx) - { - 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()) - { - line.setM_AttributeSetInstance_ID(asi.getM_AttributeSetInstance_ID()); - log.config("New ASI=" + line); - needSave = true; - } - } - 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()); - 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 - - // No AttributeSetInstance found for remainder - if (qtyToDeliver.signum() != 0) - { - MInOutLineMA ma = new MInOutLineMA (line, - 0, qtyToDeliver); - 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); - // 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())) - { - 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()); - 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(); - 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(); - 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 +/****************************************************************************** + * 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.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.print.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** + * 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 + *
  • FR [ 1948157 ] Is necessary the reference for document reverse + * @see http://sourceforge.net/tracker/?func=detail&atid=879335&aid=1948157&group_id=176962 + */ +public class MInOut extends X_M_InOut implements DocAction +{ + /** + * 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()); + } // 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 + + /** + * 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 + + + /** 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())); + rs.close(); + rs = null; + pstmt.close(); + pstmt = null; + } + catch (SQLException ex) + { + log.log(Level.SEVERE, sql, ex); + list = null; + // throw new DBException(ex); + } + finally + { + try + { + if (rs != null) + rs.close(); + if (pstmt != null) + pstmt.close(); + } + catch (SQLException e) + { + } + } + pstmt = null; + rs = 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())) + { + 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 QtySOMA = Env.ZERO; + BigDecimal QtyPOMA = Env.ZERO; + if (sLine.getC_OrderLine_ID() != 0) + { + if (isSOTrx()) + QtySOMA = ma.getMovementQty(); + else + QtyPOMA = ma.getMovementQty(); + } + BigDecimal diffQtyOrdered = QtyPOMA.negate(); + if (!sameWarehouse) { + diffQtyOrdered = Env.ZERO; + } + // 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, QtySOMA.negate(), diffQtyOrdered, 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, Env.ZERO, QtyPOMA.negate(), 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 diffQtyOrdered = QtyPO.negate(); + if (!sameWarehouse) { + diffQtyOrdered = 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, QtySO.negate(), diffQtyOrdered, 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, Env.ZERO, 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 = "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 = "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()); + // 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 + + /** + * 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); + // 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())) + { + 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()); + 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 7bf79d52eb..c2625e4c7f 100644 --- a/base/src/org/compiere/model/MInventory.java +++ b/base/src/org/compiere/model/MInventory.java @@ -1,972 +1,1182 @@ -/****************************************************************************** - * 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.*; -import java.math.*; -import java.sql.*; -import java.util.*; -import java.util.logging.*; -import org.compiere.process.*; -import org.compiere.util.*; - -/** - * Physical Inventory Model - * - * @author Jorg Janke - * @version $Id: MInventory.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ - */ -public class MInventory extends X_M_Inventory implements DocAction -{ - /** - * Get Inventory from Cache - * @param ctx context - * @param M_Inventory_ID id - * @return MInventory - */ - public static MInventory get (Properties ctx, int M_Inventory_ID) - { - Integer key = new Integer (M_Inventory_ID); - MInventory retValue = (MInventory) s_cache.get (key); - if (retValue != null) - return retValue; - retValue = new MInventory (ctx, M_Inventory_ID, null); - if (retValue.get_ID () != 0) - s_cache.put (key, retValue); - return retValue; - } // get - - /** Cache */ - private static CCache s_cache = new CCache("M_Inventory", 5, 5); - - - /** - * Standard Constructor - * @param ctx context - * @param M_Inventory_ID id - * @param trxName transaction - */ - public MInventory (Properties ctx, int M_Inventory_ID, String trxName) - { - super (ctx, M_Inventory_ID, trxName); - if (M_Inventory_ID == 0) - { - // setName (null); - // setM_Warehouse_ID (0); // FK - setMovementDate (new Timestamp(System.currentTimeMillis())); - setDocAction (DOCACTION_Complete); // CO - setDocStatus (DOCSTATUS_Drafted); // DR - setIsApproved (false); - setMovementDate (new Timestamp(System.currentTimeMillis())); // @#Date@ - setPosted (false); - setProcessed (false); - } - } // MInventory - - /** - * Load Constructor - * @param ctx context - * @param rs result set - * @param trxName transaction - */ - public MInventory (Properties ctx, ResultSet rs, String trxName) - { - super(ctx, rs, trxName); - } // MInventory - - /** - * Warehouse Constructor - * @param wh warehouse - */ - public MInventory (MWarehouse wh) - { - this (wh.getCtx(), 0, wh.get_TrxName()); - setClientOrg(wh); - setM_Warehouse_ID(wh.getM_Warehouse_ID()); - } // MInventory - - - /** Lines */ - private MInventoryLine[] m_lines = null; - - /** - * Get Lines - * @param requery requery - * @return array of lines - */ - public MInventoryLine[] 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_InventoryLine WHERE M_Inventory_ID=? ORDER BY Line"; - PreparedStatement pstmt = null; - try - { - pstmt = DB.prepareStatement (sql, get_TrxName()); - pstmt.setInt (1, getM_Inventory_ID()); - ResultSet rs = pstmt.executeQuery (); - while (rs.next ()) - list.add (new MInventoryLine (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_lines = new MInventoryLine[list.size ()]; - list.toArray (m_lines); - return m_lines; - } // getLines - - /** - * Add to Description - * @param description text - */ - public void addDescription (String description) - { - String desc = getDescription(); - if (desc == null) - setDescription(description); - else - setDescription(desc + " | " + description); - } // addDescription - - /** - * Overwrite Client/Org - from Import. - * @param AD_Client_ID client - * @param AD_Org_ID org - */ - public void setClientOrg (int AD_Client_ID, int AD_Org_ID) - { - super.setClientOrg(AD_Client_ID, AD_Org_ID); - } // setClientOrg - - /** - * String Representation - * @return info - */ - public String toString () - { - StringBuffer sb = new StringBuffer ("MInventory["); - sb.append (get_ID()) - .append ("-").append (getDocumentNo()) - .append (",M_Warehouse_ID=").append(getM_Warehouse_ID()) - .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.INVOICE, getC_Invoice_ID()); - // if (re == null) - return null; - // return re.getPDF(file); - } // createPDF - - - /** - * Before Save - * @param newRecord new - * @return true - */ - protected boolean beforeSave (boolean newRecord) - { - if (getC_DocType_ID() == 0) - { - MDocType types[] = MDocType.getOfDocBaseType(getCtx(), MDocType.DOCBASETYPE_MaterialPhysicalInventory); - if (types.length > 0) // get first - setC_DocType_ID(types[0].getC_DocType_ID()); - else - { - log.saveError("Error", Msg.parseTranslation(getCtx(), "@NotFound@ @C_DocType_ID@")); - return false; - } - } - return true; - } // beforeSave - - - /** - * 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_InventoryLine SET Processed='" - + (processed ? "Y" : "N") - + "' WHERE M_Inventory_ID=" + getM_Inventory_ID(); - int noLine = DB.executeUpdate(sql, get_TrxName()); - m_lines = null; - log.fine("Processed=" + processed + " - Lines=" + noLine); - } // setProcessed - - - /************************************************************************** - * 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()); - } // processIt - - /** 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; - - // Std Period open? - if (!MPeriod.isOpen(getCtx(), getMovementDate(), MDocType.DOCBASETYPE_MaterialPhysicalInventory)) - { - m_processMsg = "@PeriodClosed@"; - return DocAction.STATUS_Invalid; - } - MInventoryLine[] lines = getLines(false); - if (lines.length == 0) - { - m_processMsg = "@NoLines@"; - return DocAction.STATUS_Invalid; - } - - // TODO: Add up Amounts - // setApprovalAmt(); - - 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; - - // Implicit Approval - if (!isApproved()) - approveIt(); - log.info(toString()); - - //vpj-cd begin e-evolution recalculate the attribute instances and qty. - MInventoryLine[] linesup = getLines(false); - for (int i = 0; i < linesup.length; i++) - { - MInventoryLine line = linesup[i]; - - String sql1 = "Delete From M_InventoryLineMA " - + " WHERE M_InventoryLine_ID=" +line.getM_InventoryLine_ID(); - int no = DB.executeUpdate(sql1, get_TrxName()); - log.info("MA deleted " + no); - - StringBuffer sql = new StringBuffer( - "SELECT s.M_Product_ID, s.M_Locator_ID, s.M_AttributeSetInstance_ID," - + " s.QtyOnHand, p.M_AttributeSet_ID " - + "FROM M_Product p" - + " INNER JOIN M_Storage s ON (s.M_Product_ID=p.M_Product_ID)" - + " INNER JOIN M_Locator l ON (s.M_Locator_ID=l.M_Locator_ID) " - + "WHERE l.M_Warehouse_ID=?" - + " AND p.IsActive='Y' AND p.IsStocked='Y' and p.ProductType='I'" - + " AND s.M_Locator_ID=" +line.getM_Locator_ID() - + " AND s.M_Product_ID=" +line.getM_Product_ID() - + " AND s.QtyOnHand <> 0 " - ); - PreparedStatement pstmt = null; - try - { - pstmt = DB.prepareStatement (sql.toString(), get_TrxName()); - int index = 1; - pstmt.setInt (index++, getM_Warehouse_ID()); - ResultSet rs = pstmt.executeQuery (); - while (rs.next ()) - { - MInventoryLineMA maup = new MInventoryLineMA (line, - rs.getInt(3), rs.getBigDecimal(4)); - - if (!maup.save()) - ; - } - rs.close (); - pstmt.close (); - pstmt = null; - } - catch (Exception e) - { - log.log(Level.SEVERE, sql.toString(), e); - } - try - { - if (pstmt != null) - pstmt.close (); - pstmt = null; - } - catch (Exception e) - { - pstmt = null; - } - } - //vpj-cd e-evolution recalculate the attribute instances and qty END. - // - MInventoryLine[] lines = getLines(false); - for (int i = 0; i < lines.length; i++) - { - MInventoryLine line = lines[i]; - if (!line.isActive()) - continue; - - MTransaction trx = null; - if (line.getM_AttributeSetInstance_ID() == 0) - { - BigDecimal qtyDiff = line.getQtyInternalUse().negate(); - if (qtyDiff.signum() == 0) - qtyDiff = line.getQtyCount().subtract(line.getQtyBook()); - // - if (qtyDiff.signum() > 0) - { - // Storage - MStorage storage = MStorage.get(getCtx(), line.getM_Locator_ID(), - line.getM_Product_ID(), 0, get_TrxName()); - if (storage == null) - storage = MStorage.getCreate(getCtx(), line.getM_Locator_ID(), - line.getM_Product_ID(), 0, get_TrxName()); - BigDecimal qtyNew = storage.getQtyOnHand().add(qtyDiff); - log.fine("Diff=" + qtyDiff - + " - OnHand=" + storage.getQtyOnHand() + "->" + qtyNew); - storage.setQtyOnHand(qtyNew); - storage.setDateLastInventory(getMovementDate()); - if (!storage.save(get_TrxName())) - { - m_processMsg = "Storage not updated(1)"; - return DocAction.STATUS_Invalid; - } - log.fine(storage.toString()); - // Transaction - trx = new MTransaction (getCtx(), line.getAD_Org_ID(), - MTransaction.MOVEMENTTYPE_InventoryIn, - line.getM_Locator_ID(), line.getM_Product_ID(), 0, - qtyDiff, getMovementDate(), get_TrxName()); - trx.setM_InventoryLine_ID(line.getM_InventoryLine_ID()); - if (!trx.save()) - { - m_processMsg = "Transaction not inserted(1)"; - return DocAction.STATUS_Invalid; - } - } - else // negative qty - { - MInventoryLineMA mas[] = MInventoryLineMA.get(getCtx(), - line.getM_InventoryLine_ID(), get_TrxName()); - for (int j = 0; j < mas.length; j++) - { - MInventoryLineMA ma = mas[j]; - // Storage - MStorage storage = MStorage.get(getCtx(), line.getM_Locator_ID(), - line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), get_TrxName()); - if (storage == null) - storage = MStorage.getCreate(getCtx(), line.getM_Locator_ID(), - line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), get_TrxName()); - // - BigDecimal maxDiff = qtyDiff; - if (maxDiff.signum() < 0 - && ma.getMovementQty().compareTo(maxDiff.negate()) < 0) - maxDiff = ma.getMovementQty().negate(); - BigDecimal qtyNew = ma.getMovementQty().add(maxDiff); // Storage+Diff - log.fine("MA Qty=" + ma.getMovementQty() - + ",Diff=" + qtyDiff + "|" + maxDiff - + " - OnHand=" + storage.getQtyOnHand() + "->" + qtyNew - + " {" + ma.getM_AttributeSetInstance_ID() + "}"); - // - storage.setQtyOnHand(qtyNew); - storage.setDateLastInventory(getMovementDate()); - if (!storage.save(get_TrxName())) - { - m_processMsg = "Storage not updated (MA)"; - return DocAction.STATUS_Invalid; - } - log.fine(storage.toString()); - - // Transaction - trx = new MTransaction (getCtx(), line.getAD_Org_ID(), - MTransaction.MOVEMENTTYPE_InventoryIn, - line.getM_Locator_ID(), line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), - maxDiff, getMovementDate(), get_TrxName()); - trx.setM_InventoryLine_ID(line.getM_InventoryLine_ID()); - if (!trx.save()) - { - m_processMsg = "Transaction not inserted (MA)"; - return DocAction.STATUS_Invalid; - } - // - qtyDiff = qtyDiff.subtract(maxDiff); - if (qtyDiff.signum() == 0) - break; - } - } // negative qty - } - - // Fallback - if (trx == null) - { - // Storage - MStorage storage = MStorage.get(getCtx(), line.getM_Locator_ID(), - line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), get_TrxName()); - if (storage == null) - storage = MStorage.getCreate(getCtx(), line.getM_Locator_ID(), - line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), get_TrxName()); - // - BigDecimal qtyDiff = line.getQtyInternalUse().negate(); - if (Env.ZERO.compareTo(qtyDiff) == 0) - qtyDiff = line.getQtyCount().subtract(line.getQtyBook()); - BigDecimal qtyNew = storage.getQtyOnHand().add(qtyDiff); - log.fine("Count=" + line.getQtyCount() - + ",Book=" + line.getQtyBook() + ", Difference=" + qtyDiff - + " - OnHand=" + storage.getQtyOnHand() + "->" + qtyNew); - // - storage.setQtyOnHand(qtyNew); - storage.setDateLastInventory(getMovementDate()); - if (!storage.save(get_TrxName())) - { - m_processMsg = "Storage not updated(2)"; - return DocAction.STATUS_Invalid; - } - log.fine(storage.toString()); - - // Transaction - trx = new MTransaction (getCtx(), line.getAD_Org_ID(), - MTransaction.MOVEMENTTYPE_InventoryIn, - line.getM_Locator_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), - qtyDiff, getMovementDate(), get_TrxName()); - trx.setM_InventoryLine_ID(line.getM_InventoryLine_ID()); - if (!trx.save()) - { - m_processMsg = "Transaction not inserted(2)"; - return DocAction.STATUS_Invalid; - } - } // Fallback - - } // for all lines - - // 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(); - - // - setProcessed(true); - setDocAction(DOCACTION_Close); - return DocAction.STATUS_Completed; - } // completeIt - - /** - * 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. - * (NOT USED) - * Sets line ASI - */ - private void checkMaterialPolicy() - { - int no = MInventoryLineMA.deleteInventoryMA(getM_Inventory_ID(), get_TrxName()); - if (no > 0) - log.config("Delete old #" + no); - MInventoryLine[] lines = getLines(false); - - // Check Lines - for (int i = 0; i < lines.length; i++) - { - MInventoryLine line = lines[i]; - boolean needSave = false; - - // Attribute Set Instance - if (line.getM_AttributeSetInstance_ID() == 0) - { - MProduct product = MProduct.get(getCtx(), line.getM_Product_ID()); - BigDecimal qtyDiff = line.getQtyInternalUse().negate(); - if (Env.ZERO.compareTo(qtyDiff) == 0) - qtyDiff = line.getQtyCount().subtract(line.getQtyBook()); - log.fine("Count=" + line.getQtyCount() - + ",Book=" + line.getQtyBook() + ", Difference=" + qtyDiff); - if (qtyDiff.signum() > 0) // Incoming Trx - { - 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()) - { - line.setM_AttributeSetInstance_ID(asi.getM_AttributeSetInstance_ID()); - needSave = true; - } - } - 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()); - BigDecimal qtyToDeliver = qtyDiff.negate(); - 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); - MInventoryLineMA ma = new MInventoryLineMA (line, - storage.getM_AttributeSetInstance_ID(), - storage.getQtyOnHand().negate()); - if (!ma.save()) - ; - qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand()); - log.fine("#" + ii + ": " + ma + ", QtyToDeliver=" + qtyToDeliver); - } - } - else // create addl material allocation - { - MInventoryLineMA ma = new MInventoryLineMA (line, - storage.getM_AttributeSetInstance_ID(), - qtyToDeliver.negate()); - if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0) - qtyToDeliver = Env.ZERO; - else - { - ma.setMovementQty(storage.getQtyOnHand().negate()); - 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) - { - MInventoryLineMA ma = new MInventoryLineMA (line, - 0, qtyToDeliver.negate()); - if (!ma.save()) - ; - log.fine("##: " + ma); - } - } // outgoing Trx - } // attributeSetInstance - - if (needSave && !line.save()) - log.severe("NOT saved " + line); - } // for all lines - - } // checkMaterialPolicy - - /** - * Void Document. - * @return false - */ - 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 - MInventoryLine[] lines = getLines(false); - for (int i = 0; i < lines.length; i++) - { - MInventoryLine line = lines[i]; - BigDecimal oldCount = line.getQtyCount(); - BigDecimal oldInternal = line.getQtyInternalUse(); - if (oldCount.compareTo(line.getQtyBook()) != 0 - || oldInternal.signum() != 0) - { - line.setQtyInternalUse(Env.ZERO); - line.setQtyCount(line.getQtyBook()); - line.addDescription("Void (" + oldCount + "/" + oldInternal + ")"); - 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; - - setDocAction(DOCACTION_None); - return true; - } // closeIt - - /** - * Reverse Correction - * @return false - */ - 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(), getMovementDate(), dt.getDocBaseType())) - { - m_processMsg = "@PeriodClosed@"; - return false; - } - - // Deep Copy - MInventory reversal = new MInventory(getCtx(), 0, get_TrxName()); - copyValues(this, reversal, getAD_Client_ID(), getAD_Org_ID()); - reversal.setDocStatus(DOCSTATUS_Drafted); - reversal.setDocAction(DOCACTION_Complete); - reversal.setIsApproved (false); - reversal.setPosted(false); - reversal.setProcessed(false); - reversal.addDescription("{->" + getDocumentNo() + ")"); - if (!reversal.save()) - { - m_processMsg = "Could not create Inventory Reversal"; - return false; - } - - // Reverse Line Qty - MInventoryLine[] oLines = getLines(true); - for (int i = 0; i < oLines.length; i++) - { - MInventoryLine oLine = oLines[i]; - MInventoryLine rLine = new MInventoryLine(getCtx(), 0, get_TrxName()); - copyValues(oLine, rLine, oLine.getAD_Client_ID(), oLine.getAD_Org_ID()); - rLine.setM_Inventory_ID(reversal.getM_Inventory_ID()); - rLine.setParent(reversal); - // - rLine.setQtyBook (oLine.getQtyCount()); // switch - rLine.setQtyCount (oLine.getQtyBook()); - rLine.setQtyInternalUse (oLine.getQtyInternalUse().negate()); - if (!rLine.save()) - { - m_processMsg = "Could not create Inventory Reversal Line"; - return false; - } - } - // - if (!reversal.processIt(DocAction.ACTION_Complete)) - { - m_processMsg = "Reversal ERROR: " + reversal.getProcessMsg(); - return false; - } - reversal.closeIt(); - reversal.setDocStatus(DOCSTATUS_Reversed); - reversal.setDocAction(DOCACTION_None); - reversal.save(); - m_processMsg = reversal.getDocumentNo(); - - // Update Reversed (this) - addDescription("(" + reversal.getDocumentNo() + "<-)"); - // After reverseCorrect - m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_REVERSECORRECT); - if (m_processMsg != null) - return false; - setProcessed(true); - setDocStatus(DOCSTATUS_Reversed); // may come from void - setDocAction(DOCACTION_None); - - return true; - } // reverseCorrectionIt - - /** - * Reverse Accrual - * @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(),"ApprovalAmt")).append("=").append(getApprovalAmt()) - .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 getUpdatedBy(); - } // getDoc_User_ID - - /** - * Get Document Currency - * @return C_Currency_ID - */ - public int getC_Currency_ID() - { - // MPriceList pl = MPriceList.get(getCtx(), getM_PriceList_ID()); - // return pl.getC_Currency_ID(); - return 0; - } // getC_Currency_ID - -} // MInventory +/****************************************************************************** + * 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.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.process.*; +import org.compiere.util.*; + +/** + * Physical Inventory Model + * + * @author Jorg Janke + * @version $Id: MInventory.java,v 1.3 2006/07/30 00:51:05 jjanke Exp $ + * @author victor.perez@e-evolution.com, e-Evolution + *
  • FR [ 1948157 ] Is necessary the reference for document reverse + * @see http://sourceforge.net/tracker/?func=detail&atid=879335&aid=1948157&group_id=176962 + */ +public class MInventory extends X_M_Inventory implements DocAction +{ + /** + * Get Inventory from Cache + * @param ctx context + * @param M_Inventory_ID id + * @return MInventory + */ + public static MInventory get (Properties ctx, int M_Inventory_ID) + { + Integer key = new Integer (M_Inventory_ID); + MInventory retValue = (MInventory) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MInventory (ctx, M_Inventory_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache = new CCache("M_Inventory", 5, 5); + + + /** + * Standard Constructor + * @param ctx context + * @param M_Inventory_ID id + * @param trxName transaction + */ + public MInventory (Properties ctx, int M_Inventory_ID, String trxName) + { + super (ctx, M_Inventory_ID, trxName); + if (M_Inventory_ID == 0) + { + // setName (null); + // setM_Warehouse_ID (0); // FK + setMovementDate (new Timestamp(System.currentTimeMillis())); + setDocAction (DOCACTION_Complete); // CO + setDocStatus (DOCSTATUS_Drafted); // DR + setIsApproved (false); + setMovementDate (new Timestamp(System.currentTimeMillis())); // @#Date@ + setPosted (false); + setProcessed (false); + } + } // MInventory + + /** + * Load Constructor + * @param ctx context + * @param rs result set + * @param trxName transaction + */ + public MInventory (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MInventory + + /** + * Warehouse Constructor + * @param wh warehouse + */ + public MInventory (MWarehouse wh) + { + this (wh.getCtx(), 0, wh.get_TrxName()); + setClientOrg(wh); + setM_Warehouse_ID(wh.getM_Warehouse_ID()); + } // MInventory + + + /** Lines */ + private MInventoryLine[] m_lines = null; + + /** + * Get Lines + * @param requery requery + * @return array of lines + */ + public MInventoryLine[] 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_InventoryLine WHERE M_Inventory_ID=? ORDER BY Line"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getM_Inventory_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MInventoryLine (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_lines = new MInventoryLine[list.size ()]; + list.toArray (m_lines); + return m_lines; + } // getLines + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + + /** + * Overwrite Client/Org - from Import. + * @param AD_Client_ID client + * @param AD_Org_ID org + */ + public void setClientOrg (int AD_Client_ID, int AD_Org_ID) + { + super.setClientOrg(AD_Client_ID, AD_Org_ID); + } // setClientOrg + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MInventory["); + sb.append (get_ID()) + .append ("-").append (getDocumentNo()) + .append (",M_Warehouse_ID=").append(getM_Warehouse_ID()) + .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.INVOICE, getC_Invoice_ID()); + // if (re == null) + return null; + // return re.getPDF(file); + } // createPDF + + + /** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + if (getC_DocType_ID() == 0) + { + MDocType types[] = MDocType.getOfDocBaseType(getCtx(), MDocType.DOCBASETYPE_MaterialPhysicalInventory); + if (types.length > 0) // get first + setC_DocType_ID(types[0].getC_DocType_ID()); + else + { + log.saveError("Error", Msg.parseTranslation(getCtx(), "@NotFound@ @C_DocType_ID@")); + return false; + } + } + return true; + } // beforeSave + + + /** + * 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_InventoryLine SET Processed='" + + (processed ? "Y" : "N") + + "' WHERE M_Inventory_ID=" + getM_Inventory_ID(); + int noLine = DB.executeUpdate(sql, get_TrxName()); + m_lines = null; + log.fine("Processed=" + processed + " - Lines=" + noLine); + } // setProcessed + + + /************************************************************************** + * 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()); + } // processIt + + /** 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; + + // Std Period open? + if (!MPeriod.isOpen(getCtx(), getMovementDate(), MDocType.DOCBASETYPE_MaterialPhysicalInventory)) + { + m_processMsg = "@PeriodClosed@"; + return DocAction.STATUS_Invalid; + } + MInventoryLine[] lines = getLines(false); + if (lines.length == 0) + { + m_processMsg = "@NoLines@"; + return DocAction.STATUS_Invalid; + } + + // TODO: Add up Amounts + // setApprovalAmt(); + + 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; + + // Implicit Approval + if (!isApproved()) + approveIt(); + log.info(toString()); + + //vpj-cd begin e-evolution recalculate the attribute instances and qty. + /*MInventoryLine[] linesup = getLines(false); + for (int i = 0; i < linesup.length; i++) + { + MInventoryLine line = linesup[i]; + + String sql1 = "Delete From M_InventoryLineMA " + + " WHERE M_InventoryLine_ID=" +line.getM_InventoryLine_ID(); + int no = DB.executeUpdate(sql1, get_TrxName()); + log.info("MA deleted " + no); + + StringBuffer sql = new StringBuffer( + "SELECT s.M_Product_ID, s.M_Locator_ID, s.M_AttributeSetInstance_ID," + + " s.QtyOnHand, p.M_AttributeSet_ID " + + "FROM M_Product p" + + " INNER JOIN M_Storage s ON (s.M_Product_ID=p.M_Product_ID)" + + " INNER JOIN M_Locator l ON (s.M_Locator_ID=l.M_Locator_ID) " + + "WHERE l.M_Warehouse_ID=?" + + " AND p.IsActive='Y' AND p.IsStocked='Y' and p.ProductType='I'" + + " AND s.M_Locator_ID=" +line.getM_Locator_ID() + + " AND s.M_Product_ID=" +line.getM_Product_ID() + + " AND s.QtyOnHand <> 0 " + ); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql.toString(), get_TrxName()); + int index = 1; + pstmt.setInt (index++, getM_Warehouse_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MInventoryLineMA maup = new MInventoryLineMA (line, + rs.getInt(3), rs.getBigDecimal(4)); + + if (!maup.save()) + ; + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, sql.toString(), e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + }*/ + //vpj-cd e-evolution recalculate the attribute instances and qty END. + /* + // + MInventoryLine[] lines = getLines(false); + for (int i = 0; i < lines.length; i++) + { + MInventoryLine line = lines[i]; + if (!line.isActive()) + continue; + + MTransaction trx = null; + if (line.getM_AttributeSetInstance_ID() == 0) + { + BigDecimal qtyDiff = line.getQtyInternalUse().negate(); + if (qtyDiff.signum() == 0) + qtyDiff = line.getQtyCount().subtract(line.getQtyBook()); + // + if (qtyDiff.signum() > 0) + { + // Storage + MStorage storage = MStorage.get(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), 0, get_TrxName()); + if (storage == null) + storage = MStorage.getCreate(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), 0, get_TrxName()); + BigDecimal qtyNew = storage.getQtyOnHand().add(qtyDiff); + log.fine("Diff=" + qtyDiff + + " - OnHand=" + storage.getQtyOnHand() + "->" + qtyNew); + storage.setQtyOnHand(qtyNew); + storage.setDateLastInventory(getMovementDate()); + if (!storage.save(get_TrxName())) + { + m_processMsg = "Storage not updated(1)"; + return DocAction.STATUS_Invalid; + } + log.fine(storage.toString()); + // Transaction + trx = new MTransaction (getCtx(), line.getAD_Org_ID(), + MTransaction.MOVEMENTTYPE_InventoryIn, + line.getM_Locator_ID(), line.getM_Product_ID(), 0, + qtyDiff, getMovementDate(), get_TrxName()); + trx.setM_InventoryLine_ID(line.getM_InventoryLine_ID()); + if (!trx.save()) + { + m_processMsg = "Transaction not inserted(1)"; + return DocAction.STATUS_Invalid; + } + } + else // negative qty + { + MInventoryLineMA mas[] = MInventoryLineMA.get(getCtx(), + line.getM_InventoryLine_ID(), get_TrxName()); + for (int j = 0; j < mas.length; j++) + { + MInventoryLineMA ma = mas[j]; + // Storage + MStorage storage = MStorage.get(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), get_TrxName()); + if (storage == null) + storage = MStorage.getCreate(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), get_TrxName()); + // + BigDecimal maxDiff = qtyDiff; + if (maxDiff.signum() < 0 + && ma.getMovementQty().compareTo(maxDiff.negate()) < 0) + maxDiff = ma.getMovementQty().negate(); + BigDecimal qtyNew = ma.getMovementQty().add(maxDiff); // Storage+Diff + log.fine("MA Qty=" + ma.getMovementQty() + + ",Diff=" + qtyDiff + "|" + maxDiff + + " - OnHand=" + storage.getQtyOnHand() + "->" + qtyNew + + " {" + ma.getM_AttributeSetInstance_ID() + "}"); + // + storage.setQtyOnHand(qtyNew); + storage.setDateLastInventory(getMovementDate()); + if (!storage.save(get_TrxName())) + { + m_processMsg = "Storage not updated (MA)"; + return DocAction.STATUS_Invalid; + } + log.fine(storage.toString()); + + // Transaction + trx = new MTransaction (getCtx(), line.getAD_Org_ID(), + MTransaction.MOVEMENTTYPE_InventoryIn, + line.getM_Locator_ID(), line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), + maxDiff, getMovementDate(), get_TrxName()); + trx.setM_InventoryLine_ID(line.getM_InventoryLine_ID()); + if (!trx.save()) + { + m_processMsg = "Transaction not inserted (MA)"; + return DocAction.STATUS_Invalid; + } + // + qtyDiff = qtyDiff.subtract(maxDiff); + if (qtyDiff.signum() == 0) + break; + } + } // negative qty + } + // Fallback + if (trx == null) + { + // Storage + MStorage storage = MStorage.get(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), get_TrxName()); + if (storage == null) + storage = MStorage.getCreate(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), get_TrxName()); + // + BigDecimal qtyDiff = line.getQtyInternalUse().negate(); + if (Env.ZERO.compareTo(qtyDiff) == 0) + qtyDiff = line.getQtyCount().subtract(line.getQtyBook()); + BigDecimal qtyNew = storage.getQtyOnHand().add(qtyDiff); + log.fine("Count=" + line.getQtyCount() + + ",Book=" + line.getQtyBook() + ", Difference=" + qtyDiff + + " - OnHand=" + storage.getQtyOnHand() + "->" + qtyNew); + // + storage.setQtyOnHand(qtyNew); + storage.setDateLastInventory(getMovementDate()); + if (!storage.save(get_TrxName())) + { + m_processMsg = "Storage not updated(2)"; + return DocAction.STATUS_Invalid; + } + log.fine(storage.toString()); + + // Transaction + trx = new MTransaction (getCtx(), line.getAD_Org_ID(), + MTransaction.MOVEMENTTYPE_InventoryIn, + line.getM_Locator_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), + qtyDiff, getMovementDate(), get_TrxName()); + trx.setM_InventoryLine_ID(line.getM_InventoryLine_ID()); + if (!trx.save()) + { + m_processMsg = "Transaction not inserted(2)"; + return DocAction.STATUS_Invalid; + } + } // Fallback + + */ + + + MInventoryLine[] lines = getLines(false); + for (MInventoryLine line : lines) + { + if (!line.isActive()) + continue; + + MProduct product = line.getProduct(); + + //Get Quantity to Inventory Inernal Use + BigDecimal qtyDiff = line.getQtyInternalUse().negate(); + //If Quantity to Inventory Internal Use = Zero Then is Physical Inventory Else is Inventory Internal Use + if (qtyDiff.signum() == 0) + qtyDiff = line.getQtyCount().subtract(line.getQtyBook()); + + //Ignore the Material Policy when is Reverse Correction + if(!isReversal()) + checkMaterialPolicy(line, qtyDiff); + + // Stock Movement - Counterpart MOrder.reserveStock + if (product != null + && product.isStocked() ) + { + log.fine("Material Transaction"); + MTransaction mtrx = null; + + //If AttributeSetInstance = Zero then create new AttributeSetInstance use Inventory Line MA else use current AttributeSetInstance + if (line.getM_AttributeSetInstance_ID() == 0 || qtyDiff.compareTo(Env.ZERO) == 0) + { + MInventoryLineMA mas[] = MInventoryLineMA.get(getCtx(), + line.getM_InventoryLine_ID(), get_TrxName()); + + for (int j = 0; j < mas.length; j++) + { + MInventoryLineMA ma = mas[j]; + BigDecimal QtyMA = ma.getMovementQty(); + BigDecimal QtyNew = QtyMA.add(qtyDiff); + log.fine("Diff=" + qtyDiff + + " - Instance OnHand=" + QtyMA + "->" + QtyNew); + + if (!MStorage.add(getCtx(), getM_Warehouse_ID(), + line.getM_Locator_ID(), + line.getM_Product_ID(), + ma.getM_AttributeSetInstance_ID(), 0, + QtyMA.negate(), Env.ZERO, Env.ZERO, get_TrxName())) + { + m_processMsg = "Cannot correct Inventory (MA)"; + return DocAction.STATUS_Invalid; + } + + // Only Update Date Last Inventory if is a Physical Inventory + if(line.getQtyInternalUse().compareTo(Env.ZERO) == 0) + { + MStorage storage = MStorage.get(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), get_TrxName()); + storage.setDateLastInventory(getMovementDate()); + if (!storage.save(get_TrxName())) + { + m_processMsg = "Storage not updated(2)"; + return DocAction.STATUS_Invalid; + } + } + + String m_MovementType =null; + if(QtyMA.negate().compareTo(Env.ZERO) > 0 ) + m_MovementType = MTransaction.MOVEMENTTYPE_InventoryIn; + else + m_MovementType = MTransaction.MOVEMENTTYPE_InventoryOut; + // Transaction + mtrx = new MTransaction (getCtx(), line.getAD_Org_ID(), m_MovementType, + line.getM_Locator_ID(), line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), + QtyMA.negate(), getMovementDate(), get_TrxName()); + mtrx.setM_InventoryLine_ID(line.getM_InventoryLine_ID()); + if (!mtrx.save()) + { + m_processMsg = "Transaction not inserted(2)"; + return DocAction.STATUS_Invalid; + } + qtyDiff = QtyNew; + } + } + + //sLine.getM_AttributeSetInstance_ID() != 0 + // Fallback + if (mtrx == null) + { + //Fallback: Update Storage - see also VMatch.createMatchRecord + if (!MStorage.add(getCtx(), getM_Warehouse_ID(), + line.getM_Locator_ID(), + line.getM_Product_ID(), + line.getM_AttributeSetInstance_ID(), 0, + qtyDiff, Env.ZERO, Env.ZERO, get_TrxName())) + { + m_processMsg = "Cannot correct Inventory (MA)"; + return DocAction.STATUS_Invalid; + } + + // Only Update Date Last Inventory if is a Physical Inventory + if(line.getQtyInternalUse().compareTo(Env.ZERO) == 0) + { + MStorage storage = MStorage.get(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), get_TrxName()); + + storage.setDateLastInventory(getMovementDate()); + if (!storage.save(get_TrxName())) + { + m_processMsg = "Storage not updated(2)"; + return DocAction.STATUS_Invalid; + } + } + + String m_MovementType =null; + if(qtyDiff.compareTo(Env.ZERO) > 0 ) + m_MovementType = MTransaction.MOVEMENTTYPE_InventoryIn; + else + m_MovementType = MTransaction.MOVEMENTTYPE_InventoryOut; + // Transaction + mtrx = new MTransaction (getCtx(), line.getAD_Org_ID(), m_MovementType, + line.getM_Locator_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), + qtyDiff, getMovementDate(), get_TrxName()); + mtrx.setM_InventoryLine_ID(line.getM_InventoryLine_ID()); + if (!mtrx.save()) + { + m_processMsg = "Transaction not inserted(2)"; + return DocAction.STATUS_Invalid; + } + } // Fallback + } // stock movement + + + } // for all lines + + // 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(); + + // + setProcessed(true); + setDocAction(DOCACTION_Close); + return DocAction.STATUS_Completed; + } // completeIt + + /** + * 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. + * (NOT USED) + * Sets line ASI + */ + private void checkMaterialPolicy(MInventoryLine line, BigDecimal qtyDiff) + { + int no = MInventoryLineMA.deleteInventoryMA(line.getM_InventoryLine_ID(), get_TrxName()); + if (no > 0) + log.config("Delete old #" + no); + + + // Check Line + 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()); + if (qtyDiff.signum() > 0) // Incoming Trx + { + 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()); + needSave = true; + } + } + 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()); + BigDecimal qtyToDeliver = qtyDiff.negate(); + + /*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); + MInventoryLineMA ma = new MInventoryLineMA (line, + storage.getM_AttributeSetInstance_ID(), + storage.getQtyOnHand().negate()); + if (!ma.save()) + ; + qtyToDeliver = qtyToDeliver.subtract(storage.getQtyOnHand()); + log.fine("#" + ii + ": " + ma + ", QtyToDeliver=" + qtyToDeliver); + } + } + else // create addl material allocation + { + MInventoryLineMA ma = new MInventoryLineMA (line, + storage.getM_AttributeSetInstance_ID(), + qtyToDeliver.negate()); + if (storage.getQtyOnHand().compareTo(qtyToDeliver) >= 0) + qtyToDeliver = Env.ZERO; + else + { + ma.setMovementQty(storage.getQtyOnHand().negate()); + 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) + { + //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, + storage.getM_AttributeSetInstance_ID(), + qtyToDeliver); + if (!ma.save()) + { + throw new IllegalStateException("Error try create ASI Reservation"); + } + qtyToDeliver = Env.ZERO; + log.fine( ma + ", QtyToDeliver=" + qtyToDeliver); + //return; + } + else + { + MInventoryLineMA ma = new MInventoryLineMA (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) + { + MInventoryLineMA ma = new MInventoryLineMA (line, 0 , qtyToDeliver.add(qtyASI)); + + if (!ma.save()) + ; + log.fine("##: " + ma); + } + } // outgoing Trx + + if (needSave && !line.save()) + log.severe("NOT saved " + line); + } // for all lines + + } // checkMaterialPolicy + + /** + * Void Document. + * @return false + */ + 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 + MInventoryLine[] lines = getLines(false); + for (int i = 0; i < lines.length; i++) + { + MInventoryLine line = lines[i]; + BigDecimal oldCount = line.getQtyCount(); + BigDecimal oldInternal = line.getQtyInternalUse(); + if (oldCount.compareTo(line.getQtyBook()) != 0 + || oldInternal.signum() != 0) + { + line.setQtyInternalUse(Env.ZERO); + line.setQtyCount(line.getQtyBook()); + line.addDescription("Void (" + oldCount + "/" + oldInternal + ")"); + 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; + + setDocAction(DOCACTION_None); + return true; + } // closeIt + + /** + * Reverse Correction + * @return false + */ + 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(), getMovementDate(), dt.getDocBaseType())) + { + m_processMsg = "@PeriodClosed@"; + return false; + } + + // Deep Copy + MInventory reversal = new MInventory(getCtx(), 0, get_TrxName()); + copyValues(this, reversal, getAD_Client_ID(), getAD_Org_ID()); + reversal.setDocStatus(DOCSTATUS_Drafted); + reversal.setDocAction(DOCACTION_Complete); + reversal.setIsApproved (false); + reversal.setPosted(false); + reversal.setProcessed(false); + reversal.addDescription("{->" + getDocumentNo() + ")"); + //FR1948157 + reversal.setReversal_ID(getM_Inventory_ID()); + if (!reversal.save()) + { + m_processMsg = "Could not create Inventory Reversal"; + return false; + } + reversal.setReversal(true); + + // Reverse Line Qty + MInventoryLine[] oLines = getLines(true); + for (int i = 0; i < oLines.length; i++) + { + MInventoryLine oLine = oLines[i]; + MInventoryLine rLine = new MInventoryLine(getCtx(), 0, get_TrxName()); + copyValues(oLine, rLine, oLine.getAD_Client_ID(), oLine.getAD_Org_ID()); + rLine.setM_Inventory_ID(reversal.getM_Inventory_ID()); + rLine.setParent(reversal); + // + rLine.setQtyBook (oLine.getQtyCount()); // switch + rLine.setQtyCount (oLine.getQtyBook()); + rLine.setQtyInternalUse (oLine.getQtyInternalUse().negate()); + + if (!rLine.save()) + { + m_processMsg = "Could not create Inventory Reversal Line"; + return false; + } + + //We need to copy MA + if (rLine.getM_AttributeSetInstance_ID() == 0) + { + MInventoryLineMA mas[] = MInventoryLineMA.get(getCtx(), + oLines[i].getM_InventoryLine_ID(), get_TrxName()); + for (int j = 0; j < mas.length; j++) + { + MInventoryLineMA ma = new MInventoryLineMA (rLine, + mas[j].getM_AttributeSetInstance_ID(), + mas[j].getMovementQty().negate()); + if (!ma.save()) + ; + } + } + } + // + if (!reversal.processIt(DocAction.ACTION_Complete)) + { + m_processMsg = "Reversal ERROR: " + reversal.getProcessMsg(); + return false; + } + reversal.closeIt(); + reversal.setDocStatus(DOCSTATUS_Reversed); + reversal.setDocAction(DOCACTION_None); + reversal.save(); + m_processMsg = reversal.getDocumentNo(); + + // Update Reversed (this) + addDescription("(" + reversal.getDocumentNo() + "<-)"); + // After reverseCorrect + m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_REVERSECORRECT); + if (m_processMsg != null) + return false; + setProcessed(true); + //FR1948157 + setReversal_ID(reversal.getM_Inventory_ID()); + setDocStatus(DOCSTATUS_Reversed); // may come from void + setDocAction(DOCACTION_None); + + return true; + } // reverseCorrectionIt + + /** + * Reverse Accrual + * @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(),"ApprovalAmt")).append("=").append(getApprovalAmt()) + .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 getUpdatedBy(); + } // getDoc_User_ID + + /** + * Get Document Currency + * @return C_Currency_ID + */ + public int getC_Currency_ID() + { + // MPriceList pl = MPriceList.get(getCtx(), getM_PriceList_ID()); + // return pl.getC_Currency_ID(); + return 0; + } // getC_Currency_ID + + /** 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 + +} // MInventory diff --git a/base/src/org/compiere/model/MInventoryLine.java b/base/src/org/compiere/model/MInventoryLine.java index 583e059af9..b0a299bdaa 100644 --- a/base/src/org/compiere/model/MInventoryLine.java +++ b/base/src/org/compiere/model/MInventoryLine.java @@ -364,9 +364,9 @@ public class MInventoryLine extends X_M_InventoryLine return false; // Create MA - if (newRecord && success - && m_isManualEntry && getM_AttributeSetInstance_ID() == 0) - createMA(); + //if (newRecord && success + // && m_isManualEntry && getM_AttributeSetInstance_ID() == 0) + // createMA(); return true; } // afterSave diff --git a/base/src/org/compiere/model/MInventoryLineMA.java b/base/src/org/compiere/model/MInventoryLineMA.java index 7b29af56f3..f1d99218df 100644 --- a/base/src/org/compiere/model/MInventoryLineMA.java +++ b/base/src/org/compiere/model/MInventoryLineMA.java @@ -80,11 +80,11 @@ public class MInventoryLineMA extends X_M_InventoryLineMA * @param trxName transaction * @return number of rows deleted or -1 for error */ - public static int deleteInventoryMA (int M_Inventory_ID, String trxName) + public static int deleteInventoryMA (int M_InventoryLine_ID, String trxName) { String sql = "DELETE FROM M_InventoryLineMA ma WHERE EXISTS " + "(SELECT * FROM M_InventoryLine l WHERE l.M_InventoryLine_ID=ma.M_InventoryLine_ID" - + " AND M_Inventory_ID=" + M_Inventory_ID + ")"; + + " AND M_InventoryLine_ID=" + M_InventoryLine_ID + ")"; return DB.executeUpdate(sql, trxName); } // deleteInventoryMA diff --git a/base/src/org/compiere/model/MInvoice.java b/base/src/org/compiere/model/MInvoice.java index e1be96502f..02e6fa2d8e 100644 --- a/base/src/org/compiere/model/MInvoice.java +++ b/base/src/org/compiere/model/MInvoice.java @@ -1,2368 +1,2399 @@ -/****************************************************************************** - * 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.*; -import java.math.*; -import java.sql.*; -import java.util.*; -import java.util.logging.*; -import org.compiere.print.*; -import org.compiere.process.*; -import org.compiere.util.*; - - -/** - * Invoice Model. - * Please do not set DocStatus and C_DocType_ID directly. - * They are set in the process() method. - * Use DocAction and C_DocTypeTarget_ID instead. - * - * @author Jorg Janke - * @version $Id: MInvoice.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ - * - * Modifications: Added RMA functionality (Ashley Ramdass) - */ -public class MInvoice extends X_C_Invoice implements DocAction -{ - /** - * Get Payments Of BPartner - * @param ctx context - * @param C_BPartner_ID id - * @param trxName transaction - * @return array - */ - public static MInvoice[] getOfBPartner (Properties ctx, int C_BPartner_ID, String trxName) - { - ArrayList list = new ArrayList(); - String sql = "SELECT * FROM C_Invoice WHERE C_BPartner_ID=?"; - PreparedStatement pstmt = null; - try - { - pstmt = DB.prepareStatement(sql, trxName); - pstmt.setInt(1, C_BPartner_ID); - ResultSet rs = pstmt.executeQuery(); - while (rs.next()) - list.add(new MInvoice(ctx,rs, trxName)); - rs.close(); - pstmt.close(); - pstmt = null; - } - catch (Exception e) - { - s_log.log(Level.SEVERE, sql, e); - } - try - { - if (pstmt != null) - pstmt.close(); - pstmt = null; - } - catch (Exception e) - { - pstmt = null; - } - - // - MInvoice[] retValue = new MInvoice[list.size()]; - list.toArray(retValue); - return retValue; - } // getOfBPartner - - /** - * Create new Invoice by copying - * @param from invoice - * @param dateDoc date of the document date - * @param C_DocTypeTarget_ID target doc type - * @param isSOTrx sales order - * @param counter create counter links - * @param trxName trx - * @param setOrder set Order links - * @return Invoice - */ - public static MInvoice copyFrom (MInvoice from, Timestamp dateDoc, - int C_DocTypeTarget_ID, boolean isSOTrx, boolean counter, - String trxName, boolean setOrder) - { - MInvoice to = new MInvoice (from.getCtx(), 0, null); - to.set_TrxName(trxName); - PO.copyValues (from, to, from.getAD_Client_ID(), from.getAD_Org_ID()); - to.set_ValueNoCheck ("C_Invoice_ID", I_ZERO); - to.set_ValueNoCheck ("DocumentNo", null); - // - to.setDocStatus (DOCSTATUS_Drafted); // Draft - to.setDocAction(DOCACTION_Complete); - // - to.setC_DocType_ID(0); - to.setC_DocTypeTarget_ID (C_DocTypeTarget_ID); - to.setIsSOTrx(isSOTrx); - // - to.setDateInvoiced (dateDoc); - to.setDateAcct (dateDoc); - to.setDatePrinted(null); - to.setIsPrinted (false); - // - to.setIsApproved (false); - to.setC_Payment_ID(0); - to.setC_CashLine_ID(0); - to.setIsPaid (false); - to.setIsInDispute(false); - // - // Amounts are updated by trigger when adding lines - to.setGrandTotal(Env.ZERO); - to.setTotalLines(Env.ZERO); - // - to.setIsTransferred (false); - to.setPosted (false); - to.setProcessed (false); - //[ 1633721 ] Reverse Documents- Processing=Y - to.setProcessing(false); - // delete references - to.setIsSelfService(false); - if (!setOrder) - to.setC_Order_ID(0); - if (counter) - { - to.setRef_Invoice_ID(from.getC_Invoice_ID()); - // Try to find Order 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()); - } - } - else - to.setRef_Invoice_ID(0); - - if (!to.save(trxName)) - throw new IllegalStateException("Could not create Invoice"); - if (counter) - from.setRef_Invoice_ID(to.getC_Invoice_ID()); - - // Lines - if (to.copyLinesFrom(from, counter, setOrder) == 0) - throw new IllegalStateException("Could not create Invoice Lines"); - - return to; - } // copyFrom - - /** - * Get PDF File Name - * @param documentDir directory - * @param C_Invoice_ID invoice - * @return file name - */ - public static String getPDFFileName (String documentDir, int C_Invoice_ID) - { - StringBuffer sb = new StringBuffer (documentDir); - if (sb.length() == 0) - sb.append("."); - if (!sb.toString().endsWith(File.separator)) - sb.append(File.separator); - sb.append("C_Invoice_ID_") - .append(C_Invoice_ID) - .append(".pdf"); - return sb.toString(); - } // getPDFFileName - - - /** - * Get MInvoice from Cache - * @param ctx context - * @param C_Invoice_ID id - * @return MInvoice - */ - public static MInvoice get (Properties ctx, int C_Invoice_ID) - { - Integer key = new Integer (C_Invoice_ID); - MInvoice retValue = (MInvoice) s_cache.get (key); - if (retValue != null) - return retValue; - retValue = new MInvoice (ctx, C_Invoice_ID, null); - if (retValue.get_ID () != 0) - s_cache.put (key, retValue); - return retValue; - } // get - - /** Cache */ - private static CCache s_cache = new CCache("C_Invoice", 20, 2); // 2 minutes - - - /************************************************************************** - * Invoice Constructor - * @param ctx context - * @param C_Invoice_ID invoice or 0 for new - * @param trxName trx name - */ - public MInvoice (Properties ctx, int C_Invoice_ID, String trxName) - { - super (ctx, C_Invoice_ID, trxName); - if (C_Invoice_ID == 0) - { - setDocStatus (DOCSTATUS_Drafted); // Draft - setDocAction (DOCACTION_Complete); - // - setPaymentRule(PAYMENTRULE_OnCredit); // Payment Terms - - setDateInvoiced (new Timestamp (System.currentTimeMillis ())); - setDateAcct (new Timestamp (System.currentTimeMillis ())); - // - setChargeAmt (Env.ZERO); - setTotalLines (Env.ZERO); - setGrandTotal (Env.ZERO); - // - setIsSOTrx (true); - setIsTaxIncluded (false); - setIsApproved (false); - setIsDiscountPrinted (false); - setIsPaid (false); - setSendEMail (false); - setIsPrinted (false); - setIsTransferred (false); - setIsSelfService(false); - setIsPayScheduleValid(false); - setIsInDispute(false); - setPosted(false); - super.setProcessed (false); - setProcessing(false); - } - } // MInvoice - - /** - * Load Constructor - * @param ctx context - * @param rs result set record - * @param trxName transaction - */ - public MInvoice (Properties ctx, ResultSet rs, String trxName) - { - super(ctx, rs, trxName); - } // MInvoice - - /** - * Create Invoice from Order - * @param order order - * @param C_DocTypeTarget_ID target document type - * @param invoiceDate date or null - */ - public MInvoice (MOrder order, int C_DocTypeTarget_ID, Timestamp invoiceDate) - { - this (order.getCtx(), 0, order.get_TrxName()); - setClientOrg(order); - setOrder(order); // set base settings - // - if (C_DocTypeTarget_ID == 0) - C_DocTypeTarget_ID = DB.getSQLValue(null, - "SELECT C_DocTypeInvoice_ID FROM C_DocType WHERE C_DocType_ID=?", - order.getC_DocType_ID()); - setC_DocTypeTarget_ID(C_DocTypeTarget_ID); - if (invoiceDate != null) - setDateInvoiced(invoiceDate); - setDateAcct(getDateInvoiced()); - // - setSalesRep_ID(order.getSalesRep_ID()); - // - setC_BPartner_ID(order.getBill_BPartner_ID()); - setC_BPartner_Location_ID(order.getBill_Location_ID()); - setAD_User_ID(order.getBill_User_ID()); - } // MInvoice - - /** - * Create Invoice from Shipment - * @param ship shipment - * @param invoiceDate date or null - */ - public MInvoice (MInOut ship, Timestamp invoiceDate) - { - this (ship.getCtx(), 0, ship.get_TrxName()); - setClientOrg(ship); - setShipment(ship); // set base settings - // - setC_DocTypeTarget_ID(); - if (invoiceDate != null) - setDateInvoiced(invoiceDate); - setDateAcct(getDateInvoiced()); - // - setSalesRep_ID(ship.getSalesRep_ID()); - setAD_User_ID(ship.getAD_User_ID()); - } // MInvoice - - /** - * Create Invoice from Batch Line - * @param batch batch - * @param line batch line - */ - public MInvoice (MInvoiceBatch batch, MInvoiceBatchLine line) - { - this (line.getCtx(), 0, line.get_TrxName()); - setClientOrg(line); - setDocumentNo(line.getDocumentNo()); - // - setIsSOTrx(batch.isSOTrx()); - MBPartner bp = new MBPartner (line.getCtx(), line.getC_BPartner_ID(), line.get_TrxName()); - setBPartner(bp); // defaults - // - setIsTaxIncluded(line.isTaxIncluded()); - // May conflict with default price list - setC_Currency_ID(batch.getC_Currency_ID()); - setC_ConversionType_ID(batch.getC_ConversionType_ID()); - // - // setPaymentRule(order.getPaymentRule()); - // setC_PaymentTerm_ID(order.getC_PaymentTerm_ID()); - // setPOReference(""); - setDescription(batch.getDescription()); - // setDateOrdered(order.getDateOrdered()); - // - setAD_OrgTrx_ID(line.getAD_OrgTrx_ID()); - setC_Project_ID(line.getC_Project_ID()); - // setC_Campaign_ID(line.getC_Campaign_ID()); - setC_Activity_ID(line.getC_Activity_ID()); - setUser1_ID(line.getUser1_ID()); - setUser2_ID(line.getUser2_ID()); - // - setC_DocTypeTarget_ID(line.getC_DocType_ID()); - setDateInvoiced(line.getDateInvoiced()); - setDateAcct(line.getDateAcct()); - // - setSalesRep_ID(batch.getSalesRep_ID()); - // - setC_BPartner_ID(line.getC_BPartner_ID()); - setC_BPartner_Location_ID(line.getC_BPartner_Location_ID()); - setAD_User_ID(line.getAD_User_ID()); - } // MInvoice - - /** Open Amount */ - private BigDecimal m_openAmt = null; - - /** Invoice Lines */ - private MInvoiceLine[] m_lines; - /** Invoice Taxes */ - private MInvoiceTax[] m_taxes; - /** Logger */ - private static CLogger s_log = CLogger.getCLogger(MInvoice.class); - - /** - * Overwrite Client/Org if required - * @param AD_Client_ID client - * @param AD_Org_ID org - */ - public void setClientOrg (int AD_Client_ID, int AD_Org_ID) - { - super.setClientOrg(AD_Client_ID, AD_Org_ID); - } // setClientOrg - - /** - * 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 Defaults - int ii = 0; - if (isSOTrx()) - ii = bp.getC_PaymentTerm_ID(); - else - ii = bp.getPO_PaymentTerm_ID(); - if (ii != 0) - setC_PaymentTerm_ID(ii); - // - if (isSOTrx()) - ii = bp.getM_PriceList_ID(); - else - ii = bp.getPO_PriceList_ID(); - if (ii != 0) - setM_PriceList_ID(ii); - // - String ss = bp.getPaymentRule(); - if (ss != null) - setPaymentRule(ss); - - - // Set Locations - MBPartnerLocation[] locs = bp.getLocations(false); - if (locs != null) - { - for (int i = 0; i < locs.length; i++) - { - if ((locs[i].isBillTo() && isSOTrx()) - || (locs[i].isPayFrom() && !isSOTrx())) - setC_BPartner_Location_ID(locs[i].getC_BPartner_Location_ID()); - } - // set to first - 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 - - /** - * Set Order References - * @param order order - */ - public void setOrder (MOrder order) - { - if (order == null) - return; - - setC_Order_ID(order.getC_Order_ID()); - setIsSOTrx(order.isSOTrx()); - setIsDiscountPrinted(order.isDiscountPrinted()); - setIsSelfService(order.isSelfService()); - setSendEMail(order.isSendEMail()); - // - setM_PriceList_ID(order.getM_PriceList_ID()); - setIsTaxIncluded(order.isTaxIncluded()); - setC_Currency_ID(order.getC_Currency_ID()); - setC_ConversionType_ID(order.getC_ConversionType_ID()); - // - setPaymentRule(order.getPaymentRule()); - setC_PaymentTerm_ID(order.getC_PaymentTerm_ID()); - setPOReference(order.getPOReference()); - setDescription(order.getDescription()); - setDateOrdered(order.getDateOrdered()); - // - setAD_OrgTrx_ID(order.getAD_OrgTrx_ID()); - setC_Project_ID(order.getC_Project_ID()); - setC_Campaign_ID(order.getC_Campaign_ID()); - setC_Activity_ID(order.getC_Activity_ID()); - setUser1_ID(order.getUser1_ID()); - setUser2_ID(order.getUser2_ID()); - } // setOrder - - /** - * Set Shipment References - * @param ship shipment - */ - public void setShipment (MInOut ship) - { - if (ship == null) - return; - - setIsSOTrx(ship.isSOTrx()); - // - MBPartner bp = new MBPartner (getCtx(), ship.getC_BPartner_ID(), null); - setBPartner (bp); - // - setSendEMail(ship.isSendEMail()); - // - setPOReference(ship.getPOReference()); - setDescription(ship.getDescription()); - setDateOrdered(ship.getDateOrdered()); - // - setAD_OrgTrx_ID(ship.getAD_OrgTrx_ID()); - setC_Project_ID(ship.getC_Project_ID()); - setC_Campaign_ID(ship.getC_Campaign_ID()); - setC_Activity_ID(ship.getC_Activity_ID()); - setUser1_ID(ship.getUser1_ID()); - setUser2_ID(ship.getUser2_ID()); - // - if (ship.getC_Order_ID() != 0) - { - setC_Order_ID(ship.getC_Order_ID()); - MOrder order = new MOrder (getCtx(), ship.getC_Order_ID(), get_TrxName()); - setIsDiscountPrinted(order.isDiscountPrinted()); - setM_PriceList_ID(order.getM_PriceList_ID()); - setIsTaxIncluded(order.isTaxIncluded()); - setC_Currency_ID(order.getC_Currency_ID()); - setC_ConversionType_ID(order.getC_ConversionType_ID()); - setPaymentRule(order.getPaymentRule()); - setC_PaymentTerm_ID(order.getC_PaymentTerm_ID()); - // - MDocType dt = MDocType.get(getCtx(), order.getC_DocType_ID()); - if (dt.getC_DocTypeInvoice_ID() != 0) - setC_DocTypeTarget_ID(dt.getC_DocTypeInvoice_ID()); - // Overwrite Invoice Address - setC_BPartner_Location_ID(order.getBill_Location_ID()); - } - // Check if Shipment/Receipt is based on RMA - if (ship.getM_RMA_ID() != 0) - { - MRMA rma = new MRMA(getCtx(), ship.getM_RMA_ID(), get_TrxName()); - MOrder rmaOrder = rma.getOriginalOrder(); - setM_RMA_ID(ship.getM_RMA_ID()); - setIsSOTrx(rma.isSOTrx()); - setM_PriceList_ID(rmaOrder.getM_PriceList_ID()); - setIsTaxIncluded(rmaOrder.isTaxIncluded()); - setC_Currency_ID(rmaOrder.getC_Currency_ID()); - setC_ConversionType_ID(rmaOrder.getC_ConversionType_ID()); - setPaymentRule(rmaOrder.getPaymentRule()); - setC_PaymentTerm_ID(rmaOrder.getC_PaymentTerm_ID()); - - // Retrieves the invoice DocType - MDocType dt = MDocType.get(getCtx(), rma.getC_DocType_ID()); - if (dt.getC_DocTypeInvoice_ID() != 0) - { - setC_DocTypeTarget_ID(dt.getC_DocTypeInvoice_ID()); - } - setC_BPartner_Location_ID(rmaOrder.getBill_Location_ID()); - } - - } // setShipment - - /** - * Set Target Document Type - * @param DocBaseType doc type MDocType.DOCBASETYPE_ - */ - public void setC_DocTypeTarget_ID (String DocBaseType) - { - String sql = "SELECT C_DocType_ID FROM C_DocType " - + "WHERE AD_Client_ID=? AND DocBaseType=?" - + " AND IsActive='Y' " - + "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); - setC_DocTypeTarget_ID (C_DocType_ID); - boolean isSOTrx = MDocType.DOCBASETYPE_ARInvoice.equals(DocBaseType) - || MDocType.DOCBASETYPE_ARCreditMemo.equals(DocBaseType); - setIsSOTrx (isSOTrx); - } - } // setC_DocTypeTarget_ID - - /** - * Set Target Document Type. - * Based on SO flag AP/AP Invoice - */ - public void setC_DocTypeTarget_ID () - { - if (getC_DocTypeTarget_ID() > 0) - return; - if (isSOTrx()) - setC_DocTypeTarget_ID(MDocType.DOCBASETYPE_ARInvoice); - else - setC_DocTypeTarget_ID(MDocType.DOCBASETYPE_APInvoice); - } // setC_DocTypeTarget_ID - - - /** - * Get Grand Total - * @param creditMemoAdjusted adjusted for CM (negative) - * @return grand total - */ - public BigDecimal getGrandTotal (boolean creditMemoAdjusted) - { - if (!creditMemoAdjusted) - return super.getGrandTotal(); - // - BigDecimal amt = getGrandTotal(); - if (isCreditMemo()) - return amt.negate(); - return amt; - } // getGrandTotal - - - /** - * Get Invoice Lines of Invoice - * @param whereClause starting with AND - * @return lines - */ - private MInvoiceLine[] getLines (String whereClause) - { - ArrayList list = new ArrayList(); - String sql = "SELECT * FROM C_InvoiceLine WHERE C_Invoice_ID=? "; - if (whereClause != null) - sql += whereClause; - sql += " ORDER BY Line"; - PreparedStatement pstmt = null; - try - { - pstmt = DB.prepareStatement(sql, get_TrxName()); - pstmt.setInt(1, getC_Invoice_ID()); - ResultSet rs = pstmt.executeQuery(); - while (rs.next()) - { - MInvoiceLine il = new MInvoiceLine(getCtx(), rs, get_TrxName()); - il.setInvoice(this); - list.add(il); - } - rs.close(); - pstmt.close(); - pstmt = null; - } - catch (Exception e) - { - log.log(Level.SEVERE, "getLines", e); - } - finally - { - try - { - if (pstmt != null) - pstmt.close (); - } - catch (Exception e) - {} - pstmt = null; - } - - // - MInvoiceLine[] lines = new MInvoiceLine[list.size()]; - list.toArray(lines); - return lines; - } // getLines - - /** - * Get Invoice Lines - * @param requery - * @return lines - */ - public MInvoiceLine[] getLines (boolean requery) - { - if (m_lines == null || m_lines.length == 0 || requery) - m_lines = getLines(null); - set_TrxName(m_lines, get_TrxName()); - return m_lines; - } // getLines - - /** - * Get Lines of Invoice - * @return lines - */ - public MInvoiceLine[] getLines() - { - return getLines(false); - } // getLines - - - /** - * Renumber Lines - * @param step start and step - */ - public void renumberLines (int step) - { - int number = step; - MInvoiceLine[] lines = getLines(false); - for (int i = 0; i < lines.length; i++) - { - MInvoiceLine line = lines[i]; - line.setLine(number); - line.save(); - number += step; - } - m_lines = null; - } // renumberLines - - /** - * Copy Lines From other Invoice. - * @param otherInvoice invoice - * @param counter create counter links - * @param setOrder set order links - * @return number of lines copied - */ - public int copyLinesFrom (MInvoice otherInvoice, boolean counter, boolean setOrder) - { - if (isProcessed() || isPosted() || otherInvoice == null) - return 0; - MInvoiceLine[] fromLines = otherInvoice.getLines(false); - int count = 0; - for (int i = 0; i < fromLines.length; i++) - { - MInvoiceLine line = new MInvoiceLine (getCtx(), 0, get_TrxName()); - MInvoiceLine fromLine = fromLines[i]; - 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.setC_Invoice_ID(getC_Invoice_ID()); - line.setInvoice(this); - line.set_ValueNoCheck ("C_InvoiceLine_ID", I_ZERO); // new - // Reset - if (!setOrder) - line.setC_OrderLine_ID(0); - line.setRef_InvoiceLine_ID(0); - line.setM_InOutLine_ID(0); - line.setA_Asset_ID(0); - line.setM_AttributeSetInstance_ID(0); - line.setS_ResourceAssignment_ID(0); - // New Tax - if (getC_BPartner_ID() != otherInvoice.getC_BPartner_ID()) - line.setTax(); // recalculate - // - if (counter) - { - line.setRef_InvoiceLine_ID(fromLine.getC_InvoiceLine_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.setM_InOutLine_ID(0); - if (fromLine.getM_InOutLine_ID() != 0) - { - MInOutLine peer = new MInOutLine (getCtx(), fromLine.getM_InOutLine_ID(), get_TrxName()); - if (peer.getRef_InOutLine_ID() != 0) - line.setM_InOutLine_ID(peer.getRef_InOutLine_ID()); - } - } - // - line.setProcessed(false); - if (line.save(get_TrxName())) - count++; - // Cross Link - if (counter) - { - fromLine.setRef_InvoiceLine_ID(line.getC_InvoiceLine_ID()); - fromLine.save(get_TrxName()); - } - - // MZ Goodwill - // copy the landed cost - line.copyLandedCostFrom(fromLine); - line.allocateLandedCosts(); - // end MZ - } - 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 - - /** - * Get Taxes - * @param requery requery - * @return array of taxes - */ - public MInvoiceTax[] getTaxes (boolean requery) - { - if (m_taxes != null && !requery) - return m_taxes; - String sql = "SELECT * FROM C_InvoiceTax WHERE C_Invoice_ID=?"; - ArrayList list = new ArrayList(); - PreparedStatement pstmt = null; - try - { - pstmt = DB.prepareStatement (sql, get_TrxName()); - pstmt.setInt (1, getC_Invoice_ID()); - ResultSet rs = pstmt.executeQuery (); - while (rs.next ()) - list.add(new MInvoiceTax(getCtx(), rs, get_TrxName())); - rs.close (); - pstmt.close (); - pstmt = null; - } - catch (Exception e) - { - log.log(Level.SEVERE, "getTaxes", e); - } - try - { - if (pstmt != null) - pstmt.close (); - pstmt = null; - } - catch (Exception e) - { - pstmt = null; - } - - m_taxes = new MInvoiceTax[list.size ()]; - list.toArray (m_taxes); - return m_taxes; - } // getTaxes - - /** - * Add to Description - * @param description text - */ - public void addDescription (String description) - { - String desc = getDescription(); - if (desc == null) - setDescription(description); - else - setDescription(desc + " | " + description); - } // addDescription - - /** - * Is it a Credit Memo? - * @return true if CM - */ - public boolean isCreditMemo() - { - MDocType dt = MDocType.get(getCtx(), - getC_DocType_ID()==0 ? getC_DocTypeTarget_ID() : getC_DocType_ID()); - return MDocType.DOCBASETYPE_APCreditMemo.equals(dt.getDocBaseType()) - || MDocType.DOCBASETYPE_ARCreditMemo.equals(dt.getDocBaseType()); - } // isCreditMemo - - /** - * Set Processed. - * Propergate to Lines/Taxes - * @param processed processed - */ - public void setProcessed (boolean processed) - { - super.setProcessed (processed); - if (get_ID() == 0) - return; - String set = "SET Processed='" - + (processed ? "Y" : "N") - + "' WHERE C_Invoice_ID=" + getC_Invoice_ID(); - int noLine = DB.executeUpdate("UPDATE C_InvoiceLine " + set, get_TrxName()); - int noTax = DB.executeUpdate("UPDATE C_InvoiceTax " + set, get_TrxName()); - m_lines = null; - m_taxes = null; - log.fine(processed + " - Lines=" + noLine + ", Tax=" + noTax); - } // setProcessed - - /** - * Validate Invoice Pay Schedule - * @return pay schedule is valid - */ - public boolean validatePaySchedule() - { - MInvoicePaySchedule[] schedule = MInvoicePaySchedule.getInvoicePaySchedule - (getCtx(), getC_Invoice_ID(), 0, get_TrxName()); - log.fine("#" + schedule.length); - if (schedule.length == 0) - { - setIsPayScheduleValid(false); - return false; - } - // Add up due amounts - BigDecimal total = Env.ZERO; - for (int i = 0; i < schedule.length; i++) - { - schedule[i].setParent(this); - BigDecimal due = schedule[i].getDueAmt(); - if (due != null) - total = total.add(due); - } - boolean valid = getGrandTotal().compareTo(total) == 0; - setIsPayScheduleValid(valid); - - // Update Schedule Lines - for (int i = 0; i < schedule.length; i++) - { - if (schedule[i].isValid() != valid) - { - schedule[i].setIsValid(valid); - schedule[i].save(get_TrxName()); - } - } - return valid; - } // validatePaySchedule - - - /************************************************************************** - * Before Save - * @param newRecord new - * @return true - */ - protected boolean beforeSave (boolean newRecord) - { - log.fine(""); - // No Partner Info - set Template - if (getC_BPartner_ID() == 0) - setBPartner(MBPartner.getTemplate(getCtx(), getAD_Client_ID())); - if (getC_BPartner_Location_ID() == 0) - setBPartner(new MBPartner(getCtx(), getC_BPartner_ID(), null)); - - // Price List - if (getM_PriceList_ID() == 0) - { - int ii = Env.getContextAsInt(getCtx(), "#M_PriceList_ID"); - if (ii != 0) - setM_PriceList_ID(ii); - else - { - String sql = "SELECT M_PriceList_ID FROM M_PriceList WHERE AD_Client_ID=? AND IsDefault='Y'"; - ii = DB.getSQLValue (null, sql, getAD_Client_ID()); - if (ii != 0) - setM_PriceList_ID (ii); - } - } - - // Currency - if (getC_Currency_ID() == 0) - { - String sql = "SELECT C_Currency_ID FROM M_PriceList WHERE M_PriceList_ID=?"; - int ii = DB.getSQLValue (null, sql, getM_PriceList_ID()); - if (ii != 0) - setC_Currency_ID (ii); - else - setC_Currency_ID(Env.getContextAsInt(getCtx(), "#C_Currency_ID")); - } - - // Sales Rep - if (getSalesRep_ID() == 0) - { - int ii = Env.getContextAsInt(getCtx(), "#SalesRep_ID"); - if (ii != 0) - setSalesRep_ID (ii); - } - - // Document Type - if (getC_DocType_ID() == 0) - setC_DocType_ID (0); // make sure it's set to 0 - if (getC_DocTypeTarget_ID() == 0) - setC_DocTypeTarget_ID(isSOTrx() ? MDocType.DOCBASETYPE_ARInvoice : MDocType.DOCBASETYPE_APInvoice); - - // Payment Term - if (getC_PaymentTerm_ID() == 0) - { - int ii = Env.getContextAsInt(getCtx(), "#C_PaymentTerm_ID"); - if (ii != 0) - setC_PaymentTerm_ID (ii); - else - { - String sql = "SELECT C_PaymentTerm_ID FROM C_PaymentTerm WHERE AD_Client_ID=? AND IsDefault='Y'"; - ii = DB.getSQLValue(null, sql, getAD_Client_ID()); - if (ii != 0) - setC_PaymentTerm_ID (ii); - } - } - return true; - } // beforeSave - - /** - * Before Delete - * @return true if it can be deleted - */ - protected boolean beforeDelete () - { - if (getC_Order_ID() != 0) - { - log.saveError("Error", Msg.getMsg(getCtx(), "CannotDelete")); - return false; - } - return true; - } // beforeDelete - - /** - * String Representation - * @return info - */ - public String toString () - { - StringBuffer sb = new StringBuffer ("MInvoice[") - .append(get_ID()).append("-").append(getDocumentNo()) - .append(",GrandTotal=").append(getGrandTotal()); - if (m_lines != null) - sb.append(" (#").append(m_lines.length).append(")"); - sb.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 - - - /** - * 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 C_InvoiceLine ol" - + " SET AD_Org_ID =" - + "(SELECT AD_Org_ID" - + " FROM C_Invoice o WHERE ol.C_Invoice_ID=o.C_Invoice_ID) " - + "WHERE C_Invoice_ID=" + getC_Invoice_ID(); - int no = DB.executeUpdate(sql, get_TrxName()); - log.fine("Lines -> #" + no); - } - return true; - } // afterSave - - - /** - * Set Price List (and Currency) when valid - * @param M_PriceList_ID price list - */ - public void setM_PriceList_ID (int M_PriceList_ID) - { - String sql = "SELECT M_PriceList_ID, C_Currency_ID " - + "FROM M_PriceList WHERE M_PriceList_ID=?"; - PreparedStatement pstmt = null; - try - { - pstmt = DB.prepareStatement(sql, null); - pstmt.setInt(1, M_PriceList_ID); - ResultSet rs = pstmt.executeQuery(); - if (rs.next()) - { - super.setM_PriceList_ID (rs.getInt(1)); - setC_Currency_ID (rs.getInt(2)); - } - rs.close(); - pstmt.close(); - pstmt = null; - } - catch (Exception e) - { - log.log(Level.SEVERE, "setM_PriceList_ID", e); - } - finally - { - try - { - if (pstmt != null) - pstmt.close (); - } - catch (Exception e) - {} - pstmt = null; - } - } // setM_PriceList_ID - - - /** - * Get Allocated Amt in Invoice Currency - * @return pos/neg amount or null - */ - public BigDecimal getAllocatedAmt () - { - BigDecimal retValue = null; - String sql = "SELECT SUM(currencyConvert(al.Amount+al.DiscountAmt+al.WriteOffAmt," - + "ah.C_Currency_ID, i.C_Currency_ID,ah.DateTrx,COALESCE(i.C_ConversionType_ID,0), al.AD_Client_ID,al.AD_Org_ID)) " - + "FROM C_AllocationLine al" - + " INNER JOIN C_AllocationHdr ah ON (al.C_AllocationHdr_ID=ah.C_AllocationHdr_ID)" - + " INNER JOIN C_Invoice i ON (al.C_Invoice_ID=i.C_Invoice_ID) " - + "WHERE al.C_Invoice_ID=?" - + " AND ah.IsActive='Y' AND al.IsActive='Y'"; - PreparedStatement pstmt = null; - try - { - pstmt = DB.prepareStatement(sql, get_TrxName()); - pstmt.setInt(1, getC_Invoice_ID()); - ResultSet rs = pstmt.executeQuery(); - if (rs.next()) - retValue = rs.getBigDecimal(1); - 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; - } - // log.fine("getAllocatedAmt - " + retValue); - // ? ROUND(NVL(v_AllocatedAmt,0), 2); - return retValue; - } // getAllocatedAmt - - /** - * Test Allocation (and set paid flag) - * @return true if updated - */ - public boolean testAllocation() - { - boolean change = false; - - if ( isProcessed() ) { - BigDecimal alloc = getAllocatedAmt(); // absolute - if (alloc == null) - alloc = Env.ZERO; - BigDecimal total = getGrandTotal(); - if (!isSOTrx()) - total = total.negate(); - if (isCreditMemo()) - total = total.negate(); - boolean test = total.compareTo(alloc) == 0; - change = test != isPaid(); - if (change) - setIsPaid(test); - log.fine("Paid=" + test - + " (" + alloc + "=" + total + ")"); - } - - return change; - } // testAllocation - - /** - * Set Paid Flag for invoices - * @param ctx context - * @param C_BPartner_ID if 0 all - * @param trxName transaction - */ - public static void setIsPaid (Properties ctx, int C_BPartner_ID, String trxName) - { - int counter = 0; - String sql = "SELECT * FROM C_Invoice " - + "WHERE IsPaid='N' AND DocStatus IN ('CO','CL')"; - if (C_BPartner_ID > 1) - sql += " AND C_BPartner_ID=?"; - else - sql += " AND AD_Client_ID=" + Env.getAD_Client_ID(ctx); - PreparedStatement pstmt = null; - try - { - pstmt = DB.prepareStatement (sql, trxName); - if (C_BPartner_ID > 1) - pstmt.setInt (1, C_BPartner_ID); - ResultSet rs = pstmt.executeQuery (); - while (rs.next ()) - { - MInvoice invoice = new MInvoice(ctx, rs, trxName); - if (invoice.testAllocation()) - if (invoice.save()) - counter++; - } - rs.close (); - pstmt.close (); - pstmt = null; - } - catch (Exception e) - { - s_log.log(Level.SEVERE, sql, e); - } - try - { - if (pstmt != null) - pstmt.close (); - pstmt = null; - } - catch (Exception e) - { - pstmt = null; - } - s_log.config("#" + counter); - /**/ - } // setIsPaid - - /** - * Get Open Amount. - * Used by web interface - * @return Open Amt - */ - public BigDecimal getOpenAmt () - { - return getOpenAmt (true, null); - } // getOpenAmt - - /** - * Get Open Amount - * @param creditMemoAdjusted adjusted for CM (negative) - * @param paymentDate ignored Payment Date - * @return Open Amt - */ - public BigDecimal getOpenAmt (boolean creditMemoAdjusted, Timestamp paymentDate) - { - if (isPaid()) - return Env.ZERO; - // - if (m_openAmt == null) - { - m_openAmt = getGrandTotal(); - if (paymentDate != null) - { - // Payment Discount - // Payment Schedule - } - BigDecimal allocated = getAllocatedAmt(); - if (allocated != null) - { - allocated = allocated.abs(); // is absolute - m_openAmt = m_openAmt.subtract(allocated); - } - } - // - if (!creditMemoAdjusted) - return m_openAmt; - if (isCreditMemo()) - return m_openAmt.negate(); - return m_openAmt; - } // getOpenAmt - - - /** - * Get Document Status - * @return Document Status Clear Text - */ - public String getDocStatusName() - { - return MRefList.getListName(getCtx(), 131, getDocStatus()); - } // getDocStatusName - - - /************************************************************************** - * 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.INVOICE, getC_Invoice_ID(), get_TrxName()); - if (re == null) - return null; - return re.getPDF(file); - } // createPDF - - /** - * Get PDF File Name - * @param documentDir directory - * @return file name - */ - public String getPDFFileName (String documentDir) - { - return getPDFFileName (documentDir, getC_Invoice_ID()); - } // getPDFFileName - - /** - * Get ISO Code of Currency - * @return Currency ISO - */ - public String getCurrencyISO() - { - return MCurrency.getISO_Code (getCtx(), getC_Currency_ID()); - } // getCurrencyISO - - /** - * Get Currency Precision - * @return precision - */ - public int getPrecision() - { - return MCurrency.getStdPrecision(getCtx(), getC_Currency_ID()); - } // getPrecision - - - /************************************************************************** - * 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("unlockIt - " + toString()); - setProcessing(false); - return true; - } // unlockIt - - /** - * Invalidate Document - * @return true if success - */ - public boolean invalidateIt() - { - log.info("invalidateIt - " + 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_DocTypeTarget_ID()); - - // Std Period open? - if (!MPeriod.isOpen(getCtx(), getDateAcct(), dt.getDocBaseType())) - { - m_processMsg = "@PeriodClosed@"; - return DocAction.STATUS_Invalid; - } - // Lines - MInvoiceLine[] lines = getLines(true); - if (lines.length == 0) - { - m_processMsg = "@NoLines@"; - return DocAction.STATUS_Invalid; - } - // No Cash Book - if (PAYMENTRULE_Cash.equals(getPaymentRule()) - && MCashBook.get(getCtx(), getAD_Org_ID(), getC_Currency_ID()) == null) - { - m_processMsg = "@NoCashBook@"; - return DocAction.STATUS_Invalid; - } - - // Convert/Check DocType - if (getC_DocType_ID() != getC_DocTypeTarget_ID() ) - setC_DocType_ID(getC_DocTypeTarget_ID()); - if (getC_DocType_ID() == 0) - { - m_processMsg = "No Document Type"; - return DocAction.STATUS_Invalid; - } - - explodeBOM(); - if (!calculateTaxTotal()) // setTotals - { - m_processMsg = "Error calculating Tax"; - return DocAction.STATUS_Invalid; - } - - createPaySchedule(); - - // Credit Status - if (isSOTrx() && !isReversal()) - { - MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), null); - if (MBPartner.SOCREDITSTATUS_CreditStop.equals(bp.getSOCreditStatus())) - { - m_processMsg = "@BPartnerCreditStop@ - @TotalOpenBalance@=" - + bp.getTotalOpenBalance() - + ", @SO_CreditLimit@=" + bp.getSO_CreditLimit(); - return DocAction.STATUS_Invalid; - } - } - - // Landed Costs - if (!isSOTrx()) - { - for (int i = 0; i < lines.length; i++) - { - MInvoiceLine line = lines[i]; - String error = line.allocateLandedCosts(); - if (error != null && error.length() > 0) - { - m_processMsg = error; - return DocAction.STATUS_Invalid; - } - } - } - - m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_PREPARE); - if (m_processMsg != null) - return DocAction.STATUS_Invalid; - - // Add up Amounts - m_justPrepared = true; - if (!DOCACTION_Complete.equals(getDocAction())) - setDocAction(DOCACTION_Complete); - return DocAction.STATUS_InProgress; - } // prepareIt - - /** - * Explode non stocked BOM. - */ - private void explodeBOM () - { - String where = "AND IsActive='Y' AND EXISTS " - + "(SELECT * FROM M_Product p WHERE C_InvoiceLine.M_Product_ID=p.M_Product_ID" - + " AND p.IsBOM='Y' AND p.IsVerified='Y' AND p.IsStocked='N')"; - // - String sql = "SELECT COUNT(*) FROM C_InvoiceLine " - + "WHERE C_Invoice_ID=? " + where; - int count = DB.getSQLValue(get_TrxName(), sql, getC_Invoice_ID()); - while (count != 0) - { - renumberLines (100); - - // Order Lines with non-stocked BOMs - MInvoiceLine[] lines = getLines (where); - for (int i = 0; i < lines.length; i++) - { - MInvoiceLine line = lines[i]; - MProduct product = MProduct.get (getCtx(), line.getM_Product_ID()); - log.fine(product.getName()); - // New Lines - int lineNo = line.getLine (); - MProductBOM[] boms = MProductBOM.getBOMLines (product); - for (int j = 0; j < boms.length; j++) - { - MProductBOM bom = boms[j]; - MInvoiceLine newLine = new MInvoiceLine (this); - newLine.setLine (++lineNo); - newLine.setM_Product_ID (bom.getProduct().getM_Product_ID(), - bom.getProduct().getC_UOM_ID()); - newLine.setQty (line.getQtyInvoiced().multiply( - bom.getBOMQty ())); // Invoiced/Entered - if (bom.getDescription () != null) - newLine.setDescription (bom.getDescription ()); - // - newLine.setPrice (); - newLine.save (get_TrxName()); - } - // Convert into Comment Line - line.setM_Product_ID (0); - line.setM_AttributeSetInstance_ID (0); - line.setPriceEntered (Env.ZERO); - line.setPriceActual (Env.ZERO); - line.setPriceLimit (Env.ZERO); - line.setPriceList (Env.ZERO); - line.setLineNetAmt (Env.ZERO); - // - String description = product.getName (); - if (product.getDescription () != null) - description += " " + product.getDescription (); - if (line.getDescription () != null) - description += " " + line.getDescription (); - line.setDescription (description); - line.save (get_TrxName()); - } // for all lines with BOM - - m_lines = null; - count = DB.getSQLValue (get_TrxName(), sql, getC_Invoice_ID ()); - renumberLines (10); - } // while count != 0 - } // explodeBOM - - /** - * Calculate Tax and Total - * @return true if calculated - */ - private boolean calculateTaxTotal() - { - log.fine(""); - // Delete Taxes - DB.executeUpdate("DELETE C_InvoiceTax WHERE C_Invoice_ID=" + getC_Invoice_ID(), get_TrxName()); - m_taxes = null; - - // Lines - BigDecimal totalLines = Env.ZERO; - ArrayList taxList = new ArrayList(); - MInvoiceLine[] lines = getLines(false); - for (int i = 0; i < lines.length; i++) - { - MInvoiceLine line = lines[i]; - /** Sync ownership for SO - if (isSOTrx() && line.getAD_Org_ID() != getAD_Org_ID()) - { - line.setAD_Org_ID(getAD_Org_ID()); - line.save(); - } **/ - Integer taxID = new Integer(line.getC_Tax_ID()); - if (!taxList.contains(taxID)) - { - MInvoiceTax iTax = MInvoiceTax.get (line, getPrecision(), - false, get_TrxName()); // current Tax - if (iTax != null) - { - iTax.setIsTaxIncluded(isTaxIncluded()); - if (!iTax.calculateTaxFromLines()) - return false; - if (!iTax.save()) - return false; - taxList.add(taxID); - } - } - totalLines = totalLines.add(line.getLineNetAmt()); - } - - // Taxes - BigDecimal grandTotal = totalLines; - MInvoiceTax[] taxes = getTaxes(true); - for (int i = 0; i < taxes.length; i++) - { - MInvoiceTax iTax = taxes[i]; - MTax tax = iTax.getTax(); - if (tax.isSummary()) - { - MTax[] cTaxes = tax.getChildTaxes(false); // Multiple taxes - for (int j = 0; j < cTaxes.length; j++) - { - MTax cTax = cTaxes[j]; - BigDecimal taxAmt = cTax.calculateTax(iTax.getTaxBaseAmt(), isTaxIncluded(), getPrecision()); - // - MInvoiceTax newITax = new MInvoiceTax(getCtx(), 0, get_TrxName()); - newITax.setClientOrg(this); - newITax.setC_Invoice_ID(getC_Invoice_ID()); - newITax.setC_Tax_ID(cTax.getC_Tax_ID()); - newITax.setPrecision(getPrecision()); - newITax.setIsTaxIncluded(isTaxIncluded()); - newITax.setTaxBaseAmt(iTax.getTaxBaseAmt()); - newITax.setTaxAmt(taxAmt); - if (!newITax.save(get_TrxName())) - return false; - // - if (!isTaxIncluded()) - grandTotal = grandTotal.add(taxAmt); - } - if (!iTax.delete(true, get_TrxName())) - return false; - } - else - { - if (!isTaxIncluded()) - grandTotal = grandTotal.add(iTax.getTaxAmt()); - } - } - // - setTotalLines(totalLines); - setGrandTotal(grandTotal); - return true; - } // calculateTaxTotal - - - /** - * (Re) Create Pay Schedule - * @return true if valid schedule - */ - private boolean createPaySchedule() - { - if (getC_PaymentTerm_ID() == 0) - return false; - MPaymentTerm pt = new MPaymentTerm(getCtx(), getC_PaymentTerm_ID(), null); - log.fine(pt.toString()); - return pt.apply(this); // calls validate pay schedule - } // createPaySchedule - - - /** - * 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; - - // Implicit Approval - if (!isApproved()) - approveIt(); - log.info(toString()); - StringBuffer info = new StringBuffer(); - - // Create Cash - if (PAYMENTRULE_Cash.equals(getPaymentRule())) - { - // Modifications for POSterita - /* - MCash cash = MCash.get (getCtx(), getAD_Org_ID(), - getDateInvoiced(), getC_Currency_ID(), get_TrxName()); - */ - - MCash cash; - - int posId = Env.getContextAsInt(getCtx(),Env.POS_ID); - - if (posId != 0) - { - MPOS pos = new MPOS(getCtx(),posId,get_TrxName()); - int cashBookId = pos.getC_CashBook_ID(); - cash = MCash.get(getCtx(),cashBookId,getDateInvoiced(),get_TrxName()); - } - else - { - cash = MCash.get (getCtx(), getAD_Org_ID(), - getDateInvoiced(), getC_Currency_ID(), get_TrxName()); - } - - // End Posterita Modifications - - if (cash == null || cash.get_ID() == 0) - { - m_processMsg = "@NoCashBook@"; - return DocAction.STATUS_Invalid; - } - MCashLine cl = new MCashLine (cash); - cl.setInvoice(this); - if (!cl.save(get_TrxName())) - { - m_processMsg = "Could not save Cash Journal Line"; - return DocAction.STATUS_Invalid; - } - info.append("@C_Cash_ID@: " + cash.getName() + " #" + cl.getLine()); - setC_CashLine_ID(cl.getC_CashLine_ID()); - } // CashBook - - // Update Order & Match - int matchInv = 0; - int matchPO = 0; - MInvoiceLine[] lines = getLines(false); - for (int i = 0; i < lines.length; i++) - { - MInvoiceLine line = lines[i]; - - // Update Order Line - MOrderLine ol = null; - if (line.getC_OrderLine_ID() != 0) - { - if (isSOTrx() - || line.getM_Product_ID() == 0) - { - ol = new MOrderLine (getCtx(), line.getC_OrderLine_ID(), get_TrxName()); - if (line.getQtyInvoiced() != null) - ol.setQtyInvoiced(ol.getQtyInvoiced().add(line.getQtyInvoiced())); - if (!ol.save(get_TrxName())) - { - m_processMsg = "Could not update Order Line"; - return DocAction.STATUS_Invalid; - } - } - // Order Invoiced Qty updated via Matching Inv-PO - else if (!isSOTrx() - && line.getM_Product_ID() != 0 - && !isReversal()) - { - // MatchPO is created also from MInOut when Invoice exists before Shipment - BigDecimal matchQty = line.getQtyInvoiced(); - MMatchPO po = MMatchPO.create (line, null, - getDateInvoiced(), matchQty); - if (!po.save(get_TrxName())) - { - m_processMsg = "Could not create PO Matching"; - return DocAction.STATUS_Invalid; - } - else - matchPO++; - } - } - - // Matching - Inv-Shipment - if (!isSOTrx() - && line.getM_InOutLine_ID() != 0 - && line.getM_Product_ID() != 0 - && !isReversal()) - { - MInOutLine receiptLine = new MInOutLine (getCtx(),line.getM_InOutLine_ID(), get_TrxName()); - BigDecimal matchQty = line.getQtyInvoiced(); - - if (receiptLine.getMovementQty().compareTo(matchQty) < 0) - matchQty = receiptLine.getMovementQty(); - - MMatchInv inv = new MMatchInv(line, getDateInvoiced(), matchQty); - if (!inv.save(get_TrxName())) - { - m_processMsg = "Could not create Invoice Matching"; - return DocAction.STATUS_Invalid; - } - else - matchInv++; - } - } // for all lines - if (matchInv > 0) - info.append(" @M_MatchInv_ID@#").append(matchInv).append(" "); - if (matchPO > 0) - info.append(" @M_MatchPO_ID@#").append(matchPO).append(" "); - - - - // Update BP Statistics - MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), get_TrxName()); - // Update total revenue and balance / credit limit (reversed on AllocationLine.processIt) - BigDecimal invAmt = MConversionRate.convertBase(getCtx(), getGrandTotal(true), // CM adjusted - getC_Currency_ID(), getDateAcct(), 0, getAD_Client_ID(), getAD_Org_ID()); - if (invAmt == null) - { - m_processMsg = "Could not convert C_Currency_ID=" + getC_Currency_ID() - + " to base C_Currency_ID=" + MClient.get(Env.getCtx()).getC_Currency_ID(); - return DocAction.STATUS_Invalid; - } - // Total Balance - BigDecimal newBalance = bp.getTotalOpenBalance(false); - if (newBalance == null) - newBalance = Env.ZERO; - if (isSOTrx()) - { - newBalance = newBalance.add(invAmt); - // - if (bp.getFirstSale() == null) - bp.setFirstSale(getDateInvoiced()); - BigDecimal newLifeAmt = bp.getActualLifeTimeValue(); - if (newLifeAmt == null) - newLifeAmt = invAmt; - else - newLifeAmt = newLifeAmt.add(invAmt); - BigDecimal newCreditAmt = bp.getSO_CreditUsed(); - if (newCreditAmt == null) - newCreditAmt = invAmt; - else - newCreditAmt = newCreditAmt.add(invAmt); - // - log.fine("GrandTotal=" + getGrandTotal(true) + "(" + invAmt - + ") BP Life=" + bp.getActualLifeTimeValue() + "->" + newLifeAmt - + ", Credit=" + bp.getSO_CreditUsed() + "->" + newCreditAmt - + ", Balance=" + bp.getTotalOpenBalance(false) + " -> " + newBalance); - bp.setActualLifeTimeValue(newLifeAmt); - bp.setSO_CreditUsed(newCreditAmt); - } // SO - else - { - newBalance = newBalance.subtract(invAmt); - log.fine("GrandTotal=" + getGrandTotal(true) + "(" + invAmt - + ") Balance=" + bp.getTotalOpenBalance(false) + " -> " + newBalance); - } - bp.setTotalOpenBalance(newBalance); - bp.setSOCreditStatus(); - if (!bp.save(get_TrxName())) - { - m_processMsg = "Could not update Business Partner"; - return DocAction.STATUS_Invalid; - } - - // User - Last Result/Contact - if (getAD_User_ID() != 0) - { - MUser user = new MUser (getCtx(), getAD_User_ID(), get_TrxName()); - user.setLastContact(new Timestamp(System.currentTimeMillis())); - user.setLastResult(Msg.translate(getCtx(), "C_Invoice_ID") + ": " + getDocumentNo()); - if (!user.save(get_TrxName())) - { - m_processMsg = "Could not update Business Partner User"; - return DocAction.STATUS_Invalid; - } - } // user - - // Update Project - if (isSOTrx() && getC_Project_ID() != 0) - { - MProject project = new MProject (getCtx(), getC_Project_ID(), get_TrxName()); - BigDecimal amt = getGrandTotal(true); - int C_CurrencyTo_ID = project.getC_Currency_ID(); - if (C_CurrencyTo_ID != getC_Currency_ID()) - amt = MConversionRate.convert(getCtx(), amt, getC_Currency_ID(), C_CurrencyTo_ID, - getDateAcct(), 0, getAD_Client_ID(), getAD_Org_ID()); - if (amt == null) - { - m_processMsg = "Could not convert C_Currency_ID=" + getC_Currency_ID() - + " to Project C_Currency_ID=" + C_CurrencyTo_ID; - return DocAction.STATUS_Invalid; - } - BigDecimal newAmt = project.getInvoicedAmt(); - if (newAmt == null) - newAmt = amt; - else - newAmt = newAmt.add(amt); - log.fine("GrandTotal=" + getGrandTotal(true) + "(" + amt - + ") Project " + project.getName() - + " - Invoiced=" + project.getInvoicedAmt() + "->" + newAmt); - project.setInvoicedAmt(newAmt); - if (!project.save(get_TrxName())) - { - m_processMsg = "Could not update Project"; - return DocAction.STATUS_Invalid; - } - } // project - - // 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(); - - // Counter Documents - MInvoice counter = createCounterDoc(); - if (counter != null) - info.append(" - @CounterDoc@: @C_Invoice_ID@=").append(counter.getDocumentNo()); - - m_processMsg = info.toString().trim(); - setProcessed(true); - setDocAction(DOCACTION_Close); - return DocAction.STATUS_Completed; - } // completeIt - - /** - * Set the definite document number after completed - */ - private void setDefiniteDocumentNo() { - MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); - if (dt.isOverwriteDateOnComplete()) { - setDateInvoiced(new Timestamp (System.currentTimeMillis())); - } - if (dt.isOverwriteSeqOnComplete()) { - String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true, this); - if (value != null) - setDocumentNo(value); - } - } - - /** - * Create Counter Document - * @return counter invoice - */ - private MInvoice createCounterDoc() - { - // Is this a counter doc ? - if (getRef_Invoice_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(), null); - 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 - MInvoice counter = copyFrom(this, getDateInvoiced(), - 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); - // Refernces (Should not be required - counter.setSalesRep_ID(getSalesRep_ID()); - counter.save(get_TrxName()); - - // Update copied lines - MInvoiceLine[] counterLines = counter.getLines(true); - for (int i = 0; i < counterLines.length; i++) - { - MInvoiceLine counterLine = counterLines[i]; - counterLine.setClientOrg(counter); - counterLine.setInvoice(counter); // copies header values (BP, etc.) - counterLine.setPrice(); - counterLine.setTax(); - // - 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(); - setDocAction(DOCACTION_None); - 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 - MInvoiceLine[] lines = getLines(false); - for (int i = 0; i < lines.length; i++) - { - MInvoiceLine line = lines[i]; - BigDecimal old = line.getQtyInvoiced(); - if (old.compareTo(Env.ZERO) != 0) - { - line.setQty(Env.ZERO); - line.setTaxAmt(Env.ZERO); - line.setLineNetAmt(Env.ZERO); - line.setLineTotalAmt(Env.ZERO); - line.addDescription(Msg.getMsg(getCtx(), "Voided") + " (" + old + ")"); - // Unlink Shipment - if (line.getM_InOutLine_ID() != 0) - { - MInOutLine ioLine = new MInOutLine(getCtx(), line.getM_InOutLine_ID(), get_TrxName()); - ioLine.setIsInvoiced(false); - ioLine.save(get_TrxName()); - line.setM_InOutLine_ID(0); - } - line.save(get_TrxName()); - } - } - addDescription(Msg.getMsg(getCtx(), "Voided")); - setIsPaid(true); - setC_Payment_ID(0); - } - 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())) - { - m_processMsg = "@PeriodClosed@"; - return false; - } - // - MAllocationHdr[] allocations = MAllocationHdr.getOfInvoice(getCtx(), - getC_Invoice_ID(), get_TrxName()); - for (int i = 0; i < allocations.length; i++) - { - allocations[i].setDocAction(DocAction.ACTION_Reverse_Correct); - allocations[i].reverseCorrectIt(); - allocations[i].save(get_TrxName()); - } - // Reverse/Delete Matching - if (!isSOTrx()) - { - MMatchInv[] mInv = MMatchInv.getInvoice(getCtx(), getC_Invoice_ID(), get_TrxName()); - for (int i = 0; i < mInv.length; i++) - mInv[i].delete(true); - MMatchPO[] mPO = MMatchPO.getInvoice(getCtx(), getC_Invoice_ID(), get_TrxName()); - for (int i = 0; i < mPO.length; i++) - { - if (mPO[i].getM_InOutLine_ID() == 0) - mPO[i].delete(true); - else - { - mPO[i].setC_InvoiceLine_ID(null); - mPO[i].save(get_TrxName()); - } - } - } - // - load(get_TrxName()); // reload allocation reversal info - - // Deep Copy - MInvoice reversal = copyFrom (this, getDateInvoiced(), - getC_DocType_ID(), isSOTrx(), false, get_TrxName(), true); - if (reversal == null) - { - m_processMsg = "Could not create Invoice Reversal"; - return false; - } - reversal.setReversal(true); - - // Reverse Line Qty - MInvoiceLine[] rLines = reversal.getLines(false); - for (int i = 0; i < rLines.length; i++) - { - MInvoiceLine rLine = rLines[i]; - rLine.setQtyEntered(rLine.getQtyEntered().negate()); - rLine.setQtyInvoiced(rLine.getQtyInvoiced().negate()); - rLine.setLineNetAmt(rLine.getLineNetAmt().negate()); - if (rLine.getTaxAmt() != null && rLine.getTaxAmt().compareTo(Env.ZERO) != 0) - rLine.setTaxAmt(rLine.getTaxAmt().negate()); - if (rLine.getLineTotalAmt() != null && rLine.getLineTotalAmt().compareTo(Env.ZERO) != 0) - rLine.setLineTotalAmt(rLine.getLineTotalAmt().negate()); - if (!rLine.save(get_TrxName())) - { - m_processMsg = "Could not correct Invoice Reversal Line"; - return false; - } - } - reversal.setC_Order_ID(getC_Order_ID()); - reversal.addDescription("{->" + getDocumentNo() + ")"); - // - if (!reversal.processIt(DocAction.ACTION_Complete)) - { - m_processMsg = "Reversal ERROR: " + reversal.getProcessMsg(); - return false; - } - reversal.setC_Payment_ID(0); - reversal.setIsPaid(true); - reversal.closeIt(); - reversal.setProcessing (false); - reversal.setDocStatus(DOCSTATUS_Reversed); - reversal.setDocAction(DOCACTION_None); - reversal.save(get_TrxName()); - m_processMsg = reversal.getDocumentNo(); - // - addDescription("(" + reversal.getDocumentNo() + "<-)"); - - // Clean up Reversed (this) - MInvoiceLine[] iLines = getLines(false); - for (int i = 0; i < iLines.length; i++) - { - MInvoiceLine iLine = iLines[i]; - if (iLine.getM_InOutLine_ID() != 0) - { - MInOutLine ioLine = new MInOutLine(getCtx(), iLine.getM_InOutLine_ID(), get_TrxName()); - ioLine.setIsInvoiced(false); - ioLine.save(get_TrxName()); - // Reconsiliation - iLine.setM_InOutLine_ID(0); - iLine.save(get_TrxName()); - } - } - setProcessed(true); - setDocStatus(DOCSTATUS_Reversed); // may come from void - setDocAction(DOCACTION_None); - setC_Payment_ID(0); - setIsPaid(true); - - // Create Allocation - MAllocationHdr alloc = new MAllocationHdr(getCtx(), false, getDateAcct(), - getC_Currency_ID(), - Msg.translate(getCtx(), "C_Invoice_ID") + ": " + getDocumentNo() + "/" + reversal.getDocumentNo(), - get_TrxName()); - alloc.setAD_Org_ID(getAD_Org_ID()); - if (alloc.save()) - { - // Amount - BigDecimal gt = getGrandTotal(true); - if (!isSOTrx()) - gt = gt.negate(); - // Orig Line - MAllocationLine aLine = new MAllocationLine (alloc, gt, - Env.ZERO, Env.ZERO, Env.ZERO); - aLine.setC_Invoice_ID(getC_Invoice_ID()); - aLine.save(); - // Reversal Line - MAllocationLine rLine = new MAllocationLine (alloc, gt.negate(), - Env.ZERO, Env.ZERO, Env.ZERO); - rLine.setC_Invoice_ID(reversal.getC_Invoice_ID()); - rLine.save(); - // Process It - if (alloc.processIt(DocAction.ACTION_Complete)) - alloc.save(); - } - - //MZ Goodwill - if (!isSOTrx()) - { - // delete Matched Invoice Cost Detail - MInvoiceLine[] lines = getLines(); - for (int i = 0; i < lines.length; i++) - { - MCostDetail cd = MCostDetail.get (getCtx(), "C_InvoiceLine_ID=? AND M_AttributeSetInstance_ID=?", - lines[i].getC_InvoiceLine_ID(), lines[i].getM_AttributeSetInstance_ID(), get_TrxName()); - if (cd != null) - { - cd.setProcessed(false); - cd.delete(true); - } - } - } - //End MZ - // After reverseCorrect - m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_REVERSECORRECT); - if (m_processMsg != null) - return false; - - return true; - } // reverseCorrectIt - - /** - * 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()); - // : Grand Total = 123.00 (#1) - sb.append(": "). - append(Msg.translate(getCtx(),"GrandTotal")).append("=").append(getGrandTotal()) - .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 getGrandTotal(); - } // getApprovalAmt - - /** - * - * @param rma - */ - public void setRMA(MRMA rma) - { - setM_RMA_ID(rma.getM_RMA_ID()); - setAD_Org_ID(rma.getAD_Org_ID()); - setDescription(rma.getDescription()); - setC_BPartner_ID(rma.getC_BPartner_ID()); - setSalesRep_ID(rma.getSalesRep_ID()); - - setGrandTotal(rma.getAmt()); - setIsSOTrx(rma.isSOTrx()); - setTotalLines(rma.getAmt()); - - MInvoice originalInvoice = rma.getOriginalInvoice(); - - if (originalInvoice == null) - { - throw new IllegalStateException("Not invoiced - RMA: " + rma.getDocumentNo()); - } - - setC_BPartner_Location_ID(originalInvoice.getC_BPartner_Location_ID()); - setAD_User_ID(originalInvoice.getAD_User_ID()); - setC_Currency_ID(originalInvoice.getC_Currency_ID()); - setIsTaxIncluded(originalInvoice.isTaxIncluded()); - setM_PriceList_ID(originalInvoice.getM_PriceList_ID()); - setC_Project_ID(originalInvoice.getC_Project_ID()); - setC_Activity_ID(originalInvoice.getC_Activity_ID()); - setC_Campaign_ID(originalInvoice.getC_Campaign_ID()); - setUser1_ID(originalInvoice.getUser1_ID()); - setUser2_ID(originalInvoice.getUser2_ID()); - } - -} // MInvoice +/****************************************************************************** + * 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.*; +import java.math.*; +import java.sql.*; +import java.util.*; +import java.util.logging.*; +import org.compiere.print.*; +import org.compiere.process.*; +import org.compiere.util.*; +import org.eevolution.model.MPPProductBOM; +import org.eevolution.model.MPPProductBOMLine; + + +/** + * Invoice Model. + * Please do not set DocStatus and C_DocType_ID directly. + * They are set in the process() method. + * Use DocAction and C_DocTypeTarget_ID instead. + * + * @author Jorg Janke + * @version $Id: MInvoice.java,v 1.2 2006/07/30 00:51:02 jjanke Exp $ + * @author victor.perez@e-evolution.com + * @see http://sourceforge.net/tracker/?func=detail&atid=879335&aid=1948157&group_id=176962 + * Modifications: Added RMA functionality (Ashley Ramdass) + */ +public class MInvoice extends X_C_Invoice implements DocAction +{ + /** + * Get Payments Of BPartner + * @param ctx context + * @param C_BPartner_ID id + * @param trxName transaction + * @return array + */ + public static MInvoice[] getOfBPartner (Properties ctx, int C_BPartner_ID, String trxName) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_Invoice WHERE C_BPartner_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, trxName); + pstmt.setInt(1, C_BPartner_ID); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + list.add(new MInvoice(ctx,rs, trxName)); + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + // + MInvoice[] retValue = new MInvoice[list.size()]; + list.toArray(retValue); + return retValue; + } // getOfBPartner + + /** + * Create new Invoice by copying + * @param from invoice + * @param dateDoc date of the document date + * @param C_DocTypeTarget_ID target doc type + * @param isSOTrx sales order + * @param counter create counter links + * @param trxName trx + * @param setOrder set Order links + * @return Invoice + */ + public static MInvoice copyFrom (MInvoice from, Timestamp dateDoc, + int C_DocTypeTarget_ID, boolean isSOTrx, boolean counter, + String trxName, boolean setOrder) + { + MInvoice to = new MInvoice (from.getCtx(), 0, null); + to.set_TrxName(trxName); + PO.copyValues (from, to, from.getAD_Client_ID(), from.getAD_Org_ID()); + to.set_ValueNoCheck ("C_Invoice_ID", I_ZERO); + to.set_ValueNoCheck ("DocumentNo", null); + // + to.setDocStatus (DOCSTATUS_Drafted); // Draft + to.setDocAction(DOCACTION_Complete); + // + to.setC_DocType_ID(0); + to.setC_DocTypeTarget_ID (C_DocTypeTarget_ID); + to.setIsSOTrx(isSOTrx); + // + to.setDateInvoiced (dateDoc); + to.setDateAcct (dateDoc); + to.setDatePrinted(null); + to.setIsPrinted (false); + // + to.setIsApproved (false); + to.setC_Payment_ID(0); + to.setC_CashLine_ID(0); + to.setIsPaid (false); + to.setIsInDispute(false); + // + // Amounts are updated by trigger when adding lines + to.setGrandTotal(Env.ZERO); + to.setTotalLines(Env.ZERO); + // + to.setIsTransferred (false); + to.setPosted (false); + to.setProcessed (false); + //[ 1633721 ] Reverse Documents- Processing=Y + to.setProcessing(false); + // delete references + to.setIsSelfService(false); + if (!setOrder) + to.setC_Order_ID(0); + if (counter) + { + to.setRef_Invoice_ID(from.getC_Invoice_ID()); + // Try to find Order 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()); + } + } + else + to.setRef_Invoice_ID(0); + + if (!to.save(trxName)) + throw new IllegalStateException("Could not create Invoice"); + if (counter) + from.setRef_Invoice_ID(to.getC_Invoice_ID()); + + // Lines + if (to.copyLinesFrom(from, counter, setOrder) == 0) + throw new IllegalStateException("Could not create Invoice Lines"); + + return to; + } // copyFrom + + /** + * Get PDF File Name + * @param documentDir directory + * @param C_Invoice_ID invoice + * @return file name + */ + public static String getPDFFileName (String documentDir, int C_Invoice_ID) + { + StringBuffer sb = new StringBuffer (documentDir); + if (sb.length() == 0) + sb.append("."); + if (!sb.toString().endsWith(File.separator)) + sb.append(File.separator); + sb.append("C_Invoice_ID_") + .append(C_Invoice_ID) + .append(".pdf"); + return sb.toString(); + } // getPDFFileName + + + /** + * Get MInvoice from Cache + * @param ctx context + * @param C_Invoice_ID id + * @return MInvoice + */ + public static MInvoice get (Properties ctx, int C_Invoice_ID) + { + Integer key = new Integer (C_Invoice_ID); + MInvoice retValue = (MInvoice) s_cache.get (key); + if (retValue != null) + return retValue; + retValue = new MInvoice (ctx, C_Invoice_ID, null); + if (retValue.get_ID () != 0) + s_cache.put (key, retValue); + return retValue; + } // get + + /** Cache */ + private static CCache s_cache = new CCache("C_Invoice", 20, 2); // 2 minutes + + + /************************************************************************** + * Invoice Constructor + * @param ctx context + * @param C_Invoice_ID invoice or 0 for new + * @param trxName trx name + */ + public MInvoice (Properties ctx, int C_Invoice_ID, String trxName) + { + super (ctx, C_Invoice_ID, trxName); + if (C_Invoice_ID == 0) + { + setDocStatus (DOCSTATUS_Drafted); // Draft + setDocAction (DOCACTION_Complete); + // + setPaymentRule(PAYMENTRULE_OnCredit); // Payment Terms + + setDateInvoiced (new Timestamp (System.currentTimeMillis ())); + setDateAcct (new Timestamp (System.currentTimeMillis ())); + // + setChargeAmt (Env.ZERO); + setTotalLines (Env.ZERO); + setGrandTotal (Env.ZERO); + // + setIsSOTrx (true); + setIsTaxIncluded (false); + setIsApproved (false); + setIsDiscountPrinted (false); + setIsPaid (false); + setSendEMail (false); + setIsPrinted (false); + setIsTransferred (false); + setIsSelfService(false); + setIsPayScheduleValid(false); + setIsInDispute(false); + setPosted(false); + super.setProcessed (false); + setProcessing(false); + } + } // MInvoice + + /** + * Load Constructor + * @param ctx context + * @param rs result set record + * @param trxName transaction + */ + public MInvoice (Properties ctx, ResultSet rs, String trxName) + { + super(ctx, rs, trxName); + } // MInvoice + + /** + * Create Invoice from Order + * @param order order + * @param C_DocTypeTarget_ID target document type + * @param invoiceDate date or null + */ + public MInvoice (MOrder order, int C_DocTypeTarget_ID, Timestamp invoiceDate) + { + this (order.getCtx(), 0, order.get_TrxName()); + setClientOrg(order); + setOrder(order); // set base settings + // + if (C_DocTypeTarget_ID == 0) + C_DocTypeTarget_ID = DB.getSQLValue(null, + "SELECT C_DocTypeInvoice_ID FROM C_DocType WHERE C_DocType_ID=?", + order.getC_DocType_ID()); + setC_DocTypeTarget_ID(C_DocTypeTarget_ID); + if (invoiceDate != null) + setDateInvoiced(invoiceDate); + setDateAcct(getDateInvoiced()); + // + setSalesRep_ID(order.getSalesRep_ID()); + // + setC_BPartner_ID(order.getBill_BPartner_ID()); + setC_BPartner_Location_ID(order.getBill_Location_ID()); + setAD_User_ID(order.getBill_User_ID()); + } // MInvoice + + /** + * Create Invoice from Shipment + * @param ship shipment + * @param invoiceDate date or null + */ + public MInvoice (MInOut ship, Timestamp invoiceDate) + { + this (ship.getCtx(), 0, ship.get_TrxName()); + setClientOrg(ship); + setShipment(ship); // set base settings + // + setC_DocTypeTarget_ID(); + if (invoiceDate != null) + setDateInvoiced(invoiceDate); + setDateAcct(getDateInvoiced()); + // + setSalesRep_ID(ship.getSalesRep_ID()); + setAD_User_ID(ship.getAD_User_ID()); + } // MInvoice + + /** + * Create Invoice from Batch Line + * @param batch batch + * @param line batch line + */ + public MInvoice (MInvoiceBatch batch, MInvoiceBatchLine line) + { + this (line.getCtx(), 0, line.get_TrxName()); + setClientOrg(line); + setDocumentNo(line.getDocumentNo()); + // + setIsSOTrx(batch.isSOTrx()); + MBPartner bp = new MBPartner (line.getCtx(), line.getC_BPartner_ID(), line.get_TrxName()); + setBPartner(bp); // defaults + // + setIsTaxIncluded(line.isTaxIncluded()); + // May conflict with default price list + setC_Currency_ID(batch.getC_Currency_ID()); + setC_ConversionType_ID(batch.getC_ConversionType_ID()); + // + // setPaymentRule(order.getPaymentRule()); + // setC_PaymentTerm_ID(order.getC_PaymentTerm_ID()); + // setPOReference(""); + setDescription(batch.getDescription()); + // setDateOrdered(order.getDateOrdered()); + // + setAD_OrgTrx_ID(line.getAD_OrgTrx_ID()); + setC_Project_ID(line.getC_Project_ID()); + // setC_Campaign_ID(line.getC_Campaign_ID()); + setC_Activity_ID(line.getC_Activity_ID()); + setUser1_ID(line.getUser1_ID()); + setUser2_ID(line.getUser2_ID()); + // + setC_DocTypeTarget_ID(line.getC_DocType_ID()); + setDateInvoiced(line.getDateInvoiced()); + setDateAcct(line.getDateAcct()); + // + setSalesRep_ID(batch.getSalesRep_ID()); + // + setC_BPartner_ID(line.getC_BPartner_ID()); + setC_BPartner_Location_ID(line.getC_BPartner_Location_ID()); + setAD_User_ID(line.getAD_User_ID()); + } // MInvoice + + /** Open Amount */ + private BigDecimal m_openAmt = null; + + /** Invoice Lines */ + private MInvoiceLine[] m_lines; + /** Invoice Taxes */ + private MInvoiceTax[] m_taxes; + /** Logger */ + private static CLogger s_log = CLogger.getCLogger(MInvoice.class); + + /** + * Overwrite Client/Org if required + * @param AD_Client_ID client + * @param AD_Org_ID org + */ + public void setClientOrg (int AD_Client_ID, int AD_Org_ID) + { + super.setClientOrg(AD_Client_ID, AD_Org_ID); + } // setClientOrg + + /** + * 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 Defaults + int ii = 0; + if (isSOTrx()) + ii = bp.getC_PaymentTerm_ID(); + else + ii = bp.getPO_PaymentTerm_ID(); + if (ii != 0) + setC_PaymentTerm_ID(ii); + // + if (isSOTrx()) + ii = bp.getM_PriceList_ID(); + else + ii = bp.getPO_PriceList_ID(); + if (ii != 0) + setM_PriceList_ID(ii); + // + String ss = bp.getPaymentRule(); + if (ss != null) + setPaymentRule(ss); + + + // Set Locations + MBPartnerLocation[] locs = bp.getLocations(false); + if (locs != null) + { + for (int i = 0; i < locs.length; i++) + { + if ((locs[i].isBillTo() && isSOTrx()) + || (locs[i].isPayFrom() && !isSOTrx())) + setC_BPartner_Location_ID(locs[i].getC_BPartner_Location_ID()); + } + // set to first + 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 + + /** + * Set Order References + * @param order order + */ + public void setOrder (MOrder order) + { + if (order == null) + return; + + setC_Order_ID(order.getC_Order_ID()); + setIsSOTrx(order.isSOTrx()); + setIsDiscountPrinted(order.isDiscountPrinted()); + setIsSelfService(order.isSelfService()); + setSendEMail(order.isSendEMail()); + // + setM_PriceList_ID(order.getM_PriceList_ID()); + setIsTaxIncluded(order.isTaxIncluded()); + setC_Currency_ID(order.getC_Currency_ID()); + setC_ConversionType_ID(order.getC_ConversionType_ID()); + // + setPaymentRule(order.getPaymentRule()); + setC_PaymentTerm_ID(order.getC_PaymentTerm_ID()); + setPOReference(order.getPOReference()); + setDescription(order.getDescription()); + setDateOrdered(order.getDateOrdered()); + // + setAD_OrgTrx_ID(order.getAD_OrgTrx_ID()); + setC_Project_ID(order.getC_Project_ID()); + setC_Campaign_ID(order.getC_Campaign_ID()); + setC_Activity_ID(order.getC_Activity_ID()); + setUser1_ID(order.getUser1_ID()); + setUser2_ID(order.getUser2_ID()); + } // setOrder + + /** + * Set Shipment References + * @param ship shipment + */ + public void setShipment (MInOut ship) + { + if (ship == null) + return; + + setIsSOTrx(ship.isSOTrx()); + // + MBPartner bp = new MBPartner (getCtx(), ship.getC_BPartner_ID(), null); + setBPartner (bp); + // + setSendEMail(ship.isSendEMail()); + // + setPOReference(ship.getPOReference()); + setDescription(ship.getDescription()); + setDateOrdered(ship.getDateOrdered()); + // + setAD_OrgTrx_ID(ship.getAD_OrgTrx_ID()); + setC_Project_ID(ship.getC_Project_ID()); + setC_Campaign_ID(ship.getC_Campaign_ID()); + setC_Activity_ID(ship.getC_Activity_ID()); + setUser1_ID(ship.getUser1_ID()); + setUser2_ID(ship.getUser2_ID()); + // + if (ship.getC_Order_ID() != 0) + { + setC_Order_ID(ship.getC_Order_ID()); + MOrder order = new MOrder (getCtx(), ship.getC_Order_ID(), get_TrxName()); + setIsDiscountPrinted(order.isDiscountPrinted()); + setM_PriceList_ID(order.getM_PriceList_ID()); + setIsTaxIncluded(order.isTaxIncluded()); + setC_Currency_ID(order.getC_Currency_ID()); + setC_ConversionType_ID(order.getC_ConversionType_ID()); + setPaymentRule(order.getPaymentRule()); + setC_PaymentTerm_ID(order.getC_PaymentTerm_ID()); + // + MDocType dt = MDocType.get(getCtx(), order.getC_DocType_ID()); + if (dt.getC_DocTypeInvoice_ID() != 0) + setC_DocTypeTarget_ID(dt.getC_DocTypeInvoice_ID()); + // Overwrite Invoice Address + setC_BPartner_Location_ID(order.getBill_Location_ID()); + } + // Check if Shipment/Receipt is based on RMA + if (ship.getM_RMA_ID() != 0) + { + MRMA rma = new MRMA(getCtx(), ship.getM_RMA_ID(), get_TrxName()); + MOrder rmaOrder = rma.getOriginalOrder(); + setM_RMA_ID(ship.getM_RMA_ID()); + setIsSOTrx(rma.isSOTrx()); + setM_PriceList_ID(rmaOrder.getM_PriceList_ID()); + setIsTaxIncluded(rmaOrder.isTaxIncluded()); + setC_Currency_ID(rmaOrder.getC_Currency_ID()); + setC_ConversionType_ID(rmaOrder.getC_ConversionType_ID()); + setPaymentRule(rmaOrder.getPaymentRule()); + setC_PaymentTerm_ID(rmaOrder.getC_PaymentTerm_ID()); + + // Retrieves the invoice DocType + MDocType dt = MDocType.get(getCtx(), rma.getC_DocType_ID()); + if (dt.getC_DocTypeInvoice_ID() != 0) + { + setC_DocTypeTarget_ID(dt.getC_DocTypeInvoice_ID()); + } + setC_BPartner_Location_ID(rmaOrder.getBill_Location_ID()); + } + + } // setShipment + + /** + * Set Target Document Type + * @param DocBaseType doc type MDocType.DOCBASETYPE_ + */ + public void setC_DocTypeTarget_ID (String DocBaseType) + { + String sql = "SELECT C_DocType_ID FROM C_DocType " + + "WHERE AD_Client_ID=? AND DocBaseType=?" + + " AND IsActive='Y' " + + "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); + setC_DocTypeTarget_ID (C_DocType_ID); + boolean isSOTrx = MDocType.DOCBASETYPE_ARInvoice.equals(DocBaseType) + || MDocType.DOCBASETYPE_ARCreditMemo.equals(DocBaseType); + setIsSOTrx (isSOTrx); + } + } // setC_DocTypeTarget_ID + + /** + * Set Target Document Type. + * Based on SO flag AP/AP Invoice + */ + public void setC_DocTypeTarget_ID () + { + if (getC_DocTypeTarget_ID() > 0) + return; + if (isSOTrx()) + setC_DocTypeTarget_ID(MDocType.DOCBASETYPE_ARInvoice); + else + setC_DocTypeTarget_ID(MDocType.DOCBASETYPE_APInvoice); + } // setC_DocTypeTarget_ID + + + /** + * Get Grand Total + * @param creditMemoAdjusted adjusted for CM (negative) + * @return grand total + */ + public BigDecimal getGrandTotal (boolean creditMemoAdjusted) + { + if (!creditMemoAdjusted) + return super.getGrandTotal(); + // + BigDecimal amt = getGrandTotal(); + if (isCreditMemo()) + return amt.negate(); + return amt; + } // getGrandTotal + + + /** + * Get Invoice Lines of Invoice + * @param whereClause starting with AND + * @return lines + */ + private MInvoiceLine[] getLines (String whereClause) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM C_InvoiceLine WHERE C_Invoice_ID=? "; + if (whereClause != null) + sql += whereClause; + sql += " ORDER BY Line"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_Invoice_ID()); + ResultSet rs = pstmt.executeQuery(); + while (rs.next()) + { + MInvoiceLine il = new MInvoiceLine(getCtx(), rs, get_TrxName()); + il.setInvoice(this); + list.add(il); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "getLines", e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + + // + MInvoiceLine[] lines = new MInvoiceLine[list.size()]; + list.toArray(lines); + return lines; + } // getLines + + /** + * Get Invoice Lines + * @param requery + * @return lines + */ + public MInvoiceLine[] getLines (boolean requery) + { + if (m_lines == null || m_lines.length == 0 || requery) + m_lines = getLines(null); + set_TrxName(m_lines, get_TrxName()); + return m_lines; + } // getLines + + /** + * Get Lines of Invoice + * @return lines + */ + public MInvoiceLine[] getLines() + { + return getLines(false); + } // getLines + + + /** + * Renumber Lines + * @param step start and step + */ + public void renumberLines (int step) + { + int number = step; + MInvoiceLine[] lines = getLines(false); + for (int i = 0; i < lines.length; i++) + { + MInvoiceLine line = lines[i]; + line.setLine(number); + line.save(); + number += step; + } + m_lines = null; + } // renumberLines + + /** + * Copy Lines From other Invoice. + * @param otherInvoice invoice + * @param counter create counter links + * @param setOrder set order links + * @return number of lines copied + */ + public int copyLinesFrom (MInvoice otherInvoice, boolean counter, boolean setOrder) + { + if (isProcessed() || isPosted() || otherInvoice == null) + return 0; + MInvoiceLine[] fromLines = otherInvoice.getLines(false); + int count = 0; + for (int i = 0; i < fromLines.length; i++) + { + MInvoiceLine line = new MInvoiceLine (getCtx(), 0, get_TrxName()); + MInvoiceLine fromLine = fromLines[i]; + 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.setC_Invoice_ID(getC_Invoice_ID()); + line.setInvoice(this); + line.set_ValueNoCheck ("C_InvoiceLine_ID", I_ZERO); // new + // Reset + if (!setOrder) + line.setC_OrderLine_ID(0); + line.setRef_InvoiceLine_ID(0); + line.setM_InOutLine_ID(0); + line.setA_Asset_ID(0); + line.setM_AttributeSetInstance_ID(0); + line.setS_ResourceAssignment_ID(0); + // New Tax + if (getC_BPartner_ID() != otherInvoice.getC_BPartner_ID()) + line.setTax(); // recalculate + // + if (counter) + { + line.setRef_InvoiceLine_ID(fromLine.getC_InvoiceLine_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.setM_InOutLine_ID(0); + if (fromLine.getM_InOutLine_ID() != 0) + { + MInOutLine peer = new MInOutLine (getCtx(), fromLine.getM_InOutLine_ID(), get_TrxName()); + if (peer.getRef_InOutLine_ID() != 0) + line.setM_InOutLine_ID(peer.getRef_InOutLine_ID()); + } + } + // + line.setProcessed(false); + if (line.save(get_TrxName())) + count++; + // Cross Link + if (counter) + { + fromLine.setRef_InvoiceLine_ID(line.getC_InvoiceLine_ID()); + fromLine.save(get_TrxName()); + } + + // MZ Goodwill + // copy the landed cost + line.copyLandedCostFrom(fromLine); + line.allocateLandedCosts(); + // end MZ + } + 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 + + /** + * Get Taxes + * @param requery requery + * @return array of taxes + */ + public MInvoiceTax[] getTaxes (boolean requery) + { + if (m_taxes != null && !requery) + return m_taxes; + String sql = "SELECT * FROM C_InvoiceTax WHERE C_Invoice_ID=?"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getC_Invoice_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MInvoiceTax(getCtx(), rs, get_TrxName())); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "getTaxes", e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + + m_taxes = new MInvoiceTax[list.size ()]; + list.toArray (m_taxes); + return m_taxes; + } // getTaxes + + /** + * Add to Description + * @param description text + */ + public void addDescription (String description) + { + String desc = getDescription(); + if (desc == null) + setDescription(description); + else + setDescription(desc + " | " + description); + } // addDescription + + /** + * Is it a Credit Memo? + * @return true if CM + */ + public boolean isCreditMemo() + { + MDocType dt = MDocType.get(getCtx(), + getC_DocType_ID()==0 ? getC_DocTypeTarget_ID() : getC_DocType_ID()); + return MDocType.DOCBASETYPE_APCreditMemo.equals(dt.getDocBaseType()) + || MDocType.DOCBASETYPE_ARCreditMemo.equals(dt.getDocBaseType()); + } // isCreditMemo + + /** + * Set Processed. + * Propergate to Lines/Taxes + * @param processed processed + */ + public void setProcessed (boolean processed) + { + super.setProcessed (processed); + if (get_ID() == 0) + return; + String set = "SET Processed='" + + (processed ? "Y" : "N") + + "' WHERE C_Invoice_ID=" + getC_Invoice_ID(); + int noLine = DB.executeUpdate("UPDATE C_InvoiceLine " + set, get_TrxName()); + int noTax = DB.executeUpdate("UPDATE C_InvoiceTax " + set, get_TrxName()); + m_lines = null; + m_taxes = null; + log.fine(processed + " - Lines=" + noLine + ", Tax=" + noTax); + } // setProcessed + + /** + * Validate Invoice Pay Schedule + * @return pay schedule is valid + */ + public boolean validatePaySchedule() + { + MInvoicePaySchedule[] schedule = MInvoicePaySchedule.getInvoicePaySchedule + (getCtx(), getC_Invoice_ID(), 0, get_TrxName()); + log.fine("#" + schedule.length); + if (schedule.length == 0) + { + setIsPayScheduleValid(false); + return false; + } + // Add up due amounts + BigDecimal total = Env.ZERO; + for (int i = 0; i < schedule.length; i++) + { + schedule[i].setParent(this); + BigDecimal due = schedule[i].getDueAmt(); + if (due != null) + total = total.add(due); + } + boolean valid = getGrandTotal().compareTo(total) == 0; + setIsPayScheduleValid(valid); + + // Update Schedule Lines + for (int i = 0; i < schedule.length; i++) + { + if (schedule[i].isValid() != valid) + { + schedule[i].setIsValid(valid); + schedule[i].save(get_TrxName()); + } + } + return valid; + } // validatePaySchedule + + + /************************************************************************** + * Before Save + * @param newRecord new + * @return true + */ + protected boolean beforeSave (boolean newRecord) + { + log.fine(""); + // No Partner Info - set Template + if (getC_BPartner_ID() == 0) + setBPartner(MBPartner.getTemplate(getCtx(), getAD_Client_ID())); + if (getC_BPartner_Location_ID() == 0) + setBPartner(new MBPartner(getCtx(), getC_BPartner_ID(), null)); + + // Price List + if (getM_PriceList_ID() == 0) + { + int ii = Env.getContextAsInt(getCtx(), "#M_PriceList_ID"); + if (ii != 0) + setM_PriceList_ID(ii); + else + { + String sql = "SELECT M_PriceList_ID FROM M_PriceList WHERE AD_Client_ID=? AND IsDefault='Y'"; + ii = DB.getSQLValue (null, sql, getAD_Client_ID()); + if (ii != 0) + setM_PriceList_ID (ii); + } + } + + // Currency + if (getC_Currency_ID() == 0) + { + String sql = "SELECT C_Currency_ID FROM M_PriceList WHERE M_PriceList_ID=?"; + int ii = DB.getSQLValue (null, sql, getM_PriceList_ID()); + if (ii != 0) + setC_Currency_ID (ii); + else + setC_Currency_ID(Env.getContextAsInt(getCtx(), "#C_Currency_ID")); + } + + // Sales Rep + if (getSalesRep_ID() == 0) + { + int ii = Env.getContextAsInt(getCtx(), "#SalesRep_ID"); + if (ii != 0) + setSalesRep_ID (ii); + } + + // Document Type + if (getC_DocType_ID() == 0) + setC_DocType_ID (0); // make sure it's set to 0 + if (getC_DocTypeTarget_ID() == 0) + setC_DocTypeTarget_ID(isSOTrx() ? MDocType.DOCBASETYPE_ARInvoice : MDocType.DOCBASETYPE_APInvoice); + + // Payment Term + if (getC_PaymentTerm_ID() == 0) + { + int ii = Env.getContextAsInt(getCtx(), "#C_PaymentTerm_ID"); + if (ii != 0) + setC_PaymentTerm_ID (ii); + else + { + String sql = "SELECT C_PaymentTerm_ID FROM C_PaymentTerm WHERE AD_Client_ID=? AND IsDefault='Y'"; + ii = DB.getSQLValue(null, sql, getAD_Client_ID()); + if (ii != 0) + setC_PaymentTerm_ID (ii); + } + } + return true; + } // beforeSave + + /** + * Before Delete + * @return true if it can be deleted + */ + protected boolean beforeDelete () + { + if (getC_Order_ID() != 0) + { + log.saveError("Error", Msg.getMsg(getCtx(), "CannotDelete")); + return false; + } + return true; + } // beforeDelete + + /** + * String Representation + * @return info + */ + public String toString () + { + StringBuffer sb = new StringBuffer ("MInvoice[") + .append(get_ID()).append("-").append(getDocumentNo()) + .append(",GrandTotal=").append(getGrandTotal()); + if (m_lines != null) + sb.append(" (#").append(m_lines.length).append(")"); + sb.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 + + + /** + * 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 C_InvoiceLine ol" + + " SET AD_Org_ID =" + + "(SELECT AD_Org_ID" + + " FROM C_Invoice o WHERE ol.C_Invoice_ID=o.C_Invoice_ID) " + + "WHERE C_Invoice_ID=" + getC_Invoice_ID(); + int no = DB.executeUpdate(sql, get_TrxName()); + log.fine("Lines -> #" + no); + } + return true; + } // afterSave + + + /** + * Set Price List (and Currency) when valid + * @param M_PriceList_ID price list + */ + public void setM_PriceList_ID (int M_PriceList_ID) + { + String sql = "SELECT M_PriceList_ID, C_Currency_ID " + + "FROM M_PriceList WHERE M_PriceList_ID=?"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, null); + pstmt.setInt(1, M_PriceList_ID); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + { + super.setM_PriceList_ID (rs.getInt(1)); + setC_Currency_ID (rs.getInt(2)); + } + rs.close(); + pstmt.close(); + pstmt = null; + } + catch (Exception e) + { + log.log(Level.SEVERE, "setM_PriceList_ID", e); + } + finally + { + try + { + if (pstmt != null) + pstmt.close (); + } + catch (Exception e) + {} + pstmt = null; + } + } // setM_PriceList_ID + + + /** + * Get Allocated Amt in Invoice Currency + * @return pos/neg amount or null + */ + public BigDecimal getAllocatedAmt () + { + BigDecimal retValue = null; + String sql = "SELECT SUM(currencyConvert(al.Amount+al.DiscountAmt+al.WriteOffAmt," + + "ah.C_Currency_ID, i.C_Currency_ID,ah.DateTrx,COALESCE(i.C_ConversionType_ID,0), al.AD_Client_ID,al.AD_Org_ID)) " + + "FROM C_AllocationLine al" + + " INNER JOIN C_AllocationHdr ah ON (al.C_AllocationHdr_ID=ah.C_AllocationHdr_ID)" + + " INNER JOIN C_Invoice i ON (al.C_Invoice_ID=i.C_Invoice_ID) " + + "WHERE al.C_Invoice_ID=?" + + " AND ah.IsActive='Y' AND al.IsActive='Y'"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement(sql, get_TrxName()); + pstmt.setInt(1, getC_Invoice_ID()); + ResultSet rs = pstmt.executeQuery(); + if (rs.next()) + retValue = rs.getBigDecimal(1); + 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; + } + // log.fine("getAllocatedAmt - " + retValue); + // ? ROUND(NVL(v_AllocatedAmt,0), 2); + return retValue; + } // getAllocatedAmt + + /** + * Test Allocation (and set paid flag) + * @return true if updated + */ + public boolean testAllocation() + { + boolean change = false; + + if ( isProcessed() ) { + BigDecimal alloc = getAllocatedAmt(); // absolute + if (alloc == null) + alloc = Env.ZERO; + BigDecimal total = getGrandTotal(); + if (!isSOTrx()) + total = total.negate(); + if (isCreditMemo()) + total = total.negate(); + boolean test = total.compareTo(alloc) == 0; + change = test != isPaid(); + if (change) + setIsPaid(test); + log.fine("Paid=" + test + + " (" + alloc + "=" + total + ")"); + } + + return change; + } // testAllocation + + /** + * Set Paid Flag for invoices + * @param ctx context + * @param C_BPartner_ID if 0 all + * @param trxName transaction + */ + public static void setIsPaid (Properties ctx, int C_BPartner_ID, String trxName) + { + int counter = 0; + String sql = "SELECT * FROM C_Invoice " + + "WHERE IsPaid='N' AND DocStatus IN ('CO','CL')"; + if (C_BPartner_ID > 1) + sql += " AND C_BPartner_ID=?"; + else + sql += " AND AD_Client_ID=" + Env.getAD_Client_ID(ctx); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + if (C_BPartner_ID > 1) + pstmt.setInt (1, C_BPartner_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + { + MInvoice invoice = new MInvoice(ctx, rs, trxName); + if (invoice.testAllocation()) + if (invoice.save()) + counter++; + } + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + s_log.config("#" + counter); + /**/ + } // setIsPaid + + /** + * Get Open Amount. + * Used by web interface + * @return Open Amt + */ + public BigDecimal getOpenAmt () + { + return getOpenAmt (true, null); + } // getOpenAmt + + /** + * Get Open Amount + * @param creditMemoAdjusted adjusted for CM (negative) + * @param paymentDate ignored Payment Date + * @return Open Amt + */ + public BigDecimal getOpenAmt (boolean creditMemoAdjusted, Timestamp paymentDate) + { + if (isPaid()) + return Env.ZERO; + // + if (m_openAmt == null) + { + m_openAmt = getGrandTotal(); + if (paymentDate != null) + { + // Payment Discount + // Payment Schedule + } + BigDecimal allocated = getAllocatedAmt(); + if (allocated != null) + { + allocated = allocated.abs(); // is absolute + m_openAmt = m_openAmt.subtract(allocated); + } + } + // + if (!creditMemoAdjusted) + return m_openAmt; + if (isCreditMemo()) + return m_openAmt.negate(); + return m_openAmt; + } // getOpenAmt + + + /** + * Get Document Status + * @return Document Status Clear Text + */ + public String getDocStatusName() + { + return MRefList.getListName(getCtx(), 131, getDocStatus()); + } // getDocStatusName + + + /************************************************************************** + * 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.INVOICE, getC_Invoice_ID(), get_TrxName()); + if (re == null) + return null; + return re.getPDF(file); + } // createPDF + + /** + * Get PDF File Name + * @param documentDir directory + * @return file name + */ + public String getPDFFileName (String documentDir) + { + return getPDFFileName (documentDir, getC_Invoice_ID()); + } // getPDFFileName + + /** + * Get ISO Code of Currency + * @return Currency ISO + */ + public String getCurrencyISO() + { + return MCurrency.getISO_Code (getCtx(), getC_Currency_ID()); + } // getCurrencyISO + + /** + * Get Currency Precision + * @return precision + */ + public int getPrecision() + { + return MCurrency.getStdPrecision(getCtx(), getC_Currency_ID()); + } // getPrecision + + + /************************************************************************** + * 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("unlockIt - " + toString()); + setProcessing(false); + return true; + } // unlockIt + + /** + * Invalidate Document + * @return true if success + */ + public boolean invalidateIt() + { + log.info("invalidateIt - " + 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_DocTypeTarget_ID()); + + // Std Period open? + if (!MPeriod.isOpen(getCtx(), getDateAcct(), dt.getDocBaseType())) + { + m_processMsg = "@PeriodClosed@"; + return DocAction.STATUS_Invalid; + } + // Lines + MInvoiceLine[] lines = getLines(true); + if (lines.length == 0) + { + m_processMsg = "@NoLines@"; + return DocAction.STATUS_Invalid; + } + // No Cash Book + if (PAYMENTRULE_Cash.equals(getPaymentRule()) + && MCashBook.get(getCtx(), getAD_Org_ID(), getC_Currency_ID()) == null) + { + m_processMsg = "@NoCashBook@"; + return DocAction.STATUS_Invalid; + } + + // Convert/Check DocType + if (getC_DocType_ID() != getC_DocTypeTarget_ID() ) + setC_DocType_ID(getC_DocTypeTarget_ID()); + if (getC_DocType_ID() == 0) + { + m_processMsg = "No Document Type"; + return DocAction.STATUS_Invalid; + } + + explodeBOM(); + if (!calculateTaxTotal()) // setTotals + { + m_processMsg = "Error calculating Tax"; + return DocAction.STATUS_Invalid; + } + + createPaySchedule(); + + // Credit Status + if (isSOTrx() && !isReversal()) + { + MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), null); + if (MBPartner.SOCREDITSTATUS_CreditStop.equals(bp.getSOCreditStatus())) + { + m_processMsg = "@BPartnerCreditStop@ - @TotalOpenBalance@=" + + bp.getTotalOpenBalance() + + ", @SO_CreditLimit@=" + bp.getSO_CreditLimit(); + return DocAction.STATUS_Invalid; + } + } + + // Landed Costs + if (!isSOTrx()) + { + for (int i = 0; i < lines.length; i++) + { + MInvoiceLine line = lines[i]; + String error = line.allocateLandedCosts(); + if (error != null && error.length() > 0) + { + m_processMsg = error; + return DocAction.STATUS_Invalid; + } + } + } + + m_processMsg = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_PREPARE); + if (m_processMsg != null) + return DocAction.STATUS_Invalid; + + // Add up Amounts + m_justPrepared = true; + if (!DOCACTION_Complete.equals(getDocAction())) + setDocAction(DOCACTION_Complete); + return DocAction.STATUS_InProgress; + } // prepareIt + + /** + * Explode non stocked BOM. + */ + private void explodeBOM () + { + String where = "AND IsActive='Y' AND EXISTS " + + "(SELECT * FROM M_Product p WHERE C_InvoiceLine.M_Product_ID=p.M_Product_ID" + + " AND p.IsBOM='Y' AND p.IsVerified='Y' AND p.IsStocked='N')"; + // + String sql = "SELECT COUNT(*) FROM C_InvoiceLine " + + "WHERE C_Invoice_ID=? " + where; + int count = DB.getSQLValue(get_TrxName(), sql, getC_Invoice_ID()); + while (count != 0) + { + renumberLines (100); + + // Order Lines with non-stocked BOMs + MInvoiceLine[] lines = getLines (where); + for (int i = 0; i < lines.length; i++) + { + MInvoiceLine line = lines[i]; + MProduct product = MProduct.get (getCtx(), line.getM_Product_ID()); + log.fine(product.getName()); + // New Lines + int lineNo = line.getLine (); + + //find default BOM with valid dates and to this product + MPPProductBOM bom = MPPProductBOM.get(product, getAD_Org_ID(),getDateInvoiced(), get_TrxName()); + if(bom != null) + { + MPPProductBOMLine[] bomlines = bom.getLines(getDateInvoiced()); + for (int j = 0; j < bomlines.length; j++) + { + MPPProductBOMLine bomline = bomlines[j]; + MInvoiceLine newLine = new MInvoiceLine (this); + newLine.setLine (++lineNo); + newLine.setM_Product_ID (bomline.getM_Product_ID ()); + newLine.setC_UOM_ID (bomline.getC_UOM_ID ()); + newLine.setQty (line.getQtyInvoiced().multiply( + bomline.getQtyBOM ())); // Invoiced/Entered + if (bomline.getDescription () != null) + newLine.setDescription (bomline.getDescription ()); + // + newLine.setPrice (); + newLine.save (get_TrxName()); + } + } + + /*MProductBOM[] boms = MProductBOM.getBOMLines (product); + for (int j = 0; j < boms.length; j++) + { + MProductBOM bom = boms[j]; + MInvoiceLine newLine = new MInvoiceLine (this); + newLine.setLine (++lineNo); + newLine.setM_Product_ID (bom.getProduct().getM_Product_ID(), + bom.getProduct().getC_UOM_ID()); + newLine.setQty (line.getQtyInvoiced().multiply( + bom.getBOMQty ())); // Invoiced/Entered + if (bom.getDescription () != null) + newLine.setDescription (bom.getDescription ()); + // + newLine.setPrice (); + newLine.save (get_TrxName()); + }*/ + + // Convert into Comment Line + line.setM_Product_ID (0); + line.setM_AttributeSetInstance_ID (0); + line.setPriceEntered (Env.ZERO); + line.setPriceActual (Env.ZERO); + line.setPriceLimit (Env.ZERO); + line.setPriceList (Env.ZERO); + line.setLineNetAmt (Env.ZERO); + // + String description = product.getName (); + if (product.getDescription () != null) + description += " " + product.getDescription (); + if (line.getDescription () != null) + description += " " + line.getDescription (); + line.setDescription (description); + line.save (get_TrxName()); + } // for all lines with BOM + + m_lines = null; + count = DB.getSQLValue (get_TrxName(), sql, getC_Invoice_ID ()); + renumberLines (10); + } // while count != 0 + } // explodeBOM + + /** + * Calculate Tax and Total + * @return true if calculated + */ + private boolean calculateTaxTotal() + { + log.fine(""); + // Delete Taxes + DB.executeUpdate("DELETE C_InvoiceTax WHERE C_Invoice_ID=" + getC_Invoice_ID(), get_TrxName()); + m_taxes = null; + + // Lines + BigDecimal totalLines = Env.ZERO; + ArrayList taxList = new ArrayList(); + MInvoiceLine[] lines = getLines(false); + for (int i = 0; i < lines.length; i++) + { + MInvoiceLine line = lines[i]; + /** Sync ownership for SO + if (isSOTrx() && line.getAD_Org_ID() != getAD_Org_ID()) + { + line.setAD_Org_ID(getAD_Org_ID()); + line.save(); + } **/ + Integer taxID = new Integer(line.getC_Tax_ID()); + if (!taxList.contains(taxID)) + { + MInvoiceTax iTax = MInvoiceTax.get (line, getPrecision(), + false, get_TrxName()); // current Tax + if (iTax != null) + { + iTax.setIsTaxIncluded(isTaxIncluded()); + if (!iTax.calculateTaxFromLines()) + return false; + if (!iTax.save()) + return false; + taxList.add(taxID); + } + } + totalLines = totalLines.add(line.getLineNetAmt()); + } + + // Taxes + BigDecimal grandTotal = totalLines; + MInvoiceTax[] taxes = getTaxes(true); + for (int i = 0; i < taxes.length; i++) + { + MInvoiceTax iTax = taxes[i]; + MTax tax = iTax.getTax(); + if (tax.isSummary()) + { + MTax[] cTaxes = tax.getChildTaxes(false); // Multiple taxes + for (int j = 0; j < cTaxes.length; j++) + { + MTax cTax = cTaxes[j]; + BigDecimal taxAmt = cTax.calculateTax(iTax.getTaxBaseAmt(), isTaxIncluded(), getPrecision()); + // + MInvoiceTax newITax = new MInvoiceTax(getCtx(), 0, get_TrxName()); + newITax.setClientOrg(this); + newITax.setC_Invoice_ID(getC_Invoice_ID()); + newITax.setC_Tax_ID(cTax.getC_Tax_ID()); + newITax.setPrecision(getPrecision()); + newITax.setIsTaxIncluded(isTaxIncluded()); + newITax.setTaxBaseAmt(iTax.getTaxBaseAmt()); + newITax.setTaxAmt(taxAmt); + if (!newITax.save(get_TrxName())) + return false; + // + if (!isTaxIncluded()) + grandTotal = grandTotal.add(taxAmt); + } + if (!iTax.delete(true, get_TrxName())) + return false; + } + else + { + if (!isTaxIncluded()) + grandTotal = grandTotal.add(iTax.getTaxAmt()); + } + } + // + setTotalLines(totalLines); + setGrandTotal(grandTotal); + return true; + } // calculateTaxTotal + + + /** + * (Re) Create Pay Schedule + * @return true if valid schedule + */ + private boolean createPaySchedule() + { + if (getC_PaymentTerm_ID() == 0) + return false; + MPaymentTerm pt = new MPaymentTerm(getCtx(), getC_PaymentTerm_ID(), null); + log.fine(pt.toString()); + return pt.apply(this); // calls validate pay schedule + } // createPaySchedule + + + /** + * 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; + + // Implicit Approval + if (!isApproved()) + approveIt(); + log.info(toString()); + StringBuffer info = new StringBuffer(); + + // Create Cash + if (PAYMENTRULE_Cash.equals(getPaymentRule())) + { + // Modifications for POSterita + /* + MCash cash = MCash.get (getCtx(), getAD_Org_ID(), + getDateInvoiced(), getC_Currency_ID(), get_TrxName()); + */ + + MCash cash; + + int posId = Env.getContextAsInt(getCtx(),Env.POS_ID); + + if (posId != 0) + { + MPOS pos = new MPOS(getCtx(),posId,get_TrxName()); + int cashBookId = pos.getC_CashBook_ID(); + cash = MCash.get(getCtx(),cashBookId,getDateInvoiced(),get_TrxName()); + } + else + { + cash = MCash.get (getCtx(), getAD_Org_ID(), + getDateInvoiced(), getC_Currency_ID(), get_TrxName()); + } + + // End Posterita Modifications + + if (cash == null || cash.get_ID() == 0) + { + m_processMsg = "@NoCashBook@"; + return DocAction.STATUS_Invalid; + } + MCashLine cl = new MCashLine (cash); + cl.setInvoice(this); + if (!cl.save(get_TrxName())) + { + m_processMsg = "Could not save Cash Journal Line"; + return DocAction.STATUS_Invalid; + } + info.append("@C_Cash_ID@: " + cash.getName() + " #" + cl.getLine()); + setC_CashLine_ID(cl.getC_CashLine_ID()); + } // CashBook + + // Update Order & Match + int matchInv = 0; + int matchPO = 0; + MInvoiceLine[] lines = getLines(false); + for (int i = 0; i < lines.length; i++) + { + MInvoiceLine line = lines[i]; + + // Update Order Line + MOrderLine ol = null; + if (line.getC_OrderLine_ID() != 0) + { + if (isSOTrx() + || line.getM_Product_ID() == 0) + { + ol = new MOrderLine (getCtx(), line.getC_OrderLine_ID(), get_TrxName()); + if (line.getQtyInvoiced() != null) + ol.setQtyInvoiced(ol.getQtyInvoiced().add(line.getQtyInvoiced())); + if (!ol.save(get_TrxName())) + { + m_processMsg = "Could not update Order Line"; + return DocAction.STATUS_Invalid; + } + } + // Order Invoiced Qty updated via Matching Inv-PO + else if (!isSOTrx() + && line.getM_Product_ID() != 0 + && !isReversal()) + { + // MatchPO is created also from MInOut when Invoice exists before Shipment + BigDecimal matchQty = line.getQtyInvoiced(); + MMatchPO po = MMatchPO.create (line, null, + getDateInvoiced(), matchQty); + if (!po.save(get_TrxName())) + { + m_processMsg = "Could not create PO Matching"; + return DocAction.STATUS_Invalid; + } + else + matchPO++; + } + } + + // Matching - Inv-Shipment + if (!isSOTrx() + && line.getM_InOutLine_ID() != 0 + && line.getM_Product_ID() != 0 + && !isReversal()) + { + MInOutLine receiptLine = new MInOutLine (getCtx(),line.getM_InOutLine_ID(), get_TrxName()); + BigDecimal matchQty = line.getQtyInvoiced(); + + if (receiptLine.getMovementQty().compareTo(matchQty) < 0) + matchQty = receiptLine.getMovementQty(); + + MMatchInv inv = new MMatchInv(line, getDateInvoiced(), matchQty); + if (!inv.save(get_TrxName())) + { + m_processMsg = "Could not create Invoice Matching"; + return DocAction.STATUS_Invalid; + } + else + matchInv++; + } + } // for all lines + if (matchInv > 0) + info.append(" @M_MatchInv_ID@#").append(matchInv).append(" "); + if (matchPO > 0) + info.append(" @M_MatchPO_ID@#").append(matchPO).append(" "); + + + + // Update BP Statistics + MBPartner bp = new MBPartner (getCtx(), getC_BPartner_ID(), get_TrxName()); + // Update total revenue and balance / credit limit (reversed on AllocationLine.processIt) + BigDecimal invAmt = MConversionRate.convertBase(getCtx(), getGrandTotal(true), // CM adjusted + getC_Currency_ID(), getDateAcct(), 0, getAD_Client_ID(), getAD_Org_ID()); + if (invAmt == null) + { + m_processMsg = "Could not convert C_Currency_ID=" + getC_Currency_ID() + + " to base C_Currency_ID=" + MClient.get(Env.getCtx()).getC_Currency_ID(); + return DocAction.STATUS_Invalid; + } + // Total Balance + BigDecimal newBalance = bp.getTotalOpenBalance(false); + if (newBalance == null) + newBalance = Env.ZERO; + if (isSOTrx()) + { + newBalance = newBalance.add(invAmt); + // + if (bp.getFirstSale() == null) + bp.setFirstSale(getDateInvoiced()); + BigDecimal newLifeAmt = bp.getActualLifeTimeValue(); + if (newLifeAmt == null) + newLifeAmt = invAmt; + else + newLifeAmt = newLifeAmt.add(invAmt); + BigDecimal newCreditAmt = bp.getSO_CreditUsed(); + if (newCreditAmt == null) + newCreditAmt = invAmt; + else + newCreditAmt = newCreditAmt.add(invAmt); + // + log.fine("GrandTotal=" + getGrandTotal(true) + "(" + invAmt + + ") BP Life=" + bp.getActualLifeTimeValue() + "->" + newLifeAmt + + ", Credit=" + bp.getSO_CreditUsed() + "->" + newCreditAmt + + ", Balance=" + bp.getTotalOpenBalance(false) + " -> " + newBalance); + bp.setActualLifeTimeValue(newLifeAmt); + bp.setSO_CreditUsed(newCreditAmt); + } // SO + else + { + newBalance = newBalance.subtract(invAmt); + log.fine("GrandTotal=" + getGrandTotal(true) + "(" + invAmt + + ") Balance=" + bp.getTotalOpenBalance(false) + " -> " + newBalance); + } + bp.setTotalOpenBalance(newBalance); + bp.setSOCreditStatus(); + if (!bp.save(get_TrxName())) + { + m_processMsg = "Could not update Business Partner"; + return DocAction.STATUS_Invalid; + } + + // User - Last Result/Contact + if (getAD_User_ID() != 0) + { + MUser user = new MUser (getCtx(), getAD_User_ID(), get_TrxName()); + user.setLastContact(new Timestamp(System.currentTimeMillis())); + user.setLastResult(Msg.translate(getCtx(), "C_Invoice_ID") + ": " + getDocumentNo()); + if (!user.save(get_TrxName())) + { + m_processMsg = "Could not update Business Partner User"; + return DocAction.STATUS_Invalid; + } + } // user + + // Update Project + if (isSOTrx() && getC_Project_ID() != 0) + { + MProject project = new MProject (getCtx(), getC_Project_ID(), get_TrxName()); + BigDecimal amt = getGrandTotal(true); + int C_CurrencyTo_ID = project.getC_Currency_ID(); + if (C_CurrencyTo_ID != getC_Currency_ID()) + amt = MConversionRate.convert(getCtx(), amt, getC_Currency_ID(), C_CurrencyTo_ID, + getDateAcct(), 0, getAD_Client_ID(), getAD_Org_ID()); + if (amt == null) + { + m_processMsg = "Could not convert C_Currency_ID=" + getC_Currency_ID() + + " to Project C_Currency_ID=" + C_CurrencyTo_ID; + return DocAction.STATUS_Invalid; + } + BigDecimal newAmt = project.getInvoicedAmt(); + if (newAmt == null) + newAmt = amt; + else + newAmt = newAmt.add(amt); + log.fine("GrandTotal=" + getGrandTotal(true) + "(" + amt + + ") Project " + project.getName() + + " - Invoiced=" + project.getInvoicedAmt() + "->" + newAmt); + project.setInvoicedAmt(newAmt); + if (!project.save(get_TrxName())) + { + m_processMsg = "Could not update Project"; + return DocAction.STATUS_Invalid; + } + } // project + + // 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(); + + // Counter Documents + MInvoice counter = createCounterDoc(); + if (counter != null) + info.append(" - @CounterDoc@: @C_Invoice_ID@=").append(counter.getDocumentNo()); + + m_processMsg = info.toString().trim(); + setProcessed(true); + setDocAction(DOCACTION_Close); + return DocAction.STATUS_Completed; + } // completeIt + + /** + * Set the definite document number after completed + */ + private void setDefiniteDocumentNo() { + MDocType dt = MDocType.get(getCtx(), getC_DocType_ID()); + if (dt.isOverwriteDateOnComplete()) { + setDateInvoiced(new Timestamp (System.currentTimeMillis())); + } + if (dt.isOverwriteSeqOnComplete()) { + String value = DB.getDocumentNo(getC_DocType_ID(), get_TrxName(), true, this); + if (value != null) + setDocumentNo(value); + } + } + + /** + * Create Counter Document + * @return counter invoice + */ + private MInvoice createCounterDoc() + { + // Is this a counter doc ? + if (getRef_Invoice_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(), null); + 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 + MInvoice counter = copyFrom(this, getDateInvoiced(), + 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); + // Refernces (Should not be required + counter.setSalesRep_ID(getSalesRep_ID()); + counter.save(get_TrxName()); + + // Update copied lines + MInvoiceLine[] counterLines = counter.getLines(true); + for (int i = 0; i < counterLines.length; i++) + { + MInvoiceLine counterLine = counterLines[i]; + counterLine.setClientOrg(counter); + counterLine.setInvoice(counter); // copies header values (BP, etc.) + counterLine.setPrice(); + counterLine.setTax(); + // + 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(); + setDocAction(DOCACTION_None); + 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 + MInvoiceLine[] lines = getLines(false); + for (int i = 0; i < lines.length; i++) + { + MInvoiceLine line = lines[i]; + BigDecimal old = line.getQtyInvoiced(); + if (old.compareTo(Env.ZERO) != 0) + { + line.setQty(Env.ZERO); + line.setTaxAmt(Env.ZERO); + line.setLineNetAmt(Env.ZERO); + line.setLineTotalAmt(Env.ZERO); + line.addDescription(Msg.getMsg(getCtx(), "Voided") + " (" + old + ")"); + // Unlink Shipment + if (line.getM_InOutLine_ID() != 0) + { + MInOutLine ioLine = new MInOutLine(getCtx(), line.getM_InOutLine_ID(), get_TrxName()); + ioLine.setIsInvoiced(false); + ioLine.save(get_TrxName()); + line.setM_InOutLine_ID(0); + } + line.save(get_TrxName()); + } + } + addDescription(Msg.getMsg(getCtx(), "Voided")); + setIsPaid(true); + setC_Payment_ID(0); + } + 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())) + { + m_processMsg = "@PeriodClosed@"; + return false; + } + // + MAllocationHdr[] allocations = MAllocationHdr.getOfInvoice(getCtx(), + getC_Invoice_ID(), get_TrxName()); + for (int i = 0; i < allocations.length; i++) + { + allocations[i].setDocAction(DocAction.ACTION_Reverse_Correct); + allocations[i].reverseCorrectIt(); + allocations[i].save(get_TrxName()); + } + // Reverse/Delete Matching + if (!isSOTrx()) + { + MMatchInv[] mInv = MMatchInv.getInvoice(getCtx(), getC_Invoice_ID(), get_TrxName()); + for (int i = 0; i < mInv.length; i++) + mInv[i].delete(true); + MMatchPO[] mPO = MMatchPO.getInvoice(getCtx(), getC_Invoice_ID(), get_TrxName()); + for (int i = 0; i < mPO.length; i++) + { + if (mPO[i].getM_InOutLine_ID() == 0) + mPO[i].delete(true); + else + { + mPO[i].setC_InvoiceLine_ID(null); + mPO[i].save(get_TrxName()); + } + } + } + // + load(get_TrxName()); // reload allocation reversal info + + // Deep Copy + MInvoice reversal = copyFrom (this, getDateInvoiced(), + getC_DocType_ID(), isSOTrx(), false, get_TrxName(), true); + if (reversal == null) + { + m_processMsg = "Could not create Invoice Reversal"; + return false; + } + reversal.setReversal(true); + + // Reverse Line Qty + MInvoiceLine[] rLines = reversal.getLines(false); + for (int i = 0; i < rLines.length; i++) + { + MInvoiceLine rLine = rLines[i]; + rLine.setQtyEntered(rLine.getQtyEntered().negate()); + rLine.setQtyInvoiced(rLine.getQtyInvoiced().negate()); + rLine.setLineNetAmt(rLine.getLineNetAmt().negate()); + if (rLine.getTaxAmt() != null && rLine.getTaxAmt().compareTo(Env.ZERO) != 0) + rLine.setTaxAmt(rLine.getTaxAmt().negate()); + if (rLine.getLineTotalAmt() != null && rLine.getLineTotalAmt().compareTo(Env.ZERO) != 0) + rLine.setLineTotalAmt(rLine.getLineTotalAmt().negate()); + if (!rLine.save(get_TrxName())) + { + m_processMsg = "Could not correct Invoice Reversal Line"; + return false; + } + } + reversal.setC_Order_ID(getC_Order_ID()); + reversal.addDescription("{->" + getDocumentNo() + ")"); + // + if (!reversal.processIt(DocAction.ACTION_Complete)) + { + m_processMsg = "Reversal ERROR: " + reversal.getProcessMsg(); + return false; + } + reversal.setC_Payment_ID(0); + //FR1948157 + reversal.setReversal_ID(getC_Invoice_ID()); + reversal.setIsPaid(true); + reversal.closeIt(); + reversal.setProcessing (false); + reversal.setDocStatus(DOCSTATUS_Reversed); + reversal.setDocAction(DOCACTION_None); + reversal.save(get_TrxName()); + m_processMsg = reversal.getDocumentNo(); + // + addDescription("(" + reversal.getDocumentNo() + "<-)"); + + // Clean up Reversed (this) + MInvoiceLine[] iLines = getLines(false); + for (int i = 0; i < iLines.length; i++) + { + MInvoiceLine iLine = iLines[i]; + if (iLine.getM_InOutLine_ID() != 0) + { + MInOutLine ioLine = new MInOutLine(getCtx(), iLine.getM_InOutLine_ID(), get_TrxName()); + ioLine.setIsInvoiced(false); + ioLine.save(get_TrxName()); + // Reconsiliation + iLine.setM_InOutLine_ID(0); + iLine.save(get_TrxName()); + } + } + setProcessed(true); + //FR1948157 + setReversal_ID(reversal.getC_Invoice_ID()); + setDocStatus(DOCSTATUS_Reversed); // may come from void + setDocAction(DOCACTION_None); + setC_Payment_ID(0); + setIsPaid(true); + + // Create Allocation + MAllocationHdr alloc = new MAllocationHdr(getCtx(), false, getDateAcct(), + getC_Currency_ID(), + Msg.translate(getCtx(), "C_Invoice_ID") + ": " + getDocumentNo() + "/" + reversal.getDocumentNo(), + get_TrxName()); + alloc.setAD_Org_ID(getAD_Org_ID()); + if (alloc.save()) + { + // Amount + BigDecimal gt = getGrandTotal(true); + if (!isSOTrx()) + gt = gt.negate(); + // Orig Line + MAllocationLine aLine = new MAllocationLine (alloc, gt, + Env.ZERO, Env.ZERO, Env.ZERO); + aLine.setC_Invoice_ID(getC_Invoice_ID()); + aLine.save(); + // Reversal Line + MAllocationLine rLine = new MAllocationLine (alloc, gt.negate(), + Env.ZERO, Env.ZERO, Env.ZERO); + rLine.setC_Invoice_ID(reversal.getC_Invoice_ID()); + rLine.save(); + // Process It + if (alloc.processIt(DocAction.ACTION_Complete)) + alloc.save(); + } + + //MZ Goodwill + if (!isSOTrx()) + { + // delete Matched Invoice Cost Detail + MInvoiceLine[] lines = getLines(); + for (int i = 0; i < lines.length; i++) + { + MCostDetail cd = MCostDetail.get (getCtx(), "C_InvoiceLine_ID=? AND M_AttributeSetInstance_ID=?", + lines[i].getC_InvoiceLine_ID(), lines[i].getM_AttributeSetInstance_ID(), get_TrxName()); + if (cd != null) + { + cd.setProcessed(false); + cd.delete(true); + } + } + } + //End MZ + // After reverseCorrect + m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_REVERSECORRECT); + if (m_processMsg != null) + return false; + + return true; + } // reverseCorrectIt + + /** + * 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()); + // : Grand Total = 123.00 (#1) + sb.append(": "). + append(Msg.translate(getCtx(),"GrandTotal")).append("=").append(getGrandTotal()) + .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 getGrandTotal(); + } // getApprovalAmt + + /** + * + * @param rma + */ + public void setRMA(MRMA rma) + { + setM_RMA_ID(rma.getM_RMA_ID()); + setAD_Org_ID(rma.getAD_Org_ID()); + setDescription(rma.getDescription()); + setC_BPartner_ID(rma.getC_BPartner_ID()); + setSalesRep_ID(rma.getSalesRep_ID()); + + setGrandTotal(rma.getAmt()); + setIsSOTrx(rma.isSOTrx()); + setTotalLines(rma.getAmt()); + + MInvoice originalInvoice = rma.getOriginalInvoice(); + + if (originalInvoice == null) + { + throw new IllegalStateException("Not invoiced - RMA: " + rma.getDocumentNo()); + } + + setC_BPartner_Location_ID(originalInvoice.getC_BPartner_Location_ID()); + setAD_User_ID(originalInvoice.getAD_User_ID()); + setC_Currency_ID(originalInvoice.getC_Currency_ID()); + setIsTaxIncluded(originalInvoice.isTaxIncluded()); + setM_PriceList_ID(originalInvoice.getM_PriceList_ID()); + setC_Project_ID(originalInvoice.getC_Project_ID()); + setC_Activity_ID(originalInvoice.getC_Activity_ID()); + setC_Campaign_ID(originalInvoice.getC_Campaign_ID()); + setUser1_ID(originalInvoice.getUser1_ID()); + setUser2_ID(originalInvoice.getUser2_ID()); + } + +} // MInvoice diff --git a/base/src/org/compiere/model/MJournal.java b/base/src/org/compiere/model/MJournal.java index 429d9c9774..3c69700b69 100644 --- a/base/src/org/compiere/model/MJournal.java +++ b/base/src/org/compiere/model/MJournal.java @@ -33,6 +33,9 @@ import org.compiere.util.*; * @author Teo Sarca, SC ARHIPAC SERVICE SRL *
  • BF [ 1619150 ] Usability/Consistency: reversed gl journal description *
  • BF [ 1775358 ] GL Journal DateAcct/C_Period_ID issue + * @author victor.perez@e-evolution.com, e-Evolution + *
  • FR [ 1948157 ] Is necessary the reference for document reverse + * @see http://sourceforge.net/tracker/?func=detail&atid=879335&aid=1948157&group_id=176962 */ public class MJournal extends X_GL_Journal implements DocAction { @@ -677,6 +680,8 @@ public class MJournal extends X_GL_Journal implements DocAction reverse.setDateAcct(getDateAcct()); // Reverse indicator reverse.addDescription("(->" + getDocumentNo() + ")"); + //FR [ 1948157 ] + reverse.setReversal_ID(getGL_Journal_ID()); if (!reverse.save()) return null; addDescription("(" + reverse.getDocumentNo() + "<-)"); @@ -685,6 +690,8 @@ public class MJournal extends X_GL_Journal implements DocAction reverse.copyLinesFrom(this, null, 'C'); // setProcessed(true); + //FR [ 1948157 ] + setReversal_ID(reverse.getGL_Journal_ID()); setDocAction(DOCACTION_None); return reverse; } // reverseCorrectionIt diff --git a/base/src/org/compiere/model/MJournalBatch.java b/base/src/org/compiere/model/MJournalBatch.java index 491515f7a9..9c1d08b2ad 100644 --- a/base/src/org/compiere/model/MJournalBatch.java +++ b/base/src/org/compiere/model/MJournalBatch.java @@ -28,6 +28,9 @@ import org.compiere.util.*; * Journal Batch Model * * @author Jorg Janke + * @author victor.perez@e-evolution.com, e-Evolution + *
  • FR [ 1948157 ] Is necessary the reference for document reverse + * @see http://sourceforge.net/tracker/?func=detail&atid=879335&aid=1948157&group_id=176962 * @version $Id: MJournalBatch.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ */ public class MJournalBatch extends X_GL_JournalBatch implements DocAction @@ -618,6 +621,8 @@ public class MJournalBatch extends X_GL_JournalBatch implements DocAction else description += " ** " + getDocumentNo() + " **"; reverse.setDescription(description); + //[ 1948157 ] + reverse.setReversal_ID(getGL_JournalBatch_ID()); reverse.save(); // @@ -634,6 +639,10 @@ public class MJournalBatch extends X_GL_JournalBatch implements DocAction } journal.save(); } + + //[ 1948157 ] + setReversal_ID(reverse.getGL_JournalBatch_ID()); + save(); // After reverseCorrect m_processMsg = ModelValidationEngine.get().fireDocValidate(this,ModelValidator.TIMING_AFTER_REVERSECORRECT); if (m_processMsg != null) diff --git a/base/src/org/compiere/model/MLocator.java b/base/src/org/compiere/model/MLocator.java index 40be411f6d..421b003f84 100644 --- a/base/src/org/compiere/model/MLocator.java +++ b/base/src/org/compiere/model/MLocator.java @@ -25,6 +25,8 @@ import org.compiere.util.*; * Warehouse Locator Object * * @author Jorg Janke + * @author victor.perez@e-evolution.com + * @see [ 1966333 ] New Method to get the Default Locator based in Warehouse http://sourceforge.net/tracker/index.php?func=detail&aid=1966333&group_id=176962&atid=879335 * @version $Id: MLocator.java,v 1.3 2006/07/30 00:58:37 jjanke Exp $ */ public class MLocator extends X_M_Locator @@ -40,7 +42,7 @@ public class MLocator extends X_M_Locator String trxName = null; MLocator retValue = null; String sql = "SELECT * FROM M_Locator l " - + "WHERE IsDefault='Y'" + + "WHERE IsActive = 'Y' AND IsDefault='Y'" + " AND EXISTS (SELECT * FROM M_Locator lx " + "WHERE l.M_Warehouse_ID=lx.M_Warehouse_ID AND lx.M_Locator_ID=?) " + "ORDER BY Created"; @@ -67,6 +69,43 @@ public class MLocator extends X_M_Locator return retValue; } // getDefault + /** + * FR [ 1966333 ] + * Get oldest Default Locator of warehouse with locator + * @param ctx context + * @param M_Locator_ID locator + * @return locator or null + */ + public static MLocator getDefault (MWarehouse warehouse) + { + String trxName = null; + MLocator retValue = null; + String sql = "SELECT * FROM M_Locator l " + + "WHERE IsActive = 'Y' AND IsDefault='Y' AND l.M_Warehouse_ID=? " + + "ORDER BY PriorityNo"; + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, warehouse.getM_Warehouse_ID()); + rs = pstmt.executeQuery (); + while (rs.next ()) + retValue = new MLocator (warehouse.getCtx(), rs, trxName); + } + catch (Exception e) + { + s_log.log (Level.SEVERE, sql, e); + } + finally + { + DB.close(rs, pstmt); + rs = null; pstmt = null; + } + + return retValue; + } // getDefault + /** * Get the Locator with the combination or create new one @@ -82,7 +121,7 @@ public class MLocator extends X_M_Locator String X, String Y, String Z) { MLocator retValue = null; - String sql = "SELECT * FROM M_Locator WHERE M_Warehouse_ID=? AND X=? AND Y=? AND Z=?"; + String sql = "SELECT * FROM M_Locator WHERE IsActive = 'Y' AND M_Warehouse_ID=? AND X=? AND Y=? AND Z=?"; PreparedStatement pstmt = null; ResultSet rs = null; try diff --git a/base/src/org/compiere/model/MMenu.java b/base/src/org/compiere/model/MMenu.java index fce012c5bd..5182996f01 100644 --- a/base/src/org/compiere/model/MMenu.java +++ b/base/src/org/compiere/model/MMenu.java @@ -19,12 +19,15 @@ package org.compiere.model; import java.sql.*; import java.util.*; import java.util.logging.*; + import org.compiere.util.*; /** * Menu Model * * @author Jorg Janke + * @author victor.perez@e-evolution.com + * @see FR [ 1966326 ] Is necessary create method to get ID menu use menu Name http://sourceforge.net/tracker/index.php?func=detail&aid=1966326&group_id=176962&atid=879335 * @version $Id: MMenu.java,v 1.3 2006/07/30 00:58:18 jjanke Exp $ */ public class MMenu extends X_AD_Menu @@ -166,4 +169,35 @@ public class MMenu extends X_AD_Menu return success; } // afterDelete + /** + * FR [ 1966326 ] + * get Menu ID + * @param String Menu Name + * @return int retValue + */ + public static int getMenu_ID(String menuName) { + int retValue = 0; + String SQL = "SELECT AD_Menu_ID FROM AD_Menu WHERE Name = ?"; + PreparedStatement pstmt = null; + ResultSet rs = null; + try + { + pstmt = DB.prepareStatement(SQL, null); + pstmt.setString(1, menuName); + rs = pstmt.executeQuery(); + if (rs.next()) + retValue = rs.getInt(1); + } + catch (SQLException e) + { + s_log.log(Level.SEVERE, SQL, e); + retValue = -1; + } + finally + { + DB.close(rs, pstmt); + } + return retValue; + } + } // MMenu diff --git a/base/src/org/compiere/model/MMovement.java b/base/src/org/compiere/model/MMovement.java index f1342b6cba..7bbdd21a46 100644 --- a/base/src/org/compiere/model/MMovement.java +++ b/base/src/org/compiere/model/MMovement.java @@ -24,10 +24,14 @@ import java.util.logging.*; import org.compiere.process.*; import org.compiere.util.*; +import org.eevolution.model.*; /** * Inventory Movement Model * * @author Jorg Janke + * @author victor.perez@e-evolution.com, e-Evolution + *
  • FR [ 1948157 ] Is necessary the reference for document reverse + * @see http://sourceforge.net/tracker/?func=detail&atid=879335&aid=1948157&group_id=176962 * @version $Id: MMovement.java,v 1.3 2006/07/30 00:51:03 jjanke Exp $ */ public class MMovement extends X_M_Movement implements DocAction @@ -321,7 +325,7 @@ public class MMovement extends X_M_Movement implements DocAction // Add up Amounts - checkMaterialPolicy(); + //checkMaterialPolicy(); // Confirmation if (dt.isInTransit()) @@ -414,117 +418,177 @@ public class MMovement extends X_M_Movement implements DocAction { MMovementLine line = lines[i]; MTransaction trxFrom = null; - if (line.getM_AttributeSetInstance_ID() == 0) - { - MMovementLineMA mas[] = MMovementLineMA.get(getCtx(), - line.getM_MovementLine_ID(), get_TrxName()); - for (int j = 0; j < mas.length; j++) - { - MMovementLineMA ma = mas[j]; - // - MStorage storageFrom = MStorage.get(getCtx(), line.getM_Locator_ID(), - line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), get_TrxName()); - if (storageFrom == null) - storageFrom = MStorage.getCreate(getCtx(), line.getM_Locator_ID(), - line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), get_TrxName()); - // - MStorage storageTo = MStorage.get(getCtx(), line.getM_LocatorTo_ID(), - line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), get_TrxName()); - if (storageTo == null) - storageTo = MStorage.getCreate(getCtx(), line.getM_LocatorTo_ID(), - line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), get_TrxName()); - // - storageFrom.setQtyOnHand(storageFrom.getQtyOnHand().subtract(ma.getMovementQty())); - if (!storageFrom.save(get_TrxName())) - { - m_processMsg = "Storage From not updated (MA)"; - return DocAction.STATUS_Invalid; - } - // - storageTo.setQtyOnHand(storageTo.getQtyOnHand().add(ma.getMovementQty())); - if (!storageTo.save(get_TrxName())) - { - m_processMsg = "Storage To not updated (MA)"; - return DocAction.STATUS_Invalid; - } - - // - trxFrom = new MTransaction (getCtx(), line.getAD_Org_ID(), - MTransaction.MOVEMENTTYPE_MovementFrom, - line.getM_Locator_ID(), line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), - ma.getMovementQty().negate(), getMovementDate(), get_TrxName()); - trxFrom.setM_MovementLine_ID(line.getM_MovementLine_ID()); - if (!trxFrom.save()) - { - m_processMsg = "Transaction From not inserted (MA)"; - return DocAction.STATUS_Invalid; - } - // - MTransaction trxTo = new MTransaction (getCtx(), line.getAD_Org_ID(), - MTransaction.MOVEMENTTYPE_MovementTo, - line.getM_LocatorTo_ID(), line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), - ma.getMovementQty(), getMovementDate(), get_TrxName()); - trxTo.setM_MovementLine_ID(line.getM_MovementLine_ID()); - if (!trxTo.save()) - { - m_processMsg = "Transaction To not inserted (MA)"; - return DocAction.STATUS_Invalid; - } - } - } - // Fallback - We have ASI - if (trxFrom == null) - { - MStorage storageFrom = MStorage.get(getCtx(), line.getM_Locator_ID(), - line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), get_TrxName()); - if (storageFrom == null) - storageFrom = MStorage.getCreate(getCtx(), line.getM_Locator_ID(), - line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), get_TrxName()); - // - MStorage storageTo = MStorage.get(getCtx(), line.getM_LocatorTo_ID(), - line.getM_Product_ID(), line.getM_AttributeSetInstanceTo_ID(), get_TrxName()); - if (storageTo == null) - storageTo = MStorage.getCreate(getCtx(), line.getM_LocatorTo_ID(), - line.getM_Product_ID(), line.getM_AttributeSetInstanceTo_ID(), get_TrxName()); - // - storageFrom.setQtyOnHand(storageFrom.getQtyOnHand().subtract(line.getMovementQty())); - if (!storageFrom.save(get_TrxName())) - { - m_processMsg = "Storage From not updated"; - return DocAction.STATUS_Invalid; - } - // - storageTo.setQtyOnHand(storageTo.getQtyOnHand().add(line.getMovementQty())); - if (!storageTo.save(get_TrxName())) - { - m_processMsg = "Storage To not updated"; - return DocAction.STATUS_Invalid; - } - // - trxFrom = new MTransaction (getCtx(), line.getAD_Org_ID(), - MTransaction.MOVEMENTTYPE_MovementFrom, - line.getM_Locator_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), - line.getMovementQty().negate(), getMovementDate(), get_TrxName()); - trxFrom.setM_MovementLine_ID(line.getM_MovementLine_ID()); - if (!trxFrom.save()) - { - m_processMsg = "Transaction From not inserted"; - return DocAction.STATUS_Invalid; - } - // - MTransaction trxTo = new MTransaction (getCtx(), line.getAD_Org_ID(), - MTransaction.MOVEMENTTYPE_MovementTo, - line.getM_LocatorTo_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstanceTo_ID(), - line.getMovementQty(), getMovementDate(), get_TrxName()); - trxTo.setM_MovementLine_ID(line.getM_MovementLine_ID()); - if (!trxTo.save()) - { - m_processMsg = "Transaction To not inserted"; - return DocAction.STATUS_Invalid; - } - } // Fallback - } // for all lines + //Stock Movement - Counterpart MOrder.reserveStock + MProduct product = line.getProduct(); + if (product != null + && product.isStocked() ) + { + //Ignore the Material Policy when is Reverse Correction + if(!isReversal()) + checkMaterialPolicy(line); + + if (line.getM_AttributeSetInstance_ID() == 0) + { + MMovementLineMA mas[] = MMovementLineMA.get(getCtx(), + line.getM_MovementLine_ID(), get_TrxName()); + for (int j = 0; j < mas.length; j++) + { + MMovementLineMA ma = mas[j]; + // + /*MStorage storageFrom = MStorage.get(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), get_TrxName()); + if (storageFrom == null) + storageFrom = MStorage.getCreate(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), get_TrxName()); + //*/ + MLocator locator = new MLocator (getCtx(), line.getM_Locator_ID(), get_TrxName()); + //Update Storage + if (!MStorage.add(getCtx(),locator.getM_Warehouse_ID(), + line.getM_Locator_ID(), + line.getM_Product_ID(), + ma.getM_AttributeSetInstance_ID(), 0, + ma.getMovementQty().negate(), Env.ZERO , Env.ZERO , get_TrxName())) + { + m_processMsg = "Cannot correct Inventory (MA)"; + return DocAction.STATUS_Invalid; + } + + /*MStorage storageTo = MStorage.get(getCtx(), line.getM_LocatorTo_ID(), + line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), get_TrxName()); + if (storageTo == null) + storageTo = MStorage.getCreate(getCtx(), line.getM_LocatorTo_ID(), + line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), get_TrxName()); + //*/ + + MLocator locatorTo = new MLocator (getCtx(), line.getM_LocatorTo_ID(), get_TrxName()); + //Update Storage + if (!MStorage.add(getCtx(),locator.getM_Warehouse_ID(), + line.getM_LocatorTo_ID(), + line.getM_Product_ID(), + ma.getM_AttributeSetInstance_ID(), 0, + ma.getMovementQty(), Env.ZERO , Env.ZERO , get_TrxName())) + { + m_processMsg = "Cannot correct Inventory (MA)"; + return DocAction.STATUS_Invalid; + } + + /*storageFrom.setQtyOnHand(storageFrom.getQtyOnHand().subtract(ma.getMovementQty())); + if (!storageFrom.save(get_TrxName())) + { + m_processMsg = "Storage From not updated (MA)"; + return DocAction.STATUS_Invalid; + } + // + storageTo.setQtyOnHand(storageTo.getQtyOnHand().add(ma.getMovementQty())); + if (!storageTo.save(get_TrxName())) + { + m_processMsg = "Storage To not updated (MA)"; + return DocAction.STATUS_Invalid; + }*/ + + // + trxFrom = new MTransaction (getCtx(), line.getAD_Org_ID(), + MTransaction.MOVEMENTTYPE_MovementFrom, + line.getM_Locator_ID(), line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), + ma.getMovementQty().negate(), getMovementDate(), get_TrxName()); + trxFrom.setM_MovementLine_ID(line.getM_MovementLine_ID()); + if (!trxFrom.save()) + { + m_processMsg = "Transaction From not inserted (MA)"; + return DocAction.STATUS_Invalid; + } + // + MTransaction trxTo = new MTransaction (getCtx(), line.getAD_Org_ID(), + MTransaction.MOVEMENTTYPE_MovementTo, + line.getM_LocatorTo_ID(), line.getM_Product_ID(), ma.getM_AttributeSetInstance_ID(), + ma.getMovementQty(), getMovementDate(), get_TrxName()); + trxTo.setM_MovementLine_ID(line.getM_MovementLine_ID()); + if (!trxTo.save()) + { + m_processMsg = "Transaction To not inserted (MA)"; + return DocAction.STATUS_Invalid; + } + } + } + // Fallback - We have ASI + if (trxFrom == null) + { + /*MStorage storageFrom = MStorage.get(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), get_TrxName()); + if (storageFrom == null) + storageFrom = MStorage.getCreate(getCtx(), line.getM_Locator_ID(), + line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), get_TrxName()); + // + MStorage storageTo = MStorage.get(getCtx(), line.getM_LocatorTo_ID(), + line.getM_Product_ID(), line.getM_AttributeSetInstanceTo_ID(), get_TrxName()); + if (storageTo == null) + storageTo = MStorage.getCreate(getCtx(), line.getM_LocatorTo_ID(), + line.getM_Product_ID(), line.getM_AttributeSetInstanceTo_ID(), get_TrxName()); + // + storageFrom.setQtyOnHand(storageFrom.getQtyOnHand().subtract(line.getMovementQty())); + if (!storageFrom.save(get_TrxName())) + { + m_processMsg = "Storage From not updated"; + return DocAction.STATUS_Invalid; + } + // + storageTo.setQtyOnHand(storageTo.getQtyOnHand().add(line.getMovementQty())); + if (!storageTo.save(get_TrxName())) + { + m_processMsg = "Storage To not updated"; + return DocAction.STATUS_Invalid; + }*/ + + MLocator locator = new MLocator (getCtx(), line.getM_Locator_ID(), get_TrxName()); + //Update Storage + if (!MStorage.add(getCtx(),locator.getM_Warehouse_ID(), + line.getM_Locator_ID(), + line.getM_Product_ID(), + line.getM_AttributeSetInstance_ID(), 0, + line.getMovementQty().negate(), Env.ZERO , Env.ZERO , get_TrxName())) + { + m_processMsg = "Cannot correct Inventory (MA)"; + return DocAction.STATUS_Invalid; + } + + MLocator locatorTo = new MLocator (getCtx(), line.getM_LocatorTo_ID(), get_TrxName()); + //Update Storage + if (!MStorage.add(getCtx(),locator.getM_Warehouse_ID(), + line.getM_LocatorTo_ID(), + line.getM_Product_ID(), + line.getM_AttributeSetInstance_ID(), 0, + line.getMovementQty(), Env.ZERO , Env.ZERO , get_TrxName())) + { + m_processMsg = "Cannot correct Inventory (MA)"; + return DocAction.STATUS_Invalid; + } + + // + trxFrom = new MTransaction (getCtx(), line.getAD_Org_ID(), + MTransaction.MOVEMENTTYPE_MovementFrom, + line.getM_Locator_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstance_ID(), + line.getMovementQty().negate(), getMovementDate(), get_TrxName()); + trxFrom.setM_MovementLine_ID(line.getM_MovementLine_ID()); + if (!trxFrom.save()) + { + m_processMsg = "Transaction From not inserted"; + return DocAction.STATUS_Invalid; + } + // + MTransaction trxTo = new MTransaction (getCtx(), line.getAD_Org_ID(), + MTransaction.MOVEMENTTYPE_MovementTo, + line.getM_LocatorTo_ID(), line.getM_Product_ID(), line.getM_AttributeSetInstanceTo_ID(), + line.getMovementQty(), getMovementDate(), get_TrxName()); + trxTo.setM_MovementLine_ID(line.getM_MovementLine_ID()); + if (!trxTo.save()) + { + m_processMsg = "Transaction To not inserted"; + return DocAction.STATUS_Invalid; + } + } // Fallback + } // product stock + } // for all lines // User Validation String valid = ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_COMPLETE); if (valid != null) @@ -561,18 +625,19 @@ public class MMovement extends X_M_Movement implements DocAction * Check Material Policy * Sets line ASI */ - private void checkMaterialPolicy() + private void checkMaterialPolicy(MMovementLine line) { int no = MMovementLineMA.deleteMovementMA(getM_Movement_ID(), get_TrxName()); if (no > 0) log.config("Delete old #" + no); - MMovementLine[] lines = getLines(false); + //MMovementLine[] lines = getLines(false); // Check Lines - for (int i = 0; i < lines.length; i++) - { - MMovementLine line = lines[i]; + //for (int i = 0; i < lines.length; i++) + //{ + // MMovementLine line = lines[i]; boolean needSave = false; + BigDecimal qtyASI = Env.ZERO ; // Attribute Set Instance if (line.getM_AttributeSetInstance_ID() == 0) @@ -583,7 +648,8 @@ public class MMovement extends X_M_Movement implements DocAction 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++) + + /*for (int ii = 0; ii < storages.length; ii++) { MStorage storage = storages[ii]; if (ii == 0) @@ -635,12 +701,58 @@ public class MMovement extends X_M_Movement implements DocAction 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, + storage.getM_AttributeSetInstance_ID(), + qtyToDeliver); + if (!ma.save()) + { + throw new IllegalStateException("Error try create ASI Reservation"); + } + qtyToDeliver = Env.ZERO; + log.fine( ma + ", QtyToDeliver=" + qtyToDeliver); + //return; + } + else + { + MMovementLineMA ma = new MMovementLineMA (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) + { + MMovementLineMA ma = new MMovementLineMA (line, 0 , qtyToDeliver.add(qtyASI)); + + if (!ma.save()) + ; + log.fine("##: " + ma); } } // attributeSetInstance if (needSave && !line.save()) log.severe("NOT saved " + line); - } // for all lines + //} // for all lines } // checkMaterialPolicy @@ -750,12 +862,14 @@ public class MMovement extends X_M_Movement implements DocAction reversal.setPosted(false); reversal.setProcessed(false); reversal.addDescription("{->" + getDocumentNo() + ")"); + //FR [ 1948157 ] + reversal.setReversal_ID(getM_Movement_ID()); if (!reversal.save()) { m_processMsg = "Could not create Movement Reversal"; return false; } - + reversal.setReversal(true); // Reverse Line Qty MMovementLine[] oLines = getLines(true); for (int i = 0; i < oLines.length; i++) @@ -795,6 +909,8 @@ public class MMovement extends X_M_Movement implements DocAction // Update Reversed (this) addDescription("(" + reversal.getDocumentNo() + "<-)"); + //FR [ 1948157 ] + setReversal_ID(reversal.getM_Movement_ID()); setProcessed(true); setDocStatus(DOCSTATUS_Reversed); // may come from void setDocAction(DOCACTION_None); @@ -890,5 +1006,79 @@ public class MMovement extends X_M_Movement implements DocAction return 0; } // getC_Currency_ID + /** + * Order Constructor - create header only + * @param order order + * @param movementDate optional movement date (default today) + * @param C_DocType_ID document type or 0 + */ + public MMovement (MDDOrder order, int C_DocType_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_DocType_ID == 0) + C_DocType_ID = DB.getSQLValue(null, + "SELECT C_DocType_ID FROM C_DocType WHERE C_DocType_ID=?", + order.getC_DocType_ID()); + setC_DocType_ID (C_DocType_ID); + + // Default - Today + if (movementDate != null) + setMovementDate (movementDate); + + //setDateAcct (getMovementDate()); + + // Copy from Order + setDD_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()); + } // MMovement + + /** 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 + } // MMovement diff --git a/base/src/org/compiere/model/MMovementLine.java b/base/src/org/compiere/model/MMovementLine.java index b290f19d5b..1d98958a60 100644 --- a/base/src/org/compiere/model/MMovementLine.java +++ b/base/src/org/compiere/model/MMovementLine.java @@ -19,7 +19,9 @@ package org.compiere.model; import java.math.*; import java.sql.*; import java.util.*; +import java.util.logging.Level; import org.compiere.util.*; +import org.eevolution.model.*; /** * Inventory Move Line Model @@ -53,6 +55,8 @@ public class MMovementLine extends X_M_MovementLine setProcessed (false); } } // MMovementLine + /** Static Logger */ + private static CLogger s_log = CLogger.getCLogger (MMovementLine.class); /** * Load Constructor @@ -200,6 +204,119 @@ public class MMovementLine extends X_M_MovementLine return true; } // beforeSave + /** + * Set Distribution Order Line. + * Does not set Quantity! + * @param oLine order line + * @param M_Locator_ID locator + * @param Qty used only to find suitable locator + */ + public void setOrderLine (MDDOrderLine oLine, int M_Locator_ID, BigDecimal Qty) + { + setDD_OrderLine_ID(oLine.getDD_OrderLine_ID()); + setLine(oLine.getLine()); + //setC_UOM_ID(oLine.getC_UOM_ID()); + MProduct product = oLine.getProduct(); + if (product == null) + { + set_ValueNoCheck("M_Product_ID", null); + set_ValueNoCheck("M_AttributeSetInstance_ID", null); + set_ValueNoCheck("M_Locator_ID", null); + } + else + { + setM_Product_ID(oLine.getM_Product_ID()); + setM_AttributeSetInstance_ID(oLine.getM_AttributeSetInstance_ID()); + // + if (product.isItem()) + { + setM_Locator_ID(M_Locator_ID); + } + else + set_ValueNoCheck("M_Locator_ID", null); + } + //setC_Charge_ID(oLine.getC_Charge_ID()); + setDescription(oLine.getDescription()); + //setIsDescription(oLine.isDescription()); + // + //setC_Project_ID(oLine.getC_Project_ID()); + //setC_ProjectPhase_ID(oLine.getC_ProjectPhase_ID()); + //setC_ProjectTask_ID(oLine.getC_ProjectTask_ID()); + //setC_Activity_ID(oLine.getC_Activity_ID()); + //setC_Campaign_ID(oLine.getC_Campaign_ID()); + //setAD_OrgTrx_ID(oLine.getAD_OrgTrx_ID()); + //setUser1_ID(oLine.getUser1_ID()); + //setUser2_ID(oLine.getUser2_ID()); + } // setOrderLine + /** + * Set M_Locator_ID + * @param M_Locator_ID id + */ + public void setM_Locator_ID (int M_Locator_ID) + { + if (M_Locator_ID < 0) + throw new IllegalArgumentException ("M_Locator_ID is mandatory."); + // set to 0 explicitly to reset + set_Value ("M_Locator_ID", new Integer(M_Locator_ID)); + } // setM_Locator_ID + + /** + * Set M_Locator_ID + * @param M_Locator_ID id + */ + public void setM_LocatorTo_ID (int M_Locator_ID) + { + if (M_Locator_ID < 0) + throw new IllegalArgumentException ("M_LocatorTo_ID is mandatory."); + // set to 0 explicitly to reset + set_Value ("M_Locator_ID", new Integer(M_Locator_ID)); + } // setM_Locator_ID + + /** + * Get Movement lines Of Distribution Order Line + * @param ctx context + * @param DD_OrderLine_ID line + * @param where optional addition where clause + * @param trxName transaction + * @return array of receipt lines + */ + public static MMovementLine[] getOfOrderLine (Properties ctx, + int DD_OrderLine_ID, String where, String trxName) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_MovementLine WHERE DD_OrderLine_ID=?"; + if (where != null && where.length() > 0) + sql += " AND " + where; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, trxName); + pstmt.setInt (1, DD_OrderLine_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add(new MMovementLine(ctx, rs, trxName)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MMovementLine[] retValue = new MMovementLine[list.size ()]; + list.toArray (retValue); + return retValue; + } // getOfOrderLine } // MMovementLine diff --git a/base/src/org/compiere/model/MOrder.java b/base/src/org/compiere/model/MOrder.java index fe9f976aad..bd8a543a32 100644 --- a/base/src/org/compiere/model/MOrder.java +++ b/base/src/org/compiere/model/MOrder.java @@ -24,6 +24,7 @@ import java.sql.Timestamp; import java.util.ArrayList; import java.util.Properties; import java.util.logging.Level; +import java.util.regex.Pattern; import org.compiere.print.ReportEngine; import org.compiere.process.DocAction; @@ -31,6 +32,9 @@ import org.compiere.process.DocumentEngine; import org.compiere.util.DB; import org.compiere.util.Env; import org.compiere.util.Msg; +import org.eevolution.model.MPPProductBOMLine; +import org.eevolution.model.MPPProductBOM; + /** * Order Model. @@ -1355,23 +1359,51 @@ public class MOrder extends X_C_Order implements DocAction log.fine(product.getName()); // New Lines int lineNo = line.getLine (); - MProductBOM[] boms = MProductBOM.getBOMLines (product); + //find default BOM with valid dates and to this product + MPPProductBOM bom = MPPProductBOM.get(product, getAD_Org_ID(),getDatePromised(), get_TrxName()); + if(bom != null) + { + MPPProductBOMLine[] bomlines = bom.getLines(getDatePromised()); + for (int j = 0; j < bomlines.length; j++) + { + MPPProductBOMLine bomline = bomlines[j]; + MOrderLine newLine = new MOrderLine (this); + newLine.setLine (++lineNo); + newLine.setM_Product_ID (bomline.getM_Product_ID ()); + newLine.setC_UOM_ID (bomline.getC_UOM_ID ()); + newLine.setQty (line.getQtyOrdered ().multiply ( + bomline.getQtyBOM())); + if (bomline.getDescription () != null) + newLine.setDescription (bomline.getDescription ()); + // + newLine.setPrice (); + newLine.save (get_TrxName()); + } + } + + /*MProductBOM[] boms = MProductBOM.getBOMLines (product); for (int j = 0; j < boms.length; j++) { - MProductBOM bom = boms[j]; + //MProductBOM bom = boms[j]; + MPPProductBOMLine bom = boms[j]; MOrderLine newLine = new MOrderLine (this); newLine.setLine (++lineNo); - newLine.setM_Product_ID (bom.getProduct () - .getM_Product_ID ()); - newLine.setC_UOM_ID (bom.getProduct ().getC_UOM_ID ()); + //newLine.setM_Product_ID (bom.getProduct () + // .getM_Product_ID ()); + newLine.setM_Product_ID (bom.getM_Product_ID ()); + //newLine.setC_UOM_ID (bom.getProduct ().getC_UOM_ID ()); + newLine.setC_UOM_ID (bom.getC_UOM_ID ()); + //newLine.setQty (line.getQtyOrdered ().multiply ( + // bom.getBOMQty ())); newLine.setQty (line.getQtyOrdered ().multiply ( - bom.getBOMQty ())); + bom.getQtyBOM())); if (bom.getDescription () != null) newLine.setDescription (bom.getDescription ()); // newLine.setPrice (); newLine.save (get_TrxName()); - } + }*/ + // Convert into Comment Line line.setM_Product_ID (0); line.setM_AttributeSetInstance_ID (0); @@ -2178,6 +2210,58 @@ public class MOrder extends X_C_Order implements DocAction return true; } // closeIt + /** + * @author: phib + * re-open a closed order + * (reverse steps of close()) + */ + public String reopenIt() { + log.info(toString()); + if (!MOrder.DOCSTATUS_Closed.equals(getDocStatus())) + { + return "Not closed - can't reopen"; + } + + // + MOrderLine[] lines = getLines(true, "M_Product_ID"); + for (int i = 0; i < lines.length; i++) + { + MOrderLine line = lines[i]; + if (Env.ZERO.compareTo(line.getQtyLostSales()) != 0) + { + line.setQtyOrdered(line.getQtyLostSales().add(line.getQtyDelivered())); + line.setQtyLostSales(Env.ZERO); + // QtyEntered unchanged + + // Strip Close() tags from description + String desc = line.getDescription(); + if (desc == null) + desc = ""; + Pattern pattern = Pattern.compile("( \\| )?Close \\(.*\\)"); + String[] parts = pattern.split(desc); + desc = ""; + for (String s : parts) { + desc = desc.concat(s); + } + line.setDescription(desc); + if (!line.save(get_TrxName())) + return "Couldn't save orderline"; + } + } + // Clear Reservations + if (!reserveStock(null, lines)) + { + m_processMsg = "Cannot unreserve Stock (close)"; + return "Failed to update reservations"; + } + + setDocStatus(MOrder.DOCSTATUS_Completed); + setDocAction(DOCACTION_Close); + if (!this.save(get_TrxName())) + return "Couldn't save reopened order"; + else + return ""; + } // reopenIt /** * Reverse Correction - same void * @return true if success diff --git a/base/src/org/compiere/model/MPayment.java b/base/src/org/compiere/model/MPayment.java index d09cf93d21..31146aa12f 100644 --- a/base/src/org/compiere/model/MPayment.java +++ b/base/src/org/compiere/model/MPayment.java @@ -52,7 +52,11 @@ import org.compiere.util.*; * When Payment is posed, the Allocation is made * * @author Jorg Janke + * @author victor.perez@e-evolution.com, e-Evolution + *
  • FR [ 1948157 ] Is necessary the reference for document reverse + * @see http://sourceforge.net/tracker/?func=detail&atid=879335&aid=1948157&group_id=176962 * @version $Id: MPayment.java,v 1.4 2006/10/02 05:18:39 jjanke Exp $ + * @author victor.perez@e-evolution.com www.e-evolution.com FR [ 1866214 ] http://sourceforge.net/tracker/index.php?func=detail&aid=1866214&group_id=176962&atid=879335 */ public final class MPayment extends X_C_Payment implements DocAction, ProcessCall @@ -2167,6 +2171,8 @@ public final class MPayment extends X_C_Payment reversal.setPosted(false); reversal.setDescription(getDescription()); reversal.addDescription("{->" + getDocumentNo() + ")"); + //FR [ 1948157 ] + reversal.setReversal_ID(getC_Payment_ID()); reversal.save(get_TrxName()); // Post Reversal if (!reversal.processIt(DocAction.ACTION_Complete)) @@ -2188,6 +2194,8 @@ public final class MPayment extends X_C_Payment setDocStatus(DOCSTATUS_Reversed); setDocAction(DOCACTION_None); setProcessed(true); + //FR [ 1948157 ] + setReversal_ID(reversal.getC_Payment_ID()); // Create automatic Allocation MAllocationHdr alloc = new MAllocationHdr (getCtx(), false, diff --git a/base/src/org/compiere/model/MStorage.java b/base/src/org/compiere/model/MStorage.java index ebcfbfc860..fdaa69a837 100644 --- a/base/src/org/compiere/model/MStorage.java +++ b/base/src/org/compiere/model/MStorage.java @@ -95,8 +95,10 @@ 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=?" - + " AND M_AttributeSetInstance_ID > 0" - + " AND QtyOnHand > 0 " + // 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 " + "ORDER BY M_AttributeSetInstance_ID"; if (!FiFo) sql += " DESC"; diff --git a/base/src/org/compiere/model/MWarehouse.java b/base/src/org/compiere/model/MWarehouse.java index 96535a4279..9c3c1f61c4 100644 --- a/base/src/org/compiere/model/MWarehouse.java +++ b/base/src/org/compiere/model/MWarehouse.java @@ -25,6 +25,8 @@ import org.compiere.util.*; * Warehouse Model * * @author Jorg Janke + * @author victor.perez@e-evolution.com + * @see FR [ 1966337 ] New Method to get the Transit Warehouse based in ID Org http://sourceforge.net/tracker/index.php?func=detail&aid=1966337&group_id=176962&atid=879335 * @version $Id: MWarehouse.java,v 1.3 2006/07/30 00:58:05 jjanke Exp $ */ public class MWarehouse extends X_M_Warehouse @@ -56,7 +58,7 @@ public class MWarehouse extends X_M_Warehouse public static MWarehouse[] getForOrg (Properties ctx, int AD_Org_ID) { ArrayList list = new ArrayList(); - String sql = "SELECT * FROM M_Warehouse WHERE AD_Org_ID=? ORDER BY Created"; + String sql = "SELECT * FROM M_Warehouse WHERE IsActive = 'Y' AND AD_Org_ID=? ORDER BY Created"; PreparedStatement pstmt = null; try { @@ -88,6 +90,47 @@ public class MWarehouse extends X_M_Warehouse return retValue; } // get + /** + * FR [ 1966337 ] + * Get Warehouses Transit for Org + * @param ctx context + * @param AD_Org_ID id + * @return warehouse + */ + public static MWarehouse[] getInTransitForOrg (Properties ctx, int AD_Org_ID) + { + ArrayList list = new ArrayList(); + String sql = "SELECT * FROM M_Warehouse WHERE IsActive = 'Y' AND IsInTransit = 'Y' AND AD_Org_ID=? ORDER BY Created"; + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, null); + pstmt.setInt (1, AD_Org_ID); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new MWarehouse (ctx, rs, null)); + rs.close (); + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + s_log.log(Level.SEVERE, sql, e); + } + try + { + if (pstmt != null) + pstmt.close (); + pstmt = null; + } + catch (Exception e) + { + pstmt = null; + } + MWarehouse[] retValue = new MWarehouse[list.size ()]; + list.toArray (retValue); + return retValue; + } // get /** Cache */ private static CCache s_cache = new CCache("M_Warehouse", 5); @@ -150,7 +193,7 @@ public class MWarehouse extends X_M_Warehouse if (!reload && m_locators != null) return m_locators; // - String sql = "SELECT * FROM M_Locator WHERE M_Warehouse_ID=? ORDER BY X,Y,Z"; + String sql = "SELECT * FROM M_Locator WHERE IsActive = 'Y' AND M_Warehouse_ID=? ORDER BY X,Y,Z"; ArrayList list = new ArrayList(); PreparedStatement pstmt = null; try diff --git a/base/src/org/compiere/model/ModelValidator.java b/base/src/org/compiere/model/ModelValidator.java index 9d480d1a4a..a3a555d8c9 100644 --- a/base/src/org/compiere/model/ModelValidator.java +++ b/base/src/org/compiere/model/ModelValidator.java @@ -32,16 +32,19 @@ public interface ModelValidator public static final int TYPE_NEW = 1; public static final int CHANGETYPE_NEW = 1; // Compatibility with Compiere 260c public static final int TYPE_AFTER_NEW = 4; // teo_sarca [ 1675490 ] + public static final int TYPE_AFTER_NEW_REPLICATION = 7; // @Trifon /** Model Change Type Change */ public static final int TYPE_BEFORE_CHANGE = 2; // teo_sarca [ 1675490 ] public static final int TYPE_CHANGE = 2; public static final int CHANGETYPE_CHANGE = 2; // Compatibility with Compiere 260c public static final int TYPE_AFTER_CHANGE = 5; // teo_sarca [ 1675490 ] + public static final int TYPE_AFTER_CHANGE_REPLICATION = 8; // @Trifon /** Model Change Type Delete */ public static final int TYPE_BEFORE_DELETE = 3; // teo_sarca [ 1675490 ] public static final int TYPE_DELETE = 3; public static final int CHANGETYPE_DELETE = 3; // Compatibility with Compiere 260c public static final int TYPE_AFTER_DELETE = 6; // teo_sarca [ 1675490 ] + public static final int TYPE_BEFORE_DELETE_REPLICATION = 9; // @Trifon // Correlation between constant events and list of event script model validators public static String[] tableEventValidators = new String[] { @@ -51,7 +54,10 @@ public interface ModelValidator X_AD_Table_ScriptValidator.EVENTMODELVALIDATOR_TableBeforeDelete, // TYPE_BEFORE_DELETE = 3 X_AD_Table_ScriptValidator.EVENTMODELVALIDATOR_TableAfterNew, // TYPE_AFTER_NEW = 4 X_AD_Table_ScriptValidator.EVENTMODELVALIDATOR_TableAfterChange, // TYPE_AFTER_CHANGE = 5 - X_AD_Table_ScriptValidator.EVENTMODELVALIDATOR_TableAfterDelete // TYPE_AFTER_DELETE = 6 + X_AD_Table_ScriptValidator.EVENTMODELVALIDATOR_TableAfterDelete, // TYPE_AFTER_DELETE = 6 + X_AD_Table_ScriptValidator.EVENTMODELVALIDATOR_TableAfterNewReplication, // TYPE_AFTER_NEW_REPLICATION = 7 + X_AD_Table_ScriptValidator.EVENTMODELVALIDATOR_TableAfterChangeReplication, // TYPE_AFTER_CHANGE_REPLICATION = 8 + X_AD_Table_ScriptValidator.EVENTMODELVALIDATOR_TableBeforeDeleteReplication // TYPE_BEFORE_DELETE_REPLICATION = 9 }; /** Called before document is prepared */ diff --git a/base/src/org/compiere/model/PO.java b/base/src/org/compiere/model/PO.java index 62bf027836..9ecd41e832 100644 --- a/base/src/org/compiere/model/PO.java +++ b/base/src/org/compiere/model/PO.java @@ -208,7 +208,9 @@ public abstract class PO /** Accounting Columns */ private ArrayList s_acctColumns = null; - + /** TODO - Trifon */ + private boolean m_isReplication = false; + /** Access Level S__ 100 4 System info */ public static final int ACCESSLEVEL_SYSTEM = 4; /** Access Level _C_ 010 2 Client info */ @@ -1977,7 +1979,12 @@ public abstract class PO // Call ModelValidators TYPE_AFTER_NEW/TYPE_AFTER_CHANGE - teo_sarca [ 1675490 ] if (success) { String errorMsg = ModelValidationEngine.get().fireModelChange - (this, newRecord ? ModelValidator.TYPE_AFTER_NEW : ModelValidator.TYPE_AFTER_CHANGE); + (this, newRecord ? + (isReplication() ? ModelValidator.TYPE_AFTER_NEW_REPLICATION : ModelValidator.TYPE_AFTER_NEW) + : + (isReplication() ? ModelValidator.TYPE_AFTER_CHANGE_REPLICATION : ModelValidator.TYPE_AFTER_CHANGE) + ); + setReplication(false); if (errorMsg != null) { log.saveError("Error", errorMsg); success = false; @@ -2031,6 +2038,12 @@ public abstract class PO return save(); } // save + public boolean saveReplica (boolean isFromReplication) + { + setReplication(isFromReplication); + return save(); + } + /** * Is there a Change to be saved? * @return true if record changed @@ -2184,7 +2197,7 @@ public abstract class PO // don't encrypt NULL sql.append(DB.TO_STRING(value.toString())); } else { - sql.append(encrypt(i,DB.TO_STRING(value.toString()))); + sql.append(encrypt(i,DB.TO_STRING(value.toString()))); } } @@ -2620,125 +2633,126 @@ public abstract class PO m_trxName = localTrxName; } - try + try + { + if (!beforeDelete()) { - if (!beforeDelete()) - { - log.warning("beforeDelete failed"); - return false; - } - } - catch (Exception e) - { - log.log(Level.WARNING, "beforeDelete", e); - log.saveError("Error", e.toString(), false); - // throw new DBException(e); - return false; - } - // Delete Restrict AD_Table_ID/Record_ID (Requests, ..) - String errorMsg = PO_Record.exists(AD_Table_ID, Record_ID, m_trxName); - if (errorMsg != null) - { - log.saveError("CannotDelete", errorMsg); - return false; - } - // Call ModelValidators TYPE_DELETE - errorMsg = ModelValidationEngine.get().fireModelChange - (this, ModelValidator.TYPE_DELETE); - if (errorMsg != null) - { - log.saveError("Error", errorMsg); + log.warning("beforeDelete failed"); return false; } + } + catch (Exception e) + { + log.log(Level.WARNING, "beforeDelete", e); + log.saveError("Error", e.toString(), false); + // throw new DBException(e); + return false; + } + // Delete Restrict AD_Table_ID/Record_ID (Requests, ..) + String errorMsg = PO_Record.exists(AD_Table_ID, Record_ID, m_trxName); + if (errorMsg != null) + { + log.saveError("CannotDelete", errorMsg); + return false; + } + // Call ModelValidators TYPE_DELETE + errorMsg = ModelValidationEngine.get().fireModelChange + (this, isReplication() ? ModelValidator.TYPE_BEFORE_DELETE_REPLICATION : ModelValidator.TYPE_DELETE); + setReplication(false); // @Trifon + if (errorMsg != null) + { + log.saveError("Error", errorMsg); + return false; + } - // - deleteTranslations(localTrxName); - // Delete Cascade AD_Table_ID/Record_ID (Attachments, ..) - PO_Record.deleteCascade(AD_Table_ID, Record_ID, localTrxName); - - // The Delete Statement - StringBuffer sql = new StringBuffer ("DELETE FROM ") //jz why no FROM?? - .append(p_info.getTableName()) - .append(" WHERE ") - .append(get_WhereClause(true)); - int no = DB.executeUpdate(sql.toString(), localTrxName); + // + deleteTranslations(localTrxName); + // Delete Cascade AD_Table_ID/Record_ID (Attachments, ..) + PO_Record.deleteCascade(AD_Table_ID, Record_ID, localTrxName); + + // The Delete Statement + StringBuffer sql = new StringBuffer ("DELETE FROM ") //jz why no FROM?? + .append(p_info.getTableName()) + .append(" WHERE ") + .append(get_WhereClause(true)); + int no = DB.executeUpdate(sql.toString(), localTrxName); success = no == 1; - - // Save ID - m_idOld = get_ID(); - // - if (!success) + + // Save ID + m_idOld = get_ID(); + // + if (!success) + { + log.warning("Not deleted"); + if (localTrx != null) + localTrx.rollback(); + } + else + { + if (success) { - log.warning("Not deleted"); - if (localTrx != null) - localTrx.rollback(); + // Change Log + MSession session = MSession.get (p_ctx, false); + if (session == null) + log.fine("No Session found"); + else if (m_IDs.length == 1) + { + int AD_ChangeLog_ID = 0; + int size = get_ColumnCount(); + for (int i = 0; i < size; i++) + { + Object value = m_oldValues[i]; + if (value != null + && !p_info.isEncrypted(i) // not encrypted + && !p_info.isVirtualColumn(i) // no virtual column + && !"Password".equals(p_info.getColumnName(i)) + ) + { + // change log on delete + MChangeLog cLog = session.changeLog ( + m_trxName != null ? m_trxName : localTrxName, AD_ChangeLog_ID, + AD_Table_ID, p_info.getColumn(i).AD_Column_ID, + Record_ID, getAD_Client_ID(), getAD_Org_ID(), value, null, MChangeLog.EVENTCHANGELOG_Delete); + if (cLog != null) + AD_ChangeLog_ID = cLog.getAD_ChangeLog_ID(); + } + } // for all fields + } + + // Housekeeping + m_IDs[0] = I_ZERO; + if (m_trxName == null) + log.fine("complete"); + else + log.fine("[" + m_trxName + "] - complete"); + m_attachment = null; } else { - if (success) - { - // Change Log - MSession session = MSession.get (p_ctx, false); - if (session == null) - log.fine("No Session found"); - else if (m_IDs.length == 1) - { - int AD_ChangeLog_ID = 0; - int size = get_ColumnCount(); - for (int i = 0; i < size; i++) - { - Object value = m_oldValues[i]; - if (value != null - && !p_info.isEncrypted(i) // not encrypted - && !p_info.isVirtualColumn(i) // no virtual column - && !"Password".equals(p_info.getColumnName(i)) - ) - { - // change log on delete - MChangeLog cLog = session.changeLog ( - m_trxName != null ? m_trxName : localTrxName, AD_ChangeLog_ID, - AD_Table_ID, p_info.getColumn(i).AD_Column_ID, - Record_ID, getAD_Client_ID(), getAD_Org_ID(), value, null, MChangeLog.EVENTCHANGELOG_Delete); - if (cLog != null) - AD_ChangeLog_ID = cLog.getAD_ChangeLog_ID(); - } - } // for all fields - } - - // Housekeeping - m_IDs[0] = I_ZERO; - if (m_trxName == null) - log.fine("complete"); - else - log.fine("[" + m_trxName + "] - complete"); - m_attachment = null; - } - else - { - log.warning("Not deleted"); - } + log.warning("Not deleted"); } - - try - { - success = afterDelete (success); - } - catch (Exception e) - { - log.log(Level.WARNING, "afterDelete", e); - log.saveError("Error", e.toString(), false); + } + + try + { + success = afterDelete (success); + } + catch (Exception e) + { + log.log(Level.WARNING, "afterDelete", e); + log.saveError("Error", e.toString(), false); + success = false; + // throw new DBException(e); + } + + // Call ModelValidators TYPE_AFTER_DELETE - teo_sarca [ 1675490 ] + if (success) { + errorMsg = ModelValidationEngine.get().fireModelChange(this, ModelValidator.TYPE_AFTER_DELETE); + if (errorMsg != null) { + log.saveError("Error", errorMsg); success = false; - // throw new DBException(e); - } - - // Call ModelValidators TYPE_AFTER_DELETE - teo_sarca [ 1675490 ] - if (success) { - errorMsg = ModelValidationEngine.get().fireModelChange(this, ModelValidator.TYPE_AFTER_DELETE); - if (errorMsg != null) { - log.saveError("Error", errorMsg); - success = false; - } } + } if (!success) { @@ -2758,15 +2772,15 @@ public abstract class PO } } - // Reset - if (success) - { - m_idOld = 0; - int size = p_info.getColumnCount(); - m_oldValues = new Object[size]; - m_newValues = new Object[size]; - CacheMgt.get().reset(p_info.getTableName()); - } + // Reset + if (success) + { + m_idOld = 0; + int size = p_info.getColumnCount(); + m_oldValues = new Object[size]; + m_newValues = new Object[size]; + CacheMgt.get().reset(p_info.getTableName()); + } } finally { @@ -3622,6 +3636,16 @@ public abstract class PO public void setDoc(Doc doc) { m_doc = doc; } + + public void setReplication(boolean isFromReplication) + { + m_isReplication = isFromReplication; + } + + public boolean isReplication() + { + return m_isReplication; + } /** * Set the accounting document associated to the PO - for use in POST ModelValidator diff --git a/base/src/org/compiere/print/layout/LayoutEngine.java b/base/src/org/compiere/print/layout/LayoutEngine.java index 000b56e895..a0d261e499 100644 --- a/base/src/org/compiere/print/layout/LayoutEngine.java +++ b/base/src/org/compiere/print/layout/LayoutEngine.java @@ -1569,11 +1569,7 @@ public class LayoutEngine implements Pageable, Printable, Doc Object dataElement = null; if (item.isPrinted()) // Text Columns { - if (item.isTypePrintFormat()) - { - log.warning("Unsupported: PrintFormat in Table: " + item); - } - else if (item.isTypeImage()) + if (item.isTypeImage()) { if (item.isImageField()) { @@ -1631,7 +1627,11 @@ public class LayoutEngine implements Pageable, Printable, Doc data[row][col] = element; } } - else + else if (item.isTypeText() ) + { + data[row][col] = item.getPrintName(format.getLanguage()); + } + else if (item.isTypeField()) { Object obj = null; if (item.getAD_Column_ID() > 0) // teo_sarca, [ 1673542 ] @@ -1651,6 +1651,10 @@ public class LayoutEngine implements Pageable, Printable, Doc // System.out.println(" row=" + row + ",col=" + col + " - " + item.getAD_Column_ID() + " => " + dataElement); data[row][col] = dataElement; } + else // item.isTypeBox() or isTypePrintFormat() + { + log.warning("Unsupported: " + (item.isTypeBox() ? "Box" : "PrintFormat") + " in Table: " + item); + } col++; } // printed } // for all columns diff --git a/base/src/org/compiere/process/Aging.java b/base/src/org/compiere/process/Aging.java index 7102b6d61b..1ee6eae56f 100644 --- a/base/src/org/compiere/process/Aging.java +++ b/base/src/org/compiere/process/Aging.java @@ -26,12 +26,16 @@ import org.compiere.util.*; * Invoice Aging Report. * Based on RV_Aging. * @author Jorg Janke + * @author victor.perez@e-evolution.com FR 1933937 Is necessary a new Aging to Date + * @see http://sourceforge.net/tracker/index.php?func=detail&aid=1933937&group_id=176962&atid=879335 * @version $Id: Aging.java,v 1.5 2006/10/07 00:58:44 jjanke Exp $ */ public class Aging extends SvrProcess { /** The date to calculate the days due from */ private Timestamp p_StatementDate = null; + //FR 1933937 + private boolean p_DateAcct = false; private boolean p_IsSOTrx = false; private int p_C_Currency_ID = 0; private int p_C_BP_Group_ID = 0; @@ -53,6 +57,8 @@ public class Aging extends SvrProcess ; else if (name.equals("StatementDate")) p_StatementDate = (Timestamp)para[i].getParameter(); + else if (name.equals("DateAcct")) + p_DateAcct = "Y".equals(para[i].getParameter()); else if (name.equals("IsSOTrx")) p_IsSOTrx = "Y".equals(para[i].getParameter()); else if (name.equals("C_Currency_ID")) @@ -84,28 +90,46 @@ public class Aging extends SvrProcess + ", C_Currency_ID=" + p_C_Currency_ID + ", C_BP_Group_ID=" + p_C_BP_Group_ID + ", C_BPartner_ID=" + p_C_BPartner_ID + ", IsListInvoices=" + p_IsListInvoices); - // + //FR 1933937 + String dateacct = DB.TO_DATE(p_StatementDate); + StringBuffer sql = new StringBuffer(); sql.append("SELECT bp.C_BP_Group_ID, oi.C_BPartner_ID,oi.C_Invoice_ID,oi.C_InvoicePaySchedule_ID, " + "oi.C_Currency_ID, oi.IsSOTrx, " // 5..6 + "oi.DateInvoiced, oi.NetDays,oi.DueDate,oi.DaysDue, "); // 7..10 if (p_C_Currency_ID == 0) - sql.append("oi.GrandTotal, oi.PaidAmt, oi.OpenAmt "); // 11..13 + if (!p_DateAcct)//FR 1933937 + sql.append("oi.GrandTotal, oi.PaidAmt, oi.OpenAmt "); // 11..13 + else + sql.append("oi.GrandTotal, invoicePaidToDate(oi.C_Invoice_ID, oi.C_Currency_ID, 1,"+dateacct+") AS PaidAmt, invoiceOpenToDate(oi.C_Invoice_ID,oi.C_InvoicePaySchedule_ID,"+dateacct+") AS OpenAmt "); // 11..13 else { String s = ",oi.C_Currency_ID," + p_C_Currency_ID + ",oi.DateAcct,oi.C_ConversionType_ID,oi.AD_Client_ID,oi.AD_Org_ID)"; - sql.append("currencyConvert(oi.GrandTotal").append(s) // 11.. - .append(", currencyConvert(oi.PaidAmt").append(s) + sql.append("currencyConvert(oi.GrandTotal").append(s); // 11.. + if (!p_DateAcct) + sql.append(", currencyConvert(oi.PaidAmt").append(s) .append(", currencyConvert(oi.OpenAmt").append(s); + else + sql.append(", currencyConvert(invoicePaidToDate(oi.C_Invoice_ID, oi.C_Currency_ID, 1,"+dateacct+")").append(s) + .append(", currencyConvert(invoiceOpenToDate(oi.C_Invoice_ID,oi.C_InvoicePaySchedule_ID,"+dateacct+")").append(s); + } - sql.append(",oi.C_Activity_ID,oi.C_Campaign_ID,oi.C_Project_ID " // 14 - + "FROM RV_OpenItem oi" - + " INNER JOIN C_BPartner bp ON (oi.C_BPartner_ID=bp.C_BPartner_ID) " + sql.append(",oi.C_Activity_ID,oi.C_Campaign_ID,oi.C_Project_ID "); // 14 + if (!p_DateAcct)//FR 1933937 + sql.append( "FROM RV_OpenItem oi"); + else + sql.append( "FROM RV_OpenItemToDate oi"); + + sql.append(" INNER JOIN C_BPartner bp ON (oi.C_BPartner_ID=bp.C_BPartner_ID) " + "WHERE oi.ISSoTrx=").append(p_IsSOTrx ? "'Y'" : "'N'"); if (p_C_BPartner_ID > 0) sql.append(" AND oi.C_BPartner_ID=").append(p_C_BPartner_ID); else if (p_C_BP_Group_ID > 0) sql.append(" AND bp.C_BP_Group_ID=").append(p_C_BP_Group_ID); + + if (p_DateAcct)//FR 1933937 + sql.append("AND invoiceOpenToDate(oi.C_Invoice_ID,oi.C_InvoicePaySchedule_ID,"+dateacct+") <> 0 "); + sql.append(" ORDER BY oi.C_BPartner_ID, oi.C_Currency_ID, oi.C_Invoice_ID"); log.finest(sql.toString()); @@ -174,6 +198,7 @@ public class Aging extends SvrProcess aging.setC_Activity_ID(C_Activity_ID); aging.setC_Campaign_ID(C_Campaign_ID); aging.setC_Project_ID(C_Project_ID); + aging.setDateAcct(p_DateAcct); } // Fill Buckets aging.add (DueDate, DaysDue, GrandTotal, OpenAmt); diff --git a/base/src/org/compiere/process/DocumentEngine.java b/base/src/org/compiere/process/DocumentEngine.java index c7d42e827b..8bf859e1c9 100644 --- a/base/src/org/compiere/process/DocumentEngine.java +++ b/base/src/org/compiere/process/DocumentEngine.java @@ -33,6 +33,7 @@ import org.compiere.interfaces.Server; import org.compiere.interfaces.ServerHome; import org.compiere.model.MAllocationHdr; import org.compiere.model.MBankStatement; +import org.compiere.model.MCash; import org.compiere.model.MClient; import org.compiere.model.MInOut; import org.compiere.model.MInventory; @@ -53,6 +54,7 @@ import org.compiere.util.Ini; * * @author Jorg Janke * @author Karsten Thiemann FR [ 1782412 ] + * @author victor.perez@e-evolution.com www.e-evolution.com FR [ 1866214 ] http://sourceforge.net/tracker/index.php?func=detail&aid=1866214&group_id=176962&atid=879335 * @version $Id: DocumentEngine.java,v 1.2 2006/07/30 00:54:44 jjanke Exp $ */ public class DocumentEngine implements DocAction @@ -1009,6 +1011,18 @@ public class DocumentEngine implements DocAction options[index++] = DocumentEngine.ACTION_Reverse_Correct; } } + //[ 1782412 ] + /******************** + * Cash + */ + else if (AD_Table_ID == MCash.Table_ID) + { + // Complete .. CO + if (docStatus.equals(DocumentEngine.STATUS_Completed)) + { + options[index++] = DocumentEngine.ACTION_Void; + } + } /******************** * Bank Statement */ diff --git a/base/src/org/compiere/process/M_Product_BOM_Check.java b/base/src/org/compiere/process/M_Product_BOM_Check.java index ac7cf671a9..5bd2853144 100644 --- a/base/src/org/compiere/process/M_Product_BOM_Check.java +++ b/base/src/org/compiere/process/M_Product_BOM_Check.java @@ -131,7 +131,8 @@ public class M_Product_BOM_Check extends SvrProcess // Insert BOM Nodes into "All" table sql1 = new StringBuffer("INSERT INTO T_Selection2 (AD_PInstance_ID, Query_ID, T_Selection_ID) " + "SELECT " + m_AD_PInstance_ID + ", 0, p.M_Product_ID FROM M_Product p WHERE IsBOM='Y' AND EXISTS " - + "(SELECT * FROM M_Product_BOM b WHERE p.M_Product_ID=b.M_ProductBOM_ID AND b.M_Product_ID IN " + //+ "(SELECT * FROM M_Product_BOM b WHERE p.M_Product_ID=b.M_ProductBOM_ID AND b.M_Product_ID IN " + + "(SELECT * FROM PP_Product_BOM b WHERE p.M_Product_ID=b.M_Product_ID AND b.M_Product_ID IN " + "(SELECT T_Selection_ID FROM T_Selection WHERE AD_PInstance_ID="+ m_AD_PInstance_ID + "))"); no = DB.executeUpdate(sql1.toString(), get_TrxName()); if (no == -1) raiseError("InsertingRoot:ERROR", sql1.toString()); @@ -141,7 +142,8 @@ public class M_Product_BOM_Check extends SvrProcess if (no == -1) raiseError("InsertingRoot:ERROR", sql1.toString()); sql1 = new StringBuffer("INSERT INTO T_Selection2 (AD_PInstance_ID, Query_ID, T_Selection_ID) " + "SELECT " + m_AD_PInstance_ID + ", 1, p.M_Product_ID FROM M_Product p WHERE IsBOM='Y' AND EXISTS " - + "(SELECT * FROM M_Product_BOM b WHERE p.M_Product_ID=b.M_ProductBOM_ID AND b.M_Product_ID IN " + //+ "(SELECT * FROM M_Product_BOM b WHERE p.M_Product_ID=b.M_ProductBOM_ID AND b.M_Product_ID IN " + + "(SELECT * FROM PP_Product_BOM b WHERE p.M_Product_ID=b.M_Product_ID AND b.M_Product_ID IN " + "(SELECT T_Selection_ID FROM T_Selection WHERE AD_PInstance_ID="+ m_AD_PInstance_ID + "))"); no = DB.executeUpdate(sql1.toString(), get_TrxName()); if (no == -1) raiseError("InsertingRoot:ERROR", sql1.toString()); diff --git a/base/src/org/compiere/process/OrderBatchProcess.java b/base/src/org/compiere/process/OrderBatchProcess.java index fee4ed4256..dac01bec0e 100644 --- a/base/src/org/compiere/process/OrderBatchProcess.java +++ b/base/src/org/compiere/process/OrderBatchProcess.java @@ -12,7 +12,8 @@ * 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 * + * or via info@compiere.org or http://www.compiere.org/license.html * + * @contributor Karsten Thiemann / Schaeffer AG - kthiemann@adempiere.org * *****************************************************************************/ package org.compiere.process; @@ -37,6 +38,8 @@ public class OrderBatchProcess extends SvrProcess private Timestamp p_DateOrdered_From = null; private Timestamp p_DateOrdered_To = null; private String p_DocAction = null; + private String p_IsDelivered = null; + private String p_IsInvoiced = null; /** * Prepare @@ -64,6 +67,11 @@ public class OrderBatchProcess extends SvrProcess } else if (name.equals("DocAction")) p_DocAction = (String)para[i].getParameter(); + else if (name.equals("IsDelivered")) { + p_IsDelivered = (String)para[i].getParameter(); + } else if (name.equals("IsInvoiced")) { + p_IsInvoiced = (String)para[i].getParameter(); + } else log.log(Level.SEVERE, "Unknown Parameter: " + name); } @@ -79,7 +87,8 @@ public class OrderBatchProcess extends SvrProcess log.info("C_DocTypeTarget_ID=" + p_C_DocTypeTarget_ID + ", DocStatus=" + p_DocStatus + ", IsSelfService=" + p_IsSelfService + ", C_BPartner_ID=" + p_C_BPartner_ID + ", DateOrdered=" + p_DateOrdered_From + "->" + p_DateOrdered_To - + ", DocAction=" + p_DocAction); + + ", DocAction=" + p_DocAction + ", IsDelivered=" + p_IsDelivered + + ", IsInvoiced=" + p_IsInvoiced); if (p_C_DocTypeTarget_ID == 0) throw new AdempiereUserError("@NotFound@: @C_DocTypeTarget_ID@"); @@ -89,16 +98,28 @@ public class OrderBatchProcess extends SvrProcess throw new AdempiereUserError("@NotFound@: @DocAction@"); // - StringBuffer sql = new StringBuffer("SELECT * FROM C_Order " - + "WHERE C_DocTypeTarget_ID=? AND DocStatus=?"); + StringBuffer sql = new StringBuffer("SELECT * FROM C_Order o " + + " WHERE o.C_DocTypeTarget_ID=? AND o.DocStatus=? "); if (p_IsSelfService != null && p_IsSelfService.length() == 1) - sql.append(" AND IsSelfService='").append(p_IsSelfService).append("'"); + sql.append(" AND o.IsSelfService='").append(p_IsSelfService).append("'"); if (p_C_BPartner_ID != 0) - sql.append(" AND C_BPartner_ID=").append(p_C_BPartner_ID); + sql.append(" AND o.C_BPartner_ID=").append(p_C_BPartner_ID); if (p_DateOrdered_From != null) - sql.append(" AND TRUNC(DateOrdered) >= ").append(DB.TO_DATE(p_DateOrdered_From, true)); + sql.append(" AND TRUNC(o.DateOrdered) >= ").append(DB.TO_DATE(p_DateOrdered_From, true)); if (p_DateOrdered_To != null) - sql.append(" AND TRUNC(DateOrdered) <= ").append(DB.TO_DATE(p_DateOrdered_To, true)); + sql.append(" AND TRUNC(o.DateOrdered) <= ").append(DB.TO_DATE(p_DateOrdered_To, true)); + if ("Y".equals(p_IsDelivered)) + sql.append(" AND NOT EXISTS (SELECT l.C_OrderLine_ID FROM C_OrderLine l ") + .append(" WHERE l.C_Order_ID=o.C_Order_ID AND l.QtyOrdered>l.QtyDelivered) "); + else if ("N".equals(p_IsDelivered)) + sql.append(" AND EXISTS (SELECT l.C_OrderLine_ID FROM C_OrderLine l ") + .append(" WHERE l.C_Order_ID=o.C_Order_ID AND l.QtyOrdered>l.QtyDelivered) "); + if ("Y".equals(p_IsInvoiced)) + sql.append(" AND NOT EXISTS (SELECT l.C_OrderLine_ID FROM C_OrderLine l ") + .append(" WHERE l.C_Order_ID=o.C_Order_ID AND l.QtyOrdered>l.QtyInvoiced) "); + else if ("N".equals(p_IsInvoiced)) + sql.append(" AND EXISTS (SELECT l.C_OrderLine_ID FROM C_OrderLine l ") + .append(" WHERE l.C_Order_ID=o.C_Order_ID AND l.QtyOrdered>l.QtyInvoiced) "); int counter = 0; int errCounter = 0; diff --git a/base/src/org/compiere/process/OrderOpen.java b/base/src/org/compiere/process/OrderOpen.java index 3abd24fbd3..67627a74e2 100644 --- a/base/src/org/compiere/process/OrderOpen.java +++ b/base/src/org/compiere/process/OrderOpen.java @@ -18,6 +18,7 @@ package org.compiere.process; import java.util.logging.*; import org.compiere.model.*; +import org.compiere.util.AdempiereSystemError; /** * Re-Open Order Process (from Closed to Completed) @@ -53,20 +54,20 @@ public class OrderOpen extends SvrProcess * @return Message * @throws Exception if not successful */ - protected String doIt() throws Exception + protected String doIt() throws AdempiereSystemError { log.info("doIt - Open C_Order_ID=" + p_C_Order_ID); if (p_C_Order_ID == 0) - throw new IllegalArgumentException("C_Order_ID == 0"); + return ""; // MOrder order = new MOrder (getCtx(), p_C_Order_ID, get_TrxName()); - if (MOrder.DOCSTATUS_Closed.equals(order.getDocStatus())) + String msg = order.reopenIt(); + if ( msg.length() != 0 ) { - order.setDocStatus(MOrder.DOCSTATUS_Completed); - return order.save() ? "@OK@" : "@Error@"; + throw new AdempiereSystemError(msg); } - else - throw new IllegalStateException("Order is not closed"); + + return order.save() ? "@OK@" : "@Error@"; } // doIt } // OrderOpen diff --git a/base/src/org/compiere/process/OrderPOCreate.java b/base/src/org/compiere/process/OrderPOCreate.java index f355fa64ea..8ce6489fff 100644 --- a/base/src/org/compiere/process/OrderPOCreate.java +++ b/base/src/org/compiere/process/OrderPOCreate.java @@ -96,8 +96,8 @@ public class OrderPOCreate extends SvrProcess String sql = "SELECT * FROM C_Order o " + "WHERE o.IsSOTrx='Y'" // No Duplicates - // " AND o.Ref_Order_ID IS NULL" - + " AND NOT EXISTS (SELECT * FROM C_OrderLine ol WHERE o.C_Order_ID=ol.C_Order_ID AND ol.Ref_OrderLine_ID IS NOT NULL)" + // " AND o.Link_Order_ID IS NULL" + + " AND NOT EXISTS (SELECT * FROM C_OrderLine ol WHERE o.C_Order_ID=ol.C_Order_ID AND ol.Link_OrderLine_ID IS NOT NULL)" ; if (p_C_Order_ID != 0) sql += " AND o.C_Order_ID=?"; @@ -213,7 +213,7 @@ public class OrderPOCreate extends SvrProcess if (soLines[i].getM_Product_ID() == M_Product_ID) { MOrderLine poLine = new MOrderLine (po); - poLine.setRef_OrderLine_ID(soLines[i].getC_OrderLine_ID()); + poLine.setLink_OrderLine_ID(soLines[i].getC_OrderLine_ID()); poLine.setM_Product_ID(soLines[i].getM_Product_ID()); poLine.setM_AttributeSetInstance_ID(soLines[i].getM_AttributeSetInstance_ID()); poLine.setC_UOM_ID(soLines[i].getC_UOM_ID()); @@ -223,6 +223,9 @@ public class OrderPOCreate extends SvrProcess poLine.setDatePromised(soLines[i].getDatePromised()); poLine.setPrice(); poLine.save(); + + soLines[i].setLink_OrderLine_ID(poLine.getC_OrderLine_ID()); + soLines[i].save(); } } } @@ -239,7 +242,7 @@ public class OrderPOCreate extends SvrProcess // Set Reference to PO if (counter == 1 && po != null) { - so.setRef_Order_ID(po.getC_Order_ID()); + so.setLink_Order_ID(po.getC_Order_ID()); so.save(); } return counter; @@ -254,7 +257,7 @@ public class OrderPOCreate extends SvrProcess { MOrder po = new MOrder (getCtx(), 0, get_TrxName()); po.setClientOrg(so.getAD_Client_ID(), so.getAD_Org_ID()); - po.setRef_Order_ID(so.getC_Order_ID()); + po.setLink_Order_ID(so.getC_Order_ID()); po.setIsSOTrx(false); po.setC_DocTypeTarget_ID(); // diff --git a/base/src/org/compiere/process/ReplenishReport.java b/base/src/org/compiere/process/ReplenishReport.java index 93ef3bd2c8..3388aa2d1a 100644 --- a/base/src/org/compiere/process/ReplenishReport.java +++ b/base/src/org/compiere/process/ReplenishReport.java @@ -22,6 +22,7 @@ import java.util.*; import java.math.*; import org.compiere.model.*; +import org.eevolution.model.*; import java.util.logging.*; import org.compiere.util.*; @@ -105,6 +106,8 @@ public class ReplenishReport extends SvrProcess createRequisition(); else if (p_ReplenishmentCreate.equals("MMM")) createMovements(); + else if (p_ReplenishmentCreate.equals("DOO")) + createDO(); return m_info; } // doIt @@ -546,7 +549,154 @@ public class ReplenishReport extends SvrProcess m_info = "#" + noMoves + info; log.info(m_info); } - } // createRequisition + } // Create Inventory Movements + + /** + * Create Distribution Order + */ + private void createDO() throws Exception + { + int noMoves = 0; + String info = ""; + // + MClient client = null; + MDDOrder order = null; + int M_Warehouse_ID = 0; + int M_WarehouseSource_ID = 0; + MWarehouse whSource = null; + MWarehouse wh = null; + X_T_Replenish[] replenishs = getReplenishDO("M_WarehouseSource_ID IS NOT NULL"); + for (X_T_Replenish replenish:replenishs) + { + if (whSource == null || whSource.getM_WarehouseSource_ID() != replenish.getM_WarehouseSource_ID()) + whSource = MWarehouse.get(getCtx(), replenish.getM_WarehouseSource_ID()); + if (wh == null || wh.getM_Warehouse_ID() != replenish.getM_Warehouse_ID()) + wh = MWarehouse.get(getCtx(), replenish.getM_Warehouse_ID()); + if (client == null || client.getAD_Client_ID() != whSource.getAD_Client_ID()) + client = MClient.get(getCtx(), whSource.getAD_Client_ID()); + // + if (order == null + || M_WarehouseSource_ID != replenish.getM_WarehouseSource_ID() + || M_Warehouse_ID != replenish.getM_Warehouse_ID()) + { + M_WarehouseSource_ID = replenish.getM_WarehouseSource_ID(); + M_Warehouse_ID = replenish.getM_Warehouse_ID(); + + order = new MDDOrder (getCtx(), 0, get_TrxName()); + order.setC_DocType_ID(p_C_DocType_ID); + order.setDescription(Msg.getMsg(getCtx(), "Replenishment") + + ": " + whSource.getName() + "->" + wh.getName()); + // Set Org + order.setAD_Org_ID(whSource.getAD_Org_ID()); + // Set Org Trx + MOrg orgTrx = MOrg.get(getCtx(), wh.getAD_Org_ID()); + order.setAD_OrgTrx_ID(orgTrx.getAD_Org_ID()); + int C_BPartner_ID = orgTrx.getLinkedC_BPartner_ID(get_TrxName()); + if (C_BPartner_ID==0) + throw new AdempiereUserError(Msg.translate(getCtx(), "C_BPartner_ID")+ " @FillMandatory@ "); + MBPartner bp = new MBPartner(getCtx(),C_BPartner_ID,get_TrxName()); + // Set BPartner Link to Org + order.setBPartner(bp); + order.setDateOrdered(new Timestamp(System.currentTimeMillis())); + //order.setDatePromised(DatePromised); + order.setDeliveryRule(MDDOrder.DELIVERYRULE_Availability); + order.setDeliveryViaRule(MDDOrder.DELIVERYVIARULE_Delivery); + order.setPriorityRule(MDDOrder.PRIORITYRULE_Medium); + order.setIsInDispute(false); + order.setIsApproved(false); + order.setIsDropShip(false); + order.setIsDelivered(false); + order.setIsInTransit(false); + order.setIsPrinted(false); + order.setIsSelected(false); + order.setIsSOTrx(false); + // Warehouse in Transit + MWarehouse[] whsInTransit = MWarehouse.getForOrg(getCtx(), whSource.getAD_Org_ID()); + for (MWarehouse whInTransit:whsInTransit) + { + if(whInTransit.isInTransit()) + order.setM_Warehouse_ID(whInTransit.getM_Warehouse_ID()); + } + if (order.getM_Warehouse_ID()==0) + throw new AdempiereUserError("Warehouse inTransit is @FillMandatory@ "); + + if (!order.save()) + return; + log.fine(order.toString()); + noMoves++; + info += " - " + order.getDocumentNo(); + } + + // To + int M_LocatorTo_ID = wh.getDefaultLocator().getM_Locator_ID(); + int M_Locator_ID = whSource.getDefaultLocator().getM_Locator_ID(); + if(M_LocatorTo_ID == 0 || M_Locator_ID==0) + throw new AdempiereUserError(Msg.translate(getCtx(), "M_Locator_ID")+" @FillMandatory@ "); + + // From: Look-up Storage + /*MProduct product = MProduct.get(getCtx(), replenish.getM_Product_ID()); + MProductCategory pc = MProductCategory.get(getCtx(), product.getM_Product_Category_ID()); + String MMPolicy = pc.getMMPolicy(); + if (MMPolicy == null || MMPolicy.length() == 0) + MMPolicy = client.getMMPolicy(); + // + MStorage[] storages = MStorage.getWarehouse(getCtx(), + whSource.getM_Warehouse_ID(), replenish.getM_Product_ID(), 0, 0, + true, null, + MClient.MMPOLICY_FiFo.equals(MMPolicy), get_TrxName()); + + + BigDecimal target = replenish.getQtyToOrder(); + for (int j = 0; j < storages.length; j++) + { + MStorage storage = storages[j]; + if (storage.getQtyOnHand().signum() <= 0) + continue; + BigDecimal moveQty = target; + if (storage.getQtyOnHand().compareTo(moveQty) < 0) + moveQty = storage.getQtyOnHand(); + // + MDDOrderLine line = new MDDOrderLine(order); + line.setM_Product_ID(replenish.getM_Product_ID()); + line.setQtyEntered(moveQty); + if (replenish.getQtyToOrder().compareTo(moveQty) != 0) + line.setDescription("Total: " + replenish.getQtyToOrder()); + line.setM_Locator_ID(storage.getM_Locator_ID()); // from + line.setM_AttributeSetInstance_ID(storage.getM_AttributeSetInstance_ID()); + line.setM_LocatorTo_ID(M_LocatorTo_ID); // to + line.setM_AttributeSetInstanceTo_ID(storage.getM_AttributeSetInstance_ID()); + line.setIsInvoiced(false); + line.save(); + // + target = target.subtract(moveQty); + if (target.signum() == 0) + break; + }*/ + + MDDOrderLine line = new MDDOrderLine(order); + line.setM_Product_ID(replenish.getM_Product_ID()); + line.setQty(replenish.getQtyToOrder()); + if (replenish.getQtyToOrder().compareTo(replenish.getQtyToOrder()) != 0) + line.setDescription("Total: " + replenish.getQtyToOrder()); + line.setM_Locator_ID(M_Locator_ID); // from + line.setM_AttributeSetInstance_ID(0); + line.setM_LocatorTo_ID(M_LocatorTo_ID); // to + line.setM_AttributeSetInstanceTo_ID(0); + line.setIsInvoiced(false); + line.save(); + + } + if (replenishs.length == 0) + { + m_info = "No Source Warehouse"; + log.warning(m_info); + } + else + { + m_info = "#" + noMoves + info; + log.info(m_info); + } + } // create Distribution Order /** * Get Replenish Records @@ -591,4 +741,47 @@ public class ReplenishReport extends SvrProcess return retValue; } // getReplenish + /** + * Get Replenish Records + * @return replenish + */ + private X_T_Replenish[] getReplenishDO (String where) + { + String sql = "SELECT * FROM T_Replenish " + + "WHERE AD_PInstance_ID=? "; + if (where != null && where.length() > 0) + sql += " AND " + where; + sql += " ORDER BY M_Warehouse_ID, M_WarehouseSource_ID, C_BPartner_ID"; + ArrayList list = new ArrayList(); + PreparedStatement pstmt = null; + try + { + pstmt = DB.prepareStatement (sql, get_TrxName()); + pstmt.setInt (1, getAD_PInstance_ID()); + ResultSet rs = pstmt.executeQuery (); + while (rs.next ()) + list.add (new X_T_Replenish (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; + } + X_T_Replenish[] retValue = new X_T_Replenish[list.size ()]; + list.toArray (retValue); + return retValue; + } // getReplenish + } // Replenish diff --git a/client/src/org/compiere/apps/AEnv.java b/client/src/org/compiere/apps/AEnv.java index 2abeb3ea49..0eda330bb3 100644 --- a/client/src/org/compiere/apps/AEnv.java +++ b/client/src/org/compiere/apps/AEnv.java @@ -24,6 +24,8 @@ import java.sql.*; import java.util.*; import java.util.logging.*; import javax.swing.*; + +import org.compiere.apps.form.FormFrame; import org.compiere.db.*; import org.compiere.grid.ed.Calculator; import org.compiere.interfaces.*; @@ -37,7 +39,10 @@ import org.compiere.util.*; * @author Jorg Janke * @version $Id: AEnv.java,v 1.2 2006/07/30 00:51:27 jjanke Exp $ * - * Colin Rooney (croo) & kstan_79 RFE#1670185 + * @author Colin Rooney (croo) & kstan_79 RFE#1670185 + * @author victor.perez@e-evolution.com + * @see FR [ 1966328 ] New Window Info to MRP and CRP into View http://sourceforge.net/tracker/index.php?func=detail&aid=1966328&group_id=176962&atid=879335 + * */ public final class AEnv { @@ -365,6 +370,23 @@ public final class AEnv { new org.compiere.apps.search.InfoSchedule (Env.getFrame(c), null, false); } + //FR [ 1966328 ] + else if (actionCommand.equals("InfoMRP") && AEnv.canAccessInfo("MRP")) + { + CFrame frame = (CFrame) Env.getFrame(c); + int m_menu_id = MMenu.getMenu_ID("MRP Info"); + AMenu menu = AEnv.getAMenu(frame); + AMenuStartItem form = new AMenuStartItem (m_menu_id, true, Msg.translate(Env.getCtx(), "MRP Info"), menu); // async load + form.start(); + } + else if (actionCommand.equals("InfoCRP") && AEnv.canAccessInfo("CRP")) + { + CFrame frame = (CFrame) Env.getFrame(c); + int m_menu_id = MMenu.getMenu_ID("CRP Info"); + AMenu menu = AEnv.getAMenu(frame); + AMenuStartItem form = new AMenuStartItem (m_menu_id, true, Msg.translate(Env.getCtx(), "CRP Info"), menu); // async load + form.start(); + } else if (actionCommand.equals("InfoOrder") && AEnv.canAccessInfo("ORDER")) { org.compiere.apps.search.Info.showOrder (Env.getFrame(c), WindowNo, ""); @@ -389,6 +411,7 @@ public final class AEnv { org.compiere.apps.search.Info.showAssignment (Env.getFrame(c), WindowNo, ""); } + // Go Menu ------------------------ else if (actionCommand.equals("WorkFlow")) @@ -609,6 +632,21 @@ public final class AEnv ((AMenu)top).getWindowManager().add(frame); } } + + /** + * FR [ 1966328 ] + * get AMenu + * @param frame + */ + public static AMenu getAMenu(CFrame frame) + { + JFrame top = Env.getWindow(0); + if (top instanceof AMenu) + { + return (AMenu)top; + } + return null; + } /** * Exit System * @param status System exit status (usually 0 for no error) diff --git a/client/src/org/compiere/apps/AMenu.java b/client/src/org/compiere/apps/AMenu.java index 5a8c5d227b..71ee78c2fe 100644 --- a/client/src/org/compiere/apps/AMenu.java +++ b/client/src/org/compiere/apps/AMenu.java @@ -79,7 +79,10 @@ import org.compiere.util.Splash; * @author Jorg Janke * @version $Id: AMenu.java,v 1.2 2006/07/30 00:51:27 jjanke Exp $ * - * Colin Rooney (croo) RFE#1670185 restrict access to info queries + * @author Colin Rooney (croo) RFE#1670185 restrict access to info queries + * @author victor.perez@e-evolution.com + * @see FR [ 1966328 ] New Window Info to MRP and CRP into View http://sourceforge.net/tracker/index.php?func=detail&aid=1966328&group_id=176962&atid=879335 + * */ public final class AMenu extends CFrame implements ActionListener, PropertyChangeListener, ChangeListener @@ -418,6 +421,15 @@ public final class AMenu extends CFrame { AEnv.addMenuItem("InfoSchedule", null, null, mView, this); } + //FR [ 1966328 ] + if (MRole.getDefault().isAllow_Info_MRP()) + { + AEnv.addMenuItem("InfoMRP", "Info", null, mView, this); + } + if (MRole.getDefault().isAllow_Info_CRP()) + { + AEnv.addMenuItem("InfoCRP", "Info", null, mView, this); + } mView.addSeparator(); if (MRole.getDefault().isAllow_Info_Order()) { diff --git a/client/src/org/compiere/apps/APanel.java b/client/src/org/compiere/apps/APanel.java index 7008f22582..1197488627 100644 --- a/client/src/org/compiere/apps/APanel.java +++ b/client/src/org/compiere/apps/APanel.java @@ -54,6 +54,9 @@ import org.compiere.util.*; * @author Teo Sarca, SC ARHIPAC SERVICE SRL *
  • BF [ 1824621 ] History button can't be canceled *
  • BF [ 1941271 ] VTreePanel is modifying even if is save wasn't successfull + * @author victor.perez@e-evolution.com + * @see FR [ 1966328 ] New Window Info to MRP and CRP into View http://sourceforge.net/tracker/index.php?func=detail&aid=1966328&group_id=176962&atid=879335 + * */ public final class APanel extends CPanel implements DataStatusListener, ChangeListener, ActionListener, ASyncProcess @@ -282,6 +285,15 @@ public final class APanel extends CPanel { AEnv.addMenuItem("InfoSchedule", null, null, mView, this); } + //FR [ 1966328 ] + if (MRole.getDefault().isAllow_Info_MRP()) + { + AEnv.addMenuItem("InfoMRP", "Info", null, mView, this); + } + if (MRole.getDefault().isAllow_Info_CRP()) + { + AEnv.addMenuItem("InfoCRP", "Info", null, mView, this); + } mView.addSeparator(); if (MRole.getDefault().isAllow_Info_Order()) { @@ -312,6 +324,8 @@ public final class APanel extends CPanel AEnv.addMenuItem("InfoAsset", "Info", null, mView, this); } + + mView.addSeparator(); aAttachment = addAction("Attachment", mView, KeyStroke.getKeyStroke(KeyEvent.VK_F7, 0), true); // toggle aChat = addAction("Chat", mView, null, true); // toggle diff --git a/client/src/org/compiere/apps/AStart.java b/client/src/org/compiere/apps/AStart.java index 332c5d9e92..4bb16df8d9 100644 --- a/client/src/org/compiere/apps/AStart.java +++ b/client/src/org/compiere/apps/AStart.java @@ -105,6 +105,10 @@ public final class AStart extends JApplet return null; } + public void setStandAlone(boolean ok) + { + isStandalone=ok; + } /** * Main method */ diff --git a/client/src/org/compiere/apps/form/FormFrame.java b/client/src/org/compiere/apps/form/FormFrame.java index b0da153f43..9572b36aee 100644 --- a/client/src/org/compiere/apps/form/FormFrame.java +++ b/client/src/org/compiere/apps/form/FormFrame.java @@ -434,5 +434,12 @@ public class FormFrame extends CFrame { return p_AD_Form_ID; } // getAD_Window_ID + /** + * @return Returns the manuBar + */ + public JMenuBar getMenu() + { + return menuBar; + } } // FormFrame diff --git a/client/src/org/compiere/apps/form/VAllocation.java b/client/src/org/compiere/apps/form/VAllocation.java index 04b50af7d0..7ef3d455c6 100644 --- a/client/src/org/compiere/apps/form/VAllocation.java +++ b/client/src/org/compiere/apps/form/VAllocation.java @@ -98,7 +98,7 @@ public class VAllocation extends CPanel // private int i_open = 6; private int i_discount = 7; - private int i_writeOff = 8; + private int i_writeOff = 8; private int i_overUnder = 9; private int i_applied = 10; // private int i_multiplier = 10; @@ -135,8 +135,11 @@ public class VAllocation extends CPanel private JLabel dateLabel = new JLabel(); private VDate dateField = new VDate(); private JCheckBox autoWriteOff = new JCheckBox(); + private int m_AD_Org_ID = 0; + private JLabel organizationLabel = new JLabel(); + private VLookup organizationPick = null; - private ArrayList m_bpartnerCheck = new ArrayList(); + private ArrayList m_bpartnerCheck = new ArrayList(); /** * Static Init @@ -148,6 +151,7 @@ public class VAllocation extends CPanel // mainPanel.setLayout(mainLayout); dateLabel.setText(Msg.getMsg(Env.getCtx(), "Date")); + dateLabel.setToolTipText(Msg.getMsg(Env.getCtx(), "AllocDate", false)); autoWriteOff.setSelected(false); autoWriteOff.setText(Msg.getMsg(Env.getCtx(), "AutoWriteOff", true)); autoWriteOff.setToolTipText(Msg.getMsg(Env.getCtx(), "AutoWriteOff", false)); @@ -182,6 +186,14 @@ public class VAllocation extends CPanel invoiceScrollPane.setPreferredSize(new Dimension(200, 200)); paymentScrollPane.setPreferredSize(new Dimension(200, 200)); mainPanel.add(parameterPanel, BorderLayout.NORTH); + + //org filter + organizationLabel.setText(Msg.translate(Env.getCtx(), "AD_Org_ID")); + parameterPanel.add(organizationLabel, new GridBagConstraints(4, 0, 1, 1, 0.0, 0.0 + ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5,5,5,5), 0, 0)); + parameterPanel.add(organizationPick, new GridBagConstraints(5, 0, 1, 1, 0.0, 0.0 + ,GridBagConstraints.WEST, GridBagConstraints.NONE, new Insets(5,5,5,5), 0, 0)); + parameterPanel.add(bpartnerLabel, new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0 ,GridBagConstraints.EAST, GridBagConstraints.NONE, new Insets(5, 5, 5, 5), 0, 0)); parameterPanel.add(bpartnerSearch, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0 @@ -251,6 +263,15 @@ public class VAllocation extends CPanel currencyPick.setValue(new Integer(m_C_Currency_ID)); currencyPick.addVetoableChangeListener(this); + // Organization filter selection + AD_Column_ID = 839; //C_Period.AD_Org_ID (needed to allow org 0) + MLookup lookupOrg = MLookupFactory.get(Env.getCtx(), m_WindowNo, 0, AD_Column_ID, DisplayType.TableDir); + organizationPick = new VLookup("AD_Org_ID", true, false, true, lookupOrg); + organizationPick.setValue(Env.getAD_Org_ID(Env.getCtx())); + organizationPick.addVetoableChangeListener(this); + + m_AD_Org_ID = Env.getAD_Org_ID(Env.getCtx()); + // BPartner AD_Column_ID = 3499; // C_Invoice.C_BPartner_ID MLookup lookupBP = MLookupFactory.get (Env.getCtx(), m_WindowNo, 0, AD_Column_ID, DisplayType.Search); @@ -301,26 +322,34 @@ public class VAllocation extends CPanel Vector> data = new Vector>(); StringBuffer sql = new StringBuffer("SELECT p.DateTrx,p.DocumentNo,p.C_Payment_ID," // 1..3 + "c.ISO_Code,p.PayAmt," // 4..5 - + "currencyConvert(p.PayAmt,p.C_Currency_ID,?,p.DateTrx,p.C_ConversionType_ID,p.AD_Client_ID,p.AD_Org_ID),"// 6 #1 - + "currencyConvert(paymentAvailable(C_Payment_ID),p.C_Currency_ID,?,p.DateTrx,p.C_ConversionType_ID,p.AD_Client_ID,p.AD_Org_ID)," // 7 #2 + + "currencyConvert(p.PayAmt,p.C_Currency_ID,?,?,p.C_ConversionType_ID,p.AD_Client_ID,p.AD_Org_ID),"// 6 #1, #2 + + "currencyConvert(paymentAvailable(C_Payment_ID),p.C_Currency_ID,?,?,p.C_ConversionType_ID,p.AD_Client_ID,p.AD_Org_ID)," // 7 #3, #4 + "p.MultiplierAP " + "FROM C_Payment_v p" // Corrected for AP/AR + " INNER JOIN C_Currency c ON (p.C_Currency_ID=c.C_Currency_ID) " + "WHERE p.IsAllocated='N' AND p.Processed='Y'" + " AND p.C_Charge_ID IS NULL" // Prepayments OK - + " AND p.C_BPartner_ID=?"); // #3 + + " AND p.C_BPartner_ID=?"); // #5 if (!multiCurrency.isSelected()) - sql.append(" AND p.C_Currency_ID=?"); // #4 + sql.append(" AND p.C_Currency_ID=?"); // #6 + if (m_AD_Org_ID != 0 ) + sql.append(" AND p.AD_Org_ID=" + m_AD_Org_ID); sql.append(" ORDER BY p.DateTrx,p.DocumentNo"); + + // role security + sql = new StringBuffer( MRole.getDefault(Env.getCtx(), false).addAccessSQL( sql.toString(), "p", MRole.SQL_FULLYQUALIFIED, MRole.SQL_RO ) ); + log.fine("PaySQL=" + sql.toString()); try { PreparedStatement pstmt = DB.prepareStatement(sql.toString(), null); pstmt.setInt(1, m_C_Currency_ID); - pstmt.setInt(2, m_C_Currency_ID); - pstmt.setInt(3, m_C_BPartner_ID); + pstmt.setTimestamp(2, (Timestamp)dateField.getValue()); + pstmt.setInt(3, m_C_Currency_ID); + pstmt.setTimestamp(4, (Timestamp)dateField.getValue()); + pstmt.setInt(5, m_C_BPartner_ID); if (!multiCurrency.isSelected()) - pstmt.setInt(4, m_C_Currency_ID); + pstmt.setInt(6, m_C_Currency_ID); ResultSet rs = pstmt.executeQuery(); while (rs.next()) { @@ -414,29 +443,37 @@ public class VAllocation extends CPanel data = new Vector>(); sql = new StringBuffer("SELECT i.DateInvoiced,i.DocumentNo,i.C_Invoice_ID," // 1..3 + "c.ISO_Code,i.GrandTotal*i.MultiplierAP, " // 4..5 Orig Currency - + "currencyConvert(i.GrandTotal*i.MultiplierAP,i.C_Currency_ID,?,i.DateInvoiced,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID), " // 6 #1 Converted - + "currencyConvert(invoiceOpen(C_Invoice_ID,C_InvoicePaySchedule_ID),i.C_Currency_ID,?,i.DateInvoiced,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID)*i.MultiplierAP, " // 7 #2 Converted Open + + "currencyConvert(i.GrandTotal*i.MultiplierAP,i.C_Currency_ID,?,?,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID), " // 6 #1 Converted, #2 Date + + "currencyConvert(invoiceOpen(C_Invoice_ID,C_InvoicePaySchedule_ID),i.C_Currency_ID,?,?,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID)*i.MultiplierAP, " // 7 #3, #4 Converted Open + "currencyConvert(invoiceDiscount" // 8 AllowedDiscount - + "(i.C_Invoice_ID,?,C_InvoicePaySchedule_ID),i.C_Currency_ID,?,i.DateInvoiced,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID)*i.Multiplier*i.MultiplierAP," // #3, #4 + + "(i.C_Invoice_ID,?,C_InvoicePaySchedule_ID),i.C_Currency_ID,?,i.DateInvoiced,i.C_ConversionType_ID,i.AD_Client_ID,i.AD_Org_ID)*i.Multiplier*i.MultiplierAP," // #5, #6 + "i.MultiplierAP " + "FROM C_Invoice_v i" // corrected for CM/Split + " INNER JOIN C_Currency c ON (i.C_Currency_ID=c.C_Currency_ID) " + "WHERE i.IsPaid='N' AND i.Processed='Y'" - + " AND i.C_BPartner_ID=?"); // #5 + + " AND i.C_BPartner_ID=?"); // #7 if (!multiCurrency.isSelected()) - sql.append(" AND i.C_Currency_ID=?"); // #6 + sql.append(" AND i.C_Currency_ID=?"); // #8 + if (m_AD_Org_ID != 0 ) + sql.append(" AND i.AD_Org_ID=" + m_AD_Org_ID); sql.append(" ORDER BY i.DateInvoiced, i.DocumentNo"); log.fine("InvSQL=" + sql.toString()); + + // role security + sql = new StringBuffer( MRole.getDefault(Env.getCtx(), false).addAccessSQL( sql.toString(), "i", MRole.SQL_FULLYQUALIFIED, MRole.SQL_RO ) ); + try { PreparedStatement pstmt = DB.prepareStatement(sql.toString(), null); pstmt.setInt(1, m_C_Currency_ID); - pstmt.setInt(2, m_C_Currency_ID); - pstmt.setTimestamp(3, (Timestamp)dateField.getValue()); - pstmt.setInt(4, m_C_Currency_ID); - pstmt.setInt(5, m_C_BPartner_ID); + pstmt.setTimestamp(2, (Timestamp)dateField.getValue()); + pstmt.setInt(3, m_C_Currency_ID); + pstmt.setTimestamp(4, (Timestamp)dateField.getValue()); + pstmt.setTimestamp(5, (Timestamp)dateField.getValue()); + pstmt.setInt(6, m_C_Currency_ID); + pstmt.setInt(7, m_C_BPartner_ID); if (!multiCurrency.isSelected()) - pstmt.setInt(6, m_C_Currency_ID); + pstmt.setInt(8, m_C_Currency_ID); ResultSet rs = pstmt.executeQuery(); while (rs.next()) { @@ -672,7 +709,7 @@ public class VAllocation extends CPanel discount = open; if ( writeOff.abs().compareTo(open.abs()) > 0) writeOff = open; - + // if overUnder has same sign as open it is an under payment -> less than open if ( overUnder.signum() == openSign && overUnder.abs().compareTo(open.abs()) > 0) overUnder = open; @@ -682,11 +719,11 @@ public class VAllocation extends CPanel * 1) |overUnder + writeOff + discount| < open * 2) |writeOff + discount| < open ( in case overUnder is 'negative') * 3) discount + writeOff + overUnder + applied = 0 - * + * * As only one column is edited at a time and the initial position was one of compliance * with the rules, we only need to redistribute the increase/decrease in the edited column to * the others. - */ + */ // comply with rules 1 or 2 BigDecimal amtOver; @@ -705,12 +742,12 @@ public class VAllocation extends CPanel { overUnder = Env.ZERO; amtOver = temp.negate(); - } + } else - { + { overUnder = temp; amtOver = Env.ZERO; - } + } } if ( col != i_writeOff ) @@ -720,14 +757,14 @@ public class VAllocation extends CPanel { writeOff = Env.ZERO; amtOver = temp.negate(); - } + } else { writeOff = temp; amtOver = Env.ZERO; } } - + if ( col != i_discount ) { temp = discount.subtract(amtOver); @@ -736,7 +773,7 @@ public class VAllocation extends CPanel discount = Env.ZERO; amtOver = temp.negate(); } - else + else { discount = temp; amtOver = Env.ZERO; @@ -762,14 +799,14 @@ public class VAllocation extends CPanel { writeOff = amtUnder; remainder = temp.subtract(amtUnder); - } + } else { writeOff = temp; remainder = Env.ZERO; } } - + if ( col != i_overUnder ) { temp = overUnder.add(remainder); @@ -865,7 +902,8 @@ public class VAllocation extends CPanel if (((Boolean)payment.getValueAt(i, 0)).booleanValue()) { Timestamp ts = (Timestamp)payment.getValueAt(i, 1); - allocDate = TimeUtil.max(allocDate, ts); + if ( !multiCurrency.isSelected() ) // the converted amounts are only valid for the selected date + allocDate = TimeUtil.max(allocDate, ts); BigDecimal bd = (BigDecimal)payment.getValueAt(i, i_payment); totalPay = totalPay.add(bd); // Applied Pay m_noPayments++; @@ -886,7 +924,8 @@ public class VAllocation extends CPanel if (((Boolean)invoice.getValueAt(i, 0)).booleanValue()) { Timestamp ts = (Timestamp)invoice.getValueAt(i, 1); - allocDate = TimeUtil.max(allocDate, ts); + if ( !multiCurrency.isSelected() ) // converted amounts only valid for selected date + allocDate = TimeUtil.max(allocDate, ts); BigDecimal bd = (BigDecimal)invoice.getValueAt(i, i_applied); totalInv = totalInv.add(bd); // Applied Inv m_noInvoices++; @@ -924,6 +963,18 @@ public class VAllocation extends CPanel String name = e.getPropertyName(); Object value = e.getNewValue(); log.config(name + "=" + value); + + // Organization + if (name.equals("AD_Org_ID")) + { + if (value == null) + m_AD_Org_ID = 0; + else + m_AD_Org_ID = ((Integer) value).intValue(); + + loadBPartner(); + } + if (value == null) return; diff --git a/client/src/org/compiere/grid/GridController.java b/client/src/org/compiere/grid/GridController.java index 9a8b709683..a7649d32d1 100644 --- a/client/src/org/compiere/grid/GridController.java +++ b/client/src/org/compiere/grid/GridController.java @@ -762,6 +762,7 @@ public class GridController extends CPanel int rowTable = vTable.getSelectedRow(); int rowCurrent = m_mTab.getCurrentRow(); log.config("(" + m_mTab.toString() + ") Row in Table=" + rowTable + ", in Model=" + rowCurrent); + /* BT [ 1972495 ] Multirow Automatic New Record loses context // FR [ 1757088 ] if(rowCurrent + 1 == vTable.getRowCount() && !isSingleRow() && Env.isAutoNew(Env.getCtx()) && m_mTab.getRecord_ID() != -1) { @@ -771,7 +772,7 @@ public class GridController extends CPanel dynamicDisplay(0); vTable.getSelectionModel().addListSelectionListener(this); return; - } + } */ if (rowTable == -1) // nothing selected { if (rowCurrent >= 0) diff --git a/client/src/org/compiere/grid/ed/VLocationDialog.java b/client/src/org/compiere/grid/ed/VLocationDialog.java index b7c92223ee..6ca9ba95ae 100644 --- a/client/src/org/compiere/grid/ed/VLocationDialog.java +++ b/client/src/org/compiere/grid/ed/VLocationDialog.java @@ -26,7 +26,7 @@ import org.compiere.model.*; import org.compiere.swing.*; import org.compiere.util.*; -import org.adempiere.interfaces.*; +import com.akunagroup.uk.postcode.*; import org.adempiere.model.*; /** @@ -37,6 +37,8 @@ import org.adempiere.model.*; * * @author Teo Sarca, SC ARHIPAC SERVICE SRL *
  • BF [ 1831060 ] Location dialog should use Address1, Address2 ... elements + * @author Michael Judd, Akuna Ltd (UK) + *
  • FR [ 1741222 ] - Webservice connector for address lookups */ public class VLocationDialog extends CDialog implements ActionListener @@ -121,7 +123,7 @@ public class VLocationDialog extends CDialog private CLabel lRegion = new CLabel(Msg.getMsg(Env.getCtx(), "Region")); private CLabel lPostal = new CLabel(Msg.getMsg(Env.getCtx(), "Postal")); private CLabel lPostalAdd = new CLabel(Msg.getMsg(Env.getCtx(), "PostalAdd")); - private CLabel lOnline = new CLabel(""); // dummy to use addLine without error.... + private CLabel lOnline = new CLabel(""); private CTextField fAddress1 = new CTextField(20); // length=60 private CTextField fAddress2 = new CTextField(20); // length=60 private CTextField fAddress3 = new CTextField(20); // length=60 @@ -214,6 +216,7 @@ public class VLocationDialog extends CDialog addLine(line++, lOnline, fOnline); + fOnline.setText(Msg.getMsg(Env.getCtx(), "Online")); // Country Last addLine(line++, lCountry, fCountry); @@ -228,7 +231,6 @@ public class VLocationDialog extends CDialog fCity.setText(m_location.getCity()); fPostal.setText(m_location.getPostal()); fPostalAdd.setText(m_location.getPostal_Add()); - fOnline.setText(Msg.getMsg(Env.getCtx(), "Online")); if (m_location.getCountry().isHasRegion()) { lRegion.setText(m_location.getCountry().getRegionName()); @@ -395,10 +397,10 @@ public class VLocationDialog extends CDialog private String lookupPostcode(MCountry country, String postcode) { // Initialise the lookup class. - PostcodeLookupInterface pcLookup = null; - try { - PostcodeLookupInterface pcLookupTmp = (PostcodeLookupInterface) Class - .forName(country.getLookupClassName()).newInstance(); + AddressLookupInterface pcLookup = null; + try { + AddressLookupInterface pcLookupTmp = (AddressLookupInterface) Class + .forName(country.getLookupClassName()).newInstance(); pcLookup = pcLookupTmp.newInstance(); } catch (Exception e) { e.printStackTrace(); @@ -415,7 +417,7 @@ public class VLocationDialog extends CDialog pcLookup.setPassword(country.getLookupPassword()); if (pcLookup.lookupPostcode(postcode)==1){ // Success - fillLocation(pcLookup.getPostCodeData(), country); + fillLocation(pcLookup.getAddressData(), country); fAddress1.requestFocusInWindow(); } else return "Postcode Lookup Error"; @@ -476,6 +478,9 @@ public class VLocationDialog extends CDialog // Overwrite the values in location field. fAddress1.setText(values.getStreet1()); + fAddress2.setText(values.getStreet2()); + fAddress3.setText(values.getStreet3()); + fAddress4.setText(values.getStreet4()); fCity.setText(values.getCity()); fPostal.setText(values.getPostcode()); @@ -495,7 +500,7 @@ public class VLocationDialog extends CDialog if (regions[i].getName().equals(values.getRegion()) ) { - // found county + // found Region fRegion.setSelectedItem(regions[i]); log.fine("Found region: " + regions[i].getName()); found = true; @@ -508,6 +513,11 @@ public class VLocationDialog extends CDialog if (region.save()) { log.fine("Added new region from web service: " + values.getRegion()); + // clears cache + Env.reset(false); + //reload regions to combo box + fRegion = new CComboBox(MRegion.getRegions(Env.getCtx(), country.getC_Country_ID())); + // select region fRegion.setSelectedItem(values); } else log.severe("Error saving new region: " + region.getName()); diff --git a/client/src/org/compiere/grid/ed/VLookup.java b/client/src/org/compiere/grid/ed/VLookup.java index db2ec54481..517f00aff2 100644 --- a/client/src/org/compiere/grid/ed/VLookup.java +++ b/client/src/org/compiere/grid/ed/VLookup.java @@ -29,6 +29,8 @@ import org.compiere.model.*; import org.compiere.swing.*; import org.compiere.util.*; +import org.eevolution.model.*; + /** * Lookup Visual Field. *

    @@ -766,7 +768,8 @@ public class VLookup extends JComponent int M_PriceList_ID = Env.getContextAsInt(Env.getCtx(), m_lookup.getWindowNo(), "M_PriceList_ID"); int AD_Table_ID = MColumn.getTable_ID(Env.getCtx(), m_mField.getAD_Column_ID(), null); - multipleSelection = (MOrderLine.Table_ID == AD_Table_ID) || (MInvoiceLine.Table_ID == AD_Table_ID); + + multipleSelection = (MOrderLine.Table_ID == AD_Table_ID) || (MInvoiceLine.Table_ID == AD_Table_ID) || (MPPProductBOMLine.Table_ID == AD_Table_ID) || (MProductPrice.Table_ID == AD_Table_ID); // Show Info InfoProduct ip = new InfoProduct (frame, true, m_lookup.getWindowNo(), diff --git a/client/src/org/compiere/print/Viewer.java b/client/src/org/compiere/print/Viewer.java index 9e00ec864b..6dc04ff8e1 100644 --- a/client/src/org/compiere/print/Viewer.java +++ b/client/src/org/compiere/print/Viewer.java @@ -47,6 +47,9 @@ import org.adempiere.pdf.*; * @author Teo Sarca, SC ARHIPAC SERVICE SRL *

  • FR [ 1762466 ] Add "Window" menu to report viewer. *
  • FR [ 1894640 ] Report Engine: Excel Export support + * @author victor.perez@e-evolution.com + * @see FR [ 1966328 ] New Window Info to MRP and CRP into View http://sourceforge.net/tracker/index.php?func=detail&aid=1966328&group_id=176962&atid=879335 + * */ public class Viewer extends CFrame implements ActionListener, ChangeListener, WindowStateListener @@ -412,6 +415,15 @@ public class Viewer extends CFrame { AEnv.addMenuItem("InfoSchedule", null, null, mView, this); } + //FR [ 1966328 ] + if (MRole.getDefault().isAllow_Info_MRP()) + { + AEnv.addMenuItem("InfoMRP", "Info", null, mView, this); + } + if (MRole.getDefault().isAllow_Info_CRP()) + { + AEnv.addMenuItem("InfoCRP", "Info", null, mView, this); + } mView.addSeparator(); if (MRole.getDefault().isAllow_Info_Order()) { @@ -441,6 +453,8 @@ public class Viewer extends CFrame { AEnv.addMenuItem("InfoAsset", "Info", null, mView, this); } + + // Go JMenu mGo = AEnv.getMenu("Go"); menuBar.add(mGo); diff --git a/db/ddlutils/postgresql/views/C_INVOICE_LINETAX_V.sql b/db/ddlutils/postgresql/views/C_INVOICE_LINETAX_V.sql index 39ee90ec30..aad9cbeb72 100644 --- a/db/ddlutils/postgresql/views/C_INVOICE_LINETAX_V.sql +++ b/db/ddlutils/postgresql/views/C_INVOICE_LINETAX_V.sql @@ -49,9 +49,11 @@ SELECT il.AD_Client_ID, il.AD_Org_ID, il.IsActive, il.Created, il.CreatedBy, il. 'en_US' AS AD_Language, il.C_Invoice_ID, il.C_InvoiceLine_ID, il.C_Tax_ID, il.TaxAmt, il.LineTotalAmt, t.TaxIndicator, - il.Line+(b.Line/100) AS Line, p.M_Product_ID, - il.QtyInvoiced*b.BOMQty AS QtyInvoiced, - il.QtyEntered*b.BOMQty AS QtyEntered, + il.Line+(bl.Line/100) AS Line, p.M_Product_ID, + --il.QtyInvoiced*b.BOMQty AS QtyInvoiced, + CASE WHEN bl.IsQtyPercentage = 'N' THEN il.QtyInvoiced*bl.QtyBOM ELSE il.QtyInvoiced*(bl.QtyBatch / 100) END AS QtyInvoiced, + --il.QtyEntered*b.BOMQty AS QtyEntered, + CASE WHEN bl.IsQtyPercentage = 'N' THEN il.QtyEntered*bl.QtyBOM ELSE il.QtyEntered*(bl.QtyBatch / 100) END AS QtyEntered, uom.UOMSymbol, p.Name, -- main b.Description, @@ -60,13 +62,22 @@ SELECT il.AD_Client_ID, il.AD_Org_ID, il.IsActive, il.Created, il.CreatedBy, il. il.M_AttributeSetInstance_ID, asi.M_AttributeSet_ID, asi.SerNo, asi.Lot, asi.M_Lot_ID,asi.GuaranteeDate, p.Description as ProductDescription, p.ImageURL, il.C_Campaign_ID, il.C_Project_ID, il.C_Activity_ID, il.C_ProjectPhase_ID, il.C_ProjectTask_ID -FROM M_Product_BOM b -- BOM lines +/*FROM M_Product_BOM b -- BOM lines INNER JOIN C_InvoiceLine il ON (b.M_Product_ID=il.M_Product_ID) INNER JOIN M_Product bp ON (bp.M_Product_ID=il.M_Product_ID -- BOM Product AND bp.IsBOM='Y' AND bp.IsVerified='Y' AND bp.IsInvoicePrintDetails='Y') INNER JOIN M_Product p ON (b.M_ProductBOM_ID=p.M_Product_ID) -- BOM line product INNER JOIN C_UOM uom ON (p.C_UOM_ID=uom.C_UOM_ID) LEFT OUTER JOIN C_Tax t ON (il.C_Tax_ID=t.C_Tax_ID) + LEFT OUTER JOIN M_AttributeSetInstance asi ON (il.M_AttributeSetInstance_ID=asi.M_AttributeSetInstance_ID)*/ +FROM PP_Product_BOM b -- BOM lines + INNER JOIN C_InvoiceLine il ON (b.M_Product_ID=il.M_Product_ID) + INNER JOIN M_Product bp ON (bp.M_Product_ID=il.M_Product_ID -- BOM Product + AND bp.IsBOM='Y' AND bp.IsVerified='Y' AND bp.IsInvoicePrintDetails='Y') + INNER JOIN PP_Product_BOMLine bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + INNER JOIN M_Product p ON (bl.M_Product_ID=p.M_Product_ID) -- BOM line product + INNER JOIN C_UOM uom ON (p.C_UOM_ID=uom.C_UOM_ID) + LEFT OUTER JOIN C_Tax t ON (il.C_Tax_ID=t.C_Tax_ID) LEFT OUTER JOIN M_AttributeSetInstance asi ON (il.M_AttributeSetInstance_ID=asi.M_AttributeSetInstance_ID) UNION -- comment lines SELECT il.AD_Client_ID, il.AD_Org_ID, il.IsActive, il.Created, il.CreatedBy, il.Updated, il.UpdatedBy, diff --git a/db/ddlutils/postgresql/views/C_INVOICE_LINETAX_VT.sql b/db/ddlutils/postgresql/views/C_INVOICE_LINETAX_VT.sql index 84790d1450..9da6465a85 100644 --- a/db/ddlutils/postgresql/views/C_INVOICE_LINETAX_VT.sql +++ b/db/ddlutils/postgresql/views/C_INVOICE_LINETAX_VT.sql @@ -49,9 +49,11 @@ SELECT il.AD_Client_ID, il.AD_Org_ID, il.IsActive, il.Created, il.CreatedBy, il. uom.AD_Language, il.C_Invoice_ID, il.C_InvoiceLine_ID, il.C_Tax_ID, il.TaxAmt, il.LineTotalAmt, t.TaxIndicator, - il.Line+(b.Line/100) AS Line, p.M_Product_ID, - il.QtyInvoiced*b.BOMQty AS QtyInvoiced, - il.QtyEntered*b.BOMQty AS QtyEntered, + il.Line+(bl.Line/100) AS Line, p.M_Product_ID, + --il.QtyInvoiced*b.BOMQty AS QtyInvoiced, + CASE WHEN bl.IsQtyPercentage = 'N' THEN il.QtyInvoiced*bl.QtyBOM ELSE il.QtyInvoiced*(bl.QtyBatch / 100) END AS QtyInvoiced, + --il.QtyEntered*b.BOMQty AS QtyEntered, + CASE WHEN bl.IsQtyPercentage = 'N' THEN il.QtyEntered*bl.QtyBOM ELSE il.QtyEntered*(bl.QtyBatch / 100) END AS QtyEntered, uom.UOMSymbol, COALESCE(pt.Name,p.Name) AS Name, -- main b.Description, @@ -60,7 +62,7 @@ SELECT il.AD_Client_ID, il.AD_Org_ID, il.IsActive, il.Created, il.CreatedBy, il. il.M_AttributeSetInstance_ID, asi.M_AttributeSet_ID, asi.SerNo, asi.Lot, asi.M_Lot_ID,asi.GuaranteeDate, pt.Description as ProductDescription, p.ImageURL, il.C_Campaign_ID, il.C_Project_ID, il.C_Activity_ID, il.C_ProjectPhase_ID, il.C_ProjectTask_ID -FROM M_Product_BOM b -- BOM lines +/*FROM M_Product_BOM b -- BOM lines INNER JOIN C_InvoiceLine il ON (b.M_Product_ID=il.M_Product_ID) INNER JOIN M_Product bp ON (bp.M_Product_ID=il.M_Product_ID -- BOM Product AND bp.IsBOM='Y' AND bp.IsVerified='Y' AND bp.IsInvoicePrintDetails='Y') @@ -68,6 +70,16 @@ FROM M_Product_BOM b -- BOM lines INNER JOIN C_UOM_Trl uom ON (p.C_UOM_ID=uom.C_UOM_ID) INNER JOIN M_Product_Trl pt ON (b.M_ProductBOM_ID=pt.M_Product_ID AND uom.AD_Language=pt.AD_Language) LEFT OUTER JOIN C_Tax t ON (il.C_Tax_ID=t.C_Tax_ID) + LEFT OUTER JOIN M_AttributeSetInstance asi ON (il.M_AttributeSetInstance_ID=asi.M_AttributeSetInstance_ID)*/ +FROM PP_Product_BOM b -- BOM lines + INNER JOIN C_InvoiceLine il ON (b.M_Product_ID=il.M_Product_ID) + INNER JOIN M_Product bp ON (bp.M_Product_ID=il.M_Product_ID -- BOM Product + AND bp.IsBOM='Y' AND bp.IsVerified='Y' AND bp.IsInvoicePrintDetails='Y') + INNER JOIN PP_Product_BOMLine bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + INNER JOIN M_Product p ON (bl.M_Product_ID=p.M_Product_ID) -- BOM line product + INNER JOIN C_UOM_Trl uom ON (p.C_UOM_ID=uom.C_UOM_ID) + INNER JOIN M_Product_Trl pt ON (bl.M_Product_ID=pt.M_Product_ID AND uom.AD_Language=pt.AD_Language) + LEFT OUTER JOIN C_Tax t ON (il.C_Tax_ID=t.C_Tax_ID) LEFT OUTER JOIN M_AttributeSetInstance asi ON (il.M_AttributeSetInstance_ID=asi.M_AttributeSetInstance_ID) UNION -- comment line SELECT il.AD_Client_ID, il.AD_Org_ID, il.IsActive, il.Created, il.CreatedBy, il.Updated, il.UpdatedBy, diff --git a/db/ddlutils/postgresql/views/C_ORDER_LINETAX_V.sql b/db/ddlutils/postgresql/views/C_ORDER_LINETAX_V.sql index 2dbe7f8464..141527e42e 100644 --- a/db/ddlutils/postgresql/views/C_ORDER_LINETAX_V.sql +++ b/db/ddlutils/postgresql/views/C_ORDER_LINETAX_V.sql @@ -2,7 +2,7 @@ CREATE OR REPLACE VIEW C_ORDER_LINETAX_V (AD_CLIENT_ID, AD_ORG_ID, ISACTIVE, CREATED, CREATEDBY, UPDATED, UPDATEDBY, AD_LANGUAGE, C_ORDER_ID, C_ORDERLINE_ID, C_TAX_ID, TAXINDICATOR, C_BPARTNER_ID, C_BPARTNER_LOCATION_ID, BPNAME, - C_LOCATION_ID, LINE, M_PRODUCT_ID, QTYORDERED, QTYENTERED, + C_LOCATION_ID, LINE, M_PRODUCT_ID,VendorProductNo, QTYORDERED, QTYENTERED, UOMSYMBOL, NAME, DESCRIPTION, DOCUMENTNOTE, UPC, SKU, PRODUCTVALUE, RESOURCEDESCRIPTION, PRICELIST, PRICEENTEREDLIST, DISCOUNT, PRICEACTUAL, PRICEENTERED, LINENETAMT, PRODUCTDESCRIPTION, @@ -13,7 +13,7 @@ SELECT ol.AD_Client_ID, ol.AD_Org_ID, ol.IsActive, ol.Created, ol.CreatedBy, ol. 'en_US' AS AD_Language, ol.C_Order_ID, ol.C_OrderLine_ID, ol.C_Tax_ID, t.TaxIndicator, ol.C_BPartner_ID, ol.C_BPartner_Location_ID, bp.Name AS BPName, bpl.C_Location_ID, - ol.Line, p.M_Product_ID, + ol.Line, p.M_Product_ID, po.VendorProductNo, CASE WHEN ol.QtyOrdered<>0 OR ol.M_Product_ID IS NOT NULL THEN ol.QtyOrdered END AS QtyOrdered, CASE WHEN ol.QtyEntered<>0 OR ol.M_Product_ID IS NOT NULL THEN ol.QtyEntered END AS QtyEntered, CASE WHEN ol.QtyEntered<>0 OR ol.M_Product_ID IS NOT NULL THEN uom.UOMSymbol END AS UOMSymbol, @@ -37,6 +37,7 @@ FROM C_OrderLine ol INNER JOIN C_UOM uom ON (ol.C_UOM_ID=uom.C_UOM_ID) INNER JOIN C_Order i ON (ol.C_Order_ID=i.C_Order_ID) LEFT OUTER JOIN M_Product p ON (ol.M_Product_ID=p.M_Product_ID) + LEFT OUTER JOIN M_Product_PO po ON (p.M_Product_ID=po.M_Product_ID) LEFT OUTER JOIN S_ResourceAssignment ra ON (ol.S_ResourceAssignment_ID=ra.S_ResourceAssignment_ID) LEFT OUTER JOIN C_Charge c ON (ol.C_Charge_ID=c.C_Charge_ID) LEFT OUTER JOIN C_BPartner_Product pp ON (ol.M_Product_ID=pp.M_Product_ID AND i.C_BPartner_ID=pp.C_BPartner_ID) @@ -48,18 +49,30 @@ SELECT ol.AD_Client_ID, ol.AD_Org_ID, ol.IsActive, ol.Created, ol.CreatedBy, ol. 'en_US' AS AD_Language, ol.C_Order_ID, ol.C_OrderLine_ID, ol.C_Tax_ID, null, null, null, null, null, - ol.Line+(b.Line/100) AS Line, p.M_Product_ID, - ol.QtyOrdered*b.BOMQty AS QtyInvoiced, ol.QtyEntered*b.BOMQty AS QtyEntered, uom.UOMSymbol, + ol.Line+(bl.Line/100) AS Line, p.M_Product_ID,po.VendorProductNo, + --ol.QtyOrdered*bl.BOMQty AS QtyInvoiced + CASE WHEN bl.IsQtyPercentage = 'N' THEN ol.QtyOrdered*bl.QtyBOM ELSE ol.QtyOrdered*(bl.QtyBatch / 100) END AS QtyInvoiced, + --ol.QtyEntered*bl.BOMQty AS QtyEntered, + CASE WHEN bl.IsQtyPercentage = 'N' THEN ol.QtyEntered*bl.QtyBOM ELSE ol.QtyEntered*(bl.QtyBatch / 100) END AS QtyEntered, + uom.UOMSymbol, p.Name, -- main - b.Description, + bl.Description, p.DocumentNote, p.UPC, p.SKU, p.Value AS ProductValue, null, null, null, null, null, null, null, p.Description as ProductDescription, p.ImageURL, ol.C_Campaign_ID, ol.C_Project_ID, ol.C_Activity_ID, ol.C_ProjectPhase_ID, ol.C_ProjectTask_ID -FROM M_Product_BOM b -- BOM lines +/*FROM M_Product_BOM b -- BOM lines INNER JOIN C_OrderLine ol ON (b.M_Product_ID=ol.M_Product_ID) INNER JOIN M_Product bp ON (bp.M_Product_ID=ol.M_Product_ID -- BOM Product AND bp.IsBOM='Y' AND bp.IsVerified='Y' AND bp.IsInvoicePrintDetails='Y') INNER JOIN M_Product p ON (b.M_ProductBOM_ID=p.M_Product_ID) -- BOM line product + INNER JOIN C_UOM uom ON (p.C_UOM_ID=uom.C_UOM_ID)*/ +FROM PP_Product_BOM b + INNER JOIN C_OrderLine ol ON (b.M_Product_ID=ol.M_Product_ID) + INNER JOIN M_Product bp ON (bp.M_Product_ID=ol.M_Product_ID -- BOM Product + AND bp.IsBOM='Y' AND bp.IsVerified='Y' AND bp.IsInvoicePrintDetails='Y') + INNER JOIN PP_Product_BOMLine bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + INNER JOIN M_Product p ON (p.M_Product_ID=bl.M_Product_ID) -- BOM line product + LEFT OUTER JOIN M_Product_PO po ON (p.M_Product_ID=po.M_Product_ID) INNER JOIN C_UOM uom ON (p.C_UOM_ID=uom.C_UOM_ID) UNION SELECT AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, @@ -67,7 +80,7 @@ SELECT AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy null, null, null, null, null, null, null, null, - null, null, + null, null,null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,null,null,null,null @@ -76,7 +89,7 @@ UNION SELECT ot.AD_Client_ID, ot.AD_Org_ID, ot.IsActive, ot.Created, ot.CreatedBy, ot.Updated, ot.UpdatedBy, 'en_US', ot.C_Order_ID, null, ot.C_Tax_ID, t.TaxIndicator, null, null, null, null, - null, null, + null, null,null, null, null, null, t.Name, null, null, null, null, null, null, diff --git a/db/ddlutils/postgresql/views/C_ORDER_LINETAX_VT.sql b/db/ddlutils/postgresql/views/C_ORDER_LINETAX_VT.sql index 9d0137e281..90ec75cede 100644 --- a/db/ddlutils/postgresql/views/C_ORDER_LINETAX_VT.sql +++ b/db/ddlutils/postgresql/views/C_ORDER_LINETAX_VT.sql @@ -2,7 +2,7 @@ CREATE OR REPLACE VIEW C_ORDER_LINETAX_VT (AD_CLIENT_ID, AD_ORG_ID, ISACTIVE, CREATED, CREATEDBY, UPDATED, UPDATEDBY, AD_LANGUAGE, C_ORDER_ID, C_ORDERLINE_ID, C_TAX_ID, TAXINDICATOR, C_BPARTNER_ID, C_BPARTNER_LOCATION_ID, BPNAME, - C_LOCATION_ID, LINE, M_PRODUCT_ID, QTYORDERED, QTYENTERED, + C_LOCATION_ID, LINE, M_PRODUCT_ID,VendorProductNo, QTYORDERED, QTYENTERED, UOMSYMBOL, NAME, DESCRIPTION, DOCUMENTNOTE, UPC, SKU, PRODUCTVALUE, RESOURCEDESCRIPTION, PRICELIST, PRICEENTEREDLIST, DISCOUNT, PRICEACTUAL, PRICEENTERED, LINENETAMT, PRODUCTDESCRIPTION, @@ -13,7 +13,7 @@ SELECT ol.AD_Client_ID, ol.AD_Org_ID, ol.IsActive, ol.Created, ol.CreatedBy, ol. uom.AD_Language, ol.C_Order_ID, ol.C_OrderLine_ID, ol.C_Tax_ID, t.TaxIndicator, ol.C_BPartner_ID, ol.C_BPartner_Location_ID, bp.Name AS BPName, bpl.C_Location_ID, - ol.Line, p.M_Product_ID, + ol.Line, p.M_Product_ID,po.VendorProductNo, CASE WHEN ol.QtyOrdered<>0 OR ol.M_Product_ID IS NOT NULL THEN ol.QtyOrdered END AS QtyOrdered, CASE WHEN ol.QtyEntered<>0 OR ol.M_Product_ID IS NOT NULL THEN ol.QtyEntered END AS QtyEntered, CASE WHEN ol.QtyEntered<>0 OR ol.M_Product_ID IS NOT NULL THEN uom.UOMSymbol END AS UOMSymbol, @@ -37,6 +37,7 @@ FROM C_OrderLine ol INNER JOIN C_UOM_Trl uom ON (ol.C_UOM_ID=uom.C_UOM_ID) INNER JOIN C_Order i ON (ol.C_Order_ID=i.C_Order_ID) LEFT OUTER JOIN M_Product p ON (ol.M_Product_ID=p.M_Product_ID) + LEFT OUTER JOIN M_Product_PO po ON (p.M_Product_ID=po.M_Product_ID) LEFT OUTER JOIN M_Product_Trl pt ON (ol.M_Product_ID=pt.M_Product_ID AND uom.AD_Language=pt.AD_Language) LEFT OUTER JOIN S_ResourceAssignment ra ON (ol.S_ResourceAssignment_ID=ra.S_ResourceAssignment_ID) LEFT OUTER JOIN C_Charge c ON (ol.C_Charge_ID=c.C_Charge_ID) @@ -49,27 +50,40 @@ SELECT ol.AD_Client_ID, ol.AD_Org_ID, ol.IsActive, ol.Created, ol.CreatedBy, ol. uom.AD_Language, ol.C_Order_ID, ol.C_OrderLine_ID, ol.C_Tax_ID, null, null, null, null, null, - ol.Line+(b.Line/100) AS Line, p.M_Product_ID, - ol.QtyOrdered*b.BOMQty AS QtyInvoiced, ol.QtyEntered*b.BOMQty AS QtyEntered, uom.UOMSymbol, + ol.Line+(bl.Line/100) AS Line, p.M_Product_ID,po.VendorProductNo, + --ol.QtyOrdered*b.BOMQty AS QtyInvoiced, + CASE WHEN bl.IsQtyPercentage = 'N' THEN ol.QtyOrdered*bl.QtyBOM ELSE ol.QtyOrdered*(bl.QtyBatch / 100) END AS QtyInvoiced, + --ol.QtyEntered*b.BOMQty AS QtyEntered, + CASE WHEN bl.IsQtyPercentage = 'N' THEN ol.QtyEntered*bl.QtyBOM ELSE ol.QtyEntered*(bl.QtyBatch / 100) END AS QtyEntered, + uom.UOMSymbol, COALESCE(pt.Name, p.Name) AS Name, -- main b.Description, COALESCE(pt.DocumentNote, p.DocumentNote) AS DocumentNote, p.UPC, p.SKU, p.Value AS ProductValue, null, null, null, null, null, null, null, pt.Description AS ProductDescription, p.ImageURL, ol.C_Campaign_ID, ol.C_Project_ID, ol.C_Activity_ID, ol.C_ProjectPhase_ID, ol.C_ProjectTask_ID -FROM M_Product_BOM b -- BOM lines +/*FROM M_Product_BOM b -- BOM lines INNER JOIN C_OrderLine ol ON (b.M_Product_ID=ol.M_Product_ID) INNER JOIN M_Product bp ON (bp.M_Product_ID=ol.M_Product_ID -- BOM Product AND bp.IsBOM='Y' AND bp.IsVerified='Y' AND bp.IsInvoicePrintDetails='Y') INNER JOIN M_Product p ON (b.M_ProductBOM_ID=p.M_Product_ID) -- BOM line product INNER JOIN C_UOM_Trl uom ON (p.C_UOM_ID=uom.C_UOM_ID) - INNER JOIN M_Product_Trl pt ON (b.M_ProductBOM_ID=pt.M_Product_ID AND uom.AD_Language=pt.AD_Language) + INNER JOIN M_Product_Trl pt ON (b.M_ProductBOM_ID=pt.M_Product_ID AND uom.AD_Language=pt.AD_Language)*/ +FROM PP_Product_BOM b + INNER JOIN C_OrderLine ol ON (b.M_Product_ID=ol.M_Product_ID) + INNER JOIN M_Product bp ON (bp.M_Product_ID=ol.M_Product_ID -- BOM Product + AND bp.IsBOM='Y' AND bp.IsVerified='Y' AND bp.IsInvoicePrintDetails='Y') + INNER JOIN PP_Product_BOMLine bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + INNER JOIN M_Product p ON (p.M_Product_ID=bl.M_Product_ID) -- BOM line product + LEFT OUTER JOIN M_Product_PO po ON (p.M_Product_ID=po.M_Product_ID) + INNER JOIN C_UOM_Trl uom ON (p.C_UOM_ID=uom.C_UOM_ID) + INNER JOIN M_Product_Trl pt ON (pt.M_Product_ID=bl.M_Product_ID AND uom.AD_Language=pt.AD_Language) UNION SELECT o.AD_Client_ID, o.AD_Org_ID, o.IsActive, o.Created, o.CreatedBy, o.Updated, o.UpdatedBy, l.AD_Language, o.C_Order_ID, null, null, null, null, null, null, null, null, null, null, null, - null, null, + null, null,null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null,null,null,null,null @@ -79,7 +93,7 @@ UNION SELECT ot.AD_Client_ID, ot.AD_Org_ID, ot.IsActive, ot.Created, ot.CreatedBy, ot.Updated, ot.UpdatedBy, t.AD_Language, ot.C_Order_ID, null, ot.C_Tax_ID, t.TaxIndicator, null, null, null, null, - null, null, + null, null,null, null, null, null, t.Name, null, null, null, null, null, null, diff --git a/db/ddlutils/postgresql/views/M_INOUT_LINE_V.sql b/db/ddlutils/postgresql/views/M_INOUT_LINE_V.sql index f17173e114..ef95df6924 100644 --- a/db/ddlutils/postgresql/views/M_INOUT_LINE_V.sql +++ b/db/ddlutils/postgresql/views/M_INOUT_LINE_V.sql @@ -37,8 +37,12 @@ UNION -- BOM lines SELECT iol.AD_Client_ID, iol.AD_Org_ID, iol.IsActive, iol.Created, iol.CreatedBy, iol.Updated, iol.UpdatedBy, 'en_US' AS AD_Language, iol.M_InOut_ID, iol.M_InOutLine_ID, - iol.Line+(b.Line/100) AS Line, p.M_Product_ID, - iol.MovementQty*b.BOMQty AS QtyInvoiced, iol.QtyEntered*b.BOMQty AS QtyEntered, uom.UOMSymbol, + iol.Line+(bl.Line/100) AS Line, p.M_Product_ID, + --iol.MovementQty*b.BOMQty AS QtyInvoiced, + CASE WHEN bl.IsQtyPercentage = 'N' THEN iol.MovementQty*bl.QtyBOM ELSE iol.MovementQty*(bl.QtyBatch / 100) END AS QtyInvoiced, + --iol.QtyEntered*b.BOMQty AS QtyEntered, + CASE WHEN bl.IsQtyPercentage = 'N' THEN iol.QtyEntered*bl.QtyBOM ELSE iol.QtyEntered*(bl.QtyBatch / 100) END AS QtyEntered, + uom.UOMSymbol, null, null, null, p.Name, -- main line b.Description, -- second line @@ -48,7 +52,7 @@ SELECT iol.AD_Client_ID, iol.AD_Org_ID, iol.IsActive, iol.Created, iol.CreatedBy iol.M_AttributeSetInstance_ID, asi.M_AttributeSet_ID, asi.SerNo, asi.Lot, asi.M_Lot_ID,asi.GuaranteeDate, p.Description AS ProductDescription, p.ImageURL, iol.C_Campaign_ID, iol.C_Project_ID, iol.C_Activity_ID, iol.C_ProjectPhase_ID, iol.C_ProjectTask_ID -FROM M_Product_BOM b -- BOM lines +/*FROM M_Product_BOM b -- BOM lines INNER JOIN M_InOutLine iol ON (b.M_Product_ID=iol.M_Product_ID) INNER JOIN M_Product bp ON (bp.M_Product_ID=iol.M_Product_ID -- BOM Product AND bp.IsBOM='Y' AND bp.IsVerified='Y' AND bp.IsPickListPrintDetails='Y') @@ -56,6 +60,16 @@ FROM M_Product_BOM b -- BOM lines INNER JOIN C_UOM uom ON (p.C_UOM_ID=uom.C_UOM_ID) LEFT OUTER JOIN M_AttributeSetInstance asi ON (iol.M_AttributeSetInstance_ID=asi.M_AttributeSetInstance_ID) LEFT OUTER JOIN M_Locator l ON (iol.M_Locator_ID=l.M_Locator_ID); +*/ +FROM PP_Product_BOM b -- BOM lines + INNER JOIN M_InOutLine iol ON (b.M_Product_ID=iol.M_Product_ID) + INNER JOIN M_Product bp ON (bp.M_Product_ID=iol.M_Product_ID -- BOM Product + AND bp.IsBOM='Y' AND bp.IsVerified='Y' AND bp.IsPickListPrintDetails='Y') + INNER JOIN PP_Product_BOMLine bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + INNER JOIN M_Product p ON (bl.M_Product_ID=p.M_Product_ID) -- BOM line product + INNER JOIN C_UOM uom ON (p.C_UOM_ID=uom.C_UOM_ID) + LEFT OUTER JOIN M_AttributeSetInstance asi ON (iol.M_AttributeSetInstance_ID=asi.M_AttributeSetInstance_ID) + LEFT OUTER JOIN M_Locator l ON (iol.M_Locator_ID=l.M_Locator_ID); diff --git a/db/ddlutils/postgresql/views/M_INOUT_LINE_VT.sql b/db/ddlutils/postgresql/views/M_INOUT_LINE_VT.sql index 672c7e89d5..9239325a81 100644 --- a/db/ddlutils/postgresql/views/M_INOUT_LINE_VT.sql +++ b/db/ddlutils/postgresql/views/M_INOUT_LINE_VT.sql @@ -38,8 +38,12 @@ UNION SELECT iol.AD_Client_ID, iol.AD_Org_ID, iol.IsActive, iol.Created, iol.CreatedBy, iol.Updated, iol.UpdatedBy, uom.AD_Language, iol.M_InOut_ID, iol.M_InOutLine_ID, - iol.Line+(b.Line/100) AS Line, p.M_Product_ID, - iol.MovementQty*b.BOMQty AS QtyInvoiced, iol.QtyEntered*b.BOMQty AS QtyEntered, uom.UOMSymbol, + iol.Line+(bl.Line/100) AS Line, p.M_Product_ID, + --iol.MovementQty*b.BOMQty AS QtyInvoiced, + CASE WHEN bl.IsQtyPercentage = 'N' THEN iol.MovementQty*bl.QtyBOM ELSE iol.MovementQty*(bl.QtyBatch / 100) END AS QtyInvoiced, + --iol.QtyEntered*b.BOMQty AS QtyEntered, + CASE WHEN bl.IsQtyPercentage = 'N' THEN iol.QtyEntered*bl.QtyBOM ELSE iol.QtyEntered*(bl.QtyBatch / 100) END AS QtyEntered, + uom.UOMSymbol, null, null, null, COALESCE (pt.Name, p.Name) AS Name, -- main line b.Description, -- second line @@ -49,7 +53,7 @@ SELECT iol.AD_Client_ID, iol.AD_Org_ID, iol.IsActive, iol.Created, iol.CreatedBy iol.M_AttributeSetInstance_ID, asi.M_AttributeSet_ID, asi.SerNo, asi.Lot, asi.M_Lot_ID,asi.GuaranteeDate, pt.Description AS ProductDescription, p.ImageURL, iol.C_Campaign_ID, iol.C_Project_ID, iol.C_Activity_ID, iol.C_ProjectPhase_ID, iol.C_ProjectTask_ID -FROM M_Product_BOM b -- BOM lines +/*FROM M_Product_BOM b -- BOM lines INNER JOIN M_InOutLine iol ON (b.M_Product_ID=iol.M_Product_ID) INNER JOIN M_Product bp ON (bp.M_Product_ID=iol.M_Product_ID -- BOM Product AND bp.IsBOM='Y' AND bp.IsVerified='Y' AND bp.IsPickListPrintDetails='Y') @@ -57,6 +61,16 @@ FROM M_Product_BOM b -- BOM lines INNER JOIN C_UOM_Trl uom ON (p.C_UOM_ID=uom.C_UOM_ID) INNER JOIN M_Product_Trl pt ON (iol.M_Product_ID=pt.M_Product_ID AND uom.AD_Language=pt.AD_Language) LEFT OUTER JOIN M_AttributeSetInstance asi ON (iol.M_AttributeSetInstance_ID=asi.M_AttributeSetInstance_ID) + LEFT OUTER JOIN M_Locator l ON (iol.M_Locator_ID=l.M_Locator_ID);*/ +FROM PP_Product_BOM b -- BOM lines + INNER JOIN M_InOutLine iol ON (b.M_Product_ID=iol.M_Product_ID) + INNER JOIN M_Product bp ON (bp.M_Product_ID=iol.M_Product_ID -- BOM Product + AND bp.IsBOM='Y' AND bp.IsVerified='Y' AND bp.IsPickListPrintDetails='Y') + INNER JOIN PP_Product_BOMLine bl ON (bl.PP_Product_BOM_ID=b.PP_Product_BOM_ID) + INNER JOIN M_Product p ON (bl.M_Product_ID=p.M_Product_ID) -- BOM line product + INNER JOIN C_UOM_Trl uom ON (p.C_UOM_ID=uom.C_UOM_ID) + INNER JOIN M_Product_Trl pt ON (iol.M_Product_ID=pt.M_Product_ID AND uom.AD_Language=pt.AD_Language) + LEFT OUTER JOIN M_AttributeSetInstance asi ON (iol.M_AttributeSetInstance_ID=asi.M_AttributeSetInstance_ID) LEFT OUTER JOIN M_Locator l ON (iol.M_Locator_ID=l.M_Locator_ID); diff --git a/db/ddlutils/postgresql/views/RV_M_TRANSACTION.sql b/db/ddlutils/postgresql/views/RV_M_TRANSACTION.sql index b4cffa7d80..6bfbbbc5e4 100644 --- a/db/ddlutils/postgresql/views/RV_M_TRANSACTION.sql +++ b/db/ddlutils/postgresql/views/RV_M_TRANSACTION.sql @@ -6,10 +6,11 @@ AS SELECT t.AD_Client_ID,t.AD_Org_ID, t.MovementDate, t.MovementQty, t.M_Product_ID, t.M_Locator_ID, t.M_AttributeSetInstance_ID, p.M_Product_Category_ID, p.Value, - po.C_BPartner_ID, po.PricePO, po.PriceLastPO, po.PriceList + --po.C_BPartner_ID, po.PricePO, po.PriceLastPO, po.PriceList FROM M_Transaction t INNER JOIN M_Product p ON (t.M_Product_ID=p.M_Product_ID) - INNER JOIN M_Product_PO po ON (t.M_Product_ID=po.M_Product_ID) + --INNER JOIN M_Product_PO po ON (t.M_Product_ID=po.M_Product_ID) + LEFT JOIN M_CostDetail cd (M_) WHERE po.IsCurrentVendor='Y'; diff --git a/db/ddlutils/postgresql/views/RV_OPENITEM.sql b/db/ddlutils/postgresql/views/RV_OPENITEM.sql index ad3d594833..395d897919 100644 --- a/db/ddlutils/postgresql/views/RV_OPENITEM.sql +++ b/db/ddlutils/postgresql/views/RV_OPENITEM.sql @@ -2,7 +2,8 @@ CREATE OR REPLACE VIEW RV_OPENITEM (AD_ORG_ID, AD_CLIENT_ID, DOCUMENTNO, C_INVOICE_ID, C_ORDER_ID, C_BPARTNER_ID, ISSOTRX, DATEINVOICED, DATEACCT, NETDAYS, DUEDATE, DAYSDUE, DISCOUNTDATE, DISCOUNTAMT, GRANDTOTAL, - PAIDAMT, OPENAMT, C_CURRENCY_ID, C_CONVERSIONTYPE_ID, C_PAYMENTTERM_ID, + PAIDAMT, OPENAMT, + C_CURRENCY_ID, C_CONVERSIONTYPE_ID, C_PAYMENTTERM_ID, ISPAYSCHEDULEVALID, C_INVOICEPAYSCHEDULE_ID, INVOICECOLLECTIONTYPE, C_CAMPAIGN_ID, C_PROJECT_ID, C_ACTIVITY_ID) AS @@ -24,8 +25,8 @@ SELECT i.AD_Org_ID, i.AD_Client_ID, FROM RV_C_Invoice i INNER JOIN C_PaymentTerm p ON (i.C_PaymentTerm_ID=p.C_PaymentTerm_ID) WHERE -- i.IsPaid='N' - invoiceOpen(i.C_Invoice_ID,0) <> 0 - AND i.IsPayScheduleValid<>'Y' + invoiceOpen(i.C_Invoice_ID,0) <> 0 AND + i.IsPayScheduleValid<>'Y' AND i.DocStatus<>'DR' UNION SELECT i.AD_Org_ID, i.AD_Client_ID, @@ -46,8 +47,8 @@ SELECT i.AD_Org_ID, i.AD_Client_ID, FROM RV_C_Invoice i INNER JOIN C_InvoicePaySchedule ips ON (i.C_Invoice_ID=ips.C_Invoice_ID) WHERE -- i.IsPaid='N' - invoiceOpen(i.C_Invoice_ID,ips.C_InvoicePaySchedule_ID) <> 0 - AND i.IsPayScheduleValid='Y' + invoiceOpen(i.C_Invoice_ID,ips.C_InvoicePaySchedule_ID) <> 0 AND + i.IsPayScheduleValid='Y' AND i.DocStatus<>'DR' AND ips.IsValid='Y'; diff --git a/serverRoot/src/main/server/org/compiere/server/AdempiereServer.java b/serverRoot/src/main/server/org/compiere/server/AdempiereServer.java index 0472f50efb..4347d099d5 100644 --- a/serverRoot/src/main/server/org/compiere/server/AdempiereServer.java +++ b/serverRoot/src/main/server/org/compiere/server/AdempiereServer.java @@ -23,6 +23,7 @@ import org.compiere.ldap.*; import org.compiere.model.*; import org.compiere.util.*; import org.compiere.wf.*; +import org.eevolution.model.*; /** * Adempiere Server Base @@ -51,6 +52,8 @@ public abstract class AdempiereServer extends Thread return new Scheduler ((MScheduler)model); if (model instanceof MLdapProcessor) return new LdapProcessor((MLdapProcessor)model); + if (model instanceof MIMPProcessor) // @Trifon + return new ReplicationProcessor((MIMPProcessor)model); // throw new IllegalArgumentException("Unknown Processor"); } // create diff --git a/serverRoot/src/main/server/org/compiere/server/AdempiereServerMgr.java b/serverRoot/src/main/server/org/compiere/server/AdempiereServerMgr.java index d79098a82d..ef5ade24e0 100644 --- a/serverRoot/src/main/server/org/compiere/server/AdempiereServerMgr.java +++ b/serverRoot/src/main/server/org/compiere/server/AdempiereServerMgr.java @@ -23,6 +23,7 @@ import org.compiere.*; import org.compiere.model.*; import org.compiere.util.*; import org.compiere.wf.*; +import org.eevolution.model.*; /** * Adempiere Server Manager @@ -156,6 +157,16 @@ public class AdempiereServerMgr server.setPriority(Thread.NORM_PRIORITY-1); m_servers.add(server); } + // ImportProcessor - @Trifon + MIMPProcessor[] importModels = MIMPProcessor.getActive(m_ctx); + for (int i = 0; i < importModels.length; i++) + { + MIMPProcessor lp = importModels[i]; + AdempiereServer server = AdempiereServer.create(lp); + server.start(); + server.setPriority(Thread.NORM_PRIORITY-1); + m_servers.add(server); + } log.fine("#" + noServers); return startAll(); diff --git a/sqlj/oracle/createSQLJ.sql b/sqlj/oracle/createSQLJ.sql index a27d33c517..83333ed03c 100644 --- a/sqlj/oracle/createSQLJ.sql +++ b/sqlj/oracle/createSQLJ.sql @@ -69,6 +69,32 @@ CREATE OR REPLACE FUNCTION bomQtyReserved (M_Product_ID NUMBER, M_Warehouse_ID N NAME 'org.compiere.sqlj.Product.bomQtyReserved(int,int,int) return java.math.BigDecimal'; / + +CREATE OR REPLACE FUNCTION bomQtyAvailableASI (M_Product_ID NUMBER, M_AttributeSetInstance_ID NUMBER, M_Warehouse_ID NUMBER, + M_Locator_ID NUMBER) + RETURN NUMBER + AS LANGUAGE JAVA + NAME 'org.compiere.sqlj.Product.bomQtyAvailableASI(int,int,int,int) return java.math.BigDecimal'; +/ +CREATE OR REPLACE FUNCTION bomQtyOnHandASI (M_Product_ID NUMBER,M_AttributeSetInstance_ID NUMBER, M_Warehouse_ID NUMBER, + M_Locator_ID NUMBER) + RETURN NUMBER + AS LANGUAGE JAVA + NAME 'org.compiere.sqlj.Product.bomQtyOnHandASI(int,int,int,int) return java.math.BigDecimal'; +/ +CREATE OR REPLACE FUNCTION bomQtyOrderedASI (M_Product_ID NUMBER, M_AttributeSetInstance_ID NUMBER, M_Warehouse_ID NUMBER, + M_Locator_ID NUMBER) + RETURN NUMBER + AS LANGUAGE JAVA + NAME 'org.compiere.sqlj.Product.bomQtyOrderedASI(int,int,int,int) return java.math.BigDecimal'; +/ +CREATE OR REPLACE FUNCTION bomQtyReservedASI (M_Product_ID NUMBER, M_AttributeSetInstance_ID NUMBER, M_Warehouse_ID NUMBER, + M_Locator_ID NUMBER) + RETURN NUMBER + AS LANGUAGE JAVA + NAME 'org.compiere.sqlj.Product.bomQtyReserved(int,int,int,int) return java.math.BigDecimal'; +/ + /** Currency **/ CREATE OR REPLACE FUNCTION currencyBase (Amount NUMBER, C_CurrencyFrom_ID NUMBER, ConversionDate DATE, AD_Client_ID NUMBER, AD_Org_ID NUMBER) @@ -108,12 +134,26 @@ CREATE OR REPLACE FUNCTION invoiceOpen (p_C_Invoice_ID NUMBER, p_C_InvoicePaySch AS LANGUAGE JAVA NAME 'org.compiere.sqlj.Invoice.open(int,int) return java.math.BigDecimal'; / + CREATE OR REPLACE FUNCTION invoicePaid (p_C_Invoice_ID NUMBER, p_C_Currency_ID NUMBER, p_MultiplierAP NUMBER) RETURN NUMBER AS LANGUAGE JAVA NAME 'org.compiere.sqlj.Invoice.paid(int,int,int) return java.math.BigDecimal'; / + + +CREATE OR REPLACE FUNCTION invoiceOpenToDate (p_C_Invoice_ID NUMBER, p_C_InvoicePaySchedule_ID NUMBER,p_AcctDate DATE) + RETURN NUMBER + AS LANGUAGE JAVA + NAME 'org.compiere.sqlj.Invoice.openToDate(int,int,java.sql.Timestamp) return java.math.BigDecimal'; +/ + +CREATE OR REPLACE FUNCTION invoicePaidToDate (p_C_Invoice_ID NUMBER, p_C_Currency_ID NUMBER, p_MultiplierAP NUMBER,p_AcctDate DATE) + RETURN NUMBER + AS LANGUAGE JAVA + NAME 'org.compiere.sqlj.Invoice.paid(int,int,int,java.sql.Timestamp) return java.math.BigDecimal'; +/ CREATE OR REPLACE FUNCTION invoiceDiscount (p_C_Invoice_ID NUMBER, p_PayDate Date, p_C_InvoicePaySchedule_ID NUMBER) RETURN NUMBER diff --git a/utils_dev/RUN_build.bat b/utils_dev/RUN_build.bat index 5026fc1fa7..fe9b102ffb 100644 --- a/utils_dev/RUN_build.bat +++ b/utils_dev/RUN_build.bat @@ -3,14 +3,14 @@ @Rem Check java home @IF NOT EXIST "%JAVA_HOME%\bin" ECHO "** JAVA_HOME NOT found" -@SET PATH=%JAVA_HOME%\bin;%PATH% +@SET PATH="%JAVA_HOME%\bin";%PATH% @Rem Check jdk @IF NOT EXIST "%JAVA_HOME%\lib\tools.jar" ECHO "** Need Full Java SDK **" @Rem Set ant classpath @SET ANT_CLASSPATH=%CLASSPATH%;..\tools\lib\ant.jar;..\tools\lib\ant-launcher.jar;..\tools\lib\ant-swing.jar;..\tools\lib\ant-commons-net.jar;..\tools\lib\commons-net-1.4.0.jar -@SET ANT_CLASSPATH=%ANT_CLASSPATH%;"%JAVA_HOME%\lib\tools.jar" +@SET ANT_CLASSPATH="%ANT_CLASSPATH%";"%JAVA_HOME%\lib\tools.jar" @SET ANT_OPTS=-Xms128m -Xmx512m