@Override public ShippingMetaData getShippingMetaData(MerchantStore store) throws ServiceException { ShippingMetaData metaData = new ShippingMetaData(); // configured country List<Country> countries = getShipToCountryList(store, store.getDefaultLanguage()); metaData.setShipToCountry(countries); // configured modules Map<String, IntegrationConfiguration> modules = getShippingModulesConfigured(store); List<String> moduleKeys = new ArrayList<String>(); if (modules != null) { for (String key : modules.keySet()) { moduleKeys.add(key); } } metaData.setModules(moduleKeys); // pre processors List<ShippingQuotePrePostProcessModule> preProcessors = this.shippingModulePreProcessors; List<String> preProcessorKeys = new ArrayList<String>(); if (preProcessors != null) { for (ShippingQuotePrePostProcessModule processor : preProcessors) { preProcessorKeys.add(processor.getModuleCode()); if (SHIPPING_DISTANCE.equals(processor.getModuleCode())) { metaData.setUseDistanceModule(true); } } } metaData.setPreProcessors(preProcessorKeys); // post processors List<ShippingQuotePrePostProcessModule> postProcessors = this.shippingModulePostProcessors; List<String> postProcessorKeys = new ArrayList<String>(); if (postProcessors != null) { for (ShippingQuotePrePostProcessModule processor : postProcessors) { postProcessorKeys.add(processor.getModuleCode()); } } metaData.setPostProcessors(postProcessorKeys); return metaData; }
@Override public ShippingQuote getShippingQuote( MerchantStore store, Delivery delivery, List<ShippingProduct> products, Language language) throws ServiceException { // ShippingConfiguration -> Global configuration of a given store // IntegrationConfiguration -> Configuration of a given module // IntegrationModule -> The concrete module as defined in integrationmodules.properties // delivery without postal code is accepted Validate.notNull(store, "MerchantStore must not be null"); Validate.notNull(delivery, "Delivery must not be null"); Validate.notEmpty(products, "products must not be empty"); Validate.notNull(language, "Language must not be null"); ShippingQuote shippingQuote = new ShippingQuote(); ShippingQuoteModule shippingQuoteModule = null; try { if (StringUtils.isBlank(delivery.getPostalCode())) { shippingQuote.getWarnings().add("No postal code in delivery address"); shippingQuote.setShippingReturnCode(ShippingQuote.NO_POSTAL_CODE); } // get configuration ShippingConfiguration shippingConfiguration = getShippingConfiguration(store); ShippingType shippingType = ShippingType.INTERNATIONAL; /** get shipping origin * */ ShippingOrigin shippingOrigin = shippingOriginService.getByStore(store); if (shippingOrigin == null || !shippingOrigin.isActive()) { shippingOrigin = new ShippingOrigin(); shippingOrigin.setAddress(store.getStoreaddress()); shippingOrigin.setCity(store.getStorecity()); shippingOrigin.setCountry(store.getCountry()); shippingOrigin.setPostalCode(store.getStorepostalcode()); shippingOrigin.setState(store.getStorestateprovince()); shippingOrigin.setZone(store.getZone()); } if (shippingConfiguration == null) { shippingConfiguration = new ShippingConfiguration(); } if (shippingConfiguration.getShippingType() != null) { shippingType = shippingConfiguration.getShippingType(); } // look if customer country code excluded Country shipCountry = delivery.getCountry(); if (shipCountry == null) { throw new ServiceException("Delivery country is null"); } // a ship to country is required Validate.notNull(shipCountry); Validate.notNull(store.getCountry()); if (shippingType.name().equals(ShippingType.NATIONAL.name())) { // customer country must match store country if (!shipCountry.getIsoCode().equals(store.getCountry().getIsoCode())) { shippingQuote.setShippingReturnCode( ShippingQuote.NO_SHIPPING_TO_SELECTED_COUNTRY + " " + shipCountry.getIsoCode()); return shippingQuote; } } else if (shippingType.name().equals(ShippingType.INTERNATIONAL.name())) { // customer shipping country code must be in accepted list List<String> supportedCountries = this.getSupportedCountries(store); if (!supportedCountries.contains(shipCountry.getIsoCode())) { shippingQuote.setShippingReturnCode( ShippingQuote.NO_SHIPPING_TO_SELECTED_COUNTRY + " " + shipCountry.getIsoCode()); return shippingQuote; } } // must have a shipping module configured Map<String, IntegrationConfiguration> modules = this.getShippingModulesConfigured(store); if (modules == null) { shippingQuote.setShippingReturnCode(ShippingQuote.NO_SHIPPING_MODULE_CONFIGURED); return shippingQuote; } /** uses this module name * */ String moduleName = null; IntegrationConfiguration configuration = null; for (String module : modules.keySet()) { moduleName = module; configuration = modules.get(module); // use the first active module if (configuration.isActive()) { shippingQuoteModule = this.shippingModules.get(module); if (shippingQuoteModule instanceof ShippingQuotePrePostProcessModule) { shippingQuoteModule = null; continue; } else { break; } } } if (shippingQuoteModule == null) { shippingQuote.setShippingReturnCode(ShippingQuote.NO_SHIPPING_MODULE_CONFIGURED); return shippingQuote; } /** merchant module configs * */ List<IntegrationModule> shippingMethods = this.getShippingMethods(store); IntegrationModule shippingModule = null; for (IntegrationModule mod : shippingMethods) { if (mod.getCode().equals(moduleName)) { shippingModule = mod; break; } } /** general module configs * */ if (shippingModule == null) { shippingQuote.setShippingReturnCode(ShippingQuote.NO_SHIPPING_MODULE_CONFIGURED); return shippingQuote; } // calculate order total BigDecimal orderTotal = calculateOrderTotal(products, store); List<PackageDetails> packages = this.getPackagesDetails(products, store); // free shipping ? if (shippingConfiguration.isFreeShippingEnabled()) { BigDecimal freeShippingAmount = shippingConfiguration.getOrderTotalFreeShipping(); if (freeShippingAmount != null) { if (orderTotal.doubleValue() > freeShippingAmount.doubleValue()) { if (shippingConfiguration.getFreeShippingType() == ShippingType.NATIONAL) { if (store.getCountry().getIsoCode().equals(shipCountry.getIsoCode())) { shippingQuote.setFreeShipping(true); shippingQuote.setFreeShippingAmount(freeShippingAmount); return shippingQuote; } } else { // international all shippingQuote.setFreeShipping(true); shippingQuote.setFreeShippingAmount(freeShippingAmount); return shippingQuote; } } } } // handling fees BigDecimal handlingFees = shippingConfiguration.getHandlingFees(); if (handlingFees != null) { shippingQuote.setHandlingFees(handlingFees); } // tax basis shippingQuote.setApplyTaxOnShipping(shippingConfiguration.isTaxOnShipping()); Locale locale = languageService.toLocale(language); // invoke pre processors if (!CollectionUtils.isEmpty(shippingModulePreProcessors)) { for (ShippingQuotePrePostProcessModule preProcessor : shippingModulePreProcessors) { // System.out.println("Using pre-processor " + preProcessor.getModuleCode()); preProcessor.prePostProcessShippingQuotes( shippingQuote, packages, orderTotal, delivery, shippingOrigin, store, configuration, shippingModule, shippingConfiguration, shippingMethods, locale); // TODO switch module if required if (shippingQuote.getCurrentShippingModule() != null && !shippingQuote .getCurrentShippingModule() .getCode() .equals(shippingModule.getCode())) { shippingModule = shippingQuote.getCurrentShippingModule(); moduleName = shippingModule.getCode(); shippingQuoteModule = this.shippingModules.get(shippingModule.getCode()); configuration = modules.get(shippingModule.getCode()); } } } // invoke module List<ShippingOption> shippingOptions = null; try { shippingOptions = shippingQuoteModule.getShippingQuotes( shippingQuote, packages, orderTotal, delivery, shippingOrigin, store, configuration, shippingModule, shippingConfiguration, locale); } catch (Exception e) { LOGGER.error("Error while calculating shipping", e); merchantLogService.save( new MerchantLog( store, "Can't process " + shippingModule.getModule() + " -> " + e.getMessage())); shippingQuote.setQuoteError(e.getMessage()); shippingQuote.setShippingReturnCode(ShippingQuote.ERROR); return shippingQuote; } if (shippingOptions == null && !StringUtils.isBlank(delivery.getPostalCode())) { shippingQuote.setShippingReturnCode(ShippingQuote.NO_SHIPPING_TO_SELECTED_COUNTRY); } shippingQuote.setShippingModuleCode(moduleName); // filter shipping options ShippingOptionPriceType shippingOptionPriceType = shippingConfiguration.getShippingOptionPriceType(); ShippingOption selectedOption = null; if (shippingOptions != null) { for (ShippingOption option : shippingOptions) { if (selectedOption == null) { selectedOption = option; } // set price text String priceText = pricingService.getDisplayAmount(option.getOptionPrice(), store); option.setOptionPriceText(priceText); option.setShippingModuleCode(moduleName); if (StringUtils.isBlank(option.getOptionName())) { String countryName = delivery.getCountry().getName(); if (countryName == null) { Map<String, Country> deliveryCountries = countryService.getCountriesMap(language); Country dCountry = (Country) deliveryCountries.get(delivery.getCountry().getIsoCode()); if (dCountry != null) { countryName = dCountry.getName(); } else { countryName = delivery.getCountry().getIsoCode(); } } option.setOptionName(countryName); } if (shippingOptionPriceType.name().equals(ShippingOptionPriceType.HIGHEST.name())) { if (option.getOptionPrice().longValue() > selectedOption.getOptionPrice().longValue()) { selectedOption = option; } } if (shippingOptionPriceType.name().equals(ShippingOptionPriceType.LEAST.name())) { if (option.getOptionPrice().longValue() < selectedOption.getOptionPrice().longValue()) { selectedOption = option; } } if (shippingOptionPriceType.name().equals(ShippingOptionPriceType.ALL.name())) { if (option.getOptionPrice().longValue() < selectedOption.getOptionPrice().longValue()) { selectedOption = option; } } } shippingQuote.setSelectedShippingOption(selectedOption); if (selectedOption != null && !shippingOptionPriceType.name().equals(ShippingOptionPriceType.ALL.name())) { shippingOptions = new ArrayList<ShippingOption>(); shippingOptions.add(selectedOption); } } /** set final delivery address * */ shippingQuote.setDeliveryAddress(delivery); shippingQuote.setShippingOptions(shippingOptions); /** post processors * */ // invoke pre processors if (!CollectionUtils.isEmpty(shippingModulePostProcessors)) { for (ShippingQuotePrePostProcessModule postProcessor : shippingModulePostProcessors) { // get module info // get module configuration IntegrationConfiguration integrationConfiguration = modules.get(postProcessor.getModuleCode()); IntegrationModule postProcessModule = null; for (IntegrationModule mod : shippingMethods) { if (mod.getCode().equals(postProcessor.getModuleCode())) { postProcessModule = mod; break; } } IntegrationModule module = postProcessModule; postProcessor.prePostProcessShippingQuotes( shippingQuote, packages, orderTotal, delivery, shippingOrigin, store, integrationConfiguration, module, shippingConfiguration, shippingMethods, locale); } } } catch (Exception e) { throw new ServiceException(e); } return shippingQuote; }