All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.broadleafcommerce.core.offer.service.discount.domain.PromotableOrderAdjustmentImpl Maven / Gradle / Ivy

There is a newer version: 3.1.15-GA
Show newest version
/*
 * #%L
 * BroadleafCommerce Framework
 * %%
 * Copyright (C) 2009 - 2013 Broadleaf Commerce
 * %%
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * #L%
 */
package org.broadleafcommerce.core.offer.service.discount.domain;

import org.broadleafcommerce.common.money.Money;
import org.broadleafcommerce.core.offer.domain.Offer;
import org.broadleafcommerce.core.offer.service.type.OfferDiscountType;

import java.math.BigDecimal;
import java.math.RoundingMode;

public class PromotableOrderAdjustmentImpl implements PromotableOrderAdjustment {
    
    private static final long serialVersionUID = 1L;
    
    protected PromotableCandidateOrderOffer promotableCandidateOrderOffer;
    protected PromotableOrder promotableOrder;
    protected Money adjustmentValue;
    protected Offer offer;
    
    protected boolean roundOfferValues = true;
    protected int roundingScale = 2;
    protected RoundingMode roundingMode = RoundingMode.HALF_EVEN;

    public PromotableOrderAdjustmentImpl(PromotableCandidateOrderOffer promotableCandidateOrderOffer, PromotableOrder promotableOrder) {
        assert (promotableOrder != null);
        assert (promotableCandidateOrderOffer != null);

        this.promotableCandidateOrderOffer = promotableCandidateOrderOffer;
        this.promotableOrder = promotableOrder;
        this.offer = promotableCandidateOrderOffer.getOffer();
        computeAdjustmentValue();
    }
    
    public PromotableOrderAdjustmentImpl(PromotableCandidateOrderOffer promotableCandidateOrderOffer,
            PromotableOrder promotableOrder, Money adjustmentValue) {
        this(promotableCandidateOrderOffer, promotableOrder);
        if (promotableOrder.isIncludeOrderAndItemAdjustments()) {
            this.adjustmentValue = adjustmentValue;
        }
    }

    @Override
    public PromotableOrder getPromotableOrder() {
        return promotableOrder;
    }
    
    @Override
    public Offer getOffer() {
        return offer;
    }
    
    /*
     * Calculates the value of the adjustment by first getting the current value of the order and then
     * calculating the value of this adjustment.   
     * 
     * If this adjustment value is greater than the currentOrderValue (e.g. would make the order go negative
     * then the adjustment value is set to the value of the order).  
     */
    protected void computeAdjustmentValue() {
        adjustmentValue = new Money(promotableOrder.getOrderCurrency());
        Money currentOrderValue = promotableOrder.calculateSubtotalWithAdjustments();
        
        // We also need to consider order offers that have been applied when figuring out if the current value of this
        // adjustment will be more than the current subtotal of the order
        currentOrderValue = currentOrderValue.subtract(promotableOrder.calculateOrderAdjustmentTotal());

        // Note: FIXED_PRICE not calculated as this is not a valid option for offers.
        if (offer.getDiscountType().equals(OfferDiscountType.AMOUNT_OFF)) {
            adjustmentValue = new Money(offer.getValue(), promotableOrder.getOrderCurrency());            
        } else if (offer.getDiscountType().equals(OfferDiscountType.PERCENT_OFF)) {
            BigDecimal offerValue = currentOrderValue.getAmount().multiply(offer.getValue().divide(new BigDecimal("100"), 5, RoundingMode.HALF_EVEN));
            
            if (isRoundOfferValues()) {
                offerValue = offerValue.setScale(roundingScale, roundingMode);
            }
            adjustmentValue = new Money(offerValue, promotableOrder.getOrderCurrency(), 5);
        }

        if (currentOrderValue.lessThan(adjustmentValue)) {
            adjustmentValue = currentOrderValue;
        }
    }
    
    @Override
    public Money getAdjustmentValue() {
        return adjustmentValue;
    }

    /**
     * It is sometimes problematic to offer percentage-off offers with regards to rounding. For example,
     * consider an item that costs 9.99 and has a 50% promotion. To be precise, the offer value is 4.995,
     * but this may be a strange value to display to the user depending on the currency being used.
     */
    public boolean isRoundOfferValues() {
        return roundOfferValues;
    }

    /**
     * @see #isRoundOfferValues()
     * 
     * @param roundingScale
     */
    public void setRoundingScale(int roundingScale) {
        this.roundingScale = roundingScale;
    }

    public int getRoundingScale() {
        return roundingScale;
    }

    /**
     * @see #isRoundOfferValues()
     * 
     * @param roundingMode
     */
    public void setRoundingMode(RoundingMode roundingMode) {
        this.roundingMode = roundingMode;
    }

    public RoundingMode getRoundingMode() {
        return roundingMode;
    }

    @Override
    public boolean isCombinable() {
        Boolean combinable = offer.isCombinableWithOtherOffers();
        return (combinable != null && combinable);
    }

    @Override
    public boolean isTotalitarian() {
        Boolean totalitarian = offer.isTotalitarianOffer();
        return (totalitarian != null && totalitarian.booleanValue());
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy