Beispiel #1
0
  /**
   * 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
Beispiel #2
0
 /**
  * Set Price for Product and PriceList. Use only if newly created. Uses standard price list of not
  * set by order constructor
  */
 public void setPrice() {
   if (getM_Product_ID() <= 0) return;
   if (m_M_PriceList_ID <= 0) {
     throw new AdempiereException(
         "@NotFound@ @M_Pricelist_ID@ @C_BPartner_ID@ " + getC_BPartner().getName());
   }
   setPrice(m_M_PriceList_ID);
 } // setPrice
Beispiel #3
0
  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;
  }
Beispiel #4
0
  /** 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
Beispiel #6
0
  /**
   * ************************************************************************ 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
  /**
   * Creates a counter document for an order. The counter document is also processed, if there is a
   * {@link I_C_DocTypeCounter} with a <code>DocAction</code> configured.
   *
   * <p>This implementation partially uses legacy code. I didn't yet get to refactor/remove/replace
   * it all.
   */
  @Override
  public DocAction createCounterDocument(final DocAction document) {
    final I_C_Order order = InterfaceWrapperHelper.create(document, I_C_Order.class);
    final MOrder orderPO = LegacyAdapters.convertToPO(order);

    final I_C_DocType counterDocType = retrieveCounterDocTypeOrNull(document);

    final I_AD_Org counterOrg = retrieveCounterOrgOrNull(document);

    final de.metas.adempiere.model.I_C_Order counterOrder =
        InterfaceWrapperHelper.newInstance(
            de.metas.adempiere.model.I_C_Order.class, document.getCtx());
    final MOrder counterOrderPO = (MOrder) LegacyAdapters.convertToPO(counterOrder);

    counterOrder.setAD_Org(counterOrg); // 09700

    //
    counterOrder.setC_DocTypeTarget(counterDocType);
    counterOrder.setIsSOTrx(counterDocType.isSOTrx());

    // the new order needs to figure out the pricing by itself
    counterOrder.setM_PricingSystem(null);
    counterOrder.setM_PriceList(null);

    counterOrder.setDateOrdered(order.getDateOrdered());
    counterOrder.setDateAcct(order.getDateAcct());
    counterOrder.setDatePromised(order.getDatePromised());

    counterOrder.setRef_Order_ID(order.getC_Order_ID());

    final I_C_BPartner counterBP = retrieveCounterPartnerOrNull(document);
    counterOrderPO.setBPartner(counterBP);

    final I_M_Warehouse counterWarehouse =
        Services.get(IWarehouseAdvisor.class).evaluateOrderWarehouse(counterOrder);
    counterOrder.setM_Warehouse(counterWarehouse);

    // References (should not be required)
    counterOrder.setSalesRep_ID(order.getSalesRep_ID());
    InterfaceWrapperHelper.save(counterOrder);

    // copy the order lines
    final boolean counter = true;
    final boolean copyASI = true;
    counterOrderPO.copyLinesFrom(orderPO, counter, copyASI);

    // Update copied lines
    final boolean requery = true;
    final MOrderLine[] counterLines = counterOrderPO.getLines(requery, null);
    for (int i = 0; i < counterLines.length; i++) {
      final MOrderLine counterLine = counterLines[i];
      counterLine.setOrder(counterOrderPO); // copies header values (BP, etc.)
      counterLine.setPrice();
      counterLine.setTax();
      InterfaceWrapperHelper.save(counterLine);
    }
    logger.debug(counterOrder.toString());

    // Document Action
    final MDocTypeCounter counterDT =
        MDocTypeCounter.getCounterDocType(document.getCtx(), order.getC_DocType_ID());
    if (counterDT != null) {
      if (counterDT.getDocAction() != null) {
        counterOrder.setDocAction(counterDT.getDocAction());
        Services.get(IDocActionBL.class)
            .processEx(
                counterOrder,
                counterDT.getDocAction(),
                null); // not expecting a particular docStatus (e.g. for prepay orders, it might be
                       // "waiting to payment")
      }
    }
    return counterOrderPO;
  }