public static MOrderLine createOrderLine( Properties ctx, MOrder order, int productId, BigDecimal qty, BigDecimal discount, BigDecimal lineNet) throws OperationException { if (qty == null) { qty = Env.ONE; } MOrderLine orderLine = new MOrderLine(order); MProduct product = new MProduct(ctx, productId, order.get_TrxName()); MTax tax = TaxManager.getTaxFromCategory(ctx, product.getC_TaxCategory_ID(), order.get_TrxName()); orderLine.setC_Tax_ID(tax.get_ID()); orderLine.setC_UOM_ID(product.getC_UOM_ID()); orderLine.setC_BPartner_ID(order.getC_BPartner_ID()); // Must set Product Id before quantity Ordered. orderLine.setM_Product_ID(productId); orderLine.setQty(qty); orderLine.setPrice(); // Bug fix, set price to 2dp MPriceList orderPriceList = MPriceList.get(ctx, order.getM_PriceList_ID(), order.get_TrxName()); if (!orderPriceList.isTaxIncluded()) { BigDecimal taxAmt = tax.calculateTax(lineNet, true, 12); BigDecimal lineNetWithoutTax = lineNet.subtract(taxAmt); orderLine.setLineNetAmt(lineNetWithoutTax); BigDecimal unitPriceWithoutTax = lineNetWithoutTax.divide(qty, 12, BigDecimal.ROUND_HALF_DOWN); orderLine.setPriceEntered(unitPriceWithoutTax.setScale(2, BigDecimal.ROUND_HALF_UP)); orderLine.setPriceActual(unitPriceWithoutTax.setScale(2, BigDecimal.ROUND_HALF_UP)); } else { BigDecimal unitPrice = lineNet.divide(qty, 12, BigDecimal.ROUND_HALF_DOWN); orderLine.setLineNetAmt(lineNet.setScale(2, BigDecimal.ROUND_HALF_UP)); orderLine.setPriceEntered(unitPrice.setScale(2, BigDecimal.ROUND_HALF_UP)); orderLine.setPriceActual(unitPrice.setScale(2, BigDecimal.ROUND_HALF_UP)); } if (discount.doubleValue() != 0.0) { orderLine.setDiscount(); } PoManager.save(orderLine); return orderLine; }
/** * Create Order from Basket * * @param wu web User * @param wb web basket * @return true if created & processed */ private boolean createOrder(WebUser wu, WebBasket wb) { m_order = new MOrder(m_ctx, 0, null); log.fine( "AD_Client_ID=" + m_order.getAD_Client_ID() + ",AD_Org_ID=" + m_order.getAD_Org_ID() + " - " + m_order); // m_order.setC_DocTypeTarget_ID(MOrder.DocSubTypeSO_Prepay); m_order.setPaymentRule(MOrder.PAYMENTRULE_CreditCard); m_order.setDeliveryRule(MOrder.DELIVERYRULE_AfterReceipt); m_order.setInvoiceRule(MOrder.INVOICERULE_Immediate); m_order.setIsSelfService(true); if (wb.getM_PriceList_ID() > 0) m_order.setM_PriceList_ID(wb.getM_PriceList_ID()); if (wb.getSalesRep_ID() != 0) m_order.setSalesRep_ID(wb.getSalesRep_ID()); // BPartner m_order.setC_BPartner_ID(wu.getC_BPartner_ID()); m_order.setC_BPartner_Location_ID(wu.getC_BPartner_Location_ID()); m_order.setAD_User_ID(wu.getAD_User_ID()); // m_order.setSendEMail(true); m_order.setDocAction(MOrder.DOCACTION_Prepare); m_order.saveEx(); log.fine("ID=" + m_order.getC_Order_ID() + ", DocNo=" + m_order.getDocumentNo()); ArrayList<WebBasketLine> lines = wb.getLines(); for (int i = 0; i < lines.size(); i++) { WebBasketLine wbl = lines.get(i); MOrderLine ol = new MOrderLine(m_order); ol.setM_Product_ID(wbl.getM_Product_ID(), true); ol.setQty(wbl.getQuantity()); ol.setPrice(); ol.setPrice(wbl.getPrice()); ol.setTax(); ol.saveEx(); } // for all lines boolean ok = m_order.processIt(MOrder.DOCACTION_Prepare); m_order.saveEx(); // Web User = Customer if (!wu.isCustomer()) { // log.info("-------------------------------------- " + wu.isCustomer()); wu.setIsCustomer(true); wu.save(); // log.info("-------------------------------------- " + wu.isCustomer()); } BigDecimal amt = m_order.getGrandTotal(); log.info("Amt=" + amt); return ok; } // createOrder
/** Create PO's */ private void createPO() { int noOrders = 0; String info = ""; // MOrder order = null; MWarehouse wh = null; X_T_Replenish[] replenishs = getReplenish("M_WarehouseSource_ID IS NULL"); for (int i = 0; i < replenishs.length; i++) { X_T_Replenish replenish = replenishs[i]; if (wh == null || wh.getM_Warehouse_ID() != replenish.getM_Warehouse_ID()) wh = MWarehouse.get(getCtx(), replenish.getM_Warehouse_ID()); // if (order == null || order.getC_BPartner_ID() != replenish.getC_BPartner_ID() || order.getM_Warehouse_ID() != replenish.getM_Warehouse_ID()) { order = new MOrder(getCtx(), 0, get_TrxName()); order.setIsSOTrx(false); order.setC_DocTypeTarget_ID(p_C_DocType_ID); final MBPartner bp = new MBPartner(getCtx(), replenish.getC_BPartner_ID(), get_TrxName()); Services.get(IOrderBL.class).setBPartner(order, bp); order.setSalesRep_ID(getAD_User_ID()); order.setDescription(Msg.getMsg(getCtx(), "Replenishment")); // Set Org/WH order.setAD_Org_ID(wh.getAD_Org_ID()); order.setM_Warehouse_ID(wh.getM_Warehouse_ID()); if (!order.save()) return; log.debug(order.toString()); noOrders++; info += " - " + order.getDocumentNo(); } MOrderLine line = new MOrderLine(order); line.setM_Product_ID(replenish.getM_Product_ID()); line.setQty(replenish.getQtyToOrder()); line.setPrice(); line.save(); } m_info = "#" + noOrders + info; log.info(m_info); } // createPO
/** * Process. Create purchase order(s) for the resonse(s) and lines marked as Selected Winner using * the selected Purchase Quantity (in RfQ Line Quantity) . If a Response is marked as Selected * Winner, all lines are created (and Selected Winner of other responses ignored). If there is no * response marked as Selected Winner, the lines are used. * * @return message */ protected String doIt() throws Exception { MRfQ rfq = new MRfQ(getCtx(), p_C_RfQ_ID, get_TrxName()); if (rfq.get_ID() == 0) throw new IllegalArgumentException("No RfQ found"); log.info(rfq.toString()); // Complete MRfQResponse[] responses = rfq.getResponses(true, true); log.config("#Responses=" + responses.length); if (responses.length == 0) throw new IllegalArgumentException("No completed RfQ Responses found"); // Winner for entire RfQ for (int i = 0; i < responses.length; i++) { MRfQResponse response = responses[i]; if (!response.isSelectedWinner()) continue; // MBPartner bp = new MBPartner(getCtx(), response.getC_BPartner_ID(), get_TrxName()); log.config("Winner=" + bp); MOrder order = new MOrder(getCtx(), 0, get_TrxName()); order.setIsSOTrx(false); if (p_C_DocType_ID != 0) order.setC_DocTypeTarget_ID(p_C_DocType_ID); else order.setC_DocTypeTarget_ID(); order.setBPartner(bp); order.setC_BPartner_Location_ID(response.getC_BPartner_Location_ID()); order.setSalesRep_ID(rfq.getSalesRep_ID()); if (response.getDateWorkComplete() != null) order.setDatePromised(response.getDateWorkComplete()); else if (rfq.getDateWorkComplete() != null) order.setDatePromised(rfq.getDateWorkComplete()); order.saveEx(); // MRfQResponseLine[] lines = response.getLines(false); for (int j = 0; j < lines.length; j++) { // Respones Line MRfQResponseLine line = lines[j]; if (!line.isActive()) continue; MRfQResponseLineQty[] qtys = line.getQtys(false); // Response Line Qty for (int k = 0; k < qtys.length; k++) { MRfQResponseLineQty qty = qtys[k]; // Create PO Lline for all Purchase Line Qtys if (qty.getRfQLineQty().isActive() && qty.getRfQLineQty().isPurchaseQty()) { MOrderLine ol = new MOrderLine(order); ol.setM_Product_ID( line.getRfQLine().getM_Product_ID(), qty.getRfQLineQty().getC_UOM_ID()); ol.setDescription(line.getDescription()); ol.setQty(qty.getRfQLineQty().getQty()); BigDecimal price = qty.getNetAmt(); ol.setPrice(); ol.setPrice(price); ol.saveEx(); } } } response.setC_Order_ID(order.getC_Order_ID()); response.saveEx(); return order.getDocumentNo(); } // Selected Winner on Line Level int noOrders = 0; for (int i = 0; i < responses.length; i++) { MRfQResponse response = responses[i]; MBPartner bp = null; MOrder order = null; // For all Response Lines MRfQResponseLine[] lines = response.getLines(false); for (int j = 0; j < lines.length; j++) { MRfQResponseLine line = lines[j]; if (!line.isActive() || !line.isSelectedWinner()) continue; // New/different BP if (bp == null || bp.getC_BPartner_ID() != response.getC_BPartner_ID()) { bp = new MBPartner(getCtx(), response.getC_BPartner_ID(), get_TrxName()); order = null; } log.config("Line=" + line + ", Winner=" + bp); // New Order if (order == null) { order = new MOrder(getCtx(), 0, get_TrxName()); order.setIsSOTrx(false); order.setC_DocTypeTarget_ID(); order.setBPartner(bp); order.setC_BPartner_Location_ID(response.getC_BPartner_Location_ID()); order.setSalesRep_ID(rfq.getSalesRep_ID()); order.saveEx(); noOrders++; addLog(0, null, null, order.getDocumentNo()); } // For all Qtys MRfQResponseLineQty[] qtys = line.getQtys(false); for (int k = 0; k < qtys.length; k++) { MRfQResponseLineQty qty = qtys[k]; if (qty.getRfQLineQty().isActive() && qty.getRfQLineQty().isPurchaseQty()) { MOrderLine ol = new MOrderLine(order); ol.setM_Product_ID( line.getRfQLine().getM_Product_ID(), qty.getRfQLineQty().getC_UOM_ID()); ol.setDescription(line.getDescription()); ol.setQty(qty.getRfQLineQty().getQty()); BigDecimal price = qty.getNetAmt(); ol.setPrice(); ol.setPrice(price); ol.saveEx(); } } // for all Qtys } // for all Response Lines if (order != null) { response.setC_Order_ID(order.getC_Order_ID()); response.saveEx(); } } return "#" + noOrders; } // doIt
/** * ************************************************************************ 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