Search in sources :

Example 46 with MOrderLine

use of org.compiere.model.MOrderLine in project adempiere by adempiere.

the class PromotionRule method applyPromotions.

public static void applyPromotions(MOrder order) throws Exception {
    //key = C_OrderLine, value = Qty to distribution
    Map<Integer, BigDecimal> orderLineQty = new LinkedHashMap<Integer, BigDecimal>();
    Map<Integer, MOrderLine> orderLineIndex = new HashMap<Integer, MOrderLine>();
    MOrderLine[] lines = order.getLines();
    boolean hasDeleteLine = false;
    for (MOrderLine ol : lines) {
        if (ol.getM_Product_ID() > 0) {
            if (ol.getQtyOrdered().signum() > 0) {
                orderLineQty.put(ol.getC_OrderLine_ID(), ol.getQtyOrdered());
                orderLineIndex.put(ol.getC_OrderLine_ID(), ol);
            }
        } else if (ol.getC_Charge_ID() > 0) {
            Number id = (Number) ol.get_Value("M_Promotion_ID");
            if (id != null && id.intValue() > 0) {
                ol.delete(false);
                hasDeleteLine = true;
            }
        }
    }
    if (orderLineQty.isEmpty())
        return;
    //refresh order
    if (hasDeleteLine) {
        order.getLines(true, null);
        order.getTaxes(true);
        order.setGrandTotal(DB.getSQLValueBD(order.get_TrxName(), "SELECT GrandTotal From C_Order WHERE C_Order_ID = ?", order.getC_Order_ID()));
    }
    Map<Integer, List<Integer>> promotions = PromotionRule.findM_Promotion_ID(order);
    if (promotions == null || promotions.isEmpty())
        return;
    BigDecimal orderAmount = order.getGrandTotal();
    //key = M_PromotionDistribution_ID, value = C_OrderLine_ID and Qty
    Map<Integer, DistributionSet> distributions = new LinkedHashMap<Integer, DistributionSet>();
    //<M_PromotionDistribution_ID, DistributionSorting>
    Map<Integer, String> sortingType = new HashMap<Integer, String>();
    OrderLineComparator olComparator = new OrderLineComparator(orderLineIndex);
    //distribute order lines
    for (Map.Entry<Integer, List<Integer>> entry : promotions.entrySet()) {
        Query query = new Query(Env.getCtx(), MTable.get(order.getCtx(), I_M_PromotionDistribution.Table_ID), "M_PromotionDistribution.M_Promotion_ID = ? AND M_PromotionDistribution.IsActive = 'Y'", order.get_TrxName());
        query.setParameters(new Object[] { entry.getKey() });
        query.setOrderBy("SeqNo");
        List<MPromotionDistribution> list = query.<MPromotionDistribution>list();
        Query rewardQuery = new Query(Env.getCtx(), MTable.get(order.getCtx(), I_M_PromotionReward.Table_ID), "M_PromotionReward.M_Promotion_ID = ? AND M_PromotionReward.IsActive = 'Y'", order.get_TrxName());
        rewardQuery.setParameters(new Object[] { entry.getKey() });
        rewardQuery.setOrderBy("SeqNo");
        List<MPromotionReward> rewardList = rewardQuery.<MPromotionReward>list();
        List<MPromotionLine> promotionLines = new ArrayList<MPromotionLine>();
        for (Integer M_PromotionLine_ID : entry.getValue()) {
            MPromotionLine promotionLine = new MPromotionLine(order.getCtx(), M_PromotionLine_ID, order.get_TrxName());
            promotionLines.add(promotionLine);
        }
        while (true) {
            boolean hasDistributionSet = false;
            Set<Integer> promotionLineSet = new HashSet<Integer>();
            Set<Integer> mandatoryLineSet = new HashSet<Integer>();
            boolean mandatoryLineNotFound = false;
            List<Integer> validPromotionLineIDs = new ArrayList<Integer>();
            for (MPromotionLine promotionLine : promotionLines) {
                if (promotionLine.getM_PromotionGroup_ID() == 0 && promotionLine.getMinimumAmt() != null && promotionLine.getMinimumAmt().signum() >= 0) {
                    if (orderAmount.compareTo(promotionLine.getMinimumAmt()) >= 0) {
                        orderAmount = orderAmount.subtract(promotionLine.getMinimumAmt());
                        validPromotionLineIDs.add(promotionLine.getM_PromotionLine_ID());
                    } else if (promotionLine.isMandatoryPL()) {
                        mandatoryLineNotFound = true;
                        break;
                    }
                }
            }
            if (mandatoryLineNotFound) {
                break;
            }
            for (MPromotionDistribution pd : list) {
                if (entry.getValue().contains(pd.getM_PromotionLine_ID())) {
                    //sort available orderline base on distribution sorting type
                    List<Integer> orderLineIdList = new ArrayList<Integer>();
                    orderLineIdList.addAll(orderLineQty.keySet());
                    if (pd.getDistributionSorting() != null) {
                        Comparator<Integer> cmp = olComparator;
                        if (pd.getDistributionSorting().equals(MPromotionDistribution.DISTRIBUTIONSORTING_Descending))
                            cmp = Collections.reverseOrder(cmp);
                        Collections.sort(orderLineIdList, cmp);
                    }
                    DistributionSet prevSet = distributions.get(pd.getM_PromotionDistribution_ID());
                    DistributionSet distributionSet = PromotionRule.calculateDistributionQty(pd, prevSet, validPromotionLineIDs, orderLineQty, orderLineIdList, order.get_TrxName());
                    if (distributionSet != null && distributionSet.setQty.signum() > 0) {
                        hasDistributionSet = true;
                        promotionLineSet.add(pd.getM_PromotionLine_ID());
                    } else {
                        if (pd.getM_PromotionLine().isMandatoryPL()) {
                            mandatoryLineSet.add(pd.getM_PromotionLine_ID());
                        }
                    }
                    distributions.put(pd.getM_PromotionDistribution_ID(), distributionSet);
                    sortingType.put(pd.getM_PromotionDistribution_ID(), pd.getDistributionSorting());
                }
            }
            if (!hasDistributionSet)
                break;
            if (mandatoryLineSet != null) {
                mandatoryLineNotFound = false;
                for (Integer id : mandatoryLineSet) {
                    if (!promotionLineSet.contains(id)) {
                        mandatoryLineNotFound = true;
                        break;
                    }
                }
                if (mandatoryLineNotFound) {
                    break;
                }
            }
            for (MPromotionReward pr : rewardList) {
                if (pr.isForAllDistribution()) {
                    Collection<DistributionSet> all = distributions.values();
                    BigDecimal totalPrice = BigDecimal.ZERO;
                    for (DistributionSet distributionSet : all) {
                        for (Map.Entry<Integer, BigDecimal> olMap : distributionSet.orderLines.entrySet()) {
                            BigDecimal qty = (BigDecimal) olMap.getValue();
                            int C_OrderLine_ID = (Integer) olMap.getKey();
                            for (MOrderLine ol : lines) {
                                if (ol.getC_OrderLine_ID() == C_OrderLine_ID) {
                                    totalPrice = totalPrice.add(ol.getPriceActual().multiply(qty));
                                    break;
                                }
                            }
                            distributionSet.orderLines.put(olMap.getKey(), BigDecimal.ZERO);
                        }
                    }
                    BigDecimal discount = BigDecimal.ZERO;
                    if (pr.getRewardType().equals(MPromotionReward.REWARDTYPE_AbsoluteAmount)) {
                        if (pr.getAmount().compareTo(totalPrice) < 0) {
                            discount = totalPrice.subtract(pr.getAmount());
                        }
                    } else if (pr.getRewardType().equals(MPromotionReward.REWARDTYPE_FlatDiscount)) {
                        discount = pr.getAmount();
                    } else if (pr.getRewardType().equals(MPromotionReward.REWARDTYPE_Percentage)) {
                        discount = pr.getAmount().divide(BigDecimal.valueOf(100.00)).multiply(totalPrice);
                    }
                    if (discount.signum() > 0) {
                        addDiscountLine(order, null, discount, BigDecimal.valueOf(1.00), pr.getC_Charge_ID(), pr.getM_Promotion());
                    }
                } else {
                    int M_PromotionDistribution_ID = pr.getM_PromotionDistribution_ID();
                    if (!distributions.containsKey(M_PromotionDistribution_ID))
                        continue;
                    int targetDistributionID = M_PromotionDistribution_ID;
                    if (!pr.isSameDistribution()) {
                        targetDistributionID = pr.getM_TargetDistribution_ID();
                        if (!distributions.containsKey(targetDistributionID))
                            continue;
                    }
                    DistributionSet distributionSet = distributions.get(targetDistributionID);
                    //sort by reward distribution sorting
                    if (pr.getDistributionSorting() != null) {
                        Comparator<Integer> cmp = new OrderLineComparator(orderLineIndex);
                        if (pr.getDistributionSorting().equals(MPromotionReward.DISTRIBUTIONSORTING_Descending))
                            cmp = Collections.reverseOrder(cmp);
                        Set<Integer> keySet = distributionSet.orderLines.keySet();
                        List<Integer> keyList = new ArrayList<Integer>();
                        keyList.addAll(keySet);
                        Collections.sort(keyList, cmp);
                        Map<Integer, BigDecimal> sortedMap = new LinkedHashMap<Integer, BigDecimal>();
                        for (Integer id : keyList) {
                            sortedMap.put(id, distributionSet.orderLines.get(id));
                        }
                        distributionSet.orderLines = sortedMap;
                    }
                    BigDecimal setBalance = distributionSet.setQty;
                    BigDecimal toApply = pr.getQty();
                    if (toApply == null || toApply.signum() == 0)
                        toApply = BigDecimal.valueOf(-1.0);
                    BigDecimal totalPrice = BigDecimal.ZERO;
                    for (Map.Entry<Integer, BigDecimal> olMap : distributionSet.orderLines.entrySet()) {
                        BigDecimal qty = olMap.getValue();
                        int C_OrderLine_ID = olMap.getKey();
                        if (qty == null || qty.signum() <= 0)
                            continue;
                        if (qty.compareTo(setBalance) >= 0) {
                            qty = setBalance;
                            setBalance = BigDecimal.ZERO;
                        } else {
                            setBalance = setBalance.subtract(qty);
                        }
                        if (toApply.signum() > 0) {
                            if (toApply.compareTo(qty) <= 0) {
                                qty = toApply;
                                toApply = BigDecimal.ZERO;
                            } else {
                                toApply = toApply.subtract(qty);
                            }
                            BigDecimal newQty = olMap.getValue();
                            newQty = newQty.subtract(qty);
                            distributionSet.orderLines.put(olMap.getKey(), newQty);
                        }
                        for (MOrderLine ol : lines) {
                            if (ol.getC_OrderLine_ID() == C_OrderLine_ID) {
                                if (pr.getRewardType().equals(MPromotionReward.REWARDTYPE_Percentage)) {
                                    BigDecimal priceActual = ol.getPriceActual();
                                    BigDecimal discount = priceActual.multiply(pr.getAmount().divide(BigDecimal.valueOf(100.00)));
                                    addDiscountLine(order, ol, discount, qty, pr.getC_Charge_ID(), pr.getM_Promotion());
                                } else if (pr.getRewardType().equals(MPromotionReward.REWARDTYPE_FlatDiscount)) {
                                    addDiscountLine(order, ol, pr.getAmount(), BigDecimal.valueOf(1.00), pr.getC_Charge_ID(), pr.getM_Promotion());
                                } else if (pr.getRewardType().equals(MPromotionReward.REWARDTYPE_AbsoluteAmount)) {
                                    BigDecimal priceActual = ol.getPriceActual();
                                    totalPrice = totalPrice.add(priceActual.multiply(qty));
                                } else {
                                    // : Gift line
                                    BigDecimal qtyreward = pr.getM_PromotionDistribution().getQty();
                                    BigDecimal qtymodulo = ol.getQtyOrdered().divide(qtyreward, 0);
                                    addGiftLine(order, ol, pr.getAmount(), pr.getQty().multiply(qtymodulo), pr.getC_Charge_ID(), pr.getM_Promotion());
                                }
                            }
                        }
                        if (toApply.signum() == 0)
                            break;
                        if (setBalance.signum() == 0)
                            break;
                    }
                    if (pr.getRewardType().equals(MPromotionReward.REWARDTYPE_AbsoluteAmount)) {
                        if (pr.getAmount().compareTo(totalPrice) < 0) {
                            addDiscountLine(order, null, totalPrice.subtract(pr.getAmount()), BigDecimal.valueOf(1.00), pr.getC_Charge_ID(), pr.getM_Promotion());
                        }
                    }
                }
            }
        }
    }
}
Also used : Query(org.compiere.model.Query) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) LinkedHashMap(java.util.LinkedHashMap) ArrayList(java.util.ArrayList) List(java.util.List) HashSet(java.util.HashSet) BigDecimal(java.math.BigDecimal) MOrderLine(org.compiere.model.MOrderLine) HashMap(java.util.HashMap) LinkedHashMap(java.util.LinkedHashMap) Map(java.util.Map)

Example 47 with MOrderLine

use of org.compiere.model.MOrderLine in project adempiere by adempiere.

the class PromotionValidator method increasePromotionCounter.

private void increasePromotionCounter(MOrder order) {
    MOrderLine[] lines = order.getLines(false, null);
    String promotionCode = (String) order.get_Value("PromotionCode");
    for (MOrderLine ol : lines) {
        if (ol.getC_Charge_ID() > 0) {
            Integer promotionID = (Integer) ol.get_Value("M_Promotion_ID");
            if (promotionID != null && promotionID.intValue() > 0) {
                int M_PromotionPreCondition_ID = findPromotionPreConditionId(order, promotionCode, promotionID);
                if (M_PromotionPreCondition_ID > 0) {
                    String update = "UPDATE M_PromotionPreCondition SET PromotionCounter = PromotionCounter + 1 WHERE M_PromotionPreCondition_ID = ?";
                    DB.executeUpdate(update, M_PromotionPreCondition_ID, order.get_TrxName());
                }
            }
        }
    }
}
Also used : MOrderLine(org.compiere.model.MOrderLine)

Example 48 with MOrderLine

use of org.compiere.model.MOrderLine in project adempiere by adempiere.

the class PromotionValidator method decreasePromotionCounter.

private void decreasePromotionCounter(MOrder order) {
    MOrderLine[] lines = order.getLines(false, null);
    String promotionCode = (String) order.get_Value("PromotionCode");
    for (MOrderLine ol : lines) {
        if (ol.getC_Charge_ID() > 0) {
            Integer promotionID = (Integer) ol.get_Value("M_Promotion_ID");
            if (promotionID != null && promotionID.intValue() > 0) {
                int M_PromotionPreCondition_ID = findPromotionPreConditionId(order, promotionCode, promotionID);
                if (M_PromotionPreCondition_ID > 0) {
                    String update = "UPDATE M_PromotionPreCondition SET PromotionCounter = PromotionCounter - 1 WHERE M_PromotionPreCondition_ID = ?";
                    DB.executeUpdate(update, M_PromotionPreCondition_ID, order.get_TrxName());
                }
            }
        }
    }
}
Also used : MOrderLine(org.compiere.model.MOrderLine)

Example 49 with MOrderLine

use of org.compiere.model.MOrderLine in project adempiere by adempiere.

the class PromotionValidator method modelChange.

public String modelChange(PO po, int type) throws Exception {
    if (po instanceof MOrderLine) {
        if (type == TYPE_AFTER_DELETE) {
            MOrderLine ol = (MOrderLine) po;
            MOrder order = ol.getParent();
            String promotionCode = (String) order.get_Value("PromotionCode");
            if (ol.getC_Charge_ID() > 0) {
                Integer promotionID = (Integer) ol.get_Value("M_Promotion_ID");
                if (promotionID != null && promotionID.intValue() > 0) {
                    int M_PromotionPreCondition_ID = findPromotionPreConditionId(order, promotionCode, promotionID);
                    if (M_PromotionPreCondition_ID > 0) {
                        String update = "UPDATE M_PromotionPreCondition SET PromotionCounter = PromotionCounter - 1 WHERE M_PromotionPreCondition_ID = ?";
                        DB.executeUpdate(update, M_PromotionPreCondition_ID, order.get_TrxName());
                    }
                }
            }
        }
    }
    return null;
}
Also used : MOrder(org.compiere.model.MOrder) MOrderLine(org.compiere.model.MOrderLine)

Example 50 with MOrderLine

use of org.compiere.model.MOrderLine in project adempiere by adempiere.

the class Doc_Order method getCommitmentsSales.

//	getCommitmentRelease
/**
	 * 	Get Commitments Sales
	 * 	@param doc document
	 * 	@param maxQty Qty invoiced/matched
	 * 	@param C_OrderLine_ID invoice line
	 *	@return commitments (order lines)
	 */
protected static DocLine[] getCommitmentsSales(Doc doc, BigDecimal maxQty, int M_InOutLine_ID) {
    int precision = -1;
    //
    ArrayList<DocLine> list = new ArrayList<DocLine>();
    String sql = "SELECT * FROM C_OrderLine ol " + "WHERE EXISTS " + "(SELECT * FROM M_InOutLine il " + "WHERE il.C_OrderLine_ID=ol.C_OrderLine_ID" + " AND il.M_InOutLine_ID=?)";
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
        pstmt = DB.prepareStatement(sql, null);
        pstmt.setInt(1, M_InOutLine_ID);
        rs = pstmt.executeQuery();
        while (rs.next()) {
            if (maxQty.signum() == 0)
                continue;
            MOrderLine line = new MOrderLine(doc.getCtx(), rs, null);
            DocLine docLine = new DocLine(line, doc);
            //	Currency
            if (precision == -1) {
                doc.setC_Currency_ID(docLine.getC_Currency_ID());
                precision = MCurrency.getStdPrecision(doc.getCtx(), docLine.getC_Currency_ID());
            }
            //	Qty
            BigDecimal Qty = line.getQtyOrdered().max(maxQty);
            docLine.setQty(Qty, false);
            //
            BigDecimal PriceActual = line.getPriceActual();
            BigDecimal PriceCost = line.getPriceCost();
            BigDecimal LineNetAmt = null;
            if (PriceCost != null && PriceCost.signum() != 0)
                LineNetAmt = Qty.multiply(PriceCost);
            else if (Qty.equals(maxQty))
                LineNetAmt = line.getLineNetAmt();
            else
                LineNetAmt = Qty.multiply(PriceActual);
            maxQty = maxQty.subtract(Qty);
            //	DR
            docLine.setAmount(LineNetAmt);
            BigDecimal PriceList = line.getPriceList();
            int C_Tax_ID = docLine.getC_Tax_ID();
            //	Correct included Tax
            if (C_Tax_ID != 0 && line.getParent().isTaxIncluded()) {
                MTax tax = MTax.get(doc.getCtx(), C_Tax_ID);
                if (!tax.isZeroTax()) {
                    BigDecimal LineNetAmtTax = tax.calculateTax(LineNetAmt, true, precision);
                    s_log.fine("LineNetAmt=" + LineNetAmt + " - Tax=" + LineNetAmtTax);
                    LineNetAmt = LineNetAmt.subtract(LineNetAmtTax);
                    BigDecimal PriceListTax = tax.calculateTax(PriceList, true, precision);
                    PriceList = PriceList.subtract(PriceListTax);
                }
            }
            //	correct included Tax
            docLine.setAmount(LineNetAmt, PriceList, Qty);
            list.add(docLine);
        }
    } catch (Exception e) {
        s_log.log(Level.SEVERE, sql, e);
    } finally {
        DB.close(rs, pstmt);
        rs = null;
        pstmt = null;
    }
    //	Return Array
    DocLine[] dl = new DocLine[list.size()];
    list.toArray(dl);
    return dl;
}
Also used : ArrayList(java.util.ArrayList) ResultSet(java.sql.ResultSet) PreparedStatement(java.sql.PreparedStatement) MTax(org.compiere.model.MTax) MOrderLine(org.compiere.model.MOrderLine) BigDecimal(java.math.BigDecimal) SQLException(java.sql.SQLException)

Aggregations

MOrderLine (org.compiere.model.MOrderLine)74 MOrder (org.compiere.model.MOrder)37 BigDecimal (java.math.BigDecimal)35 MInOutLine (org.compiere.model.MInOutLine)15 MProduct (org.compiere.model.MProduct)12 MBPartner (org.compiere.model.MBPartner)11 MInOut (org.compiere.model.MInOut)9 ResultSet (java.sql.ResultSet)8 ArrayList (java.util.ArrayList)8 Query (org.compiere.model.Query)8 PreparedStatement (java.sql.PreparedStatement)6 MInvoice (org.compiere.model.MInvoice)6 MInvoiceLine (org.compiere.model.MInvoiceLine)6 AdempiereException (org.adempiere.exceptions.AdempiereException)5 MLocator (org.compiere.model.MLocator)5 SQLException (java.sql.SQLException)4 Timestamp (java.sql.Timestamp)4 MRMALine (org.compiere.model.MRMALine)4 MDocType (org.compiere.model.MDocType)3 MMatchPO (org.compiere.model.MMatchPO)3