package com.salesmanager.core.business.modules.integration.shipping.impl;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.drools.KnowledgeBase;
import org.drools.runtime.StatelessKnowledgeSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.salesmanager.core.model.common.Delivery;
import com.salesmanager.core.model.merchant.MerchantStore;
import com.salesmanager.core.model.shipping.PackageDetails;
import com.salesmanager.core.model.shipping.ShippingConfiguration;
import com.salesmanager.core.model.shipping.ShippingOrigin;
import com.salesmanager.core.model.shipping.ShippingQuote;
import com.salesmanager.core.model.system.IntegrationConfiguration;
import com.salesmanager.core.model.system.IntegrationModule;
import com.salesmanager.core.modules.constants.Constants;
import com.salesmanager.core.modules.integration.IntegrationException;
import com.salesmanager.core.modules.integration.shipping.model.ShippingQuotePrePostProcessModule;
/**
* Decides which shipping method is going to be used based on a decision table
* @author carlsamson
*
*/
public class ShippingDecisionPreProcessorImpl implements ShippingQuotePrePostProcessModule {
private static final Logger LOGGER = LoggerFactory.getLogger(ShippingDecisionPreProcessorImpl.class);
private final static String MODULE_CODE = "shippingDecisionModule";
private StatelessKnowledgeSession shippingMethodDecision;
private KnowledgeBase kbase;
@Override
public void prePostProcessShippingQuotes(ShippingQuote quote,
List<PackageDetails> packages, BigDecimal orderTotal,
Delivery delivery, ShippingOrigin origin, MerchantStore store,
IntegrationConfiguration globalShippingConfiguration,
IntegrationModule currentModule,
ShippingConfiguration shippingConfiguration,
List<IntegrationModule> allModules, Locale locale)
throws IntegrationException {
Validate.notNull(delivery, "Delivery cannot be null");
Validate.notNull(currentModule, "IntegrationModule cannot be null");
Validate.notNull(delivery.getCountry(), "Delivery.country cannot be null");
Validate.notNull(allModules, "List<IntegrationModule> cannot be null");
Validate.notNull(packages, "packages cannot be null");
Validate.notEmpty(packages, "packages cannot be empty");
Double distance = null;
if(quote!=null) {
//look if distance has been calculated
if(quote.getQuoteInformations()!=null) {
if(quote.getQuoteInformations().containsKey(Constants.DISTANCE_KEY)) {
distance = (Double)quote.getQuoteInformations().get(Constants.DISTANCE_KEY);
}
}
}
//calculate volume (L x W x H)
Double volume = null;
Double weight = 0D;
Double size = null;
//calculate weight, volume and largest size
for(PackageDetails pack : packages) {
weight = weight + pack.getShippingWeight();
Double tmpVolume = pack.getShippingHeight() * pack.getShippingLength() * pack.getShippingWidth();
if(volume == null || tmpVolume.doubleValue() > volume.doubleValue()) { //take the largest volume
volume = tmpVolume;
}
//largest size
List<Double> sizeList = new ArrayList<Double>();
sizeList.add(pack.getShippingHeight());
sizeList.add(pack.getShippingLength());
sizeList.add(pack.getShippingWidth());
Double maxSize = (Double)Collections.max(sizeList);
if(size==null || maxSize.doubleValue() > size.doubleValue()) {
size = maxSize.doubleValue();
}
}
//Build a ShippingInputParameters
ShippingInputParameters inputParameters = new ShippingInputParameters();
inputParameters.setWeight((long)weight.doubleValue());
inputParameters.setCountry(delivery.getCountry().getIsoCode());
if(delivery.getZone()!=null) {
inputParameters.setProvince(delivery.getZone().getCode());
} else {
inputParameters.setProvince(delivery.getState());
}
//inputParameters.setModuleName(currentModule.getCode());
if(delivery.getZone().getCode()!=null) {
inputParameters.setProvince(delivery.getZone().getCode());
}
if(size!=null) {
inputParameters.setSize((long)size.doubleValue());
}
if(distance!=null) {
double ddistance = distance.doubleValue();
long ldistance = (long)ddistance;
inputParameters.setDistance(ldistance);
}
if(volume!=null) {
inputParameters.setVolume((long)volume.doubleValue());
}
LOGGER.debug("Setting input parameters " + inputParameters.toString());
System.out.println(inputParameters.toString());
shippingMethodDecision.execute(Arrays.asList(new Object[] { inputParameters }));
LOGGER.debug("Using shipping nodule " + inputParameters.getModuleName());
if(!StringUtils.isBlank(inputParameters.getModuleName())) {
for(IntegrationModule toBeUsed : allModules) {
if(toBeUsed.getCode().equals(inputParameters.getModuleName())) {
quote.setCurrentShippingModule(toBeUsed);
break;
}
}
}
}
public StatelessKnowledgeSession getShippingMethodDecision() {
return shippingMethodDecision;
}
public void setShippingMethodDecision(StatelessKnowledgeSession shippingMethodDecision) {
this.shippingMethodDecision = shippingMethodDecision;
}
public KnowledgeBase getKbase() {
return kbase;
}
public void setKbase(KnowledgeBase kbase) {
this.kbase = kbase;
}
@Override
public String getModuleCode() {
return MODULE_CODE;
}
}