/** * ************************************************************************ Default Constructor * * @param ctx context * @param C_OrderLine_ID order line to load * @param trxName trx name */ public MOrderLine(Properties ctx, int C_OrderLine_ID, String trxName) { super(ctx, C_OrderLine_ID, trxName); if (C_OrderLine_ID == 0) { // setC_Order_ID (0); // setLine (0); // setM_Warehouse_ID (0); // @M_Warehouse_ID@ // setC_BPartner_ID(0); // setC_BPartner_Location_ID (0); // @C_BPartner_Location_ID@ // setC_Currency_ID (0); // @C_Currency_ID@ // setDateOrdered (new Timestamp(System.currentTimeMillis())); // @DateOrdered@ // // setC_Tax_ID (0); // setC_UOM_ID (0); // setFreightAmt(Env.ZERO); setLineNetAmt(Env.ZERO); // setPriceEntered(Env.ZERO); setPriceActual(Env.ZERO); setPriceLimit(Env.ZERO); setPriceList(Env.ZERO); // setM_AttributeSetInstance_ID(0); // setQtyEntered(Env.ZERO); setQtyOrdered(Env.ZERO); // 1 setQtyDelivered(Env.ZERO); setQtyInvoiced(Env.ZERO); // task 09358: get rid of this; instead, update qtyReserved at one central place // setQtyReserved(Env.ZERO); // setIsDescription(false); // N setProcessed(false); setLine(0); } } // MOrderLine
/** * ************************************************************************ Before Save * * @param newRecord * @return true if it can be saved */ @Override protected boolean beforeSave(boolean newRecord) { final boolean complete = getParent().isComplete(); if (newRecord && complete) { throw new AdempiereException("@ParentComplete@ @C_OrderLine_ID@"); } // In case our order is complete do nothing, don't update any field if (complete) { // TODO: make sure that only QtyDelivered, QtyInvoiced fields are updated. // The rest shall be forbidden. // NOTE: also please check if those are the only fields which are updated after an order is // completed return true; } // Get Defaults from Parent final I_M_Warehouse warehouse = Services.get(IWarehouseAdvisor.class).evaluateWarehouse(this); if (getC_BPartner_ID() <= 0 || getC_BPartner_Location_ID() <= 0 || warehouse == null || warehouse.getM_Warehouse_ID() <= 0 || getC_Currency_ID() <= 0) { setOrder(getParent()); } // metas: try to get the pl-id from our plv if (m_M_PriceList_ID <= 0) { final int plvId = get_ValueAsInt(de.metas.interfaces.I_C_OrderLine.COLUMNNAME_M_PriceList_Version_ID); if (plvId > 0) { m_M_PriceList_ID = DB.getSQLValueEx( get_TrxName(), "SELECT M_PriceList_ID FROM M_PriceList_Version WHERE M_PriceList_Version_ID=" + plvId); } } // metas: end if (m_M_PriceList_ID <= 0) setHeaderInfo(getParent()); // R/O Check - Product/Warehouse Change if (!newRecord && (is_ValueChanged("M_Product_ID") || is_ValueChanged("M_Warehouse_ID"))) { if (!canChangeWarehouse(true)) return false; } // Product Changed // Charge if (getC_Charge_ID() != 0 && getM_Product_ID() != 0) setM_Product_ID(0); // No Product if (getM_Product_ID() == 0) setM_AttributeSetInstance_ID(0); // Product else // Set/check Product Price { // Set Price if Actual = 0 if (m_productPrice == null && getPriceActual().signum() == 0 && getPriceList().signum() == 0) { setPrice(); } // Check if on Price list if (m_productPrice == null) getProductPricing( m_M_PriceList_ID, get_ValueAsInt(de.metas.interfaces.I_C_OrderLine.COLUMNNAME_M_PriceList_Version_ID)); if (!m_productPrice.isCalculated()) { throw new ProductNotOnPriceListException(m_productPrice, getLine()); } } // metas: Not allowed to save without (Product or Charge) and qty > 0 if (getM_Product_ID() == 0 && getC_Charge_ID() == 0 && getQtyEntered().intValue() > 0) throw new AdempiereException("@NotFound@ @M_Product_ID@/@C_Charge_ID@ (@QtyEntered@>0)"); // UOM if (getC_UOM_ID() == 0 && (getM_Product_ID() != 0 || getPriceEntered().compareTo(Env.ZERO) != 0 || getC_Charge_ID() != 0)) { int C_UOM_ID = MUOM.getDefault_UOM_ID(getCtx()); if (C_UOM_ID > 0) setC_UOM_ID(C_UOM_ID); } // Price_UOM task 06942 // note: we do not set the price-UOM, because that would only make sense if we also set the // prices themselves. // Qty Precision if (newRecord || is_ValueChanged("QtyEntered")) setQtyEntered(getQtyEntered()); if (newRecord || is_ValueChanged("QtyOrdered")) setQtyOrdered(getQtyOrdered()); // task 05295: commenting this out because also for ASI-Order-Lines it shall be allowed to order // qty that is not yet fully avalable on stock // // Qty on instance ASI for SO // if (m_IsSOTrx // && getM_AttributeSetInstance_ID() != 0 // && (newRecord || is_ValueChanged("M_Product_ID") // || is_ValueChanged("M_AttributeSetInstance_ID") // || is_ValueChanged("M_Warehouse_ID"))) // { // MProduct product = getProduct(); // if (product.isStocked()) // { // int M_AttributeSet_ID = product.getM_AttributeSet_ID(); // boolean isInstance = M_AttributeSet_ID != 0; // if (isInstance) // { // MAttributeSet mas = MAttributeSet.get(getCtx(), M_AttributeSet_ID); // isInstance = mas.isInstanceAttribute(); // } // // Max // if (isInstance) // { // MStorage[] storages = MStorage.getWarehouse(getCtx(), // Services.get(IWarehouseAdvisor.class).evaluateWarehouse(this).getM_Warehouse_ID(), // getM_Product_ID(), getM_AttributeSetInstance_ID(), // M_AttributeSet_ID, false, null, true, get_TrxName()); // BigDecimal qty = Env.ZERO; // for (int i = 0; i < storages.length; i++) // { // if (storages[i].getM_AttributeSetInstance_ID() == getM_AttributeSetInstance_ID()) // qty = qty.add(storages[i].getQtyOnHand()); // } // // if (getQtyOrdered().compareTo(qty) > 0) // { // log.warn("Qty - Stock=" + qty + ", Ordered=" + getQtyOrdered()); // log.error("QtyInsufficient", "=" + qty); // return false; // } // } // } // stocked // } // SO instance // FreightAmt Not used if (Env.ZERO.compareTo(getFreightAmt()) != 0) setFreightAmt(Env.ZERO); // Set Tax // metas: Steuer muss immer ermittelt werden, da durch eine Anschriftenaenderung im Kopf auch // Steueraenderungen in Positionen auftreten. // if (getC_Tax_ID() == 0) if (!setTax()) { return false; } // metas ende // Get Line No if (getLine() == 0) { String sql = "SELECT COALESCE(MAX(Line),0)+10 FROM C_OrderLine WHERE C_Order_ID=?"; int ii = DB.getSQLValue(get_TrxName(), sql, getC_Order_ID()); setLine(ii); } // Calculations & Rounding // FIXME: commented out because actually was doing nothing (see, it was updating another // instance of this order line, which is not saved), and more, setLineNetAmt is no longer called // from here // final I_C_OrderLine orderLine = InterfaceWrapperHelper.create(getCtx(), getC_OrderLine_ID(), // I_C_OrderLine.class, get_TrxName()); // Services.get(IOrderLineBL.class).setPrices(orderLine); // 07264 // commented out because we are not using this anymore // setLineNetAmt(); // extended Amount with or without tax // metas // setDiscount(); // metas ende return true; } // beforeSave