shopizer-aplcache
Changes
sm-core/.classpath 12(+12 -0)
sm-core/.gitignore 1(+1 -0)
sm-core/.project 23(+23 -0)
sm-core/pom.xml 657(+657 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/category/dao/CategoryDao.java 51(+51 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/category/dao/CategoryDaoImpl.java 370(+370 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/category/model/Category.java 213(+213 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/category/model/CategoryDescription.java 101(+101 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/category/service/CategoryService.java 102(+102 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/category/service/CategoryServiceImpl.java 437(+437 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/common/CatalogServiceHelper.java 100(+100 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductAttributeDao.java 24(+24 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductAttributeDaoImpl.java 122(+122 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductOptionDao.java 31(+31 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductOptionDaoImpl.java 125(+125 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductOptionValueDao.java 24(+24 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductOptionValueDaoImpl.java 120(+120 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/availability/ProductAvailabilityDao.java 8(+8 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/availability/ProductAvailabilityDaoImpl.java 14(+14 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/file/DigitalProductDao.java 13(+13 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/file/DigitalProductDaoImpl.java 58(+58 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/image/ProductImageDao.java 10(+10 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/image/ProductImageDaoImpl.java 39(+39 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/manufacturer/ManufacturerDao.java 21(+21 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/manufacturer/ManufacturerDaoImpl.java 117(+117 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/price/ProductPriceDao.java 8(+8 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/price/ProductPriceDaoImpl.java 37(+37 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/ProductDaoImpl.java 986(+986 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/relationship/ProductRelationshipDao.java 31(+31 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/relationship/ProductRelationshipDaoImpl.java 290(+290 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/review/ProductReviewDao.java 22(+22 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/review/ProductReviewDaoImpl.java 175(+175 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/type/ProductTypeDao.java 8(+8 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/type/ProductTypeDaoImpl.java 14(+14 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/AttributeCriteria.java 26(+26 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductAttribute.java 241(+241 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductOption.java 149(+149 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductOptionDescription.java 51(+51 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductOptionType.java 7(+7 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductOptionValue.java 160(+160 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductOptionValueDescription.java 38(+38 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/availability/ProductAvailability.java 184(+184 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/description/ProductDescription.java 105(+105 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/file/DigitalProduct.java 76(+76 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/file/ProductImageSize.java 10(+10 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/image/ProductImage.java 132(+132 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/image/ProductImageDescription.java 48(+48 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/manufacturer/Manufacturer.java 113(+113 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/manufacturer/ManufacturerDescription.java 72(+72 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/price/FinalPrice.java 107(+107 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/price/ProductPrice.java 182(+182 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/price/ProductPriceDescription.java 41(+41 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/price/ProductPriceType.java 7(+7 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/Product.java 418(+418 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/ProductCriteria.java 82(+82 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/ProductList.java 25(+25 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/relationship/ProductRelationship.java 121(+121 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/relationship/ProductRelationshipType.java 7(+7 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/review/ProductReview.java 150(+150 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/review/ProductReviewDescription.java 56(+56 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/type/ProductType.java 84(+84 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductAttributeService.java 29(+29 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductAttributeServiceImpl.java 92(+92 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductOptionService.java 32(+32 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductOptionServiceImpl.java 105(+105 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductOptionValueService.java 29(+29 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductOptionValueServiceImpl.java 110(+110 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/availability/ProductAvailabilityService.java 12(+12 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/availability/ProductAvailabilityServiceImpl.java 42(+42 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/file/DigitalProductService.java 24(+24 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/file/DigitalProductServiceImpl.java 110(+110 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/image/ProductImageService.java 66(+66 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/image/ProductImageServiceImpl.java 206(+206 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/manufacturer/ManufacturerService.java 38(+38 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/manufacturer/ManufacturerServiceImpl.java 98(+98 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/price/ProductPriceService.java 15(+15 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/price/ProductPriceServiceImpl.java 65(+65 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/PricingService.java 102(+102 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/PricingServiceImpl.java 94(+94 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/ProductService.java 58(+58 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/ProductServiceImpl.java 401(+401 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/relationship/ProductRelationshipService.java 89(+89 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/relationship/ProductRelationshipServiceImpl.java 147(+147 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/review/ProductReviewService.java 22(+22 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/review/ProductReviewServiceImpl.java 95(+95 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/type/ProductTypeService.java 11(+11 -0)
sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/type/ProductTypeServiceImpl.java 34(+34 -0)
sm-core/src/main/java/com/salesmanager/core/business/common/model/audit/AuditListener.java 24(+24 -0)
sm-core/src/main/java/com/salesmanager/core/business/common/model/audit/AuditSection.java 57(+57 -0)
sm-core/src/main/java/com/salesmanager/core/business/content/model/ContentDescription.java 98(+98 -0)
sm-core/src/main/java/com/salesmanager/core/business/content/model/OutputContentFile.java 26(+26 -0)
sm-core/src/main/java/com/salesmanager/core/business/content/model/StaticContentFile.java 18(+18 -0)
sm-core/src/main/java/com/salesmanager/core/business/content/service/ContentService.java 149(+149 -0)
sm-core/src/main/java/com/salesmanager/core/business/content/service/ContentServiceImpl.java 390(+390 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/CustomerRegistrationException.java 33(+33 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerAttributeDao.java 21(+21 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerAttributeDaoImpl.java 140(+140 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionDao.java 28(+28 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionDaoImpl.java 107(+107 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionSetDao.java 26(+26 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionSetDaoImpl.java 150(+150 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionValueDao.java 18(+18 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionValueDaoImpl.java 92(+92 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/exception/CustomerNotFoundException.java 22(+22 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerAttribute.java 104(+104 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOption.java 182(+182 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOptionDescription.java 58(+58 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOptionSet.java 92(+92 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOptionType.java 7(+7 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOptionValue.java 154(+154 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOptionValueDescription.java 39(+39 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/model/CustomerCriteria.java 43(+43 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerAttributeService.java 29(+29 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerAttributeServiceImpl.java 78(+78 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionService.java 27(+27 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionServiceImpl.java 94(+94 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionSetService.java 35(+35 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionSetServiceImpl.java 84(+84 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionValueService.java 24(+24 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionValueServiceImpl.java 94(+94 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/service/CustomerService.java 38(+38 -0)
sm-core/src/main/java/com/salesmanager/core/business/customer/service/CustomerServiceImpl.java 112(+112 -0)
sm-core/src/main/java/com/salesmanager/core/business/generic/dao/SalesManagerEntityDao.java 104(+104 -0)
sm-core/src/main/java/com/salesmanager/core/business/generic/dao/SalesManagerEntityDaoImpl.java 102(+102 -0)
sm-core/src/main/java/com/salesmanager/core/business/generic/dao/SalesManagerJpaDaoSupport.java 221(+221 -0)
sm-core/src/main/java/com/salesmanager/core/business/generic/exception/ConversionException.java 31(+31 -0)
sm-core/src/main/java/com/salesmanager/core/business/generic/exception/ServiceException.java 71(+71 -0)
sm-core/src/main/java/com/salesmanager/core/business/generic/model/SalesManagerEntity.java 105(+105 -0)
sm-core/src/main/java/com/salesmanager/core/business/generic/service/SalesManagerEntityService.java 92(+92 -0)
sm-core/src/main/java/com/salesmanager/core/business/generic/service/SalesManagerEntityServiceImpl.java 121(+121 -0)
sm-core/src/main/java/com/salesmanager/core/business/generic/service/TransactionalAspectAwareService.java 12(+12 -0)
sm-core/src/main/java/com/salesmanager/core/business/generic/util/EntityManagerUtils.java 53(+53 -0)
sm-core/src/main/java/com/salesmanager/core/business/generic/util/GenericEntityUtils.java 44(+44 -0)
sm-core/src/main/java/com/salesmanager/core/business/merchant/dao/MerchantStoreDaoImpl.java 146(+146 -0)
sm-core/src/main/java/com/salesmanager/core/business/merchant/service/MerchantStoreService.java 20(+20 -0)
sm-core/src/main/java/com/salesmanager/core/business/merchant/service/MerchantStoreServiceImpl.java 159(+159 -0)
sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderaccount/OrderAccountDao.java 9(+9 -0)
sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderaccount/OrderAccountDaoImpl.java 15(+15 -0)
sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderproduct/OrderProductDao.java 8(+8 -0)
sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderproduct/OrderProductDaoImpl.java 15(+15 -0)
sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderproduct/OrderProductDownloadDao.java 12(+12 -0)
sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderproduct/OrderProductDownloadDaoImpl.java 59(+59 -0)
sm-core/src/main/java/com/salesmanager/core/business/order/model/filehistory/FileHistory.java 136(+136 -0)
sm-core/src/main/java/com/salesmanager/core/business/order/model/orderaccount/OrderAccount.java 106(+106 -0)
sm-core/src/main/java/com/salesmanager/core/business/order/model/orderaccount/OrderAccountProduct.java 166(+166 -0)
sm-core/src/main/java/com/salesmanager/core/business/order/model/orderproduct/OrderProduct.java 140(+140 -0)
sm-core/src/main/java/com/salesmanager/core/business/order/model/orderproduct/OrderProductAttribute.java 132(+132 -0)
sm-core/src/main/java/com/salesmanager/core/business/order/model/orderproduct/OrderProductDownload.java 90(+90 -0)
sm-core/src/main/java/com/salesmanager/core/business/order/model/orderproduct/OrderProductPrice.java 138(+138 -0)
sm-core/src/main/java/com/salesmanager/core/business/order/model/orderstatus/OrderStatus.java 20(+20 -0)
sm-core/src/main/java/com/salesmanager/core/business/order/model/orderstatus/OrderStatusHistory.java 107(+107 -0)
sm-core/src/main/java/com/salesmanager/core/business/order/service/orderproduct/OrderProductDownloadService.java 17(+17 -0)
sm-core/src/main/java/com/salesmanager/core/business/order/service/orderproduct/OrderProductDownloadServiceImpl.java 58(+58 -0)
sm-core/src/main/java/com/salesmanager/core/business/order/service/OrderServiceImpl.java 516(+516 -0)
sm-core/src/main/java/com/salesmanager/core/business/payments/dao/TransactionDaoImpl.java 33(+33 -0)
sm-core/src/main/java/com/salesmanager/core/business/payments/model/CreditCardPayment.java 53(+53 -0)
sm-core/src/main/java/com/salesmanager/core/business/payments/service/PaymentService.java 103(+103 -0)
sm-core/src/main/java/com/salesmanager/core/business/payments/service/PaymentServiceImpl.java 694(+694 -0)
sm-core/src/main/java/com/salesmanager/core/business/payments/service/TransactionService.java 27(+27 -0)
sm-core/src/main/java/com/salesmanager/core/business/payments/service/TransactionServiceImpl.java 157(+157 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/country/dao/CountryDao.java 12(+12 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/country/dao/CountryDaoImpl.java 36(+36 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/country/model/Country.java 130(+130 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/country/model/CountryDescription.java 43(+43 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/country/service/CountryService.java 25(+25 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/country/service/CountryServiceImpl.java 125(+125 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/currency/dao/CurrencyDao.java 8(+8 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/currency/dao/CurrencyDaoImpl.java 35(+35 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/currency/model/Currency.java 90(+90 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/currency/service/CurrencyService.java 10(+10 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/currency/service/CurrencyServiceImpl.java 25(+25 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/geozone/model/GeoZone.java 92(+92 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/geozone/model/GeoZoneDescription.java 36(+36 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/init/service/InitializationDatabase.java 11(+11 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/init/service/InitializationDatabaseImpl.java 269(+269 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/language/dao/LanguageDao.java 7(+7 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/language/dao/LanguageDaoImpl.java 10(+10 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/language/model/Language.java 114(+114 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/language/service/LanguageService.java 22(+22 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/language/service/LanguageServiceImpl.java 108(+108 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/zone/imports/ZoneLoader.java 31(+31 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/zone/imports/ZoneTransient.java 28(+28 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/zone/model/ZoneDescription.java 43(+43 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/zone/service/ZoneService.java 25(+25 -0)
sm-core/src/main/java/com/salesmanager/core/business/reference/zone/service/ZoneServiceImpl.java 132(+132 -0)
sm-core/src/main/java/com/salesmanager/core/business/search/service/SearchServiceImpl.java 316(+316 -0)
sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingConfiguration.java 359(+359 -0)
sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingDescription.java 7(+7 -0)
sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingOption.java 101(+101 -0)
sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingOptionPriceType.java 7(+7 -0)
sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingPackageType.java 7(+7 -0)
sm-core/src/main/java/com/salesmanager/core/business/shipping/service/ShippingService.java 198(+198 -0)
sm-core/src/main/java/com/salesmanager/core/business/shipping/service/ShippingServiceImpl.java 750(+750 -0)
sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/dao/ShoppingCartDao.java 34(+34 -0)
sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/dao/ShoppingCartDaoImpl.java 160(+160 -0)
sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/dao/ShoppingCartItemDao.java 10(+10 -0)
sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/dao/ShoppingCartItemDaoImpl.java 14(+14 -0)
sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/model/ShoppingCart.java 150(+150 -0)
sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/model/ShoppingCartAttributeItem.java 115(+115 -0)
sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/model/ShoppingCartItem.java 229(+229 -0)
sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/service/ShoppingCartCalculationService.java 43(+43 -0)
sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/service/ShoppingCartCalculationServiceImpl.java 123(+123 -0)
sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/service/ShoppingCartService.java 86(+86 -0)
sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/service/ShoppingCartServiceImpl.java 542(+542 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/dao/MerchantConfigurationDao.java 21(+21 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/dao/MerchantConfigurationDaoImpl.java 69(+69 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/dao/ModuleConfigurationDao.java 14(+14 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/dao/ModuleConfigurationDaoImpl.java 52(+52 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/dao/SystemConfigurationDao.java 8(+8 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/dao/SystemConfigurationDaoImpl.java 14(+14 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/dao/SystemNotificationDaoImpl.java 14(+14 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/model/CustomIntegrationConfiguration.java 14(+14 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/model/IntegrationConfiguration.java 169(+169 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/model/IntegrationModule.java 255(+255 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/model/MerchantConfiguration.java 124(+124 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/model/MerchantConfigurationType.java 9(+9 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/model/SystemConfiguration.java 80(+80 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/model/SystemNotification.java 138(+138 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/service/EmailServiceImpl.java 66(+66 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/service/MerchantConfigurationService.java 31(+31 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/service/MerchantConfigurationServiceImpl.java 116(+116 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/service/MerchantLogService.java 12(+12 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/service/MerchantLogServiceImpl.java 36(+36 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/service/ModuleConfigurationService.java 17(+17 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/service/ModuleConfigurationServiceImpl.java 144(+144 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/service/SystemConfigurationService.java 12(+12 -0)
sm-core/src/main/java/com/salesmanager/core/business/system/service/SystemConfigurationServiceImpl.java 34(+34 -0)
sm-core/src/main/java/com/salesmanager/core/business/tax/dao/taxclass/TaxClassDaoImpl.java 78(+78 -0)
sm-core/src/main/java/com/salesmanager/core/business/tax/dao/taxrate/TaxRateDaoImpl.java 185(+185 -0)
sm-core/src/main/java/com/salesmanager/core/business/tax/model/taxrate/TaxRateDescription.java 52(+52 -0)
sm-core/src/main/java/com/salesmanager/core/business/tax/service/TaxClassServiceImpl.java 56(+56 -0)
sm-core/src/main/java/com/salesmanager/core/business/user/service/PermissionServiceImpl.java 106(+106 -0)
sm-core/src/main/java/com/salesmanager/core/business/user/service/UserServiceLDAPImpl.java 106(+106 -0)
sm-core/src/main/java/com/salesmanager/core/modules/cms/content/CmsStaticContentFileManagerInfinispanImpl.java 445(+445 -0)
sm-core/src/main/java/com/salesmanager/core/modules/cms/content/StaticContentFileManager.java 13(+13 -0)
sm-core/src/main/java/com/salesmanager/core/modules/cms/content/StaticContentFileManagerImpl.java 110(+110 -0)
sm-core/src/main/java/com/salesmanager/core/modules/cms/impl/StaticContentCacheManagerImpl.java 42(+42 -0)
sm-core/src/main/java/com/salesmanager/core/modules/cms/product/CmsImageFileManagerInfinispanImpl.java 515(+515 -0)
sm-core/src/main/java/com/salesmanager/core/modules/cms/product/ProductFileManagerImpl.java 356(+356 -0)
sm-core/src/main/java/com/salesmanager/core/modules/integration/IntegrationException.java 61(+61 -0)
sm-core/src/main/java/com/salesmanager/core/modules/integration/payment/impl/BeanStreamPayment.java 755(+755 -0)
sm-core/src/main/java/com/salesmanager/core/modules/integration/payment/impl/MoneyOrderPayment.java 119(+119 -0)
sm-core/src/main/java/com/salesmanager/core/modules/integration/payment/impl/PayPalExpressCheckoutPayment.java 653(+653 -0)
sm-core/src/main/java/com/salesmanager/core/modules/integration/payment/impl/PayPalRestPayment.java 262(+262 -0)
sm-core/src/main/java/com/salesmanager/core/modules/integration/payment/model/PaymentModule.java 49(+49 -0)
sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/impl/CanadaPostShippingQuote.java 563(+563 -0)
sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/impl/CustomWeightBasedShippingQuote.java 153(+153 -0)
sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/impl/DefaultPackagingImpl.java 436(+436 -0)
sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/impl/UPSShippingQuote.java 681(+681 -0)
sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/impl/USPSShippingQuote.java 721(+721 -0)
sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/CustomShippingQuoteItem.java 22(+22 -0)
sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/CustomShippingQuotesConfiguration.java 87(+87 -0)
sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/CustomShippingQuotesRegion.java 88(+88 -0)
sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/CustomShippingQuoteWeightItem.java 40(+40 -0)
sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/Packaging.java 18(+18 -0)
sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/ShippingQuoteModule.java 24(+24 -0)
sm-core/src/main/java/com/salesmanager/core/utils/reference/ConfigurationModulesLoader.java 103(+103 -0)
sm-core/src/main/java/com/salesmanager/core/utils/reference/IntegrationModulesLoader.java 190(+190 -0)
sm-core/src/main/resources/log4j.properties 13(+13 -0)
sm-core/src/main/resources/reference/zoneconfig.json 1888(+1888 -0)
sm-core/src/main/resources/spring/spring-context.xml 120(+120 -0)
sm-core/src/test/java/com/salesmanager/test/catalog/SearchByProductAttributeTestCase.java 442(+442 -0)
sm-core/src/test/java/com/salesmanager/test/core/SalesManagerCoreTestExecutionListener.java 29(+29 -0)
sm-core/src/test/resources/log4j.properties 14(+14 -0)
Details
sm-core/.classpath 12(+12 -0)
diff --git a/sm-core/.classpath b/sm-core/.classpath
new file mode 100644
index 0000000..b77ae7b
--- /dev/null
+++ b/sm-core/.classpath
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" output="target/classes" path="src/main/java"/>
+ <classpathentry kind="src" path="target/generated-sources/querydsl"/>
+ <classpathentry kind="src" path="target/generated-sources/apt"/>
+ <classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
+ <classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
+ <classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/>
+ <classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
+ <classpathentry kind="output" path="target/classes"/>
+</classpath>
sm-core/.gitignore 1(+1 -0)
diff --git a/sm-core/.gitignore b/sm-core/.gitignore
new file mode 100644
index 0000000..ea8c4bf
--- /dev/null
+++ b/sm-core/.gitignore
@@ -0,0 +1 @@
+/target
sm-core/.project 23(+23 -0)
diff --git a/sm-core/.project b/sm-core/.project
new file mode 100644
index 0000000..23f3a60
--- /dev/null
+++ b/sm-core/.project
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>sm-core</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.maven.ide.eclipse.maven2Builder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ <nature>org.maven.ide.eclipse.maven2Nature</nature>
+ </natures>
+</projectDescription>
sm-core/pom.xml 657(+657 -0)
diff --git a/sm-core/pom.xml b/sm-core/pom.xml
new file mode 100644
index 0000000..9e97a00
--- /dev/null
+++ b/sm-core/pom.xml
@@ -0,0 +1,657 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>com.shopizer</groupId>
+ <artifactId>sm-core</artifactId>
+ <version>2.0-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <name>sm-core</name>
+ <url>http://www.shopizer.com</url>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <jdk.version>1.6</jdk.version>
+
+
+ <jackson-version>1.9.13</jackson-version>
+ <axis-version>1.4</axis-version>
+ <jaxws.api.version>2.1</jaxws.api.version>
+ <jaxws.version>2.1.4</jaxws.version>
+ <jsr181.version>1.0-MR1</jsr181.version>
+ <jsr250.version>1.0</jsr250.version>
+ <org.elasticsearch-version>0.90.2</org.elasticsearch-version>
+ <jasperreports-version>3.7.4</jasperreports-version>
+
+ <freemarker.version>2.3.19</freemarker.version>
+ <org.slf4j-version>1.6.6</org.slf4j-version>
+ <hibernate.ehcache.version>3.5.1-Final</hibernate.ehcache.version>
+ <sm-core.hibernate-entitymanager-version>4.1.2</sm-core.hibernate-entitymanager-version>
+ <sm-core.hibernate-jpamodelgen.version>1.1.1.Final</sm-core.hibernate-jpamodelgen.version>
+ <sm-core.aspectj.version>1.5.4</sm-core.aspectj.version>
+ <sm-core.mysql-connector-java>5.1.19</sm-core.mysql-connector-java>
+ <sm-core.junit.version>4.9</sm-core.junit.version>
+ <sm-core.org.springframework.version>3.1.0.RELEASE</sm-core.org.springframework.version>
+ <sm-core.c3p0.version>0.9.1.2</sm-core.c3p0.version>
+ <sm-core.querydsl.version>2.3.3</sm-core.querydsl.version>
+ <sm-core.jodatime.version>2.0</sm-core.jodatime.version>
+ <sm-core.jodatime-hibernate.version>1.3</sm-core.jodatime-hibernate.version>
+ <sm-core.javassist.version>3.3</sm-core.javassist.version>
+ <sm-search.version>0.0.3</sm-search.version>
+ </properties>
+
+ <dependencies>
+
+ <!--<dependency>
+ <groupId>com.shopizer</groupId>
+ <artifactId>com.shopizer.authorizenet</artifactId>
+ <version>0.0.1-SNAPSHOT</version>
+ </dependency>-->
+
+ <!-- sm-search -->
+ <dependency>
+ <groupId>com.shopizer</groupId>
+ <artifactId>sm-search</artifactId>
+ <version>${sm-search.version}</version>
+ </dependency>
+
+
+ <!-- Loggers -->
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <version>${org.slf4j-version}</version>
+ </dependency>
+
+ <!-- Hibernate -->
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-core</artifactId>
+ <version>${sm-core.hibernate-entitymanager-version}</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>javassist</artifactId>
+ <groupId>org.javassist</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-entitymanager</artifactId>
+ <version>${sm-core.hibernate-entitymanager-version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>asm</groupId>
+ <artifactId>asm</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>asm</groupId>
+ <artifactId>asm-attrs</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>cglib</groupId>
+ <artifactId>cglib</artifactId>
+ </exclusion>
+ <exclusion>
+ <artifactId>javassist</artifactId>
+ <groupId>javassist</groupId>
+ </exclusion>
+ <exclusion>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-core</artifactId>
+ </exclusion>
+ <exclusion>
+ <artifactId>javassist</artifactId>
+ <groupId>org.javassist</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <!-- Hibernate ehcache -->
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-ehcache</artifactId>
+ <version>${hibernate.ehcache.version}</version>
+ </dependency>
+
+ <!-- Javassist -->
+ <dependency>
+ <groupId>javassist</groupId>
+ <artifactId>javassist</artifactId>
+ <version>${sm-core.javassist.version}</version>
+ </dependency>
+
+ <!-- QueryDsl -->
+ <dependency>
+ <groupId>com.mysema.querydsl</groupId>
+ <artifactId>querydsl-apt</artifactId>
+ <version>${sm-core.querydsl.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.mysema.querydsl</groupId>
+ <artifactId>querydsl-core</artifactId>
+ <version>${sm-core.querydsl.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.mysema.querydsl</groupId>
+ <artifactId>querydsl-jpa</artifactId>
+ <version>${sm-core.querydsl.version}</version>
+ </dependency>
+
+ <!-- Pool c3p0 -->
+ <dependency>
+ <groupId>c3p0</groupId>
+ <artifactId>c3p0</artifactId>
+ <version>${sm-core.c3p0.version}</version>
+ </dependency>
+
+ <!-- Spring -->
+ <!--
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-asm</artifactId>
+ <version>${sm-core.org.springframework-security.version}</version>
+ </dependency>
+ -->
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-aop</artifactId>
+ <version>${sm-core.org.springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-aspects</artifactId>
+ <version>${sm-core.org.springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-beans</artifactId>
+ <version>${sm-core.org.springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <version>${sm-core.org.springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <version>${sm-core.org.springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-expression</artifactId>
+ <version>${sm-core.org.springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-orm</artifactId>
+ <version>${sm-core.org.springframework.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ <version>${sm-core.org.springframework.version}</version>
+ </dependency>
+
+ <!-- JSR 303 with Hibernate Validator -->
+ <dependency>
+ <groupId>javax.validation</groupId>
+ <artifactId>validation-api</artifactId>
+ <version>1.0.0.GA</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-validator</artifactId>
+ <version>4.3.0.Final</version>
+ </dependency>
+
+ <!-- AspectJ -->
+ <dependency>
+ <groupId>aspectj</groupId>
+ <artifactId>aspectjrt</artifactId>
+ <version>${sm-core.aspectj.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>aspectj</groupId>
+ <artifactId>aspectjweaver</artifactId>
+ <version>${sm-core.aspectj.version}</version>
+ </dependency>
+
+ <!-- Mysql Connector -->
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ <version>${sm-core.mysql-connector-java}</version>
+ </dependency>
+
+ <!-- H2 Connector -->
+ <dependency>
+ <groupId>com.h2database</groupId>
+ <artifactId>h2</artifactId>
+ <version>1.3.152</version>
+ </dependency>
+
+
+ <!-- Jackson JSON Processor -->
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-mapper-asl</artifactId>
+ <version>${jackson-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.googlecode.json-simple</groupId>
+ <artifactId>json-simple</artifactId>
+ <version>1.1.1</version>
+ </dependency>
+
+ <!-- File Upload -->
+ <dependency>
+ <groupId>commons-fileupload</groupId>
+ <artifactId>commons-fileupload</artifactId>
+ <version>1.2.2</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.0.1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-collections</groupId>
+ <artifactId>commons-collections</artifactId>
+ <version>3.2.1</version>
+ </dependency>
+
+ <!-- Apache common -->
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <version>3.0</version>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-validator</groupId>
+ <artifactId>commons-validator</artifactId>
+ <version>1.4.0</version>
+ </dependency>
+
+ <!--
+ <dependency>
+ <groupId>org.jboss.cache</groupId>
+ <artifactId>jbosscache-core</artifactId>
+ <version>3.2.5.GA</version>
+ </dependency>
+ -->
+
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <version>2.6</version>
+ </dependency>
+
+
+ <dependency>
+ <groupId>commons-httpclient</groupId>
+ <artifactId>commons-httpclient</artifactId>
+ <version>3.1</version>
+ </dependency>
+
+
+
+ <!-- JodaTime -->
+ <dependency>
+ <groupId>joda-time</groupId>
+ <artifactId>joda-time</artifactId>
+ <version>${sm-core.jodatime.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jadira.usertype</groupId>
+ <artifactId>usertype.core</artifactId>
+ <version>3.0.0.CR1</version>
+ </dependency>
+
+
+ <!-- Infinispan -->
+ <dependency>
+ <groupId>org.infinispan</groupId>
+ <artifactId>infinispan-core</artifactId>
+ <version>5.1.6.FINAL</version>
+ </dependency>
+
+ <!-- TO REMOVE -->
+ <dependency>
+ <groupId>org.infinispan</groupId>
+ <artifactId>infinispan-cachestore-bdbje</artifactId>
+ <version>5.1.4.FINAL</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.infinispan</groupId>
+ <artifactId>infinispan-cachestore-jdbc</artifactId>
+ <version>5.1.4.FINAL</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.infinispan</groupId>
+ <artifactId>infinispan-tree</artifactId>
+ <version>5.1.6.FINAL</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.freemarker</groupId>
+ <artifactId>freemarker</artifactId>
+ <version>${freemarker.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.mail</groupId>
+ <artifactId>mail</artifactId>
+ <version>1.4.5</version>
+ </dependency>
+
+
+ <dependency>
+ <groupId>org.jopendocument</groupId>
+ <artifactId>jOpenDocument</artifactId>
+ <version>1.3b1</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.lowagie</groupId>
+ <artifactId>itext</artifactId>
+ <version>4.2.1</version>
+ </dependency>
+
+
+ <!-- integration -->
+ <!--
+ <dependency>
+ <groupId>com.paypal.sdk</groupId>
+ <artifactId>rest-api-sdk</artifactId>
+ <version>0.7.1</version>
+ </dependency>
+ -->
+
+ <dependency>
+ <groupId>com.paypal.sdk</groupId>
+ <artifactId>merchantsdk</artifactId>
+ <version>2.6.109</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.maxmind.geoip2</groupId>
+ <artifactId>geoip2</artifactId>
+ <version>0.7.0</version>
+ </dependency>
+
+
+
+ <!-- Test dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${sm-core.junit.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>${sm-core.org.springframework.version}</version>
+ <scope>test</scope>
+ </dependency>
+
+ <!-- <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc5</artifactId>
+ <version>11.1.0.7.0</version> <scope>provided</scope> </dependency> -->
+ </dependencies>
+
+ <repositories>
+ <!-- For testing against latest Spring snapshots -->
+ <repository>
+ <id>org.springframework.maven.snapshot</id>
+ <name>Spring Maven Snapshot Repository</name>
+ <url>http://maven.springframework.org/snapshot</url>
+ <releases><enabled>false</enabled></releases>
+ <snapshots><enabled>true</enabled></snapshots>
+ </repository>
+ <!-- For developing against latest Spring milestones -->
+ <repository>
+ <id>org.springframework.maven.milestone</id>
+ <name>Spring Maven Milestone Repository</name>
+ <url>http://maven.springframework.org/milestone</url>
+ <snapshots><enabled>false</enabled></snapshots>
+ </repository>
+ <repository>
+ <id>org.jboss.repository.releases</id>
+ <name>JBoss Maven Release Repository</name>
+ <url>https://repository.jboss.org/nexus/content/repositories/releases</url>
+ <snapshots><enabled>false</enabled></snapshots>
+ </repository>
+ </repositories>
+
+ <build>
+ <!--
+ Annotation processor to be generated in target/generated-sources
+ The build will generate the required annotated classes in generated-sources
+ Then will jump to the regular build in pluginManagement
+
+ mvn clean
+ mvn install
+
+ ** if the install phase complains on missing Qxyz classes then
+
+ mvn clean
+ mvn generate-sources
+ mvn install
+
+ *** Want to have the schema generated
+
+ ** hbm2ddl not working
+ mvn hibernate3:hbm2ddl
+
+ -->
+ <plugins>
+ <plugin>
+ <groupId>org.bsc.maven</groupId>
+ <artifactId>maven-processor-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>process</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>com.mysema.maven</groupId>
+ <artifactId>maven-apt-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>process</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>target/generated-sources/querydsl</outputDirectory>
+ <processor>com.mysema.query.apt.jpa.JPAAnnotationProcessor</processor>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>2.3.2</version>
+ <configuration>
+ <source>${jdk.version}</source>
+ <target>${jdk.version}</target>
+ <encoding>${project.build.sourceEncoding}</encoding>
+ <compilerArgument>-proc:none</compilerArgument>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <version>2.12</version>
+ <configuration>
+ <skipTests>true</skipTests>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>2.2</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-install-plugin</artifactId>
+ <version>2.3.1</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-release-plugin</artifactId>
+ <version>2.2.2</version>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.3</version>
+ </plugin>
+ <plugin>
+ <groupId>org.bsc.maven</groupId>
+ <artifactId>maven-processor-plugin</artifactId>
+ <version>2.0.5</version>
+ <configuration>
+ <outputDirectory>target/generated-sources</outputDirectory>
+ <options>
+ <fullyAnnotationConfigured>true</fullyAnnotationConfigured>
+ <addSuppressWarningsAnnotation>true</addSuppressWarningsAnnotation>
+ </options>
+ </configuration>
+ <executions>
+ <execution>
+ <id>process</id>
+ <goals>
+ <goal>process</goal>
+ </goals>
+ <phase>generate-sources</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.bsc.maven</groupId>
+ <artifactId>maven-processor-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>process</id>
+ <goals>
+ <goal>process</goal>
+ </goals>
+ <phase>generate-sources</phase>
+ <configuration>
+ <options>
+ <fullyAnnotationConfigured>true</fullyAnnotationConfigured>
+ <addSuppressWarningsAnnotation>true</addSuppressWarningsAnnotation>
+ </options>
+ </configuration>
+ </execution>
+ </executions>
+ <dependencies>
+ <dependency>
+ <groupId>org.hibernate</groupId>
+ <artifactId>hibernate-jpamodelgen</artifactId>
+ <version>${sm-core.hibernate-jpamodelgen.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <plugin>
+ <groupId>com.mysema.maven</groupId>
+ <artifactId>maven-apt-plugin</artifactId>
+ <version>1.0.2</version>
+ <configuration>
+ <outputDirectory>target/generated-sources/querydsl</outputDirectory>
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>process</goal>
+ </goals>
+ <configuration>
+ <processor>com.mysema.query.apt.jpa.JPAAnnotationProcessor</processor>
+ </configuration>
+ </execution>
+ </executions>
+ <dependencies>
+ <dependency>
+ <groupId>com.mysema.querydsl</groupId>
+ <artifactId>querydsl-apt</artifactId>
+ <version>${sm-core.querydsl.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <!-- hbm2ddl Hibernate entities to schema -->
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>hibernate3-maven-plugin</artifactId>
+ <version>2.2</version><!-- 2.2 -->
+ <executions>
+ <execution>
+ <phase>process-classes</phase>
+ <goals>
+ <goal>hbm2ddl</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <components>
+ <component>
+ <name>hbm2ddl</name>
+ <implementation>jpaconfiguration</implementation>
+ </component>
+ </components>
+ <componentProperties>
+ <persistenceunit>sm-unit</persistenceunit>
+ <!--<propertyfile>src/test/resources/hbm2ddl.properties</propertyfile>-->
+ <outputfilename>schema.ddl</outputfilename>
+ <drop>false</drop>
+ <create>true</create>
+ <export>false</export>
+ <format>true</format>
+ </componentProperties>
+ </configuration>
+ </plugin>
+ <!--This plugin's configuration is used to store Eclipse m2e settings
+ only. It has no influence on the Maven build itself. -->
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>aspectj-maven-plugin</artifactId>
+ <versionRange>[1.0,)</versionRange>
+ <goals>
+ <goal>test-compile</goal>
+ <goal>compile</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <execute />
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/category/dao/CategoryDao.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/category/dao/CategoryDao.java
new file mode 100644
index 0000000..dff49b7
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/category/dao/CategoryDao.java
@@ -0,0 +1,51 @@
+package com.salesmanager.core.business.catalog.category.dao;
+
+import java.util.List;
+
+import com.salesmanager.core.business.catalog.category.model.Category;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface CategoryDao extends SalesManagerEntityDao<Long, Category> {
+
+ List<Category> listBySeUrl(MerchantStore store, String seUrl);
+
+ List<Category> listByStoreAndParent(MerchantStore store, Category category);
+
+ List<Category> listByLineage(MerchantStore store, String lineage);
+
+ List<Category> getByName(MerchantStore store, String name, Language language);
+
+ Category getByCode(MerchantStore store, String code);
+
+ List<Category> listByStore(MerchantStore store);
+
+ List<Category> listByStore(MerchantStore store, Language language);
+
+ Category getById(Long id);
+
+ List<Category> listByDepth(MerchantStore store, int depth);
+
+ List<Category> listByDepth(MerchantStore store, int depth, Language language);
+
+ List<Category> listByLineage(String merchantStoreCode, String lineage);
+
+ Category getByCode(String merchantStoreCode, String code);
+
+ Category getBySeUrl(MerchantStore store, String seUrl);
+
+ List<Category> listByParent(Category category, Language language);
+
+ Category getByLanguage(long categoryId, Language language);
+
+ List<Object[]> countProductsByCategories(MerchantStore store,
+ List<Long> categoryIds);
+
+ List<Category> getByCodes(MerchantStore store, List<String> codes,
+ Language language);
+
+ List<Category> getByIds(MerchantStore store, List<Long> ids,
+ Language language);
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/category/dao/CategoryDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/category/dao/CategoryDaoImpl.java
new file mode 100644
index 0000000..99cb5cd
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/category/dao/CategoryDaoImpl.java
@@ -0,0 +1,370 @@
+package com.salesmanager.core.business.catalog.category.dao;
+
+import java.util.Date;
+import java.util.List;
+
+import javax.persistence.Query;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.catalog.category.model.Category;
+import com.salesmanager.core.business.catalog.category.model.QCategory;
+import com.salesmanager.core.business.catalog.category.model.QCategoryDescription;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Repository("categoryDao")
+public class CategoryDaoImpl extends SalesManagerEntityDaoImpl<Long, Category> implements CategoryDao {
+
+ public CategoryDaoImpl() {
+ super();
+ }
+
+ @Override
+ public List<Category> getByName(MerchantStore store, String name, Language language) {
+ QCategory qCategory = QCategory.category;
+ QCategoryDescription qDescription = QCategoryDescription.categoryDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCategory)
+ .leftJoin(qCategory.descriptions, qDescription).fetch()
+ .leftJoin(qCategory.merchantStore).fetch()
+ .where(qDescription.name.like("%" + name + "%")
+ .and(qDescription.language.id.eq(language.getId()))
+ .and(qCategory.merchantStore.id.eq(store.getId())))
+ .orderBy(qCategory.sortOrder.asc());
+
+
+
+ List<Category> categories = query.list(qCategory);
+ return categories;
+ }
+
+
+
+ @Override
+ public List<Category> listBySeUrl(MerchantStore store,String seUrl) {
+ QCategory qCategory = QCategory.category;
+ QCategoryDescription qDescription = QCategoryDescription.categoryDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCategory)
+ .leftJoin(qCategory.descriptions, qDescription).fetch()
+ .leftJoin(qCategory.merchantStore).fetch()
+ .where(qDescription.seUrl.like(seUrl)
+ .and(qCategory.merchantStore.id.eq(store.getId())))
+ .orderBy(qDescription._super.title.desc(), qDescription._super.name.desc(), qDescription.language.id.desc()).orderBy(qCategory.sortOrder.asc());
+
+ return query.list(qCategory);
+ }
+
+ @Override
+ public Category getBySeUrl(MerchantStore store,String seUrl) {
+ QCategory qCategory = QCategory.category;
+ QCategoryDescription qDescription = QCategoryDescription.categoryDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCategory)
+ .leftJoin(qCategory.descriptions, qDescription).fetch()
+ .leftJoin(qCategory.merchantStore).fetch()
+ .where(qDescription.seUrl.eq(seUrl)
+ .and(qCategory.merchantStore.id.eq(store.getId())));
+
+
+ return query.uniqueResult(qCategory);
+ }
+
+ @Override
+ public Category getByCode(MerchantStore store, String code) {
+ QCategory qCategory = QCategory.category;
+ QCategoryDescription qDescription = QCategoryDescription.categoryDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCategory)
+ .leftJoin(qCategory.descriptions, qDescription).fetch()
+ .leftJoin(qCategory.merchantStore).fetch()
+ .where(qCategory.code.eq(code)
+ .and(qCategory.merchantStore.id.eq(store.getId())));
+
+ return query.uniqueResult(qCategory);
+ }
+
+ @Override
+ public List<Category> getByCodes(MerchantStore store, List<String> codes, Language language) {
+ QCategory qCategory = QCategory.category;
+ QCategoryDescription qDescription = QCategoryDescription.categoryDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCategory)
+ .leftJoin(qCategory.descriptions, qDescription).fetch()
+ .leftJoin(qCategory.merchantStore).fetch()
+ .where(qCategory.code.in(codes)
+ .and(qCategory.merchantStore.id.eq(store.getId()))
+ .and(qDescription.language.id.eq(language.getId())))
+ .orderBy(qCategory.sortOrder.asc(), qCategory.lineage.asc(), qCategory.lineage.asc(), qCategory.depth.asc(), qDescription.language.id.desc());
+
+ return query.list(qCategory);
+ }
+
+ @Override
+ public List<Category> getByIds(MerchantStore store, List<Long> ids, Language language) {
+ QCategory qCategory = QCategory.category;
+ QCategoryDescription qDescription = QCategoryDescription.categoryDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCategory)
+ .leftJoin(qCategory.descriptions, qDescription).fetch()
+ .leftJoin(qCategory.merchantStore).fetch()
+ .where(qCategory.id.in(ids)
+ .and(qCategory.merchantStore.id.eq(store.getId()))
+ .and(qDescription.language.id.eq(language.getId())))
+ .orderBy(qCategory.sortOrder.asc(), qCategory.lineage.asc(), qCategory.lineage.asc(), qCategory.depth.asc(), qDescription.language.id.desc());
+
+ return query.list(qCategory);
+ }
+
+ @Override
+ public Category getByLanguage(long categoryId, Language language) {
+ QCategory qCategory = QCategory.category;
+ QCategoryDescription qDescription = QCategoryDescription.categoryDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCategory)
+ .leftJoin(qCategory.descriptions, qDescription).fetch()
+ .leftJoin(qCategory.merchantStore).fetch()
+ .where(qCategory.id.eq(categoryId)
+ .and(qDescription.language.code.eq(language.getCode())));
+
+
+ return query.uniqueResult(qCategory);
+ }
+
+ @Override
+ public Category getByCode(String merchantStoreCode, String code) {
+ QCategory qCategory = QCategory.category;
+ QCategoryDescription qDescription = QCategoryDescription.categoryDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCategory)
+ .leftJoin(qCategory.descriptions, qDescription).fetch()
+ .leftJoin(qCategory.merchantStore).fetch()
+ .where(qCategory.code.eq(code)
+ .and(qCategory.merchantStore.code.eq(merchantStoreCode)));
+
+
+ return query.uniqueResult(qCategory);
+ }
+
+ @Override
+ public Category getById(Long id) {
+ QCategory qCategory = QCategory.category;
+ QCategoryDescription qDescription = QCategoryDescription.categoryDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCategory)
+ .leftJoin(qCategory.descriptions, qDescription).fetch()
+ .leftJoin(qCategory.merchantStore).fetch()
+ .where(qCategory.id.eq(id));
+
+ return query.uniqueResult(qCategory);
+ }
+
+ @Override
+ public List<Category> listByLineage(MerchantStore store, String lineage) {
+ QCategory qCategory = QCategory.category;
+ QCategoryDescription qDescription = QCategoryDescription.categoryDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCategory)
+ .leftJoin(qCategory.descriptions, qDescription).fetch()
+ .leftJoin(qCategory.merchantStore).fetch()
+ .where(qCategory.lineage.like(new StringBuilder().append(lineage).append("%").toString())
+ .and(qCategory.merchantStore.id.eq(store.getId())))
+ .orderBy(qCategory.sortOrder.asc(), qCategory.lineage.asc(), qCategory.lineage.asc(), qCategory.depth.asc(), qDescription.language.id.desc());
+
+ return query.listDistinct(qCategory);
+ }
+
+ @Override
+ public List<Category> listByLineage(String merchantStoreCode, String lineage) {
+ QCategory qCategory = QCategory.category;
+ QCategoryDescription qDescription = QCategoryDescription.categoryDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCategory)
+ .leftJoin(qCategory.descriptions, qDescription).fetch()
+ .leftJoin(qCategory.merchantStore).fetch()
+ .where(qCategory.lineage.like(new StringBuilder().append(lineage).append("%").toString())
+ .and(qCategory.merchantStore.code.eq(merchantStoreCode)))
+ .orderBy(qCategory.sortOrder.asc(),qCategory.lineage.asc(), qCategory.lineage.asc(), qCategory.depth.asc(), qDescription.language.id.desc());
+
+ return query.listDistinct(qCategory);
+ }
+
+ @Override
+ public List<Category> listByDepth(MerchantStore store, int depth) {
+ QCategory qCategory = QCategory.category;
+ QCategoryDescription qDescription = QCategoryDescription.categoryDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCategory)
+ .leftJoin(qCategory.descriptions, qDescription).fetch()
+ .leftJoin(qCategory.merchantStore).fetch()
+ .where(qCategory.depth.eq(depth)
+ .and(qCategory.merchantStore.id.eq(store.getId())))
+ .orderBy(qCategory.sortOrder.asc(), qCategory.lineage.asc(), qCategory.lineage.asc(), qCategory.depth.asc(), qDescription.language.id.desc());
+
+ return query.listDistinct(qCategory);
+ }
+
+ @Override
+ public List<Category> listByDepth(MerchantStore store, int depth, Language language) {
+ QCategory qCategory = QCategory.category;
+ QCategoryDescription qDescription = QCategoryDescription.categoryDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCategory)
+ .leftJoin(qCategory.descriptions, qDescription).fetch()
+ .leftJoin(qCategory.merchantStore).fetch()
+ .where(qCategory.depth.eq(depth)
+ .and(qCategory.merchantStore.id.eq(store.getId()))
+ .and(qDescription.language.id.eq(language.getId())))
+ .orderBy(qCategory.sortOrder.asc(), qCategory.lineage.asc(), qCategory.lineage.asc(), qCategory.depth.asc(), qDescription.language.id.desc());
+
+ return query.listDistinct(qCategory);
+ }
+
+ @Override
+ public List<Category> listByParent(Category category, Language language) {
+
+ QCategory qCategory = QCategory.category;
+ QCategoryDescription qDescription = QCategoryDescription.categoryDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCategory)
+ .leftJoin(qCategory.descriptions, qDescription).fetch()
+ .leftJoin(qCategory.merchantStore).fetch()
+ .leftJoin(qCategory.parent).fetch()
+ .where(qCategory.parent.id.eq(category.getId())
+ .and(qCategory.merchantStore.id.eq(category.getMerchantStore().getId())))
+ .orderBy(qCategory.lineage.asc(), qCategory.lineage.asc(), qCategory.depth.asc(), qDescription.language.id.desc());
+
+ return query.listDistinct(qCategory);
+
+ }
+
+
+
+ @Override
+ public List<Category> listByStoreAndParent(MerchantStore store, Category category) {
+ QCategory qCategory = QCategory.category;
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ if (store == null) {
+ if (category == null) {
+ query.from(qCategory)
+ .where(qCategory.parent.isNull())
+ .orderBy(qCategory.sortOrder.asc(),qCategory.id.desc());
+ } else {
+ query.from(qCategory)
+ .where(qCategory.parent.eq(category))
+ .orderBy(qCategory.sortOrder.asc(),qCategory.id.desc());
+ }
+ } else {
+ if (category == null) {
+ query.from(qCategory)
+ .where(qCategory.parent.isNull()
+ .and(qCategory.merchantStore.eq(store)))
+ .orderBy(qCategory.sortOrder.asc(),qCategory.id.desc());
+ } else {
+ query.from(qCategory)
+ .where(qCategory.parent.eq(category)
+ .and(qCategory.merchantStore.eq(store)))
+ .orderBy(qCategory.sortOrder.asc(),qCategory.id.desc());
+ }
+ }
+
+ return query.list(qCategory);
+ }
+
+
+
+
+ @Override
+ public List<Category> listByStore(MerchantStore store) {
+ QCategory qCategory = QCategory.category;
+ QCategoryDescription qDescription = QCategoryDescription.categoryDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCategory)
+ .leftJoin(qCategory.descriptions, qDescription).fetch()
+ .leftJoin(qCategory.merchantStore).fetch()
+ .where(qCategory.merchantStore.id.eq(store.getId()))
+ .orderBy(qCategory.sortOrder.asc(),qCategory.id.asc());
+
+ return query.listDistinct(qCategory);
+ }
+
+ @Override
+ public List<Object[]> countProductsByCategories(MerchantStore store, List<Long> categoryIds) {
+
+
+ StringBuilder qs = new StringBuilder();
+ qs.append("select categories, count(product.id) from Product product ");
+ qs.append("inner join product.categories categories ");
+ qs.append("where categories.id in (:cid) ");
+ qs.append("and product.available=true and product.dateAvailable<=:dt ");
+ qs.append("group by categories.id");
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+ q.setParameter("cid", categoryIds);
+ q.setParameter("dt", new Date());
+
+
+
+ @SuppressWarnings("unchecked")
+ List<Object[]> counts = q.getResultList();
+
+
+ return counts;
+
+
+ }
+
+ @Override
+ public List<Category> listByStore(MerchantStore store, Language language) {
+ QCategory qCategory = QCategory.category;
+ QCategoryDescription qDescription = QCategoryDescription.categoryDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCategory)
+ .leftJoin(qCategory.descriptions, qDescription).fetch()
+ .leftJoin(qCategory.merchantStore).fetch()
+ .where((qCategory.merchantStore.id.eq(store.getId()))
+ .and(qDescription.language.id.eq(language.getId())))
+ .orderBy(qCategory.sortOrder.asc(),qCategory.id.asc());
+
+ return query.listDistinct(qCategory);
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/category/model/Category.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/category/model/Category.java
new file mode 100755
index 0000000..4c4e889
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/category/model/Category.java
@@ -0,0 +1,213 @@
+package com.salesmanager.core.business.catalog.category.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.UniqueConstraint;
+import javax.validation.Valid;
+
+import org.hibernate.validator.constraints.NotEmpty;
+
+import com.salesmanager.core.business.common.model.audit.AuditListener;
+import com.salesmanager.core.business.common.model.audit.AuditSection;
+import com.salesmanager.core.business.common.model.audit.Auditable;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@EntityListeners(value = AuditListener.class)
+@Table(name = "CATEGORY", schema= SchemaConstant.SALESMANAGER_SCHEMA,uniqueConstraints=
+ @UniqueConstraint(columnNames = {"MERCHANT_ID", "CODE"}) )
+
+
+public class Category extends SalesManagerEntity<Long, Category> implements Auditable {
+ private static final long serialVersionUID = -846291242449186747L;
+
+ @Id
+ @Column(name = "CATEGORY_ID", unique=true, nullable=false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "CATEGORY_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @Embedded
+ private AuditSection auditSection = new AuditSection();
+
+ @Valid
+ @OneToMany(mappedBy="category", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
+ private List<CategoryDescription> descriptions = new ArrayList<CategoryDescription>();
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="MERCHANT_ID", nullable=false)
+ private MerchantStore merchantStore;
+
+ @ManyToOne
+ @JoinColumn(name = "PARENT_ID")
+ private Category parent;
+
+ @OneToMany(mappedBy = "parent", cascade = CascadeType.REMOVE, orphanRemoval = true)
+ private List<Category> categories = new ArrayList<Category>();
+
+ @Column(name = "CATEGORY_IMAGE", length=100)
+ private String categoryImage;
+
+ @Column(name = "SORT_ORDER")
+ private Integer sortOrder = 0;
+
+ @Column(name = "CATEGORY_STATUS")
+ private boolean categoryStatus;
+
+ @Column(name = "VISIBLE")
+ private boolean visible;
+
+ @Column(name = "DEPTH")
+ private Integer depth;
+
+ @Column(name = "LINEAGE")
+ private String lineage;
+
+ @NotEmpty
+ @Column(name="CODE", length=100, nullable=false)
+ private String code;
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public Category() {
+ }
+
+ public Category(MerchantStore store) {
+ this.merchantStore = store;
+ this.id = 0L;
+ }
+
+ @Override
+ public Long getId() {
+ return this.id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ @Override
+ public AuditSection getAuditSection() {
+ return auditSection;
+ }
+
+ @Override
+ public void setAuditSection(AuditSection auditSection) {
+ this.auditSection = auditSection;
+ }
+
+ public List<CategoryDescription> getDescriptions() {
+ return descriptions;
+ }
+
+ public void setDescriptions(List<CategoryDescription> descriptions) {
+ this.descriptions = descriptions;
+ }
+
+ public String getCategoryImage() {
+ return categoryImage;
+ }
+
+ public void setCategoryImage(String categoryImage) {
+ this.categoryImage = categoryImage;
+ }
+
+ public Integer getSortOrder() {
+ return sortOrder;
+ }
+
+ public void setSortOrder(Integer sortOrder) {
+ this.sortOrder = sortOrder;
+ }
+
+ public boolean isCategoryStatus() {
+ return categoryStatus;
+ }
+
+ public void setCategoryStatus(boolean categoryStatus) {
+ this.categoryStatus = categoryStatus;
+ }
+
+ public boolean isVisible() {
+ return visible;
+ }
+
+ public void setVisible(boolean visible) {
+ this.visible = visible;
+ }
+
+ public Integer getDepth() {
+ return depth;
+ }
+
+ public void setDepth(Integer depth) {
+ this.depth = depth;
+ }
+
+ public String getLineage() {
+ return lineage;
+ }
+
+ public void setLineage(String lineage) {
+ this.lineage = lineage;
+ }
+
+ public Category getParent() {
+ return parent;
+ }
+
+ public void setParent(Category parent) {
+ this.parent = parent;
+ }
+
+
+
+
+ public MerchantStore getMerchantStore() {
+ return merchantStore;
+ }
+
+ public void setMerchantStore(MerchantStore merchantStore) {
+ this.merchantStore = merchantStore;
+ }
+
+ public List<Category> getCategories() {
+ return categories;
+ }
+
+ public void setCategories(List<Category> categories) {
+ this.categories = categories;
+ }
+
+ public CategoryDescription getDescription() {
+ if(descriptions!=null && descriptions.size()>0) {
+ return descriptions.iterator().next();
+ }
+
+ return null;
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/category/model/CategoryDescription.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/category/model/CategoryDescription.java
new file mode 100644
index 0000000..14b67f6
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/category/model/CategoryDescription.java
@@ -0,0 +1,101 @@
+package com.salesmanager.core.business.catalog.category.model;
+
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import com.salesmanager.core.business.common.model.Description;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Entity
+@Table(name="CATEGORY_DESCRIPTION", schema="SALESMANAGER",uniqueConstraints={
+ @UniqueConstraint(columnNames={
+ "CATEGORY_ID",
+ "LANGUAGE_ID"
+ })
+ }
+)
+public class CategoryDescription extends Description {
+ private static final long serialVersionUID = -3248423008455359301L;
+
+
+ @ManyToOne(targetEntity = Category.class)
+ @JoinColumn(name = "CATEGORY_ID", nullable = false)
+ private Category category;
+
+ @Column(name="SEF_URL", length=120)
+ private String seUrl;
+
+ @Column(name = "CATEGORY_HIGHLIGHT")
+ private String categoryHighlight;
+
+ public String getCategoryHighlight() {
+ return categoryHighlight;
+ }
+
+ public void setCategoryHighlight(String categoryHighlight) {
+ this.categoryHighlight = categoryHighlight;
+ }
+
+ @Column(name="META_TITLE", length=120)
+ private String metatagTitle;
+
+ @Column(name="META_KEYWORDS")
+ private String metatagKeywords;
+
+ @Column(name="META_DESCRIPTION")
+ private String metatagDescription;
+
+ public CategoryDescription() {
+ }
+
+ public CategoryDescription(String name, Language language) {
+ this.setName(name);
+ this.setLanguage(language);
+ super.setId(0L);
+ }
+
+ public String getSeUrl() {
+ return seUrl;
+ }
+
+ public void setSeUrl(String seUrl) {
+ this.seUrl = seUrl;
+ }
+
+ public String getMetatagTitle() {
+ return metatagTitle;
+ }
+
+ public void setMetatagTitle(String metatagTitle) {
+ this.metatagTitle = metatagTitle;
+ }
+
+ public String getMetatagKeywords() {
+ return metatagKeywords;
+ }
+
+ public void setMetatagKeywords(String metatagKeywords) {
+ this.metatagKeywords = metatagKeywords;
+ }
+
+ public String getMetatagDescription() {
+ return metatagDescription;
+ }
+
+ public void setMetatagDescription(String metatagDescription) {
+ this.metatagDescription = metatagDescription;
+ }
+
+ public Category getCategory() {
+ return category;
+ }
+
+ public void setCategory(Category category) {
+ this.category = category;
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/category/service/CategoryService.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/category/service/CategoryService.java
new file mode 100644
index 0000000..1238500
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/category/service/CategoryService.java
@@ -0,0 +1,102 @@
+package com.salesmanager.core.business.catalog.category.service;
+
+import java.util.List;
+
+import com.salesmanager.core.business.catalog.category.model.Category;
+import com.salesmanager.core.business.catalog.category.model.CategoryDescription;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface CategoryService extends SalesManagerEntityService<Long, Category> {
+
+ List<Category> listByLineage(MerchantStore store, String lineage) throws ServiceException;
+
+ List<Category> listBySeUrl(MerchantStore store, String seUrl) throws ServiceException;
+
+ CategoryDescription getDescription(Category category, Language language) throws ServiceException;
+
+ void addCategoryDescription(Category category, CategoryDescription description) throws ServiceException;
+
+ void addChild(Category parent, Category child) throws ServiceException;
+
+ List<Category> listByParent(Category category) throws ServiceException;
+
+ List<Category> listByStoreAndParent(MerchantStore store, Category category) throws ServiceException;
+
+
+ List<Category> getByName(MerchantStore store, String name, Language language) throws ServiceException;
+
+ List<Category> listByStore(MerchantStore store) throws ServiceException;
+
+ Category getByCode(MerchantStore store, String code)
+ throws ServiceException;
+
+ List<Category> listByStore(MerchantStore store, Language language)
+ throws ServiceException;
+
+ void saveOrUpdate(Category category) throws ServiceException;
+
+ List<Category> listByDepth(MerchantStore store, int depth);
+
+ /**
+ * Get root categories by store for a given language
+ * @param store
+ * @param depth
+ * @param language
+ * @return
+ */
+ List<Category> listByDepth(MerchantStore store, int depth, Language language);
+
+ List<Category> listByLineage(String storeCode, String lineage)
+ throws ServiceException;
+
+ Category getByCode(String storeCode, String code) throws ServiceException;
+
+ Category getBySeUrl(MerchantStore store, String seUrl);
+
+ List<Category> listByParent(Category category, Language language);
+
+ Category getByLanguage(long categoryId, Language language);
+
+ /**
+ * Returns a list by category containing the category code and the number of products
+ * 1->obj[0] = book
+ * obj[1] = 150
+ * 2->obj[0] = novell
+ * obj[1] = 35
+ * ...
+ * @param store
+ * @param categoryIds
+ * @return
+ * @throws ServiceException
+ */
+ List<Object[]> countProductsByCategories(MerchantStore store,
+ List<Long> categoryIds) throws ServiceException;
+
+ /**
+ * Returns a list of Category by category code for a given language
+ * @param store
+ * @param codes
+ * @param language
+ * @return
+ */
+ List<Category> listByCodes(MerchantStore store, List<String> codes,
+ Language language);
+
+ /**
+ * List of Category by id
+ * @param store
+ * @param ids
+ * @param language
+ * @return
+ */
+ List<Category> listByIds(MerchantStore store, List<Long> ids,
+ Language language);
+
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/category/service/CategoryServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/category/service/CategoryServiceImpl.java
new file mode 100644
index 0000000..a8aea7b
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/category/service/CategoryServiceImpl.java
@@ -0,0 +1,437 @@
+package com.salesmanager.core.business.catalog.category.service;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Set;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
+
+import com.salesmanager.core.business.catalog.category.dao.CategoryDao;
+import com.salesmanager.core.business.catalog.category.model.Category;
+import com.salesmanager.core.business.catalog.category.model.CategoryDescription;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.service.ProductService;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.constants.Constants;
+
+@Service("categoryService")
+public class CategoryServiceImpl extends SalesManagerEntityServiceImpl<Long, Category> implements CategoryService {
+
+ private CategoryDao categoryDao;
+
+
+
+ @Autowired
+ private ProductService productService;
+
+
+
+ @Autowired
+ public CategoryServiceImpl(CategoryDao categoryDao) {
+ super(categoryDao);
+
+ this.categoryDao = categoryDao;
+ }
+
+ public void create(Category category) throws ServiceException {
+
+ super.create(category);
+
+ StringBuilder lineage = new StringBuilder();
+ Category parent = category.getParent();
+ if(parent!=null && parent.getId()!=null && parent.getId()!=0) {
+ lineage.append(parent.getLineage()).append("/").append(parent.getId());
+ category.setDepth(parent.getDepth()+1);
+ } else {
+ lineage.append("/");
+ category.setDepth(0);
+ }
+ category.setLineage(lineage.toString());
+ super.update(category);
+
+
+ }
+
+ @Override
+ public List<Object[]> countProductsByCategories(MerchantStore store,
+ List<Long> categoryIds) throws ServiceException {
+
+ return categoryDao.countProductsByCategories(store, categoryIds);
+
+ }
+
+ @Override
+ public List<Category> listByCodes(MerchantStore store, List<String> codes,
+ Language language) {
+ return categoryDao.getByCodes(store, codes, language);
+ }
+
+ @Override
+ public List<Category> listByIds(MerchantStore store, List<Long> ids,
+ Language language) {
+ return categoryDao.getByIds(store, ids, language);
+ }
+
+ @Override
+ public Category getByLanguage(long categoryId, Language language) {
+ return categoryDao.getByLanguage(categoryId, language);
+ }
+
+ @Override
+ public void saveOrUpdate(Category category) throws ServiceException {
+
+
+ //save or update (persist and attach entities
+ if(category.getId()!=null && category.getId()>0) {
+
+ super.update(category);
+
+ } else {
+
+ super.save(category);
+
+ }
+
+ }
+
+ @Override
+ public List<Category> listByLineage(MerchantStore store, String lineage) throws ServiceException {
+ try {
+ return categoryDao.listByLineage(store, lineage);
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+
+ }
+
+ @Override
+ public List<Category> listByLineage(String storeCode, String lineage) throws ServiceException {
+ try {
+ return categoryDao.listByLineage(storeCode, lineage);
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+
+ }
+
+
+ @Override
+ public List<Category> listBySeUrl(MerchantStore store, String seUrl) throws ServiceException{
+
+ try {
+ return categoryDao.listBySeUrl(store, seUrl);
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+ }
+
+ @Override
+ public Category getBySeUrl(MerchantStore store,String seUrl) {
+ return categoryDao.getBySeUrl(store, seUrl);
+ }
+
+
+ @Override
+ public Category getByCode(MerchantStore store, String code) throws ServiceException {
+
+ try {
+ return categoryDao.getByCode(store, code);
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+ }
+
+ @Override
+ public Category getByCode(String storeCode, String code) throws ServiceException {
+
+ try {
+ return categoryDao.getByCode(storeCode, code);
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+ }
+
+
+ @Override
+ public Category getById(Long id) {
+
+
+ return categoryDao.getById(id);
+
+
+ }
+
+ @Override
+ public List<Category> listByParent(Category category) throws ServiceException {
+
+ try {
+ return categoryDao.listByStoreAndParent(null, category);
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+ }
+
+ @Override
+ public List<Category> listByStoreAndParent(MerchantStore store, Category category) throws ServiceException {
+
+ try {
+ return categoryDao.listByStoreAndParent(store, category);
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+ }
+
+ @Override
+ public List<Category> listByParent(Category category, Language language) {
+ Assert.notNull(category, "Category cannot be null");
+ Assert.notNull(language, "Language cannot be null");
+ Assert.notNull(category.getMerchantStore(), "category.merchantStore cannot be null");
+
+ return categoryDao.listByParent(category, language);
+ }
+
+
+ @Override
+ public void addCategoryDescription(Category category, CategoryDescription description)
+ throws ServiceException {
+
+
+
+ try {
+ category.getDescriptions().add(description);
+ description.setCategory(category);
+ update(category);
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+ }
+
+
+ //@Override
+ public void delete(Category category) throws ServiceException {
+
+ //get category with lineage (subcategories)
+ StringBuilder lineage = new StringBuilder();
+ lineage.append(category.getLineage()).append(category.getId()).append(Constants.SLASH);
+ List<Category> categories = this.listByLineage(category.getMerchantStore(), lineage.toString());
+
+ Category dbCategory = this.getById( category.getId() );
+
+
+ if(dbCategory != null && dbCategory.getId().longValue() == category.getId().longValue() ) {
+
+
+ categories.add(dbCategory);
+
+
+ Collections.reverse(categories);
+
+ List<Long> categoryIds = new ArrayList<Long>();
+
+
+ for(Category c : categories) {
+ categoryIds.add(c.getId());
+ }
+
+ List<Product> products = productService.getProducts(categoryIds);
+ org.hibernate.Session session = this.categoryDao.getEntityManager().unwrap(org.hibernate.Session.class);//need to refresh the session to update all product categories
+
+
+ for(Product product : products) {
+ session.evict(product);//refresh product so we get all product categories
+ Product dbProduct = productService.getById(product.getId());
+ Set<Category> productCategories = dbProduct.getCategories();
+ if(productCategories.size()>1) {
+ for(Category c : categories) {
+ productCategories.remove(c);
+ productService.update(dbProduct);
+ }
+
+ if(product.getCategories()==null || product.getCategories().size()==0) {
+ productService.delete(dbProduct);
+ }
+
+ } else {
+ productService.delete(dbProduct);
+ }
+
+
+ }
+
+ Category categ = this.getById(category.getId());
+ categoryDao.delete(categ);
+
+ }
+
+ }
+
+
+ //@Override
+ //public void addProduct(Category category, Product product) throws ServiceException {
+ //if (!category.getProducts().contains(product)) {
+ // category.getProducts().add(product);
+ // update(category);
+ //}
+ //}
+
+ //@Override
+ //public void removeProduct(Category category, Product product)
+ //throws ServiceException {
+ //if (category.getProducts().contains(product)) {
+ // category.getProducts().remove(product);
+ // update(category);
+ //}
+ //}
+
+ //@Override
+ //public void addProducts(Category category, List<Product> products)
+ // throws ServiceException {
+ //if (!category.getProducts().contains(products)) {
+ // category.getProducts().addAll(products);
+ // update(category);
+ //}
+ //}
+
+ //@Override
+ //public void removeProducts(Category category, List<Product> products)
+ // throws ServiceException {
+ //if (category.getProducts().contains(products)) {
+ // category.getProducts().removeAll(products);
+ // update(category);
+ //}
+ //}
+
+ @Override
+ public CategoryDescription getDescription(Category category, Language language) {
+
+
+ for (CategoryDescription description : category.getDescriptions()) {
+ if (description.getLanguage().equals(language)) {
+ return description;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public void addChild(Category parent, Category child) throws ServiceException {
+
+
+ if(child==null || child.getMerchantStore()==null) {
+ throw new ServiceException("Child category and merchant store should not be null");
+ }
+
+ try {
+
+ if(parent==null) {
+
+ //assign to root
+ child.setParent(null);
+ child.setDepth(0);
+ //child.setLineage(new StringBuilder().append("/").append(child.getId()).append("/").toString());
+ child.setLineage("/");
+
+ } else {
+
+ Category p = this.getById(parent.getId());//parent
+
+
+
+
+ String lineage = p.getLineage();
+ int depth = p.getDepth();//TODO sometimes null
+
+ child.setParent(p);
+ child.setDepth(depth+1);
+ child.setLineage(new StringBuilder().append(lineage).append(p.getId()).append("/").toString());
+
+
+ }
+
+
+ update(child);
+ StringBuilder childLineage = new StringBuilder();
+ childLineage.append(child.getLineage()).append(child.getId()).append("/");
+ List<Category> subCategories = listByLineage(child.getMerchantStore(),childLineage.toString());
+
+
+ //ajust all sub categories lineages
+ if(subCategories!=null && subCategories.size()>0) {
+ for(Category subCategory : subCategories) {
+ if(child.getId()!=subCategory.getId()) {
+ addChild(child, subCategory);
+ }
+ }
+
+ }
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+
+ }
+
+ @Override
+ public List<Category> listByDepth(MerchantStore store, int depth) {
+ return categoryDao.listByDepth(store, depth);
+ }
+
+ @Override
+ public List<Category> listByDepth(MerchantStore store, int depth, Language language) {
+ return categoryDao.listByDepth(store, depth, language);
+ }
+
+ @Override
+ public List<Category> getByName(MerchantStore store, String name, Language language) throws ServiceException {
+
+ try {
+ return categoryDao.getByName(store, name, language);
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+
+ }
+
+
+
+ @Override
+ public List<Category> listByStore(MerchantStore store)
+ throws ServiceException {
+
+ try {
+ return categoryDao.listByStore(store);
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+ }
+
+ @Override
+ public List<Category> listByStore(MerchantStore store, Language language)
+ throws ServiceException {
+
+ try {
+ return categoryDao.listByStore(store, language);
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+ }
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/common/CatalogServiceHelper.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/common/CatalogServiceHelper.java
new file mode 100644
index 0000000..efab325
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/common/CatalogServiceHelper.java
@@ -0,0 +1,100 @@
+package com.salesmanager.core.business.catalog.common;
+
+import java.util.HashSet;
+import java.util.Locale;
+import java.util.Set;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOption;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionDescription;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionValue;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionValueDescription;
+import com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability;
+import com.salesmanager.core.constants.Constants;
+
+
+public class CatalogServiceHelper {
+
+ /**
+ * Filters descriptions and set the appropriate language
+ * @param p
+ * @param language
+ */
+ public static void setToLanguage(Product p, int language) {
+
+
+ Set<ProductAttribute> attributes = p.getAttributes();
+ if(attributes!=null) {
+
+ for(ProductAttribute attribute : attributes) {
+
+ ProductOption po = attribute.getProductOption();
+ Set<ProductOptionDescription> spod = po.getDescriptions();
+ if(spod!=null) {
+ Set<ProductOptionDescription> podDescriptions = new HashSet<ProductOptionDescription>();
+ for(ProductOptionDescription pod : spod) {
+ //System.out.println(" ProductOptionDescription : " + pod.getProductOptionName());
+ if(pod.getLanguage().getId()==language) {
+ podDescriptions.add(pod);
+ }
+ }
+ po.setDescriptions(podDescriptions);
+ }
+
+ ProductOptionValue pov = attribute.getProductOptionValue();
+
+
+ Set<ProductOptionValueDescription> spovd = pov.getDescriptions();
+ if(spovd!=null) {
+ Set<ProductOptionValueDescription> povdDescriptions = new HashSet();
+ for(ProductOptionValueDescription povd : spovd) {
+ if(povd.getLanguage().getId()==language) {
+ povdDescriptions.add(povd);
+ }
+ }
+ pov.setDescriptions(povdDescriptions);
+ }
+
+ }
+ }
+
+ }
+
+ /**
+ * Overwrites the availability in order to return 1 price / region
+ * @param product
+ * @param locale
+ */
+ public static void setToAvailability(Product product, Locale locale) {
+
+ Set<ProductAvailability> availabilities = product.getAvailabilities();
+
+ ProductAvailability defaultAvailability = null;
+ ProductAvailability localeAvailability = null;
+
+ for(ProductAvailability availability : availabilities) {
+
+ if(availability.getRegion().equals(Constants.ALL_REGIONS)) {
+ defaultAvailability = availability;
+ }
+ if(availability.getRegion().equals(locale.getCountry())) {
+ localeAvailability = availability;
+ }
+
+ }
+
+ if(defaultAvailability!=null || localeAvailability!=null) {
+ Set<ProductAvailability> productAvailabilities = new HashSet<ProductAvailability>();
+ if(defaultAvailability!=null) {
+ productAvailabilities.add(defaultAvailability);
+ }
+ if(localeAvailability!=null) {
+ productAvailabilities.add(localeAvailability);
+ }
+ product.setAvailabilities(productAvailabilities);
+ }
+
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductAttributeDao.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductAttributeDao.java
new file mode 100644
index 0000000..6e4546e
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductAttributeDao.java
@@ -0,0 +1,24 @@
+package com.salesmanager.core.business.catalog.product.dao.attribute;
+
+import java.util.List;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface ProductAttributeDao extends SalesManagerEntityDao<Long, ProductAttribute> {
+
+ List<ProductAttribute> getByOptionId(MerchantStore store,
+ Long id);
+
+ List<ProductAttribute> getByOptionValueId(MerchantStore store,
+ Long id);
+
+ List<ProductAttribute> getByProduct(MerchantStore store,
+ Product product, Language language);
+
+ List<ProductAttribute> getByAttributeIds(MerchantStore store, List<Long> ids);
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductAttributeDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductAttributeDaoImpl.java
new file mode 100644
index 0000000..d2e7b9e
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductAttributeDaoImpl.java
@@ -0,0 +1,122 @@
+package com.salesmanager.core.business.catalog.product.dao.attribute;
+
+import java.util.List;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.QProduct;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute;
+import com.salesmanager.core.business.catalog.product.model.attribute.QProductAttribute;
+import com.salesmanager.core.business.catalog.product.model.attribute.QProductOption;
+import com.salesmanager.core.business.catalog.product.model.attribute.QProductOptionValue;
+import com.salesmanager.core.business.catalog.product.model.attribute.QProductOptionValueDescription;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Repository("productAttributeDao")
+public class ProductAttributeDaoImpl extends SalesManagerEntityDaoImpl<Long, ProductAttribute>
+ implements ProductAttributeDao {
+
+
+ @Override
+ public ProductAttribute getById(Long id) {
+ QProductAttribute qEntity = QProductAttribute.productAttribute;
+ QProductOption qProductOption = QProductOption.productOption;
+ QProductOptionValue qProductOptionValue = QProductOptionValue.productOptionValue;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qEntity)
+ .join(qEntity.product).fetch()
+ .leftJoin(qEntity.productOption, qProductOption).fetch()
+ .leftJoin(qEntity.productOptionValue, qProductOptionValue).fetch()
+ .leftJoin(qProductOption.descriptions).fetch()
+ .leftJoin(qProductOptionValue.descriptions).fetch()
+ .leftJoin(qProductOption.merchantStore).fetch()
+ .where(qEntity.id.eq(id));
+
+ return query.uniqueResult(qEntity);
+ }
+
+ @Override
+ public List<ProductAttribute> getByOptionId(MerchantStore store, Long id) {
+ QProductAttribute qEntity = QProductAttribute.productAttribute;
+ QProductOption qProductOption = QProductOption.productOption;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qEntity)
+ .join(qEntity.product).fetch()
+ .leftJoin(qEntity.productOption, qProductOption).fetch()
+ .leftJoin(qProductOption.merchantStore).fetch()
+ .where(qProductOption.id.eq(id)
+ .and(qProductOption.merchantStore.id.eq(store.getId())));
+
+ return query.list(qEntity);
+ }
+
+ @Override
+ public List<ProductAttribute> getByAttributeIds(MerchantStore store, List<Long> ids) {
+ QProductAttribute qEntity = QProductAttribute.productAttribute;
+ QProductOption qProductOption = QProductOption.productOption;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qEntity)
+ .join(qEntity.product).fetch()
+ .leftJoin(qEntity.productOption, qProductOption).fetch()
+ .leftJoin(qProductOption.merchantStore).fetch()
+ .where(qEntity.id.in(ids)
+ .and(qProductOption.merchantStore.id.eq(store.getId())));
+
+ return query.list(qEntity);
+ }
+
+ @Override
+ public List<ProductAttribute> getByOptionValueId(MerchantStore store, Long id) {
+ QProductAttribute qEntity = QProductAttribute.productAttribute;
+ QProductOptionValue qProductOptionValue = QProductOptionValue.productOptionValue;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qEntity)
+ .join(qEntity.product).fetch()
+ .leftJoin(qEntity.productOptionValue, qProductOptionValue).fetch()
+ .leftJoin(qProductOptionValue.merchantStore).fetch()
+ .where(qProductOptionValue.id.eq(id)
+ .and(qProductOptionValue.merchantStore.id.eq(store.getId())));
+
+ return query.list(qEntity);
+ }
+
+
+ @Override
+ public List<ProductAttribute> getByProduct(MerchantStore store, Product product, Language language) {
+ QProductAttribute qEntity = QProductAttribute.productAttribute;
+ QProductOptionValue qProductOptionValue = QProductOptionValue.productOptionValue;
+ QProductOptionValueDescription qProductOptionValueDescription = QProductOptionValueDescription.productOptionValueDescription;
+ QProduct qProduct = QProduct.product;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qEntity)
+ .leftJoin(qEntity.productOptionValue, qProductOptionValue).fetch()
+ .leftJoin(qProductOptionValue.merchantStore).fetch()
+ .join(qEntity.product,qProduct).fetch()
+ .leftJoin(qProductOptionValue.descriptions,qProductOptionValueDescription).fetch()
+ .where(qProduct.id.eq(product.getId())
+ .and(qProductOptionValue.merchantStore.id.eq(store.getId()))
+ .and(qProductOptionValueDescription.language.id.eq(language.getId())));
+
+ return query.list(qEntity);
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductOptionDao.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductOptionDao.java
new file mode 100644
index 0000000..00dbc50
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductOptionDao.java
@@ -0,0 +1,31 @@
+package com.salesmanager.core.business.catalog.product.dao.attribute;
+
+import java.util.List;
+
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOption;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface ProductOptionDao extends SalesManagerEntityDao<Long, ProductOption> {
+
+ List<ProductOption> listByStore(MerchantStore store, Language language);
+
+ List<ProductOption> getByName(MerchantStore store, String name,
+ Language language);
+
+ void saveOrUpdate(ProductOption entity) throws ServiceException;
+
+ /**
+ * Get read only attributes.
+ * @param store
+ * @param language
+ * @return
+ */
+ List<ProductOption> getReadOnly(MerchantStore store,
+ Language language);
+
+ ProductOption getByCode(MerchantStore store, String optionCode);
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductOptionDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductOptionDaoImpl.java
new file mode 100644
index 0000000..da21fd3
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductOptionDaoImpl.java
@@ -0,0 +1,125 @@
+package com.salesmanager.core.business.catalog.product.dao.attribute;
+
+import java.util.List;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOption;
+import com.salesmanager.core.business.catalog.product.model.attribute.QProductOption;
+import com.salesmanager.core.business.catalog.product.model.attribute.QProductOptionDescription;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Repository("productOptionDao")
+public class ProductOptionDaoImpl extends SalesManagerEntityDaoImpl<Long, ProductOption>
+ implements ProductOptionDao {
+
+ @Override
+ public List<ProductOption> listByStore(MerchantStore store, Language language) {
+
+ QProductOption qProductOption = QProductOption.productOption;
+ QProductOptionDescription qDescription = QProductOptionDescription.productOptionDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qProductOption)
+ .leftJoin(qProductOption.descriptions, qDescription).fetch()
+ .leftJoin(qProductOption.merchantStore).fetch()
+ .where(qProductOption.merchantStore.id.eq(store.getId())
+ .and(qDescription.language.id.eq(language.getId())))
+ .orderBy(qProductOption.id.asc());
+
+ return query.listDistinct(qProductOption);
+
+ }
+
+ @Override
+ public ProductOption getById(Long id) {
+ QProductOption qProductOption = QProductOption.productOption;
+ QProductOptionDescription qDescription = QProductOptionDescription.productOptionDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qProductOption)
+ .leftJoin(qProductOption.descriptions, qDescription).fetch()
+ .leftJoin(qProductOption.merchantStore).fetch()
+ .where(qProductOption.id.eq(id));
+
+ return query.uniqueResult(qProductOption);
+ }
+
+ @Override
+ public List<ProductOption> getByName(MerchantStore store, String name, Language language) {
+ QProductOption qProductOption = QProductOption.productOption;
+ QProductOptionDescription qDescription = QProductOptionDescription.productOptionDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qProductOption)
+ .leftJoin(qProductOption.descriptions, qDescription).fetch()
+ .leftJoin(qProductOption.merchantStore).fetch()
+ .where(qDescription.name.like("%" + name + "%")
+ .and(qDescription.language.id.eq(language.getId()))
+ .and(qProductOption.merchantStore.id.eq(store.getId())));
+
+
+
+ List<ProductOption> options = query.list(qProductOption);
+ return options;
+ }
+
+ @Override
+ public List<ProductOption> getReadOnly(MerchantStore store, Language language) {
+ QProductOption qProductOption = QProductOption.productOption;
+ QProductOptionDescription qDescription = QProductOptionDescription.productOptionDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qProductOption)
+ .leftJoin(qProductOption.descriptions, qDescription).fetch()
+ .leftJoin(qProductOption.merchantStore).fetch()
+ .where(qProductOption.readOnly.eq(true)
+ .and(qDescription.language.id.eq(language.getId()))
+ .and(qProductOption.merchantStore.id.eq(store.getId())));
+
+
+
+ List<ProductOption> options = query.list(qProductOption);
+ return options;
+ }
+
+ @Override
+ public void saveOrUpdate(ProductOption entity) throws ServiceException {
+
+
+ //save or update (persist and attach entities
+ if(entity.getId()!=null && entity.getId()>0) {
+ super.update(entity);
+ } else {
+ super.save(entity);
+ }
+ }
+
+ @Override
+ public ProductOption getByCode(MerchantStore store, String optionCode) {
+ QProductOption qProductOption = QProductOption.productOption;
+ QProductOptionDescription qDescription = QProductOptionDescription.productOptionDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qProductOption)
+ .leftJoin(qProductOption.descriptions, qDescription).fetch()
+ .leftJoin(qProductOption.merchantStore).fetch()
+ .where(qProductOption.merchantStore.id.eq(store.getId())
+ .and(qProductOption.code.eq(optionCode)));
+
+ return query.uniqueResult(qProductOption);
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductOptionValueDao.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductOptionValueDao.java
new file mode 100644
index 0000000..43bdfcb
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductOptionValueDao.java
@@ -0,0 +1,24 @@
+package com.salesmanager.core.business.catalog.product.dao.attribute;
+
+import java.util.List;
+
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionValue;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface ProductOptionValueDao extends SalesManagerEntityDao<Long, ProductOptionValue> {
+
+ List<ProductOptionValue> listByStore(MerchantStore store, Language language);
+
+ ProductOptionValue getById(MerchantStore store, Long id);
+
+ List<ProductOptionValue> getByName(MerchantStore store, String name,
+ Language language);
+
+ List<ProductOptionValue> listByStoreNoReadOnly(MerchantStore store,
+ Language language);
+
+ ProductOptionValue getByCode(MerchantStore store, String optionValueCode);
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductOptionValueDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductOptionValueDaoImpl.java
new file mode 100644
index 0000000..3c547b0
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/attribute/ProductOptionValueDaoImpl.java
@@ -0,0 +1,120 @@
+package com.salesmanager.core.business.catalog.product.dao.attribute;
+
+import java.util.List;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionValue;
+import com.salesmanager.core.business.catalog.product.model.attribute.QProductOptionValue;
+import com.salesmanager.core.business.catalog.product.model.attribute.QProductOptionValueDescription;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Repository("productOptionValueDao")
+public class ProductOptionValueDaoImpl extends SalesManagerEntityDaoImpl<Long, ProductOptionValue>
+ implements ProductOptionValueDao {
+
+
+ @Override
+ public List<ProductOptionValue> listByStore(MerchantStore store, Language language) {
+
+ QProductOptionValue qProductOption = QProductOptionValue.productOptionValue;
+ QProductOptionValueDescription qDescription = QProductOptionValueDescription.productOptionValueDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qProductOption)
+ .leftJoin(qProductOption.descriptions, qDescription).fetch()
+ .leftJoin(qProductOption.merchantStore).fetch()
+ .where(qProductOption.merchantStore.id.eq(store.getId())
+ .and(qDescription.language.id.eq(language.getId())));
+ query.orderBy(qProductOption.id.asc());
+
+
+
+ return query.listDistinct(qProductOption);
+
+ }
+
+ @Override
+ public List<ProductOptionValue> listByStoreNoReadOnly(MerchantStore store, Language language) {
+
+ QProductOptionValue qProductOption = QProductOptionValue.productOptionValue;
+ QProductOptionValueDescription qDescription = QProductOptionValueDescription.productOptionValueDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qProductOption)
+ .leftJoin(qProductOption.descriptions, qDescription).fetch()
+ .leftJoin(qProductOption.merchantStore).fetch()
+ .where(qProductOption.merchantStore.id.eq(store.getId())
+ .and(qProductOption.productOptionDisplayOnly.eq(false))
+ .and(qDescription.language.id.eq(language.getId())));
+ query.orderBy(qProductOption.id.asc());
+
+
+
+ return query.listDistinct(qProductOption);
+
+ }
+
+
+
+ @Override
+ public ProductOptionValue getById(MerchantStore store, Long id) {
+ QProductOptionValue qProductOption = QProductOptionValue.productOptionValue;
+ QProductOptionValueDescription qDescription = QProductOptionValueDescription.productOptionValueDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qProductOption)
+ .leftJoin(qProductOption.descriptions, qDescription).fetch()
+ .leftJoin(qProductOption.merchantStore).fetch()
+ .where(qProductOption.id.eq(id)
+ .and(qProductOption.merchantStore.id.eq(store.getId())));
+
+ return query.uniqueResult(qProductOption);
+ }
+
+ @Override
+ public List<ProductOptionValue> getByName(MerchantStore store, String name, Language language) {
+ QProductOptionValue qProductOption = QProductOptionValue.productOptionValue;
+ QProductOptionValueDescription qDescription = QProductOptionValueDescription.productOptionValueDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qProductOption)
+ .leftJoin(qProductOption.descriptions, qDescription).fetch()
+ .leftJoin(qProductOption.merchantStore).fetch()
+ .where(qDescription.name.like("%" + name + "%")
+ .and(qDescription.language.id.eq(language.getId()))
+ .and(qProductOption.merchantStore.id.eq(store.getId())));
+
+
+
+ List<ProductOptionValue> options = query.list(qProductOption);
+ return options;
+ }
+
+ @Override
+ public ProductOptionValue getByCode(MerchantStore store, String optionValueCode) {
+ QProductOptionValue qProductOption = QProductOptionValue.productOptionValue;
+ QProductOptionValueDescription qDescription = QProductOptionValueDescription.productOptionValueDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qProductOption)
+ .leftJoin(qProductOption.descriptions, qDescription).fetch()
+ .leftJoin(qProductOption.merchantStore).fetch()
+ .where(qProductOption.code.eq(optionValueCode)
+ .and(qProductOption.merchantStore.id.eq(store.getId())));
+
+ return query.uniqueResult(qProductOption);
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/availability/ProductAvailabilityDao.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/availability/ProductAvailabilityDao.java
new file mode 100644
index 0000000..1f8baa4
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/availability/ProductAvailabilityDao.java
@@ -0,0 +1,8 @@
+package com.salesmanager.core.business.catalog.product.dao.availability;
+
+import com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+
+public interface ProductAvailabilityDao extends SalesManagerEntityDao<Long, ProductAvailability> {
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/availability/ProductAvailabilityDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/availability/ProductAvailabilityDaoImpl.java
new file mode 100644
index 0000000..77c0346
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/availability/ProductAvailabilityDaoImpl.java
@@ -0,0 +1,14 @@
+package com.salesmanager.core.business.catalog.product.dao.availability;
+
+import org.springframework.stereotype.Repository;
+
+import com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+
+@Repository("productAvailabilityDao")
+public class ProductAvailabilityDaoImpl extends SalesManagerEntityDaoImpl<Long, ProductAvailability>
+ implements ProductAvailabilityDao {
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/file/DigitalProductDao.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/file/DigitalProductDao.java
new file mode 100644
index 0000000..e88ac90
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/file/DigitalProductDao.java
@@ -0,0 +1,13 @@
+package com.salesmanager.core.business.catalog.product.dao.file;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.file.DigitalProduct;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+
+public interface DigitalProductDao extends SalesManagerEntityDao<Long, DigitalProduct> {
+
+ DigitalProduct getByProduct(MerchantStore store, Product product);
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/file/DigitalProductDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/file/DigitalProductDaoImpl.java
new file mode 100644
index 0000000..51ccee5
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/file/DigitalProductDaoImpl.java
@@ -0,0 +1,58 @@
+package com.salesmanager.core.business.catalog.product.dao.file;
+
+import java.util.List;
+
+import javax.persistence.NonUniqueResultException;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.QProduct;
+import com.salesmanager.core.business.catalog.product.model.file.DigitalProduct;
+import com.salesmanager.core.business.catalog.product.model.file.QDigitalProduct;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+
+@Repository("digitalProductDao")
+public class DigitalProductDaoImpl extends SalesManagerEntityDaoImpl<Long, DigitalProduct>
+ implements DigitalProductDao {
+
+ @Override
+ public DigitalProduct getByProduct(MerchantStore store, Product product) {
+
+ QDigitalProduct qDigitalProduct = QDigitalProduct.digitalProduct;
+ QProduct qProduct = QProduct.product;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qDigitalProduct)
+ .innerJoin(qDigitalProduct.product, qProduct).fetch()
+ .innerJoin(qProduct.merchantStore).fetch()
+ .where(qProduct.merchantStore.id.eq(store.getId())
+ .and(qProduct.id.eq(product.getId())));
+
+ List<DigitalProduct> results = query.list(qDigitalProduct);
+ if (results.isEmpty()) return null;
+
+ else if (results.size() == 1) return results.get(0);
+ throw new NonUniqueResultException();
+ }
+
+ @Override
+ public DigitalProduct getById(Long id) {
+
+ QDigitalProduct qDigitalProduct = QDigitalProduct.digitalProduct;
+ QProduct qProduct = QProduct.product;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qDigitalProduct)
+ .innerJoin(qDigitalProduct.product, qProduct).fetch()
+ .innerJoin(qProduct.merchantStore).fetch()
+ .where(qDigitalProduct.id.eq(id));
+
+ return query.uniqueResult(qDigitalProduct);
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/image/ProductImageDao.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/image/ProductImageDao.java
new file mode 100644
index 0000000..cb921f9
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/image/ProductImageDao.java
@@ -0,0 +1,10 @@
+package com.salesmanager.core.business.catalog.product.dao.image;
+
+import com.salesmanager.core.business.catalog.product.model.image.ProductImage;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+
+public interface ProductImageDao extends SalesManagerEntityDao<Long, ProductImage> {
+
+ ProductImage getProductImageById(Long id);
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/image/ProductImageDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/image/ProductImageDaoImpl.java
new file mode 100644
index 0000000..1a703d3
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/image/ProductImageDaoImpl.java
@@ -0,0 +1,39 @@
+package com.salesmanager.core.business.catalog.product.dao.image;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.catalog.product.model.QProduct;
+import com.salesmanager.core.business.catalog.product.model.image.ProductImage;
+import com.salesmanager.core.business.catalog.product.model.image.QProductImage;
+import com.salesmanager.core.business.catalog.product.model.image.QProductImageDescription;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+
+@Repository("productImageDao")
+public class ProductImageDaoImpl extends SalesManagerEntityDaoImpl<Long, ProductImage>
+ implements ProductImageDao {
+
+ @Override
+ public ProductImage getProductImageById(Long id) {
+
+
+ QProductImage qProductImage = QProductImage.productImage1;
+ QProductImageDescription qProductImageDescription = QProductImageDescription.productImageDescription;
+ QProduct qProduct = QProduct.product;
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qProductImage)
+ .leftJoin(qProductImage.descriptions, qProductImageDescription).fetch()
+ .innerJoin(qProductImage.product,qProduct).fetch()
+ .innerJoin(qProduct.merchantStore).fetch()
+ .where(qProductImage.id.eq(id));
+
+ return query.uniqueResult(qProductImage);
+
+
+
+
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/manufacturer/ManufacturerDao.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/manufacturer/ManufacturerDao.java
new file mode 100644
index 0000000..c61da63
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/manufacturer/ManufacturerDao.java
@@ -0,0 +1,21 @@
+package com.salesmanager.core.business.catalog.product.dao.manufacturer;
+
+import java.util.List;
+
+import com.salesmanager.core.business.catalog.product.model.manufacturer.Manufacturer;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface ManufacturerDao extends SalesManagerEntityDao<Long, Manufacturer> {
+
+ List<Manufacturer> listByStore(MerchantStore store, Language language);
+
+ List<Manufacturer> listByStore(MerchantStore store);
+
+ int getCountManufAttachedProducts( Manufacturer manufacturer );
+
+ List<Manufacturer> listByProductsByCategoriesId(MerchantStore store,
+ List<Long> ids, Language language);
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/manufacturer/ManufacturerDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/manufacturer/ManufacturerDaoImpl.java
new file mode 100644
index 0000000..9f72490
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/manufacturer/ManufacturerDaoImpl.java
@@ -0,0 +1,117 @@
+package com.salesmanager.core.business.catalog.product.dao.manufacturer;
+
+import java.util.List;
+
+import javax.persistence.Query;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.Manufacturer;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.QManufacturer;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.QManufacturerDescription;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Repository("manufacturerDao")
+public class ManufacturerDaoImpl extends SalesManagerEntityDaoImpl<Long, Manufacturer>
+ implements ManufacturerDao {
+
+ @Override
+ public int getCountManufAttachedProducts( Manufacturer manufacturer ){
+ StringBuilder countBuilderSelect = new StringBuilder();
+ countBuilderSelect.append("select count(distinct p) from Product as p");
+
+ StringBuilder countBuilderWhere = new StringBuilder();
+ countBuilderWhere.append(" where p.manufacturer.id=:mId");
+
+ Query countQ = super.getEntityManager().createQuery(
+ countBuilderSelect.toString() + countBuilderWhere.toString());
+
+ countQ.setParameter("mId", manufacturer.getId() );
+
+ Number count = (Number) countQ.getSingleResult ();
+
+ return count.intValue();
+ }
+
+ @Override
+ public List<Manufacturer> listByStore(MerchantStore store, Language language) {
+ QManufacturer qManufacturer = QManufacturer.manufacturer;
+ QManufacturerDescription qManufacturerDescription = QManufacturerDescription.manufacturerDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qManufacturer)
+ .leftJoin(qManufacturer.descriptions, qManufacturerDescription).fetch()
+ .leftJoin(qManufacturer.merchantStore).fetch()
+ .where(qManufacturerDescription.language.id.eq(language.getId())
+ .and(qManufacturer.merchantStore.id.eq(store.getId())));
+
+
+
+ List<Manufacturer> manufacturers = query.list(qManufacturer);
+ return manufacturers;
+ }
+
+ public Manufacturer getById(Long id) {
+ QManufacturer qManufacturer = QManufacturer.manufacturer;
+ QManufacturerDescription qManufacturerDescription = QManufacturerDescription.manufacturerDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qManufacturer)
+ .leftJoin(qManufacturer.descriptions, qManufacturerDescription).fetch()
+ .leftJoin(qManufacturer.merchantStore).fetch()
+ .where(qManufacturer.id.eq(id));
+
+
+
+ return query.uniqueResult(qManufacturer);
+ }
+
+ @Override
+ public List<Manufacturer> listByStore(MerchantStore store) {
+ QManufacturer qManufacturer = QManufacturer.manufacturer;
+ QManufacturerDescription qManufacturerDescription = QManufacturerDescription.manufacturerDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qManufacturer)
+ .leftJoin(qManufacturer.descriptions, qManufacturerDescription).fetch()
+ .leftJoin(qManufacturer.merchantStore).fetch()
+ .where(qManufacturer.merchantStore.id.eq(store.getId()));
+
+
+
+ List<Manufacturer> manufacturers = query.list(qManufacturer);
+ return manufacturers;
+ }
+
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List<Manufacturer> listByProductsByCategoriesId(MerchantStore store, List<Long> ids, Language language) {
+ StringBuilder builderSelect = new StringBuilder();
+ builderSelect.append("select distinct manufacturer from Product as p ");
+ builderSelect.append("join p.manufacturer manufacturer ");
+ builderSelect.append("join manufacturer.descriptions md ");
+ builderSelect.append("join p.categories categs ");
+ builderSelect.append("where categs.id in (:cid) ");
+ builderSelect.append("and md.language.id=:lang");
+
+ Query query = super.getEntityManager().createQuery(
+ builderSelect.toString());
+
+ query.setParameter("cid", ids);
+ query.setParameter("lang", language.getId());
+
+ return query.getResultList();
+
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/price/ProductPriceDao.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/price/ProductPriceDao.java
new file mode 100644
index 0000000..686277f
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/price/ProductPriceDao.java
@@ -0,0 +1,8 @@
+package com.salesmanager.core.business.catalog.product.dao.price;
+
+import com.salesmanager.core.business.catalog.product.model.price.ProductPrice;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+
+public interface ProductPriceDao extends SalesManagerEntityDao<Long, ProductPrice> {
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/price/ProductPriceDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/price/ProductPriceDaoImpl.java
new file mode 100644
index 0000000..71d12dd
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/price/ProductPriceDaoImpl.java
@@ -0,0 +1,37 @@
+package com.salesmanager.core.business.catalog.product.dao.price;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.catalog.product.model.QProduct;
+import com.salesmanager.core.business.catalog.product.model.availability.QProductAvailability;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPrice;
+import com.salesmanager.core.business.catalog.product.model.price.QProductPrice;
+import com.salesmanager.core.business.catalog.product.model.price.QProductPriceDescription;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+
+@Repository("productPriceDao")
+public class ProductPriceDaoImpl extends SalesManagerEntityDaoImpl<Long, ProductPrice>
+ implements ProductPriceDao {
+
+ @Override
+ public ProductPrice getById(Long id) {
+ QProductPrice qEntity = QProductPrice.productPrice;
+ QProductAvailability qAvailability = QProductAvailability.productAvailability;
+ QProductPriceDescription qEntityDescription = QProductPriceDescription.productPriceDescription;
+ QProduct qProduct = QProduct.product;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qEntity)
+ .innerJoin(qEntity.productAvailability,qAvailability).fetch()
+ .innerJoin(qAvailability.product,qProduct).fetch()
+ .leftJoin(qEntity.descriptions, qEntityDescription).fetch()
+ .innerJoin(qProduct.merchantStore).fetch()
+ .where(qEntity.id.eq(id));
+
+ return query.uniqueResult(qEntity);
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/ProductDao.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/ProductDao.java
new file mode 100644
index 0000000..1d5ead0
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/ProductDao.java
@@ -0,0 +1,47 @@
+package com.salesmanager.core.business.catalog.product.dao;
+
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.ProductCriteria;
+import com.salesmanager.core.business.catalog.product.model.ProductList;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.tax.model.taxclass.TaxClass;
+
+public interface ProductDao extends SalesManagerEntityDao<Long, Product> {
+
+ Product getProductForLocale(long productId, Language language, Locale locale);
+
+ @SuppressWarnings("rawtypes")
+ List<Product> getProductsForLocale(MerchantStore store, Set categoryIds, Language language,
+ Locale locale);
+
+ @SuppressWarnings("rawtypes")
+ List<Product> getProductsListByCategories(Set categoryIds);
+
+
+ /**
+ * Method to be used for getting a list of products in a given language based on one to many criteria
+ * @param store
+ * @param language
+ * @param criteria
+ * @return
+ */
+ ProductList listByStore(MerchantStore store, Language language, ProductCriteria criteria);
+
+ List<Product> listByStore(MerchantStore store);
+
+ List<Product> listByTaxClass(TaxClass taxClass);
+
+ List<Product> getProductsListByCategories(Set<Long> categoryIds,
+ Language language);
+
+ Product getBySeUrl(MerchantStore store, String seUrl, Locale locale);
+
+ Product getByCode(String productCode, Language language);
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/ProductDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/ProductDaoImpl.java
new file mode 100644
index 0000000..8ab2d84
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/ProductDaoImpl.java
@@ -0,0 +1,986 @@
+package com.salesmanager.core.business.catalog.product.dao;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+
+import javax.persistence.Query;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Repository;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.ProductCriteria;
+import com.salesmanager.core.business.catalog.product.model.ProductList;
+import com.salesmanager.core.business.catalog.product.model.attribute.AttributeCriteria;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.tax.model.taxclass.TaxClass;
+import com.salesmanager.core.constants.Constants;
+
+@Repository("productDao")
+public class ProductDaoImpl extends SalesManagerEntityDaoImpl<Long, Product> implements ProductDao {
+
+ public ProductDaoImpl() {
+ super();
+ }
+
+ @Override
+ public Product getBySeUrl(MerchantStore store,String seUrl, Locale locale) {
+
+
+ List regionList = new ArrayList();
+ regionList.add("*");
+ regionList.add(locale.getCountry());
+
+
+ StringBuilder qs = new StringBuilder();
+ qs.append("select distinct p from Product as p ");
+ qs.append("join fetch p.availabilities pa ");
+ qs.append("join fetch p.descriptions pd ");
+ qs.append("join fetch p.merchantStore pm ");
+ qs.append("left join fetch pa.prices pap ");
+ qs.append("left join fetch pap.descriptions papd ");
+
+
+ //images
+ qs.append("left join fetch p.images images ");
+ //options
+ qs.append("left join fetch p.attributes pattr ");
+ qs.append("left join fetch pattr.productOption po ");
+ qs.append("left join fetch po.descriptions pod ");
+ qs.append("left join fetch pattr.productOptionValue pov ");
+ qs.append("left join fetch pov.descriptions povd ");
+ qs.append("left join fetch p.relationships pr ");
+ //other lefts
+ qs.append("left join fetch p.manufacturer manuf ");
+ qs.append("left join fetch manuf.descriptions manufd ");
+ qs.append("left join fetch p.type type ");
+ qs.append("left join fetch p.taxClass tx ");
+
+ qs.append("where pa.region in (:lid) ");
+ qs.append("and pd.seUrl=:seUrl ");
+ qs.append("and p.available=true and p.dateAvailable<=:dt ");
+ qs.append("order by pattr.productOptionSortOrder ");
+
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+
+ q.setParameter("lid", regionList);
+ q.setParameter("dt", new Date());
+ q.setParameter("seUrl", seUrl);
+
+ Product p = null;
+
+ try {
+ p = (Product)q.getSingleResult();
+ } catch(javax.persistence.NoResultException ignore) {
+
+ }
+
+
+
+
+ return p;
+
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public List<Product> getProductsForLocale(MerchantStore store, Set categoryIds, Language language, Locale locale) {
+
+ ProductList products = this.getProductsListForLocale(store, categoryIds, language, locale, 0, -1);
+
+ return products.getProducts();
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public List<Product> getProductsListByCategories(Set categoryIds) {
+
+
+ //List regionList = new ArrayList();
+ //regionList.add("*");
+ //regionList.add(locale.getCountry());
+
+
+ //TODO Test performance
+ /**
+ * Testing in debug mode takes a long time with this query
+ * running in normal mode is fine
+ */
+
+
+ StringBuilder qs = new StringBuilder();
+ qs.append("select distinct p from Product as p ");
+ qs.append("join fetch p.merchantStore merch ");
+ qs.append("join fetch p.availabilities pa ");
+ qs.append("left join fetch pa.prices pap ");
+
+ qs.append("join fetch p.descriptions pd ");
+ qs.append("join fetch p.categories categs ");
+
+
+
+ qs.append("left join fetch pap.descriptions papd ");
+
+
+ //images
+ qs.append("left join fetch p.images images ");
+
+ //options (do not need attributes for listings)
+ qs.append("left join fetch p.attributes pattr ");
+ qs.append("left join fetch pattr.productOption po ");
+ qs.append("left join fetch po.descriptions pod ");
+ qs.append("left join fetch pattr.productOptionValue pov ");
+ qs.append("left join fetch pov.descriptions povd ");
+
+ //other lefts
+ qs.append("left join fetch p.manufacturer manuf ");
+ qs.append("left join fetch p.type type ");
+ qs.append("left join fetch p.taxClass tx ");
+
+ //qs.append("where pa.region in (:lid) ");
+ qs.append("where categs.id in (:cid)");
+
+
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+ q.setParameter("cid", categoryIds);
+
+
+
+ @SuppressWarnings("unchecked")
+ List<Product> products = q.getResultList();
+
+
+ return products;
+
+
+ }
+
+ @Override
+ public List<Product> getProductsListByCategories(Set<Long> categoryIds, Language language) {
+
+
+ //List regionList = new ArrayList();
+ //regionList.add("*");
+ //regionList.add(locale.getCountry());
+
+
+ //TODO Test performance
+ /**
+ * Testing in debug mode takes a long time with this query
+ * running in normal mode is fine
+ */
+
+
+ StringBuilder qs = new StringBuilder();
+ qs.append("select distinct p from Product as p ");
+ qs.append("join fetch p.merchantStore merch ");
+ qs.append("join fetch p.availabilities pa ");
+ qs.append("left join fetch pa.prices pap ");
+
+ qs.append("join fetch p.descriptions pd ");
+ qs.append("join fetch p.categories categs ");
+
+
+
+ qs.append("left join fetch pap.descriptions papd ");
+
+
+ //images
+ qs.append("left join fetch p.images images ");
+
+ //options (do not need attributes for listings)
+ qs.append("left join fetch p.attributes pattr ");
+ qs.append("left join fetch pattr.productOption po ");
+ qs.append("left join fetch po.descriptions pod ");
+ qs.append("left join fetch pattr.productOptionValue pov ");
+ qs.append("left join fetch pov.descriptions povd ");
+
+ //other lefts
+ qs.append("left join fetch p.manufacturer manuf ");
+ qs.append("left join fetch manuf.descriptions manufd ");
+ qs.append("left join fetch p.type type ");
+ qs.append("left join fetch p.taxClass tx ");
+
+ //qs.append("where pa.region in (:lid) ");
+ qs.append("where categs.id in (:cid) ");
+ //qs.append("and pd.language.id=:lang and papd.language.id=:lang and manufd.language.id=:lang ");
+ qs.append("and pd.language.id=:lang and papd.language.id=:lang ");
+ qs.append("and p.available=true and p.dateAvailable<=:dt ");
+
+
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+ q.setParameter("cid", categoryIds);
+ q.setParameter("lang", language.getId());
+ q.setParameter("dt", new Date());
+
+
+ @SuppressWarnings("unchecked")
+ List<Product> products = q.getResultList();
+
+
+ return products;
+
+
+ }
+
+
+/* @Override
+ public ProductList getProductListByCategories(ProductCriteria criteria, Set<Long> categoryIds, Language language) {
+
+
+ //List regionList = new ArrayList();
+ //regionList.add("*");
+ //regionList.add(locale.getCountry());
+
+
+ //TODO Test performance
+ *//**
+ * Testing in debug mode takes a long time with this query
+ * running in normal mode is fine
+ *//*
+
+
+ StringBuilder qs = new StringBuilder();
+ qs.append("select p from Product as p ");
+ qs.append("join fetch p.merchantStore merch ");
+ qs.append("join fetch p.availabilities pa ");
+ qs.append("left join fetch pa.prices pap ");
+
+ qs.append("join fetch p.descriptions pd ");
+ qs.append("join fetch p.categories categs ");
+
+
+
+ qs.append("left join fetch pap.descriptions papd ");
+
+
+ //images
+ qs.append("left join fetch p.images images ");
+
+ //options (do not need attributes for listings)
+ qs.append("left join fetch p.attributes pattr ");
+ qs.append("left join fetch pattr.productOption po ");
+ qs.append("left join fetch po.descriptions pod ");
+ qs.append("left join fetch pattr.productOptionValue pov ");
+ qs.append("left join fetch pov.descriptions povd ");
+
+ //other lefts
+ qs.append("left join fetch p.manufacturer manuf ");
+ qs.append("left join fetch manuf.descriptions manufd ");
+ qs.append("left join fetch p.type type ");
+ qs.append("left join fetch p.taxClass tx ");
+
+ //qs.append("where pa.region in (:lid) ");
+ qs.append("where categs.id in (:cid) ");
+ qs.append("and pd.language.id=:lang and papd.language.id=:lang ");
+ qs.append("and p.available=true and p.dateAvailable<=:dt ");
+
+
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+ q.setParameter("cid", categoryIds);
+ q.setParameter("lang", language.getId());
+ q.setParameter("dt", new Date());
+
+ q.setFirstResult(criteria.getStartIndex());
+ q.setMaxResults(criteria.getMaxCount());
+
+ @SuppressWarnings("unchecked")
+ List<Product> products = q.getResultList();
+
+ ProductList productList = new ProductList();
+ productList.setProducts(products);
+
+
+ return productList;
+
+
+ }*/
+
+
+ @Override
+ public List<Product> listByTaxClass(TaxClass taxClass) {
+
+
+ /**
+ * Testing in debug mode takes a long time with this query
+ * running in normal mode is fine
+ */
+
+
+ StringBuilder qs = new StringBuilder();
+ qs.append("select p from Product as p ");
+ qs.append("join fetch p.merchantStore merch ");
+ qs.append("join fetch p.availabilities pa ");
+ qs.append("left join fetch pa.prices pap ");
+
+ qs.append("join fetch p.descriptions pd ");
+ qs.append("join fetch p.categories categs ");
+
+
+
+ qs.append("left join fetch pap.descriptions papd ");
+
+
+ //images
+ qs.append("left join fetch p.images images ");
+
+ //options (do not need attributes for listings)
+ qs.append("left join fetch p.attributes pattr ");
+ qs.append("left join fetch pattr.productOption po ");
+ qs.append("left join fetch po.descriptions pod ");
+ qs.append("left join fetch pattr.productOptionValue pov ");
+ qs.append("left join fetch pov.descriptions povd ");
+
+ //other lefts
+ qs.append("left join fetch p.manufacturer manuf ");
+ qs.append("left join fetch manuf.descriptions manufd ");
+ qs.append("left join fetch p.type type ");
+ qs.append("left join fetch p.taxClass tx ");
+
+ //qs.append("where pa.region in (:lid) ");
+ qs.append("where tx.id=:tid");
+
+
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+ q.setParameter("tid", taxClass.getId());
+
+
+
+ @SuppressWarnings("unchecked")
+ List<Product> products = q.getResultList();
+
+
+ return products;
+
+
+ }
+
+
+
+
+ @Override
+ public List<Product> listByStore(MerchantStore store) {
+
+
+ /**
+ * Testing in debug mode takes a long time with this query
+ * running in normal mode is fine
+ */
+
+
+ StringBuilder qs = new StringBuilder();
+ qs.append("select p from Product as p ");
+ qs.append("join fetch p.merchantStore merch ");
+ qs.append("join fetch p.availabilities pa ");
+ qs.append("left join fetch pa.prices pap ");
+
+ qs.append("join fetch p.descriptions pd ");
+ qs.append("join fetch p.categories categs ");
+
+
+
+ qs.append("left join fetch pap.descriptions papd ");
+
+
+ //images
+ qs.append("left join fetch p.images images ");
+
+ //options (do not need attributes for listings)
+ qs.append("left join fetch p.attributes pattr ");
+ qs.append("left join fetch pattr.productOption po ");
+ qs.append("left join fetch po.descriptions pod ");
+ qs.append("left join fetch pattr.productOptionValue pov ");
+ qs.append("left join fetch pov.descriptions povd ");
+
+ //other lefts
+ qs.append("left join fetch p.manufacturer manuf ");
+ qs.append("left join fetch manuf.descriptions manufd ");
+ qs.append("left join fetch p.type type ");
+ qs.append("left join fetch p.taxClass tx ");
+
+ //qs.append("where pa.region in (:lid) ");
+ qs.append("where merch.id=:mid");
+
+
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+ q.setParameter("mid", store.getId());
+
+
+
+ @SuppressWarnings("unchecked")
+ List<Product> products = q.getResultList();
+
+
+ return products;
+
+
+ }
+
+
+ /**
+ * Used for all purpose !
+ * @param store
+ * @param first
+ * @param max
+ * @return
+ */
+ @Override
+ public ProductList listByStore(MerchantStore store, Language language, ProductCriteria criteria) {
+
+ ProductList productList = new ProductList();
+
+
+ StringBuilder countBuilderSelect = new StringBuilder();
+ countBuilderSelect.append("select count(distinct p) from Product as p");
+
+ StringBuilder countBuilderWhere = new StringBuilder();
+ countBuilderWhere.append(" where p.merchantStore.id=:mId");
+
+ if(!CollectionUtils.isEmpty(criteria.getProductIds())) {
+ countBuilderWhere.append(" and p.id in (:pId)");
+ }
+
+ if(!StringUtils.isBlank(criteria.getProductName())) {
+ countBuilderSelect.append(" INNER JOIN p.descriptions pd");
+ countBuilderWhere.append(" and pd.language.id=:lang and lower(pd.name) like:nm");
+ }
+
+
+ if(!CollectionUtils.isEmpty(criteria.getCategoryIds())) {
+ countBuilderSelect.append(" INNER JOIN p.categories categs");
+ countBuilderWhere.append(" and categs.id in (:cid)");
+ }
+
+ if(criteria.getManufacturerId()!=null) {
+ countBuilderSelect.append(" INNER JOIN p.manufacturer manuf");
+ countBuilderWhere.append(" and manuf.id = :manufid");
+ }
+
+ if(!StringUtils.isBlank(criteria.getCode())) {
+
+ countBuilderWhere.append(" and lower(p.sku) like :sku");
+ }
+
+ if(!CollectionUtils.isEmpty(criteria.getAttributeCriteria())) {
+
+ countBuilderSelect.append(" INNER JOIN p.attributes pattr");
+ countBuilderSelect.append(" INNER JOIN pattr.productOption po");
+ countBuilderSelect.append(" INNER JOIN pattr.productOptionValue pov ");
+ countBuilderSelect.append(" INNER JOIN pov.descriptions povd ");
+ int count = 0;
+ for(AttributeCriteria attributeCriteria : criteria.getAttributeCriteria()) {
+ if(count==0) {
+ countBuilderWhere.append(" and po.code =:").append(attributeCriteria.getAttributeCode());
+ countBuilderWhere.append(" and povd.description like :").append("val").append(count).append(attributeCriteria.getAttributeCode());
+ }
+ count++;
+ }
+ countBuilderWhere.append(" and povd.language.id=:lang");
+
+ }
+
+
+ if(criteria.getAvailable()!=null) {
+ if(criteria.getAvailable().booleanValue()) {
+ countBuilderWhere.append(" and p.available=true and p.dateAvailable<=:dt");
+ } else {
+ countBuilderWhere.append(" and p.available=false or p.dateAvailable>:dt");
+ }
+ }
+
+ Query countQ = super.getEntityManager().createQuery(
+ countBuilderSelect.toString() + countBuilderWhere.toString());
+
+ countQ.setParameter("mId", store.getId());
+
+
+ if(!CollectionUtils.isEmpty(criteria.getCategoryIds())) {
+ countQ.setParameter("cid", criteria.getCategoryIds());
+ }
+
+
+ if(criteria.getAvailable()!=null) {
+ countQ.setParameter("dt", new Date());
+ }
+
+ if(!StringUtils.isBlank(criteria.getCode())) {
+ countQ.setParameter("sku", new StringBuilder().append("%").append(criteria.getCode().toLowerCase()).append("%").toString());
+ }
+
+ if(criteria.getManufacturerId()!=null) {
+ countQ.setParameter("manufid", criteria.getManufacturerId());
+ }
+
+ if(!CollectionUtils.isEmpty(criteria.getAttributeCriteria())) {
+ int count = 0;
+ for(AttributeCriteria attributeCriteria : criteria.getAttributeCriteria()) {
+ countQ.setParameter(attributeCriteria.getAttributeCode(),attributeCriteria.getAttributeCode());
+ countQ.setParameter("val" + count + attributeCriteria.getAttributeCode(),"%" + attributeCriteria.getAttributeValue() + "%");
+ count ++;
+ }
+ countQ.setParameter("lang", language.getId());
+ }
+
+ if(!StringUtils.isBlank(criteria.getProductName())) {
+ countQ.setParameter("nm", new StringBuilder().append("%").append(criteria.getProductName().toLowerCase()).append("%").toString());
+ countQ.setParameter("lang", language.getId());
+ }
+
+ if(!CollectionUtils.isEmpty(criteria.getProductIds())) {
+ countQ.setParameter("pId", criteria.getProductIds());
+ }
+
+ Number count = (Number) countQ.getSingleResult ();
+
+ productList.setTotalCount(count.intValue());
+
+ if(count.intValue()==0)
+ return productList;
+
+
+ StringBuilder qs = new StringBuilder();
+ qs.append("select distinct p from Product as p ");
+ qs.append("join fetch p.merchantStore merch ");
+ qs.append("join fetch p.availabilities pa ");
+ qs.append("left join fetch pa.prices pap ");
+
+ qs.append("join fetch p.descriptions pd ");
+ qs.append("left join fetch p.categories categs ");
+
+
+ //images
+ qs.append("left join fetch p.images images ");
+
+
+ //other lefts
+ qs.append("left join fetch p.manufacturer manuf ");
+ qs.append("left join fetch manuf.descriptions manufd ");
+ qs.append("left join fetch p.type type ");
+ qs.append("left join fetch p.taxClass tx ");
+
+
+ //attributes
+ if(!CollectionUtils.isEmpty(criteria.getAttributeCriteria())) {
+ qs.append(" inner join p.attributes pattr");
+ qs.append(" inner join pattr.productOption po");
+ qs.append(" inner join po.descriptions pod");
+ qs.append(" inner join pattr.productOptionValue pov ");
+ qs.append(" inner join pov.descriptions povd");
+ } else {
+ qs.append(" left join fetch p.attributes pattr");
+ qs.append(" left join fetch pattr.productOption po");
+ qs.append(" left join fetch po.descriptions pod");
+ qs.append(" left join fetch pattr.productOptionValue pov");
+ qs.append(" left join fetch pov.descriptions povd");
+ }
+
+ qs.append(" left join fetch p.relationships pr");
+
+
+ qs.append(" where merch.id=:mId");
+ qs.append(" and pd.language.id=:lang");
+
+ if(!CollectionUtils.isEmpty(criteria.getProductIds())) {
+ qs.append(" and p.id in (:pId)");
+ }
+
+ if(!CollectionUtils.isEmpty(criteria.getCategoryIds())) {
+ qs.append(" and categs.id in (:cid)");
+ }
+
+ if(criteria.getManufacturerId()!=null) {
+ qs.append(" and manuf.id = :manufid");
+ }
+
+
+ if(criteria.getAvailable()!=null) {
+ if(criteria.getAvailable().booleanValue()) {
+ qs.append(" and p.available=true and p.dateAvailable<=:dt");
+ } else {
+ qs.append(" and p.available=false and p.dateAvailable>:dt");
+ }
+ }
+
+ if(!StringUtils.isBlank(criteria.getProductName())) {
+ qs.append(" and lower(pd.name) like :nm");
+ }
+
+ if(!StringUtils.isBlank(criteria.getCode())) {
+ qs.append(" and lower(p.sku) like :sku");
+ }
+
+ if(!CollectionUtils.isEmpty(criteria.getAttributeCriteria())) {
+ int cnt = 0;
+ for(AttributeCriteria attributeCriteria : criteria.getAttributeCriteria()) {
+ qs.append(" and po.code =:").append(attributeCriteria.getAttributeCode());
+ qs.append(" and povd.description like :").append("val").append(cnt).append(attributeCriteria.getAttributeCode());
+ cnt++;
+ }
+ qs.append(" and povd.language.id=:lang");
+
+ }
+
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+
+ q.setParameter("lang", language.getId());
+ q.setParameter("mId", store.getId());
+
+ if(!CollectionUtils.isEmpty(criteria.getCategoryIds())) {
+ q.setParameter("cid", criteria.getCategoryIds());
+ }
+
+ if(!CollectionUtils.isEmpty(criteria.getProductIds())) {
+ q.setParameter("pId", criteria.getProductIds());
+ }
+
+ if(criteria.getAvailable()!=null) {
+ q.setParameter("dt", new Date());
+ }
+
+ if(criteria.getManufacturerId()!=null) {
+ q.setParameter("manufid", criteria.getManufacturerId());
+ }
+
+ if(!StringUtils.isBlank(criteria.getCode())) {
+ q.setParameter("sku", new StringBuilder().append("%").append(criteria.getCode().toLowerCase()).append("%").toString());
+ }
+
+ if(!CollectionUtils.isEmpty(criteria.getAttributeCriteria())) {
+ int cnt = 0;
+ for(AttributeCriteria attributeCriteria : criteria.getAttributeCriteria()) {
+ q.setParameter(attributeCriteria.getAttributeCode(),attributeCriteria.getAttributeCode());
+ q.setParameter("val" + cnt + attributeCriteria.getAttributeCode(),"%" + attributeCriteria.getAttributeValue() + "%");
+ cnt++;
+ }
+ }
+
+ if(!StringUtils.isBlank(criteria.getProductName())) {
+ q.setParameter("nm", new StringBuilder().append("%").append(criteria.getProductName().toLowerCase()).append("%").toString());
+ }
+
+ if(criteria.getMaxCount()>0) {
+
+
+ q.setFirstResult(criteria.getStartIndex());
+ if(criteria.getMaxCount()<count.intValue()) {
+ q.setMaxResults(criteria.getMaxCount());
+ }
+ else {
+ q.setMaxResults(count.intValue());
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ List<Product> products = q.getResultList();
+ productList.setProducts(products);
+
+ return productList;
+
+
+
+
+ }
+
+
+
+ /**
+ * This query is used for category listings. All collections are not fully loaded, only the required objects
+ * so the listing page can display everything related to all products
+ */
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private ProductList getProductsListForLocale(MerchantStore store, Set categoryIds, Language language, Locale locale, int first, int max) {
+
+
+ List regionList = new ArrayList();
+ regionList.add(Constants.ALL_REGIONS);
+ if(locale!=null) {
+ regionList.add(locale.getCountry());
+ }
+
+ ProductList productList = new ProductList();
+
+
+ Query countQ = super.getEntityManager().createQuery(
+ "select count(p) from Product as p INNER JOIN p.availabilities pa INNER JOIN p.categories categs where p.merchantStore.id=:mId and categs.id in (:cid) and pa.region in (:lid) and p.available=1 and p.dateAvailable<=:dt");
+ //"select p from Product as p join fetch p.availabilities pa join fetch p.categories categs where categs.id in (:cid) and pa.region in (:lid) and p.available=1 and p.dateAvailable<=:dt");
+
+ countQ.setParameter("cid", categoryIds);
+ countQ.setParameter("lid", regionList);
+ countQ.setParameter("dt", new Date());
+ countQ.setParameter("mId", store.getId());
+
+ //List<Product> ps = countQ.getResultList();
+
+ Number count = (Number) countQ.getSingleResult ();
+
+
+ productList.setTotalCount(count.intValue());
+
+ if(count.intValue()==0)
+ return productList;
+
+
+
+
+ StringBuilder qs = new StringBuilder();
+ qs.append("select p from Product as p ");
+ qs.append("join fetch p.merchantStore merch ");
+ qs.append("join fetch p.availabilities pa ");
+ qs.append("left join fetch pa.prices pap ");
+
+ qs.append("join fetch p.descriptions pd ");
+ qs.append("join fetch p.categories categs ");
+
+
+
+ //not necessary
+ //qs.append("join fetch pap.descriptions papd ");
+
+
+ //images
+ qs.append("left join fetch p.images images ");
+
+ //options (do not need attributes for listings)
+ //qs.append("left join fetch p.attributes pattr ");
+ //qs.append("left join fetch pattr.productOption po ");
+ //qs.append("left join fetch po.descriptions pod ");
+ //qs.append("left join fetch pattr.productOptionValue pov ");
+ //qs.append("left join fetch pov.descriptions povd ");
+
+ //other lefts
+ qs.append("left join fetch p.manufacturer manuf ");
+ qs.append("left join fetch manuf.descriptions manufd ");
+ qs.append("left join fetch p.type type ");
+ qs.append("left join fetch p.taxClass tx ");
+
+ //qs.append("where pa.region in (:lid) ");
+ qs.append("where p.merchantStore.id=mId and categs.id in (:cid) and pa.region in (:lid) ");
+ //qs.append("and p.available=true and p.dateAvailable<=:dt and pd.language.id=:lang and manufd.language.id=:lang");
+ qs.append("and p.available=true and p.dateAvailable<=:dt and pd.language.id=:lang ");
+
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+ q.setParameter("cid", categoryIds);
+ q.setParameter("lid", regionList);
+ q.setParameter("dt", new Date());
+ q.setParameter("lang", language.getId());
+ q.setParameter("mId", store.getId());
+
+
+ q.setFirstResult(first);
+ if(max>0) {
+ int maxCount = first + max;
+
+ if(maxCount < count.intValue()) {
+ q.setMaxResults(maxCount);
+ } else {
+ q.setMaxResults(count.intValue());
+ }
+ }
+
+ List<Product> products = q.getResultList();
+ productList.setProducts(products);
+
+ return productList;
+
+
+ }
+
+ @Override
+ public Product getProductForLocale(long productId, Language language, Locale locale) {
+
+
+
+ List regionList = new ArrayList();
+ regionList.add("*");
+ regionList.add(locale.getCountry());
+
+
+ StringBuilder qs = new StringBuilder();
+ qs.append("select distinct p from Product as p ");
+ qs.append("join fetch p.availabilities pa ");
+ qs.append("join fetch p.descriptions pd ");
+ qs.append("join fetch p.merchantStore pm ");
+ qs.append("left join fetch pa.prices pap ");
+ qs.append("left join fetch pap.descriptions papd ");
+
+
+
+
+ //images
+ qs.append("left join fetch p.images images ");
+ //options
+ qs.append("left join fetch p.attributes pattr ");
+ qs.append("left join fetch pattr.productOption po ");
+ qs.append("left join fetch po.descriptions pod ");
+ qs.append("left join fetch pattr.productOptionValue pov ");
+ qs.append("left join fetch pov.descriptions povd ");
+ qs.append("left join fetch p.relationships pr ");
+ //other lefts
+ qs.append("left join fetch p.manufacturer manuf ");
+ qs.append("left join fetch manuf.descriptions manufd ");
+ qs.append("left join fetch p.type type ");
+ qs.append("left join fetch p.taxClass tx ");
+
+ qs.append("where p.id=:pid and pa.region in (:lid) ");
+ qs.append("and pd.language.id=:lang and papd.language.id=:lang ");
+ qs.append("and p.available=true and p.dateAvailable<=:dt ");
+ //this cannot be done on child elements from left join
+ //qs.append("and pod.languageId=:lang and povd.languageId=:lang");
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+ q.setParameter("pid", productId);
+ q.setParameter("lid", regionList);
+ q.setParameter("dt", new Date());
+ q.setParameter("lang", language.getId());
+
+ Product p = (Product)q.getSingleResult();
+
+
+ return p;
+
+ }
+
+ @Override
+ public Product getById(Long productId) {
+
+ try {
+
+
+
+ StringBuilder qs = new StringBuilder();
+ qs.append("select distinct p from Product as p ");
+ qs.append("join fetch p.availabilities pa ");
+ qs.append("join fetch p.merchantStore merch ");
+ qs.append("join fetch p.descriptions pd ");
+ qs.append("left join fetch p.categories categs ");
+ qs.append("left join fetch pa.prices pap ");
+ qs.append("left join fetch pap.descriptions papd ");
+ qs.append("left join fetch categs.descriptions categsd ");
+
+ //images
+ qs.append("left join fetch p.images images ");
+ //options
+ qs.append("left join fetch p.images images ");
+ qs.append("left join fetch p.attributes pattr ");
+ qs.append("left join fetch pattr.productOption po ");
+ qs.append("left join fetch po.descriptions pod ");
+ qs.append("left join fetch pattr.productOptionValue pov ");
+ qs.append("left join fetch pov.descriptions povd ");
+ qs.append("left join fetch p.relationships pr ");
+ //other lefts
+ qs.append("left join fetch p.manufacturer manuf ");
+ qs.append("left join fetch manuf.descriptions manufd ");
+ qs.append("left join fetch p.type type ");
+ qs.append("left join fetch p.taxClass tx ");
+
+ qs.append("where p.id=:pid");
+
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+ q.setParameter("pid", productId);
+
+
+ Product p = (Product)q.getSingleResult();
+
+
+ return p;
+
+ } catch(javax.persistence.NoResultException ers) {
+ return null;
+ }
+
+ }
+
+ @Override
+ public Product getByCode(String productCode, Language language) {
+
+ try {
+
+
+
+ StringBuilder qs = new StringBuilder();
+ qs.append("select distinct p from Product as p ");
+ qs.append("join fetch p.availabilities pa ");
+ qs.append("join fetch p.descriptions pd ");
+ qs.append("join fetch p.merchantStore pm ");
+ qs.append("left join fetch pa.prices pap ");
+ qs.append("left join fetch pap.descriptions papd ");
+
+
+
+
+ //images
+ qs.append("left join fetch p.images images ");
+ //options
+ qs.append("left join fetch p.attributes pattr ");
+ qs.append("left join fetch pattr.productOption po ");
+ qs.append("left join fetch po.descriptions pod ");
+ qs.append("left join fetch pattr.productOptionValue pov ");
+ qs.append("left join fetch pov.descriptions povd ");
+ qs.append("left join fetch p.relationships pr ");
+ //other lefts
+ qs.append("left join fetch p.manufacturer manuf ");
+ qs.append("left join fetch manuf.descriptions manufd ");
+ qs.append("left join fetch p.type type ");
+ qs.append("left join fetch p.taxClass tx ");
+
+ qs.append("where p.sku=:code ");
+ qs.append("and pd.language.id=:lang and papd.language.id=:lang");
+ //this cannot be done on child elements from left join
+ //qs.append("and pod.languageId=:lang and povd.languageId=:lang");
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+ q.setParameter("code", productCode);
+ q.setParameter("lang", language.getId());
+
+ Product p = (Product)q.getSingleResult();
+
+
+ return p;
+
+ } catch(javax.persistence.NoResultException ers) {
+ return null;
+ }
+
+ }
+}
+
+
+
+
\ No newline at end of file
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/relationship/ProductRelationshipDao.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/relationship/ProductRelationshipDao.java
new file mode 100644
index 0000000..c924b0f
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/relationship/ProductRelationshipDao.java
@@ -0,0 +1,31 @@
+package com.salesmanager.core.business.catalog.product.dao.relationship;
+
+import java.util.List;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.relationship.ProductRelationship;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface ProductRelationshipDao extends SalesManagerEntityDao<Long, ProductRelationship> {
+
+ List<ProductRelationship> getByType(MerchantStore store, String type, Product product, Language language);
+
+ List<ProductRelationship> getByType(MerchantStore store, String type,
+ Product product);
+
+ List<ProductRelationship> getByType(MerchantStore store, String type);
+
+ List<ProductRelationship> listByProducts(Product product);
+
+ List<ProductRelationship> getByType(MerchantStore store, String type,
+ Language language);
+
+ List<ProductRelationship> getGroups(MerchantStore store);
+
+ List<ProductRelationship> getByGroup(MerchantStore store, String group);
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/relationship/ProductRelationshipDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/relationship/ProductRelationshipDaoImpl.java
new file mode 100644
index 0000000..a987585
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/relationship/ProductRelationshipDaoImpl.java
@@ -0,0 +1,290 @@
+package com.salesmanager.core.business.catalog.product.dao.relationship;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.persistence.Query;
+
+import org.springframework.stereotype.Repository;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.relationship.ProductRelationship;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Repository("productRelationshipDao")
+public class ProductRelationshipDaoImpl extends SalesManagerEntityDaoImpl<Long, ProductRelationship>
+ implements ProductRelationshipDao {
+
+ @Override
+ public List<ProductRelationship> getByType(MerchantStore store, String type, Product product, Language language) {
+ //QDSL cannot interpret the following query, that is why it is in native format
+
+ StringBuilder qs = new StringBuilder();
+ qs.append("select distinct pr from ProductRelationship as pr ");
+ qs.append("left join fetch pr.product p ");
+ qs.append("join fetch pr.relatedProduct rp ");
+ qs.append("left join fetch rp.descriptions rpd ");
+
+ qs.append("where pr.code=:code ");
+ qs.append("and p.id=:id ");
+ qs.append("and rpd.language.id=:langId");
+
+
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+ q.setParameter("code", type);
+ q.setParameter("id", product.getId());
+ q.setParameter("langId", language.getId());
+
+
+
+ @SuppressWarnings("unchecked")
+ List<ProductRelationship> relations = q.getResultList();
+
+
+ return relations;
+
+
+ }
+
+ @Override
+ public List<ProductRelationship> getByType(MerchantStore store, String type, Language language) {
+ //QDSL cannot interpret the following query, that is why it is in native format
+
+ StringBuilder qs = new StringBuilder();
+ qs.append("select distinct pr from ProductRelationship as pr ");
+ qs.append("left join fetch pr.product p ");
+ qs.append("join fetch pr.relatedProduct rp ");
+
+ qs.append("left join fetch rp.attributes pattr ");
+ qs.append("left join fetch rp.descriptions rpd ");
+ qs.append("left join fetch rp.images pd ");
+ qs.append("left join fetch rp.merchantStore rpm ");
+ qs.append("left join fetch rpm.currency rpmc ");
+ qs.append("left join fetch rp.availabilities pa ");
+ qs.append("left join fetch rp.manufacturer m ");
+ qs.append("left join fetch m.descriptions md ");
+ qs.append("left join fetch pa.prices pap ");
+ qs.append("left join fetch pap.descriptions papd ");
+
+ qs.append("where pr.code=:code ");
+ qs.append("and rpd.language.id=:langId");
+
+
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+ q.setParameter("code", type);
+ q.setParameter("langId", language.getId());
+
+
+
+ @SuppressWarnings("unchecked")
+ List<ProductRelationship> relations = q.getResultList();
+
+
+ return relations;
+
+
+ }
+
+ @Override
+ public List<ProductRelationship> getByGroup(MerchantStore store, String group) {
+ //QDSL cannot interpret the following query, that is why it is in native format
+
+ StringBuilder qs = new StringBuilder();
+ qs.append("select distinct pr from ProductRelationship as pr ");
+ qs.append("left join fetch pr.product p ");
+ qs.append("left join fetch pr.relatedProduct rp ");
+
+ qs.append("left join fetch rp.attributes pattr ");
+ qs.append("left join fetch rp.descriptions rpd ");
+ qs.append("left join fetch rp.images pd ");
+ qs.append("left join fetch rp.merchantStore rpm ");
+ qs.append("left join fetch rpm.currency rpmc ");
+ qs.append("left join fetch rp.availabilities pa ");
+ qs.append("left join fetch pa.prices pap ");
+ qs.append("left join fetch pap.descriptions papd ");
+ qs.append("left join fetch rp.manufacturer manuf ");
+ qs.append("left join fetch manuf.descriptions manufd ");
+ qs.append("left join fetch rp.type type ");
+
+ qs.append("where pr.code=:code ");
+
+
+
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+ q.setParameter("code", group);
+
+
+
+
+ @SuppressWarnings("unchecked")
+ List<ProductRelationship> relations = q.getResultList();
+
+
+ return relations;
+
+
+ }
+
+ @Override
+ public List<ProductRelationship> getGroups(MerchantStore store) {
+
+ StringBuilder qs = new StringBuilder();
+ qs.append("select distinct pr from ProductRelationship as pr ");
+ qs.append("where pr.store.id=:store ");
+
+ qs.append("and pr.product=null");
+
+
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+ q.setParameter("store", store.getId());
+
+
+
+ @SuppressWarnings("unchecked")
+ List<ProductRelationship> relations = q.getResultList();
+
+ Map<String,ProductRelationship> relationMap = new HashMap<String,ProductRelationship>();
+ for(ProductRelationship relationship : relations) {
+ if(!relationMap.containsKey(relationship.getCode())) {
+ relationMap.put(relationship.getCode(), relationship);
+ }
+ }
+
+ List<ProductRelationship> returnList = new ArrayList<ProductRelationship>(relationMap.values());
+
+
+ return returnList;
+
+
+ }
+
+
+ @Override
+ public List<ProductRelationship> getByType(MerchantStore store, String type) {
+ //QDSL cannot interpret the following query, that is why it is in native format
+
+ StringBuilder qs = new StringBuilder();
+ qs.append("select distinct pr from ProductRelationship as pr ");
+ qs.append("left join fetch pr.product p ");
+ qs.append("join fetch pr.relatedProduct rp ");
+ qs.append("left join fetch rp.descriptions rpd ");
+
+ qs.append("where pr.code=:code");
+
+
+
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+ q.setParameter("code", type);
+
+
+ @SuppressWarnings("unchecked")
+ List<ProductRelationship> relations = q.getResultList();
+
+
+ return relations;
+
+
+ }
+
+ @Override
+ public List<ProductRelationship> listByProducts(Product product) {
+ //QDSL cannot interpret the following query, that is why it is in native format
+
+ StringBuilder qs = new StringBuilder();
+ qs.append("select pr from ProductRelationship as pr ");
+ qs.append("left join fetch pr.product p ");
+ qs.append("left join fetch pr.relatedProduct rp ");
+ qs.append("left join fetch rp.attributes pattr ");
+ qs.append("left join fetch p.descriptions pd ");
+ qs.append("left join fetch rp.descriptions rpd ");
+
+ qs.append("where p.id=:id");
+ qs.append(" or rp.id=:id");
+
+
+
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+ q.setParameter("id", product.getId());
+
+
+ @SuppressWarnings("unchecked")
+ List<ProductRelationship> relations = q.getResultList();
+
+
+ return relations;
+
+
+ }
+
+ @Override
+ public List<ProductRelationship> getByType(MerchantStore store, String type, Product product) {
+ //QDSL cannot interpret the following query, that is why it is in native format
+
+
+ StringBuilder qs = new StringBuilder();
+
+ qs.append("select distinct pr from ProductRelationship as pr ");
+ qs.append("left join fetch pr.product p ");
+ qs.append("left join fetch pr.relatedProduct rp ");
+
+ qs.append("left join fetch rp.attributes pattr ");
+ qs.append("left join fetch rp.descriptions rpd ");
+ qs.append("left join fetch rp.images pd ");
+ qs.append("left join fetch rp.merchantStore rpm ");
+ qs.append("left join fetch rpm.currency rpmc ");
+ qs.append("left join fetch rp.availabilities pa ");
+ qs.append("left join fetch pa.prices pap ");
+ qs.append("left join fetch pap.descriptions papd ");
+
+ qs.append("left join fetch rp.manufacturer manuf ");
+ qs.append("left join fetch manuf.descriptions manufd ");
+ qs.append("left join fetch rp.type type ");
+
+ qs.append("where pr.code=:code ");
+ qs.append("and p.id=:pId");
+
+
+
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+ q.setParameter("code", type);
+ q.setParameter("pId", product.getId());
+
+
+ @SuppressWarnings("unchecked")
+ List<ProductRelationship> relations = q.getResultList();
+
+
+ return relations;
+
+
+ }
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/review/ProductReviewDao.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/review/ProductReviewDao.java
new file mode 100644
index 0000000..086bfcb
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/review/ProductReviewDao.java
@@ -0,0 +1,22 @@
+package com.salesmanager.core.business.catalog.product.dao.review;
+
+import java.util.List;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.review.ProductReview;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface ProductReviewDao extends SalesManagerEntityDao<Long, ProductReview> {
+
+ List<ProductReview> getByCustomer(Customer customer);
+ List<ProductReview> getByProduct(Product product);
+ List<ProductReview> getByProduct(Product product, Language language);
+ ProductReview getByProductAndCustomer(Long productId, Long customerId);
+
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/review/ProductReviewDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/review/ProductReviewDaoImpl.java
new file mode 100644
index 0000000..710065c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/review/ProductReviewDaoImpl.java
@@ -0,0 +1,175 @@
+package com.salesmanager.core.business.catalog.product.dao.review;
+
+import java.util.List;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.QProduct;
+import com.salesmanager.core.business.catalog.product.model.review.ProductReview;
+import com.salesmanager.core.business.catalog.product.model.review.QProductReview;
+import com.salesmanager.core.business.catalog.product.model.review.QProductReviewDescription;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.customer.model.QCustomer;
+import com.salesmanager.core.business.customer.model.attribute.QCustomerAttribute;
+import com.salesmanager.core.business.customer.model.attribute.QCustomerOption;
+import com.salesmanager.core.business.customer.model.attribute.QCustomerOptionValue;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Repository("productReviewDao")
+public class ProductReviewDaoImpl extends SalesManagerEntityDaoImpl<Long, ProductReview>
+ implements ProductReviewDao {
+
+
+
+ @Override
+ public List<ProductReview> getByCustomer(Customer customer) {
+
+ QProductReview qEntity = QProductReview.productReview;
+ QProductReviewDescription qDescription = QProductReviewDescription.productReviewDescription;
+ QCustomer qCustomer = QCustomer.customer;
+ QProduct qProduct = QProduct.product;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qEntity)
+ .join(qEntity.customer,qCustomer).fetch()
+ .join(qEntity.product,qProduct).fetch()
+ .leftJoin(qProduct.merchantStore).fetch()
+ .leftJoin(qEntity.descriptions,qDescription).fetch()
+ .where(qCustomer.id.eq(customer.getId()));
+
+ return query.list(qEntity);
+
+
+
+ }
+
+ @Override
+ public List<ProductReview> getByProduct(Product product) {
+
+
+ QProductReview qEntity = QProductReview.productReview;
+ QProductReviewDescription qDescription = QProductReviewDescription.productReviewDescription;
+ QProduct qProduct = QProduct.product;
+ QCustomer qCustomer = QCustomer.customer;
+ QCustomerAttribute qCustomerAttribute = QCustomerAttribute.customerAttribute;
+ QCustomerOption qCustomerOption = QCustomerOption.customerOption;
+ QCustomerOptionValue qCustomerOptionValue = QCustomerOptionValue.customerOptionValue;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qEntity)
+ .join(qEntity.customer, qCustomer).fetch()
+ .join(qCustomer.merchantStore).fetch()
+ .leftJoin(qCustomer.defaultLanguage).fetch()
+ .leftJoin(qCustomer.attributes,qCustomerAttribute).fetch()
+ .leftJoin(qCustomerAttribute.customerOption, qCustomerOption).fetch()
+ .leftJoin(qCustomerAttribute.customerOptionValue, qCustomerOptionValue).fetch()
+ .leftJoin(qCustomerOption.descriptions).fetch()
+ .leftJoin(qCustomerOptionValue.descriptions).fetch()
+ .join(qEntity.product,qProduct).fetch()
+ .leftJoin(qProduct.merchantStore).fetch()
+ .leftJoin(qEntity.descriptions,qDescription).fetch()
+ .where(qProduct.id.eq(product.getId()));
+
+ return query.list(qEntity);
+
+
+ }
+
+
+ @Override
+ public ProductReview getByProductAndCustomer(Long productId, Long customerId) {
+
+
+ QProductReview qEntity = QProductReview.productReview;
+ QProductReviewDescription qDescription = QProductReviewDescription.productReviewDescription;
+ QProduct qProduct = QProduct.product;
+ QCustomer qCustomer = QCustomer.customer;
+ QCustomerAttribute qCustomerAttribute = QCustomerAttribute.customerAttribute;
+ QCustomerOption qCustomerOption = QCustomerOption.customerOption;
+ QCustomerOptionValue qCustomerOptionValue = QCustomerOptionValue.customerOptionValue;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qEntity)
+ .join(qEntity.customer, qCustomer).fetch()
+ .join(qCustomer.merchantStore).fetch()
+ .leftJoin(qCustomer.defaultLanguage).fetch()
+ .leftJoin(qCustomer.attributes,qCustomerAttribute).fetch()
+ .leftJoin(qCustomerAttribute.customerOption, qCustomerOption).fetch()
+ .leftJoin(qCustomerAttribute.customerOptionValue, qCustomerOptionValue).fetch()
+ .leftJoin(qCustomerOption.descriptions).fetch()
+ .leftJoin(qCustomerOptionValue.descriptions).fetch()
+ .join(qEntity.product,qProduct).fetch()
+ .leftJoin(qProduct.merchantStore).fetch()
+ .leftJoin(qEntity.descriptions,qDescription).fetch()
+ .where(qProduct.id.eq(productId).and(qCustomer.id.eq(customerId)));
+
+ return query.uniqueResult(qEntity);
+
+
+ }
+
+ @Override
+ public List<ProductReview> getByProduct(Product product, Language language) {
+
+
+ QProductReview qEntity = QProductReview.productReview;
+ QProductReviewDescription qDescription = QProductReviewDescription.productReviewDescription;
+ QProduct qProduct = QProduct.product;
+ QCustomer qCustomer = QCustomer.customer;
+ QCustomerAttribute qCustomerAttribute = QCustomerAttribute.customerAttribute;
+ QCustomerOption qCustomerOption = QCustomerOption.customerOption;
+ QCustomerOptionValue qCustomerOptionValue = QCustomerOptionValue.customerOptionValue;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qEntity)
+ .join(qEntity.customer, qCustomer).fetch()
+ .join(qCustomer.merchantStore).fetch()
+ .leftJoin(qCustomer.defaultLanguage).fetch()
+ .leftJoin(qCustomer.attributes,qCustomerAttribute).fetch()
+ .leftJoin(qCustomerAttribute.customerOption, qCustomerOption).fetch()
+ .leftJoin(qCustomerAttribute.customerOptionValue, qCustomerOptionValue).fetch()
+ .leftJoin(qCustomerOption.descriptions).fetch()
+ .leftJoin(qCustomerOptionValue.descriptions).fetch()
+ .join(qEntity.product,qProduct).fetch()
+ .leftJoin(qProduct.merchantStore).fetch()
+ .leftJoin(qEntity.descriptions,qDescription).fetch()
+ .where(qProduct.id.eq(product.getId())
+ .and(qDescription.language.id.eq(language.getId())));
+
+ return query.list(qEntity);
+
+
+ }
+
+ @Override
+ public ProductReview getById(Long id) {
+
+ QProductReview qEntity = QProductReview.productReview;
+ QProductReviewDescription qDescription = QProductReviewDescription.productReviewDescription;
+ QProduct qProduct = QProduct.product;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qEntity)
+ .join(qEntity.customer).fetch()
+ .join(qEntity.product,qProduct).fetch()
+ .leftJoin(qProduct.merchantStore).fetch()
+ .leftJoin(qEntity.descriptions,qDescription).fetch()
+ .where(qEntity.id.eq(id));
+
+ return query.uniqueResult(qEntity);
+
+
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/type/ProductTypeDao.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/type/ProductTypeDao.java
new file mode 100644
index 0000000..7fe254d
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/type/ProductTypeDao.java
@@ -0,0 +1,8 @@
+package com.salesmanager.core.business.catalog.product.dao.type;
+
+import com.salesmanager.core.business.catalog.product.model.type.ProductType;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+
+public interface ProductTypeDao extends SalesManagerEntityDao<Long, ProductType> {
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/type/ProductTypeDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/type/ProductTypeDaoImpl.java
new file mode 100644
index 0000000..b49d8e0
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/dao/type/ProductTypeDaoImpl.java
@@ -0,0 +1,14 @@
+package com.salesmanager.core.business.catalog.product.dao.type;
+
+import org.springframework.stereotype.Repository;
+
+import com.salesmanager.core.business.catalog.product.model.type.ProductType;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+
+@Repository("productTypeDao")
+public class ProductTypeDaoImpl extends SalesManagerEntityDaoImpl<Long, ProductType>
+ implements ProductTypeDao {
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/AttributeCriteria.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/AttributeCriteria.java
new file mode 100644
index 0000000..f317615
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/AttributeCriteria.java
@@ -0,0 +1,26 @@
+package com.salesmanager.core.business.catalog.product.model.attribute;
+
+import java.io.Serializable;
+
+public class AttributeCriteria implements Serializable {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+ private String attributeCode;
+ private String attributeValue;
+ public void setAttributeCode(String attributeCode) {
+ this.attributeCode = attributeCode;
+ }
+ public String getAttributeCode() {
+ return attributeCode;
+ }
+ public void setAttributeValue(String attributeValue) {
+ this.attributeValue = attributeValue;
+ }
+ public String getAttributeValue() {
+ return attributeValue;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductAttribute.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductAttribute.java
new file mode 100755
index 0000000..30b8f91
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductAttribute.java
@@ -0,0 +1,241 @@
+package com.salesmanager.core.business.catalog.product.model.attribute;
+
+import java.math.BigDecimal;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Transient;
+import javax.persistence.UniqueConstraint;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@Table(name="PRODUCT_ATTRIBUTE", schema=SchemaConstant.SALESMANAGER_SCHEMA,
+ uniqueConstraints={
+ @UniqueConstraint(columnNames={
+ "OPTION_ID",
+ "OPTION_VALUE_ID",
+ "PRODUCT_ID"
+ })
+ }
+)
+public class ProductAttribute extends SalesManagerEntity<Long, ProductAttribute> {
+ private static final long serialVersionUID = -6537491946539803265L;
+
+ @Id
+ @Column(name = "PRODUCT_ATTRIBUTE_ID", unique=true, nullable=false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "PRODUCT_ATTR_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+
+ @Column(name="PRODUCT_ATRIBUTE_PRICE")
+ private BigDecimal productAttributePrice;
+
+
+ @Column(name="PRODUCT_ATTRIBUTE_SORT_ORD")
+ private Integer productOptionSortOrder;
+
+ @Column(name="PRODUCT_ATTRIBUTE_FREE")
+ private boolean productAttributeIsFree;
+
+
+ @Column(name="PRODUCT_ATTRIBUTE_WEIGHT")
+ private BigDecimal productAttributeWeight;
+
+ @Column(name="PRODUCT_ATTRIBUTE_DEFAULT")
+ private boolean attributeDefault=false;
+
+ @Column(name="PRODUCT_ATTRIBUTE_REQUIRED")
+ private boolean attributeRequired=false;
+
+ /**
+ * a read only attribute is considered as a core attribute addition
+ */
+ @Column(name="PRODUCT_ATTRIBUTE_FOR_DISP")
+ private boolean attributeDisplayOnly=false;
+
+
+ @Column(name="PRODUCT_ATTRIBUTE_DISCOUNTED")
+ private boolean attributeDiscounted=false;
+
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="OPTION_ID", nullable=false)
+ private ProductOption productOption;
+
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="OPTION_VALUE_ID", nullable=false)
+ private ProductOptionValue productOptionValue;
+
+
+ /**
+ * This transient object property
+ * is a utility used only to submit from a free text
+ */
+ @Transient
+ private String attributePrice = "0";
+
+
+ /**
+ * This transient object property
+ * is a utility used only to submit from a free text
+ */
+ @Transient
+ private String attributeSortOrder = "0";
+
+
+
+ /**
+ * This transient object property
+ * is a utility used only to submit from a free text
+ */
+ @Transient
+ private String attributeAdditionalWeight = "0";
+
+ public String getAttributePrice() {
+ return attributePrice;
+ }
+
+ public void setAttributePrice(String attributePrice) {
+ this.attributePrice = attributePrice;
+ }
+
+ @ManyToOne(targetEntity = Product.class)
+ @JoinColumn(name = "PRODUCT_ID", nullable = false)
+ private Product product;
+
+ public ProductAttribute() {
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+
+
+ public Integer getProductOptionSortOrder() {
+ return productOptionSortOrder;
+ }
+
+ public void setProductOptionSortOrder(Integer productOptionSortOrder) {
+ this.productOptionSortOrder = productOptionSortOrder;
+ }
+
+ public boolean getProductAttributeIsFree() {
+ return productAttributeIsFree;
+ }
+
+ public void setProductAttributeIsFree(boolean productAttributeIsFree) {
+ this.productAttributeIsFree = productAttributeIsFree;
+ }
+
+ public BigDecimal getProductAttributeWeight() {
+ return productAttributeWeight;
+ }
+
+ public void setProductAttributeWeight(BigDecimal productAttributeWeight) {
+ this.productAttributeWeight = productAttributeWeight;
+ }
+
+ public boolean getAttributeDefault() {
+ return attributeDefault;
+ }
+
+ public void setAttributeDefault(boolean attributeDefault) {
+ this.attributeDefault = attributeDefault;
+ }
+
+ public boolean getAttributeRequired() {
+ return attributeRequired;
+ }
+
+ public void setAttributeRequired(boolean attributeRequired) {
+ this.attributeRequired = attributeRequired;
+ }
+
+ public boolean getAttributeDisplayOnly() {
+ return attributeDisplayOnly;
+ }
+
+ public void setAttributeDisplayOnly(boolean attributeDisplayOnly) {
+ this.attributeDisplayOnly = attributeDisplayOnly;
+ }
+
+ public boolean getAttributeDiscounted() {
+ return attributeDiscounted;
+ }
+
+ public void setAttributeDiscounted(boolean attributeDiscounted) {
+ this.attributeDiscounted = attributeDiscounted;
+ }
+
+ public ProductOption getProductOption() {
+ return productOption;
+ }
+
+ public void setProductOption(ProductOption productOption) {
+ this.productOption = productOption;
+ }
+
+ public ProductOptionValue getProductOptionValue() {
+ return productOptionValue;
+ }
+
+ public void setProductOptionValue(ProductOptionValue productOptionValue) {
+ this.productOptionValue = productOptionValue;
+ }
+
+ public Product getProduct() {
+ return product;
+ }
+
+ public void setProduct(Product product) {
+ this.product = product;
+ }
+
+
+ public String getAttributeSortOrder() {
+ return attributeSortOrder;
+ }
+
+ public void setAttributeSortOrder(String attributeSortOrder) {
+ this.attributeSortOrder = attributeSortOrder;
+ }
+
+ public String getAttributeAdditionalWeight() {
+ return attributeAdditionalWeight;
+ }
+
+ public void setAttributeAdditionalWeight(String attributeAdditionalWeight) {
+ this.attributeAdditionalWeight = attributeAdditionalWeight;
+ }
+
+ public BigDecimal getProductAttributePrice() {
+ return productAttributePrice;
+ }
+
+ public void setProductAttributePrice(BigDecimal productAttributePrice) {
+ this.productAttributePrice = productAttributePrice;
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductOption.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductOption.java
new file mode 100755
index 0000000..e05353c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductOption.java
@@ -0,0 +1,149 @@
+package com.salesmanager.core.business.catalog.product.model.attribute;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Transient;
+import javax.persistence.UniqueConstraint;
+import javax.validation.constraints.Pattern;
+
+import org.hibernate.annotations.Index;
+import org.hibernate.validator.constraints.NotEmpty;
+
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.constants.SchemaConstant;
+
+
+@Entity
+@Table(name="PRODUCT_OPTION", schema=SchemaConstant.SALESMANAGER_SCHEMA, uniqueConstraints=
+ @UniqueConstraint(columnNames = {"MERCHANT_ID", "PRODUCT_OPTION_CODE"}))
+public class ProductOption extends SalesManagerEntity<Long, ProductOption> {
+ private static final long serialVersionUID = -2019269055342226086L;
+
+ @Id
+ @Column(name="PRODUCT_OPTION_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "PRODUCT_OPTION_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @Column(name="PRODUCT_OPTION_SORT_ORD")
+ private Integer productOptionSortOrder;
+
+ @Column(name="PRODUCT_OPTION_TYPE", length=10)
+ private String productOptionType;
+
+
+ @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "productOption")
+ private Set<ProductOptionDescription> descriptions = new HashSet<ProductOptionDescription>();
+
+ @Transient
+ private List<ProductOptionDescription> descriptionsList = new ArrayList<ProductOptionDescription>();
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="MERCHANT_ID", nullable=false)
+ private MerchantStore merchantStore;
+
+ @Column(name="PRODUCT_OPTION_READ")
+ private boolean readOnly;
+
+ @NotEmpty
+ @Pattern(regexp="^[a-zA-Z0-9_]*$")
+ @Column(name="PRODUCT_OPTION_CODE")
+ @Index(name="PRD_OPTION_CODE_IDX")
+ private String code;
+
+ public ProductOption() {
+ }
+
+ public Integer getProductOptionSortOrder() {
+ return productOptionSortOrder;
+ }
+
+ public void setProductOptionSortOrder(Integer productOptionSortOrder) {
+ this.productOptionSortOrder = productOptionSortOrder;
+ }
+
+ public String getProductOptionType() {
+ return productOptionType;
+ }
+
+ public void setProductOptionType(String productOptionType) {
+ this.productOptionType = productOptionType;
+ }
+
+ public Set<ProductOptionDescription> getDescriptions() {
+ return descriptions;
+ }
+
+ public void setDescriptions(Set<ProductOptionDescription> descriptions) {
+ this.descriptions = descriptions;
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+
+
+ public MerchantStore getMerchantStore() {
+ return merchantStore;
+ }
+
+ public void setMerchantStore(MerchantStore merchantStore) {
+ this.merchantStore = merchantStore;
+ }
+
+ public void setDescriptionsList(List<ProductOptionDescription> descriptionsList) {
+ this.descriptionsList = descriptionsList;
+ }
+
+ public List<ProductOptionDescription> getDescriptionsList() {
+ return descriptionsList;
+ }
+
+
+ public List<ProductOptionDescription> getDescriptionsSettoList() {
+ if(descriptionsList==null || descriptionsList.size()==0) {
+ descriptionsList = new ArrayList<ProductOptionDescription>(this.getDescriptions());
+ }
+ return descriptionsList;
+
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setReadOnly(boolean readOnly) {
+ this.readOnly = readOnly;
+ }
+
+ public boolean isReadOnly() {
+ return readOnly;
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductOptionDescription.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductOptionDescription.java
new file mode 100755
index 0000000..d458f2c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductOptionDescription.java
@@ -0,0 +1,51 @@
+package com.salesmanager.core.business.catalog.product.model.attribute;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import org.hibernate.annotations.Type;
+
+import com.salesmanager.core.business.common.model.Description;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@Table(name="PRODUCT_OPTION_DESC", schema=SchemaConstant.SALESMANAGER_SCHEMA, uniqueConstraints={
+ @UniqueConstraint(columnNames={
+ "PRODUCT_OPTION_ID",
+ "LANGUAGE_ID"
+ })
+ }
+)
+public class ProductOptionDescription extends Description {
+ private static final long serialVersionUID = -3158504904707188465L;
+
+ @ManyToOne(targetEntity = ProductOption.class)
+ @JoinColumn(name = "PRODUCT_OPTION_ID", nullable = false)
+ private ProductOption productOption;
+
+ @Column(name="PRODUCT_OPTION_COMMENT")
+ @Type(type = "org.hibernate.type.StringClobType")
+ private String productOptionComment;
+
+ public ProductOptionDescription() {
+ }
+
+ public String getProductOptionComment() {
+ return productOptionComment;
+ }
+ public void setProductOptionComment(String productOptionComment) {
+ this.productOptionComment = productOptionComment;
+ }
+
+ public ProductOption getProductOption() {
+ return productOption;
+ }
+
+ public void setProductOption(ProductOption productOption) {
+ this.productOption = productOption;
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductOptionType.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductOptionType.java
new file mode 100644
index 0000000..1c1ab6b
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductOptionType.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.catalog.product.model.attribute;
+
+public enum ProductOptionType {
+
+ Text, Radio, Select, Checkbox
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductOptionValue.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductOptionValue.java
new file mode 100755
index 0000000..376a19c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductOptionValue.java
@@ -0,0 +1,160 @@
+package com.salesmanager.core.business.catalog.product.model.attribute;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Transient;
+import javax.persistence.UniqueConstraint;
+import javax.validation.constraints.Pattern;
+
+import org.hibernate.annotations.Index;
+import org.hibernate.validator.constraints.NotEmpty;
+import org.springframework.web.multipart.MultipartFile;
+
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.constants.SchemaConstant;
+
+
+@Entity
+@Table(name="PRODUCT_OPTION_VALUE", schema=SchemaConstant.SALESMANAGER_SCHEMA, uniqueConstraints=
+ @UniqueConstraint(columnNames = {"MERCHANT_ID", "PRODUCT_OPTION_VAL_CODE"}))
+public class ProductOptionValue extends SalesManagerEntity<Long, ProductOptionValue> {
+ private static final long serialVersionUID = 3736085877929910891L;
+
+ @Id
+ @Column(name="PRODUCT_OPTION_VALUE_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "PRODUCT_OPT_VAL_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @Column(name="PRODUCT_OPT_VAL_SORT_ORD")
+ private Integer productOptionValueSortOrder;
+
+ @Column(name="PRODUCT_OPT_VAL_IMAGE")
+ private String productOptionValueImage;
+
+ @Column(name="PRODUCT_OPT_FOR_DISP")
+ private boolean productOptionDisplayOnly=false;
+
+ @NotEmpty
+ @Pattern(regexp="^[a-zA-Z0-9_]*$")
+ @Column(name="PRODUCT_OPTION_VAL_CODE")
+ @Index(name="PRD_OPTION_VAL_CODE_IDX")
+ private String code;
+
+ @Transient
+ private MultipartFile image = null;
+
+ @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "productOptionValue")
+ private Set<ProductOptionValueDescription> descriptions = new HashSet<ProductOptionValueDescription>();
+
+ @Transient
+ private List<ProductOptionValueDescription> descriptionsList = new ArrayList<ProductOptionValueDescription>();
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="MERCHANT_ID", nullable=false)
+ private MerchantStore merchantStore;
+
+ public ProductOptionValue() {
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Integer getProductOptionValueSortOrder() {
+ return productOptionValueSortOrder;
+ }
+
+ public void setProductOptionValueSortOrder(Integer productOptionValueSortOrder) {
+ this.productOptionValueSortOrder = productOptionValueSortOrder;
+ }
+
+ public String getProductOptionValueImage() {
+ return productOptionValueImage;
+ }
+
+ public void setProductOptionValueImage(String productOptionValueImage) {
+ this.productOptionValueImage = productOptionValueImage;
+ }
+
+ public Set<ProductOptionValueDescription> getDescriptions() {
+ return descriptions;
+ }
+
+ public void setDescriptions(Set<ProductOptionValueDescription> descriptions) {
+ this.descriptions = descriptions;
+ }
+
+ public MerchantStore getMerchantStore() {
+ return merchantStore;
+ }
+
+ public void setMerchantStore(MerchantStore merchantStore) {
+ this.merchantStore = merchantStore;
+ }
+
+ public void setDescriptionsList(List<ProductOptionValueDescription> descriptionsList) {
+ this.descriptionsList = descriptionsList;
+ }
+
+ public List<ProductOptionValueDescription> getDescriptionsList() {
+ return descriptionsList;
+ }
+
+ public List<ProductOptionValueDescription> getDescriptionsSettoList() {
+ if(descriptionsList==null || descriptionsList.size()==0) {
+ descriptionsList = new ArrayList<ProductOptionValueDescription>(this.getDescriptions());
+ }
+ return descriptionsList;
+ }
+
+ public void setImage(MultipartFile image) {
+ this.image = image;
+ }
+
+ public MultipartFile getImage() {
+ return image;
+ }
+
+ public boolean isProductOptionDisplayOnly() {
+ return productOptionDisplayOnly;
+ }
+
+ public void setProductOptionDisplayOnly(boolean productOptionDisplayOnly) {
+ this.productOptionDisplayOnly = productOptionDisplayOnly;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductOptionValueDescription.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductOptionValueDescription.java
new file mode 100644
index 0000000..08fab19
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/attribute/ProductOptionValueDescription.java
@@ -0,0 +1,38 @@
+package com.salesmanager.core.business.catalog.product.model.attribute;
+
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import com.salesmanager.core.business.common.model.Description;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@Table(name = "PRODUCT_OPTION_VALUE_DESCRIPTION", schema=SchemaConstant.SALESMANAGER_SCHEMA, uniqueConstraints={
+ @UniqueConstraint(columnNames={
+ "PRODUCT_OPTION_VALUE_ID",
+ "LANGUAGE_ID"
+ })
+ }
+)
+public class ProductOptionValueDescription extends Description {
+ private static final long serialVersionUID = 7402155175956813576L;
+
+ @ManyToOne(targetEntity = ProductOptionValue.class)
+ @JoinColumn(name = "PRODUCT_OPTION_VALUE_ID")
+ private ProductOptionValue productOptionValue;
+
+ public ProductOptionValueDescription() {
+ }
+
+ public ProductOptionValue getProductOptionValue() {
+ return productOptionValue;
+ }
+
+ public void setProductOptionValue(ProductOptionValue productOptionValue) {
+ this.productOptionValue = productOptionValue;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/availability/ProductAvailability.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/availability/ProductAvailability.java
new file mode 100755
index 0000000..c425f04
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/availability/ProductAvailability.java
@@ -0,0 +1,184 @@
+package com.salesmanager.core.business.catalog.product.model.availability;
+
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.persistence.Transient;
+import javax.validation.constraints.NotNull;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPrice;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.constants.Constants;
+import com.salesmanager.core.constants.SchemaConstant;
+import com.salesmanager.core.utils.CloneUtils;
+
+
+@Entity
+@Table(name="PRODUCT_AVAILABILITY", schema=SchemaConstant.SALESMANAGER_SCHEMA)
+public class ProductAvailability extends SalesManagerEntity<Long, ProductAvailability> {
+ private static final long serialVersionUID = 7449264635180797762L;
+
+ @Id
+ @Column(name = "PRODUCT_AVAIL_ID", unique=true, nullable=false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "PRODUCT_AVAIL_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+
+ @ManyToOne(targetEntity = Product.class)
+ @JoinColumn(name = "PRODUCT_ID", nullable = false)
+ private Product product;
+
+ @NotNull
+ @Column(name="QUANTITY")
+ private Integer productQuantity = 0;
+
+ @Temporal(TemporalType.DATE)
+ @Column(name="DATE_AVAILABLE")
+ private Date productDateAvailable;
+
+ @Column(name="REGION")
+ private String region = Constants.ALL_REGIONS;
+
+ @Column(name="REGION_VARIANT")
+ private String regionVariant;
+
+ @Column(name="STATUS")
+ private boolean productStatus = true;
+
+ @Column(name="FREE_SHIPPING")
+ private boolean productIsAlwaysFreeShipping;
+
+ @Column(name="QUANTITY_ORD_MIN")
+ private Integer productQuantityOrderMin = 0;
+
+ @Column(name="QUANTITY_ORD_MAX")
+ private Integer productQuantityOrderMax = 0;
+
+ @OneToMany(fetch = FetchType.LAZY, mappedBy="productAvailability", cascade = CascadeType.REMOVE)
+ private Set<ProductPrice> prices = new HashSet<ProductPrice>();
+
+ @Transient
+ public ProductPrice defaultPrice() {
+
+ for(ProductPrice price : prices) {
+ if(price.isDefaultPrice()) {
+ return price;
+ }
+ }
+ return new ProductPrice();
+ }
+
+ public ProductAvailability() {
+ }
+
+ public Integer getProductQuantity() {
+ return productQuantity;
+ }
+
+ public void setProductQuantity(Integer productQuantity) {
+ this.productQuantity = productQuantity;
+ }
+
+ public Date getProductDateAvailable() {
+ return CloneUtils.clone(productDateAvailable);
+ }
+
+ public void setProductDateAvailable(Date productDateAvailable) {
+ this.productDateAvailable = CloneUtils.clone(productDateAvailable);
+ }
+
+ public String getRegion() {
+ return region;
+ }
+
+ public void setRegion(String region) {
+ this.region = region;
+ }
+
+ public String getRegionVariant() {
+ return regionVariant;
+ }
+
+ public void setRegionVariant(String regionVariant) {
+ this.regionVariant = regionVariant;
+ }
+
+ public boolean getProductStatus() {
+ return productStatus;
+ }
+
+ public void setProductStatus(boolean productStatus) {
+ this.productStatus = productStatus;
+ }
+
+ public boolean getProductIsAlwaysFreeShipping() {
+ return productIsAlwaysFreeShipping;
+ }
+
+ public void setProductIsAlwaysFreeShipping(boolean productIsAlwaysFreeShipping) {
+ this.productIsAlwaysFreeShipping = productIsAlwaysFreeShipping;
+ }
+
+ public Integer getProductQuantityOrderMin() {
+ return productQuantityOrderMin;
+ }
+
+ public void setProductQuantityOrderMin(Integer productQuantityOrderMin) {
+ this.productQuantityOrderMin = productQuantityOrderMin;
+ }
+
+ public Integer getProductQuantityOrderMax() {
+ return productQuantityOrderMax;
+ }
+
+ public void setProductQuantityOrderMax(Integer productQuantityOrderMax) {
+ this.productQuantityOrderMax = productQuantityOrderMax;
+ }
+
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Product getProduct() {
+ return product;
+ }
+
+ public void setProduct(Product product) {
+ this.product = product;
+ }
+
+
+
+ public Set<ProductPrice> getPrices() {
+ return prices;
+ }
+
+ public void setPrices(Set<ProductPrice> prices) {
+ this.prices = prices;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/description/ProductDescription.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/description/ProductDescription.java
new file mode 100644
index 0000000..5d4774f
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/description/ProductDescription.java
@@ -0,0 +1,105 @@
+package com.salesmanager.core.business.catalog.product.model.description;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.common.model.Description;
+
+@Entity
+@Table(name = "PRODUCT_DESCRIPTION", schema="SALESMANAGER", uniqueConstraints={
+ @UniqueConstraint(columnNames={
+ "PRODUCT_ID",
+ "LANGUAGE_ID"
+ })
+ }
+)
+public class ProductDescription extends Description {
+ private static final long serialVersionUID = -7991123535661321865L;
+
+ @ManyToOne(targetEntity = Product.class)
+ @JoinColumn(name = "PRODUCT_ID", nullable = false)
+ private Product product;
+
+ @Column(name = "PRODUCT_HIGHLIGHT")
+ private String productHighlight;
+
+ @Column(name = "DOWNLOAD_LNK")
+ private String productExternalDl;
+
+ @Column(name = "SEF_URL")
+ private String seUrl;
+
+ @Column(name = "META_TITLE")
+ private String metatagTitle;
+
+ @Column(name = "META_KEYWORDS")
+ private String metatagKeywords;
+
+ @Column(name = "META_DESCRIPTION")
+ private String metatagDescription;
+
+ public ProductDescription() {
+ }
+
+ public String getProductHighlight() {
+ return productHighlight;
+ }
+
+ public void setProductHighlight(String productHighlight) {
+ this.productHighlight = productHighlight;
+ }
+
+ public String getProductExternalDl() {
+ return productExternalDl;
+ }
+
+ public void setProductExternalDl(String productExternalDl) {
+ this.productExternalDl = productExternalDl;
+ }
+
+ public String getSeUrl() {
+ return seUrl;
+ }
+
+ public void setSeUrl(String seUrl) {
+ this.seUrl = seUrl;
+ }
+
+ public String getMetatagTitle() {
+ return metatagTitle;
+ }
+
+ public void setMetatagTitle(String metatagTitle) {
+ this.metatagTitle = metatagTitle;
+ }
+
+ public String getMetatagKeywords() {
+ return metatagKeywords;
+ }
+
+ public void setMetatagKeywords(String metatagKeywords) {
+ this.metatagKeywords = metatagKeywords;
+ }
+
+ public String getMetatagDescription() {
+ return metatagDescription;
+ }
+
+ public void setMetatagDescription(String metatagDescription) {
+ this.metatagDescription = metatagDescription;
+ }
+
+ public Product getProduct() {
+ return product;
+ }
+
+ public void setProduct(Product product) {
+ this.product = product;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/file/DigitalProduct.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/file/DigitalProduct.java
new file mode 100644
index 0000000..130b669
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/file/DigitalProduct.java
@@ -0,0 +1,76 @@
+package com.salesmanager.core.business.catalog.product.model.file;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.UniqueConstraint;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.constants.SchemaConstant;
+
+
+/**
+ * Representation of a digital product
+ * @author csamson777
+ *
+ */
+@Entity
+@Table(name = "PRODUCT_DIGITAL", schema=SchemaConstant.SALESMANAGER_SCHEMA, uniqueConstraints=
+ @UniqueConstraint(columnNames = {"PRODUCT_ID", "FILE_NAME"}))
+public class DigitalProduct extends SalesManagerEntity<Long, DigitalProduct> {
+
+
+ private static final long serialVersionUID = 1L;
+
+
+ @Id
+ @Column(name = "PRODUCT_DIGITAL_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "PRODUCT_DGT_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+
+ @ManyToOne(targetEntity = Product.class)
+ @JoinColumn(name = "PRODUCT_ID", nullable = false)
+ private Product product;
+
+
+ @Column(name="FILE_NAME",nullable=false)
+ private String productFileName;
+
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getProductFileName() {
+ return productFileName;
+ }
+
+ public void setProductFileName(String productFileName) {
+ this.productFileName = productFileName;
+ }
+
+ public Product getProduct() {
+ return product;
+ }
+
+ public void setProduct(Product product) {
+ this.product = product;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/file/ProductImageSize.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/file/ProductImageSize.java
new file mode 100755
index 0000000..6db38a9
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/file/ProductImageSize.java
@@ -0,0 +1,10 @@
+package com.salesmanager.core.business.catalog.product.model.file;
+
+public enum ProductImageSize {
+
+ LARGE,
+ SMALL
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/image/ProductImage.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/image/ProductImage.java
new file mode 100755
index 0000000..91d8664
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/image/ProductImage.java
@@ -0,0 +1,132 @@
+package com.salesmanager.core.business.catalog.product.model.image;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Transient;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+
+@Entity
+@Table(name = "PRODUCT_IMAGE", schema="SALESMANAGER")
+public class ProductImage extends SalesManagerEntity<Long, ProductImage> {
+ private static final long serialVersionUID = 247514890386076337L;
+
+ @Id
+ @Column(name = "PRODUCT_IMAGE_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "PRODUCT_IMG_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @OneToMany(fetch = FetchType.LAZY, mappedBy = "productImage", cascade = CascadeType.ALL)
+ private List<ProductImageDescription> descriptions = new ArrayList<ProductImageDescription>();
+
+
+ @Column(name = "PRODUCT_IMAGE")
+ private String productImage;
+
+ @Column(name = "DEFAULT_IMAGE")
+ private boolean defaultImage = true;
+
+ @Column(name = "IMAGE_TYPE")
+ private int imageType;
+
+ @Column(name = "IMAGE_CROP")
+ private boolean imageCrop;
+
+ @ManyToOne(targetEntity = Product.class)
+ @JoinColumn(name = "PRODUCT_ID", nullable = false)
+ private Product product;
+
+ @Transient
+ private InputStream image = null;
+
+ //private MultiPartFile image
+
+ public ProductImage(){
+ }
+
+ public String getProductImage() {
+ return productImage;
+ }
+
+ public void setProductImage(String productImage) {
+ this.productImage = productImage;
+ }
+
+ public boolean isDefaultImage() {
+ return defaultImage;
+ }
+
+ public void setDefaultImage(boolean defaultImage) {
+ this.defaultImage = defaultImage;
+ }
+
+ public int getImageType() {
+ return imageType;
+ }
+
+ public void setImageType(int imageType) {
+ this.imageType = imageType;
+ }
+
+ public boolean isImageCrop() {
+ return imageCrop;
+ }
+
+ public void setImageCrop(boolean imageCrop) {
+ this.imageCrop = imageCrop;
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Product getProduct() {
+ return product;
+ }
+
+ public void setProduct(Product product) {
+ this.product = product;
+ }
+
+ public void setDescriptions(List<ProductImageDescription> descriptions) {
+ this.descriptions = descriptions;
+ }
+
+ public List<ProductImageDescription> getDescriptions() {
+ return descriptions;
+ }
+
+ public InputStream getImage() {
+ return image;
+ }
+
+ public void setImage(InputStream image) {
+ this.image = image;
+ }
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/image/ProductImageDescription.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/image/ProductImageDescription.java
new file mode 100644
index 0000000..c945f3e
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/image/ProductImageDescription.java
@@ -0,0 +1,48 @@
+package com.salesmanager.core.business.catalog.product.model.image;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import com.salesmanager.core.business.common.model.Description;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@Table(name="PRODUCT_IMAGE_DESCRIPTION", schema=SchemaConstant.SALESMANAGER_SCHEMA, uniqueConstraints={
+ @UniqueConstraint(columnNames={
+ "PRODUCT_IMAGE_ID",
+ "LANGUAGE_ID"
+ })
+ }
+)
+public class ProductImageDescription extends Description {
+ private static final long serialVersionUID = 247514890386076337L;
+
+ @ManyToOne(targetEntity = ProductImage.class)
+ @JoinColumn(name = "PRODUCT_IMAGE_ID", nullable = false)
+ private ProductImage productImage;
+
+ @Column(name="ALT_TAG", length=100)
+ private String altTag;
+
+ public ProductImage getProductImage() {
+ return productImage;
+ }
+
+ public void setProductImage(ProductImage productImage) {
+ this.productImage = productImage;
+ }
+
+ public String getAltTag() {
+ return altTag;
+ }
+
+ public void setAltTag(String altTag) {
+ this.altTag = altTag;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/manufacturer/Manufacturer.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/manufacturer/Manufacturer.java
new file mode 100644
index 0000000..7e79634
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/manufacturer/Manufacturer.java
@@ -0,0 +1,113 @@
+package com.salesmanager.core.business.catalog.product.model.manufacturer;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+import com.salesmanager.core.business.common.model.audit.AuditListener;
+import com.salesmanager.core.business.common.model.audit.AuditSection;
+import com.salesmanager.core.business.common.model.audit.Auditable;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+
+@Entity
+@EntityListeners(value = AuditListener.class)
+@Table(name = "MANUFACTURER", schema="SALESMANAGER")
+public class Manufacturer extends SalesManagerEntity<Long, Manufacturer> implements Auditable {
+ private static final long serialVersionUID = 80693964563570099L;
+
+ @Id
+ @Column(name = "MANUFACTURER_ID", unique=true, nullable=false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "MANUFACT_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @Embedded
+ private AuditSection auditSection = new AuditSection();
+
+ @OneToMany(mappedBy = "manufacturer", cascade = CascadeType.ALL , fetch = FetchType.EAGER)
+ private Set<ManufacturerDescription> descriptions = new HashSet<ManufacturerDescription>();
+
+ @Column(name = "MANUFACTURER_IMAGE")
+ private String image;
+
+ @Column(name="SORT_ORDER")
+ private Integer order = new Integer(0);
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="MERCHANT_ID", nullable=false)
+ private MerchantStore merchantStore;
+
+ public Manufacturer() {
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ @Override
+ public AuditSection getAuditSection() {
+ return auditSection;
+ }
+
+ @Override
+ public void setAuditSection(AuditSection auditSection) {
+ this.auditSection = auditSection;
+ }
+
+ public String getImage() {
+ return image;
+ }
+
+ public void setImage(String image) {
+ this.image = image;
+ }
+
+ public Set<ManufacturerDescription> getDescriptions() {
+ return descriptions;
+ }
+
+ public void setDescriptions(Set<ManufacturerDescription> descriptions) {
+ this.descriptions = descriptions;
+ }
+
+
+
+ public MerchantStore getMerchantStore() {
+ return merchantStore;
+ }
+
+ public void setMerchantStore(MerchantStore merchantStore) {
+ this.merchantStore = merchantStore;
+ }
+
+ public void setOrder(Integer order) {
+ this.order = order;
+ }
+
+ public Integer getOrder() {
+ return order;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/manufacturer/ManufacturerDescription.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/manufacturer/ManufacturerDescription.java
new file mode 100644
index 0000000..8f82404
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/manufacturer/ManufacturerDescription.java
@@ -0,0 +1,72 @@
+package com.salesmanager.core.business.catalog.product.model.manufacturer;
+
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import com.salesmanager.core.business.common.model.Description;
+
+@Entity
+@Table(name = "MANUFACTURER_DESCRIPTION", schema="SALESMANAGER", uniqueConstraints={
+ @UniqueConstraint(columnNames={
+ "MANUFACTURER_ID",
+ "LANGUAGE_ID"
+ })
+ }
+)
+public class ManufacturerDescription extends Description {
+ private static final long serialVersionUID = -2164581613773995282L;
+
+ @ManyToOne(targetEntity = Manufacturer.class)
+ @JoinColumn(name = "MANUFACTURER_ID", nullable = false)
+ private Manufacturer manufacturer;
+
+ @Column(name = "MANUFACTURERS_URL")
+ private String url;
+
+ @Column(name = "URL_CLICKED")
+ private Integer urlClicked;
+
+ @Column(name = "DATE_LAST_CLICK")
+ private Date dateLastClick;
+
+ public ManufacturerDescription() {
+ }
+
+ public String getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+
+ public Integer getUrlClicked() {
+ return urlClicked;
+ }
+
+ public void setUrlClicked(Integer urlClicked) {
+ this.urlClicked = urlClicked;
+ }
+
+ public Date getDateLastClick() {
+ return dateLastClick;
+ }
+
+ public void setDateLastClick(Date dateLastClick) {
+ this.dateLastClick = dateLastClick;
+ }
+
+ public Manufacturer getManufacturer() {
+ return manufacturer;
+ }
+
+ public void setManufacturer(Manufacturer manufacturer) {
+ this.manufacturer = manufacturer;
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/price/FinalPrice.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/price/FinalPrice.java
new file mode 100755
index 0000000..4caf675
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/price/FinalPrice.java
@@ -0,0 +1,107 @@
+package com.salesmanager.core.business.catalog.product.model.price;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Transient entity used to display
+ * different price information in the catalogue
+ * @author Carl Samson
+ *
+ */
+public class FinalPrice implements Serializable {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+ private BigDecimal discountedPrice = null;//final price if a discount is applied
+ private BigDecimal originalPrice = null;//original price
+ private BigDecimal finalPrice = null;//final price discount or not
+ private boolean discounted = false;
+ private int discountPercent = 0;
+
+ private Date discountEndDate = null;
+
+ private boolean defaultPrice;
+ private ProductPrice productPrice;
+ List<FinalPrice> additionalPrices;
+
+ public List<FinalPrice> getAdditionalPrices() {
+ return additionalPrices;
+ }
+
+ public void setAdditionalPrices(List<FinalPrice> additionalPrices) {
+ this.additionalPrices = additionalPrices;
+ }
+
+ public BigDecimal getOriginalPrice() {
+ return originalPrice;
+ }
+
+ public void setOriginalPrice(BigDecimal originalPrice) {
+ this.originalPrice = originalPrice;
+ }
+
+
+
+ public int getDiscountPercent() {
+ return discountPercent;
+ }
+
+ public void setDiscountPercent(int discountPercent) {
+ this.discountPercent = discountPercent;
+ }
+
+ public Date getDiscountEndDate() {
+ return discountEndDate;
+ }
+
+ public void setDiscountEndDate(Date discountEndDate) {
+ this.discountEndDate = discountEndDate;
+ }
+
+ public boolean isDiscounted() {
+ return discounted;
+ }
+
+ public void setDiscounted(boolean discounted) {
+ this.discounted = discounted;
+ }
+
+ public void setDiscountedPrice(BigDecimal discountedPrice) {
+ this.discountedPrice = discountedPrice;
+ }
+
+ public BigDecimal getDiscountedPrice() {
+ return discountedPrice;
+ }
+
+
+ public void setFinalPrice(BigDecimal finalPrice) {
+ this.finalPrice = finalPrice;
+ }
+
+ public BigDecimal getFinalPrice() {
+ return finalPrice;
+ }
+
+ public void setDefaultPrice(boolean defaultPrice) {
+ this.defaultPrice = defaultPrice;
+ }
+
+ public boolean isDefaultPrice() {
+ return defaultPrice;
+ }
+
+ public void setProductPrice(ProductPrice productPrice) {
+ this.productPrice = productPrice;
+ }
+
+ public ProductPrice getProductPrice() {
+ return productPrice;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/price/ProductPrice.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/price/ProductPrice.java
new file mode 100644
index 0000000..78ee7fa
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/price/ProductPrice.java
@@ -0,0 +1,182 @@
+package com.salesmanager.core.business.catalog.product.model.price;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.validation.constraints.Pattern;
+
+import org.hibernate.validator.constraints.NotEmpty;
+
+import com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.constants.SchemaConstant;
+import com.salesmanager.core.utils.CloneUtils;
+
+@Entity
+@Table(name = "PRODUCT_PRICE", schema=SchemaConstant.SALESMANAGER_SCHEMA)
+public class ProductPrice extends SalesManagerEntity<Long, ProductPrice> {
+ private static final long serialVersionUID = -9186473817468772165L;
+
+ private final static String DEFAULT_PRICE_CODE="base";
+
+ @Id
+ @Column(name = "PRODUCT_PRICE_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "PRODUCT_PRICE_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @OneToMany(fetch = FetchType.LAZY, mappedBy = "productPrice", cascade = CascadeType.ALL)
+ private Set<ProductPriceDescription> descriptions = new HashSet<ProductPriceDescription>();
+
+ @NotEmpty
+ @Pattern(regexp="^[a-zA-Z0-9_]*$")
+ @Column(name = "PRODUCT_PRICE_CODE", nullable=false)
+ private String code = DEFAULT_PRICE_CODE;
+
+ @Column(name = "PRODUCT_PRICE_AMOUNT", nullable=false)
+ private BigDecimal productPriceAmount = new BigDecimal(0);
+
+ @Column(name = "PRODUCT_PRICE_TYPE", length=20)
+ @Enumerated(value = EnumType.STRING)
+ private ProductPriceType productPriceType = ProductPriceType.ONE_TIME;
+
+ @Column(name = "DEFAULT_PRICE")
+ private boolean defaultPrice = false;
+
+ @Temporal(TemporalType.DATE)
+ @Column(name = "PRODUCT_PRICE_SPECIAL_ST_DATE")
+ private Date productPriceSpecialStartDate;
+
+ @Temporal(TemporalType.DATE)
+ @Column(name = "PRODUCT_PRICE_SPECIAL_END_DATE")
+ private Date productPriceSpecialEndDate;
+
+ @Column(name = "PRODUCT_PRICE_SPECIAL_AMOUNT")
+ private BigDecimal productPriceSpecialAmount;
+
+
+ @ManyToOne(targetEntity = ProductAvailability.class)
+ @JoinColumn(name = "PRODUCT_AVAIL_ID", nullable = false)
+ private ProductAvailability productAvailability;
+
+
+ public ProductPrice() {
+ }
+
+ @Override
+ public Long getId() {
+ return this.id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+
+
+
+ public BigDecimal getProductPriceAmount() {
+ return productPriceAmount;
+ }
+
+ public void setProductPriceAmount(BigDecimal productPriceAmount) {
+ this.productPriceAmount = productPriceAmount;
+ }
+
+
+
+ public Date getProductPriceSpecialStartDate() {
+ return CloneUtils.clone(productPriceSpecialStartDate);
+ }
+
+ public void setProductPriceSpecialStartDate(
+ Date productPriceSpecialStartDate) {
+ this.productPriceSpecialStartDate = CloneUtils.clone(productPriceSpecialStartDate);
+ }
+
+ public Date getProductPriceSpecialEndDate() {
+ return CloneUtils.clone(productPriceSpecialEndDate);
+ }
+
+ public void setProductPriceSpecialEndDate(Date productPriceSpecialEndDate) {
+ this.productPriceSpecialEndDate = CloneUtils.clone(productPriceSpecialEndDate);
+ }
+
+
+
+ public BigDecimal getProductPriceSpecialAmount() {
+ return productPriceSpecialAmount;
+ }
+
+ public void setProductPriceSpecialAmount(
+ BigDecimal productPriceSpecialAmount) {
+ this.productPriceSpecialAmount = productPriceSpecialAmount;
+ }
+
+
+
+ public Set<ProductPriceDescription> getDescriptions() {
+ return descriptions;
+ }
+
+
+
+ public void setDescriptions(Set<ProductPriceDescription> descriptions) {
+ this.descriptions = descriptions;
+ }
+
+
+
+ public boolean isDefaultPrice() {
+ return defaultPrice;
+ }
+
+ public void setDefaultPrice(boolean defaultPrice) {
+ this.defaultPrice = defaultPrice;
+ }
+
+ public void setProductAvailability(ProductAvailability productAvailability) {
+ this.productAvailability = productAvailability;
+ }
+
+ public ProductAvailability getProductAvailability() {
+ return productAvailability;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setProductPriceType(ProductPriceType productPriceType) {
+ this.productPriceType = productPriceType;
+ }
+
+ public ProductPriceType getProductPriceType() {
+ return productPriceType;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/price/ProductPriceDescription.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/price/ProductPriceDescription.java
new file mode 100644
index 0000000..65f94a8
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/price/ProductPriceDescription.java
@@ -0,0 +1,41 @@
+package com.salesmanager.core.business.catalog.product.model.price;
+
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import com.salesmanager.core.business.common.model.Description;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@Table(name="PRODUCT_PRICE_DESCRIPTION", schema=SchemaConstant.SALESMANAGER_SCHEMA, uniqueConstraints={
+ @UniqueConstraint(columnNames={
+ "PRODUCT_PRICE_ID",
+ "LANGUAGE_ID"
+ })
+ }
+)
+public class ProductPriceDescription extends Description {
+ private static final long serialVersionUID = 270521409645392808L;
+
+ public final static String DEFAULT_PRICE_DESCRIPTION = "DEFAULT";
+
+ @ManyToOne(targetEntity = ProductPrice.class)
+ @JoinColumn(name = "PRODUCT_PRICE_ID", nullable = false)
+ private ProductPrice productPrice;
+
+ public ProductPriceDescription() {
+ }
+
+ public ProductPrice getProductPrice() {
+ return productPrice;
+ }
+
+ public void setProductPrice(ProductPrice productPrice) {
+ this.productPrice = productPrice;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/price/ProductPriceType.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/price/ProductPriceType.java
new file mode 100644
index 0000000..46115c3
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/price/ProductPriceType.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.catalog.product.model.price;
+
+public enum ProductPriceType {
+
+ ONE_TIME, MONTHLY
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/Product.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/Product.java
new file mode 100755
index 0000000..57b7376
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/Product.java
@@ -0,0 +1,418 @@
+package com.salesmanager.core.business.catalog.product.model;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.validation.constraints.Pattern;
+
+import org.hibernate.annotations.Cascade;
+import org.hibernate.validator.constraints.NotEmpty;
+
+import com.salesmanager.core.business.catalog.category.model.Category;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute;
+import com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability;
+import com.salesmanager.core.business.catalog.product.model.description.ProductDescription;
+import com.salesmanager.core.business.catalog.product.model.image.ProductImage;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.Manufacturer;
+import com.salesmanager.core.business.catalog.product.model.relationship.ProductRelationship;
+import com.salesmanager.core.business.catalog.product.model.type.ProductType;
+import com.salesmanager.core.business.common.model.audit.AuditListener;
+import com.salesmanager.core.business.common.model.audit.AuditSection;
+import com.salesmanager.core.business.common.model.audit.Auditable;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.tax.model.taxclass.TaxClass;
+import com.salesmanager.core.constants.SchemaConstant;
+
+
+@Entity
+@EntityListeners(value = AuditListener.class)
+@Table(name = "PRODUCT", schema=SchemaConstant.SALESMANAGER_SCHEMA)
+public class Product extends SalesManagerEntity<Long, Product> implements Auditable {
+ private static final long serialVersionUID = -6228066416290007047L;
+
+ @Id
+ @Column(name = "PRODUCT_ID", unique=true, nullable=false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "PRODUCT_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @Embedded
+ private AuditSection auditSection = new AuditSection();
+
+ @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "product")
+ private Set<ProductDescription> descriptions = new HashSet<ProductDescription>();
+
+ @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE, mappedBy="product", orphanRemoval = true)
+ private Set<ProductAvailability> availabilities = new HashSet<ProductAvailability>();
+
+ @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE, mappedBy = "product")
+ private Set<ProductAttribute> attributes = new HashSet<ProductAttribute>();
+
+ @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE, mappedBy = "product")
+ private Set<ProductImage> images = new HashSet<ProductImage>();
+
+ @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE, mappedBy = "product")
+ private Set<ProductRelationship> relationships = new HashSet<ProductRelationship>();
+
+
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="MERCHANT_ID", nullable=false)
+ private MerchantStore merchantStore;
+
+ @ManyToMany(fetch=FetchType.LAZY, cascade = {CascadeType.REFRESH})
+ @JoinTable(name = "PRODUCT_CATEGORY", schema=SchemaConstant.SALESMANAGER_SCHEMA, joinColumns = {
+ @JoinColumn(name = "PRODUCT_ID", nullable = false, updatable = false) }
+ ,
+ inverseJoinColumns = { @JoinColumn(name = "CATEGORY_ID",
+ nullable = false, updatable = false) }
+ )
+ @Cascade({
+ org.hibernate.annotations.CascadeType.DETACH,
+ org.hibernate.annotations.CascadeType.LOCK,
+ org.hibernate.annotations.CascadeType.REFRESH,
+ org.hibernate.annotations.CascadeType.REPLICATE
+
+ })
+ private Set<Category> categories = new HashSet<Category>();
+
+ @Column(name="DATE_AVAILABLE")
+ @Temporal(TemporalType.TIMESTAMP)
+ private Date dateAvailable = new Date();
+
+
+ @Column(name="AVAILABLE")
+ private boolean available = true;
+
+
+ @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.REFRESH})
+ @JoinColumn(name="MANUFACTURER_ID", nullable=true)
+ private Manufacturer manufacturer;
+
+ @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.REFRESH})
+ @JoinColumn(name="PRODUCT_TYPE_ID", nullable=true)
+ private ProductType type;
+
+ @ManyToOne(fetch = FetchType.LAZY, cascade = {CascadeType.REFRESH})
+ @JoinColumn(name="TAX_CLASS_ID", nullable=true)
+ private TaxClass taxClass;
+
+ @Column(name = "PRODUCT_VIRTUAL")
+ private boolean productVirtual = false;
+
+ @Column(name = "PRODUCT_SHIP")
+ private boolean productShipeable = false;
+
+
+ @Column(name = "PRODUCT_FREE")
+ private boolean productIsFree;
+
+ @Column(name = "PRODUCT_LENGTH")
+ private BigDecimal productLength;
+
+ @Column(name = "PRODUCT_WIDTH")
+ private BigDecimal productWidth;
+
+ @Column(name = "PRODUCT_HEIGHT")
+ private BigDecimal productHeight;
+
+ @Column(name = "PRODUCT_WEIGHT")
+ private BigDecimal productWeight;
+
+ @Column(name = "REVIEW_AVG")
+ private BigDecimal productReviewAvg;
+
+ @Column(name = "REVIEW_COUNT")
+ private Integer productReviewCount;
+
+ @Column(name = "QUANTITY_ORDERED")
+ private Integer productOrdered;
+
+ @Column(name = "SORT_ORDER")
+ private Integer sortOrder = new Integer(0);
+
+ @NotEmpty
+ @Pattern(regexp="^[a-zA-Z0-9_]*$")
+ @Column(name = "SKU")
+ private String sku;
+
+ public Product() {
+ }
+
+ @Override
+ public Long getId() {
+ return this.id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ @Override
+ public AuditSection getAuditSection() {
+ return auditSection;
+ }
+
+ @Override
+ public void setAuditSection(AuditSection auditSection) {
+ this.auditSection = auditSection;
+ }
+
+
+ public boolean isProductVirtual() {
+ return productVirtual;
+ }
+
+
+
+ public BigDecimal getProductLength() {
+ return productLength;
+ }
+
+ public void setProductLength(BigDecimal productLength) {
+ this.productLength = productLength;
+ }
+
+ public BigDecimal getProductWidth() {
+ return productWidth;
+ }
+
+ public void setProductWidth(BigDecimal productWidth) {
+ this.productWidth = productWidth;
+ }
+
+ public BigDecimal getProductHeight() {
+ return productHeight;
+ }
+
+ public void setProductHeight(BigDecimal productHeight) {
+ this.productHeight = productHeight;
+ }
+
+ public BigDecimal getProductWeight() {
+ return productWeight;
+ }
+
+ public void setProductWeight(BigDecimal productWeight) {
+ this.productWeight = productWeight;
+ }
+
+ public BigDecimal getProductReviewAvg() {
+ return productReviewAvg;
+ }
+
+ public void setProductReviewAvg(BigDecimal productReviewAvg) {
+ this.productReviewAvg = productReviewAvg;
+ }
+
+ public Integer getProductReviewCount() {
+ return productReviewCount;
+ }
+
+ public void setProductReviewCount(Integer productReviewCount) {
+ this.productReviewCount = productReviewCount;
+ }
+
+
+
+ public Integer getProductOrdered() {
+ return productOrdered;
+ }
+
+ public void setProductOrdered(Integer productOrdered) {
+ this.productOrdered = productOrdered;
+ }
+
+ public String getSku() {
+ return sku;
+ }
+
+ public void setSku(String sku) {
+ this.sku = sku;
+ }
+
+ public Set<ProductDescription> getDescriptions() {
+ return descriptions;
+ }
+
+ public void setDescriptions(Set<ProductDescription> descriptions) {
+ this.descriptions = descriptions;
+ }
+
+
+ public boolean getProductVirtual() {
+ return productVirtual;
+ }
+
+ public void setProductVirtual(boolean productVirtual) {
+ this.productVirtual = productVirtual;
+ }
+
+ public boolean getProductIsFree() {
+ return productIsFree;
+ }
+
+ public void setProductIsFree(boolean productIsFree) {
+ this.productIsFree = productIsFree;
+ }
+
+
+
+ public Set<ProductAttribute> getAttributes() {
+ return attributes;
+ }
+
+ public void setAttributes(Set<ProductAttribute> attributes) {
+ this.attributes = attributes;
+ }
+
+
+
+ public Manufacturer getManufacturer() {
+ return manufacturer;
+ }
+
+ public void setManufacturer(Manufacturer manufacturer) {
+ this.manufacturer = manufacturer;
+ }
+
+ public ProductType getType() {
+ return type;
+ }
+
+ public void setType(ProductType type) {
+ this.type = type;
+ }
+
+
+
+ public Set<ProductAvailability> getAvailabilities() {
+ return availabilities;
+ }
+
+ public void setAvailabilities(Set<ProductAvailability> availabilities) {
+ this.availabilities = availabilities;
+ }
+
+ public TaxClass getTaxClass() {
+ return taxClass;
+ }
+
+ public void setTaxClass(TaxClass taxClass) {
+ this.taxClass = taxClass;
+ }
+
+ public Set<ProductImage> getImages() {
+ return images;
+ }
+
+ public void setImages(Set<ProductImage> images) {
+ this.images = images;
+ }
+
+ public Set<ProductRelationship> getRelationships() {
+ return relationships;
+ }
+
+ public void setRelationships(Set<ProductRelationship> relationships) {
+ this.relationships = relationships;
+ }
+
+
+ public Set<Category> getCategories() {
+ return categories;
+ }
+
+ public void setCategories(Set<Category> categories) {
+ this.categories = categories;
+ }
+
+ public MerchantStore getMerchantStore() {
+ return merchantStore;
+ }
+
+ public void setMerchantStore(MerchantStore merchantStore) {
+ this.merchantStore = merchantStore;
+ }
+
+
+
+ public Date getDateAvailable() {
+ return dateAvailable;
+ }
+
+ public void setDateAvailable(Date dateAvailable) {
+ this.dateAvailable = dateAvailable;
+ }
+
+ public void setSortOrder(Integer sortOrder) {
+ this.sortOrder = sortOrder;
+ }
+
+ public Integer getSortOrder() {
+ return sortOrder;
+ }
+
+
+
+ public void setAvailable(boolean available) {
+ this.available = available;
+ }
+
+ public boolean isAvailable() {
+ return available;
+ }
+
+ public boolean isProductShipeable() {
+ return productShipeable;
+ }
+
+ public void setProductShipeable(boolean productShipeable) {
+ this.productShipeable = productShipeable;
+ }
+
+
+ public ProductDescription getProductDescription() {
+ if(this.getDescriptions()!=null && this.getDescriptions().size()>0) {
+ return this.getDescriptions().iterator().next();
+ }
+ return null;
+ }
+
+ public ProductImage getProductImage() {
+ ProductImage productImage = null;
+ if(this.getImages()!=null && this.getImages().size()>0) {
+ for(ProductImage image : this.getImages()) {
+ productImage = image;
+ if(productImage.isDefaultImage()) {
+ break;
+ }
+ }
+ }
+ return productImage;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/ProductCriteria.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/ProductCriteria.java
new file mode 100644
index 0000000..40b5ceb
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/ProductCriteria.java
@@ -0,0 +1,82 @@
+package com.salesmanager.core.business.catalog.product.model;
+
+import java.util.List;
+
+import com.salesmanager.core.business.catalog.product.model.attribute.AttributeCriteria;
+import com.salesmanager.core.business.common.model.Criteria;
+
+public class ProductCriteria extends Criteria {
+
+
+ private String productName;
+ private List<AttributeCriteria> attributeCriteria;
+
+
+ private Boolean available = null;
+
+ private List<Long> categoryIds;
+ private List<String> availabilities;
+ private List<Long> productIds;
+
+ private Long manufacturerId = null;
+
+ public String getProductName() {
+ return productName;
+ }
+
+ public void setProductName(String productName) {
+ this.productName = productName;
+ }
+
+
+ public List<Long> getCategoryIds() {
+ return categoryIds;
+ }
+
+ public void setCategoryIds(List<Long> categoryIds) {
+ this.categoryIds = categoryIds;
+ }
+
+ public List<String> getAvailabilities() {
+ return availabilities;
+ }
+
+ public void setAvailabilities(List<String> availabilities) {
+ this.availabilities = availabilities;
+ }
+
+ public Boolean getAvailable() {
+ return available;
+ }
+
+ public void setAvailable(Boolean available) {
+ this.available = available;
+ }
+
+ public void setAttributeCriteria(List<AttributeCriteria> attributeCriteria) {
+ this.attributeCriteria = attributeCriteria;
+ }
+
+ public List<AttributeCriteria> getAttributeCriteria() {
+ return attributeCriteria;
+ }
+
+ public void setProductIds(List<Long> productIds) {
+ this.productIds = productIds;
+ }
+
+ public List<Long> getProductIds() {
+ return productIds;
+ }
+
+ public void setManufacturerId(Long manufacturerId) {
+ this.manufacturerId = manufacturerId;
+ }
+
+ public Long getManufacturerId() {
+ return manufacturerId;
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/ProductList.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/ProductList.java
new file mode 100644
index 0000000..5c6754c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/ProductList.java
@@ -0,0 +1,25 @@
+package com.salesmanager.core.business.catalog.product.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import com.salesmanager.core.business.common.model.EntityList;
+
+public class ProductList extends EntityList {
+
+
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 7267292601646149482L;
+ private List<Product> products = new ArrayList<Product>();
+ public List<Product> getProducts() {
+ return products;
+ }
+ public void setProducts(List<Product> products) {
+ this.products = products;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/relationship/ProductRelationship.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/relationship/ProductRelationship.java
new file mode 100644
index 0000000..f91fd0d
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/relationship/ProductRelationship.java
@@ -0,0 +1,121 @@
+package com.salesmanager.core.business.catalog.product.model.relationship;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@Table(name = "PRODUCT_RELATIONSHIP", schema=SchemaConstant.SALESMANAGER_SCHEMA)
+public class ProductRelationship extends SalesManagerEntity<Long, ProductRelationship> implements Serializable {
+ private static final long serialVersionUID = -9045331138054246299L;
+
+ @Id
+ @Column(name = "PRODUCT_RELATIONSHIP_ID", unique=true, nullable=false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "PRODUCT_RELATION_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @ManyToOne(targetEntity = MerchantStore.class)
+ @JoinColumn(name="MERCHANT_ID",nullable=false)
+ private MerchantStore store;
+
+ @ManyToOne(targetEntity = Product.class)
+ @JoinColumn(name="PRODUCT_ID",updatable=false,nullable=true)
+ private Product product = null;
+
+ @ManyToOne(targetEntity = Product.class)
+ @JoinColumn(name="RELATED_PRODUCT_ID",updatable=false,nullable=true)
+ private Product relatedProduct = null;
+
+ @Column(name="CODE")
+ private String code;
+
+ @Column(name="ACTIVE")
+ private boolean active = true;
+
+ public Product getProduct() {
+ return product;
+ }
+
+
+
+ public void setProduct(Product product) {
+ this.product = product;
+ }
+
+
+
+ public Product getRelatedProduct() {
+ return relatedProduct;
+ }
+
+
+
+ public void setRelatedProduct(Product relatedProduct) {
+ this.relatedProduct = relatedProduct;
+ }
+
+
+
+ public String getCode() {
+ return code;
+ }
+
+
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+
+
+ public boolean isActive() {
+ return active;
+ }
+
+
+
+ public void setActive(boolean active) {
+ this.active = active;
+ }
+
+
+
+ public ProductRelationship() {
+ }
+
+
+
+ public MerchantStore getStore() {
+ return store;
+ }
+
+ public void setStore(MerchantStore store) {
+ this.store = store;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/relationship/ProductRelationshipType.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/relationship/ProductRelationshipType.java
new file mode 100755
index 0000000..60937e5
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/relationship/ProductRelationshipType.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.catalog.product.model.relationship;
+
+public enum ProductRelationshipType {
+
+ FEATURED_ITEM, RELATED_ITEM, BUNDLED_ITEM
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/review/ProductReview.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/review/ProductReview.java
new file mode 100644
index 0000000..1601785
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/review/ProductReview.java
@@ -0,0 +1,150 @@
+package com.salesmanager.core.business.catalog.product.model.review;
+
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.common.model.audit.AuditListener;
+import com.salesmanager.core.business.common.model.audit.AuditSection;
+import com.salesmanager.core.business.common.model.audit.Auditable;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@EntityListeners(value = AuditListener.class)
+@Table(name = "PRODUCT_REVIEW", schema=SchemaConstant.SALESMANAGER_SCHEMA)
+public class ProductReview extends SalesManagerEntity<Long, ProductReview> implements Auditable {
+ private static final long serialVersionUID = -7509351278087554383L;
+
+ @Id
+ @Column(name = "PRODUCT_REVIEW_ID", unique=true, nullable=false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT",
+ pkColumnValue = "PRODUCT_REVIEW_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @Embedded
+ private AuditSection audit = new AuditSection();
+
+ @Column(name = "REVIEWS_RATING")
+ private Double reviewRating;
+
+ @Column(name = "REVIEWS_READ")
+ private Long reviewRead;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column(name = "REVIEW_DATE")
+ private Date reviewDate;
+
+ @Column(name = "STATUS")
+ private Integer status;
+
+ @ManyToOne
+ @JoinColumn(name="CUSTOMERS_ID")
+ private Customer customer;
+
+ @OneToOne
+ @JoinColumn(name="PRODUCT_ID")
+ private Product product;
+
+ @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "productReview")
+ private Set<ProductReviewDescription> descriptions = new HashSet<ProductReviewDescription>();
+
+ public ProductReview() {
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Double getReviewRating() {
+ return reviewRating;
+ }
+
+ public void setReviewRating(Double reviewRating) {
+ this.reviewRating = reviewRating;
+ }
+
+ public Long getReviewRead() {
+ return reviewRead;
+ }
+
+ public void setReviewRead(Long reviewRead) {
+ this.reviewRead = reviewRead;
+ }
+
+ public Integer getStatus() {
+ return status;
+ }
+
+ public void setStatus(Integer status) {
+ this.status = status;
+ }
+
+ public Customer getCustomer() {
+ return customer;
+ }
+
+ public void setCustomer(Customer customer) {
+ this.customer = customer;
+ }
+
+ public Product getProduct() {
+ return product;
+ }
+
+ public void setProduct(Product product) {
+ this.product = product;
+ }
+
+ public Set<ProductReviewDescription> getDescriptions() {
+ return descriptions;
+ }
+
+ public void setDescriptions(Set<ProductReviewDescription> descriptions) {
+ this.descriptions = descriptions;
+ }
+
+ @Override
+ public AuditSection getAuditSection() {
+ return audit;
+ }
+
+ @Override
+ public void setAuditSection(AuditSection audit) {
+ this.audit = audit;
+ }
+
+ public Date getReviewDate() {
+ return reviewDate;
+ }
+
+ public void setReviewDate(Date reviewDate) {
+ this.reviewDate = reviewDate;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/review/ProductReviewDescription.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/review/ProductReviewDescription.java
new file mode 100644
index 0000000..4ba872b
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/review/ProductReviewDescription.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to csti consulting
+ * You may obtain a copy of the License at
+ *
+ * http://www.csticonsulting.com
+ * Copyright (c) 2006-Aug 24, 2010 Consultation CS-TI inc.
+ *
+ * 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.
+ */
+package com.salesmanager.core.business.catalog.product.model.review;
+
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import com.salesmanager.core.business.common.model.Description;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@Table(name = "PRODUCT_REVIEW_DESCRIPTION", schema = SchemaConstant.SALESMANAGER_SCHEMA, uniqueConstraints={
+ @UniqueConstraint(columnNames={
+ "PRODUCT_REVIEW_ID",
+ "LANGUAGE_ID"
+ })
+})
+public class ProductReviewDescription extends Description {
+ private static final long serialVersionUID = -1957502640742695406L;
+
+ @ManyToOne(targetEntity = ProductReview.class)
+ @JoinColumn(name="PRODUCT_REVIEW_ID")
+ private ProductReview productReview;
+
+ public ProductReviewDescription() {
+ }
+
+ public ProductReviewDescription(Language language, String name) {
+ this.setLanguage(language);
+ this.setName(name);
+ }
+
+ public ProductReview getProductReview() {
+ return productReview;
+ }
+
+ public void setProductReview(ProductReview productReview) {
+ this.productReview = productReview;
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/type/ProductType.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/type/ProductType.java
new file mode 100644
index 0000000..018b824
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/model/type/ProductType.java
@@ -0,0 +1,84 @@
+package com.salesmanager.core.business.catalog.product.model.type;
+
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+
+import com.salesmanager.core.business.common.model.audit.AuditListener;
+import com.salesmanager.core.business.common.model.audit.AuditSection;
+import com.salesmanager.core.business.common.model.audit.Auditable;
+
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@EntityListeners(value = AuditListener.class)
+@Table(name = "PRODUCT_TYPE", schema=SchemaConstant.SALESMANAGER_SCHEMA)
+public class ProductType extends SalesManagerEntity<Long, ProductType> implements Auditable {
+ private static final long serialVersionUID = 65541494628227593L;
+
+ public final static String GENERAL_TYPE = "GENERAL";
+
+ @Id
+ @Column(name = "PRODUCT_TYPE_ID", unique=true, nullable=false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "PRD_TYPE_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @Embedded
+ private AuditSection auditSection = new AuditSection();
+
+ @Column(name = "PRD_TYPE_CODE")
+ private String code;
+
+ @Column(name = "PRD_TYPE_ADD_TO_CART")
+ private Boolean allowAddToCart;
+
+ public ProductType() {
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ @Override
+ public AuditSection getAuditSection() {
+ return auditSection;
+ }
+
+ @Override
+ public void setAuditSection(AuditSection auditSection) {
+ this.auditSection = auditSection;
+ }
+
+ public boolean isAllowAddToCart() {
+ return allowAddToCart;
+ }
+
+ public void setAllowAddToCart(boolean allowAddToCart) {
+ this.allowAddToCart = allowAddToCart;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductAttributeService.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductAttributeService.java
new file mode 100644
index 0000000..4e492d6
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductAttributeService.java
@@ -0,0 +1,29 @@
+package com.salesmanager.core.business.catalog.product.service.attribute;
+
+import java.util.List;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface ProductAttributeService extends
+ SalesManagerEntityService<Long, ProductAttribute> {
+
+ void saveOrUpdate(ProductAttribute productAttribute)
+ throws ServiceException;
+
+ List<ProductAttribute> getByOptionId(MerchantStore store,
+ Long id) throws ServiceException;
+
+ List<ProductAttribute> getByOptionValueId(MerchantStore store,
+ Long id) throws ServiceException;
+
+ List<ProductAttribute> getByProductId(MerchantStore store, Product product, Language language)
+ throws ServiceException;
+
+ List<ProductAttribute> getByAttributeIds(MerchantStore store, List<Long> ids)
+ throws ServiceException;
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductAttributeServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductAttributeServiceImpl.java
new file mode 100644
index 0000000..ebf245e
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductAttributeServiceImpl.java
@@ -0,0 +1,92 @@
+package com.salesmanager.core.business.catalog.product.service.attribute;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.catalog.product.dao.attribute.ProductAttributeDao;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPrice;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Service("productAttributeService")
+public class ProductAttributeServiceImpl extends
+ SalesManagerEntityServiceImpl<Long, ProductAttribute> implements ProductAttributeService {
+
+ private ProductAttributeDao productAttributeDao;
+
+ @Autowired
+ public ProductAttributeServiceImpl(ProductAttributeDao productAttributeDao) {
+ super(productAttributeDao);
+ this.productAttributeDao = productAttributeDao;
+ }
+
+ @Override
+ public ProductAttribute getById(Long id) {
+
+ return productAttributeDao.getById(id);
+
+ }
+
+
+ @Override
+ public List<ProductAttribute> getByOptionId(MerchantStore store,
+ Long id) throws ServiceException {
+
+ return productAttributeDao.getByOptionId(store, id);
+
+ }
+
+ @Override
+ public List<ProductAttribute> getByAttributeIds(MerchantStore store,
+ List<Long> ids) throws ServiceException {
+
+ return productAttributeDao.getByAttributeIds(store, ids);
+
+ }
+
+ @Override
+ public List<ProductAttribute> getByOptionValueId(MerchantStore store,
+ Long id) throws ServiceException {
+
+ return productAttributeDao.getByOptionValueId(store, id);
+
+ }
+
+ /**
+ * Returns all product attributes
+ */
+ @Override
+ public List<ProductAttribute> getByProductId(MerchantStore store,
+ Product product, Language language) throws ServiceException {
+ return productAttributeDao.getByProduct(store, product, language);
+
+ }
+
+
+ @Override
+ public void saveOrUpdate(ProductAttribute productAttribute)
+ throws ServiceException {
+ if(productAttribute.getId()!=null && productAttribute.getId()>0) {
+ productAttributeDao.update(productAttribute);
+ } else {
+ productAttributeDao.save(productAttribute);
+ }
+
+ }
+
+ @Override
+ public void delete(ProductAttribute attribute) throws ServiceException {
+
+ //override method, this allows the error that we try to remove a detached instance
+ attribute = this.getById(attribute.getId());
+ super.delete(attribute);
+
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductOptionService.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductOptionService.java
new file mode 100644
index 0000000..a0f709c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductOptionService.java
@@ -0,0 +1,32 @@
+package com.salesmanager.core.business.catalog.product.service.attribute;
+
+import java.util.List;
+
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOption;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface ProductOptionService extends SalesManagerEntityService<Long, ProductOption> {
+
+ List<ProductOption> listByStore(MerchantStore store, Language language)
+ throws ServiceException;
+
+
+ List<ProductOption> getByName(MerchantStore store, String name,
+ Language language) throws ServiceException;
+
+ void saveOrUpdate(ProductOption entity) throws ServiceException;
+
+
+ List<ProductOption> listReadOnly(MerchantStore store, Language language)
+ throws ServiceException;
+
+
+ ProductOption getByCode(MerchantStore store, String optionCode);
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductOptionServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductOptionServiceImpl.java
new file mode 100644
index 0000000..4fe12d7
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductOptionServiceImpl.java
@@ -0,0 +1,105 @@
+package com.salesmanager.core.business.catalog.product.service.attribute;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.catalog.product.dao.attribute.ProductOptionDao;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOption;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Service("productOptionService")
+public class ProductOptionServiceImpl extends
+ SalesManagerEntityServiceImpl<Long, ProductOption> implements ProductOptionService {
+
+
+ private ProductOptionDao productOptionDao;
+
+ @Autowired
+ private ProductAttributeService productAttributeService;
+
+ @Autowired
+ public ProductOptionServiceImpl(
+ ProductOptionDao productOptionDao) {
+ super(productOptionDao);
+ this.productOptionDao = productOptionDao;
+ }
+
+ @Override
+ public List<ProductOption> listByStore(MerchantStore store, Language language) throws ServiceException {
+
+
+ return productOptionDao.listByStore(store, language);
+
+
+ }
+
+ @Override
+ public List<ProductOption> listReadOnly(MerchantStore store, Language language) throws ServiceException {
+
+ return productOptionDao.getReadOnly(store, language);
+
+
+ }
+
+
+
+ @Override
+ public List<ProductOption> getByName(MerchantStore store, String name, Language language) throws ServiceException {
+
+ try {
+ return productOptionDao.getByName(store, name, language);
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+
+ }
+
+ @Override
+ public void saveOrUpdate(ProductOption entity) throws ServiceException {
+
+
+ //save or update (persist and attach entities
+ if(entity.getId()!=null && entity.getId()>0) {
+ super.update(entity);
+ } else {
+ super.save(entity);
+ }
+
+ }
+
+ @Override
+ public void delete(ProductOption entity) throws ServiceException {
+
+ //remove all attributes having this option
+ List<ProductAttribute> attributes = productAttributeService.getByOptionId(entity.getMerchantStore(), entity.getId());
+
+ for(ProductAttribute attribute : attributes) {
+ productAttributeService.delete(attribute);
+ }
+
+ ProductOption option = this.getById(entity.getId());
+
+ //remove option
+ super.delete(option);
+
+ }
+
+ @Override
+ public ProductOption getByCode(MerchantStore store, String optionCode) {
+ return productOptionDao.getByCode(store, optionCode);
+ }
+
+
+
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductOptionValueService.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductOptionValueService.java
new file mode 100644
index 0000000..4a2854d
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductOptionValueService.java
@@ -0,0 +1,29 @@
+package com.salesmanager.core.business.catalog.product.service.attribute;
+
+import java.util.List;
+
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionValue;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface ProductOptionValueService extends SalesManagerEntityService<Long, ProductOptionValue> {
+
+ void saveOrUpdate(ProductOptionValue entity) throws ServiceException;
+
+ List<ProductOptionValue> getByName(MerchantStore store, String name,
+ Language language) throws ServiceException;
+
+ ProductOptionValue getById(MerchantStore store, Long id)
+ throws ServiceException;
+
+ List<ProductOptionValue> listByStore(MerchantStore store, Language language)
+ throws ServiceException;
+
+ List<ProductOptionValue> listByStoreNoReadOnly(MerchantStore store,
+ Language language) throws ServiceException;
+
+ ProductOptionValue getByCode(MerchantStore store, String optionValueCode);
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductOptionValueServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductOptionValueServiceImpl.java
new file mode 100644
index 0000000..1830556
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/attribute/ProductOptionValueServiceImpl.java
@@ -0,0 +1,110 @@
+package com.salesmanager.core.business.catalog.product.service.attribute;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.catalog.product.dao.attribute.ProductOptionValueDao;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionValue;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Service("productOptionValueService")
+public class ProductOptionValueServiceImpl extends
+ SalesManagerEntityServiceImpl<Long, ProductOptionValue> implements
+ ProductOptionValueService {
+
+ @Autowired
+ private ProductAttributeService productAttributeService;
+
+ private ProductOptionValueDao productOptionValueDao;
+
+ @Autowired
+ public ProductOptionValueServiceImpl(
+ ProductOptionValueDao productOptionValueDao) {
+ super(productOptionValueDao);
+ this.productOptionValueDao = productOptionValueDao;
+ }
+
+
+ @Override
+ public List<ProductOptionValue> listByStore(MerchantStore store, Language language) throws ServiceException {
+
+ return productOptionValueDao.listByStore(store, language);
+ }
+
+ @Override
+ public List<ProductOptionValue> listByStoreNoReadOnly(MerchantStore store, Language language) throws ServiceException {
+
+ return productOptionValueDao.listByStoreNoReadOnly(store, language);
+ }
+
+ @Override
+ public ProductOptionValue getById(MerchantStore store, Long id) throws ServiceException {
+
+ try {
+ return productOptionValueDao.getById(store, id);
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+ }
+
+ @Override
+ public List<ProductOptionValue> getByName(MerchantStore store, String name, Language language) throws ServiceException {
+
+ try {
+ return productOptionValueDao.getByName(store, name, language);
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+
+ }
+
+ @Override
+ public void saveOrUpdate(ProductOptionValue entity) throws ServiceException {
+
+
+ //save or update (persist and attach entities
+ if(entity.getId()!=null && entity.getId()>0) {
+
+ super.update(entity);
+
+ } else {
+
+ super.save(entity);
+
+ }
+
+ }
+
+
+ public void delete(ProductOptionValue entity) throws ServiceException {
+
+ //remove all attributes having this option
+ List<ProductAttribute> attributes = productAttributeService.getByOptionValueId(entity.getMerchantStore(), entity.getId());
+
+ for(ProductAttribute attribute : attributes) {
+ productAttributeService.delete(attribute);
+ }
+
+ ProductOptionValue option = this.getById(entity.getMerchantStore(), entity.getId());
+
+ //remove option
+ super.delete(option);
+
+ }
+
+ @Override
+ public ProductOptionValue getByCode(MerchantStore store, String optionValueCode) {
+ return productOptionValueDao.getByCode(store, optionValueCode);
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/availability/ProductAvailabilityService.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/availability/ProductAvailabilityService.java
new file mode 100644
index 0000000..cf9dbeb
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/availability/ProductAvailabilityService.java
@@ -0,0 +1,12 @@
+package com.salesmanager.core.business.catalog.product.service.availability;
+
+import com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+
+public interface ProductAvailabilityService extends
+ SalesManagerEntityService<Long, ProductAvailability> {
+
+ void saveOrUpdate(ProductAvailability availability) throws ServiceException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/availability/ProductAvailabilityServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/availability/ProductAvailabilityServiceImpl.java
new file mode 100644
index 0000000..7d693fd
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/availability/ProductAvailabilityServiceImpl.java
@@ -0,0 +1,42 @@
+package com.salesmanager.core.business.catalog.product.service.availability;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.catalog.product.dao.availability.ProductAvailabilityDao;
+import com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+
+@Service("productAvailabilityService")
+public class ProductAvailabilityServiceImpl extends
+ SalesManagerEntityServiceImpl<Long, ProductAvailability> implements
+ ProductAvailabilityService {
+
+
+ private ProductAvailabilityDao productAvailabilityDao;
+
+ @Autowired
+ public ProductAvailabilityServiceImpl(
+ ProductAvailabilityDao productAvailabilityDao) {
+ super(productAvailabilityDao);
+ this.productAvailabilityDao = productAvailabilityDao;
+ }
+
+
+ @Override
+ public void saveOrUpdate(ProductAvailability availability) throws ServiceException {
+
+ if(availability.getId()!=null && availability.getId()>0) {
+
+ this.update(availability);
+
+ } else {
+ this.create(availability);
+ }
+
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/file/DigitalProductService.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/file/DigitalProductService.java
new file mode 100644
index 0000000..5deb29b
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/file/DigitalProductService.java
@@ -0,0 +1,24 @@
+package com.salesmanager.core.business.catalog.product.service.file;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.file.DigitalProduct;
+import com.salesmanager.core.business.content.model.InputContentFile;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+
+
+public interface DigitalProductService extends SalesManagerEntityService<Long, DigitalProduct> {
+
+ void saveOrUpdate(DigitalProduct digitalProduct) throws ServiceException;
+
+ void addProductFile(Product product, DigitalProduct digitalProduct,
+ InputContentFile inputFile) throws ServiceException;
+
+
+
+ DigitalProduct getByProduct(MerchantStore store, Product product)
+ throws ServiceException;
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/file/DigitalProductServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/file/DigitalProductServiceImpl.java
new file mode 100644
index 0000000..684bc6c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/file/DigitalProductServiceImpl.java
@@ -0,0 +1,110 @@
+package com.salesmanager.core.business.catalog.product.service.file;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
+
+import com.salesmanager.core.business.catalog.product.dao.file.DigitalProductDao;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.file.DigitalProduct;
+import com.salesmanager.core.business.catalog.product.service.ProductService;
+import com.salesmanager.core.business.content.model.FileContentType;
+import com.salesmanager.core.business.content.model.InputContentFile;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.modules.cms.content.StaticContentFileManager;
+
+@Service("digitalProductService")
+public class DigitalProductServiceImpl extends SalesManagerEntityServiceImpl<Long, DigitalProduct>
+ implements DigitalProductService {
+
+
+ private DigitalProductDao digitalProductDao;
+
+ @Autowired
+ StaticContentFileManager productDownloadsFileManager;
+
+ @Autowired
+ ProductService productService;
+
+ @Autowired
+ public DigitalProductServiceImpl(DigitalProductDao digitalProductDao) {
+ super(digitalProductDao);
+ this.digitalProductDao = digitalProductDao;
+ }
+
+ @Override
+ public void addProductFile(Product product, DigitalProduct digitalProduct, InputContentFile inputFile) throws ServiceException {
+
+ Assert.notNull(digitalProduct,"DigitalProduct cannot be null");
+ Assert.notNull(product,"Product cannot be null");
+ digitalProduct.setProduct(product);
+
+ try {
+
+ Assert.notNull(inputFile.getFile(),"InputContentFile.file cannot be null");
+
+ Assert.notNull(product.getMerchantStore(),"Product.merchantStore cannot be null");
+ this.saveOrUpdate(digitalProduct);
+
+ productDownloadsFileManager.addFile(product.getMerchantStore().getCode(), inputFile);
+
+ product.setProductVirtual(true);
+ productService.update(product);
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ } finally {
+ try {
+
+ if(inputFile.getFile()!=null) {
+ inputFile.getFile().close();
+ }
+
+ } catch(Exception ignore) {}
+ }
+
+
+ }
+
+ @Override
+ public DigitalProduct getByProduct(MerchantStore store, Product product) throws ServiceException {
+ return digitalProductDao.getByProduct(store, product);
+ }
+
+ @Override
+ public void delete(DigitalProduct digitalProduct) throws ServiceException {
+
+ Assert.notNull(digitalProduct,"DigitalProduct cannot be null");
+ Assert.notNull(digitalProduct.getProduct(),"DigitalProduct.product cannot be null");
+ //refresh file
+ digitalProduct = this.getById(digitalProduct.getId());
+ super.delete(digitalProduct);
+ productDownloadsFileManager.removeFile(digitalProduct.getProduct().getMerchantStore().getCode(), FileContentType.PRODUCT, digitalProduct.getProductFileName());
+ digitalProduct.getProduct().setProductVirtual(false);
+ productService.update(digitalProduct.getProduct());
+ }
+
+
+ @Override
+ public void saveOrUpdate(DigitalProduct digitalProduct) throws ServiceException {
+
+ Assert.notNull(digitalProduct,"DigitalProduct cannot be null");
+ Assert.notNull(digitalProduct.getProduct(),"DigitalProduct.product cannot be null");
+ if(digitalProduct.getId()==null || digitalProduct.getId().longValue()==0) {
+ super.save(digitalProduct);
+ } else {
+ super.create(digitalProduct);
+ }
+
+ digitalProduct.getProduct().setProductVirtual(true);
+ productService.update(digitalProduct.getProduct());
+
+
+ }
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/image/ProductImageService.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/image/ProductImageService.java
new file mode 100644
index 0000000..877f831
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/image/ProductImageService.java
@@ -0,0 +1,66 @@
+package com.salesmanager.core.business.catalog.product.service.image;
+
+import java.util.List;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.file.ProductImageSize;
+import com.salesmanager.core.business.catalog.product.model.image.ProductImage;
+import com.salesmanager.core.business.content.model.ImageContentFile;
+import com.salesmanager.core.business.content.model.OutputContentFile;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+
+
+public interface ProductImageService extends SalesManagerEntityService<Long, ProductImage> {
+
+
+
+ /**
+ * Add a ProductImage to the persistence and an entry to the CMS
+ * @param product
+ * @param productImage
+ * @param file
+ * @throws ServiceException
+ */
+ void addProductImage(Product product, ProductImage productImage, ImageContentFile inputImage)
+ throws ServiceException;
+
+ /**
+ * Get the image ByteArrayOutputStream and content description from CMS
+ * @param productImage
+ * @return
+ * @throws ServiceException
+ */
+ OutputContentFile getProductImage(ProductImage productImage, ProductImageSize size)
+ throws ServiceException;
+
+ /**
+ * Returns all Images for a given product
+ * @param product
+ * @return
+ * @throws ServiceException
+ */
+ List<OutputContentFile> getProductImages(Product product)
+ throws ServiceException;
+
+ void removeProductImage(ProductImage productImage) throws ServiceException;
+
+ void saveOrUpdate(ProductImage productImage) throws ServiceException;
+
+ /**
+ * Returns an image file from required identifier. This method is
+ * used by the image servlet
+ * @param store
+ * @param product
+ * @param fileName
+ * @param size
+ * @return
+ * @throws ServiceException
+ */
+ OutputContentFile getProductImage(String storeCode, String productCode,
+ String fileName, final ProductImageSize size) throws ServiceException;
+
+ void addProductImages(Product product, List<ProductImage> productImages)
+ throws ServiceException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/image/ProductImageServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/image/ProductImageServiceImpl.java
new file mode 100644
index 0000000..9b29ef7
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/image/ProductImageServiceImpl.java
@@ -0,0 +1,206 @@
+package com.salesmanager.core.business.catalog.product.service.image;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
+
+import com.salesmanager.core.business.catalog.product.dao.image.ProductImageDao;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.file.ProductImageSize;
+import com.salesmanager.core.business.catalog.product.model.image.ProductImage;
+import com.salesmanager.core.business.catalog.product.model.image.ProductImageDescription;
+import com.salesmanager.core.business.content.model.FileContentType;
+import com.salesmanager.core.business.content.model.ImageContentFile;
+import com.salesmanager.core.business.content.model.OutputContentFile;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.modules.cms.product.ProductFileManager;
+
+@Service("productImage")
+public class ProductImageServiceImpl extends SalesManagerEntityServiceImpl<Long, ProductImage>
+ implements ProductImageService {
+
+ private ProductImageDao productImageDao;
+
+ @Autowired
+ public ProductImageServiceImpl(ProductImageDao productImageDao) {
+ super(productImageDao);
+ this.productImageDao = productImageDao;
+ }
+
+ @Autowired
+ private ProductFileManager productFileManager;
+
+
+
+
+ public ProductImage getById(Long id) {
+
+
+ return productImageDao.getProductImageById(id);
+ }
+
+
+ @Override
+ public void addProductImages(Product product, List<ProductImage> productImages) throws ServiceException {
+
+ try {
+ for(ProductImage productImage : productImages) {
+
+ Assert.notNull(productImage.getImage());
+
+ InputStream inputStream = productImage.getImage();
+ ImageContentFile cmsContentImage = new ImageContentFile();
+ cmsContentImage.setFileName( productImage.getProductImage() );
+ cmsContentImage.setFile( inputStream );
+ cmsContentImage.setFileContentType(FileContentType.PRODUCT);
+
+
+
+
+ addProductImage(product,productImage,cmsContentImage);
+ }
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+ }
+
+
+ @Override
+ public void addProductImage(Product product, ProductImage productImage, ImageContentFile inputImage) throws ServiceException {
+
+
+
+
+ productImage.setProduct(product);
+
+ try {
+
+ Assert.notNull(inputImage.getFile(),"ImageContentFile.file cannot be null");
+
+
+
+ productFileManager.addProductImage(productImage, inputImage);
+
+ //insert ProductImage
+ this.saveOrUpdate(productImage);
+
+
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ } finally {
+ try {
+
+ //if(inputImage.getBufferedImage()!=null){
+ // inputImage.getBufferedImage().flush();
+ //}
+
+ if(inputImage.getFile()!=null) {
+ inputImage.getFile().close();
+ }
+
+ } catch(Exception ignore) {
+
+ }
+ }
+
+
+ }
+
+ @Override
+ public void saveOrUpdate(ProductImage productImage) throws ServiceException {
+
+
+ //save or update (persist and attach entities
+ if(productImage.getId()!=null && productImage.getId()>0) {
+
+ super.update(productImage);
+
+ } else {
+
+ List<ProductImageDescription> descriptions = productImage.getDescriptions();
+ productImage.setDescriptions(null);
+ super.save(productImage);
+
+ if(descriptions!=null && descriptions.size()>0) {
+ for(ProductImageDescription description : descriptions) {
+ this.addProductImageDescription(productImage, description);
+ }
+ }
+
+ }
+
+ }
+
+ public void addProductImageDescription(ProductImage productImage, ProductImageDescription description)
+ throws ServiceException {
+
+
+ if(productImage.getDescriptions()==null) {
+ productImage.setDescriptions(new ArrayList<ProductImageDescription>());
+ }
+
+ productImage.getDescriptions().add(description);
+ description.setProductImage(productImage);
+ update(productImage);
+
+
+ }
+
+ //TODO get default product image
+
+
+ @Override
+ public OutputContentFile getProductImage(ProductImage productImage, ProductImageSize size) throws ServiceException {
+
+
+ ProductImage pi = new ProductImage();
+ String imageName = productImage.getProductImage();
+ if(size == ProductImageSize.LARGE) {
+ imageName = "L-" + imageName;
+ }
+
+ if(size == ProductImageSize.SMALL) {
+ imageName = "S-" + imageName;
+ }
+
+ pi.setProductImage(imageName);
+ pi.setProduct(productImage.getProduct());
+
+ OutputContentFile outputImage = productFileManager.getProductImage(pi);
+
+ return outputImage;
+
+ }
+
+ @Override
+ public OutputContentFile getProductImage(final String storeCode, final String productCode, final String fileName, final ProductImageSize size) throws ServiceException {
+ OutputContentFile outputImage = productFileManager.getProductImage(storeCode, productCode, fileName, size);
+ return outputImage;
+
+ }
+
+ @Override
+ public List<OutputContentFile> getProductImages(Product product) throws ServiceException {
+ return productFileManager.getImages(product);
+ }
+
+ @Override
+ public void removeProductImage(ProductImage productImage) throws ServiceException {
+
+ productFileManager.removeProductImage(productImage);
+
+ ProductImage p = this.getById(productImage.getId());
+
+
+ this.delete(p);
+
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/manufacturer/ManufacturerService.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/manufacturer/ManufacturerService.java
new file mode 100644
index 0000000..be7c120
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/manufacturer/ManufacturerService.java
@@ -0,0 +1,38 @@
+package com.salesmanager.core.business.catalog.product.service.manufacturer;
+
+import java.util.List;
+
+import com.salesmanager.core.business.catalog.product.model.manufacturer.Manufacturer;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.ManufacturerDescription;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface ManufacturerService extends SalesManagerEntityService<Long, Manufacturer> {
+
+ List<Manufacturer> listByStore(MerchantStore store, Language language)
+ throws ServiceException;
+
+ List<Manufacturer> listByStore(MerchantStore store) throws ServiceException;
+
+ void saveOrUpdate(Manufacturer manufacturer) throws ServiceException;
+
+ void addManufacturerDescription(Manufacturer manufacturer, ManufacturerDescription description) throws ServiceException;
+
+ int getCountManufAttachedProducts( Manufacturer manufacturer ) throws ServiceException;
+
+ void delete(Manufacturer manufacturer) throws ServiceException;
+
+ /**
+ * List manufacturers by products from a given list of categories
+ * @param store
+ * @param ids
+ * @param language
+ * @return
+ * @throws ServiceException
+ */
+ List<Manufacturer> listByProductsByCategoriesId(MerchantStore store,
+ List<Long> ids, Language language) throws ServiceException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/manufacturer/ManufacturerServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/manufacturer/ManufacturerServiceImpl.java
new file mode 100644
index 0000000..77a1905
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/manufacturer/ManufacturerServiceImpl.java
@@ -0,0 +1,98 @@
+package com.salesmanager.core.business.catalog.product.service.manufacturer;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.catalog.product.dao.manufacturer.ManufacturerDao;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.description.ProductDescription;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.Manufacturer;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.ManufacturerDescription;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.customer.service.CustomerServiceImpl;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.search.service.SearchService;
+
+
+
+@Service("manufacturerService")
+public class ManufacturerServiceImpl extends
+ SalesManagerEntityServiceImpl<Long, Manufacturer> implements ManufacturerService {
+
+ @Autowired
+ SearchService searchService;
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ManufacturerServiceImpl.class);
+ private ManufacturerDao manufacturerDao;
+
+ @Autowired
+ public ManufacturerServiceImpl(
+ ManufacturerDao manufacturerDao) {
+ super(manufacturerDao);
+ this.manufacturerDao = manufacturerDao;
+ }
+
+ @Override
+ public void delete(Manufacturer manufacturer) throws ServiceException{
+ manufacturer = this.getById(manufacturer.getId() );
+ super.delete( manufacturer );
+ }
+
+ @Override
+ public int getCountManufAttachedProducts( Manufacturer manufacturer ) throws ServiceException {
+ return manufacturerDao.getCountManufAttachedProducts( manufacturer );
+ }
+
+
+ @Override
+ public List<Manufacturer> listByStore(MerchantStore store, Language language) throws ServiceException {
+ return manufacturerDao.listByStore(store, language);
+ }
+
+ @Override
+ public List<Manufacturer> listByStore(MerchantStore store) throws ServiceException {
+ return manufacturerDao.listByStore(store);
+ }
+
+ @Override
+ public List<Manufacturer> listByProductsByCategoriesId(MerchantStore store, List<Long> ids, Language language) throws ServiceException {
+ return manufacturerDao.listByProductsByCategoriesId(store, ids, language);
+ }
+
+ @Override
+ public void addManufacturerDescription(Manufacturer manufacturer, ManufacturerDescription description)
+ throws ServiceException {
+
+
+ if(manufacturer.getDescriptions()==null) {
+ manufacturer.setDescriptions(new HashSet<ManufacturerDescription>());
+ }
+
+ manufacturer.getDescriptions().add(description);
+ description.setManufacturer(manufacturer);
+ update(manufacturer);
+ }
+
+ @Override
+ public void saveOrUpdate(Manufacturer manufacturer) throws ServiceException {
+
+ LOGGER.debug("Creating Manufacturer");
+
+ if(manufacturer.getId()!=null && manufacturer.getId()>0) {
+ super.update(manufacturer);
+
+ } else {
+ super.create(manufacturer);
+
+ }
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/price/ProductPriceService.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/price/ProductPriceService.java
new file mode 100644
index 0000000..ff00729
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/price/ProductPriceService.java
@@ -0,0 +1,15 @@
+package com.salesmanager.core.business.catalog.product.service.price;
+
+import com.salesmanager.core.business.catalog.product.model.price.ProductPrice;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPriceDescription;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+
+public interface ProductPriceService extends SalesManagerEntityService<Long, ProductPrice> {
+
+ void addDescription(ProductPrice price, ProductPriceDescription description) throws ServiceException;
+
+ void saveOrUpdate(ProductPrice price) throws ServiceException;
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/price/ProductPriceServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/price/ProductPriceServiceImpl.java
new file mode 100644
index 0000000..5752204
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/price/ProductPriceServiceImpl.java
@@ -0,0 +1,65 @@
+package com.salesmanager.core.business.catalog.product.service.price;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.catalog.product.dao.price.ProductPriceDao;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPrice;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPriceDescription;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+
+@Service("productPrice")
+public class ProductPriceServiceImpl extends SalesManagerEntityServiceImpl<Long, ProductPrice>
+ implements ProductPriceService {
+
+ @Autowired
+ public ProductPriceServiceImpl(ProductPriceDao productPriceDao) {
+ super(productPriceDao);
+ }
+
+ @Override
+ public void addDescription(ProductPrice price,
+ ProductPriceDescription description) throws ServiceException {
+ price.getDescriptions().add(description);
+ //description.setPrice(price);
+ update(price);
+ }
+
+
+ @Override
+ public void saveOrUpdate(ProductPrice price) throws ServiceException {
+
+ if(price.getId()!=null && price.getId()>0) {
+ this.update(price);
+ } else {
+
+ Set<ProductPriceDescription> descriptions = price.getDescriptions();
+ price.setDescriptions(new HashSet<ProductPriceDescription>());
+ this.create(price);
+ for(ProductPriceDescription description : descriptions) {
+ description.setProductPrice(price);
+ this.addDescription(price, description);
+ }
+
+ }
+
+
+
+ }
+
+ @Override
+ public void delete(ProductPrice price) throws ServiceException {
+
+ //override method, this allows the error that we try to remove a detached instance
+ price = this.getById(price.getId());
+ super.delete(price);
+
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/PricingService.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/PricingService.java
new file mode 100644
index 0000000..8a5ff43
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/PricingService.java
@@ -0,0 +1,102 @@
+package com.salesmanager.core.business.catalog.product.service;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Locale;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute;
+import com.salesmanager.core.business.catalog.product.model.price.FinalPrice;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.currency.model.Currency;
+
+
+/**
+ * Services for Product item price calculation.
+ * @author Carl Samson
+ *
+ */
+public interface PricingService {
+
+ /**
+ * Calculates the FinalPrice of a Product taking into account
+ * all defined prices and possible rebates
+ * @param product
+ * @return
+ * @throws ServiceException
+ */
+ FinalPrice calculateProductPrice(Product product) throws ServiceException;
+
+ /**
+ * Calculates the FinalPrice of a Product taking into account
+ * all defined prices and possible rebates. It also applies other calculation
+ * based on the customer
+ * @param product
+ * @param customer
+ * @return
+ * @throws ServiceException
+ */
+ FinalPrice calculateProductPrice(Product product, Customer customer)
+ throws ServiceException;
+
+ /**
+ * Calculates the FinalPrice of a Product taking into account
+ * all defined prices and possible rebates. This method should be used to calculate
+ * any additional prices based on the default attributes or based on the user selected attributes.
+ * @param product
+ * @param attributes
+ * @return
+ * @throws ServiceException
+ */
+ FinalPrice calculateProductPrice(Product product,
+ List<ProductAttribute> attributes) throws ServiceException;
+
+ /**
+ * Calculates the FinalPrice of a Product taking into account
+ * all defined prices and possible rebates. This method should be used to calculate
+ * any additional prices based on the default attributes or based on the user selected attributes.
+ * It also applies other calculation based on the customer
+ * @param product
+ * @param attributes
+ * @param customer
+ * @return
+ * @throws ServiceException
+ */
+ FinalPrice calculateProductPrice(Product product,
+ List<ProductAttribute> attributes, Customer customer)
+ throws ServiceException;
+
+ /**
+ * Method to be used to print a displayable formated amount to the end user
+ * @param amount
+ * @param store
+ * @return
+ * @throws ServiceException
+ */
+ String getDisplayAmount(BigDecimal amount, MerchantStore store)
+ throws ServiceException;
+
+ /**
+ * Method to be used when building an amount formatted with the appropriate currency
+ * @param amount
+ * @param locale
+ * @param currency
+ * @param store
+ * @return
+ * @throws ServiceException
+ */
+ String getDisplayAmount(BigDecimal amount, Locale locale, Currency currency, MerchantStore store)
+ throws ServiceException;
+
+ /**
+ * String format of the money amount without currency symbol
+ * @param amount
+ * @param store
+ * @return
+ * @throws ServiceException
+ */
+ String getStringAmount(BigDecimal amount, MerchantStore store)
+ throws ServiceException;
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/PricingServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/PricingServiceImpl.java
new file mode 100644
index 0000000..af8c787
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/PricingServiceImpl.java
@@ -0,0 +1,94 @@
+package com.salesmanager.core.business.catalog.product.service;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Locale;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute;
+import com.salesmanager.core.business.catalog.product.model.price.FinalPrice;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.currency.model.Currency;
+import com.salesmanager.core.utils.ProductPriceUtils;
+
+/**
+ * Contains all the logic required to calculate product price
+ * @author Carl Samson
+ *
+ */
+@Service("pricingService")
+public class PricingServiceImpl implements PricingService {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(PricingServiceImpl.class);
+
+
+ @Autowired
+ private ProductPriceUtils priceUtil;
+
+ @Override
+ public FinalPrice calculateProductPrice(Product product) throws ServiceException {
+ return priceUtil.getFinalPrice(product);
+ }
+
+ @Override
+ public FinalPrice calculateProductPrice(Product product, Customer customer) throws ServiceException {
+ /** TODO add rules for price calculation **/
+ return priceUtil.getFinalPrice(product);
+ }
+
+ @Override
+ public FinalPrice calculateProductPrice(Product product, List<ProductAttribute> attributes) throws ServiceException {
+ return priceUtil.getFinalProductPrice(product, attributes);
+ }
+
+ @Override
+ public FinalPrice calculateProductPrice(Product product, List<ProductAttribute> attributes, Customer customer) throws ServiceException {
+ /** TODO add rules for price calculation **/
+ return priceUtil.getFinalProductPrice(product, attributes);
+ }
+
+ @Override
+ public String getDisplayAmount(BigDecimal amount, MerchantStore store) throws ServiceException {
+ try {
+ String price= priceUtil.getStoreFormatedAmountWithCurrency(store,amount);
+ return price;
+ } catch (Exception e) {
+ LOGGER.error("An error occured when trying to format an amount " + amount.toString());
+ throw new ServiceException(e);
+ }
+ }
+
+ @Override
+ public String getDisplayAmount(BigDecimal amount, Locale locale,
+ Currency currency, MerchantStore store) throws ServiceException {
+ try {
+ String price= priceUtil.getFormatedAmountWithCurrency(locale, currency, amount);
+ return price;
+ } catch (Exception e) {
+ LOGGER.error("An error occured when trying to format an amunt " + amount.toString() + " using locale " + locale.toString() + " and currency " + currency.toString());
+ throw new ServiceException(e);
+ }
+ }
+
+ @Override
+ public String getStringAmount(BigDecimal amount, MerchantStore store)
+ throws ServiceException {
+ try {
+ String price = priceUtil.getAdminFormatedAmount(store, amount);
+ return price;
+ } catch (Exception e) {
+ LOGGER.error("An error occured when trying to format an amount " + amount.toString());
+ throw new ServiceException(e);
+ }
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/ProductService.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/ProductService.java
new file mode 100644
index 0000000..f7f707f
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/ProductService.java
@@ -0,0 +1,58 @@
+package com.salesmanager.core.business.catalog.product.service;
+
+import java.util.List;
+import java.util.Locale;
+
+import com.salesmanager.core.business.catalog.category.model.Category;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.ProductCriteria;
+import com.salesmanager.core.business.catalog.product.model.ProductList;
+import com.salesmanager.core.business.catalog.product.model.description.ProductDescription;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.tax.model.taxclass.TaxClass;
+
+
+
+public interface ProductService extends SalesManagerEntityService<Long, Product> {
+
+ void addProductDescription(Product product, ProductDescription description) throws ServiceException;
+
+ ProductDescription getProductDescription(Product product, Language language);
+
+ Product getProductForLocale(long productId, Language language, Locale locale) throws ServiceException;
+
+ List<Product> getProductsForLocale(Category category, Language language, Locale locale) throws ServiceException;
+
+ List<Product> getProducts(List<Long> categoryIds) throws ServiceException;
+
+
+
+ ProductList listByStore(MerchantStore store, Language language,
+ ProductCriteria criteria);
+
+
+
+ void saveOrUpdate(Product product) throws ServiceException;
+
+ List<Product> listByStore(MerchantStore store);
+
+ List<Product> listByTaxClass(TaxClass taxClass);
+
+ List<Product> getProducts(List<Long> categoryIds, Language language)
+ throws ServiceException;
+
+ Product getBySeUrl(MerchantStore store, String seUrl, Locale locale);
+
+ /**
+ * Get a product by sku (code) field and the language
+ * @param productCode
+ * @param language
+ * @return
+ */
+ Product getByCode(String productCode, Language language);
+
+}
+
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/ProductServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/ProductServiceImpl.java
new file mode 100644
index 0000000..60cb6d5
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/ProductServiceImpl.java
@@ -0,0 +1,401 @@
+package com.salesmanager.core.business.catalog.product.service;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+
+import org.apache.commons.lang.Validate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.catalog.category.model.Category;
+import com.salesmanager.core.business.catalog.category.service.CategoryService;
+import com.salesmanager.core.business.catalog.common.CatalogServiceHelper;
+import com.salesmanager.core.business.catalog.product.dao.ProductDao;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.ProductCriteria;
+import com.salesmanager.core.business.catalog.product.model.ProductList;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute;
+import com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability;
+import com.salesmanager.core.business.catalog.product.model.description.ProductDescription;
+import com.salesmanager.core.business.catalog.product.model.image.ProductImage;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPrice;
+import com.salesmanager.core.business.catalog.product.model.relationship.ProductRelationship;
+import com.salesmanager.core.business.catalog.product.service.attribute.ProductAttributeService;
+import com.salesmanager.core.business.catalog.product.service.availability.ProductAvailabilityService;
+import com.salesmanager.core.business.catalog.product.service.image.ProductImageService;
+import com.salesmanager.core.business.catalog.product.service.price.ProductPriceService;
+import com.salesmanager.core.business.catalog.product.service.relationship.ProductRelationshipService;
+import com.salesmanager.core.business.content.model.FileContentType;
+import com.salesmanager.core.business.content.model.ImageContentFile;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.search.service.SearchService;
+import com.salesmanager.core.business.tax.model.taxclass.TaxClass;
+import com.salesmanager.core.utils.CoreConfiguration;
+
+@Service("productService")
+public class ProductServiceImpl extends SalesManagerEntityServiceImpl<Long, Product> implements ProductService {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ProductServiceImpl.class);
+
+ ProductDao productDao;
+
+ @Autowired
+ CategoryService categoryService;
+
+ @Autowired
+ ProductAvailabilityService productAvailabilityService;
+
+ @Autowired
+ ProductPriceService productPriceService;
+
+
+ @Autowired
+ ProductAttributeService productAttributeService;
+
+ @Autowired
+ ProductRelationshipService productRelationshipService;
+
+ @Autowired
+ SearchService searchService;
+
+ @Autowired
+ ProductImageService productImageService;
+
+ @Autowired
+ CoreConfiguration configuration;
+
+ @Autowired
+ public ProductServiceImpl(ProductDao productDao) {
+ super(productDao);
+ this.productDao = productDao;
+ }
+
+ @Override
+ public void addProductDescription(Product product, ProductDescription description)
+ throws ServiceException {
+
+
+ if(product.getDescriptions()==null) {
+ product.setDescriptions(new HashSet<ProductDescription>());
+ }
+
+ product.getDescriptions().add(description);
+ description.setProduct(product);
+ update(product);
+ searchService.index(product.getMerchantStore(), product);
+ }
+
+ @Override
+ public List<Product> getProducts(List<Long> categoryIds) throws ServiceException {
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ Set ids = new HashSet(categoryIds);
+ return productDao.getProductsListByCategories(ids);
+
+ }
+
+ @Override
+ public List<Product> getProducts(List<Long> categoryIds, Language language) throws ServiceException {
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ Set<Long> ids = new HashSet(categoryIds);
+ return productDao.getProductsListByCategories(ids, language);
+
+ }
+
+ //@Override
+/* public ProductList getProductList(ProductCriteria criteria, List<Long> categoryIds, Language language) throws ServiceException {
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ Set<Long> ids = new HashSet(categoryIds);
+ return productDao.getProductListByCategories(criteria, ids, language);
+
+ }*/
+
+ @Override
+ public ProductDescription getProductDescription(Product product, Language language) {
+ for (ProductDescription description : product.getDescriptions()) {
+ if (description.getLanguage().equals(language)) {
+ return description;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Product getBySeUrl(MerchantStore store, String seUrl, Locale locale) {
+ return productDao.getBySeUrl(store, seUrl, locale);
+ }
+
+ @Override
+ public Product getProductForLocale(long productId, Language language, Locale locale)
+ throws ServiceException {
+ Product product = productDao.getProductForLocale(productId, language, locale);
+
+
+ CatalogServiceHelper.setToAvailability(product, locale);
+ CatalogServiceHelper.setToLanguage(product, language.getId());
+ return product;
+ }
+
+ @Override
+ public List<Product> getProductsForLocale(Category category,
+ Language language, Locale locale) throws ServiceException {
+
+ if(category==null) {
+ throw new ServiceException("The category is null");
+ }
+
+ //Get the category list
+ StringBuilder lineage = new StringBuilder().append(category.getLineage()).append(category.getId()).append("/");
+ List<Category> categories = categoryService.listByLineage(category.getMerchantStore(),lineage.toString());
+ Set<Long> categoryIds = new HashSet<Long>();
+ for(Category c : categories) {
+
+ categoryIds.add(c.getId());
+
+ }
+
+ categoryIds.add(category.getId());
+
+ //Get products
+ List<Product> products = productDao.getProductsForLocale(category.getMerchantStore(), categoryIds, language, locale);
+
+ //Filter availability
+
+ return products;
+ }
+
+ @Override
+ public ProductList listByStore(MerchantStore store,
+ Language language, ProductCriteria criteria) {
+
+ return productDao.listByStore(store, language, criteria);
+ }
+
+ @Override
+ public List<Product> listByStore(MerchantStore store) {
+
+ return productDao.listByStore(store);
+ }
+
+ @Override
+ public List<Product> listByTaxClass(TaxClass taxClass) {
+ return productDao.listByTaxClass(taxClass);
+ }
+
+ @Override
+ public Product getByCode(String productCode, Language language) {
+ return productDao.getByCode(productCode, language);
+ }
+
+
+
+
+
+ @Override
+ public void delete(Product product) throws ServiceException {
+ LOGGER.debug("Deleting product");
+ Validate.notNull(product, "Product cannot be null");
+ Validate.notNull(product.getMerchantStore(), "MerchantStore cannot be null in product");
+ product = this.getById(product.getId());//Prevents detached entity error
+ product.setCategories(null);
+
+ Set<ProductImage> images = product.getImages();
+
+ for(ProductImage image : images) {
+ productImageService.removeProductImage(image);
+ }
+
+ product.setImages(null);
+
+ //related - featured
+ List<ProductRelationship> relationships = productRelationshipService.listByProduct(product);
+ for(ProductRelationship relationship : relationships) {
+ productRelationshipService.delete(relationship);
+ }
+
+ super.delete(product);
+ searchService.deleteIndex(product.getMerchantStore(), product);
+
+ }
+
+ @Override
+ public void create(Product product) throws ServiceException {
+ super.create(product);
+ searchService.index(product.getMerchantStore(), product);
+ }
+
+
+
+ @Override
+ public void saveOrUpdate(Product product) throws ServiceException {
+
+ LOGGER.debug("Save or update product ");
+ Validate.notNull(product,"product cannot be null");
+ Validate.notNull(product.getAvailabilities(),"product must have at least one availability");
+ Validate.notEmpty(product.getAvailabilities(),"product must have at least one availability");
+
+ //List of original availabilities
+ Set<ProductAvailability> originalAvailabilities = null;
+
+ //List of original attributes
+ Set<ProductAttribute> originalAttributes = null;
+
+ //List of original reviews
+ Set<ProductRelationship> originalRelationships = null;
+
+ //List of original images
+ Set<ProductImage> originalProductImages = null;
+
+
+ if(product.getId()!=null && product.getId()>0) {
+ LOGGER.debug("Update product",product.getId());
+ //get original product
+ Product originalProduct = this.getById(product.getId());
+ originalAvailabilities = originalProduct.getAvailabilities();
+ originalAttributes = originalProduct.getAttributes();
+ originalRelationships = originalProduct.getRelationships();
+ originalProductImages = originalProduct.getImages();
+ } else {
+
+ Set<ProductDescription> productDescriptions = product.getDescriptions();
+ product.setDescriptions(null);
+
+ super.create(product);
+
+ for(ProductDescription productDescription : productDescriptions) {
+ addProductDescription(product,productDescription);
+ }
+ }
+
+
+ LOGGER.debug("Creating availabilities");
+
+ //get availabilities
+ Set<ProductAvailability> availabilities = product.getAvailabilities();
+ List<Long> newAvailabilityIds = new ArrayList<Long>();
+ if(availabilities!=null && availabilities.size()>0) {
+ for(ProductAvailability availability : availabilities) {
+ availability.setProduct(product);
+ productAvailabilityService.saveOrUpdate(availability);
+ newAvailabilityIds.add(availability.getId());
+ //check prices
+ Set<ProductPrice> prices = availability.getPrices();
+ if(prices!=null && prices.size()>0) {
+
+ for(ProductPrice price : prices) {
+ price.setProductAvailability(availability);
+ productPriceService.saveOrUpdate(price);
+ }
+ }
+ }
+ }
+
+ //cleanup old availability
+ if(originalAvailabilities!=null) {
+ for(ProductAvailability availability : originalAvailabilities) {
+ if(!newAvailabilityIds.contains(availability.getId())) {
+ productAvailabilityService.delete(availability);
+ }
+ }
+ }
+
+ LOGGER.debug("Creating attributes");
+ List<Long> newAttributesIds = new ArrayList<Long>();
+ if(product.getAttributes()!=null && product.getAttributes().size()>0) {
+ Set<ProductAttribute> attributes = product.getAttributes();
+ for(ProductAttribute attribute : attributes) {
+ attribute.setProduct(product);
+ productAttributeService.saveOrUpdate(attribute);
+ newAttributesIds.add(attribute.getId());
+ }
+ }
+
+ //cleanup old attributes
+ if(originalAttributes!=null) {
+ for(ProductAttribute attribute : originalAttributes) {
+ if(!newAttributesIds.contains(attribute.getId())) {
+ productAttributeService.delete(attribute);
+ }
+ }
+ }
+
+
+ LOGGER.debug("Creating relationships");
+ List<Long> newRelationshipIds = new ArrayList<Long>();
+ if(product.getRelationships()!=null && product.getRelationships().size()>0) {
+ Set<ProductRelationship> relationships = product.getRelationships();
+ for(ProductRelationship relationship : relationships) {
+ relationship.setProduct(product);
+ productRelationshipService.saveOrUpdate(relationship);
+ newRelationshipIds.add(relationship.getId());
+ }
+ }
+ //cleanup old relationships
+ if(originalRelationships!=null) {
+ for(ProductRelationship relationship : originalRelationships) {
+ if(!newRelationshipIds.contains(relationship.getId())) {
+ productRelationshipService.delete(relationship);
+ }
+ }
+ }
+
+
+ LOGGER.debug("Creating images");
+
+ //get images
+ List<Long> newImageIds = new ArrayList<Long>();
+ Set<ProductImage> images = product.getImages();
+ if(images!=null && images.size()>0) {
+ for(ProductImage image : images) {
+ if(image.getImage()!=null && (image.getId()==null || image.getId()==0L)) {
+ image.setProduct(product);
+
+ InputStream inputStream = image.getImage();
+ ImageContentFile cmsContentImage = new ImageContentFile();
+ cmsContentImage.setFileName( image.getProductImage() );
+ cmsContentImage.setFile( inputStream );
+ cmsContentImage.setFileContentType(FileContentType.PRODUCT);
+
+
+ productImageService.addProductImage(product, image, cmsContentImage);
+ newImageIds.add(image.getId());
+ } else {
+ productImageService.update(image);
+ newImageIds.add(image.getId());
+ }
+ }
+ }
+
+ //cleanup old images
+ if(originalProductImages!=null) {
+ for(ProductImage image : originalProductImages) {
+ if(!newImageIds.contains(image.getId())) {
+ productImageService.delete(image);
+ }
+ }
+ }
+
+ if(product.getId()!=null && product.getId()>0) {
+ super.update(product);
+ }
+
+ searchService.index(product.getMerchantStore(), product);
+
+ }
+
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/relationship/ProductRelationshipService.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/relationship/ProductRelationshipService.java
new file mode 100644
index 0000000..fa7ad61
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/relationship/ProductRelationshipService.java
@@ -0,0 +1,89 @@
+package com.salesmanager.core.business.catalog.product.service.relationship;
+
+import java.util.List;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.relationship.ProductRelationship;
+import com.salesmanager.core.business.catalog.product.model.relationship.ProductRelationshipType;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface ProductRelationshipService extends
+ SalesManagerEntityService<Long, ProductRelationship> {
+
+ void saveOrUpdate(ProductRelationship relationship) throws ServiceException;
+
+ /**
+ * Get product relationship List for a given type (RELATED, FEATURED...) and language allows
+ * to return the product description in the appropriate language
+ * @param store
+ * @param product
+ * @param type
+ * @param language
+ * @return
+ * @throws ServiceException
+ */
+ List<ProductRelationship> getByType(MerchantStore store, Product product,
+ ProductRelationshipType type, Language language) throws ServiceException;
+
+ /**
+ * Get product relationship List for a given type (RELATED, FEATURED...) and a given base product
+ * @param store
+ * @param product
+ * @param type
+ * @return
+ * @throws ServiceException
+ */
+ List<ProductRelationship> getByType(MerchantStore store, Product product,
+ ProductRelationshipType type)
+ throws ServiceException;
+
+ /**
+ * Get product relationship List for a given type (RELATED, FEATURED...)
+ * @param store
+ * @param type
+ * @return
+ * @throws ServiceException
+ */
+ List<ProductRelationship> getByType(MerchantStore store,
+ ProductRelationshipType type) throws ServiceException;
+
+ List<ProductRelationship> listByProduct(Product product)
+ throws ServiceException;
+
+ List<ProductRelationship> getByType(MerchantStore store,
+ ProductRelationshipType type, Language language)
+ throws ServiceException;
+
+ /**
+ * Get a list of relationship acting as groups of products
+ * @param store
+ * @return
+ */
+ List<ProductRelationship> getGroups(MerchantStore store);
+
+ /**
+ * Creates a product group
+ * @param groupName
+ * @throws ServiceException
+ */
+ void addGroup(MerchantStore store, String groupName) throws ServiceException;
+
+ List<ProductRelationship> getByGroup(MerchantStore store, String groupName)
+ throws ServiceException;
+
+ void deleteGroup(MerchantStore store, String groupName)
+ throws ServiceException;
+
+ void deactivateGroup(MerchantStore store, String groupName)
+ throws ServiceException;
+
+ void activateGroup(MerchantStore store, String groupName)
+ throws ServiceException;
+
+ List<ProductRelationship> getByGroup(MerchantStore store, String groupName,
+ Language language) throws ServiceException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/relationship/ProductRelationshipServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/relationship/ProductRelationshipServiceImpl.java
new file mode 100644
index 0000000..9f2d265
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/relationship/ProductRelationshipServiceImpl.java
@@ -0,0 +1,147 @@
+package com.salesmanager.core.business.catalog.product.service.relationship;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.catalog.product.dao.relationship.ProductRelationshipDao;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.relationship.ProductRelationship;
+import com.salesmanager.core.business.catalog.product.model.relationship.ProductRelationshipType;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Service("productRelationshipService")
+public class ProductRelationshipServiceImpl extends
+ SalesManagerEntityServiceImpl<Long, ProductRelationship> implements
+ ProductRelationshipService {
+
+
+ private ProductRelationshipDao productRelationshipDao;
+
+ @Autowired
+ public ProductRelationshipServiceImpl(
+ ProductRelationshipDao productRelationshipDao) {
+ super(productRelationshipDao);
+ this.productRelationshipDao = productRelationshipDao;
+ }
+
+ @Override
+ public void saveOrUpdate(ProductRelationship relationship) throws ServiceException {
+
+ if(relationship.getId()!=null && relationship.getId()>0) {
+
+ this.update(relationship);
+
+ } else {
+ this.create(relationship);
+ }
+
+ }
+
+
+ @Override
+ public void addGroup(MerchantStore store, String groupName) throws ServiceException {
+ ProductRelationship relationship = new ProductRelationship();
+ relationship.setCode(groupName);
+ relationship.setStore(store);
+ relationship.setActive(true);
+ this.save(relationship);
+ }
+
+ @Override
+ public List<ProductRelationship> getGroups(MerchantStore store) {
+ return productRelationshipDao.getGroups(store);
+ }
+
+ @Override
+ public void deleteGroup(MerchantStore store, String groupName) throws ServiceException {
+ List<ProductRelationship> entities = productRelationshipDao.getByGroup(store, groupName);
+ for(ProductRelationship relation : entities) {
+ this.delete(relation);
+ }
+ }
+
+ @Override
+ public void deactivateGroup(MerchantStore store, String groupName) throws ServiceException {
+ List<ProductRelationship> entities = productRelationshipDao.getByGroup(store, groupName);
+ for(ProductRelationship relation : entities) {
+ relation.setActive(false);
+ this.saveOrUpdate(relation);
+ }
+ }
+
+ @Override
+ public void activateGroup(MerchantStore store, String groupName) throws ServiceException {
+ List<ProductRelationship> entities = this.getByGroup(store, groupName);
+ for(ProductRelationship relation : entities) {
+ relation.setActive(true);
+ this.saveOrUpdate(relation);
+ }
+ }
+
+ public void delete(ProductRelationship relationship) throws ServiceException {
+
+ //throws detached exception so need to query first
+ relationship = this.getById(relationship.getId());
+ super.delete(relationship);
+
+
+ }
+
+ @Override
+ public List<ProductRelationship> listByProduct(Product product) throws ServiceException {
+
+ return productRelationshipDao.listByProducts(product);
+
+ }
+
+
+ @Override
+ public List<ProductRelationship> getByType(MerchantStore store, Product product, ProductRelationshipType type, Language language) throws ServiceException {
+
+ return productRelationshipDao.getByType(store, type.name(), product, language);
+
+ }
+
+ @Override
+ public List<ProductRelationship> getByType(MerchantStore store, ProductRelationshipType type, Language language) throws ServiceException {
+ return productRelationshipDao.getByType(store, type.name(), language);
+ }
+
+ @Override
+ public List<ProductRelationship> getByType(MerchantStore store, ProductRelationshipType type) throws ServiceException {
+
+ return productRelationshipDao.getByType(store, type.name());
+
+ }
+
+ @Override
+ public List<ProductRelationship> getByGroup(MerchantStore store, String groupName) throws ServiceException {
+
+ return productRelationshipDao.getByType(store, groupName);
+
+ }
+
+ @Override
+ public List<ProductRelationship> getByGroup(MerchantStore store, String groupName, Language language) throws ServiceException {
+
+ return productRelationshipDao.getByType(store, groupName, language);
+
+ }
+
+ @Override
+ public List<ProductRelationship> getByType(MerchantStore store, Product product, ProductRelationshipType type) throws ServiceException {
+
+
+ return productRelationshipDao.getByType(store, type.name(), product);
+
+
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/review/ProductReviewService.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/review/ProductReviewService.java
new file mode 100644
index 0000000..bc6c031
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/review/ProductReviewService.java
@@ -0,0 +1,22 @@
+package com.salesmanager.core.business.catalog.product.service.review;
+
+import java.util.List;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.review.ProductReview;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface ProductReviewService extends
+ SalesManagerEntityService<Long, ProductReview> {
+
+
+ List<ProductReview> getByCustomer(Customer customer);
+ List<ProductReview> getByProduct(Product product);
+ List<ProductReview> getByProduct(Product product, Language language);
+ ProductReview getByProductAndCustomer(Long productId, Long customerId);
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/review/ProductReviewServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/review/ProductReviewServiceImpl.java
new file mode 100644
index 0000000..51b559a
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/review/ProductReviewServiceImpl.java
@@ -0,0 +1,95 @@
+package com.salesmanager.core.business.catalog.product.service.review;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import com.salesmanager.core.business.catalog.product.dao.review.ProductReviewDao;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.review.ProductReview;
+import com.salesmanager.core.business.catalog.product.service.ProductService;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Service("productReviewService")
+public class ProductReviewServiceImpl extends
+ SalesManagerEntityServiceImpl<Long, ProductReview> implements
+ ProductReviewService {
+
+
+ private ProductReviewDao productReviewDao;
+
+ @Autowired
+ private ProductService productService;
+
+ @Autowired
+ public ProductReviewServiceImpl(
+ ProductReviewDao productReviewDao) {
+ super(productReviewDao);
+ this.productReviewDao = productReviewDao;
+ }
+
+ @Override
+ public List<ProductReview> getByCustomer(Customer customer) {
+ return productReviewDao.getByCustomer(customer);
+ }
+
+ @Override
+ public List<ProductReview> getByProduct(Product product) {
+ return productReviewDao.getByProduct(product);
+ }
+
+ @Override
+ public ProductReview getByProductAndCustomer(Long productId, Long customerId) {
+ return productReviewDao.getByProductAndCustomer(productId, customerId);
+ }
+
+ @Override
+ public List<ProductReview> getByProduct(Product product, Language language) {
+ return productReviewDao.getByProduct(product, language);
+ }
+
+ public void create(ProductReview review) throws ServiceException {
+
+ //adjust score
+
+ //refresh product
+ Product product = productService.getById(review.getProduct().getId());
+
+ //ajust product rating
+ Integer count = 0;
+ if(product.getProductReviewCount()!=null) {
+ count = product.getProductReviewCount();
+ }
+
+
+
+
+ BigDecimal averageRating = product.getProductReviewAvg();
+ if(averageRating==null) {
+ averageRating = new BigDecimal(0);
+ }
+ //get reviews
+
+
+ BigDecimal totalRating = averageRating.multiply(new BigDecimal(count));
+ totalRating = totalRating.add(new BigDecimal(review.getReviewRating()));
+
+ count = count + 1;
+ double avg = totalRating.doubleValue() / count.intValue();
+
+ product.setProductReviewAvg(new BigDecimal(avg));
+ product.setProductReviewCount(count);
+ super.create(review);
+
+ productService.update(product);
+
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/type/ProductTypeService.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/type/ProductTypeService.java
new file mode 100644
index 0000000..fef6a47
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/type/ProductTypeService.java
@@ -0,0 +1,11 @@
+package com.salesmanager.core.business.catalog.product.service.type;
+
+import com.salesmanager.core.business.catalog.product.model.type.ProductType;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+
+public interface ProductTypeService extends SalesManagerEntityService<Long, ProductType> {
+
+ ProductType getProductType(String productTypeCode) throws ServiceException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/type/ProductTypeServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/type/ProductTypeServiceImpl.java
new file mode 100644
index 0000000..fe77059
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/catalog/product/service/type/ProductTypeServiceImpl.java
@@ -0,0 +1,34 @@
+package com.salesmanager.core.business.catalog.product.service.type;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.catalog.product.dao.type.ProductTypeDao;
+import com.salesmanager.core.business.catalog.product.model.type.ProductType;
+import com.salesmanager.core.business.catalog.product.model.type.ProductType_;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+
+@Service("productTypeService")
+public class ProductTypeServiceImpl extends SalesManagerEntityServiceImpl<Long, ProductType>
+ implements ProductTypeService {
+
+ private ProductTypeDao productTypeDao;
+
+ @Autowired
+ public ProductTypeServiceImpl(
+ ProductTypeDao productTypeDao) {
+ super(productTypeDao);
+ this.productTypeDao = productTypeDao;
+ }
+
+ @Override
+ public ProductType getProductType(String productTypeCode) throws ServiceException {
+
+ return getByField(ProductType_.code, productTypeCode);
+
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/common/model/Address.java b/sm-core/src/main/java/com/salesmanager/core/business/common/model/Address.java
new file mode 100644
index 0000000..a8fe241
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/common/model/Address.java
@@ -0,0 +1,62 @@
+package com.salesmanager.core.business.common.model;
+
+import java.io.Serializable;
+
+
+public class Address implements Serializable {
+
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+ private String city;
+ private String postalCode;
+ private String stateProvince;
+ private String zone;//code
+ private String country;//code
+
+ public void setStateProvince(String stateProvince) {
+ this.stateProvince = stateProvince;
+ }
+
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getPostalCode() {
+ return postalCode;
+ }
+
+ public void setPostalCode(String postalCode) {
+ this.postalCode = postalCode;
+ }
+
+ public String getStateProvince() {
+ return stateProvince;
+ }
+
+ public String getCountry() {
+ return country;
+ }
+
+ public void setZone(String zone) {
+ this.zone = zone;
+ }
+
+ public String getZone() {
+ return zone;
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/common/model/audit/Auditable.java b/sm-core/src/main/java/com/salesmanager/core/business/common/model/audit/Auditable.java
new file mode 100644
index 0000000..58c0332
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/common/model/audit/Auditable.java
@@ -0,0 +1,8 @@
+package com.salesmanager.core.business.common.model.audit;
+
+public interface Auditable {
+
+ AuditSection getAuditSection();
+
+ void setAuditSection(AuditSection audit);
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/common/model/audit/AuditListener.java b/sm-core/src/main/java/com/salesmanager/core/business/common/model/audit/AuditListener.java
new file mode 100644
index 0000000..a4b7ebf
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/common/model/audit/AuditListener.java
@@ -0,0 +1,24 @@
+package com.salesmanager.core.business.common.model.audit;
+
+import java.util.Date;
+
+import javax.persistence.PrePersist;
+import javax.persistence.PreUpdate;
+
+public class AuditListener {
+
+ @PrePersist
+ @PreUpdate
+ public void onSaveOrUpdate(Object o) {
+ if (o instanceof Auditable) {
+ Auditable audit = (Auditable) o;
+ AuditSection auditSection = audit.getAuditSection();
+
+ auditSection.setDateModified(new Date());
+ if (auditSection.getDateCreated() == null) {
+ auditSection.setDateCreated(new Date());
+ }
+ audit.setAuditSection(auditSection);
+ }
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/common/model/audit/AuditSection.java b/sm-core/src/main/java/com/salesmanager/core/business/common/model/audit/AuditSection.java
new file mode 100644
index 0000000..438498b
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/common/model/audit/AuditSection.java
@@ -0,0 +1,57 @@
+package com.salesmanager.core.business.common.model.audit;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import com.salesmanager.core.utils.CloneUtils;
+
+@Embeddable
+//@org.hibernate.annotations.Entity(dynamicUpdate = true, dynamicInsert = true)
+public class AuditSection implements Serializable {
+
+
+ private static final long serialVersionUID = -1934446958975060889L;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column(name = "DATE_CREATED")
+ private Date dateCreated;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column(name = "DATE_MODIFIED")
+ private Date dateModified;
+
+ @Column(name = "UPDT_ID", length=20)
+ private String modifiedBy;
+
+ public AuditSection() {
+ }
+
+ public Date getDateCreated() {
+ return CloneUtils.clone(dateCreated);
+ }
+
+ public void setDateCreated(Date dateCreated) {
+ this.dateCreated = CloneUtils.clone(dateCreated);
+ }
+
+ public Date getDateModified() {
+ return CloneUtils.clone(dateModified);
+ }
+
+ public void setDateModified(Date dateModified) {
+ this.dateModified = CloneUtils.clone(dateModified);
+ }
+
+ public String getModifiedBy() {
+ return modifiedBy;
+ }
+
+ public void setModifiedBy(String modifiedBy) {
+ this.modifiedBy = modifiedBy;
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/common/model/Billing.java b/sm-core/src/main/java/com/salesmanager/core/business/common/model/Billing.java
new file mode 100755
index 0000000..97be079
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/common/model/Billing.java
@@ -0,0 +1,139 @@
+package com.salesmanager.core.business.common.model;
+
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.FetchType;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
+import org.hibernate.validator.constraints.NotEmpty;
+
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+
+@Embeddable
+public class Billing {
+
+ @NotEmpty
+ @Column (name ="BILLING_LAST_NAME", length=64, nullable=false)
+ private String lastName;
+
+ @NotEmpty
+ @Column (name ="BILLING_FIRST_NAME", length=64, nullable=false)
+ private String firstName;
+
+
+
+ @Column (name ="BILLING_COMPANY", length=100)
+ private String company;
+
+ @Column (name ="BILLING_STREET_ADDRESS", length=256)
+ private String address;
+
+
+ @Column (name ="BILLING_CITY", length=100)
+ private String city;
+
+ @Column (name ="BILLING_POSTCODE", length=20)
+ private String postalCode;
+
+ @Column(name="BILLING_TELEPHONE", length=32)
+ private String telephone;
+
+ @Column (name ="BILLING_STATE", length=100)
+ private String state;
+
+
+ @ManyToOne(fetch = FetchType.EAGER, targetEntity = Country.class)
+ @JoinColumn(name="BILLING_COUNTRY_ID", nullable=false)
+ private Country country;
+
+
+ @ManyToOne(fetch = FetchType.EAGER, targetEntity = Zone.class)
+ @JoinColumn(name="BILLING_ZONE_ID", nullable=true)
+ private Zone zone;
+
+
+
+ public String getCompany() {
+ return company;
+ }
+
+ public void setCompany(String company) {
+ this.company = company;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getPostalCode() {
+ return postalCode;
+ }
+
+ public void setPostalCode(String postalCode) {
+ this.postalCode = postalCode;
+ }
+
+ public Country getCountry() {
+ return country;
+ }
+
+ public void setCountry(Country country) {
+ this.country = country;
+ }
+
+ public Zone getZone() {
+ return zone;
+ }
+
+ public void setZone(Zone zone) {
+ this.zone = zone;
+ }
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(String state) {
+ this.state = state;
+ }
+
+ public void setTelephone(String telephone) {
+ this.telephone = telephone;
+ }
+
+ public String getTelephone() {
+ return telephone;
+ }
+
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/common/model/Criteria.java b/sm-core/src/main/java/com/salesmanager/core/business/common/model/Criteria.java
new file mode 100644
index 0000000..a800521
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/common/model/Criteria.java
@@ -0,0 +1,40 @@
+package com.salesmanager.core.business.common.model;
+
+public class Criteria {
+
+ private int startIndex = 0;
+ private int maxCount = 0;
+ private String code;
+
+
+ private CriteriaOrderBy orderBy = CriteriaOrderBy.DESC;
+
+
+ public int getMaxCount() {
+ return maxCount;
+ }
+ public void setMaxCount(int maxCount) {
+ this.maxCount = maxCount;
+ }
+ public int getStartIndex() {
+ return startIndex;
+ }
+ public void setStartIndex(int startIndex) {
+ this.startIndex = startIndex;
+ }
+ public String getCode() {
+ return code;
+ }
+ public void setCode(String code) {
+ this.code = code;
+ }
+ public void setOrderBy(CriteriaOrderBy orderBy) {
+ this.orderBy = orderBy;
+ }
+ public CriteriaOrderBy getOrderBy() {
+ return orderBy;
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/common/model/CriteriaOrderBy.java b/sm-core/src/main/java/com/salesmanager/core/business/common/model/CriteriaOrderBy.java
new file mode 100644
index 0000000..c9a8eb7
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/common/model/CriteriaOrderBy.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.common.model;
+
+public enum CriteriaOrderBy {
+
+
+ ASC, DESC
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/common/model/Delivery.java b/sm-core/src/main/java/com/salesmanager/core/business/common/model/Delivery.java
new file mode 100755
index 0000000..5c3faf9
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/common/model/Delivery.java
@@ -0,0 +1,138 @@
+package com.salesmanager.core.business.common.model;
+
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.FetchType;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToOne;
+
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+
+@Embeddable
+public class Delivery {
+
+ @Column (name ="DELIVERY_LAST_NAME", length=64)
+ private String lastName;
+
+
+
+
+ @Column (name ="DELIVERY_FIRST_NAME", length=64)
+ private String firstName;
+
+
+
+
+ @Column (name ="DELIVERY_COMPANY", length=100)
+ private String company;
+
+ @Column (name ="DELIVERY_STREET_ADDRESS", length=256)
+ private String address;
+
+ @Column (name ="DELIVERY_CITY", length=100)
+ private String city;
+
+ @Column (name ="DELIVERY_POSTCODE", length=20)
+ private String postalCode;
+
+ @Column (name ="DELIVERY_STATE", length=100)
+ private String state;
+
+ @Column(name="DELIVERY_TELEPHONE", length=32)
+ private String telephone;
+
+ @ManyToOne(fetch = FetchType.EAGER, targetEntity = Country.class)
+ @JoinColumn(name="DELIVERY_COUNTRY_ID", nullable=true)
+ private Country country;
+
+
+ @ManyToOne(fetch = FetchType.EAGER, targetEntity = Zone.class)
+ @JoinColumn(name="DELIVERY_ZONE_ID", nullable=true)
+ private Zone zone;
+
+
+
+ public String getCompany() {
+ return company;
+ }
+
+ public void setCompany(String company) {
+ this.company = company;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ public String getCity() {
+ return city;
+ }
+
+ public void setCity(String city) {
+ this.city = city;
+ }
+
+ public String getPostalCode() {
+ return postalCode;
+ }
+
+ public void setPostalCode(String postalCode) {
+ this.postalCode = postalCode;
+ }
+
+ public Country getCountry() {
+ return country;
+ }
+
+ public void setCountry(Country country) {
+ this.country = country;
+ }
+
+ public Zone getZone() {
+ return zone;
+ }
+
+ public void setZone(Zone zone) {
+ this.zone = zone;
+ }
+
+
+ public String getState() {
+ return state;
+ }
+
+ public void setState(String state) {
+ this.state = state;
+ }
+
+ public void setTelephone(String telephone) {
+ this.telephone = telephone;
+ }
+
+ public String getTelephone() {
+ return telephone;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/common/model/Description.java b/sm-core/src/main/java/com/salesmanager/core/business/common/model/Description.java
new file mode 100644
index 0000000..59e917f
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/common/model/Description.java
@@ -0,0 +1,113 @@
+package com.salesmanager.core.business.common.model;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.EntityListeners;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.MappedSuperclass;
+import javax.persistence.TableGenerator;
+
+import org.hibernate.annotations.Type;
+import org.hibernate.validator.constraints.NotEmpty;
+
+import com.salesmanager.core.business.common.model.audit.AuditListener;
+import com.salesmanager.core.business.common.model.audit.AuditSection;
+import com.salesmanager.core.business.common.model.audit.Auditable;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@MappedSuperclass
+@EntityListeners(value = AuditListener.class)
+@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
+public class Description implements Auditable, Serializable {
+ private static final long serialVersionUID = -4335863941736710046L;
+
+ @Id
+ @Column(name = "DESCRIPTION_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "DESCRIPTION_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @Embedded
+ private AuditSection auditSection = new AuditSection();
+
+ @ManyToOne(optional = false)
+ @JoinColumn(name = "LANGUAGE_ID")
+ private Language language;
+
+ @NotEmpty
+ @Column(name="NAME", nullable = false, length=120)
+ private String name;
+
+ @Column(name="TITLE", length=100)
+ private String title;
+
+ @Column(name="DESCRIPTION")
+ @Type(type = "org.hibernate.type.StringClobType")
+ private String description;
+
+ public Description() {
+ }
+
+ public Description(Language language, String name) {
+ this.setLanguage(language);
+ this.setName(name);
+ }
+
+ @Override
+ public AuditSection getAuditSection() {
+ return auditSection;
+ }
+
+ @Override
+ public void setAuditSection(AuditSection auditSection) {
+ this.auditSection = auditSection;
+ }
+
+ public Language getLanguage() {
+ return language;
+ }
+
+ public void setLanguage(Language language) {
+ this.language = language;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/common/model/EntityList.java b/sm-core/src/main/java/com/salesmanager/core/business/common/model/EntityList.java
new file mode 100644
index 0000000..ce03d25
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/common/model/EntityList.java
@@ -0,0 +1,21 @@
+package com.salesmanager.core.business.common.model;
+
+import java.io.Serializable;
+
+public class EntityList implements Serializable {
+
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 6135941880202635567L;
+ private int totalCount;
+
+ public int getTotalCount() {
+ return totalCount;
+ }
+ public void setTotalCount(int totalCount) {
+ this.totalCount = totalCount;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/common/model/OrderTotalItem.java b/sm-core/src/main/java/com/salesmanager/core/business/common/model/OrderTotalItem.java
new file mode 100644
index 0000000..b383e83
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/common/model/OrderTotalItem.java
@@ -0,0 +1,27 @@
+package com.salesmanager.core.business.common.model;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+public class OrderTotalItem implements Serializable {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+ private BigDecimal itemPrice;
+ private String itemCode;
+ public void setItemPrice(BigDecimal itemPrice) {
+ this.itemPrice = itemPrice;
+ }
+ public BigDecimal getItemPrice() {
+ return itemPrice;
+ }
+ public void setItemCode(String itemCode) {
+ this.itemCode = itemCode;
+ }
+ public String getItemCode() {
+ return itemCode;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/content/dao/ContentDao.java b/sm-core/src/main/java/com/salesmanager/core/business/content/dao/ContentDao.java
new file mode 100755
index 0000000..82bf93e
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/content/dao/ContentDao.java
@@ -0,0 +1,50 @@
+package com.salesmanager.core.business.content.dao;
+
+import java.util.List;
+
+import com.salesmanager.core.business.content.model.Content;
+import com.salesmanager.core.business.content.model.ContentDescription;
+import com.salesmanager.core.business.content.model.ContentType;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface ContentDao extends SalesManagerEntityDao<Long, Content> {
+
+ List<Content> listByType(ContentType contentType, MerchantStore store,
+ Language language) throws ServiceException;
+
+ List<Content> listByType(List<ContentType> contentType, MerchantStore store,
+ Language language) throws ServiceException;
+
+ Content getByCode(String code, MerchantStore store)
+ throws ServiceException;
+
+ Content getByCode(String code, MerchantStore store, Language language)
+ throws ServiceException;
+
+ List<Content> listByType(List<ContentType> contentType, MerchantStore store)
+ throws ServiceException;
+
+ List<Content> listByType(ContentType contentType, MerchantStore store)
+ throws ServiceException;
+
+ /**
+ * List ContentDescription objects. Removes non visible content
+ * @param contentType
+ * @param store
+ * @param language
+ * @return
+ * @throws ServiceException
+ */
+ List<ContentDescription> listNameByType(List<ContentType> contentType,
+ MerchantStore store, Language language) throws ServiceException;
+
+ Content getByLanguage(Long id, Language language) throws ServiceException;
+
+ ContentDescription getBySeUrl(MerchantStore store, String seUrl);
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/content/dao/ContentDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/content/dao/ContentDaoImpl.java
new file mode 100755
index 0000000..a413671
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/content/dao/ContentDaoImpl.java
@@ -0,0 +1,266 @@
+package com.salesmanager.core.business.content.dao;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.content.model.Content;
+import com.salesmanager.core.business.content.model.ContentDescription;
+import com.salesmanager.core.business.content.model.ContentType;
+import com.salesmanager.core.business.content.model.QContent;
+import com.salesmanager.core.business.content.model.QContentDescription;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Repository("contentDao")
+public class ContentDaoImpl extends SalesManagerEntityDaoImpl<Long, Content> implements ContentDao {
+
+ public ContentDaoImpl() {
+ super();
+ }
+
+ @Override
+ public List<Content> listByType(ContentType contentType, MerchantStore store, Language language) throws ServiceException {
+
+ QContent qContent = QContent.content;
+ QContentDescription qContentDescription = QContentDescription.contentDescription;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qContent)
+ .leftJoin(qContent.descriptions, qContentDescription).fetch()
+ .leftJoin(qContent.merchantStore).fetch()
+ .where(qContentDescription.language.id.eq(language.getId())
+ .and(qContent.merchantStore.id.eq(store.getId()))
+ .and(qContent.contentType.eq(contentType))
+ ).orderBy(qContent.sortOrder.asc());
+
+ List<Content> contents = query.list(qContent);
+
+ return contents;
+ }
+
+ @Override
+ public List<Content> listByType(ContentType contentType, MerchantStore store) throws ServiceException {
+
+ QContent qContent = QContent.content;
+ QContentDescription qContentDescription = QContentDescription.contentDescription;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qContent)
+ .leftJoin(qContent.descriptions, qContentDescription).fetch()
+ .leftJoin(qContent.merchantStore).fetch()
+ .where(qContent.merchantStore.id.eq(store.getId())
+ .and(qContent.contentType.eq(contentType))
+ ).orderBy(qContent.sortOrder.asc());
+
+ List<Content> contents = query.list(qContent);
+
+ return contents;
+ }
+
+
+ @Override
+ public List<Content> listByType(List<ContentType> contentType, MerchantStore store, Language language) throws ServiceException {
+
+ QContent qContent = QContent.content;
+ QContentDescription qContentDescription = QContentDescription.contentDescription;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qContent)
+ .leftJoin(qContent.descriptions, qContentDescription).fetch()
+ .leftJoin(qContent.merchantStore).fetch()
+ .where(qContentDescription.language.id.eq(language.getId())
+ .and(qContent.merchantStore.id.eq(store.getId()))
+ .and(qContent.contentType.in(contentType))
+ ).orderBy(qContent.sortOrder.asc());
+
+ List<Content> contents = query.list(qContent);
+
+ return contents;
+ }
+
+ @Override
+ public List<ContentDescription> listNameByType(List<ContentType> contentType, MerchantStore store, Language language) throws ServiceException {
+
+ QContent qContent = QContent.content;
+ QContentDescription qContentDescription = QContentDescription.contentDescription;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+
+ query.from(qContent)
+ .leftJoin(qContent.descriptions, qContentDescription).fetch()
+ .leftJoin(qContent.merchantStore).fetch()
+ .where(qContentDescription.language.id.eq(language.getId())
+ .and(qContent.merchantStore.id.eq(store.getId()))
+ .and(qContent.contentType.in(contentType))
+ .and(qContent.visible.eq(true))
+ ).orderBy(qContent.sortOrder.asc());
+
+
+
+ List<Content> contents = query.list(qContent);
+
+ List<ContentDescription> descriptions = new ArrayList<ContentDescription>();
+ for(Content c : contents) {
+ String name = c.getDescription().getName();
+ String url = c.getDescription().getSeUrl();
+ ContentDescription contentDescription = new ContentDescription();
+ contentDescription.setName(name);
+ contentDescription.setSeUrl(url);
+ descriptions.add(contentDescription);
+ }
+
+ return descriptions;
+ }
+
+ @Override
+ public List<Content> listByType(List<ContentType> contentType, MerchantStore store) throws ServiceException {
+
+ QContent qContent = QContent.content;
+ QContentDescription qContentDescription = QContentDescription.contentDescription;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qContent)
+ .leftJoin(qContent.descriptions, qContentDescription).fetch()
+ .leftJoin(qContent.merchantStore).fetch()
+ .where(qContent.merchantStore.id.eq(store.getId())
+ .and(qContent.contentType.in(contentType))
+ ).orderBy(qContent.sortOrder.asc());
+
+ List<Content> contents = query.list(qContent);
+
+ return contents;
+ }
+
+ @Override
+ public Content getByCode(String code, MerchantStore store) throws ServiceException {
+
+ QContent qContent = QContent.content;
+ QContentDescription qContentDescription = QContentDescription.contentDescription;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qContent)
+ .leftJoin(qContent.descriptions, qContentDescription).fetch()
+ .leftJoin(qContent.merchantStore).fetch()
+ .where(qContent.merchantStore.id.eq(store.getId())
+ .and(qContent.code.eq(code))
+ );
+
+ Content content = query.singleResult(qContent);
+
+ return content;
+ }
+
+ @Override
+ public Content getByLanguage(Long id, Language language) throws ServiceException {
+
+ QContent qContent = QContent.content;
+ QContentDescription qContentDescription = QContentDescription.contentDescription;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qContent)
+ .leftJoin(qContent.descriptions, qContentDescription).fetch()
+ .leftJoin(qContent.merchantStore).fetch()
+ .where(qContent.id.eq(id)
+ .and(qContentDescription.language.code.eq(language.getCode())));
+
+ Content content = query.singleResult(qContent);
+
+ return content;
+ }
+
+ @Override
+ public Content getById(Long id) {
+
+ QContent qContent = QContent.content;
+ QContentDescription qContentDescription = QContentDescription.contentDescription;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qContent)
+ .leftJoin(qContent.descriptions, qContentDescription).fetch()
+ .leftJoin(qContent.merchantStore).fetch()
+ .where(qContent.id.eq(id)
+ );
+
+ Content content = query.singleResult(qContent);
+
+ return content;
+ }
+
+ @Override
+ public Content getByCode(String code, MerchantStore store, Language language) throws ServiceException {
+
+ QContent qContent = QContent.content;
+ QContentDescription qContentDescription = QContentDescription.contentDescription;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qContent)
+ .leftJoin(qContent.descriptions, qContentDescription).fetch()
+ .leftJoin(qContent.merchantStore).fetch()
+ .where(qContentDescription.language.id.eq(language.getId())
+ .and(qContent.merchantStore.id.eq(store.getId())
+ .and(qContent.code.eq(code)))
+ );
+
+ Content content = query.singleResult(qContent);
+
+ return content;
+ }
+
+ @Override
+ public ContentDescription getBySeUrl(MerchantStore store,String seUrl) {
+
+ QContent qContent = QContent.content;
+ QContentDescription qContentDescription = QContentDescription.contentDescription;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+
+ query.from(qContent)
+ .leftJoin(qContent.descriptions, qContentDescription).fetch()
+ .leftJoin(qContent.merchantStore).fetch()
+ .where(qContentDescription.seUrl.eq(seUrl)
+ .and(qContent.merchantStore.id.eq(store.getId()))
+ .and(qContent.visible.eq(true))
+ );
+
+
+
+ Content content = query.uniqueResult(qContent);
+
+
+ if(content!=null) {
+ return content.getDescription();
+ }
+
+ return null;
+
+
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/content/model/Content.java b/sm-core/src/main/java/com/salesmanager/core/business/content/model/Content.java
new file mode 100755
index 0000000..20b4be0
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/content/model/Content.java
@@ -0,0 +1,170 @@
+package com.salesmanager.core.business.content.model;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.UniqueConstraint;
+import javax.validation.Valid;
+
+import org.hibernate.validator.constraints.NotEmpty;
+
+import com.salesmanager.core.business.common.model.audit.AuditListener;
+import com.salesmanager.core.business.common.model.audit.AuditSection;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.constants.SchemaConstant;
+
+
+@Entity
+@EntityListeners(value = AuditListener.class)
+@Table(name = "CONTENT", schema= SchemaConstant.SALESMANAGER_SCHEMA,uniqueConstraints=
+ @UniqueConstraint(columnNames = {"MERCHANT_ID", "CODE"}) )
+public class Content extends SalesManagerEntity<Long, Content> implements Serializable {
+
+
+
+ private static final long serialVersionUID = 1772757159185494620L;
+
+ @Id
+ @Column(name = "CONTENT_ID", unique=true, nullable=false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "CONTENT_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @Embedded
+ private AuditSection auditSection = new AuditSection();
+
+ @Valid
+ @OneToMany(mappedBy="content", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
+ private List<ContentDescription> descriptions = new ArrayList<ContentDescription>();
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="MERCHANT_ID", nullable=false)
+ private MerchantStore merchantStore;
+
+ @NotEmpty
+ @Column(name="CODE", length=100, nullable=false)
+ private String code;
+
+ @Column(name = "VISIBLE")
+ private boolean visible;
+
+ @Column(name = "CONTENT_POSITION", length=10, nullable=true)
+ @Enumerated(value = EnumType.STRING)
+ private ContentPosition contentPosition;
+
+ //Used for grouping
+ //BOX, SECTION, PAGE
+ @Column(name = "CONTENT_TYPE", length=10, nullable=true)
+ @Enumerated(value = EnumType.STRING)
+ private ContentType contentType;
+
+ @Column(name = "SORT_ORDER")
+ private Integer sortOrder = 0;
+
+ @Override
+ public Long getId() {
+ return this.id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+
+ }
+
+ public void setAuditSection(AuditSection auditSection) {
+ this.auditSection = auditSection;
+ }
+
+ public AuditSection getAuditSection() {
+ return auditSection;
+ }
+
+ public MerchantStore getMerchantStore() {
+ return merchantStore;
+ }
+
+ public void setMerchantStore(MerchantStore merchantStore) {
+ this.merchantStore = merchantStore;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public boolean isVisible() {
+ return visible;
+ }
+
+ public void setVisible(boolean visible) {
+ this.visible = visible;
+ }
+
+
+
+ public List<ContentDescription> getDescriptions() {
+ return descriptions;
+ }
+
+ public void setDescriptions(List<ContentDescription> descriptions) {
+ this.descriptions = descriptions;
+ }
+
+ public void setContentType(ContentType contentType) {
+ this.contentType = contentType;
+ }
+
+ public ContentType getContentType() {
+ return contentType;
+ }
+
+ public ContentDescription getDescription() {
+
+ if(this.getDescriptions()!=null && this.getDescriptions().size()>0) {
+ return this.getDescriptions().get(0);
+ }
+
+ return null;
+
+ }
+
+ public void setSortOrder(Integer sortOrder) {
+ this.sortOrder = sortOrder;
+ }
+
+ public Integer getSortOrder() {
+ return sortOrder;
+ }
+
+ public void setContentPosition(ContentPosition contentPosition) {
+ this.contentPosition = contentPosition;
+ }
+
+ public ContentPosition getContentPosition() {
+ return contentPosition;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/content/model/ContentDescription.java b/sm-core/src/main/java/com/salesmanager/core/business/content/model/ContentDescription.java
new file mode 100755
index 0000000..4efeaff
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/content/model/ContentDescription.java
@@ -0,0 +1,98 @@
+package com.salesmanager.core.business.content.model;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import com.salesmanager.core.business.common.model.Description;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Entity
+@Table(name="CONTENT_DESCRIPTION", schema="SALESMANAGER",uniqueConstraints={
+ @UniqueConstraint(columnNames={
+ "CONTENT_ID",
+ "LANGUAGE_ID"
+ })
+ }
+)
+public class ContentDescription extends Description implements Serializable {
+
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -1252756716545768599L;
+
+ @ManyToOne(targetEntity = Content.class)
+ @JoinColumn(name = "CONTENT_ID", nullable = false)
+ private Content content;
+
+ @Column(name="SEF_URL", length=120)
+ private String seUrl;
+
+
+ @Column(name="META_KEYWORDS")
+ private String metatagKeywords;
+
+ @Column(name="META_TITLE")
+ private String metatagTitle;
+
+ public String getMetatagTitle() {
+ return metatagTitle;
+ }
+
+ public void setMetatagTitle(String metatagTitle) {
+ this.metatagTitle = metatagTitle;
+ }
+
+ @Column(name="META_DESCRIPTION")
+ private String metatagDescription;
+
+ public ContentDescription() {
+ }
+
+ public ContentDescription(String name, Language language) {
+ this.setName(name);
+ this.setLanguage(language);
+ super.setId(0L);
+ }
+
+ public Content getContent() {
+ return content;
+ }
+
+ public void setContent(Content content) {
+ this.content = content;
+ }
+
+ public String getSeUrl() {
+ return seUrl;
+ }
+
+ public void setSeUrl(String seUrl) {
+ this.seUrl = seUrl;
+ }
+
+
+ public String getMetatagKeywords() {
+ return metatagKeywords;
+ }
+
+ public void setMetatagKeywords(String metatagKeywords) {
+ this.metatagKeywords = metatagKeywords;
+ }
+
+ public String getMetatagDescription() {
+ return metatagDescription;
+ }
+
+ public void setMetatagDescription(String metatagDescription) {
+ this.metatagDescription = metatagDescription;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/content/model/ContentFile.java b/sm-core/src/main/java/com/salesmanager/core/business/content/model/ContentFile.java
new file mode 100644
index 0000000..36f3e48
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/content/model/ContentFile.java
@@ -0,0 +1,22 @@
+package com.salesmanager.core.business.content.model;
+
+public abstract class ContentFile {
+
+
+ private String fileName;
+ private String mimeType;
+ public void setMimeType(String mimeType) {
+ this.mimeType = mimeType;
+ }
+ public String getMimeType() {
+ return mimeType;
+ }
+ public void setFileName(String fileName) {
+ this.fileName = fileName;
+ }
+ public String getFileName() {
+ return fileName;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/content/model/ContentPosition.java b/sm-core/src/main/java/com/salesmanager/core/business/content/model/ContentPosition.java
new file mode 100644
index 0000000..c9fdfb5
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/content/model/ContentPosition.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.content.model;
+
+public enum ContentPosition {
+
+ LEFT, RIGHT
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/content/model/ContentType.java b/sm-core/src/main/java/com/salesmanager/core/business/content/model/ContentType.java
new file mode 100755
index 0000000..18f53d2
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/content/model/ContentType.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.content.model;
+
+public enum ContentType {
+
+ BOX, PAGE, SECTION
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/content/model/FileContentType.java b/sm-core/src/main/java/com/salesmanager/core/business/content/model/FileContentType.java
new file mode 100644
index 0000000..d610aa4
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/content/model/FileContentType.java
@@ -0,0 +1,25 @@
+/**
+ *
+ */
+package com.salesmanager.core.business.content.model;
+
+/**
+ * Enum defining type of static content.
+ * Currently following type of static content can be store and managed within
+ * Shopizer CMS system
+ * <pre>
+ * 1. Static content like JS, CSS file etc
+ * 2. Digital Data (audio,video)
+ * </pre>
+ *
+ * StaticContentType will be used to distinguish between Digital data and other type of static data
+ * stored with in the system.
+ *
+ * @author Umesh Awasthi
+ * @since 1.2
+ *
+ */
+public enum FileContentType
+{
+ STATIC_FILE, IMAGE, LOGO, PRODUCT, PRODUCTLG, PROPERTY, MANUFACTURER, PRODUCT_DIGITAL
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/content/model/ImageContentFile.java b/sm-core/src/main/java/com/salesmanager/core/business/content/model/ImageContentFile.java
new file mode 100644
index 0000000..7524194
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/content/model/ImageContentFile.java
@@ -0,0 +1,22 @@
+package com.salesmanager.core.business.content.model;
+
+import java.io.Serializable;
+
+public class ImageContentFile extends InputContentFile implements Serializable {
+
+
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5321162403524229224L;
+ //private BufferedImage bufferedImage;
+
+ //public void setBufferedImage(BufferedImage bufferedImage) {
+ // this.bufferedImage = bufferedImage;
+ //}
+
+ //public BufferedImage getBufferedImage() {
+ // return bufferedImage;
+ //}
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/content/model/InputContentFile.java b/sm-core/src/main/java/com/salesmanager/core/business/content/model/InputContentFile.java
new file mode 100644
index 0000000..4cd71bc
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/content/model/InputContentFile.java
@@ -0,0 +1,26 @@
+package com.salesmanager.core.business.content.model;
+
+import java.io.InputStream;
+import java.io.Serializable;
+
+
+public class InputContentFile extends StaticContentFile implements Serializable
+{
+
+ private static final long serialVersionUID = 1L;
+
+ private InputStream file;
+
+
+ public InputStream getFile()
+ {
+ return file;
+ }
+ public void setFile( InputStream file )
+ {
+ this.file = file;
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/content/model/OutputContentFile.java b/sm-core/src/main/java/com/salesmanager/core/business/content/model/OutputContentFile.java
new file mode 100644
index 0000000..cd4bbe1
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/content/model/OutputContentFile.java
@@ -0,0 +1,26 @@
+package com.salesmanager.core.business.content.model;
+
+import java.io.ByteArrayOutputStream;
+import java.io.Serializable;
+
+/**
+ * Data class responsible for carrying out static content data from Infispan cache to
+ * service layer.
+ *
+ * @author Umesh Awasthi
+ * @since 1.2
+ */
+public class OutputContentFile extends StaticContentFile implements Serializable
+{
+ private static final long serialVersionUID = 1L;
+ private ByteArrayOutputStream file;
+ public ByteArrayOutputStream getFile()
+ {
+ return file;
+ }
+ public void setFile( ByteArrayOutputStream file )
+ {
+ this.file = file;
+ }
+
+}
\ No newline at end of file
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/content/model/StaticContentFile.java b/sm-core/src/main/java/com/salesmanager/core/business/content/model/StaticContentFile.java
new file mode 100644
index 0000000..975116c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/content/model/StaticContentFile.java
@@ -0,0 +1,18 @@
+package com.salesmanager.core.business.content.model;
+
+public abstract class StaticContentFile extends ContentFile {
+
+ private FileContentType fileContentType;
+
+ public FileContentType getFileContentType() {
+ return fileContentType;
+ }
+
+ public void setFileContentType(FileContentType fileContentType) {
+ this.fileContentType = fileContentType;
+ }
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/content/service/ContentService.java b/sm-core/src/main/java/com/salesmanager/core/business/content/service/ContentService.java
new file mode 100755
index 0000000..77d1412
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/content/service/ContentService.java
@@ -0,0 +1,149 @@
+package com.salesmanager.core.business.content.service;
+
+import java.util.List;
+
+import com.salesmanager.core.business.content.model.Content;
+import com.salesmanager.core.business.content.model.ContentDescription;
+import com.salesmanager.core.business.content.model.ContentType;
+import com.salesmanager.core.business.content.model.FileContentType;
+import com.salesmanager.core.business.content.model.InputContentFile;
+import com.salesmanager.core.business.content.model.OutputContentFile;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+
+
+/**
+ *
+ * Interface defining methods responsible for CMSContentService.
+ * ContentServive will be be entry point for CMS and take care of following functionalities.
+ * <li>Adding,removing Content images for given merchant store</li>
+ * <li>Get,Save,Update Content data for given merchant store</li>
+ *
+ * @author Umesh Awasthhi
+ *
+ */
+public interface ContentService
+ extends SalesManagerEntityService<Long, Content>
+{
+
+ public List<Content> listByType( ContentType contentType, MerchantStore store, Language language )
+ throws ServiceException;
+
+ public List<Content> listByType( List<ContentType> contentType, MerchantStore store, Language language )
+ throws ServiceException;
+
+ Content getByCode( String code, MerchantStore store )
+ throws ServiceException;
+
+ void saveOrUpdate( Content content )
+ throws ServiceException;
+
+ Content getByCode( String code, MerchantStore store, Language language )
+ throws ServiceException;
+
+ /**
+ * Method responsible for storing content file for given Store.Files for given merchant store will be stored in
+ * Infinispan.
+ *
+ * @param merchantStoreCode merchant store whose content images are being saved.
+ * @param contentFile content image being stored
+ * @throws ServiceException
+ */
+ void addContentFile( String merchantStoreCode, InputContentFile contentFile )
+ throws ServiceException;
+
+
+ /**
+ * Method responsible for storing list of content image for given Store.Images for given merchant store will be stored in
+ * Infinispan.
+ *
+ * @param merchantStoreCode merchant store whose content images are being saved.
+ * @param contentImagesList list of content images being stored.
+ * @throws ServiceException
+ */
+ void addContentFiles(String merchantStoreCode,List<InputContentFile> contentFilesList) throws ServiceException;
+
+
+ /**
+ * Method to remove given content image.Images are stored in underlying system based on there name.
+ * Name will be used to search given image for removal
+ * @param imageContentType
+ * @param imageName
+ * @param merchantStoreCode merchant store code
+ * @throws ServiceException
+ */
+ public void removeFile( String merchantStoreCode, FileContentType fileContentType, String fileName) throws ServiceException;
+
+
+ /**
+ * Method to remove all images for a given merchant.It will take merchant store as an input and will
+ * remove all images associated with given merchant store.
+ *
+ * @param merchantStoreCode
+ * @throws ServiceException
+ */
+ public void removeFiles( String merchantStoreCode ) throws ServiceException;
+
+ /**
+ * Method responsible for fetching particular content image for a given merchant store. Requested image will be
+ * search in Infinispan tree cache and OutputContentImage will be sent, in case no image is found null will
+ * returned.
+ *
+ * @param merchantStoreCode
+ * @param imageName
+ * @return {@link OutputContentImage}
+ * @throws ServiceException
+ */
+ public OutputContentFile getContentFile( String merchantStoreCode, FileContentType fileContentType, String fileName )
+ throws ServiceException;
+
+
+ /**
+ * Method to get list of all images associated with a given merchant store.In case of no image method will return an empty list.
+ * @param merchantStoreCode
+ * @param imageContentType
+ * @return list of {@link OutputContentImage}
+ * @throws ServiceException
+ */
+ public List<OutputContentFile> getContentFiles( String merchantStoreCode, FileContentType fileContentType )
+ throws ServiceException;
+
+
+ List<String> getContentFilesNames(String merchantStoreCode,
+ FileContentType fileContentType) throws ServiceException;
+
+ /**
+ * Add the store logo
+ * @param merchantStoreCode
+ * @param cmsContentImage
+ * @throws ServiceException
+ */
+ void addLogo(String merchantStoreCode, InputContentFile cmsContentImage)
+ throws ServiceException;
+
+ /**
+ * Adds a property (option) image
+ * @param merchantStoreId
+ * @param cmsContentImage
+ * @throws ServiceException
+ */
+ void addOptionImage(String merchantStoreCode, InputContentFile cmsContentImage)
+ throws ServiceException;
+
+
+
+ List<Content> listByType(List<ContentType> contentType, MerchantStore store)
+ throws ServiceException;
+
+ List<ContentDescription> listNameByType(List<ContentType> contentType,
+ MerchantStore store, Language language) throws ServiceException;
+
+ Content getByLanguage(Long id, Language language) throws ServiceException;
+
+ ContentDescription getBySeUrl(MerchantStore store, String seUrl);
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/content/service/ContentServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/content/service/ContentServiceImpl.java
new file mode 100755
index 0000000..d8c53d3
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/content/service/ContentServiceImpl.java
@@ -0,0 +1,390 @@
+package com.salesmanager.core.business.content.service;
+
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.Assert;
+
+import com.salesmanager.core.business.content.dao.ContentDao;
+import com.salesmanager.core.business.content.model.Content;
+import com.salesmanager.core.business.content.model.ContentDescription;
+import com.salesmanager.core.business.content.model.ContentType;
+import com.salesmanager.core.business.content.model.FileContentType;
+import com.salesmanager.core.business.content.model.InputContentFile;
+import com.salesmanager.core.business.content.model.OutputContentFile;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.modules.cms.content.StaticContentFileManager;
+
+@Service( "contentService" )
+public class ContentServiceImpl
+ extends SalesManagerEntityServiceImpl<Long, Content>
+ implements ContentService
+{
+
+ private static final Logger LOG = LoggerFactory.getLogger( ContentServiceImpl.class );
+
+ private final ContentDao contentDao;
+
+ @Autowired
+ StaticContentFileManager staticContentFileManager;
+
+ @Autowired
+ StaticContentFileManager contentFileManager;
+
+ @Autowired
+ public ContentServiceImpl( final ContentDao contentDao )
+ {
+ super( contentDao );
+
+ this.contentDao = contentDao;
+ }
+
+ @Override
+ public List<Content> listByType( final ContentType contentType, final MerchantStore store, final Language language )
+ throws ServiceException
+ {
+
+ return contentDao.listByType( contentType, store, language );
+ }
+
+ @Override
+ public void delete(Content content) throws ServiceException {
+
+ Content c = this.getById(content.getId());
+ super.delete(c);
+
+
+ }
+
+ @Override
+ public Content getByLanguage(Long id, Language language) throws ServiceException {
+ return contentDao.getByLanguage(id, language);
+ }
+
+
+
+ @Override
+ public List<Content> listByType( final List<ContentType> contentType, final MerchantStore store, final Language language )
+ throws ServiceException
+ {
+
+
+ return contentDao.listByType( contentType, store, language );
+ }
+
+ @Override
+ public List<ContentDescription> listNameByType( final List<ContentType> contentType, final MerchantStore store, final Language language )
+ throws ServiceException
+ {
+
+
+ return contentDao.listNameByType(contentType, store, language);
+ }
+
+ @Override
+ public List<Content> listByType( final List<ContentType> contentType, final MerchantStore store )
+ throws ServiceException
+ {
+
+
+ return contentDao.listByType( contentType, store );
+ }
+
+ @Override
+ public Content getByCode( final String code, final MerchantStore store )
+ throws ServiceException
+ {
+
+ return contentDao.getByCode( code, store );
+
+ }
+
+ @Override
+ public Content getById( Long id ) {
+ return contentDao.getById(id);
+ }
+
+ @Override
+ public void saveOrUpdate( final Content content )
+ throws ServiceException
+ {
+
+ // save or update (persist and attach entities
+ if ( content.getId() != null && content.getId() > 0 )
+ {
+ super.update( content );
+ }
+ else
+ {
+ super.save( content );
+ }
+
+ }
+
+ @Override
+ public Content getByCode( final String code, final MerchantStore store, final Language language )
+ throws ServiceException
+ {
+ return contentDao.getByCode( code, store, language );
+ }
+
+ /**
+ * Method responsible for adding content file for given merchant store in underlying Infinispan tree
+ * cache. It will take {@link InputContentFile} and will store file for given merchant store according to its type.
+ * it can save an image or any type of file (pdf, css, js ...)
+ * @param merchantStoreCode Merchant store
+ * @param contentFile {@link InputContentFile} being stored
+ * @throws ServiceException service exception
+ */
+ @Override
+ public void addContentFile( final String merchantStoreCode, final InputContentFile contentFile )
+ throws ServiceException
+ {
+ Assert.notNull( merchantStoreCode, "Merchant store Id can not be null" );
+ Assert.notNull( contentFile, "InputContentFile image can not be null" );
+ Assert.notNull( contentFile.getFileContentType(), "InputContentFile.fileContentType can not be null" );
+
+ if(contentFile.getFileContentType().name().equals(FileContentType.IMAGE.name())
+ || contentFile.getFileContentType().name().equals(FileContentType.STATIC_FILE.name())) {
+ addFile(merchantStoreCode,contentFile);
+ } else {
+ addImage(merchantStoreCode,contentFile);
+ }
+
+
+
+ }
+
+ @Override
+ public void addLogo( final String merchantStoreCode, InputContentFile cmsContentImage )
+ throws ServiceException {
+
+
+ Assert.notNull( merchantStoreCode, "Merchant store Id can not be null" );
+ Assert.notNull( cmsContentImage, "CMSContent image can not be null" );
+
+
+ cmsContentImage.setFileContentType(FileContentType.LOGO);
+ addImage(merchantStoreCode,cmsContentImage);
+
+
+ }
+
+ @Override
+ public void addOptionImage( final String merchantStoreCode, InputContentFile cmsContentImage )
+ throws ServiceException {
+
+
+ Assert.notNull( merchantStoreCode, "Merchant store Id can not be null" );
+ Assert.notNull( cmsContentImage, "CMSContent image can not be null" );
+ cmsContentImage.setFileContentType(FileContentType.PROPERTY);
+ addImage(merchantStoreCode,cmsContentImage);
+
+
+ }
+
+
+ private void addImage(final String merchantStoreCode, InputContentFile contentImage ) throws ServiceException {
+
+ try
+ {
+ LOG.info( "Adding content image for merchant id {}", merchantStoreCode);
+ contentFileManager.addFile( merchantStoreCode, contentImage );
+
+ } catch ( Exception e )
+ {
+ LOG.error( "Error while trying to convert input stream to buffered image", e );
+ throw new ServiceException( e );
+
+ } finally {
+
+ try {
+ if(contentImage.getFile()!=null) {
+ contentImage.getFile().close();
+ }
+ } catch (Exception ignore) {}
+
+ }
+
+ }
+
+ private void addFile(final String merchantStoreCode, InputContentFile contentImage ) throws ServiceException {
+
+ try
+ {
+ LOG.info( "Adding content file for merchant id {}", merchantStoreCode);
+ staticContentFileManager.addFile(merchantStoreCode, contentImage);
+
+ } catch ( Exception e )
+ {
+ LOG.error( "Error while trying to convert input stream to buffered image", e );
+ throw new ServiceException( e );
+
+ } finally {
+
+ try {
+ if(contentImage.getFile()!=null) {
+ contentImage.getFile().close();
+ }
+ } catch (Exception ignore) {}
+ }
+
+ }
+
+
+
+ /**
+ * Method responsible for adding list of content images for given merchant store in underlying Infinispan tree
+ * cache. It will take list of {@link CMSContentImage} and will store them for given merchant store.
+ *
+ * @param merchantStoreCode Merchant store
+ * @param contentImagesList list of {@link CMSContentImage} being stored
+ * @throws ServiceException service exception
+ */
+ @Override
+ public void addContentFiles(String merchantStoreCode,
+ List<InputContentFile> contentFilesList) throws ServiceException {
+
+ Assert.notNull( merchantStoreCode, "Merchant store ID can not be null" );
+ Assert.notEmpty( contentFilesList, "File list can not be empty" );
+ LOG.info( "Adding total {} images for given merchant",contentFilesList.size() );
+
+ LOG.info( "Adding content images for merchant...." );
+ //contentFileManager.addImages( merchantStoreCode, contentImagesList );
+ staticContentFileManager.addFiles(merchantStoreCode, contentFilesList);
+
+ try {
+ for(InputContentFile file : contentFilesList) {
+ if(file.getFile()!=null) {
+ file.getFile().close();
+ }
+ }
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+ }
+
+ /**
+ * Method to remove given content image.Images are stored in underlying system based on there name.
+ * Name will be used to search given image for removal
+ * @param contentImage
+ * @param merchantStoreCode merchant store
+ * @throws ServiceException
+ */
+ @Override
+ public void removeFile(String merchantStoreCode,
+ FileContentType fileContentType, String fileName)
+ throws ServiceException {
+ Assert.notNull( merchantStoreCode, "Merchant Store Id can not be null" );
+ Assert.notNull( fileContentType, "Content file type can not be null" );
+ Assert.notNull( fileName, "Content Image type can not be null" );
+
+
+ //check where to remove the file
+ if(fileContentType.name().equals(FileContentType.IMAGE.name())
+ || fileContentType.name().equals(FileContentType.STATIC_FILE.name())) {
+ staticContentFileManager.removeFile(merchantStoreCode, fileContentType, fileName);
+ } else {
+ contentFileManager.removeFile( merchantStoreCode, fileContentType, fileName );
+ }
+
+ }
+
+ /**
+ * Method to remove all images for a given merchant.It will take merchant store as an input and will
+ * remove all images associated with given merchant store.
+ *
+ * @param merchantStoreCode
+ * @throws ServiceException
+ */
+ @Override
+ public void removeFiles(String merchantStoreCode) throws ServiceException {
+ Assert.notNull( merchantStoreCode, "Merchant Store Id can not be null" );
+
+
+
+ contentFileManager.removeFiles( merchantStoreCode );
+ staticContentFileManager.removeFiles(merchantStoreCode);
+
+ }
+
+
+ /**
+ * Implementation for getContentImage method defined in {@link ContentService} interface. Methods will return
+ * Content image with given image name for the Merchant store or will return null if no image with given name found
+ * for requested Merchant Store in Infinispan tree cache.
+ *
+ * @param store Merchant merchantStoreCode
+ * @param imageName name of requested image
+ * @return {@link OutputContentImage}
+ * @throws ServiceException
+ */
+ @Override
+ public OutputContentFile getContentFile(String merchantStoreCode,
+ FileContentType fileContentType, String fileName)
+ throws ServiceException {
+ Assert.notNull( merchantStoreCode, "Merchant store ID can not be null" );
+ Assert.notNull( fileName, "File name can not be null" );
+
+ if(fileContentType.name().equals(FileContentType.IMAGE.name())
+ || fileContentType.name().equals(FileContentType.STATIC_FILE.name())) {
+ return staticContentFileManager.getFile(merchantStoreCode, fileContentType, fileName);
+
+ } else {
+ return contentFileManager.getFile( merchantStoreCode, fileContentType, fileName );
+ }
+
+
+ }
+
+ /**
+ * Implementation for getContentImages method defined in {@link ContentService} interface. Methods will return list of all
+ * Content image associated with given Merchant store or will return empty list if no image is associated with
+ * given Merchant Store in Infinispan tree cache.
+ *
+ * @param merchantStoreId Merchant store
+ * @return list of {@link OutputContentImage}
+ * @throws ServiceException
+ */
+ @Override
+ public List<OutputContentFile> getContentFiles(String merchantStoreCode,
+ FileContentType fileContentType) throws ServiceException {
+ Assert.notNull( merchantStoreCode, "Merchant store Id can not be null" );
+ return staticContentFileManager.getFiles(merchantStoreCode, fileContentType);
+ }
+
+ /**
+ * Returns the image names for a given merchant and store
+ * @param merchantStoreCode
+ * @param imageContentType
+ * @return images name list
+ * @throws ServiceException
+ */
+ @Override
+ public List<String> getContentFilesNames(String merchantStoreCode,
+ FileContentType fileContentType) throws ServiceException {
+ Assert.notNull( merchantStoreCode, "Merchant store Id can not be null" );
+
+ if(fileContentType.name().equals(FileContentType.IMAGE.name())
+ || fileContentType.name().equals(FileContentType.STATIC_FILE.name())) {
+ return staticContentFileManager.getFileNames(merchantStoreCode, fileContentType);
+ } else {
+ return contentFileManager.getFileNames(merchantStoreCode, fileContentType);
+ }
+ }
+
+ @Override
+ public ContentDescription getBySeUrl(MerchantStore store,String seUrl) {
+ return contentDao.getBySeUrl(store, seUrl);
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/CustomerRegistrationException.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/CustomerRegistrationException.java
new file mode 100644
index 0000000..2fce46a
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/CustomerRegistrationException.java
@@ -0,0 +1,33 @@
+package com.salesmanager.core.business.customer;
+
+
+
+/**
+ * <p>Exception thrown when system able register customer
+ * </p>
+ *
+ * @author Umesh Awasthi
+ * @since 1.2
+ *
+ */
+public class CustomerRegistrationException extends Exception
+{
+
+ private static final long serialVersionUID = 879320340641131133L;
+
+ public CustomerRegistrationException(final String msg, final Throwable cause)
+ {
+ super(msg, cause);
+ }
+
+ public CustomerRegistrationException(final String msg)
+ {
+ super(msg);
+ }
+
+ public CustomerRegistrationException(Throwable t)
+ {
+ super(t);
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerAttributeDao.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerAttributeDao.java
new file mode 100644
index 0000000..cd3df64
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerAttributeDao.java
@@ -0,0 +1,21 @@
+package com.salesmanager.core.business.customer.dao.attribute;
+
+import java.util.List;
+
+import com.salesmanager.core.business.customer.model.attribute.CustomerAttribute;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+
+public interface CustomerAttributeDao extends SalesManagerEntityDao<Long, CustomerAttribute> {
+
+ CustomerAttribute getByOptionId(MerchantStore store, Long customerId, Long id);
+
+ List<CustomerAttribute> getByOptionValueId(MerchantStore store, Long id);
+
+ List<CustomerAttribute> getByOptionId(MerchantStore store, Long id);
+
+ List<CustomerAttribute> getByCustomerId(MerchantStore store, Long customerId);
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerAttributeDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerAttributeDaoImpl.java
new file mode 100644
index 0000000..dea06d2
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerAttributeDaoImpl.java
@@ -0,0 +1,140 @@
+package com.salesmanager.core.business.customer.dao.attribute;
+
+import java.util.List;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.customer.model.QCustomer;
+import com.salesmanager.core.business.customer.model.attribute.CustomerAttribute;
+import com.salesmanager.core.business.customer.model.attribute.QCustomerAttribute;
+import com.salesmanager.core.business.customer.model.attribute.QCustomerOption;
+import com.salesmanager.core.business.customer.model.attribute.QCustomerOptionValue;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+
+@Repository("customerAttributeDao")
+public class CustomerAttributeDaoImpl extends SalesManagerEntityDaoImpl<Long, CustomerAttribute>
+ implements CustomerAttributeDao {
+
+
+ @Override
+ public CustomerAttribute getById(Long id) {
+ QCustomerAttribute qCustomerAttribute = QCustomerAttribute.customerAttribute;
+ QCustomerOption qCustomerOption = QCustomerOption.customerOption;
+ QCustomerOptionValue qCustomerOptionValue = QCustomerOptionValue.customerOptionValue;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCustomerAttribute)
+ .join(qCustomerAttribute.customer).fetch()
+ .leftJoin(qCustomerAttribute.customerOption, qCustomerOption).fetch()
+ .leftJoin(qCustomerAttribute.customerOptionValue, qCustomerOptionValue).fetch()
+ .leftJoin(qCustomerOption.descriptions).fetch()
+ .leftJoin(qCustomerOptionValue.descriptions).fetch()
+ .where(qCustomerAttribute.id.eq(id));
+
+ return query.uniqueResult(qCustomerAttribute);
+
+ }
+
+ @Override
+ public CustomerAttribute getByOptionId(MerchantStore store, Long customerId, Long id) {
+ QCustomerAttribute qCustomerAttribute = QCustomerAttribute.customerAttribute;
+ QCustomerOption qCustomerOption = QCustomerOption.customerOption;
+ QCustomer qCustomer = QCustomer.customer;
+ QCustomerOptionValue qCustomerOptionValue = QCustomerOptionValue.customerOptionValue;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCustomerAttribute)
+ .join(qCustomerAttribute.customer,qCustomer).fetch()
+ .leftJoin(qCustomerAttribute.customerOption, qCustomerOption).fetch()
+ .leftJoin(qCustomerAttribute.customerOptionValue, qCustomerOptionValue).fetch()
+ .leftJoin(qCustomerOption.descriptions).fetch()
+ .leftJoin(qCustomerOptionValue.descriptions).fetch()
+ .where(qCustomerOption.merchantStore.id.eq(store.getId())
+ .and(qCustomerOption.id.eq(id))
+ .and(qCustomer.id.eq(customerId)));
+
+
+ return query.uniqueResult(qCustomerAttribute);
+ }
+
+ @Override
+ public List<CustomerAttribute> getByCustomerId(MerchantStore store, Long customerId) {
+ QCustomerAttribute qCustomerAttribute = QCustomerAttribute.customerAttribute;
+ QCustomerOption qCustomerOption = QCustomerOption.customerOption;
+ QCustomer qCustomer = QCustomer.customer;
+ QCustomerOptionValue qCustomerOptionValue = QCustomerOptionValue.customerOptionValue;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+
+ query.from(qCustomerAttribute)
+ .join(qCustomerAttribute.customer,qCustomer).fetch()
+ .leftJoin(qCustomerAttribute.customerOption, qCustomerOption).fetch()
+ .leftJoin(qCustomerAttribute.customerOptionValue, qCustomerOptionValue).fetch()
+ .leftJoin(qCustomerOption.descriptions).fetch()
+ .leftJoin(qCustomerOptionValue.descriptions).fetch()
+ .where(qCustomerOption.merchantStore.id.eq(store.getId())
+ .and(qCustomer.id.eq(customerId)));
+
+ System.out.println("done");
+
+ return query.listDistinct(qCustomerAttribute);
+ }
+
+ @Override
+ public List<CustomerAttribute> getByOptionValueId(MerchantStore store, Long id) {
+ QCustomerAttribute qCustomerAttribute = QCustomerAttribute.customerAttribute;
+ QCustomerOption qCustomerOption = QCustomerOption.customerOption;
+ QCustomerOptionValue qCustomerOptionValue = QCustomerOptionValue.customerOptionValue;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCustomerAttribute)
+ .join(qCustomerAttribute.customer).fetch()
+ .leftJoin(qCustomerAttribute.customerOption, qCustomerOption).fetch()
+ .leftJoin(qCustomerAttribute.customerOptionValue, qCustomerOptionValue).fetch()
+ .leftJoin(qCustomerOption.descriptions).fetch()
+ .leftJoin(qCustomerOptionValue.descriptions).fetch()
+ .where(qCustomerOptionValue.merchantStore.id.eq(store.getId())
+ .and(qCustomerOptionValue.id.eq(id)));
+
+
+ return query.list(qCustomerAttribute);
+ }
+
+ @Override
+ public List<CustomerAttribute> getByOptionId(MerchantStore store, Long id) {
+ QCustomerAttribute qCustomerAttribute = QCustomerAttribute.customerAttribute;
+ QCustomerOption qCustomerOption = QCustomerOption.customerOption;
+ QCustomerOptionValue qCustomerOptionValue = QCustomerOptionValue.customerOptionValue;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCustomerAttribute)
+ .join(qCustomerAttribute.customer).fetch()
+ .leftJoin(qCustomerAttribute.customerOption, qCustomerOption).fetch()
+ .leftJoin(qCustomerAttribute.customerOptionValue, qCustomerOptionValue).fetch()
+ .leftJoin(qCustomerOption.descriptions).fetch()
+ .leftJoin(qCustomerOptionValue.descriptions).fetch()
+ .where(qCustomerOptionValue.merchantStore.id.eq(store.getId())
+ .and(qCustomerOption.id.eq(id)));
+
+
+ return query.list(qCustomerAttribute);
+ }
+
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionDao.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionDao.java
new file mode 100644
index 0000000..1dc0ed9
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionDao.java
@@ -0,0 +1,28 @@
+package com.salesmanager.core.business.customer.dao.attribute;
+
+import java.util.List;
+
+import com.salesmanager.core.business.customer.model.attribute.CustomerOption;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface CustomerOptionDao extends SalesManagerEntityDao<Long, CustomerOption> {
+
+ List<CustomerOption> listByStore(MerchantStore store, Language language);
+
+
+
+ void saveOrUpdate(CustomerOption entity) throws ServiceException;
+
+
+ /**
+ * Get a unique CustomerOption by code
+ * @param store
+ * @param optionCode
+ * @return
+ */
+ CustomerOption getByCode(MerchantStore store, String optionCode);
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionDaoImpl.java
new file mode 100644
index 0000000..312613a
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionDaoImpl.java
@@ -0,0 +1,107 @@
+package com.salesmanager.core.business.customer.dao.attribute;
+
+import java.util.List;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.customer.model.attribute.CustomerOption;
+import com.salesmanager.core.business.customer.model.attribute.QCustomerOption;
+import com.salesmanager.core.business.customer.model.attribute.QCustomerOptionDescription;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Repository("customerOptionDao")
+public class CustomerOptionDaoImpl extends SalesManagerEntityDaoImpl<Long, CustomerOption>
+ implements CustomerOptionDao {
+
+ @Override
+ public List<CustomerOption> listByStore(MerchantStore store, Language language) {
+
+
+ QCustomerOption qCustomerOption = QCustomerOption.customerOption;
+ QCustomerOptionDescription qCustomerOptionDescription = QCustomerOptionDescription.customerOptionDescription;
+
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCustomerOption)
+ .leftJoin(qCustomerOption.descriptions, qCustomerOptionDescription).fetch()
+ .leftJoin(qCustomerOption.merchantStore).fetch()
+ .where(qCustomerOption.merchantStore.id.eq(store.getId())
+ .and(qCustomerOptionDescription.language.id.eq(language.getId())))
+ .orderBy(qCustomerOption.sortOrder.asc());
+
+ return query.listDistinct(qCustomerOption);
+
+ }
+
+ @Override
+ public CustomerOption getById(Long id) {
+
+
+ QCustomerOption qCustomerOption = QCustomerOption.customerOption;
+ QCustomerOptionDescription qCustomerOptionDescription = QCustomerOptionDescription.customerOptionDescription;
+
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCustomerOption)
+ .leftJoin(qCustomerOption.descriptions, qCustomerOptionDescription).fetch()
+ .leftJoin(qCustomerOption.merchantStore).fetch()
+ .where(qCustomerOption.id.eq(id));
+
+ return query.uniqueResult(qCustomerOption);
+
+
+
+ }
+
+ @Override
+ public CustomerOption getByCode(MerchantStore store, String optionCode) {
+
+
+ QCustomerOption qCustomerOption = QCustomerOption.customerOption;
+ QCustomerOptionDescription qCustomerOptionDescription = QCustomerOptionDescription.customerOptionDescription;
+
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCustomerOption)
+ .leftJoin(qCustomerOption.descriptions, qCustomerOptionDescription).fetch()
+ .leftJoin(qCustomerOption.merchantStore).fetch()
+ .where(qCustomerOption.merchantStore.id.eq(store.getId())
+ .and(qCustomerOption.code.eq(optionCode)));
+
+ return query.uniqueResult(qCustomerOption);
+
+
+
+ }
+
+
+
+ @Override
+ public void saveOrUpdate(CustomerOption entity) throws ServiceException {
+
+ if(entity.getId()!=null && entity.getId()>0) {
+
+ super.update(entity);
+
+ } else {
+
+ super.save(entity);
+
+ }
+
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionSetDao.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionSetDao.java
new file mode 100644
index 0000000..0f1f9f5
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionSetDao.java
@@ -0,0 +1,26 @@
+package com.salesmanager.core.business.customer.dao.attribute;
+
+import java.util.List;
+
+import com.salesmanager.core.business.customer.model.attribute.CustomerOptionSet;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface CustomerOptionSetDao extends SalesManagerEntityDao<Long, CustomerOptionSet> {
+
+ List<CustomerOptionSet> getByOptionId(MerchantStore store, Long id);
+
+ List<CustomerOptionSet> listByStore(MerchantStore store, Language language);
+
+ CustomerOptionSet getById(Long customerOptionSetId);
+
+ List<CustomerOptionSet> getByOptionValueId(MerchantStore store, Long id);
+
+
+
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionSetDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionSetDaoImpl.java
new file mode 100644
index 0000000..8079ce9
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionSetDaoImpl.java
@@ -0,0 +1,150 @@
+package com.salesmanager.core.business.customer.dao.attribute;
+
+import java.util.List;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.customer.model.attribute.CustomerOptionSet;
+import com.salesmanager.core.business.customer.model.attribute.QCustomerOption;
+import com.salesmanager.core.business.customer.model.attribute.QCustomerOptionDescription;
+import com.salesmanager.core.business.customer.model.attribute.QCustomerOptionSet;
+import com.salesmanager.core.business.customer.model.attribute.QCustomerOptionValue;
+import com.salesmanager.core.business.customer.model.attribute.QCustomerOptionValueDescription;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Repository("customerOptionSetDao")
+public class CustomerOptionSetDaoImpl extends SalesManagerEntityDaoImpl<Long, CustomerOptionSet> implements CustomerOptionSetDao {
+
+
+ @Override
+ public CustomerOptionSet getById(Long customerOptionSetId) {
+ QCustomerOptionSet qCustomerOptionSet= QCustomerOptionSet.customerOptionSet;
+ QCustomerOption qCustomerOption = QCustomerOption.customerOption;
+ QCustomerOptionValue qCustomerOptionValue = QCustomerOptionValue.customerOptionValue;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCustomerOptionSet)
+ .join(qCustomerOptionSet.customerOption,qCustomerOption).fetch()
+ .join(qCustomerOptionSet.customerOptionValue,qCustomerOptionValue).fetch()
+ .join(qCustomerOption.merchantStore).fetch()
+ .join(qCustomerOptionValue.merchantStore).fetch()
+ .leftJoin(qCustomerOption.descriptions).fetch()
+ .leftJoin(qCustomerOptionValue.descriptions).fetch()
+ .where(qCustomerOptionSet.id.eq(customerOptionSetId)
+ );
+
+ return query.uniqueResult(qCustomerOptionSet);
+
+
+ }
+
+ @Override
+ public List<CustomerOptionSet> getByOptionId(MerchantStore store, Long id) {
+ QCustomerOptionSet qCustomerOptionSet= QCustomerOptionSet.customerOptionSet;
+ QCustomerOption qCustomerOption = QCustomerOption.customerOption;
+ QCustomerOptionValue qCustomerOptionValue = QCustomerOptionValue.customerOptionValue;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCustomerOptionSet)
+ .join(qCustomerOptionSet.customerOption,qCustomerOption).fetch()
+ .join(qCustomerOption.merchantStore).fetch()
+ .join(qCustomerOptionSet.customerOptionValue,qCustomerOptionValue).fetch()
+ .join(qCustomerOptionValue.merchantStore).fetch()
+ .leftJoin(qCustomerOption.descriptions).fetch()
+ .leftJoin(qCustomerOptionValue.descriptions).fetch()
+ .where(qCustomerOption.id.eq(id)
+ .and(qCustomerOption.merchantStore.id.eq(store.getId())));
+
+
+ return query.list(qCustomerOptionSet);
+ }
+
+ @Override
+ public List<CustomerOptionSet> getByOptionValueId(MerchantStore store, Long id) {
+ QCustomerOptionSet qCustomerOptionSet= QCustomerOptionSet.customerOptionSet;
+ QCustomerOption qCustomerOption = QCustomerOption.customerOption;
+ QCustomerOptionValue qCustomerOptionValue = QCustomerOptionValue.customerOptionValue;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCustomerOptionSet)
+ .join(qCustomerOptionSet.customerOption,qCustomerOption).fetch()
+ .join(qCustomerOption.merchantStore).fetch()
+ .join(qCustomerOptionSet.customerOptionValue,qCustomerOptionValue).fetch()
+ .join(qCustomerOptionValue.merchantStore).fetch()
+ .leftJoin(qCustomerOption.descriptions).fetch()
+ .leftJoin(qCustomerOptionValue.descriptions).fetch()
+ .where(qCustomerOptionValue.id.eq(id)
+ .and(qCustomerOption.merchantStore.id.eq(store.getId())));
+
+
+ return query.list(qCustomerOptionSet);
+ }
+
+ @Override
+ public List<CustomerOptionSet> listByStore(MerchantStore store, Language language) {
+
+
+ QCustomerOptionSet qCustomerOptionSet= QCustomerOptionSet.customerOptionSet;
+ QCustomerOption qCustomerOption = QCustomerOption.customerOption;
+ QCustomerOptionDescription qCustomerOptionDescription = QCustomerOptionDescription.customerOptionDescription;
+ QCustomerOptionValue qCustomerOptionValue = QCustomerOptionValue.customerOptionValue;
+ QCustomerOptionValueDescription qCustomerOptionValueDescription = QCustomerOptionValueDescription.customerOptionValueDescription;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCustomerOptionSet)
+ .join(qCustomerOptionSet.customerOption,qCustomerOption).fetch()
+ .join(qCustomerOptionSet.customerOptionValue,qCustomerOptionValue).fetch()
+ .leftJoin(qCustomerOption.descriptions,qCustomerOptionDescription).fetch()
+ .leftJoin(qCustomerOptionValue.descriptions,qCustomerOptionValueDescription).fetch()
+ .where(qCustomerOption.merchantStore.id.eq(store.getId())
+ .and(qCustomerOptionDescription.language.id.eq(language.getId()))
+ .and(qCustomerOptionValueDescription.language.id.eq(language.getId()))
+ ).orderBy(qCustomerOptionSet.sortOrder.asc());
+
+
+ return query.list(qCustomerOptionSet);
+
+
+
+/* StringBuilder qs = new StringBuilder();
+ qs.append("select distinct cos from CustomerOptionSet as cos ");
+ qs.append("join fetch cos.customerOption po ");
+ qs.append("join fetch cos.customerOptionValue ov ");
+ qs.append("join fetch po.merchantStore pm ");
+ qs.append("left join fetch po.descriptions pop ");
+ qs.append("left join fetch ov.descriptions ovd ");
+ qs.append("where pm.id =:mid ");
+ qs.append("and pop.language.id =:lid ");
+ qs.append("and ovd.language.id =:lid ");
+ qs.append("order by cos.sortOrder asc");
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+
+ q.setParameter("mid", store.getId());
+ q.setParameter("lid", language.getId());
+
+
+ @SuppressWarnings("unchecked")
+ List<CustomerOptionSet> returnList = q.getResultList();
+ return returnList;*/
+ }
+
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionValueDao.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionValueDao.java
new file mode 100644
index 0000000..d7b9753
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionValueDao.java
@@ -0,0 +1,18 @@
+package com.salesmanager.core.business.customer.dao.attribute;
+
+import java.util.List;
+
+import com.salesmanager.core.business.customer.model.attribute.CustomerOptionValue;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface CustomerOptionValueDao extends SalesManagerEntityDao<Long, CustomerOptionValue> {
+
+ List<CustomerOptionValue> listByStore(MerchantStore store, Language language);
+
+ CustomerOptionValue getByCode(MerchantStore store, String optionValueCode);
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionValueDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionValueDaoImpl.java
new file mode 100644
index 0000000..88c1bbe
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/attribute/CustomerOptionValueDaoImpl.java
@@ -0,0 +1,92 @@
+package com.salesmanager.core.business.customer.dao.attribute;
+
+import java.util.List;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.customer.model.attribute.CustomerOptionValue;
+import com.salesmanager.core.business.customer.model.attribute.QCustomerOptionValue;
+import com.salesmanager.core.business.customer.model.attribute.QCustomerOptionValueDescription;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Repository("customerOptionValueDao")
+public class CustomerOptionValueDaoImpl extends SalesManagerEntityDaoImpl<Long, CustomerOptionValue>
+ implements CustomerOptionValueDao {
+
+
+ @Override
+ public List<CustomerOptionValue> listByStore(MerchantStore store, Language language) {
+
+
+ QCustomerOptionValue qCustomerOptionValue = QCustomerOptionValue.customerOptionValue;
+ QCustomerOptionValueDescription qCustomerOptionValueDescription = QCustomerOptionValueDescription.customerOptionValueDescription;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCustomerOptionValue)
+ .leftJoin(qCustomerOptionValue.descriptions, qCustomerOptionValueDescription).fetch()
+ .leftJoin(qCustomerOptionValue.merchantStore).fetch()
+ .where(qCustomerOptionValue.merchantStore.id.eq(store.getId())
+ .and(qCustomerOptionValueDescription.language.id.eq(language.getId())))
+ .orderBy(qCustomerOptionValue.sortOrder.asc());
+
+ return query.listDistinct(qCustomerOptionValue);
+
+
+ }
+
+
+
+
+
+ @Override
+ public CustomerOptionValue getById(Long id) {
+
+
+
+ QCustomerOptionValue qCustomerOptionValue = QCustomerOptionValue.customerOptionValue;
+ QCustomerOptionValueDescription qCustomerOptionValueDescription = QCustomerOptionValueDescription.customerOptionValueDescription;
+
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCustomerOptionValue)
+ .leftJoin(qCustomerOptionValue.descriptions, qCustomerOptionValueDescription).fetch()
+ .leftJoin(qCustomerOptionValue.merchantStore).fetch()
+ .where(qCustomerOptionValue.id.eq(id));
+
+ return query.uniqueResult(qCustomerOptionValue);
+
+ }
+
+ @Override
+ public CustomerOptionValue getByCode(MerchantStore store, String optionValueCode) {
+
+
+
+ QCustomerOptionValue qCustomerOptionValue = QCustomerOptionValue.customerOptionValue;
+ QCustomerOptionValueDescription qCustomerOptionValueDescription = QCustomerOptionValueDescription.customerOptionValueDescription;
+
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCustomerOptionValue)
+ .leftJoin(qCustomerOptionValue.descriptions, qCustomerOptionValueDescription).fetch()
+ .leftJoin(qCustomerOptionValue.merchantStore).fetch()
+ .where(qCustomerOptionValue.merchantStore.id.eq(store.getId())
+ .and(qCustomerOptionValue.code.eq(optionValueCode)));
+
+ return query.uniqueResult(qCustomerOptionValue);
+
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/CustomerDAO.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/CustomerDAO.java
new file mode 100644
index 0000000..3688b10
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/CustomerDAO.java
@@ -0,0 +1,24 @@
+package com.salesmanager.core.business.customer.dao;
+
+import java.util.List;
+
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.customer.model.CustomerCriteria;
+import com.salesmanager.core.business.customer.model.CustomerList;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+
+public interface CustomerDAO extends SalesManagerEntityDao<Long, Customer> {
+
+ public List<Customer> getByName(String name);
+
+ List<Customer> listByStore(MerchantStore store);
+
+ Customer getByNick(String nick);
+
+ CustomerList listByStore(MerchantStore store, CustomerCriteria criteria);
+
+ Customer getByNick(String nick, int storeId);
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/CustomerDAOImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/CustomerDAOImpl.java
new file mode 100644
index 0000000..69aa086
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/dao/CustomerDAOImpl.java
@@ -0,0 +1,332 @@
+package com.salesmanager.core.business.customer.dao;
+
+import java.util.List;
+
+import javax.persistence.NoResultException;
+import javax.persistence.Query;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.BooleanBuilder;
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.customer.model.CustomerCriteria;
+import com.salesmanager.core.business.customer.model.CustomerList;
+import com.salesmanager.core.business.customer.model.QCustomer;
+import com.salesmanager.core.business.customer.model.attribute.QCustomerAttribute;
+import com.salesmanager.core.business.customer.model.attribute.QCustomerOption;
+import com.salesmanager.core.business.customer.model.attribute.QCustomerOptionValue;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.merchant.model.QMerchantStore;
+import com.salesmanager.core.business.reference.country.model.QCountry;
+import com.salesmanager.core.business.reference.zone.model.QZone;
+
+@Repository("customerDao")
+public class CustomerDAOImpl extends SalesManagerEntityDaoImpl<Long, Customer> implements CustomerDAO {
+
+ public CustomerDAOImpl() {
+ super();
+ }
+
+
+ @Override
+ public Customer getById(Long id){
+ QCustomer qCustomer = QCustomer.customer;
+ QCountry qCountry = QCountry.country;
+ QZone qZone = QZone.zone;
+ QCustomerAttribute qCustomerAttribute = QCustomerAttribute.customerAttribute;
+ QCustomerOption qCustomerOption = QCustomerOption.customerOption;
+ QCustomerOptionValue qCustomerOptionValue = QCustomerOptionValue.customerOptionValue;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCustomer)
+ .join(qCustomer.merchantStore).fetch()
+ //.leftJoin(qCustomer.billing.country,qCountry).fetch()
+ //.leftJoin(qCustomer.billing.zone,qZone).fetch()
+ .leftJoin(qCustomer.defaultLanguage).fetch()
+ .leftJoin(qCustomer.attributes,qCustomerAttribute).fetch()
+ .leftJoin(qCustomerAttribute.customerOption, qCustomerOption).fetch()
+ .leftJoin(qCustomerAttribute.customerOptionValue, qCustomerOptionValue).fetch()
+ .leftJoin(qCustomerOption.descriptions).fetch()
+ .leftJoin(qCustomerOptionValue.descriptions).fetch()
+ .where(qCustomer.id.eq(id));
+
+ return query.uniqueResult(qCustomer);
+ }
+
+
+
+ @Override
+ public List<Customer> getByName(String name){
+ QCustomer qCustomer = QCustomer.customer;
+ QCountry qCountry = QCountry.country;
+ QZone qZone = QZone.zone;
+ QCustomerAttribute qCustomerAttribute = QCustomerAttribute.customerAttribute;
+ QCustomerOption qCustomerOption = QCustomerOption.customerOption;
+ QCustomerOptionValue qCustomerOptionValue = QCustomerOptionValue.customerOptionValue;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCustomer)
+ .join(qCustomer.merchantStore).fetch()
+ //.leftJoin(qCustomer.billing.country,qCountry).fetch()
+ //.leftJoin(qCustomer.billing.zone,qZone).fetch()
+ .leftJoin(qCustomer.defaultLanguage).fetch()
+ .leftJoin(qCustomer.attributes,qCustomerAttribute).fetch()
+ .leftJoin(qCustomerAttribute.customerOption, qCustomerOption).fetch()
+ .leftJoin(qCustomerAttribute.customerOptionValue, qCustomerOptionValue).fetch()
+ .leftJoin(qCustomerOption.descriptions).fetch()
+ .leftJoin(qCustomerOptionValue.descriptions).fetch()
+ .where(
+ qCustomer.billing.firstName.eq(name).or(qCustomer.billing.lastName.eq(name))
+
+ );
+
+ return query.list(qCustomer);
+ }
+
+ @Override
+ public CustomerList listByStore(MerchantStore store, CustomerCriteria criteria) {
+
+
+
+ CustomerList customerList = new CustomerList();
+ StringBuilder countBuilderSelect = new StringBuilder();
+ countBuilderSelect.append("select count(c) from Customer as c");
+
+ StringBuilder countBuilderWhere = new StringBuilder();
+ countBuilderWhere.append(" where c.merchantStore.id=:mId");
+
+ if(!StringUtils.isBlank(criteria.getName())) {
+ countBuilderWhere.append(" and c.billing.firstName like:nm");
+ countBuilderWhere.append(" or c.billing.lastName like:nm");
+ }
+
+ if(!StringUtils.isBlank(criteria.getFirstName())) {
+ countBuilderWhere.append(" and c..billing.firstName like:fn");
+ }
+
+ if(!StringUtils.isBlank(criteria.getLastName())) {
+ countBuilderWhere.append(" and c.billing.lastName like:ln");
+ }
+
+ if(!StringUtils.isBlank(criteria.getEmail())) {
+ countBuilderWhere.append(" and c.emailAddress like:email");
+ }
+
+ if(!StringUtils.isBlank(criteria.getCountry())) {
+ countBuilderWhere.append(" and c.billing.country.isoCode like:country");
+ }
+
+ Query countQ = super.getEntityManager().createQuery(
+ countBuilderSelect.toString() + countBuilderWhere.toString());
+
+ countQ.setParameter("mId", store.getId());
+
+
+ if(!StringUtils.isBlank(criteria.getName())) {
+ countQ.setParameter("nm",new StringBuilder().append("%").append(criteria.getName()).append("%").toString());
+ }
+
+ if(!StringUtils.isBlank(criteria.getFirstName())) {
+ countQ.setParameter("fn",new StringBuilder().append("%").append(criteria.getFirstName()).append("%").toString());
+ }
+
+ if(!StringUtils.isBlank(criteria.getLastName())) {
+ countQ.setParameter("ln",new StringBuilder().append("%").append(criteria.getLastName()).append("%").toString());
+ }
+
+ if(!StringUtils.isBlank(criteria.getEmail())) {
+ countQ.setParameter("email",new StringBuilder().append("%").append(criteria.getEmail()).append("%").toString());
+ }
+
+ if(!StringUtils.isBlank(criteria.getCountry())) {
+ countQ.setParameter("country",new StringBuilder().append("%").append(criteria.getCountry()).append("%").toString());
+ }
+
+
+
+ Number count = (Number) countQ.getSingleResult ();
+
+ customerList.setTotalCount(count.intValue());
+
+ if(count.intValue()==0)
+ return customerList;
+
+
+
+ QCustomer qCustomer = QCustomer.customer;
+ QCountry qCountry = QCountry.country;
+ QZone qZone = QZone.zone;
+ QCustomerAttribute qCustomerAttribute = QCustomerAttribute.customerAttribute;
+ QCustomerOption qCustomerOption = QCustomerOption.customerOption;
+ QCustomerOptionValue qCustomerOptionValue = QCustomerOptionValue.customerOptionValue;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCustomer)
+ .join(qCustomer.merchantStore).fetch()
+ .leftJoin(qCustomer.defaultLanguage).fetch()
+ .leftJoin(qCustomer.attributes,qCustomerAttribute).fetch()
+ .leftJoin(qCustomerAttribute.customerOption, qCustomerOption).fetch()
+ .leftJoin(qCustomerAttribute.customerOptionValue, qCustomerOptionValue).fetch()
+ .leftJoin(qCustomerOption.descriptions).fetch()
+ .leftJoin(qCustomerOptionValue.descriptions).fetch();
+
+ query.where(qCustomer.merchantStore.id.eq(store.getId()));
+ BooleanBuilder pBuilder = null;
+
+ if(!StringUtils.isBlank(criteria.getName())) {
+ if(pBuilder==null) {
+ pBuilder = new BooleanBuilder();
+ }
+ pBuilder.and(qCustomer.billing.firstName.like(new StringBuilder().append("%").append(criteria.getName()).append("%").toString())
+ .or(qCustomer.billing.lastName.like(new StringBuilder().append("%").append(criteria.getName()).append("%").toString())));
+
+ }
+
+
+ if(!StringUtils.isBlank(criteria.getFirstName())) {
+ if(pBuilder==null) {
+ pBuilder = new BooleanBuilder();
+ }
+ pBuilder.and(qCustomer.billing.firstName.like(new StringBuilder().append("%").append(criteria.getFirstName()).append("%").toString()));
+ }
+
+ if(!StringUtils.isBlank(criteria.getLastName())) {
+ if(pBuilder==null) {
+ pBuilder = new BooleanBuilder();
+ }
+ pBuilder.and(qCustomer.billing.lastName.like(new StringBuilder().append("%").append(criteria.getLastName()).append("%").toString()));
+ }
+
+ if(!StringUtils.isBlank(criteria.getEmail())) {
+ if(pBuilder==null) {
+ pBuilder = new BooleanBuilder();
+ }
+ pBuilder.and(qCustomer.emailAddress.like(new StringBuilder().append("%").append(criteria.getEmail()).append("%").toString()));
+ }
+
+ if(!StringUtils.isBlank(criteria.getCountry())) {
+ if(pBuilder==null) {
+ pBuilder = new BooleanBuilder();
+ }
+ pBuilder.and(qCustomer.billing.country.isoCode.like(new StringBuilder().append("%").append(criteria.getCountry()).append("%").toString()));
+ }
+
+ if(pBuilder!=null) {
+ query.where(pBuilder);
+ }
+
+
+
+ if(criteria.getMaxCount()>0) {
+ query.limit(criteria.getMaxCount());
+ query.offset(criteria.getStartIndex());
+ }
+
+
+ customerList.setCustomers(query.list(qCustomer));
+
+ return customerList;
+
+ }
+
+
+ @Override
+ public Customer getByNick(String nick){
+ QCustomer qCustomer = QCustomer.customer;
+ QCountry qCountry = QCountry.country;
+ QZone qZone = QZone.zone;
+ QCustomerAttribute qCustomerAttribute = QCustomerAttribute.customerAttribute;
+ QCustomerOption qCustomerOption = QCustomerOption.customerOption;
+ QCustomerOptionValue qCustomerOptionValue = QCustomerOptionValue.customerOptionValue;
+
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCustomer)
+ .join(qCustomer.merchantStore).fetch()
+ //.leftJoin(qCustomer.billing.country,qCountry).fetch()
+ //.leftJoin(qCustomer.billing.zone,qZone).fetch()
+ .leftJoin(qCustomer.defaultLanguage).fetch()
+ .leftJoin(qCustomer.groups).fetch()
+ .leftJoin(qCustomer.attributes,qCustomerAttribute).fetch()
+ .leftJoin(qCustomerAttribute.customerOption, qCustomerOption).fetch()
+ .leftJoin(qCustomerAttribute.customerOptionValue, qCustomerOptionValue).fetch()
+ .leftJoin(qCustomerOption.descriptions).fetch()
+ .leftJoin(qCustomerOptionValue.descriptions).fetch()
+ .where(qCustomer.nick.eq(nick));
+
+ return query.uniqueResult(qCustomer);
+ }
+
+ @Override
+ public Customer getByNick(String nick, int storeId){
+ QCustomer qCustomer = QCustomer.customer;
+ QMerchantStore qMerchantStore = QMerchantStore.merchantStore;
+ QCountry qCountry = QCountry.country;
+ QZone qZone = QZone.zone;
+ QCustomerAttribute qCustomerAttribute = QCustomerAttribute.customerAttribute;
+ QCustomerOption qCustomerOption = QCustomerOption.customerOption;
+ QCustomerOptionValue qCustomerOptionValue = QCustomerOptionValue.customerOptionValue;
+
+ try {
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCustomer)
+ .join(qCustomer.merchantStore, qMerchantStore).fetch()
+ //.leftJoin(qCustomer.billing.country,qCountry).fetch()
+ //.leftJoin(qCustomer.billing.zone,qZone).fetch()
+ .leftJoin(qCustomer.defaultLanguage).fetch()
+ .leftJoin(qCustomer.groups).fetch()
+ .leftJoin(qCustomer.attributes,qCustomerAttribute).fetch()
+ .leftJoin(qCustomerAttribute.customerOption, qCustomerOption).fetch()
+ .leftJoin(qCustomerAttribute.customerOptionValue, qCustomerOptionValue).fetch()
+ .leftJoin(qCustomerOption.descriptions).fetch()
+ .leftJoin(qCustomerOptionValue.descriptions).fetch()
+ .where(qCustomer.nick.eq(nick).and(qMerchantStore.id.eq(storeId)));
+
+ return query.uniqueResult(qCustomer);
+
+ } catch(NoResultException nre) {
+ return null;
+ }
+ }
+
+ @Override
+ public List<Customer> listByStore(MerchantStore store){
+ QCustomer qCustomer = QCustomer.customer;
+ QCountry qCountry = QCountry.country;
+ QZone qZone = QZone.zone;
+ QCustomerAttribute qCustomerAttribute = QCustomerAttribute.customerAttribute;
+ QCustomerOption qCustomerOption = QCustomerOption.customerOption;
+ QCustomerOptionValue qCustomerOptionValue = QCustomerOptionValue.customerOptionValue;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCustomer)
+ .join(qCustomer.merchantStore).fetch()
+ //.leftJoin(qCustomer.billing.country,qCountry).fetch()
+ //.leftJoin(qCustomer.billing.zone,qZone).fetch()
+ .leftJoin(qCustomer.defaultLanguage).fetch()
+ .leftJoin(qCustomer.attributes,qCustomerAttribute).fetch()
+ .leftJoin(qCustomerAttribute.customerOption, qCustomerOption).fetch()
+ .leftJoin(qCustomerAttribute.customerOptionValue, qCustomerOptionValue).fetch()
+ .leftJoin(qCustomerOption.descriptions).fetch()
+ .leftJoin(qCustomerOptionValue.descriptions).fetch()
+ .where(qCustomer.merchantStore.id.eq(store.getId()));
+
+ return query.list(qCustomer);
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/exception/CustomerNotFoundException.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/exception/CustomerNotFoundException.java
new file mode 100644
index 0000000..ccb3ff7
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/exception/CustomerNotFoundException.java
@@ -0,0 +1,22 @@
+package com.salesmanager.core.business.customer.exception;
+
+public class CustomerNotFoundException extends Exception
+{
+
+ private static final long serialVersionUID = 132801185016247023L;
+
+ public CustomerNotFoundException(final String msg, final Throwable cause)
+ {
+ super(msg, cause);
+ }
+
+ public CustomerNotFoundException(final String msg)
+ {
+ super(msg);
+ }
+
+ public CustomerNotFoundException(Throwable t)
+ {
+ super(t);
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerAttribute.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerAttribute.java
new file mode 100644
index 0000000..043e599
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerAttribute.java
@@ -0,0 +1,104 @@
+package com.salesmanager.core.business.customer.model.attribute;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.UniqueConstraint;
+
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@Table(name="CUSTOMER_ATTRIBUTE", schema=SchemaConstant.SALESMANAGER_SCHEMA,
+ uniqueConstraints={
+ @UniqueConstraint(columnNames={
+ "OPTION_ID",
+ "CUSTOMER_ID"
+ })
+ }
+)
+public class CustomerAttribute extends SalesManagerEntity<Long, CustomerAttribute> {
+ private static final long serialVersionUID = -6537491946539803265L;
+
+ @Id
+ @Column(name = "CUSTOMER_ATTRIBUTE_ID", unique=true, nullable=false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "CUST_ATTR_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="OPTION_ID", nullable=false)
+ private CustomerOption customerOption;
+
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="OPTION_VALUE_ID", nullable=false)
+ private CustomerOptionValue customerOptionValue;
+
+ @Column(name="CUSTOMER_ATTR_TXT_VAL")
+ private String textValue;
+
+
+ @ManyToOne(targetEntity = Customer.class)
+ @JoinColumn(name = "CUSTOMER_ID", nullable = false)
+ private Customer customer;
+
+ public CustomerAttribute() {
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+
+
+ public CustomerOption getCustomerOption() {
+ return customerOption;
+ }
+
+ public void setCustomerOption(CustomerOption customerOption) {
+ this.customerOption = customerOption;
+ }
+
+ public CustomerOptionValue getCustomerOptionValue() {
+ return customerOptionValue;
+ }
+
+ public void setCustomerOptionValue(CustomerOptionValue customerOptionValue) {
+ this.customerOptionValue = customerOptionValue;
+ }
+
+
+ public Customer getCustomer() {
+ return customer;
+ }
+
+ public void setCustomer(Customer customer) {
+ this.customer = customer;
+ }
+
+ public void setTextValue(String textValue) {
+ this.textValue = textValue;
+ }
+
+ public String getTextValue() {
+ return textValue;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOption.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOption.java
new file mode 100644
index 0000000..467e2f7
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOption.java
@@ -0,0 +1,182 @@
+package com.salesmanager.core.business.customer.model.attribute;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Transient;
+import javax.persistence.UniqueConstraint;
+import javax.validation.Valid;
+import javax.validation.constraints.Pattern;
+
+import org.hibernate.annotations.Index;
+import org.hibernate.validator.constraints.NotEmpty;
+
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.constants.SchemaConstant;
+
+
+@Entity
+@Table(name="CUSTOMER_OPTION", schema=SchemaConstant.SALESMANAGER_SCHEMA, uniqueConstraints=
+ @UniqueConstraint(columnNames = {"MERCHANT_ID", "CUSTOMER_OPT_CODE"}))
+public class CustomerOption extends SalesManagerEntity<Long, CustomerOption> {
+ private static final long serialVersionUID = -2019269055342226086L;
+
+ @Id
+ @Column(name="CUSTOMER_OPTION_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "CUSTOMER_OPTION_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @Column(name="SORT_ORDER")
+ private Integer sortOrder = 0;
+
+ @Column(name="CUSTOMER_OPTION_TYPE", length=10)
+ private String customerOptionType;
+
+ @NotEmpty
+ @Pattern(regexp="^[a-zA-Z0-9_]*$")
+ @Column(name="CUSTOMER_OPT_CODE")
+ @Index(name="CUST_OPT_CODE_IDX")
+ private String code;
+
+ @Column(name="CUSTOMER_OPT_ACTIVE")
+ private boolean active;
+
+ @Column(name="CUSTOMER_OPT_PUBLIC")
+ private boolean publicOption;
+
+ @Valid
+ @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "customerOption")
+ private Set<CustomerOptionDescription> descriptions = new HashSet<CustomerOptionDescription>();
+
+ @Transient
+ private List<CustomerOptionDescription> descriptionsList = new ArrayList<CustomerOptionDescription>();
+
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="MERCHANT_ID", nullable=false)
+ private MerchantStore merchantStore;
+
+ public CustomerOption() {
+ }
+
+
+
+ public Set<CustomerOptionDescription> getDescriptions() {
+ return descriptions;
+ }
+
+ public void setDescriptions(Set<CustomerOptionDescription> descriptions) {
+ this.descriptions = descriptions;
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+
+
+ public MerchantStore getMerchantStore() {
+ return merchantStore;
+ }
+
+ public void setMerchantStore(MerchantStore merchantStore) {
+ this.merchantStore = merchantStore;
+ }
+
+ public void setDescriptionsList(List<CustomerOptionDescription> descriptionsList) {
+ this.descriptionsList = descriptionsList;
+ }
+
+ public List<CustomerOptionDescription> getDescriptionsList() {
+ return descriptionsList;
+ }
+
+
+ public List<CustomerOptionDescription> getDescriptionsSettoList() {
+ if(descriptionsList==null || descriptionsList.size()==0) {
+ descriptionsList = new ArrayList<CustomerOptionDescription>(this.getDescriptions());
+ }
+ return descriptionsList;
+
+ }
+
+ public String getCustomerOptionType() {
+ return customerOptionType;
+ }
+
+
+
+ public void setCustomerOptionType(String customerOptionType) {
+ this.customerOptionType = customerOptionType;
+ }
+
+
+
+ public String getCode() {
+ return code;
+ }
+
+
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+
+
+ public boolean isActive() {
+ return active;
+ }
+
+
+
+ public void setActive(boolean active) {
+ this.active = active;
+ }
+
+
+
+ public boolean isPublicOption() {
+ return publicOption;
+ }
+
+
+
+ public void setPublicOption(boolean publicOption) {
+ this.publicOption = publicOption;
+ }
+
+
+
+ public void setSortOrder(Integer sortOrder) {
+ this.sortOrder = sortOrder;
+ }
+
+
+
+ public Integer getSortOrder() {
+ return sortOrder;
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOptionDescription.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOptionDescription.java
new file mode 100644
index 0000000..9d31fd6
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOptionDescription.java
@@ -0,0 +1,58 @@
+package com.salesmanager.core.business.customer.model.attribute;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import org.hibernate.annotations.Type;
+
+import com.salesmanager.core.business.common.model.Description;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@Table(name="CUSTOMER_OPTION_DESC", schema=SchemaConstant.SALESMANAGER_SCHEMA, uniqueConstraints={
+ @UniqueConstraint(columnNames={
+ "CUSTOMER_OPTION_ID",
+ "LANGUAGE_ID"
+ })
+ }
+)
+public class CustomerOptionDescription extends Description {
+ private static final long serialVersionUID = -3158504904707188465L;
+
+ @ManyToOne(targetEntity = CustomerOption.class)
+ @JoinColumn(name = "CUSTOMER_OPTION_ID", nullable = false)
+ private CustomerOption customerOption;
+
+ @Column(name="CUSTOMER_OPTION_COMMENT")
+ @Type(type = "org.hibernate.type.StringClobType")
+ private String customerOptionComment;
+
+
+
+ public CustomerOptionDescription() {
+ }
+
+ public CustomerOption getCustomerOption() {
+ return customerOption;
+ }
+
+ public void setCustomerOption(CustomerOption customerOption) {
+ this.customerOption = customerOption;
+ }
+
+ public String getCustomerOptionComment() {
+ return customerOptionComment;
+ }
+
+ public void setCustomerOptionComment(String customerOptionComment) {
+ this.customerOptionComment = customerOptionComment;
+ }
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOptionSet.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOptionSet.java
new file mode 100644
index 0000000..98d04ea
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOptionSet.java
@@ -0,0 +1,92 @@
+package com.salesmanager.core.business.customer.model.attribute;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.UniqueConstraint;
+
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@Table(name="CUSTOMER_OPTION_SET", schema=SchemaConstant.SALESMANAGER_SCHEMA,
+ uniqueConstraints={
+ @UniqueConstraint(columnNames={
+ "CUSTOMER_OPTION_ID",
+ "CUSTOMER_OPTION_VALUE_ID"
+ })
+ }
+)
+public class CustomerOptionSet extends SalesManagerEntity<Long, CustomerOptionSet> {
+
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @Column(name = "CUSTOMER_OPTIONSET_ID", unique=true, nullable=false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "CUST_OPTSET_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="CUSTOMER_OPTION_ID", nullable=false)
+ private CustomerOption customerOption = null;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="CUSTOMER_OPTION_VALUE_ID", nullable=false)
+ private CustomerOptionValue customerOptionValue = null;
+
+
+
+ @Column(name="SORT_ORDER")
+ private Integer sortOrder = new Integer(0);
+
+
+
+ public int getSortOrder() {
+ return sortOrder;
+ }
+
+ public void setSortOrder(int sortOrder) {
+ this.sortOrder = sortOrder;
+ }
+
+ public void setCustomerOptionValue(CustomerOptionValue customerOptionValue) {
+ this.customerOptionValue = customerOptionValue;
+ }
+
+ public CustomerOptionValue getCustomerOptionValue() {
+ return customerOptionValue;
+ }
+
+ public void setCustomerOption(CustomerOption customerOption) {
+ this.customerOption = customerOption;
+ }
+
+ public CustomerOption getCustomerOption() {
+ return customerOption;
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOptionType.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOptionType.java
new file mode 100644
index 0000000..97ef780
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOptionType.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.customer.model.attribute;
+
+public enum CustomerOptionType {
+
+ Text, Radio, Select, Checkbox
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOptionValue.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOptionValue.java
new file mode 100644
index 0000000..af34d60
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOptionValue.java
@@ -0,0 +1,154 @@
+package com.salesmanager.core.business.customer.model.attribute;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Transient;
+import javax.persistence.UniqueConstraint;
+import javax.validation.Valid;
+import javax.validation.constraints.Pattern;
+
+import org.hibernate.annotations.Index;
+import org.hibernate.validator.constraints.NotEmpty;
+import org.springframework.web.multipart.MultipartFile;
+
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.constants.SchemaConstant;
+
+
+@Entity
+@Table(name="CUSTOMER_OPTION_VALUE", schema=SchemaConstant.SALESMANAGER_SCHEMA, uniqueConstraints=
+ @UniqueConstraint(columnNames = {"MERCHANT_ID", "CUSTOMER_OPT_VAL_CODE"}))
+public class CustomerOptionValue extends SalesManagerEntity<Long, CustomerOptionValue> {
+ private static final long serialVersionUID = 3736085877929910891L;
+
+ @Id
+ @Column(name="CUSTOMER_OPTION_VALUE_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "CUSTOMER_OPT_VAL_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @Column(name="SORT_ORDER")
+ private Integer sortOrder = 0;
+
+ @Column(name="CUSTOMER_OPT_VAL_IMAGE")
+ private String customerOptionValueImage;
+
+ @NotEmpty
+ @Pattern(regexp="^[a-zA-Z0-9_]*$")
+ @Column(name="CUSTOMER_OPT_VAL_CODE")
+ @Index(name="CUST_OPT_VAL_CODE_IDX")
+ private String code;
+
+ @Transient
+ private MultipartFile image = null;
+
+ @Valid
+ @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "customerOptionValue")
+ private Set<CustomerOptionValueDescription> descriptions = new HashSet<CustomerOptionValueDescription>();
+
+ @Transient
+ private List<CustomerOptionValueDescription> descriptionsList = new ArrayList<CustomerOptionValueDescription>();
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="MERCHANT_ID", nullable=false)
+ private MerchantStore merchantStore;
+
+ public CustomerOptionValue() {
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+
+ public Set<CustomerOptionValueDescription> getDescriptions() {
+ return descriptions;
+ }
+
+ public void setDescriptions(Set<CustomerOptionValueDescription> descriptions) {
+ this.descriptions = descriptions;
+ }
+
+ public MerchantStore getMerchantStore() {
+ return merchantStore;
+ }
+
+ public void setMerchantStore(MerchantStore merchantStore) {
+ this.merchantStore = merchantStore;
+ }
+
+ public void setDescriptionsList(List<CustomerOptionValueDescription> descriptionsList) {
+ this.descriptionsList = descriptionsList;
+ }
+
+ public List<CustomerOptionValueDescription> getDescriptionsList() {
+ return descriptionsList;
+ }
+
+ public List<CustomerOptionValueDescription> getDescriptionsSettoList() {
+ if(descriptionsList==null || descriptionsList.size()==0) {
+ descriptionsList = new ArrayList<CustomerOptionValueDescription>(this.getDescriptions());
+ }
+ return descriptionsList;
+ }
+
+ public void setImage(MultipartFile image) {
+ this.image = image;
+ }
+
+ public MultipartFile getImage() {
+ return image;
+ }
+
+
+ public String getCustomerOptionValueImage() {
+ return customerOptionValueImage;
+ }
+
+ public void setCustomerOptionValueImage(String customerOptionValueImage) {
+ this.customerOptionValueImage = customerOptionValueImage;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+
+ public void setSortOrder(Integer sortOrder) {
+ this.sortOrder = sortOrder;
+ }
+
+ public Integer getSortOrder() {
+ return sortOrder;
+ }
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOptionValueDescription.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOptionValueDescription.java
new file mode 100644
index 0000000..33f2308
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/attribute/CustomerOptionValueDescription.java
@@ -0,0 +1,39 @@
+package com.salesmanager.core.business.customer.model.attribute;
+
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import com.salesmanager.core.business.common.model.Description;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@Table(name = "CUSTOMER_OPT_VAL_DESCRIPTION", schema=SchemaConstant.SALESMANAGER_SCHEMA, uniqueConstraints={
+ @UniqueConstraint(columnNames={
+ "CUSTOMER_OPT_VAL_ID",
+ "LANGUAGE_ID"
+ })
+ }
+)
+public class CustomerOptionValueDescription extends Description {
+ private static final long serialVersionUID = 7402155175956813576L;
+
+ @ManyToOne(targetEntity = CustomerOptionValue.class)
+ @JoinColumn(name = "CUSTOMER_OPT_VAL_ID")
+ private CustomerOptionValue customerOptionValue;
+
+
+ public CustomerOptionValueDescription() {
+ }
+
+ public CustomerOptionValue getCustomerOptionValue() {
+ return customerOptionValue;
+ }
+
+ public void setCustomerOptionValue(CustomerOptionValue customerOptionValue) {
+ this.customerOptionValue = customerOptionValue;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/model/Customer.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/Customer.java
new file mode 100644
index 0000000..48e29f5
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/Customer.java
@@ -0,0 +1,290 @@
+package com.salesmanager.core.business.customer.model;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.persistence.Transient;
+import javax.validation.Valid;
+
+import org.hibernate.annotations.Cascade;
+import org.hibernate.validator.constraints.Email;
+import org.hibernate.validator.constraints.NotEmpty;
+
+import com.salesmanager.core.business.catalog.product.model.review.ProductReview;
+import com.salesmanager.core.business.customer.model.attribute.CustomerAttribute;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.user.model.Group;
+import com.salesmanager.core.constants.SchemaConstant;
+import com.salesmanager.core.utils.CloneUtils;
+
+@Entity
+@Table(name = "CUSTOMER", schema=SchemaConstant.SALESMANAGER_SCHEMA)
+public class Customer extends SalesManagerEntity<Long, Customer> {
+ private static final long serialVersionUID = -6966934116557219193L;
+
+ @Id
+ @Column(name = "CUSTOMER_ID", unique=true, nullable=false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT",
+ pkColumnValue = "CUSTOMER_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.REMOVE, mappedBy = "customer")
+ private Set<CustomerAttribute> attributes = new HashSet<CustomerAttribute>();
+
+ @Column(name="CUSTOMER_GENDER", length=1, nullable=true)
+ @Enumerated(value = EnumType.STRING)
+ private CustomerGender gender;
+
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column(name="CUSTOMER_DOB")
+ private Date dateOfBirth;
+
+ @Email
+ @NotEmpty
+ @Column(name="CUSTOMER_EMAIL_ADDRESS", length=96, nullable=false)
+ private String emailAddress;
+
+ @Column(name="CUSTOMER_NICK", length=96)
+ private String nick;
+
+ @Column(name="CUSTOMER_COMPANY", length=100)
+ private String company;
+
+
+ @Column(name="CUSTOMER_PASSWORD", length=50)
+ private String password;
+
+
+ @Column(name="CUSTOMER_ANONYMOUS")
+ private boolean anonymous;
+
+
+
+ @ManyToOne(fetch = FetchType.LAZY, targetEntity = Language.class)
+ @JoinColumn(name = "LANGUAGE_ID", nullable=false)
+ private Language defaultLanguage;
+
+
+
+ @OneToMany(mappedBy = "customer", targetEntity = ProductReview.class)
+ private List<ProductReview> reviews = new ArrayList<ProductReview>();
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="MERCHANT_ID", nullable=false)
+ private MerchantStore merchantStore;
+
+
+ @Embedded
+ private com.salesmanager.core.business.common.model.Delivery delivery = null;
+
+ @Valid
+ @Embedded
+ private com.salesmanager.core.business.common.model.Billing billing = null;
+
+
+ @ManyToMany(fetch=FetchType.LAZY, cascade = {CascadeType.REFRESH})
+ @JoinTable(name = "CUSTOMER_GROUP", schema=SchemaConstant.SALESMANAGER_SCHEMA, joinColumns = {
+ @JoinColumn(name = "CUSTOMER_ID", nullable = false, updatable = false) }
+ ,
+ inverseJoinColumns = { @JoinColumn(name = "GROUP_ID",
+ nullable = false, updatable = false) }
+ )
+ @Cascade({
+ org.hibernate.annotations.CascadeType.DETACH,
+ org.hibernate.annotations.CascadeType.LOCK,
+ org.hibernate.annotations.CascadeType.REFRESH,
+ org.hibernate.annotations.CascadeType.REPLICATE
+
+ })
+ private List<Group> groups = new ArrayList<Group>();
+
+ @Transient
+ private String showCustomerStateList;
+
+ @Transient
+ private String showBillingStateList;
+
+ @Transient
+ private String showDeliveryStateList;
+
+
+ public Customer() {
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+
+
+ public Date getDateOfBirth() {
+ return CloneUtils.clone(dateOfBirth);
+ }
+
+ public void setDateOfBirth(Date dateOfBirth) {
+ this.dateOfBirth = CloneUtils.clone(dateOfBirth);
+ }
+
+ public String getEmailAddress() {
+ return emailAddress;
+ }
+
+ public void setEmailAddress(String emailAddress) {
+ this.emailAddress = emailAddress;
+ }
+
+ public String getNick() {
+ return nick;
+ }
+
+ public void setNick(String nick) {
+ this.nick = nick;
+ }
+
+ public String getCompany() {
+ return company;
+ }
+
+ public void setCompany(String company) {
+ this.company = company;
+ }
+
+
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+
+
+ public boolean isAnonymous() {
+ return anonymous;
+ }
+
+ public void setAnonymous(boolean anonymous) {
+ this.anonymous = anonymous;
+ }
+
+
+ public List<ProductReview> getReviews() {
+ return reviews;
+ }
+
+ public void setReviews(List<ProductReview> reviews) {
+ this.reviews = reviews;
+ }
+
+ public void setMerchantStore(MerchantStore merchantStore) {
+ this.merchantStore = merchantStore;
+ }
+
+ public MerchantStore getMerchantStore() {
+ return merchantStore;
+ }
+
+ public void setDelivery(com.salesmanager.core.business.common.model.Delivery delivery) {
+ this.delivery = delivery;
+ }
+
+ public com.salesmanager.core.business.common.model.Delivery getDelivery() {
+ return delivery;
+ }
+
+ public void setBilling(com.salesmanager.core.business.common.model.Billing billing) {
+ this.billing = billing;
+ }
+
+ public com.salesmanager.core.business.common.model.Billing getBilling() {
+ return billing;
+ }
+
+ public void setGroups(List<Group> groups) {
+ this.groups = groups;
+ }
+
+ public List<Group> getGroups() {
+ return groups;
+ }
+ public String getShowCustomerStateList() {
+ return showCustomerStateList;
+ }
+
+ public void setShowCustomerStateList(String showCustomerStateList) {
+ this.showCustomerStateList = showCustomerStateList;
+ }
+
+ public String getShowBillingStateList() {
+ return showBillingStateList;
+ }
+
+ public void setShowBillingStateList(String showBillingStateList) {
+ this.showBillingStateList = showBillingStateList;
+ }
+
+ public String getShowDeliveryStateList() {
+ return showDeliveryStateList;
+ }
+
+ public void setShowDeliveryStateList(String showDeliveryStateList) {
+ this.showDeliveryStateList = showDeliveryStateList;
+ }
+
+ public Language getDefaultLanguage() {
+ return defaultLanguage;
+ }
+
+ public void setDefaultLanguage(Language defaultLanguage) {
+ this.defaultLanguage = defaultLanguage;
+ }
+
+ public void setAttributes(Set<CustomerAttribute> attributes) {
+ this.attributes = attributes;
+ }
+
+ public Set<CustomerAttribute> getAttributes() {
+ return attributes;
+ }
+
+ public void setGender(CustomerGender gender) {
+ this.gender = gender;
+ }
+
+ public CustomerGender getGender() {
+ return gender;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/model/CustomerCriteria.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/CustomerCriteria.java
new file mode 100644
index 0000000..7873a77
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/CustomerCriteria.java
@@ -0,0 +1,43 @@
+package com.salesmanager.core.business.customer.model;
+
+import com.salesmanager.core.business.common.model.Criteria;
+
+public class CustomerCriteria extends Criteria {
+
+ private String firstName;
+ private String lastName;
+ private String name;
+ private String email;
+ private String country;
+ public String getFirstName() {
+ return firstName;
+ }
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+ public String getLastName() {
+ return lastName;
+ }
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+ public String getEmail() {
+ return email;
+ }
+ public void setEmail(String email) {
+ this.email = email;
+ }
+ public String getCountry() {
+ return country;
+ }
+ public void setCountry(String country) {
+ this.country = country;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/model/CustomerGender.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/CustomerGender.java
new file mode 100644
index 0000000..46859fd
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/CustomerGender.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.customer.model;
+
+public enum CustomerGender {
+
+ M, F
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/model/CustomerList.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/CustomerList.java
new file mode 100644
index 0000000..707d652
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/model/CustomerList.java
@@ -0,0 +1,22 @@
+package com.salesmanager.core.business.customer.model;
+
+import java.util.List;
+
+import com.salesmanager.core.business.common.model.EntityList;
+
+public class CustomerList extends EntityList {
+
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -3108842276158069739L;
+ private List<Customer> customers;
+ public void setCustomers(List<Customer> customers) {
+ this.customers = customers;
+ }
+ public List<Customer> getCustomers() {
+ return customers;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerAttributeService.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerAttributeService.java
new file mode 100644
index 0000000..6ec476c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerAttributeService.java
@@ -0,0 +1,29 @@
+package com.salesmanager.core.business.customer.service.attribute;
+
+import java.util.List;
+
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.customer.model.attribute.CustomerAttribute;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+
+public interface CustomerAttributeService extends
+ SalesManagerEntityService<Long, CustomerAttribute> {
+
+ void saveOrUpdate(CustomerAttribute customerAttribute)
+ throws ServiceException;
+
+ CustomerAttribute getByCustomerOptionId(MerchantStore store,
+ Long customerId, Long id);
+
+ List<CustomerAttribute> getByCustomerOptionValueId(MerchantStore store,
+ Long id);
+
+ List<CustomerAttribute> getByOptionId(MerchantStore store, Long id);
+
+
+ List<CustomerAttribute> getByCustomer(MerchantStore store, Customer customer);
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerAttributeServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerAttributeServiceImpl.java
new file mode 100644
index 0000000..e7c1291
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerAttributeServiceImpl.java
@@ -0,0 +1,78 @@
+package com.salesmanager.core.business.customer.service.attribute;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.customer.dao.attribute.CustomerAttributeDao;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.customer.model.attribute.CustomerAttribute;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+
+@Service("customerAttributeService")
+public class CustomerAttributeServiceImpl extends
+ SalesManagerEntityServiceImpl<Long, CustomerAttribute> implements CustomerAttributeService {
+
+ private CustomerAttributeDao customerAttributeDao;
+
+ @Autowired
+ public CustomerAttributeServiceImpl(CustomerAttributeDao customerAttributeDao) {
+ super(customerAttributeDao);
+ this.customerAttributeDao = customerAttributeDao;
+ }
+
+
+
+
+
+ @Override
+ public void saveOrUpdate(CustomerAttribute customerAttribute)
+ throws ServiceException {
+ if(customerAttribute.getId()!=null && customerAttribute.getId()>0) {
+ customerAttributeDao.update(customerAttribute);
+ } else {
+ customerAttributeDao.save(customerAttribute);
+ }
+
+ }
+
+ @Override
+ public void delete(CustomerAttribute attribute) throws ServiceException {
+
+ //override method, this allows the error that we try to remove a detached instance
+ attribute = this.getById(attribute.getId());
+ super.delete(attribute);
+
+ }
+
+
+
+ @Override
+ public CustomerAttribute getByCustomerOptionId(MerchantStore store, Long customerId, Long id) {
+ return customerAttributeDao.getByOptionId(store, customerId, id);
+ }
+
+
+
+ @Override
+ public List<CustomerAttribute> getByCustomer(MerchantStore store, Customer customer) {
+ return customerAttributeDao.getByCustomerId(store, customer.getId());
+ }
+
+
+ @Override
+ public List<CustomerAttribute> getByCustomerOptionValueId(MerchantStore store,
+ Long id) {
+ return customerAttributeDao.getByOptionValueId(store, id);
+ }
+
+ @Override
+ public List<CustomerAttribute> getByOptionId(MerchantStore store,
+ Long id) {
+ return customerAttributeDao.getByOptionId(store, id);
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionService.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionService.java
new file mode 100644
index 0000000..0f43b22
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionService.java
@@ -0,0 +1,27 @@
+package com.salesmanager.core.business.customer.service.attribute;
+
+import java.util.List;
+
+import com.salesmanager.core.business.customer.model.attribute.CustomerOption;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface CustomerOptionService extends SalesManagerEntityService<Long, CustomerOption> {
+
+ List<CustomerOption> listByStore(MerchantStore store, Language language)
+ throws ServiceException;
+
+
+
+ void saveOrUpdate(CustomerOption entity) throws ServiceException;
+
+
+
+ CustomerOption getByCode(MerchantStore store, String optionCode);
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionServiceImpl.java
new file mode 100644
index 0000000..3cdc6e9
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionServiceImpl.java
@@ -0,0 +1,94 @@
+package com.salesmanager.core.business.customer.service.attribute;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.customer.dao.attribute.CustomerOptionDao;
+import com.salesmanager.core.business.customer.model.attribute.CustomerAttribute;
+import com.salesmanager.core.business.customer.model.attribute.CustomerOption;
+import com.salesmanager.core.business.customer.model.attribute.CustomerOptionSet;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Service("customerOptionService")
+public class CustomerOptionServiceImpl extends
+ SalesManagerEntityServiceImpl<Long, CustomerOption> implements CustomerOptionService {
+
+
+ private CustomerOptionDao customerOptionDao;
+
+ @Autowired
+ private CustomerAttributeService customerAttributeService;
+
+ @Autowired
+ private CustomerOptionSetService customerOptionSetService;
+
+
+ @Autowired
+ public CustomerOptionServiceImpl(
+ CustomerOptionDao customerOptionDao) {
+ super(customerOptionDao);
+ this.customerOptionDao = customerOptionDao;
+ }
+
+ @Override
+ public List<CustomerOption> listByStore(MerchantStore store, Language language) throws ServiceException {
+
+ return customerOptionDao.listByStore(store, language);
+
+ }
+
+
+ @Override
+ public void saveOrUpdate(CustomerOption entity) throws ServiceException {
+
+
+ //save or update (persist and attach entities
+ if(entity.getId()!=null && entity.getId()>0) {
+ super.update(entity);
+ } else {
+ super.save(entity);
+ }
+
+ }
+
+
+ @Override
+ public void delete(CustomerOption customerOption) throws ServiceException {
+
+ //remove all attributes having this option
+ List<CustomerAttribute> attributes = customerAttributeService.getByOptionId(customerOption.getMerchantStore(), customerOption.getId());
+
+ for(CustomerAttribute attribute : attributes) {
+ customerAttributeService.delete(attribute);
+ }
+
+ CustomerOption option = this.getById(customerOption.getId());
+
+ List<CustomerOptionSet> optionSets = customerOptionSetService.listByOption(customerOption, customerOption.getMerchantStore());
+
+ for(CustomerOptionSet optionSet : optionSets) {
+ customerOptionSetService.delete(optionSet);
+ }
+
+ //remove option
+ super.delete(option);
+
+ }
+
+ @Override
+ public CustomerOption getByCode(MerchantStore store, String optionCode) {
+ return customerOptionDao.getByCode(store, optionCode);
+ }
+
+
+
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionSetService.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionSetService.java
new file mode 100644
index 0000000..cf93835
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionSetService.java
@@ -0,0 +1,35 @@
+package com.salesmanager.core.business.customer.service.attribute;
+
+import java.util.List;
+
+import com.salesmanager.core.business.customer.model.attribute.CustomerOption;
+import com.salesmanager.core.business.customer.model.attribute.CustomerOptionSet;
+import com.salesmanager.core.business.customer.model.attribute.CustomerOptionValue;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface CustomerOptionSetService extends SalesManagerEntityService<Long, CustomerOptionSet> {
+
+
+
+ void saveOrUpdate(CustomerOptionSet entity) throws ServiceException;
+
+
+
+
+ List<CustomerOptionSet> listByStore(MerchantStore store,
+ Language language) throws ServiceException;
+
+
+
+
+ List<CustomerOptionSet> listByOption(CustomerOption option,
+ MerchantStore store) throws ServiceException;
+
+
+ List<CustomerOptionSet> listByOptionValue(CustomerOptionValue optionValue,
+ MerchantStore store) throws ServiceException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionSetServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionSetServiceImpl.java
new file mode 100644
index 0000000..76033c6
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionSetServiceImpl.java
@@ -0,0 +1,84 @@
+package com.salesmanager.core.business.customer.service.attribute;
+
+import java.util.List;
+
+import org.apache.commons.lang.Validate;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.customer.dao.attribute.CustomerOptionSetDao;
+import com.salesmanager.core.business.customer.model.attribute.CustomerOption;
+import com.salesmanager.core.business.customer.model.attribute.CustomerOptionSet;
+import com.salesmanager.core.business.customer.model.attribute.CustomerOptionValue;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Service("customerOptionSetService")
+public class CustomerOptionSetServiceImpl extends
+ SalesManagerEntityServiceImpl<Long, CustomerOptionSet> implements CustomerOptionSetService {
+
+
+ @Autowired
+ private CustomerOptionSetDao customerOptionSetDao;
+
+
+ @Autowired
+ public CustomerOptionSetServiceImpl(
+ CustomerOptionSetDao customerOptionSetDao) {
+ super(customerOptionSetDao);
+ this.customerOptionSetDao = customerOptionSetDao;
+ }
+
+
+ @Override
+ public List<CustomerOptionSet> listByOption(CustomerOption option, MerchantStore store) throws ServiceException {
+ Validate.notNull(store,"merchant store cannot be null");
+ Validate.notNull(option,"option cannot be null");
+
+ return customerOptionSetDao.getByOptionId(store, option.getId());
+ }
+
+ @Override
+ public void delete(CustomerOptionSet customerOptionSet) throws ServiceException {
+ customerOptionSet = customerOptionSetDao.getById(customerOptionSet.getId());
+ super.delete(customerOptionSet);
+ }
+
+ @Override
+ public List<CustomerOptionSet> listByStore(MerchantStore store, Language language) throws ServiceException {
+ Validate.notNull(store,"merchant store cannot be null");
+
+
+ return customerOptionSetDao.listByStore(store,language);
+ }
+
+
+ @Override
+ public void saveOrUpdate(CustomerOptionSet entity) throws ServiceException {
+ Validate.notNull(entity,"customer option set cannot be null");
+
+ if(entity.getId()>0) {
+ super.update(entity);
+ } else {
+ super.create(entity);
+ }
+
+ }
+
+
+ @Override
+ public List<CustomerOptionSet> listByOptionValue(
+ CustomerOptionValue optionValue, MerchantStore store)
+ throws ServiceException {
+ return customerOptionSetDao.getByOptionValueId(store, optionValue.getId());
+ }
+
+
+
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionValueService.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionValueService.java
new file mode 100644
index 0000000..0f6271e
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionValueService.java
@@ -0,0 +1,24 @@
+package com.salesmanager.core.business.customer.service.attribute;
+
+import java.util.List;
+
+import com.salesmanager.core.business.customer.model.attribute.CustomerOptionValue;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface CustomerOptionValueService extends SalesManagerEntityService<Long, CustomerOptionValue> {
+
+
+
+ List<CustomerOptionValue> listByStore(MerchantStore store, Language language)
+ throws ServiceException;
+
+ void saveOrUpdate(CustomerOptionValue entity) throws ServiceException;
+
+ CustomerOptionValue getByCode(MerchantStore store, String optionValueCode);
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionValueServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionValueServiceImpl.java
new file mode 100644
index 0000000..0b4f649
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/service/attribute/CustomerOptionValueServiceImpl.java
@@ -0,0 +1,94 @@
+package com.salesmanager.core.business.customer.service.attribute;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.customer.dao.attribute.CustomerOptionValueDao;
+import com.salesmanager.core.business.customer.model.attribute.CustomerAttribute;
+import com.salesmanager.core.business.customer.model.attribute.CustomerOptionSet;
+import com.salesmanager.core.business.customer.model.attribute.CustomerOptionValue;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Service("customerOptionValueService")
+public class CustomerOptionValueServiceImpl extends
+ SalesManagerEntityServiceImpl<Long, CustomerOptionValue> implements
+ CustomerOptionValueService {
+
+ @Autowired
+ private CustomerAttributeService customerAttributeService;
+
+ private CustomerOptionValueDao customerOptionValueDao;
+
+ @Autowired
+ private CustomerOptionSetService customerOptionSetService;
+
+ @Autowired
+ public CustomerOptionValueServiceImpl(
+ CustomerOptionValueDao customerOptionValueDao) {
+ super(customerOptionValueDao);
+ this.customerOptionValueDao = customerOptionValueDao;
+ }
+
+
+ @Override
+ public List<CustomerOptionValue> listByStore(MerchantStore store, Language language) throws ServiceException {
+
+ return customerOptionValueDao.listByStore(store, language);
+ }
+
+
+
+
+ @Override
+ public void saveOrUpdate(CustomerOptionValue entity) throws ServiceException {
+
+
+ //save or update (persist and attach entities
+ if(entity.getId()!=null && entity.getId()>0) {
+
+ super.update(entity);
+
+ } else {
+
+ super.save(entity);
+
+ }
+
+ }
+
+
+ public void delete(CustomerOptionValue customerOptionValue) throws ServiceException {
+
+ //remove all attributes having this option
+ List<CustomerAttribute> attributes = customerAttributeService.getByCustomerOptionValueId(customerOptionValue.getMerchantStore(), customerOptionValue.getId());
+
+ for(CustomerAttribute attribute : attributes) {
+ customerAttributeService.delete(attribute);
+ }
+
+ List<CustomerOptionSet> optionSets = customerOptionSetService.listByOptionValue(customerOptionValue, customerOptionValue.getMerchantStore());
+
+ for(CustomerOptionSet optionSet : optionSets) {
+ customerOptionSetService.delete(optionSet);
+ }
+
+ CustomerOptionValue option = super.getById(customerOptionValue.getId());
+
+ //remove option
+ super.delete(option);
+
+ }
+
+ @Override
+ public CustomerOptionValue getByCode(MerchantStore store, String optionValueCode) {
+ return customerOptionValueDao.getByCode(store, optionValueCode);
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/service/CustomerService.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/service/CustomerService.java
new file mode 100644
index 0000000..386bdfd
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/service/CustomerService.java
@@ -0,0 +1,38 @@
+package com.salesmanager.core.business.customer.service;
+
+
+import java.util.List;
+
+import com.salesmanager.core.business.common.model.Address;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.customer.model.CustomerCriteria;
+import com.salesmanager.core.business.customer.model.CustomerList;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+
+public interface CustomerService extends SalesManagerEntityService<Long, Customer> {
+
+ public List<Customer> getByName(String firstName);
+
+ List<Customer> listByStore(MerchantStore store);
+
+ Customer getByNick(String nick);
+ void saveOrUpdate(Customer customer) throws ServiceException ;
+
+ CustomerList listByStore(MerchantStore store, CustomerCriteria criteria);
+
+ Customer getByNick(String nick, int storeId);
+
+ /**
+ * Return an {@link com.salesmanager.core.business.common.model.Address} object from the client IP address. Uses underlying GeoLocation module
+ * @param store
+ * @param ipAddress
+ * @return
+ * @throws ServiceException
+ */
+ Address getCustomerAddress(MerchantStore store, String ipAddress)
+ throws ServiceException;
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/customer/service/CustomerServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/customer/service/CustomerServiceImpl.java
new file mode 100644
index 0000000..6e1fb02
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/customer/service/CustomerServiceImpl.java
@@ -0,0 +1,112 @@
+package com.salesmanager.core.business.customer.service;
+
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.common.model.Address;
+import com.salesmanager.core.business.customer.dao.CustomerDAO;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.customer.model.CustomerCriteria;
+import com.salesmanager.core.business.customer.model.CustomerList;
+import com.salesmanager.core.business.customer.model.attribute.CustomerAttribute;
+import com.salesmanager.core.business.customer.service.attribute.CustomerAttributeService;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.modules.utils.GeoLocation;
+
+@Service("customerService")
+public class CustomerServiceImpl extends SalesManagerEntityServiceImpl<Long, Customer> implements CustomerService {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CustomerServiceImpl.class);
+
+ private CustomerDAO customerDAO;
+
+ @Autowired
+ private CustomerAttributeService customerAttributeService;
+
+ @Autowired
+ private GeoLocation geoLocation;
+
+
+ @Autowired
+ public CustomerServiceImpl(CustomerDAO customerDAO) {
+ super(customerDAO);
+ this.customerDAO = customerDAO;
+ }
+
+ @Override
+ public List<Customer> getByName(String firstName) {
+ return customerDAO.getByName(firstName);
+ }
+
+ @Override
+ public Customer getById(Long id) {
+ return customerDAO.getById(id);
+ }
+
+ @Override
+ public Customer getByNick(String nick) {
+ return customerDAO.getByNick(nick);
+ }
+
+ @Override
+ public Customer getByNick(String nick, int storeId) {
+ return customerDAO.getByNick(nick, storeId);
+ }
+
+ @Override
+ public List<Customer> listByStore(MerchantStore store) {
+ return customerDAO.listByStore(store);
+ }
+
+ @Override
+ public CustomerList listByStore(MerchantStore store, CustomerCriteria criteria) {
+ return customerDAO.listByStore(store,criteria);
+ }
+
+ @Override
+ public Address getCustomerAddress(MerchantStore store, String ipAddress) throws ServiceException {
+
+ try {
+ return geoLocation.getAddress(ipAddress);
+ } catch(Exception e) {
+ throw new ServiceException(e);
+ }
+
+ }
+
+ @Override
+ public void saveOrUpdate(Customer customer) throws ServiceException {
+
+ LOGGER.debug("Creating Customer");
+
+ if(customer.getId()!=null && customer.getId()>0) {
+ super.update(customer);
+ } else {
+
+ super.create(customer);
+
+ }
+ }
+
+ public void delete(Customer customer) throws ServiceException {
+ customer = getById(customer.getId());
+
+ //delete attributes
+ List<CustomerAttribute> attributes =customerAttributeService.getByCustomer(customer.getMerchantStore(), customer);
+ if(attributes!=null) {
+ for(CustomerAttribute attribute : attributes) {
+ customerAttributeService.delete(attribute);
+ }
+ }
+ customerDAO.delete(customer);
+
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/generic/dao/SalesManagerEntityDao.java b/sm-core/src/main/java/com/salesmanager/core/business/generic/dao/SalesManagerEntityDao.java
new file mode 100644
index 0000000..b694983
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/generic/dao/SalesManagerEntityDao.java
@@ -0,0 +1,104 @@
+package com.salesmanager.core.business.generic.dao;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.criteria.Expression;
+import javax.persistence.criteria.Order;
+import javax.persistence.metamodel.SingularAttribute;
+
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+
+
+/**
+ * @param <E> type entity
+ */
+public interface SalesManagerEntityDao<K extends Serializable & Comparable<K>, E extends SalesManagerEntity<K, ?>> {
+
+ /**
+ * @param clazz class
+ * @param id id
+ * @return entity
+ */
+ E getEntity(Class<? extends E> clazz, K id);
+
+ /**
+ * @param id id
+ * @return entity
+ */
+ E getById(K id);
+
+ /**
+ * @param entity entity
+ */
+ void save(E entity);
+
+ /**
+ * @param entity entity
+ */
+ void update(E entity);
+
+ /**
+ * @param entity entity
+ */
+ void delete(E entity);
+
+ /**
+ * @param entity entity
+ */
+ E refresh(E entity);
+
+ /**
+ * @return liste d'entitys
+ */
+ List<E> list();
+
+ /**
+ * @return nombre d'entitys
+ */
+ Long count();
+
+ void flush();
+
+ void clear();
+
+ /**
+ * @param <V> type value
+ * @param attribute
+ * @param fieldValue
+ * @return numbers of entities
+ */
+ <V> Long countByField(SingularAttribute<? super E, V> attribute, V fieldValue);
+
+ /**
+ * @param <V> type value
+ * @param attribute
+ * @param fieldValue
+ * @return entities
+ */
+ <V> List<E> listByField(SingularAttribute<? super E, V> attribute, V fieldValue);
+
+ /**
+ * @param <V>
+ * @param attribute
+ * @param fieldValue
+ * @return
+ * @throws NoResultException
+ * @throws {@link NonUniqueResultException}
+ */
+ <V> E getByField(SingularAttribute<? super E, V> attribute, V fieldValue);
+
+ <T extends E> List<T> list(Class<T> objectClass, Expression<Boolean> filter, Integer limit, Integer offset, Order... orders);
+
+ Long count(Expression<Boolean> filter);
+
+ EntityManager getEntityManager();
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/generic/dao/SalesManagerEntityDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/generic/dao/SalesManagerEntityDaoImpl.java
new file mode 100644
index 0000000..ba7e2e9
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/generic/dao/SalesManagerEntityDaoImpl.java
@@ -0,0 +1,102 @@
+package com.salesmanager.core.business.generic.dao;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.EntityManager;
+import javax.persistence.criteria.Expression;
+import javax.persistence.criteria.Order;
+import javax.persistence.metamodel.SingularAttribute;
+
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.generic.util.GenericEntityUtils;
+
+/**
+ * @param <T> entity type
+ */
+public abstract class SalesManagerEntityDaoImpl<K extends Serializable & Comparable<K>, E extends SalesManagerEntity<K, ?>>
+ extends SalesManagerJpaDaoSupport
+ implements SalesManagerEntityDao<K, E> {
+
+ private Class<E> objectClass;
+
+ @SuppressWarnings("unchecked")
+ public SalesManagerEntityDaoImpl() {
+ this.objectClass = (Class<E>) GenericEntityUtils.getGenericEntityClassFromComponentDefinition(getClass());
+ }
+
+ protected final Class<E> getObjectClass() {
+ return objectClass;
+ }
+
+
+ public E getEntity(Class<? extends E> clazz, K id) {
+ return super.getEntity(getObjectClass(), id);
+ }
+
+
+ public E getById(K id) {
+ return super.getEntity(getObjectClass(), id);
+ }
+
+
+ public <V> E getByField(SingularAttribute<? super E, V> attribute, V fieldValue) {
+ return super.getByField(getObjectClass(), attribute, fieldValue);
+ }
+
+
+ public void update(E entity) {
+ super.update(entity);
+ }
+
+
+ public void save(E entity) {
+ super.save(entity);
+ }
+
+
+ public void delete(E entity) {
+ super.delete(entity);
+ }
+
+
+ public E refresh(E entity) {
+ return super.refresh(entity);
+ }
+
+
+ public List<E> list() {
+ return super.listEntity(getObjectClass());
+ }
+
+
+ public <V> List<E> listByField(SingularAttribute<? super E, V> attribute, V fieldValue) {
+ return super.listEntityByField(getObjectClass(), attribute, fieldValue);
+ }
+
+
+ public <T extends E> List<T> list(Class<T> objectClass, Expression<Boolean> filter, Integer limit, Integer offset, Order... orders) {
+ return super.listEntity(objectClass, filter, limit, offset, orders);
+ }
+
+
+ public Long count() {
+ return super.countEntity(getObjectClass());
+ }
+
+
+ public <V> Long countByField(SingularAttribute<? super E, V> attribute, V fieldValue) {
+ return super.countEntityByField(getObjectClass(), attribute, fieldValue);
+ }
+
+
+ public Long count(Expression<Boolean> filter) {
+ return super.countEntity(getObjectClass(), filter);
+ }
+
+
+ @Override
+ public EntityManager getEntityManager() {
+ return super.getEntityManager();
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/generic/dao/SalesManagerJpaDaoSupport.java b/sm-core/src/main/java/com/salesmanager/core/business/generic/dao/SalesManagerJpaDaoSupport.java
new file mode 100644
index 0000000..ab5c979
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/generic/dao/SalesManagerJpaDaoSupport.java
@@ -0,0 +1,221 @@
+package com.salesmanager.core.business.generic.dao;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.ListIterator;
+
+import javax.persistence.EntityManager;
+import javax.persistence.NoResultException;
+import javax.persistence.PersistenceContext;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Expression;
+import javax.persistence.criteria.Order;
+import javax.persistence.criteria.Root;
+import javax.persistence.metamodel.SingularAttribute;
+
+import org.springframework.stereotype.Repository;
+import org.springframework.transaction.annotation.Transactional;
+
+@Repository("entityDao")
+@Transactional
+public class SalesManagerJpaDaoSupport {
+
+ @PersistenceContext
+ private EntityManager entityManager;
+
+ /**
+ * Cree la requete et applique les conditions de limite / offset et retourne la {@link TypedQuery}
+ * correspondante.
+ *
+ * @param <T> le type de l'entite retournee
+ * @param criteria
+ * @param limit null si pas de limite
+ * @param offset null si pas d'offset
+ * @return la {@link TypedQuery} avec limite et offset le cas echeant
+ */
+ protected <T> TypedQuery<T> buildTypedQuery(CriteriaQuery<T> criteria, Integer limit, Integer offset) {
+ TypedQuery<T> query = getEntityManager().createQuery(criteria);
+ if (offset != null) {
+ query.setFirstResult(offset);
+ }
+ if (limit != null) {
+ query.setMaxResults(limit);
+ }
+ return query;
+
+ }
+
+ protected void filterCriteriaQuery(CriteriaQuery<?> criteria, Expression<Boolean> filter) {
+ if (filter != null) {
+ criteria.where(filter);
+ }
+ }
+
+ protected <T> Root<T> rootCriteriaQuery(CriteriaBuilder builder, CriteriaQuery<?> criteria, Class<T> objectClass) {
+ return criteria.from(objectClass);
+ }
+
+ public <T, K> T getEntity(Class<T> clazz, K id) {
+ return getEntityManager().find(clazz, id);
+ }
+
+ public <T, V> T getByField(Class<T> clazz, SingularAttribute<? super T, V> attribute, V fieldValue) {
+ CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
+ CriteriaQuery<T> criteria = builder.createQuery(clazz);
+ Root<T> root = criteria.from(clazz);
+ criteria.where(builder.equal(root.get(attribute), fieldValue));
+
+ try {
+ return buildTypedQuery(criteria, null, null).getSingleResult();
+ } catch (NoResultException e) {
+ return null;
+ }
+ }
+
+ protected <T> void update(T entity) {
+ if (!getEntityManager().contains(entity)) {
+ getEntityManager().merge(entity);
+ //throw new PersistenceException("Updated entity must be attached");
+ }
+ //TODO: http://blog.xebia.com/2009/03/23/jpa-implementation-patterns-saving-detached-entities/
+ }
+
+ protected <T> void save(T entity) {
+ getEntityManager().persist(entity);
+ }
+
+ protected <T> void delete(T entity) {
+ if (!getEntityManager().contains(entity)) {
+ getEntityManager().merge(entity);
+ //throw new PersistenceException("Failed to delete a detached entity");
+ }
+ getEntityManager().remove(entity);
+ }
+
+ protected <T> T refresh(T entity) {
+ getEntityManager().refresh(entity);
+
+ return entity;
+ }
+
+ public void flush() {
+ getEntityManager().flush();
+ }
+
+ public void clear() {
+ getEntityManager().clear();
+ }
+
+ protected <T> List<T> listEntity(Class<T> objectClass, Expression<Boolean> filter, Integer limit, Integer offset, Order... orders) {
+ CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
+ CriteriaQuery<T> criteria = builder.createQuery(objectClass);
+ rootCriteriaQuery(builder, criteria, objectClass);
+
+ if (filter != null) {
+ filterCriteriaQuery(criteria, filter);
+ }
+ if (orders != null && orders.length > 0) {
+ criteria.orderBy(orders);
+ }
+ TypedQuery<T> query = buildTypedQuery(criteria, limit, offset);
+
+ List<T> entities = query.getResultList();
+
+ if (orders == null || orders.length == 0) {
+ sort(entities);
+ }
+
+ return entities;
+ }
+
+ protected <T> List<T> listEntity(Class<T> objectClass) {
+ return listEntity(objectClass, null, null, null);
+ }
+
+ protected <T> List<T> listEntity(Class<T> objectClass, Expression<Boolean> filter) {
+ return listEntity(objectClass, filter, null, null);
+ }
+
+ protected <T, V> List<T> listEntityByField(Class<T> objectClass, SingularAttribute<? super T, V> attribute, V fieldValue) {
+ CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
+ CriteriaQuery<T> criteria = builder.createQuery(objectClass);
+
+ Root<T> root = rootCriteriaQuery(builder, criteria, objectClass);
+ criteria.where(builder.equal(root.get(attribute), fieldValue));
+
+ List<T> entities = buildTypedQuery(criteria, null, null).getResultList();
+
+ sort(entities);
+
+ return entities;
+ }
+
+ protected <T> Long countEntity(Class<T> clazz) {
+ CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
+ CriteriaQuery<Long> criteria = builder.createQuery(Long.class);
+ Root<T> root = rootCriteriaQuery(builder, criteria, clazz);
+
+ criteria.select(builder.count(root));
+
+ return buildTypedQuery(criteria, null, null).getSingleResult();
+ }
+
+ protected <T, V> Long countEntityByField(Class<T> clazz, SingularAttribute<? super T, V> attribute, V fieldValue) {
+ CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
+ CriteriaQuery<Long> criteria = builder.createQuery(Long.class);
+
+ Root<T> root = rootCriteriaQuery(builder, criteria, clazz);
+ criteria.select(builder.count(root));
+
+ Expression<Boolean> filter = builder.equal(root.get(attribute), fieldValue);
+ filterCriteriaQuery(criteria, filter);
+
+ return buildTypedQuery(criteria, null, null).getSingleResult();
+ }
+
+ protected <T> Long countEntity(Class<T> clazz, Expression<Boolean> filter) {
+ CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
+ CriteriaQuery<Long> criteria = builder.createQuery(Long.class);
+
+ Root<T> root = rootCriteriaQuery(builder, criteria, clazz);
+ criteria.select(builder.count(root));
+
+ filterCriteriaQuery(criteria, filter);
+
+ return buildTypedQuery(criteria, null, null).getSingleResult();
+ }
+
+ protected <E> E getSingleResultOrNull(CriteriaQuery<E> cq) {
+ try {
+ return getEntityManager().createQuery(cq).getSingleResult();
+ } catch (NoResultException e) {
+ return null;
+ }
+ }
+
+ protected <E> E getSingleResultOrNull(TypedQuery<E> tq) {
+ try {
+ return tq.getSingleResult();
+ } catch (NoResultException e) {
+ return null;
+ }
+ }
+
+ protected EntityManager getEntityManager() {
+ return entityManager;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected <T> void sort(List<T> entities) {
+ Object[] a = entities.toArray();
+ Arrays.sort(a);
+ ListIterator<T> i = entities.listIterator();
+ for (int j = 0; j < a.length; j++) {
+ i.next();
+ i.set((T) a[j]);
+ }
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/generic/exception/ConversionException.java b/sm-core/src/main/java/com/salesmanager/core/business/generic/exception/ConversionException.java
new file mode 100644
index 0000000..2537042
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/generic/exception/ConversionException.java
@@ -0,0 +1,31 @@
+/**
+ *
+ */
+package com.salesmanager.core.business.generic.exception;
+
+/**
+ * @author Umesh A
+ *
+ */
+public class ConversionException extends Exception
+{
+ private static final long serialVersionUID = 687400310032876603L;
+
+ public ConversionException(final String msg, final Throwable cause)
+ {
+ super(msg, cause);
+ }
+
+ public ConversionException(final String msg)
+ {
+ super(msg);
+ }
+
+ public ConversionException(Throwable t)
+ {
+ super(t);
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/generic/exception/ServiceException.java b/sm-core/src/main/java/com/salesmanager/core/business/generic/exception/ServiceException.java
new file mode 100644
index 0000000..dccab11
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/generic/exception/ServiceException.java
@@ -0,0 +1,71 @@
+package com.salesmanager.core.business.generic.exception;
+
+/**
+ * <p>Exception générée par les services de l'application.</p>
+ */
+public class ServiceException extends Exception {
+
+ private static final long serialVersionUID = -6854945379036729034L;
+ private int exceptionType = 0;//regular error
+
+
+
+
+ public final static int EXCEPTION_VALIDATION = 99;
+ public final static int EXCEPTION_PAYMENT_DECLINED = 100;
+ public final static int EXCEPTION_TRANSACTION_DECLINED = 101;
+
+ private String messageCode = null;
+
+
+
+ public void setMessageCode(String messageCode) {
+ this.messageCode = messageCode;
+ }
+
+ public ServiceException() {
+ super();
+ }
+
+ public ServiceException(String messageCode) {
+ super();
+ this.messageCode = messageCode;
+ }
+
+ public ServiceException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public ServiceException(Throwable cause) {
+ super(cause);
+ }
+
+ public ServiceException(int exceptionType) {
+ super();
+ this.exceptionType = exceptionType;
+ }
+
+ public ServiceException(int exceptionType, String message) {
+ super(message);
+ this.exceptionType = exceptionType;
+ }
+
+ public ServiceException(int exceptionType, String message, String messageCode) {
+ super(message);
+ this.messageCode = messageCode;
+ this.exceptionType = exceptionType;
+ }
+
+ public int getExceptionType() {
+ return exceptionType;
+ }
+
+ public void setExceptionType(int exceptionType) {
+ this.exceptionType = exceptionType;
+ }
+
+ public String getMessageCode() {
+ return messageCode;
+ }
+
+}
\ No newline at end of file
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/generic/model/SalesManagerEntity.java b/sm-core/src/main/java/com/salesmanager/core/business/generic/model/SalesManagerEntity.java
new file mode 100644
index 0000000..5c8662c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/generic/model/SalesManagerEntity.java
@@ -0,0 +1,105 @@
+package com.salesmanager.core.business.generic.model;
+
+import java.io.Serializable;
+import java.text.Collator;
+import java.util.Locale;
+
+import org.hibernate.Hibernate;
+
+
+/**
+ * <p>Entité racine pour la persistence des objets via JPA.</p>
+ *
+ * @param <E> type de l'entité
+ */
+public abstract class SalesManagerEntity<K extends Serializable & Comparable<K>, E extends SalesManagerEntity<K, ?>>
+ implements Serializable, Comparable<E> {
+
+ private static final long serialVersionUID = -3988499137919577054L;
+
+ public static final Collator DEFAULT_STRING_COLLATOR = Collator.getInstance(Locale.FRENCH);
+
+ static {
+ DEFAULT_STRING_COLLATOR.setStrength(Collator.PRIMARY);
+ }
+
+ /**
+ * Retourne la valeur de l'identifiant unique.
+ *
+ * @return id
+ */
+ public abstract K getId();
+
+ /**
+ * Définit la valeur de l'identifiant unique.
+ *
+ * @param id id
+ */
+ public abstract void setId(K id);
+
+ /**
+ * Indique si l'objet a déjà été persisté ou non
+ *
+ * @return vrai si l'objet n'a pas encore été persisté
+ */
+ public boolean isNew() {
+ return getId() == null;
+ }
+
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean equals(Object object) {
+ if (object == null) {
+ return false;
+ }
+ if (object == this) {
+ return true;
+ }
+
+ // l'objet peut être proxyfié donc on utilise Hibernate.getClass() pour sortir la vraie classe
+ if (Hibernate.getClass(object) != Hibernate.getClass(this)) {
+ return false;
+ }
+
+ SalesManagerEntity<K, E> entity = (SalesManagerEntity<K, E>) object; // NOSONAR : traité au-dessus mais wrapper Hibernate
+ K id = getId();
+
+ if (id == null) {
+ return false;
+ }
+
+ return id.equals(entity.getId());
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 7;
+
+ K id = getId();
+ hash = 31 * hash + ((id == null) ? 0 : id.hashCode());
+
+ return hash;
+ }
+
+ public int compareTo(E o) {
+ if (this == o) {
+ return 0;
+ }
+ return this.getId().compareTo(o.getId());
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("entity.");
+ builder.append(Hibernate.getClass(this).getSimpleName());
+ builder.append("<");
+ builder.append(getId());
+ builder.append("-");
+ builder.append(super.toString());
+ builder.append(">");
+
+ return builder.toString();
+ }
+}
\ No newline at end of file
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/generic/service/SalesManagerEntityService.java b/sm-core/src/main/java/com/salesmanager/core/business/generic/service/SalesManagerEntityService.java
new file mode 100644
index 0000000..6aa7420
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/generic/service/SalesManagerEntityService.java
@@ -0,0 +1,92 @@
+package com.salesmanager.core.business.generic.service;
+
+import java.io.Serializable;
+import java.util.List;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.user.model.User;
+
+/**
+ * <p>Service racine pour la gestion des entités.</p>
+ *
+ * @param <T> type d'entité
+ */
+public interface SalesManagerEntityService<K extends Serializable & Comparable<K>, E extends SalesManagerEntity<K, ?>> extends TransactionalAspectAwareService{
+
+ /**
+ * Crée l'entité dans la base de données. Mis à part dans les tests pour faire des sauvegardes simples, utiliser
+ * create() car il est possible qu'il y ait des listeners sur la création d'une entité.
+ *
+ * @param entity entité
+ */
+ void save(E entity) throws ServiceException;
+
+ /**
+ * Met à jour l'entité dans la base de données.
+ *
+ * @param entity entité
+ */
+ void update(E entity) throws ServiceException;
+
+ /**
+ * Crée l'entité dans la base de données.
+ *
+ * @param entity entité
+ */
+ void create(E entity) throws ServiceException;
+
+ /**
+ * Supprime l'entité de la base de données
+ *
+ * @param entity entité
+ */
+ void delete(E entity) throws ServiceException;
+
+ /**
+ * Rafraîchit l'entité depuis la base de données
+ *
+ * @param entity entité
+ */
+ E refresh(E entity);
+
+
+ /**
+ * Retourne une entité à partir de son id.
+ *
+ * @param id identifiant
+ * @return entité
+ */
+ E getById(K id);
+
+ /**
+ * Renvoie la liste de l'ensemble des entités de ce type.
+ *
+ * @return liste d'entités
+ */
+ List<E> list();
+
+ /**
+ * Retourne une entité à partir de sa classe et son id.
+ *
+ * @param clazz classe
+ * @param id identifiant
+ * @return entité
+ */
+ E getEntity(Class<? extends E> clazz, K id);
+
+ /**
+ * Compte le nombre d'entités de ce type présentes dans la base.
+ *
+ * @return nombre d'entités
+ */
+ Long count();
+
+ /**
+ * Flushe la session.
+ */
+ void flush();
+
+ void clear();
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/generic/service/SalesManagerEntityServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/generic/service/SalesManagerEntityServiceImpl.java
new file mode 100644
index 0000000..17a7fdc
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/generic/service/SalesManagerEntityServiceImpl.java
@@ -0,0 +1,121 @@
+package com.salesmanager.core.business.generic.service;
+
+import java.io.Serializable;
+import java.util.List;
+
+import javax.persistence.metamodel.SingularAttribute;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.generic.util.GenericEntityUtils;
+
+/**
+ * @param <T> entity type
+ */
+public abstract class SalesManagerEntityServiceImpl<K extends Serializable & Comparable<K>, E extends SalesManagerEntity<K, ?>>
+ implements SalesManagerEntityService<K, E> {
+
+ /**
+ * Classe de l'entité, déterminé à partir des paramètres generics.
+ */
+ private Class<E> objectClass;
+
+ private SalesManagerEntityDao<K, E> genericDao;
+
+ @SuppressWarnings("unchecked")
+ public SalesManagerEntityServiceImpl(SalesManagerEntityDao<K, E> genericDao) {
+ this.genericDao = genericDao;
+
+ this.objectClass = (Class<E>) GenericEntityUtils.getGenericEntityClassFromComponentDefinition(getClass());
+ }
+
+ protected final Class<E> getObjectClass() {
+ return objectClass;
+ }
+
+
+ public E getEntity(Class<? extends E> clazz, K id) {
+ return genericDao.getEntity(clazz, id);
+ }
+
+
+ public E getById(K id) {
+ return genericDao.getById(id);
+ }
+
+ /**
+ * @param fieldName condition field
+ * @param fieldValue field value
+ * @return entity
+ */
+ protected <V> E getByField(SingularAttribute<? super E, V> fieldName, V fieldValue) {
+ return genericDao.getByField(fieldName, fieldValue);
+ }
+
+
+ public void save(E entity) throws ServiceException {
+ genericDao.save(entity);
+ }
+
+
+ public void create(E entity) throws ServiceException {
+ createEntity(entity);
+ }
+
+
+ protected void createEntity(E entity) throws ServiceException {
+ save(entity);
+ }
+
+
+ public final void update(E entity) throws ServiceException {
+ updateEntity(entity);
+ }
+
+ protected void updateEntity(E entity) throws ServiceException {
+ genericDao.update(entity);
+ }
+
+
+ public void delete(E entity) throws ServiceException {
+ genericDao.delete(entity);
+ }
+
+
+ public void flush() {
+ genericDao.flush();
+ }
+
+
+ public void clear() {
+ genericDao.clear();
+ }
+
+
+ public E refresh(E entity) {
+ return genericDao.refresh(entity);
+ }
+
+
+ public List<E> list() {
+ return genericDao.list();
+ }
+
+ /**
+ * Renvoie la liste des entités dont le champ donné en paramètre a la bonne valeur.
+ *
+ * @param fieldName le champ sur lequel appliquer la condition
+ * @param fieldValue valeur du champ
+ * @return liste d'entités
+ */
+ protected <V> List<E> listByField(SingularAttribute<? super E, V> fieldName, V fieldValue) {
+ return genericDao.listByField(fieldName, fieldValue);
+ }
+
+
+ public Long count() {
+ return genericDao.count();
+ }
+
+}
\ No newline at end of file
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/generic/service/TransactionalAspectAwareService.java b/sm-core/src/main/java/com/salesmanager/core/business/generic/service/TransactionalAspectAwareService.java
new file mode 100644
index 0000000..f7a6b0a
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/generic/service/TransactionalAspectAwareService.java
@@ -0,0 +1,12 @@
+package com.salesmanager.core.business.generic.service;
+
+/**
+ * Indique que le service doit être rendu transactionnel via un aspect.
+ *
+ * Cela permet de simplifier la configuration Spring de la partie transactionnelle car
+ * il suffit alors de déclarer le pointcut de l'aspect sur
+ * this(com.salesmanager.core.business.generic.service.ITransactionalAspectAwareService)
+ */
+public interface TransactionalAspectAwareService {
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/generic/util/EntityManagerUtils.java b/sm-core/src/main/java/com/salesmanager/core/business/generic/util/EntityManagerUtils.java
new file mode 100644
index 0000000..84c5ce2
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/generic/util/EntityManagerUtils.java
@@ -0,0 +1,53 @@
+package com.salesmanager.core.business.generic.util;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.PersistenceContext;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.orm.jpa.EntityManagerFactoryUtils;
+import org.springframework.orm.jpa.EntityManagerHolder;
+import org.springframework.stereotype.Component;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
+
+/**
+ * <p>Classe permettant de manipuler le EntityManager.</p>
+ *
+ * <p>Utilisée dans les tests pour ouvrir la session au début d'un test et la fermet à la fin</p>
+ */
+@Component
+public class EntityManagerUtils {
+
+ @Autowired
+ private EntityManagerFactory entityManagerFactory;
+
+ @PersistenceContext
+ private EntityManager entityManager;
+
+ /**
+ * Mise en place du EntityManager
+ */
+ public EntityManager openEntityManager() {
+ if (TransactionSynchronizationManager.hasResource(entityManagerFactory)) {
+ return ((EntityManagerHolder) TransactionSynchronizationManager.getResource(entityManagerFactory)).getEntityManager();
+ } else {
+ EntityManager entityManager = entityManagerFactory.createEntityManager();
+ TransactionSynchronizationManager.bindResource(entityManagerFactory, new EntityManagerHolder(entityManager));
+ return entityManager;
+ }
+ }
+
+ /**
+ * Suppression du EntityManager.
+ */
+ public void closeEntityManager() {
+ if (TransactionSynchronizationManager.hasResource(entityManagerFactory)) {
+ EntityManagerHolder entityManagerHolder = (EntityManagerHolder) TransactionSynchronizationManager.unbindResource(entityManagerFactory);
+ EntityManagerFactoryUtils.closeEntityManager(entityManagerHolder.getEntityManager());
+ }
+ }
+
+ public EntityManager getEntityManager() {
+ return entityManager;
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/generic/util/GenericEntityUtils.java b/sm-core/src/main/java/com/salesmanager/core/business/generic/util/GenericEntityUtils.java
new file mode 100644
index 0000000..7443d04
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/generic/util/GenericEntityUtils.java
@@ -0,0 +1,44 @@
+package com.salesmanager.core.business.generic.util;
+
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+
+public final class GenericEntityUtils {
+
+ public static Class<?> getGenericEntityClassFromComponentDefinition(Class<?> clazz) {
+ int retriesCount = 0;
+
+ while(true) {
+ if (clazz.getGenericSuperclass() instanceof ParameterizedType) {
+ Type[] argumentTypes = ((ParameterizedType) clazz.getGenericSuperclass()).getActualTypeArguments();
+
+ for (Type argumentType : argumentTypes) {
+ Class<?> argumentClass;
+
+ if (argumentType instanceof ParameterizedType) {
+ argumentClass = (Class<?>) ((ParameterizedType) argumentType).getRawType();
+ } else {
+ argumentClass = (Class<?>) argumentType;
+ }
+
+ if (SalesManagerEntity.class.isAssignableFrom(argumentClass)) {
+ return argumentClass;
+ }
+ }
+ }
+
+ clazz = clazz.getSuperclass();
+ retriesCount ++;
+
+ if (retriesCount > 5) {
+ throw new IllegalArgumentException("Unable to find a generic type extending GenericEntity.");
+ }
+ }
+ }
+
+ private GenericEntityUtils() {
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/merchant/dao/MerchantStoreDao.java b/sm-core/src/main/java/com/salesmanager/core/business/merchant/dao/MerchantStoreDao.java
new file mode 100644
index 0000000..8d5db68
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/merchant/dao/MerchantStoreDao.java
@@ -0,0 +1,17 @@
+package com.salesmanager.core.business.merchant.dao;
+
+import java.util.Collection;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+
+public interface MerchantStoreDao extends SalesManagerEntityDao<Integer, MerchantStore> {
+
+ public Collection<Product> getProducts(MerchantStore merchantStore) throws ServiceException;
+
+ public MerchantStore getMerchantStore(Integer merchantStoreId);
+
+ public MerchantStore getMerchantStore(String code) throws ServiceException;
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/merchant/dao/MerchantStoreDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/merchant/dao/MerchantStoreDaoImpl.java
new file mode 100644
index 0000000..5fc4cda
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/merchant/dao/MerchantStoreDaoImpl.java
@@ -0,0 +1,146 @@
+package com.salesmanager.core.business.merchant.dao;
+
+import java.util.Collection;
+
+import org.hibernate.Session;
+import org.hibernate.criterion.CriteriaSpecification;
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.merchant.model.QMerchantStore;
+
+
+@Repository("merchantStoreDao")
+public class MerchantStoreDaoImpl extends SalesManagerEntityDaoImpl<Integer, MerchantStore> implements MerchantStoreDao {
+
+ public MerchantStoreDaoImpl() {
+ super();
+ }
+
+ @Override
+ public Collection<Product> getProducts(MerchantStore merchantStore) throws ServiceException {
+
+
+
+
+ StringBuilder qs = new StringBuilder();
+
+
+ qs.append("from ProductMerchant as pm, Product as p ");
+ qs.append("join fetch p.availabilities pa ");
+ qs.append("join fetch p.descriptions pd ");
+ qs.append("join fetch pa.prices pap ");
+ qs.append("join fetch pap.descriptions papd ");
+ //images
+ qs.append("left join fetch p.images images ");
+ //options
+ qs.append("left join fetch p.attributes pattr ");
+ qs.append("left join fetch pattr.productOption po ");
+ qs.append("left join fetch po.descriptions pod ");
+ qs.append("left join fetch pattr.productOptionValue pov ");
+ qs.append("left join fetch pov.descriptions povd ");
+
+ qs.append("where pm.merchantId=:mid ");
+ qs.append("and pm.productId=p.productId ");
+
+
+
+
+
+ // TODO : WTF?
+ String hql = qs.toString();
+ //Query q = this.entityManager.createQuery(hql);
+
+ Session session = (Session)super.getEntityManager().getDelegate();
+ org.hibernate.Query q = session.createQuery(qs.toString());
+ q.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
+
+
+
+ q.setInteger("mid", merchantStore.getId());
+ //q.setParameterList("lid", regionList);
+ //@TODO languageUtil
+ //q.setParameter("lang", 1);
+
+ Collection<Product> results = q.list();
+ //MerchantStore s = (MerchantStore)q.getSingleResult();
+ //Collection<Product> results = s.getProducts();
+
+ return results;
+
+
+
+
+ }
+
+ @Override
+ public MerchantStore getById(Integer id) {
+
+ QMerchantStore qMerchantStore = QMerchantStore.merchantStore;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+ query.from(qMerchantStore)
+ .innerJoin(qMerchantStore.defaultLanguage).fetch()
+ .leftJoin(qMerchantStore.currency).fetch()
+ .leftJoin(qMerchantStore.country).fetch()
+ .leftJoin(qMerchantStore.zone).fetch()
+ .leftJoin(qMerchantStore.languages).fetch()
+ .where(qMerchantStore.id.eq(id));
+
+ return query.uniqueResult(qMerchantStore);
+
+ }
+
+ @Override
+ public MerchantStore getMerchantStore(String code) throws ServiceException {
+
+/*
+ String q = "from MerchantStore m join fetch m.defaultLanguage left join fetch m.currency left join fetch m.country left join fetch m.zone left join fetch m.languages where m.code=:code";
+
+
+ Query queryQ = super.getEntityManager().createQuery(q);
+ queryQ.setParameter("code", code);
+
+ return (MerchantStore)queryQ.getSingleResult();*/
+ //TODO add fetch
+ QMerchantStore qMerchantStore = QMerchantStore.merchantStore;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+ query.from(qMerchantStore)
+ .innerJoin(qMerchantStore.defaultLanguage).fetch()
+ .leftJoin(qMerchantStore.currency).fetch()
+ .leftJoin(qMerchantStore.country).fetch()
+ .leftJoin(qMerchantStore.zone).fetch()
+ .leftJoin(qMerchantStore.languages).fetch()
+ .where(qMerchantStore.code.eq(code));
+
+ return query.uniqueResult(qMerchantStore);
+ }
+
+ public MerchantStore getMerchantStore(Integer merchantStoreId) {
+
+
+ QMerchantStore qMerchantStore = QMerchantStore.merchantStore;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+ //TODO Zone country
+ query.from(qMerchantStore)
+ .innerJoin(qMerchantStore.defaultLanguage)
+ .leftJoin(qMerchantStore.currency)
+ .leftJoin(qMerchantStore.country)
+ .leftJoin(qMerchantStore.zone)
+ .leftJoin(qMerchantStore.languages)
+ .where(qMerchantStore.id.eq(merchantStoreId));
+
+ return query.uniqueResult(qMerchantStore);
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/merchant/model/MerchantStore.java b/sm-core/src/main/java/com/salesmanager/core/business/merchant/model/MerchantStore.java
new file mode 100755
index 0000000..35e77dd
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/merchant/model/MerchantStore.java
@@ -0,0 +1,385 @@
+package com.salesmanager.core.business.merchant.model;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.persistence.Transient;
+import javax.validation.constraints.Pattern;
+
+import org.hibernate.validator.constraints.Email;
+import org.hibernate.validator.constraints.NotEmpty;
+
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.currency.model.Currency;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.core.constants.MeasureUnit;
+import com.salesmanager.core.constants.SchemaConstant;
+import com.salesmanager.core.utils.CloneUtils;
+
+@Entity
+@Table(name = "MERCHANT_STORE", schema=SchemaConstant.SALESMANAGER_SCHEMA)
+public class MerchantStore extends SalesManagerEntity<Integer, MerchantStore> {
+ private static final long serialVersionUID = 7671103335743647655L;
+
+
+ public final static String DEFAULT_STORE = "DEFAULT";
+
+ @Id
+ @Column(name = "MERCHANT_ID", unique=true, nullable=false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT",
+ pkColumnValue = "STORE_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Integer id;
+
+ @NotEmpty
+ @Column(name = "STORE_NAME", nullable=false, length=100)
+ private String storename;
+
+ @NotEmpty
+ @Pattern(regexp="^[a-zA-Z0-9_]*$")
+ @Column(name = "STORE_CODE", nullable=false, unique=true, length=100)
+ private String code;
+
+ @NotEmpty
+ @Column(name = "STORE_PHONE", length=50)
+ private String storephone;
+
+ @Column(name = "STORE_ADDRESS")
+ private String storeaddress;
+
+ @NotEmpty
+ @Column(name = "STORE_CITY", length=100)
+ private String storecity;
+
+ @NotEmpty
+ @Column(name = "STORE_POSTAL_CODE", length=15)
+ private String storepostalcode;
+
+ @ManyToOne(fetch = FetchType.LAZY, targetEntity = Country.class)
+ @JoinColumn(name="COUNTRY_ID", nullable=false, updatable=true)
+ private Country country;
+
+ @ManyToOne(fetch = FetchType.LAZY, targetEntity = Zone.class)
+ @JoinColumn(name="ZONE_ID", nullable=true, updatable=true)
+ private Zone zone;
+
+ @Column(name = "STORE_STATE_PROV", length=100)
+ private String storestateprovince;
+
+ @Column(name = "WEIGHTUNITCODE", length=5)
+ private String weightunitcode = MeasureUnit.LB.name();
+
+ @Column(name = "SEIZEUNITCODE", length=5)
+ private String seizeunitcode = MeasureUnit.IN.name();
+
+ @Temporal(TemporalType.DATE)
+ @Column(name = "IN_BUSINESS_SINCE")
+ private Date inBusinessSince = new Date();
+
+ @Transient
+ private String dateBusinessSince;
+
+ @ManyToOne(fetch = FetchType.LAZY, targetEntity = Language.class)
+ @JoinColumn(name = "LANGUAGE_ID", nullable=false)
+ private Language defaultLanguage;
+
+ @NotEmpty
+ @ManyToMany(fetch = FetchType.LAZY)
+ @JoinTable(name = "MERCHANT_LANGUAGE")
+ private List<Language> languages = new ArrayList<Language>();
+
+ @Column(name = "USE_CACHE")
+ private boolean useCache = false;
+
+ @Column(name="STORE_TEMPLATE", length=25)
+ private String storeTemplate;
+
+ @Column(name="INVOICE_TEMPLATE", length=25)
+ private String invoiceTemplate;
+
+ @Column(name="DOMAIN_NAME", length=80)
+ private String domainName;
+
+ @Column(name="CONTINUESHOPPINGURL", length=150)
+ private String continueshoppingurl;
+
+ @Email
+ @NotEmpty
+ @Column(name = "STORE_EMAIL", length=60, nullable=false)
+ private String storeEmailAddress;
+
+ @Column(name="STORE_LOGO", length=100)
+ private String storeLogo;
+
+ @ManyToOne(fetch = FetchType.LAZY, targetEntity = Currency.class)
+ @JoinColumn(name = "CURRENCY_ID", nullable=false)
+ private Currency currency;
+
+ @Column(name = "CURRENCY_FORMAT_NATIONAL")
+ private boolean currencyFormatNational;
+
+ public MerchantStore() {
+ }
+
+ public boolean isUseCache() {
+ return useCache;
+ }
+
+ public void setUseCache(boolean useCache) {
+ this.useCache = useCache;
+ }
+
+ @Override
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ @Override
+ public Integer getId() {
+ return this.id;
+ }
+
+ public String getStorename() {
+ return storename;
+ }
+
+ public void setStorename(String storename) {
+ this.storename = storename;
+ }
+
+ public String getStorephone() {
+ return storephone;
+ }
+
+ public void setStorephone(String storephone) {
+ this.storephone = storephone;
+ }
+
+ public String getStoreaddress() {
+ return storeaddress;
+ }
+
+ public void setStoreaddress(String storeaddress) {
+ this.storeaddress = storeaddress;
+ }
+
+ public String getStorecity() {
+ return storecity;
+ }
+
+ public void setStorecity(String storecity) {
+ this.storecity = storecity;
+ }
+
+ public String getStorepostalcode() {
+ return storepostalcode;
+ }
+
+ public void setStorepostalcode(String storepostalcode) {
+ this.storepostalcode = storepostalcode;
+ }
+
+ public Country getCountry() {
+ return country;
+ }
+
+ public void setCountry(Country country) {
+ this.country = country;
+ }
+
+ public Zone getZone() {
+ return zone;
+ }
+
+ public void setZone(Zone zone) {
+ this.zone = zone;
+ }
+
+ public String getStorestateprovince() {
+ return storestateprovince;
+ }
+
+ public void setStorestateprovince(String storestateprovince) {
+ this.storestateprovince = storestateprovince;
+ }
+
+ public Currency getCurrency() {
+ return currency;
+ }
+
+ public void setCurrency(Currency currency) {
+ this.currency = currency;
+ }
+
+ public String getWeightunitcode() {
+ return weightunitcode;
+ }
+
+ public void setWeightunitcode(String weightunitcode) {
+ this.weightunitcode = weightunitcode;
+ }
+
+ public String getSeizeunitcode() {
+ return seizeunitcode;
+ }
+
+ public void setSeizeunitcode(String seizeunitcode) {
+ this.seizeunitcode = seizeunitcode;
+ }
+
+
+
+ public Date getInBusinessSince() {
+ return CloneUtils.clone(inBusinessSince);
+ }
+
+ public void setInBusinessSince(Date inBusinessSince) {
+ this.inBusinessSince = CloneUtils.clone(inBusinessSince);
+ }
+
+ public Language getDefaultLanguage() {
+ return defaultLanguage;
+ }
+
+ public void setDefaultLanguage(Language defaultLanguage) {
+ this.defaultLanguage = defaultLanguage;
+ }
+
+
+
+ public List<Language> getLanguages() {
+ return languages;
+ }
+
+ public void setLanguages(List<Language> languages) {
+ this.languages = languages;
+ }
+
+ //reverse mappings
+/* @SuppressWarnings("unused")
+ @ManyToMany(fetch = FetchType.LAZY, mappedBy = "stores", cascade = { CascadeType.REFRESH})
+ private Set<Manufacturer> manufacturers = new HashSet<Manufacturer>();*/
+
+
+/* @SuppressWarnings("unused")
+ @ManyToMany(fetch = FetchType.LAZY, mappedBy = "stores", cascade = CascadeType.REMOVE)
+ private Set<TaxClass> taxClasses = new HashSet<TaxClass>();*/
+
+/* @SuppressWarnings("unused")
+ @ManyToMany(fetch = FetchType.LAZY, mappedBy = "stores", cascade = CascadeType.REMOVE)
+ private Set<ProductOption> productOptions = new HashSet<ProductOption>();*/
+
+/* @SuppressWarnings("unused")
+ @ManyToMany(fetch = FetchType.LAZY, mappedBy = "stores", cascade = CascadeType.REMOVE)
+ private Set<ProductOptionValue> productOptionValues = new HashSet<ProductOptionValue>();*/
+
+/* @SuppressWarnings("unused")
+ @ManyToMany(fetch = FetchType.LAZY, mappedBy = "stores", cascade = CascadeType.REMOVE)
+ private Set<Product> products = new HashSet<Product>();*/
+
+
+/*
+ //TODO ManyToMany
+ @SuppressWarnings("unused")
+ @OneToMany(mappedBy = "merchant", cascade = CascadeType.REMOVE)
+ private List<TaxRate> taxRates = new ArrayList<TaxRate>();*/
+
+
+
+ public String getStoreLogo() {
+ return storeLogo;
+ }
+
+ public void setStoreLogo(String storeLogo) {
+ this.storeLogo = storeLogo;
+ }
+
+ public String getStoreTemplate() {
+ return storeTemplate;
+ }
+
+ public void setStoreTemplate(String storeTemplate) {
+ this.storeTemplate = storeTemplate;
+ }
+
+ public String getInvoiceTemplate() {
+ return invoiceTemplate;
+ }
+
+ public void setInvoiceTemplate(String invoiceTemplate) {
+ this.invoiceTemplate = invoiceTemplate;
+ }
+
+ public String getDomainName() {
+ return domainName;
+ }
+
+ public void setDomainName(String domainName) {
+ this.domainName = domainName;
+ }
+
+ public String getContinueshoppingurl() {
+ return continueshoppingurl;
+ }
+
+ public void setContinueshoppingurl(String continueshoppingurl) {
+ this.continueshoppingurl = continueshoppingurl;
+ }
+
+ public String getStoreEmailAddress() {
+ return storeEmailAddress;
+ }
+
+ public void setStoreEmailAddress(String storeEmailAddress) {
+ this.storeEmailAddress = storeEmailAddress;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public void setDateBusinessSince(String dateBusinessSince) {
+ this.dateBusinessSince = dateBusinessSince;
+ }
+
+ public String getDateBusinessSince() {
+ return dateBusinessSince;
+ }
+
+ public void setCurrencyFormatNational(boolean currencyFormatNational) {
+ this.currencyFormatNational = currencyFormatNational;
+ }
+
+ public boolean isCurrencyFormatNational() {
+ return currencyFormatNational;
+ }
+
+
+
+
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/merchant/service/MerchantStoreService.java b/sm-core/src/main/java/com/salesmanager/core/business/merchant/service/MerchantStoreService.java
new file mode 100755
index 0000000..10524c2
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/merchant/service/MerchantStoreService.java
@@ -0,0 +1,20 @@
+package com.salesmanager.core.business.merchant.service;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+
+public interface MerchantStoreService extends SalesManagerEntityService<Integer, MerchantStore>{
+
+
+ //Collection<Product> getProducts(MerchantStore merchantStore) throws ServiceException;
+
+ //MerchantStore getMerchantStore(Integer merchantStoreId) throws ServiceException;
+
+ MerchantStore getMerchantStore(String merchantStoreCode)
+ throws ServiceException;
+
+ MerchantStore getByCode(String code) throws ServiceException ;
+
+ void saveOrUpdate(MerchantStore store) throws ServiceException;
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/merchant/service/MerchantStoreServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/merchant/service/MerchantStoreServiceImpl.java
new file mode 100755
index 0000000..e1417a8
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/merchant/service/MerchantStoreServiceImpl.java
@@ -0,0 +1,159 @@
+package com.salesmanager.core.business.merchant.service;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.catalog.category.model.Category;
+import com.salesmanager.core.business.catalog.category.service.CategoryService;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.Manufacturer;
+import com.salesmanager.core.business.catalog.product.service.manufacturer.ManufacturerService;
+import com.salesmanager.core.business.catalog.product.service.type.ProductTypeService;
+import com.salesmanager.core.business.content.service.ContentService;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.customer.service.CustomerService;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.dao.MerchantStoreDao;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.business.order.service.OrderService;
+import com.salesmanager.core.business.system.model.MerchantConfiguration;
+import com.salesmanager.core.business.system.service.MerchantConfigurationService;
+import com.salesmanager.core.business.tax.model.taxclass.TaxClass;
+import com.salesmanager.core.business.tax.service.TaxClassService;
+import com.salesmanager.core.business.user.model.User;
+import com.salesmanager.core.business.user.service.UserService;
+
+@Service("merchantService")
+public class MerchantStoreServiceImpl extends SalesManagerEntityServiceImpl<Integer, MerchantStore>
+ implements MerchantStoreService {
+
+
+
+ @Autowired
+ protected ProductTypeService productTypeService;
+
+ @Autowired
+ private TaxClassService taxClassService;
+
+ @Autowired
+ private ContentService contentService;
+
+ @Autowired
+ private MerchantConfigurationService merchantConfigurationService;
+
+ @Autowired
+ private CategoryService categoryService;
+
+ @Autowired
+ private UserService userService;
+
+ @Autowired
+ private OrderService orderService;
+
+ @Autowired
+ private CustomerService customerService;
+
+ @Autowired
+ private ManufacturerService manufacturerService;
+
+ private MerchantStoreDao merchantStoreDao;
+
+ @Autowired
+ public MerchantStoreServiceImpl(MerchantStoreDao merchantStoreDao) {
+ super(merchantStoreDao);
+ this.merchantStoreDao = merchantStoreDao;
+ }
+
+
+ //@Override
+ public MerchantStore getMerchantStore(String merchantStoreCode) throws ServiceException {
+ return merchantStoreDao.getMerchantStore(merchantStoreCode);
+ }
+
+ @Override
+ public void saveOrUpdate(MerchantStore store) throws ServiceException {
+
+ if(store.getId()==null) {
+ super.save(store);
+ } else {
+ super.update(store);
+ }
+ }
+
+
+
+ //@Override
+ //public Collection<Product> getProducts(MerchantStore merchantStore) throws ServiceException {
+
+
+ // return merchantStoreDao.getProducts(merchantStore);
+
+
+ //}
+
+ @Override
+ public MerchantStore getByCode(String code) throws ServiceException {
+
+ return merchantStoreDao.getMerchantStore(code);
+ }
+
+ @Override
+ public void delete(MerchantStore merchant) throws ServiceException {
+
+ merchant = this.getById(merchant.getId());
+
+
+ //reference
+ List<Manufacturer> manufacturers = manufacturerService.listByStore(merchant);
+ for(Manufacturer manufacturer : manufacturers) {
+ manufacturerService.delete(manufacturer);
+ }
+
+ List<MerchantConfiguration> configurations = merchantConfigurationService.listByStore(merchant);
+ for(MerchantConfiguration configuration : configurations) {
+ merchantConfigurationService.delete(configuration);
+ }
+
+
+ //TODO taxService
+ List<TaxClass> taxClasses = taxClassService.listByStore(merchant);
+ for(TaxClass taxClass : taxClasses) {
+ taxClassService.delete(taxClass);
+ }
+
+ //content
+ contentService.removeFiles(merchant.getCode());
+ //TODO staticContentService.removeImages
+
+ //category / product
+ List<Category> categories = categoryService.listByStore(merchant);
+ for(Category category : categories) {
+ categoryService.delete(category);
+ }
+
+ //users
+ List<User> users = userService.listByStore(merchant);
+ for(User user : users) {
+ userService.delete(user);
+ }
+
+ //customers
+ List<Customer> customers = customerService.listByStore(merchant);
+ for(Customer customer : customers) {
+ customerService.delete(customer);
+ }
+
+ //orders
+ List<Order> orders = orderService.listByStore(merchant);
+ for(Order order : orders) {
+ orderService.delete(order);
+ }
+
+ super.delete(merchant);
+
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderaccount/OrderAccountDao.java b/sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderaccount/OrderAccountDao.java
new file mode 100644
index 0000000..3183e9e
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderaccount/OrderAccountDao.java
@@ -0,0 +1,9 @@
+package com.salesmanager.core.business.order.dao.orderaccount;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.order.model.orderaccount.OrderAccount;
+
+public interface OrderAccountDao extends SalesManagerEntityDao<Long, OrderAccount > {
+
+}
+
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderaccount/OrderAccountDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderaccount/OrderAccountDaoImpl.java
new file mode 100644
index 0000000..0a0b493
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderaccount/OrderAccountDaoImpl.java
@@ -0,0 +1,15 @@
+package com.salesmanager.core.business.order.dao.orderaccount;
+
+import org.springframework.stereotype.Repository;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.order.model.orderaccount.OrderAccount;
+
+@Repository("orderAccountDao")
+public class OrderAccountDaoImpl extends SalesManagerEntityDaoImpl<Long, OrderAccount> implements OrderAccountDao {
+
+ public OrderAccountDaoImpl() {
+ super();
+ }
+
+}
\ No newline at end of file
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/dao/OrderDao.java b/sm-core/src/main/java/com/salesmanager/core/business/order/dao/OrderDao.java
new file mode 100644
index 0000000..53e1c95
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/dao/OrderDao.java
@@ -0,0 +1,13 @@
+package com.salesmanager.core.business.order.dao;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.business.order.model.OrderCriteria;
+import com.salesmanager.core.business.order.model.OrderList;
+
+public interface OrderDao extends SalesManagerEntityDao<Long, Order> {
+
+ OrderList listByStore(MerchantStore store, OrderCriteria criteria);
+
+}
\ No newline at end of file
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/dao/OrderDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/order/dao/OrderDaoImpl.java
new file mode 100644
index 0000000..9855e0c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/dao/OrderDaoImpl.java
@@ -0,0 +1,173 @@
+package com.salesmanager.core.business.order.dao;
+
+import javax.persistence.Query;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.BooleanBuilder;
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.common.model.CriteriaOrderBy;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.business.order.model.OrderCriteria;
+import com.salesmanager.core.business.order.model.OrderList;
+import com.salesmanager.core.business.order.model.QOrder;
+import com.salesmanager.core.business.order.model.QOrderTotal;
+import com.salesmanager.core.business.order.model.orderproduct.QOrderProduct;
+import com.salesmanager.core.business.order.model.orderproduct.QOrderProductAttribute;
+import com.salesmanager.core.business.order.model.orderstatus.QOrderStatusHistory;
+
+@Repository("orderDao")
+public class OrderDaoImpl extends SalesManagerEntityDaoImpl<Long, Order> implements OrderDao {
+
+ public OrderDaoImpl() {
+ super();
+ }
+
+ @Override
+ public Order getById(Long id) {
+
+
+ QOrder qOrder = QOrder.order;
+ QOrderProduct qOrderProduct = QOrderProduct.orderProduct;
+ QOrderTotal qOrderTotal = QOrderTotal.orderTotal;
+ QOrderStatusHistory qOrderStatusHistory = QOrderStatusHistory.orderStatusHistory;
+ QOrderProductAttribute qOrderProductAttribute = QOrderProductAttribute.orderProductAttribute;
+ //OrderAccount not loaded for now
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qOrder)
+ .join(qOrder.orderProducts, qOrderProduct).fetch()
+ .join(qOrder.orderTotal, qOrderTotal).fetch()
+ .leftJoin(qOrder.orderHistory, qOrderStatusHistory).fetch()
+ .leftJoin(qOrderProduct.downloads).fetch()
+ .leftJoin(qOrderProduct.orderAttributes,qOrderProductAttribute).fetch()
+ .leftJoin(qOrderProduct.prices).fetch()
+ .where(qOrder.id.eq(id));
+
+
+ return query.uniqueResult(qOrder);
+
+ }
+
+
+
+ @Override
+ public OrderList listByStore(MerchantStore store, OrderCriteria criteria) {
+
+ OrderList orderList = new OrderList();
+ StringBuilder countBuilderSelect = new StringBuilder();
+ countBuilderSelect.append("select count(o) from Order as o");
+
+ StringBuilder countBuilderWhere = new StringBuilder();
+ countBuilderWhere.append(" where o.merchant.id=:mId");
+
+ if(!StringUtils.isBlank(criteria.getCustomerName())) {
+ countBuilderWhere.append(" and o.billing.firstName like:nm");
+ countBuilderWhere.append(" or o.billing.lastName like:nm");
+ }
+
+ if(!StringUtils.isBlank(criteria.getPaymentMethod())) {
+ countBuilderWhere.append(" and o.paymentModuleCode like:pm");
+ }
+
+ if(criteria.getCustomerId()!=null) {
+ countBuilderWhere.append(" and o.customerId =:cid");
+ }
+
+ Query countQ = super.getEntityManager().createQuery(
+ countBuilderSelect.toString() + countBuilderWhere.toString());
+
+ countQ.setParameter("mId", store.getId());
+
+ if(!StringUtils.isBlank(criteria.getCustomerName())) {
+ countQ.setParameter("nm",new StringBuilder().append("%").append(criteria.getCustomerName()).append("%").toString());
+ }
+
+ if(!StringUtils.isBlank(criteria.getPaymentMethod())) {
+ countQ.setParameter("pm",new StringBuilder().append("%").append(criteria.getPaymentMethod()).append("%").toString());
+ }
+
+ if(criteria.getCustomerId()!=null) {
+ countQ.setParameter("cid", criteria.getCustomerId());
+ }
+
+
+
+ Number count = (Number) countQ.getSingleResult ();
+
+ orderList.setTotalCount(count.intValue());
+
+ if(count.intValue()==0)
+ return orderList;
+
+
+
+ QOrder qOrder = QOrder.order;
+ QOrderProduct qOrderProduct = QOrderProduct.orderProduct;
+ QOrderTotal qOrderTotal = QOrderTotal.orderTotal;
+ QOrderStatusHistory qOrderStatusHistory = QOrderStatusHistory.orderStatusHistory;
+ QOrderProductAttribute qOrderProductAttribute = QOrderProductAttribute.orderProductAttribute;
+ //OrderAccount not loaded for now
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qOrder)
+ .join(qOrder.orderProducts, qOrderProduct).fetch()
+ .join(qOrder.orderTotal, qOrderTotal).fetch()
+ .leftJoin(qOrder.orderHistory, qOrderStatusHistory).fetch()
+ .leftJoin(qOrderProduct.downloads).fetch()
+ .leftJoin(qOrderProduct.orderAttributes,qOrderProductAttribute).fetch()
+ .leftJoin(qOrderProduct.prices).fetch();
+
+ query.where(qOrder.merchant.id.eq(store.getId()))
+ .orderBy(qOrder.id.desc());
+ BooleanBuilder pBuilder = null;
+
+ if(!StringUtils.isBlank(criteria.getCustomerName())) {
+ if(pBuilder==null) {
+ pBuilder = new BooleanBuilder();
+ } pBuilder.and(qOrder.billing.firstName.like(new StringBuilder().append("%").append(criteria.getCustomerName()).append("%").toString())
+ .or(qOrder.billing.lastName.like(new StringBuilder().append("%").append(criteria.getCustomerName()).append("%").toString())));
+ }
+
+ if(!StringUtils.isBlank(criteria.getPaymentMethod())) {
+ if(pBuilder==null) {
+ pBuilder = new BooleanBuilder();
+ }
+ pBuilder.and(qOrder.paymentModuleCode.stringValue().like(new StringBuilder().append("%").append(criteria.getPaymentMethod()).append("%").toString()));
+ }
+
+ if(criteria.getCustomerId()!=null) {
+ if(pBuilder==null) {
+ pBuilder = new BooleanBuilder();
+ }
+ pBuilder.and(qOrder.customerId.eq(criteria.getCustomerId()));
+ }
+
+ if(pBuilder!=null) {
+ query.where(pBuilder);
+ }
+
+ if(criteria.getOrderBy().name().equals(CriteriaOrderBy.ASC)) {
+ query.orderBy(qOrder.datePurchased.asc());
+ } else {
+ query.orderBy(qOrder.datePurchased.desc());
+ }
+
+ if(criteria.getMaxCount()>0) {
+ query.limit(criteria.getMaxCount());
+ query.offset(criteria.getStartIndex());
+ }
+
+
+ orderList.setOrders(query.list(qOrder));
+
+ return orderList;
+
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderproduct/OrderProductDao.java b/sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderproduct/OrderProductDao.java
new file mode 100644
index 0000000..616f576
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderproduct/OrderProductDao.java
@@ -0,0 +1,8 @@
+package com.salesmanager.core.business.order.dao.orderproduct;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.order.model.orderproduct.OrderProduct;
+
+public interface OrderProductDao extends SalesManagerEntityDao<Long, OrderProduct> {
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderproduct/OrderProductDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderproduct/OrderProductDaoImpl.java
new file mode 100644
index 0000000..770d2ee
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderproduct/OrderProductDaoImpl.java
@@ -0,0 +1,15 @@
+package com.salesmanager.core.business.order.dao.orderproduct;
+
+import org.springframework.stereotype.Repository;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.order.model.orderproduct.OrderProduct;
+
+@Repository("orderProductDao")
+public class OrderProductDaoImpl extends SalesManagerEntityDaoImpl<Long, OrderProduct> implements OrderProductDao{
+
+
+ public OrderProductDaoImpl() {
+ super();
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderproduct/OrderProductDownloadDao.java b/sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderproduct/OrderProductDownloadDao.java
new file mode 100644
index 0000000..dc9ff73
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderproduct/OrderProductDownloadDao.java
@@ -0,0 +1,12 @@
+package com.salesmanager.core.business.order.dao.orderproduct;
+
+import java.util.List;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.order.model.orderproduct.OrderProductDownload;
+
+public interface OrderProductDownloadDao extends SalesManagerEntityDao<Long, OrderProductDownload> {
+
+ List<OrderProductDownload> getByOrderId(Long orderId);
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderproduct/OrderProductDownloadDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderproduct/OrderProductDownloadDaoImpl.java
new file mode 100644
index 0000000..0210992
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/dao/orderproduct/OrderProductDownloadDaoImpl.java
@@ -0,0 +1,59 @@
+package com.salesmanager.core.business.order.dao.orderproduct;
+
+import java.util.List;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.order.model.QOrder;
+import com.salesmanager.core.business.order.model.orderproduct.OrderProductDownload;
+import com.salesmanager.core.business.order.model.orderproduct.QOrderProduct;
+import com.salesmanager.core.business.order.model.orderproduct.QOrderProductDownload;
+
+@Repository("orderProductDownloadDao")
+public class OrderProductDownloadDaoImpl extends SalesManagerEntityDaoImpl<Long, OrderProductDownload> implements OrderProductDownloadDao{
+
+ @Override
+ public OrderProductDownload getById(Long id) {
+
+ QOrderProductDownload qOrderProductDownload = QOrderProductDownload.orderProductDownload;
+ QOrderProduct qOrderProduct = QOrderProduct.orderProduct;
+ QOrder qOrder = QOrder.order;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qOrderProductDownload)
+ .leftJoin(qOrderProductDownload.orderProduct, qOrderProduct).fetch()
+ .leftJoin(qOrderProduct.order, qOrder).fetch()
+ .leftJoin(qOrder.merchant).fetch()
+ .where(qOrderProductDownload.id.eq(id));
+
+
+
+ OrderProductDownload orderProduct = query.uniqueResult(qOrderProductDownload);
+ return orderProduct;
+ }
+
+ @Override
+ public List<OrderProductDownload> getByOrderId(Long orderId) {
+
+ QOrderProductDownload qOrderProductDownload = QOrderProductDownload.orderProductDownload;
+ QOrderProduct qOrderProduct = QOrderProduct.orderProduct;
+ QOrder qOrder = QOrder.order;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qOrderProductDownload)
+ .leftJoin(qOrderProductDownload.orderProduct, qOrderProduct).fetch()
+ .leftJoin(qOrderProduct.order, qOrder).fetch()
+ .leftJoin(qOrder.merchant).fetch()
+ .where(qOrder.id.eq(orderId));
+
+
+
+ return query.list(qOrderProductDownload);
+
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/dao/OrderTotalDao.java b/sm-core/src/main/java/com/salesmanager/core/business/order/dao/OrderTotalDao.java
new file mode 100644
index 0000000..59b3981
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/dao/OrderTotalDao.java
@@ -0,0 +1,8 @@
+package com.salesmanager.core.business.order.dao;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.order.model.OrderTotal;
+
+public interface OrderTotalDao extends SalesManagerEntityDao<Long, OrderTotal > {
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/dao/OrderTotalDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/order/dao/OrderTotalDaoImpl.java
new file mode 100644
index 0000000..8d5208f
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/dao/OrderTotalDaoImpl.java
@@ -0,0 +1,15 @@
+package com.salesmanager.core.business.order.dao;
+
+import org.springframework.stereotype.Repository;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.order.model.OrderTotal;
+
+@Repository("orderTotalDao")
+public class OrderTotalDaoImpl extends SalesManagerEntityDaoImpl<Long, OrderTotal> implements OrderTotalDao {
+
+ public OrderTotalDaoImpl() {
+ super();
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/model/filehistory/FileHistory.java b/sm-core/src/main/java/com/salesmanager/core/business/order/model/filehistory/FileHistory.java
new file mode 100644
index 0000000..23293f7
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/model/filehistory/FileHistory.java
@@ -0,0 +1,136 @@
+
+package com.salesmanager.core.business.order.model.filehistory;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.persistence.UniqueConstraint;
+
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.constants.SchemaConstant;
+import com.salesmanager.core.utils.CloneUtils;
+
+@Entity
+@Table (name="FILE_HISTORY", schema=SchemaConstant.SALESMANAGER_SCHEMA, uniqueConstraints={
+ @UniqueConstraint(
+ columnNames={
+ "MERCHANT_ID",
+ "FILE_ID"
+ }
+ )
+ }
+)
+public class FileHistory implements Serializable {
+ private static final long serialVersionUID = 1321251632883237664L;
+
+ @Id
+ @Column(name = "FILE_HISTORY_ID", unique = true, nullable = false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT",
+ pkColumnValue = "FILE_HISTORY_ID_NEXT_VALUE")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @ManyToOne(targetEntity = MerchantStore.class)
+ @JoinColumn(name = "MERCHANT_ID", nullable = false)
+ private MerchantStore store;
+
+ @Column(name = "FILE_ID")
+ private Long fileId;
+
+ @Column ( name="FILESIZE", nullable=false )
+ private Integer filesize;
+
+ @Temporal(TemporalType.TIMESTAMP )
+ @Column ( name="DATE_ADDED", length=0, nullable=false )
+ private Date dateAdded;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column ( name="DATE_DELETED", length=0 )
+ private Date dateDeleted;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column ( name="ACCOUNTED_DATE", length=0 )
+ private Date accountedDate;
+
+ @Column ( name="DOWNLOAD_COUNT", nullable=false )
+ private Integer downloadCount;
+
+ public FileHistory() {
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public MerchantStore getStore() {
+ return store;
+ }
+
+ public void setStore(MerchantStore store) {
+ this.store = store;
+ }
+
+ public Long getFileId() {
+ return fileId;
+ }
+
+ public void setFileId(Long fileId) {
+ this.fileId = fileId;
+ }
+
+ public Integer getFilesize() {
+ return filesize;
+ }
+
+ public void setFilesize(Integer filesize) {
+ this.filesize = filesize;
+ }
+
+ public Date getDateAdded() {
+ return CloneUtils.clone(dateAdded);
+ }
+
+ public void setDateAdded(Date dateAdded) {
+ this.dateAdded = CloneUtils.clone(dateAdded);
+ }
+
+ public Date getDateDeleted() {
+ return CloneUtils.clone(dateDeleted);
+ }
+
+ public void setDateDeleted(Date dateDeleted) {
+ this.dateDeleted = CloneUtils.clone(dateDeleted);
+ }
+
+ public Date getAccountedDate() {
+ return CloneUtils.clone(accountedDate);
+ }
+
+ public void setAccountedDate(Date accountedDate) {
+ this.accountedDate = CloneUtils.clone(accountedDate);
+ }
+
+ public Integer getDownloadCount() {
+ return downloadCount;
+ }
+
+ public void setDownloadCount(Integer downloadCount) {
+ this.downloadCount = downloadCount;
+ }
+
+}
\ No newline at end of file
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/model/Order.java b/sm-core/src/main/java/com/salesmanager/core/business/order/model/Order.java
new file mode 100644
index 0000000..641819c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/model/Order.java
@@ -0,0 +1,365 @@
+package com.salesmanager.core.business.order.model;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.LinkedHashSet;
+import java.util.Locale;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.validation.Valid;
+
+import org.hibernate.annotations.OrderBy;
+import org.hibernate.annotations.Type;
+
+import com.salesmanager.core.business.common.model.Billing;
+import com.salesmanager.core.business.common.model.Delivery;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.orderproduct.OrderProduct;
+import com.salesmanager.core.business.order.model.orderstatus.OrderStatus;
+import com.salesmanager.core.business.order.model.orderstatus.OrderStatusHistory;
+import com.salesmanager.core.business.order.model.payment.CreditCard;
+import com.salesmanager.core.business.payments.model.PaymentType;
+import com.salesmanager.core.business.reference.currency.model.Currency;
+import com.salesmanager.core.constants.SchemaConstant;
+import com.salesmanager.core.utils.CloneUtils;
+
+@Entity
+@Table (name="ORDERS", schema = SchemaConstant.SALESMANAGER_SCHEMA)
+public class Order extends SalesManagerEntity<Long, Order> {
+
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @Column (name ="ORDER_ID" , unique=true , nullable=false )
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT",
+ pkColumnValue = "ORDER_ID_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @Column (name ="ORDER_STATUS")
+ @Enumerated(value = EnumType.STRING)
+ private OrderStatus status;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column (name ="LAST_MODIFIED")
+ private Date lastModified;
+
+ //the customer object can be detached. An order can exist and the customer deleted
+ @Column (name ="CUSTOMER_ID")
+ private Long customerId;
+
+ @Temporal(TemporalType.DATE)
+ @Column (name ="DATE_PURCHASED")
+ private Date datePurchased;
+
+ //used for an order payable on multiple installment
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column (name ="ORDER_DATE_FINISHED")
+ private Date orderDateFinished;
+
+ //What was the exchange rate
+ @Column (name ="CURRENCY_VALUE")
+ private BigDecimal currencyValue = new BigDecimal(1);//default 1-1
+
+ @Column (name ="ORDER_TOTAL")
+ private BigDecimal total;
+
+ @Column (name ="IP_ADDRESS")
+ private String ipAddress;
+
+ @Column (name ="CHANNEL")
+ @Enumerated(value = EnumType.STRING)
+ private OrderChannel channel;
+
+ @Column (name ="ORDER_TYPE")
+ @Enumerated(value = EnumType.STRING)
+ private OrderType orderType = OrderType.ORDER;
+
+ @Column (name ="PAYMENT_TYPE")
+ @Enumerated(value = EnumType.STRING)
+ private PaymentType paymentType;
+
+ @Column (name ="PAYMENT_MODULE_CODE")
+ private String paymentModuleCode;
+
+
+ @Column (name ="SHIPPING_MODULE_CODE")
+ private String shippingModuleCode;
+
+
+ @Embedded
+ private Delivery delivery = null;
+
+ @Valid
+ @Embedded
+ private Billing billing = null;
+
+ @Embedded
+ private CreditCard creditCard = null;
+
+
+ @ManyToOne(targetEntity = Currency.class)
+ @JoinColumn(name = "CURRENCY_ID")
+ private Currency currency;
+
+ @Type(type="locale")
+ @Column (name ="LOCALE")
+ private Locale locale;
+
+
+
+ @ManyToOne(targetEntity = MerchantStore.class)
+ @JoinColumn(name="MERCHANTID")
+ private MerchantStore merchant;
+
+ //@OneToMany(mappedBy = "order")
+ //private Set<OrderAccount> orderAccounts = new HashSet<OrderAccount>();
+
+ @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
+ private Set<OrderProduct> orderProducts = new LinkedHashSet<OrderProduct>();
+
+ @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
+ @OrderBy(clause = "sort_order asc")
+ private Set<OrderTotal> orderTotal = new LinkedHashSet<OrderTotal>();
+
+ @OneToMany(mappedBy = "order", cascade = CascadeType.ALL)
+ @OrderBy(clause = "ORDER_STATUS_HISTORY_ID asc")
+ private Set<OrderStatusHistory> orderHistory = new LinkedHashSet<OrderStatusHistory>();
+
+ public Order() {
+ }
+
+ @Column (name ="CUSTOMER_EMAIL_ADDRESS", length=50, nullable=false)
+ private String customerEmailAddress;
+
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public OrderStatus getStatus() {
+ return status;
+ }
+
+ public void setStatus(OrderStatus status) {
+ this.status = status;
+ }
+
+ public Date getLastModified() {
+ return CloneUtils.clone(lastModified);
+ }
+
+ public void setLastModified(Date lastModified) {
+ this.lastModified = CloneUtils.clone(lastModified);
+ }
+
+ public Date getDatePurchased() {
+ return CloneUtils.clone(datePurchased);
+ }
+
+ public void setDatePurchased(Date datePurchased) {
+ this.datePurchased = CloneUtils.clone(datePurchased);
+ }
+
+ public Date getOrderDateFinished() {
+ return CloneUtils.clone(orderDateFinished);
+ }
+
+ public void setOrderDateFinished(Date orderDateFinished) {
+ this.orderDateFinished = CloneUtils.clone(orderDateFinished);
+ }
+
+ public BigDecimal getCurrencyValue() {
+ return currencyValue;
+ }
+
+ public void setCurrencyValue(BigDecimal currencyValue) {
+ this.currencyValue = currencyValue;
+ }
+
+ public BigDecimal getTotal() {
+ return total;
+ }
+
+ public void setTotal(BigDecimal total) {
+ this.total = total;
+ }
+
+
+ public String getIpAddress() {
+ return ipAddress;
+ }
+
+ public void setIpAddress(String ipAddress) {
+ this.ipAddress = ipAddress;
+ }
+
+
+ public String getPaymentModuleCode() {
+ return paymentModuleCode;
+ }
+
+ public void setPaymentModuleCode(String paymentModuleCode) {
+ this.paymentModuleCode = paymentModuleCode;
+ }
+
+
+
+ public String getShippingModuleCode() {
+ return shippingModuleCode;
+ }
+
+ public void setShippingModuleCode(String shippingModuleCode) {
+ this.shippingModuleCode = shippingModuleCode;
+ }
+
+
+
+ public Currency getCurrency() {
+ return currency;
+ }
+
+ public void setCurrency(Currency currency) {
+ this.currency = currency;
+ }
+
+ public MerchantStore getMerchant() {
+ return merchant;
+ }
+
+ public void setMerchant(MerchantStore merchant) {
+ this.merchant = merchant;
+ }
+
+ public Set<OrderProduct> getOrderProducts() {
+ return orderProducts;
+ }
+
+ public void setOrderProducts(Set<OrderProduct> orderProducts) {
+ this.orderProducts = orderProducts;
+ }
+
+ public Set<OrderTotal> getOrderTotal() {
+ return orderTotal;
+ }
+
+ public void setOrderTotal(Set<OrderTotal> orderTotal) {
+ this.orderTotal = orderTotal;
+ }
+
+ public Set<OrderStatusHistory> getOrderHistory() {
+ return orderHistory;
+ }
+
+ public void setOrderHistory(Set<OrderStatusHistory> orderHistory) {
+ this.orderHistory = orderHistory;
+ }
+
+
+ public void setDelivery(Delivery delivery) {
+ this.delivery = delivery;
+ }
+
+ public Delivery getDelivery() {
+ return delivery;
+ }
+
+ public void setBilling(Billing billing) {
+ this.billing = billing;
+ }
+
+ public Billing getBilling() {
+ return billing;
+ }
+
+ public Long getCustomerId() {
+ return customerId;
+ }
+
+ public void setCustomerId(Long customerId) {
+ this.customerId = customerId;
+ }
+
+
+ public String getCustomerEmailAddress() {
+ return customerEmailAddress;
+ }
+
+ public void setCustomerEmailAddress(String customerEmailAddress) {
+ this.customerEmailAddress = customerEmailAddress;
+ }
+
+
+ public void setChannel(OrderChannel channel) {
+ this.channel = channel;
+ }
+
+
+ public OrderChannel getChannel() {
+ return channel;
+ }
+
+
+ public void setCreditCard(CreditCard creditCard) {
+ this.creditCard = creditCard;
+ }
+
+
+ public CreditCard getCreditCard() {
+ return creditCard;
+ }
+
+
+ public void setPaymentType(PaymentType paymentType) {
+ this.paymentType = paymentType;
+ }
+
+
+ public PaymentType getPaymentType() {
+ return paymentType;
+ }
+
+ public OrderType getOrderType() {
+ return orderType;
+ }
+
+ public void setOrderType(OrderType orderType) {
+ this.orderType = orderType;
+ }
+
+ public Locale getLocale() {
+ return locale;
+ }
+
+ public void setLocale(Locale locale) {
+ this.locale = locale;
+ }
+
+}
\ No newline at end of file
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderaccount/OrderAccount.java b/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderaccount/OrderAccount.java
new file mode 100644
index 0000000..dec1522
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderaccount/OrderAccount.java
@@ -0,0 +1,106 @@
+package com.salesmanager.core.business.order.model.orderaccount;
+
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.constants.SchemaConstant;
+import com.salesmanager.core.utils.CloneUtils;
+
+@Entity
+@Table(name = "ORDER_ACCOUNT", schema = SchemaConstant.SALESMANAGER_SCHEMA)
+public class OrderAccount extends SalesManagerEntity<Long, OrderAccount> {
+private static final long serialVersionUID = -2429388347536330540L;
+
+ @Id
+ @Column(name = "ORDER_ACCOUNT_ID", unique = true, nullable = false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "ORDER_ACCOUNT_ID_NEXT_VALUE")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @ManyToOne
+ @JoinColumn(name = "ORDER_ID", nullable = false)
+ private Order order;
+
+ @Temporal(TemporalType.DATE)
+ @Column(name = "ORDER_ACCOUNT_START_DATE", nullable = false, length = 0)
+ private Date orderAccountStartDate;
+
+ @Temporal(TemporalType.DATE)
+ @Column(name = "ORDER_ACCOUNT_END_DATE", length = 0)
+ private Date orderAccountEndDate;
+
+ @Column(name = "ORDER_ACCOUNT_BILL_DAY", nullable = false)
+ private Integer orderAccountBillDay;
+
+ @OneToMany(mappedBy = "orderAccount", cascade = CascadeType.ALL)
+ private Set<OrderAccountProduct> orderAccountProducts = new HashSet<OrderAccountProduct>();
+
+ public OrderAccount() {
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Order getOrder() {
+ return order;
+ }
+
+ public void setOrder(Order order) {
+ this.order = order;
+ }
+
+ public Date getOrderAccountStartDate() {
+ return CloneUtils.clone(orderAccountStartDate);
+ }
+
+ public void setOrderAccountStartDate(Date orderAccountStartDate) {
+ this.orderAccountStartDate = CloneUtils.clone(orderAccountStartDate);
+ }
+
+ public Date getOrderAccountEndDate() {
+ return CloneUtils.clone(orderAccountEndDate);
+ }
+
+ public void setOrderAccountEndDate(Date orderAccountEndDate) {
+ this.orderAccountEndDate = CloneUtils.clone(orderAccountEndDate);
+ }
+
+ public Integer getOrderAccountBillDay() {
+ return orderAccountBillDay;
+ }
+
+ public void setOrderAccountBillDay(Integer orderAccountBillDay) {
+ this.orderAccountBillDay = orderAccountBillDay;
+ }
+
+ public Set<OrderAccountProduct> getOrderAccountProducts() {
+ return orderAccountProducts;
+ }
+
+ public void setOrderAccountProducts(
+ Set<OrderAccountProduct> orderAccountProducts) {
+ this.orderAccountProducts = orderAccountProducts;
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderaccount/OrderAccountProduct.java b/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderaccount/OrderAccountProduct.java
new file mode 100644
index 0000000..b8c997a
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderaccount/OrderAccountProduct.java
@@ -0,0 +1,166 @@
+package com.salesmanager.core.business.order.model.orderaccount;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import com.salesmanager.core.business.order.model.orderproduct.OrderProduct;
+import com.salesmanager.core.constants.SchemaConstant;
+import com.salesmanager.core.utils.CloneUtils;
+
+@Entity
+@Table (name="ORDER_ACCOUNT_PRODUCT", schema=SchemaConstant.SALESMANAGER_SCHEMA )
+public class OrderAccountProduct implements Serializable {
+ private static final long serialVersionUID = -7437197293537758668L;
+
+ @Id
+ @Column (name="ORDER_ACCOUNT_PRODUCT_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT",
+ pkColumnValue = "ORDERACCOUNTPRODUCT_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long orderAccountProductId;
+
+ @ManyToOne
+ @JoinColumn(name = "ORDER_ACCOUNT_ID" , nullable=false)
+ private OrderAccount orderAccount;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name = "ORDER_PRODUCT_ID" , nullable=false)
+ private OrderProduct orderProduct;
+
+ @Temporal(TemporalType.DATE)
+ @Column (name="ORDER_ACCOUNT_PRODUCT_ST_DT" , length=0 , nullable=false)
+ private Date orderAccountProductStartDate;
+
+ @Temporal(TemporalType.DATE)
+ @Column (name="ORDER_ACCOUNT_PRODUCT_END_DT", length=0)
+ private Date orderAccountProductEndDate;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column (name="ORDER_ACCOUNT_PRODUCT_EOT" , length=0 )
+ private Date orderAccountProductEot;
+
+ @Temporal(TemporalType.DATE)
+ @Column (name="ORDER_ACCOUNT_PRODUCT_ACCNT_DT" , length=0 )
+ private Date orderAccountProductAccountedDate;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column (name="ORDER_ACCOUNT_PRODUCT_L_ST_DT" , length=0 )
+ private Date orderAccountProductLastStatusDate;
+
+ @Column (name="ORDER_ACCOUNT_PRODUCT_L_TRX_ST" , nullable=false )
+ private Integer orderAccountProductLastTransactionStatus;
+
+ @Column (name="ORDER_ACCOUNT_PRODUCT_PM_FR_TY" , nullable=false )
+ private Integer orderAccountProductPaymentFrequencyType;
+
+ @Column (name="ORDER_ACCOUNT_PRODUCT_STATUS" , nullable=false )
+ private Integer orderAccountProductStatus;
+
+ public OrderAccountProduct() {
+ }
+
+ public Long getOrderAccountProductId() {
+ return orderAccountProductId;
+ }
+
+ public void setOrderAccountProductId(Long orderAccountProductId) {
+ this.orderAccountProductId = orderAccountProductId;
+ }
+
+ public OrderAccount getOrderAccount() {
+ return orderAccount;
+ }
+
+ public void setOrderAccount(OrderAccount orderAccount) {
+ this.orderAccount = orderAccount;
+ }
+
+ public OrderProduct getOrderProduct() {
+ return orderProduct;
+ }
+
+ public void setOrderProduct(OrderProduct orderProduct) {
+ this.orderProduct = orderProduct;
+ }
+
+ public Date getOrderAccountProductStartDate() {
+ return CloneUtils.clone(orderAccountProductStartDate);
+ }
+
+ public void setOrderAccountProductStartDate(Date orderAccountProductStartDate) {
+ this.orderAccountProductStartDate = CloneUtils.clone(orderAccountProductStartDate);
+ }
+
+ public Date getOrderAccountProductEndDate() {
+ return CloneUtils.clone(orderAccountProductEndDate);
+ }
+
+ public void setOrderAccountProductEndDate(Date orderAccountProductEndDate) {
+ this.orderAccountProductEndDate = CloneUtils.clone(orderAccountProductEndDate);
+ }
+
+ public Date getOrderAccountProductEot() {
+ return CloneUtils.clone(orderAccountProductEot);
+ }
+
+ public void setOrderAccountProductEot(Date orderAccountProductEot) {
+ this.orderAccountProductEot = CloneUtils.clone(orderAccountProductEot);
+ }
+
+ public Date getOrderAccountProductAccountedDate() {
+ return CloneUtils.clone(orderAccountProductAccountedDate);
+ }
+
+ public void setOrderAccountProductAccountedDate(
+ Date orderAccountProductAccountedDate) {
+ this.orderAccountProductAccountedDate = CloneUtils.clone(orderAccountProductAccountedDate);
+ }
+
+ public Date getOrderAccountProductLastStatusDate() {
+ return CloneUtils.clone(orderAccountProductLastStatusDate);
+ }
+
+ public void setOrderAccountProductLastStatusDate(
+ Date orderAccountProductLastStatusDate) {
+ this.orderAccountProductLastStatusDate = CloneUtils.clone(orderAccountProductLastStatusDate);
+ }
+
+ public Integer getOrderAccountProductLastTransactionStatus() {
+ return orderAccountProductLastTransactionStatus;
+ }
+
+ public void setOrderAccountProductLastTransactionStatus(
+ Integer orderAccountProductLastTransactionStatus) {
+ this.orderAccountProductLastTransactionStatus = orderAccountProductLastTransactionStatus;
+ }
+
+ public Integer getOrderAccountProductPaymentFrequencyType() {
+ return orderAccountProductPaymentFrequencyType;
+ }
+
+ public void setOrderAccountProductPaymentFrequencyType(
+ Integer orderAccountProductPaymentFrequencyType) {
+ this.orderAccountProductPaymentFrequencyType = orderAccountProductPaymentFrequencyType;
+ }
+
+ public Integer getOrderAccountProductStatus() {
+ return orderAccountProductStatus;
+ }
+
+ public void setOrderAccountProductStatus(Integer orderAccountProductStatus) {
+ this.orderAccountProductStatus = orderAccountProductStatus;
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderChannel.java b/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderChannel.java
new file mode 100644
index 0000000..c26c9d1
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderChannel.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.order.model;
+
+public enum OrderChannel {
+
+ ONLINE
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderCriteria.java b/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderCriteria.java
new file mode 100755
index 0000000..b74948d
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderCriteria.java
@@ -0,0 +1,35 @@
+package com.salesmanager.core.business.order.model;
+
+import com.salesmanager.core.business.common.model.Criteria;
+
+public class OrderCriteria extends Criteria {
+
+ private String customerName;
+ private String paymentMethod;
+ private Long customerId;
+ public void setPaymentMethod(String paymentMethod) {
+ this.paymentMethod = paymentMethod;
+ }
+ public String getPaymentMethod() {
+ return paymentMethod;
+ }
+ public void setCustomerName(String customerName) {
+ this.customerName = customerName;
+ }
+ public String getCustomerName() {
+ return customerName;
+ }
+ public Long getCustomerId()
+ {
+ return customerId;
+ }
+ public void setCustomerId( Long customerId )
+ {
+ this.customerId = customerId;
+ }
+
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderList.java b/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderList.java
new file mode 100644
index 0000000..a4ffe72
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderList.java
@@ -0,0 +1,23 @@
+package com.salesmanager.core.business.order.model;
+
+import java.util.List;
+
+import com.salesmanager.core.business.common.model.EntityList;
+
+public class OrderList extends EntityList {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6645927228659963628L;
+ private List<Order> orders;
+
+ public void setOrders(List<Order> orders) {
+ this.orders = orders;
+ }
+
+ public List<Order> getOrders() {
+ return orders;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderproduct/OrderProduct.java b/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderproduct/OrderProduct.java
new file mode 100644
index 0000000..1e48b5e
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderproduct/OrderProduct.java
@@ -0,0 +1,140 @@
+package com.salesmanager.core.business.order.model.orderproduct;
+
+import java.math.BigDecimal;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@Table (name="ORDER_PRODUCT" , schema=SchemaConstant.SALESMANAGER_SCHEMA)
+public class OrderProduct extends SalesManagerEntity<Long, OrderProduct> {
+ private static final long serialVersionUID = 176131742783954627L;
+
+ @Id
+ @Column (name="ORDER_PRODUCT_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "ORDER_PRODUCT_ID_NEXT_VALUE")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @Column (name="PRODUCT_SKU")
+ private String sku;
+
+ @Column (name="PRODUCT_NAME" , length=64 , nullable=false)
+ private String productName;
+
+ @Column (name="PRODUCT_QUANTITY")
+ private int productQuantity;
+
+ @Column (name="ONETIME_CHARGE" , nullable=false )
+ private BigDecimal oneTimeCharge;
+
+
+ @ManyToOne(targetEntity = Order.class)
+ @JoinColumn(name = "ORDER_ID", nullable = false)
+ private Order order;
+
+ @OneToMany(mappedBy = "orderProduct", cascade = CascadeType.ALL)
+ private Set<OrderProductAttribute> orderAttributes = new HashSet<OrderProductAttribute>();
+
+ @OneToMany(mappedBy = "orderProduct", cascade = CascadeType.ALL)
+ private Set<OrderProductPrice> prices = new HashSet<OrderProductPrice>();
+
+ @OneToMany(mappedBy = "orderProduct", cascade = CascadeType.ALL)
+ private Set<OrderProductDownload> downloads = new HashSet<OrderProductDownload>();
+
+ public OrderProduct() {
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+
+ public String getProductName() {
+ return productName;
+ }
+
+ public void setProductName(String productName) {
+ this.productName = productName;
+ }
+
+ public int getProductQuantity() {
+ return productQuantity;
+ }
+
+ public void setProductQuantity(int productQuantity) {
+ this.productQuantity = productQuantity;
+ }
+
+
+
+ public Order getOrder() {
+ return order;
+ }
+
+ public void setOrder(Order order) {
+ this.order = order;
+ }
+
+
+ public Set<OrderProductAttribute> getOrderAttributes() {
+ return orderAttributes;
+ }
+
+ public void setOrderAttributes(Set<OrderProductAttribute> orderAttributes) {
+ this.orderAttributes = orderAttributes;
+ }
+
+ public Set<OrderProductPrice> getPrices() {
+ return prices;
+ }
+
+ public void setPrices(Set<OrderProductPrice> prices) {
+ this.prices = prices;
+ }
+
+ public Set<OrderProductDownload> getDownloads() {
+ return downloads;
+ }
+
+ public void setDownloads(Set<OrderProductDownload> downloads) {
+ this.downloads = downloads;
+ }
+
+
+ public void setSku(String sku) {
+ this.sku = sku;
+ }
+
+ public String getSku() {
+ return sku;
+ }
+
+ public void setOneTimeCharge(BigDecimal oneTimeCharge) {
+ this.oneTimeCharge = oneTimeCharge;
+ }
+
+ public BigDecimal getOneTimeCharge() {
+ return oneTimeCharge;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderproduct/OrderProductAttribute.java b/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderproduct/OrderProductAttribute.java
new file mode 100644
index 0000000..c0369e3
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderproduct/OrderProductAttribute.java
@@ -0,0 +1,132 @@
+package com.salesmanager.core.business.order.model.orderproduct;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@Table (name="ORDER_PRODUCT_ATTRIBUTE" , schema=SchemaConstant.SALESMANAGER_SCHEMA)
+public class OrderProductAttribute implements Serializable {
+ private static final long serialVersionUID = 6037571119918073015L;
+
+ @Id
+ @Column (name="ORDER_PRODUCT_ATTRIBUTE_ID", nullable=false , unique=true )
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "ORDER_PRODUCT_ATTR_ID_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @Column ( name= "PRODUCT_ATTRIBUTE_PRICE" , nullable=false , precision=15 , scale=4 )
+ private BigDecimal productAttributePrice;
+
+ @Column ( name= "PRODUCT_ATTRIBUTE_IS_FREE" , nullable=false )
+ private boolean productAttributeIsFree;
+
+ @Column ( name= "PRODUCT_ATTRIBUTE_WEIGHT" , precision=15 , scale=4 )
+ private java.math.BigDecimal productAttributeWeight;
+
+ @ManyToOne
+ @JoinColumn(name = "ORDER_PRODUCT_ID", nullable = false)
+ private OrderProduct orderProduct;
+
+ @Column(name = "PRODUCT_OPTION_ID", nullable = false)
+ private Long productOptionId;
+
+
+ @Column(name = "PRODUCT_OPTION_VALUE_ID", nullable = false)
+ private Long productOptionValueId;
+
+ @Column ( name= "PRODUCT_ATTRIBUTE_NAME")
+ private String productAttributeName;
+
+ @Column ( name= "PRODUCT_ATTRIBUTE_VAL_NAME")
+ private String productAttributeValueName;
+
+ public OrderProductAttribute() {
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+
+ public boolean isProductAttributeIsFree() {
+ return productAttributeIsFree;
+ }
+
+ public void setProductAttributeIsFree(boolean productAttributeIsFree) {
+ this.productAttributeIsFree = productAttributeIsFree;
+ }
+
+ public java.math.BigDecimal getProductAttributeWeight() {
+ return productAttributeWeight;
+ }
+
+ public void setProductAttributeWeight(
+ java.math.BigDecimal productAttributeWeight) {
+ this.productAttributeWeight = productAttributeWeight;
+ }
+
+ public OrderProduct getOrderProduct() {
+ return orderProduct;
+ }
+
+ public void setOrderProduct(OrderProduct orderProduct) {
+ this.orderProduct = orderProduct;
+ }
+
+ public String getProductAttributeName() {
+ return productAttributeName;
+ }
+
+ public void setProductAttributeName(String productAttributeName) {
+ this.productAttributeName = productAttributeName;
+ }
+
+ public String getProductAttributeValueName() {
+ return productAttributeValueName;
+ }
+
+ public void setProductAttributeValueName(String productAttributeValueName) {
+ this.productAttributeValueName = productAttributeValueName;
+ }
+
+ public BigDecimal getProductAttributePrice() {
+ return productAttributePrice;
+ }
+
+ public void setProductAttributePrice(BigDecimal productAttributePrice) {
+ this.productAttributePrice = productAttributePrice;
+ }
+
+ public Long getProductOptionId() {
+ return productOptionId;
+ }
+
+ public void setProductOptionId(Long productOptionId) {
+ this.productOptionId = productOptionId;
+ }
+
+ public Long getProductOptionValueId() {
+ return productOptionValueId;
+ }
+
+ public void setProductOptionValueId(Long productOptionValueId) {
+ this.productOptionValueId = productOptionValueId;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderproduct/OrderProductDownload.java b/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderproduct/OrderProductDownload.java
new file mode 100644
index 0000000..8d5395b
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderproduct/OrderProductDownload.java
@@ -0,0 +1,90 @@
+package com.salesmanager.core.business.order.model.orderproduct;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@Table (name="ORDER_PRODUCT_DOWNLOAD", schema=SchemaConstant.SALESMANAGER_SCHEMA)
+public class OrderProductDownload extends SalesManagerEntity<Long, OrderProductDownload> implements Serializable {
+ private static final long serialVersionUID = -8935511990745477240L;
+
+ public final static int DEFAULT_DOWNLOAD_MAX_DAYS = 31;
+
+ @Id
+ @Column (name="ORDER_PRODUCT_DOWNLOAD_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "ORDER_PRODUCT_DL_ID_NEXT_VALUE")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @ManyToOne
+ @JoinColumn(name = "ORDER_PRODUCT_ID", nullable = false)
+ private OrderProduct orderProduct;
+
+ @Column(name = "ORDER_PRODUCT_FILENAME", nullable = false)
+ private String orderProductFilename;
+
+ @Column(name = "DOWNLOAD_MAXDAYS", nullable = false)
+ private Integer maxdays = DEFAULT_DOWNLOAD_MAX_DAYS;
+
+ @Column(name = "DOWNLOAD_COUNT", nullable = false)
+ private Integer downloadCount;
+
+
+
+ public OrderProductDownload() {
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public OrderProduct getOrderProduct() {
+ return orderProduct;
+ }
+
+ public void setOrderProduct(OrderProduct orderProduct) {
+ this.orderProduct = orderProduct;
+ }
+
+ public String getOrderProductFilename() {
+ return orderProductFilename;
+ }
+
+ public void setOrderProductFilename(String orderProductFilename) {
+ this.orderProductFilename = orderProductFilename;
+ }
+
+ public Integer getMaxdays() {
+ return maxdays;
+ }
+
+ public void setMaxdays(Integer maxdays) {
+ this.maxdays = maxdays;
+ }
+
+ public Integer getDownloadCount() {
+ return downloadCount;
+ }
+
+ public void setDownloadCount(Integer downloadCount) {
+ this.downloadCount = downloadCount;
+ }
+
+
+}
\ No newline at end of file
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderproduct/OrderProductPrice.java b/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderproduct/OrderProductPrice.java
new file mode 100644
index 0000000..b7a9094
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderproduct/OrderProductPrice.java
@@ -0,0 +1,138 @@
+package com.salesmanager.core.business.order.model.orderproduct;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@Table (name="ORDER_PRODUCT_PRICE" , schema=SchemaConstant.SALESMANAGER_SCHEMA)
+public class OrderProductPrice implements Serializable {
+ private static final long serialVersionUID = 3734737890163564311L;
+
+ @Id
+ @Column (name="ORDER_PRODUCT_PRICE_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT",
+ pkColumnValue = "ORDER_PRD_PRICE_ID_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @ManyToOne
+ @JoinColumn(name = "ORDER_PRODUCT_ID", nullable = false)
+ private OrderProduct orderProduct;
+
+
+ @Column(name = "PRODUCT_PRICE_CODE", nullable = false , length=64 )
+ private String productPriceCode;
+
+ @Column(name = "PRODUCT_PRICE", nullable = false)
+ private BigDecimal productPrice;
+
+ @Column(name = "PRODUCT_PRICE_SPECIAL")
+ private BigDecimal productPriceSpecial;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column (name="PRD_PRICE_SPECIAL_ST_DT" , length=0)
+ private Date productPriceSpecialStartDate;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column (name="PRD_PRICE_SPECIAL_END_DT" , length=0)
+ private Date productPriceSpecialEndDate;
+
+
+ @Column(name = "DEFAULT_PRICE", nullable = false)
+ private Boolean defaultPrice;
+
+
+ @Column(name = "PRODUCT_PRICE_NAME", nullable = true)
+ private String productPriceName;
+
+ public OrderProductPrice() {
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Boolean getDefaultPrice() {
+ return defaultPrice;
+ }
+
+ public void setDefaultPrice(Boolean defaultPrice) {
+ this.defaultPrice = defaultPrice;
+ }
+
+ public String getProductPriceName() {
+ return productPriceName;
+ }
+
+ public void setProductPriceName(String productPriceName) {
+ this.productPriceName = productPriceName;
+ }
+
+ public OrderProduct getOrderProduct() {
+ return orderProduct;
+ }
+
+ public void setOrderProduct(OrderProduct orderProduct) {
+ this.orderProduct = orderProduct;
+ }
+
+ public void setProductPriceCode(String productPriceCode) {
+ this.productPriceCode = productPriceCode;
+ }
+
+ public String getProductPriceCode() {
+ return productPriceCode;
+ }
+
+ public void setProductPriceSpecialStartDate(
+ Date productPriceSpecialStartDate) {
+ this.productPriceSpecialStartDate = productPriceSpecialStartDate;
+ }
+
+ public Date getProductPriceSpecialStartDate() {
+ return productPriceSpecialStartDate;
+ }
+
+ public void setProductPriceSpecialEndDate(Date productPriceSpecialEndDate) {
+ this.productPriceSpecialEndDate = productPriceSpecialEndDate;
+ }
+
+ public Date getProductPriceSpecialEndDate() {
+ return productPriceSpecialEndDate;
+ }
+
+ public void setProductPriceSpecial(BigDecimal productPriceSpecial) {
+ this.productPriceSpecial = productPriceSpecial;
+ }
+
+ public BigDecimal getProductPriceSpecial() {
+ return productPriceSpecial;
+ }
+
+ public void setProductPrice(BigDecimal productPrice) {
+ this.productPrice = productPrice;
+ }
+
+ public BigDecimal getProductPrice() {
+ return productPrice;
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderstatus/OrderStatus.java b/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderstatus/OrderStatus.java
new file mode 100644
index 0000000..ee45847
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderstatus/OrderStatus.java
@@ -0,0 +1,20 @@
+package com.salesmanager.core.business.order.model.orderstatus;
+
+public enum OrderStatus {
+
+ ORDERED("ordered"),
+ PROCESSED("processed"),
+ DELIVERED("delivered"),
+ REFUNDED("refunded"),
+ ;
+
+ private String value;
+
+ private OrderStatus(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderstatus/OrderStatusHistory.java b/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderstatus/OrderStatusHistory.java
new file mode 100644
index 0000000..b204a84
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/model/orderstatus/OrderStatusHistory.java
@@ -0,0 +1,107 @@
+package com.salesmanager.core.business.order.model.orderstatus;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import org.hibernate.annotations.Type;
+
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.constants.SchemaConstant;
+import com.salesmanager.core.utils.CloneUtils;
+
+@Entity
+@Table (name="ORDER_STATUS_HISTORY" , schema=SchemaConstant.SALESMANAGER_SCHEMA)
+public class OrderStatusHistory implements Serializable {
+ private static final long serialVersionUID = 3438730310126102187L;
+
+ @Id
+ @Column ( name="ORDER_STATUS_HISTORY_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT",
+ pkColumnValue = "STATUS_HIST_ID_NEXT_VALUE")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @ManyToOne(targetEntity = Order.class)
+ @JoinColumn(name = "ORDER_ID", nullable = false)
+ private Order order;
+
+ @Enumerated(value = EnumType.STRING)
+ private OrderStatus status;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column(name = "DATE_ADDED", nullable = false)
+ private Date dateAdded;
+
+ @Column(name = "CUSTOMER_NOTIFIED")
+ private java.lang.Integer customerNotified;
+
+ @Column(name = "COMMENTS")
+ @Type(type = "org.hibernate.type.StringClobType")
+ private String comments;
+
+ public OrderStatusHistory() {
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public Order getOrder() {
+ return order;
+ }
+
+ public void setOrder(Order order) {
+ this.order = order;
+ }
+
+ public OrderStatus getStatus() {
+ return status;
+ }
+
+ public void setStatus(OrderStatus status) {
+ this.status = status;
+ }
+
+ public Date getDateAdded() {
+ return CloneUtils.clone(dateAdded);
+ }
+
+ public void setDateAdded(Date dateAdded) {
+ this.dateAdded = CloneUtils.clone(dateAdded);
+ }
+
+ public java.lang.Integer getCustomerNotified() {
+ return customerNotified;
+ }
+
+ public void setCustomerNotified(java.lang.Integer customerNotified) {
+ this.customerNotified = customerNotified;
+ }
+
+ public String getComments() {
+ return comments;
+ }
+
+ public void setComments(String comments) {
+ this.comments = comments;
+ }
+
+}
\ No newline at end of file
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderSummary.java b/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderSummary.java
new file mode 100644
index 0000000..99fc69b
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderSummary.java
@@ -0,0 +1,40 @@
+package com.salesmanager.core.business.order.model;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import com.salesmanager.core.business.shipping.model.ShippingSummary;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartItem;
+
+
+/**
+ * This object is used as input object for many services
+ * such as order total calculation and tax calculation
+ * @author Carl Samson
+ *
+ */
+public class OrderSummary implements Serializable {
+
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+ private ShippingSummary shippingSummary;
+ private List<ShoppingCartItem> products = new ArrayList<ShoppingCartItem>();
+
+ public void setProducts(List<ShoppingCartItem> products) {
+ this.products = products;
+ }
+ public List<ShoppingCartItem> getProducts() {
+ return products;
+ }
+ public void setShippingSummary(ShippingSummary shippingSummary) {
+ this.shippingSummary = shippingSummary;
+ }
+ public ShippingSummary getShippingSummary() {
+ return shippingSummary;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderTotal.java b/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderTotal.java
new file mode 100644
index 0000000..a22c44d
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderTotal.java
@@ -0,0 +1,155 @@
+package com.salesmanager.core.business.order.model;
+
+import java.math.BigDecimal;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+import org.hibernate.annotations.Type;
+
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.constants.SchemaConstant;
+
+
+/**
+ * Order line items related to an order.
+ * @author casams1
+ *
+ */
+
+@Entity
+@Table (name="ORDER_TOTAL" , schema=SchemaConstant.SALESMANAGER_SCHEMA)
+public class OrderTotal extends SalesManagerEntity<Long, OrderTotal> {
+ private static final long serialVersionUID = -5885315557404081674L;
+
+ @Id
+ @Column(name = "ORDER_ACCOUNT_ID", unique=true, nullable=false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "ORDER_TOTAL_ID_NEXT_VALUE")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @Column (name ="CODE", nullable=false)
+ private String orderTotalCode;//SHIPPING, TAX
+
+ @Column (name ="TITLE", nullable=true)
+ private String title;
+
+ @Column (name ="TEXT", nullable=true)
+ @Type(type = "org.hibernate.type.StringClobType")
+ private String text;
+
+ @Column (name ="VALUE", precision=15, scale=4, nullable=false )
+ private BigDecimal value;
+
+ @Column (name ="MODULE", length=60 , nullable=true )
+ private String module;
+
+ @Column (name ="ORDER_VALUE_TYPE")
+ @Enumerated(value = EnumType.STRING)
+ private OrderValueType orderValueType = OrderValueType.ONE_TIME;
+
+ @Column (name ="ORDER_TOTAL_TYPE")
+ @Enumerated(value = EnumType.STRING)
+ private OrderTotalType orderTotalType = null;
+
+ @Column (name ="SORT_ORDER", nullable=false)
+ private int sortOrder;
+
+ @ManyToOne(targetEntity = Order.class)
+ @JoinColumn(name = "ORDER_ID", nullable=false)
+ private Order order;
+
+ public OrderTotal() {
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ public BigDecimal getValue() {
+ return value;
+ }
+
+ public void setValue(BigDecimal value) {
+ this.value = value;
+ }
+
+ public String getModule() {
+ return module;
+ }
+
+ public void setModule(String module) {
+ this.module = module;
+ }
+
+ public int getSortOrder() {
+ return sortOrder;
+ }
+
+ public void setSortOrder(int sortOrder) {
+ this.sortOrder = sortOrder;
+ }
+
+ public Order getOrder() {
+ return order;
+ }
+
+ public void setOrder(Order order) {
+ this.order = order;
+ }
+
+ public void setOrderTotalCode(String orderTotalCode) {
+ this.orderTotalCode = orderTotalCode;
+ }
+
+ public String getOrderTotalCode() {
+ return orderTotalCode;
+ }
+
+ public void setOrderValueType(OrderValueType orderValueType) {
+ this.orderValueType = orderValueType;
+ }
+
+ public OrderValueType getOrderValueType() {
+ return orderValueType;
+ }
+
+ public void setOrderTotalType(OrderTotalType orderTotalType) {
+ this.orderTotalType = orderTotalType;
+ }
+
+ public OrderTotalType getOrderTotalType() {
+ return orderTotalType;
+ }
+
+
+}
\ No newline at end of file
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderTotalSummary.java b/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderTotalSummary.java
new file mode 100644
index 0000000..9339888
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderTotalSummary.java
@@ -0,0 +1,56 @@
+package com.salesmanager.core.business.order.model;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * Output object after total calculation
+ * @author Carl Samson
+ *
+ */
+public class OrderTotalSummary implements Serializable {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+ private BigDecimal subTotal;//one time price for items
+ private BigDecimal total;//final price
+ private BigDecimal taxTotal;//total of taxes
+
+ private List<OrderTotal> totals;//all other fees (tax, shipping ....)
+
+ public BigDecimal getSubTotal() {
+ return subTotal;
+ }
+
+ public void setSubTotal(BigDecimal subTotal) {
+ this.subTotal = subTotal;
+ }
+
+ public BigDecimal getTotal() {
+ return total;
+ }
+
+ public void setTotal(BigDecimal total) {
+ this.total = total;
+ }
+
+ public List<OrderTotal> getTotals() {
+ return totals;
+ }
+
+ public void setTotals(List<OrderTotal> totals) {
+ this.totals = totals;
+ }
+
+ public BigDecimal getTaxTotal() {
+ return taxTotal;
+ }
+
+ public void setTaxTotal(BigDecimal taxTotal) {
+ this.taxTotal = taxTotal;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderTotalType.java b/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderTotalType.java
new file mode 100644
index 0000000..32f905e
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderTotalType.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.order.model;
+
+public enum OrderTotalType {
+
+ SHIPPING, HANDLING, TAX, PRODUCT, SUBTOTAL, TOTAL, CREDIT, REFUND
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderType.java b/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderType.java
new file mode 100644
index 0000000..39e1311
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderType.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.order.model;
+
+public enum OrderType {
+
+ ORDER, BOOKING
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderValueType.java b/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderValueType.java
new file mode 100644
index 0000000..d716472
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/model/OrderValueType.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.order.model;
+
+public enum OrderValueType {
+
+ ONE_TIME, MONTHLY
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/model/payment/CreditCard.java b/sm-core/src/main/java/com/salesmanager/core/business/order/model/payment/CreditCard.java
new file mode 100644
index 0000000..090a603
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/model/payment/CreditCard.java
@@ -0,0 +1,69 @@
+package com.salesmanager.core.business.order.model.payment;
+
+import javax.persistence.Column;
+import javax.persistence.Embeddable;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+
+import com.salesmanager.core.business.payments.model.CreditCardType;
+
+@Embeddable
+public class CreditCard {
+
+ @Column (name ="CARD_TYPE")
+ @Enumerated(value = EnumType.STRING)
+ private CreditCardType cardType;
+
+ @Column (name ="CC_OWNER")
+ private String ccOwner;
+
+ @Column (name ="CC_NUMBER")
+ private String ccNumber;
+
+ @Column (name ="CC_EXPIRES")
+ private String ccExpires;
+
+ @Column (name ="CC_CVV")
+ private String ccCvv;
+
+ public String getCcOwner() {
+ return ccOwner;
+ }
+
+ public void setCcOwner(String ccOwner) {
+ this.ccOwner = ccOwner;
+ }
+
+ public String getCcNumber() {
+ return ccNumber;
+ }
+
+ public void setCcNumber(String ccNumber) {
+ this.ccNumber = ccNumber;
+ }
+
+ public String getCcExpires() {
+ return ccExpires;
+ }
+
+ public void setCcExpires(String ccExpires) {
+ this.ccExpires = ccExpires;
+ }
+
+ public String getCcCvv() {
+ return ccCvv;
+ }
+
+ public void setCcCvv(String ccCvv) {
+ this.ccCvv = ccCvv;
+ }
+
+ public void setCardType(CreditCardType cardType) {
+ this.cardType = cardType;
+ }
+
+ public CreditCardType getCardType() {
+ return cardType;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/service/orderproduct/OrderProductDownloadService.java b/sm-core/src/main/java/com/salesmanager/core/business/order/service/orderproduct/OrderProductDownloadService.java
new file mode 100644
index 0000000..60d4adf
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/service/orderproduct/OrderProductDownloadService.java
@@ -0,0 +1,17 @@
+package com.salesmanager.core.business.order.service.orderproduct;
+
+import java.util.List;
+
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.order.model.orderproduct.OrderProductDownload;
+
+public interface OrderProductDownloadService extends SalesManagerEntityService<Long, OrderProductDownload> {
+
+ /**
+ * List {@link OrderProductDownload} by order id
+ * @param orderId
+ * @return
+ */
+ List<OrderProductDownload> getByOrderId(Long orderId);
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/service/orderproduct/OrderProductDownloadServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/order/service/orderproduct/OrderProductDownloadServiceImpl.java
new file mode 100644
index 0000000..e46d150
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/service/orderproduct/OrderProductDownloadServiceImpl.java
@@ -0,0 +1,58 @@
+package com.salesmanager.core.business.order.service.orderproduct;
+
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.customer.service.CustomerService;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.order.dao.orderproduct.OrderProductDownloadDao;
+import com.salesmanager.core.business.order.model.orderproduct.OrderProductDownload;
+import com.salesmanager.core.business.payments.service.PaymentService;
+import com.salesmanager.core.business.payments.service.TransactionService;
+import com.salesmanager.core.business.shipping.service.ShippingService;
+import com.salesmanager.core.business.tax.service.TaxService;
+import com.salesmanager.core.modules.order.InvoiceModule;
+
+
+@Service("orderProductDownloadService")
+public class OrderProductDownloadServiceImpl extends SalesManagerEntityServiceImpl<Long, OrderProductDownload> implements OrderProductDownloadService {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(OrderProductDownloadServiceImpl.class);
+
+ @Autowired
+ private InvoiceModule invoiceModule;
+
+ @Autowired
+ private ShippingService shippingService;
+
+ @Autowired
+ private PaymentService paymentService;
+
+ @Autowired
+ private TaxService taxService;
+
+ @Autowired
+ private CustomerService customerService;
+
+ @Autowired
+ private TransactionService transactionService;
+
+ private final OrderProductDownloadDao orderProductDownloadDao;
+
+ @Autowired
+ public OrderProductDownloadServiceImpl(final OrderProductDownloadDao orderProductDownloadDao) {
+ super(orderProductDownloadDao);
+ this.orderProductDownloadDao = orderProductDownloadDao;
+ }
+
+ @Override
+ public List<OrderProductDownload> getByOrderId(Long orderId) {
+ return orderProductDownloadDao.getByOrderId(orderId);
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/service/OrderService.java b/sm-core/src/main/java/com/salesmanager/core/business/order/service/OrderService.java
new file mode 100644
index 0000000..0307ad5
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/service/OrderService.java
@@ -0,0 +1,108 @@
+package com.salesmanager.core.business.order.service;
+
+import java.io.ByteArrayOutputStream;
+import java.util.List;
+
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.business.order.model.OrderCriteria;
+import com.salesmanager.core.business.order.model.OrderList;
+import com.salesmanager.core.business.order.model.OrderSummary;
+import com.salesmanager.core.business.order.model.OrderTotalSummary;
+import com.salesmanager.core.business.order.model.orderstatus.OrderStatusHistory;
+import com.salesmanager.core.business.payments.model.Payment;
+import com.salesmanager.core.business.payments.model.Transaction;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCart;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartItem;
+
+public interface OrderService extends SalesManagerEntityService<Long, Order> {
+
+ void addOrderStatusHistory(Order order, OrderStatusHistory history)
+ throws ServiceException;
+
+ /**
+ * Can be used to calculates the final prices of all items contained in checkout page
+ * @param orderSummary
+ * @param customer
+ * @param store
+ * @param language
+ * @return
+ * @throws ServiceException
+ */
+ OrderTotalSummary caculateOrderTotal(OrderSummary orderSummary,
+ Customer customer, MerchantStore store, Language language)
+ throws ServiceException;
+
+ /**
+ * Can be used to calculates the final prices of all items contained in a ShoppingCart
+ * @param orderSummary
+ * @param store
+ * @param language
+ * @return
+ * @throws ServiceException
+ */
+ OrderTotalSummary caculateOrderTotal(OrderSummary orderSummary,
+ MerchantStore store, Language language) throws ServiceException;
+
+
+ /**
+ * Can be used to calculates the final prices of all items contained in checkout page
+ * @param shoppingCart
+ * @param customer
+ * @param store
+ * @param language
+ * @return @return {@link OrderTotalSummary}
+ * @throws ServiceException
+ */
+ OrderTotalSummary calculateShoppingCartTotal(final ShoppingCart shoppingCart,final Customer customer, final MerchantStore store, final Language language) throws ServiceException;
+
+ /**
+ * Can be used to calculates the final prices of all items contained in a ShoppingCart
+ * @param shoppingCart
+ * @param store
+ * @param language
+ * @return {@link OrderTotalSummary}
+ * @throws ServiceException
+ */
+ OrderTotalSummary calculateShoppingCartTotal(final ShoppingCart shoppingCart,final MerchantStore store, final Language language) throws ServiceException;
+
+ ByteArrayOutputStream generateInvoice(MerchantStore store, Order order,
+ Language language) throws ServiceException;
+
+ Order getOrder(Long id);
+
+ List<Order> listByStore(MerchantStore merchantStore);
+
+
+
+
+
+ OrderList listByStore(MerchantStore store, OrderCriteria criteria);
+
+ void saveOrUpdate(Order order) throws ServiceException;
+
+ Order processOrder(Order order, Customer customer,
+ List<ShoppingCartItem> items, OrderTotalSummary summary,
+ Payment payment, MerchantStore store) throws ServiceException;
+
+ Order processOrder(Order order, Customer customer,
+ List<ShoppingCartItem> items, OrderTotalSummary summary,
+ Payment payment, Transaction transaction, MerchantStore store)
+ throws ServiceException;
+
+
+
+
+ /**
+ * Determines if an Order has download files
+ * @param order
+ * @return
+ * @throws ServiceException
+ */
+ boolean hasDownloadFiles(Order order) throws ServiceException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/order/service/OrderServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/order/service/OrderServiceImpl.java
new file mode 100644
index 0000000..146f3d6
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/order/service/OrderServiceImpl.java
@@ -0,0 +1,516 @@
+package com.salesmanager.core.business.order.service;
+
+import java.io.ByteArrayOutputStream;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang.Validate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.catalog.product.model.price.FinalPrice;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.customer.service.CustomerService;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.dao.OrderDao;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.business.order.model.OrderCriteria;
+import com.salesmanager.core.business.order.model.OrderList;
+import com.salesmanager.core.business.order.model.OrderSummary;
+import com.salesmanager.core.business.order.model.OrderTotal;
+import com.salesmanager.core.business.order.model.OrderTotalSummary;
+import com.salesmanager.core.business.order.model.OrderTotalType;
+import com.salesmanager.core.business.order.model.OrderValueType;
+import com.salesmanager.core.business.order.model.Order_;
+import com.salesmanager.core.business.order.model.orderproduct.OrderProduct;
+import com.salesmanager.core.business.order.model.orderstatus.OrderStatus;
+import com.salesmanager.core.business.order.model.orderstatus.OrderStatusHistory;
+import com.salesmanager.core.business.payments.model.Payment;
+import com.salesmanager.core.business.payments.model.Transaction;
+import com.salesmanager.core.business.payments.service.PaymentService;
+import com.salesmanager.core.business.payments.service.TransactionService;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.shipping.model.ShippingConfiguration;
+import com.salesmanager.core.business.shipping.service.ShippingService;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCart;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartItem;
+import com.salesmanager.core.business.tax.model.TaxItem;
+import com.salesmanager.core.business.tax.service.TaxService;
+import com.salesmanager.core.constants.Constants;
+import com.salesmanager.core.modules.order.InvoiceModule;
+
+
+@Service("orderService")
+public class OrderServiceImpl extends SalesManagerEntityServiceImpl<Long, Order> implements OrderService {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(OrderServiceImpl.class);
+
+ @Autowired
+ private InvoiceModule invoiceModule;
+
+ @Autowired
+ private ShippingService shippingService;
+
+ @Autowired
+ private PaymentService paymentService;
+
+ @Autowired
+ private TaxService taxService;
+
+ @Autowired
+ private CustomerService customerService;
+
+ @Autowired
+ private TransactionService transactionService;
+
+ private final OrderDao orderDao;
+
+ @Autowired
+ public OrderServiceImpl(final OrderDao orderDao) {
+ super(orderDao);
+ this.orderDao = orderDao;
+ }
+
+ @Override
+ public void addOrderStatusHistory(final Order order, final OrderStatusHistory history) throws ServiceException {
+ order.getOrderHistory().add(history);
+ history.setOrder(order);
+ update(order);
+ }
+
+ @Override
+ public Order processOrder(Order order, Customer customer, List<ShoppingCartItem> items, OrderTotalSummary summary, Payment payment, MerchantStore store) throws ServiceException {
+
+ return this.process(order, customer, items, summary, payment, null, store);
+ }
+
+ @Override
+ public Order processOrder(Order order, Customer customer, List<ShoppingCartItem> items, OrderTotalSummary summary, Payment payment, Transaction transaction, MerchantStore store) throws ServiceException {
+
+ return this.process(order, customer, items, summary, payment, transaction, store);
+ }
+
+ private Order process(Order order, Customer customer, List<ShoppingCartItem> items, OrderTotalSummary summary, Payment payment, Transaction transaction, MerchantStore store) throws ServiceException {
+
+
+ Validate.notNull(order, "Order cannot be null");
+ Validate.notNull(customer, "Customer cannot be null (even if anonymous order)");
+ Validate.notEmpty(items, "ShoppingCart items cannot be null");
+ Validate.notNull(payment, "Payment cannot be null");
+ Validate.notNull(store, "MerchantStore cannot be null");
+ Validate.notNull(summary, "Order total Summary cannot be null");
+
+ //first process payment
+ Transaction processTransaction = paymentService.processPayment(customer, store, payment, items, order);
+ //transactionService.save(processTransaction);
+
+ if(order.getOrderHistory()==null || order.getOrderHistory().size()==0 || order.getStatus()==null) {
+ OrderStatus status = order.getStatus();
+ if(status==null) {
+ status = OrderStatus.ORDERED;
+ order.setStatus(status);
+ }
+ Set<OrderStatusHistory> statusHistorySet = new HashSet<OrderStatusHistory>();
+ OrderStatusHistory statusHistory = new OrderStatusHistory();
+ statusHistory.setStatus(status);
+ statusHistory.setDateAdded(new Date());
+ statusHistory.setOrder(order);
+ statusHistorySet.add(statusHistory);
+ order.setOrderHistory(statusHistorySet);
+
+ }
+
+ if(customer.getId()==null || customer.getId()==0) {
+ customerService.create(customer);
+ }
+
+ order.setCustomerId(customer.getId());
+
+ this.create(order);
+
+ if(transaction!=null) {
+ transaction.setOrder(order);
+ if(transaction.getId()==null || transaction.getId()==0) {
+ transactionService.create(transaction);
+ } else {
+ transactionService.update(transaction);
+ }
+ }
+
+ if(processTransaction!=null) {
+ processTransaction.setOrder(order);
+ if(processTransaction.getId()==null || processTransaction.getId()==0) {
+ transactionService.create(processTransaction);
+ } else {
+ transactionService.update(processTransaction);
+ }
+ }
+
+ return order;
+
+
+ }
+
+ private OrderTotalSummary caculateOrder(final OrderSummary summary, final Customer customer, final MerchantStore store, final Language language) throws Exception {
+
+ OrderTotalSummary totalSummary = new OrderTotalSummary();
+ List<OrderTotal> orderTotals = new ArrayList<OrderTotal>();
+ Map<String,OrderTotal> otherPricesTotals = new HashMap<String,OrderTotal>();
+
+ ShippingConfiguration shippingConfiguration = null;
+
+ BigDecimal grandTotal = new BigDecimal(0);
+ grandTotal.setScale(2, RoundingMode.HALF_UP);
+
+ //price by item
+ /**
+ * qty * price
+ * subtotal
+ */
+ BigDecimal subTotal = new BigDecimal(0);
+ subTotal.setScale(2, RoundingMode.HALF_UP);
+ for(ShoppingCartItem item : summary.getProducts()) {
+
+ BigDecimal st = item.getItemPrice().multiply(new BigDecimal(item.getQuantity()));
+ item.setSubTotal(st);
+ subTotal = subTotal.add(st);
+ //Other prices
+ FinalPrice finalPrice = item.getFinalPrice();
+ if(finalPrice!=null) {
+ List<FinalPrice> otherPrices = finalPrice.getAdditionalPrices();
+ if(otherPrices!=null) {
+ for(FinalPrice price : otherPrices) {
+ if(!price.isDefaultPrice()) {
+ OrderTotal itemSubTotal = otherPricesTotals.get(price.getProductPrice().getCode());
+
+ if(itemSubTotal==null) {
+ itemSubTotal = new OrderTotal();
+ itemSubTotal.setModule(Constants.OT_ITEM_PRICE_MODULE_CODE);
+ itemSubTotal.setText(Constants.OT_ITEM_PRICE_MODULE_CODE);
+ itemSubTotal.setTitle(Constants.OT_ITEM_PRICE_MODULE_CODE);
+ itemSubTotal.setOrderTotalCode(price.getProductPrice().getCode());
+ itemSubTotal.setOrderTotalType(OrderTotalType.PRODUCT);
+ itemSubTotal.setSortOrder(0);
+ otherPricesTotals.put(price.getProductPrice().getCode(), itemSubTotal);
+ }
+
+ BigDecimal orderTotalValue = itemSubTotal.getValue();
+ if(orderTotalValue==null) {
+ orderTotalValue = new BigDecimal(0);
+ orderTotalValue.setScale(2, RoundingMode.HALF_UP);
+ }
+
+ orderTotalValue = orderTotalValue.add(price.getFinalPrice());
+ itemSubTotal.setValue(orderTotalValue);
+ if(price.getProductPrice().getProductPriceType().name().equals(OrderValueType.ONE_TIME)) {
+ subTotal = subTotal.add(price.getFinalPrice());
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+
+ totalSummary.setSubTotal(subTotal);
+ grandTotal=grandTotal.add(subTotal);
+
+ OrderTotal orderTotalSubTotal = new OrderTotal();
+ orderTotalSubTotal.setModule(Constants.OT_SUBTOTAL_MODULE_CODE);
+ orderTotalSubTotal.setOrderTotalType(OrderTotalType.SUBTOTAL);
+ orderTotalSubTotal.setOrderTotalCode("order.total.subtotal");
+ orderTotalSubTotal.setTitle(Constants.OT_SUBTOTAL_MODULE_CODE);
+ orderTotalSubTotal.setText("order.total.subtotal");
+ orderTotalSubTotal.setSortOrder(5);
+ orderTotalSubTotal.setValue(subTotal);
+
+ //TODO autowire a list of post processing modules for price calculation - drools, custom modules
+ //may affect the sub total
+
+ orderTotals.add(orderTotalSubTotal);
+
+
+ //shipping
+ if(summary.getShippingSummary()!=null) {
+
+
+ OrderTotal shippingSubTotal = new OrderTotal();
+ shippingSubTotal.setModule(Constants.OT_SHIPPING_MODULE_CODE);
+ shippingSubTotal.setOrderTotalType(OrderTotalType.SHIPPING);
+ shippingSubTotal.setOrderTotalCode("order.total.shipping");
+ shippingSubTotal.setTitle(Constants.OT_SHIPPING_MODULE_CODE);
+ shippingSubTotal.setText("order.total.shipping");
+ shippingSubTotal.setSortOrder(10);
+
+ orderTotals.add(shippingSubTotal);
+
+ if(!summary.getShippingSummary().isFreeShipping()) {
+ shippingSubTotal.setValue(summary.getShippingSummary().getShipping());
+ grandTotal=grandTotal.add(summary.getShippingSummary().getShipping());
+ } else {
+ shippingSubTotal.setValue(new BigDecimal(0));
+ grandTotal=grandTotal.add(new BigDecimal(0));
+ }
+
+ //check handling fees
+ shippingConfiguration = shippingService.getShippingConfiguration(store);
+ if(summary.getShippingSummary().getHandling()!=null && summary.getShippingSummary().getHandling().doubleValue()>0) {
+ if(shippingConfiguration.getHandlingFees()!=null && shippingConfiguration.getHandlingFees().doubleValue()>0) {
+ OrderTotal handlingubTotal = new OrderTotal();
+ handlingubTotal.setModule(Constants.OT_HANDLING_MODULE_CODE);
+ handlingubTotal.setOrderTotalType(OrderTotalType.HANDLING);
+ handlingubTotal.setOrderTotalCode("order.total.handling");
+ handlingubTotal.setTitle(Constants.OT_HANDLING_MODULE_CODE);
+ handlingubTotal.setText("order.total.handling");
+ handlingubTotal.setSortOrder(12);
+ handlingubTotal.setValue(summary.getShippingSummary().getHandling());
+ orderTotals.add(handlingubTotal);
+ grandTotal=grandTotal.add(summary.getShippingSummary().getHandling());
+ }
+ }
+ }
+
+ //tax
+ List<TaxItem> taxes = taxService.calculateTax(summary, customer, store, language);
+ if(taxes!=null && taxes.size()>0) {
+ BigDecimal totalTaxes = new BigDecimal(0);
+ totalTaxes.setScale(2, RoundingMode.HALF_UP);
+ int taxCount = 20;
+ for(TaxItem tax : taxes) {
+
+ OrderTotal taxLine = new OrderTotal();
+ taxLine.setModule(Constants.OT_TAX_MODULE_CODE);
+ taxLine.setOrderTotalType(OrderTotalType.TAX);
+ taxLine.setOrderTotalCode(tax.getLabel());
+ taxLine.setSortOrder(taxCount);
+ taxLine.setTitle(Constants.OT_TAX_MODULE_CODE);
+ taxLine.setText(tax.getLabel());
+ taxLine.setValue(tax.getItemPrice());
+
+ totalTaxes = totalTaxes.add(tax.getItemPrice());
+ orderTotals.add(taxLine);
+ //grandTotal=grandTotal.add(tax.getItemPrice());
+
+ taxCount ++;
+
+ }
+ grandTotal = grandTotal.add(totalTaxes);
+ totalSummary.setTaxTotal(totalTaxes);
+ }
+
+ // grand total
+ OrderTotal orderTotal = new OrderTotal();
+ orderTotal.setModule(Constants.OT_TOTAL_MODULE_CODE);
+ orderTotal.setOrderTotalType(OrderTotalType.TOTAL);
+ orderTotal.setOrderTotalCode("order.total.total");
+ orderTotal.setTitle(Constants.OT_TOTAL_MODULE_CODE);
+ orderTotal.setText("order.total.total");
+ orderTotal.setSortOrder(300);
+ orderTotal.setValue(grandTotal);
+ orderTotals.add(orderTotal);
+
+ totalSummary.setTotal(grandTotal);
+ totalSummary.setTotals(orderTotals);
+ return totalSummary;
+
+ }
+
+
+ @Override
+ public OrderTotalSummary caculateOrderTotal(final OrderSummary orderSummary, final Customer customer, final MerchantStore store, final Language language) throws ServiceException {
+ Validate.notNull(orderSummary,"Order summary cannot be null");
+ Validate.notNull(orderSummary.getProducts(),"Order summary.products cannot be null");
+ Validate.notNull(store,"MerchantStore cannot be null");
+ Validate.notNull(customer,"Customer cannot be null");
+
+ try {
+ return caculateOrder(orderSummary, customer, store, language);
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+ }
+
+
+
+ @Override
+ public OrderTotalSummary caculateOrderTotal(final OrderSummary orderSummary, final MerchantStore store, final Language language) throws ServiceException {
+ Validate.notNull(orderSummary,"Order summary cannot be null");
+ Validate.notNull(orderSummary.getProducts(),"Order summary.products cannot be null");
+ Validate.notNull(store,"MerchantStore cannot be null");
+
+ try {
+ return caculateOrder(orderSummary, null, store, language);
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+ }
+
+ private OrderTotalSummary caculateShoppingCart( final ShoppingCart shoppingCart, final Customer customer, final MerchantStore store, final Language language) throws Exception {
+
+
+
+
+
+ OrderSummary orderSummary = new OrderSummary();
+
+ List<ShoppingCartItem> itemsSet = new ArrayList<ShoppingCartItem>(shoppingCart.getLineItems());
+ orderSummary.setProducts(itemsSet);
+
+
+ return this.caculateOrder(orderSummary, customer, store, language);
+
+ }
+
+
+ /**
+ * <p>Method will be used to calculate Shopping cart total as well will update price for each
+ * line items.
+ * </p>
+ * @param shoppingCart
+ * @param customer
+ * @param store
+ * @param language
+ * @return {@link OrderTotalSummary}
+ * @throws ServiceException
+ *
+ */
+ @Override
+ public OrderTotalSummary calculateShoppingCartTotal(
+ final ShoppingCart shoppingCart, final Customer customer, final MerchantStore store,
+ final Language language) throws ServiceException {
+ Validate.notNull(shoppingCart,"Order summary cannot be null");
+ Validate.notNull(customer,"Customery cannot be null");
+ Validate.notNull(store,"MerchantStore cannot be null.");
+ try {
+ return caculateShoppingCart(shoppingCart, customer, store, language);
+ } catch (Exception e) {
+ LOGGER.error( "Error while calculating shopping cart total" +e );
+ throw new ServiceException(e);
+ }
+
+ }
+
+
+
+
+ /**
+ * <p>Method will be used to calculate Shopping cart total as well will update price for each
+ * line items.
+ * </p>
+ * @param shoppingCart
+ * @param store
+ * @param language
+ * @return {@link OrderTotalSummary}
+ * @throws ServiceException
+ *
+ */
+ @Override
+ public OrderTotalSummary calculateShoppingCartTotal(
+ final ShoppingCart shoppingCart, final MerchantStore store, final Language language)
+ throws ServiceException {
+ Validate.notNull(shoppingCart,"Order summary cannot be null");
+ Validate.notNull(store,"MerchantStore cannot be null");
+
+ try {
+ return caculateShoppingCart(shoppingCart, null, store, language);
+ } catch (Exception e) {
+ LOGGER.error( "Error while calculating shopping cart total" +e );
+ throw new ServiceException(e);
+ }
+ }
+
+ @Override
+ public void delete(final Order order) throws ServiceException {
+
+
+ super.delete(order);
+ }
+
+
+ @Override
+ public ByteArrayOutputStream generateInvoice(final MerchantStore store, final Order order, final Language language) throws ServiceException {
+
+ Validate.notNull(order.getOrderProducts(),"Order products cannot be null");
+ Validate.notNull(order.getOrderTotal(),"Order totals cannot be null");
+
+ try {
+ ByteArrayOutputStream stream = invoiceModule.createInvoice(store, order, language);
+ return stream;
+ } catch(Exception e) {
+ throw new ServiceException(e);
+ }
+
+
+
+ }
+
+ @Override
+ public Order getOrder(final Long orderId ) {
+ return getById(orderId);
+ }
+
+
+
+ @Override
+ public List<Order> listByStore(final MerchantStore merchantStore) {
+ return listByField(Order_.merchant, merchantStore);
+ }
+
+ @Override
+ public OrderList listByStore(final MerchantStore store, final OrderCriteria criteria) {
+
+ return orderDao.listByStore(store, criteria);
+ }
+
+
+ @Override
+ public void saveOrUpdate(final Order order) throws ServiceException {
+
+ if(order.getId()!=null && order.getId()>0) {
+ LOGGER.debug("Updating Order");
+ super.update(order);
+
+ } else {
+ LOGGER.debug("Creating Order");
+ super.create(order);
+
+ }
+ }
+
+ @Override
+ public boolean hasDownloadFiles(Order order) throws ServiceException {
+
+ Validate.notNull(order,"Order cannot be null");
+ Validate.notNull(order.getOrderProducts(),"Order products cannot be null");
+ Validate.notEmpty(order.getOrderProducts(),"Order products cannot be empty");
+
+ boolean hasDownloads = false;
+ for(OrderProduct orderProduct : order.getOrderProducts()) {
+
+ if(CollectionUtils.isNotEmpty(orderProduct.getDownloads())) {
+ hasDownloads = true;
+ break;
+ }
+ }
+
+ return hasDownloads;
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/payments/dao/TransactionDao.java b/sm-core/src/main/java/com/salesmanager/core/business/payments/dao/TransactionDao.java
new file mode 100644
index 0000000..9aa89cb
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/payments/dao/TransactionDao.java
@@ -0,0 +1,15 @@
+package com.salesmanager.core.business.payments.dao;
+
+import java.util.List;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.business.payments.model.Transaction;
+
+public interface TransactionDao extends SalesManagerEntityDao<Long, Transaction> {
+
+ List<Transaction> listByOrder(Order order);
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/payments/dao/TransactionDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/payments/dao/TransactionDaoImpl.java
new file mode 100644
index 0000000..9fb2528
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/payments/dao/TransactionDaoImpl.java
@@ -0,0 +1,33 @@
+package com.salesmanager.core.business.payments.dao;
+
+import java.util.List;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.business.payments.model.QTransaction;
+import com.salesmanager.core.business.payments.model.Transaction;
+
+@Repository("transactionDao")
+public class TransactionDaoImpl extends SalesManagerEntityDaoImpl<Long, Transaction>
+ implements TransactionDao {
+
+ @Override
+ public List<Transaction> listByOrder(Order order){
+ QTransaction qTransaction = QTransaction.transaction;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qTransaction)
+ .join(qTransaction.order).fetch()
+ .where(qTransaction.order.id.eq(order.getId()));
+
+ return query.list(qTransaction);
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/payments/model/BasicPayment.java b/sm-core/src/main/java/com/salesmanager/core/business/payments/model/BasicPayment.java
new file mode 100644
index 0000000..41fbee4
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/payments/model/BasicPayment.java
@@ -0,0 +1,11 @@
+package com.salesmanager.core.business.payments.model;
+
+
+/**
+ * When the user performs a payment using money order or cheque
+ * @author Carl Samson
+ *
+ */
+public class BasicPayment extends Payment {
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/payments/model/CreditCardPayment.java b/sm-core/src/main/java/com/salesmanager/core/business/payments/model/CreditCardPayment.java
new file mode 100644
index 0000000..2a5d4b0
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/payments/model/CreditCardPayment.java
@@ -0,0 +1,53 @@
+package com.salesmanager.core.business.payments.model;
+
+/**
+ * When the user performs a payment using a credit card
+ * @author Carl Samson
+ *
+ */
+public class CreditCardPayment extends Payment {
+
+ private String creditCardNumber;
+ private String credidCardValidationNumber;
+ private String expirationMonth;
+ private String expirationYear;
+ private String cardOwner;
+ private CreditCardType creditCard;
+ public String getCreditCardNumber() {
+ return creditCardNumber;
+ }
+ public void setCreditCardNumber(String creditCardNumber) {
+ this.creditCardNumber = creditCardNumber;
+ }
+ public String getCredidCardValidationNumber() {
+ return credidCardValidationNumber;
+ }
+ public void setCredidCardValidationNumber(String credidCardValidationNumber) {
+ this.credidCardValidationNumber = credidCardValidationNumber;
+ }
+ public String getExpirationMonth() {
+ return expirationMonth;
+ }
+ public void setExpirationMonth(String expirationMonth) {
+ this.expirationMonth = expirationMonth;
+ }
+ public String getExpirationYear() {
+ return expirationYear;
+ }
+ public void setExpirationYear(String expirationYear) {
+ this.expirationYear = expirationYear;
+ }
+ public String getCardOwner() {
+ return cardOwner;
+ }
+ public void setCardOwner(String cardOwner) {
+ this.cardOwner = cardOwner;
+ }
+ public CreditCardType getCreditCard() {
+ return creditCard;
+ }
+ public void setCreditCard(CreditCardType creditCard) {
+ this.creditCard = creditCard;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/payments/model/CreditCardType.java b/sm-core/src/main/java/com/salesmanager/core/business/payments/model/CreditCardType.java
new file mode 100644
index 0000000..7c7699d
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/payments/model/CreditCardType.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.payments.model;
+
+public enum CreditCardType {
+
+ AMEX, VISA, MASTERCARD, DINERS, DISCOVERY
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/payments/model/Payment.java b/sm-core/src/main/java/com/salesmanager/core/business/payments/model/Payment.java
new file mode 100644
index 0000000..785933b
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/payments/model/Payment.java
@@ -0,0 +1,44 @@
+package com.salesmanager.core.business.payments.model;
+
+import com.salesmanager.core.business.reference.currency.model.Currency;
+
+public class Payment {
+
+ private PaymentType paymentType;
+ private TransactionType transactionType = TransactionType.AUTHORIZECAPTURE;
+ private String moduleName;
+ private Currency currency;
+
+ public void setPaymentType(PaymentType paymentType) {
+ this.paymentType = paymentType;
+ }
+
+ public PaymentType getPaymentType() {
+ return paymentType;
+ }
+
+ public void setTransactionType(TransactionType transactionType) {
+ this.transactionType = transactionType;
+ }
+
+ public TransactionType getTransactionType() {
+ return transactionType;
+ }
+
+ public void setModuleName(String moduleName) {
+ this.moduleName = moduleName;
+ }
+
+ public String getModuleName() {
+ return moduleName;
+ }
+
+ public Currency getCurrency() {
+ return currency;
+ }
+
+ public void setCurrency(Currency currency) {
+ this.currency = currency;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/payments/model/PaymentMethod.java b/sm-core/src/main/java/com/salesmanager/core/business/payments/model/PaymentMethod.java
new file mode 100644
index 0000000..effca46
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/payments/model/PaymentMethod.java
@@ -0,0 +1,57 @@
+package com.salesmanager.core.business.payments.model;
+
+import java.io.Serializable;
+
+import com.salesmanager.core.business.system.model.IntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+
+/**
+ * Object to be used in store front with meta data and configuration
+ * informations required to display to the end user
+ * @author Carl Samson
+ *
+ */
+public class PaymentMethod implements Serializable {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+ private String paymentMethodCode;
+ private PaymentType paymentType;
+ private boolean defaultSelected;
+ private IntegrationModule module;
+ private IntegrationConfiguration informations;
+
+ public PaymentType getPaymentType() {
+ return paymentType;
+ }
+ public void setPaymentType(PaymentType paymentType) {
+ this.paymentType = paymentType;
+ }
+ public String getPaymentMethodCode() {
+ return paymentMethodCode;
+ }
+ public void setPaymentMethodCode(String paymentMethodCode) {
+ this.paymentMethodCode = paymentMethodCode;
+ }
+ public boolean isDefaultSelected() {
+ return defaultSelected;
+ }
+ public void setDefaultSelected(boolean defaultSelected) {
+ this.defaultSelected = defaultSelected;
+ }
+ public IntegrationModule getModule() {
+ return module;
+ }
+ public void setModule(IntegrationModule module) {
+ this.module = module;
+ }
+ public IntegrationConfiguration getInformations() {
+ return informations;
+ }
+ public void setInformations(IntegrationConfiguration informations) {
+ this.informations = informations;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/payments/model/PaymentType.java b/sm-core/src/main/java/com/salesmanager/core/business/payments/model/PaymentType.java
new file mode 100644
index 0000000..0bbd1eb
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/payments/model/PaymentType.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.payments.model;
+
+public enum PaymentType {
+
+ CREDITCARD, FREE, COD, MONEYORDER, PAYPAL
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/payments/model/PaypalPayment.java b/sm-core/src/main/java/com/salesmanager/core/business/payments/model/PaypalPayment.java
new file mode 100644
index 0000000..67b5880
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/payments/model/PaypalPayment.java
@@ -0,0 +1,31 @@
+package com.salesmanager.core.business.payments.model;
+
+/**
+ * When the user performs a payment using paypal
+ * @author Carl Samson
+ *
+ */
+public class PaypalPayment extends Payment {
+
+ //express checkout
+ private String payerId;
+ private String paymentToken;
+
+ public PaypalPayment() {
+ super.setPaymentType(PaymentType.PAYPAL);
+ }
+
+ public void setPayerId(String payerId) {
+ this.payerId = payerId;
+ }
+ public String getPayerId() {
+ return payerId;
+ }
+ public void setPaymentToken(String paymentToken) {
+ this.paymentToken = paymentToken;
+ }
+ public String getPaymentToken() {
+ return paymentToken;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/payments/model/Transaction.java b/sm-core/src/main/java/com/salesmanager/core/business/payments/model/Transaction.java
new file mode 100644
index 0000000..50eff18
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/payments/model/Transaction.java
@@ -0,0 +1,183 @@
+package com.salesmanager.core.business.payments.model;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.persistence.Transient;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.hibernate.annotations.Type;
+import org.json.simple.JSONAware;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.salesmanager.core.business.common.model.audit.AuditListener;
+import com.salesmanager.core.business.common.model.audit.AuditSection;
+import com.salesmanager.core.business.common.model.audit.Auditable;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.constants.SchemaConstant;
+
+
+@Entity
+@EntityListeners(value = AuditListener.class)
+@Table(name = "SM_TRANSACTION", schema= SchemaConstant.SALESMANAGER_SCHEMA)
+public class Transaction extends SalesManagerEntity<Long, Transaction> implements Serializable, Auditable, JSONAware {
+
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(Transaction.class);
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @Column(name = "TRANSACTION_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "TRANSACT_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @Embedded
+ private AuditSection auditSection = new AuditSection();
+
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="ORDER_ID", nullable=true)
+ private Order order;
+
+ @Column(name="AMOUNT")
+ private BigDecimal amount;
+
+ @Column(name="TRANSACTION_DATE")
+ @Temporal(TemporalType.TIMESTAMP)
+ private Date transactionDate;
+
+ @Column(name="TRANSACTION_TYPE")
+ @Enumerated(value = EnumType.STRING)
+ private TransactionType transactionType;
+
+ @Column(name="PAYMENT_TYPE")
+ @Enumerated(value = EnumType.STRING)
+ private PaymentType paymentType;
+
+ @Column(name="DETAILS")
+ @Type(type = "org.hibernate.type.StringClobType")
+ private String details;
+
+ @Transient
+ private Map<String,String> transactionDetails= new HashMap<String,String>();
+
+ @Override
+ public AuditSection getAuditSection() {
+ return this.auditSection;
+ }
+
+ @Override
+ public void setAuditSection(AuditSection audit) {
+ this.auditSection = audit;
+
+ }
+
+ @Override
+ public Long getId() {
+ return this.id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+
+ }
+
+ public Order getOrder() {
+ return order;
+ }
+
+ public void setOrder(Order order) {
+ this.order = order;
+ }
+
+ public BigDecimal getAmount() {
+ return amount;
+ }
+
+ public void setAmount(BigDecimal amount) {
+ this.amount = amount;
+ }
+
+ public Date getTransactionDate() {
+ return transactionDate;
+ }
+
+ public void setTransactionDate(Date transactionDate) {
+ this.transactionDate = transactionDate;
+ }
+
+ public TransactionType getTransactionType() {
+ return transactionType;
+ }
+
+ public void setTransactionType(TransactionType transactionType) {
+ this.transactionType = transactionType;
+ }
+
+ public PaymentType getPaymentType() {
+ return paymentType;
+ }
+
+ public void setPaymentType(PaymentType paymentType) {
+ this.paymentType = paymentType;
+ }
+
+ public String getDetails() {
+ return details;
+ }
+
+ public void setDetails(String details) {
+ this.details = details;
+ }
+
+ public Map<String, String> getTransactionDetails() {
+ return transactionDetails;
+ }
+
+ public void setTransactionDetails(Map<String, String> transactionDetails) {
+ this.transactionDetails = transactionDetails;
+ }
+
+ @Override
+ public String toJSONString() {
+
+ if(this.getTransactionDetails()!=null && this.getTransactionDetails().size()>0) {
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ return mapper.writeValueAsString(this.getTransactionDetails());
+ } catch (Exception e) {
+ LOGGER.error("Cannot parse transactions map",e);
+ }
+
+ }
+
+ return null;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/payments/model/TransactionType.java b/sm-core/src/main/java/com/salesmanager/core/business/payments/model/TransactionType.java
new file mode 100644
index 0000000..3015853
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/payments/model/TransactionType.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.payments.model;
+
+public enum TransactionType {
+
+ INIT, AUTHORIZE, CAPTURE, AUTHORIZECAPTURE, REFUND
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/payments/service/PaymentService.java b/sm-core/src/main/java/com/salesmanager/core/business/payments/service/PaymentService.java
new file mode 100644
index 0000000..ef7bc9c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/payments/service/PaymentService.java
@@ -0,0 +1,103 @@
+package com.salesmanager.core.business.payments.service;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Map;
+
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.business.payments.model.CreditCardType;
+import com.salesmanager.core.business.payments.model.Payment;
+import com.salesmanager.core.business.payments.model.PaymentMethod;
+import com.salesmanager.core.business.payments.model.Transaction;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartItem;
+import com.salesmanager.core.business.system.model.IntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+import com.salesmanager.core.modules.integration.payment.model.PaymentModule;
+
+public interface PaymentService {
+
+
+
+ public List<IntegrationModule> getPaymentMethods(MerchantStore store)
+ throws ServiceException;
+
+ Map<String, IntegrationConfiguration> getPaymentModulesConfigured(
+ MerchantStore store) throws ServiceException;
+
+ Transaction processPayment(Customer customer, MerchantStore store, Payment payment, List<ShoppingCartItem> items, Order order) throws ServiceException;
+ Transaction processRefund(Order order, Customer customer, MerchantStore store, BigDecimal amount) throws ServiceException;
+
+ /**
+ * Get a specific Payment module by payment type CREDITCART, MONEYORDER ...
+ * @param store
+ * @param type (payment type)
+ * @return IntegrationModule
+ * @throws ServiceException
+ */
+ IntegrationModule getPaymentMethodByType(MerchantStore store, String type)
+ throws ServiceException;
+
+ /**
+ * Get a specific Payment module by payment code (defined in integrationmoduel.json) paypal, authorizenet ..
+ * @param store
+ * @param name
+ * @return IntegrationModule
+ * @throws ServiceException
+ */
+ IntegrationModule getPaymentMethodByCode(MerchantStore store, String name)
+ throws ServiceException;
+
+ /**
+ * Saves a payment module configuration
+ * @param configuration
+ * @param store
+ * @throws ServiceException
+ */
+ void savePaymentModuleConfiguration(IntegrationConfiguration configuration,
+ MerchantStore store) throws ServiceException;
+
+ /**
+ * Validates if the credit card input information are correct
+ * @param number
+ * @param type
+ * @param month
+ * @param date
+ * @throws ServiceException
+ */
+ void validateCreditCard(String number, CreditCardType creditCard, String month, String date)
+ throws ServiceException;
+
+ /**
+ * Get the integration configuration
+ * for a specific payment module
+ * @param moduleCode
+ * @param store
+ * @return IntegrationConfiguration
+ * @throws ServiceException
+ */
+ IntegrationConfiguration getPaymentConfiguration(String moduleCode,
+ MerchantStore store) throws ServiceException;
+
+ void removePaymentModuleConfiguration(String moduleCode, MerchantStore store)
+ throws ServiceException;
+
+ Transaction processCapturePayment(Order order, Customer customer,
+ MerchantStore store)
+ throws ServiceException;
+
+ List<PaymentMethod> getAcceptedPaymentMethods(MerchantStore store)
+ throws ServiceException;
+
+ /**
+ * Returns a PaymentModule based on the payment code
+ * @param paymentModuleCode
+ * @return PaymentModule
+ * @throws ServiceException
+ */
+ PaymentModule getPaymentModule(String paymentModuleCode)
+ throws ServiceException;
+
+}
\ No newline at end of file
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/payments/service/PaymentServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/payments/service/PaymentServiceImpl.java
new file mode 100644
index 0000000..3adc63a
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/payments/service/PaymentServiceImpl.java
@@ -0,0 +1,694 @@
+package com.salesmanager.core.business.payments.service;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.annotation.Resource;
+
+import org.apache.commons.lang.Validate;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.business.order.model.OrderTotal;
+import com.salesmanager.core.business.order.model.OrderTotalType;
+import com.salesmanager.core.business.order.model.orderstatus.OrderStatus;
+import com.salesmanager.core.business.order.model.orderstatus.OrderStatusHistory;
+import com.salesmanager.core.business.order.service.OrderService;
+import com.salesmanager.core.business.payments.model.CreditCardPayment;
+import com.salesmanager.core.business.payments.model.CreditCardType;
+import com.salesmanager.core.business.payments.model.Payment;
+import com.salesmanager.core.business.payments.model.PaymentMethod;
+import com.salesmanager.core.business.payments.model.PaymentType;
+import com.salesmanager.core.business.payments.model.Transaction;
+import com.salesmanager.core.business.payments.model.TransactionType;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartItem;
+import com.salesmanager.core.business.system.model.IntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+import com.salesmanager.core.business.system.model.MerchantConfiguration;
+import com.salesmanager.core.business.system.service.MerchantConfigurationService;
+import com.salesmanager.core.business.system.service.ModuleConfigurationService;
+import com.salesmanager.core.constants.Constants;
+import com.salesmanager.core.modules.integration.IntegrationException;
+import com.salesmanager.core.modules.integration.payment.model.PaymentModule;
+import com.salesmanager.core.modules.utils.Encryption;
+import com.salesmanager.core.utils.reference.ConfigurationModulesLoader;
+
+@Service("paymentService")
+public class PaymentServiceImpl implements PaymentService {
+
+
+
+ private final static String PAYMENT_MODULES = "PAYMENT";
+
+ @Autowired
+ private MerchantConfigurationService merchantConfigurationService;
+
+ @Autowired
+ private ModuleConfigurationService moduleConfigurationService;
+
+ @Autowired
+ private TransactionService transactionService;
+
+ @Autowired
+ private OrderService orderService;
+
+ @Autowired
+ @Resource(name="paymentModules")
+ private Map<String,PaymentModule> paymentModules;
+
+ @Autowired
+ private Encryption encryption;
+
+ @Override
+ public List<IntegrationModule> getPaymentMethods(MerchantStore store) throws ServiceException {
+
+ List<IntegrationModule> modules = moduleConfigurationService.getIntegrationModules(PAYMENT_MODULES);
+ List<IntegrationModule> returnModules = new ArrayList<IntegrationModule>();
+
+ for(IntegrationModule module : modules) {
+ if(module.getRegionsSet().contains(store.getCountry().getIsoCode())
+ || module.getRegionsSet().contains("*")) {
+
+ returnModules.add(module);
+ }
+ }
+
+ return returnModules;
+ }
+
+ @Override
+ public List<PaymentMethod> getAcceptedPaymentMethods(MerchantStore store) throws ServiceException {
+
+ Map<String,IntegrationConfiguration> modules = this.getPaymentModulesConfigured(store);
+
+ List<PaymentMethod> returnModules = new ArrayList<PaymentMethod>();
+
+ for(String module : modules.keySet()) {
+ IntegrationConfiguration config = modules.get(module);
+ if(config.isActive()) {
+
+ IntegrationModule md = this.getPaymentMethodByCode(store, config.getModuleCode());
+ if(md==null) {
+ continue;
+ }
+ PaymentMethod paymentMethod = new PaymentMethod();
+
+ paymentMethod.setDefaultSelected(config.isDefaultSelected());
+ paymentMethod.setPaymentMethodCode(config.getModuleCode());
+ paymentMethod.setModule(md);
+ paymentMethod.setInformations(config);
+ PaymentType type = PaymentType.COD;
+ if(md.getType().equalsIgnoreCase(PaymentType.CREDITCARD.name())) {
+ type = PaymentType.CREDITCARD;
+ } else if(md.getType().equalsIgnoreCase(PaymentType.FREE.name())) {
+ type = PaymentType.FREE;
+ } else if(md.getType().equalsIgnoreCase(PaymentType.MONEYORDER.name())) {
+ type = PaymentType.MONEYORDER;
+ } else if(md.getType().equalsIgnoreCase(PaymentType.PAYPAL.name())) {
+ type = PaymentType.PAYPAL;
+ }
+ paymentMethod.setPaymentType(type);
+ returnModules.add(paymentMethod);
+ }
+ }
+
+ return returnModules;
+
+
+ }
+
+ @Override
+ public IntegrationModule getPaymentMethodByType(MerchantStore store, String type) throws ServiceException {
+ List<IntegrationModule> modules = getPaymentMethods(store);
+
+ for(IntegrationModule module : modules) {
+ if(module.getModule().equals(type)) {
+
+ return module;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public IntegrationModule getPaymentMethodByCode(MerchantStore store,
+ String code) throws ServiceException {
+ List<IntegrationModule> modules = getPaymentMethods(store);
+
+ for(IntegrationModule module : modules) {
+ if(module.getCode().equals(code)) {
+
+ return module;
+ }
+ }
+
+ return null;
+ }
+
+ @Override
+ public IntegrationConfiguration getPaymentConfiguration(String moduleCode, MerchantStore store) throws ServiceException {
+
+
+ Map<String,IntegrationConfiguration> configuredModules = getPaymentModulesConfigured(store);
+ if(configuredModules!=null) {
+ for(String key : configuredModules.keySet()) {
+ if(key.equals(moduleCode)) {
+ return configuredModules.get(key);
+ }
+ }
+ }
+
+ return null;
+
+ }
+
+
+
+ @Override
+ public Map<String,IntegrationConfiguration> getPaymentModulesConfigured(MerchantStore store) throws ServiceException {
+
+ try {
+
+ Map<String,IntegrationConfiguration> modules = new HashMap<String,IntegrationConfiguration>();
+ MerchantConfiguration merchantConfiguration = merchantConfigurationService.getMerchantConfiguration(PAYMENT_MODULES, store);
+ if(merchantConfiguration!=null) {
+
+ if(!StringUtils.isBlank(merchantConfiguration.getValue())) {
+
+ String decrypted = encryption.decrypt(merchantConfiguration.getValue());
+ modules = ConfigurationModulesLoader.loadIntegrationConfigurations(decrypted);
+
+
+ }
+ }
+ return modules;
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+ }
+
+ @Override
+ public void savePaymentModuleConfiguration(IntegrationConfiguration configuration, MerchantStore store) throws ServiceException {
+
+ //validate entries
+ try {
+
+ String moduleCode = configuration.getModuleCode();
+ PaymentModule module = (PaymentModule)paymentModules.get(moduleCode);
+ if(module==null) {
+ throw new ServiceException("Payment module " + moduleCode + " does not exist");
+ }
+ module.validateModuleConfiguration(configuration, store);
+
+ } catch (IntegrationException ie) {
+ throw ie;
+ }
+
+ try {
+ Map<String,IntegrationConfiguration> modules = new HashMap<String,IntegrationConfiguration>();
+ MerchantConfiguration merchantConfiguration = merchantConfigurationService.getMerchantConfiguration(PAYMENT_MODULES, store);
+ if(merchantConfiguration!=null) {
+ if(!StringUtils.isBlank(merchantConfiguration.getValue())) {
+
+ String decrypted = encryption.decrypt(merchantConfiguration.getValue());
+
+ modules = ConfigurationModulesLoader.loadIntegrationConfigurations(decrypted);
+ }
+ } else {
+ merchantConfiguration = new MerchantConfiguration();
+ merchantConfiguration.setMerchantStore(store);
+ merchantConfiguration.setKey(PAYMENT_MODULES);
+ }
+ modules.put(configuration.getModuleCode(), configuration);
+
+ String configs = ConfigurationModulesLoader.toJSONString(modules);
+
+ String encrypted = encryption.encrypt(configs);
+ merchantConfiguration.setValue(encrypted);
+
+ merchantConfigurationService.saveOrUpdate(merchantConfiguration);
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+ }
+
+ @Override
+ public void removePaymentModuleConfiguration(String moduleCode, MerchantStore store) throws ServiceException {
+
+
+
+ try {
+ Map<String,IntegrationConfiguration> modules = new HashMap<String,IntegrationConfiguration>();
+ MerchantConfiguration merchantConfiguration = merchantConfigurationService.getMerchantConfiguration(PAYMENT_MODULES, store);
+ if(merchantConfiguration!=null) {
+
+ if(!StringUtils.isBlank(merchantConfiguration.getValue())) {
+
+ String decrypted = encryption.decrypt(merchantConfiguration.getValue());
+ modules = ConfigurationModulesLoader.loadIntegrationConfigurations(decrypted);
+ }
+
+ modules.remove(moduleCode);
+ String configs = ConfigurationModulesLoader.toJSONString(modules);
+
+ String encrypted = encryption.encrypt(configs);
+ merchantConfiguration.setValue(encrypted);
+
+ merchantConfigurationService.saveOrUpdate(merchantConfiguration);
+
+
+ }
+
+ MerchantConfiguration configuration = merchantConfigurationService.getMerchantConfiguration(moduleCode, store);
+
+ if(configuration!=null) {//custom module
+
+ merchantConfigurationService.delete(configuration);
+ }
+
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+ }
+
+
+
+
+
+ @Override
+ public Transaction processPayment(Customer customer,
+ MerchantStore store, Payment payment, List<ShoppingCartItem> items, Order order)
+ throws ServiceException {
+
+
+ Validate.notNull(customer);
+ Validate.notNull(store);
+ Validate.notNull(payment);
+ Validate.notNull(order);
+ Validate.notNull(order.getTotal());
+
+ payment.setCurrency(store.getCurrency());
+
+ BigDecimal amount = order.getTotal();
+
+ //must have a shipping module configured
+ Map<String, IntegrationConfiguration> modules = this.getPaymentModulesConfigured(store);
+ if(modules==null){
+ throw new ServiceException("No payment module configured");
+ }
+
+ IntegrationConfiguration configuration = modules.get(payment.getModuleName());
+
+ if(configuration==null) {
+ throw new ServiceException("Payment module " + payment.getModuleName() + " is not configured");
+ }
+
+ if(!configuration.isActive()) {
+ throw new ServiceException("Payment module " + payment.getModuleName() + " is not active");
+ }
+
+ String sTransactionType = configuration.getIntegrationKeys().get("transaction");
+ if(sTransactionType==null) {
+ sTransactionType = TransactionType.AUTHORIZECAPTURE.name();
+ }
+
+
+ if(sTransactionType.equals(TransactionType.AUTHORIZE.name())) {
+ payment.setTransactionType(TransactionType.AUTHORIZE);
+ } else {
+ payment.setTransactionType(TransactionType.AUTHORIZECAPTURE);
+ }
+
+
+ PaymentModule module = this.paymentModules.get(payment.getModuleName());
+
+ if(module==null) {
+ throw new ServiceException("Payment module " + payment.getModuleName() + " does not exist");
+ }
+
+ if(payment instanceof CreditCardPayment) {
+ CreditCardPayment creditCardPayment = (CreditCardPayment)payment;
+ validateCreditCard(creditCardPayment.getCreditCardNumber(),creditCardPayment.getCreditCard(),creditCardPayment.getExpirationMonth(),creditCardPayment.getExpirationYear());
+ }
+
+ IntegrationModule integrationModule = getPaymentMethodByCode(store,payment.getModuleName());
+ TransactionType transactionType = TransactionType.valueOf(sTransactionType);
+ if(transactionType==null) {
+ transactionType = payment.getTransactionType();
+ if(transactionType.equals(TransactionType.CAPTURE.name())) {
+ throw new ServiceException("This method does not allow to process capture transaction. Use processCapturePayment");
+ }
+ }
+
+ Transaction transaction = null;
+ if(transactionType == TransactionType.AUTHORIZE) {
+ transaction = module.authorize(store, customer, items, amount, payment, configuration, integrationModule);
+ } else if(transactionType == TransactionType.AUTHORIZECAPTURE) {
+ transaction = module.authorizeAndCapture(store, customer, items, amount, payment, configuration, integrationModule);
+ } else if(transactionType == TransactionType.INIT) {
+ transaction = module.initTransaction(store, customer, amount, payment, configuration, integrationModule);
+ }
+
+
+ if(transactionType != TransactionType.INIT) {
+ transactionService.create(transaction);
+ }
+
+ if(transactionType == TransactionType.AUTHORIZECAPTURE) {
+ order.setStatus(OrderStatus.ORDERED);
+ if(payment.getPaymentType().name()!=PaymentType.MONEYORDER.name()) {
+ order.setStatus(OrderStatus.PROCESSED);
+ }
+ }
+
+ return transaction;
+
+
+
+ }
+
+ @Override
+ public PaymentModule getPaymentModule(String paymentModuleCode) throws ServiceException {
+ return paymentModules.get(paymentModuleCode);
+ }
+
+ @Override
+ public Transaction processCapturePayment(Order order, Customer customer,
+ MerchantStore store)
+ throws ServiceException {
+
+
+ Validate.notNull(customer);
+ Validate.notNull(store);
+ Validate.notNull(order);
+
+
+
+ //must have a shipping module configured
+ Map<String, IntegrationConfiguration> modules = this.getPaymentModulesConfigured(store);
+ if(modules==null){
+ throw new ServiceException("No payment module configured");
+ }
+
+ IntegrationConfiguration configuration = modules.get(order.getPaymentModuleCode());
+
+ if(configuration==null) {
+ throw new ServiceException("Payment module " + order.getPaymentModuleCode() + " is not configured");
+ }
+
+ if(!configuration.isActive()) {
+ throw new ServiceException("Payment module " + order.getPaymentModuleCode() + " is not active");
+ }
+
+
+ PaymentModule module = this.paymentModules.get(order.getPaymentModuleCode());
+
+ if(module==null) {
+ throw new ServiceException("Payment module " + order.getPaymentModuleCode() + " does not exist");
+ }
+
+
+ IntegrationModule integrationModule = getPaymentMethodByCode(store,order.getPaymentModuleCode());
+
+ //TransactionType transactionType = payment.getTransactionType();
+
+ //get the previous transaction
+ Transaction trx = transactionService.getCapturableTransaction(order);
+ if(trx==null) {
+ throw new ServiceException("No capturable transaction for order id " + order.getId());
+ }
+ Transaction transaction = module.capture(store, customer, order, trx, configuration, integrationModule);
+ transaction.setOrder(order);
+
+
+
+ transactionService.create(transaction);
+
+
+ OrderStatusHistory orderHistory = new OrderStatusHistory();
+ orderHistory.setOrder(order);
+ orderHistory.setStatus(OrderStatus.PROCESSED);
+ orderHistory.setDateAdded(new Date());
+
+ orderService.addOrderStatusHistory(order, orderHistory);
+
+ order.setStatus(OrderStatus.PROCESSED);
+ orderService.saveOrUpdate(order);
+
+ return transaction;
+
+
+
+ }
+
+ @Override
+ public Transaction processRefund(Order order, Customer customer,
+ MerchantStore store, BigDecimal amount)
+ throws ServiceException {
+
+
+ Validate.notNull(customer);
+ Validate.notNull(store);
+ Validate.notNull(amount);
+ Validate.notNull(order);
+ Validate.notNull(order.getOrderTotal());
+
+
+ BigDecimal orderTotal = order.getTotal();
+
+ if(amount.doubleValue()>orderTotal.doubleValue()) {
+ throw new ServiceException("Invalid amount, the refunded amount is greater than the total allowed");
+ }
+
+
+ String module = order.getPaymentModuleCode();
+ Map<String, IntegrationConfiguration> modules = this.getPaymentModulesConfigured(store);
+ if(modules==null){
+ throw new ServiceException("No payment module configured");
+ }
+
+ IntegrationConfiguration configuration = modules.get(module);
+
+ if(configuration==null) {
+ throw new ServiceException("Payment module " + module + " is not configured");
+ }
+
+ PaymentModule paymentModule = this.paymentModules.get(module);
+
+ if(paymentModule==null) {
+ throw new ServiceException("Payment module " + paymentModule + " does not exist");
+ }
+
+ boolean partial = false;
+ if(amount.doubleValue()!=order.getTotal().doubleValue()) {
+ partial = true;
+ }
+
+ IntegrationModule integrationModule = getPaymentMethodByCode(store,module);
+
+ //get the associated transaction
+ Transaction refundable = transactionService.getRefundableTransaction(order);
+
+ if(refundable==null) {
+ throw new ServiceException("No refundable transaction for this order");
+ }
+
+ Transaction transaction = paymentModule.refund(partial, store, refundable, order, amount, configuration, integrationModule);
+ transaction.setOrder(order);
+ transactionService.create(transaction);
+
+ OrderTotal refund = new OrderTotal();
+ refund.setModule(Constants.OT_REFUND_MODULE_CODE);
+ refund.setText(Constants.OT_REFUND_MODULE_CODE);
+ refund.setTitle(Constants.OT_REFUND_MODULE_CODE);
+ refund.setOrderTotalCode(Constants.OT_REFUND_MODULE_CODE);
+ refund.setOrderTotalType(OrderTotalType.REFUND);
+ refund.setValue(amount);
+ refund.setSortOrder(100);
+ refund.setOrder(order);
+
+ order.getOrderTotal().add(refund);
+
+ //update order total
+ orderTotal = orderTotal.subtract(amount);
+
+ //update ordertotal refund
+ Set<OrderTotal> totals = order.getOrderTotal();
+ for(OrderTotal total : totals) {
+ if(total.getModule().equals(Constants.OT_TOTAL_MODULE_CODE)) {
+ total.setValue(orderTotal);
+ }
+ }
+
+
+
+ order.setTotal(orderTotal);
+ order.setStatus(OrderStatus.REFUNDED);
+
+
+
+ OrderStatusHistory orderHistory = new OrderStatusHistory();
+ orderHistory.setOrder(order);
+ orderHistory.setStatus(OrderStatus.REFUNDED);
+ orderHistory.setDateAdded(new Date());
+ order.getOrderHistory().add(orderHistory);
+
+ orderService.saveOrUpdate(order);
+
+ return transaction;
+ }
+
+ @Override
+ public void validateCreditCard(String number, CreditCardType creditCard, String month, String date)
+ throws ServiceException {
+
+ try {
+ Integer.parseInt(month);
+ Integer.parseInt(date);
+ } catch (NumberFormatException nfe) {
+ ServiceException ex = new ServiceException(ServiceException.EXCEPTION_VALIDATION,"Invalid date format","messages.error.creditcard.dateformat");
+ throw ex;
+ }
+
+ if (StringUtils.isBlank(number)) {
+ ServiceException ex = new ServiceException(ServiceException.EXCEPTION_VALIDATION,"Invalid card number","messages.error.creditcard.number");
+ throw ex;
+ }
+
+ Matcher m = Pattern.compile("[^\\d\\s.-]").matcher(number);
+
+ if (m.find()) {
+ ServiceException ex = new ServiceException(ServiceException.EXCEPTION_VALIDATION,"Invalid card number","messages.error.creditcard.number");
+ throw ex;
+ }
+
+ Matcher matcher = Pattern.compile("[\\s.-]").matcher(number);
+
+ number = matcher.replaceAll("");
+ validateCreditCardDate(Integer.parseInt(month), Integer.parseInt(date));
+ validateCreditCardNumber(number, creditCard);
+ }
+
+ private void validateCreditCardDate(int m, int y) throws ServiceException {
+ java.util.Calendar cal = new java.util.GregorianCalendar();
+ int monthNow = cal.get(java.util.Calendar.MONTH) + 1;
+ int yearNow = cal.get(java.util.Calendar.YEAR);
+ if (yearNow > y) {
+ ServiceException ex = new ServiceException(ServiceException.EXCEPTION_VALIDATION,"Invalid date format","messages.error.creditcard.dateformat");
+ throw ex;
+ }
+ // OK, change implementation
+ if (yearNow == y && monthNow > m) {
+ ServiceException ex = new ServiceException(ServiceException.EXCEPTION_VALIDATION,"Invalid date format","messages.error.creditcard.dateformat");
+ throw ex;
+ }
+
+ }
+
+ private void validateCreditCardNumber(String number, CreditCardType creditCard)
+ throws ServiceException {
+
+ //TODO implement
+ if(CreditCardType.MASTERCARD.equals(creditCard.name())) {
+ if (number.length() != 16
+ || Integer.parseInt(number.substring(0, 2)) < 51
+ || Integer.parseInt(number.substring(0, 2)) > 55) {
+ ServiceException ex = new ServiceException(ServiceException.EXCEPTION_VALIDATION,"Invalid card number","messages.error.creditcard.number");
+ throw ex;
+ }
+ }
+
+ if(CreditCardType.VISA.equals(creditCard.name())) {
+ if ((number.length() != 13 && number.length() != 16)
+ || Integer.parseInt(number.substring(0, 1)) != 4) {
+ ServiceException ex = new ServiceException(ServiceException.EXCEPTION_VALIDATION,"Invalid card number","messages.error.creditcard.number");
+ throw ex;
+ }
+ }
+
+ if(CreditCardType.AMEX.equals(creditCard.name())) {
+ if (number.length() != 15
+ || (Integer.parseInt(number.substring(0, 2)) != 34 && Integer
+ .parseInt(number.substring(0, 2)) != 37)) {
+ ServiceException ex = new ServiceException(ServiceException.EXCEPTION_VALIDATION,"Invalid card number","messages.error.creditcard.number");
+ throw ex;
+ }
+ }
+
+ if(CreditCardType.DINERS.equals(creditCard.name())) {
+ if (number.length() != 14
+ || ((Integer.parseInt(number.substring(0, 2)) != 36 && Integer
+ .parseInt(number.substring(0, 2)) != 38)
+ && Integer.parseInt(number.substring(0, 3)) < 300 || Integer
+ .parseInt(number.substring(0, 3)) > 305)) {
+ ServiceException ex = new ServiceException(ServiceException.EXCEPTION_VALIDATION,"Invalid card number","messages.error.creditcard.number");
+ throw ex;
+ }
+ }
+
+ if(CreditCardType.DISCOVERY.equals(creditCard.name())) {
+ if (number.length() != 16
+ || Integer.parseInt(number.substring(0, 5)) != 6011) {
+ ServiceException ex = new ServiceException(ServiceException.EXCEPTION_VALIDATION,"Invalid card number","messages.error.creditcard.number");
+ throw ex;
+ }
+ }
+
+ luhnValidate(number);
+ }
+
+ // The Luhn algorithm is basically a CRC type
+ // system for checking the validity of an entry.
+ // All major credit cards use numbers that will
+ // pass the Luhn check. Also, all of them are based
+ // on MOD 10.
+
+ private void luhnValidate(String numberString)
+ throws ServiceException {
+ char[] charArray = numberString.toCharArray();
+ int[] number = new int[charArray.length];
+ int total = 0;
+
+ for (int i = 0; i < charArray.length; i++) {
+ number[i] = Character.getNumericValue(charArray[i]);
+ }
+
+ for (int i = number.length - 2; i > -1; i -= 2) {
+ number[i] *= 2;
+
+ if (number[i] > 9)
+ number[i] -= 9;
+ }
+
+ for (int i = 0; i < number.length; i++)
+ total += number[i];
+
+ if (total % 10 != 0) {
+ ServiceException ex = new ServiceException(ServiceException.EXCEPTION_VALIDATION,"Invalid card number","messages.error.creditcard.number");
+ throw ex;
+ }
+
+ }
+
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/payments/service/TransactionService.java b/sm-core/src/main/java/com/salesmanager/core/business/payments/service/TransactionService.java
new file mode 100644
index 0000000..c8ba2ff
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/payments/service/TransactionService.java
@@ -0,0 +1,27 @@
+package com.salesmanager.core.business.payments.service;
+
+import java.util.List;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.business.payments.model.Transaction;
+
+
+public interface TransactionService extends SalesManagerEntityService<Long, Transaction> {
+
+ /**
+ * Obtain a previous transaction that has type authorize for a give order
+ * @param order
+ * @return
+ * @throws ServiceException
+ */
+ Transaction getCapturableTransaction(Order order) throws ServiceException;
+
+ Transaction getRefundableTransaction(Order order) throws ServiceException;
+
+ List<Transaction> listTransactions(Order order) throws ServiceException;
+
+
+
+}
\ No newline at end of file
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/payments/service/TransactionServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/payments/service/TransactionServiceImpl.java
new file mode 100644
index 0000000..c8ffa31
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/payments/service/TransactionServiceImpl.java
@@ -0,0 +1,157 @@
+package com.salesmanager.core.business.payments.service;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.mysql.jdbc.log.Log;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.business.payments.dao.TransactionDao;
+import com.salesmanager.core.business.payments.model.Transaction;
+import com.salesmanager.core.business.payments.model.TransactionType;
+
+@Service("transactionService")
+public class TransactionServiceImpl extends SalesManagerEntityServiceImpl<Long, Transaction> implements TransactionService {
+
+
+ TransactionDao transactionDao;
+
+ @Autowired
+ public TransactionServiceImpl(TransactionDao transactionDao) {
+ super(transactionDao);
+ this.transactionDao = transactionDao;
+ }
+
+ @Override
+ public void create(Transaction transaction) throws ServiceException {
+
+ //parse JSON string
+ String transactionDetails = transaction.toJSONString();
+ if(!StringUtils.isBlank(transactionDetails)) {
+ transaction.setDetails(transactionDetails);
+ }
+
+ super.create(transaction);
+
+
+ }
+
+ @Override
+ public List<Transaction> listTransactions(Order order) throws ServiceException {
+
+ List<Transaction> transactions = transactionDao.listByOrder(order);
+ ObjectMapper mapper = new ObjectMapper();
+ for(Transaction transaction : transactions) {
+ if(!StringUtils.isBlank(transaction.getDetails())) {
+ try {
+ @SuppressWarnings("unchecked")
+ Map<String,String> objects = mapper.readValue(transaction.getDetails(), Map.class);
+ transaction.setTransactionDetails(objects);
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+ }
+ }
+
+ return transactions;
+ }
+
+ @Override
+ public Transaction getCapturableTransaction(Order order)
+ throws ServiceException {
+ List<Transaction> transactions = transactionDao.listByOrder(order);
+ ObjectMapper mapper = new ObjectMapper();
+ Transaction capturable = null;
+ for(Transaction transaction : transactions) {
+ if(transaction.getTransactionType().name().equals(TransactionType.AUTHORIZE.name())) {
+ if(!StringUtils.isBlank(transaction.getDetails())) {
+ try {
+ @SuppressWarnings("unchecked")
+ Map<String,String> objects = mapper.readValue(transaction.getDetails(), Map.class);
+ transaction.setTransactionDetails(objects);
+ capturable = transaction;
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+ }
+ }
+ if(transaction.getTransactionType().name().equals(TransactionType.CAPTURE.name())) {
+ break;
+ }
+ if(transaction.getTransactionType().name().equals(TransactionType.REFUND.name())) {
+ break;
+ }
+ }
+
+ return capturable;
+ }
+
+ @Override
+ public Transaction getRefundableTransaction(Order order)
+ throws ServiceException {
+ List<Transaction> transactions = transactionDao.listByOrder(order);
+ Map<String,Transaction> finalTransactions = new HashMap<String,Transaction>();
+ Transaction finalTransaction = null;
+ for(Transaction transaction : transactions) {
+ //System.out.println("Transaction type " + transaction.getTransactionType().name());
+ if(transaction.getTransactionType().name().equals(TransactionType.AUTHORIZECAPTURE.name())) {
+ finalTransactions.put(TransactionType.AUTHORIZECAPTURE.name(),transaction);
+ continue;
+ }
+ if(transaction.getTransactionType().name().equals(TransactionType.CAPTURE.name())) {
+ finalTransactions.put(TransactionType.CAPTURE.name(),transaction);
+ continue;
+ }
+ if(transaction.getTransactionType().name().equals(TransactionType.REFUND.name())) {
+ //check transaction id
+ Transaction previousRefund = finalTransactions.get(TransactionType.REFUND.name());
+ if(previousRefund!=null) {
+ Date previousDate = previousRefund.getTransactionDate();
+ Date currentDate = transaction.getTransactionDate();
+ if(previousDate.before(currentDate)) {
+ finalTransactions.put(TransactionType.REFUND.name(),transaction);
+ continue;
+ }
+ } else {
+ finalTransactions.put(TransactionType.REFUND.name(),transaction);
+ continue;
+ }
+ }
+ }
+
+ if(finalTransactions.containsKey(TransactionType.AUTHORIZECAPTURE.name())) {
+ finalTransaction = finalTransactions.get(TransactionType.AUTHORIZECAPTURE.name());
+ }
+
+ if(finalTransactions.containsKey(TransactionType.CAPTURE.name())) {
+ finalTransaction = finalTransactions.get(TransactionType.CAPTURE.name());
+ }
+
+ //if(finalTransactions.containsKey(TransactionType.REFUND.name())) {
+ // finalTransaction = finalTransactions.get(TransactionType.REFUND.name());
+ //}
+
+
+ if(finalTransaction!=null && !StringUtils.isBlank(finalTransaction.getDetails())) {
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ @SuppressWarnings("unchecked")
+ Map<String,String> objects = mapper.readValue(finalTransaction.getDetails(), Map.class);
+ finalTransaction.setTransactionDetails(objects);
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+ }
+
+ return finalTransaction;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/country/dao/CountryDao.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/country/dao/CountryDao.java
new file mode 100644
index 0000000..44ddfc6
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/country/dao/CountryDao.java
@@ -0,0 +1,12 @@
+package com.salesmanager.core.business.reference.country.dao;
+
+import java.util.List;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface CountryDao extends SalesManagerEntityDao<Integer,Country> {
+
+ public List<Country> listByLanguage(Language language);
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/country/dao/CountryDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/country/dao/CountryDaoImpl.java
new file mode 100644
index 0000000..42b76c9
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/country/dao/CountryDaoImpl.java
@@ -0,0 +1,36 @@
+package com.salesmanager.core.business.reference.country.dao;
+
+import java.util.List;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.country.model.QCountry;
+import com.salesmanager.core.business.reference.country.model.QCountryDescription;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Repository("countryDao")
+public class CountryDaoImpl extends SalesManagerEntityDaoImpl<Integer, Country> implements CountryDao {
+
+
+ @Override
+ public List<Country> listByLanguage(Language language) {
+ QCountry qCountry = QCountry.country;
+ QCountryDescription qDescription = QCountryDescription.countryDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCountry)
+ .leftJoin(qCountry.descriptions, qDescription).fetch()
+ .where(qDescription.language.id.eq(language.getId()))
+ .orderBy(qDescription.name.asc());
+
+
+
+ List<Country> countries = query.list(qCountry);
+ return countries;
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/country/model/Country.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/country/model/Country.java
new file mode 100644
index 0000000..6be29db
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/country/model/Country.java
@@ -0,0 +1,130 @@
+package com.salesmanager.core.business.reference.country.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Cacheable;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Transient;
+
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.reference.geozone.model.GeoZone;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@Table(name = "COUNTRY", schema=SchemaConstant.SALESMANAGER_SCHEMA)
+@Cacheable
+public class Country extends SalesManagerEntity<Integer, Country> {
+ private static final long serialVersionUID = -7388011537255588035L;
+
+ @Id
+ @Column(name="COUNTRY_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT",
+ pkColumnValue = "COUNTRY_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Integer id;
+
+ @OneToMany(mappedBy = "country", cascade = CascadeType.ALL)
+ private List<CountryDescription> descriptions = new ArrayList<CountryDescription>();
+
+ @OneToMany(mappedBy = "country")
+ private List<Zone> zones = new ArrayList<Zone>();
+
+ @ManyToOne(targetEntity = GeoZone.class)
+ @JoinColumn(name = "GEOZONE_ID")
+ private GeoZone geoZone;
+
+ @Column(name = "COUNTRY_SUPPORTED")
+ private boolean supported = true;
+
+ @Column(name = "COUNTRY_ISOCODE", unique=true, nullable = false)
+ private String isoCode;
+
+ @Transient
+ private String name;
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Country() {
+ }
+
+ public Country(String isoCode) {
+ this.setIsoCode(isoCode);
+ }
+
+ public boolean getSupported() {
+ return supported;
+ }
+
+ public void setSupported(boolean supported) {
+ this.supported = supported;
+ }
+
+ public String getIsoCode() {
+ return isoCode;
+ }
+
+ public void setIsoCode(String isoCode) {
+ this.isoCode = isoCode;
+ }
+
+
+ @Override
+ public Integer getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public List<Zone> getZones() {
+ return zones;
+ }
+
+ public void setZones(List<Zone> zones) {
+ this.zones = zones;
+ }
+
+ public List<CountryDescription> getDescriptions() {
+ return descriptions;
+ }
+
+ public void setDescriptions(List<CountryDescription> descriptions) {
+ this.descriptions = descriptions;
+ }
+
+ public GeoZone getGeoZone() {
+ return geoZone;
+ }
+
+ public void setGeoZone(GeoZone geoZone) {
+ this.geoZone = geoZone;
+ }
+
+/* public GeoZone getGeoZone() {
+ return geoZone;
+ }
+
+ public void setGeoZone(GeoZone geoZone) {
+ this.geoZone = geoZone;
+ }*/
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/country/model/CountryDescription.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/country/model/CountryDescription.java
new file mode 100644
index 0000000..c63c039
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/country/model/CountryDescription.java
@@ -0,0 +1,43 @@
+package com.salesmanager.core.business.reference.country.model;
+
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import com.salesmanager.core.business.common.model.Description;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Entity
+@Table(name = "COUNTRY_DESCRIPTION", schema="SALESMANAGER", uniqueConstraints={
+ @UniqueConstraint(columnNames={
+ "COUNTRY_ID",
+ "LANGUAGE_ID"
+ })
+ }
+)
+public class CountryDescription extends Description {
+ private static final long serialVersionUID = 9048940117896071174L;
+
+ @ManyToOne(targetEntity = Country.class)
+ @JoinColumn(name = "COUNTRY_ID", nullable = false)
+ private Country country;
+
+ public CountryDescription() {
+ }
+
+ public CountryDescription(Language language, String name) {
+ this.setLanguage(language);
+ this.setName(name);
+ }
+
+ public Country getCountry() {
+ return country;
+ }
+
+ public void setCountry(Country country) {
+ this.country = country;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/country/service/CountryService.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/country/service/CountryService.java
new file mode 100644
index 0000000..09733a3
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/country/service/CountryService.java
@@ -0,0 +1,25 @@
+package com.salesmanager.core.business.reference.country.service;
+
+import java.util.List;
+import java.util.Map;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.country.model.CountryDescription;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface CountryService extends SalesManagerEntityService<Integer, Country> {
+
+ public Country getByCode(String code) throws ServiceException;
+
+ public void addCountryDescription(Country country, CountryDescription description) throws ServiceException;
+
+ public List<Country> getCountries(Language language) throws ServiceException;
+
+ Map<String, Country> getCountriesMap(Language language)
+ throws ServiceException;
+
+ List<Country> getCountries(List<String> isoCodes, Language language)
+ throws ServiceException;
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/country/service/CountryServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/country/service/CountryServiceImpl.java
new file mode 100644
index 0000000..c67609b
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/country/service/CountryServiceImpl.java
@@ -0,0 +1,125 @@
+package com.salesmanager.core.business.reference.country.service;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.reference.country.dao.CountryDao;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.country.model.CountryDescription;
+import com.salesmanager.core.business.reference.country.model.Country_;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.utils.CacheUtils;
+
+@Service("countryService")
+public class CountryServiceImpl extends SalesManagerEntityServiceImpl<Integer, Country>
+ implements CountryService {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CountryServiceImpl.class);
+
+ private CountryDao countryDao;
+
+ @Autowired
+ private CacheUtils cache;
+
+
+ @Autowired
+ public CountryServiceImpl(CountryDao countryDao) {
+ super(countryDao);
+ this.countryDao = countryDao;
+ }
+
+ public Country getByCode(String code) throws ServiceException {
+ return countryDao.getByField(Country_.isoCode, code);
+ }
+
+ @Override
+ public void addCountryDescription(Country country, CountryDescription description) throws ServiceException {
+ country.getDescriptions().add(description);
+ description.setCountry(country);
+ update(country);
+ }
+
+ @Override
+ public Map<String,Country> getCountriesMap(Language language) throws ServiceException {
+
+ List<Country> countries = this.getCountries(language);
+
+ Map<String,Country> returnMap = new LinkedHashMap<String,Country>();
+
+ for(Country country : countries) {
+ returnMap.put(country.getIsoCode(), country);
+ }
+
+ return returnMap;
+ }
+
+
+ @Override
+ public List<Country> getCountries(final List<String> isoCodes, final Language language) throws ServiceException {
+ List<Country> countryList = getCountries(language);
+ List<Country> requestedCountryList = new ArrayList<Country>();
+ if(!CollectionUtils.isEmpty(countryList)) {
+ for(Country c : countryList) {
+ if(isoCodes.contains(c.getIsoCode())) {
+ requestedCountryList.add(c);
+ }
+ }
+ }
+ return requestedCountryList;
+ }
+
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List<Country> getCountries(Language language) throws ServiceException {
+
+ List<Country> countries = null;
+ try {
+
+ //CacheUtils cacheUtils = CacheUtils.getInstance();
+
+ countries = (List<Country>) cache.getFromCache("COUNTRIES_" + language.getCode());
+
+
+
+ if(countries==null) {
+
+ countries = countryDao.listByLanguage(language);
+
+ //set names
+ for(Country country : countries) {
+
+ CountryDescription description = country.getDescriptions().get(0);
+ country.setName(description.getName());
+
+ }
+
+ cache.putInCache(countries, "COUNTRIES_" + language.getCode());
+
+ }
+
+
+
+
+
+ } catch (Exception e) {
+ LOGGER.error("getCountries()", e);
+ }
+
+ return countries;
+
+
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/currency/dao/CurrencyDao.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/currency/dao/CurrencyDao.java
new file mode 100644
index 0000000..67ae75a
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/currency/dao/CurrencyDao.java
@@ -0,0 +1,8 @@
+package com.salesmanager.core.business.reference.currency.dao;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.reference.currency.model.Currency;
+
+public interface CurrencyDao extends SalesManagerEntityDao<Long, Currency> {
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/currency/dao/CurrencyDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/currency/dao/CurrencyDaoImpl.java
new file mode 100644
index 0000000..7118fe5
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/currency/dao/CurrencyDaoImpl.java
@@ -0,0 +1,35 @@
+package com.salesmanager.core.business.reference.currency.dao;
+
+import java.util.List;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.reference.currency.model.Currency;
+import com.salesmanager.core.business.reference.currency.model.QCurrency;
+
+@Repository("currencyDao")
+public class CurrencyDaoImpl extends SalesManagerEntityDaoImpl<Long, Currency>
+ implements CurrencyDao {
+
+
+ @Override
+ public List<Currency> list() {
+ QCurrency qCurrency = QCurrency.currency1;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qCurrency)
+ .orderBy(qCurrency.code.asc());
+
+
+
+ List<Currency> currencies = query.list(qCurrency);
+ return currencies;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/currency/model/Currency.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/currency/model/Currency.java
new file mode 100644
index 0000000..0e1912c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/currency/model/Currency.java
@@ -0,0 +1,90 @@
+package com.salesmanager.core.business.reference.currency.model;
+
+import java.io.Serializable;
+
+import javax.persistence.Cacheable;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@Table(name = "CURRENCY", schema = SchemaConstant.SALESMANAGER_SCHEMA)
+@Cacheable
+public class Currency extends SalesManagerEntity<Long, Currency> implements Serializable {
+ private static final long serialVersionUID = -999926410367685145L;
+
+ @Id
+ @Column(name = "CURRENCY_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "CURRENCY_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @Column(name = "CURRENCY_CURRENCY_CODE" ,nullable = false, unique = true)
+ private java.util.Currency currency;
+
+ @Column(name = "CURRENCY_SUPPORTED")
+ private Boolean supported = true;
+
+ @Column(name = "CURRENCY_CODE", unique = true)
+ private String code;
+
+ @Column(name = "CURRENCY_NAME", unique = true)
+ private String name;
+
+ public Currency() {
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public java.util.Currency getCurrency() {
+ return currency;
+ }
+
+ public void setCurrency(java.util.Currency currency) {
+ this.currency = currency;
+ this.code = currency.getCurrencyCode();
+ }
+
+ public Boolean getSupported() {
+ return supported;
+ }
+
+ public void setSupported(Boolean supported) {
+ this.supported = supported;
+ }
+
+ public String getCode() {
+ if (currency.getCurrencyCode() != code) {
+ return currency.getCurrencyCode();
+ }
+ return code;
+ }
+
+ public String getSymbol() {
+ return currency.getSymbol();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/currency/service/CurrencyService.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/currency/service/CurrencyService.java
new file mode 100644
index 0000000..c7796bc
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/currency/service/CurrencyService.java
@@ -0,0 +1,10 @@
+package com.salesmanager.core.business.reference.currency.service;
+
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.reference.currency.model.Currency;
+
+public interface CurrencyService extends SalesManagerEntityService<Long, Currency> {
+
+ Currency getByCode(String code);
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/currency/service/CurrencyServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/currency/service/CurrencyServiceImpl.java
new file mode 100644
index 0000000..870cf4a
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/currency/service/CurrencyServiceImpl.java
@@ -0,0 +1,25 @@
+package com.salesmanager.core.business.reference.currency.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.reference.currency.dao.CurrencyDao;
+import com.salesmanager.core.business.reference.currency.model.Currency;
+import com.salesmanager.core.business.reference.currency.model.Currency_;
+
+@Service("currencyService")
+public class CurrencyServiceImpl extends SalesManagerEntityServiceImpl<Long, Currency>
+ implements CurrencyService {
+
+ @Autowired
+ public CurrencyServiceImpl(CurrencyDao currencyDao) {
+ super(currencyDao);
+ }
+
+ @Override
+ public Currency getByCode(String code) {
+ return getByField(Currency_.code, code);
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/geozone/model/GeoZone.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/geozone/model/GeoZone.java
new file mode 100644
index 0000000..f957d1d
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/geozone/model/GeoZone.java
@@ -0,0 +1,92 @@
+package com.salesmanager.core.business.reference.geozone.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.reference.country.model.Country;
+
+@Entity
+@Table(name = "GEOZONE", schema="SALESMANAGER")
+// TODO : create DAO / Service
+public class GeoZone extends SalesManagerEntity<Long, GeoZone> {
+ private static final long serialVersionUID = -5992008645857938825L;
+
+ @Id
+ @Column(name = "GEOZONE_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "GEOZONE_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @OneToMany(mappedBy = "geoZone", cascade = CascadeType.ALL)
+ private List<GeoZoneDescription> descriptions = new ArrayList<GeoZoneDescription>();
+
+ @OneToMany(mappedBy = "geoZone", targetEntity = Country.class)
+ private List<Country> countries = new ArrayList<Country>();
+
+
+
+ @Column(name = "GEOZONE_NAME")
+ private String name;
+
+ @Column(name = "GEOZONE_CODE")
+ private String code;
+
+ public GeoZone() {
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public List<Country> getCountries() {
+ return countries;
+ }
+
+ public void setCountries(List<Country> countries) {
+ this.countries = countries;
+ }
+
+ public List<GeoZoneDescription> getDescriptions() {
+ return descriptions;
+ }
+
+ public void setDescriptions(List<GeoZoneDescription> descriptions) {
+ this.descriptions = descriptions;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/geozone/model/GeoZoneDescription.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/geozone/model/GeoZoneDescription.java
new file mode 100644
index 0000000..15925b6
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/geozone/model/GeoZoneDescription.java
@@ -0,0 +1,36 @@
+package com.salesmanager.core.business.reference.geozone.model;
+
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import com.salesmanager.core.business.common.model.Description;
+
+@Entity
+@Table(name="GEOZONE_DESCRIPTION", schema="SALESMANAGER", uniqueConstraints={
+ @UniqueConstraint(columnNames={
+ "GEOZONE_ID",
+ "LANGUAGE_ID"
+ })
+ }
+)
+public class GeoZoneDescription extends Description {
+ private static final long serialVersionUID = 7759498146450786218L;
+
+ @ManyToOne(targetEntity = GeoZone.class)
+ @JoinColumn(name = "GEOZONE_ID")
+ private GeoZone geoZone;
+
+ public GeoZoneDescription() {
+ }
+
+ public GeoZone getGeoZone() {
+ return geoZone;
+ }
+
+ public void setGeoZone(GeoZone geoZone) {
+ this.geoZone = geoZone;
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/init/service/InitializationDatabase.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/init/service/InitializationDatabase.java
new file mode 100644
index 0000000..7c6266f
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/init/service/InitializationDatabase.java
@@ -0,0 +1,11 @@
+package com.salesmanager.core.business.reference.init.service;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+
+public interface InitializationDatabase {
+
+ boolean isEmpty();
+
+ void populate(String name) throws ServiceException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/init/service/InitializationDatabaseImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/init/service/InitializationDatabaseImpl.java
new file mode 100644
index 0000000..1f7c3f0
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/init/service/InitializationDatabaseImpl.java
@@ -0,0 +1,269 @@
+package com.salesmanager.core.business.reference.init.service;
+
+import java.sql.Date;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.salesmanager.core.business.catalog.product.model.type.ProductType;
+import com.salesmanager.core.business.catalog.product.service.type.ProductTypeService;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.merchant.service.MerchantStoreService;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.country.model.CountryDescription;
+import com.salesmanager.core.business.reference.country.service.CountryService;
+import com.salesmanager.core.business.reference.currency.model.Currency;
+import com.salesmanager.core.business.reference.currency.service.CurrencyService;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.language.service.LanguageService;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.core.business.reference.zone.model.ZoneDescription;
+import com.salesmanager.core.business.reference.zone.service.ZoneService;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+import com.salesmanager.core.business.system.service.ModuleConfigurationService;
+import com.salesmanager.core.business.tax.model.taxclass.TaxClass;
+import com.salesmanager.core.business.tax.service.TaxClassService;
+import com.salesmanager.core.constants.SchemaConstant;
+import com.salesmanager.core.utils.reference.IntegrationModulesLoader;
+import com.salesmanager.core.utils.reference.ZonesLoader;
+
+@Service("initializationDatabase")
+public class InitializationDatabaseImpl implements InitializationDatabase {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(InitializationDatabaseImpl.class);
+
+
+
+ @Autowired
+ private ZoneService zoneService;
+
+ @Autowired
+ private LanguageService languageService;
+
+ @Autowired
+ private CountryService countryService;
+
+ @Autowired
+ private CurrencyService currencyService;
+
+ @Autowired
+ protected MerchantStoreService merchantService;
+
+ @Autowired
+ protected ProductTypeService productTypeService;
+
+ @Autowired
+ private TaxClassService taxClassService;
+
+ @Autowired
+ private ZonesLoader zonesLoader;
+
+ @Autowired
+ private IntegrationModulesLoader modulesLoader;
+
+ @Autowired
+ private ModuleConfigurationService moduleConfigurationService;
+
+
+
+ private String name;
+
+ public boolean isEmpty() {
+ return languageService.count() == 0;
+ }
+
+ @Transactional
+ public void populate(String contextName) throws ServiceException {
+ this.name = contextName;
+
+ createLanguages();
+ createCountries();
+ createZones();
+ createCurrencies();
+ createSubReferences();
+ createModules();
+ createMerchant();
+
+
+ }
+
+
+
+ private void createCurrencies() throws ServiceException {
+ LOGGER.info(String.format("%s : Populating Currencies ", name));
+
+ //Locale [] locales = Locale.getAvailableLocales();
+ //Locale l = locales[0];
+
+ for (String code : SchemaConstant.CURRENCY_MAP.keySet()) {
+
+
+ try {
+ java.util.Currency c = java.util.Currency.getInstance(code);
+
+ if(c==null) {
+ LOGGER.info(String.format("%s : Populating Currencies : no currency for code : %s", name, code));
+ }
+
+ //check if it exist
+
+ Currency currency = new Currency();
+ currency.setName(c.getCurrencyCode());
+ currency.setCurrency(c);
+ currencyService.create(currency);
+
+ //System.out.println(l.getCountry() + " " + c.getSymbol() + " " + c.getSymbol(l));
+ } catch (IllegalArgumentException e) {
+ LOGGER.info(String.format("%s : Populating Currencies : no currency for code : %s", name, code));
+ }
+ }
+ }
+
+ private void createCountries() throws ServiceException {
+ LOGGER.info(String.format("%s : Populating Countries ", name));
+ List<Language> languages = languageService.list();
+ for(String code : SchemaConstant.COUNTRY_ISO_CODE) {
+ Locale locale = SchemaConstant.LOCALES.get(code);
+ if (locale != null) {
+ Country country = new Country(code);
+ countryService.create(country);
+
+ for (Language language : languages) {
+ String name = locale.getDisplayCountry(new Locale(language.getCode()));
+ CountryDescription description = new CountryDescription(language, name);
+ countryService.addCountryDescription(country, description);
+ }
+ }
+ }
+ }
+
+ private void createZones() throws ServiceException {
+ LOGGER.info(String.format("%s : Populating Zones ", name));
+ try {
+
+ Map<String,Zone> zonesMap = new HashMap<String,Zone>();
+ zonesMap = zonesLoader.loadZones("reference/zoneconfig.json");
+
+ for (Map.Entry<String, Zone> entry : zonesMap.entrySet()) {
+ String key = entry.getKey();
+ Zone value = entry.getValue();
+ if(value.getDescriptions()==null) {
+ LOGGER.warn("This zone " + key + " has no descriptions");
+ continue;
+ }
+
+ List<ZoneDescription> zoneDescriptions = value.getDescriptions();
+ value.setDescriptons(null);
+
+ zoneService.create(value);
+
+ for(ZoneDescription description : zoneDescriptions) {
+ description.setZone(value);
+ zoneService.addDescription(value, description);
+ }
+ }
+
+ } catch (Exception e) {
+
+ throw new ServiceException(e);
+ }
+
+ }
+
+ private void createLanguages() throws ServiceException {
+ LOGGER.info(String.format("%s : Populating Languages ", name));
+ for(String code : SchemaConstant.LANGUAGE_ISO_CODE) {
+ Language language = new Language(code);
+ languageService.create(language);
+ }
+ }
+
+ private void createMerchant() throws ServiceException {
+ LOGGER.info(String.format("%s : Creating merchant ", name));
+
+ Date date = new Date(System.currentTimeMillis());
+
+ Language en = languageService.getByCode("en");
+ Country ca = countryService.getByCode("CA");
+ Currency currency = currencyService.getByCode("CAD");
+ Zone qc = zoneService.getByCode("QC");
+
+ List<Language> supportedLanguages = new ArrayList<Language>();
+ supportedLanguages.add(en);
+
+ //create a merchant
+ MerchantStore store = new MerchantStore();
+ store.setCountry(ca);
+ store.setCurrency(currency);
+ store.setDefaultLanguage(en);
+ store.setInBusinessSince(date);
+ store.setZone(qc);
+ store.setStorename("Default store");
+ store.setStorephone("888-888-8888");
+ store.setCode(MerchantStore.DEFAULT_STORE);
+ store.setStorecity("My city");
+ store.setStoreaddress("1234 Street address");
+ store.setStorepostalcode("H2H-2H2");
+ store.setStoreEmailAddress("test@test.com");
+ store.setDomainName("localhost:8080");
+ store.setStoreTemplate("bootstrap");
+ store.setLanguages(supportedLanguages);
+
+ merchantService.create(store);
+
+
+ TaxClass taxclass = new TaxClass(TaxClass.DEFAULT_TAX_CLASS);
+ taxclass.setMerchantStore(store);
+
+ taxClassService.create(taxclass);
+
+
+ }
+
+ private void createModules() throws ServiceException {
+
+ try {
+
+ List<IntegrationModule> modules = modulesLoader.loadIntegrationModules("reference/integrationmodules.json");
+ for (IntegrationModule entry : modules) {
+ moduleConfigurationService.create(entry);
+ }
+
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+
+ }
+
+ private void createSubReferences() throws ServiceException {
+
+ LOGGER.info(String.format("%s : Loading catalog sub references ", name));
+
+
+
+ ProductType productType = new ProductType();
+ productType.setCode(ProductType.GENERAL_TYPE);
+ productTypeService.create(productType);
+
+
+
+
+ }
+
+
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/language/dao/LanguageDao.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/language/dao/LanguageDao.java
new file mode 100644
index 0000000..fc0ff60
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/language/dao/LanguageDao.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.reference.language.dao;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface LanguageDao extends SalesManagerEntityDao<Integer, Language> {
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/language/dao/LanguageDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/language/dao/LanguageDaoImpl.java
new file mode 100644
index 0000000..b80df29
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/language/dao/LanguageDaoImpl.java
@@ -0,0 +1,10 @@
+package com.salesmanager.core.business.reference.language.dao;
+
+import org.springframework.stereotype.Repository;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Repository("languageDao")
+public class LanguageDaoImpl extends SalesManagerEntityDaoImpl<Integer, Language> implements LanguageDao {
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/language/model/Language.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/language/model/Language.java
new file mode 100644
index 0000000..d359f59
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/language/model/Language.java
@@ -0,0 +1,114 @@
+package com.salesmanager.core.business.reference.language.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Cacheable;
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+import com.salesmanager.core.business.common.model.audit.AuditListener;
+import com.salesmanager.core.business.common.model.audit.AuditSection;
+import com.salesmanager.core.business.common.model.audit.Auditable;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@EntityListeners(value = AuditListener.class)
+@Table(name = "LANGUAGE", schema=SchemaConstant.SALESMANAGER_SCHEMA)
+@Cacheable
+public class Language extends SalesManagerEntity<Integer, Language> implements Auditable {
+ private static final long serialVersionUID = -7676627812941330669L;
+
+
+
+ @Id
+ @Column(name="LANGUAGE_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT",
+ pkColumnValue = "LANG_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Integer id;
+
+ @Embedded
+ private AuditSection auditSection = new AuditSection();
+
+ @Column(name="CODE", nullable = false)
+ private String code;
+
+ @Column(name="SORT_ORDER")
+ private Integer sortOrder;
+
+ @SuppressWarnings("unused")
+ @OneToMany(mappedBy = "defaultLanguage", targetEntity = MerchantStore.class)
+ private List<MerchantStore> storesDefaultLanguage;
+
+ @SuppressWarnings("unused")
+ @ManyToMany(mappedBy = "languages", targetEntity = MerchantStore.class)
+ private List<MerchantStore> stores = new ArrayList<MerchantStore>();
+
+ public Language() {
+ }
+
+ public Language(String code) {
+ this.setCode(code);
+ }
+
+ @Override
+ public Integer getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public Integer getSortOrder() {
+ return sortOrder;
+ }
+
+ public void setSortOrder(Integer sortOrder) {
+ this.sortOrder = sortOrder;
+ }
+
+ @Override
+ public AuditSection getAuditSection() {
+ return auditSection;
+ }
+
+ @Override
+ public void setAuditSection(AuditSection auditSection) {
+ this.auditSection = auditSection;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (null == obj)
+ return false;
+ if (!(obj instanceof Language)) {
+ return false;
+ } else {
+ Language language = (Language) obj;
+ return (this.id == language.getId());
+ }
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/language/service/LanguageService.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/language/service/LanguageService.java
new file mode 100644
index 0000000..6296660
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/language/service/LanguageService.java
@@ -0,0 +1,22 @@
+package com.salesmanager.core.business.reference.language.service;
+
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface LanguageService extends SalesManagerEntityService<Integer, Language> {
+
+ Language getByCode(String code) throws ServiceException;
+
+ Map<String, Language> getLanguagesMap() throws ServiceException;
+
+ List<Language> getLanguages() throws ServiceException;
+
+ Locale toLocale(Language language);
+
+ Language toLanguage(Locale locale);
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/language/service/LanguageServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/language/service/LanguageServiceImpl.java
new file mode 100644
index 0000000..429ed17
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/language/service/LanguageServiceImpl.java
@@ -0,0 +1,108 @@
+package com.salesmanager.core.business.reference.language.service;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.reference.language.dao.LanguageDao;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.language.model.Language_;
+import com.salesmanager.core.utils.CacheUtils;
+
+@Service("languageService")
+public class LanguageServiceImpl extends SalesManagerEntityServiceImpl<Integer, Language>
+ implements LanguageService {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(LanguageServiceImpl.class);
+
+ @Autowired
+ private CacheUtils cache;
+
+ @Autowired
+ public LanguageServiceImpl(LanguageDao languageDao) {
+ super(languageDao);
+ }
+
+ @Override
+ public Language getByCode(String code) throws ServiceException {
+ return getByField(Language_.code, code);
+ }
+
+ @Override
+ public Locale toLocale(Language language) {
+ return new Locale(language.getCode());
+ }
+
+ @Override
+ public Language toLanguage(Locale locale) {
+
+ try {
+ Language lang = getLanguagesMap().get(locale.getLanguage());
+ return lang;
+ } catch (Exception e) {
+ LOGGER.error("Cannot convert locale " + locale.getLanguage() + " to language");
+ }
+
+ return null;
+
+ }
+
+ @Override
+ public Map<String,Language> getLanguagesMap() throws ServiceException {
+
+ List<Language> langs = this.getLanguages();
+
+ Map<String,Language> returnMap = new LinkedHashMap<String,Language>();
+
+ for(Language lang : langs) {
+
+ returnMap.put(lang.getCode(), lang);
+
+ }
+
+ return returnMap;
+
+
+ }
+
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public List<Language> getLanguages() throws ServiceException {
+
+
+ List<Language> langs = null;
+ try {
+
+ //CacheUtils cacheUtils = CacheUtils.getInstance();
+
+ langs = (List<Language>) cache.getFromCache("LANGUAGES");
+
+
+
+ if(langs==null) {
+ langs = this.list();
+ cache.putInCache(langs, "LANGUAGES");
+ }
+
+
+
+
+
+ } catch (Exception e) {
+ LOGGER.error("getCountries()", e);
+ }
+
+ return langs;
+
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/dao/ZoneDao.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/dao/ZoneDao.java
new file mode 100644
index 0000000..b0f1e0b
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/dao/ZoneDao.java
@@ -0,0 +1,17 @@
+package com.salesmanager.core.business.reference.zone.dao;
+
+import java.util.List;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+
+
+public interface ZoneDao extends SalesManagerEntityDao<Long,Zone> {
+
+ List<Zone> listByLanguageAndCountry(Country country, Language language);
+
+ List<Zone> listByLanguage(Language language);
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/dao/ZoneDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/dao/ZoneDaoImpl.java
new file mode 100644
index 0000000..9b48d28
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/dao/ZoneDaoImpl.java
@@ -0,0 +1,54 @@
+package com.salesmanager.core.business.reference.zone.dao;
+
+import java.util.List;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.zone.model.QZone;
+import com.salesmanager.core.business.reference.zone.model.QZoneDescription;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+
+@Repository("zoneDao")
+public class ZoneDaoImpl extends SalesManagerEntityDaoImpl<Long, Zone> implements ZoneDao {
+
+ @Override
+ public List<Zone> listByLanguageAndCountry(Country country, Language language) {
+ QZone qZone = QZone.zone;
+ QZoneDescription qDescription = QZoneDescription.zoneDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qZone)
+ .leftJoin(qZone.descriptions, qDescription).fetch()
+ .where(qDescription.language.id.eq(language.getId())
+ .and(qZone.country.isoCode.eq(country.getIsoCode())))
+ .orderBy(qDescription.name.asc());
+
+
+
+ List<Zone> zones = query.list(qZone);
+ return zones;
+ }
+
+ @Override
+ public List<Zone> listByLanguage(Language language) {
+ QZone qZone = QZone.zone;
+ QZoneDescription qDescription = QZoneDescription.zoneDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qZone)
+ .leftJoin(qZone.descriptions, qDescription).fetch()
+ .where(qDescription.language.id.eq(language.getId()))
+ .orderBy(qDescription.name.asc());
+
+ List<Zone> zones = query.list(qZone);
+ return zones;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/imports/ZoneLoader.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/imports/ZoneLoader.java
new file mode 100644
index 0000000..faf5221
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/imports/ZoneLoader.java
@@ -0,0 +1,31 @@
+package com.salesmanager.core.business.reference.zone.imports;
+
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.type.TypeReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class ZoneLoader {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ZoneLoader.class);
+
+ public Map<String, List<ZoneTransient>> loadZoneConfigurations() {
+
+ ObjectMapper mapper = new ObjectMapper();
+ InputStream in = this.getClass().getResourceAsStream("/reference/zoneconfig.json");
+ Map<String,List<ZoneTransient>> zoneConfigurations = new HashMap<String, List<ZoneTransient>>();
+ try {
+ zoneConfigurations = mapper.readValue(in, new TypeReference<HashMap<String,List<ZoneTransient>>>() { });
+ } catch (Exception e) {
+ LOGGER.error("Error import zones.", e);
+ }
+
+ return zoneConfigurations;
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/imports/ZoneTransient.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/imports/ZoneTransient.java
new file mode 100644
index 0000000..899d974
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/imports/ZoneTransient.java
@@ -0,0 +1,28 @@
+package com.salesmanager.core.business.reference.zone.imports;
+
+public class ZoneTransient {
+
+ private String zoneCode;
+ private String zoneName;
+ private String countryCode;
+
+ public String getZoneCode() {
+ return zoneCode;
+ }
+ public void setZoneCode(String zoneCode) {
+ this.zoneCode = zoneCode;
+ }
+ public String getZoneName() {
+ return zoneName;
+ }
+ public void setZoneName(String zoneName) {
+ this.zoneName = zoneName;
+ }
+ public String getCountryCode() {
+ return countryCode;
+ }
+ public void setCountryCode(String countryCode) {
+ this.countryCode = countryCode;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/model/Zone.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/model/Zone.java
new file mode 100644
index 0000000..36401ac
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/model/Zone.java
@@ -0,0 +1,102 @@
+package com.salesmanager.core.business.reference.zone.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Transient;
+
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@Table(name = "ZONE", schema=SchemaConstant.SALESMANAGER_SCHEMA)
+public class Zone extends SalesManagerEntity<Long, Zone>{
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @Column(name="ZONE_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT",
+ pkColumnValue = "ZONE_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @OneToMany(mappedBy = "zone", cascade = CascadeType.ALL)
+ private List<ZoneDescription> descriptions = new ArrayList<ZoneDescription>();
+
+ @ManyToOne
+ @JoinColumn(name="COUNTRY_ID", nullable = false)
+ private Country country;
+
+ @Transient
+ private String name;
+
+
+
+ @Column(name = "ZONE_CODE", unique=true, nullable = false)
+ private String code;
+
+ public Zone() {
+ }
+
+ public Zone(Country country, String name, String code) {
+ this.setCode(code);
+ this.setCountry(country);
+ this.setCode(name);
+ }
+
+ public Country getCountry() {
+ return country;
+ }
+
+ public void setCountry(Country country) {
+ this.country = country;
+ }
+
+
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+ public List<ZoneDescription> getDescriptions() {
+ return descriptions;
+ }
+
+ public void setDescriptons(List<ZoneDescription> descriptions) {
+ this.descriptions = descriptions;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/model/ZoneDescription.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/model/ZoneDescription.java
new file mode 100644
index 0000000..234d3da
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/model/ZoneDescription.java
@@ -0,0 +1,43 @@
+package com.salesmanager.core.business.reference.zone.model;
+
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import com.salesmanager.core.business.common.model.Description;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Entity
+@Table(name="ZONE_DESCRIPTION", uniqueConstraints={
+ @UniqueConstraint(columnNames={
+ "ZONE_ID",
+ "LANGUAGE_ID"
+ })
+ }
+)
+public class ZoneDescription extends Description {
+ private static final long serialVersionUID = 6448836326562270923L;
+
+ @ManyToOne(targetEntity = Zone.class)
+ @JoinColumn(name = "ZONE_ID", nullable = false)
+ private Zone zone;
+
+ public ZoneDescription() {
+ }
+
+ public ZoneDescription(Zone zone, Language language, String name) {
+ setZone(zone);
+ setLanguage(language);
+ setName(name);
+ }
+
+ public Zone getZone() {
+ return zone;
+ }
+
+ public void setZone(Zone zone) {
+ this.zone = zone;
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/service/ZoneService.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/service/ZoneService.java
new file mode 100644
index 0000000..ce0daeb
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/service/ZoneService.java
@@ -0,0 +1,25 @@
+package com.salesmanager.core.business.reference.zone.service;
+
+import java.util.List;
+import java.util.Map;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.core.business.reference.zone.model.ZoneDescription;
+
+public interface ZoneService extends SalesManagerEntityService<Long, Zone> {
+
+ Zone getByCode(String code);
+
+ void addDescription(Zone zone, ZoneDescription description) throws ServiceException;
+
+ List<Zone> getZones(Country country, Language language)
+ throws ServiceException;
+
+ Map<String, Zone> getZones(Language language) throws ServiceException;
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/service/ZoneServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/service/ZoneServiceImpl.java
new file mode 100644
index 0000000..7d16657
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/reference/zone/service/ZoneServiceImpl.java
@@ -0,0 +1,132 @@
+package com.salesmanager.core.business.reference.zone.service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.zone.dao.ZoneDao;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.core.business.reference.zone.model.ZoneDescription;
+import com.salesmanager.core.business.reference.zone.model.Zone_;
+import com.salesmanager.core.constants.Constants;
+import com.salesmanager.core.utils.CacheUtils;
+
+@Service("zoneService")
+public class ZoneServiceImpl extends SalesManagerEntityServiceImpl<Long, Zone> implements
+ ZoneService {
+
+ private final static String ZONE_CACHE_PREFIX = "ZONES_";
+
+ private ZoneDao zoneDao;
+
+ @Autowired
+ private CacheUtils cache;
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ZoneServiceImpl.class);
+
+ @Autowired
+ public ZoneServiceImpl(ZoneDao zoneDao) {
+ super(zoneDao);
+ this.zoneDao = zoneDao;
+ }
+
+ @Override
+ public Zone getByCode(String code) {
+ return getByField(Zone_.code, code);
+ }
+
+ @Override
+ public void addDescription(Zone zone, ZoneDescription description) throws ServiceException {
+ if (zone.getDescriptions()!=null) {
+ if(!zone.getDescriptions().contains(description)) {
+ zone.getDescriptions().add(description);
+ update(zone);
+ }
+ } else {
+ List<ZoneDescription> descriptions = new ArrayList<ZoneDescription>();
+ descriptions.add(description);
+ zone.setDescriptons(descriptions);
+ update(zone);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public List<Zone> getZones(Country country, Language language) throws ServiceException {
+
+ List<Zone> zones = null;
+ try {
+
+ String cacheKey = ZONE_CACHE_PREFIX + country.getIsoCode() + Constants.UNDERSCORE + language.getCode();
+
+ zones = (List<Zone>) cache.getFromCache(cacheKey);
+
+
+
+ if(zones==null) {
+
+ zones = zoneDao.listByLanguageAndCountry(country, language);
+
+ //set names
+ for(Zone zone : zones) {
+ ZoneDescription description = zone.getDescriptions().get(0);
+ zone.setName(description.getName());
+
+ }
+ cache.putInCache(zones, cacheKey);
+ }
+
+ } catch (Exception e) {
+ LOGGER.error("getZones()", e);
+ }
+ return zones;
+
+
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public Map<String, Zone> getZones(Language language) throws ServiceException {
+
+ Map<String, Zone> zones = null;
+ try {
+
+ String cacheKey = ZONE_CACHE_PREFIX + language.getCode();
+
+ zones = (Map<String, Zone>) cache.getFromCache(cacheKey);
+
+
+
+ if(zones==null) {
+ zones = new HashMap<String, Zone>();
+ List<Zone> zns = zoneDao.listByLanguage(language);
+
+ //set names
+ for(Zone zone : zns) {
+ ZoneDescription description = zone.getDescriptions().get(0);
+ zone.setName(description.getName());
+ zones.put(zone.getCode(), zone);
+
+ }
+ cache.putInCache(zones, cacheKey);
+ }
+
+ } catch (Exception e) {
+ LOGGER.error("getZones()", e);
+ }
+ return zones;
+
+
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/search/model/IndexProduct.java b/sm-core/src/main/java/com/salesmanager/core/business/search/model/IndexProduct.java
new file mode 100644
index 0000000..4e15b0c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/search/model/IndexProduct.java
@@ -0,0 +1,148 @@
+package com.salesmanager.core.business.search.model;
+
+import java.util.List;
+
+import org.json.simple.JSONArray;
+import org.json.simple.JSONAware;
+import org.json.simple.JSONObject;
+
+public class IndexProduct implements JSONAware {
+
+ private String name;
+ private Double price;
+ private List<String> categories;//category code
+ private String manufacturer;//id of the manufacturer
+ private boolean available;
+ private String description;
+ private List<String> tags;//keywords ?
+ private String highlight;
+ private String store;
+ private String lang;
+ private String id;//required by the search framework
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public String toJSONString() {
+
+
+
+
+ JSONObject obj = new JSONObject();
+ obj.put("name", this.getName());
+ obj.put("price", this.getPrice());
+ obj.put("description", this.getDescription());
+ obj.put("highlight", this.getHighlight());
+ obj.put("store", this.getStore());
+ obj.put("manufacturer", this.getManufacturer());
+ obj.put("lang", this.getLang());
+ obj.put("id", this.getId());
+ if(categories!=null) {
+ JSONArray categoriesArray = new JSONArray();
+ for(String category : categories) {
+ categoriesArray.add(category);
+ }
+ obj.put("categories", categoriesArray);
+ }
+
+ if(tags!=null) {
+ JSONArray tagsArray = new JSONArray();
+ for(String tag : tags) {
+ tagsArray.add(tag);
+ }
+ obj.put("tags", tagsArray);
+ }
+
+ return obj.toJSONString();
+
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+
+ public List<String> getCategories() {
+ return categories;
+ }
+
+ public void setCategories(List<String> categories) {
+ this.categories = categories;
+ }
+
+ public boolean isAvailable() {
+ return available;
+ }
+
+ public void setAvailable(boolean available) {
+ this.available = available;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public List<String> getTags() {
+ return tags;
+ }
+
+ public void setTags(List<String> tags) {
+ this.tags = tags;
+ }
+
+ public String getHighlight() {
+ return highlight;
+ }
+
+ public void setHighlight(String highlight) {
+ this.highlight = highlight;
+ }
+
+ public void setPrice(Double price) {
+ this.price = price;
+ }
+
+ public Double getPrice() {
+ return price;
+ }
+
+ public void setStore(String store) {
+ this.store = store;
+ }
+
+ public String getStore() {
+ return store;
+ }
+
+ public void setLang(String lang) {
+ this.lang = lang;
+ }
+
+ public String getLang() {
+ return lang;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setManufacturer(String manufacturer) {
+ this.manufacturer = manufacturer;
+ }
+
+ public String getManufacturer() {
+ return manufacturer;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/search/model/SearchEntry.java b/sm-core/src/main/java/com/salesmanager/core/business/search/model/SearchEntry.java
new file mode 100644
index 0000000..5b6ba57
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/search/model/SearchEntry.java
@@ -0,0 +1,22 @@
+package com.salesmanager.core.business.search.model;
+
+import java.util.List;
+
+public class SearchEntry {
+
+ private IndexProduct indexProduct;//product as saved in the index
+ private List<String> highlights;
+ public void setHighlights(List<String> highlights) {
+ this.highlights = highlights;
+ }
+ public List<String> getHighlights() {
+ return highlights;
+ }
+ public void setIndexProduct(IndexProduct indexProduct) {
+ this.indexProduct = indexProduct;
+ }
+ public IndexProduct getIndexProduct() {
+ return indexProduct;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/search/model/SearchFacet.java b/sm-core/src/main/java/com/salesmanager/core/business/search/model/SearchFacet.java
new file mode 100644
index 0000000..840f883
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/search/model/SearchFacet.java
@@ -0,0 +1,27 @@
+package com.salesmanager.core.business.search.model;
+
+public class SearchFacet {
+
+ private String name;
+ private String key;
+ private long count;
+ public void setKey(String key) {
+ this.key = key;
+ }
+ public String getKey() {
+ return key;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+ public String getName() {
+ return name;
+ }
+ public void setCount(long count) {
+ this.count = count;
+ }
+ public long getCount() {
+ return count;
+ };
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/search/model/SearchKeywords.java b/sm-core/src/main/java/com/salesmanager/core/business/search/model/SearchKeywords.java
new file mode 100644
index 0000000..0ef1d3e
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/search/model/SearchKeywords.java
@@ -0,0 +1,34 @@
+package com.salesmanager.core.business.search.model;
+
+import java.util.List;
+
+import org.json.simple.JSONArray;
+import org.json.simple.JSONAware;
+import org.json.simple.JSONObject;
+
+public class SearchKeywords implements JSONAware{
+
+ private List<String> keywords;
+
+ public void setKeywords(List<String> keywords) {
+ this.keywords = keywords;
+ }
+
+ public List<String> getKeywords() {
+ return keywords;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public String toJSONString() {
+ JSONArray jsonArray = new JSONArray();
+ for(String kw : keywords) {
+ JSONObject data = new JSONObject();
+ data.put("name", kw);
+ data.put("value", kw);
+ jsonArray.add(data);
+ }
+ return jsonArray.toJSONString();
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/search/model/SearchResponse.java b/sm-core/src/main/java/com/salesmanager/core/business/search/model/SearchResponse.java
new file mode 100644
index 0000000..986c87a
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/search/model/SearchResponse.java
@@ -0,0 +1,39 @@
+package com.salesmanager.core.business.search.model;
+
+import java.util.List;
+import java.util.Map;
+
+public class SearchResponse {
+
+ private int totalCount = 0;//total number of entries
+ private int entryCount = 0;//number of entries asked
+
+ private List<SearchEntry> entries;
+ private Map<String,List<SearchFacet>> facets;//facet key (example : category) & facet description (example : category code)
+
+ public void setTotalCount(int totalCount) {
+ this.totalCount = totalCount;
+ }
+ public int getTotalCount() {
+ return totalCount;
+ }
+ public void setEntryCount(int entryCount) {
+ this.entryCount = entryCount;
+ }
+ public int getEntryCount() {
+ return entryCount;
+ }
+ public void setEntries(List<SearchEntry> entries) {
+ this.entries = entries;
+ }
+ public List<SearchEntry> getEntries() {
+ return entries;
+ }
+ public void setFacets(Map<String,List<SearchFacet>> facets) {
+ this.facets = facets;
+ }
+ public Map<String,List<SearchFacet>> getFacets() {
+ return facets;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/search/service/SearchService.java b/sm-core/src/main/java/com/salesmanager/core/business/search/service/SearchService.java
new file mode 100644
index 0000000..7f63e2c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/search/service/SearchService.java
@@ -0,0 +1,58 @@
+package com.salesmanager.core.business.search.service;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.search.model.SearchKeywords;
+import com.salesmanager.core.business.search.model.SearchResponse;
+
+public interface SearchService {
+
+ /**
+ * The indexing service for products. The index service must be invoked when a product is
+ * created or updated
+ * @param store
+ * @param product
+ * @throws ServiceException
+ */
+ void index(MerchantStore store, Product product) throws ServiceException;
+
+ /**
+ * Deletes an index in the appropriate language. Must be invoked when a product is deleted
+ * @param store
+ * @param product
+ * @throws ServiceException
+ */
+ void deleteIndex(MerchantStore store, Product product)
+ throws ServiceException;
+
+ /**
+ * Similar keywords based on a a series of characters. Used in the auto-complete
+ * functionality
+ * @param collectionName
+ * @param jsonString
+ * @param entriesCount
+ * @return
+ * @throws ServiceException
+ */
+ SearchKeywords searchForKeywords(String collectionName,
+ String jsonString, int entriesCount) throws ServiceException;
+
+ /**
+ * Search products based on user entry
+ * @param store
+ * @param languageCode
+ * @param jsonString
+ * @param entriesCount
+ * @param startIndex
+ * @throws ServiceException
+ */
+ SearchResponse search(MerchantStore store, String languageCode, String jsonString,
+ int entriesCount, int startIndex) throws ServiceException;
+
+ /**
+ * Initializes search service in order to avoid lazy initialization
+ */
+ void initService();
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/search/service/SearchServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/search/service/SearchServiceImpl.java
new file mode 100644
index 0000000..5065aa4
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/search/service/SearchServiceImpl.java
@@ -0,0 +1,316 @@
+package com.salesmanager.core.business.search.service;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.elasticsearch.common.text.Text;
+import org.elasticsearch.search.highlight.HighlightField;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.catalog.category.model.Category;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.description.ProductDescription;
+import com.salesmanager.core.business.catalog.product.model.price.FinalPrice;
+import com.salesmanager.core.business.catalog.product.service.PricingService;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.search.model.IndexProduct;
+import com.salesmanager.core.business.search.model.SearchEntry;
+import com.salesmanager.core.business.search.model.SearchFacet;
+import com.salesmanager.core.business.search.model.SearchKeywords;
+import com.salesmanager.core.constants.Constants;
+import com.salesmanager.core.utils.CoreConfiguration;
+import com.shopizer.search.services.Facet;
+import com.shopizer.search.services.SearchHit;
+import com.shopizer.search.services.SearchRequest;
+import com.shopizer.search.services.SearchResponse;
+
+
+@Service("productSearchService")
+public class SearchServiceImpl implements SearchService {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SearchServiceImpl.class);
+
+
+ private final static String PRODUCT_INDEX_NAME = "product";
+ private final static String UNDERSCORE = "_";
+ private final static String INDEX_PRODUCTS = "INDEX_PRODUCTS";
+
+ @Autowired
+ private com.shopizer.search.services.SearchService searchService;
+
+ @Autowired
+ private PricingService pricingService;
+
+ @Autowired
+ private CoreConfiguration configuration;
+
+ @Override
+ public void initService() {
+ searchService.initService();
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public void index(MerchantStore store, Product product)
+ throws ServiceException {
+
+ /**
+ * When a product is saved or updated the indexing process occurs
+ *
+ * A product entity will have to be transformed to a bean ProductIndex
+ * which contains the indices as described in product.json
+ *
+ * {"product": {
+ "properties" : {
+ "name" : {"type":"string","index":"analyzed"},
+ "price" : {"type":"string","index":"not_analyzed"},
+ "category" : {"type":"string","index":"not_analyzed"},
+ "lang" : {"type":"string","index":"not_analyzed"},
+ "available" : {"type":"string","index":"not_analyzed"},
+ "description" : {"type":"string","index":"analyzed","index_analyzer":"english"},
+ "tags" : {"type":"string","index":"not_analyzed"}
+ }
+ }
+ }
+ *
+ * productService saveOrUpdate as well as create and update will invoke
+ * productSearchService.index
+ *
+ * A copy of properies between Product to IndexProduct
+ * Then IndexProduct will be transformed to a json representation by the invocation
+ * of .toJSONString on IndexProduct
+ *
+ * Then index product
+ * searchService.index(json, "product_<LANGUAGE_CODE>_<MERCHANT_CODE>", "product");
+ *
+ * example ...index(json,"product_en_default",product)
+ *
+ */
+
+ if(configuration.getProperty(INDEX_PRODUCTS)==null || configuration.getProperty(INDEX_PRODUCTS).equals(Constants.FALSE)) {
+ return;
+ }
+
+ FinalPrice price = pricingService.calculateProductPrice(product);
+
+
+ Set<ProductDescription> descriptions = product.getDescriptions();
+ for(ProductDescription description : descriptions) {
+
+ StringBuilder collectionName = new StringBuilder();
+ collectionName.append(PRODUCT_INDEX_NAME).append(UNDERSCORE).append(description.getLanguage().getCode()).append(UNDERSCORE).append(store.getCode().toLowerCase());
+
+ IndexProduct index = new IndexProduct();
+
+ index.setId(String.valueOf(product.getId()));
+ index.setStore(store.getCode().toLowerCase());
+ index.setLang(description.getLanguage().getCode());
+ index.setAvailable(product.isAvailable());
+ index.setDescription(description.getDescription());
+ index.setName(description.getName());
+ if(product.getManufacturer()!=null) {
+ index.setManufacturer(String.valueOf(product.getManufacturer().getId()));
+ }
+ if(price!=null) {
+ index.setPrice(price.getFinalPrice().doubleValue());
+ }
+ index.setHighlight(description.getProductHighlight());
+ if(!StringUtils.isBlank(description.getMetatagKeywords())){
+ String[] tags = description.getMetatagKeywords().split(",");
+ @SuppressWarnings("unchecked")
+ List<String> tagsList = new ArrayList(Arrays.asList(tags));
+ index.setTags(tagsList);
+ }
+
+
+ Set<Category> categories = product.getCategories();
+ if(!CollectionUtils.isEmpty(categories)) {
+ List<String> categoryList = new ArrayList<String>();
+ for(Category category : categories) {
+ categoryList.add(category.getCode());
+ }
+ index.setCategories(categoryList);
+ }
+
+ String jsonString = index.toJSONString();
+ try {
+ searchService.index(jsonString, collectionName.toString(), new StringBuilder().append(PRODUCT_INDEX_NAME).append(UNDERSCORE).append(description.getLanguage().getCode()).toString());
+ } catch (Exception e) {
+ throw new ServiceException("Cannot index product id [" + product.getId() + "], " + e.getMessage() ,e);
+ }
+ }
+ }
+
+ @Override
+ public void deleteIndex(MerchantStore store, Product product) throws ServiceException {
+
+ if(configuration.getProperty(INDEX_PRODUCTS)==null || configuration.getProperty(INDEX_PRODUCTS).equals(Constants.FALSE)) {
+ return;
+ }
+
+ Set<ProductDescription> descriptions = product.getDescriptions();
+ for(ProductDescription description : descriptions) {
+
+ StringBuilder collectionName = new StringBuilder();
+ collectionName.append(PRODUCT_INDEX_NAME).append(UNDERSCORE).append(description.getLanguage().getCode()).append(UNDERSCORE).append(store.getCode().toLowerCase());
+
+ try {
+ searchService.deleteObject(collectionName.toString(), new StringBuilder().append(PRODUCT_INDEX_NAME).append(UNDERSCORE).append(description.getLanguage().getCode()).toString(), String.valueOf(product.getId()));
+ } catch (Exception e) {
+ LOGGER.error("Cannot delete index for product id [" + product.getId() + "], ",e);
+ }
+ }
+
+ }
+
+ @Override
+ public SearchKeywords searchForKeywords(String collectionName, String jsonString, int entriesCount) throws ServiceException {
+
+ /**
+ * $('#search').searchAutocomplete({
+ url: '<%=request.getContextPath()%>/search/autocomplete/keyword_en'
+ //filter: function() {
+ //return '\"filter\" : {\"numeric_range\" : {\"price\" : {\"from\" : \"22\",\"to\" : \"45\",\"include_lower\" : true,\"include_upper\" : true}}}';
+ //}
+ });
+
+ **/
+
+ try {
+
+ SearchResponse response = searchService.searchAutoComplete(collectionName, jsonString, entriesCount);
+
+ SearchKeywords keywords = new SearchKeywords();
+ keywords.setKeywords(Arrays.asList(response.getInlineSearchList()));
+
+ return keywords;
+
+ } catch (Exception e) {
+ LOGGER.error("Error while searching keywords " + jsonString,e);
+ throw new ServiceException(e);
+ }
+
+
+ }
+
+ @Override
+ public com.salesmanager.core.business.search.model.SearchResponse search(MerchantStore store, String languageCode, String jsonString, int entriesCount, int startIndex) throws ServiceException {
+
+
+ try {
+
+ StringBuilder collectionName = new StringBuilder();
+ collectionName.append(PRODUCT_INDEX_NAME).append(UNDERSCORE).append(languageCode).append(UNDERSCORE).append(store.getCode().toLowerCase());
+
+
+ SearchRequest request = new SearchRequest();
+ request.setCollection(collectionName.toString());
+ request.setSize(entriesCount);
+ request.setStart(startIndex);
+ request.setJson(jsonString);
+
+ SearchResponse response =searchService.search(request);
+
+ com.salesmanager.core.business.search.model.SearchResponse resp = new com.salesmanager.core.business.search.model.SearchResponse();
+
+
+ resp.setTotalCount(response.getCount());
+
+ List<SearchEntry> entries = new ArrayList<SearchEntry>();
+
+ Collection<SearchHit> hits = response.getSearchHits();
+ for(SearchHit hit : hits) {
+
+ SearchEntry entry = new SearchEntry();
+
+ Map<String,Object> metaEntries = hit.getMetaEntries();
+ IndexProduct indexProduct = new IndexProduct();
+ Map sourceEntries = (Map)metaEntries.get("source");
+
+ indexProduct.setDescription((String)sourceEntries.get("description"));
+ indexProduct.setHighlight((String)sourceEntries.get("highlight"));
+ indexProduct.setId((String)sourceEntries.get("id"));
+ indexProduct.setLang((String)sourceEntries.get("lang"));
+ indexProduct.setName(((String)sourceEntries.get("name")));
+ indexProduct.setManufacturer(((String)sourceEntries.get("manufacturer")));
+ indexProduct.setPrice(((Double)sourceEntries.get("price")));
+ indexProduct.setStore(((String)sourceEntries.get("store")));
+ entry.setIndexProduct(indexProduct);
+ entries.add(entry);
+
+ Map<String, HighlightField> fields = hit.getHighlightFields();
+ if(fields!=null) {
+ List<String> highlights = new ArrayList<String>();
+ for(HighlightField field : fields.values()) {
+
+ Text[] text = field.getFragments();
+ //text[0]
+ String f = field.getName();
+ highlights.add(f);
+
+
+ }
+
+ entry.setHighlights(highlights);
+
+ }
+ }
+
+ resp.setEntries(entries);
+
+ Map<String,Facet> facets = response.getFacets();
+ if(facets!=null) {
+ Map<String,List<SearchFacet>> searchFacets = new HashMap<String,List<SearchFacet>>();
+ for(String key : facets.keySet()) {
+
+ Facet f = facets.get(key);
+
+ List<SearchFacet> fs = searchFacets.get(key);
+ if(fs==null) {
+ fs = new ArrayList<SearchFacet>();
+ searchFacets.put(key, fs);
+ }
+
+ List<com.shopizer.search.services.Entry> facetEntries = f.getEntries();
+ for(com.shopizer.search.services.Entry facetEntry : facetEntries) {
+
+ SearchFacet searchFacet = new SearchFacet();
+ searchFacet.setKey(facetEntry.getName());
+ searchFacet.setName(facetEntry.getName());
+ searchFacet.setCount(f.getEntries().size());
+
+ fs.add(searchFacet);
+
+ }
+
+ }
+
+ resp.setFacets(searchFacets);
+
+ }
+
+
+
+ return resp;
+
+
+ } catch (Exception e) {
+ LOGGER.error("Error while searching keywords " + jsonString,e);
+ throw new ServiceException(e);
+ }
+
+ }
+
+}
+
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/PackageDetails.java b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/PackageDetails.java
new file mode 100644
index 0000000..0464ac5
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/PackageDetails.java
@@ -0,0 +1,65 @@
+package com.salesmanager.core.business.shipping.model;
+
+public class PackageDetails {
+
+ private double shippingWeight;
+ private double shippingMaxWeight;
+ private double shippingLength;
+ private double shippingHeight;
+ private double shippingWidth;
+ private int shippingQuantity;
+ private int treshold;
+
+ private String itemName = "";
+
+
+ public String getItemName() {
+ return itemName;
+ }
+ public void setItemName(String itemName) {
+ this.itemName = itemName;
+ }
+ public double getShippingWeight() {
+ return shippingWeight;
+ }
+ public void setShippingWeight(double shippingWeight) {
+ this.shippingWeight = shippingWeight;
+ }
+ public double getShippingMaxWeight() {
+ return shippingMaxWeight;
+ }
+ public void setShippingMaxWeight(double shippingMaxWeight) {
+ this.shippingMaxWeight = shippingMaxWeight;
+ }
+ public double getShippingLength() {
+ return shippingLength;
+ }
+ public void setShippingLength(double shippingLength) {
+ this.shippingLength = shippingLength;
+ }
+ public double getShippingHeight() {
+ return shippingHeight;
+ }
+ public void setShippingHeight(double shippingHeight) {
+ this.shippingHeight = shippingHeight;
+ }
+ public double getShippingWidth() {
+ return shippingWidth;
+ }
+ public void setShippingWidth(double shippingWidth) {
+ this.shippingWidth = shippingWidth;
+ }
+ public int getShippingQuantity() {
+ return shippingQuantity;
+ }
+ public void setShippingQuantity(int shippingQuantity) {
+ this.shippingQuantity = shippingQuantity;
+ }
+ public int getTreshold() {
+ return treshold;
+ }
+ public void setTreshold(int treshold) {
+ this.treshold = treshold;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingBasisType.java b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingBasisType.java
new file mode 100644
index 0000000..a28f2b5
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingBasisType.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.shipping.model;
+
+public enum ShippingBasisType {
+
+ BILLING, SHIPPING
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingConfiguration.java b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingConfiguration.java
new file mode 100644
index 0000000..3b6101c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingConfiguration.java
@@ -0,0 +1,359 @@
+package com.salesmanager.core.business.shipping.model;
+
+import java.math.BigDecimal;
+
+import org.json.simple.JSONAware;
+import org.json.simple.JSONObject;
+
+/**
+ * Object saved in the database maintaining various shipping options
+ * @author casams1
+ *
+ */
+public class ShippingConfiguration implements JSONAware {
+
+ //enums
+ private ShippingType shippingType = ShippingType.NATIONAL;
+ private ShippingBasisType shippingBasisType = ShippingBasisType.SHIPPING;
+ private ShippingOptionPriceType shippingOptionPriceType = ShippingOptionPriceType.ALL;
+ private ShippingPackageType shippingPackageType = ShippingPackageType.ITEM;
+ private ShippingDescription shippingDescription = ShippingDescription.SHORT_DESCRIPTION;
+ private ShippingType freeShippingType = null;
+
+ private int boxWidth = 0;
+ private int boxHeight = 0;
+ private int boxLength = 0;
+ private double boxWeight = 0;
+ private double maxWeight = 0;
+
+ //free shipping
+ private boolean freeShippingEnabled = false;
+ private BigDecimal orderTotalFreeShipping = null;
+
+
+ private BigDecimal handlingFees = null;
+ private boolean taxOnShipping = false;
+
+
+ //JSON bindings
+ private String shipType;
+ private String shipBaseType;
+ private String shipOptionPriceType = ShippingOptionPriceType.ALL.name();
+ private String shipPackageType;
+ private String shipDescription;
+ private String shipFreeType;
+
+ //Transient
+ private String orderTotalFreeShippingText = null;
+ private String handlingFeesText = null;
+
+
+ public String getShipType() {
+ return shipType;
+ }
+
+
+ public String getShipBaseType() {
+ return shipBaseType;
+ }
+
+
+ public String getShipOptionPriceType() {
+ return shipOptionPriceType;
+ }
+
+
+
+ public void setShippingOptionPriceType(ShippingOptionPriceType shippingOptionPriceType) {
+ this.shippingOptionPriceType = shippingOptionPriceType;
+ this.shipOptionPriceType = this.shippingOptionPriceType.name();
+ }
+
+
+ public ShippingOptionPriceType getShippingOptionPriceType() {
+ return shippingOptionPriceType;
+ }
+
+
+ public void setShippingBasisType(ShippingBasisType shippingBasisType) {
+ this.shippingBasisType = shippingBasisType;
+ this.shipBaseType = this.shippingBasisType.name();
+ }
+
+
+ public ShippingBasisType getShippingBasisType() {
+ return shippingBasisType;
+ }
+
+
+ public void setShippingType(ShippingType shippingType) {
+ this.shippingType = shippingType;
+ this.shipType = this.shippingType.name();
+ }
+
+
+ public ShippingType getShippingType() {
+ return shippingType;
+ }
+
+ public ShippingPackageType getShippingPackageType() {
+ return shippingPackageType;
+ }
+
+
+ public void setShippingPackageType(ShippingPackageType shippingPackageType) {
+ this.shippingPackageType = shippingPackageType;
+ this.shipPackageType = shippingPackageType.name();
+ }
+
+
+ public String getShipPackageType() {
+ return shipPackageType;
+ }
+
+
+ /** JSON bindding **/
+ public void setShipType(String shipType) {
+ this.shipType = shipType;
+ ShippingType sType = ShippingType.NATIONAL;
+ if(shipType.equals(ShippingType.INTERNATIONAL.name())) {
+ sType = ShippingType.INTERNATIONAL;
+ }
+ setShippingType(sType);
+ }
+
+
+ public void setShipOptionPriceType(String shipOptionPriceType) {
+ this.shipOptionPriceType = shipOptionPriceType;
+ ShippingOptionPriceType sType = ShippingOptionPriceType.ALL;
+ if(shipOptionPriceType.equals(ShippingOptionPriceType.HIGHEST.name())) {
+ sType = ShippingOptionPriceType.HIGHEST;
+ }
+ if(shipOptionPriceType.equals(ShippingOptionPriceType.LEAST.name())) {
+ sType = ShippingOptionPriceType.LEAST;
+ }
+ setShippingOptionPriceType(sType);
+ }
+
+
+ public void setShipBaseType(String shipBaseType) {
+ this.shipBaseType = shipBaseType;
+ ShippingBasisType sType = ShippingBasisType.SHIPPING;
+ if(shipBaseType.equals(ShippingBasisType.BILLING.name())) {
+ sType = ShippingBasisType.BILLING;
+ }
+ setShippingBasisType(sType);
+ }
+
+
+
+ public void setShipPackageType(String shipPackageType) {
+ this.shipPackageType = shipPackageType;
+ ShippingPackageType sType = ShippingPackageType.ITEM;
+ if(shipPackageType.equals(ShippingPackageType.BOX.name())) {
+ sType = ShippingPackageType.BOX;
+ }
+ this.setShippingPackageType(sType);
+ }
+
+ public void setShipDescription(String shipDescription) {
+ this.shipDescription = shipDescription;
+ ShippingDescription sType = ShippingDescription.SHORT_DESCRIPTION;
+ if(shipDescription.equals(ShippingDescription.LONG_DESCRIPTION.name())) {
+ sType = ShippingDescription.LONG_DESCRIPTION;
+ }
+ this.setShippingDescription(sType);
+ }
+
+ public void setShipFreeType(String shipFreeType) {
+ this.shipFreeType = shipFreeType;
+ ShippingType sType = ShippingType.NATIONAL;
+ if(shipFreeType.equals(ShippingType.INTERNATIONAL.name())) {
+ sType = ShippingType.INTERNATIONAL;
+ }
+ setFreeShippingType(sType);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public String toJSONString() {
+ JSONObject data = new JSONObject();
+ data.put("shipBaseType", this.getShippingBasisType().name());
+ data.put("shipOptionPriceType", this.getShippingOptionPriceType().name());
+ data.put("shipType", this.getShippingType().name());
+ data.put("shipPackageType", this.getShippingPackageType().name());
+ if(shipFreeType!=null) {
+ data.put("shipFreeType", this.getFreeShippingType().name());
+ }
+ data.put("shipDescription", this.getShippingDescription().name());
+
+
+ data.put("boxWidth", this.getBoxWidth());
+ data.put("boxHeight", this.getBoxHeight());
+ data.put("boxLength", this.getBoxLength());
+ data.put("boxWeight", this.getBoxWeight());
+ data.put("maxWeight", this.getMaxWeight());
+ data.put("freeShippingEnabled", this.freeShippingEnabled);
+ data.put("orderTotalFreeShipping", this.orderTotalFreeShipping);
+ data.put("handlingFees", this.handlingFees);
+ data.put("taxOnShipping", this.taxOnShipping);
+
+
+ return data.toJSONString();
+ }
+
+
+ public int getBoxWidth() {
+ return boxWidth;
+ }
+
+
+ public void setBoxWidth(int boxWidth) {
+ this.boxWidth = boxWidth;
+ }
+
+
+ public int getBoxHeight() {
+ return boxHeight;
+ }
+
+
+ public void setBoxHeight(int boxHeight) {
+ this.boxHeight = boxHeight;
+ }
+
+
+ public int getBoxLength() {
+ return boxLength;
+ }
+
+
+ public void setBoxLength(int boxLength) {
+ this.boxLength = boxLength;
+ }
+
+
+ public double getBoxWeight() {
+ return boxWeight;
+ }
+
+
+ public void setBoxWeight(double boxWeight) {
+ this.boxWeight = boxWeight;
+ }
+
+
+ public double getMaxWeight() {
+ return maxWeight;
+ }
+
+
+ public void setMaxWeight(double maxWeight) {
+ this.maxWeight = maxWeight;
+ }
+
+
+ public boolean isFreeShippingEnabled() {
+ return freeShippingEnabled;
+ }
+
+
+ public void setFreeShippingEnabled(boolean freeShippingEnabled) {
+ this.freeShippingEnabled = freeShippingEnabled;
+ }
+
+
+ public BigDecimal getOrderTotalFreeShipping() {
+ return orderTotalFreeShipping;
+ }
+
+
+ public void setOrderTotalFreeShipping(BigDecimal orderTotalFreeShipping) {
+ this.orderTotalFreeShipping = orderTotalFreeShipping;
+ }
+
+
+ public void setHandlingFees(BigDecimal handlingFees) {
+ this.handlingFees = handlingFees;
+ }
+
+
+ public BigDecimal getHandlingFees() {
+ return handlingFees;
+ }
+
+
+ public void setTaxOnShipping(boolean taxOnShipping) {
+ this.taxOnShipping = taxOnShipping;
+ }
+
+
+ public boolean isTaxOnShipping() {
+ return taxOnShipping;
+ }
+
+
+
+
+
+ public String getShipDescription() {
+ return shipDescription;
+ }
+
+
+ public void setShippingDescription(ShippingDescription shippingDescription) {
+ this.shippingDescription = shippingDescription;
+ }
+
+
+ public ShippingDescription getShippingDescription() {
+ return shippingDescription;
+ }
+
+
+ public void setFreeShippingType(ShippingType freeShippingType) {
+ this.freeShippingType = freeShippingType;
+ }
+
+
+ public ShippingType getFreeShippingType() {
+ return freeShippingType;
+ }
+
+
+
+ public String getShipFreeType() {
+ return shipFreeType;
+ }
+
+
+ public void setOrderTotalFreeShippingText(String orderTotalFreeShippingText) {
+ this.orderTotalFreeShippingText = orderTotalFreeShippingText;
+ }
+
+
+ public String getOrderTotalFreeShippingText() {
+ return orderTotalFreeShippingText;
+ }
+
+
+ public void setHandlingFeesText(String handlingFeesText) {
+ this.handlingFeesText = handlingFeesText;
+ }
+
+
+ public String getHandlingFeesText() {
+ return handlingFeesText;
+ }
+
+
+
+
+
+
+
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingDescription.java b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingDescription.java
new file mode 100644
index 0000000..97b6f98
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingDescription.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.shipping.model;
+
+public enum ShippingDescription {
+
+
+ SHORT_DESCRIPTION, LONG_DESCRIPTION
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingOption.java b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingOption.java
new file mode 100644
index 0000000..3cafa82
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingOption.java
@@ -0,0 +1,101 @@
+package com.salesmanager.core.business.shipping.model;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ShippingOption implements Serializable {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ShippingOption.class);
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+ private BigDecimal optionPrice;
+
+ private String optionName;
+ private String optionCode;
+ private String optionDeliveryDate;
+ private String optionShippingDate;
+ private String optionPriceText;
+ private String optionId;
+ private String description;
+
+ private String estimatedNumberOfDays;
+
+
+
+ public BigDecimal getOptionPrice() {
+
+ if(!StringUtils.isBlank(this.getOptionPriceText())) {
+ try {
+ this.optionPrice = new BigDecimal(this.getOptionPriceText());
+ } catch(Exception e) {
+ LOGGER.equals("Can't convert price text " + this.getOptionPriceText() + " to big decimal");
+ }
+ }
+
+ return optionPrice;
+ }
+
+ public void setOptionPrice(BigDecimal optionPrice) {
+ this.optionPrice = optionPrice;
+ }
+
+ public void setOptionCode(String optionCode) {
+ this.optionCode = optionCode;
+ }
+ public String getOptionCode() {
+ return optionCode;
+ }
+ public void setOptionName(String optionName) {
+ this.optionName = optionName;
+ }
+ public String getOptionName() {
+ return optionName;
+ }
+
+ public void setOptionPriceText(String optionPriceText) {
+ this.optionPriceText = optionPriceText;
+ }
+ public String getOptionPriceText() {
+ return optionPriceText;
+ }
+ public void setOptionId(String optionId) {
+ this.optionId = optionId;
+ }
+ public String getOptionId() {
+ return optionId;
+ }
+ public void setOptionDeliveryDate(String optionDeliveryDate) {
+ this.optionDeliveryDate = optionDeliveryDate;
+ }
+ public String getOptionDeliveryDate() {
+ return optionDeliveryDate;
+ }
+ public void setOptionShippingDate(String optionShippingDate) {
+ this.optionShippingDate = optionShippingDate;
+ }
+ public String getOptionShippingDate() {
+ return optionShippingDate;
+ }
+ public void setDescription(String description) {
+ this.description = description;
+ }
+ public String getDescription() {
+ return description;
+ }
+ public void setEstimatedNumberOfDays(String estimatedNumberOfDays) {
+ this.estimatedNumberOfDays = estimatedNumberOfDays;
+ }
+ public String getEstimatedNumberOfDays() {
+ return estimatedNumberOfDays;
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingOptionPriceType.java b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingOptionPriceType.java
new file mode 100644
index 0000000..91c9ed7
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingOptionPriceType.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.shipping.model;
+
+public enum ShippingOptionPriceType {
+
+ LEAST, HIGHEST, ALL
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingPackageType.java b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingPackageType.java
new file mode 100644
index 0000000..215c842
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingPackageType.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.shipping.model;
+
+public enum ShippingPackageType {
+
+ ITEM, BOX
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingProduct.java b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingProduct.java
new file mode 100644
index 0000000..f7c6b42
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingProduct.java
@@ -0,0 +1,27 @@
+package com.salesmanager.core.business.shipping.model;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+
+public class ShippingProduct {
+
+ public ShippingProduct(Product product) {
+ this.product = product;
+
+ }
+
+ private int quantity = 1;
+ private Product product;
+ public void setQuantity(int quantity) {
+ this.quantity = quantity;
+ }
+ public int getQuantity() {
+ return quantity;
+ }
+ public void setProduct(Product product) {
+ this.product = product;
+ }
+ public Product getProduct() {
+ return product;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingQuote.java b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingQuote.java
new file mode 100644
index 0000000..2e70b13
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingQuote.java
@@ -0,0 +1,99 @@
+package com.salesmanager.core.business.shipping.model;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.List;
+
+public class ShippingQuote implements Serializable {
+
+
+
+
+
+
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+ public final static String NO_SHIPPING_TO_SELECTED_COUNTRY = "NO_SHIPPING_TO_SELECTED_COUNTRY";
+ public final static String NO_SHIPPING_MODULE_CONFIGURED= "NO_SHIPPING_MODULE_CONFIGURED";
+ public final static String ERROR= "ERROR";
+
+ private String shippingModuleCode;
+ private List<ShippingOption> shippingOptions = null;
+ /** if an error occurs, this field will be populated from constants defined above **/
+ private String shippingReturnCode = null;
+ /** indicates if this quote is configured with free shipping **/
+ private boolean freeShipping;
+ /** the threshold amount for being free shipping **/
+ private BigDecimal freeShippingAmount;
+ /** handling fees to be added on top of shipping fees **/
+ private BigDecimal handlingFees;
+ /** apply tax on shipping **/
+ private boolean applyTaxOnShipping;
+
+ private ShippingOption selectedShippingOption = null;
+
+ private String quoteError = null;
+
+
+
+ public void setShippingOptions(List<ShippingOption> shippingOptions) {
+ this.shippingOptions = shippingOptions;
+ }
+ public List<ShippingOption> getShippingOptions() {
+ return shippingOptions;
+ }
+ public void setShippingModuleCode(String shippingModuleCode) {
+ this.shippingModuleCode = shippingModuleCode;
+ }
+ public String getShippingModuleCode() {
+ return shippingModuleCode;
+ }
+ public void setShippingReturnCode(String shippingReturnCode) {
+ this.shippingReturnCode = shippingReturnCode;
+ }
+ public String getShippingReturnCode() {
+ return shippingReturnCode;
+ }
+ public void setFreeShipping(boolean freeShipping) {
+ this.freeShipping = freeShipping;
+ }
+ public boolean isFreeShipping() {
+ return freeShipping;
+ }
+ public void setFreeShippingAmount(BigDecimal freeShippingAmount) {
+ this.freeShippingAmount = freeShippingAmount;
+ }
+ public BigDecimal getFreeShippingAmount() {
+ return freeShippingAmount;
+ }
+ public void setHandlingFees(BigDecimal handlingFees) {
+ this.handlingFees = handlingFees;
+ }
+ public BigDecimal getHandlingFees() {
+ return handlingFees;
+ }
+ public void setApplyTaxOnShipping(boolean applyTaxOnShipping) {
+ this.applyTaxOnShipping = applyTaxOnShipping;
+ }
+ public boolean isApplyTaxOnShipping() {
+ return applyTaxOnShipping;
+ }
+ public void setSelectedShippingOption(ShippingOption selectedShippingOption) {
+ this.selectedShippingOption = selectedShippingOption;
+ }
+ public ShippingOption getSelectedShippingOption() {
+ return selectedShippingOption;
+ }
+ public String getQuoteError() {
+ return quoteError;
+ }
+ public void setQuoteError(String quoteError) {
+ this.quoteError = quoteError;
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingSummary.java b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingSummary.java
new file mode 100644
index 0000000..58b9e3e
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingSummary.java
@@ -0,0 +1,60 @@
+package com.salesmanager.core.business.shipping.model;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * Contains shipping fees according to user selections
+ * @author casams1
+ *
+ */
+public class ShippingSummary implements Serializable {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+ private BigDecimal shipping;
+ private BigDecimal handling;
+ private String shippingModule;
+ private String shippingOption;
+ private boolean freeShipping;
+ private boolean taxOnShipping;
+ public BigDecimal getShipping() {
+ return shipping;
+ }
+ public void setShipping(BigDecimal shipping) {
+ this.shipping = shipping;
+ }
+ public BigDecimal getHandling() {
+ return handling;
+ }
+ public void setHandling(BigDecimal handling) {
+ this.handling = handling;
+ }
+ public String getShippingModule() {
+ return shippingModule;
+ }
+ public void setShippingModule(String shippingModule) {
+ this.shippingModule = shippingModule;
+ }
+ public String getShippingOption() {
+ return shippingOption;
+ }
+ public void setShippingOption(String shippingOption) {
+ this.shippingOption = shippingOption;
+ }
+ public boolean isFreeShipping() {
+ return freeShipping;
+ }
+ public void setFreeShipping(boolean freeShipping) {
+ this.freeShipping = freeShipping;
+ }
+ public boolean isTaxOnShipping() {
+ return taxOnShipping;
+ }
+ public void setTaxOnShipping(boolean taxOnShipping) {
+ this.taxOnShipping = taxOnShipping;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingType.java b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingType.java
new file mode 100644
index 0000000..af8bd46
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shipping/model/ShippingType.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.shipping.model;
+
+public enum ShippingType {
+
+ NATIONAL, INTERNATIONAL
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shipping/service/ShippingService.java b/sm-core/src/main/java/com/salesmanager/core/business/shipping/service/ShippingService.java
new file mode 100755
index 0000000..9b5ccca
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shipping/service/ShippingService.java
@@ -0,0 +1,198 @@
+package com.salesmanager.core.business.shipping.service;
+
+import java.util.List;
+import java.util.Map;
+
+import com.salesmanager.core.business.common.model.Delivery;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.shipping.model.PackageDetails;
+import com.salesmanager.core.business.shipping.model.ShippingConfiguration;
+import com.salesmanager.core.business.shipping.model.ShippingOption;
+import com.salesmanager.core.business.shipping.model.ShippingProduct;
+import com.salesmanager.core.business.shipping.model.ShippingQuote;
+import com.salesmanager.core.business.shipping.model.ShippingSummary;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartItem;
+import com.salesmanager.core.business.system.model.CustomIntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+
+public interface ShippingService {
+
+ /**
+ * Returns a list of supported countries (ship to country list) configured by merchant
+ * when the merchant configured shipping National and has saved a list of ship to country
+ * from the list
+ * @param store
+ * @return
+ * @throws ServiceException
+ */
+ public List<String> getSupportedCountries(MerchantStore store)
+ throws ServiceException;
+
+ public void setSupportedCountries(MerchantStore store,
+ List<String> countryCodes) throws ServiceException;
+
+ /**
+ * Returns a list of available shipping modules
+ * @param store
+ * @return
+ * @throws ServiceException
+ */
+ public List<IntegrationModule> getShippingMethods(MerchantStore store)
+ throws ServiceException;
+
+
+ /**
+ * Returns a list of configured shipping modules for a given merchant
+ * @param store
+ * @return
+ * @throws ServiceException
+ */
+ Map<String, IntegrationConfiguration> getShippingModulesConfigured(
+ MerchantStore store) throws ServiceException;
+
+ /**
+ * Adds a Shipping configuration
+ * @param configuration
+ * @param store
+ * @throws ServiceException
+ */
+ void saveShippingQuoteModuleConfiguration(IntegrationConfiguration configuration,
+ MerchantStore store) throws ServiceException;
+
+ /**
+ * ShippingType (NATIONAL, INTERNATIONSL)
+ * ShippingBasisType (SHIPPING, BILLING)
+ * ShippingPriceOptionType (ALL, LEAST, HIGHEST)
+ * Packages
+ * Handling
+ * @param store
+ * @return
+ * @throws ServiceException
+ */
+ ShippingConfiguration getShippingConfiguration(MerchantStore store)
+ throws ServiceException;
+
+ /**
+ * Saves ShippingConfiguration for a given MerchantStore
+ * @param shippingConfiguration
+ * @param store
+ * @throws ServiceException
+ */
+ void saveShippingConfiguration(ShippingConfiguration shippingConfiguration,
+ MerchantStore store) throws ServiceException;
+
+ void removeShippingQuoteModuleConfiguration(String moduleCode,
+ MerchantStore store) throws ServiceException;
+
+ /**
+ * Provides detailed information on boxes that will be used
+ * when getting a ShippingQuote
+ * @param products
+ * @param store
+ * @return
+ * @throws ServiceException
+ */
+ List<PackageDetails> getPackagesDetails(List<ShippingProduct> products,
+ MerchantStore store) throws ServiceException;
+
+ /**
+ * Get a list of ShippingQuote from a configured
+ * shipping gateway. The quotes are displayed to the end user so he can pick
+ * the ShippingOption he wants
+ * @param store
+ * @param customer
+ * @param products
+ * @param language
+ * @return
+ * @throws ServiceException
+ */
+ ShippingQuote getShippingQuote(MerchantStore store, Delivery delivery,
+ List<ShippingProduct> products, Language language)
+ throws ServiceException;
+
+
+ /**
+ * Returns a shipping module configuration given a moduleCode
+ * @param moduleCode
+ * @param store
+ * @return
+ * @throws ServiceException
+ */
+ IntegrationConfiguration getShippingConfiguration(String moduleCode,
+ MerchantStore store) throws ServiceException;
+
+ /**
+ * Retrieves the custom configuration for a given module
+ * @param moduleCode
+ * @param store
+ * @return
+ * @throws ServiceException
+ */
+
+
+ CustomIntegrationConfiguration getCustomShippingConfiguration(
+ String moduleCode, MerchantStore store) throws ServiceException;
+
+ /**
+ * Weight based configuration
+ * @param moduleCode
+ * @param shippingConfiguration
+ * @param store
+ * @throws ServiceException
+ */
+ void saveCustomShippingConfiguration(String moduleCode,
+ CustomIntegrationConfiguration shippingConfiguration,
+ MerchantStore store) throws ServiceException;
+
+ /**
+ * Removes a custom shipping quote
+ * module
+ * @param moduleCode
+ * @param store
+ * @throws ServiceException
+ */
+ void removeCustomShippingQuoteModuleConfiguration(String moduleCode,
+ MerchantStore store) throws ServiceException;
+
+ /**
+ * The {@link ShippingSummary} is built from the ShippingOption the user has selected
+ * The ShippingSummary is used for order calculation
+ * @param store
+ * @param shippingQuote
+ * @param selectedShippingOption
+ * @return
+ * @throws ServiceException
+ */
+ ShippingSummary getShippingSummary(MerchantStore store, ShippingQuote shippingQuote,
+ ShippingOption selectedShippingOption) throws ServiceException;
+
+ /**
+ * Returns a list of supported countries (ship to country list) configured by merchant
+ * If the merchant configured shipping National, then only store country will be in the list
+ * If the merchant configured shipping International, then the list of accepted country is returned
+ * from the list
+ * @param store
+ * @param language
+ * @return
+ * @throws ServiceException
+ */
+ List<Country> getShipToCountryList(MerchantStore store, Language language)
+ throws ServiceException;
+
+ /**
+ * Determines if Shipping should be proposed to the customer
+ * @param items
+ * @param store
+ * @return
+ * @throws ServiceException
+ */
+ boolean requiresShipping(List<ShoppingCartItem> items, MerchantStore store) throws ServiceException;
+
+
+
+
+}
\ No newline at end of file
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shipping/service/ShippingServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/shipping/service/ShippingServiceImpl.java
new file mode 100755
index 0000000..cca2e23
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shipping/service/ShippingServiceImpl.java
@@ -0,0 +1,750 @@
+package com.salesmanager.core.business.shipping.service;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import javax.annotation.Resource;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.Validate;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.price.FinalPrice;
+import com.salesmanager.core.business.catalog.product.service.PricingService;
+import com.salesmanager.core.business.common.model.Delivery;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.country.service.CountryService;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.language.service.LanguageService;
+import com.salesmanager.core.business.shipping.model.PackageDetails;
+import com.salesmanager.core.business.shipping.model.ShippingConfiguration;
+import com.salesmanager.core.business.shipping.model.ShippingOption;
+import com.salesmanager.core.business.shipping.model.ShippingOptionPriceType;
+import com.salesmanager.core.business.shipping.model.ShippingPackageType;
+import com.salesmanager.core.business.shipping.model.ShippingProduct;
+import com.salesmanager.core.business.shipping.model.ShippingQuote;
+import com.salesmanager.core.business.shipping.model.ShippingSummary;
+import com.salesmanager.core.business.shipping.model.ShippingType;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartItem;
+import com.salesmanager.core.business.system.model.CustomIntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+import com.salesmanager.core.business.system.model.MerchantConfiguration;
+import com.salesmanager.core.business.system.model.MerchantLog;
+import com.salesmanager.core.business.system.service.MerchantConfigurationService;
+import com.salesmanager.core.business.system.service.MerchantLogService;
+import com.salesmanager.core.business.system.service.ModuleConfigurationService;
+import com.salesmanager.core.constants.ShippingConstants;
+import com.salesmanager.core.modules.integration.IntegrationException;
+import com.salesmanager.core.modules.integration.shipping.model.Packaging;
+import com.salesmanager.core.modules.integration.shipping.model.ShippingQuoteModule;
+import com.salesmanager.core.modules.utils.Encryption;
+import com.salesmanager.core.utils.reference.ConfigurationModulesLoader;
+
+@Service("shippingService")
+public class ShippingServiceImpl implements ShippingService {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ShippingServiceImpl.class);
+
+
+ private final static String SUPPORTED_COUNTRIES = "SUPPORTED_CNTR";
+ private final static String SHIPPING_MODULES = "SHIPPING";
+
+ @Autowired
+ private MerchantConfigurationService merchantConfigurationService;
+
+
+ @Autowired
+ private PricingService pricingService;
+
+ @Autowired
+ private ModuleConfigurationService moduleConfigurationService;
+
+ @Autowired
+ private Packaging packaging;
+
+ @Autowired
+ private CountryService countryService;
+
+ @Autowired
+ private LanguageService languageService;
+
+ @Autowired
+ private Encryption encryption;
+
+ @Autowired
+ private MerchantLogService merchantLogService;
+
+ @Autowired
+ @Resource(name="shippingModules")
+ private Map<String,ShippingQuoteModule> shippingModules;
+
+ @Override
+ public ShippingConfiguration getShippingConfiguration(MerchantStore store) throws ServiceException {
+
+ MerchantConfiguration configuration = merchantConfigurationService.getMerchantConfiguration(ShippingConstants.SHIPPING_CONFIGURATION, store);
+
+ ShippingConfiguration shippingConfiguration = null;
+
+ if(configuration!=null) {
+ String value = configuration.getValue();
+
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ shippingConfiguration = mapper.readValue(value, ShippingConfiguration.class);
+ } catch(Exception e) {
+ throw new ServiceException("Cannot parse json string " + value);
+ }
+ }
+ return shippingConfiguration;
+
+ }
+
+ @Override
+ public IntegrationConfiguration getShippingConfiguration(String moduleCode, MerchantStore store) throws ServiceException {
+
+
+ Map<String,IntegrationConfiguration> configuredModules = getShippingModulesConfigured(store);
+ if(configuredModules!=null) {
+ for(String key : configuredModules.keySet()) {
+ if(key.equals(moduleCode)) {
+ return configuredModules.get(key);
+ }
+ }
+ }
+
+ return null;
+
+ }
+
+ @Override
+ public CustomIntegrationConfiguration getCustomShippingConfiguration(String moduleCode, MerchantStore store) throws ServiceException {
+
+
+ ShippingQuoteModule quoteModule = (ShippingQuoteModule)shippingModules.get(moduleCode);
+ if(quoteModule==null) {
+ return null;
+ }
+ return quoteModule.getCustomModuleConfiguration(store);
+
+ }
+
+ @Override
+ public void saveShippingConfiguration(ShippingConfiguration shippingConfiguration, MerchantStore store) throws ServiceException {
+
+ MerchantConfiguration configuration = merchantConfigurationService.getMerchantConfiguration(ShippingConstants.SHIPPING_CONFIGURATION, store);
+
+ if(configuration==null) {
+ configuration = new MerchantConfiguration();
+ configuration.setMerchantStore(store);
+ configuration.setKey(ShippingConstants.SHIPPING_CONFIGURATION);
+ }
+
+ String value = shippingConfiguration.toJSONString();
+ configuration.setValue(value);
+ merchantConfigurationService.saveOrUpdate(configuration);
+
+ }
+
+ @Override
+ public void saveCustomShippingConfiguration(String moduleCode, CustomIntegrationConfiguration shippingConfiguration, MerchantStore store) throws ServiceException {
+
+
+ ShippingQuoteModule quoteModule = (ShippingQuoteModule)shippingModules.get(moduleCode);
+ if(quoteModule==null) {
+ throw new ServiceException("Shipping module " + moduleCode + " does not exist");
+ }
+
+ String configurationValue = shippingConfiguration.toJSONString();
+
+
+ try {
+
+ MerchantConfiguration configuration = merchantConfigurationService.getMerchantConfiguration(moduleCode, store);
+
+ if(configuration==null) {
+
+ configuration = new MerchantConfiguration();
+ configuration.setKey(moduleCode);
+ configuration.setMerchantStore(store);
+ }
+ configuration.setValue(configurationValue);
+ merchantConfigurationService.saveOrUpdate(configuration);
+
+ } catch (Exception e) {
+ throw new IntegrationException(e);
+ }
+
+
+
+ }
+
+
+ @Override
+ public List<IntegrationModule> getShippingMethods(MerchantStore store) throws ServiceException {
+
+ List<IntegrationModule> modules = moduleConfigurationService.getIntegrationModules(SHIPPING_MODULES);
+ List<IntegrationModule> returnModules = new ArrayList<IntegrationModule>();
+
+ for(IntegrationModule module : modules) {
+ if(module.getRegionsSet().contains(store.getCountry().getIsoCode())
+ || module.getRegionsSet().contains("*")) {
+
+ returnModules.add(module);
+ }
+ }
+
+ return returnModules;
+ }
+
+ @Override
+ public void saveShippingQuoteModuleConfiguration(IntegrationConfiguration configuration, MerchantStore store) throws ServiceException {
+
+ //validate entries
+ try {
+
+ String moduleCode = configuration.getModuleCode();
+ ShippingQuoteModule quoteModule = (ShippingQuoteModule)shippingModules.get(moduleCode);
+ if(quoteModule==null) {
+ throw new ServiceException("Shipping quote module " + moduleCode + " does not exist");
+ }
+ quoteModule.validateModuleConfiguration(configuration, store);
+
+ } catch (IntegrationException ie) {
+ throw ie;
+ }
+
+ try {
+ Map<String,IntegrationConfiguration> modules = new HashMap<String,IntegrationConfiguration>();
+ MerchantConfiguration merchantConfiguration = merchantConfigurationService.getMerchantConfiguration(SHIPPING_MODULES, store);
+ if(merchantConfiguration!=null) {
+ if(!StringUtils.isBlank(merchantConfiguration.getValue())) {
+
+ String decrypted = encryption.decrypt(merchantConfiguration.getValue());
+ modules = ConfigurationModulesLoader.loadIntegrationConfigurations(decrypted);
+ }
+ } else {
+ merchantConfiguration = new MerchantConfiguration();
+ merchantConfiguration.setMerchantStore(store);
+ merchantConfiguration.setKey(SHIPPING_MODULES);
+ }
+ modules.put(configuration.getModuleCode(), configuration);
+
+ String configs = ConfigurationModulesLoader.toJSONString(modules);
+
+ String encrypted = encryption.encrypt(configs);
+ merchantConfiguration.setValue(encrypted);
+ merchantConfigurationService.saveOrUpdate(merchantConfiguration);
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+ }
+
+
+ @Override
+ public void removeShippingQuoteModuleConfiguration(String moduleCode, MerchantStore store) throws ServiceException {
+
+
+
+ try {
+ Map<String,IntegrationConfiguration> modules = new HashMap<String,IntegrationConfiguration>();
+ MerchantConfiguration merchantConfiguration = merchantConfigurationService.getMerchantConfiguration(SHIPPING_MODULES, store);
+ if(merchantConfiguration!=null) {
+ if(!StringUtils.isBlank(merchantConfiguration.getValue())) {
+ String decrypted = encryption.decrypt(merchantConfiguration.getValue());
+ modules = ConfigurationModulesLoader.loadIntegrationConfigurations(decrypted);
+ }
+
+ modules.remove(moduleCode);
+ String configs = ConfigurationModulesLoader.toJSONString(modules);
+ String encrypted = encryption.encrypt(configs);
+ merchantConfiguration.setValue(encrypted);
+ merchantConfigurationService.saveOrUpdate(merchantConfiguration);
+
+
+ }
+
+ MerchantConfiguration configuration = merchantConfigurationService.getMerchantConfiguration(moduleCode, store);
+
+ if(configuration!=null) {//custom module
+
+ merchantConfigurationService.delete(configuration);
+ }
+
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+ }
+
+ @Override
+ public void removeCustomShippingQuoteModuleConfiguration(String moduleCode, MerchantStore store) throws ServiceException {
+
+
+
+ try {
+
+ removeShippingQuoteModuleConfiguration(moduleCode,store);
+ MerchantConfiguration merchantConfiguration = merchantConfigurationService.getMerchantConfiguration(moduleCode, store);
+ if(merchantConfiguration!=null) {
+ merchantConfigurationService.delete(merchantConfiguration);
+ }
+
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+ }
+
+ @Override
+ public Map<String,IntegrationConfiguration> getShippingModulesConfigured(MerchantStore store) throws ServiceException {
+ try {
+
+
+ Map<String,IntegrationConfiguration> modules = new HashMap<String,IntegrationConfiguration>();
+ MerchantConfiguration merchantConfiguration = merchantConfigurationService.getMerchantConfiguration(SHIPPING_MODULES, store);
+ if(merchantConfiguration!=null) {
+ if(!StringUtils.isBlank(merchantConfiguration.getValue())) {
+ String decrypted = encryption.decrypt(merchantConfiguration.getValue());
+ modules = ConfigurationModulesLoader.loadIntegrationConfigurations(decrypted);
+
+ }
+ }
+ return modules;
+
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+ }
+
+ @Override
+ public ShippingSummary getShippingSummary(MerchantStore store, ShippingQuote shippingQuote, ShippingOption selectedShippingOption) throws ServiceException {
+
+ ShippingSummary shippingSummary = new ShippingSummary();
+ shippingSummary.setFreeShipping(shippingQuote.isFreeShipping());
+ shippingSummary.setHandling(shippingQuote.getHandlingFees());
+ shippingSummary.setShipping(selectedShippingOption.getOptionPrice());
+ shippingSummary.setShippingModule(shippingQuote.getShippingModuleCode());
+ shippingSummary.setShippingOption(selectedShippingOption.getDescription());
+
+ return shippingSummary;
+ }
+
+ @Override
+ public ShippingQuote getShippingQuote(MerchantStore store, Delivery delivery, List<ShippingProduct> products, Language language) throws ServiceException {
+
+ ShippingQuote shippingQuote = new ShippingQuote();
+ ShippingQuoteModule shippingQuoteModule = null;
+
+ try {
+
+ //get configuration
+ ShippingConfiguration shippingConfiguration = getShippingConfiguration(store);
+ ShippingType shippingType = ShippingType.INTERNATIONAL;
+
+ 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);
+ 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 module
+ List<ShippingOption> shippingOptions = null;
+
+ try {
+ shippingOptions = shippingQuoteModule.getShippingQuotes(packages, orderTotal, delivery, 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) {
+ 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);
+
+ 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);
+ }
+
+ }
+
+ shippingQuote.setShippingOptions(shippingOptions);
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+ return shippingQuote;
+
+ }
+
+ @Override
+ public List<String> getSupportedCountries(MerchantStore store) throws ServiceException {
+
+ List<String> supportedCountries = new ArrayList<String>();
+ MerchantConfiguration configuration = merchantConfigurationService.getMerchantConfiguration(SUPPORTED_COUNTRIES, store);
+
+ if(configuration!=null) {
+
+ String countries = configuration.getValue();
+ if(!StringUtils.isBlank(countries)) {
+
+ Object objRegions=JSONValue.parse(countries);
+ JSONArray arrayRegions=(JSONArray)objRegions;
+ @SuppressWarnings("rawtypes")
+ Iterator i = arrayRegions.iterator();
+ while(i.hasNext()) {
+ supportedCountries.add((String)i.next());
+ }
+ }
+
+ }
+
+ return supportedCountries;
+ }
+
+ @Override
+ public List<Country> getShipToCountryList(MerchantStore store, Language language) throws ServiceException {
+
+
+ ShippingConfiguration shippingConfiguration = getShippingConfiguration(store);
+ ShippingType shippingType = ShippingType.INTERNATIONAL;
+ List<String> supportedCountries = new ArrayList<String>();
+ if(shippingConfiguration==null) {
+ shippingConfiguration = new ShippingConfiguration();
+ }
+
+ if(shippingConfiguration.getShippingType()!=null) {
+ shippingType = shippingConfiguration.getShippingType();
+ }
+
+
+ if(shippingType.name().equals(ShippingType.NATIONAL.name())){
+
+ supportedCountries.add(store.getCountry().getIsoCode());
+
+ } else {
+
+ MerchantConfiguration configuration = merchantConfigurationService.getMerchantConfiguration(SUPPORTED_COUNTRIES, store);
+
+ if(configuration!=null) {
+
+ String countries = configuration.getValue();
+ if(!StringUtils.isBlank(countries)) {
+
+ Object objRegions=JSONValue.parse(countries);
+ JSONArray arrayRegions=(JSONArray)objRegions;
+ @SuppressWarnings("rawtypes")
+ Iterator i = arrayRegions.iterator();
+ while(i.hasNext()) {
+ supportedCountries.add((String)i.next());
+ }
+ }
+
+ }
+
+ }
+
+ return countryService.getCountries(supportedCountries, language);
+
+ }
+
+
+ @Override
+ public void setSupportedCountries(MerchantStore store, List<String> countryCodes) throws ServiceException {
+
+
+ //transform a list of string to json entry
+ ObjectMapper mapper = new ObjectMapper();
+
+ try {
+ String value = mapper.writeValueAsString(countryCodes);
+
+ MerchantConfiguration configuration = merchantConfigurationService.getMerchantConfiguration(SUPPORTED_COUNTRIES, store);
+
+ if(configuration==null) {
+ configuration = new MerchantConfiguration();
+ configuration.
+ setKey(SUPPORTED_COUNTRIES);
+ configuration.setMerchantStore(store);
+ }
+
+ configuration.setValue(value);
+
+ merchantConfigurationService.saveOrUpdate(configuration);
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+ }
+
+
+ private BigDecimal calculateOrderTotal(List<ShippingProduct> products, MerchantStore store) throws Exception {
+
+ BigDecimal total = new BigDecimal(0);
+ for(ShippingProduct shippingProduct : products) {
+ FinalPrice price = pricingService.calculateProductPrice(shippingProduct.getProduct());
+
+ BigDecimal currentPrice = price.getFinalPrice();
+ currentPrice = currentPrice.multiply(new BigDecimal(shippingProduct.getQuantity()));
+ total = total.add(currentPrice);
+ }
+
+
+ return total;
+
+
+ }
+
+ @Override
+ public List<PackageDetails> getPackagesDetails(
+ List<ShippingProduct> products, MerchantStore store)
+ throws ServiceException {
+
+ List<PackageDetails> packages = null;
+
+ ShippingConfiguration shippingConfiguration = this.getShippingConfiguration(store);
+ //determine if the system has to use BOX or ITEM
+ ShippingPackageType shippingPackageType = ShippingPackageType.ITEM;
+ if(shippingConfiguration!=null) {
+ shippingPackageType = shippingConfiguration.getShippingPackageType();
+ }
+
+ if(shippingPackageType.name().equals(ShippingPackageType.BOX.name())){
+ packages = packaging.getBoxPackagesDetails(products, store);
+ } else {
+ packages = packaging.getItemPackagesDetails(products, store);
+ }
+
+ return packages;
+
+ }
+
+ @Override
+ public boolean requiresShipping(List<ShoppingCartItem> items,
+ MerchantStore store) throws ServiceException {
+
+ boolean requiresShipping = false;
+ for(ShoppingCartItem item : items) {
+ Product product = item.getProduct();
+ if(!product.isProductVirtual() && product.isProductShipeable()) {
+ requiresShipping = true;
+ }
+ }
+
+ return requiresShipping;
+ }
+
+
+
+
+
+}
+
+
+
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/dao/ShoppingCartDao.java b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/dao/ShoppingCartDao.java
new file mode 100644
index 0000000..4c804dd
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/dao/ShoppingCartDao.java
@@ -0,0 +1,34 @@
+package com.salesmanager.core.business.shoppingcart.dao;
+
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCart;
+
+public interface ShoppingCartDao extends SalesManagerEntityDao<Long, ShoppingCart> {
+
+ ShoppingCart getById(Long id, MerchantStore store);
+
+ ShoppingCart getByCustomer(Customer customer);
+
+ ShoppingCart getByCode(String code, MerchantStore store);
+
+ /**
+ * Get a ShoppingCart object without collection objects
+ * @param id
+ * @return
+ */
+ ShoppingCart getShoppingCartById(Long id);
+
+ /**
+ * Get a ShoppingCart object without collection objects
+ * @param code
+ * @return
+ */
+ ShoppingCart getShoppingCartByCode(String code);
+
+ public void removeShoppingCart(ShoppingCart cart);
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/dao/ShoppingCartDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/dao/ShoppingCartDaoImpl.java
new file mode 100644
index 0000000..b0ddde4
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/dao/ShoppingCartDaoImpl.java
@@ -0,0 +1,160 @@
+package com.salesmanager.core.business.shoppingcart.dao;
+
+import java.util.List;
+
+import javax.persistence.NonUniqueResultException;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.shoppingcart.model.QShoppingCart;
+import com.salesmanager.core.business.shoppingcart.model.QShoppingCartItem;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCart;
+
+@Repository("shoppingCartDao")
+public class ShoppingCartDaoImpl extends SalesManagerEntityDaoImpl<Long, ShoppingCart>
+ implements ShoppingCartDao {
+
+
+ @Override
+ public ShoppingCart getById(final Long id) {
+
+ try {
+ QShoppingCart qShoppingCart = QShoppingCart.shoppingCart;
+ QShoppingCartItem qShoppingCartItem = QShoppingCartItem.shoppingCartItem;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qShoppingCart)
+ .leftJoin(qShoppingCart.lineItems, qShoppingCartItem).fetch()
+ .leftJoin(qShoppingCartItem.attributes).fetch()
+ .leftJoin(qShoppingCart.merchantStore).fetch()
+ .where(qShoppingCart.id.eq(id));
+
+ return query.uniqueResult(qShoppingCart);
+ } catch(javax.persistence.NoResultException ers) {
+ return null;
+ }
+
+ }
+
+ @Override
+ public ShoppingCart getShoppingCartById(final Long id) {
+
+ QShoppingCart qShoppingCart = QShoppingCart.shoppingCart;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qShoppingCart)
+ .leftJoin(qShoppingCart.merchantStore).fetch()
+ .where(qShoppingCart.id.eq(id));
+
+ return query.uniqueResult(qShoppingCart);
+
+ }
+
+ @Override
+ public ShoppingCart getShoppingCartByCode(final String code) {
+
+ QShoppingCart qShoppingCart = QShoppingCart.shoppingCart;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qShoppingCart)
+ .leftJoin(qShoppingCart.merchantStore).fetch()
+ .where(qShoppingCart.shoppingCartCode.eq(code));
+
+ List<ShoppingCart> results = query.list(qShoppingCart);
+ if (results.isEmpty()) return null;
+
+ else if (results.size() >= 1) return results.get(0);
+ return null;
+
+
+ }
+
+ @Override
+ public ShoppingCart getById(final Long id, final MerchantStore store) {
+
+ try {
+
+ QShoppingCart qShoppingCart = QShoppingCart.shoppingCart;
+ QShoppingCartItem qShoppingCartItem = QShoppingCartItem.shoppingCartItem;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qShoppingCart)
+ .leftJoin(qShoppingCart.lineItems, qShoppingCartItem).fetch()
+ .leftJoin(qShoppingCartItem.attributes).fetch()
+ .leftJoin(qShoppingCart.merchantStore).fetch()
+ .where(qShoppingCart.id.eq(id)
+ .and(qShoppingCart.merchantStore.id.eq(store.getId())));
+
+ return query.uniqueResult(qShoppingCart);
+
+ } catch(javax.persistence.NoResultException ers) {
+ return null;
+ }
+
+ }
+
+ @Override
+ public ShoppingCart getByCode(final String code, final MerchantStore store) {
+
+
+ QShoppingCart qShoppingCart = QShoppingCart.shoppingCart;
+ QShoppingCartItem qShoppingCartItem = QShoppingCartItem.shoppingCartItem;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qShoppingCart)
+ .leftJoin(qShoppingCart.lineItems, qShoppingCartItem).fetch()
+ .leftJoin(qShoppingCartItem.attributes).fetch()
+ .leftJoin(qShoppingCart.merchantStore).fetch()
+ .where(qShoppingCart.shoppingCartCode.eq(code)
+ .and(qShoppingCart.merchantStore.id.eq(store.getId())));
+
+ List<ShoppingCart> results = query.list(qShoppingCart);
+ if (results.isEmpty()) return null;
+
+ else if (results.size() >= 1) return results.get(0);
+ return null;
+
+ }
+
+ @Override
+ public ShoppingCart getByCustomer(final Customer customer) {
+
+ QShoppingCart qShoppingCart = QShoppingCart.shoppingCart;
+ QShoppingCartItem qShoppingCartItem = QShoppingCartItem.shoppingCartItem;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qShoppingCart)
+ .leftJoin(qShoppingCart.lineItems, qShoppingCartItem).fetch()
+ .leftJoin(qShoppingCartItem.attributes).fetch()
+ .leftJoin(qShoppingCart.merchantStore).fetch()
+ .where(qShoppingCart.customerId.eq(customer.getId()));
+
+ List<ShoppingCart> results = query.list(qShoppingCart);
+ if (results.isEmpty()) return null;
+
+ else if (results.size() >= 1) return results.get(0);
+ return null;
+
+ }
+
+ @Override
+ public void removeShoppingCart( final ShoppingCart cart )
+ {
+ ShoppingCart shoppingCart=getEntityManager().merge( cart );
+ getEntityManager().remove( shoppingCart );
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/dao/ShoppingCartItemDao.java b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/dao/ShoppingCartItemDao.java
new file mode 100644
index 0000000..3c88594
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/dao/ShoppingCartItemDao.java
@@ -0,0 +1,10 @@
+package com.salesmanager.core.business.shoppingcart.dao;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartItem;
+
+public interface ShoppingCartItemDao extends SalesManagerEntityDao<Long, ShoppingCartItem> {
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/dao/ShoppingCartItemDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/dao/ShoppingCartItemDaoImpl.java
new file mode 100644
index 0000000..9212f88
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/dao/ShoppingCartItemDaoImpl.java
@@ -0,0 +1,14 @@
+package com.salesmanager.core.business.shoppingcart.dao;
+
+import org.springframework.stereotype.Repository;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartItem;
+
+@Repository("shoppingCartItemDao")
+public class ShoppingCartItemDaoImpl extends SalesManagerEntityDaoImpl<Long, ShoppingCartItem>
+ implements ShoppingCartItemDao {
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/model/ShoppingCart.java b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/model/ShoppingCart.java
new file mode 100644
index 0000000..7635a7c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/model/ShoppingCart.java
@@ -0,0 +1,150 @@
+/**
+ *
+ */
+package com.salesmanager.core.business.shoppingcart.model;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Transient;
+
+import org.hibernate.annotations.Index;
+
+import com.salesmanager.core.business.common.model.audit.AuditListener;
+import com.salesmanager.core.business.common.model.audit.AuditSection;
+import com.salesmanager.core.business.common.model.audit.Auditable;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.constants.SchemaConstant;
+
+/**
+ * <p>Shopping cart is responsible for storing and carrying
+ * shopping cart information.Shopping Cart consists of {@link ShoppingCartItem}
+ * which represents individual lines items associated with the shopping cart</p>
+ * @author Umesh Awasthi
+ * version 2.0
+ *
+ */
+@Entity
+@EntityListeners(value = AuditListener.class)
+@Table(name = "SHOPPING_CART", schema=SchemaConstant.SALESMANAGER_SCHEMA)
+public class ShoppingCart extends SalesManagerEntity<Long, ShoppingCart> implements Auditable{
+
+
+ private static final long serialVersionUID = 1L;
+
+ @Embedded
+ private AuditSection auditSection = new AuditSection();
+
+ @Id
+ @Column(name = "SHP_CART_ID", unique=true, nullable=false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "SHP_CRT_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ /**
+ * Will be used to fetch shopping cart model from the controller
+ * this is a unique code that should be attributed from the client (UI)
+ *
+ */
+ @Index(name="SHP_CART_CODE_IDX")
+ @Column(name = "SHP_CART_CODE", unique=true, nullable=false)
+ private String shoppingCartCode;
+
+ @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval=true, mappedBy = "shoppingCart")
+ private Set<ShoppingCartItem> lineItems = new HashSet<ShoppingCartItem>();
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="MERCHANT_ID", nullable=false)
+ private MerchantStore merchantStore;
+
+ @Index(name="SHP_CART_CUSTOMER_IDX")
+ @Column(name = "CUSTOMER_ID", nullable = true)
+ private Long customerId;
+
+ @Transient
+ private boolean obsolete = false;//when all items are obsolete
+
+ @Override
+ public AuditSection getAuditSection() {
+ return auditSection;
+ }
+
+ @Override
+ public void setAuditSection(AuditSection audit) {
+ this.auditSection = audit;
+
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+
+ }
+
+
+ public boolean isObsolete() {
+ return obsolete;
+ }
+
+ public void setObsolete(boolean obsolete) {
+ this.obsolete = obsolete;
+ }
+
+ public Set<ShoppingCartItem> getLineItems() {
+ return lineItems;
+ }
+
+ public void setLineItems(Set<ShoppingCartItem> lineItems) {
+ this.lineItems = lineItems;
+ }
+
+ public String getShoppingCartCode()
+ {
+ return shoppingCartCode;
+ }
+
+ public void setShoppingCartCode( String shoppingCartCode )
+ {
+ this.shoppingCartCode = shoppingCartCode;
+ }
+
+
+ public void setCustomerId(Long customerId) {
+ this.customerId = customerId;
+ }
+
+ public Long getCustomerId() {
+ return customerId;
+ }
+
+ public void setMerchantStore(MerchantStore merchantStore) {
+ this.merchantStore = merchantStore;
+ }
+
+ public MerchantStore getMerchantStore() {
+ return merchantStore;
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/model/ShoppingCartAttributeItem.java b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/model/ShoppingCartAttributeItem.java
new file mode 100644
index 0000000..717fbb4
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/model/ShoppingCartAttributeItem.java
@@ -0,0 +1,115 @@
+package com.salesmanager.core.business.shoppingcart.model;
+
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Transient;
+
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute;
+import com.salesmanager.core.business.common.model.audit.AuditListener;
+import com.salesmanager.core.business.common.model.audit.AuditSection;
+import com.salesmanager.core.business.common.model.audit.Auditable;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.constants.SchemaConstant;
+
+
+@Entity
+@EntityListeners(value = AuditListener.class)
+@Table(name = "SHOPPING_CART_ATTR_ITEM", schema=SchemaConstant.SALESMANAGER_SCHEMA)
+public class ShoppingCartAttributeItem extends SalesManagerEntity<Long, ShoppingCartAttributeItem> implements Auditable {
+
+
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @Column(name = "SHP_CART_ATTR_ITEM_ID", unique=true, nullable=false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "SHP_CRT_ATTR_ITM_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @Embedded
+ private AuditSection auditSection = new AuditSection();
+
+
+
+ @Column(name="PRODUCT_ATTR_ID", nullable=false)
+ private Long productAttributeId;
+
+ @Transient
+ private ProductAttribute productAttribute;
+
+
+
+ @ManyToOne(targetEntity = ShoppingCartItem.class)
+ @JoinColumn(name = "SHP_CART_ITEM_ID", nullable = false)
+ private ShoppingCartItem shoppingCartItem;
+
+ public ShoppingCartAttributeItem(ShoppingCartItem shoppingCartItem, ProductAttribute productAttribute) {
+ this.shoppingCartItem = shoppingCartItem;
+ this.productAttribute = productAttribute;
+ this.productAttributeId = productAttribute.getId();
+ }
+
+ public ShoppingCartAttributeItem() {
+
+ }
+
+
+
+ public ShoppingCartItem getShoppingCartItem() {
+ return shoppingCartItem;
+ }
+
+ public void setShoppingCartItem(ShoppingCartItem shoppingCartItem) {
+ this.shoppingCartItem = shoppingCartItem;
+ }
+
+ @Override
+ public AuditSection getAuditSection() {
+ return auditSection;
+ }
+
+ @Override
+ public void setAuditSection(AuditSection audit) {
+ this.auditSection = audit;
+
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+
+ }
+
+
+ public void setProductAttributeId(Long productAttributeId) {
+ this.productAttributeId = productAttributeId;
+ }
+
+ public Long getProductAttributeId() {
+ return productAttributeId;
+ }
+
+ public void setProductAttribute(ProductAttribute productAttribute) {
+ this.productAttribute = productAttribute;
+ }
+
+ public ProductAttribute getProductAttribute() {
+ return productAttribute;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/model/ShoppingCartItem.java b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/model/ShoppingCartItem.java
new file mode 100644
index 0000000..9283bee
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/model/ShoppingCartItem.java
@@ -0,0 +1,229 @@
+package com.salesmanager.core.business.shoppingcart.model;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Transient;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.price.FinalPrice;
+import com.salesmanager.core.business.common.model.audit.AuditListener;
+import com.salesmanager.core.business.common.model.audit.AuditSection;
+import com.salesmanager.core.business.common.model.audit.Auditable;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.constants.SchemaConstant;
+
+
+@Entity
+@EntityListeners(value = AuditListener.class)
+@Table(name = "SHOPPING_CART_ITEM", schema=SchemaConstant.SALESMANAGER_SCHEMA)
+public class ShoppingCartItem extends SalesManagerEntity<Long, ShoppingCartItem> implements Auditable, Serializable {
+
+
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @Column(name = "SHP_CART_ITEM_ID", unique=true, nullable=false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "SHP_CRT_ITM_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @ManyToOne(targetEntity = ShoppingCart.class)
+ @JoinColumn(name = "SHP_CART_ID", nullable = false)
+ private ShoppingCart shoppingCart;
+
+ @Column(name="QUANTITY")
+ private Integer quantity = new Integer(1);
+
+
+ @Embedded
+ private AuditSection auditSection = new AuditSection();
+
+ @Column(name="PRODUCT_ID", nullable=false)
+ private Long productId;
+
+ @Transient
+ private boolean productVirtual;
+
+ @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval=true, mappedBy = "shoppingCartItem")
+ private Set<ShoppingCartAttributeItem> attributes = new HashSet<ShoppingCartAttributeItem>();
+
+ @Transient
+ private BigDecimal itemPrice;//item final price including all rebates
+
+ @Transient
+ private BigDecimal subTotal;//item final price * quantity
+
+ @Transient
+ private FinalPrice finalPrice;//contains price details (raw prices)
+
+
+ @Transient
+ private Product product;
+
+ @Transient
+ private boolean obsolete = false;
+
+
+
+
+ public ShoppingCartItem(ShoppingCart shoppingCart, Product product) {
+ this.product = product;
+ this.productId = product.getId();
+ this.quantity = 1;
+ this.shoppingCart = shoppingCart;
+
+ }
+
+ public ShoppingCartItem(Product product) {
+ this.product = product;
+ this.productId = product.getId();
+ this.quantity = 1;
+
+ }
+
+ public ShoppingCartItem() {
+
+ }
+
+ @Override
+ public AuditSection getAuditSection() {
+ return auditSection;
+ }
+
+ @Override
+ public void setAuditSection(AuditSection audit) {
+ this.auditSection = audit;
+
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+
+ }
+
+
+
+ public void setAttributes(Set<ShoppingCartAttributeItem> attributes) {
+ this.attributes.clear();
+ this.attributes.addAll( attributes );
+ //this.attributes = attributes;
+ }
+
+ public Set<ShoppingCartAttributeItem> getAttributes() {
+ return attributes;
+ }
+
+ public void setItemPrice(BigDecimal itemPrice) {
+ this.itemPrice = itemPrice;
+ }
+
+ public BigDecimal getItemPrice() {
+ return itemPrice;
+ }
+
+ public void setQuantity(Integer quantity) {
+ this.quantity = quantity;
+ }
+
+ public Integer getQuantity() {
+ return quantity;
+ }
+
+
+
+ public ShoppingCart getShoppingCart() {
+ return shoppingCart;
+ }
+
+ public void setShoppingCart(ShoppingCart shoppingCart) {
+ this.shoppingCart = shoppingCart;
+ }
+
+ public void setProductId(Long productId) {
+ this.productId = productId;
+ }
+
+ public Long getProductId() {
+ return productId;
+ }
+
+ public void setProduct(Product product) {
+ this.product = product;
+ }
+
+ public Product getProduct() {
+ return product;
+ }
+
+ public void addAttributes(ShoppingCartAttributeItem shoppingCartAttributeItem)
+ {
+ this.attributes.add(shoppingCartAttributeItem);
+ }
+
+ public void removeAttributes(ShoppingCartAttributeItem shoppingCartAttributeItem)
+ {
+ this.attributes.remove(shoppingCartAttributeItem);
+ }
+
+ public void removeAllAttributes(){
+ this.attributes.removeAll(Collections.EMPTY_SET);
+ }
+
+ public void setSubTotal(BigDecimal subTotal) {
+ this.subTotal = subTotal;
+ }
+
+ public BigDecimal getSubTotal() {
+ return subTotal;
+ }
+
+ public void setFinalPrice(FinalPrice finalPrice) {
+ this.finalPrice = finalPrice;
+ }
+
+ public FinalPrice getFinalPrice() {
+ return finalPrice;
+ }
+
+ public boolean isObsolete() {
+ return obsolete;
+ }
+
+ public void setObsolete(boolean obsolete) {
+ this.obsolete = obsolete;
+ }
+
+
+ public boolean isProductVirtual() {
+ return productVirtual;
+ }
+
+ public void setProductVirtual(boolean productVirtual) {
+ this.productVirtual = productVirtual;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/service/ShoppingCartCalculationService.java b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/service/ShoppingCartCalculationService.java
new file mode 100644
index 0000000..f5543d9
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/service/ShoppingCartCalculationService.java
@@ -0,0 +1,43 @@
+/**
+ *
+ */
+package com.salesmanager.core.business.shoppingcart.service;
+
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.OrderTotalSummary;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCart;
+
+/**
+ * Interface declaring various methods used to calculate {@link ShoppingCart}
+ * object details.
+ * @author Umesh Awasthi
+ * @since 1.2
+ *
+ */
+public interface ShoppingCartCalculationService
+{
+ /**
+ * Method which will be used to calculate price for each line items as
+ * well Total and Sub-total for {@link ShoppingCart}.
+ * @param cartModel ShoopingCart mode representing underlying DB object
+ * @param customer
+ * @param store
+ * @param language
+ * @throws ServiceException
+ */
+ public OrderTotalSummary calculate(final ShoppingCart cartModel,final Customer customer, final MerchantStore store, final Language language) throws ServiceException;
+
+
+ /**
+ * Method which will be used to calculate price for each line items as
+ * well Total and Sub-total for {@link ShoppingCart}.
+ * @param cartModel ShoopingCart mode representing underlying DB object
+ * @param store
+ * @param language
+ * @throws ServiceException
+ */
+ public OrderTotalSummary calculate(final ShoppingCart cartModel, final MerchantStore store, final Language language) throws ServiceException;
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/service/ShoppingCartCalculationServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/service/ShoppingCartCalculationServiceImpl.java
new file mode 100644
index 0000000..d6d9375
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/service/ShoppingCartCalculationServiceImpl.java
@@ -0,0 +1,123 @@
+/**
+ *
+ */
+package com.salesmanager.core.business.shoppingcart.service;
+
+import org.apache.commons.lang.Validate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.OrderTotalSummary;
+import com.salesmanager.core.business.order.service.OrderService;
+import com.salesmanager.core.business.order.service.OrderServiceImpl;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCart;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartItem;
+/**
+ * <p>Implementation class responsible for calculating state of shopping cart.
+ * This class will take care of calculating price of each line items of shopping cart
+ * as well any discount including sub-total and total amount.
+ * </p>
+ *
+ * @author Umesh Awasthi
+ * @version 1.2
+ */
+@Service("shoppingCartCalculationService")
+public class ShoppingCartCalculationServiceImpl implements ShoppingCartCalculationService
+{
+
+
+ protected final Logger LOG = LoggerFactory.getLogger(getClass());
+
+ @Autowired
+ private ShoppingCartService shoppingCartService;
+
+ @Autowired
+ private OrderService orderService;
+
+
+
+ /**
+ * <p>Method used to recalculate state of shopping cart every time any change has been made
+ * to underlying {@link ShoppingCart} object in DB.</p>
+ * Following operations will be performed by this method.
+ *
+ * <li>Calculate price for each {@link ShoppingCartItem} and update it. </li>
+ * <p>
+ * This method is backbone method for all price calculation related to shopping cart.</p>
+ *
+ * @see OrderServiceImpl
+ *
+ * @param cartModel
+ * @param customer
+ * @param store
+ * @param language
+ * @throws ServiceException
+ */
+ @Override
+ public OrderTotalSummary calculate( final ShoppingCart cartModel ,final Customer customer, final MerchantStore store, final Language language ) throws ServiceException
+ {
+
+ Validate.notNull(cartModel,"cart cannot be null");
+ Validate.notNull(cartModel.getLineItems(),"Cart should have line items.");
+ Validate.notNull(store,"MerchantStore cannot be null");
+ Validate.notNull(customer,"Customer cannot be null");
+ OrderTotalSummary orderTotalSummary=orderService.calculateShoppingCartTotal( cartModel, customer,store, language );
+ updateCartModel(cartModel);
+ return orderTotalSummary;
+
+
+ }
+
+
+ /**
+ * <p>Method used to recalculate state of shopping cart every time any change has been made
+ * to underlying {@link ShoppingCart} object in DB.</p>
+ * Following operations will be performed by this method.
+ *
+ * <li>Calculate price for each {@link ShoppingCartItem} and update it. </li>
+ * <p>
+ * This method is backbone method for all price calculation related to shopping cart.</p>
+ *
+ * @see OrderServiceImpl
+ *
+ * @param cartModel
+ * @param store
+ * @param language
+ * @throws ServiceException
+ */
+ @Override
+ public OrderTotalSummary calculate( final ShoppingCart cartModel , final MerchantStore store, final Language language ) throws ServiceException
+ {
+
+ Validate.notNull(cartModel,"cart cannot be null");
+ Validate.notNull(cartModel.getLineItems(),"Cart should have line items.");
+ Validate.notNull(store,"MerchantStore cannot be null");
+ OrderTotalSummary orderTotalSummary=orderService.calculateShoppingCartTotal( cartModel, store, language );
+ updateCartModel(cartModel);
+ return orderTotalSummary;
+
+
+ }
+
+
+
+ public ShoppingCartService getShoppingCartService()
+ {
+ return shoppingCartService;
+ }
+
+
+ private void updateCartModel(final ShoppingCart cartModel) throws ServiceException{
+ shoppingCartService.saveOrUpdate( cartModel );
+ }
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/service/ShoppingCartService.java b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/service/ShoppingCartService.java
new file mode 100644
index 0000000..6c3cab8
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/service/ShoppingCartService.java
@@ -0,0 +1,86 @@
+package com.salesmanager.core.business.shoppingcart.service;
+
+import java.util.List;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.shipping.model.ShippingProduct;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCart;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartItem;
+
+
+public interface ShoppingCartService extends SalesManagerEntityService<Long, ShoppingCart> {
+
+ ShoppingCart getShoppingCart(Customer customer) throws ServiceException;
+
+ void saveOrUpdate(ShoppingCart shoppingCart) throws ServiceException;
+
+ ShoppingCart getById(Long id, MerchantStore store) throws ServiceException;
+
+ ShoppingCart getByCode(String code, MerchantStore store)
+ throws ServiceException;
+
+ ShoppingCart getByCustomer(Customer customer) throws ServiceException;
+
+ /**
+ * Creates a list of ShippingProduct based on the ShoppingCart
+ * if items are virtual return list will be null
+ * @param cart
+ * @return
+ * @throws ServiceException
+ */
+ List<ShippingProduct> createShippingProduct(ShoppingCart cart)
+ throws ServiceException;
+
+
+
+ /**
+ * Looks if the items in the ShoppingCart are free of charges
+ * @param cart
+ * @return
+ * @throws ServiceException
+ */
+ boolean isFreeShoppingCart(ShoppingCart cart) throws ServiceException;
+
+ boolean isFreeShoppingCart(List<ShoppingCartItem> items) throws ServiceException;
+
+ /**
+ * Populates a ShoppingCartItem from a Product and attributes if any
+ * @param product
+ * @return
+ * @throws ServiceException
+ */
+ ShoppingCartItem populateShoppingCartItem(Product product)
+ throws ServiceException;
+
+ void deleteCart(ShoppingCart cart) throws ServiceException;
+
+
+ void removeShoppingCart(ShoppingCart cart) throws ServiceException;
+
+ /**
+ *
+ * @param userShoppingModel
+ * @param sessionCart
+ * @param store
+ * @return {@link ShoppingCart} merged Shopping Cart
+ * @throws Exception
+ */
+ public ShoppingCart mergeShoppingCarts(final ShoppingCart userShoppingCart,final ShoppingCart sessionCart,final MerchantStore store ) throws Exception;
+
+ /**
+ * Determines if the shopping cart requires shipping
+ * @param cart
+ * @return
+ * @throws ServiceException
+ */
+ boolean requiresShipping(ShoppingCart cart) throws ServiceException;
+
+
+
+
+
+}
\ No newline at end of file
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/service/ShoppingCartServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/service/ShoppingCartServiceImpl.java
new file mode 100644
index 0000000..bfdf486
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/shoppingcart/service/ShoppingCartServiceImpl.java
@@ -0,0 +1,542 @@
+package com.salesmanager.core.business.shoppingcart.service;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.Validate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute;
+import com.salesmanager.core.business.catalog.product.model.price.FinalPrice;
+import com.salesmanager.core.business.catalog.product.service.PricingService;
+import com.salesmanager.core.business.catalog.product.service.ProductService;
+import com.salesmanager.core.business.catalog.product.service.attribute.ProductAttributeService;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.shipping.model.ShippingProduct;
+import com.salesmanager.core.business.shoppingcart.dao.ShoppingCartDao;
+import com.salesmanager.core.business.shoppingcart.dao.ShoppingCartItemDao;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCart;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartAttributeItem;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartItem;
+
+@Service("shoppingCartService")
+public class ShoppingCartServiceImpl extends SalesManagerEntityServiceImpl<Long, ShoppingCart> implements ShoppingCartService {
+
+
+ private final ShoppingCartDao shoppingCartDao;
+
+ @Autowired
+ private ProductService productService;
+
+ @Autowired
+ private ShoppingCartItemDao shoppingCartItemDao;
+
+ @Autowired
+ private PricingService pricingService;
+
+ @Autowired
+ private ProductAttributeService productAttributeService;
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ShoppingCartServiceImpl.class);
+
+ @Autowired
+ public ShoppingCartServiceImpl(
+ final ShoppingCartDao shoppingCartDao) {
+ super(shoppingCartDao);
+ this.shoppingCartDao = shoppingCartDao;
+
+ }
+
+
+ /**
+ * Retrieve a {@link ShoppingCart} cart for a given customer
+ */
+ @Override
+ @Transactional
+ public ShoppingCart getShoppingCart(final Customer customer) throws ServiceException {
+
+ try {
+
+ ShoppingCart shoppingCart = shoppingCartDao.getByCustomer(customer);
+ populateShoppingCart(shoppingCart);
+ if(shoppingCart!=null && shoppingCart.isObsolete()) {
+ delete(shoppingCart);
+ return null;
+ } else {
+ return shoppingCart;
+ }
+
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+ }
+
+ /**
+ * Save or update a {@link ShoppingCart} for a given customer
+ */
+ @Override
+ public void saveOrUpdate(final ShoppingCart shoppingCart) throws ServiceException {
+ if(shoppingCart.getId()==null || shoppingCart.getId().longValue()==0) {
+ super.create(shoppingCart);
+ } else {
+ super.update(shoppingCart);
+ }
+ }
+
+ /**
+ * Get a {@link ShoppingCart} for a given id and MerchantStore. Will update the shopping cart
+ * prices and items based on the actual inventory. This method will remove the shopping cart if
+ * no items are attached.
+ */
+ @Override
+ @Transactional
+ public ShoppingCart getById(final Long id, final MerchantStore store) throws ServiceException {
+
+ try {
+ ShoppingCart shoppingCart = shoppingCartDao.getById(id, store);
+ if(shoppingCart==null) {
+ return null;
+ }
+ populateShoppingCart(shoppingCart);
+
+ if(shoppingCart.isObsolete()) {
+ delete(shoppingCart);
+ return null;
+ } else {
+ return shoppingCart;
+ }
+
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+
+ }
+
+ /**
+ * Get a {@link ShoppingCart} for a given id. Will update the shopping cart
+ * prices and items based on the actual inventory. This method will remove the shopping cart if
+ * no items are attached.
+ */
+ @Override
+ public ShoppingCart getById(final Long id) {
+
+
+ try {
+ ShoppingCart shoppingCart = shoppingCartDao.getById(id);
+ if(shoppingCart==null) {
+ return null;
+ }
+ populateShoppingCart(shoppingCart);
+
+
+ if(shoppingCart.isObsolete()) {
+ delete(shoppingCart);
+ return null;
+ } else {
+ return shoppingCart;
+ }
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ return null;
+
+ }
+
+ /**
+ * Get a {@link ShoppingCart} for a given code. Will update the shopping cart
+ * prices and items based on the actual inventory. This method will remove the shopping cart if
+ * no items are attached.
+ */
+ @Override
+ @Transactional
+ public ShoppingCart getByCode(final String code, final MerchantStore store) throws ServiceException {
+
+ try {
+ ShoppingCart shoppingCart = shoppingCartDao.getByCode(code, store);
+ if(shoppingCart==null) {
+ return null;
+ }
+ populateShoppingCart(shoppingCart);
+
+
+ if(shoppingCart.isObsolete()) {
+ delete(shoppingCart);
+ return null;
+ } else {
+ return shoppingCart;
+ }
+
+ }catch(javax.persistence.NoResultException nre) {
+ return null;
+ } catch (RuntimeException e) {
+ throw new ServiceException(e);
+ } catch (Exception ee) {
+ throw new ServiceException(ee);
+ } catch (Throwable t) {
+ throw new ServiceException(t);
+ }
+
+
+ }
+
+ @Override
+ public void deleteCart(final ShoppingCart shoppingCart) throws ServiceException {
+ ShoppingCart cart = this.getById(shoppingCart.getId());
+ if(cart!=null) {
+ super.delete(cart);
+ }
+ }
+
+
+ @Override
+ public ShoppingCart getByCustomer(final Customer customer) throws ServiceException {
+
+ try {
+ ShoppingCart shoppingCart = shoppingCartDao.getByCustomer(customer);
+ if(shoppingCart==null) {
+ return null;
+ }
+ return populateShoppingCart(shoppingCart);
+
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+ }
+
+ @Transactional(noRollbackFor={org.springframework.dao.EmptyResultDataAccessException.class})
+ private ShoppingCart populateShoppingCart(final ShoppingCart shoppingCart) throws Exception {
+
+ try {
+
+ boolean cartIsObsolete = true;
+ if(shoppingCart!=null) {
+
+ Set<ShoppingCartItem> items = shoppingCart.getLineItems();
+ if(items==null || items.size()==0) {
+ shoppingCart.setObsolete(true);
+ return shoppingCart;
+
+ }
+
+ //Set<ShoppingCartItem> shoppingCartItems = new HashSet<ShoppingCartItem>();
+ for(ShoppingCartItem item : items) {
+ LOGGER.debug("Populate item " + item.getId());
+ populateItem(item);
+ LOGGER.debug("Obsolete item ? " + item.isObsolete());
+ if(item.isObsolete()) {
+ } else {
+ cartIsObsolete = false;
+ }
+ }
+
+ //shoppingCart.setLineItems(shoppingCartItems);
+ boolean refreshCart = false;
+ Set<ShoppingCartItem> refreshedItems = new HashSet<ShoppingCartItem>();
+ for(ShoppingCartItem item : items) {
+ if(!item.isObsolete()) {
+ refreshedItems.add(item);
+ } else {
+ refreshCart = true;
+ }
+ }
+
+ if(refreshCart) {
+ shoppingCart.setLineItems(refreshedItems);
+ update(shoppingCart);
+ }
+
+ if(cartIsObsolete) {
+ shoppingCart.setObsolete(true);
+ }
+ return shoppingCart;
+ }
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+ return shoppingCart;
+
+ }
+
+ @Override
+ public ShoppingCartItem populateShoppingCartItem(final Product product) throws ServiceException {
+ Validate.notNull(product, "Product should not be null");
+ Validate.notNull(product.getMerchantStore(), "Product.merchantStore should not be null");
+
+
+ ShoppingCartItem item = new ShoppingCartItem(product);
+
+ //Set<ProductAttribute> productAttributes = product.getAttributes();
+ //Set<ShoppingCartAttributeItem> attributesList = new HashSet<ShoppingCartAttributeItem>();
+ //if(!CollectionUtils.isEmpty(productAttributes)) {
+
+ // for(ProductAttribute productAttribute : productAttributes) {
+ // ShoppingCartAttributeItem attributeItem = new ShoppingCartAttributeItem();
+ // attributeItem.setShoppingCartItem(item);
+ // attributeItem.setProductAttribute(productAttribute);
+ // attributeItem.setProductAttributeId(productAttribute.getId());
+ // attributesList.add(attributeItem);
+
+ // }
+
+ // item.setAttributes(attributesList);
+ //}
+
+ item.setProductVirtual(product.isProductVirtual());
+
+ //set item price
+ FinalPrice price = pricingService.calculateProductPrice(product);
+ item.setItemPrice(price.getFinalPrice());
+ return item;
+
+
+ }
+
+
+ private void populateItem(final ShoppingCartItem item) throws Exception {
+
+ Product product = null;
+
+ Long productId = item.getProductId();
+ product = productService.getById(productId);
+
+ if(product==null) {
+ item.setObsolete(true);
+ return;
+ }
+
+
+ item.setProduct(product);
+
+ if(product.isProductVirtual()) {
+ item.setProductVirtual(true);
+ }
+
+ Set<ShoppingCartAttributeItem> attributes = item.getAttributes();
+ Set<ProductAttribute> productAttributes = product.getAttributes();
+ List<ProductAttribute> attributesList = new ArrayList<ProductAttribute>();
+ if(productAttributes!=null && productAttributes.size()>0 && attributes!=null && attributes.size()>0) {
+ for(ShoppingCartAttributeItem attribute : attributes) {
+ long attributeId = attribute.getProductAttributeId().longValue();
+ for(ProductAttribute productAttribute : productAttributes) {
+
+ if(productAttribute.getId().longValue()==attributeId) {
+ attribute.setProductAttribute(productAttribute);
+ attributesList.add(productAttribute);
+ break;
+ }
+
+ }
+
+ }
+ }
+
+ //set item price
+ FinalPrice price = pricingService.calculateProductPrice(product, attributesList);
+ item.setItemPrice(price.getFinalPrice());
+ item.setFinalPrice(price);
+
+
+
+ BigDecimal subTotal = item.getItemPrice().multiply(new BigDecimal(item.getQuantity().intValue()));
+ item.setSubTotal(subTotal);
+
+
+ }
+
+ @Override
+ public List<ShippingProduct> createShippingProduct(final ShoppingCart cart) throws ServiceException {
+ /**
+ * Determines if products are virtual
+ */
+ Set<ShoppingCartItem> items = cart.getLineItems();
+ List<ShippingProduct> shippingProducts = null;
+ for(ShoppingCartItem item : items) {
+ Product product = item.getProduct();
+ if(!product.isProductVirtual() && product.isProductShipeable()) {
+ if(shippingProducts==null) {
+ shippingProducts = new ArrayList<ShippingProduct>();
+ }
+ ShippingProduct shippingProduct = new ShippingProduct(product);
+ shippingProduct.setQuantity(item.getQuantity());
+ shippingProducts.add(shippingProduct);
+ }
+ }
+
+ return shippingProducts;
+
+ }
+
+
+ @Override
+ public boolean isFreeShoppingCart(final ShoppingCart cart) throws ServiceException {
+ /**
+ * Determines if products are free
+ */
+ Set<ShoppingCartItem> items = cart.getLineItems();
+ for(ShoppingCartItem item : items) {
+ Product product = item.getProduct();
+ FinalPrice finalPrice = pricingService.calculateProductPrice(product);
+ if(finalPrice.getFinalPrice().longValue()>0) {
+ return false;
+ }
+ }
+
+ return true;
+
+ }
+
+ @Override
+ public boolean requiresShipping(final ShoppingCart cart) throws ServiceException {
+
+ Validate.notNull(cart,"Shopping cart cannot be null");
+ Validate.notNull(cart.getLineItems(),"ShoppingCart items cannot be null");
+ boolean requiresShipping = false;
+ for(ShoppingCartItem item : cart.getLineItems()) {
+ Product product = item.getProduct();
+ if(product.isProductShipeable()) {
+ requiresShipping = true;
+ break;
+ }
+ }
+
+ return requiresShipping;
+
+ }
+
+ @Override
+ public void removeShoppingCart( final ShoppingCart cart )
+ throws ServiceException
+ {
+ shoppingCartDao.removeShoppingCart( cart );
+ }
+
+
+ @Override
+ public ShoppingCart mergeShoppingCarts( final ShoppingCart userShoppingModel, final ShoppingCart sessionCart,final MerchantStore store ) throws Exception
+ {
+ if(sessionCart.getCustomerId() !=null && sessionCart.getCustomerId() ==userShoppingModel.getCustomerId() ){
+ LOGGER.info( "Session Shopping cart belongs to same logged in user" );
+ if(CollectionUtils.isNotEmpty( userShoppingModel.getLineItems() ) && CollectionUtils.isNotEmpty( sessionCart.getLineItems() )){
+ return userShoppingModel;
+ }
+ }
+
+ LOGGER.info( "Starting merging shopping carts" );
+ if(CollectionUtils.isNotEmpty( sessionCart.getLineItems() )){
+ Set<ShoppingCartItem> shoppingCartItemsSet=getShoppingCartItems(sessionCart,store,userShoppingModel);
+ boolean duplicateFound = false;
+ if(CollectionUtils.isNotEmpty(shoppingCartItemsSet)) {
+ for(ShoppingCartItem sessionShoppingCartItem : shoppingCartItemsSet){
+ if(CollectionUtils.isNotEmpty(userShoppingModel.getLineItems())){
+ for(ShoppingCartItem cartItem : userShoppingModel.getLineItems()){
+ if(cartItem.getProduct().getId().longValue()==sessionShoppingCartItem.getProduct().getId().longValue()) {
+ if(CollectionUtils.isNotEmpty(cartItem.getAttributes())) {
+ if(!duplicateFound) {
+ LOGGER.info( "Dupliate item found..updating exisitng product quantity" );
+ cartItem.setQuantity(cartItem.getQuantity() + sessionShoppingCartItem.getQuantity());
+ duplicateFound = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if(!duplicateFound) {
+ LOGGER.info( "New item found..adding item to Shopping cart" );
+ userShoppingModel.getLineItems().add( sessionShoppingCartItem );
+ }
+ }
+
+ }
+
+ }
+ LOGGER.info( "Shopping Cart merged successfully.....");
+ saveOrUpdate( userShoppingModel );
+ removeShoppingCart( sessionCart );
+
+ return userShoppingModel;
+ }
+
+
+
+ private Set<ShoppingCartItem> getShoppingCartItems( final ShoppingCart sessionCart,final MerchantStore store,final ShoppingCart cartModel )
+ throws Exception
+ {
+
+ Set<ShoppingCartItem> shoppingCartItemsSet=null;
+ if(CollectionUtils.isNotEmpty( sessionCart.getLineItems() )){
+ shoppingCartItemsSet=new HashSet<ShoppingCartItem>();
+ for(ShoppingCartItem shoppingCartItem : sessionCart.getLineItems()){
+ Product product = productService.getById( shoppingCartItem.getProductId() );
+ if ( product == null )
+ {
+ throw new Exception( "Item with id " + shoppingCartItem.getProductId() + " does not exist" );
+ }
+
+ if ( product.getMerchantStore().getId().intValue() != store.getId().intValue() )
+ {
+ throw new Exception( "Item with id " + shoppingCartItem.getProductId() + " does not belong to merchant "
+ + store.getId() );
+ }
+
+ ShoppingCartItem item= populateShoppingCartItem( product );
+ item.setQuantity( shoppingCartItem.getQuantity() );
+ item.setShoppingCart( cartModel );
+
+ List<ShoppingCartAttributeItem> cartAttributes = new ArrayList<ShoppingCartAttributeItem>( shoppingCartItem.getAttributes() );
+ if(CollectionUtils.isNotEmpty( cartAttributes )){
+ for(ShoppingCartAttributeItem shoppingCartAttributeItem :cartAttributes ){
+ ProductAttribute productAttribute =productAttributeService.getById( shoppingCartAttributeItem.getId() );
+ if ( productAttribute != null
+ && productAttribute.getProduct().getId().longValue() == product.getId().longValue() ){
+
+ ShoppingCartAttributeItem attributeItem=new ShoppingCartAttributeItem(item,productAttribute);
+ if ( shoppingCartAttributeItem.getId() > 0 )
+ {
+ attributeItem.setId( shoppingCartAttributeItem.getId() );
+ }
+ item.addAttributes( attributeItem );
+
+ }
+ }
+ }
+
+ shoppingCartItemsSet.add( item );
+ }
+
+ }
+ return shoppingCartItemsSet;
+ }
+
+
+ @Override
+ public boolean isFreeShoppingCart(List<ShoppingCartItem> items)
+ throws ServiceException {
+ ShoppingCart cart = new ShoppingCart();
+ Set<ShoppingCartItem> cartItems = new HashSet<ShoppingCartItem>(items);
+ cart.setLineItems(cartItems);
+ return this.isFreeShoppingCart(cart);
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/dao/MerchantConfigurationDao.java b/sm-core/src/main/java/com/salesmanager/core/business/system/dao/MerchantConfigurationDao.java
new file mode 100755
index 0000000..008f5f0
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/dao/MerchantConfigurationDao.java
@@ -0,0 +1,21 @@
+package com.salesmanager.core.business.system.dao;
+
+import java.util.List;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.system.model.MerchantConfiguration;
+import com.salesmanager.core.business.system.model.MerchantConfigurationType;
+
+public interface MerchantConfigurationDao extends SalesManagerEntityDao<Long, MerchantConfiguration> {
+
+
+
+ MerchantConfiguration getMerchantConfiguration(String key, MerchantStore store);
+
+ List<MerchantConfiguration> getMerchantConfigurations(MerchantStore store);
+
+ List<MerchantConfiguration> listByType(MerchantConfigurationType type,
+ MerchantStore store);
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/dao/MerchantConfigurationDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/system/dao/MerchantConfigurationDaoImpl.java
new file mode 100755
index 0000000..55aa335
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/dao/MerchantConfigurationDaoImpl.java
@@ -0,0 +1,69 @@
+package com.salesmanager.core.business.system.dao;
+
+import java.util.List;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.system.model.MerchantConfiguration;
+import com.salesmanager.core.business.system.model.MerchantConfigurationType;
+import com.salesmanager.core.business.system.model.QMerchantConfiguration;
+
+@Repository("merchantConfigurationDao")
+public class MerchantConfigurationDaoImpl extends SalesManagerEntityDaoImpl<Long, MerchantConfiguration>
+ implements MerchantConfigurationDao {
+
+
+ @Override
+ public MerchantConfiguration getMerchantConfiguration(String key, MerchantStore store) {
+
+
+
+ QMerchantConfiguration qMerchantConfiguration = QMerchantConfiguration.merchantConfiguration;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+ query.from(qMerchantConfiguration)
+ .innerJoin(qMerchantConfiguration.merchantStore).fetch()
+ .where(qMerchantConfiguration.merchantStore.id.eq(store.getId())
+ .and(qMerchantConfiguration.key.eq(key)));
+
+ return query.uniqueResult(qMerchantConfiguration);
+
+ }
+
+ @Override
+ public List<MerchantConfiguration> getMerchantConfigurations(MerchantStore store) {
+
+ QMerchantConfiguration qMerchantConfiguration = QMerchantConfiguration.merchantConfiguration;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+ query.from(qMerchantConfiguration)
+ .innerJoin(qMerchantConfiguration.merchantStore).fetch()
+ .where(qMerchantConfiguration.merchantStore.id.eq(store.getId()));
+
+ return query.list(qMerchantConfiguration);
+
+ }
+
+ @Override
+ public List<MerchantConfiguration> listByType(MerchantConfigurationType type, MerchantStore store) {
+
+
+ QMerchantConfiguration qMerchantConfiguration = QMerchantConfiguration.merchantConfiguration;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+ query.from(qMerchantConfiguration)
+ .innerJoin(qMerchantConfiguration.merchantStore).fetch()
+ .where(qMerchantConfiguration.merchantStore.id.eq(store.getId())
+ .and(qMerchantConfiguration.merchantConfigurationType.eq(type)));
+
+ return query.list(qMerchantConfiguration);
+
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/dao/MerchantLogDao.java b/sm-core/src/main/java/com/salesmanager/core/business/system/dao/MerchantLogDao.java
new file mode 100644
index 0000000..cff3990
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/dao/MerchantLogDao.java
@@ -0,0 +1,14 @@
+package com.salesmanager.core.business.system.dao;
+
+import java.util.List;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.system.model.MerchantLog;
+
+public interface MerchantLogDao extends SalesManagerEntityDao<Long, MerchantLog> {
+
+
+ List<MerchantLog> listByMerchant(MerchantStore store);
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/dao/MerchantLogDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/system/dao/MerchantLogDaoImpl.java
new file mode 100644
index 0000000..3f0ff64
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/dao/MerchantLogDaoImpl.java
@@ -0,0 +1,34 @@
+package com.salesmanager.core.business.system.dao;
+
+import java.util.List;
+
+import org.springframework.stereotype.Repository;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.system.model.MerchantLog;
+
+@Repository("merchantLogDao")
+public class MerchantLogDaoImpl extends SalesManagerEntityDaoImpl<Long, MerchantLog>
+ implements MerchantLogDao {
+
+
+
+
+ @Override
+ public List<MerchantLog> listByMerchant(MerchantStore store) {
+
+/* QMerchantLog qMerchantLog = QMerchantLog.
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+ query.from(qMerchantCnfiguration)
+ .innerJoin(qMerchantCnfiguration.merchantStore).fetch()
+ .where(qMerchantCnfiguration.merchantStore.id.eq(store.getId()));
+
+ return query.list(qMerchantCnfiguration);*/
+
+ return null;
+
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/dao/ModuleConfigurationDao.java b/sm-core/src/main/java/com/salesmanager/core/business/system/dao/ModuleConfigurationDao.java
new file mode 100755
index 0000000..a3c0100
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/dao/ModuleConfigurationDao.java
@@ -0,0 +1,14 @@
+package com.salesmanager.core.business.system.dao;
+
+import java.util.List;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+
+public interface ModuleConfigurationDao extends SalesManagerEntityDao<Long, IntegrationModule> {
+
+ List<IntegrationModule> getModulesConfiguration(String module);
+
+ IntegrationModule getByCode(String moduleCode);
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/dao/ModuleConfigurationDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/system/dao/ModuleConfigurationDaoImpl.java
new file mode 100755
index 0000000..db53779
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/dao/ModuleConfigurationDaoImpl.java
@@ -0,0 +1,52 @@
+package com.salesmanager.core.business.system.dao;
+
+import java.util.List;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+import com.salesmanager.core.business.system.model.QIntegrationModule;
+
+@Repository("integrationModuleDao")
+public class ModuleConfigurationDaoImpl extends SalesManagerEntityDaoImpl<Long, IntegrationModule>
+ implements ModuleConfigurationDao {
+
+
+ @Override
+ public List<IntegrationModule> getModulesConfiguration(String module) {
+
+
+
+ QIntegrationModule qIntegrationModule = QIntegrationModule.integrationModule;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+ query.from(qIntegrationModule)
+ .where(qIntegrationModule.module.eq(module));
+
+ return query.list(qIntegrationModule);
+
+
+ }
+
+ @Override
+ public IntegrationModule getByCode(String moduleCode) {
+
+
+
+ QIntegrationModule qIntegrationModule = QIntegrationModule.integrationModule;
+
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+ query.from(qIntegrationModule)
+ .where(qIntegrationModule.code.eq(moduleCode));
+
+ return query.uniqueResult(qIntegrationModule);
+
+
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/dao/SystemConfigurationDao.java b/sm-core/src/main/java/com/salesmanager/core/business/system/dao/SystemConfigurationDao.java
new file mode 100644
index 0000000..7199265
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/dao/SystemConfigurationDao.java
@@ -0,0 +1,8 @@
+package com.salesmanager.core.business.system.dao;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.system.model.SystemConfiguration;
+
+public interface SystemConfigurationDao extends SalesManagerEntityDao<Long, SystemConfiguration> {
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/dao/SystemConfigurationDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/system/dao/SystemConfigurationDaoImpl.java
new file mode 100644
index 0000000..c513587
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/dao/SystemConfigurationDaoImpl.java
@@ -0,0 +1,14 @@
+package com.salesmanager.core.business.system.dao;
+
+import org.springframework.stereotype.Repository;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.system.model.SystemConfiguration;
+
+@Repository("systemConfigurationDao")
+public class SystemConfigurationDaoImpl extends SalesManagerEntityDaoImpl<Long, SystemConfiguration>
+ implements SystemConfigurationDao {
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/dao/SystemNotificationDao.java b/sm-core/src/main/java/com/salesmanager/core/business/system/dao/SystemNotificationDao.java
new file mode 100755
index 0000000..febef93
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/dao/SystemNotificationDao.java
@@ -0,0 +1,8 @@
+package com.salesmanager.core.business.system.dao;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.system.model.SystemNotification;
+
+public interface SystemNotificationDao extends SalesManagerEntityDao<Long, SystemNotification> {
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/dao/SystemNotificationDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/system/dao/SystemNotificationDaoImpl.java
new file mode 100755
index 0000000..554604e
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/dao/SystemNotificationDaoImpl.java
@@ -0,0 +1,14 @@
+package com.salesmanager.core.business.system.dao;
+
+import org.springframework.stereotype.Repository;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.system.model.SystemNotification;
+
+@Repository("systemNotificationDao")
+public class SystemNotificationDaoImpl extends SalesManagerEntityDaoImpl<Long, SystemNotification>
+ implements SystemNotificationDao {
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/model/CustomIntegrationConfiguration.java b/sm-core/src/main/java/com/salesmanager/core/business/system/model/CustomIntegrationConfiguration.java
new file mode 100644
index 0000000..365fb8e
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/model/CustomIntegrationConfiguration.java
@@ -0,0 +1,14 @@
+package com.salesmanager.core.business.system.model;
+
+import org.json.simple.JSONAware;
+
+/**
+ * Used as a marker interface to commit additional
+ * integration module information to the database
+ * @author casams1
+ *
+ */
+public interface CustomIntegrationConfiguration extends JSONAware{
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/model/Environment.java b/sm-core/src/main/java/com/salesmanager/core/business/system/model/Environment.java
new file mode 100644
index 0000000..3eae1d8
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/model/Environment.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.system.model;
+
+public enum Environment {
+
+ TEST, PRODUCTION
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/model/IntegrationConfiguration.java b/sm-core/src/main/java/com/salesmanager/core/business/system/model/IntegrationConfiguration.java
new file mode 100755
index 0000000..25e57a6
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/model/IntegrationConfiguration.java
@@ -0,0 +1,169 @@
+package com.salesmanager.core.business.system.model;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.codehaus.jackson.annotate.JsonProperty;
+import org.json.simple.JSONAware;
+import org.json.simple.JSONObject;
+
+/**
+ * Object used to contain the integration information with an external gateway
+ * Uses simple JSON to encode the object in JSON by implementing JSONAware
+ * and uses jackson JSON decode to parse JSON String to an Object
+ * @author csamson
+ *
+ */
+public class IntegrationConfiguration implements JSONAware {
+
+
+ public final static String TEST_ENVIRONMENT = "TEST";
+ public final static String PRODUCTION_ENVIRONMENT = "PRODUCTION";
+
+ private String moduleCode;
+ private boolean active;
+ private boolean defaultSelected;
+ //private boolean customModule;
+ private Map<String,String> integrationKeys= new HashMap<String,String>();
+ private Map<String,List<String>> integrationOptions= new HashMap<String,List<String>>();
+ private String environment;
+
+
+ public String getModuleCode() {
+ return moduleCode;
+ }
+ @JsonProperty("moduleCode")
+ public void setModuleCode(String moduleCode) {
+ this.moduleCode = moduleCode;
+ }
+ public boolean isActive() {
+ return active;
+ }
+ @JsonProperty("active")
+ public void setActive(boolean active) {
+ this.active = active;
+ }
+ public Map<String, String> getIntegrationKeys() {
+ return integrationKeys;
+ }
+ @JsonProperty("integrationKeys")
+ public void setIntegrationKeys(Map<String, String> integrationKeys) {
+ this.integrationKeys = integrationKeys;
+ }
+
+
+ protected String getJsonInfo() {
+
+ StringBuilder returnString = new StringBuilder();
+ returnString.append("{");
+ returnString.append("\"moduleCode\"").append(":\"").append(this.getModuleCode()).append("\"");
+ returnString.append(",");
+ returnString.append("\"active\"").append(":").append(this.isActive());
+ returnString.append(",");
+ returnString.append("\"defaultSelected\"").append(":").append(this.isDefaultSelected());
+ returnString.append(",");
+ //returnString.append("\"customModule\"").append(":").append(this.isCustomModule());
+ //returnString.append(",");
+ returnString.append("\"environment\"").append(":\"").append(this.getEnvironment()).append("\"");
+ //returnString.append("}");
+ return returnString.toString();
+
+ }
+
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public String toJSONString() {
+
+
+ StringBuilder returnString = new StringBuilder();
+ returnString.append(getJsonInfo());
+
+ if(this.getIntegrationKeys().size()>0) {
+
+ JSONObject data = new JSONObject();
+ Set<String> keys = this.getIntegrationKeys().keySet();
+ for(String key : keys) {
+ data.put(key, this.getIntegrationKeys().get(key));
+ }
+ String dataField = data.toJSONString();
+
+ returnString.append(",").append("\"integrationKeys\"").append(":");
+ returnString.append(dataField.toString());
+
+
+ }
+
+
+ if(this.getIntegrationOptions()!=null && this.getIntegrationOptions().size()>0) {
+
+ //JSONObject data = new JSONObject();
+ StringBuilder optionDataEntries = new StringBuilder();
+ Set<String> keys = this.getIntegrationOptions().keySet();
+ int countOptions = 0;
+ for(String key : keys) {
+
+ List<String> values = this.getIntegrationOptions().get(key);
+ StringBuilder optionsEntries = new StringBuilder();
+ StringBuilder dataEntries = new StringBuilder();
+
+ int count = 0;
+ for(String value : values) {
+
+ dataEntries.append("\"").append(value).append("\"");
+ if(count<values.size()-1) {
+ dataEntries.append(",");
+ }
+ count++;
+ }
+
+ optionsEntries.append("[").append(dataEntries.toString()).append("]");
+
+ optionDataEntries.append("\"").append(key).append("\":").append(optionsEntries.toString());
+
+ if(countOptions<keys.size()-1) {
+ optionDataEntries.append(",");
+ }
+ countOptions ++;
+
+ }
+ String dataField = optionDataEntries.toString();
+
+ returnString.append(",").append("\"integrationOptions\"").append(":{");
+ returnString.append(dataField.toString());
+ returnString.append("}");
+
+ }
+
+
+ returnString.append("}");
+
+
+ return returnString.toString();
+
+ }
+ public void setEnvironment(String environment) {
+ this.environment = environment;
+ }
+ public String getEnvironment() {
+ return environment;
+ }
+ public Map<String,List<String>> getIntegrationOptions() {
+ return integrationOptions;
+ }
+ public void setIntegrationOptions(Map<String,List<String>> integrationOptions) {
+ this.integrationOptions = integrationOptions;
+ }
+ public boolean isDefaultSelected() {
+ return defaultSelected;
+ }
+ public void setDefaultSelected(boolean defaultSelected) {
+ this.defaultSelected = defaultSelected;
+ }
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/model/IntegrationModule.java b/sm-core/src/main/java/com/salesmanager/core/business/system/model/IntegrationModule.java
new file mode 100755
index 0000000..8eb317e
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/model/IntegrationModule.java
@@ -0,0 +1,255 @@
+package com.salesmanager.core.business.system.model;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Transient;
+
+import org.hibernate.annotations.Type;
+
+import com.salesmanager.core.business.common.model.audit.AuditListener;
+import com.salesmanager.core.business.common.model.audit.AuditSection;
+import com.salesmanager.core.business.common.model.audit.Auditable;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@EntityListeners(value = AuditListener.class)
+@Table(name = "MODULE_CONFIGURATION", schema= SchemaConstant.SALESMANAGER_SCHEMA)
+
+
+public class IntegrationModule extends SalesManagerEntity<Long, IntegrationModule> implements Serializable, Auditable {
+
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -357523134800965997L;
+
+ @Id
+ @Column(name = "MODULE_CONF_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "MOD_CONF_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+
+
+ @Column(name="MODULE")
+ private String module;
+
+ @Column(name="CODE", nullable=false)
+ private String code;
+
+ @Column(name="REGIONS")
+ private String regions;
+
+ @Column(name="CONFIGURATION")
+ @Type(type = "org.hibernate.type.StringClobType")
+ private String configuration;
+
+ @Column(name="DETAILS")
+ @Type(type = "org.hibernate.type.StringClobType")
+ private String configDetails;
+
+ @Column(name="TYPE")
+ private String type;
+
+
+ @Column(name="IMAGE")
+ private String image;
+
+ @Column(name="CUSTOM_IND")
+ private boolean customModule = false;
+
+ @Transient
+ private Set<String> regionsSet = new HashSet<String>();
+
+ /**
+ * Contains a map of module config by environment (DEV,PROD)
+ */
+ @Transient
+ private Map<String,ModuleConfig> moduleConfigs = new HashMap<String,ModuleConfig>();
+
+
+ @Transient
+ private Map<String,String> details = new HashMap<String,String>();
+
+
+ public Map<String, String> getDetails() {
+ return details;
+ }
+
+
+
+ public void setDetails(Map<String, String> details) {
+ this.details = details;
+ }
+
+
+
+ @Embedded
+ private AuditSection auditSection = new AuditSection();
+
+
+
+ @Override
+ public AuditSection getAuditSection() {
+ return auditSection;
+ }
+
+
+
+ @Override
+ public void setAuditSection(AuditSection audit) {
+ this.auditSection = audit;
+
+ }
+
+
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+
+
+ public String getModule() {
+ return module;
+ }
+
+
+
+ public void setModule(String module) {
+ this.module = module;
+ }
+
+
+
+ public String getRegions() {
+ return regions;
+ }
+
+
+
+ public void setRegions(String regions) {
+ this.regions = regions;
+ }
+
+
+
+ public String getConfiguration() {
+ return configuration;
+ }
+
+
+
+ public void setConfiguration(String configuration) {
+ this.configuration = configuration;
+ }
+
+
+
+ public void setRegionsSet(Set<String> regionsSet) {
+ this.regionsSet = regionsSet;
+ }
+
+
+
+ public Set<String> getRegionsSet() {
+ return regionsSet;
+ }
+
+
+
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+
+
+ public String getCode() {
+ return code;
+ }
+
+
+
+ public void setModuleConfigs(Map<String,ModuleConfig> moduleConfigs) {
+ this.moduleConfigs = moduleConfigs;
+ }
+
+
+
+ public Map<String,ModuleConfig> getModuleConfigs() {
+ return moduleConfigs;
+ }
+
+
+
+ public void setImage(String image) {
+ this.image = image;
+ }
+
+
+
+ public String getImage() {
+ return image;
+ }
+
+
+
+ public void setCustomModule(boolean customModule) {
+ this.customModule = customModule;
+ }
+
+
+
+ public boolean isCustomModule() {
+ return customModule;
+ }
+
+ public String getConfigDetails() {
+ return configDetails;
+ }
+
+
+
+ public void setConfigDetails(String configDetails) {
+ this.configDetails = configDetails;
+ }
+
+
+
+ public void setType(String type) {
+ this.type = type;
+ }
+
+
+
+ public String getType() {
+ return type;
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/model/MerchantConfig.java b/sm-core/src/main/java/com/salesmanager/core/business/system/model/MerchantConfig.java
new file mode 100644
index 0000000..ae5d8f6
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/model/MerchantConfig.java
@@ -0,0 +1,110 @@
+package com.salesmanager.core.business.system.model;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+import org.json.simple.JSONAware;
+import org.json.simple.JSONObject;
+
+public class MerchantConfig implements Serializable, JSONAware {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+ private boolean displayCustomerSection =false;
+ private boolean displayContactUs =false;
+ private boolean displayStoreAddress = false;
+ private boolean displayAddToCartOnFeaturedItems = false;
+
+ /** Store default search json config **/
+ private Map<String,Boolean> useDefaultSearchConfig= new HashMap<String,Boolean>();//language code | true or false
+ private Map<String,String> defaultSearchConfigPath= new HashMap<String,String>();//language code | file path
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public String toJSONString() {
+ JSONObject data = new JSONObject();
+ data.put("displayCustomerSection", this.isDisplayCustomerSection());
+ data.put("displayContactUs", this.isDisplayContactUs());
+ data.put("displayStoreAddress", this.isDisplayStoreAddress());
+ data.put("displayAddToCartOnFeaturedItems", this.isDisplayAddToCartOnFeaturedItems());
+
+ if(useDefaultSearchConfig!=null) {
+ JSONObject obj = new JSONObject();
+ for(String key : useDefaultSearchConfig.keySet()) {
+ Boolean val = (Boolean)useDefaultSearchConfig.get(key);
+ if(val!=null) {
+ obj.put(key,val);
+ }
+ }
+ data.put("useDefaultSearchConfig", obj);
+ }
+
+ if(defaultSearchConfigPath!=null) {
+ JSONObject obj = new JSONObject();
+ for(String key : defaultSearchConfigPath.keySet()) {
+ String val = (String)defaultSearchConfigPath.get(key);
+ if(!StringUtils.isBlank(val)) {
+ obj.put(key, val);
+ }
+ }
+ data.put("defaultSearchConfigPath", obj);
+ }
+
+
+ return data.toJSONString();
+ }
+
+ public void setDisplayCustomerSection(boolean displayCustomerSection) {
+ this.displayCustomerSection = displayCustomerSection;
+ }
+
+ public boolean isDisplayCustomerSection() {
+ return displayCustomerSection;
+ }
+
+ public void setDisplayContactUs(boolean displayContactUs) {
+ this.displayContactUs = displayContactUs;
+ }
+
+ public boolean isDisplayContactUs() {
+ return displayContactUs;
+ }
+
+ public boolean isDisplayStoreAddress() {
+ return displayStoreAddress;
+ }
+
+ public void setDisplayStoreAddress(boolean displayStoreAddress) {
+ this.displayStoreAddress = displayStoreAddress;
+ }
+
+ public void setUseDefaultSearchConfig(Map<String,Boolean> useDefaultSearchConfig) {
+ this.useDefaultSearchConfig = useDefaultSearchConfig;
+ }
+
+ public Map<String,Boolean> getUseDefaultSearchConfig() {
+ return useDefaultSearchConfig;
+ }
+
+ public void setDefaultSearchConfigPath(Map<String,String> defaultSearchConfigPath) {
+ this.defaultSearchConfigPath = defaultSearchConfigPath;
+ }
+
+ public Map<String,String> getDefaultSearchConfigPath() {
+ return defaultSearchConfigPath;
+ }
+
+ public void setDisplayAddToCartOnFeaturedItems(
+ boolean displayAddToCartOnFeaturedItems) {
+ this.displayAddToCartOnFeaturedItems = displayAddToCartOnFeaturedItems;
+ }
+
+ public boolean isDisplayAddToCartOnFeaturedItems() {
+ return displayAddToCartOnFeaturedItems;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/model/MerchantConfiguration.java b/sm-core/src/main/java/com/salesmanager/core/business/system/model/MerchantConfiguration.java
new file mode 100755
index 0000000..6a9a5fc
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/model/MerchantConfiguration.java
@@ -0,0 +1,124 @@
+package com.salesmanager.core.business.system.model;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.UniqueConstraint;
+
+import org.hibernate.annotations.Type;
+
+import com.salesmanager.core.business.common.model.audit.AuditListener;
+import com.salesmanager.core.business.common.model.audit.AuditSection;
+import com.salesmanager.core.business.common.model.audit.Auditable;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.constants.SchemaConstant;
+
+/**
+ * Merchant configuration information
+ * @author Carl Samson
+ *
+ */
+@Entity
+@EntityListeners(value = AuditListener.class)
+@Table(name = "MERCHANT_CONFIGURATION", schema= SchemaConstant.SALESMANAGER_SCHEMA, uniqueConstraints=
+ @UniqueConstraint(columnNames = {"MERCHANT_ID", "CONFIG_KEY"}))
+public class MerchantConfiguration extends SalesManagerEntity<Long, MerchantConfiguration> implements Serializable, Auditable {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 4246917986731953459L;
+
+ @Id
+ @Column(name = "MERCHANT_CONFIG_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "MERCH_CONF_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="MERCHANT_ID", nullable=true)
+ private MerchantStore merchantStore;
+
+ @Embedded
+ private AuditSection auditSection = new AuditSection();
+
+ @Column(name="CONFIG_KEY")
+ private String key;
+
+
+ @Column(name="VALUE")
+ @Type(type = "org.hibernate.type.StringClobType")
+ private String value;
+
+ @Column(name="TYPE")
+ @Enumerated(value = EnumType.STRING)
+ private MerchantConfigurationType merchantConfigurationType = MerchantConfigurationType.INTEGRATION;
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public AuditSection getAuditSection() {
+ return auditSection;
+ }
+
+ public void setAuditSection(AuditSection auditSection) {
+ this.auditSection = auditSection;
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+
+
+ public MerchantStore getMerchantStore() {
+ return merchantStore;
+ }
+
+ public void setMerchantStore(MerchantStore merchantStore) {
+ this.merchantStore = merchantStore;
+ }
+
+ public void setMerchantConfigurationType(MerchantConfigurationType merchantConfigurationType) {
+ this.merchantConfigurationType = merchantConfigurationType;
+ }
+
+ public MerchantConfigurationType getMerchantConfigurationType() {
+ return merchantConfigurationType;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/model/MerchantConfigurationType.java b/sm-core/src/main/java/com/salesmanager/core/business/system/model/MerchantConfigurationType.java
new file mode 100644
index 0000000..a496272
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/model/MerchantConfigurationType.java
@@ -0,0 +1,9 @@
+package com.salesmanager.core.business.system.model;
+
+public enum MerchantConfigurationType {
+
+ INTEGRATION,
+ SHOP,
+ CONFIG
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/model/MerchantLog.java b/sm-core/src/main/java/com/salesmanager/core/business/system/model/MerchantLog.java
new file mode 100644
index 0000000..bcf1c15
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/model/MerchantLog.java
@@ -0,0 +1,106 @@
+package com.salesmanager.core.business.system.model;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+import org.hibernate.annotations.Type;
+
+import com.salesmanager.core.business.common.model.audit.AuditListener;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@EntityListeners(value = AuditListener.class)
+@Table(name = "MERCHANT_LOG", schema= SchemaConstant.SALESMANAGER_SCHEMA)
+public class MerchantLog extends SalesManagerEntity<Long, MerchantLog> implements Serializable {
+
+
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ @Id
+ @Column(name = "MERCHANT_LOG_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "MOD_CONF_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="MERCHANT_ID", nullable=false)
+ private MerchantStore store;
+
+ @Column(name="MODULE", length=25, nullable=true)
+ private String module;
+
+
+ @Column(name="LOG")
+ @Type(type = "org.hibernate.type.StringClobType")
+ private String log;
+
+ public MerchantLog(MerchantStore store, String log) {
+ this.store = store;
+ this.log = log;
+ }
+
+ public MerchantLog(MerchantStore store, String module, String log) {
+ this.store = store;
+ this.module = module;
+ this.log = log;
+ }
+
+
+ public Long getId() {
+ return id;
+ }
+
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+
+ public MerchantStore getStore() {
+ return store;
+ }
+
+
+ public void setStore(MerchantStore store) {
+ this.store = store;
+ }
+
+
+ public String getModule() {
+ return module;
+ }
+
+
+ public void setModule(String module) {
+ this.module = module;
+ }
+
+
+ public String getLog() {
+ return log;
+ }
+
+
+ public void setLog(String log) {
+ this.log = log;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/model/Module.java b/sm-core/src/main/java/com/salesmanager/core/business/system/model/Module.java
new file mode 100755
index 0000000..98c1bb0
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/model/Module.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.system.model;
+
+public enum Module {
+
+ PAYMENT, SHIPPING
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/model/ModuleConfig.java b/sm-core/src/main/java/com/salesmanager/core/business/system/model/ModuleConfig.java
new file mode 100755
index 0000000..138c721
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/model/ModuleConfig.java
@@ -0,0 +1,56 @@
+package com.salesmanager.core.business.system.model;
+
+public class ModuleConfig {
+
+
+ private String scheme;
+ private String host;
+ private String port;
+ private String uri;
+ private String env;
+ private String config1;
+ private String config2;
+ public String getScheme() {
+ return scheme;
+ }
+ public void setScheme(String scheme) {
+ this.scheme = scheme;
+ }
+ public String getHost() {
+ return host;
+ }
+ public void setHost(String host) {
+ this.host = host;
+ }
+ public String getPort() {
+ return port;
+ }
+ public void setPort(String port) {
+ this.port = port;
+ }
+ public String getUri() {
+ return uri;
+ }
+ public void setUri(String uri) {
+ this.uri = uri;
+ }
+ public void setEnv(String env) {
+ this.env = env;
+ }
+ public String getEnv() {
+ return env;
+ }
+ public String getConfig1() {
+ return config1;
+ }
+ public void setConfig1(String config1) {
+ this.config1 = config1;
+ }
+ public String getConfig2() {
+ return config2;
+ }
+ public void setConfig2(String config2) {
+ this.config2 = config2;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/model/SystemConfiguration.java b/sm-core/src/main/java/com/salesmanager/core/business/system/model/SystemConfiguration.java
new file mode 100644
index 0000000..c32b7e0
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/model/SystemConfiguration.java
@@ -0,0 +1,80 @@
+package com.salesmanager.core.business.system.model;
+
+import java.io.Serializable;
+
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+import com.salesmanager.core.business.common.model.audit.AuditListener;
+import com.salesmanager.core.business.common.model.audit.AuditSection;
+import com.salesmanager.core.business.common.model.audit.Auditable;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.constants.SchemaConstant;
+
+/**
+ * Global system configuration information
+ * @author casams1
+ *
+ */
+@Entity
+@EntityListeners(value = AuditListener.class)
+@Table(name = "SYSTEM_CONFIGURATION", schema= SchemaConstant.SALESMANAGER_SCHEMA)
+public class SystemConfiguration extends SalesManagerEntity<Long, SystemConfiguration> implements Serializable, Auditable {
+ private static final long serialVersionUID = 6831573162350751684L;
+
+ @Id
+ @Column(name = "SYSTEM_CONFIG_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "SYST_CONF_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @Column(name="CONFIG_KEY")
+ private String key;
+
+ @Column(name="VALUE")
+ private String value;
+
+ @Embedded
+ private AuditSection auditSection = new AuditSection();
+
+ public AuditSection getAuditSection() {
+ return auditSection;
+ }
+
+ public void setAuditSection(AuditSection auditSection) {
+ this.auditSection = auditSection;
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/model/SystemNotification.java b/sm-core/src/main/java/com/salesmanager/core/business/system/model/SystemNotification.java
new file mode 100755
index 0000000..b7f696e
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/model/SystemNotification.java
@@ -0,0 +1,138 @@
+package com.salesmanager.core.business.system.model;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.persistence.UniqueConstraint;
+
+import com.salesmanager.core.business.common.model.audit.AuditListener;
+import com.salesmanager.core.business.common.model.audit.AuditSection;
+import com.salesmanager.core.business.common.model.audit.Auditable;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.user.model.User;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@EntityListeners(value = AuditListener.class)
+
+@Table(name = "SYSTEM_NOTIFICATION", schema= SchemaConstant.SALESMANAGER_SCHEMA,uniqueConstraints=
+ @UniqueConstraint(columnNames = {"MERCHANT_ID", "CONFIG_KEY"}) )
+public class SystemNotification extends SalesManagerEntity<Long, SystemNotification> implements Serializable, Auditable {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6269172313628887000L;
+
+ @Id
+ @Column(name = "SYSTEM_NOTIF_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "SYST_NOTIF_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @Column(name="CONFIG_KEY")
+ private String key;
+
+ @Column(name="VALUE")
+ private String value;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="MERCHANT_ID", nullable=true)
+ private MerchantStore merchantStore;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="USER_ID", nullable=true)
+ private User user;
+
+ @Temporal(TemporalType.DATE)
+ @Column(name = "START_DATE")
+ private Date startDate;
+
+ @Temporal(TemporalType.DATE)
+ @Column(name = "END_DATE")
+ private Date endDate;
+
+ @Embedded
+ private AuditSection auditSection = new AuditSection();
+
+ public AuditSection getAuditSection() {
+ return auditSection;
+ }
+
+ public void setAuditSection(AuditSection auditSection) {
+ this.auditSection = auditSection;
+ }
+
+ @Override
+ public Long getId() {
+ return id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public void setKey(String key) {
+ this.key = key;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ public void setStartDate(Date startDate) {
+ this.startDate = startDate;
+ }
+
+ public Date getStartDate() {
+ return startDate;
+ }
+
+ public void setMerchantStore(MerchantStore merchantStore) {
+ this.merchantStore = merchantStore;
+ }
+
+ public MerchantStore getMerchantStore() {
+ return merchantStore;
+ }
+
+ public void setEndDate(Date endDate) {
+ this.endDate = endDate;
+ }
+
+ public Date getEndDate() {
+ return endDate;
+ }
+
+ public void setUser(User user) {
+ this.user = user;
+ }
+
+ public User getUser() {
+ return user;
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/service/EmailService.java b/sm-core/src/main/java/com/salesmanager/core/business/system/service/EmailService.java
new file mode 100644
index 0000000..632f54b
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/service/EmailService.java
@@ -0,0 +1,17 @@
+package com.salesmanager.core.business.system.service;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.modules.email.Email;
+import com.salesmanager.core.modules.email.EmailConfig;
+
+
+public interface EmailService {
+
+ public void sendHtmlEmail(MerchantStore store, Email email) throws ServiceException, Exception;
+
+ public EmailConfig getEmailConfiguration(MerchantStore store) throws ServiceException;
+
+ public void saveEmailConfiguration(EmailConfig emailConfig, MerchantStore store) throws ServiceException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/service/EmailServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/system/service/EmailServiceImpl.java
new file mode 100644
index 0000000..15ccb51
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/service/EmailServiceImpl.java
@@ -0,0 +1,66 @@
+package com.salesmanager.core.business.system.service;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.system.model.MerchantConfiguration;
+import com.salesmanager.core.constants.Constants;
+import com.salesmanager.core.modules.email.Email;
+import com.salesmanager.core.modules.email.EmailConfig;
+import com.salesmanager.core.modules.email.HtmlEmailSender;
+
+@Service("emailService")
+public class EmailServiceImpl implements EmailService {
+
+ @Autowired
+ private MerchantConfigurationService merchantConfigurationService;
+
+ @Autowired
+ private HtmlEmailSender sender;
+
+ @Override
+ public void sendHtmlEmail(MerchantStore store, Email email) throws ServiceException, Exception {
+
+ EmailConfig emailConfig = getEmailConfiguration(store);
+
+ sender.setEmailConfig(emailConfig);
+ sender.send(email);
+ }
+
+ @Override
+ public EmailConfig getEmailConfiguration(MerchantStore store) throws ServiceException {
+
+ MerchantConfiguration configuration = merchantConfigurationService.getMerchantConfiguration(Constants.EMAIL_CONFIG, store);
+ EmailConfig emailConfig = null;
+ if(configuration!=null) {
+ String value = configuration.getValue();
+
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ emailConfig = mapper.readValue(value, EmailConfig.class);
+ } catch(Exception e) {
+ throw new ServiceException("Cannot parse json string " + value);
+ }
+ }
+ return emailConfig;
+ }
+
+
+ @Override
+ public void saveEmailConfiguration(EmailConfig emailConfig, MerchantStore store) throws ServiceException {
+ MerchantConfiguration configuration = merchantConfigurationService.getMerchantConfiguration(Constants.EMAIL_CONFIG, store);
+ if(configuration==null) {
+ configuration = new MerchantConfiguration();
+ configuration.setMerchantStore(store);
+ configuration.setKey(Constants.EMAIL_CONFIG);
+ }
+
+ String value = emailConfig.toJSONString();
+ configuration.setValue(value);
+ merchantConfigurationService.saveOrUpdate(configuration);
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/service/MerchantConfigurationService.java b/sm-core/src/main/java/com/salesmanager/core/business/system/service/MerchantConfigurationService.java
new file mode 100755
index 0000000..2147f58
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/service/MerchantConfigurationService.java
@@ -0,0 +1,31 @@
+package com.salesmanager.core.business.system.service;
+
+import java.util.List;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.system.model.MerchantConfig;
+import com.salesmanager.core.business.system.model.MerchantConfiguration;
+import com.salesmanager.core.business.system.model.MerchantConfigurationType;
+
+public interface MerchantConfigurationService extends
+ SalesManagerEntityService<Long, MerchantConfiguration> {
+
+ MerchantConfiguration getMerchantConfiguration(String key, MerchantStore store) throws ServiceException;
+
+ public void saveOrUpdate(MerchantConfiguration entity) throws ServiceException;
+
+ List<MerchantConfiguration> listByStore(MerchantStore store)
+ throws ServiceException;
+
+ List<MerchantConfiguration> listByType(MerchantConfigurationType type,
+ MerchantStore store) throws ServiceException;
+
+ MerchantConfig getMerchantConfig(MerchantStore store)
+ throws ServiceException;
+
+ void saveMerchantConfig(MerchantConfig config, MerchantStore store)
+ throws ServiceException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/service/MerchantConfigurationServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/system/service/MerchantConfigurationServiceImpl.java
new file mode 100755
index 0000000..4673bc3
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/service/MerchantConfigurationServiceImpl.java
@@ -0,0 +1,116 @@
+package com.salesmanager.core.business.system.service;
+
+import java.util.List;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.shipping.model.ShippingConfiguration;
+import com.salesmanager.core.business.system.dao.MerchantConfigurationDao;
+import com.salesmanager.core.business.system.model.MerchantConfig;
+import com.salesmanager.core.business.system.model.MerchantConfiguration;
+import com.salesmanager.core.business.system.model.MerchantConfigurationType;
+import com.salesmanager.core.constants.Constants;
+import com.salesmanager.core.constants.ShippingConstants;
+
+@Service("merchantConfigurationService")
+public class MerchantConfigurationServiceImpl extends
+ SalesManagerEntityServiceImpl<Long, MerchantConfiguration> implements
+ MerchantConfigurationService {
+
+ private MerchantConfigurationDao merchantConfigurationDao;
+
+ @Autowired
+ public MerchantConfigurationServiceImpl(
+ MerchantConfigurationDao merchantConfigurationDao) {
+ super(merchantConfigurationDao);
+ this.merchantConfigurationDao = merchantConfigurationDao;
+ }
+
+
+ @Override
+ public MerchantConfiguration getMerchantConfiguration(String key, MerchantStore store) throws ServiceException {
+ return merchantConfigurationDao.getMerchantConfiguration(key, store);
+ }
+
+ @Override
+ public List<MerchantConfiguration> listByStore(MerchantStore store) throws ServiceException {
+ return merchantConfigurationDao.getMerchantConfigurations(store);
+ }
+
+ @Override
+ public List<MerchantConfiguration> listByType(MerchantConfigurationType type, MerchantStore store) throws ServiceException {
+ return merchantConfigurationDao.listByType(type, store);
+ }
+
+ @Override
+ public void saveOrUpdate(MerchantConfiguration entity) throws ServiceException {
+
+
+
+ if(entity.getId()!=null && entity.getId()>0) {
+ super.update(entity);
+ } else {
+ super.create(entity);
+
+ }
+ }
+
+
+ @Override
+ public void delete(MerchantConfiguration merchantConfiguration) throws ServiceException {
+ MerchantConfiguration config = merchantConfigurationDao.getById(merchantConfiguration.getId());
+ if(config!=null) {
+ super.delete(config);
+ }
+ }
+
+ @Override
+ public MerchantConfig getMerchantConfig(MerchantStore store) throws ServiceException {
+
+ MerchantConfiguration configuration = merchantConfigurationDao.getMerchantConfiguration(Constants.MERCHANT_CONFIG, store);
+
+ MerchantConfig config = null;
+ if(configuration!=null) {
+ String value = configuration.getValue();
+
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ config = mapper.readValue(value, MerchantConfig.class);
+ } catch(Exception e) {
+ throw new ServiceException("Cannot parse json string " + value);
+ }
+ }
+ return config;
+
+ }
+
+ @Override
+ public void saveMerchantConfig(MerchantConfig config, MerchantStore store) throws ServiceException {
+
+ MerchantConfiguration configuration = merchantConfigurationDao.getMerchantConfiguration(Constants.MERCHANT_CONFIG, store);
+
+ if(configuration==null) {
+ configuration = new MerchantConfiguration();
+ configuration.setMerchantStore(store);
+ configuration.setKey(Constants.MERCHANT_CONFIG);
+ }
+
+ String value = config.toJSONString();
+ configuration.setValue(value);
+ if(configuration.getId()!=null && configuration.getId()>0) {
+ super.update(configuration);
+ } else {
+ super.create(configuration);
+
+ }
+
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/service/MerchantLogService.java b/sm-core/src/main/java/com/salesmanager/core/business/system/service/MerchantLogService.java
new file mode 100644
index 0000000..5906d18
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/service/MerchantLogService.java
@@ -0,0 +1,12 @@
+package com.salesmanager.core.business.system.service;
+
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.system.model.MerchantLog;
+
+public interface MerchantLogService extends
+ SalesManagerEntityService<Long, MerchantLog> {
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/service/MerchantLogServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/system/service/MerchantLogServiceImpl.java
new file mode 100644
index 0000000..79738af
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/service/MerchantLogServiceImpl.java
@@ -0,0 +1,36 @@
+package com.salesmanager.core.business.system.service;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.system.dao.MerchantLogDao;
+import com.salesmanager.core.business.system.model.MerchantLog;
+
+@Service("merchantLogService")
+public class MerchantLogServiceImpl extends
+ SalesManagerEntityServiceImpl<Long, MerchantLog> implements
+ MerchantLogService {
+
+ @SuppressWarnings("unused")
+ private static final Logger LOGGER = LoggerFactory.getLogger(MerchantLogServiceImpl.class);
+
+
+
+ private MerchantLogDao merchantLogDao;
+
+ @Autowired
+ public MerchantLogServiceImpl(
+ MerchantLogDao merchantLogDao) {
+ super(merchantLogDao);
+ this.merchantLogDao = merchantLogDao;
+ }
+
+
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/service/ModuleConfigurationService.java b/sm-core/src/main/java/com/salesmanager/core/business/system/service/ModuleConfigurationService.java
new file mode 100755
index 0000000..1ba92b7
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/service/ModuleConfigurationService.java
@@ -0,0 +1,17 @@
+package com.salesmanager.core.business.system.service;
+
+import java.util.List;
+
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+
+public interface ModuleConfigurationService extends
+ SalesManagerEntityService<Long, IntegrationModule> {
+
+ List<IntegrationModule> getIntegrationModules(String module);
+
+ IntegrationModule getByCode(String moduleCode);
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/service/ModuleConfigurationServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/system/service/ModuleConfigurationServiceImpl.java
new file mode 100755
index 0000000..f7b9522
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/service/ModuleConfigurationServiceImpl.java
@@ -0,0 +1,144 @@
+package com.salesmanager.core.business.system.service;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.json.simple.JSONArray;
+import org.json.simple.JSONValue;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.system.dao.ModuleConfigurationDao;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+import com.salesmanager.core.business.system.model.ModuleConfig;
+import com.salesmanager.core.utils.CacheUtils;
+
+@Service("moduleConfigurationService")
+public class ModuleConfigurationServiceImpl extends
+ SalesManagerEntityServiceImpl<Long, IntegrationModule> implements
+ ModuleConfigurationService {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ModuleConfigurationServiceImpl.class);
+
+
+
+ private ModuleConfigurationDao integrationModuleDao;
+
+ @Autowired
+ private CacheUtils cache;
+
+ @Autowired
+ public ModuleConfigurationServiceImpl(
+ ModuleConfigurationDao integrationModuleDao) {
+ super(integrationModuleDao);
+ this.integrationModuleDao = integrationModuleDao;
+ }
+
+ @Override
+ public IntegrationModule getByCode(String moduleCode) {
+ return integrationModuleDao.getByCode(moduleCode);
+ }
+
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ public List<IntegrationModule> getIntegrationModules(String module) {
+
+
+ List<IntegrationModule> modules = null;
+ try {
+
+ //CacheUtils cacheUtils = CacheUtils.getInstance();
+ modules = (List<IntegrationModule>) cache.getFromCache("INTEGRATION_M)" + module);
+ if(modules==null) {
+ modules = integrationModuleDao.getModulesConfiguration(module);
+ //set json objects
+ for(IntegrationModule mod : modules) {
+
+ String regions = mod.getRegions();
+ if(regions!=null) {
+ Object objRegions=JSONValue.parse(regions);
+ JSONArray arrayRegions=(JSONArray)objRegions;
+ Iterator i = arrayRegions.iterator();
+ while(i.hasNext()) {
+ mod.getRegionsSet().add((String)i.next());
+ }
+ }
+
+
+ String details = mod.getConfigDetails();
+ if(details!=null) {
+
+ //Map objects = mapper.readValue(config, Map.class);
+
+ Map<String,String> objDetails= (Map<String, String>) JSONValue.parse(details);
+ mod.setDetails(objDetails);
+
+
+ }
+
+
+ String configs = mod.getConfiguration();
+ if(configs!=null) {
+
+ //Map objects = mapper.readValue(config, Map.class);
+
+ Object objConfigs=JSONValue.parse(configs);
+ JSONArray arrayConfigs=(JSONArray)objConfigs;
+
+ Map<String,ModuleConfig> moduleConfigs = new HashMap<String,ModuleConfig>();
+
+ Iterator i = arrayConfigs.iterator();
+ while(i.hasNext()) {
+
+ Map values = (Map)i.next();
+ String env = (String)values.get("env");
+ ModuleConfig config = new ModuleConfig();
+ config.setScheme((String)values.get("scheme"));
+ config.setHost((String)values.get("host"));
+ config.setPort((String)values.get("port"));
+ config.setUri((String)values.get("uri"));
+ config.setEnv((String)values.get("env"));
+ if((String)values.get("config1")!=null) {
+ config.setConfig1((String)values.get("config1"));
+ }
+ if((String)values.get("config2")!=null) {
+ config.setConfig1((String)values.get("config2"));
+ }
+
+ moduleConfigs.put(env, config);
+
+
+
+ }
+
+ mod.setModuleConfigs(moduleConfigs);
+
+
+ }
+
+
+ }
+ cache.putInCache(modules, "INTEGRATION_M)" + module);
+ }
+
+ } catch (Exception e) {
+ LOGGER.error("getIntegrationModules()", e);
+ }
+ return modules;
+
+
+ }
+
+
+
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/service/SystemConfigurationService.java b/sm-core/src/main/java/com/salesmanager/core/business/system/service/SystemConfigurationService.java
new file mode 100644
index 0000000..08d1d35
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/service/SystemConfigurationService.java
@@ -0,0 +1,12 @@
+package com.salesmanager.core.business.system.service;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.system.model.SystemConfiguration;
+
+public interface SystemConfigurationService extends
+ SalesManagerEntityService<Long, SystemConfiguration> {
+
+ SystemConfiguration getByKey(String key) throws ServiceException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/system/service/SystemConfigurationServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/system/service/SystemConfigurationServiceImpl.java
new file mode 100644
index 0000000..03b295e
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/system/service/SystemConfigurationServiceImpl.java
@@ -0,0 +1,34 @@
+package com.salesmanager.core.business.system.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.system.dao.SystemConfigurationDao;
+import com.salesmanager.core.business.system.model.SystemConfiguration;
+import com.salesmanager.core.business.system.model.SystemConfiguration_;
+
+@Service("systemConfigurationService")
+public class SystemConfigurationServiceImpl extends
+ SalesManagerEntityServiceImpl<Long, SystemConfiguration> implements
+ SystemConfigurationService {
+
+
+ private SystemConfigurationDao systemConfigurationDao;
+
+ @Autowired
+ public SystemConfigurationServiceImpl(
+ SystemConfigurationDao systemConfigurationDao) {
+ super(systemConfigurationDao);
+ this.systemConfigurationDao = systemConfigurationDao;
+ }
+
+ public SystemConfiguration getByKey(String key) throws ServiceException {
+ return super.getByField(SystemConfiguration_.key, key);
+ }
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/tax/dao/taxclass/TaxClassDao.java b/sm-core/src/main/java/com/salesmanager/core/business/tax/dao/taxclass/TaxClassDao.java
new file mode 100644
index 0000000..ba767ee
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/tax/dao/taxclass/TaxClassDao.java
@@ -0,0 +1,17 @@
+package com.salesmanager.core.business.tax.dao.taxclass;
+
+import java.util.List;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.tax.model.taxclass.TaxClass;
+
+public interface TaxClassDao extends SalesManagerEntityDao<Long, TaxClass> {
+
+ List<TaxClass> listByStore(MerchantStore store);
+
+ TaxClass getByCode(String code);
+
+ TaxClass getByCode(String code, MerchantStore store);
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/tax/dao/taxclass/TaxClassDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/tax/dao/taxclass/TaxClassDaoImpl.java
new file mode 100644
index 0000000..2c5ca43
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/tax/dao/taxclass/TaxClassDaoImpl.java
@@ -0,0 +1,78 @@
+package com.salesmanager.core.business.tax.dao.taxclass;
+
+import java.util.List;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.tax.model.taxclass.QTaxClass;
+import com.salesmanager.core.business.tax.model.taxclass.TaxClass;
+
+@Repository("taxClassDao")
+public class TaxClassDaoImpl extends SalesManagerEntityDaoImpl<Long, TaxClass> implements TaxClassDao{
+
+ public TaxClassDaoImpl() {
+ super();
+ }
+
+
+ @Override
+ public List<TaxClass> listByStore(MerchantStore store) {
+ QTaxClass qTax = QTaxClass.taxClass;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qTax)
+ .leftJoin(qTax.merchantStore).fetch()
+ .where(qTax.merchantStore.id.eq(store.getId())
+ .or(qTax.merchantStore.isNull()));
+
+ List<TaxClass> taxes = query.list(qTax);
+ return taxes;
+ }
+
+
+ @Override
+ public TaxClass getByCode(String code) {
+ QTaxClass qTax = QTaxClass.taxClass;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qTax)
+ .leftJoin(qTax.merchantStore).fetch()
+ .where(qTax.code.eq(code));
+
+ return query.uniqueResult(qTax);
+ }
+
+ @Override
+ public TaxClass getByCode(String code, MerchantStore store) {
+ QTaxClass qTax = QTaxClass.taxClass;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qTax)
+ .leftJoin(qTax.merchantStore).fetch()
+ .where(qTax.code.eq(code).and(qTax.merchantStore.id.eq(store.getId())));
+
+ return query.uniqueResult(qTax);
+ }
+
+ @Override
+ public TaxClass getById(Long id) {
+ QTaxClass qTax = QTaxClass.taxClass;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qTax)
+ .leftJoin(qTax.merchantStore).fetch()
+ .where(qTax.id.eq(id));
+
+ return query.uniqueResult(qTax);
+ }
+
+
+}
\ No newline at end of file
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/tax/dao/taxrate/TaxRateDao.java b/sm-core/src/main/java/com/salesmanager/core/business/tax/dao/taxrate/TaxRateDao.java
new file mode 100644
index 0000000..01acc69
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/tax/dao/taxrate/TaxRateDao.java
@@ -0,0 +1,28 @@
+package com.salesmanager.core.business.tax.dao.taxrate;
+
+import java.util.List;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.core.business.tax.model.taxclass.TaxClass;
+import com.salesmanager.core.business.tax.model.taxrate.TaxRate;
+
+public interface TaxRateDao extends SalesManagerEntityDao<Long, TaxRate> {
+
+ List<TaxRate> listByStore(MerchantStore store);
+
+ List<TaxRate> listByCountryZoneAndTaxClass(Country country, Zone zone,
+ TaxClass taxClass, MerchantStore store, Language language);
+
+ List<TaxRate> listByCountryStateProvinceAndTaxClass(Country country,
+ String stateProvince, TaxClass taxClass, MerchantStore store,
+ Language language);
+
+ TaxRate getByCode(String code, MerchantStore store);
+
+ List<TaxRate> listByStore(MerchantStore store, Language language);
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/tax/dao/taxrate/TaxRateDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/tax/dao/taxrate/TaxRateDaoImpl.java
new file mode 100644
index 0000000..2520eff
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/tax/dao/taxrate/TaxRateDaoImpl.java
@@ -0,0 +1,185 @@
+package com.salesmanager.core.business.tax.dao.taxrate;
+
+import java.util.List;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.core.business.tax.model.taxclass.TaxClass;
+import com.salesmanager.core.business.tax.model.taxrate.QTaxRate;
+import com.salesmanager.core.business.tax.model.taxrate.QTaxRateDescription;
+import com.salesmanager.core.business.tax.model.taxrate.TaxRate;
+
+@Repository("taxRateDao")
+public class TaxRateDaoImpl extends SalesManagerEntityDaoImpl<Long, TaxRate> implements TaxRateDao{
+
+ public TaxRateDaoImpl() {
+ super();
+ }
+
+ @Override
+ public List<TaxRate> listByStore(MerchantStore store) {
+
+
+ QTaxRate qTax = QTaxRate.taxRate1;
+ QTaxRateDescription qTaxDescription = QTaxRateDescription.taxRateDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qTax)
+ .leftJoin(qTax.merchantStore).fetch()
+ .leftJoin(qTax.descriptions,qTaxDescription).fetch()
+ .join(qTax.country).fetch()
+ .leftJoin(qTax.zone).fetch()
+ .leftJoin(qTax.parent).fetch()
+ .where(qTax.merchantStore.id.eq(store.getId())
+ ).orderBy(qTax.taxPriority.asc());
+
+ List<TaxRate> taxes = query.list(qTax);
+ return taxes;
+
+
+
+ }
+
+ @Override
+ public List<TaxRate> listByStore(MerchantStore store, Language language) {
+
+
+ QTaxRate qTax = QTaxRate.taxRate1;
+ QTaxRateDescription qTaxDescription = QTaxRateDescription.taxRateDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qTax)
+ .leftJoin(qTax.merchantStore).fetch()
+ .leftJoin(qTax.descriptions,qTaxDescription).fetch()
+ .join(qTax.country).fetch()
+ .leftJoin(qTax.zone).fetch()
+ .leftJoin(qTax.parent).fetch()
+ .where(qTax.merchantStore.id.eq(store.getId())
+ .and(qTaxDescription.language.id.eq(language.getId())))
+ .orderBy(qTax.taxPriority.asc());
+
+ List<TaxRate> taxes = query.list(qTax);
+ return taxes;
+
+
+
+ }
+
+ @Override
+ public TaxRate getByCode(String code, MerchantStore store) {
+
+
+ QTaxRate qTax = QTaxRate.taxRate1;
+ QTaxRateDescription qTaxDescription = QTaxRateDescription.taxRateDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qTax)
+ .leftJoin(qTax.merchantStore).fetch()
+ .leftJoin(qTax.descriptions,qTaxDescription).fetch()
+ .join(qTax.country).fetch()
+ .leftJoin(qTax.zone).fetch()
+ .leftJoin(qTax.parent).fetch()
+ .where(qTax.merchantStore.id.eq(store.getId())
+ .and(qTax.code.eq(code))
+ ).orderBy(qTax.taxPriority.asc());
+
+ TaxRate tax = query.uniqueResult(qTax);
+ return tax;
+
+
+
+ }
+
+ @Override
+ public TaxRate getById(Long id) {
+
+
+ QTaxRate qTax = QTaxRate.taxRate1;
+ QTaxRateDescription qTaxDescription = QTaxRateDescription.taxRateDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qTax)
+ .leftJoin(qTax.merchantStore).fetch()
+ .leftJoin(qTax.descriptions,qTaxDescription).fetch()
+ .join(qTax.country).fetch()
+ .leftJoin(qTax.zone).fetch()
+ .leftJoin(qTax.parent).fetch()
+ .where(qTax.id.eq(id)
+ ).orderBy(qTax.taxPriority.asc());
+
+ TaxRate tax = query.uniqueResult(qTax);
+ return tax;
+
+
+
+ }
+
+ @Override
+ public List<TaxRate> listByCountryZoneAndTaxClass(Country country, Zone zone, TaxClass taxClass, MerchantStore store, Language language) {
+
+
+ QTaxRate qTax = QTaxRate.taxRate1;
+ QTaxRateDescription qTaxDescription = QTaxRateDescription.taxRateDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qTax)
+ .leftJoin(qTax.merchantStore).fetch()
+ .leftJoin(qTax.descriptions,qTaxDescription).fetch()
+ .join(qTax.country).fetch()
+ .leftJoin(qTax.zone).fetch()
+ .leftJoin(qTax.parent).fetch()
+ .where(qTax.merchantStore.id.eq(store.getId())
+ .and(
+ qTax.isNotNull().and(qTax.zone.id.eq(zone.getId())).or(qTax.isNull())
+ )
+ .and(qTax.country.id.eq(country.getId())
+ .and(qTaxDescription.language.id.eq(language.getId())))
+ ).orderBy(qTax.taxPriority.asc());
+
+ List<TaxRate> taxes = query.list(qTax);
+ return taxes;
+
+ }
+
+
+ @Override
+ public List<TaxRate> listByCountryStateProvinceAndTaxClass(Country country, String stateProvince, TaxClass taxClass, MerchantStore store, Language language) {
+
+
+ QTaxRate qTax = QTaxRate.taxRate1;
+ QTaxRateDescription qTaxDescription = QTaxRateDescription.taxRateDescription;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qTax)
+ .leftJoin(qTax.merchantStore).fetch()
+ .leftJoin(qTax.descriptions,qTaxDescription).fetch()
+ .join(qTax.country).fetch()
+ .leftJoin(qTax.parent).fetch()
+ .where(qTax.merchantStore.id.eq(store.getId())
+ .and(
+ qTax.stateProvince.eq(stateProvince)
+ )
+ .and(qTax.country.id.eq(country.getId())
+ .and(qTaxDescription.language.id.eq(language.getId())))
+ ).orderBy(qTax.taxPriority.asc());
+
+ List<TaxRate> taxes = query.list(qTax);
+ return taxes;
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/tax/model/TaxBasisCalculation.java b/sm-core/src/main/java/com/salesmanager/core/business/tax/model/TaxBasisCalculation.java
new file mode 100644
index 0000000..ecbd64c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/tax/model/TaxBasisCalculation.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.tax.model;
+
+public enum TaxBasisCalculation {
+
+ STOREADDRESS, SHIPPINGADDRESS, BILLINGADDRESS
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/tax/model/taxclass/TaxClass.java b/sm-core/src/main/java/com/salesmanager/core/business/tax/model/taxclass/TaxClass.java
new file mode 100644
index 0000000..5b24f3a
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/tax/model/taxclass/TaxClass.java
@@ -0,0 +1,123 @@
+package com.salesmanager.core.business.tax.model.taxclass;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.UniqueConstraint;
+
+import org.hibernate.validator.constraints.NotEmpty;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.tax.model.taxrate.TaxRate;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@Table(name = "TAX_CLASS", schema = SchemaConstant.SALESMANAGER_SCHEMA,uniqueConstraints=
+ @UniqueConstraint(columnNames = {"MERCHANT_ID", "TAX_CLASS_CODE"}) )
+public class TaxClass extends SalesManagerEntity<Long, TaxClass> {
+ private static final long serialVersionUID = -325750148480212355L;
+
+ public final static String DEFAULT_TAX_CLASS = "DEFAULT";
+
+ public TaxClass(String code) {
+ this.code = code;
+ this.title = code;
+ }
+
+ @Id
+ @Column(name = "TAX_CLASS_ID", unique=true, nullable=false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "TX_CLASS_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @NotEmpty
+ @Column(name="TAX_CLASS_CODE", nullable=false, length=10)
+ private String code;
+
+ @NotEmpty
+ @Column(name = "TAX_CLASS_TITLE" , nullable=false , length=32 )
+ private String title;
+
+
+
+ @OneToMany(mappedBy = "taxClass", targetEntity = Product.class)
+ private List<Product> products = new ArrayList<Product>();
+
+
+/* @ManyToMany(fetch=FetchType.LAZY, cascade = CascadeType.ALL)
+ @JoinTable(name = "MERCHANT_TAXCLASS", schema=SchemaConstant.SALESMANAGER_SCHEMA, joinColumns = {
+ @JoinColumn(name = "TAX_CLASS_ID", nullable = false) },
+ inverseJoinColumns = { @JoinColumn(name = "MERCHANT_ID",
+ nullable = false) })
+ private Set<MerchantStore> stores = new HashSet<MerchantStore>();*/
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="MERCHANT_ID", nullable=true)
+ private MerchantStore merchantStore;
+
+
+ @OneToMany(mappedBy = "taxClass")
+ private List<TaxRate> taxRates = new ArrayList<TaxRate>();
+
+ public TaxClass() {
+ super();
+ }
+
+ @Override
+ public Long getId() {
+ return this.id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(String title) {
+ this.title = title;
+ }
+
+ public String getCode() {
+ return code;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public List<TaxRate> getTaxRates() {
+ return taxRates;
+ }
+
+ public void setTaxRates(List<TaxRate> taxRates) {
+ this.taxRates = taxRates;
+ }
+
+
+ public MerchantStore getMerchantStore() {
+ return merchantStore;
+ }
+
+ public void setMerchantStore(MerchantStore merchantStore) {
+ this.merchantStore = merchantStore;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/tax/model/TaxConfiguration.java b/sm-core/src/main/java/com/salesmanager/core/business/tax/model/TaxConfiguration.java
new file mode 100644
index 0000000..6fd726e
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/tax/model/TaxConfiguration.java
@@ -0,0 +1,53 @@
+package com.salesmanager.core.business.tax.model;
+
+import org.json.simple.JSONAware;
+import org.json.simple.JSONObject;
+
+/**
+ * Set of various tax configuration settings saved in MerchantConfiguration
+ * @author carl samson
+ *
+ */
+public class TaxConfiguration implements JSONAware {
+
+ private TaxBasisCalculation taxBasisCalculation = TaxBasisCalculation.SHIPPINGADDRESS;
+
+ private boolean collectTaxIfDifferentProvinceOfStoreCountry = true;
+ private boolean collectTaxIfDifferentCountryOfStoreCountry = false;
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public String toJSONString() {
+ JSONObject data = new JSONObject();
+ data.put("taxBasisCalculation", this.getTaxBasisCalculation().name());
+
+ return data.toJSONString();
+ }
+
+ public void setTaxBasisCalculation(TaxBasisCalculation taxBasisCalculation) {
+ this.taxBasisCalculation = taxBasisCalculation;
+ }
+
+ public TaxBasisCalculation getTaxBasisCalculation() {
+ return taxBasisCalculation;
+ }
+
+ public void setCollectTaxIfDifferentProvinceOfStoreCountry(
+ boolean collectTaxIfDifferentProvinceOfStoreCountry) {
+ this.collectTaxIfDifferentProvinceOfStoreCountry = collectTaxIfDifferentProvinceOfStoreCountry;
+ }
+
+ public boolean isCollectTaxIfDifferentProvinceOfStoreCountry() {
+ return collectTaxIfDifferentProvinceOfStoreCountry;
+ }
+
+ public void setCollectTaxIfDifferentCountryOfStoreCountry(
+ boolean collectTaxIfDifferentCountryOfStoreCountry) {
+ this.collectTaxIfDifferentCountryOfStoreCountry = collectTaxIfDifferentCountryOfStoreCountry;
+ }
+
+ public boolean isCollectTaxIfDifferentCountryOfStoreCountry() {
+ return collectTaxIfDifferentCountryOfStoreCountry;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/tax/model/TaxItem.java b/sm-core/src/main/java/com/salesmanager/core/business/tax/model/TaxItem.java
new file mode 100644
index 0000000..61440b9
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/tax/model/TaxItem.java
@@ -0,0 +1,32 @@
+package com.salesmanager.core.business.tax.model;
+
+import com.salesmanager.core.business.common.model.OrderTotalItem;
+import com.salesmanager.core.business.tax.model.taxrate.TaxRate;
+
+public class TaxItem extends OrderTotalItem {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+ private String label;
+ private TaxRate taxRate=null;
+
+ public void setLabel(String label) {
+ this.label = label;
+ }
+
+ public String getLabel() {
+ return label;
+ }
+
+ public void setTaxRate(TaxRate taxRate) {
+ this.taxRate = taxRate;
+ }
+
+ public TaxRate getTaxRate() {
+ return taxRate;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/tax/model/taxrate/TaxRate.java b/sm-core/src/main/java/com/salesmanager/core/business/tax/model/taxrate/TaxRate.java
new file mode 100644
index 0000000..e08e5b2
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/tax/model/taxrate/TaxRate.java
@@ -0,0 +1,252 @@
+/*
+ * Licensed to csti consulting
+ * You may obtain a copy of the License at
+ *
+ * http://www.csticonsulting.com
+ * Copyright (c) 2006-Aug 24, 2010 Consultation CS-TI inc.
+ *
+ * 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.
+ */
+package com.salesmanager.core.business.tax.model.taxrate;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Transient;
+import javax.persistence.UniqueConstraint;
+import javax.validation.Valid;
+
+import org.hibernate.validator.constraints.NotEmpty;
+
+import com.salesmanager.core.business.common.model.audit.AuditListener;
+import com.salesmanager.core.business.common.model.audit.AuditSection;
+import com.salesmanager.core.business.common.model.audit.Auditable;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.core.business.tax.model.taxclass.TaxClass;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@EntityListeners(value = AuditListener.class)
+@Table(name = "TAX_RATE" , schema = SchemaConstant.SALESMANAGER_SCHEMA,uniqueConstraints={
+ @UniqueConstraint(columnNames={
+ "TAX_CODE",
+ "MERCHANT_ID"
+ })
+ }
+ )
+public class TaxRate extends SalesManagerEntity<Long, TaxRate> implements Auditable {
+ private static final long serialVersionUID = 3356827741612925066L;
+
+ @Id
+ @Column(name = "TAX_RATE_ID")
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "TAX_RATE_ID_NEXT_VALUE")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ @Embedded
+ private AuditSection auditSection = new AuditSection();
+
+ @Column(name = "TAX_PRIORITY")
+ private Integer taxPriority = 0;
+
+ @Column(name = "TAX_RATE" , nullable= false , precision=7, scale=4)
+ private BigDecimal taxRate;
+
+ @NotEmpty
+ @Column(name = "TAX_CODE")
+ private String code;
+
+
+ @Column(name = "PIGGYBACK")
+ private boolean piggyback;
+
+ @ManyToOne
+ @JoinColumn(name = "TAX_CLASS_ID" , nullable=false)
+ private TaxClass taxClass;
+
+
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="MERCHANT_ID", nullable=false)
+ private MerchantStore merchantStore;
+
+ @Valid
+ @OneToMany(mappedBy = "taxRate", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
+ private List<TaxRateDescription> descriptions = new ArrayList<TaxRateDescription>();
+
+ @ManyToOne(fetch = FetchType.LAZY, targetEntity = Country.class)
+ @JoinColumn(name="COUNTRY_ID", nullable=false, updatable=true)
+ private Country country;
+
+ @OneToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="ZONE_ID", nullable=true, updatable=true)
+ private Zone zone;
+
+ @Column(name = "STORE_STATE_PROV", length=100)
+ private String stateProvince;
+
+ @ManyToOne
+ @JoinColumn(name = "PARENT_ID")
+ private TaxRate parent;
+
+ @OneToMany(mappedBy = "parent", cascade = CascadeType.REMOVE, orphanRemoval = true)
+ private List<TaxRate> taxRates = new ArrayList<TaxRate>();
+
+ @Transient
+ private String rateText;
+
+
+ public String getRateText() {
+ return rateText;
+ }
+
+ public void setRateText(String rateText) {
+ this.rateText = rateText;
+ }
+
+ public TaxRate() {
+ }
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ @Override
+ public AuditSection getAuditSection() {
+ return auditSection;
+ }
+
+ @Override
+ public void setAuditSection(AuditSection auditSection) {
+ this.auditSection = auditSection;
+ }
+
+ public Integer getTaxPriority() {
+ return taxPriority;
+ }
+
+ public void setTaxPriority(Integer taxPriority) {
+ this.taxPriority = taxPriority;
+ }
+
+ public BigDecimal getTaxRate() {
+ return taxRate;
+ }
+
+ public void setTaxRate(BigDecimal taxRate) {
+ this.taxRate = taxRate;
+ }
+
+ public boolean isPiggyback() {
+ return piggyback;
+ }
+
+ public void setPiggyback(boolean piggyback) {
+ this.piggyback = piggyback;
+ }
+
+ public TaxClass getTaxClass() {
+ return taxClass;
+ }
+
+ public void setTaxClass(TaxClass taxClass) {
+ this.taxClass = taxClass;
+ }
+
+
+
+ public List<TaxRateDescription> getDescriptions() {
+ return descriptions;
+ }
+
+ public void setDescriptions(List<TaxRateDescription> descriptions) {
+ this.descriptions = descriptions;
+ }
+
+
+
+ public MerchantStore getMerchantStore() {
+ return merchantStore;
+ }
+
+ public void setMerchantStore(MerchantStore merchantStore) {
+ this.merchantStore = merchantStore;
+ }
+
+ public void setCountry(Country country) {
+ this.country = country;
+ }
+
+ public Country getCountry() {
+ return country;
+ }
+
+ public void setZone(Zone zone) {
+ this.zone = zone;
+ }
+
+ public Zone getZone() {
+ return zone;
+ }
+
+
+ public void setTaxRates(List<TaxRate> taxRates) {
+ this.taxRates = taxRates;
+ }
+
+ public List<TaxRate> getTaxRates() {
+ return taxRates;
+ }
+
+ public void setParent(TaxRate parent) {
+ this.parent = parent;
+ }
+
+ public TaxRate getParent() {
+ return parent;
+ }
+
+ public void setStateProvince(String stateProvince) {
+ this.stateProvince = stateProvince;
+ }
+
+ public String getStateProvince() {
+ return stateProvince;
+ }
+
+ public void setCode(String code) {
+ this.code = code;
+ }
+
+ public String getCode() {
+ return code;
+ }
+}
\ No newline at end of file
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/tax/model/taxrate/TaxRateDescription.java b/sm-core/src/main/java/com/salesmanager/core/business/tax/model/taxrate/TaxRateDescription.java
new file mode 100644
index 0000000..6265fca
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/tax/model/taxrate/TaxRateDescription.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to csti consulting
+ * You may obtain a copy of the License at
+ *
+ * http://www.csticonsulting.com
+ * Copyright (c) 2006-Aug 24, 2010 Consultation CS-TI inc.
+ *
+ * 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.
+ */
+package com.salesmanager.core.business.tax.model.taxrate;
+
+import javax.persistence.Entity;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.UniqueConstraint;
+
+import com.salesmanager.core.business.common.model.Description;
+import com.salesmanager.core.constants.SchemaConstant;
+
+
+@Entity
+@Table(name = "TAX_RATE_DESCRIPTION" , schema=SchemaConstant.SALESMANAGER_SCHEMA ,uniqueConstraints={
+ @UniqueConstraint(columnNames={
+ "TAX_RATE_ID",
+ "LANGUAGE_ID"
+ })
+ }
+ )
+public class TaxRateDescription extends Description {
+ private static final long serialVersionUID = -4752794805878361822L;
+
+ @ManyToOne(targetEntity = TaxRate.class)
+ @JoinColumn(name = "TAX_RATE_ID")
+ private TaxRate taxRate;
+
+ public TaxRateDescription() {
+ }
+
+ public TaxRate getTaxRate() {
+ return taxRate;
+ }
+
+ public void setTaxRate(TaxRate taxRate) {
+ this.taxRate = taxRate;
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/tax/service/TaxClassService.java b/sm-core/src/main/java/com/salesmanager/core/business/tax/service/TaxClassService.java
new file mode 100644
index 0000000..988e347
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/tax/service/TaxClassService.java
@@ -0,0 +1,19 @@
+package com.salesmanager.core.business.tax.service;
+
+import java.util.List;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.tax.model.taxclass.TaxClass;
+
+public interface TaxClassService extends SalesManagerEntityService<Long, TaxClass> {
+
+ public List<TaxClass> listByStore(MerchantStore store) throws ServiceException;
+
+ TaxClass getByCode(String code) throws ServiceException;
+
+ TaxClass getByCode(String code, MerchantStore store)
+ throws ServiceException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/tax/service/TaxClassServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/tax/service/TaxClassServiceImpl.java
new file mode 100644
index 0000000..7505048
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/tax/service/TaxClassServiceImpl.java
@@ -0,0 +1,56 @@
+package com.salesmanager.core.business.tax.service;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.tax.dao.taxclass.TaxClassDao;
+import com.salesmanager.core.business.tax.model.taxclass.TaxClass;
+
+@Service("taxClassService")
+public class TaxClassServiceImpl extends SalesManagerEntityServiceImpl<Long, TaxClass>
+ implements TaxClassService {
+
+ private TaxClassDao taxClassDao;
+
+ @Autowired
+ public TaxClassServiceImpl(TaxClassDao taxClassDao) {
+ super(taxClassDao);
+
+ this.taxClassDao = taxClassDao;
+ }
+
+ @Override
+ public List<TaxClass> listByStore(MerchantStore store) throws ServiceException {
+ return taxClassDao.listByStore(store);
+ }
+
+ @Override
+ public TaxClass getByCode(String code) throws ServiceException {
+ return taxClassDao.getByCode(code);
+ }
+
+ @Override
+ public TaxClass getByCode(String code, MerchantStore store) throws ServiceException {
+ return taxClassDao.getByCode(code, store);
+ }
+
+ @Override
+ public void delete(TaxClass taxClass) throws ServiceException {
+
+ TaxClass t = this.getById(taxClass.getId());
+ super.delete(t);
+
+ }
+
+ @Override
+ public TaxClass getById(Long id) {
+ return taxClassDao.getById(id);
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/tax/service/TaxRateService.java b/sm-core/src/main/java/com/salesmanager/core/business/tax/service/TaxRateService.java
new file mode 100644
index 0000000..db7e9af
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/tax/service/TaxRateService.java
@@ -0,0 +1,34 @@
+package com.salesmanager.core.business.tax.service;
+
+import java.util.List;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.core.business.tax.model.taxclass.TaxClass;
+import com.salesmanager.core.business.tax.model.taxrate.TaxRate;
+
+public interface TaxRateService extends SalesManagerEntityService<Long, TaxRate> {
+
+ public List<TaxRate> listByStore(MerchantStore store) throws ServiceException;
+
+ List<TaxRate> listByCountryZoneAndTaxClass(Country country, Zone zone,
+ TaxClass taxClass, MerchantStore store, Language language)
+ throws ServiceException;
+
+ List<TaxRate> listByCountryStateProvinceAndTaxClass(Country country,
+ String stateProvince, TaxClass taxClass, MerchantStore store,
+ Language language) throws ServiceException;
+
+ TaxRate getByCode(String code, MerchantStore store)
+ throws ServiceException;
+
+ List<TaxRate> listByStore(MerchantStore store, Language language)
+ throws ServiceException;
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/tax/service/TaxRateServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/tax/service/TaxRateServiceImpl.java
new file mode 100644
index 0000000..be56d0b
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/tax/service/TaxRateServiceImpl.java
@@ -0,0 +1,70 @@
+package com.salesmanager.core.business.tax.service;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.core.business.tax.dao.taxrate.TaxRateDao;
+import com.salesmanager.core.business.tax.model.taxclass.TaxClass;
+import com.salesmanager.core.business.tax.model.taxrate.TaxRate;
+
+@Service("taxRateService")
+public class TaxRateServiceImpl extends SalesManagerEntityServiceImpl<Long, TaxRate>
+ implements TaxRateService {
+
+ private TaxRateDao taxRateDao;
+
+ @Autowired
+ public TaxRateServiceImpl(TaxRateDao taxRateDao) {
+ super(taxRateDao);
+
+ this.taxRateDao = taxRateDao;
+ }
+
+ @Override
+ public List<TaxRate> listByStore(MerchantStore store)
+ throws ServiceException {
+ return taxRateDao.listByStore(store);
+ }
+
+ @Override
+ public List<TaxRate> listByStore(MerchantStore store, Language language)
+ throws ServiceException {
+ return taxRateDao.listByStore(store, language);
+ }
+
+
+ @Override
+ public TaxRate getByCode(String code, MerchantStore store)
+ throws ServiceException {
+ return taxRateDao.getByCode(code,store);
+ }
+
+ @Override
+ public List<TaxRate> listByCountryZoneAndTaxClass(Country country, Zone zone, TaxClass taxClass, MerchantStore store, Language language) throws ServiceException {
+ return taxRateDao.listByCountryZoneAndTaxClass(country, zone, taxClass, store, language);
+ }
+
+ @Override
+ public List<TaxRate> listByCountryStateProvinceAndTaxClass(Country country, String stateProvince, TaxClass taxClass, MerchantStore store, Language language) throws ServiceException {
+ return taxRateDao.listByCountryStateProvinceAndTaxClass(country, stateProvince, taxClass, store, language);
+ }
+
+ @Override
+ public void delete(TaxRate taxRate) throws ServiceException {
+
+ TaxRate t = this.getById(taxRate.getId());
+ super.delete(t);
+
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/tax/service/TaxService.java b/sm-core/src/main/java/com/salesmanager/core/business/tax/service/TaxService.java
new file mode 100644
index 0000000..15d3ca3
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/tax/service/TaxService.java
@@ -0,0 +1,48 @@
+package com.salesmanager.core.business.tax.service;
+
+import java.util.List;
+import java.util.Locale;
+
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.OrderSummary;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.tax.model.TaxConfiguration;
+import com.salesmanager.core.business.tax.model.TaxItem;
+
+
+public interface TaxService {
+
+ /**
+ * Retrieves tax configurations (TaxConfiguration) for a given MerchantStore
+ * @param store
+ * @return
+ * @throws ServiceException
+ */
+ TaxConfiguration getTaxConfiguration(MerchantStore store)
+ throws ServiceException;
+
+ /**
+ * Saves ShippingConfiguration to MerchantConfiguration table
+ * @param shippingConfiguration
+ * @param store
+ * @throws ServiceException
+ */
+ void saveTaxConfiguration(TaxConfiguration shippingConfiguration,
+ MerchantStore store) throws ServiceException;
+
+ /**
+ * Calculates tax over an OrderSummary
+ * @param orderSummary
+ * @param customer
+ * @param store
+ * @param locale
+ * @return
+ * @throws ServiceException
+ */
+ List<TaxItem> calculateTax(OrderSummary orderSummary, Customer customer,
+ MerchantStore store, Language language) throws ServiceException;
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/tax/service/TaxServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/tax/service/TaxServiceImpl.java
new file mode 100644
index 0000000..1671534
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/tax/service/TaxServiceImpl.java
@@ -0,0 +1,305 @@
+package com.salesmanager.core.business.tax.service;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+import org.apache.commons.lang3.StringUtils;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.common.model.Billing;
+import com.salesmanager.core.business.common.model.Delivery;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.OrderSummary;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.language.service.LanguageService;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.core.business.shipping.model.ShippingSummary;
+import com.salesmanager.core.business.shipping.service.ShippingService;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartItem;
+import com.salesmanager.core.business.system.model.MerchantConfiguration;
+import com.salesmanager.core.business.system.service.MerchantConfigurationService;
+import com.salesmanager.core.business.tax.model.TaxBasisCalculation;
+import com.salesmanager.core.business.tax.model.TaxConfiguration;
+import com.salesmanager.core.business.tax.model.TaxItem;
+import com.salesmanager.core.business.tax.model.taxclass.TaxClass;
+import com.salesmanager.core.business.tax.model.taxrate.TaxRate;
+
+@Service("taxService")
+public class TaxServiceImpl
+ implements TaxService {
+
+ private final static String TAX_CONFIGURATION = "TAX_CONFIG";
+ private final static String DEFAULT_TAX_CLASS = "DEFAULT";
+
+ @Autowired
+ private MerchantConfigurationService merchantConfigurationService;
+
+ @Autowired
+ private TaxRateService taxRateService;
+
+ @Autowired
+ private LanguageService languageService;
+
+ @Autowired
+ private ShippingService shippingService;
+
+ @Autowired
+ private TaxClassService taxClassService;
+
+ @Override
+ public TaxConfiguration getTaxConfiguration(MerchantStore store) throws ServiceException {
+
+
+
+ MerchantConfiguration configuration = merchantConfigurationService.getMerchantConfiguration(TAX_CONFIGURATION, store);
+ TaxConfiguration taxConfiguration = null;
+ if(configuration!=null) {
+ String value = configuration.getValue();
+
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ taxConfiguration = mapper.readValue(value, TaxConfiguration.class);
+ } catch(Exception e) {
+ throw new ServiceException("Cannot parse json string " + value);
+ }
+ }
+ return taxConfiguration;
+ }
+
+
+ @Override
+ public void saveTaxConfiguration(TaxConfiguration shippingConfiguration, MerchantStore store) throws ServiceException {
+
+ MerchantConfiguration configuration = merchantConfigurationService.getMerchantConfiguration(TAX_CONFIGURATION, store);
+
+ if(configuration==null) {
+ configuration = new MerchantConfiguration();
+ configuration.setMerchantStore(store);
+ configuration.setKey(TAX_CONFIGURATION);
+ }
+
+ String value = shippingConfiguration.toJSONString();
+ configuration.setValue(value);
+ merchantConfigurationService.saveOrUpdate(configuration);
+
+ }
+
+ @Override
+ public List<TaxItem> calculateTax(OrderSummary orderSummary, Customer customer, MerchantStore store, Language language) throws ServiceException {
+
+
+ if(customer==null) {
+ return null;
+ }
+
+ List<ShoppingCartItem> items = orderSummary.getProducts();
+
+ List<TaxItem> taxLines = new ArrayList<TaxItem>();
+
+ if(items==null) {
+ return taxLines;
+ }
+
+ //determine tax calculation basis
+ TaxConfiguration taxConfiguration = this.getTaxConfiguration(store);
+ if(taxConfiguration==null) {
+ taxConfiguration = new TaxConfiguration();
+ taxConfiguration.setTaxBasisCalculation(TaxBasisCalculation.SHIPPINGADDRESS);
+ }
+
+ Country country = customer.getBilling().getCountry();
+ Zone zone = customer.getBilling().getZone();
+ String stateProvince = customer.getBilling().getState();
+
+ TaxBasisCalculation taxBasisCalculation = taxConfiguration.getTaxBasisCalculation();
+ if(taxBasisCalculation.name().equals(TaxBasisCalculation.SHIPPINGADDRESS)){
+ Delivery shipping = customer.getDelivery();
+ if(shipping!=null) {
+ country = shipping.getCountry();
+ zone = shipping.getZone();
+ stateProvince = shipping.getState();
+ }
+ } else if(taxBasisCalculation.name().equals(TaxBasisCalculation.BILLINGADDRESS)){
+ Billing billing = customer.getBilling();
+ if(billing!=null) {
+ country = billing.getCountry();
+ zone = billing.getZone();
+ stateProvince = billing.getState();
+ }
+ } else if(taxBasisCalculation.name().equals(TaxBasisCalculation.STOREADDRESS)){
+ country = store.getCountry();
+ zone = store.getZone();
+ stateProvince = store.getStorestateprovince();
+ }
+
+ //check other conditions
+ //do not collect tax on other provinces of same country
+ if(!taxConfiguration.isCollectTaxIfDifferentProvinceOfStoreCountry()) {
+ if((zone!=null && store.getZone()!=null) && (zone.getId().longValue() != store.getZone().getId().longValue())) {
+ return null;
+ }
+ if(!StringUtils.isBlank(stateProvince)) {
+ if(store.getZone()!=null) {
+ if(!store.getZone().getName().equals(stateProvince)) {
+ return null;
+ }
+ }
+ else if(!StringUtils.isBlank(store.getStorestateprovince())) {
+
+ if(!store.getStorestateprovince().equals(stateProvince)) {
+ return null;
+ }
+ }
+ }
+ }
+
+ //collect tax in different countries
+ if(taxConfiguration.isCollectTaxIfDifferentCountryOfStoreCountry()) {
+ //use store country
+ country = store.getCountry();
+ zone = store.getZone();
+ stateProvince = store.getStorestateprovince();
+ }
+
+ Map<Long,TaxClass> taxClasses = new HashMap<Long,TaxClass>();
+
+ //put items in a map by tax class id
+ Map<Long,BigDecimal> taxClassAmountMap = new HashMap<Long,BigDecimal>();
+ for(ShoppingCartItem item : items) {
+
+ BigDecimal itemPrice = item.getItemPrice();
+ TaxClass taxClass = item.getProduct().getTaxClass();
+ int quantity = item.getQuantity();
+ itemPrice = itemPrice.multiply(new BigDecimal(quantity));
+ if(taxClass==null) {
+ taxClass = taxClassService.getByCode(DEFAULT_TAX_CLASS);
+ }
+ BigDecimal subTotal = taxClassAmountMap.get(taxClass.getId());
+ if(subTotal==null) {
+ subTotal = new BigDecimal(0);
+ subTotal.setScale(2, RoundingMode.HALF_UP);
+ }
+
+ subTotal = subTotal.add(itemPrice);
+ taxClassAmountMap.put(taxClass.getId(), subTotal);
+ taxClasses.put(taxClass.getId(), taxClass);
+
+ }
+
+ //tax on shipping ?
+ //ShippingConfiguration shippingConfiguration = shippingService.getShippingConfiguration(store);
+
+ /** always calculate tax on shipping **/
+ //if(shippingConfiguration!=null) {
+ //if(shippingConfiguration.isTaxOnShipping()){
+ //use default tax class for shipping
+ TaxClass defaultTaxClass = taxClassService.getByCode(TaxClass.DEFAULT_TAX_CLASS);
+ //taxClasses.put(defaultTaxClass.getId(), defaultTaxClass);
+ BigDecimal amnt = taxClassAmountMap.get(defaultTaxClass.getId());
+ if(amnt==null) {
+ amnt = new BigDecimal(0);
+ amnt.setScale(2, RoundingMode.HALF_UP);
+ }
+ ShippingSummary shippingSummary = orderSummary.getShippingSummary();
+ if(shippingSummary!=null && shippingSummary.getShipping()!=null && shippingSummary.getShipping().doubleValue()>0) {
+ amnt = amnt.add(shippingSummary.getShipping());
+ if(shippingSummary.getHandling()!=null && shippingSummary.getHandling().doubleValue()>0) {
+ amnt = amnt.add(shippingSummary.getHandling());
+ }
+ }
+ taxClassAmountMap.put(defaultTaxClass.getId(), amnt);
+ //}
+ //}
+
+
+ List<TaxItem> taxItems = new ArrayList<TaxItem>();
+
+ //iterate through the tax class and get appropriate rates
+ for(Long taxClassId : taxClassAmountMap.keySet()) {
+
+ //get taxRate by tax class
+ List<TaxRate> taxRates = null;
+ if(!StringUtils.isBlank(stateProvince)&& zone==null) {
+ taxRates = taxRateService.listByCountryStateProvinceAndTaxClass(country, stateProvince, taxClasses.get(taxClassId), store, language);
+ } else {
+ taxRates = taxRateService.listByCountryZoneAndTaxClass(country, zone, taxClasses.get(taxClassId), store, language);
+ }
+
+ if(taxRates==null || taxRates.size()==0){
+ continue;
+ }
+ BigDecimal taxedItemValue = null;
+ BigDecimal totalTaxedItemValue = new BigDecimal(0);
+ totalTaxedItemValue.setScale(2, RoundingMode.HALF_UP);
+ BigDecimal beforeTaxeAmount = taxClassAmountMap.get(taxClassId);
+ for(TaxRate taxRate : taxRates) {
+
+ double taxRateDouble = taxRate.getTaxRate().doubleValue();//5% ... 8% ...
+
+
+ if(taxRate.isPiggyback()) {//(compound)
+ if(totalTaxedItemValue.doubleValue()>0) {
+ beforeTaxeAmount = totalTaxedItemValue;
+ }
+ } //else just use nominal taxing (combine)
+
+ double value = (beforeTaxeAmount.doubleValue() * taxRateDouble)/100;
+ double roundedValue = new BigDecimal(value).setScale(2, RoundingMode.HALF_UP).doubleValue();
+ taxedItemValue = new BigDecimal(roundedValue).setScale(2, RoundingMode.HALF_UP);
+ totalTaxedItemValue = beforeTaxeAmount.add(taxedItemValue);
+
+ TaxItem taxItem = new TaxItem();
+ taxItem.setItemPrice(taxedItemValue);
+ taxItem.setLabel(taxRate.getDescriptions().get(0).getName());
+ taxItem.setTaxRate(taxRate);
+ taxItems.add(taxItem);
+
+ }
+
+ }
+
+
+
+ Map<String,TaxItem> taxItemsMap = new TreeMap<String,TaxItem>();
+ //consolidate tax rates of same code
+ for(TaxItem taxItem : taxItems) {
+
+ TaxRate taxRate = taxItem.getTaxRate();
+ if(!taxItemsMap.containsKey(taxRate.getCode())) {
+ taxItemsMap.put(taxRate.getCode(), taxItem);
+ }
+
+ TaxItem item = taxItemsMap.get(taxRate.getCode());
+ BigDecimal amount = item.getItemPrice();
+ amount = amount.add(taxItem.getItemPrice());
+
+ }
+
+ if(taxItemsMap.size()==0) {
+ return null;
+ }
+
+
+ @SuppressWarnings("rawtypes")
+ Collection<TaxItem> values = taxItemsMap.values();
+
+
+ @SuppressWarnings("unchecked")
+ List<TaxItem> list = new ArrayList<TaxItem>(values);
+ return list;
+
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/user/dao/GroupDao.java b/sm-core/src/main/java/com/salesmanager/core/business/user/dao/GroupDao.java
new file mode 100755
index 0000000..39b287b
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/user/dao/GroupDao.java
@@ -0,0 +1,17 @@
+package com.salesmanager.core.business.user.dao;
+
+import java.util.List;
+import java.util.Set;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.user.model.Group;
+import com.salesmanager.core.business.user.model.GroupType;
+
+public interface GroupDao extends SalesManagerEntityDao<Integer, Group> {
+
+ List<Group> getGroupsListBypermissions(Set<Integer> ids);
+
+ List<Group> listGroup(GroupType groupType);
+
+ List<Group> listGroupByIds(Set<Integer> ids);
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/user/dao/GroupDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/user/dao/GroupDaoImpl.java
new file mode 100755
index 0000000..4f7582e
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/user/dao/GroupDaoImpl.java
@@ -0,0 +1,77 @@
+package com.salesmanager.core.business.user.dao;
+
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.Query;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.user.model.Group;
+import com.salesmanager.core.business.user.model.GroupType;
+import com.salesmanager.core.business.user.model.QGroup;
+
+@Repository("groupDao")
+public class GroupDaoImpl extends SalesManagerEntityDaoImpl<Integer, Group> implements
+ GroupDao {
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public List<Group> getGroupsListBypermissions(Set permissionIds) {
+ StringBuilder qs = new StringBuilder();
+ qs.append("select g from Group as g ");
+ qs.append("join fetch g.permissions perms ");
+ qs.append("where perms.id in (:cid) ");
+
+
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+ q.setParameter("cid", permissionIds);
+
+ @SuppressWarnings("unchecked")
+ List<Group> groups = q.getResultList();
+
+
+ return groups;
+ }
+
+ @Override
+ public List<Group> listGroupByIds(Set<Integer> ids) {
+
+ StringBuilder qs = new StringBuilder();
+ qs.append("select distinct g from Group as g ");
+ qs.append("join fetch g.permissions perms ");
+ qs.append("where g.id in (:gid) ");
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+ q.setParameter("gid", ids);
+
+ @SuppressWarnings("unchecked")
+ List<Group> groups = q.getResultList();
+
+
+ return groups;
+
+ }
+
+ @Override
+ public List<Group> listGroup(GroupType groupType) {
+ QGroup qGroup = QGroup.group;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qGroup)
+ .where(qGroup.groupType.eq(groupType))
+ .orderBy(qGroup.id.asc());
+
+ return query.listDistinct(qGroup);
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/user/dao/PermissionDao.java b/sm-core/src/main/java/com/salesmanager/core/business/user/dao/PermissionDao.java
new file mode 100755
index 0000000..9c86310
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/user/dao/PermissionDao.java
@@ -0,0 +1,23 @@
+package com.salesmanager.core.business.user.dao;
+
+import java.util.List;
+import java.util.Set;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.user.model.Permission;
+import com.salesmanager.core.business.user.model.PermissionCriteria;
+import com.salesmanager.core.business.user.model.PermissionList;
+
+public interface PermissionDao extends SalesManagerEntityDao<Integer, Permission> {
+
+ List<Permission> listPermission();
+
+ Permission getById(Integer permissionId);
+
+ List<Permission> getPermissionsListByGroups(Set permissionIds);
+
+ PermissionList listByCriteria(PermissionCriteria criteria);
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/user/dao/PermissionDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/user/dao/PermissionDaoImpl.java
new file mode 100755
index 0000000..115d119
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/user/dao/PermissionDaoImpl.java
@@ -0,0 +1,140 @@
+package com.salesmanager.core.business.user.dao;
+
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+
+import javax.persistence.Query;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.ProductList;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.user.model.Permission;
+import com.salesmanager.core.business.user.model.PermissionCriteria;
+import com.salesmanager.core.business.user.model.PermissionList;
+import com.salesmanager.core.business.user.model.QPermission;
+
+@Repository("permissionDao")
+public class PermissionDaoImpl extends SalesManagerEntityDaoImpl<Integer, Permission> implements
+ PermissionDao {
+
+ @Override
+ public List<Permission> listPermission() {
+ QPermission qPermission = QPermission.permission;
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qPermission)
+ .orderBy(qPermission.id.asc());
+
+ return query.listDistinct(qPermission);
+ }
+
+ @Override
+ public Permission getById(Integer permissionId) {
+ QPermission qPermission = QPermission.permission;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qPermission)
+ .where(qPermission.id.eq(permissionId));
+
+ return query.uniqueResult(qPermission);
+ }
+
+
+ @Override
+ public List<Permission> getPermissionsListByGroups(Set groupIds) {
+ StringBuilder qs = new StringBuilder();
+ qs.append("select distinct p from Permission as p ");
+ qs.append("join fetch p.groups grous ");
+ qs.append("where grous.id in (:cid)");
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+ q.setParameter("cid", groupIds);
+
+ @SuppressWarnings("unchecked")
+ List<Permission> permissions = q.getResultList();
+
+ return permissions;
+ }
+
+ @Override
+ public PermissionList listByCriteria(PermissionCriteria criteria) {
+ PermissionList permissionList = new PermissionList();
+
+
+ StringBuilder countBuilderSelect = new StringBuilder();
+ countBuilderSelect.append("select count(p) from Permission as p");
+
+ StringBuilder countBuilderWhere = new StringBuilder();
+
+
+ if(criteria.getGroupIds()!=null && criteria.getGroupIds().size()>0) {
+ countBuilderSelect.append(" INNER JOIN p.groups grous");
+ countBuilderWhere.append(" where grous.id in (:cid)");
+ }
+
+
+ Query countQ = super.getEntityManager().createQuery(
+ countBuilderSelect.toString() + countBuilderWhere.toString());
+
+ if(criteria.getGroupIds()!=null && criteria.getGroupIds().size()>0) {
+ countQ.setParameter("cid", criteria.getGroupIds());
+ }
+
+
+ Number count = (Number) countQ.getSingleResult ();
+
+ permissionList.setTotalCount(count.intValue());
+
+ if(count.intValue()==0)
+ return permissionList;
+
+
+ StringBuilder qs = new StringBuilder();
+ qs.append("select p from Permission as p ");
+ qs.append("join fetch p.groups grous ");
+
+ if(criteria.getGroupIds()!=null && criteria.getGroupIds().size()>0) {
+ qs.append(" where grous.id in (:cid)");
+ }
+
+ qs.append(" order by p.id asc ");
+
+ String hql = qs.toString();
+ Query q = super.getEntityManager().createQuery(hql);
+
+
+ if(criteria.getGroupIds()!=null && criteria.getGroupIds().size()>0) {
+ q.setParameter("cid", criteria.getGroupIds());
+ }
+
+ if(criteria.getMaxCount()>0) {
+
+
+ q.setFirstResult(criteria.getStartIndex());
+ if(criteria.getMaxCount()<count.intValue()) {
+ q.setMaxResults(criteria.getMaxCount());
+ permissionList.setTotalCount(criteria.getMaxCount());
+ }
+ else {
+ q.setMaxResults(count.intValue());
+ permissionList.setTotalCount(count.intValue());
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ List<Permission> permissions = q.getResultList();
+ permissionList.setPermissions(permissions);
+
+ return permissionList;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/user/dao/UserDao.java b/sm-core/src/main/java/com/salesmanager/core/business/user/dao/UserDao.java
new file mode 100755
index 0000000..fd0928c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/user/dao/UserDao.java
@@ -0,0 +1,19 @@
+package com.salesmanager.core.business.user.dao;
+
+import java.util.List;
+
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDao;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.user.model.User;
+
+public interface UserDao extends SalesManagerEntityDao<Long, User> {
+
+ User getByUserName(String userName);
+
+ List<User> listUser();
+
+ List<User> listUserByStore(MerchantStore store);
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/user/dao/UserDaoImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/user/dao/UserDaoImpl.java
new file mode 100755
index 0000000..0aad078
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/user/dao/UserDaoImpl.java
@@ -0,0 +1,90 @@
+package com.salesmanager.core.business.user.dao;
+
+import java.util.List;
+
+import org.springframework.stereotype.Repository;
+
+import com.mysema.query.jpa.JPQLQuery;
+import com.mysema.query.jpa.impl.JPAQuery;
+import com.salesmanager.core.business.generic.dao.SalesManagerEntityDaoImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.user.model.QGroup;
+import com.salesmanager.core.business.user.model.QUser;
+import com.salesmanager.core.business.user.model.User;
+
+@Repository("userDao")
+public class UserDaoImpl extends SalesManagerEntityDaoImpl<Long, User> implements
+ UserDao {
+
+ @Override
+ public User getByUserName(String userName) {
+
+
+ QUser qUser = QUser.user;
+ QGroup qGroup = QGroup.group;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qUser)
+ .innerJoin(qUser.groups, qGroup).fetch()
+ .innerJoin(qUser.merchantStore).fetch()
+ .leftJoin(qUser.defaultLanguage).fetch()
+ .where(qUser.adminName.eq(userName));
+
+
+
+ User user = query.uniqueResult(qUser);
+ return user;
+ }
+
+ @Override
+ public User getById(Long id) {
+
+
+ QUser qUser = QUser.user;
+ QGroup qGroup = QGroup.group;
+
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qUser)
+ .innerJoin(qUser.groups, qGroup).fetch()
+ .innerJoin(qUser.merchantStore).fetch()
+ .leftJoin(qUser.defaultLanguage).fetch()
+ .where(qUser.id.eq(id));
+
+
+
+ User user = query.uniqueResult(qUser);
+ return user;
+ }
+
+ @Override
+ public List<User> listUser() {
+ QUser qUser = QUser.user;
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qUser)
+ .innerJoin(qUser.groups).fetch()
+ .innerJoin(qUser.merchantStore).fetch()
+ .leftJoin(qUser.defaultLanguage).fetch()
+ .orderBy(qUser.id.asc());
+
+ return query.listDistinct(qUser);
+ }
+
+ @Override
+ public List<User> listUserByStore(MerchantStore store) {
+ QUser qUser = QUser.user;
+ JPQLQuery query = new JPAQuery (getEntityManager());
+
+ query.from(qUser)
+ .innerJoin(qUser.groups).fetch()
+ .innerJoin(qUser.merchantStore).fetch()
+ .leftJoin(qUser.defaultLanguage).fetch()
+ .orderBy(qUser.id.asc())
+ .where(qUser.merchantStore.id.eq(store.getId()));
+
+ return query.listDistinct(qUser);
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/user/model/Group.java b/sm-core/src/main/java/com/salesmanager/core/business/user/model/Group.java
new file mode 100755
index 0000000..82077e9
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/user/model/Group.java
@@ -0,0 +1,112 @@
+package com.salesmanager.core.business.user.model;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.EnumType;
+import javax.persistence.Enumerated;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.ManyToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+import org.hibernate.validator.constraints.NotEmpty;
+
+import com.salesmanager.core.business.common.model.audit.AuditListener;
+import com.salesmanager.core.business.common.model.audit.AuditSection;
+import com.salesmanager.core.business.common.model.audit.Auditable;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.constants.SchemaConstant;
+
+
+@Entity
+@EntityListeners(value = AuditListener.class)
+@Table(name = "SM_GROUP", schema=SchemaConstant.SALESMANAGER_SCHEMA)
+public class Group extends SalesManagerEntity<Integer, Group> implements Auditable {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 3786127652573709701L;
+ @Id
+ @Column(name = "GROUP_ID", unique=true, nullable=false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "GROUP_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Integer id;
+
+ public Group() {
+
+ }
+
+ @Column (name ="GROUP_TYPE")
+ @Enumerated(value = EnumType.STRING)
+ private GroupType groupType;
+
+ @NotEmpty
+ @Column(name="GROUP_NAME", unique=true)
+ private String groupName;
+
+ public Group(String groupName) {
+ this.groupName = groupName;
+ }
+
+ @ManyToMany(mappedBy = "groups")
+ private Set<Permission> permissions = new HashSet<Permission>();
+
+ public Set<Permission> getPermissions() {
+ return permissions;
+ }
+
+ public void setPermissions(Set<Permission> permissions) {
+ this.permissions = permissions;
+ }
+
+ @Embedded
+ private AuditSection auditSection = new AuditSection();
+
+
+ @Override
+ public AuditSection getAuditSection() {
+ return this.auditSection;
+ }
+
+ @Override
+ public void setAuditSection(AuditSection audit) {
+ this.auditSection = audit;
+ }
+
+ @Override
+ public Integer getId() {
+ return this.id;
+ }
+
+ @Override
+ public void setId(Integer id) {
+ this.id = id;
+ }
+
+ public String getGroupName() {
+ return groupName;
+ }
+
+ public void setGroupName(String groupName) {
+ this.groupName = groupName;
+ }
+
+ public void setGroupType(GroupType groupType) {
+ this.groupType = groupType;
+ }
+
+ public GroupType getGroupType() {
+ return groupType;
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/user/model/GroupType.java b/sm-core/src/main/java/com/salesmanager/core/business/user/model/GroupType.java
new file mode 100644
index 0000000..2bcbfea
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/user/model/GroupType.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.business.user.model;
+
+public enum GroupType {
+
+ ADMIN, CUSTOMER
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/user/model/Permission.java b/sm-core/src/main/java/com/salesmanager/core/business/user/model/Permission.java
new file mode 100755
index 0000000..d5e306e
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/user/model/Permission.java
@@ -0,0 +1,116 @@
+package com.salesmanager.core.business.user.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+
+import org.hibernate.annotations.Cascade;
+import org.hibernate.validator.constraints.NotEmpty;
+
+import com.salesmanager.core.business.common.model.audit.AuditListener;
+import com.salesmanager.core.business.common.model.audit.AuditSection;
+import com.salesmanager.core.business.common.model.audit.Auditable;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@EntityListeners(value = AuditListener.class)
+@Table(name = "PERMISSION", schema=SchemaConstant.SALESMANAGER_SCHEMA)
+public class Permission extends SalesManagerEntity<Integer, Permission> implements Auditable {
+
+
+
+ private static final long serialVersionUID = 813468140197420748L;
+
+ @Id
+ @Column(name = "PERMISSION_ID", unique=true, nullable=false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "PERMISSION_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Integer id;
+
+ public Permission() {
+
+ }
+
+ public Permission(String permissionName) {
+ this.permissionName = permissionName;
+ }
+
+
+ @NotEmpty
+ @Column(name="PERMISSION_NAME", unique=true)
+ private String permissionName;
+
+ @ManyToMany(fetch=FetchType.LAZY, cascade = {CascadeType.REFRESH})
+ @JoinTable(name = "PERMISSION_GROUP", schema=SchemaConstant.SALESMANAGER_SCHEMA, joinColumns = {
+ @JoinColumn(name = "PERMISSION_ID", nullable = false, updatable = false) }
+ ,
+ inverseJoinColumns = { @JoinColumn(name = "GROUP_ID",
+ nullable = false, updatable = false) }
+ )
+ @Cascade({
+ org.hibernate.annotations.CascadeType.DETACH,
+ org.hibernate.annotations.CascadeType.LOCK,
+ org.hibernate.annotations.CascadeType.REFRESH,
+ org.hibernate.annotations.CascadeType.REPLICATE
+
+ })
+ private List<Group> groups = new ArrayList<Group>();
+
+ @Embedded
+ private AuditSection auditSection = new AuditSection();
+
+
+ @Override
+ public Integer getId() {
+ return this.id;
+ }
+
+ @Override
+ public void setId(Integer id) {
+ this.id = id;
+
+ }
+
+ @Override
+ public AuditSection getAuditSection() {
+ return this.auditSection;
+ }
+
+ @Override
+ public void setAuditSection(AuditSection audit) {
+ this.auditSection = audit;
+
+ }
+
+ public String getPermissionName() {
+ return permissionName;
+ }
+
+ public void setPermissionName(String permissionName) {
+ this.permissionName = permissionName;
+ }
+
+ public void setGroups(List<Group> groups) {
+ this.groups = groups;
+ }
+
+ public List<Group> getGroups() {
+ return groups;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/user/model/PermissionCriteria.java b/sm-core/src/main/java/com/salesmanager/core/business/user/model/PermissionCriteria.java
new file mode 100644
index 0000000..7717f94
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/user/model/PermissionCriteria.java
@@ -0,0 +1,54 @@
+package com.salesmanager.core.business.user.model;
+
+import java.util.List;
+import java.util.Set;
+
+import com.salesmanager.core.business.common.model.Criteria;
+
+public class PermissionCriteria extends Criteria {
+
+
+ private String permissionName;
+
+
+ private Boolean available = null;
+
+ private Set<Integer> groupIds;
+
+ private List<String> availabilities;
+
+
+ public List<String> getAvailabilities() {
+ return availabilities;
+ }
+
+ public void setAvailabilities(List<String> availabilities) {
+ this.availabilities = availabilities;
+ }
+
+ public Boolean getAvailable() {
+ return available;
+ }
+
+ public void setAvailable(Boolean available) {
+ this.available = available;
+ }
+
+ public String getPermissionName() {
+ return permissionName;
+ }
+
+ public void setPermissionName(String permissionName) {
+ this.permissionName = permissionName;
+ }
+
+ public Set<Integer> getGroupIds() {
+ return groupIds;
+ }
+
+ public void setGroupIds(Set<Integer> groupIds) {
+ this.groupIds = groupIds;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/user/model/PermissionList.java b/sm-core/src/main/java/com/salesmanager/core/business/user/model/PermissionList.java
new file mode 100644
index 0000000..89f78f2
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/user/model/PermissionList.java
@@ -0,0 +1,26 @@
+package com.salesmanager.core.business.user.model;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+public class PermissionList implements Serializable {
+
+
+ private static final long serialVersionUID = -3122326940968441727L;
+ private int totalCount;
+ private List<Permission> permissions = new ArrayList<Permission>();
+ public int getTotalCount() {
+ return totalCount;
+ }
+ public void setTotalCount(int totalCount) {
+ this.totalCount = totalCount;
+ }
+ public List<Permission> getPermissions() {
+ return permissions;
+ }
+ public void setPermissions(List<Permission> permissions) {
+ this.permissions = permissions;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/user/model/User.java b/sm-core/src/main/java/com/salesmanager/core/business/user/model/User.java
new file mode 100755
index 0000000..d0df6f1
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/user/model/User.java
@@ -0,0 +1,298 @@
+package com.salesmanager.core.business.user.model;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Embedded;
+import javax.persistence.Entity;
+import javax.persistence.EntityListeners;
+import javax.persistence.FetchType;
+import javax.persistence.GeneratedValue;
+import javax.persistence.GenerationType;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+import javax.persistence.TableGenerator;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+
+import org.hibernate.annotations.Cascade;
+import org.hibernate.validator.constraints.Email;
+import org.hibernate.validator.constraints.NotEmpty;
+
+import com.salesmanager.core.business.common.model.audit.AuditListener;
+import com.salesmanager.core.business.common.model.audit.AuditSection;
+import com.salesmanager.core.business.generic.model.SalesManagerEntity;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.common.model.audit.Auditable;
+import com.salesmanager.core.constants.SchemaConstant;
+
+@Entity
+@EntityListeners(value = AuditListener.class)
+@Table(name = "USER", schema=SchemaConstant.SALESMANAGER_SCHEMA)
+public class User extends SalesManagerEntity<Long, User> implements Auditable {
+
+
+ private static final long serialVersionUID = 5401059537544058710L;
+
+ @Id
+ @Column(name = "USER_ID", unique=true, nullable=false)
+ @TableGenerator(name = "TABLE_GEN", table = "SM_SEQUENCER", pkColumnName = "SEQ_NAME", valueColumnName = "SEQ_COUNT", pkColumnValue = "USER_SEQ_NEXT_VAL")
+ @GeneratedValue(strategy = GenerationType.TABLE, generator = "TABLE_GEN")
+ private Long id;
+
+ public User() {
+
+ }
+
+ public User(String userName,String password, String email) {
+
+ this.adminName = userName;
+ this.adminPassword = password;
+ this.adminEmail = email;
+ }
+
+ @NotEmpty
+ @Column(name="ADMIN_NAME", length=100, unique=true)
+ private String adminName;
+
+ @ManyToMany(fetch=FetchType.LAZY, cascade = {CascadeType.REFRESH})
+ @JoinTable(name = "USER_GROUP", schema=SchemaConstant.SALESMANAGER_SCHEMA, joinColumns = {
+ @JoinColumn(name = "USER_ID", nullable = false, updatable = false) }
+ ,
+ inverseJoinColumns = { @JoinColumn(name = "GROUP_ID",
+ nullable = false, updatable = false) }
+ )
+ @Cascade({
+ org.hibernate.annotations.CascadeType.DETACH,
+ org.hibernate.annotations.CascadeType.LOCK,
+ org.hibernate.annotations.CascadeType.REFRESH,
+ org.hibernate.annotations.CascadeType.REPLICATE
+
+ })
+ private List<Group> groups = new ArrayList<Group>();
+
+ @NotEmpty
+ @Email
+ @Column(name="ADMIN_EMAIL")
+ private String adminEmail;
+
+ @NotEmpty
+ @Column(name="ADMIN_PASSWORD", length=50)
+ private String adminPassword;
+
+ @ManyToOne(fetch = FetchType.LAZY)
+ @JoinColumn(name="MERCHANT_ID", nullable=false)
+ private MerchantStore merchantStore;
+
+
+ @Column(name="ADMIN_FIRST_NAME")
+ private String firstName;
+
+ @Column(name="ACTIVE")
+ private boolean active = true;
+
+
+ @Column(name="ADMIN_LAST_NAME")
+ private String lastName;
+
+ @ManyToOne(fetch = FetchType.LAZY, targetEntity = Language.class)
+ @JoinColumn(name = "LANGUAGE_ID")
+ private Language defaultLanguage;
+
+
+ @Column(name="ADMIN_Q1")
+ private String question1;
+
+ @Column(name="ADMIN_Q2")
+ private String question2;
+
+ @Column(name="ADMIN_Q3")
+ private String question3;
+
+ @Column(name="ADMIN_A1")
+ private String answer1;
+
+ @Column(name="ADMIN_A2")
+ private String answer2;
+
+ @Column(name="ADMIN_A3")
+ private String answer3;
+
+
+ @Embedded
+ private AuditSection auditSection = new AuditSection();
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column(name = "LAST_ACCESS")
+ private Date lastAccess;
+
+ @Temporal(TemporalType.TIMESTAMP)
+ @Column(name = "LOGIN_ACCESS")
+ private Date loginTime;
+
+ @Override
+ public Long getId() {
+ return this.id;
+ }
+
+ @Override
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ @Override
+ public AuditSection getAuditSection() {
+ return auditSection;
+ }
+
+ @Override
+ public void setAuditSection(AuditSection audit) {
+ auditSection = audit;
+
+ }
+
+ public String getAdminName() {
+ return adminName;
+ }
+
+ public void setAdminName(String adminName) {
+ this.adminName = adminName;
+ }
+
+ public String getAdminEmail() {
+ return adminEmail;
+ }
+
+ public void setAdminEmail(String adminEmail) {
+ this.adminEmail = adminEmail;
+ }
+
+ public String getAdminPassword() {
+ return adminPassword;
+ }
+
+ public void setAdminPassword(String adminPassword) {
+ this.adminPassword = adminPassword;
+ }
+
+ public String getFirstName() {
+ return firstName;
+ }
+
+ public void setFirstName(String firstName) {
+ this.firstName = firstName;
+ }
+
+ public String getLastName() {
+ return lastName;
+ }
+
+ public void setLastName(String lastName) {
+ this.lastName = lastName;
+ }
+
+ public Language getDefaultLanguage() {
+ return defaultLanguage;
+ }
+
+ public void setDefaultLanguage(Language defaultLanguage) {
+ this.defaultLanguage = defaultLanguage;
+ }
+
+ public String getQuestion1() {
+ return question1;
+ }
+
+ public void setQuestion1(String question1) {
+ this.question1 = question1;
+ }
+
+ public String getQuestion2() {
+ return question2;
+ }
+
+ public void setQuestion2(String question2) {
+ this.question2 = question2;
+ }
+
+ public String getQuestion3() {
+ return question3;
+ }
+
+ public void setQuestion3(String question3) {
+ this.question3 = question3;
+ }
+
+ public String getAnswer1() {
+ return answer1;
+ }
+
+ public void setAnswer1(String answer1) {
+ this.answer1 = answer1;
+ }
+
+ public String getAnswer2() {
+ return answer2;
+ }
+
+ public void setAnswer2(String answer2) {
+ this.answer2 = answer2;
+ }
+
+ public String getAnswer3() {
+ return answer3;
+ }
+
+ public void setAnswer3(String answer3) {
+ this.answer3 = answer3;
+ }
+
+ public void setGroups(List<Group> groups) {
+ this.groups = groups;
+ }
+
+ public List<Group> getGroups() {
+ return groups;
+ }
+
+ public MerchantStore getMerchantStore() {
+ return merchantStore;
+ }
+
+ public void setMerchantStore(MerchantStore merchantStore) {
+ this.merchantStore = merchantStore;
+ }
+
+ public void setActive(boolean active) {
+ this.active = active;
+ }
+
+ public boolean isActive() {
+ return active;
+ }
+
+ public void setLastAccess(Date lastAccess) {
+ this.lastAccess = lastAccess;
+ }
+
+ public Date getLastAccess() {
+ return lastAccess;
+ }
+
+ public void setLoginTime(Date loginTime) {
+ this.loginTime = loginTime;
+ }
+
+ public Date getLoginTime() {
+ return loginTime;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/user/service/GroupService.java b/sm-core/src/main/java/com/salesmanager/core/business/user/service/GroupService.java
new file mode 100755
index 0000000..26b0408
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/user/service/GroupService.java
@@ -0,0 +1,17 @@
+package com.salesmanager.core.business.user.service;
+
+import java.util.List;
+import java.util.Set;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.user.model.Group;
+import com.salesmanager.core.business.user.model.GroupType;
+
+public interface GroupService extends SalesManagerEntityService<Integer, Group> {
+
+
+ List<Group> listGroup(GroupType groupType) throws ServiceException;
+ List<Group> listGroupByIds(Set<Integer> ids) throws ServiceException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/user/service/GroupServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/user/service/GroupServiceImpl.java
new file mode 100755
index 0000000..87947ab
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/user/service/GroupServiceImpl.java
@@ -0,0 +1,52 @@
+package com.salesmanager.core.business.user.service;
+
+import java.util.List;
+import java.util.Set;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.user.dao.GroupDao;
+import com.salesmanager.core.business.user.model.Group;
+import com.salesmanager.core.business.user.model.GroupType;
+
+@Service("groupService")
+public class GroupServiceImpl extends
+ SalesManagerEntityServiceImpl<Integer, Group> implements GroupService {
+
+ GroupDao groupDao;
+
+
+ @Autowired
+ public GroupServiceImpl(GroupDao groupDao) {
+ super(groupDao);
+ this.groupDao = groupDao;
+
+ }
+
+
+
+
+
+
+ @Override
+ public List<Group> listGroup(GroupType groupType) throws ServiceException {
+ try {
+ return groupDao.listGroup(groupType);
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+ }
+
+ public List<Group> listGroupByIds(Set<Integer> ids) throws ServiceException {
+ try {
+ return groupDao.listGroupByIds(ids);
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/user/service/PermissionService.java b/sm-core/src/main/java/com/salesmanager/core/business/user/service/PermissionService.java
new file mode 100755
index 0000000..ec7e750
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/user/service/PermissionService.java
@@ -0,0 +1,32 @@
+package com.salesmanager.core.business.user.service;
+
+import java.util.List;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.user.model.Group;
+import com.salesmanager.core.business.user.model.Permission;
+import com.salesmanager.core.business.user.model.PermissionCriteria;
+import com.salesmanager.core.business.user.model.PermissionList;
+
+public interface PermissionService extends SalesManagerEntityService<Integer, Permission> {
+
+ List<Permission> getByName();
+
+ List<Permission> listPermission() throws ServiceException;
+
+ Permission getById(Integer permissionId);
+
+ void saveOrUpdate(Permission permission);
+
+// void deletePermission(Permission permission) throws ServiceException;
+
+ List<Permission> getPermissions(List<Integer> groupIds) throws ServiceException;
+
+ void deletePermission(Permission permission) throws ServiceException;
+
+ PermissionList listByCriteria(PermissionCriteria criteria) throws ServiceException ;
+
+ void removePermission(Permission permission, Group group) throws ServiceException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/user/service/PermissionServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/user/service/PermissionServiceImpl.java
new file mode 100755
index 0000000..d8acfcf
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/user/service/PermissionServiceImpl.java
@@ -0,0 +1,106 @@
+package com.salesmanager.core.business.user.service;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.salesmanager.core.business.catalog.category.model.Category;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.image.ProductImage;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.service.MerchantStoreService;
+import com.salesmanager.core.business.reference.language.service.LanguageService;
+import com.salesmanager.core.business.user.dao.PermissionDao;
+import com.salesmanager.core.business.user.model.Group;
+import com.salesmanager.core.business.user.model.Permission;
+import com.salesmanager.core.business.user.model.PermissionCriteria;
+import com.salesmanager.core.business.user.model.PermissionList;
+
+@Service("permissionService")
+public class PermissionServiceImpl extends
+ SalesManagerEntityServiceImpl<Integer, Permission> implements
+ PermissionService {
+
+ PermissionDao permissionDao;
+
+ @Autowired
+ private LanguageService languageService;
+
+ @Autowired
+ private MerchantStoreService merchantService;
+
+ @Autowired
+ private GroupService groupService;
+
+ @Autowired
+ public PermissionServiceImpl(PermissionDao permissionDao) {
+ super(permissionDao);
+ this.permissionDao = permissionDao;
+
+ }
+
+ @Override
+ public List<Permission> getByName() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+
+ @Override
+ public Permission getById(Integer permissionId) {
+ return permissionDao.getById(permissionId);
+
+ }
+
+ @Override
+ public void saveOrUpdate(Permission permission) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void deletePermission(Permission permission) throws ServiceException {
+ permission = this.getById(permission.getId());//Prevents detached entity error
+ permission.setGroups(null);
+
+ this.delete(permission);
+ }
+
+
+ @Override
+ public List<Permission> getPermissions(List<Integer> groupIds)
+ throws ServiceException {
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ Set ids = new HashSet(groupIds);
+ return permissionDao.getPermissionsListByGroups(ids);
+ }
+
+ @Override
+ public PermissionList listByCriteria(PermissionCriteria criteria)
+ throws ServiceException {
+ return permissionDao.listByCriteria(criteria);
+ }
+
+ @Override
+ public void removePermission(Permission permission,Group group) throws ServiceException {
+ permission = this.getById(permission.getId());//Prevents detached entity error
+
+ permission.getGroups().remove(group);
+
+
+// this.delete(permission);
+ }
+
+ @Override
+ public List<Permission> listPermission() throws ServiceException {
+ return permissionDao.listPermission();
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/user/service/UserService.java b/sm-core/src/main/java/com/salesmanager/core/business/user/service/UserService.java
new file mode 100755
index 0000000..b40003d
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/user/service/UserService.java
@@ -0,0 +1,28 @@
+package com.salesmanager.core.business.user.service;
+
+import java.util.List;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityService;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.user.model.User;
+import com.salesmanager.core.modules.email.Email;
+
+public interface UserService extends SalesManagerEntityService<Long, User> {
+
+ User getByUserName(String userName) throws ServiceException;
+
+ List<User> listUser() throws ServiceException;
+
+ /**
+ * Create or update a User
+ * @param user
+ * @throws ServiceException
+ */
+ void saveOrUpdate(User user) throws ServiceException;
+
+ List<User> listByStore(MerchantStore store) throws ServiceException;
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/user/service/UserServiceImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/user/service/UserServiceImpl.java
new file mode 100755
index 0000000..a9788e0
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/user/service/UserServiceImpl.java
@@ -0,0 +1,77 @@
+package com.salesmanager.core.business.user.service;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.service.SalesManagerEntityServiceImpl;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.system.service.EmailService;
+import com.salesmanager.core.business.user.dao.UserDao;
+import com.salesmanager.core.business.user.model.User;
+import com.salesmanager.core.modules.email.Email;
+
+
+public class UserServiceImpl extends SalesManagerEntityServiceImpl<Long, User>
+ implements UserService {
+
+
+ private UserDao userDao;
+
+ @Autowired
+ public UserServiceImpl(UserDao userDao) {
+ super(userDao);
+ this.userDao = userDao;
+
+ }
+
+ @Autowired
+ private EmailService emailService;
+
+ @Override
+ public User getByUserName(String userName) throws ServiceException {
+
+ return userDao.getByUserName(userName);
+
+ }
+
+ @Override
+ public void delete(User user) throws ServiceException {
+
+ User u = this.getById(user.getId());
+ super.delete(u);
+
+ }
+
+ @Override
+ public List<User> listUser() throws ServiceException {
+ try {
+ return userDao.listUser();
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+ }
+
+ @Override
+ public List<User> listByStore(MerchantStore store) throws ServiceException {
+ try {
+ return userDao.listUserByStore(store);
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+ }
+
+
+ @Override
+ public void saveOrUpdate(User user) throws ServiceException {
+
+ if(user.getId()==null || user.getId().longValue()==0) {
+ userDao.save(user);
+ } else {
+ userDao.update(user);
+ }
+
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/business/user/service/UserServiceLDAPImpl.java b/sm-core/src/main/java/com/salesmanager/core/business/user/service/UserServiceLDAPImpl.java
new file mode 100644
index 0000000..fc84915
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/business/user/service/UserServiceLDAPImpl.java
@@ -0,0 +1,106 @@
+package com.salesmanager.core.business.user.service;
+
+import java.util.List;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.user.model.User;
+import com.salesmanager.core.modules.email.Email;
+
+public class UserServiceLDAPImpl implements UserService {
+
+ @Override
+ public void save(User entity) throws ServiceException {
+ throw new ServiceException("Not implemented");
+
+ }
+
+ @Override
+ public void update(User entity) throws ServiceException {
+ throw new ServiceException("Not implemented");
+
+ }
+
+ @Override
+ public void create(User entity) throws ServiceException {
+ throw new ServiceException("Not implemented");
+
+ }
+
+ @Override
+ public void delete(User entity) throws ServiceException {
+ throw new ServiceException("Not implemented");
+
+ }
+
+ @Override
+ public User refresh(User entity) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public User getById(Long id) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public List<User> list() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+
+
+ @Override
+ public Long count() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void flush() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void clear() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public User getByUserName(String userName) throws ServiceException {
+ // TODO Auto-generated method stub
+ throw new ServiceException("Not implemented");
+ }
+
+ @Override
+ public List<User> listUser() throws ServiceException {
+ // TODO Auto-generated method stub
+ throw new ServiceException("Not implemented");
+ }
+
+ @Override
+ public void saveOrUpdate(User user) throws ServiceException {
+ throw new ServiceException("Not implemented");
+
+ }
+
+ @Override
+ public List<User> listByStore(MerchantStore store)
+ throws ServiceException {
+ // TODO Auto-generated method stub
+ throw new ServiceException("Not implemented");
+ }
+
+ @Override
+ public User getEntity(Class<? extends User> clazz, Long id) {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/constants/Constants.java b/sm-core/src/main/java/com/salesmanager/core/constants/Constants.java
new file mode 100644
index 0000000..8647615
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/constants/Constants.java
@@ -0,0 +1,34 @@
+package com.salesmanager.core.constants;
+
+import java.util.Currency;
+import java.util.Locale;
+
+public class Constants {
+
+ public final static String TEST_ENVIRONMENT= "TEST";
+ public final static String PRODUCTION_ENVIRONMENT= "PRODUCTION";
+ public final static String SHOP_URI = "/shop";
+
+ public static final String ALL_REGIONS = "*";
+ public final static String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";
+ public final static String DEFAULT_DATE_FORMAT_YEAR = "yyyy";
+
+ public final static String EMAIL_CONFIG = "EMAIL_CONFIG";
+ public final static String MERCHANT_CONFIG = "MERCHANT_CONFIG";
+
+ public final static String UNDERSCORE = "_";
+ public final static String SLASH = "/";
+ public final static String TRUE = "true";
+ public final static String FALSE = "false";
+ public final static String OT_ITEM_PRICE_MODULE_CODE = "itemprice";
+ public final static String OT_SUBTOTAL_MODULE_CODE = "subtotal";
+ public final static String OT_TOTAL_MODULE_CODE = "total";
+ public final static String OT_SHIPPING_MODULE_CODE = "shipping";
+ public final static String OT_HANDLING_MODULE_CODE = "handling";
+ public final static String OT_TAX_MODULE_CODE = "tax";
+ public final static String OT_REFUND_MODULE_CODE = "refund";
+
+ public final static Locale DEFAULT_LOCALE = Locale.US;
+ public final static Currency DEFAULT_CURRENCY = Currency.getInstance(Locale.US);
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/constants/MeasureUnit.java b/sm-core/src/main/java/com/salesmanager/core/constants/MeasureUnit.java
new file mode 100644
index 0000000..2d6607b
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/constants/MeasureUnit.java
@@ -0,0 +1,7 @@
+package com.salesmanager.core.constants;
+
+public enum MeasureUnit {
+
+ KG, LB, CM, IN
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/constants/SchemaConstant.java b/sm-core/src/main/java/com/salesmanager/core/constants/SchemaConstant.java
new file mode 100644
index 0000000..8e842d6
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/constants/SchemaConstant.java
@@ -0,0 +1,268 @@
+package com.salesmanager.core.constants;
+
+import java.util.HashMap;
+import java.util.Locale;
+
+public class SchemaConstant {
+
+ public final static String SALESMANAGER_SCHEMA = "SALESMANAGER";
+
+ /**
+ * Languages iso codes
+ *
+ */
+ public static final String[] LANGUAGE_ISO_CODE = {"en", "fr"};
+
+ /**
+ * Country iso codes
+ */
+ public static final String[] COUNTRY_ISO_CODE = { "AF","AX","AL","DZ",
+ "AS","AD","AO","AI","AQ","AG","AR","AM","AW","AU","AT","AZ","BS","BH",
+ "BD","BB","BY","BE","BZ","BJ","BM","BT","BO","BA","BW","BV","BR","IO",
+ "BN","BG","BF","BI","KH","CM","CA","CV","KY","CF","TD","CL","CN","CX",
+ "CC","CO","KM","CG","CD","CK","CR","CI","HR","CU","CY","CZ","DK","DJ",
+ "DM","DO","EC","EG","SV","GQ","ER","EE","ET","FK","FO","FJ","FI","FR",
+ "GF","PF","TF","GA","GM","GE","DE","GH","GI","GR","GL","GD","GP","GU",
+ "GT","GG","GN","GW","GY","HT","HM","VA","HN","HK","HU","IS","IN","ID",
+ "IR","IQ","IE","IM","IL","IT","JM","JP","JE","JO","KZ","KE","KI","KP",
+ "KR","KW","KG","LA","LV","LB","LS","LR","LY","LI","LT","LU","MO","MK",
+ "MG","MW","MY","MV","ML","MT","MH","MQ","MR","MU","YT","MX","FM","MD",
+ "MC","MN","ME","MS","MA","MZ","MM","NA","NR","NP","NL","AN","NC","NZ",
+ "NI","NE","NG","NU","NF","MP","NO","OM","PK","PW","PS","PA","PG","PY",
+ "PE","PH","PN","PL","PT","PR","QA","RE","RO","RU","RW","SH","KN","LC",
+ "PM","VC","WS","SM","ST","SA","SN","RS","SC","SL","SG","SK","SI","SB",
+ "SO","ZA","GS","ES","LK","SD","SR","SJ","SZ","SE","CH","SY","TW","TJ",
+ "TZ","TH","TL","TG","TK","TO","TT","TN","TR","TM","TC","TV","UG","UA",
+ "AE","GB","US","UM","UY","UZ","VU","VE","VN","VG","VI","WF","EH",
+ "YE","ZM","ZW" };
+
+ /**
+ * Locale per country iso codes
+ */
+ public static final HashMap<String, Locale> LOCALES = new HashMap<String, Locale>();
+
+ static {
+ for (Locale locale : Locale.getAvailableLocales()) {
+ LOCALES.put(locale.getCountry(), locale);
+ }
+ }
+
+ /**
+ * Currency codes with name
+ */
+ public static final HashMap<String, String> CURRENCY_MAP = new HashMap<String, String>();
+
+ static {
+ CURRENCY_MAP.put("AFN", "Afghani");
+ CURRENCY_MAP.put("EUR", "Euro");
+ CURRENCY_MAP.put("ALL", "Lek");
+ CURRENCY_MAP.put("DZD", "Algerian Dinar");
+ CURRENCY_MAP.put("USD", "US Dollar");
+ CURRENCY_MAP.put("AOA", "Kwanza");
+ CURRENCY_MAP.put("XCD", "East Caribbean Dollar");
+ CURRENCY_MAP.put("ARS", "Argentine Peso");
+ CURRENCY_MAP.put("AMD", "Armenian Dram");
+ CURRENCY_MAP.put("AWG", "Aruban Florin");
+ CURRENCY_MAP.put("AUD", "Australian Dollar");
+ CURRENCY_MAP.put("AZN", "Azerbaijanian Manat");
+ CURRENCY_MAP.put("BSD", "Bahamian Dollar");
+ CURRENCY_MAP.put("BHD", "Bahraini Dinar");
+ CURRENCY_MAP.put("BDT", "Taka");
+ CURRENCY_MAP.put("BBD", "Barbados Dollar");
+ CURRENCY_MAP.put("BYR", "Belarussian Ruble");
+ CURRENCY_MAP.put("BZD", "Belize Dollar");
+ CURRENCY_MAP.put("XOF", "CFA Franc BCEAO");
+ CURRENCY_MAP.put("BMD", "Bermudian Dollar");
+ CURRENCY_MAP.put("BTN", "Ngultrum");
+ CURRENCY_MAP.put("INR", "Indian Rupee");
+ CURRENCY_MAP.put("BOB", "Boliviano");
+ CURRENCY_MAP.put("BOV", "Mvdol");
+ CURRENCY_MAP.put("BAM", "Convertible Mark");
+ CURRENCY_MAP.put("BWP", "Pula");
+ CURRENCY_MAP.put("NOK", "Norwegian Krone");
+ CURRENCY_MAP.put("BRL", "Brazilian Real");
+ CURRENCY_MAP.put("BND", "Brunei Dollar");
+ CURRENCY_MAP.put("BGN", "Bulgarian Lev");
+ CURRENCY_MAP.put("XOF", "CFA Franc BCEAO");
+ CURRENCY_MAP.put("BIF", "Burundi Franc");
+ CURRENCY_MAP.put("KHR", "Riel");
+ CURRENCY_MAP.put("XAF", "CFA Franc BEAC");
+ CURRENCY_MAP.put("CAD", "Canadian Dollar");
+ CURRENCY_MAP.put("CVE", "Cape Verde Escudo");
+ CURRENCY_MAP.put("KYD", "Cayman Islands Dollar");
+ CURRENCY_MAP.put("CLF", "Unidades de fomento");
+ CURRENCY_MAP.put("CLP", "Chilean Peso");
+ CURRENCY_MAP.put("CNY", "Yuan Renminbi");
+ CURRENCY_MAP.put("COP", "Colombian Peso");
+ //CURRENCY_MAP.put("COU", "Unidad de Valor Real");
+ CURRENCY_MAP.put("KMF", "Comoro Franc");
+ CURRENCY_MAP.put("XAF", "CFA Franc BEAC");
+ CURRENCY_MAP.put("CDF", "Congolese Franc");
+ CURRENCY_MAP.put("NZD", "New Zealand Dollar");
+ CURRENCY_MAP.put("CRC", "Costa Rican Colon");
+ CURRENCY_MAP.put("XOF", "CFA Franc BCEAO");
+ CURRENCY_MAP.put("HRK", "Croatian Kuna");
+ //CURRENCY_MAP.put("CUC", "Peso Convertible");
+ CURRENCY_MAP.put("CUP", "Cuban Peso");
+ CURRENCY_MAP.put("ANG", "Netherlands Antillean Guilder");
+ CURRENCY_MAP.put("CZK", "Czech Koruna");
+ CURRENCY_MAP.put("DKK", "Danish Krone");
+ CURRENCY_MAP.put("DJF", "Djibouti Franc");
+ CURRENCY_MAP.put("XCD", "East Caribbean Dollar");
+ CURRENCY_MAP.put("DOP", "Dominican Peso");
+ CURRENCY_MAP.put("EGP", "Egyptian Pound");
+ CURRENCY_MAP.put("SVC", "El Salvador Colon");
+ CURRENCY_MAP.put("XAF", "CFA Franc BEAC");
+ CURRENCY_MAP.put("ERN", "Nakfa");
+ CURRENCY_MAP.put("ETB", "Ethiopian Birr");
+ CURRENCY_MAP.put("FKP", "Falkland Islands Pound");
+ CURRENCY_MAP.put("DKK", "Danish Krone");
+ CURRENCY_MAP.put("FJD", "Fiji Dollar");
+ CURRENCY_MAP.put("XPF", "CFP Franc");
+ CURRENCY_MAP.put("XAF", "CFA Franc BEAC");
+ CURRENCY_MAP.put("GMD", "Dalasi");
+ CURRENCY_MAP.put("GEL", "Lari");
+ CURRENCY_MAP.put("GHS", "Ghana Cedi");
+ CURRENCY_MAP.put("GIP", "Gibraltar Pound");
+ CURRENCY_MAP.put("DKK", "Danish Krone");
+ CURRENCY_MAP.put("XCD", "East Caribbean Dollar");
+ CURRENCY_MAP.put("GTQ", "Quetzal");
+ CURRENCY_MAP.put("GBP", "Pound Sterling");
+ CURRENCY_MAP.put("GNF", "Guinea Franc");
+ CURRENCY_MAP.put("XOF", "CFA Franc BCEAO");
+ CURRENCY_MAP.put("GYD", "Guyana Dollar");
+ CURRENCY_MAP.put("HTG", "Gourde");
+ CURRENCY_MAP.put("HNL", "Lempira");
+ CURRENCY_MAP.put("HKD", "Hong Kong Dollar");
+ CURRENCY_MAP.put("HUF", "Forint");
+ CURRENCY_MAP.put("ISK", "Iceland Krona");
+ CURRENCY_MAP.put("INR", "Indian Rupee");
+ CURRENCY_MAP.put("IDR", "Rupiah");
+ CURRENCY_MAP.put("XDR", "SDR (Special Drawing Right)");
+ CURRENCY_MAP.put("IRR", "Iranian Rial");
+ CURRENCY_MAP.put("IQD", "Iraqi Dinar");
+ CURRENCY_MAP.put("GBP", "Pound Sterling");
+ CURRENCY_MAP.put("ILS", "New Israeli Sheqel");
+ CURRENCY_MAP.put("JMD", "Jamaican Dollar");
+ CURRENCY_MAP.put("JPY", "Yen");
+ CURRENCY_MAP.put("GBP", "Pound Sterling");
+ CURRENCY_MAP.put("JOD", "Jordanian Dinar");
+ CURRENCY_MAP.put("KZT", "Tenge");
+ CURRENCY_MAP.put("KES", "Kenyan Shilling");
+ CURRENCY_MAP.put("AUD", "Australian Dollar");
+ CURRENCY_MAP.put("KPW", "North Korean Won");
+ CURRENCY_MAP.put("KRW", "Won");
+ CURRENCY_MAP.put("KWD", "Kuwaiti Dinar");
+ CURRENCY_MAP.put("KGS", "Som");
+ CURRENCY_MAP.put("LAK", "Kip");
+ CURRENCY_MAP.put("LVL", "Latvian Lats");
+ CURRENCY_MAP.put("LBP", "Lebanese Pound");
+ CURRENCY_MAP.put("LSL", "Loti");
+ CURRENCY_MAP.put("ZAR", "Rand");
+ CURRENCY_MAP.put("LRD", "Liberian Dollar");
+ CURRENCY_MAP.put("LYD", "Libyan Dinar");
+ CURRENCY_MAP.put("CHF", "Swiss Franc");
+ CURRENCY_MAP.put("LTL", "Lithuanian Litas");
+ CURRENCY_MAP.put("EUR", "Euro");
+ CURRENCY_MAP.put("MOP", "Pataca");
+ CURRENCY_MAP.put("MKD", "Denar");
+ CURRENCY_MAP.put("MGA", "Malagasy Ariary");
+ CURRENCY_MAP.put("MWK", "Kwacha");
+ CURRENCY_MAP.put("MYR", "Malaysian Ringgit");
+ CURRENCY_MAP.put("MVR", "Rufiyaa");
+ CURRENCY_MAP.put("XOF", "CFA Franc BCEAO");
+ CURRENCY_MAP.put("MRO", "Ouguiya");
+ CURRENCY_MAP.put("MUR", "Mauritius Rupee");
+ //CURRENCY_MAP.put("XUA", "ADB Unit of Account");
+ CURRENCY_MAP.put("MXN", "Mexican Peso");
+ CURRENCY_MAP.put("MXV", "Mexican Unidad de Inversion (UDI)");
+ CURRENCY_MAP.put("MDL", "Moldovan Leu");
+ CURRENCY_MAP.put("MNT", "Tugrik");
+ CURRENCY_MAP.put("XCD", "East Caribbean Dollar");
+ CURRENCY_MAP.put("MAD", "Moroccan Dirham");
+ CURRENCY_MAP.put("MZN", "Mozambique Metical");
+ CURRENCY_MAP.put("MMK", "Kyat");
+ CURRENCY_MAP.put("NAD", "Namibia Dollar");
+ CURRENCY_MAP.put("ZAR", "Rand");
+ CURRENCY_MAP.put("NPR", "Nepalese Rupee");
+ CURRENCY_MAP.put("XPF", "CFP Franc");
+ CURRENCY_MAP.put("NZD", "New Zealand Dollar");
+ CURRENCY_MAP.put("NIO", "Cordoba Oro");
+ CURRENCY_MAP.put("XOF", "CFA Franc BCEAO");
+ CURRENCY_MAP.put("NGN", "Naira");
+ CURRENCY_MAP.put("NZD", "New Zealand Dollar");
+ CURRENCY_MAP.put("AUD", "Australian Dollar");
+ CURRENCY_MAP.put("NOK", "Norwegian Krone");
+ CURRENCY_MAP.put("OMR", "Rial Omani");
+ CURRENCY_MAP.put("PKR", "Pakistan Rupee");
+ CURRENCY_MAP.put("PAB", "Balboa");
+ CURRENCY_MAP.put("PGK", "Kina");
+ CURRENCY_MAP.put("PYG", "Guarani");
+ CURRENCY_MAP.put("PEN", "Nuevo Sol");
+ CURRENCY_MAP.put("PHP", "Philippine Peso");
+ CURRENCY_MAP.put("NZD", "New Zealand Dollar");
+ CURRENCY_MAP.put("PLN", "Zloty");
+ CURRENCY_MAP.put("USD", "US Dollar");
+ CURRENCY_MAP.put("QAR", "Qatari Rial");
+ CURRENCY_MAP.put("RON", "New Romanian Leu");
+ CURRENCY_MAP.put("RUB", "Russian Ruble");
+ CURRENCY_MAP.put("RWF", "Rwanda Franc");
+ CURRENCY_MAP.put("SHP", "Saint Helena Pound");
+ CURRENCY_MAP.put("XCD", "East Caribbean Dollar");
+ CURRENCY_MAP.put("WST", "Tala");
+ CURRENCY_MAP.put("STD", "Dobra");
+ CURRENCY_MAP.put("SAR", "Saudi Riyal");
+ CURRENCY_MAP.put("XOF", "CFA Franc BCEAO");
+ CURRENCY_MAP.put("RSD", "Serbian Dinar");
+ CURRENCY_MAP.put("SCR", "Seychelles Rupee");
+ CURRENCY_MAP.put("SLL", "Leone");
+ CURRENCY_MAP.put("SGD", "Singapore Dollar");
+ CURRENCY_MAP.put("ANG", "Netherlands Antillean Guilder");
+ //CURRENCY_MAP.put("XSU", "Sucre");
+ CURRENCY_MAP.put("SBD", "Solomon Islands Dollar");
+ CURRENCY_MAP.put("SOS", "Somali Shilling");
+ CURRENCY_MAP.put("ZAR", "Rand");
+ //CURRENCY_MAP.put("SSP", "South Sudanese Pound");
+ CURRENCY_MAP.put("LKR", "Sri Lanka Rupee");
+ CURRENCY_MAP.put("SDG", "Sudanese Pound");
+ CURRENCY_MAP.put("SRD", "Surinam Dollar");
+ CURRENCY_MAP.put("NOK", "Norwegian Krone");
+ CURRENCY_MAP.put("SZL", "Lilangeni");
+ CURRENCY_MAP.put("SEK", "Swedish Krona");
+ //CURRENCY_MAP.put("CHE", "WIR Euro");
+ CURRENCY_MAP.put("CHF", "Swiss Franc");
+ //CURRENCY_MAP.put("CHW", "WIR Franc");
+ CURRENCY_MAP.put("SYP", "Syrian Pound");
+ CURRENCY_MAP.put("TWD", "New Taiwan Dollar");
+ CURRENCY_MAP.put("TJS", "Somoni");
+ CURRENCY_MAP.put("TZS", "Tanzanian Shilling");
+ CURRENCY_MAP.put("THB", "Baht");
+ CURRENCY_MAP.put("USD", "US Dollar");
+ CURRENCY_MAP.put("XOF", "CFA Franc BCEAO");
+ CURRENCY_MAP.put("NZD", "New Zealand Dollar");
+ CURRENCY_MAP.put("TTD", "Trinidad and Tobago Dollar");
+ CURRENCY_MAP.put("TND", "Tunisian Dinar");
+ CURRENCY_MAP.put("TRY", "Turkish Lira");
+ //CURRENCY_MAP.put("TMT", "Turkmenistan New Manat");
+ CURRENCY_MAP.put("AUD", "Australian Dollar");
+ CURRENCY_MAP.put("UGX", "Uganda Shilling");
+ CURRENCY_MAP.put("UAH", "Hryvnia");
+ CURRENCY_MAP.put("AED", "UAE Dirham");
+ CURRENCY_MAP.put("GBP", "Pound Sterling");
+ //CURRENCY_MAP.put("UYI", "Uruguay Peso en Unidades Indexadas (URUIURUI)");
+ CURRENCY_MAP.put("UYU", "Peso Uruguayo");
+ CURRENCY_MAP.put("UZS", "Uzbekistan Sum");
+ CURRENCY_MAP.put("VUV", "Vatu");
+ CURRENCY_MAP.put("VEF", "Bolivar Fuerte");
+ CURRENCY_MAP.put("VND", "Dong");
+ CURRENCY_MAP.put("USD", "US Dollar");
+ CURRENCY_MAP.put("XPF", "CFP Franc");
+ CURRENCY_MAP.put("MAD", "Moroccan Dirham");
+ CURRENCY_MAP.put("YER", "Yemeni Rial");
+ CURRENCY_MAP.put("ZMK", "Zambian Kwacha");
+ //CURRENCY_MAP.put("ZWL", "Zimbabwe Dollar");
+
+
+
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/constants/ShippingConstants.java b/sm-core/src/main/java/com/salesmanager/core/constants/ShippingConstants.java
new file mode 100644
index 0000000..8384db4
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/constants/ShippingConstants.java
@@ -0,0 +1,10 @@
+package com.salesmanager.core.constants;
+
+
+public class ShippingConstants {
+
+ public final static String SHIPPING_CONFIGURATION= "SHIPPING_CONFIG";
+ public final static String SHIPPING_NATIONAL = "NATIONAL";
+ public final static String SHIPPING_INTERNATIONAL = "INTERNATIONAL";
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/constants/SystemConstants.java b/sm-core/src/main/java/com/salesmanager/core/constants/SystemConstants.java
new file mode 100644
index 0000000..218be09
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/constants/SystemConstants.java
@@ -0,0 +1,11 @@
+package com.salesmanager.core.constants;
+
+public class SystemConstants {
+
+
+
+ public final static String SYSTEM_USER = "SYSTEM";
+ public final static String CONFIG_VALUE_TRUE = "true";
+ public final static String CONFIG_VALUE_FALSE = "false";
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/common/ImageGet.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/common/ImageGet.java
new file mode 100755
index 0000000..526df7b
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/common/ImageGet.java
@@ -0,0 +1,15 @@
+package com.salesmanager.core.modules.cms.common;
+
+import java.util.List;
+
+import com.salesmanager.core.business.content.model.FileContentType;
+import com.salesmanager.core.business.content.model.OutputContentFile;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+
+public interface ImageGet
+{
+
+ public List<OutputContentFile> getImages( final String merchantStoreCode, FileContentType imageContentType )
+ throws ServiceException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/common/ImageRemove.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/common/ImageRemove.java
new file mode 100755
index 0000000..a767e91
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/common/ImageRemove.java
@@ -0,0 +1,11 @@
+package com.salesmanager.core.modules.cms.common;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+
+
+public interface ImageRemove {
+
+
+ public void removeImages(final String merchantStoreCode) throws ServiceException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/common/StaticContentData.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/common/StaticContentData.java
new file mode 100644
index 0000000..121f0af
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/common/StaticContentData.java
@@ -0,0 +1,52 @@
+/**
+ *
+ */
+package com.salesmanager.core.modules.cms.common;
+
+import java.io.Serializable;
+
+import com.salesmanager.core.business.content.model.FileContentType;
+
+
+/**
+ * Abstract class for Static content data containing common attributes
+ * for handling static content data.
+ *
+ * @author Umesh Awasthi
+ *@since 1.2
+ */
+public abstract class StaticContentData implements Serializable
+{
+
+
+ private static final long serialVersionUID = 1L;
+ private String fileName;
+ private FileContentType contentType = FileContentType.STATIC_FILE;
+ private String fileContentType;
+
+ public String getFileName()
+ {
+ return fileName;
+ }
+ public void setFileName( String fileName )
+ {
+ this.fileName = fileName;
+ }
+
+ public String getFileContentType()
+ {
+ return fileContentType;
+ }
+ public void setFileContentType( String fileContentType )
+ {
+ this.fileContentType = fileContentType;
+ }
+ public void setContentType(FileContentType contentType) {
+ this.contentType = contentType;
+ }
+ public FileContentType getContentType() {
+ return contentType;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/CmsStaticContentFileManagerInfinispanImpl.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/CmsStaticContentFileManagerInfinispanImpl.java
new file mode 100644
index 0000000..df01248
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/CmsStaticContentFileManagerInfinispanImpl.java
@@ -0,0 +1,445 @@
+/**
+ *
+ */
+package com.salesmanager.core.modules.cms.content;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.net.FileNameMap;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.apache.commons.io.IOUtils;
+import org.infinispan.tree.Fqn;
+import org.infinispan.tree.Node;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.salesmanager.core.business.content.model.FileContentType;
+import com.salesmanager.core.business.content.model.InputContentFile;
+import com.salesmanager.core.business.content.model.OutputContentFile;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.modules.cms.impl.CacheManager;
+
+
+
+/**
+ * Manages
+ * - Images
+ * - Files (js, pdf, css...)
+ * @author Umesh Awasthi
+ * @since 1.2
+ *
+ */
+public class CmsStaticContentFileManagerInfinispanImpl implements FilePut,FileGet,FileRemove
+{
+
+ private static final Logger LOGGER = LoggerFactory.getLogger( CmsStaticContentFileManagerInfinispanImpl.class );
+ private static CmsStaticContentFileManagerInfinispanImpl fileManager = null;
+ private static final String ROOT_NAME="static-merchant-";
+
+ private String rootName = ROOT_NAME;
+
+ private CacheManager cacheManager;
+
+ public void stopFileManager()
+ {
+
+ try
+ {
+ cacheManager.getManager().stop();
+ LOGGER.info( "Stopping CMS" );
+ }
+ catch ( final Exception e )
+ {
+ LOGGER.error( "Error while stopping CmsStaticContentFileManager", e );
+ }
+ }
+
+ public static CmsStaticContentFileManagerInfinispanImpl getInstance()
+ {
+
+ if ( fileManager == null )
+ {
+ fileManager = new CmsStaticContentFileManagerInfinispanImpl();
+ }
+
+ return fileManager;
+
+ }
+
+
+ /**
+ * <p>Method to add static content data for given merchant.Static content data can be of following type
+ * <pre>
+ * 1. CSS and JS files
+ * 2. Digital Data like audio or video
+ * </pre>
+ * </p>
+ * <p>
+ * Merchant store code will be used to create cache node where merchant data will be stored,input data will
+ * contain name, file as well type of data being stored.
+ * @see FileContentType
+ * </p>
+ *
+ * @param merchantStoreCode merchant store for whom data is being stored
+ * @param inputStaticContentData data object being stored
+ * @throws ServiceException
+ *
+ */
+ @Override
+ public void addFile( final String merchantStoreCode, final InputContentFile inputStaticContentData )
+ throws ServiceException
+ {
+ if ( cacheManager.getTreeCache() == null )
+ {
+ LOGGER.error( "Unable to find cacheManager.getTreeCache() in Infinispan.." );
+ throw new ServiceException( "CmsStaticContentFileManagerInfinispanImpl has a null cacheManager.getTreeCache()" );
+ }
+ try
+ {
+
+ String nodePath = this.getNodePath(merchantStoreCode, inputStaticContentData.getFileContentType());
+
+ final Node<String, Object> merchantNode = this.getNode(nodePath);
+
+ merchantNode.put(inputStaticContentData.getFileName(), IOUtils.toByteArray( inputStaticContentData.getFile() ));
+
+ LOGGER.info( "Content data added successfully." );
+ }
+ catch ( final Exception e )
+ {
+ LOGGER.error( "Error while saving static content data", e );
+ throw new ServiceException( e );
+
+ }
+
+ }
+
+ /**
+ * <p>
+ * Method to add files for given store.Files will be stored in Infinispan and will be retrieved based on
+ * the storeID. Following steps will be performed to store static content files
+ * </p>
+ * <li>Merchant Node will be retrieved from the cacheTree if it exists else new node will be created.</li> <li>
+ * Files will be stored in StaticContentCacheAttribute , which eventually will be stored in Infinispan</li>
+ *
+ * @param merchantStoreCode Merchant store for which files are getting stored in Infinispan.
+ * @param inputStaticContentDataList input static content file list which will get {@link InputContentImage} stored
+ * @throws ServiceException if content file storing process fail.
+ * @see InputStaticContentData
+ * @see StaticContentCacheAttribute
+ */
+ @Override
+ public void addFiles( final String merchantStoreCode, final List<InputContentFile> inputStaticContentDataList )
+ throws ServiceException
+ {
+ if ( cacheManager.getTreeCache() == null )
+ {
+ LOGGER.error( "Unable to find cacheManager.getTreeCache() in Infinispan.." );
+ throw new ServiceException( "CmsStaticContentFileManagerInfinispanImpl has a null cacheManager.getTreeCache()" );
+ }
+ try
+ {
+
+ for(final InputContentFile inputStaticContentData:inputStaticContentDataList){
+
+
+ String nodePath = this.getNodePath(merchantStoreCode, inputStaticContentData.getFileContentType());
+ final Node<String, Object> merchantNode = this.getNode(nodePath);
+ merchantNode.put(inputStaticContentData.getFileName(), IOUtils.toByteArray( inputStaticContentData.getFile() ));
+
+
+ }
+
+
+
+ LOGGER.info( "Total {} files added successfully.",inputStaticContentDataList.size() );
+
+ }
+ catch ( final Exception e )
+ {
+ LOGGER.error( "Error while saving content image", e );
+ throw new ServiceException( e );
+
+ }
+ }
+
+
+ /**
+ * Method to return static data for given Merchant store based on the file name. Content data will be searched
+ * in underlying Infinispan cache tree and {@link OutputStaticContentData} will be returned on finding an associated
+ * file. In case of no file, null be returned.
+ *
+ * @param store Merchant store
+ * @param contentFileName name of file being requested
+ * @return {@link OutputStaticContentData}
+ * @throws ServiceException
+ */
+ @Override
+ public OutputContentFile getFile( final String merchantStoreCode, final FileContentType fileContentType, final String contentFileName )
+ throws ServiceException
+ {
+
+ if ( cacheManager.getTreeCache() == null )
+ {
+ throw new ServiceException( "CmsStaticContentFileManagerInfinispan has a null cacheManager.getTreeCache()" );
+ }
+ OutputContentFile outputStaticContentData=null;
+ InputStream input = null;
+ try
+ {
+
+
+ String nodePath = this.getNodePath(merchantStoreCode, fileContentType);
+
+ final Node<String, Object> merchantNode = this.getNode(nodePath);
+
+
+ final byte[] fileBytes= (byte[]) merchantNode.get( contentFileName );
+
+ if ( fileBytes == null )
+ {
+ LOGGER.warn( "file byte is null, no file found" );
+ return null;
+ }
+
+ input=new ByteArrayInputStream( fileBytes );
+
+ final ByteArrayOutputStream output = new ByteArrayOutputStream();
+ IOUtils.copy( input, output );
+
+ outputStaticContentData=new OutputContentFile();
+ outputStaticContentData.setFile( output );
+ outputStaticContentData.setMimeType( URLConnection.getFileNameMap().getContentTypeFor(contentFileName) );
+ outputStaticContentData.setFileName( contentFileName );
+ outputStaticContentData.setFileContentType( fileContentType );
+
+ }
+ catch ( final Exception e )
+ {
+ LOGGER.error( "Error while fetching file for {} merchant ", merchantStoreCode);
+ throw new ServiceException( e );
+ }
+ return outputStaticContentData != null ? outputStaticContentData : null;
+ }
+
+
+ @Override
+ public List<OutputContentFile> getFiles(
+ final String merchantStoreCode, final FileContentType staticContentType) throws ServiceException {
+
+
+
+ if ( cacheManager.getTreeCache() == null )
+ {
+ throw new ServiceException( "CmsStaticContentFileManagerInfinispan has a null cacheManager.getTreeCache()" );
+ }
+ List<OutputContentFile> images = new ArrayList<OutputContentFile>();
+ try
+ {
+
+ FileNameMap fileNameMap = URLConnection.getFileNameMap();
+ String nodePath = this.getNodePath(merchantStoreCode, staticContentType);
+
+ final Node<String, Object> merchantNode = this.getNode(nodePath);
+
+ for(String key : merchantNode.getKeys()) {
+
+ byte[] imageBytes = (byte[])merchantNode.get( key );
+
+ OutputContentFile contentImage = new OutputContentFile();
+
+ InputStream input = new ByteArrayInputStream( imageBytes );
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ IOUtils.copy( input, output );
+
+ String contentType = fileNameMap.getContentTypeFor( key );
+
+ contentImage.setFile( output );
+ contentImage.setMimeType( contentType );
+ contentImage.setFileName( key );
+
+ images.add( contentImage );
+
+
+ }
+
+
+
+ }
+ catch ( final Exception e )
+ {
+ LOGGER.error( "Error while fetching file for {} merchant ", merchantStoreCode);
+ throw new ServiceException( e );
+ }
+
+
+ return images;
+
+
+ }
+
+
+
+ @Override
+ public void removeFile( final String merchantStoreCode, final FileContentType staticContentType, final String fileName )
+ throws ServiceException
+ {
+
+
+ if ( cacheManager.getTreeCache() == null )
+ {
+ throw new ServiceException( "CmsStaticContentFileManagerInfinispan has a null cacheManager.getTreeCache()" );
+ }
+
+ try
+ {
+
+
+ String nodePath = this.getNodePath(merchantStoreCode, staticContentType);
+ final Node<String, Object> merchantNode = this.getNode(nodePath);
+
+ merchantNode.remove(fileName);
+
+ }
+ catch ( final Exception e )
+ {
+ LOGGER.error( "Error while fetching file for {} merchant ", merchantStoreCode);
+ throw new ServiceException( e );
+ }
+
+
+ }
+
+ /**
+ * Removes the data in a given merchant node
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public void removeFiles( final String merchantStoreCode )
+ throws ServiceException
+ {
+
+ LOGGER.info( "Removing all images for {} merchant ",merchantStoreCode);
+ if ( cacheManager.getTreeCache() == null )
+ {
+ LOGGER.error( "Unable to find cacheManager.getTreeCache() in Infinispan.." );
+ throw new ServiceException( "CmsImageFileManagerInfinispan has a null cacheManager.getTreeCache()" );
+ }
+
+ try
+ {
+
+
+ final StringBuilder merchantPath = new StringBuilder();
+ merchantPath.append( getRootName()).append(merchantStoreCode );
+ cacheManager.getTreeCache().getRoot().remove(merchantPath.toString());
+
+
+
+
+ }
+ catch ( final Exception e )
+ {
+ LOGGER.error( "Error while deleting content image for {} merchant ", merchantStoreCode);
+ throw new ServiceException( e );
+ }
+
+ }
+
+ @SuppressWarnings({ "unchecked"})
+ private Node<String, Object> getNode( final String node )
+ {
+ LOGGER.debug( "Fetching node for store {} from Infinispan", node );
+ final StringBuilder merchantPath = new StringBuilder();
+ merchantPath.append( getRootName() ).append(node);
+
+ Fqn contentFilesFqn = Fqn.fromString(merchantPath.toString());
+
+ Node<String,Object> nd = cacheManager.getTreeCache().getRoot().getChild(contentFilesFqn);
+
+ if(nd==null) {
+
+ cacheManager.getTreeCache().getRoot().addChild(contentFilesFqn);
+ nd = cacheManager.getTreeCache().getRoot().getChild(contentFilesFqn);
+
+ }
+
+ return nd;
+
+ }
+
+ private String getNodePath(final String storeCode,final FileContentType contentType) {
+
+ StringBuilder nodePath = new StringBuilder();
+ nodePath.append(storeCode).append("/").append(contentType.name());
+
+ return nodePath.toString();
+
+ }
+
+
+
+ public CacheManager getCacheManager() {
+ return cacheManager;
+ }
+
+ public void setCacheManager(CacheManager cacheManager) {
+ this.cacheManager = cacheManager;
+ }
+
+
+ /**
+ * Queries the CMS to retrieve all static content files. Only the name of the file will be returned to the client
+ * @param merchantStoreCode
+ * @return
+ * @throws ServiceException
+ */
+ @Override
+ public List<String> getFileNames(final String merchantStoreCode, final FileContentType staticContentType)
+ throws ServiceException {
+
+
+
+ if ( cacheManager.getTreeCache() == null )
+ {
+ throw new ServiceException( "CmsStaticContentFileManagerInfinispan has a null cacheManager.getTreeCache()" );
+ }
+
+ try
+ {
+
+
+
+ String nodePath = this.getNodePath(merchantStoreCode, staticContentType);
+ final Node<String, Object> objectNode = this.getNode(nodePath);
+
+ if(objectNode.getKeys().isEmpty()) {
+ LOGGER.warn( "Unable to find content attribute for given merchant" );
+ return Collections.<String> emptyList();
+ }
+ return new ArrayList<String>(objectNode.getKeys());
+
+ }
+ catch ( final Exception e )
+ {
+ LOGGER.error( "Error while fetching file for {} merchant ", merchantStoreCode);
+ throw new ServiceException( e );
+ }
+
+ }
+
+ public void setRootName(String rootName) {
+ this.rootName = rootName;
+ }
+
+ public String getRootName() {
+ return rootName;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/ContentImageGet.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/ContentImageGet.java
new file mode 100755
index 0000000..df285ea
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/ContentImageGet.java
@@ -0,0 +1,15 @@
+package com.salesmanager.core.modules.cms.content;
+
+import java.util.List;
+
+import com.salesmanager.core.business.content.model.FileContentType;
+import com.salesmanager.core.business.content.model.OutputContentFile;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.modules.cms.common.ImageGet;
+
+public interface ContentImageGet extends ImageGet {
+
+ public OutputContentFile getImage(final String merchantStoreCode, String imageName,FileContentType imageContentType) throws ServiceException;
+ public List<String> getImageNames(final String merchantStoreCode, FileContentType imageContentType) throws ServiceException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/ContentImageRemove.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/ContentImageRemove.java
new file mode 100755
index 0000000..75f0c89
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/ContentImageRemove.java
@@ -0,0 +1,14 @@
+package com.salesmanager.core.modules.cms.content;
+
+
+import com.salesmanager.core.business.content.model.FileContentType;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.modules.cms.common.ImageRemove;
+
+public interface ContentImageRemove extends ImageRemove {
+
+
+
+ public void removeImage(final String merchantStoreCode,final FileContentType imageContentType, final String imageName) throws ServiceException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/FileGet.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/FileGet.java
new file mode 100644
index 0000000..80bddc8
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/FileGet.java
@@ -0,0 +1,21 @@
+package com.salesmanager.core.modules.cms.content;
+
+import java.util.List;
+
+import com.salesmanager.core.business.content.model.FileContentType;
+import com.salesmanager.core.business.content.model.OutputContentFile;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+
+
+/**
+ * Methods to retrieve the static content from the CMS
+ * @author Carl Samson
+ *
+ */
+public interface FileGet
+{
+
+ public OutputContentFile getFile(final String merchantStoreCode, FileContentType fileContentType, String contentName) throws ServiceException;
+ public List<String> getFileNames(final String merchantStoreCode,FileContentType fileContentType) throws ServiceException;
+ public List<OutputContentFile> getFiles(final String merchantStoreCode, FileContentType fileContentType) throws ServiceException;
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/FilePut.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/FilePut.java
new file mode 100644
index 0000000..e6c78c9
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/FilePut.java
@@ -0,0 +1,20 @@
+/**
+ *
+ */
+package com.salesmanager.core.modules.cms.content;
+
+import java.util.List;
+
+import com.salesmanager.core.business.content.model.InputContentFile;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+
+
+/**
+ * @author Umesh Awasthi
+ *
+ */
+public interface FilePut
+{
+ public void addFile(final String merchantStoreCode, InputContentFile inputStaticContentData) throws ServiceException;
+ public void addFiles(final String merchantStoreCode, List<InputContentFile> inputStaticContentDataList) throws ServiceException;
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/FileRemove.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/FileRemove.java
new file mode 100644
index 0000000..bc72996
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/FileRemove.java
@@ -0,0 +1,19 @@
+/**
+ *
+ */
+package com.salesmanager.core.modules.cms.content;
+
+import com.salesmanager.core.business.content.model.FileContentType;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+
+
+/**
+ * @author Umesh Awasthi
+ *
+ */
+public interface FileRemove
+{
+ public void removeFile(String merchantStoreCode, FileContentType staticContentType, String fileName) throws ServiceException;
+ public void removeFiles(String merchantStoreCode) throws ServiceException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/ImagePut.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/ImagePut.java
new file mode 100755
index 0000000..1702794
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/ImagePut.java
@@ -0,0 +1,14 @@
+package com.salesmanager.core.modules.cms.content;
+
+import java.util.List;
+
+import com.salesmanager.core.business.content.model.InputContentFile;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+
+public interface ImagePut {
+
+
+ public void addImage(final String merchantStoreCode, InputContentFile image) throws ServiceException;
+ public void addImages(final String merchantStoreCode, List<InputContentFile> imagesList) throws ServiceException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/StaticContentFileManager.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/StaticContentFileManager.java
new file mode 100644
index 0000000..73b6669
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/StaticContentFileManager.java
@@ -0,0 +1,13 @@
+/**
+ *
+ */
+package com.salesmanager.core.modules.cms.content;
+
+/**
+ * @author Umesh Awasthi
+ *
+ */
+public abstract class StaticContentFileManager implements FileGet,FilePut,FileRemove
+{
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/StaticContentFileManagerImpl.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/StaticContentFileManagerImpl.java
new file mode 100644
index 0000000..a2b6fc6
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/content/StaticContentFileManagerImpl.java
@@ -0,0 +1,110 @@
+/**
+ *
+ */
+package com.salesmanager.core.modules.cms.content;
+
+import java.util.List;
+
+import com.salesmanager.core.business.content.model.FileContentType;
+import com.salesmanager.core.business.content.model.InputContentFile;
+import com.salesmanager.core.business.content.model.OutputContentFile;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+
+
+/**
+ * @author Umesh Awasthi
+ *
+ */
+public class StaticContentFileManagerImpl extends StaticContentFileManager
+{
+
+ private FilePut uploadFile;
+ private FileGet getFile;
+ private FileRemove removeFile;
+
+
+
+ @Override
+ public void addFile( final String merchantStoreCode, final InputContentFile inputStaticContentData )
+ throws ServiceException
+ {
+ uploadFile.addFile( merchantStoreCode, inputStaticContentData );
+
+ }
+
+ /**
+ * Implementation for add static data files. This method will called respected add files method of underlying
+ * CMSStaticContentManager. For CMS Content files {@link CmsStaticContentFileManagerInfinispanImpl} will take care of adding
+ * given content images with Infinispan cache.
+ *
+ * @param merchantStoreCode merchant store.
+ * @param inputStaticContentDataList Input content images
+ * @throws ServiceException
+ */
+ @Override
+ public void addFiles( final String merchantStoreCode, final List<InputContentFile> inputStaticContentDataList )
+ throws ServiceException
+ {
+ uploadFile.addFiles( merchantStoreCode, inputStaticContentDataList );
+ }
+ @Override
+ public void removeFile( final String merchantStoreCode, final FileContentType staticContentType, final String fileName)
+ throws ServiceException
+ {
+ removeFile.removeFile(merchantStoreCode, staticContentType, fileName);
+
+ }
+
+
+ @Override
+ public OutputContentFile getFile(String merchantStoreCode,
+ FileContentType fileContentType, String contentName)
+ throws ServiceException {
+ return getFile.getFile(merchantStoreCode, fileContentType, contentName);
+ }
+
+ @Override
+ public List<String> getFileNames(String merchantStoreCode,
+ FileContentType fileContentType) throws ServiceException {
+ return getFile.getFileNames(merchantStoreCode, fileContentType);
+ }
+
+ @Override
+ public List<OutputContentFile> getFiles(String merchantStoreCode,
+ FileContentType fileContentType) throws ServiceException {
+ return getFile.getFiles(merchantStoreCode, fileContentType);
+ }
+
+ @Override
+ public void removeFiles(String merchantStoreCode) throws ServiceException {
+ removeFile.removeFiles(merchantStoreCode);
+ }
+
+
+
+ public void setRemoveFile(FileRemove removeFile) {
+ this.removeFile = removeFile;
+ }
+
+ public FileRemove getRemoveFile() {
+ return removeFile;
+ }
+
+ public void setGetFile(FileGet getFile) {
+ this.getFile = getFile;
+ }
+
+ public FileGet getGetFile() {
+ return getFile;
+ }
+
+ public void setUploadFile(FilePut uploadFile) {
+ this.uploadFile = uploadFile;
+ }
+
+ public FilePut getUploadFile() {
+ return uploadFile;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/impl/CacheManager.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/impl/CacheManager.java
new file mode 100644
index 0000000..7a678dc
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/impl/CacheManager.java
@@ -0,0 +1,13 @@
+package com.salesmanager.core.modules.cms.impl;
+
+import org.infinispan.manager.EmbeddedCacheManager;
+import org.infinispan.tree.TreeCache;
+
+public interface CacheManager {
+
+ public EmbeddedCacheManager getManager();
+
+ @SuppressWarnings("rawtypes")
+ public TreeCache getTreeCache();
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/impl/CacheManagerImpl.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/impl/CacheManagerImpl.java
new file mode 100644
index 0000000..e45234c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/impl/CacheManagerImpl.java
@@ -0,0 +1,65 @@
+package com.salesmanager.core.modules.cms.impl;
+
+import org.infinispan.Cache;
+import org.infinispan.manager.EmbeddedCacheManager;
+import org.infinispan.tree.TreeCache;
+import org.infinispan.tree.TreeCacheFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class CacheManagerImpl implements CacheManager {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CacheManagerImpl.class);
+
+ @SuppressWarnings("rawtypes")
+ private TreeCache treeCache = null;
+
+ @SuppressWarnings("unchecked")
+ protected void init(String namedCache) {
+
+
+ try {
+
+
+ //manager = new DefaultCacheManager(repositoryFileName);
+
+ VendorCacheManager cacheManager = VendorCacheManager.getInstance();
+
+ @SuppressWarnings("rawtypes")
+ Cache cache = cacheManager.getManager().getCache(namedCache);
+ cache.getCacheConfiguration().invocationBatching().enabled();
+
+ TreeCacheFactory f = new TreeCacheFactory();
+
+ treeCache = f.createTreeCache(cache);
+
+ cache.start();
+
+ LOGGER.debug("CMS started");
+
+
+
+ } catch (Exception e) {
+ LOGGER.error("Error while instantiating CmsImageFileManager",e);
+ } finally {
+
+ }
+
+
+
+
+
+ }
+
+ public EmbeddedCacheManager getManager() {
+ return VendorCacheManager.getInstance().getManager();
+ }
+
+ @SuppressWarnings("rawtypes")
+ public TreeCache getTreeCache() {
+ return treeCache;
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/impl/StaticContentCacheManagerImpl.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/impl/StaticContentCacheManagerImpl.java
new file mode 100644
index 0000000..d974b40
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/impl/StaticContentCacheManagerImpl.java
@@ -0,0 +1,42 @@
+/**
+ *
+ */
+package com.salesmanager.core.modules.cms.impl;
+
+/**
+ * Cache manager to handle static content data in Infinispan cache.
+ * static content data can be of following type
+ * <pre>
+ * 1. CSS files.
+ * 2. JS Files.
+ * 3. Digital Data.
+ * </pre>
+ * @author Umesh Awasthi
+ * @version 1.2
+ *
+ *
+ */
+public class StaticContentCacheManagerImpl extends CacheManagerImpl
+{
+ private static StaticContentCacheManagerImpl cacheManager = null;
+ private final static String NAMED_CACHE = "FilesRepository";
+
+
+ private StaticContentCacheManagerImpl() {
+
+ super.init(NAMED_CACHE);
+
+
+ }
+
+ public static StaticContentCacheManagerImpl getInstance() {
+
+ if(cacheManager==null) {
+ cacheManager = new StaticContentCacheManagerImpl();
+ }
+
+ return cacheManager;
+
+
+ }
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/impl/StoreCacheManagerImpl.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/impl/StoreCacheManagerImpl.java
new file mode 100644
index 0000000..dd13a92
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/impl/StoreCacheManagerImpl.java
@@ -0,0 +1,42 @@
+package com.salesmanager.core.modules.cms.impl;
+
+
+
+/**
+ * Used for managing images
+ * @author casams1
+ *
+ */
+public class StoreCacheManagerImpl extends CacheManagerImpl {
+
+
+ private static StoreCacheManagerImpl cacheManager = null;
+ private final static String NAMED_CACHE = "StoreRepository";
+
+
+
+
+ private StoreCacheManagerImpl() {
+
+ super.init(NAMED_CACHE);
+
+
+ }
+
+
+ public static StoreCacheManagerImpl getInstance() {
+
+ if(cacheManager==null) {
+ cacheManager = new StoreCacheManagerImpl();
+
+ }
+
+ return cacheManager;
+
+
+ }
+
+
+
+}
+
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/impl/VendorCacheManager.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/impl/VendorCacheManager.java
new file mode 100644
index 0000000..ea7d509
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/impl/VendorCacheManager.java
@@ -0,0 +1,41 @@
+package com.salesmanager.core.modules.cms.impl;
+
+import org.infinispan.manager.DefaultCacheManager;
+import org.infinispan.manager.EmbeddedCacheManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class VendorCacheManager {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(VendorCacheManager.class);
+ private EmbeddedCacheManager manager = null;
+ private static VendorCacheManager vendorCacheManager = null;
+ private String repositoryFileName = "cms/infinispan_configuration.xml";
+
+
+
+ private VendorCacheManager(){
+
+ try {
+ manager = new DefaultCacheManager(repositoryFileName);
+ } catch (Exception e) {
+ LOGGER.error("Cannot start manager " + e.toString());
+ }
+
+ }
+
+
+ public static VendorCacheManager getInstance() {
+ if(vendorCacheManager==null) {
+ vendorCacheManager = new VendorCacheManager();
+
+ }
+ return vendorCacheManager;
+ }
+
+
+ public EmbeddedCacheManager getManager() {
+ return manager;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/product/CmsImageFileManagerInfinispanImpl.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/product/CmsImageFileManagerInfinispanImpl.java
new file mode 100755
index 0000000..514c14f
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/product/CmsImageFileManagerInfinispanImpl.java
@@ -0,0 +1,515 @@
+package com.salesmanager.core.modules.cms.product;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.net.FileNameMap;
+import java.net.URLConnection;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.commons.io.IOUtils;
+import org.infinispan.tree.Fqn;
+import org.infinispan.tree.Node;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.file.ProductImageSize;
+import com.salesmanager.core.business.catalog.product.model.image.ProductImage;
+import com.salesmanager.core.business.content.model.FileContentType;
+import com.salesmanager.core.business.content.model.ImageContentFile;
+import com.salesmanager.core.business.content.model.OutputContentFile;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.constants.Constants;
+import com.salesmanager.core.modules.cms.impl.CacheManager;
+
+/**
+ * Manager for storing in retrieving image files from the CMS This is a layer on top of Infinispan
+ * https://docs.jboss.org/author/display/ISPN/Tree+API+Module
+ *
+ * Manages
+ * - Product images
+ * @author Carl Samson
+ */
+public class CmsImageFileManagerInfinispanImpl
+ implements ProductImagePut, ProductImageGet, ProductImageRemove
+{
+
+ private static final Logger LOGGER = LoggerFactory.getLogger( CmsImageFileManagerInfinispanImpl.class );
+
+ private static CmsImageFileManagerInfinispanImpl fileManager = null;
+
+ private final static String ROOT_NAME = "product-merchant";
+
+ private final static String SMALL = "SMALL";
+ private final static String LARGE = "LARGE";
+
+ private String rootName = ROOT_NAME;
+
+ private CacheManager cacheManager;
+
+ /**
+ * Requires to stop the engine when image servlet un-deploys
+ */
+ public void stopFileManager()
+ {
+
+ try
+ {
+ cacheManager.getManager().stop();
+ LOGGER.info( "Stopping CMS" );
+ }
+ catch ( Exception e )
+ {
+ LOGGER.error( "Error while stopping CmsImageFileManager", e );
+ }
+ }
+
+ public static CmsImageFileManagerInfinispanImpl getInstance()
+ {
+
+ if ( fileManager == null )
+ {
+ fileManager = new CmsImageFileManagerInfinispanImpl();
+ }
+
+ return fileManager;
+
+ }
+
+ private CmsImageFileManagerInfinispanImpl()
+ {
+
+ }
+
+ /**
+ * root -productFiles -merchant-id PRODUCT-ID(key) -> CacheAttribute(value) - image 1 - image 2 - image 3
+ */
+
+ @Override
+ public void addProductImage( ProductImage productImage,
+ ImageContentFile contentImage )
+ throws ServiceException
+ {
+
+ if ( cacheManager.getTreeCache() == null )
+ {
+ throw new ServiceException( "CmsImageFileManagerInfinispan has a null cacheManager.getTreeCache()" );
+ }
+
+ try
+ {
+
+ // node
+ StringBuilder nodePath = new StringBuilder();
+ nodePath.append(productImage.getProduct().getMerchantStore().getCode()).append(Constants.SLASH).append(productImage.getProduct().getSku()).append(Constants.SLASH);
+
+
+ if(contentImage.getFileContentType().name().equals(FileContentType.PRODUCT.name())) {
+ nodePath.append(SMALL);
+ } else if(contentImage.getFileContentType().name().equals(FileContentType.PRODUCTLG.name())) {
+ nodePath.append(LARGE);
+ }
+
+ Node<String, Object> productNode = this.getNode(nodePath.toString());
+
+
+ InputStream isFile = contentImage.getFile();
+
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ IOUtils.copy( isFile, output );
+
+
+ // object for a given product containing all images
+ productNode.put(contentImage.getFileName(), output.toByteArray());
+
+
+ }
+ catch ( Exception e )
+ {
+
+ throw new ServiceException( e );
+
+ }
+
+ }
+
+ @Override
+ public OutputContentFile getProductImage( ProductImage productImage )
+ throws ServiceException
+ {
+
+ return getProductImage(productImage.getProduct().getMerchantStore().getCode(),productImage.getProduct().getSku(),productImage.getProductImage());
+
+ }
+
+
+ public List<OutputContentFile> getImages( MerchantStore store, FileContentType imageContentType )
+ throws ServiceException
+ {
+
+ return getImages(store.getCode(),imageContentType);
+
+ }
+
+ @Override
+ public List<OutputContentFile> getImages( Product product )
+ throws ServiceException
+ {
+
+ if ( cacheManager.getTreeCache() == null )
+ {
+ throw new ServiceException( "CmsImageFileManagerInfinispan has a null cacheManager.getTreeCache()" );
+ }
+
+ List<OutputContentFile> images = new ArrayList<OutputContentFile>();
+
+
+ try
+ {
+
+
+ FileNameMap fileNameMap = URLConnection.getFileNameMap();
+ StringBuilder nodePath = new StringBuilder();
+ nodePath.append(product.getMerchantStore().getCode());
+
+ Node<String, Object> merchantNode = this.getNode(nodePath.toString());
+
+ if ( merchantNode == null )
+ {
+ return null;
+ }
+
+
+ for(String key : merchantNode.getKeys()) {
+
+ byte[] imageBytes = (byte[])merchantNode.get( key );
+
+ OutputContentFile contentImage = new OutputContentFile();
+
+ InputStream input = new ByteArrayInputStream( imageBytes );
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ IOUtils.copy( input, output );
+
+ String contentType = fileNameMap.getContentTypeFor( key );
+
+ contentImage.setFile( output );
+ contentImage.setMimeType( contentType );
+ contentImage.setFileName( key );
+
+ images.add( contentImage );
+
+
+ }
+
+
+ }
+
+ catch ( Exception e )
+ {
+ throw new ServiceException( e );
+ }
+ finally
+ {
+
+ }
+
+ return images;
+ }
+
+
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public void removeImages( final String merchantStoreCode )
+ throws ServiceException
+ {
+ if ( cacheManager.getTreeCache() == null )
+ {
+ throw new ServiceException( "CmsImageFileManagerInfinispan has a null cacheManager.getTreeCache()" );
+ }
+
+ try
+ {
+
+
+ final StringBuilder merchantPath = new StringBuilder();
+ merchantPath.append( getRootName()).append(merchantStoreCode );
+ cacheManager.getTreeCache().getRoot().remove(merchantPath.toString());
+
+
+
+ }
+ catch ( Exception e )
+ {
+ throw new ServiceException( e );
+ }
+ finally
+ {
+
+ }
+
+ }
+
+
+ @Override
+ public void removeProductImage( ProductImage productImage )
+ throws ServiceException
+ {
+
+ if ( cacheManager.getTreeCache() == null )
+ {
+ throw new ServiceException( "CmsImageFileManagerInfinispan has a null cacheManager.getTreeCache()" );
+ }
+
+ try
+ {
+
+
+ StringBuilder nodePath = new StringBuilder();
+ nodePath.append(productImage.getProduct().getMerchantStore().getCode()).append(Constants.SLASH).append(productImage.getProduct().getSku());
+
+
+ Node<String, Object> productNode = this.getNode(nodePath.toString());
+ productNode.remove(productImage.getProductImage());
+
+
+
+
+
+ }
+ catch ( Exception e )
+ {
+ throw new ServiceException( e );
+ }
+ finally
+ {
+
+ }
+
+ }
+
+ @Override
+ public void removeProductImages( Product product )
+ throws ServiceException
+ {
+
+ if ( cacheManager.getTreeCache() == null )
+ {
+ throw new ServiceException( "CmsImageFileManagerInfinispan has a null cacheManager.getTreeCache()" );
+ }
+
+ try
+ {
+
+
+ StringBuilder nodePath = new StringBuilder();
+ nodePath.append(product.getMerchantStore().getCode());
+
+
+ Node<String, Object> merchantNode = this.getNode(nodePath.toString());
+
+ merchantNode.remove(product.getSku());
+
+
+
+
+ }
+ catch ( Exception e )
+ {
+ throw new ServiceException( e );
+ }
+ finally
+ {
+
+ }
+
+ }
+
+
+ @Override
+ public List<OutputContentFile> getImages(final String merchantStoreCode,
+ FileContentType imageContentType) throws ServiceException {
+ if ( cacheManager.getTreeCache() == null )
+ {
+ throw new ServiceException( "CmsImageFileManagerInfinispan has a null cacheManager.getTreeCache()" );
+ }
+ List<OutputContentFile> images = new ArrayList<OutputContentFile>();
+ FileNameMap fileNameMap = URLConnection.getFileNameMap();
+
+ try
+ {
+
+
+ StringBuilder nodePath = new StringBuilder();
+ nodePath.append(merchantStoreCode);
+
+
+ Node<String, Object> merchantNode = this.getNode(nodePath.toString());
+
+ Set<Node<String,Object>> childs = merchantNode.getChildren();
+
+ Iterator<Node<String,Object>> iterator = childs.iterator();
+ //TODO image sizes
+ while(iterator.hasNext()) {
+
+ Node<String,Object> node = iterator.next();
+
+ for(String key : node.getKeys()) {
+
+
+ byte[] imageBytes = (byte[])merchantNode.get( key );
+
+ OutputContentFile contentImage = new OutputContentFile();
+
+ InputStream input = new ByteArrayInputStream( imageBytes );
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ IOUtils.copy( input, output );
+
+ String contentType = fileNameMap.getContentTypeFor( key );
+
+ contentImage.setFile( output );
+ contentImage.setMimeType( contentType );
+ contentImage.setFileName( key );
+
+ images.add( contentImage );
+
+
+ }
+
+ }
+
+
+
+
+ }
+ catch ( Exception e )
+ {
+ throw new ServiceException( e );
+ }
+ finally
+ {
+
+ }
+
+ return images;
+ }
+
+ @Override
+ public OutputContentFile getProductImage(String merchantStoreCode,
+ String productCode, String imageName) throws ServiceException {
+ return getProductImage(merchantStoreCode, productCode, imageName, ProductImageSize.SMALL.name());
+ }
+
+ @Override
+ public OutputContentFile getProductImage(String merchantStoreCode,
+ String productCode, String imageName, ProductImageSize size)
+ throws ServiceException {
+ return getProductImage(merchantStoreCode, productCode, imageName, size.name());
+ }
+
+ private OutputContentFile getProductImage(String merchantStoreCode,
+ String productCode, String imageName, String size) throws ServiceException {
+
+ if ( cacheManager.getTreeCache() == null )
+ {
+ throw new ServiceException( "CmsImageFileManagerInfinispan has a null cacheManager.getTreeCache()" );
+ }
+ InputStream input = null;
+ OutputContentFile contentImage = new OutputContentFile();
+ try
+ {
+
+ FileNameMap fileNameMap = URLConnection.getFileNameMap();
+
+ //SMALL by default
+ StringBuilder nodePath = new StringBuilder();
+ nodePath.append(merchantStoreCode).append(Constants.SLASH).append(productCode).append(Constants.SLASH).append(size);
+
+ Node<String,Object> productNode = this.getNode(nodePath.toString());
+
+ byte[] imageBytes = (byte[])productNode.get( imageName );
+
+
+
+ input = new ByteArrayInputStream( imageBytes );
+ ByteArrayOutputStream output = new ByteArrayOutputStream();
+ IOUtils.copy( input, output );
+
+ String contentType = fileNameMap.getContentTypeFor( imageName );
+
+ contentImage.setFile( output );
+ contentImage.setMimeType( contentType );
+ contentImage.setFileName( imageName );
+
+
+
+ }
+ catch ( Exception e )
+ {
+ throw new ServiceException( e );
+ }
+ finally
+ {
+ if ( input != null )
+ {
+ try
+ {
+ input.close();
+ }
+ catch ( Exception ignore )
+ {
+ }
+ }
+ }
+
+ return contentImage;
+
+ }
+
+
+ @SuppressWarnings("unchecked")
+ private Node<String, Object> getNode( final String node )
+ {
+ LOGGER.debug( "Fetching node for store {} from Infinispan", node );
+ final StringBuilder merchantPath = new StringBuilder();
+ merchantPath.append( getRootName() ).append(node);
+
+ Fqn contentFilesFqn = Fqn.fromString(merchantPath.toString());
+
+ Node<String,Object> nd = cacheManager.getTreeCache().getRoot().getChild(contentFilesFqn);
+
+ if(nd==null) {
+
+ cacheManager.getTreeCache().getRoot().addChild(contentFilesFqn);
+ nd = cacheManager.getTreeCache().getRoot().getChild(contentFilesFqn);
+
+ }
+
+ return nd;
+
+ }
+
+ public CacheManager getCacheManager() {
+ return cacheManager;
+ }
+
+ public void setCacheManager(CacheManager cacheManager) {
+ this.cacheManager = cacheManager;
+ }
+
+ public void setRootName(String rootName) {
+ this.rootName = rootName;
+ }
+
+ public String getRootName() {
+ return rootName;
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/product/ProductFileManager.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/product/ProductFileManager.java
new file mode 100755
index 0000000..63c2417
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/product/ProductFileManager.java
@@ -0,0 +1,11 @@
+package com.salesmanager.core.modules.cms.product;
+
+
+
+
+public abstract class ProductFileManager implements ProductImagePut, ProductImageGet, ProductImageRemove {
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/product/ProductFileManagerImpl.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/product/ProductFileManagerImpl.java
new file mode 100755
index 0000000..dce5a90
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/product/ProductFileManagerImpl.java
@@ -0,0 +1,356 @@
+package com.salesmanager.core.modules.cms.product;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.net.FileNameMap;
+import java.net.URLConnection;
+import java.util.List;
+
+import javax.imageio.ImageIO;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.file.ProductImageSize;
+import com.salesmanager.core.business.catalog.product.model.image.ProductImage;
+import com.salesmanager.core.business.content.model.FileContentType;
+import com.salesmanager.core.business.content.model.ImageContentFile;
+import com.salesmanager.core.business.content.model.OutputContentFile;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.constants.Constants;
+import com.salesmanager.core.utils.CoreConfiguration;
+import com.salesmanager.core.utils.ProductImageCropUtils;
+import com.salesmanager.core.utils.ProductImageSizeUtils;
+
+
+public class ProductFileManagerImpl extends ProductFileManager {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ProductFileManagerImpl.class);
+
+
+ private ProductImagePut uploadImage;
+ private ProductImageGet getImage;
+ private ProductImageRemove removeImage;
+
+ private CoreConfiguration configuration;
+
+ private final static String PRODUCT_IMAGE_HEIGHT_SIZE = "PRODUCT_IMAGE_HEIGHT_SIZE";
+ private final static String PRODUCT_IMAGE_WIDTH_SIZE = "PRODUCT_IMAGE_WIDTH_SIZE";
+ private final static String CROP_UPLOADED_IMAGES ="CROP_UPLOADED_IMAGES";
+
+
+ public CoreConfiguration getConfiguration() {
+ return configuration;
+ }
+
+
+ public void setConfiguration(CoreConfiguration configuration) {
+ this.configuration = configuration;
+ }
+
+
+ public ProductImageRemove getRemoveImage() {
+ return removeImage;
+ }
+
+
+ public void setRemoveImage(ProductImageRemove removeImage) {
+ this.removeImage = removeImage;
+ }
+
+
+ public void addProductImage(ProductImage productImage, ImageContentFile contentImage)
+ throws ServiceException {
+
+
+ try {
+
+ /** copy to input stream **/
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ // Fake code simulating the copy
+ // You can generally do better with nio if you need...
+ // And please, unlike me, do something about the Exceptions :D
+ byte[] buffer = new byte[1024];
+ int len;
+ while ((len = contentImage.getFile().read(buffer)) > -1 ) {
+ baos.write(buffer, 0, len);
+ }
+ baos.flush();
+
+ // Open new InputStreams using the recorded bytes
+ // Can be repeated as many times as you wish
+ InputStream is1 = new ByteArrayInputStream(baos.toByteArray());
+ InputStream is2 = new ByteArrayInputStream(baos.toByteArray());
+
+ BufferedImage bufferedImage = ImageIO.read(is2);
+ //contentImage.setBufferedImage(bufferedImage);
+ contentImage.setFile(is1);
+
+
+ //upload original -- L
+ contentImage.setFileContentType(FileContentType.PRODUCTLG);
+ uploadImage.addProductImage(productImage, contentImage);
+
+/* //default large
+ InputContentImage largeContentImage = new InputContentImage(ImageContentType.PRODUCT);
+ largeContentImage.setFile(contentImage.getFile());
+ largeContentImage.setDefaultImage(productImage.isDefaultImage());
+ largeContentImage.setImageName(new StringBuilder().append("L-").append(productImage.getProductImage()).toString());
+
+
+ uploadImage.uploadProductImage(configuration, productImage, largeContentImage);*/
+
+/* //default small
+ InputContentImage smallContentImage = new InputContentImage(ImageContentType.PRODUCT);
+ smallContentImage.setFile(contentImage.getFile());
+ smallContentImage.setDefaultImage(productImage.isDefaultImage());
+ smallContentImage.setImageName(new StringBuilder().append("S-").append(productImage.getProductImage()).toString());
+
+ uploadImage.uploadProductImage(configuration, productImage, smallContentImage);*/
+
+
+ //get template properties file
+
+ String slargeImageHeight = configuration.getProperty(PRODUCT_IMAGE_HEIGHT_SIZE);
+ String slargeImageWidth = configuration.getProperty(PRODUCT_IMAGE_WIDTH_SIZE);
+
+ //String ssmallImageHeight = configuration.getProperty("SMALL_IMAGE_HEIGHT_SIZE");
+ //String ssmallImageWidth = configuration.getProperty("SMALL_IMAGE_WIDTH_SIZE");
+
+
+ if(!StringUtils.isBlank(slargeImageHeight) && !StringUtils.isBlank(slargeImageWidth)) { //&& !StringUtils.isBlank(ssmallImageHeight) && !StringUtils.isBlank(ssmallImageWidth)) {
+
+
+ FileNameMap fileNameMap = URLConnection.getFileNameMap();
+
+ String contentType = fileNameMap.getContentTypeFor(contentImage.getFileName());
+ String extension = null;
+ if(contentType!=null) {
+ extension = contentType.substring(contentType.indexOf("/")+1,contentType.length());
+ }
+
+ if(extension==null){
+ extension="jpeg";
+ }
+
+
+ int largeImageHeight = Integer.parseInt(slargeImageHeight);
+ int largeImageWidth = Integer.parseInt(slargeImageWidth);
+
+ if(largeImageHeight<=0 || largeImageWidth<=0) {
+ String sizeMsg = "Image configuration set to an invalid value [PRODUCT_IMAGE_HEIGHT_SIZE] " + largeImageHeight + " , [PRODUCT_IMAGE_WIDTH_SIZE] " + largeImageWidth;
+ LOGGER.error(sizeMsg);
+ throw new ServiceException(sizeMsg);
+ }
+
+ if(!StringUtils.isBlank(configuration.getProperty(CROP_UPLOADED_IMAGES)) && configuration.getProperty(CROP_UPLOADED_IMAGES).equals(Constants.TRUE)) {
+ //crop image
+ ProductImageCropUtils utils = new ProductImageCropUtils(bufferedImage, largeImageWidth, largeImageHeight);
+ if(utils.isCropeable()) {
+ bufferedImage = utils.getCroppedImage();
+ }
+ }
+
+
+ //TODO print cropped image
+
+
+ //do not keep a large image for now, just take care of the regular image and a small image
+
+ //resize large
+ //ByteArrayOutputStream output = new ByteArrayOutputStream();
+ BufferedImage largeResizedImage = ProductImageSizeUtils.resizeWithRatio(bufferedImage, largeImageWidth, largeImageHeight);
+
+
+ File tempLarge = File.createTempFile(new StringBuilder().append(productImage.getProduct().getId()).append("tmpLarge").toString(), "." + extension );
+ ImageIO.write(largeResizedImage, extension, tempLarge);
+
+ FileInputStream isLarge = new FileInputStream(tempLarge);
+
+
+ //IOUtils.copy(isLarge, output);
+
+
+ ImageContentFile largeContentImage = new ImageContentFile();
+ largeContentImage.setFileContentType(FileContentType.PRODUCT);
+ largeContentImage.setFileName(productImage.getProductImage());
+ largeContentImage.setFile(isLarge);
+
+
+ //largeContentImage.setBufferedImage(bufferedImage);
+
+ //largeContentImage.setFile(output);
+ //largeContentImage.setDefaultImage(false);
+ //largeContentImage.setImageName(new StringBuilder().append("L-").append(productImage.getProductImage()).toString());
+
+
+ uploadImage.addProductImage(productImage, largeContentImage);
+
+ //output.flush();
+ //output.close();
+
+ tempLarge.delete();
+
+ //now upload original
+
+
+
+/* //resize small
+ BufferedImage smallResizedImage = ProductImageSizeUtils.resize(cropped, smallImageWidth, smallImageHeight);
+ File tempSmall = File.createTempFile(new StringBuilder().append(productImage.getProduct().getId()).append("tmpSmall").toString(), "." + extension );
+ ImageIO.write(smallResizedImage, extension, tempSmall);
+
+ //byte[] is = IOUtils.toByteArray(new FileInputStream(tempSmall));
+
+ FileInputStream isSmall = new FileInputStream(tempSmall);
+
+ output = new ByteArrayOutputStream();
+ IOUtils.copy(isSmall, output);
+
+
+ smallContentImage = new InputContentImage(ImageContentType.PRODUCT);
+ smallContentImage.setFile(output);
+ smallContentImage.setDefaultImage(false);
+ smallContentImage.setImageName(new StringBuilder().append("S-").append(productImage.getProductImage()).toString());
+
+ uploadImage.uploadProductImage(configuration, productImage, smallContentImage);
+
+ output.flush();
+ output.close();
+
+ tempSmall.delete();*/
+
+
+
+ } else {
+ //small will be the same as the original
+ contentImage.setFileContentType(FileContentType.PRODUCT);
+ uploadImage.addProductImage(productImage, contentImage);
+ }
+
+
+
+
+
+
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ } finally {
+ try {
+ productImage.getImage().close();
+ } catch(Exception ignore) {}
+ }
+
+}
+
+
+ public OutputContentFile getProductImage(ProductImage productImage) throws ServiceException {
+ //will return original
+ return getImage.getProductImage(productImage);
+ }
+
+
+ @Override
+ public List<OutputContentFile> getImages(final String merchantStoreCode, FileContentType imageContentType)
+ throws ServiceException {
+ //will return original
+ return getImage.getImages(merchantStoreCode,FileContentType.PRODUCT);
+ }
+
+ @Override
+ public List<OutputContentFile> getImages(Product product)
+ throws ServiceException {
+ return getImage.getImages(product);
+ }
+
+
+
+
+
+
+ @Override
+ public void removeProductImage(ProductImage productImage)
+ throws ServiceException {
+
+ this.removeImage.removeProductImage(productImage);
+
+/* ProductImage large = new ProductImage();
+ large.setProduct(productImage.getProduct());
+ large.setProductImage("L" + productImage.getProductImage());
+
+ this.removeImage.removeProductImage(large);
+
+ ProductImage small = new ProductImage();
+ small.setProduct(productImage.getProduct());
+ small.setProductImage("S" + productImage.getProductImage());
+
+ this.removeImage.removeProductImage(small);*/
+
+ }
+
+
+ @Override
+ public void removeProductImages(Product product) throws ServiceException {
+
+ this.removeImage.removeProductImages(product);
+
+ }
+
+
+ @Override
+ public void removeImages(final String merchantStoreCode) throws ServiceException {
+
+ this.removeImage.removeImages(merchantStoreCode);
+
+ }
+
+
+ public ProductImagePut getUploadImage() {
+ return uploadImage;
+ }
+
+
+ public void setUploadImage(ProductImagePut uploadImage) {
+ this.uploadImage = uploadImage;
+ }
+
+
+
+
+ public ProductImageGet getGetImage() {
+ return getImage;
+ }
+
+
+ public void setGetImage(ProductImageGet getImage) {
+ this.getImage = getImage;
+ }
+
+
+ @Override
+ public OutputContentFile getProductImage(String merchantStoreCode,
+ String productCode, String imageName) throws ServiceException {
+ return getImage.getProductImage(merchantStoreCode, productCode, imageName);
+ }
+
+
+
+ @Override
+ public OutputContentFile getProductImage(String merchantStoreCode,
+ String productCode, String imageName, ProductImageSize size)
+ throws ServiceException {
+ return getImage.getProductImage(merchantStoreCode, productCode, imageName, size);
+ }
+
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/product/ProductImageGet.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/product/ProductImageGet.java
new file mode 100755
index 0000000..ab21b7d
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/product/ProductImageGet.java
@@ -0,0 +1,28 @@
+package com.salesmanager.core.modules.cms.product;
+
+import java.util.List;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.file.ProductImageSize;
+import com.salesmanager.core.business.catalog.product.model.image.ProductImage;
+import com.salesmanager.core.business.content.model.OutputContentFile;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.modules.cms.common.ImageGet;
+
+public interface ProductImageGet extends ImageGet{
+
+ /**
+ * Used for accessing the path directly
+ * @param merchantStoreCode
+ * @param product
+ * @param imageName
+ * @return
+ * @throws ServiceException
+ */
+ public OutputContentFile getProductImage(final String merchantStoreCode, final String productCode, final String imageName) throws ServiceException;
+ public OutputContentFile getProductImage(final String merchantStoreCode, final String productCode, final String imageName, final ProductImageSize size) throws ServiceException;
+ public OutputContentFile getProductImage(ProductImage productImage) throws ServiceException;
+ public List<OutputContentFile> getImages(Product product) throws ServiceException;
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/product/ProductImagePut.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/product/ProductImagePut.java
new file mode 100755
index 0000000..34bc3a0
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/product/ProductImagePut.java
@@ -0,0 +1,14 @@
+package com.salesmanager.core.modules.cms.product;
+
+import com.salesmanager.core.business.catalog.product.model.image.ProductImage;
+import com.salesmanager.core.business.content.model.ImageContentFile;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+
+
+public interface ProductImagePut {
+
+
+ public void addProductImage(ProductImage productImage, ImageContentFile contentImage) throws ServiceException;
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/cms/product/ProductImageRemove.java b/sm-core/src/main/java/com/salesmanager/core/modules/cms/product/ProductImageRemove.java
new file mode 100755
index 0000000..a81776f
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/cms/product/ProductImageRemove.java
@@ -0,0 +1,17 @@
+package com.salesmanager.core.modules.cms.product;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.image.ProductImage;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.modules.cms.common.ImageRemove;
+
+
+public interface ProductImageRemove extends ImageRemove {
+
+
+ public void removeProductImage(ProductImage productImage) throws ServiceException;
+ public void removeProductImages(Product product) throws ServiceException;
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/email/Email.java b/sm-core/src/main/java/com/salesmanager/core/modules/email/Email.java
new file mode 100755
index 0000000..5a6ce76
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/email/Email.java
@@ -0,0 +1,70 @@
+package com.salesmanager.core.modules.email;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+public class Email implements Serializable {
+
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 6481794982612826257L;
+ private String from;
+ private String fromEmail;
+ private String to;
+ private String subject;
+ private String templateName;
+
+ private Map<String,String> templateTokens = new HashMap<String,String>();
+
+ public String getFrom() {
+ return from;
+ }
+
+ public void setFrom(String from) {
+ this.from = from;
+ }
+
+ public String getTo() {
+ return to;
+ }
+
+ public void setTo(String to) {
+ this.to = to;
+ }
+
+ public String getSubject() {
+ return subject;
+ }
+
+ public void setSubject(String subject) {
+ this.subject = subject;
+ }
+
+ public String getTemplateName() {
+ return templateName;
+ }
+
+ public void setTemplateName(String templateName) {
+ this.templateName = templateName;
+ }
+
+ public Map<String, String> getTemplateTokens() {
+ return templateTokens;
+ }
+
+ public void setTemplateTokens(Map<String, String> templateTokens) {
+ this.templateTokens = templateTokens;
+ }
+
+ public void setFromEmail(String fromEmail) {
+ this.fromEmail = fromEmail;
+ }
+
+ public String getFromEmail() {
+ return fromEmail;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/email/EmailConfig.java b/sm-core/src/main/java/com/salesmanager/core/modules/email/EmailConfig.java
new file mode 100755
index 0000000..0820869
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/email/EmailConfig.java
@@ -0,0 +1,113 @@
+package com.salesmanager.core.modules.email;
+
+import org.json.simple.JSONAware;
+import org.json.simple.JSONObject;
+
+public class EmailConfig implements JSONAware {
+
+ private String host;
+ private String port;
+ private String protocol;
+ private String username;
+ private String password;
+ private boolean smtpAuth = false;
+ private boolean starttls = false;
+
+ private String emailTemplatesPath = null;
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public String toJSONString() {
+ JSONObject data = new JSONObject();
+ data.put("host", this.getHost());
+ data.put("port", this.getPort());
+ data.put("protocol", this.getProtocol());
+ data.put("username", this.getUsername());
+ data.put("smtpAuth", this.isSmtpAuth());
+ data.put("starttls", this.isStarttls());
+ data.put("password", this.getPassword());
+ return data.toJSONString();
+ }
+
+
+
+ public boolean isSmtpAuth() {
+ return smtpAuth;
+ }
+ public void setSmtpAuth(boolean smtpAuth) {
+ this.smtpAuth = smtpAuth;
+ }
+ public boolean isStarttls() {
+ return starttls;
+ }
+ public void setStarttls(boolean starttls) {
+ this.starttls = starttls;
+ }
+ public void setEmailTemplatesPath(String emailTemplatesPath) {
+ this.emailTemplatesPath = emailTemplatesPath;
+ }
+ public String getEmailTemplatesPath() {
+ return emailTemplatesPath;
+ }
+
+
+
+ public String getHost() {
+ return host;
+ }
+
+
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+
+
+ public String getPort() {
+ return port;
+ }
+
+
+
+ public void setPort(String port) {
+ this.port = port;
+ }
+
+
+
+ public String getProtocol() {
+ return protocol;
+ }
+
+
+
+ public void setProtocol(String protocol) {
+ this.protocol = protocol;
+ }
+
+
+
+ public String getUsername() {
+ return username;
+ }
+
+
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+
+
+ public String getPassword() {
+ return password;
+ }
+
+
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/email/HtmlEmailSender.java b/sm-core/src/main/java/com/salesmanager/core/modules/email/HtmlEmailSender.java
new file mode 100755
index 0000000..388d01e
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/email/HtmlEmailSender.java
@@ -0,0 +1,10 @@
+package com.salesmanager.core.modules.email;
+
+
+public interface HtmlEmailSender {
+
+ public void send(final Email email) throws Exception;
+
+ public void setEmailConfig(EmailConfig emailConfig);
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/email/HtmlEmailSenderImpl.java b/sm-core/src/main/java/com/salesmanager/core/modules/email/HtmlEmailSenderImpl.java
new file mode 100755
index 0000000..1708523
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/email/HtmlEmailSenderImpl.java
@@ -0,0 +1,195 @@
+package com.salesmanager.core.modules.email;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.StringWriter;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.mail.BodyPart;
+import javax.mail.Message;
+import javax.mail.MessagingException;
+import javax.mail.Multipart;
+import javax.mail.internet.InternetAddress;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.MimeMessage;
+import javax.mail.internet.MimeMultipart;
+
+import org.springframework.mail.MailPreparationException;
+import org.springframework.mail.javamail.JavaMailSender;
+import org.springframework.mail.javamail.JavaMailSenderImpl;
+import org.springframework.mail.javamail.MimeMessagePreparator;
+
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateException;
+
+
+public class HtmlEmailSenderImpl implements HtmlEmailSender {
+
+ private static final String CHARSET = "UTF-8";
+ private Configuration freemarkerMailConfiguration;
+ private JavaMailSender mailSender;
+ private EmailConfig emailConfig;
+
+ private final static String TEMPLATE_PATH = "templates/email";
+
+ @Override
+ public void send(Email email)
+ throws Exception {
+
+ final String eml = email.getFrom();
+ final String from = email.getFromEmail();
+ final String to = email.getTo();
+ final String subject = email.getSubject();
+ final String tmpl = email.getTemplateName();
+ final Map<String,String> templateTokens = email.getTemplateTokens();
+
+ MimeMessagePreparator preparator = new MimeMessagePreparator() {
+ public void prepare(MimeMessage mimeMessage)
+ throws MessagingException, IOException {
+
+ JavaMailSenderImpl impl = (JavaMailSenderImpl)mailSender;
+ // if email configuration is present in Database, use the same
+ if(emailConfig != null) {
+ impl.setProtocol(emailConfig.getProtocol());
+ impl.setHost(emailConfig.getHost());
+ impl.setPort(Integer.parseInt(emailConfig.getPort()));
+ impl.setUsername(emailConfig.getUsername());
+ impl.setPassword(emailConfig.getPassword());
+
+ Properties prop = new Properties();
+ prop.put("mail.smtp.auth", emailConfig.isSmtpAuth());
+ prop.put("mail.smtp.starttls.enable", emailConfig.isStarttls());
+ impl.setJavaMailProperties(prop);
+ }
+
+ mimeMessage.setRecipient(Message.RecipientType.TO, new InternetAddress(to));
+
+ InternetAddress inetAddress = new InternetAddress();
+
+ inetAddress.setPersonal(eml);
+ inetAddress.setAddress(from);
+
+ mimeMessage.setFrom(inetAddress);
+ mimeMessage.setSubject(subject);
+
+ Multipart mp = new MimeMultipart("alternative");
+
+ // Create a "text" Multipart message
+ BodyPart textPart = new MimeBodyPart();
+ freemarkerMailConfiguration.setClassForTemplateLoading(HtmlEmailSenderImpl.class, "/");
+ Template textTemplate = freemarkerMailConfiguration.getTemplate(new StringBuilder(TEMPLATE_PATH).append("").append("/").append(tmpl).toString());
+ final StringWriter textWriter = new StringWriter();
+ try {
+ textTemplate.process(templateTokens, textWriter);
+ } catch (TemplateException e) {
+ throw new MailPreparationException(
+ "Can't generate text mail", e);
+ }
+ textPart.setDataHandler(new javax.activation.DataHandler(
+ new javax.activation.DataSource() {
+ public InputStream getInputStream()
+ throws IOException {
+ //return new StringBufferInputStream(textWriter
+ // .toString());
+ return new ByteArrayInputStream(textWriter
+ .toString().getBytes(CHARSET));
+ }
+
+ public OutputStream getOutputStream()
+ throws IOException {
+ throw new IOException("Read-only data");
+ }
+
+ public String getContentType() {
+ return "text/plain";
+ }
+
+ public String getName() {
+ return "main";
+ }
+ }));
+ mp.addBodyPart(textPart);
+
+ // Create a "HTML" Multipart message
+ Multipart htmlContent = new MimeMultipart("related");
+ BodyPart htmlPage = new MimeBodyPart();
+ freemarkerMailConfiguration.setClassForTemplateLoading(HtmlEmailSenderImpl.class, "/");
+ Template htmlTemplate = freemarkerMailConfiguration.getTemplate(new StringBuilder(TEMPLATE_PATH).append("").append("/").append(tmpl).toString());
+ final StringWriter htmlWriter = new StringWriter();
+ try {
+ htmlTemplate.process(templateTokens, htmlWriter);
+ } catch (TemplateException e) {
+ throw new MailPreparationException(
+ "Can't generate HTML mail", e);
+ }
+ htmlPage.setDataHandler(new javax.activation.DataHandler(
+ new javax.activation.DataSource() {
+ public InputStream getInputStream()
+ throws IOException {
+ //return new StringBufferInputStream(htmlWriter
+ // .toString());
+ return new ByteArrayInputStream(textWriter
+ .toString().getBytes(CHARSET));
+ }
+
+ public OutputStream getOutputStream()
+ throws IOException {
+ throw new IOException("Read-only data");
+ }
+
+ public String getContentType() {
+ return "text/html";
+ }
+
+ public String getName() {
+ return "main";
+ }
+ }));
+ htmlContent.addBodyPart(htmlPage);
+ BodyPart htmlPart = new MimeBodyPart();
+ htmlPart.setContent(htmlContent);
+ mp.addBodyPart(htmlPart);
+
+ mimeMessage.setContent(mp);
+
+ // if(attachment!=null) {
+ // MimeMessageHelper messageHelper = new
+ // MimeMessageHelper(mimeMessage, true);
+ // messageHelper.addAttachment(attachmentFileName, attachment);
+ // }
+
+ }
+ };
+
+ mailSender.send(preparator);
+ }
+
+ public Configuration getFreemarkerMailConfiguration() {
+ return freemarkerMailConfiguration;
+ }
+
+ public void setFreemarkerMailConfiguration(Configuration freemarkerMailConfiguration) {
+ this.freemarkerMailConfiguration = freemarkerMailConfiguration;
+ }
+
+ public JavaMailSender getMailSender() {
+ return mailSender;
+ }
+
+ public void setMailSender(JavaMailSender mailSender) {
+ this.mailSender = mailSender;
+ }
+
+ public EmailConfig getEmailConfig() {
+ return emailConfig;
+ }
+
+ public void setEmailConfig(EmailConfig emailConfig) {
+ this.emailConfig = emailConfig;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/integration/IntegrationException.java b/sm-core/src/main/java/com/salesmanager/core/modules/integration/IntegrationException.java
new file mode 100644
index 0000000..cc6cd9d
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/integration/IntegrationException.java
@@ -0,0 +1,61 @@
+package com.salesmanager.core.modules.integration;
+
+import java.util.List;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+
+public class IntegrationException extends ServiceException {
+
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ public static final int ERROR_VALIDATION_SAVE = 100;
+ public static final int TRANSACTION_EXCEPTION = 99;
+
+ private List<String> errorFields;
+
+ private int errorCode = 0;
+
+ public int getErrorCode() {
+ return errorCode;
+ }
+
+ public void setErrorCode(int errorCode) {
+ this.errorCode = errorCode;
+ }
+
+ public IntegrationException(Exception e) {
+ super(e);
+ }
+
+ public IntegrationException(String message, Exception e) {
+ super(message,e);
+ }
+
+ public IntegrationException(int code, String message) {
+
+ super(message);
+ this.errorCode = code;
+ }
+
+ public IntegrationException(int code) {
+
+ this.errorCode = code;
+ }
+
+ public IntegrationException(String message) {
+ super(message);
+ }
+
+ public void setErrorFields(List<String> errorFields) {
+ this.errorFields = errorFields;
+ }
+
+ public List<String> getErrorFields() {
+ return errorFields;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/integration/payment/impl/BeanStreamPayment.java b/sm-core/src/main/java/com/salesmanager/core/modules/integration/payment/impl/BeanStreamPayment.java
new file mode 100644
index 0000000..71bacf4
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/integration/payment/impl/BeanStreamPayment.java
@@ -0,0 +1,755 @@
+package com.salesmanager.core.modules.integration.payment.impl;
+
+import java.io.BufferedReader;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.InputStreamReader;
+import java.math.BigDecimal;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.StringTokenizer;
+import java.util.UUID;
+
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.business.payments.model.CreditCardPayment;
+import com.salesmanager.core.business.payments.model.Payment;
+import com.salesmanager.core.business.payments.model.PaymentType;
+import com.salesmanager.core.business.payments.model.Transaction;
+import com.salesmanager.core.business.payments.model.TransactionType;
+import com.salesmanager.core.business.reference.country.service.CountryService;
+import com.salesmanager.core.business.reference.zone.service.ZoneService;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartItem;
+import com.salesmanager.core.business.system.model.IntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+import com.salesmanager.core.business.system.model.MerchantLog;
+import com.salesmanager.core.business.system.model.ModuleConfig;
+import com.salesmanager.core.business.system.service.MerchantLogService;
+import com.salesmanager.core.modules.integration.IntegrationException;
+import com.salesmanager.core.modules.integration.payment.model.PaymentModule;
+import com.salesmanager.core.utils.CreditCardUtils;
+import com.salesmanager.core.utils.ProductPriceUtils;
+
+public class BeanStreamPayment implements PaymentModule {
+
+ @Autowired
+ private ProductPriceUtils productPriceUtils;
+
+ @Autowired
+ private MerchantLogService merchantLogService;
+
+ @Autowired
+ private CountryService countryService;
+
+ @Autowired
+ private ZoneService zoneService;
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(BeanStreamPayment.class);
+
+ @Override
+ public Transaction initTransaction(MerchantStore store, Customer customer,
+ BigDecimal amount, Payment payment,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Transaction authorize(MerchantStore store, Customer customer,
+ List<ShoppingCartItem> items, BigDecimal amount, Payment payment,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+ return processTransaction(store, customer, TransactionType.AUTHORIZE,
+ amount,
+ payment,
+ configuration,
+ module);
+ }
+
+ @Override
+ public Transaction capture(MerchantStore store, Customer customer,
+ Order order, Transaction capturableTransaction,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+
+
+ try {
+
+
+
+ //authorize a preauth
+
+
+ String trnID = capturableTransaction.getTransactionDetails().get("TRANSACTIONID");
+
+ String amnt = productPriceUtils.getAdminFormatedAmount(store, order.getTotal());
+
+ /**
+ merchant_id=123456789&requestType=BACKEND
+ &trnType=PAC&username=user1234&password=pass1234&trnID=1000
+ 2115 --> requires also adjId [not documented]
+ **/
+
+ StringBuilder messageString = new StringBuilder();
+ messageString.append("requestType=BACKEND&");
+ messageString.append("merchant_id=").append(configuration.getIntegrationKeys().get("merchantid")).append("&");
+ messageString.append("trnType=").append("PAC").append("&");
+ messageString.append("username=").append(configuration.getIntegrationKeys().get("username")).append("&");
+ messageString.append("password=").append(configuration.getIntegrationKeys().get("password")).append("&");
+ messageString.append("trnAmount=").append(amnt).append("&");
+ messageString.append("adjId=").append(trnID).append("&");
+ messageString.append("trnID=").append(trnID);
+
+ LOGGER.debug("REQUEST SENT TO BEANSTREAM -> " + messageString.toString());
+
+
+
+ Transaction response = this.sendTransaction(null, store, messageString.toString(), "PAC", TransactionType.CAPTURE, PaymentType.CREDITCARD, order.getTotal(), configuration, module);
+
+ return response;
+
+ } catch(Exception e) {
+
+ if(e instanceof IntegrationException)
+ throw (IntegrationException)e;
+ throw new IntegrationException("Error while processing BeanStream transaction",e);
+
+ }
+
+ }
+
+ @Override
+ public Transaction authorizeAndCapture(MerchantStore store, Customer customer,
+ List<ShoppingCartItem> items, BigDecimal amount, Payment payment,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+ return processTransaction(
+ store,
+ customer,
+ TransactionType.AUTHORIZECAPTURE,
+ amount,
+ payment,
+ configuration,
+ module);
+ }
+
+ @Override
+ public Transaction refund(boolean partial, MerchantStore store, Transaction transaction,
+ Order order, BigDecimal amount,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+
+
+
+
+ HttpURLConnection conn = null;
+
+ try {
+
+
+ boolean bSandbox = false;
+ if (configuration.getEnvironment().equals("TEST")) {// sandbox
+ bSandbox = true;
+ }
+
+ String server = "";
+
+
+ ModuleConfig configs = module.getModuleConfigs().get("PROD");
+
+ if (bSandbox == true) {
+ configs = module.getModuleConfigs().get("TEST");
+ }
+
+ if(configs==null) {
+ throw new IntegrationException("Module not configured for TEST or PROD");
+ }
+
+
+ server = new StringBuffer().append(
+
+ configs.getScheme()).append("://")
+ .append(configs.getHost())
+ .append(":")
+ .append(configs.getPort())
+ .append(configs.getUri()).toString();
+
+ String trnID = transaction.getTransactionDetails().get("TRANSACTIONID");
+
+ String amnt = productPriceUtils.getAdminFormatedAmount(store, amount);
+
+ /**
+ merchant_id=123456789&requestType=BACKEND
+ &trnType=R&username=user1234&password=pass1234
+ &trnOrderNumber=1234&trnAmount=1.00&adjId=1000
+ 2115
+ **/
+ StringBuilder messageString = new StringBuilder();
+
+
+
+ messageString.append("requestType=BACKEND&");
+ messageString.append("merchant_id=").append(configuration.getIntegrationKeys().get("merchantid")).append("&");
+ messageString.append("trnType=").append("R").append("&");
+ messageString.append("username=").append(configuration.getIntegrationKeys().get("username")).append("&");
+ messageString.append("password=").append(configuration.getIntegrationKeys().get("password")).append("&");
+ messageString.append("trnOrderNumber=").append(transaction.getTransactionDetails().get("TRNORDERNUMBER")).append("&");
+ messageString.append("trnAmount=").append(amnt).append("&");
+ messageString.append("adjId=").append(trnID);
+
+ LOGGER.debug("REQUEST SENT TO BEANSTREAM -> " + messageString.toString());
+
+
+
+
+ URL postURL = new URL(server.toString());
+ conn = (HttpURLConnection) postURL.openConnection();
+
+
+
+
+ Transaction response = this.sendTransaction(null, store, messageString.toString(), "R", TransactionType.REFUND, PaymentType.CREDITCARD, amount, configuration, module);
+
+ return response;
+
+ } catch(Exception e) {
+
+ if(e instanceof IntegrationException)
+ throw (IntegrationException)e;
+ throw new IntegrationException("Error while processing BeanStream transaction",e);
+
+ } finally {
+
+
+ if (conn != null) {
+ try {
+ conn.disconnect();
+ } catch (Exception ignore) {
+ // TODO: handle exception
+ }
+ }
+ }
+
+
+
+ }
+
+
+ private Transaction sendTransaction(
+ String orderNumber,
+ MerchantStore store,
+ String transaction,
+ String beanstreamType,
+ TransactionType transactionType,
+ PaymentType paymentType,
+ BigDecimal amount,
+ IntegrationConfiguration configuration,
+ IntegrationModule module
+ ) throws IntegrationException {
+
+ String agent = "Mozilla/4.0";
+ String respText = "";
+ Map<String,String> nvp = null;
+ DataOutputStream output = null;
+ DataInputStream in = null;
+ BufferedReader is = null;
+ HttpURLConnection conn =null;
+ try {
+
+ //transaction = "requestType=BACKEND&merchant_id=300200260&trnType=P&username=carlito&password=shopizer001&orderNumber=caa71106-7e3f-4975-a657-a35904dc32a0&trnCardOwner=Carl Samson&trnCardNumber=5100000020002000&trnExpMonth=10&trnExpYear=14&trnCardCvd=123&trnAmount=77.01&ordName=Carl S&ordAddress1=358 Du Languedoc&ordCity=Victoria&ordProvince=BC&ordPostalCode=V8T2E7&ordCountry=CA&ordPhoneNumber=(444) 555-6666&ordEmailAddress=csamson777@yahoo.com";
+ /**
+ requestType=BACKEND&merchant_id=300200260
+ &trnType=P
+ &username=carlito&password=shopizer001
+ &orderNumber=caa71106-7e3f-4975-a657-a35904dc32a0
+ &trnCardOwner=Carl Samson
+ &trnCardNumber=5100000020002000
+ &trnExpMonth=10
+ &trnExpYear=14
+ &trnCardCvd=123
+ &trnAmount=77.01
+ &ordName=Carl S
+ &ordAddress1=378 Du Languedoc
+ &ordCity=Boucherville
+ &ordProvince=QC
+ &ordPostalCode=J4B8J9
+ &ordCountry=CA
+ &ordPhoneNumber=(444) 555-6666
+ &ordEmailAddress=test@yahoo.com
+ **/
+
+ /**
+ merchant_id=123456789&requestType=BACKEND
+ &trnType=P&trnOrderNumber=1234TEST&trnAmount=5.00&trnCardOwner=Joe+Test
+ &trnCardNumber=4030000010001234
+ &trnExpMonth=10
+ &trnExpYear=16
+ &ordName=Joe+Test
+ &ordAddress1=123+Test+Street
+ &ordCity=Victoria
+ &ordProvince=BC
+ &ordCountry=CA
+ &ordPostalCode=V8T2E7
+ &ordPhoneNumber=5555555555
+ &ordEmailAddress=joe%40testemail.com
+ **/
+
+
+
+ boolean bSandbox = false;
+ if (configuration.getEnvironment().equals("TEST")) {// sandbox
+ bSandbox = true;
+ }
+
+ String server = "";
+
+ ModuleConfig configs = module.getModuleConfigs().get("PROD");
+
+ if (bSandbox == true) {
+ configs = module.getModuleConfigs().get("TEST");
+ }
+
+ if(configs==null) {
+ throw new IntegrationException("Module not configured for TEST or PROD");
+ }
+
+
+ server = new StringBuffer().append(
+
+ configs.getScheme()).append("://")
+ .append(configs.getHost())
+ .append(":")
+ .append(configs.getPort())
+ .append(configs.getUri()).toString();
+
+
+
+ URL postURL = new URL(server.toString());
+ conn = (HttpURLConnection) postURL.openConnection();
+
+
+ // Set connection parameters. We need to perform input and output,
+ // so set both as true.
+ conn.setDoInput(true);
+ conn.setDoOutput(true);
+
+ // Set the content type we are POSTing. We impersonate it as
+ // encoded form data
+ conn.setRequestProperty("Content-Type",
+ "application/x-www-form-urlencoded");
+ conn.setRequestProperty("User-Agent", agent);
+
+ conn.setRequestProperty("Content-Length", String
+ .valueOf(transaction.length()));
+ conn.setRequestMethod("POST");
+
+ // get the output stream to POST to.
+ output = new DataOutputStream(conn.getOutputStream());
+ output.writeBytes(transaction);
+ output.flush();
+
+
+ // Read input from the input stream.
+ in = new DataInputStream(conn.getInputStream());
+ int rc = conn.getResponseCode();
+ if (rc != -1) {
+ is = new BufferedReader(new InputStreamReader(conn
+ .getInputStream()));
+ String _line = null;
+ while (((_line = is.readLine()) != null)) {
+ respText = respText + _line;
+ }
+
+ LOGGER.debug("BeanStream response -> " + respText.trim());
+
+ nvp = formatUrlResponse(respText.trim());
+ } else {
+ throw new IntegrationException("Invalid response from BeanStream, return code is " + rc);
+ }
+
+ //check
+ //trnApproved=1&trnId=10003067&messageId=1&messageText=Approved&trnOrderNumber=E40089&authCode=TEST&errorType=N&errorFields=
+
+ String transactionApproved = (String)nvp.get("TRNAPPROVED");
+ String transactionId = (String)nvp.get("TRNID");
+ String messageId = (String)nvp.get("MESSAGEID");
+ String messageText = (String)nvp.get("MESSAGETEXT");
+ String orderId = (String)nvp.get("TRNORDERNUMBER");
+ String authCode = (String)nvp.get("AUTHCODE");
+ String errorType = (String)nvp.get("ERRORTYPE");
+ String errorFields = (String)nvp.get("ERRORFIELDS");
+ if(!StringUtils.isBlank(orderNumber)) {
+ nvp.put("INTERNALORDERID", orderNumber);
+ }
+
+ if(StringUtils.isBlank(transactionApproved)) {
+ throw new IntegrationException("Required field transactionApproved missing from BeanStream response");
+ }
+
+ //errors
+ if(transactionApproved.equals("0")) {
+
+ merchantLogService.save(
+ new MerchantLog(store,
+ "Can't process BeanStream message "
+ + messageText + " return code id " + messageId));
+
+ IntegrationException te = new IntegrationException(
+ "Can't process BeanStream message " + messageText);
+ te.setExceptionType(IntegrationException.EXCEPTION_PAYMENT_DECLINED);
+ te.setMessageCode("message.payment.beanstream." + messageId);
+ te.setErrorCode(IntegrationException.TRANSACTION_EXCEPTION);
+ throw te;
+ }
+
+ //create transaction object
+
+ //return parseResponse(type,transaction,respText,nvp,order);
+ return this.parseResponse(transactionType, paymentType, nvp, amount);
+
+
+ } catch(Exception e) {
+ if(e instanceof IntegrationException) {
+ throw (IntegrationException)e;
+ }
+
+ throw new IntegrationException("Error while processing BeanStream transaction",e);
+
+ } finally {
+ if (is != null) {
+ try {
+ is.close();
+ } catch (Exception ignore) {
+ // TODO: handle exception
+ }
+ }
+
+ if (in != null) {
+ try {
+ in.close();
+ } catch (Exception ignore) {
+ // TODO: handle exception
+ }
+ }
+
+ if (output != null) {
+ try {
+ output.close();
+ } catch (Exception ignore) {
+ // TODO: handle exception
+ }
+ }
+
+ if (conn != null) {
+ try {
+ conn.disconnect();
+ } catch (Exception ignore) {
+ // TODO: handle exception
+ }
+ }
+
+ }
+
+
+ }
+
+
+
+ private Transaction processTransaction(MerchantStore store, Customer customer, TransactionType type,
+ BigDecimal amount, Payment payment,
+ IntegrationConfiguration configuration, IntegrationModule module) throws IntegrationException {
+
+
+
+
+
+ boolean bSandbox = false;
+ if (configuration.getEnvironment().equals("TEST")) {// sandbox
+ bSandbox = true;
+ }
+
+ String server = "";
+
+ ModuleConfig configs = module.getModuleConfigs().get("PROD");
+
+ if (bSandbox == true) {
+ configs = module.getModuleConfigs().get("TEST");
+ }
+
+ if(configs==null) {
+ throw new IntegrationException("Module not configured for TEST or PROD");
+ }
+
+
+ server = new StringBuffer().append(
+
+ configs.getScheme()).append("://")
+ .append(configs.getHost())
+ .append(":")
+ .append(configs.getPort())
+ .append(configs.getUri()).toString();
+
+ HttpURLConnection conn = null;
+
+ try {
+
+ String uniqueId = UUID.randomUUID().toString();//TODO
+
+ String orderNumber = uniqueId;
+
+ String amnt = productPriceUtils.getAdminFormatedAmount(store, amount);
+
+
+ StringBuilder messageString = new StringBuilder();
+
+ String transactionType = "P";
+ if(type == TransactionType.AUTHORIZE) {
+ transactionType = "PA";
+ } else if(type == TransactionType.AUTHORIZECAPTURE) {
+ transactionType = "P";
+ }
+
+ CreditCardPayment creditCardPayment = (CreditCardPayment)payment;
+
+ messageString.append("requestType=BACKEND&");
+ messageString.append("merchant_id=").append(configuration.getIntegrationKeys().get("merchantid")).append("&");
+ messageString.append("trnType=").append(transactionType).append("&");
+ messageString.append("username=").append(configuration.getIntegrationKeys().get("username")).append("&");
+ messageString.append("password=").append(configuration.getIntegrationKeys().get("password")).append("&");
+ messageString.append("orderNumber=").append(orderNumber).append("&");
+ messageString.append("trnCardOwner=").append(creditCardPayment.getCardOwner()).append("&");
+ messageString.append("trnCardNumber=").append(creditCardPayment.getCreditCardNumber()).append("&");
+ messageString.append("trnExpMonth=").append(creditCardPayment.getExpirationMonth()).append("&");
+ messageString.append("trnExpYear=").append(creditCardPayment.getExpirationYear().substring(2)).append("&");
+ messageString.append("trnCardCvd=").append(creditCardPayment.getCredidCardValidationNumber()).append("&");
+ messageString.append("trnAmount=").append(amnt).append("&");
+
+ StringBuilder nm = new StringBuilder();
+ nm.append(customer.getBilling().getFirstName()).append(" ").append(customer.getBilling().getLastName());
+
+
+ messageString.append("ordName=").append(nm.toString()).append("&");
+ messageString.append("ordAddress1=").append(customer.getBilling().getAddress()).append("&");
+ messageString.append("ordCity=").append(customer.getBilling().getCity()).append("&");
+
+ String stateProvince = customer.getBilling().getState();
+ if(customer.getBilling().getZone()!=null) {
+ stateProvince = customer.getBilling().getZone().getCode();
+ }
+
+ String countryName = customer.getBilling().getCountry().getIsoCode();
+
+ messageString.append("ordProvince=").append(stateProvince).append("&");
+ messageString.append("ordPostalCode=").append(customer.getBilling().getPostalCode().replaceAll("\\s","")).append("&");
+ messageString.append("ordCountry=").append(countryName).append("&");
+ messageString.append("ordPhoneNumber=").append(customer.getBilling().getTelephone()).append("&");
+ messageString.append("ordEmailAddress=").append(customer.getEmailAddress());
+
+
+
+
+ /**
+ * purchase (P)
+ * -----------
+ REQUEST -> merchant_id=123456789&requestType=BACKEND&trnType=P&trnOrderNumber=1234TEST&trnAmount=5.00&trnCardOwner=Joe+Test&trnCardNumber=4030000010001234&trnExpMonth=10&trnExpYear=10&ordName=Joe+Test&ordAddress1=123+Test+Street&ordCity=Victoria&ordProvince=BC&ordCountry=CA&ordPostalCode=V8T2E7&ordPhoneNumber=5555555555&ordEmailAddress=joe%40testemail.com
+ RESPONSE-> trnApproved=1&trnId=10003067&messageId=1&messageText=Approved&trnOrderNumber=E40089&authCode=TEST&errorType=N&errorFields=&responseType=T&trnAmount=10%2E00&trnDate=1%2F17%2F2008+11%3A36%3A34+AM&avsProcessed=0&avsId=0&avsResult=0&avsAddrMatch=0&avsPostalMatch=0&avsMessage=Address+Verification+not+performed+for+this+transaction%2E&rspCodeCav=0&rspCavResult=0&rspCodeCredit1=0&rspCodeCredit2=0&rspCodeCredit3=0&rspCodeCredit4=0&rspCodeAddr1=0&rspCodeAddr2=0&rspCodeAddr3=0&rspCodeAddr4=0&rspCodeDob=0&rspCustomerDec=&trnType=P&paymentMethod=CC&ref1=&ref2=&ref3=&ref4=&ref5=
+
+ pre authorization (PA)
+ ----------------------
+
+ Prior to processing a pre-authorization through the API, you must modify the transaction settings in your Beanstream merchant member area to allow for this transaction type.
+ - Log in to the Beanstream online member area at www.beanstream.com/admin/sDefault.asp.
+ - Navigate to administration - account admin - order settings in the left menu.
+ Under the heading �Restrict Internet Transaction Processing Types,� select either of the last two options. The �Purchases or Pre-Authorization Only� option will allow you to process both types of transaction through your web interface. De-selecting the �Restrict Internet Transaction Processing Types� checkbox will allow you to process all types of transactions including returns, voids and pre-auth completions.
+
+ capture (PAC) -> requires trnId
+ -------------
+
+ refund (R)
+ -------------
+ REQUEST -> merchant_id=123456789&requestType=BACKEND&trnType=R&username=user1234&password=pass1234&trnOrderNumber=1234&trnAmount=1.00&adjId=10002115
+ RESPONSE-> trnApproved=1&trnId=10002118&messageId=1&messageText=Approved&trnOrderNumber=1234R&authCode=TEST&errorType=N&errorFields=&responseType=T&trnAmount=1%2E00&trnDate=8%2F17%2F2009+1%3A44%3A56+PM&avsProcessed=0&avsId=0&avsResult=0&avsAddrMatch=0&avsPostalMatch=0&avsMessage=Address+Verification+not+performed+for+this+transaction%2E&cardType=VI&trnType=R&paymentMethod=CC&ref1=&ref2=&ref3=&ref4=&ref5=
+
+
+ //notes
+ //On receipt of the transaction response, the merchant must display order amount, transaction ID number, bank authorization code (authCode), currency, date and �messageText� to the customer on a confirmation page.
+ */
+
+
+ //String agent = "Mozilla/4.0";
+ //String respText = "";
+ //Map nvp = null;
+
+
+ /** debug **/
+
+
+
+ StringBuffer messageLogString = new StringBuffer();
+
+
+ messageLogString.append("requestType=BACKEND&");
+ messageLogString.append("merchant_id=").append(configuration.getIntegrationKeys().get("merchantid")).append("&");
+ messageLogString.append("trnType=").append(type).append("&");
+ messageLogString.append("orderNumber=").append(orderNumber).append("&");
+ messageLogString.append("trnCardOwner=").append(creditCardPayment.getCardOwner()).append("&");
+ messageLogString.append("trnCardNumber=").append(CreditCardUtils.maskCardNumber(creditCardPayment.getCreditCardNumber())).append("&");
+ messageLogString.append("trnExpMonth=").append(creditCardPayment.getExpirationMonth()).append("&");
+ messageLogString.append("trnExpYear=").append(creditCardPayment.getExpirationYear()).append("&");
+ messageLogString.append("trnCardCvd=").append(creditCardPayment.getCredidCardValidationNumber()).append("&");
+ messageLogString.append("trnAmount=").append(amnt).append("&");
+
+ messageLogString.append("ordName=").append(nm.toString()).append("&");
+ messageLogString.append("ordAddress1=").append(customer.getBilling().getAddress()).append("&");
+ messageLogString.append("ordCity=").append(customer.getBilling().getCity()).append("&");
+
+
+
+ messageLogString.append("ordProvince=").append(stateProvince).append("&");
+ messageLogString.append("ordPostalCode=").append(customer.getBilling().getPostalCode()).append("&");
+ messageLogString.append("ordCountry=").append(customer.getBilling().getCountry().getName()).append("&");
+ messageLogString.append("ordPhoneNumber=").append(customer.getBilling().getTelephone()).append("&");
+ messageLogString.append("ordEmailAddress=").append(customer.getEmailAddress());
+
+
+
+
+ /** debug **/
+
+
+ LOGGER.debug("REQUEST SENT TO BEANSTREAM -> " + messageLogString.toString());
+
+
+ URL postURL = new URL(server.toString());
+ conn = (HttpURLConnection) postURL.openConnection();
+
+
+
+ Transaction response = this.sendTransaction(orderNumber, store, messageString.toString(), transactionType, type, payment.getPaymentType(), amount, configuration, module);
+
+ return response;
+
+
+
+ } catch(Exception e) {
+
+ if(e instanceof IntegrationException)
+ throw (IntegrationException)e;
+ throw new IntegrationException("Error while processing BeanStream transaction",e);
+
+ } finally {
+
+
+ if (conn != null) {
+ try {
+ conn.disconnect();
+ } catch (Exception ignore) {}
+ }
+ }
+
+ }
+
+
+
+ private Transaction parseResponse(TransactionType transactionType,
+ PaymentType paymentType, Map<String,String> nvp,
+ BigDecimal amount) throws Exception {
+
+
+ Transaction transaction = new Transaction();
+ transaction.setAmount(amount);
+ //transaction.setOrder(order);
+ transaction.setTransactionDate(new Date());
+ transaction.setTransactionType(transactionType);
+ transaction.setPaymentType(PaymentType.CREDITCARD);
+ transaction.getTransactionDetails().put("TRANSACTIONID", (String)nvp.get("TRNID"));
+ transaction.getTransactionDetails().put("TRNAPPROVED", (String)nvp.get("TRNAPPROVED"));
+ transaction.getTransactionDetails().put("TRNORDERNUMBER", (String)nvp.get("TRNORDERNUMBER"));
+ transaction.getTransactionDetails().put("MESSAGETEXT", (String)nvp.get("MESSAGETEXT"));
+ if(nvp.get("INTERNALORDERID")!=null) {
+ transaction.getTransactionDetails().put("INTERNALORDERID", (String)nvp.get("INTERNALORDERID"));
+ }
+ return transaction;
+
+ }
+
+ private Map formatUrlResponse(String payload) throws Exception {
+ HashMap<String,String> nvp = new HashMap<String,String> ();
+ StringTokenizer stTok = new StringTokenizer(payload, "&");
+ while (stTok.hasMoreTokens()) {
+ StringTokenizer stInternalTokenizer = new StringTokenizer(stTok
+ .nextToken(), "=");
+ if (stInternalTokenizer.countTokens() == 2) {
+ String key = URLDecoder.decode(stInternalTokenizer.nextToken(),
+ "UTF-8");
+ String value = URLDecoder.decode(stInternalTokenizer
+ .nextToken(), "UTF-8");
+ nvp.put(key.toUpperCase(), value);
+ }
+ }
+ return nvp;
+ }
+
+ @Override
+ public void validateModuleConfiguration(
+ IntegrationConfiguration integrationConfiguration,
+ MerchantStore store) throws IntegrationException {
+
+
+ List<String> errorFields = null;
+
+
+ Map<String,String> keys = integrationConfiguration.getIntegrationKeys();
+
+ //validate integrationKeys['merchantid']
+ if(keys==null || StringUtils.isBlank(keys.get("merchantid"))) {
+ errorFields = new ArrayList<String>();
+ errorFields.add("merchantid");
+ }
+
+ //validate integrationKeys['username']
+ if(keys==null || StringUtils.isBlank(keys.get("username"))) {
+ if(errorFields==null) {
+ errorFields = new ArrayList<String>();
+ }
+ errorFields.add("username");
+ }
+
+
+ //validate integrationKeys['password']
+ if(keys==null || StringUtils.isBlank(keys.get("password"))) {
+ if(errorFields==null) {
+ errorFields = new ArrayList<String>();
+ }
+ errorFields.add("password");
+ }
+
+
+
+ if(errorFields!=null) {
+ IntegrationException ex = new IntegrationException(IntegrationException.ERROR_VALIDATION_SAVE);
+ ex.setErrorFields(errorFields);
+ throw ex;
+
+ }
+
+
+
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/integration/payment/impl/MoneyOrderPayment.java b/sm-core/src/main/java/com/salesmanager/core/modules/integration/payment/impl/MoneyOrderPayment.java
new file mode 100644
index 0000000..0877a68
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/integration/payment/impl/MoneyOrderPayment.java
@@ -0,0 +1,119 @@
+package com.salesmanager.core.modules.integration.payment.impl;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.business.payments.model.Payment;
+import com.salesmanager.core.business.payments.model.PaymentType;
+import com.salesmanager.core.business.payments.model.Transaction;
+import com.salesmanager.core.business.payments.model.TransactionType;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartItem;
+import com.salesmanager.core.business.system.model.IntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+import com.salesmanager.core.modules.integration.IntegrationException;
+import com.salesmanager.core.modules.integration.payment.model.PaymentModule;
+
+public class MoneyOrderPayment implements PaymentModule {
+
+ @Override
+ public void validateModuleConfiguration(
+ IntegrationConfiguration integrationConfiguration,
+ MerchantStore store) throws IntegrationException {
+
+ List<String> errorFields = null;
+
+
+ Map<String,String> keys = integrationConfiguration.getIntegrationKeys();
+
+ //validate integrationKeys['address']
+ if(keys==null || StringUtils.isBlank(keys.get("address"))) {
+ errorFields = new ArrayList<String>();
+ errorFields.add("address");
+ }
+
+ if(errorFields!=null) {
+ IntegrationException ex = new IntegrationException(IntegrationException.ERROR_VALIDATION_SAVE);
+ ex.setErrorFields(errorFields);
+ throw ex;
+
+ }
+
+
+
+ return;
+
+ }
+
+ @Override
+ public Transaction initTransaction(MerchantStore store, Customer customer,
+ BigDecimal amount, Payment payment,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+ //NOT REQUIRED
+ return null;
+ }
+
+ @Override
+ public Transaction authorize(MerchantStore store, Customer customer,
+ List<ShoppingCartItem> items, BigDecimal amount, Payment payment,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+ //NOT REQUIRED
+ return null;
+ }
+
+/* @Override
+ public Transaction capture(MerchantStore store, Customer customer,
+ List<ShoppingCartItem> items, BigDecimal amount, Payment payment, Transaction transaction,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+ //NOT REQUIRED
+ return null;
+ }*/
+
+ @Override
+ public Transaction authorizeAndCapture(MerchantStore store, Customer customer,
+ List<ShoppingCartItem> items, BigDecimal amount, Payment payment,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+
+
+ Transaction transaction = new Transaction();
+ transaction.setAmount(amount);
+ transaction.setTransactionDate(new Date());
+ transaction.setTransactionType(TransactionType.AUTHORIZECAPTURE);
+ transaction.setPaymentType(PaymentType.MONEYORDER);
+
+
+ return transaction;
+
+
+
+ }
+
+ @Override
+ public Transaction refund(boolean partial, MerchantStore store, Transaction transaction,
+ Order order, BigDecimal amount,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+ throw new IntegrationException("Transaction not supported");
+ }
+
+ @Override
+ public Transaction capture(MerchantStore store, Customer customer,
+ Order order, Transaction capturableTransaction,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/integration/payment/impl/PayPalExpressCheckoutPayment.java b/sm-core/src/main/java/com/salesmanager/core/modules/integration/payment/impl/PayPalExpressCheckoutPayment.java
new file mode 100644
index 0000000..58b6132
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/integration/payment/impl/PayPalExpressCheckoutPayment.java
@@ -0,0 +1,653 @@
+package com.salesmanager.core.modules.integration.payment.impl;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang.Validate;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import urn.ebay.api.PayPalAPI.DoCaptureReq;
+import urn.ebay.api.PayPalAPI.DoCaptureRequestType;
+import urn.ebay.api.PayPalAPI.DoCaptureResponseType;
+import urn.ebay.api.PayPalAPI.DoExpressCheckoutPaymentReq;
+import urn.ebay.api.PayPalAPI.DoExpressCheckoutPaymentRequestType;
+import urn.ebay.api.PayPalAPI.DoExpressCheckoutPaymentResponseType;
+import urn.ebay.api.PayPalAPI.GetExpressCheckoutDetailsReq;
+import urn.ebay.api.PayPalAPI.GetExpressCheckoutDetailsRequestType;
+import urn.ebay.api.PayPalAPI.GetExpressCheckoutDetailsResponseType;
+import urn.ebay.api.PayPalAPI.PayPalAPIInterfaceServiceService;
+import urn.ebay.api.PayPalAPI.RefundTransactionReq;
+import urn.ebay.api.PayPalAPI.RefundTransactionRequestType;
+import urn.ebay.api.PayPalAPI.RefundTransactionResponseType;
+import urn.ebay.api.PayPalAPI.SetExpressCheckoutReq;
+import urn.ebay.api.PayPalAPI.SetExpressCheckoutRequestType;
+import urn.ebay.api.PayPalAPI.SetExpressCheckoutResponseType;
+import urn.ebay.apis.CoreComponentTypes.BasicAmountType;
+import urn.ebay.apis.eBLBaseComponents.CompleteCodeType;
+import urn.ebay.apis.eBLBaseComponents.DoExpressCheckoutPaymentRequestDetailsType;
+import urn.ebay.apis.eBLBaseComponents.PaymentDetailsItemType;
+import urn.ebay.apis.eBLBaseComponents.PaymentDetailsType;
+import urn.ebay.apis.eBLBaseComponents.PaymentInfoType;
+import urn.ebay.apis.eBLBaseComponents.RefundType;
+import urn.ebay.apis.eBLBaseComponents.SetExpressCheckoutRequestDetailsType;
+
+import com.salesmanager.core.business.catalog.product.service.PricingService;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.business.order.model.OrderTotal;
+import com.salesmanager.core.business.order.model.OrderTotalSummary;
+import com.salesmanager.core.business.payments.model.Payment;
+import com.salesmanager.core.business.payments.model.PaymentType;
+import com.salesmanager.core.business.payments.model.Transaction;
+import com.salesmanager.core.business.payments.model.TransactionType;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartItem;
+import com.salesmanager.core.business.system.model.IntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+import com.salesmanager.core.constants.Constants;
+import com.salesmanager.core.modules.integration.IntegrationException;
+import com.salesmanager.core.modules.integration.payment.model.PaymentModule;
+import com.salesmanager.core.utils.CoreConfiguration;
+
+public class PayPalExpressCheckoutPayment implements PaymentModule {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(PayPalExpressCheckoutPayment.class);
+
+
+ @Autowired
+ private PricingService pricingService;
+
+ @Autowired
+ private CoreConfiguration coreConfiguration;
+
+ @Override
+ public void validateModuleConfiguration(
+ IntegrationConfiguration integrationConfiguration,
+ MerchantStore store) throws IntegrationException {
+
+
+ List<String> errorFields = null;
+
+ //validate integrationKeys['account']
+ Map<String,String> keys = integrationConfiguration.getIntegrationKeys();
+ if(keys==null || StringUtils.isBlank(keys.get("api"))) {
+ errorFields = new ArrayList<String>();
+ errorFields.add("api");
+ }
+
+ if(keys==null || StringUtils.isBlank(keys.get("username"))) {
+ if(errorFields==null) {
+ errorFields = new ArrayList<String>();
+ }
+ errorFields.add("username");
+ }
+
+ if(keys==null || StringUtils.isBlank(keys.get("signature"))) {
+ if(errorFields==null) {
+ errorFields = new ArrayList<String>();
+ }
+ errorFields.add("signature");
+ }
+
+
+ if(errorFields!=null) {
+ IntegrationException ex = new IntegrationException(IntegrationException.ERROR_VALIDATION_SAVE);
+ ex.setErrorFields(errorFields);
+ throw ex;
+
+ }
+
+
+ }
+
+ @Override
+ public Transaction initTransaction(MerchantStore store, Customer customer,
+ BigDecimal amount, Payment payment,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+
+ throw new IntegrationException("Not imlemented");
+ }
+
+ @Override
+ public Transaction authorize(MerchantStore store, Customer customer,
+ List<ShoppingCartItem> items, BigDecimal amount, Payment payment,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+
+
+ com.salesmanager.core.business.payments.model.PaypalPayment paypalPayment = (com.salesmanager.core.business.payments.model.PaypalPayment)payment;
+ Validate.notNull(paypalPayment.getPaymentToken(), "A paypal payment token is required to process this transaction");
+
+ return processTransaction(store, customer, items, amount, paypalPayment, configuration, module);
+
+
+ }
+
+/* @Override
+ public Transaction capture(MerchantStore store, Customer customer,
+ List<ShoppingCartItem> items, BigDecimal amount, Payment payment, Transaction transaction,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+
+ com.salesmanager.core.business.payments.model.PaypalPayment paypalPayment = (com.salesmanager.core.business.payments.model.PaypalPayment)payment;
+ Validate.notNull(paypalPayment.getPaymentToken(), "A paypal payment token is required to process this transaction");
+
+ return processTransaction(store, customer, items, amount, paypalPayment, configuration, module);
+
+ }*/
+
+ public Transaction initPaypalTransaction(MerchantStore store,
+ List<ShoppingCartItem> items, OrderTotalSummary summary, Payment payment,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+
+
+
+ try {
+
+
+ PaymentDetailsType paymentDetails = new PaymentDetailsType();
+ if(configuration.getIntegrationKeys().get("transaction").equalsIgnoreCase(TransactionType.AUTHORIZECAPTURE.name())) {
+ paymentDetails.setPaymentAction(urn.ebay.apis.eBLBaseComponents.PaymentActionCodeType.SALE);
+ } else {
+ paymentDetails.setPaymentAction(urn.ebay.apis.eBLBaseComponents.PaymentActionCodeType.AUTHORIZATION);
+ }
+
+
+ List<PaymentDetailsItemType> lineItems = new ArrayList<PaymentDetailsItemType>();
+
+ for(ShoppingCartItem cartItem : items) {
+
+ PaymentDetailsItemType item = new PaymentDetailsItemType();
+ BasicAmountType amt = new BasicAmountType();
+ amt.setCurrencyID(urn.ebay.apis.eBLBaseComponents.CurrencyCodeType.fromValue(payment.getCurrency().getCode()));
+ amt.setValue(pricingService.getStringAmount(cartItem.getFinalPrice().getFinalPrice(), store));
+ //itemsTotal = itemsTotal.add(cartItem.getSubTotal());
+ int itemQuantity = cartItem.getQuantity();
+ item.setQuantity(itemQuantity);
+ item.setName(cartItem.getProduct().getProductDescription().getName());
+ item.setAmount(amt);
+ //System.out.println(pricingService.getStringAmount(cartItem.getSubTotal(), store));
+ lineItems.add(item);
+
+ }
+
+
+ List<OrderTotal> orderTotals = summary.getTotals();
+ BigDecimal tax = null;
+ for(OrderTotal total : orderTotals) {
+
+ if(total.getModule().equals(Constants.OT_SHIPPING_MODULE_CODE)) {
+ BasicAmountType shipping = new BasicAmountType();
+ shipping.setCurrencyID(urn.ebay.apis.eBLBaseComponents.CurrencyCodeType.fromValue(store.getCurrency().getCode()));
+ shipping.setValue(pricingService.getStringAmount(total.getValue(), store));
+ //System.out.println(pricingService.getStringAmount(total.getValue(), store));
+ paymentDetails.setShippingTotal(shipping);
+ }
+
+ if(total.getModule().equals(Constants.OT_HANDLING_MODULE_CODE)) {
+ BasicAmountType handling = new BasicAmountType();
+ handling.setCurrencyID(urn.ebay.apis.eBLBaseComponents.CurrencyCodeType.fromValue(store.getCurrency().getCode()));
+ handling.setValue(pricingService.getStringAmount(total.getValue(), store));
+ //System.out.println(pricingService.getStringAmount(total.getValue(), store));
+ paymentDetails.setHandlingTotal(handling);
+ }
+
+ if(total.getModule().equals(Constants.OT_TAX_MODULE_CODE)) {
+ if(tax==null) {
+ tax = new BigDecimal("0");
+ }
+ tax = tax.add(total.getValue());
+ }
+
+ }
+
+ if(tax!=null) {
+ BasicAmountType taxAmnt = new BasicAmountType();
+ taxAmnt.setCurrencyID(urn.ebay.apis.eBLBaseComponents.CurrencyCodeType.fromValue(store.getCurrency().getCode()));
+ taxAmnt.setValue(pricingService.getStringAmount(tax, store));
+ //System.out.println(pricingService.getStringAmount(tax, store));
+ paymentDetails.setTaxTotal(taxAmnt);
+ }
+
+
+
+ BasicAmountType itemTotal = new BasicAmountType();
+ itemTotal.setCurrencyID(urn.ebay.apis.eBLBaseComponents.CurrencyCodeType.fromValue(store.getCurrency().getCode()));
+ itemTotal.setValue(pricingService.getStringAmount(summary.getSubTotal(), store));
+ paymentDetails.setItemTotal(itemTotal);
+
+ paymentDetails.setPaymentDetailsItem(lineItems);
+ BasicAmountType orderTotal = new BasicAmountType();
+ orderTotal.setCurrencyID(urn.ebay.apis.eBLBaseComponents.CurrencyCodeType.fromValue(store.getCurrency().getCode()));
+ orderTotal.setValue(pricingService.getStringAmount(summary.getTotal(), store));
+ //System.out.println(pricingService.getStringAmount(itemsTotal, store));
+ paymentDetails.setOrderTotal(orderTotal);
+ List<PaymentDetailsType> paymentDetailsList = new ArrayList<PaymentDetailsType>();
+ paymentDetailsList.add(paymentDetails);
+
+ StringBuilder RETURN_URL = new StringBuilder().append(
+ coreConfiguration.getProperty("ORDER_SCHEME", "http")).append("://")
+ .append(store.getDomainName()).append("/")
+ .append(coreConfiguration.getProperty("CONTEXT_PATH", "sm-shop"));
+
+
+
+ SetExpressCheckoutRequestDetailsType setExpressCheckoutRequestDetails = new SetExpressCheckoutRequestDetailsType();
+ String returnUrl = RETURN_URL.toString() + new StringBuilder().append(Constants.SHOP_URI).append("/paypal/checkout").append(coreConfiguration.getProperty("URL_EXTENSION", ".html")).append("/success").toString();
+ String cancelUrl = RETURN_URL.toString() + new StringBuilder().append(Constants.SHOP_URI).append("/paypal/checkout").append(coreConfiguration.getProperty("URL_EXTENSION", ".html")).append("/cancel").toString();
+
+ setExpressCheckoutRequestDetails.setReturnURL(returnUrl);
+ setExpressCheckoutRequestDetails.setCancelURL(cancelUrl);
+
+
+ setExpressCheckoutRequestDetails.setPaymentDetails(paymentDetailsList);
+
+ SetExpressCheckoutRequestType setExpressCheckoutRequest = new SetExpressCheckoutRequestType(setExpressCheckoutRequestDetails);
+ setExpressCheckoutRequest.setVersion("104.0");
+
+ SetExpressCheckoutReq setExpressCheckoutReq = new SetExpressCheckoutReq();
+ setExpressCheckoutReq.setSetExpressCheckoutRequest(setExpressCheckoutRequest);
+
+
+ String mode = "sandbox";
+ String env = configuration.getEnvironment();
+ if(Constants.PRODUCTION_ENVIRONMENT.equals(env)) {
+ mode = "production";
+ }
+
+ Map<String,String> configurationMap = new HashMap<String,String>();
+ configurationMap.put("mode", mode);
+ configurationMap.put("acct1.UserName", configuration.getIntegrationKeys().get("username"));
+ configurationMap.put("acct1.Password", configuration.getIntegrationKeys().get("api"));
+ configurationMap.put("acct1.Signature", configuration.getIntegrationKeys().get("signature"));
+
+ PayPalAPIInterfaceServiceService service = new PayPalAPIInterfaceServiceService(configurationMap);
+ SetExpressCheckoutResponseType setExpressCheckoutResponse = service.setExpressCheckout(setExpressCheckoutReq);
+
+ String token = setExpressCheckoutResponse.getToken();
+ String correlationID = setExpressCheckoutResponse.getCorrelationID();
+ String ack = setExpressCheckoutResponse.getAck().getValue();
+
+ if(!"Success".equals(ack)) {
+ LOGGER.error("Wrong value from init transaction " + ack);
+ throw new IntegrationException("Wrong paypal ack from init transaction " + ack);
+ }
+
+ Transaction transaction = new Transaction();
+ transaction.setAmount(summary.getTotal());
+ //transaction.setOrder(order);
+ transaction.setTransactionDate(new Date());
+ transaction.setTransactionType(TransactionType.INIT);
+ transaction.setPaymentType(PaymentType.PAYPAL);
+ transaction.getTransactionDetails().put("TOKEN", token);
+ transaction.getTransactionDetails().put("CORRELATION", correlationID);
+
+
+ return transaction;
+
+ //redirect user to
+ //https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-5LL13394G30048922
+
+ } catch(Exception e) {
+ e.printStackTrace();
+ throw new IntegrationException(e);
+ }
+
+
+ }
+
+ @Override
+ public Transaction authorizeAndCapture(MerchantStore store,
+ Customer customer, List<ShoppingCartItem> items, BigDecimal amount, Payment payment,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+
+ com.salesmanager.core.business.payments.model.PaypalPayment paypalPayment = (com.salesmanager.core.business.payments.model.PaypalPayment)payment;
+ Validate.notNull(paypalPayment.getPaymentToken(), "A paypal payment token is required to process this transaction");
+
+ return processTransaction(store, customer, items, amount, paypalPayment, configuration, module);
+
+
+ }
+
+ @Override
+ public Transaction refund(boolean partial, MerchantStore store,
+ Transaction transaction, Order order, BigDecimal amount,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+
+
+ try {
+
+
+
+ Validate.notNull(transaction,"Transaction cannot be null");
+ Validate.notNull((String)transaction.getTransactionDetails().get("TRANSACTIONID"), "Transaction details must contain a TRANSACTIONID");
+ Validate.notNull(order,"Order must not be null");
+ Validate.notNull(order.getCurrency(),"Order nust contain Currency object");
+
+ String mode = "sandbox";
+ String env = configuration.getEnvironment();
+ if(Constants.PRODUCTION_ENVIRONMENT.equals(env)) {
+ mode = "production";
+ }
+
+
+ RefundTransactionRequestType refundTransactionRequest = new RefundTransactionRequestType();
+ refundTransactionRequest.setVersion("104.0");
+
+ RefundTransactionReq refundRequest = new RefundTransactionReq();
+ refundRequest.setRefundTransactionRequest(refundTransactionRequest);
+
+
+ Map<String,String> configurationMap = new HashMap<String,String>();
+ configurationMap.put("mode", mode);
+ configurationMap.put("acct1.UserName", configuration.getIntegrationKeys().get("username"));
+ configurationMap.put("acct1.Password", configuration.getIntegrationKeys().get("api"));
+ configurationMap.put("acct1.Signature", configuration.getIntegrationKeys().get("signature"));
+
+
+ PayPalAPIInterfaceServiceService service = new PayPalAPIInterfaceServiceService(configurationMap);
+
+
+
+ RefundType refundType = RefundType.FULL;
+ if(partial) {
+ refundType = RefundType.PARTIAL;
+ }
+
+ refundTransactionRequest.setRefundType(refundType);
+
+ BasicAmountType refundAmount = new BasicAmountType();
+ refundAmount.setValue(pricingService.getStringAmount(amount, store));
+ refundAmount.setCurrencyID(urn.ebay.apis.eBLBaseComponents.CurrencyCodeType.fromValue(order.getCurrency().getCode()));
+
+ refundTransactionRequest.setAmount(refundAmount);
+ refundTransactionRequest.setTransactionID(transaction.getTransactionDetails().get("TRANSACTIONID"));
+
+ RefundTransactionResponseType refundTransactionResponse = service.refundTransaction(refundRequest);
+
+ String refundAck = refundTransactionResponse.getAck().getValue();
+
+
+ if(!"Success".equals(refundAck)) {
+ LOGGER.error("Wrong value from transaction commit " + refundAck);
+ throw new IntegrationException(ServiceException.EXCEPTION_TRANSACTION_DECLINED,"Paypal refund transaction code [" + refundTransactionResponse.getErrors().get(0).getErrorCode() + "], message-> " + refundTransactionResponse.getErrors().get(0).getShortMessage());
+ }
+
+
+ Transaction newTransaction = new Transaction();
+ newTransaction.setAmount(amount);
+ newTransaction.setTransactionDate(new Date());
+ newTransaction.setTransactionType(TransactionType.REFUND);
+ newTransaction.setPaymentType(PaymentType.PAYPAL);
+ newTransaction.getTransactionDetails().put("TRANSACTIONID", refundTransactionResponse.getRefundTransactionID());
+ transaction.getTransactionDetails().put("CORRELATION", refundTransactionResponse.getCorrelationID());
+
+
+
+ return newTransaction;
+
+
+ } catch(Exception e) {
+ if(e instanceof IntegrationException) {
+ throw (IntegrationException)e;
+ } else {
+ throw new IntegrationException(e);
+ }
+ }
+
+
+
+
+
+
+ }
+
+ private Transaction processTransaction(MerchantStore store,
+ Customer customer, List<ShoppingCartItem> items, BigDecimal amount, Payment payment,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+
+
+ com.salesmanager.core.business.payments.model.PaypalPayment paypalPayment = (com.salesmanager.core.business.payments.model.PaypalPayment)payment;
+
+ try {
+
+
+ String mode = "sandbox";
+ String env = configuration.getEnvironment();
+ if(Constants.PRODUCTION_ENVIRONMENT.equals(env)) {
+ mode = "production";
+ }
+
+
+ //get token from url and return the user to generate a payerid
+
+ GetExpressCheckoutDetailsRequestType getExpressCheckoutDetailsRequest = new GetExpressCheckoutDetailsRequestType(paypalPayment.getPaymentToken());
+ getExpressCheckoutDetailsRequest.setVersion("104.0");
+
+ GetExpressCheckoutDetailsReq getExpressCheckoutDetailsReq = new GetExpressCheckoutDetailsReq();
+ getExpressCheckoutDetailsReq.setGetExpressCheckoutDetailsRequest(getExpressCheckoutDetailsRequest);
+
+ Map<String,String> configurationMap = new HashMap<String,String>();
+ configurationMap.put("mode", mode);
+ configurationMap.put("acct1.UserName", configuration.getIntegrationKeys().get("username"));
+ configurationMap.put("acct1.Password", configuration.getIntegrationKeys().get("api"));
+ configurationMap.put("acct1.Signature", configuration.getIntegrationKeys().get("signature"));
+
+
+ PayPalAPIInterfaceServiceService service = new PayPalAPIInterfaceServiceService(configurationMap);
+ GetExpressCheckoutDetailsResponseType getExpressCheckoutDetailsResponse = service.getExpressCheckoutDetails(getExpressCheckoutDetailsReq);
+
+
+ String token = getExpressCheckoutDetailsResponse.getGetExpressCheckoutDetailsResponseDetails().getToken();
+ String correlationID = getExpressCheckoutDetailsResponse.getCorrelationID();
+ String ack = getExpressCheckoutDetailsResponse.getAck().getValue();
+ String payerId = getExpressCheckoutDetailsResponse.getGetExpressCheckoutDetailsResponseDetails().getPayerInfo().getPayerID();
+
+ //TOKEN=EC-9VT64354BS889423P&CHECKOUTSTATUS=PaymentActionNotInitiated&TIMESTAMP=2014-01-26T17:30:17Z&CORRELATIONID=84dfe1d0939cc&ACK=Success&VERSION=104.0&BUILD=9285531&EMAIL=csamson777-facilitator@yahoo.com&PAYERID=XURV79Z6URDV4&PAYERSTATUS=verified&BUSINESS=facilitator account's Test Store&FIRSTNAME=facilitator&LASTNAME=account&COUNTRYCODE=US&SHIPTONAME=facilitator account's Test Store&SHIPTOSTREET=1 Main St&SHIPTOCITY=San Jose&SHIPTOSTATE=CA&SHIPTOZIP=95131&SHIPTOCOUNTRYCODE=US&SHIPTOCOUNTRYNAME=United States&ADDRESSSTATUS=Confirmed&CURRENCYCODE=USD&AMT=1.00&ITEMAMT=1.00&SHIPPINGAMT=0.00&HANDLINGAMT=0.00&TAXAMT=0.00&INSURANCEAMT=0.00&SHIPDISCAMT=0.00&L_NAME0=item&L_QTY0=1&L_TAXAMT0=0.00&L_AMT0=1.00&L_ITEMWEIGHTVALUE0= 0.00000&L_ITEMLENGTHVALUE0= 0.00000&L_ITEMWIDTHVALUE0= 0.00000&L_ITEMHEIGHTVALUE0= 0.00000&PAYMENTREQUEST_0_CURRENCYCODE=USD&PAYMENTREQUEST_0_AMT=1.00&PAYMENTREQUEST_0_ITEMAMT=1.00&PAYMENTREQUEST_0_SHIPPINGAMT=0.00&PAYMENTREQUEST_0_HANDLINGAMT=0.00&PAYMENTREQUEST_0_TAXAMT=0.00&PAYMENTREQUEST_0_INSURANCEAMT=0.00&PAYMENTREQUEST_0_SHIPDISCAMT=0.00&PAYMENTREQUEST_0_INSURANCEOPTIONOFFERED=false&PAYMENTREQUEST_0_SHIPTONAME=facilitator account's Test Store&PAYMENTREQUEST_0_SHIPTOSTREET=1 Main St&PAYMENTREQUEST_0_SHIPTOCITY=San Jose&PAYMENTREQUEST_0_SHIPTOSTATE=CA&PAYMENTREQUEST_0_SHIPTOZIP=95131&PAYMENTREQUEST_0_SHIPTOCOUNTRYCODE=US&PAYMENTREQUEST_0_SHIPTOCOUNTRYNAME=United States&PAYMENTREQUEST_0_ADDRESSSTATUS=Confirmed&PAYMENTREQUEST_0_ADDRESSNORMALIZATIONSTATUS=None&L_PAYMENTREQUEST_0_NAME0=item&L_PAYMENTREQUEST_0_QTY0=1&L_PAYMENTREQUEST_0_TAXAMT0=0.00&L_PAYMENTREQUEST_0_AMT0=1.00&L_PAYMENTREQUEST_0_ITEMWEIGHTVALUE0= 0.00000&L_PAYMENTREQUEST_0_ITEMLENGTHVALUE0= 0.00000&L_PAYMENTREQUEST_0_ITEMWIDTHVALUE0= 0.00000&L_PAYMENTREQUEST_0_ITEMHEIGHTVALUE0= 0.00000&PAYMENTREQUESTINFO_0_ERRORCODE=0
+
+ if(!"Success".equals(ack)) {
+ LOGGER.error("Wrong value from anthorize and capture transaction " + ack);
+ throw new IntegrationException("Wrong paypal ack from init transaction " + ack);
+ }
+
+
+ PaymentDetailsType paymentDetail = new PaymentDetailsType();
+ /** IPN **/
+ //paymentDetail.setNotifyURL("http://replaceIpnUrl.com");
+ BasicAmountType orderTotal = new BasicAmountType();
+ orderTotal.setValue(pricingService.getStringAmount(amount, store));
+ orderTotal.setCurrencyID(urn.ebay.apis.eBLBaseComponents.CurrencyCodeType.fromValue(payment.getCurrency().getCode()));
+ paymentDetail.setOrderTotal(orderTotal);
+ paymentDetail.setButtonSource("Shopizer_Cart_AP");
+ /** sale or pre-auth **/
+ if(payment.getTransactionType().name().equals(TransactionType.AUTHORIZE.name())) {
+ paymentDetail.setPaymentAction(urn.ebay.apis.eBLBaseComponents.PaymentActionCodeType.AUTHORIZATION);
+ } else {
+ paymentDetail.setPaymentAction(urn.ebay.apis.eBLBaseComponents.PaymentActionCodeType.SALE);
+ }
+
+ List<PaymentDetailsType> paymentDetails = new ArrayList<PaymentDetailsType>();
+ paymentDetails.add(paymentDetail);
+
+ DoExpressCheckoutPaymentRequestDetailsType doExpressCheckoutPaymentRequestDetails = new DoExpressCheckoutPaymentRequestDetailsType();
+ doExpressCheckoutPaymentRequestDetails.setToken(token);
+ doExpressCheckoutPaymentRequestDetails.setPayerID(payerId);
+ doExpressCheckoutPaymentRequestDetails.setPaymentDetails(paymentDetails);
+
+ DoExpressCheckoutPaymentRequestType doExpressCheckoutPaymentRequest = new DoExpressCheckoutPaymentRequestType(doExpressCheckoutPaymentRequestDetails);
+ doExpressCheckoutPaymentRequest.setVersion("104.0");
+
+ DoExpressCheckoutPaymentReq doExpressCheckoutPaymentReq = new DoExpressCheckoutPaymentReq();
+ doExpressCheckoutPaymentReq.setDoExpressCheckoutPaymentRequest(doExpressCheckoutPaymentRequest);
+
+
+ DoExpressCheckoutPaymentResponseType doExpressCheckoutPaymentResponse = service.doExpressCheckoutPayment(doExpressCheckoutPaymentReq);
+ String commitAck = doExpressCheckoutPaymentResponse.getAck().getValue();
+
+
+ if(!"Success".equals(commitAck)) {
+ LOGGER.error("Wrong value from transaction commit " + ack);
+ throw new IntegrationException("Wrong paypal ack from init transaction " + ack);
+ }
+
+
+ List<PaymentInfoType> paymentInfoList = doExpressCheckoutPaymentResponse.getDoExpressCheckoutPaymentResponseDetails().getPaymentInfo();
+ String transactionId = null;
+
+ for(PaymentInfoType paymentInfo : paymentInfoList) {
+ transactionId = paymentInfo.getTransactionID();
+ }
+
+
+
+
+ //TOKEN=EC-90U93956LU4997256&SUCCESSPAGEREDIRECTREQUESTED=false&TIMESTAMP=2014-02-16T15:41:03Z&CORRELATIONID=39d4ab666c1d7&ACK=Success&VERSION=104.0&BUILD=9720069&INSURANCEOPTIONSELECTED=false&SHIPPINGOPTIONISDEFAULT=false&PAYMENTINFO_0_TRANSACTIONID=4YA742984J1256935&PAYMENTINFO_0_TRANSACTIONTYPE=expresscheckout&PAYMENTINFO_0_PAYMENTTYPE=instant&PAYMENTINFO_0_ORDERTIME=2014-02-16T15:41:03Z&PAYMENTINFO_0_AMT=1.00&PAYMENTINFO_0_FEEAMT=0.33&PAYMENTINFO_0_TAXAMT=0.00&PAYMENTINFO_0_CURRENCYCODE=USD&PAYMENTINFO_0_PAYMENTSTATUS=Completed&PAYMENTINFO_0_PENDINGREASON=None&PAYMENTINFO_0_REASONCODE=None&PAYMENTINFO_0_PROTECTIONELIGIBILITY=Eligible&PAYMENTINFO_0_PROTECTIONELIGIBILITYTYPE=ItemNotReceivedEligible,UnauthorizedPaymentEligible&PAYMENTINFO_0_SECUREMERCHANTACCOUNTID=TWLK53YN7GDM6&PAYMENTINFO_0_ERRORCODE=0&PAYMENTINFO_0_ACK=Success
+
+ Transaction transaction = new Transaction();
+ transaction.setAmount(amount);
+ transaction.setTransactionDate(new Date());
+ transaction.setTransactionType(payment.getTransactionType());
+ transaction.setPaymentType(PaymentType.PAYPAL);
+ transaction.getTransactionDetails().put("TOKEN", token);
+ transaction.getTransactionDetails().put("PAYERID", payerId);
+ transaction.getTransactionDetails().put("TRANSACTIONID", transactionId);
+ transaction.getTransactionDetails().put("CORRELATION", correlationID);
+
+
+
+ return transaction;
+
+
+ } catch(Exception e) {
+ throw new IntegrationException(e);
+ }
+
+
+
+ }
+
+ @Override
+ public Transaction capture(MerchantStore store, Customer customer,
+ Order order, Transaction capturableTransaction,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+
+
+
+ try {
+
+
+
+ Validate.notNull(capturableTransaction,"Transaction cannot be null");
+ Validate.notNull((String)capturableTransaction.getTransactionDetails().get("TRANSACTIONID"), "Transaction details must contain a TRANSACTIONID");
+ Validate.notNull(order,"Order must not be null");
+ Validate.notNull(order.getCurrency(),"Order nust contain Currency object");
+
+ String mode = "sandbox";
+ String env = configuration.getEnvironment();
+ if(Constants.PRODUCTION_ENVIRONMENT.equals(env)) {
+ mode = "production";
+ }
+
+
+ Map<String,String> configurationMap = new HashMap<String,String>();
+ configurationMap.put("mode", mode);
+ configurationMap.put("acct1.UserName", configuration.getIntegrationKeys().get("username"));
+ configurationMap.put("acct1.Password", configuration.getIntegrationKeys().get("api"));
+ configurationMap.put("acct1.Signature", configuration.getIntegrationKeys().get("signature"));
+
+
+ DoCaptureReq doCaptureReq = new DoCaptureReq();
+
+
+
+
+ BasicAmountType amount = new BasicAmountType();
+ amount.setValue(pricingService.getStringAmount(order.getTotal(), store));
+ amount.setCurrencyID(urn.ebay.apis.eBLBaseComponents.CurrencyCodeType.fromValue(order.getCurrency().getCode()));
+
+ // DoCaptureRequest which takes mandatory params:
+ //
+ // Authorization ID - Authorization identification number of the
+ // payment you want to capture. This is the transaction ID
+ DoCaptureRequestType doCaptureRequest = new DoCaptureRequestType(
+ (String)capturableTransaction.getTransactionDetails().get("TRANSACTIONID"), amount, CompleteCodeType.NOTCOMPLETE);
+
+ doCaptureReq.setDoCaptureRequest(doCaptureRequest);
+
+ // ## Creating service wrapper object
+ // Creating service wrapper object to make API call and loading
+ // configuration file for your credentials and endpoint
+ PayPalAPIInterfaceServiceService service = new PayPalAPIInterfaceServiceService(configurationMap);
+
+ DoCaptureResponseType doCaptureResponse = null;
+
+ // ## Making API call
+ // Invoke the appropriate method corresponding to API in service
+ // wrapper object
+ doCaptureResponse = service
+ .doCapture(doCaptureReq);
+
+
+ // ## Accessing response parameters
+ // You can access the response parameters using getter methods in
+ // response object as shown below
+ // ### Success values
+ if(!"Success".equals(doCaptureResponse.getAck().getValue())) {
+ LOGGER.error("Wrong value from transaction commit " + doCaptureResponse.getAck().getValue());
+ throw new IntegrationException("Wrong paypal ack from refund transaction " + doCaptureResponse.getAck().getValue());
+ }
+ //if (doCaptureResponse.getAck().getValue()
+ // .equalsIgnoreCase("success")) {
+
+ // Authorization identification number
+ //logger.info("Authorization ID:"
+ // + doCaptureResponse.getDoCaptureResponseDetails()
+ // .getAuthorizationID());
+ //}
+ // ### Error Values
+ // Access error values from error list using getter methods
+ //else {
+ // List<ErrorType> errorList = doCaptureResponse.getErrors();
+ // logger.severe("API Error Message : "
+ // + errorList.get(0).getLongMessage());
+ //}
+
+ //String refundAck = refundTransactionResponse.getAck().getValue();
+
+
+
+
+
+ Transaction newTransaction = new Transaction();
+ newTransaction.setAmount(order.getTotal());
+ newTransaction.setTransactionDate(new Date());
+ newTransaction.setTransactionType(TransactionType.CAPTURE);
+ newTransaction.setPaymentType(PaymentType.PAYPAL);
+ newTransaction.getTransactionDetails().put("AUTHORIZATIONID", doCaptureResponse.getDoCaptureResponseDetails().getAuthorizationID());
+ newTransaction.getTransactionDetails().put("TRANSACTIONID", (String)capturableTransaction.getTransactionDetails().get("TRANSACTIONID"));
+
+ return newTransaction;
+
+
+ } catch(Exception e) {
+ throw new IntegrationException(e);
+ }
+
+
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/integration/payment/impl/PayPalRestPayment.java b/sm-core/src/main/java/com/salesmanager/core/modules/integration/payment/impl/PayPalRestPayment.java
new file mode 100644
index 0000000..54e4b23
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/integration/payment/impl/PayPalRestPayment.java
@@ -0,0 +1,262 @@
+package com.salesmanager.core.modules.integration.payment.impl;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+
+//import com.paypal.core.rest.OAuthTokenCredential;
+//import com.paypal.core.rest.PayPalRESTException;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.business.payments.model.Payment;
+import com.salesmanager.core.business.payments.model.Transaction;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartItem;
+import com.salesmanager.core.business.system.model.IntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+import com.salesmanager.core.business.system.service.MerchantConfigurationService;
+import com.salesmanager.core.business.system.service.MerchantLogService;
+import com.salesmanager.core.modules.integration.IntegrationException;
+import com.salesmanager.core.modules.integration.payment.model.PaymentModule;
+import com.salesmanager.core.utils.ProductPriceUtils;
+
+public class PayPalRestPayment implements PaymentModule {
+
+ @Autowired
+ private ProductPriceUtils productPriceUtils;
+
+ @Autowired
+ private MerchantConfigurationService merchantConfigurationService;
+
+ @Autowired
+ private MerchantLogService merchantLogService;
+
+ @Override
+ public void validateModuleConfiguration(
+ IntegrationConfiguration integrationConfiguration,
+ MerchantStore store) throws IntegrationException {
+
+
+ List<String> errorFields = null;
+
+ //validate integrationKeys['account']
+ Map<String,String> keys = integrationConfiguration.getIntegrationKeys();
+ if(keys==null || StringUtils.isBlank(keys.get("client"))) {
+ errorFields = new ArrayList<String>();
+ errorFields.add("client");
+ }
+
+ if(keys==null || StringUtils.isBlank(keys.get("secret"))) {
+ if(errorFields==null) {
+ errorFields = new ArrayList<String>();
+ }
+ errorFields.add("secret");
+ }
+
+
+ if(errorFields!=null) {
+ IntegrationException ex = new IntegrationException(IntegrationException.ERROR_VALIDATION_SAVE);
+ ex.setErrorFields(errorFields);
+ throw ex;
+
+ }
+
+ }
+
+ @Override
+ public Transaction initTransaction(MerchantStore store, Customer customer,
+ BigDecimal amount, Payment payment,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Transaction authorize(MerchantStore store, Customer customer,
+ List<ShoppingCartItem> items, BigDecimal amount, Payment payment,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+
+ return null;
+
+/*
+ // ###AccessToken
+ // Retrieve the access token from
+ // OAuthTokenCredential by passing in
+ // ClientID and ClientSecret
+ APIContext apiContext = null;
+ String accessToken = null;
+
+ try {
+
+ String clientID = configuration.getIntegrationKeys().get("client");
+ String secret = configuration.getIntegrationKeys().get("secret");
+
+ accessToken = getAccessToken(clientID, secret);
+
+ // ### Api Context
+ // Pass in a `ApiContext` object to authenticate
+ // the call and to send a unique request id
+ // (that ensures idempotency). The SDK generates
+ // a request id if you do not pass one explicitly.
+ apiContext = new APIContext(accessToken);
+ // Use this variant if you want to pass in a request id
+ // that is meaningful in your application, ideally
+ // a order id.
+
+ * String requestId = Long.toString(System.nanoTime(); APIContext
+ * apiContext = new APIContext(accessToken, requestId ));
+
+
+ // ###Authorization
+ // Retrieve an Authorization Id
+ // by making a Payment with intent
+ // as 'authorize' and parsing through
+ // the Payment object
+
+
+ String authorizationID = null;
+
+ // ###Details
+ // Let's you specify details of a payment amount.
+ //Details details = new Details();
+ //details.setShipping("0.03");
+ //details.setSubtotal("107.41");
+ //details.setTax("0.03");
+
+ // ###Amount
+ // Let's you specify a payment amount.
+
+ String sAmount = productPriceUtils.getAdminFormatedAmount(store, amount);
+
+
+ Amount amnt = new Amount();
+ amnt.setCurrency(store.getCurrency().getCode());
+ amnt.setTotal(sAmount);
+ //amnt.setDetails(details);
+
+ // ###Transaction
+ // A transaction defines the contract of a
+ // payment - what is the payment for and who
+ // is fulfilling it. Transaction is created with
+ // a `Payee` and `Amount` types
+ com.paypal.api.payments.Transaction transaction = new com.paypal.api.payments.Transaction();
+ transaction.setAmount(amnt);
+ //TODO change description
+ transaction.setDescription("This is the payment transaction description.");
+
+ // The Payment creation API requires a list of
+ // Transaction; add the created `Transaction`
+ // to a List
+ List<com.paypal.api.payments.Transaction> transactions = new ArrayList<com.paypal.api.payments.Transaction>();
+ transactions.add(transaction);
+
+ // ###Payer
+ // A resource representing a Payer that funds a payment
+ // Payment Method
+ // as 'paypal'
+ Payer payer = new Payer();
+ payer.setPaymentMethod("paypal");
+
+ // ###Payment
+ // A Payment Resource; create one using
+ // the above types and intent as 'sale'
+ com.paypal.api.payments.Payment ppayment = new com.paypal.api.payments.Payment();
+ ppayment.setIntent("sale");
+ ppayment.setPayer(payer);
+ ppayment.setTransactions(transactions);
+
+ // ###Redirect URLs
+ RedirectUrls redirectUrls = new RedirectUrls();
+ String guid = UUID.randomUUID().toString().replaceAll("-", "");
+ redirectUrls.setCancelUrl(req.getScheme() + "://"
+ + req.getServerName() + ":" + req.getServerPort()
+ + req.getContextPath() + "/paymentwithpaypal?guid=" + guid);
+ redirectUrls.setReturnUrl(req.getScheme() + "://"
+ + req.getServerName() + ":" + req.getServerPort()
+ + req.getContextPath() + "/paymentwithpaypal?guid=" + guid);
+ payment.setRedirectUrls(redirectUrls);
+
+ // Create a payment by posting to the APIService
+ // using a valid AccessToken
+ // The return object contains the status;
+ try {
+ Payment createdPayment = payment.create(apiContext);
+ LOGGER.info("Created payment with id = "
+ + createdPayment.getId() + " and status = "
+ + createdPayment.getState());
+ // ###Payment Approval Url
+ Iterator<Links> links = createdPayment.getLinks().iterator();
+ while (links.hasNext()) {
+ Links link = links.next();
+ if (link.getRel().equalsIgnoreCase("approval_url")) {
+ req.setAttribute("redirectURL", link.getHref());
+ }
+ }
+ req.setAttribute("response", Payment.getLastResponse());
+ map.put(guid, createdPayment.getId());
+ } catch (PayPalRESTException e) {
+ req.setAttribute("error", e.getMessage());
+ }
+ } catch (PayPalRESTException e) {
+ throw new IntegrationException(e);
+ }
+*/
+
+
+ }
+
+/* @Override
+ public Transaction capture(MerchantStore store, Customer customer,
+ List<ShoppingCartItem> items, BigDecimal amount, Payment payment, Transaction transaction,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+ // TODO Auto-generated method stub
+ return null;
+ }*/
+
+ @Override
+ public Transaction authorizeAndCapture(MerchantStore store,
+ Customer customer, List<ShoppingCartItem> items, BigDecimal amount, Payment payment,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public Transaction refund(boolean partial, MerchantStore store,
+ Transaction transaction, Order order, BigDecimal amount,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ private String getAccessToken(String clientID, String clientSecret) throws Exception {
+
+ // ###AccessToken
+ // Retrieve the access token from
+ // OAuthTokenCredential by passing in
+ // ClientID and ClientSecret
+
+ return null;
+ //return new OAuthTokenCredential(clientID, clientSecret)
+ // .getAccessToken();
+ }
+
+ @Override
+ public Transaction capture(MerchantStore store, Customer customer,
+ Order order, Transaction capturableTransaction,
+ IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/integration/payment/model/PaymentModule.java b/sm-core/src/main/java/com/salesmanager/core/modules/integration/payment/model/PaymentModule.java
new file mode 100644
index 0000000..a6790bd
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/integration/payment/model/PaymentModule.java
@@ -0,0 +1,49 @@
+package com.salesmanager.core.modules.integration.payment.model;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.business.payments.model.Payment;
+import com.salesmanager.core.business.payments.model.Transaction;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartItem;
+import com.salesmanager.core.business.system.model.IntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+import com.salesmanager.core.modules.integration.IntegrationException;
+
+public interface PaymentModule {
+
+ public void validateModuleConfiguration(IntegrationConfiguration integrationConfiguration, MerchantStore store) throws IntegrationException;
+
+ /**
+ * Returns token-value related to the initialization of the transaction This
+ * method is invoked for paypal express checkout
+ * @param customer
+ * @param order
+ * @return
+ * @throws IntegrationException
+ */
+ public Transaction initTransaction(
+ MerchantStore store, Customer customer, BigDecimal amount, Payment payment, IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException;
+
+ public Transaction authorize(
+ MerchantStore store, Customer customer, List<ShoppingCartItem> items, BigDecimal amount, Payment payment, IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException;
+
+
+ public Transaction capture(
+ MerchantStore store, Customer customer, Order order, Transaction capturableTransaction, IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException;
+
+ public Transaction authorizeAndCapture(
+ MerchantStore store, Customer customer, List<ShoppingCartItem> items, BigDecimal amount, Payment payment, IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException;
+
+ public Transaction refund(
+ boolean partial, MerchantStore store, Transaction transaction, Order order, BigDecimal amount, IntegrationConfiguration configuration, IntegrationModule module)
+ throws IntegrationException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/impl/CanadaPostShippingQuote.java b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/impl/CanadaPostShippingQuote.java
new file mode 100644
index 0000000..3eeabea
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/impl/CanadaPostShippingQuote.java
@@ -0,0 +1,563 @@
+package com.salesmanager.core.modules.integration.shipping.impl;
+
+import java.io.Reader;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.commons.digester.Digester;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.RequestEntity;
+import org.apache.commons.httpclient.methods.StringRequestEntity;
+import org.apache.commons.lang.Validate;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.salesmanager.core.business.common.model.Delivery;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.shipping.model.PackageDetails;
+import com.salesmanager.core.business.shipping.model.ShippingConfiguration;
+import com.salesmanager.core.business.shipping.model.ShippingOption;
+import com.salesmanager.core.business.system.model.CustomIntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+import com.salesmanager.core.business.system.model.MerchantLog;
+import com.salesmanager.core.business.system.model.ModuleConfig;
+import com.salesmanager.core.business.system.service.MerchantLogService;
+import com.salesmanager.core.constants.MeasureUnit;
+import com.salesmanager.core.modules.integration.IntegrationException;
+import com.salesmanager.core.modules.integration.shipping.model.ShippingQuoteModule;
+import com.salesmanager.core.utils.DataUtils;
+import com.salesmanager.core.utils.ProductPriceUtils;
+
+/**
+ * Integrates with Canada Post sell online API
+ * @author casams1
+ *
+ */
+public class CanadaPostShippingQuote implements ShippingQuoteModule {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CanadaPostShippingQuote.class);
+
+
+ private final static String SHIPPING_TURN_AROUND_TIME = "24";
+
+
+ @Autowired
+ private ProductPriceUtils productPriceUtils;
+
+ @Autowired
+ private MerchantLogService merchantLogService;
+
+ @Override
+ public void validateModuleConfiguration(
+ IntegrationConfiguration integrationConfiguration,
+ MerchantStore store) throws IntegrationException {
+
+
+
+
+ List<String> errorFields = null;
+
+ //validate integrationKeys['account']
+ Map<String,String> keys = integrationConfiguration.getIntegrationKeys();
+ if(keys==null || StringUtils.isBlank(keys.get("account"))) {
+ errorFields = new ArrayList<String>();
+ errorFields.add("identifier");
+ }
+
+ //validate at least one integrationOptions['packages']
+ Map<String,List<String>> options = integrationConfiguration.getIntegrationOptions();
+ if(options==null) {
+ errorFields = new ArrayList<String>();
+ errorFields.add("identifier");
+ }
+
+ List<String> packages = options.get("packages");
+ if(packages==null || packages.size()==0) {
+ if(errorFields==null) {
+ errorFields = new ArrayList<String>();
+ }
+ errorFields.add("packages");
+ }
+
+ if(errorFields!=null) {
+ IntegrationException ex = new IntegrationException(IntegrationException.ERROR_VALIDATION_SAVE);
+ ex.setErrorFields(errorFields);
+ throw ex;
+
+ }
+
+ }
+
+ @Override
+ public List<ShippingOption> getShippingQuotes(List<PackageDetails> packages, BigDecimal orderTotal, Delivery delivery, MerchantStore store, IntegrationConfiguration configuration, IntegrationModule module, ShippingConfiguration shippingConfiguration, Locale locale) throws IntegrationException {
+ BigDecimal total = orderTotal;
+
+
+ Validate.notNull(packages, "Packages are null");
+ Validate.notNull(delivery.getPostalCode(), "Delivery postal code is null");
+
+ List<ShippingOption> options = null;
+
+ // only applies to Canada and US
+ Country country = delivery.getCountry();
+
+
+
+
+ if(!(country.getIsoCode().equals("US") || country.getIsoCode().equals("CA"))) {
+ throw new IntegrationException("Canadapost Not configured for shipping in country " + country.getIsoCode());
+ }
+
+ // supports en and fr
+ String language = locale.getLanguage();
+ if (!language.equals(Locale.FRENCH.getLanguage())
+ && !language.equals(Locale.ENGLISH.getLanguage())) {
+ language = Locale.ENGLISH.getLanguage();
+ }
+
+
+ // if store is not CAD /** maintained in the currency **/
+/* if (!store.getCurrency().equals(Constants.CURRENCY_CODE_CAD)) {
+ total = CurrencyUtil.convertToCurrency(total, store.getCurrency(),
+ Constants.CURRENCY_CODE_CAD);
+ }*/
+
+
+ PostMethod httppost = null;
+ CanadaPostParsedElements canadaPost = null;
+
+ try {
+
+ Map<String,String> keys = configuration.getIntegrationKeys();
+ if(keys==null || StringUtils.isBlank(keys.get("account"))) {
+ throw new IntegrationException("Canadapost missing configuration key account");
+ }
+
+
+ String host = null;
+ String protocol = null;
+ String port = null;
+ String url = null;
+
+
+
+ //against which environment are we using the service
+ String env = configuration.getEnvironment();
+
+
+ Map<String, ModuleConfig> moduleConfigsMap = module.getModuleConfigs();
+ for(String key : moduleConfigsMap.keySet()) {
+
+ ModuleConfig moduleConfig = (ModuleConfig)moduleConfigsMap.get(key);
+ if(moduleConfig.getEnv().equals(env)) {
+ host = moduleConfig.getHost();
+ protocol = moduleConfig.getScheme();
+ port = moduleConfig.getPort();
+ url = moduleConfig.getUri();
+ }
+ }
+
+
+
+ // accept KG and CM
+
+ StringBuilder request = new StringBuilder();
+
+ request.append("<?xml version=\"1.0\" ?>");
+ request.append("<eparcel>");
+ request.append("<language>").append(language).append("</language>");
+
+ request.append("<ratesAndServicesRequest>");
+ request.append("<merchantCPCID>").append(keys.get("account")).append(
+ "</merchantCPCID>");
+ request.append("<fromPostalCode>").append(
+ DataUtils
+ .trimPostalCode(store.getStorepostalcode()))
+ .append("</fromPostalCode>");
+ request.append("<turnAroundTime>").append(SHIPPING_TURN_AROUND_TIME).append(
+ "</turnAroundTime>");
+ request.append("<itemsPrice>").append(
+ productPriceUtils.getFormatedAmountWithCurrency(store,total, locale))
+ .append("</itemsPrice>");
+ request.append("<lineItems>");
+
+
+ for(PackageDetails pack : packages) {
+ request.append("<item>");
+ request.append("<quantity>").append(pack.getShippingQuantity())
+ .append("</quantity>");
+ request.append("<weight>").append(
+ String.valueOf(DataUtils.getWeight(pack
+ .getShippingWeight(), store,
+ MeasureUnit.KG.name()))).append("</weight>");
+ request.append("<length>").append(
+ String.valueOf(DataUtils.getMeasure(pack
+ .getShippingLength(), store,
+ MeasureUnit.CM.name()))).append("</length>");
+ request.append("<width>").append(
+ String.valueOf(DataUtils.getMeasure(pack
+ .getShippingWidth(), store,
+ MeasureUnit.CM.name()))).append("</width>");
+ request.append("<height>").append(
+ String.valueOf(DataUtils.getMeasure(pack
+ .getShippingHeight(), store,
+ MeasureUnit.CM.name()))).append("</height>");
+ request.append("<description>").append(pack.getItemName())
+ .append("</description>");
+ request.append("<readyToShip/>");//item is properly packed
+ request.append("</item>");
+ }
+
+ request.append("</lineItems>");
+
+ request.append("<city>").append(delivery.getCity()).append(
+ "</city>");
+ if(delivery.getZone()!=null) {
+ request.append("<provOrState>").append(delivery.getZone().getCode())
+ .append("</provOrState>");
+ } else {
+ request.append("<provOrState>").append(delivery.getZone())
+ .append("</provOrState>");
+ }
+ request.append("<country>")
+ .append(delivery.getCountry().getIsoCode()).append(
+ "</country>");
+ request.append("<postalCode>").append(
+ DataUtils
+ .trimPostalCode(delivery.getPostalCode()))
+ .append("</postalCode>");
+ request.append("</ratesAndServicesRequest>");
+ request.append("</eparcel>");
+
+
+ /**
+ * <?xml version="1.0" ?> <eparcel>
+ * <!--********************************--> <!-- Prefered language
+ * for the --> <!-- response (FR/EN) (optional) -->
+ * <!--********************************--> <language>en</language>
+ *
+ * <ratesAndServicesRequest>
+ * <!--**********************************--> <!-- Merchant
+ * Identification assigned --> <!-- by Canada Post --> <!-- --> <!--
+ * Note: Use 'CPC_DEMO_HTML' or ask --> <!-- our Help Desk to change
+ * your --> <!-- profile if you want HTML to be --> <!-- returned to
+ * you --> <!--**********************************--> <merchantCPCID>
+ * CPC_DEMO_XML </merchantCPCID>
+ *
+ * <!--*********************************--> <!--Origin Postal Code
+ * --> <!--This parameter is optional -->
+ * <!--*********************************-->
+ * <fromPostalCode>m1p1c0</fromPostalCode>
+ *
+ * <!--**********************************--> <!-- Turn Around Time
+ * (hours) --> <!-- This parameter is optional -->
+ * <!--**********************************--> <turnAroundTime> 24
+ * </turnAroundTime>
+ *
+ * <!--**********************************--> <!-- Total amount in $
+ * of the items --> <!-- for insurance calculation --> <!-- This
+ * parameter is optional -->
+ * <!--**********************************-->
+ * <itemsPrice>0.00</itemsPrice>
+ *
+ * <!--**********************************--> <!-- List of items in
+ * the shopping --> <!-- cart --> <!-- Each item is defined by : -->
+ * <!-- - quantity (mandatory) --> <!-- - size (mandatory) --> <!--
+ * - weight (mandatory) --> <!-- - description (mandatory) --> <!--
+ * - ready to ship (optional) -->
+ * <!--**********************************--> <lineItems> <item>
+ * <quantity> 1 </quantity> <weight> 1.491 </weight> <length> 1
+ * </length> <width> 1 </width> <height> 1 </height> <description>
+ * KAO Diskettes </description> </item>
+ *
+ * <item> <quantity> 1 </quantity> <weight> 1.5 </weight> <length>
+ * 20 </length> <width> 30 </width> <height> 20 </height>
+ * <description> My Ready To Ship Item</description>
+ * <!--**********************************************--> <!-- By
+ * adding the 'readyToShip' tag, Sell Online --> <!-- will not pack
+ * this item in the boxes --> <!-- defined in the merchant profile.
+ * --> <!-- Instead, this item will be shipped in its --> <!--
+ * original box: 1.5 kg and 20x30x20 cm -->
+ * <!--**********************************************-->
+ * <readyToShip/> </item> </lineItems>
+ *
+ * <!--********************************--> <!-- City where the
+ * parcel will be --> <!-- shipped to -->
+ * <!--********************************--> <city> </city>
+ *
+ * <!--********************************--> <!-- Province (Canada) or
+ * State (US)--> <!-- where the parcel will be --> <!-- shipped to
+ * --> <!--********************************--> <provOrState>
+ * Wisconsin </provOrState>
+ *
+ * <!--********************************--> <!-- Country or ISO
+ * Country code --> <!-- where the parcel will be --> <!-- shipped
+ * to --> <!--********************************--> <country> CANADA
+ * </country>
+ *
+ * <!--********************************--> <!-- Postal Code (or ZIP)
+ * where the --> <!-- parcel will be shipped to -->
+ * <!--********************************--> <postalCode>
+ * H3K1E5</postalCode> </ratesAndServicesRequest> </eparcel>
+ **/
+
+
+ LOGGER.debug("canadapost request " + request.toString());
+
+ HttpClient client = new HttpClient();
+
+ StringBuilder u = new StringBuilder().append(protocol).append("://").append(host).append(":").append(port);
+ if(!StringUtils.isBlank(url)) {
+ u.append(url);
+ }
+
+ LOGGER.debug("Canadapost URL " + u.toString());
+
+ httppost = new PostMethod(u.toString());
+ RequestEntity entity = new StringRequestEntity(request.toString(),
+ "text/plain", "UTF-8");
+ httppost.setRequestEntity(entity);
+
+ int result = client.executeMethod(httppost);
+
+ if (result != 200) {
+ LOGGER.error("Communication Error with canadapost " + protocol
+ + "://" + host + ":" + port + url);
+ throw new Exception("Communication Error with canadapost "
+ + protocol + "://" + host + ":" + port + url);
+ }
+ String stringresult = httppost.getResponseBodyAsString();
+ LOGGER.debug("canadapost response " + stringresult);
+
+
+/* <eparcel>
+ <error>
+ <statusCode>-3001</statusCode>
+ <statusMessage>Destination Postal Code/State Name/ Country is illegal. </statusMessage>
+ <requestID>2773909</requestID>
+ </error>
+ </eparcel>*/
+
+ canadaPost = new CanadaPostParsedElements();
+ Digester digester = new Digester();
+ digester.push(canadaPost);
+
+ digester.addCallMethod(
+ "eparcel/error/statusCode",
+ "setStatusCode", 0);
+
+ digester.addCallMethod(
+ "eparcel/error/statusMessage",
+ "setStatusMessage", 0);
+
+ digester.addCallMethod(
+ "eparcel/ratesAndServicesResponse/statusCode",
+ "setStatusCode", 0);
+ digester.addCallMethod(
+ "eparcel/ratesAndServicesResponse/statusMessage",
+ "setStatusMessage", 0);
+ digester.addObjectCreate(
+ "eparcel/ratesAndServicesResponse/product",
+ ShippingOption.class);
+ digester.addSetProperties(
+ "eparcel/ratesAndServicesResponse/product", "sequence",
+ "optionId");
+ digester.addCallMethod(
+ "eparcel/ratesAndServicesResponse/product/shippingDate",
+ "setOptionShippingDate", 0);
+ digester.addCallMethod(
+ "eparcel/ratesAndServicesResponse/product/deliveryDate",
+ "setOptionDeliveryDate", 0);
+ digester.addCallMethod(
+ "eparcel/ratesAndServicesResponse/product/name",
+ "setOptionName", 0);
+ digester.addCallMethod(
+ "eparcel/ratesAndServicesResponse/product/rate",
+ "setOptionPriceText", 0);
+
+ digester.addSetNext("eparcel/ratesAndServicesResponse/product",
+ "addOption");
+
+ /**
+ * response
+ *
+ * <?xml version="1.0" ?> <!DOCTYPE eparcel (View Source for full
+ * doctype...)> - <eparcel> - <ratesAndServicesResponse>
+ * <statusCode>1</statusCode> <statusMessage>OK</statusMessage>
+ * <requestID>1769506</requestID> <handling>0.0</handling>
+ * <language>0</language> - <product id="1040" sequence="1">
+ * <name>Priority Courier</name> <rate>38.44</rate>
+ * <shippingDate>2008-12-22</shippingDate>
+ * <deliveryDate>2008-12-23</deliveryDate>
+ * <deliveryDayOfWeek>3</deliveryDayOfWeek>
+ * <nextDayAM>true</nextDayAM> <packingID>P_0</packingID> </product>
+ * - <product id="1020" sequence="2"> <name>Expedited</name>
+ * <rate>16.08</rate> <shippingDate>2008-12-22</shippingDate>
+ * <deliveryDate>2008-12-23</deliveryDate>
+ * <deliveryDayOfWeek>3</deliveryDayOfWeek>
+ * <nextDayAM>false</nextDayAM> <packingID>P_0</packingID>
+ * </product> - <product id="1010" sequence="3">
+ * <name>Regular</name> <rate>16.08</rate>
+ * <shippingDate>2008-12-22</shippingDate>
+ * <deliveryDate>2008-12-29</deliveryDate>
+ * <deliveryDayOfWeek>2</deliveryDayOfWeek>
+ * <nextDayAM>false</nextDayAM> <packingID>P_0</packingID>
+ * </product> - <packing> <packingID>P_0</packingID> - <box>
+ * <name>Small Box</name> <weight>1.691</weight>
+ * <expediterWeight>1.691</expediterWeight> <length>25.0</length>
+ * <width>17.0</width> <height>16.0</height> - <packedItem>
+ * <quantity>1</quantity> <description>KAO Diskettes</description>
+ * </packedItem> </box> - <box> <name>My Ready To Ship Item</name>
+ * <weight>2.0</weight> <expediterWeight>1.5</expediterWeight>
+ * <length>30.0</length> <width>20.0</width> <height>20.0</height> -
+ * <packedItem> <quantity>1</quantity> <description>My Ready To Ship
+ * Item</description> </packedItem> </box> </packing> -
+ * <shippingOptions> <insurance>No</insurance>
+ * <deliveryConfirmation>Yes</deliveryConfirmation>
+ * <signature>No</signature> </shippingOptions> <comment />
+ * </ratesAndServicesResponse> </eparcel> - <!-- END_OF_EPARCEL -->
+ **/
+
+ Reader reader = new StringReader(stringresult);
+
+ digester.parse(reader);
+
+
+ if (canadaPost == null || canadaPost.getStatusCode() == null) {
+ LOGGER.error("Nothing received from CanadaPost");
+ return null;
+ }
+
+ System.out.println(canadaPost.getStatusCode());
+
+ if (canadaPost.getStatusCode().equals("-6")
+ || canadaPost.getStatusCode().equals("-7")) {
+ merchantLogService.save(
+ new MerchantLog(store,
+ "Can't process CanadaPost statusCode="
+ + canadaPost.getStatusCode() + " message= "
+ + canadaPost.getStatusMessage()));
+ }
+
+ if (canadaPost.getStatusCode().equals("-5000")) {
+ merchantLogService.save(
+ new MerchantLog(store,("An error occured with canadapost request (code-> "
+ + canadaPost.getStatusCode() + " message-> "
+ + canadaPost.getStatusMessage() )));
+ throw new IntegrationException("Error with post canada service " + canadaPost.getStatusMessage());
+ }
+
+ if (!canadaPost.getStatusCode().equals("1")) {
+ merchantLogService.save(
+ new MerchantLog(store,("An error occured with canadapost request (code-> "
+ + canadaPost.getStatusCode() + " message-> "
+ + canadaPost.getStatusMessage() )));
+ throw new IntegrationException("Error with post canada service " + canadaPost.getStatusMessage());
+ }
+
+ //String carrier = getShippingMethodDescription(locale);
+ // cost is in CAD, need to do conversion
+
+/* boolean requiresCurrencyConversion = false;
+ String storeCurrency = store.getCurrency();
+ if (!storeCurrency.equals(Constants.CURRENCY_CODE_CAD)) {
+ requiresCurrencyConversion = true;
+ }*/
+
+
+
+
+
+
+/* options = canadaPost.getOptions();
+ for(ShippingOption option : options) {
+ StringBuilder description = new StringBuilder();
+ description.append(option.getOptionName());
+ if (shippingConfiguration.getShippingDescription()==ShippingDescription.LONG_DESCRIPTION) {
+ description.append(" (").append(option.getOptionDeliveryDate())
+ .append(")");
+ }
+ option.setDescription(description.toString());
+ if (requiresCurrencyConversion) {
+ option.setOptionPrice(CurrencyUtil.convertToCurrency(option
+ .getOptionPrice(), Constants.CURRENCY_CODE_CAD,
+ store.getCurrency()));
+ }
+ // System.out.println(option.getOptionPrice().toString());
+
+ }*/
+
+
+
+ } catch (Exception e) {
+ LOGGER.error("Canadapost getShippingQuote", e);
+ throw new IntegrationException(e);
+ } finally {
+ if (httppost != null) {
+ httppost.releaseConnection();
+ }
+ }
+
+
+
+ return options;
+ }
+
+
+
+ @Override
+ public CustomIntegrationConfiguration getCustomModuleConfiguration(
+ MerchantStore store) throws IntegrationException {
+ //nothing to do
+ return null;
+ }
+
+
+
+
+
+
+}
+
+class CanadaPostParsedElements {
+
+ private String statusCode;
+ private String statusMessage;
+ private List<ShippingOption> options = new ArrayList<ShippingOption>();
+
+ public void addOption(ShippingOption option) {
+ options.add(option);
+ }
+
+ public List<ShippingOption> getOptions() {
+ return options;
+ }
+
+ public String getStatusCode() {
+ return statusCode;
+ }
+
+ public void setStatusCode(String statusCode) {
+ this.statusCode = statusCode;
+ }
+
+ public String getStatusMessage() {
+ return statusMessage;
+ }
+
+ public void setStatusMessage(String statusMessage) {
+ this.statusMessage = statusMessage;
+ }
+
+}
+
+
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/impl/CustomWeightBasedShippingQuote.java b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/impl/CustomWeightBasedShippingQuote.java
new file mode 100644
index 0000000..e80cf72
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/impl/CustomWeightBasedShippingQuote.java
@@ -0,0 +1,153 @@
+package com.salesmanager.core.modules.integration.shipping.impl;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.salesmanager.core.business.common.model.Delivery;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.shipping.model.PackageDetails;
+import com.salesmanager.core.business.shipping.model.ShippingBasisType;
+import com.salesmanager.core.business.shipping.model.ShippingConfiguration;
+import com.salesmanager.core.business.shipping.model.ShippingOption;
+import com.salesmanager.core.business.system.model.CustomIntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+import com.salesmanager.core.business.system.model.MerchantConfiguration;
+import com.salesmanager.core.business.system.service.MerchantConfigurationService;
+import com.salesmanager.core.modules.integration.IntegrationException;
+import com.salesmanager.core.modules.integration.shipping.model.CustomShippingQuoteWeightItem;
+import com.salesmanager.core.modules.integration.shipping.model.CustomShippingQuotesConfiguration;
+import com.salesmanager.core.modules.integration.shipping.model.CustomShippingQuotesRegion;
+import com.salesmanager.core.modules.integration.shipping.model.ShippingQuoteModule;
+import com.salesmanager.core.utils.ProductPriceUtils;
+
+public class CustomWeightBasedShippingQuote implements ShippingQuoteModule {
+
+ public final static String MODULE_CODE = "weightBased";
+ private final static String CUSTOM_WEIGHT = "CUSTOM_WEIGHT";
+
+ @Autowired
+ private MerchantConfigurationService merchantConfigurationService;
+
+ @Autowired
+ private ProductPriceUtils productPriceUtils;
+
+
+ @Override
+ public void validateModuleConfiguration(
+ IntegrationConfiguration integrationConfiguration,
+ MerchantStore store) throws IntegrationException {
+
+
+ //not used, it has its own controller with complex validators
+
+ }
+
+
+ @Override
+ public CustomIntegrationConfiguration getCustomModuleConfiguration(
+ MerchantStore store) throws IntegrationException {
+
+ try {
+
+ MerchantConfiguration configuration = merchantConfigurationService.getMerchantConfiguration(MODULE_CODE, store);
+
+ if(configuration!=null) {
+ String value = configuration.getValue();
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ CustomShippingQuotesConfiguration config = mapper.readValue(value, CustomShippingQuotesConfiguration.class);
+ return config;
+ } catch(Exception e) {
+ throw new ServiceException("Cannot parse json string " + value);
+ }
+
+ } else {
+ CustomShippingQuotesConfiguration custom = new CustomShippingQuotesConfiguration();
+ custom.setModuleCode(MODULE_CODE);
+ return custom;
+ }
+
+ } catch (Exception e) {
+ throw new IntegrationException(e);
+ }
+
+
+ }
+
+ @Override
+ public List<ShippingOption> getShippingQuotes(
+ List<PackageDetails> packages, BigDecimal orderTotal,
+ Delivery delivery, MerchantStore store,
+ IntegrationConfiguration configuration, IntegrationModule module,
+ ShippingConfiguration shippingConfiguration, Locale locale)
+ throws IntegrationException {
+
+
+
+ //get configuration
+ CustomShippingQuotesConfiguration customConfiguration = (CustomShippingQuotesConfiguration)this.getCustomModuleConfiguration(store);
+
+
+ List<CustomShippingQuotesRegion> regions = customConfiguration.getRegions();
+
+ ShippingBasisType shippingType = shippingConfiguration.getShippingBasisType();
+ ShippingOption shippingOption = null;
+ try {
+
+
+ for(CustomShippingQuotesRegion region : customConfiguration.getRegions()) {
+
+ for(String countryCode : region.getCountries()) {
+ if(countryCode.equals(delivery.getCountry().getIsoCode())) {
+
+
+ //determine shipping weight
+ double weight = 0;
+ for(PackageDetails packageDetail : packages) {
+ weight = weight + packageDetail.getShippingWeight();
+ }
+
+ //see the price associated with the width
+ List<CustomShippingQuoteWeightItem> quoteItems = region.getQuoteItems();
+ for(CustomShippingQuoteWeightItem quoteItem : quoteItems) {
+ if(weight<= quoteItem.getMaximumWeight()) {
+ shippingOption = new ShippingOption();
+ shippingOption.setOptionCode(new StringBuilder().append(CUSTOM_WEIGHT).toString());
+ shippingOption.setOptionId(new StringBuilder().append(CUSTOM_WEIGHT).append("_").append(region.getCustomRegionName()).toString());
+ shippingOption.setOptionPrice(quoteItem.getPrice());
+ shippingOption.setOptionPriceText(productPriceUtils.getStoreFormatedAmountWithCurrency(store, quoteItem.getPrice()));
+ break;
+ }
+ }
+
+ }
+
+
+ }
+
+ }
+
+ if(shippingOption!=null) {
+ List<ShippingOption> options = new ArrayList<ShippingOption>();
+ options.add(shippingOption);
+ return options;
+ }
+
+ return null;
+
+ } catch (Exception e) {
+ throw new IntegrationException(e);
+ }
+
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/impl/DefaultPackagingImpl.java b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/impl/DefaultPackagingImpl.java
new file mode 100644
index 0000000..1a95a72
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/impl/DefaultPackagingImpl.java
@@ -0,0 +1,436 @@
+package com.salesmanager.core.modules.integration.shipping.impl;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.shipping.model.PackageDetails;
+import com.salesmanager.core.business.shipping.model.ShippingConfiguration;
+import com.salesmanager.core.business.shipping.model.ShippingProduct;
+import com.salesmanager.core.business.shipping.service.ShippingService;
+import com.salesmanager.core.business.system.model.MerchantLog;
+import com.salesmanager.core.business.system.service.MerchantLogService;
+import com.salesmanager.core.modules.integration.shipping.model.Packaging;
+
+public class DefaultPackagingImpl implements Packaging {
+
+
+ @Autowired
+ private ShippingService shippingService;
+
+ @Autowired
+ private MerchantLogService merchantLogService;
+
+ /** default dimensions **/
+ private final static Double defaultWeight = 1D;
+ private final static Double defaultHeight = 4D;
+ private final static Double defaultLength = 4D;
+ private final static Double defaultWidth = 4D;
+
+ @Override
+ public List<PackageDetails> getBoxPackagesDetails(
+ List<ShippingProduct> products, MerchantStore store)
+ throws ServiceException {
+
+
+ if (products == null) {
+ throw new ServiceException("Product list cannot be null !!");
+ }
+
+ double width = 0;
+ double length = 0;
+ double height = 0;
+ double weight = 0;
+ double maxweight = 0;
+
+ //int treshold = 0;
+
+
+ ShippingConfiguration shippingConfiguration = shippingService.getShippingConfiguration(store);
+ if(shippingConfiguration==null) {
+ throw new ServiceException("ShippingConfiguration not found for merchant " + store.getCode());
+ }
+
+ width = new Double(shippingConfiguration.getBoxWidth()).doubleValue();
+ length = new Double(shippingConfiguration.getBoxLength()).doubleValue();
+ height = new Double(shippingConfiguration.getBoxHeight()).doubleValue();
+ weight = new Double(shippingConfiguration.getBoxWeight()).doubleValue();
+ maxweight = new Double(shippingConfiguration.getMaxWeight()).doubleValue();
+
+
+
+ List<PackageDetails> boxes = new ArrayList<PackageDetails>();
+
+ // maximum number of boxes
+ int maxBox = 100;
+ int iterCount = 0;
+
+ List<Product> individualProducts = new ArrayList<Product>();
+
+ // need to put items individually
+ for(ShippingProduct shippingProduct : products){
+
+ Product product = shippingProduct.getProduct();
+ if (product.isProductVirtual()) {
+ continue;
+ }
+
+ int qty = shippingProduct.getQuantity();
+
+ Set<ProductAttribute> attrs = shippingProduct.getProduct().getAttributes();
+
+ // set attributes values
+ BigDecimal w = product.getProductWeight();
+ BigDecimal h = product.getProductHeight();
+ BigDecimal l = product.getProductLength();
+ BigDecimal wd = product.getProductWidth();
+ if(w==null) {
+ w = new BigDecimal(defaultWeight);
+ }
+ if(h==null) {
+ h = new BigDecimal(defaultHeight);
+ }
+ if(l==null) {
+ l = new BigDecimal(defaultLength);
+ }
+ if(wd==null) {
+ wd = new BigDecimal(defaultWidth);
+ }
+ if (attrs != null && attrs.size() > 0) {
+ for(ProductAttribute attribute : attrs) {
+ if(attribute.getProductAttributeWeight()!=null) {
+ w = w.add(attribute.getProductAttributeWeight());
+ }
+ }
+ }
+
+
+
+ if (qty > 1) {
+
+ for (int i = 1; i <= qty; i++) {
+ Product temp = new Product();
+ temp.setProductHeight(h);
+ temp.setProductLength(l);
+ temp.setProductWidth(wd);
+ temp.setProductWeight(w);
+ temp.setAttributes(product.getAttributes());
+ temp.setDescriptions(product.getDescriptions());
+ individualProducts.add(temp);
+ }
+ } else {
+ Product temp = new Product();
+ temp.setProductHeight(h);
+ temp.setProductLength(l);
+ temp.setProductWidth(wd);
+ temp.setProductWeight(w);
+ temp.setAttributes(product.getAttributes());
+ temp.setDescriptions(product.getDescriptions());
+ individualProducts.add(temp);
+ }
+ iterCount++;
+ }
+
+ if (iterCount == 0) {
+ return null;
+ }
+
+ int productCount = individualProducts.size();
+
+ List<PackingBox> boxesList = new ArrayList<PackingBox>();
+
+ //start the creation of boxes
+ PackingBox box = new PackingBox();
+ // set box max volume
+ double maxVolume = width * length * height;
+
+ if (maxVolume == 0 || maxweight == 0) {
+
+ merchantLogService.save(new MerchantLog(store,"shipping","Check shipping box configuration, it has a volume of "
+ + maxVolume + " and a maximum weight of "
+ + maxweight
+ + ". Those values must be greater than 0."));
+
+ throw new ServiceException("Product configuration exceeds box configuraton");
+
+
+ }
+
+
+ box.setVolumeLeft(maxVolume);
+ box.setWeightLeft(maxweight);
+
+ boxesList.add(box);//assign first box
+
+ //int boxCount = 1;
+ List<Product> assignedProducts = new ArrayList<Product>();
+
+ // calculate the volume for the next object
+ if (assignedProducts.size() > 0) {
+ individualProducts.removeAll(assignedProducts);
+ assignedProducts = new ArrayList<Product>();
+ }
+
+ boolean productAssigned = false;
+
+ for(Product p : individualProducts) {
+
+ //Set<ProductAttribute> attributes = p.getAttributes();
+ productAssigned = false;
+
+ double productWeight = p.getProductWeight().doubleValue();
+
+
+ // validate if product fits in the box
+ if (p.getProductWidth().doubleValue() > width
+ || p.getProductHeight().doubleValue() > height
+ || p.getProductLength().doubleValue() > length) {
+ // log message to customer
+ merchantLogService.save(new MerchantLog(store,"shipping","Product "
+ + p.getSku()
+ + " has a demension larger than the box size specified. Will use per item calculation."));
+ throw new ServiceException("Product configuration exceeds box configuraton");
+
+ }
+
+ if (productWeight > maxweight) {
+ merchantLogService.save(new MerchantLog(store,"shipping","Product "
+ + p.getSku()
+ + " has a weight larger than the box maximum weight specified. Will use per item calculation."));
+
+ throw new ServiceException("Product configuration exceeds box configuraton");
+
+ }
+
+ double productVolume = (p.getProductWidth().doubleValue()
+ * p.getProductHeight().doubleValue() * p
+ .getProductLength().doubleValue());
+
+ if (productVolume == 0) {
+
+ merchantLogService.save(new MerchantLog(store,"shipping","Product "
+ + p.getSku()
+ + " has one of the dimension set to 0 and therefore cannot calculate the volume"));
+
+ throw new ServiceException("Product configuration exceeds box configuraton");
+
+
+ }
+
+ if (productVolume > maxVolume) {
+
+ throw new ServiceException("Product configuration exceeds box configuraton");
+
+ }
+
+ //List boxesList = boxesList;
+
+ // try each box
+ //Iterator boxIter = boxesList.iterator();
+ for (PackingBox pbox : boxesList) {
+ double volumeLeft = pbox.getVolumeLeft();
+ double weightLeft = pbox.getWeightLeft();
+
+ if ((volumeLeft * .75) >= productVolume
+ && pbox.getWeightLeft() >= productWeight) {// fit the item
+ // in this
+ // box
+ // fit in the current box
+ volumeLeft = volumeLeft - productVolume;
+ pbox.setVolumeLeft(volumeLeft);
+ weightLeft = weightLeft - productWeight;
+ pbox.setWeightLeft(weightLeft);
+
+ assignedProducts.add(p);
+ productCount--;
+
+ double w = pbox.getWeight();
+ w = w + productWeight;
+ pbox.setWeight(w);
+ productAssigned = true;
+ maxBox--;
+ break;
+
+ }
+
+ }
+
+ if (!productAssigned) {// create a new box
+
+ box = new PackingBox();
+ // set box max volume
+ box.setVolumeLeft(maxVolume);
+ box.setWeightLeft(maxweight);
+
+ boxesList.add(box);
+
+ double volumeLeft = box.getVolumeLeft() - productVolume;
+ box.setVolumeLeft(volumeLeft);
+ double weightLeft = box.getWeightLeft() - productWeight;
+ box.setWeightLeft(weightLeft);
+ assignedProducts.add(p);
+ productCount--;
+ double w = box.getWeight();
+ w = w + productWeight;
+ box.setWeight(w);
+ maxBox--;
+ }
+
+ }
+
+ // now prepare the shipping info
+
+ // number of boxes
+
+ //Iterator ubIt = usedBoxesList.iterator();
+
+ System.out.println("###################################");
+ System.out.println("Number of boxes " + boxesList.size());
+ System.out.println("###################################");
+
+ for(PackingBox pb : boxesList) {
+ PackageDetails details = new PackageDetails();
+ details.setShippingHeight(height);
+ details.setShippingLength(length);
+ details.setShippingWeight(weight + box.getWeight());
+ details.setShippingWidth(width);
+ details.setItemName(store.getCode());
+ boxes.add(details);
+ }
+
+ return boxes;
+
+ }
+
+ @Override
+ public List<PackageDetails> getItemPackagesDetails(
+ List<ShippingProduct> products, MerchantStore store)
+ throws ServiceException {
+
+
+ List<PackageDetails> packages = new ArrayList<PackageDetails>();
+ for(ShippingProduct shippingProduct : products) {
+ Product product = shippingProduct.getProduct();
+
+ if (product.isProductVirtual()) {
+ continue;
+ }
+
+ //BigDecimal weight = product.getProductWeight();
+ Set<ProductAttribute> attributes = product.getAttributes();
+ // set attributes values
+ BigDecimal w = product.getProductWeight();
+ BigDecimal h = product.getProductHeight();
+ BigDecimal l = product.getProductLength();
+ BigDecimal wd = product.getProductWidth();
+ if(w==null) {
+ w = new BigDecimal(defaultWeight);
+ }
+ if(h==null) {
+ h = new BigDecimal(defaultHeight);
+ }
+ if(l==null) {
+ l = new BigDecimal(defaultLength);
+ }
+ if(wd==null) {
+ wd = new BigDecimal(defaultWidth);
+ }
+ if (attributes != null && attributes.size() > 0) {
+ for(ProductAttribute attribute : attributes) {
+ if(attribute.getAttributeAdditionalWeight()!=null) {
+ w = w.add(attribute.getProductAttributeWeight());
+ }
+ }
+ }
+
+
+
+ if (shippingProduct.getQuantity() == 1) {
+ PackageDetails detail = new PackageDetails();
+
+
+ detail.setShippingHeight(h
+ .doubleValue());
+ detail.setShippingLength(l
+ .doubleValue());
+ detail.setShippingWeight(w.doubleValue());
+ detail.setShippingWidth(wd.doubleValue());
+ detail.setShippingQuantity(shippingProduct.getQuantity());
+ String description = "item";
+ if(product.getDescriptions().size()>0) {
+ description = product.getDescriptions().iterator().next().getName();
+ }
+ detail.setItemName(description);
+
+ packages.add(detail);
+ } else if (shippingProduct.getQuantity() > 1) {
+ for (int i = 0; i < shippingProduct.getQuantity(); i++) {
+ PackageDetails detail = new PackageDetails();
+ detail.setShippingHeight(h
+ .doubleValue());
+ detail.setShippingLength(l
+ .doubleValue());
+ detail.setShippingWeight(w.doubleValue());
+ detail.setShippingWidth(wd
+ .doubleValue());
+ detail.setShippingQuantity(shippingProduct.getQuantity());
+ String description = "item";
+ if(product.getDescriptions().size()>0) {
+ description = product.getDescriptions().iterator().next().getName();
+ }
+ detail.setItemName(description);
+
+ packages.add(detail);
+ }
+ }
+ }
+
+ return packages;
+
+
+
+ }
+
+
+}
+
+
+class PackingBox {
+
+ private double volumeLeft;
+ private double weightLeft;
+ private double weight;
+
+ public double getVolumeLeft() {
+ return volumeLeft;
+ }
+
+ public void setVolumeLeft(double volumeLeft) {
+ this.volumeLeft = volumeLeft;
+ }
+
+ public double getWeight() {
+ return weight;
+ }
+
+ public void setWeight(double weight) {
+ this.weight = weight;
+ }
+
+ public double getWeightLeft() {
+ return weightLeft;
+ }
+
+ public void setWeightLeft(double weightLeft) {
+ this.weightLeft = weightLeft;
+ }
+
+}
+
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/impl/UPSShippingQuote.java b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/impl/UPSShippingQuote.java
new file mode 100644
index 0000000..89cec30
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/impl/UPSShippingQuote.java
@@ -0,0 +1,681 @@
+package com.salesmanager.core.modules.integration.shipping.impl;
+
+import java.io.BufferedReader;
+import java.io.Reader;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.digester.Digester;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.methods.PostMethod;
+import org.apache.commons.httpclient.methods.RequestEntity;
+import org.apache.commons.httpclient.methods.StringRequestEntity;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.salesmanager.core.business.common.model.Delivery;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.shipping.model.PackageDetails;
+import com.salesmanager.core.business.shipping.model.ShippingConfiguration;
+import com.salesmanager.core.business.shipping.model.ShippingOption;
+import com.salesmanager.core.business.system.model.CustomIntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+import com.salesmanager.core.business.system.model.ModuleConfig;
+import com.salesmanager.core.modules.integration.IntegrationException;
+import com.salesmanager.core.modules.integration.shipping.model.ShippingQuoteModule;
+import com.salesmanager.core.utils.DataUtils;
+
+/**
+ * Integrates with UPS online API
+ * @author casams1
+ *
+ */
+public class UPSShippingQuote implements ShippingQuoteModule {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(UPSShippingQuote.class);
+
+
+ @Override
+ public void validateModuleConfiguration(
+ IntegrationConfiguration integrationConfiguration,
+ MerchantStore store) throws IntegrationException {
+
+
+ List<String> errorFields = null;
+
+ //validate integrationKeys['accessKey']
+ Map<String,String> keys = integrationConfiguration.getIntegrationKeys();
+ if(keys==null || StringUtils.isBlank(keys.get("accessKey"))) {
+ errorFields = new ArrayList<String>();
+ errorFields.add("accessKey");
+ }
+
+ if(keys==null || StringUtils.isBlank(keys.get("userId"))) {
+ errorFields = new ArrayList<String>();
+ errorFields.add("userId");
+ }
+
+ if(keys==null || StringUtils.isBlank(keys.get("password"))) {
+ errorFields = new ArrayList<String>();
+ errorFields.add("password");
+ }
+
+ //validate at least one integrationOptions['packages']
+ Map<String,List<String>> options = integrationConfiguration.getIntegrationOptions();
+ if(options==null) {
+ errorFields = new ArrayList<String>();
+ errorFields.add("packages");
+ }
+
+ List<String> packages = options.get("packages");
+ if(packages==null || packages.size()==0) {
+ if(errorFields==null) {
+ errorFields = new ArrayList<String>();
+ }
+ errorFields.add("packages");
+ }
+
+/* List<String> services = options.get("services");
+ if(services==null || services.size()==0) {
+ if(errorFields==null) {
+ errorFields = new ArrayList<String>();
+ }
+ errorFields.add("services");
+ }
+
+ if(services!=null && services.size()>3) {
+ if(errorFields==null) {
+ errorFields = new ArrayList<String>();
+ }
+ errorFields.add("services");
+ }*/
+
+ if(errorFields!=null) {
+ IntegrationException ex = new IntegrationException(IntegrationException.ERROR_VALIDATION_SAVE);
+ ex.setErrorFields(errorFields);
+ throw ex;
+
+ }
+
+
+
+ }
+
+ @Override
+ public List<ShippingOption> getShippingQuotes(
+ List<PackageDetails> packages, BigDecimal orderTotal,
+ Delivery delivery, MerchantStore store,
+ IntegrationConfiguration configuration, IntegrationModule module,
+ ShippingConfiguration shippingConfiguration, Locale locale)
+ throws IntegrationException {
+
+
+
+ BigDecimal total = orderTotal;
+
+ if (packages == null) {
+ return null;
+ }
+
+ List<ShippingOption> options = null;
+
+ // only applies to Canada and US
+ Country country = delivery.getCountry();
+
+
+
+ if(!(country.getIsoCode().equals("US") || country.getIsoCode().equals("CA"))) {
+ return null;
+ //throw new IntegrationException("UPS Not configured for shipping in country " + country.getIsoCode());
+ }
+
+ // supports en and fr
+ String language = locale.getLanguage();
+ if (!language.equals(Locale.FRENCH.getLanguage())
+ && !language.equals(Locale.ENGLISH.getLanguage())) {
+ language = Locale.ENGLISH.getLanguage();
+ }
+
+ String pack = configuration.getIntegrationOptions().get("packages").get(0);
+ Map<String,String> keys = configuration.getIntegrationKeys();
+
+ String accessKey = keys.get("accessKey");
+ String userId = keys.get("userId");
+ String password = keys.get("password");
+
+
+ String host = null;
+ String protocol = null;
+ String port = null;
+ String url = null;
+
+ StringBuilder xmlbuffer = new StringBuilder();
+ PostMethod httppost = null;
+ BufferedReader reader = null;
+
+ try {
+ String env = configuration.getEnvironment();
+
+ Set<String> regions = module.getRegionsSet();
+ if(!regions.contains(store.getCountry().getIsoCode())) {
+ throw new IntegrationException("Can't use the service for store country code ");
+ }
+
+ Map<String, ModuleConfig> moduleConfigsMap = module.getModuleConfigs();
+ for(String key : moduleConfigsMap.keySet()) {
+
+ ModuleConfig moduleConfig = (ModuleConfig)moduleConfigsMap.get(key);
+ if(moduleConfig.getEnv().equals(env)) {
+ host = moduleConfig.getHost();
+ protocol = moduleConfig.getScheme();
+ port = moduleConfig.getPort();
+ url = moduleConfig.getUri();
+ }
+ }
+
+
+ StringBuilder xmlreqbuffer = new StringBuilder();
+ xmlreqbuffer.append("<?xml version=\"1.0\"?>");
+ xmlreqbuffer.append("<AccessRequest>");
+ xmlreqbuffer.append("<AccessLicenseNumber>");
+ xmlreqbuffer.append(accessKey);
+ xmlreqbuffer.append("</AccessLicenseNumber>");
+ xmlreqbuffer.append("<UserId>");
+ xmlreqbuffer.append(userId);
+ xmlreqbuffer.append("</UserId>");
+ xmlreqbuffer.append("<Password>");
+ xmlreqbuffer.append(password);
+ xmlreqbuffer.append("</Password>");
+ xmlreqbuffer.append("</AccessRequest>");
+
+ String xmlhead = xmlreqbuffer.toString();
+
+
+ String weightCode = store.getWeightunitcode();
+ String measureCode = store.getSeizeunitcode();
+
+ if (weightCode.equals("KG")) {
+ weightCode = "KGS";
+ } else {
+ weightCode = "LBS";
+ }
+
+ String xml = "<?xml version=\"1.0\"?><RatingServiceSelectionRequest><Request><TransactionReference><CustomerContext>Shopizer</CustomerContext><XpciVersion>1.0001</XpciVersion></TransactionReference><RequestAction>Rate</RequestAction><RequestOption>Shop</RequestOption></Request>";
+ StringBuffer xmldatabuffer = new StringBuffer();
+
+ /**
+ * <Shipment>
+ *
+ * <Shipper> <Address> <City></City>
+ * <StateProvinceCode>QC</StateProvinceCode>
+ * <CountryCode>CA</CountryCode> <PostalCode></PostalCode>
+ * </Address> </Shipper>
+ *
+ * <ShipTo> <Address> <City>Redwood Shores</City>
+ * <StateProvinceCode>CA</StateProvinceCode>
+ * <CountryCode>US</CountryCode> <PostalCode></PostalCode>
+ * <ResidentialAddressIndicator/> </Address> </ShipTo>
+ *
+ * <Package> <PackagingType> <Code>21</Code> </PackagingType>
+ * <PackageWeight> <UnitOfMeasurement> <Code>LBS</Code>
+ * </UnitOfMeasurement> <Weight>1.1</Weight> </PackageWeight>
+ * <PackageServiceOptions> <InsuredValue>
+ * <CurrencyCode>CAD</CurrencyCode>
+ * <MonetaryValue>100</MonetaryValue> </InsuredValue>
+ * </PackageServiceOptions> </Package>
+ *
+ *
+ * </Shipment>
+ *
+ * <CustomerClassification> <Code>03</Code>
+ * </CustomerClassification> </RatingServiceSelectionRequest>
+ * **/
+
+ /**Map countriesMap = (Map) RefCache.getAllcountriesmap(LanguageUtil
+ .getLanguageNumberCode(locale.getLanguage()));
+ Map zonesMap = (Map) RefCache.getAllZonesmap(LanguageUtil
+ .getLanguageNumberCode(locale.getLanguage()));
+
+ Country storeCountry = (Country) countriesMap.get(store
+ .getCountry());
+
+ Country customerCountry = (Country) countriesMap.get(customer
+ .getCustomerCountryId());
+
+ int sZone = -1;
+ try {
+ sZone = Integer.parseInt(store.getZone());
+ } catch (Exception e) {
+ // TODO: handle exception
+ }
+
+ Zone storeZone = (Zone) zonesMap.get(sZone);
+ Zone customerZone = (Zone) zonesMap.get(customer
+ .getCustomerZoneId());**/
+
+
+
+ xmldatabuffer.append("<PickupType><Code>03</Code></PickupType>");
+ // xmldatabuffer.append("<Description>Daily Pickup</Description>");
+ xmldatabuffer.append("<Shipment><Shipper>");
+ xmldatabuffer.append("<Address>");
+ xmldatabuffer.append("<City>");
+ xmldatabuffer.append(store.getStorecity());
+ xmldatabuffer.append("</City>");
+ // if(!StringUtils.isBlank(store.getStorestateprovince())) {
+ if (store.getZone() != null) {
+ xmldatabuffer.append("<StateProvinceCode>");
+ xmldatabuffer.append(store.getZone().getCode());// zone code
+ xmldatabuffer.append("</StateProvinceCode>");
+ }
+ xmldatabuffer.append("<CountryCode>");
+ xmldatabuffer.append(store.getCountry().getIsoCode());
+ xmldatabuffer.append("</CountryCode>");
+ xmldatabuffer.append("<PostalCode>");
+ xmldatabuffer.append(DataUtils
+ .trimPostalCode(store.getStorepostalcode()));
+ xmldatabuffer.append("</PostalCode></Address></Shipper>");
+
+ // ship to
+ xmldatabuffer.append("<ShipTo>");
+ xmldatabuffer.append("<Address>");
+ xmldatabuffer.append("<City>");
+ xmldatabuffer.append(delivery.getCity());
+ xmldatabuffer.append("</City>");
+ // if(!StringUtils.isBlank(customer.getCustomerState())) {
+ if (delivery.getZone() != null) {
+ xmldatabuffer.append("<StateProvinceCode>");
+ xmldatabuffer.append(delivery.getZone().getCode());// zone code
+ xmldatabuffer.append("</StateProvinceCode>");
+ }
+ xmldatabuffer.append("<CountryCode>");
+ xmldatabuffer.append(delivery.getCountry().getIsoCode());
+ xmldatabuffer.append("</CountryCode>");
+ xmldatabuffer.append("<PostalCode>");
+ xmldatabuffer.append(DataUtils
+ .trimPostalCode(delivery.getPostalCode()));
+ xmldatabuffer.append("</PostalCode></Address></ShipTo>");
+ // xmldatabuffer.append("<Service><Code>11</Code></Service>");//TODO service codes (next day ...)
+
+
+ for(PackageDetails packageDetail : packages){
+
+ xmldatabuffer.append("<Package>");
+ xmldatabuffer.append("<PackagingType>");
+ xmldatabuffer.append("<Code>");
+ xmldatabuffer.append(pack);
+ xmldatabuffer.append("</Code>");
+ xmldatabuffer.append("</PackagingType>");
+
+ // weight
+ xmldatabuffer.append("<PackageWeight>");
+ xmldatabuffer.append("<UnitOfMeasurement>");
+ xmldatabuffer.append("<Code>");
+ xmldatabuffer.append(weightCode);
+ xmldatabuffer.append("</Code>");
+ xmldatabuffer.append("</UnitOfMeasurement>");
+ xmldatabuffer.append("<Weight>");
+ xmldatabuffer.append(new BigDecimal(packageDetail.getShippingWeight())
+ .setScale(1, BigDecimal.ROUND_HALF_UP));
+ xmldatabuffer.append("</Weight>");
+ xmldatabuffer.append("</PackageWeight>");
+
+ // dimension
+ xmldatabuffer.append("<Dimensions>");
+ xmldatabuffer.append("<UnitOfMeasurement>");
+ xmldatabuffer.append("<Code>");
+ xmldatabuffer.append(measureCode);
+ xmldatabuffer.append("</Code>");
+ xmldatabuffer.append("</UnitOfMeasurement>");
+ xmldatabuffer.append("<Length>");
+ xmldatabuffer.append(new BigDecimal(packageDetail.getShippingLength())
+ .setScale(2, BigDecimal.ROUND_HALF_UP));
+ xmldatabuffer.append("</Length>");
+ xmldatabuffer.append("<Width>");
+ xmldatabuffer.append(new BigDecimal(packageDetail.getShippingWidth())
+ .setScale(2, BigDecimal.ROUND_HALF_UP));
+ xmldatabuffer.append("</Width>");
+ xmldatabuffer.append("<Height>");
+ xmldatabuffer.append(new BigDecimal(packageDetail.getShippingHeight())
+ .setScale(2, BigDecimal.ROUND_HALF_UP));
+ xmldatabuffer.append("</Height>");
+ xmldatabuffer.append("</Dimensions>");
+ xmldatabuffer.append("</Package>");
+
+ }
+
+ xmldatabuffer.append("</Shipment>");
+ xmldatabuffer.append("</RatingServiceSelectionRequest>");
+
+ xmlbuffer.append(xmlhead).append(xml).append(
+ xmldatabuffer.toString());
+
+
+
+ LOGGER.debug("UPS QUOTE REQUEST " + xmlbuffer.toString());
+
+ String data = "";
+
+
+ HttpClient client = new HttpClient();
+ httppost = new PostMethod(protocol + "://" + host + ":" + port
+ + url);
+ RequestEntity entity = new StringRequestEntity(
+ xmlbuffer.toString(), "text/plain", "UTF-8");
+ httppost.setRequestEntity(entity);
+
+ int result = client.executeMethod(httppost);
+ if (result != 200) {
+ LOGGER.error("Communication Error with ups quote " + result + " "
+ + protocol + "://" + host + ":" + port + url);
+ throw new Exception("UPS quote communication error " + result);
+ }
+ data = httppost.getResponseBodyAsString();
+ LOGGER.debug("ups quote response " + data);
+
+ UPSParsedElements parsed = new UPSParsedElements();
+
+ Digester digester = new Digester();
+ digester.push(parsed);
+ digester.addCallMethod(
+ "RatingServiceSelectionResponse/Response/Error",
+ "setErrorCode", 0);
+ digester.addCallMethod(
+ "RatingServiceSelectionResponse/Response/ErrorDescriprion",
+ "setError", 0);
+ digester
+ .addCallMethod(
+ "RatingServiceSelectionResponse/Response/ResponseStatusCode",
+ "setStatusCode", 0);
+ digester
+ .addCallMethod(
+ "RatingServiceSelectionResponse/Response/ResponseStatusDescription",
+ "setStatusMessage", 0);
+ digester
+ .addCallMethod(
+ "RatingServiceSelectionResponse/Response/Error/ErrorDescription",
+ "setError", 0);
+
+ digester.addObjectCreate(
+ "RatingServiceSelectionResponse/RatedShipment",
+ ShippingOption.class);
+ // digester.addSetProperties(
+ // "RatingServiceSelectionResponse/RatedShipment", "sequence",
+ // "optionId" );
+ digester
+ .addCallMethod(
+ "RatingServiceSelectionResponse/RatedShipment/Service/Code",
+ "setOptionId", 0);
+ digester
+ .addCallMethod(
+ "RatingServiceSelectionResponse/RatedShipment/TotalCharges/MonetaryValue",
+ "setOptionPriceText", 0);
+ //digester
+ // .addCallMethod(
+ // "RatingServiceSelectionResponse/RatedShipment/TotalCharges/CurrencyCode",
+ // "setCurrency", 0);
+ digester
+ .addCallMethod(
+ "RatingServiceSelectionResponse/RatedShipment/Service/Code",
+ "setOptionCode", 0);
+ digester
+ .addCallMethod(
+ "RatingServiceSelectionResponse/RatedShipment/GuaranteedDaysToDelivery",
+ "setEstimatedNumberOfDays", 0);
+ digester.addSetNext("RatingServiceSelectionResponse/RatedShipment",
+ "addOption");
+
+ // <?xml
+ // version="1.0"?><AddressValidationResponse><Response><TransactionReference><CustomerContext>SalesManager
+ // Data</CustomerContext><XpciVersion>1.0</XpciVersion></TransactionReference><ResponseStatusCode>0</ResponseStatusCode><ResponseStatusDescription>Failure</ResponseStatusDescription><Error><ErrorSeverity>Hard</ErrorSeverity><ErrorCode>10002</ErrorCode><ErrorDescription>The
+ // XML document is well formed but the document is not
+ // valid</ErrorDescription><ErrorLocation><ErrorLocationElementName>AddressValidationRequest</ErrorLocationElementName></ErrorLocation></Error></Response></AddressValidationResponse>
+
+ Reader xmlreader = new StringReader(data);
+
+ digester.parse(xmlreader);
+
+ if (!StringUtils.isBlank(parsed.getErrorCode())) {
+
+
+ LOGGER.error("Can't process UPS statusCode="
+ + parsed.getErrorCode() + " message= "
+ + parsed.getError());
+ throw new IntegrationException(parsed.getError());
+ }
+ if (!StringUtils.isBlank(parsed.getStatusCode())
+ && !parsed.getStatusCode().equals("1")) {
+
+ throw new IntegrationException(parsed.getError());
+ }
+
+ if (parsed.getOptions() == null || parsed.getOptions().size() == 0) {
+
+ throw new IntegrationException("No shipping options available for the configuration");
+ }
+
+ /*String carrier = getShippingMethodDescription(locale);
+ // cost is in CAD, need to do conversion
+
+
+ boolean requiresCurrencyConversion = false; String storeCurrency
+ = store.getCurrency();
+ if(!storeCurrency.equals(Constants.CURRENCY_CODE_CAD)) {
+ requiresCurrencyConversion = true; }
+
+
+ LabelUtil labelUtil = LabelUtil.getInstance();
+ Map serviceMap = com.salesmanager.core.util.ShippingUtil
+ .buildServiceMap("upsxml", locale);
+
+ *//** Details on whit RT quote information to display **//*
+ MerchantConfiguration rtdetails = config
+ .getMerchantConfiguration(ShippingConstants.MODULE_SHIPPING_DISPLAY_REALTIME_QUOTES);
+ int displayQuoteDeliveryTime = ShippingConstants.NO_DISPLAY_RT_QUOTE_TIME;
+
+
+ if (rtdetails != null) {
+
+ if (!StringUtils.isBlank(rtdetails.getConfigurationValue1())) {// display
+ // or
+ // not
+ // quotes
+ try {
+ displayQuoteDeliveryTime = Integer.parseInt(rtdetails
+ .getConfigurationValue1());
+
+ } catch (Exception e) {
+ log.error("Display quote is not an integer value ["
+ + rtdetails.getConfigurationValue1() + "]");
+ }
+ }
+ }*/
+
+
+ List<ShippingOption> shippingOptions = parsed.getOptions();
+
+ if(shippingOptions!=null) {
+
+ Map<String,String> details = module.getDetails();
+
+ for(ShippingOption option : shippingOptions) {
+
+ String name = details.get(option.getOptionCode());
+ option.setOptionName(name);
+ if(option.getOptionPrice()==null) {
+ String priceText = option.getOptionPriceText();
+ if(StringUtils.isBlank(priceText)) {
+ throw new IntegrationException("Price text is null for option " + name);
+ }
+
+ try {
+ BigDecimal price = new BigDecimal(priceText);
+ option.setOptionPrice(price);
+ } catch(Exception e) {
+ throw new IntegrationException("Can't convert to numeric price " + priceText);
+ }
+
+ }
+
+
+ }
+
+
+ }
+
+/* if (options != null) {
+
+ Map selectedintlservices = (Map) config
+ .getConfiguration("service-global-upsxml");
+
+ Iterator i = options.iterator();
+ while (i.hasNext()) {
+ ShippingOption option = (ShippingOption) i.next();
+ // option.setCurrency(store.getCurrency());
+ StringBuffer description = new StringBuffer();
+
+ String code = option.getOptionCode();
+ option.setOptionCode(code);
+ // get description
+ String label = (String) serviceMap.get(code);
+ if (label == null) {
+ log
+ .warn("UPSXML cannot find description for service code "
+ + code);
+ }
+
+ option.setOptionName(label);
+
+ description.append(option.getOptionName());
+ if (displayQuoteDeliveryTime == ShippingConstants.DISPLAY_RT_QUOTE_TIME) {
+ if (!StringUtils.isBlank(option
+ .getEstimatedNumberOfDays())) {
+ description.append(" (").append(
+ option.getEstimatedNumberOfDays()).append(
+ " ").append(
+ labelUtil.getText(locale,
+ "label.generic.days.lowercase"))
+ .append(")");
+ }
+ }
+ option.setDescription(description.toString());
+
+ // get currency
+ if (!option.getCurrency().equals(store.getCurrency())) {
+ option.setOptionPrice(CurrencyUtil.convertToCurrency(
+ option.getOptionPrice(), option.getCurrency(),
+ store.getCurrency()));
+ }
+
+ if (!selectedintlservices.containsKey(option
+ .getOptionCode())) {
+ if (returnColl == null) {
+ returnColl = new ArrayList();
+ }
+ returnColl.add(option);
+ // options.remove(option);
+ }
+
+ }
+
+ if (options.size() == 0) {
+ LogMerchantUtil
+ .log(
+ store.getMerchantId(),
+ " none of the service code returned by UPS ["
+ + selectedintlservices
+ .keySet()
+ .toArray(
+ new String[selectedintlservices
+ .size()])
+ + "] for this shipping is in your selection list");
+ }
+ }*/
+
+
+
+ return shippingOptions;
+
+ } catch (Exception e1) {
+ LOGGER.error("UPS quote error",e1);
+ throw new IntegrationException(e1);
+ } finally {
+ if (reader != null) {
+ try {
+ reader.close();
+ } catch (Exception ignore) {
+ }
+ }
+
+ if (httppost != null) {
+ httppost.releaseConnection();
+ }
+ }
+}
+
+
+ @Override
+ public CustomIntegrationConfiguration getCustomModuleConfiguration(
+ MerchantStore store) throws IntegrationException {
+ //nothing to do
+ return null;
+ }}
+
+
+class UPSParsedElements {
+
+ private String statusCode;
+ private String statusMessage;
+ private String error = "";
+ private String errorCode = "";
+ private List<ShippingOption> options = new ArrayList<ShippingOption>();
+
+ public void addOption(ShippingOption option) {
+ options.add(option);
+ }
+
+ public List<ShippingOption> getOptions() {
+ return options;
+ }
+
+ public String getStatusCode() {
+ return statusCode;
+ }
+
+ public void setStatusCode(String statusCode) {
+ this.statusCode = statusCode;
+ }
+
+ public String getStatusMessage() {
+ return statusMessage;
+ }
+
+ public void setStatusMessage(String statusMessage) {
+ this.statusMessage = statusMessage;
+ }
+
+ public String getError() {
+ return error;
+ }
+
+ public void setError(String error) {
+ this.error = error;
+ }
+
+ public String getErrorCode() {
+ return errorCode;
+ }
+
+ public void setErrorCode(String errorCode) {
+ this.errorCode = errorCode;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/impl/USPSShippingQuote.java b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/impl/USPSShippingQuote.java
new file mode 100644
index 0000000..9cedbb4
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/impl/USPSShippingQuote.java
@@ -0,0 +1,721 @@
+package com.salesmanager.core.modules.integration.shipping.impl;
+
+import java.io.Reader;
+import java.io.StringReader;
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.commons.digester.Digester;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.salesmanager.core.business.common.model.Delivery;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.country.service.CountryService;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.shipping.model.PackageDetails;
+import com.salesmanager.core.business.shipping.model.ShippingConfiguration;
+import com.salesmanager.core.business.shipping.model.ShippingOption;
+import com.salesmanager.core.business.system.model.CustomIntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+import com.salesmanager.core.business.system.model.MerchantLog;
+import com.salesmanager.core.business.system.model.ModuleConfig;
+import com.salesmanager.core.business.system.service.MerchantLogService;
+import com.salesmanager.core.constants.Constants;
+import com.salesmanager.core.constants.MeasureUnit;
+import com.salesmanager.core.modules.integration.IntegrationException;
+import com.salesmanager.core.modules.integration.shipping.model.ShippingQuoteModule;
+import com.salesmanager.core.utils.DataUtils;
+import com.salesmanager.core.utils.ProductPriceUtils;
+
+/**
+ * Integrates with USPS online API
+ * @author casams1
+ *
+ */
+public class USPSShippingQuote implements ShippingQuoteModule {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(USPSShippingQuote.class);
+
+
+ @Autowired
+ private ProductPriceUtils productPriceUtils;
+
+ @Autowired
+ private CountryService countryService;
+
+
+ @Override
+ public void validateModuleConfiguration(
+ IntegrationConfiguration integrationConfiguration,
+ MerchantStore store) throws IntegrationException {
+
+
+ List<String> errorFields = null;
+
+ //validate integrationKeys['account']
+ Map<String,String> keys = integrationConfiguration.getIntegrationKeys();
+ if(keys==null || StringUtils.isBlank(keys.get("account"))) {
+ errorFields = new ArrayList<String>();
+ errorFields.add("identifier");
+ }
+
+ //validate at least one integrationOptions['packages']
+ Map<String,List<String>> options = integrationConfiguration.getIntegrationOptions();
+ if(options==null) {
+ errorFields = new ArrayList<String>();
+ errorFields.add("identifier");
+ }
+
+ List<String> packages = options.get("packages");
+ if(packages==null || packages.size()==0) {
+ if(errorFields==null) {
+ errorFields = new ArrayList<String>();
+ }
+ errorFields.add("packages");
+ }
+
+/* List<String> services = options.get("services");
+ if(services==null || services.size()==0) {
+ if(errorFields==null) {
+ errorFields = new ArrayList<String>();
+ }
+ errorFields.add("services");
+ }
+
+ if(services!=null && services.size()>3) {
+ if(errorFields==null) {
+ errorFields = new ArrayList<String>();
+ }
+ errorFields.add("services");
+ }*/
+
+ if(errorFields!=null) {
+ IntegrationException ex = new IntegrationException(IntegrationException.ERROR_VALIDATION_SAVE);
+ ex.setErrorFields(errorFields);
+ throw ex;
+
+ }
+
+
+
+ }
+
+ @Override
+ public List<ShippingOption> getShippingQuotes(
+ List<PackageDetails> packages, BigDecimal orderTotal,
+ Delivery delivery, MerchantStore store,
+ IntegrationConfiguration configuration, IntegrationModule module,
+ ShippingConfiguration shippingConfiguration, Locale locale)
+ throws IntegrationException {
+
+
+
+ if (packages == null) {
+ return null;
+ }
+
+
+
+ // only applies to Canada and US
+/* Country country = delivery.getCountry();
+ if(!country.getIsoCode().equals("US") || !country.getIsoCode().equals("US")){
+ throw new IntegrationException("USPS Not configured for shipping in country " + country.getIsoCode());
+ }*/
+
+
+
+ // supports en and fr
+ String language = locale.getLanguage();
+ if (!language.equals(Locale.FRENCH.getLanguage())
+ && !language.equals(Locale.ENGLISH.getLanguage())) {
+ language = Locale.ENGLISH.getLanguage();
+ }
+
+
+ // if store is not CAD /** maintained in the currency **/
+/* if (!store.getCurrency().equals(Constants.CURRENCY_CODE_CAD)) {
+ total = CurrencyUtil.convertToCurrency(total, store.getCurrency(),
+ Constants.CURRENCY_CODE_CAD);
+ }*/
+
+ Language lang = store.getDefaultLanguage();
+
+
+
+ GetMethod httpget = null;
+ Reader xmlreader = null;
+ String pack = configuration.getIntegrationOptions().get("packages").get(0);
+
+ try {
+
+ Map<String,Country> countries = countryService.getCountriesMap(lang);
+
+ Country destination = countries.get(delivery.getCountry().getIsoCode());
+
+
+
+ Map<String,String> keys = configuration.getIntegrationKeys();
+ if(keys==null || StringUtils.isBlank(keys.get("account"))) {
+ return null;//TODO can we return null
+ }
+
+
+ String host = null;
+ String protocol = null;
+ String port = null;
+ String url = null;
+
+
+
+ //against which environment are we using the service
+ String env = configuration.getEnvironment();
+
+ //must be US
+ if(!store.getCountry().getIsoCode().equals("US")) {
+ throw new IntegrationException("Can't use the service for store country code ");
+ }
+
+ Map<String, ModuleConfig> moduleConfigsMap = module.getModuleConfigs();
+ for(String key : moduleConfigsMap.keySet()) {
+
+ ModuleConfig moduleConfig = (ModuleConfig)moduleConfigsMap.get(key);
+ if(moduleConfig.getEnv().equals(env)) {
+ host = moduleConfig.getHost();
+ protocol = moduleConfig.getScheme();
+ port = moduleConfig.getPort();
+ url = moduleConfig.getUri();
+ }
+ }
+
+
+ StringBuilder xmlheader = new StringBuilder();
+ if(store.getCountry().getIsoCode().equals(delivery.getCountry().getIsoCode())) {
+ xmlheader.append("<RateV3Request USERID=\"").append(keys.get("account")).append("\">");
+ } else {
+ xmlheader.append("<IntlRateRequest USERID=\"").append(keys.get("account")).append("\">");
+ }
+
+
+
+ StringBuilder xmldatabuffer = new StringBuilder();
+
+
+ double totalW = 0;
+ double totalH = 0;
+ double totalL = 0;
+ double totalG = 0;
+ double totalP = 0;
+
+ for (PackageDetails detail : packages) {
+
+
+ // need size in inch
+ double w = DataUtils.getMeasure(detail.getShippingWidth(),
+ store, MeasureUnit.IN.name());
+ double h = DataUtils.getMeasure(detail.getShippingHeight(),
+ store, MeasureUnit.IN.name());
+ double l = DataUtils.getMeasure(detail.getShippingLength(),
+ store, MeasureUnit.IN.name());
+
+ totalW = totalW + w;
+ totalH = totalH + h;
+ totalL = totalL + l;
+
+ // Girth = Length + (Width x 2) + (Height x 2)
+ double girth = l + (w * 2) + (h * 2);
+
+ totalG = totalG + girth;
+
+ // need weight in pounds
+ double p = DataUtils.getWeight(detail.getShippingWeight(), store, MeasureUnit.LB.name());
+
+ totalP = totalP + p;
+
+ }
+
+/* BigDecimal convertedOrderTotal = CurrencyUtil.convertToCurrency(
+ orderTotal, store.getCurrency(),
+ Constants.CURRENCY_CODE_USD);*/
+
+ // calculate total shipping volume
+
+ // ship date is 3 days from here
+
+ Calendar c = Calendar.getInstance();
+ c.setTime(new Date());
+ c.add(Calendar.DATE, 3);
+ Date newDate = c.getTime();
+
+ SimpleDateFormat format = new SimpleDateFormat(Constants.DEFAULT_DATE_FORMAT);
+ String shipDate = format.format(newDate);
+
+
+
+ int i = 1;
+
+ // need pounds and ounces
+ int pounds = (int) totalP;
+ String ouncesString = String.valueOf(totalP - pounds);
+ int ouncesIndex = ouncesString.indexOf(".");
+ String ounces = "00";
+ if (ouncesIndex > -1) {
+ ounces = ouncesString.substring(ouncesIndex + 1);
+ }
+
+ String size = "REGULAR";
+
+ if (totalL + totalG <= 64) {
+ size = "REGULAR";
+ } else if (totalL + totalG <= 108) {
+ size = "LARGE";
+ } else {
+ size = "OVERSIZE";
+ }
+
+ /**
+ * Domestic <Package ID="1ST"> <Service>ALL</Service>
+ * <ZipOrigination>90210</ZipOrigination>
+ * <ZipDestination>96698</ZipDestination> <Pounds>8</Pounds>
+ * <Ounces>32</Ounces> <Container/> <Size>REGULAR</Size>
+ * <Machinable>true</Machinable> </Package>
+ *
+ * //MAXWEIGHT=70 lbs
+ *
+ *
+ * //domestic container default=VARIABLE whiteSpace=collapse
+ * enumeration=VARIABLE enumeration=FLAT RATE BOX enumeration=FLAT
+ * RATE ENVELOPE enumeration=LG FLAT RATE BOX
+ * enumeration=RECTANGULAR enumeration=NONRECTANGULAR
+ *
+ * //INTL enumeration=Package enumeration=Postcards or aerogrammes
+ * enumeration=Matter for the blind enumeration=Envelope
+ *
+ * Size May be left blank in situations that do not Size. Defined as
+ * follows: REGULAR: package plus girth is 84 inches or less; LARGE:
+ * package length plus girth measure more than 84 inches not more
+ * than 108 inches; OVERSIZE: package length plus girth is more than
+ * 108 but not 130 inches. For example: <Size>REGULAR</Size>
+ *
+ * International <Package ID="1ST"> <Machinable>true</Machinable>
+ * <MailType>Envelope</MailType> <Country>Canada</Country>
+ * <Length>0</Length> <Width>0</Width> <Height>0</Height>
+ * <ValueOfContents>250</ValueOfContents> </Package>
+ *
+ * <Package ID="2ND"> <Pounds>4</Pounds> <Ounces>3</Ounces>
+ * <MailType>Package</MailType> <GXG> <Length>46</Length>
+ * <Width>14</Width> <Height>15</Height> <POBoxFlag>N</POBoxFlag>
+ * <GiftFlag>N</GiftFlag> </GXG>
+ * <ValueOfContents>250</ValueOfContents> <Country>Japan</Country>
+ * </Package>
+ */
+
+ xmldatabuffer.append("<Package ID=\"").append(i).append("\">");
+
+
+ if(store.getCountry().getIsoCode().equals(delivery.getCountry().getIsoCode())) {
+
+ xmldatabuffer.append("<Service>");
+ xmldatabuffer.append("ALL");
+ xmldatabuffer.append("</Service>");
+ xmldatabuffer.append("<ZipOrigination>");
+ xmldatabuffer.append(DataUtils
+ .trimPostalCode(store.getStorepostalcode()));
+ xmldatabuffer.append("</ZipOrigination>");
+ xmldatabuffer.append("<ZipDestination>");
+ xmldatabuffer.append(DataUtils
+ .trimPostalCode(delivery.getPostalCode()));
+ xmldatabuffer.append("</ZipDestination>");
+ xmldatabuffer.append("<Pounds>");
+ xmldatabuffer.append(pounds);
+ xmldatabuffer.append("</Pounds>");
+ xmldatabuffer.append("<Ounces>");
+ xmldatabuffer.append(ounces);
+ xmldatabuffer.append("</Ounces>");
+ xmldatabuffer.append("<Container>");
+ xmldatabuffer.append(pack);
+ xmldatabuffer.append("</Container>");
+ xmldatabuffer.append("<Size>");
+ xmldatabuffer.append(size);
+ xmldatabuffer.append("</Size>");
+ xmldatabuffer.append("<Machinable>true</Machinable>");//TODO must be changed if not machinable
+ xmldatabuffer.append("<ShipDate>");
+ xmldatabuffer.append(shipDate);
+ xmldatabuffer.append("</ShipDate>");
+ } else {
+ // if international
+ xmldatabuffer.append("<Pounds>");
+ xmldatabuffer.append(pounds);
+ xmldatabuffer.append("</Pounds>");
+ xmldatabuffer.append("<Ounces>");
+ xmldatabuffer.append(ounces);
+ xmldatabuffer.append("</Ounces>");
+ xmldatabuffer.append("<MailType>");
+ xmldatabuffer.append(pack);
+ xmldatabuffer.append("</MailType>");
+ xmldatabuffer.append("<ValueOfContents>");
+ xmldatabuffer.append(productPriceUtils.getAdminFormatedAmount(store, orderTotal));
+ xmldatabuffer.append("</ValueOfContents>");
+ xmldatabuffer.append("<Country>");
+ xmldatabuffer.append(destination.getName());
+ xmldatabuffer.append("</Country>");
+ }
+
+ // if international & CXG
+ /*
+ * xmldatabuffer.append("<CXG>"); xmldatabuffer.append("<Length>");
+ * xmldatabuffer.append(""); xmldatabuffer.append("</Length>");
+ * xmldatabuffer.append("<Width>"); xmldatabuffer.append("");
+ * xmldatabuffer.append("</Width>");
+ * xmldatabuffer.append("<Height>"); xmldatabuffer.append("");
+ * xmldatabuffer.append("</Height>");
+ * xmldatabuffer.append("<POBoxFlag>"); xmldatabuffer.append("");
+ * xmldatabuffer.append("</POBoxFlag>");
+ * xmldatabuffer.append("<GiftFlag>"); xmldatabuffer.append("");
+ * xmldatabuffer.append("</GiftFlag>");
+ * xmldatabuffer.append("</CXG>");
+ */
+
+ /*
+ * xmldatabuffer.append("<Width>"); xmldatabuffer.append(totalW);
+ * xmldatabuffer.append("</Width>");
+ * xmldatabuffer.append("<Length>"); xmldatabuffer.append(totalL);
+ * xmldatabuffer.append("</Length>");
+ * xmldatabuffer.append("<Height>"); xmldatabuffer.append(totalH);
+ * xmldatabuffer.append("</Height>");
+ * xmldatabuffer.append("<Girth>"); xmldatabuffer.append(totalG);
+ * xmldatabuffer.append("</Girth>");
+ */
+
+ xmldatabuffer.append("</Package>");
+
+ String xmlfooter = "</RateV3Request>";
+ if(!store.getCountry().getIsoCode().equals(delivery.getCountry().getIsoCode())) {
+ xmlfooter = "</IntlRateRequest>";
+ }
+
+ StringBuilder xmlbuffer = new StringBuilder().append(xmlheader.toString()).append(
+ xmldatabuffer.toString()).append(xmlfooter.toString());
+
+ LOGGER.debug("USPS QUOTE REQUEST " + xmlbuffer.toString());
+
+ String data = "";
+
+
+ HttpClient client = new HttpClient();
+
+ @SuppressWarnings("deprecation")
+ String encoded = java.net.URLEncoder.encode(xmlbuffer.toString());
+
+ String completeUri = url + "?API=RateV3&XML=" + encoded;
+ if(!store.getCountry().getIsoCode().equals(delivery.getCountry().getIsoCode())) {
+ completeUri = url + "?API=IntlRate&XML=" + encoded;
+ }
+
+ // ?API=RateV3
+
+ httpget = new GetMethod(protocol + "://" + host + ":" + port
+ + completeUri);
+ // RequestEntity entity = new
+ // StringRequestEntity(xmlbuffer.toString(),"text/plain","UTF-8");
+ // httpget.setRequestEntity(entity);
+
+ int result = client.executeMethod(httpget);
+ if (result != 200) {
+ LOGGER.error("Communication Error with usps quote " + result + " "
+ + protocol + "://" + host + ":" + port + url);
+ throw new Exception("USPS quote communication error " + result);
+ }
+ data = httpget.getResponseBodyAsString();
+ LOGGER.debug("usps quote response " + data);
+
+ USPSParsedElements parsed = new USPSParsedElements();
+
+ /**
+ * <RateV3Response> <Package ID="1ST">
+ * <ZipOrigination>44106</ZipOrigination>
+ * <ZipDestination>20770</ZipDestination>
+ */
+
+ Digester digester = new Digester();
+ digester.push(parsed);
+
+ if(store.getCountry().getIsoCode().equals(delivery.getCountry().getIsoCode())) {
+
+ digester.addCallMethod("Error/Description",
+ "setError", 0);
+ digester.addCallMethod("RateV3Response/Package/Error/Description",
+ "setError", 0);
+ digester
+ .addObjectCreate(
+ "RateV3Response/Package/Postage",
+ ShippingOption.class);
+ digester.addSetProperties("RateV3Response/Package/Postage",
+ "CLASSID", "optionId");
+ digester.addCallMethod(
+ "RateV3Response/Package/Postage/MailService",
+ "setOptionName", 0);
+ digester.addCallMethod(
+ "RateV3Response/Package/Postage/MailService",
+ "setOptionCode", 0);
+ digester.addCallMethod("RateV3Response/Package/Postage/Rate",
+ "setOptionPriceText", 0);
+ //digester
+ // .addCallMethod(
+ // "RateV3Response/Package/Postage/Commitment/CommitmentDate",
+ // "estimatedNumberOfDays", 0);
+ digester.addSetNext("RateV3Response/Package/Postage",
+ "addOption");
+
+ } else {
+
+ digester.addCallMethod("Error/Description",
+ "setError", 0);
+ digester.addCallMethod("IntlRateResponse/Package/Error/Description",
+ "setError", 0);
+ digester
+ .addObjectCreate(
+ "IntlRateResponse/Package/Service",
+ ShippingOption.class);
+ digester.addSetProperties("IntlRateResponse/Package/Service",
+ "ID", "optionId");
+ digester.addCallMethod(
+ "IntlRateResponse/Package/Service/SvcDescription",
+ "setOptionName", 0);
+ digester.addCallMethod(
+ "IntlRateResponse/Package/Service/SvcDescription",
+ "setOptionCode", 0);
+ digester.addCallMethod(
+ "IntlRateResponse/Package/Service/Postage",
+ "setOptionPriceText", 0);
+ //digester.addCallMethod(
+ // "IntlRateResponse/Package/Service/SvcCommitments",
+ // "setEstimatedNumberOfDays", 0);
+ digester.addSetNext("IntlRateResponse/Package/Service",
+ "addOption");
+
+ }
+
+ // <?xml
+ // version="1.0"?><AddressValidationResponse><Response><TransactionReference><CustomerContext>SalesManager
+ // Data</CustomerContext><XpciVersion>1.0</XpciVersion></TransactionReference><ResponseStatusCode>0</ResponseStatusCode><ResponseStatusDescription>Failure</ResponseStatusDescription><Error><ErrorSeverity>Hard</ErrorSeverity><ErrorCode>10002</ErrorCode><ErrorDescription>The
+ // XML document is well formed but the document is not
+ // valid</ErrorDescription><ErrorLocation><ErrorLocationElementName>AddressValidationRequest</ErrorLocationElementName></ErrorLocation></Error></Response></AddressValidationResponse>
+
+
+ //<?xml version="1.0"?>
+ //<IntlRateResponse><Package ID="1"><Error><Number>-2147218046</Number>
+ //<Source>IntlPostage;clsIntlPostage.GetCountryAndRestirctedServiceId;clsIntlPostage.CalcAllPostageDimensionsXML;IntlRate.ProcessRequest</Source>
+ //<Description>Invalid Country Name</Description><HelpFile></HelpFile><HelpContext>1000440</HelpContext></Error></Package></IntlRateResponse>
+
+
+ xmlreader = new StringReader(data);
+ digester.parse(xmlreader);
+
+ if (!StringUtils.isBlank(parsed.getError())) {
+ LOGGER.error("Can't process USPS message= "
+ + parsed.getError());
+ throw new IntegrationException(parsed.getError());
+ }
+ if (!StringUtils.isBlank(parsed.getStatusCode())
+ && !parsed.getStatusCode().equals("1")) {
+ LOGGER.error("Can't process USPS statusCode="
+ + parsed.getStatusCode() + " message= "
+ + parsed.getError());
+ throw new IntegrationException(parsed.getError());
+ }
+
+ if (parsed.getOptions() == null || parsed.getOptions().size() == 0) {
+ LOGGER.warn("No options returned from USPS");
+ throw new IntegrationException(parsed.getError());
+ }
+
+
+
+/* String carrier = getShippingMethodDescription(locale);
+ // cost is in USD, need to do conversion
+
+ MerchantConfiguration rtdetails = config
+ .getMerchantConfiguration(ShippingConstants.MODULE_SHIPPING_DISPLAY_REALTIME_QUOTES);
+ int displayQuoteDeliveryTime = ShippingConstants.NO_DISPLAY_RT_QUOTE_TIME;
+ if (rtdetails != null) {
+
+ if (!StringUtils.isBlank(rtdetails.getConfigurationValue1())) {// display
+ // or
+ // not
+ // quotes
+ try {
+ displayQuoteDeliveryTime = Integer.parseInt(rtdetails
+ .getConfigurationValue1());
+
+ } catch (Exception e) {
+ log.error("Display quote is not an integer value ["
+ + rtdetails.getConfigurationValue1() + "]");
+ }
+ }
+ }
+
+ LabelUtil labelUtil = LabelUtil.getInstance();*/
+ // Map serviceMap =
+ // com.salesmanager.core.util.ShippingUtil.buildServiceMap("usps",locale);
+
+ @SuppressWarnings("unchecked")
+ List<ShippingOption> shippingOptions = parsed.getOptions();
+
+/* List<ShippingOption> returnOptions = null;
+
+ if (shippingOptions != null && shippingOptions.size() > 0) {
+
+ returnOptions = new ArrayList<ShippingOption>();
+ // Map selectedintlservices =
+ // (Map)config.getConfiguration("service-global-usps");
+ // need to create a Map of LABEL - LABLEL
+ // Iterator servicesIterator =
+ // selectedintlservices.keySet().iterator();
+ // Map services = new HashMap();
+
+ // ResourceBundle bundle = ResourceBundle.getBundle("usps",
+ // locale);
+
+ // while(servicesIterator.hasNext()) {
+ // String key = (String)servicesIterator.next();
+ // String value =
+ // bundle.getString("shipping.quote.services.label." + key);
+ // services.put(value, key);
+ // }
+
+ for(ShippingOption option : shippingOptions) {
+
+ StringBuilder description = new StringBuilder();
+ description.append(option.getOptionName());
+ //if (displayQuoteDeliveryTime == ShippingConstants.DISPLAY_RT_QUOTE_TIME) {
+ if (shippingConfiguration.getShippingDescription()==ShippingDescription.LONG_DESCRIPTION) {
+ if (option.getEstimatedNumberOfDays()>0) {
+ description.append(" (").append(
+ option.getEstimatedNumberOfDays()).append(
+ " ").append(
+ " d")
+ .append(")");
+ }
+ }
+ option.setDescription(description.toString());
+
+ // get currency
+ if (!option.getCurrency().equals(store.getCurrency())) {
+ option.setOptionPrice(CurrencyUtil.convertToCurrency(
+ option.getOptionPrice(), option.getCurrency(),
+ store.getCurrency()));
+ }
+
+ // if(!services.containsKey(option.getOptionCode())) {
+ // if(returnColl==null) {
+ // returnColl = new ArrayList();
+ // }
+ // returnColl.add(option);
+ // }
+ returnOptions.add(option);
+ }
+
+ // if(options.size()==0) {
+ // CommonService.logServiceMessage(store.getMerchantId(),
+ // " none of the service code returned by UPS [" +
+ // selectedintlservices.keySet().toArray(new
+ // String[selectedintlservices.size()]) +
+ // "] for this shipping is in your selection list");
+ // }
+
+ }*/
+
+ return shippingOptions;
+
+ } catch (Exception e1) {
+ LOGGER.error("Error in USPS shipping quote ",e1);
+ throw new IntegrationException(e1);
+ } finally {
+ if (xmlreader != null) {
+ try {
+ xmlreader.close();
+ } catch (Exception ignore) {
+ }
+ }
+ if (httpget != null) {
+ httpget.releaseConnection();
+ }
+ }
+
+
+ }
+
+
+
+ @Override
+ public CustomIntegrationConfiguration getCustomModuleConfiguration(
+ MerchantStore store) throws IntegrationException {
+ //nothing to do
+ return null;
+ }
+
+}
+
+
+class USPSParsedElements {
+
+ private String statusCode;
+ private String statusMessage;
+ private String error = "";
+ private String errorCode = "";
+ private List<ShippingOption> options = new ArrayList<ShippingOption>();
+
+ public void addOption(ShippingOption option) {
+ options.add(option);
+ }
+
+ public List getOptions() {
+ return options;
+ }
+
+ public String getStatusCode() {
+ return statusCode;
+ }
+
+ public void setStatusCode(String statusCode) {
+ this.statusCode = statusCode;
+ }
+
+ public String getStatusMessage() {
+ return statusMessage;
+ }
+
+ public void setStatusMessage(String statusMessage) {
+ this.statusMessage = statusMessage;
+ }
+
+ public String getError() {
+ return error;
+ }
+
+ public void setError(String error) {
+ this.error = error;
+ }
+
+ public String getErrorCode() {
+ return errorCode;
+ }
+
+ public void setErrorCode(String errorCode) {
+ this.errorCode = errorCode;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/CustomShippingQuoteItem.java b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/CustomShippingQuoteItem.java
new file mode 100644
index 0000000..4881db7
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/CustomShippingQuoteItem.java
@@ -0,0 +1,22 @@
+package com.salesmanager.core.modules.integration.shipping.model;
+
+import java.math.BigDecimal;
+
+public abstract class CustomShippingQuoteItem {
+
+ private String priceText;
+ private BigDecimal price;
+ public void setPriceText(String priceText) {
+ this.priceText = priceText;
+ }
+ public String getPriceText() {
+ return priceText;
+ }
+ public void setPrice(BigDecimal price) {
+ this.price = price;
+ }
+ public BigDecimal getPrice() {
+ return price;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/CustomShippingQuotesConfiguration.java b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/CustomShippingQuotesConfiguration.java
new file mode 100644
index 0000000..93be6df
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/CustomShippingQuotesConfiguration.java
@@ -0,0 +1,87 @@
+package com.salesmanager.core.modules.integration.shipping.model;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.json.simple.JSONObject;
+
+import com.salesmanager.core.business.system.model.CustomIntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationConfiguration;
+
+public class CustomShippingQuotesConfiguration extends IntegrationConfiguration implements CustomIntegrationConfiguration, Serializable {
+
+ /**
+ *
+ */
+ private String moduleCode;
+
+ private List<CustomShippingQuotesRegion> regions = new ArrayList<CustomShippingQuotesRegion>();
+
+
+ private static final long serialVersionUID = 1L;
+
+
+ @SuppressWarnings("unchecked")
+ public String toJSONString() {
+ //JSONObject data = new JSONObject();
+
+ //data.put("active", super.isActive());
+ //data.put("moduleCode", this.getModuleCode());
+
+
+ StringBuilder returnString = new StringBuilder();
+ returnString.append("{");
+ returnString.append("\"moduleCode\"").append(":\"").append(this.getModuleCode()).append("\"");
+ returnString.append(",");
+ returnString.append("\"active\"").append(":").append(this.isActive());
+
+
+
+ if(regions!=null && regions.size()>0) {
+
+ returnString.append(",");
+ //org.json.simple.JSONArray array=new org.json.simple.JSONArray();
+ StringBuilder regionsList = new StringBuilder();
+ int countRegion = 0;
+ regionsList.append("[");
+ for(CustomShippingQuotesRegion region : regions) {
+ regionsList.append(region.toJSONString());
+ countRegion ++;
+ if(countRegion<regions.size()) {
+ regionsList.append(",");
+ }
+ }
+ regionsList.append("]");
+ returnString.append("\"regions\"").append(":").append(regionsList.toString());
+ }
+
+ //return data.toJSONString();
+ returnString.append("}");
+ return returnString.toString();
+
+
+
+
+ }
+
+ @Override
+ public String getModuleCode() {
+ return moduleCode;
+ }
+
+ @Override
+ public void setModuleCode(String moduleCode) {
+ this.moduleCode = moduleCode;
+
+ }
+
+ public void setRegions(List<CustomShippingQuotesRegion> regions) {
+ this.regions = regions;
+ }
+
+ public List<CustomShippingQuotesRegion> getRegions() {
+ return regions;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/CustomShippingQuotesRegion.java b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/CustomShippingQuotesRegion.java
new file mode 100644
index 0000000..c37f279
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/CustomShippingQuotesRegion.java
@@ -0,0 +1,88 @@
+package com.salesmanager.core.modules.integration.shipping.model;
+
+import java.util.List;
+
+import org.json.simple.JSONAware;
+
+public class CustomShippingQuotesRegion implements JSONAware {
+
+ private String customRegionName;//a name given by the merchant for this custom region
+ private List<String> countries;//a list of country code for this region
+
+ private List<CustomShippingQuoteWeightItem> quoteItems;//price max weight
+
+ public void setQuoteItems(List<CustomShippingQuoteWeightItem> quoteItems) {
+ this.quoteItems = quoteItems;
+ }
+
+ public List<CustomShippingQuoteWeightItem> getQuoteItems() {
+ return quoteItems;
+ }
+
+ public void setCountries(List<String> countries) {
+ this.countries = countries;
+ }
+
+ public List<String> getCountries() {
+ return countries;
+ }
+
+ public void setCustomRegionName(String customRegionName) {
+ this.customRegionName = customRegionName;
+ }
+
+ public String getCustomRegionName() {
+ return customRegionName;
+ }
+
+
+ public String toJSONString() {
+
+
+ StringBuilder returnString = new StringBuilder();
+ returnString.append("{");
+ returnString.append("\"customRegionName\"").append(":\"").append(this.getCustomRegionName()).append("\"");
+
+
+
+ if(countries!=null) {
+ returnString.append(",");
+ StringBuilder coutriesList = new StringBuilder();
+ int countCountry = 0;
+ coutriesList.append("[");
+ for(String country : countries) {
+ coutriesList.append("\"").append(country).append("\"");
+ countCountry ++;
+ if(countCountry<countries.size()) {
+ coutriesList.append(",");
+ }
+ }
+
+ coutriesList.append("]");
+ returnString.append("\"countries\"").append(":").append(coutriesList.toString());
+ }
+
+ if(quoteItems!=null) {
+ returnString.append(",");
+ StringBuilder quotesList = new StringBuilder();
+ int countQuotes = 0;
+ quotesList.append("[");
+ for(CustomShippingQuoteWeightItem quote : quoteItems) {
+ quotesList.append(quote.toJSONString());
+ countQuotes ++;
+ if(countQuotes<quoteItems.size()) {
+ quotesList.append(",");
+ }
+ }
+ quotesList.append("]");
+
+ returnString.append("\"quoteItems\"").append(":").append(quotesList.toString());
+ }
+ returnString.append("}");
+ return returnString.toString();
+
+
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/CustomShippingQuoteWeightItem.java b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/CustomShippingQuoteWeightItem.java
new file mode 100644
index 0000000..ee5b087
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/CustomShippingQuoteWeightItem.java
@@ -0,0 +1,40 @@
+package com.salesmanager.core.modules.integration.shipping.model;
+
+import org.json.simple.JSONAware;
+import org.json.simple.JSONObject;
+
+public class CustomShippingQuoteWeightItem extends CustomShippingQuoteItem implements JSONAware {
+
+ private int maximumWeight;
+
+ private String priceText;
+
+ public String getPriceText() {
+ return priceText;
+ }
+
+ public void setPriceText(String priceText) {
+ this.priceText = priceText;
+ }
+
+ public void setMaximumWeight(int maximumWeight) {
+ this.maximumWeight = maximumWeight;
+ }
+
+ public int getMaximumWeight() {
+ return maximumWeight;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public String toJSONString() {
+ JSONObject data = new JSONObject();
+ data.put("price", super.getPrice());
+ data.put("maximumWeight", this.getMaximumWeight());
+
+ return data.toJSONString();
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/Packaging.java b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/Packaging.java
new file mode 100644
index 0000000..fe54e27
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/Packaging.java
@@ -0,0 +1,18 @@
+package com.salesmanager.core.modules.integration.shipping.model;
+
+import java.util.List;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.shipping.model.PackageDetails;
+import com.salesmanager.core.business.shipping.model.ShippingProduct;
+
+public interface Packaging {
+
+ public List<PackageDetails> getBoxPackagesDetails(
+ List<ShippingProduct> products, MerchantStore store) throws ServiceException;
+
+ public List<PackageDetails> getItemPackagesDetails(
+ List<ShippingProduct> products, MerchantStore store) throws ServiceException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/ShippingQuoteModule.java b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/ShippingQuoteModule.java
new file mode 100644
index 0000000..691a722
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/integration/shipping/model/ShippingQuoteModule.java
@@ -0,0 +1,24 @@
+package com.salesmanager.core.modules.integration.shipping.model;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Locale;
+
+import com.salesmanager.core.business.common.model.Delivery;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.shipping.model.PackageDetails;
+import com.salesmanager.core.business.shipping.model.ShippingConfiguration;
+import com.salesmanager.core.business.shipping.model.ShippingOption;
+import com.salesmanager.core.business.system.model.CustomIntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+import com.salesmanager.core.modules.integration.IntegrationException;
+
+public interface ShippingQuoteModule {
+
+ public void validateModuleConfiguration(IntegrationConfiguration integrationConfiguration, MerchantStore store) throws IntegrationException;
+ public CustomIntegrationConfiguration getCustomModuleConfiguration(MerchantStore store) throws IntegrationException;
+
+ public List<ShippingOption> getShippingQuotes(List<PackageDetails> packages, BigDecimal orderTotal, Delivery delivery, MerchantStore store, IntegrationConfiguration configuration, IntegrationModule module, ShippingConfiguration shippingConfiguration, Locale locale) throws IntegrationException;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/order/InvoiceModule.java b/sm-core/src/main/java/com/salesmanager/core/modules/order/InvoiceModule.java
new file mode 100644
index 0000000..d715a50
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/order/InvoiceModule.java
@@ -0,0 +1,13 @@
+package com.salesmanager.core.modules.order;
+
+import java.io.ByteArrayOutputStream;
+
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+public interface InvoiceModule {
+
+ public ByteArrayOutputStream createInvoice(MerchantStore store, Order order, Language language) throws Exception;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/order/ODSInvoiceModule.java b/sm-core/src/main/java/com/salesmanager/core/modules/order/ODSInvoiceModule.java
new file mode 100644
index 0000000..bc33e98
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/order/ODSInvoiceModule.java
@@ -0,0 +1,404 @@
+package com.salesmanager.core.modules.order;
+
+import java.awt.Graphics2D;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.text.SimpleDateFormat;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.jopendocument.dom.OOUtils;
+import org.jopendocument.dom.spreadsheet.Sheet;
+import org.jopendocument.dom.spreadsheet.SpreadSheet;
+import org.jopendocument.model.OpenDocument;
+import org.jopendocument.renderer.ODTRenderer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.lowagie.text.Document;
+import com.lowagie.text.PageSize;
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.pdf.PdfContentByte;
+import com.lowagie.text.pdf.PdfDocument;
+import com.lowagie.text.pdf.PdfTemplate;
+import com.lowagie.text.pdf.PdfWriter;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.business.order.model.OrderTotal;
+import com.salesmanager.core.business.order.model.orderproduct.OrderProduct;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.country.service.CountryService;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.core.business.reference.zone.service.ZoneService;
+import com.salesmanager.core.constants.Constants;
+import com.salesmanager.core.utils.ProductPriceUtils;
+import com.salesmanager.core.utils.ProductUtils;
+
+public class ODSInvoiceModule implements InvoiceModule {
+
+ private final static String INVOICE_TEMPLATE = "templates/invoice/Invoice";
+ private final static String INVOICE_TEMPLATE_EXTENSION = ".ods";
+ private final static String TEMP_INVOICE_SUFFIX_NAME = "_invoice.ods";
+ private final static int ADDRESS_ROW_START = 2;
+ private final static int ADDRESS_ROW_END = 5;
+
+ private final static int BILLTO_ROW_START = 8;
+ private final static int BILLTO_ROW_END = 13;
+
+ private final static int PRODUCT_ROW_START = 16;
+
+ private static final Logger LOGGER = LoggerFactory.getLogger( ODSInvoiceModule.class );
+
+ @Autowired
+ private ZoneService zoneService;
+
+ @Autowired
+ private CountryService countryService;
+
+ @Autowired
+ private ProductPriceUtils priceUtil;
+
+
+ @Override
+ public ByteArrayOutputStream createInvoice(MerchantStore store, Order order, Language language) throws Exception {
+
+
+
+
+ List<Zone> zones = zoneService.getZones(store.getCountry(), language);
+ Map<String,Country> countries = countryService.getCountriesMap(language);
+
+ //get default template
+ String template = new StringBuilder().append(INVOICE_TEMPLATE).append("_").append(language.getCode().toLowerCase()).append(INVOICE_TEMPLATE_EXTENSION).toString();
+
+ //try by language
+ InputStream is = null;
+ try {
+ is = getClass().getClassLoader().getResourceAsStream(template);
+ } catch (Exception e) {
+ LOGGER.warn("Cannot open template " + template);
+ throw new Exception("Cannot open " + template);
+ }
+
+ if(is==null) {
+ try {
+ is = getClass().getClassLoader().getResourceAsStream(new StringBuilder().append(INVOICE_TEMPLATE).append(INVOICE_TEMPLATE_EXTENSION).toString());
+ } catch (Exception e) {
+ LOGGER.warn("Cannot open template " + template);
+ throw new Exception("Cannot open " + new StringBuilder().append(INVOICE_TEMPLATE).append(INVOICE_TEMPLATE_EXTENSION).toString());
+ }
+ }
+
+ if(is==null) {
+ LOGGER.warn("Cannot open template " + template);
+ throw new Exception("Cannot open " + new StringBuilder().append(INVOICE_TEMPLATE).append(INVOICE_TEMPLATE_EXTENSION).toString());
+ }
+
+ File file = new File(order.getId() + "_working");
+ OutputStream os = new FileOutputStream(file);
+ IOUtils.copy(is, os);
+ os.close();
+ //File file = new File(resource.toURI().toURL());
+
+ Sheet sheet = SpreadSheet.createFromFile(file).getSheet(0);
+
+
+ //Store name
+ sheet.setValueAt(store.getStorename(), 0, 0);
+
+
+
+ //Address
+ //count store address cell
+ int storeAddressCell = ADDRESS_ROW_START;
+
+ Map<String,Zone> zns = zoneService.getZones(language);
+
+
+ //3
+ StringBuilder storeAddress = null;
+ if(!StringUtils.isBlank(store.getStoreaddress())) {
+ storeAddress = new StringBuilder();
+ storeAddress.append(store.getStoreaddress());
+ }
+ if(!StringUtils.isBlank(store.getStorecity())) {
+ if(storeAddress==null) {
+ storeAddress = new StringBuilder();
+ } else {
+ storeAddress.append(", ");
+ }
+ storeAddress.append(store.getStorecity());
+ }
+ if(storeAddress!=null) {
+ sheet.setValueAt(storeAddress.toString(), 0, storeAddressCell);
+ storeAddressCell ++;
+ }
+
+ //4
+ StringBuilder storeProvince = null;
+ if(store.getZone()!=null) {
+ storeProvince = new StringBuilder();
+
+ for(Zone z : zones) {
+ if(z.getCode().equals(store.getZone().getCode())) {
+ storeProvince.append(z.getName());
+ break;
+ }
+ }
+
+ } else {
+ if(!StringUtils.isBlank(store.getStorestateprovince())) {
+ storeProvince = new StringBuilder();
+ storeProvince.append(store.getStorestateprovince());
+ }
+ }
+ if(store.getCountry()!=null) {
+ if(storeProvince==null) {
+ storeProvince = new StringBuilder();
+ } else {
+ storeProvince.append(", ");
+ }
+
+ Country c = countries.get(store.getCountry().getIsoCode());
+ if(c!=null) {
+ storeProvince.append(c.getName());
+ } else {
+ storeProvince.append(store.getCountry().getIsoCode());
+ }
+
+ }
+ if(storeProvince!=null) {
+ sheet.setValueAt(storeProvince.toString(), 0, storeAddressCell);
+ storeAddressCell ++;
+ }
+
+ //5
+ if(!StringUtils.isBlank(store.getStorepostalcode())) {
+ sheet.setValueAt(store.getStorepostalcode(), 0, storeAddressCell);
+ storeAddressCell ++;
+ }
+
+ //6
+ if(!StringUtils.isBlank(store.getStorephone())) {
+ sheet.setValueAt(store.getStorephone(), 0, storeAddressCell);
+ }
+
+ //delete address blank lines
+ for(int i = storeAddressCell; i<ADDRESS_ROW_END; i++) {
+ sheet.setValueAt("", 0, i);
+ }
+
+ //invoice date
+ SimpleDateFormat format = new SimpleDateFormat(Constants.DEFAULT_DATE_FORMAT);
+ sheet.setValueAt(format.format(order.getDatePurchased()), 3, 2);
+
+ //invoice number
+ sheet.setValueAt(order.getId(), 3, 3);
+
+ //bill to
+ //count bill to address cell
+ int billToCell = BILLTO_ROW_START;
+ if(!StringUtils.isBlank(order.getBilling().getFirstName())) {
+ StringBuilder nm = new StringBuilder();
+ nm.append(order.getBilling().getFirstName()).append(" ").append(order.getBilling().getLastName());
+ sheet.setValueAt(nm.toString(), 0, billToCell);
+ billToCell ++;
+ }
+
+ //9
+ if(!StringUtils.isBlank(order.getBilling().getCompany())) {
+ sheet.setValueAt(order.getBilling().getCompany(), 0, billToCell);
+ billToCell ++;
+ }
+
+ //10
+ StringBuilder billToAddress = null;
+ if(!StringUtils.isBlank(order.getBilling().getAddress())) {
+ billToAddress = new StringBuilder();
+ billToAddress.append(order.getBilling().getAddress());
+ }
+ if(!StringUtils.isBlank(order.getBilling().getCity())) {
+ if(billToAddress==null) {
+ billToAddress = new StringBuilder();
+ } else {
+ billToAddress.append(", ");
+ }
+ billToAddress.append(order.getBilling().getCity());
+ }
+ if(billToAddress!=null) {
+ sheet.setValueAt(billToAddress.toString(), 0, billToCell);
+ billToCell ++;
+ }
+
+ //11
+ StringBuilder billToProvince = null;
+ if(order.getBilling().getZone()!=null) {
+ billToProvince = new StringBuilder();
+
+ Zone billingZone = zns.get(order.getBilling().getZone().getCode());
+ if(billingZone!=null) {
+ billToProvince.append(billingZone.getName());
+ }
+
+ } else {
+ if(!StringUtils.isBlank(order.getBilling().getState())) {
+ billToProvince = new StringBuilder();
+ billToProvince.append(order.getBilling().getState());
+ }
+ }
+ if(order.getBilling().getCountry()!=null) {
+ if(billToProvince==null) {
+ billToProvince = new StringBuilder();
+ } else {
+ billToProvince.append(", ");
+ }
+ Country c = countries.get(order.getBilling().getCountry().getIsoCode());
+ if(c!=null) {
+ billToProvince.append(c.getName());
+ } else {
+ billToProvince.append(order.getBilling().getCountry().getIsoCode());
+ }
+
+ }
+ if(billToProvince!=null) {
+ sheet.setValueAt(billToProvince.toString(), 0, billToCell);
+ billToCell ++;
+ }
+
+ //12
+ if(!StringUtils.isBlank(order.getBilling().getPostalCode())) {
+ billToCell ++;
+ sheet.setValueAt(order.getBilling().getPostalCode(), 0, billToCell);
+ billToCell ++;
+ }
+
+ //13
+ if(!StringUtils.isBlank(order.getBilling().getTelephone())) {
+ sheet.setValueAt(order.getBilling().getTelephone(), 0, billToCell);
+ }
+
+ //delete address blank lines
+ for(int i = billToCell; i<BILLTO_ROW_END; i++) {
+ sheet.setValueAt("", 0, i);
+ }
+
+ //products
+ Set<OrderProduct> orderProducts = order.getOrderProducts();
+ int productCell = PRODUCT_ROW_START;
+ for(OrderProduct orderProduct : orderProducts) {
+
+
+ String orderProductName = ProductUtils.buildOrderProductDisplayName(orderProduct);
+
+ sheet.setValueAt(orderProductName.toString(), 0, productCell);
+
+ int quantity = orderProduct.getProductQuantity();
+ sheet.setValueAt(quantity, 1, productCell);
+ String amount = priceUtil.getStoreFormatedAmountWithCurrency(store, orderProduct.getOneTimeCharge());
+ sheet.setValueAt(amount, 2, productCell);
+ String t = priceUtil.getStoreFormatedAmountWithCurrency(store, priceUtil.getOrderProductTotalPrice(store, orderProduct));
+ sheet.setValueAt(t, 3, productCell);
+
+ productCell++;
+
+ }
+
+ //print totals
+ productCell++;
+ Set<OrderTotal> totals = order.getOrderTotal();
+ for(OrderTotal orderTotal : totals) {
+
+ String totalName = orderTotal.getText();
+ if(totalName.contains(".")) {
+ totalName = orderTotal.getTitle();
+ }
+ String totalValue = priceUtil.getStoreFormatedAmountWithCurrency(store,orderTotal.getValue());
+ sheet.setValueAt(totalName, 2, productCell);
+ sheet.setValueAt(totalValue, 3, productCell);
+ productCell++;
+ }
+
+ //sheet.getCellAt(0, 0).setImage(arg0)
+ //sheet.getCellAt(0, 0).setStyleName(arg0)
+ //sheet.getCellAt(0, 0).getStyle().
+
+
+ //generate invoice file
+ StringBuilder tempInvoiceName = new StringBuilder();
+ tempInvoiceName.append(order.getId()).append(TEMP_INVOICE_SUFFIX_NAME);
+ File outputFile = new File(tempInvoiceName.toString());
+ OOUtils.open(sheet.getSpreadSheet().saveAs(outputFile));
+
+
+
+ final OpenDocument doc = new OpenDocument();
+ doc.loadFrom(tempInvoiceName.toString());
+
+ // Open the PDF document
+ Document document = new Document(PageSize.A4);
+
+
+ //File outFile = new File("invoice.pdf");
+
+ PdfDocument pdf = new PdfDocument();
+
+ document.addDocListener(pdf);
+
+ //FileOutputStream fileOutputStream = new FileOutputStream(outFile);
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+
+
+ PdfWriter writer = PdfWriter.getInstance(pdf, outputStream);
+ pdf.addWriter(writer);
+
+ document.open();
+
+ // Create a template and a Graphics2D object
+ Rectangle pageSize = document.getPageSize();
+ int w = (int) (pageSize.getWidth() * 0.9);
+ int h = (int) (pageSize.getHeight() * 0.95);
+ PdfContentByte cb = writer.getDirectContent();
+ PdfTemplate tp = cb.createTemplate(w, h);
+
+ Graphics2D g2 = tp.createPrinterGraphics(w, h, null);
+ // If you want to prevent copy/paste, you can use
+ // g2 = tp.createGraphicsShapes(w, h, true, 0.9f);
+
+ tp.setWidth(w);
+ tp.setHeight(h);
+
+ // Configure the renderer
+ ODTRenderer renderer = new ODTRenderer(doc);
+ renderer.setIgnoreMargins(true);
+ renderer.setPaintMaxResolution(true);
+
+ // Scale the renderer to fit width
+ renderer.setResizeFactor(renderer.getPrintWidth() / w);
+ // Render
+ renderer.paintComponent(g2);
+ g2.dispose();
+
+ // Add our spreadsheet in the middle of the page
+ float offsetX = (pageSize.getWidth() - w) / 2;
+ float offsetY = (pageSize.getHeight() - h) / 2;
+ cb.addTemplate(tp, offsetX, offsetY);
+ // Close the PDF document
+ document.close();
+ outputFile.delete();//remove temp file
+ file.delete();//remove spreadsheet file
+ is.close();
+ return outputStream;
+
+
+
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/utils/Encryption.java b/sm-core/src/main/java/com/salesmanager/core/modules/utils/Encryption.java
new file mode 100644
index 0000000..e665d8c
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/utils/Encryption.java
@@ -0,0 +1,30 @@
+package com.salesmanager.core.modules.utils;
+
+/**
+ * Can be used to encrypt block or information that has to
+ * be maintained secret
+ * @author Carl Samson
+ *
+ */
+public interface Encryption {
+
+
+ /**
+ * Encrypts a string value
+ * @param key
+ * @param value
+ * @return
+ * @throws Exception
+ */
+ public String encrypt(String value) throws Exception;
+
+ /**
+ * Decrypts a string value
+ * @param key
+ * @param value
+ * @return
+ * @throws Exception
+ */
+ public String decrypt(String value) throws Exception;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/utils/EncryptionImpl.java b/sm-core/src/main/java/com/salesmanager/core/modules/utils/EncryptionImpl.java
new file mode 100644
index 0000000..43c44e4
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/utils/EncryptionImpl.java
@@ -0,0 +1,105 @@
+package com.salesmanager.core.modules.utils;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+
+import org.apache.commons.lang3.StringUtils;
+
+public final class EncryptionImpl implements Encryption {
+
+ private final static String IV_P = "fedcba9876543210";
+ private final static String KEY_SPEC = "AES";
+ private final static String CYPHER_SPEC = "AES/CBC/PKCS5Padding";
+
+
+
+ private String secretKey;
+
+
+
+ @Override
+ public String encrypt(String value) throws Exception {
+
+
+ // value = StringUtils.rightPad(value, 16,"*");
+ // Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
+ // NEED TO UNDERSTAND WHY PKCS5Padding DOES NOT WORK
+ Cipher cipher = Cipher.getInstance(CYPHER_SPEC);
+ SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(), KEY_SPEC);
+ IvParameterSpec ivSpec = new IvParameterSpec(IV_P
+ .getBytes());
+ cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
+ byte[] inpbytes = value.getBytes();
+ byte[] encrypted = cipher.doFinal(inpbytes);
+ return new String(bytesToHex(encrypted));
+
+
+ }
+
+ @Override
+ public String decrypt(String value) throws Exception {
+
+
+ if (StringUtils.isBlank(value))
+ throw new Exception("Nothing to encrypt");
+
+ // NEED TO UNDERSTAND WHY PKCS5Padding DOES NOT WORK
+ // Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
+ Cipher cipher = Cipher.getInstance(CYPHER_SPEC);
+ SecretKeySpec keySpec = new SecretKeySpec(secretKey.getBytes(), KEY_SPEC);
+ IvParameterSpec ivSpec = new IvParameterSpec(IV_P
+ .getBytes());
+ cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec);
+ byte[] outText;
+ outText = cipher.doFinal(hexToBytes(value));
+ return new String(outText);
+
+
+ }
+
+
+ private String bytesToHex(byte[] data) {
+ if (data == null) {
+ return null;
+ } else {
+ int len = data.length;
+ String str = "";
+ for (int i = 0; i < len; i++) {
+ if ((data[i] & 0xFF) < 16) {
+ str = str + "0"
+ + java.lang.Integer.toHexString(data[i] & 0xFF);
+ } else {
+ str = str + java.lang.Integer.toHexString(data[i] & 0xFF);
+ }
+
+ }
+ return str;
+ }
+ }
+
+ private static byte[] hexToBytes(String str) {
+ if (str == null) {
+ return null;
+ } else if (str.length() < 2) {
+ return null;
+ } else {
+ int len = str.length() / 2;
+ byte[] buffer = new byte[len];
+ for (int i = 0; i < len; i++) {
+ buffer[i] = (byte) Integer.parseInt(str.substring(i * 2,
+ i * 2 + 2), 16);
+ }
+ return buffer;
+ }
+ }
+
+ public String getSecretKey() {
+ return secretKey;
+ }
+
+ public void setSecretKey(String secretKey) {
+ this.secretKey = secretKey;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/utils/GeoLocation.java b/sm-core/src/main/java/com/salesmanager/core/modules/utils/GeoLocation.java
new file mode 100644
index 0000000..716330a
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/utils/GeoLocation.java
@@ -0,0 +1,9 @@
+package com.salesmanager.core.modules.utils;
+
+import com.salesmanager.core.business.common.model.Address;
+
+public interface GeoLocation {
+
+ Address getAddress(String ipAddress) throws Exception;
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/modules/utils/GeoLocationImpl.java b/sm-core/src/main/java/com/salesmanager/core/modules/utils/GeoLocationImpl.java
new file mode 100644
index 0000000..7bd4ebc
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/modules/utils/GeoLocationImpl.java
@@ -0,0 +1,57 @@
+package com.salesmanager.core.modules.utils;
+
+import java.net.InetAddress;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.maxmind.geoip2.DatabaseReader;
+import com.maxmind.geoip2.model.CityResponse;
+import com.salesmanager.core.business.common.model.Address;
+
+
+public class GeoLocationImpl implements GeoLocation {
+
+ private DatabaseReader reader = null;
+ private static final Logger LOGGER = LoggerFactory.getLogger( GeoLocationImpl.class );
+ //@Value("${dbPath:classpath:/reference/GeoLite2-Country.mmdb}")
+ //private Resource db;
+
+
+
+
+ @Override
+ public Address getAddress(String ipAddress) throws Exception {
+
+ if(reader==null) {
+ //if(db!=null) {
+ //File file = db.getFile();
+ try {
+ java.io.InputStream inputFile = GeoLocationImpl.class.getClassLoader().getResourceAsStream("reference/GeoLite2-Country.mmdb");
+ reader = new DatabaseReader.Builder(inputFile).build();
+ } catch(Exception e) {
+ LOGGER.error("Cannot instantiate IP database",e);
+ }
+ //}
+ }
+
+ Address address = new Address();
+
+
+ CityResponse response = reader.city(InetAddress.getByName(ipAddress));
+
+ address.setCountry(response.getCountry().getIsoCode());
+ address.setPostalCode(response.getPostal().getCode());
+ address.setZone(response.getMostSpecificSubdivision().getIsoCode());
+ address.setCity(response.getCity().getName());
+
+
+
+
+ return address;
+
+
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/utils/AbstractDataPopulator.java b/sm-core/src/main/java/com/salesmanager/core/utils/AbstractDataPopulator.java
new file mode 100644
index 0000000..edd967d
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/utils/AbstractDataPopulator.java
@@ -0,0 +1,41 @@
+/**
+ *
+ */
+package com.salesmanager.core.utils;
+
+import java.util.Locale;
+
+import com.salesmanager.core.business.generic.exception.ConversionException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+
+/**
+ * @author Umesh A
+ *
+ */
+public abstract class AbstractDataPopulator<Source,Target> implements DataPopulator<Source, Target>
+{
+
+
+
+ private Locale locale;
+
+ public void setLocale(Locale locale) {
+ this.locale = locale;
+ }
+ public Locale getLocale() {
+ return locale;
+ }
+
+
+ @Override
+ public Target populate(Source source, MerchantStore store, Language language) throws ConversionException{
+ return populate(source,createTarget(), store, language);
+ }
+
+ protected abstract Target createTarget();
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/utils/ajax/AjaxPageableResponse.java b/sm-core/src/main/java/com/salesmanager/core/utils/ajax/AjaxPageableResponse.java
new file mode 100644
index 0000000..cde51e6
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/utils/ajax/AjaxPageableResponse.java
@@ -0,0 +1,108 @@
+package com.salesmanager.core.utils.ajax;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.json.simple.JSONObject;
+
+public class AjaxPageableResponse extends AjaxResponse {
+
+
+ private int startRow;
+ public int getStartRow() {
+ return startRow;
+ }
+
+
+
+ public void setStartRow(int startRow) {
+ this.startRow = startRow;
+ }
+
+
+
+ private int endRow;
+ private int totalRow;
+
+ protected String getPageInfo() {
+
+ StringBuilder returnString = new StringBuilder();
+ returnString.append("\"startRow\"").append(":");
+ returnString.append(this.startRow).append(",");
+ returnString.append("\"endRow\"").append(":").append(this.endRow).append(",");
+ returnString.append("\"totalRows\"").append(":").append(super.getData().size());
+ return returnString.toString();
+
+ }
+
+
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public String toJSONString() {
+
+ StringBuilder returnString = new StringBuilder();
+
+ returnString.append(getJsonInfo()).append(",");
+ returnString.append(getPageInfo());
+
+ if(this.getData().size()>0) {
+ StringBuilder dataEntries = null;
+ int count = 0;
+ for(Map keyValue : this.getData()) {
+ if(dataEntries == null) {
+ dataEntries = new StringBuilder();
+ }
+ JSONObject data = new JSONObject();
+ Set<String> keys = keyValue.keySet();
+ for(String key : keys) {
+ data.put(key, keyValue.get(key));
+ }
+ String dataField = data.toJSONString();
+ dataEntries.append(dataField);
+ if(count<super.getData().size()-1) {
+ dataEntries.append(",");
+ }
+ count ++;
+ }
+
+ returnString.append(",").append("\"data\"").append(":[");
+ if(dataEntries!=null) {
+ returnString.append(dataEntries.toString());
+ }
+ returnString.append("]");
+ }
+ returnString.append("}}");
+
+
+ return returnString.toString();
+
+
+
+ }
+
+
+
+ public int getEndRow() {
+ return endRow;
+ }
+
+
+
+ public void setEndRow(int endRow) {
+ this.endRow = endRow;
+ }
+
+
+
+ public int getTotalRow() {
+ return totalRow;
+ }
+
+
+
+ public void setTotalRow(int totalRow) {
+ this.totalRow = totalRow;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/utils/ajax/AjaxResponse.java b/sm-core/src/main/java/com/salesmanager/core/utils/ajax/AjaxResponse.java
new file mode 100644
index 0000000..e020f2f
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/utils/ajax/AjaxResponse.java
@@ -0,0 +1,186 @@
+package com.salesmanager.core.utils.ajax;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.collections.CollectionUtils;
+import org.json.simple.JSONAware;
+import org.json.simple.JSONObject;
+
+public class AjaxResponse implements JSONAware {
+
+ public final static int RESPONSE_STATUS_SUCCESS=0;
+ public final static int RESPONSE_STATUS_FAIURE=-1;
+ public final static int RESPONSE_STATUS_VALIDATION_FAILED=-2;
+ public final static int RESPONSE_OPERATION_COMPLETED=9999;
+ public final static int CODE_ALREADY_EXIST=9998;
+
+ private int status;
+ private List<Map<String,String>> data = new ArrayList<Map<String,String>>();
+ private Map<String,String> dataMap = new HashMap<String,String>();
+ private Map<String,String> validationMessages = new HashMap<String,String>();
+ public Map<String, String> getValidationMessages() {
+ return validationMessages;
+ }
+ public void setValidationMessages(Map<String, String> validationMessages) {
+ this.validationMessages = validationMessages;
+ }
+ public int getStatus() {
+ return status;
+ }
+ public void setStatus(int status) {
+ this.status = status;
+ }
+ protected List<Map<String,String>> getData() {
+ return data;
+ }
+
+ public void addDataEntry(Map<String,String> dataEntry) {
+ this.data.add(dataEntry);
+ }
+
+ public void addEntry(String key, String value) {
+ dataMap.put(key, value);
+ }
+
+
+ public void setErrorMessage(Throwable t) {
+ this.setStatusMessage(t.getMessage());
+ }
+
+ public void setErrorString(String t) {
+ this.setStatusMessage(t);
+ }
+
+
+ public void addValidationMessage(String fieldName, String message) {
+ this.validationMessages.put(fieldName, message);
+ }
+
+ private String statusMessage = null;
+
+
+ public String getStatusMessage() {
+ return statusMessage;
+ }
+ public void setStatusMessage(String statusMessage) {
+ this.statusMessage = statusMessage;
+ }
+
+
+ protected String getJsonInfo() {
+
+ StringBuilder returnString = new StringBuilder();
+ returnString.append("{");
+ returnString.append("\"response\"").append(":");
+ returnString.append("{");
+ returnString.append("\"status\"").append(":").append(this.getStatus());
+ if(this.getStatusMessage()!=null && this.getStatus()!=0) {
+ returnString.append(",").append("\"statusMessage\"").append(":\"").append(JSONObject.escape(this.getStatusMessage())).append("\"");
+ }
+ return returnString.toString();
+
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Override
+ public String toJSONString() {
+ StringBuilder returnString = new StringBuilder();
+
+ returnString.append(getJsonInfo());
+
+ if(this.getData().size()>0) {
+ StringBuilder dataEntries = null;
+ int count = 0;
+ for(Map keyValue : this.getData()) {
+ if(dataEntries == null) {
+ dataEntries = new StringBuilder();
+ }
+ JSONObject data = new JSONObject();
+ Set<String> keys = keyValue.keySet();
+ for(String key : keys) {
+ data.put(key, keyValue.get(key));
+ }
+ String dataField = data.toJSONString();
+ dataEntries.append(dataField);
+ if(count<this.data.size()-1) {
+ dataEntries.append(",");
+ }
+ count ++;
+ }
+
+ returnString.append(",").append("\"data\"").append(":[");
+ if(dataEntries!=null) {
+ returnString.append(dataEntries.toString());
+ }
+ returnString.append("]");
+ }
+
+ if(this.getDataMap().size()>0) {
+ StringBuilder dataEntries = null;
+ int count = 0;
+ for(String key : this.getDataMap().keySet()) {
+ if(dataEntries == null) {
+ dataEntries = new StringBuilder();
+ }
+
+ dataEntries.append("\"").append(key).append("\"");
+ dataEntries.append(":");
+ dataEntries.append("\"").append(this.getDataMap().get(key)).append("\"");
+
+ if(count<this.getDataMap().size()-1) {
+ dataEntries.append(",");
+ }
+ count ++;
+ }
+
+ if(dataEntries!=null) {
+ returnString.append(",").append(dataEntries.toString());
+ }
+ }
+
+ if(CollectionUtils.isNotEmpty(this.getValidationMessages().values())) {
+ StringBuilder dataEntries = null;
+ int count = 0;
+ for(String key : this.getValidationMessages().keySet()) {
+ if(dataEntries == null) {
+ dataEntries = new StringBuilder();
+ }
+ dataEntries.append("{");
+ dataEntries.append("\"field\":\"").append(key).append("\"");
+ dataEntries.append(",");
+ dataEntries.append("\"message\":\"").append(this.getValidationMessages().get(key)).append("\"");
+ dataEntries.append("}");
+
+ if(count<this.getValidationMessages().size()-1) {
+ dataEntries.append(",");
+ }
+ count ++;
+ }
+
+ returnString.append(",").append("\"validations\"").append(":[");
+ if(dataEntries!=null) {
+ returnString.append(dataEntries.toString());
+ }
+ returnString.append("]");
+
+ }
+
+ returnString.append("}}");
+
+
+ return returnString.toString();
+
+
+ }
+ public Map<String,String> getDataMap() {
+ return dataMap;
+ }
+ public void setDataMap(Map<String,String> dataMap) {
+ this.dataMap = dataMap;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/utils/ApplicationContextListenerUtils.java b/sm-core/src/main/java/com/salesmanager/core/utils/ApplicationContextListenerUtils.java
new file mode 100644
index 0000000..4ee0584
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/utils/ApplicationContextListenerUtils.java
@@ -0,0 +1,20 @@
+package com.salesmanager.core.utils;
+
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.event.ContextStartedEvent;
+
+import com.salesmanager.core.business.search.service.SearchService;
+
+public class ApplicationContextListenerUtils implements ApplicationListener<ContextStartedEvent> {
+
+ @Override
+ public void onApplicationEvent(ContextStartedEvent event) {
+ ApplicationContext applicationContext = event.getApplicationContext();
+ /** init search service **/
+ SearchService searchService = (SearchService)applicationContext.getBean("productSearchService");
+ searchService.initService();
+
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/utils/CacheUtils.java b/sm-core/src/main/java/com/salesmanager/core/utils/CacheUtils.java
new file mode 100644
index 0000000..e23ed25
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/utils/CacheUtils.java
@@ -0,0 +1,112 @@
+package com.salesmanager.core.utils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.cache.Cache;
+import org.springframework.cache.Cache.ValueWrapper;
+import org.springframework.stereotype.Component;
+
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+
+@Component("cache")
+public class CacheUtils {
+
+
+ @Inject
+ @Qualifier("serviceCache")
+ private Cache cache;
+
+
+ public final static String REFERENCE_CACHE = "REF";
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CacheUtils.class);
+
+ private final static String KEY_DELIMITER = "_";
+
+
+
+ public void putInCache(Object object, String keyName) throws Exception {
+
+ cache.put(keyName, object);
+
+ }
+
+
+ public Object getFromCache(String keyName) throws Exception {
+
+ ValueWrapper vw = cache.get(keyName);
+ if(vw!=null) {
+ return vw.get();
+ }
+
+ return null;
+
+ }
+
+ public List<String> getCacheKeys(MerchantStore store) throws Exception {
+
+ net.sf.ehcache.Cache cacheImpl = (net.sf.ehcache.Cache) cache.getNativeCache();
+ List<String> returnKeys = new ArrayList<String>();
+ for (Object key: cacheImpl.getKeys()) {
+
+
+ try {
+ String sKey = (String)key;
+
+ // a key should be <storeId>_<rest of the key>
+ int delimiterPosition = sKey.indexOf(KEY_DELIMITER);
+
+ if(delimiterPosition>0 && Character.isDigit(sKey.charAt(0))) {
+
+ String keyRemaining = sKey.substring(delimiterPosition+1);
+ returnKeys.add(keyRemaining);
+
+ }
+
+ } catch (Exception e) {
+ LOGGER.equals("key " + key + " cannot be converted to a String or parsed");
+ }
+ }
+
+ return returnKeys;
+ }
+
+ public void shutDownCache() throws Exception {
+
+ }
+
+ public void removeFromCache(String keyName) throws Exception {
+ cache.evict(keyName);
+ }
+
+ public void removeAllFromCache(MerchantStore store) throws Exception {
+ net.sf.ehcache.Cache cacheImpl = (net.sf.ehcache.Cache) cache.getNativeCache();
+ for (Object key: cacheImpl.getKeys()) {
+ try {
+ String sKey = (String)key;
+
+ // a key should be <storeId>_<rest of the key>
+ int delimiterPosition = sKey.indexOf(KEY_DELIMITER);
+
+ if(delimiterPosition>0 && Character.isDigit(sKey.charAt(0))) {
+
+
+ cache.evict(key);
+
+ }
+
+ } catch (Exception e) {
+ LOGGER.equals("key " + key + " cannot be converted to a String or parsed");
+ }
+ }
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/utils/CloneUtils.java b/sm-core/src/main/java/com/salesmanager/core/utils/CloneUtils.java
new file mode 100644
index 0000000..6377078
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/utils/CloneUtils.java
@@ -0,0 +1,16 @@
+package com.salesmanager.core.utils;
+
+import java.util.Date;
+
+public class CloneUtils {
+
+ private CloneUtils() {};
+
+ public static Date clone(Date date) {
+ if (date != null) {
+ return (Date) date.clone();
+ }
+ return null;
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/utils/CoreConfiguration.java b/sm-core/src/main/java/com/salesmanager/core/utils/CoreConfiguration.java
new file mode 100644
index 0000000..cbcd4ca
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/utils/CoreConfiguration.java
@@ -0,0 +1,46 @@
+package com.salesmanager.core.utils;
+
+import java.util.Properties;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+@Component
+public class CoreConfiguration {
+
+
+ public Properties properties = new Properties();
+ private static final Logger LOGGER = LoggerFactory.getLogger(CoreConfiguration.class);
+
+ public Properties getProperties() {
+ return properties;
+ }
+
+ public void setProperties(Properties properties) {
+ this.properties = properties;
+ }
+
+ public CoreConfiguration() {}
+
+ public String getProperty(String propertyKey) {
+
+ return properties.getProperty(propertyKey);
+
+
+ }
+
+ public String getProperty(String propertyKey, String defaultValue) {
+
+ String prop = defaultValue;
+ try {
+ prop = properties.getProperty(propertyKey);
+ } catch(Exception e) {
+ LOGGER.warn("Cannot find property " + propertyKey);
+ }
+ return prop;
+
+
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/utils/CreditCardUtils.java b/sm-core/src/main/java/com/salesmanager/core/utils/CreditCardUtils.java
new file mode 100644
index 0000000..162ef2b
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/utils/CreditCardUtils.java
@@ -0,0 +1,32 @@
+package com.salesmanager.core.utils;
+
+
+public class CreditCardUtils {
+
+
+ public static final int MASTERCARD = 0, VISA = 1;
+ public static final int AMEX = 2, DISCOVER = 3, DINERS = 4;
+
+ public static String maskCardNumber(String clearcardnumber)
+ throws Exception {
+
+ if (clearcardnumber.length() < 10) {
+ throw new Exception("Invalid number of digits");
+ }
+
+ int length = clearcardnumber.length();
+
+ String prefix = clearcardnumber.substring(0, 4);
+ String suffix = clearcardnumber.substring(length - 4);
+
+ StringBuffer mask = new StringBuffer();
+ mask.append(prefix).append("XXXXXXXXXX").append(suffix);
+
+ return mask.toString();
+ }
+
+
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/utils/DataPopulator.java b/sm-core/src/main/java/com/salesmanager/core/utils/DataPopulator.java
new file mode 100644
index 0000000..e075809
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/utils/DataPopulator.java
@@ -0,0 +1,22 @@
+/**
+ *
+ */
+package com.salesmanager.core.utils;
+
+import com.salesmanager.core.business.generic.exception.ConversionException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+/**
+ * @author Umesh A
+ *
+ */
+public interface DataPopulator<Source,Target>
+{
+
+
+ public Target populate(Source source,Target target, MerchantStore store, Language language) throws ConversionException;
+ public Target populate(Source source, MerchantStore store, Language language) throws ConversionException;
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/utils/DataUtils.java b/sm-core/src/main/java/com/salesmanager/core/utils/DataUtils.java
new file mode 100644
index 0000000..fd411dd
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/utils/DataUtils.java
@@ -0,0 +1,102 @@
+package com.salesmanager.core.utils;
+
+import java.math.BigDecimal;
+
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.constants.MeasureUnit;
+
+public class DataUtils {
+
+ /**
+ * Removes dashes
+ * @param postalCode
+ * @return
+ */
+ public static String trimPostalCode(String postalCode) {
+
+ String pc = postalCode.replaceAll("[^a-zA-Z0-9]", "");
+
+ return pc;
+
+ }
+
+
+ /**
+ * Get the measure according to the appropriate measure base. If the measure
+ * configured in store is LB and it needs KG then the appropriate
+ * calculation is done
+ *
+ * @param weight
+ * @param store
+ * @param base
+ * @return
+ */
+ public static double getWeight(double weight, MerchantStore store,
+ String base) {
+
+ double weightConstant = 2.2;
+ if (base.equals(MeasureUnit.LB.name())) {
+ if (store.getWeightunitcode().equals(MeasureUnit.LB.name())) {
+ return new BigDecimal(String.valueOf(weight)).setScale(2,
+ BigDecimal.ROUND_HALF_UP).doubleValue();
+ } else {// pound = kilogram
+ double answer = weight * weightConstant;
+ BigDecimal w = new BigDecimal(answer);
+ return w.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
+ }
+ } else {// need KG
+ if (store.getWeightunitcode().equals(MeasureUnit.KG.name())) {
+ return new BigDecimal(String.valueOf(weight)).setScale(2,
+ BigDecimal.ROUND_HALF_UP).doubleValue();
+ } else {
+
+ double answer = weight / weightConstant;
+ BigDecimal w = new BigDecimal(answer);
+ return w.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
+
+ }
+ }
+ }
+
+ /**
+ * Get the measure according to the appropriate measure base. If the measure
+ * configured in store is IN and it needs CM or vise versa then the
+ * appropriate calculation is done
+ *
+ * @param weight
+ * @param store
+ * @param base
+ * @return
+ */
+ public static double getMeasure(double measure, MerchantStore store,
+ String base) {
+
+ if (base.equals(MeasureUnit.IN.name())) {
+ if (store.getSeizeunitcode().equals(MeasureUnit.IN.name())) {
+ return new BigDecimal(String.valueOf(measure)).setScale(2,
+ BigDecimal.ROUND_HALF_UP).doubleValue();
+ } else {// centimeter (inch to centimeter)
+ double measureConstant = 2.54;
+
+ double answer = measure * measureConstant;
+ BigDecimal w = new BigDecimal(answer);
+ return w.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
+
+ }
+ } else {// need CM
+ if (store.getSeizeunitcode().equals(MeasureUnit.CM.name())) {
+ return new BigDecimal(String.valueOf(measure)).setScale(2)
+ .doubleValue();
+ } else {// in (centimeter to inch)
+ double measureConstant = 0.39;
+
+ double answer = measure * measureConstant;
+ BigDecimal w = new BigDecimal(answer);
+ return w.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
+
+ }
+ }
+
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/utils/EntityPopulator.java b/sm-core/src/main/java/com/salesmanager/core/utils/EntityPopulator.java
new file mode 100644
index 0000000..9071474
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/utils/EntityPopulator.java
@@ -0,0 +1,18 @@
+/**
+ *
+ */
+package com.salesmanager.core.utils;
+
+import com.salesmanager.core.business.generic.exception.ConversionException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+
+/**
+ * @author Umesh A
+ *
+ */
+public interface EntityPopulator<Source,Target>
+{
+
+ public Target populateToEntity(Source source, Target target, MerchantStore store) throws ConversionException;
+ public Target populateToEntity(Source source) throws ConversionException;
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/utils/ProductImageCropUtils.java b/sm-core/src/main/java/com/salesmanager/core/utils/ProductImageCropUtils.java
new file mode 100755
index 0000000..68d295e
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/utils/ProductImageCropUtils.java
@@ -0,0 +1,232 @@
+package com.salesmanager.core.utils;
+
+import java.awt.Rectangle;
+import java.awt.image.BufferedImage;
+import java.io.File;
+import java.io.IOException;
+import java.net.FileNameMap;
+import java.net.URLConnection;
+
+import javax.imageio.ImageIO;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ProductImageCropUtils {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ProductImageCropUtils.class);
+
+ private boolean cropeable = true;
+
+ private int cropeBaseline = 0;// o is width, 1 is height
+
+ private int getCropeBaseline() {
+ return cropeBaseline;
+ }
+
+
+
+ private double cropAreaWidth = 0;
+ private double cropAreaHeight = 0;
+
+ //private InputStream originalFile = null;
+ private BufferedImage originalFile = null;
+
+
+
+ public ProductImageCropUtils(BufferedImage file, int largeImageWidth, int largeImageHeight) {
+
+
+
+ try {
+
+
+ this.originalFile = file;
+
+ /** Original Image **/
+ // get original image size
+
+ int width = originalFile.getWidth();
+ int height = originalFile.getHeight();
+
+ /*** determine if image can be cropped ***/
+ determineCropeable(width, largeImageWidth, height, largeImageHeight);
+
+ /*** determine crop area calculation baseline ***/
+ //this.determineBaseline(width, height);
+
+ determineCropArea(width, largeImageWidth, height, largeImageHeight);
+
+ } catch (Exception e) {
+ LOGGER.error("Image Utils error in constructor", e);
+ }
+
+
+
+
+
+
+ }
+
+
+ private void determineCropeable(int width, int specificationsWidth,
+ int height, int specificationsHeight) {
+ /*** determine if image can be cropped ***/
+ // height
+ int y = height - specificationsHeight;
+ // width
+ int x = width - specificationsWidth;
+
+ if (x < 0 || y < 0) {
+ setCropeable(false);
+ }
+
+ if (x == 0 && y == 0) {
+ setCropeable(false);
+ }
+
+
+ if((height % specificationsHeight) == 0 && (width % specificationsWidth) == 0 ) {
+ setCropeable(false);
+ }
+
+
+
+ }
+
+
+ private void determineCropArea(int width, int specificationsWidth,
+ int height, int specificationsHeight) {
+
+ cropAreaWidth = specificationsWidth;
+ cropAreaHeight = specificationsHeight;
+
+
+ double factorWidth = new Integer(width).doubleValue() / new Integer(specificationsWidth).doubleValue();
+ double factorHeight = new Integer(height).doubleValue() / new Integer(specificationsHeight).doubleValue();
+
+ double factor = factorWidth;
+
+ if(factorWidth>factorHeight) {
+ factor = factorHeight;
+ }
+
+
+ // crop factor
+/* double factor = 1;
+ if (this.getCropeBaseline() == 0) {// width
+ factor = new Integer(width).doubleValue()
+ / new Integer(specificationsWidth).doubleValue();
+ } else {// height
+ factor = new Integer(height).doubleValue()
+ / new Integer(specificationsHeight).doubleValue();
+ }*/
+
+ double w = factor * specificationsWidth;
+ double h = factor * specificationsHeight;
+
+ if(w==h) {
+ setCropeable(false);
+ }
+
+
+ cropAreaWidth = w;
+
+ if(cropAreaWidth > width)
+ cropAreaWidth = width;
+
+ cropAreaHeight = h;
+
+ if(cropAreaHeight > height)
+ cropAreaHeight = height;
+
+ /*
+ * if(factor>1) { //determine croping section for(double
+ * i=factor;i>1;i--) { //multiply specifications by factor int newWidth
+ * = (int)(i * specificationsWidth); int newHeight = (int)(i *
+ * specificationsHeight); //check if new size >= original image
+ * if(width>=newWidth && height>=newHeight) { cropAreaWidth = newWidth;
+ * cropAreaHeight = newHeight; break; } } }
+ */
+
+ }
+
+
+ public File getCroppedImage(File originalFile, int x1, int y1, int width,
+ int height) throws Exception {
+
+ if(!this.cropeable) {
+ return originalFile;
+ }
+
+ FileNameMap fileNameMap = URLConnection.getFileNameMap();
+ String contentType = fileNameMap.getContentTypeFor(originalFile.getName());
+
+ String extension = contentType.substring(contentType.indexOf("/"),contentType.length());
+
+ BufferedImage image = ImageIO.read(originalFile);
+ BufferedImage out = image.getSubimage(x1, y1, width, height);
+ File tempFile = File.createTempFile("temp", "." + extension );
+ tempFile.deleteOnExit();
+ ImageIO.write(out, extension, tempFile);
+ return tempFile;
+ }
+
+ public BufferedImage getCroppedImage() throws IOException {
+
+
+ //out if croppedArea == 0 or file is null
+
+
+
+
+ Rectangle goal = new Rectangle( (int)this.getCropAreaWidth(), (int) this.getCropAreaHeight());
+
+ //Then intersect it with the dimensions of your image:
+
+ Rectangle clip = goal.intersection(new Rectangle(originalFile.getWidth(), originalFile.getHeight()));
+
+ //Now, clip corresponds to the portion of bi that will fit within your goal. In this case 100 x50.
+
+ //Now get the subImage using the value of clip.
+
+ BufferedImage clippedImg = originalFile.getSubimage(clip.x, clip.y, clip.width, clip.height);
+
+
+ return clippedImg;
+
+
+
+
+ }
+
+
+
+
+ public double getCropAreaWidth() {
+ return cropAreaWidth;
+ }
+
+ public void setCropAreaWidth(int cropAreaWidth) {
+ this.cropAreaWidth = cropAreaWidth;
+ }
+
+ public double getCropAreaHeight() {
+ return cropAreaHeight;
+ }
+
+ public void setCropAreaHeight(int cropAreaHeight) {
+ this.cropAreaHeight = cropAreaHeight;
+ }
+
+ public void setCropeable(boolean cropeable) {
+ this.cropeable = cropeable;
+ }
+
+ public boolean isCropeable() {
+ return cropeable;
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/utils/ProductImageSizeUtils.java b/sm-core/src/main/java/com/salesmanager/core/utils/ProductImageSizeUtils.java
new file mode 100755
index 0000000..1bf19f4
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/utils/ProductImageSizeUtils.java
@@ -0,0 +1,151 @@
+package com.salesmanager.core.utils;
+
+import java.awt.AlphaComposite;
+import java.awt.Graphics2D;
+import java.awt.RenderingHints;
+import java.awt.Transparency;
+import java.awt.image.BufferedImage;
+
+/**
+ * Utility class for image resize functions
+ * @author Carl Samson
+ *
+ */
+public class ProductImageSizeUtils {
+
+
+ private ProductImageSizeUtils() {
+
+ }
+
+
+ /**
+ * Simple resize, does not maintain aspect ratio
+ * @param image
+ * @param width
+ * @param height
+ * @return
+ */
+
+ public static BufferedImage resize(BufferedImage image, int width, int height) {
+ int type = image.getType() == 0 ? BufferedImage.TYPE_INT_ARGB : image
+ .getType();
+ BufferedImage resizedImage = new BufferedImage(width, height, type);
+ Graphics2D g = resizedImage.createGraphics();
+ g.setComposite(AlphaComposite.Src);
+ g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
+ RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+ g.setRenderingHint(RenderingHints.KEY_RENDERING,
+ RenderingHints.VALUE_RENDER_QUALITY);
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
+ RenderingHints.VALUE_ANTIALIAS_ON);
+ g.drawImage(image, 0, 0, width, height, null);
+ g.dispose();
+ return resizedImage;
+ }
+
+ /**
+ *
+ * @param img
+ * @param targetWidth
+ * @param targetHeight
+ * @param hint
+ * {@code RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR},
+ * {@code RenderingHints.VALUE_INTERPOLATION_BILINEAR},
+ * {@code RenderingHints.VALUE_INTERPOLATION_BICUBIC})
+ * @param higherQuality
+ * @return
+ */
+ public static BufferedImage resizeWithHint(BufferedImage img,
+ int targetWidth, int targetHeight, Object hint,
+ boolean higherQuality) {
+ int type = (img.getTransparency() == Transparency.OPAQUE) ? BufferedImage.TYPE_INT_RGB
+ : BufferedImage.TYPE_INT_ARGB;
+ BufferedImage ret = (BufferedImage) img;
+ int w, h;
+ if (higherQuality) {
+ // Use multi-step technique: start with original size, then
+ // scale down in multiple passes with drawImage()
+ // until the target size is reached
+ w = img.getWidth();
+ h = img.getHeight();
+ } else {
+ // Use one-step technique: scale directly from original
+ // size to target size with a single drawImage() call
+ w = targetWidth;
+ h = targetHeight;
+ }
+
+ do {
+ if (higherQuality && w > targetWidth) {
+ w /= 2;
+ if (w < targetWidth) {
+ w = targetWidth;
+ }
+ }
+
+ if (higherQuality && h > targetHeight) {
+ h /= 2;
+ if (h < targetHeight) {
+ h = targetHeight;
+ }
+ }
+
+ BufferedImage tmp = new BufferedImage(w, h, type);
+ Graphics2D g2 = tmp.createGraphics();
+ g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, hint);
+ g2.drawImage(ret, 0, 0, w, h, null);
+ g2.dispose();
+
+ ret = tmp;
+ } while (w != targetWidth || h != targetHeight);
+
+ return ret;
+ }
+
+
+ public static BufferedImage resizeWithRatio(BufferedImage image, int destinationWidth, int destinationHeight) {
+
+ int type = image.getType() == 0? BufferedImage.TYPE_INT_ARGB : image.getType();
+
+ //*Special* if the width or height is 0 use image src dimensions
+ if (destinationWidth == 0) {
+ destinationWidth = image.getWidth();
+ }
+ if (destinationHeight == 0) {
+ destinationHeight = image.getHeight();
+ }
+
+ int fHeight = destinationHeight;
+ int fWidth = destinationWidth;
+
+ //Work out the resized width/height
+ if (image.getHeight() > destinationHeight || image.getWidth() > destinationWidth) {
+ fHeight = destinationHeight;
+ int wid = destinationWidth;
+ float sum = (float)image.getWidth() / (float)image.getHeight();
+ fWidth = Math.round(fHeight * sum);
+
+ if (fWidth > wid) {
+ //rezise again for the width this time
+ fHeight = Math.round(wid/sum);
+ fWidth = wid;
+ }
+ }
+
+ BufferedImage resizedImage = new BufferedImage(fWidth, fHeight, type);
+ Graphics2D g = resizedImage.createGraphics();
+ g.setComposite(AlphaComposite.Src);
+
+ g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+ g.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
+ g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+
+ g.drawImage(image, 0, 0, fWidth, fHeight, null);
+ g.dispose();
+
+ return resizedImage;
+ }
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/utils/ProductPriceUtils.java b/sm-core/src/main/java/com/salesmanager/core/utils/ProductPriceUtils.java
new file mode 100755
index 0000000..6eee5f9
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/utils/ProductPriceUtils.java
@@ -0,0 +1,614 @@
+package com.salesmanager.core.utils;
+
+import java.math.BigDecimal;
+import java.text.NumberFormat;
+import java.util.ArrayList;
+import java.util.Currency;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.lang.Validate;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.validator.routines.BigDecimalValidator;
+import org.apache.commons.validator.routines.CurrencyValidator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute;
+import com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability;
+import com.salesmanager.core.business.catalog.product.model.price.FinalPrice;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPrice;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.orderproduct.OrderProduct;
+import com.salesmanager.core.constants.Constants;
+
+
+/**
+ * This class determines the price that is displayed in the catalogue for a given item.
+ * It does not calculate the total price for a given item
+ * @author casams1
+ *
+ */
+@Component("priceUtil")
+public class ProductPriceUtils {
+
+ private final static char DECIMALCOUNT = '2';
+ private final static char DECIMALPOINT = '.';
+ private final static char THOUSANDPOINT = ',';
+
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ProductPriceUtils.class);
+
+
+
+ /**
+ * Get the price without discount
+ * @param store
+ * @param product
+ * @param locale
+ * @return
+ */
+ public BigDecimal getPrice(MerchantStore store, Product product, Locale locale) {
+
+ BigDecimal defaultPrice = new BigDecimal(0);
+
+ Set<ProductAvailability> availabilities = product.getAvailabilities();
+ for(ProductAvailability availability : availabilities) {
+
+ Set<ProductPrice> prices = availability.getPrices();
+ for(ProductPrice price : prices) {
+
+ if(price.isDefaultPrice()) {
+ defaultPrice = price.getProductPriceAmount();
+ }
+ }
+ }
+
+ return defaultPrice;
+ }
+
+ /**
+ * This method calculates the final price taking into account
+ * all attributes included having a specified default attribute with an attribute price gt 0
+ * in the product object. The calculation is based
+ * on the default price.
+ * Attributes may be null
+ * @param Product
+ * @param List<ProductAttribute>
+ * @return FinalPrice
+ */
+ public FinalPrice getFinalProductPrice(Product product, List<ProductAttribute> attributes) {
+
+
+ FinalPrice finalPrice = calculateFinalPrice(product);
+
+ //attributes
+ BigDecimal attributePrice = null;
+ if(attributes!=null && attributes.size()>0) {
+ for(ProductAttribute attribute : attributes) {
+ if(attribute.getProductAttributePrice()!=null && attribute.getProductAttributePrice().doubleValue()>0) {
+ if(attributePrice==null) {
+ attributePrice = new BigDecimal(0);
+ }
+ attributePrice = attributePrice.add(attribute.getProductAttributePrice());
+ }
+ }
+
+ if(attributePrice!=null && attributePrice.doubleValue()>0) {
+ BigDecimal fp = finalPrice.getFinalPrice();
+ fp = fp.add(attributePrice);
+ finalPrice.setFinalPrice(fp);
+
+ BigDecimal op = finalPrice.getOriginalPrice();
+ op = op.add(attributePrice);
+ finalPrice.setOriginalPrice(op);
+
+ BigDecimal dp = finalPrice.getDiscountedPrice();
+ if(dp!=null) {
+ dp = dp.add(attributePrice);
+ finalPrice.setDiscountedPrice(dp);
+ }
+
+ }
+ }
+
+
+ return finalPrice;
+
+ }
+
+
+ /**
+ * This is the final price calculated from all configured prices
+ * and all possibles discounts. This price does not calculate the attributes
+ * or other prices than the default one
+ * @param store
+ * @param product
+ * @param locale
+ * @return
+ */
+ public FinalPrice getFinalPrice(Product product) {
+
+
+
+ FinalPrice finalPrice = calculateFinalPrice(product);
+
+ //attributes
+ BigDecimal attributePrice = null;
+ if(product.getAttributes()!=null && product.getAttributes().size()>0) {
+ for(ProductAttribute attribute : product.getAttributes()) {
+ if(attribute.getAttributeDefault()) {
+ if(attribute.getProductAttributePrice()!=null && attribute.getProductAttributePrice().doubleValue()>0) {
+ if(attributePrice==null) {
+ attributePrice = new BigDecimal(0);
+ }
+ attributePrice = attributePrice.add(attribute.getProductAttributePrice());
+ }
+ }
+ }
+
+ if(attributePrice!=null && attributePrice.doubleValue()>0) {
+ BigDecimal fp = finalPrice.getFinalPrice();
+ fp = fp.add(attributePrice);
+ finalPrice.setFinalPrice(fp);
+
+ BigDecimal op = finalPrice.getOriginalPrice();
+ op = op.add(attributePrice);
+ finalPrice.setOriginalPrice(op);
+ }
+ }
+
+ return finalPrice;
+
+ }
+
+
+
+
+ /**
+ * This is the format that will be displayed
+ * in the admin input text fields when editing
+ * an entity having a BigDecimal to be displayed
+ * as a raw amount 1,299.99
+ * The admin user will also be force to input
+ * the amount using that format
+ * @param store
+ * @param amount
+ * @return
+ * @throws Exception
+ */
+ public String getAdminFormatedAmount(MerchantStore store, BigDecimal amount) throws Exception {
+
+ if(amount==null) {
+ return "";
+ }
+
+ NumberFormat nf = null;
+
+
+ nf = NumberFormat.getInstance(Constants.DEFAULT_LOCALE);
+
+ nf.setMaximumFractionDigits(Integer.parseInt(Character
+ .toString(DECIMALCOUNT)));
+ nf.setMinimumFractionDigits(Integer.parseInt(Character
+ .toString(DECIMALCOUNT)));
+
+ return nf.format(amount);
+ }
+
+
+ /**
+ * This method has to be used to format store front amounts
+ * It will display national format amount ex:
+ * $1,345.99
+ * Rs.1.345.99
+ * or international format
+ * USD1,345.79
+ * INR1,345.79
+ * @param store
+ * @param amount
+ * @return String
+ * @throws Exception
+ */
+ public String getStoreFormatedAmountWithCurrency(MerchantStore store, BigDecimal amount) throws Exception {
+ if(amount==null) {
+ return "";
+ }
+
+
+
+ Currency currency = Constants.DEFAULT_CURRENCY;
+ Locale locale = Constants.DEFAULT_LOCALE;
+
+ try {
+
+ currency = store.getCurrency().getCurrency();
+ locale = new Locale(store.getDefaultLanguage().getCode(),store.getCountry().getIsoCode());
+ } catch (Exception e) {
+ LOGGER.error("Cannot create currency or locale instance for store " + store.getCode());
+ }
+
+
+ NumberFormat currencyInstance = null;
+
+
+ if(store.isCurrencyFormatNational()) {
+ currencyInstance = NumberFormat.getCurrencyInstance(locale);//national
+ } else {
+ currencyInstance = NumberFormat.getCurrencyInstance();//international
+ }
+ currencyInstance.setCurrency(currency);
+
+
+ return currencyInstance.format(amount.doubleValue());
+
+
+ }
+
+
+ public String getFormatedAmountWithCurrency(Locale locale, com.salesmanager.core.business.reference.currency.model.Currency currency, BigDecimal amount) throws Exception {
+ if(amount==null) {
+ return "";
+ }
+
+ Currency curr = currency.getCurrency();
+
+
+
+ NumberFormat currencyInstance = null;
+
+ currencyInstance = NumberFormat.getCurrencyInstance(locale);
+ currencyInstance.setCurrency(curr);
+ return currencyInstance.format(amount.doubleValue());
+
+
+ }
+
+
+
+ /**
+ * This method will return the required formated amount
+ * with the appropriate currency
+ * @param store
+ * @param amount
+ * @return
+ * @throws Exception
+ */
+ public String getAdminFormatedAmountWithCurrency(MerchantStore store, BigDecimal amount) throws Exception {
+ if(amount==null) {
+ return "";
+ }
+
+
+
+
+ NumberFormat nf = null;
+
+
+ Currency currency = store.getCurrency().getCurrency();
+ nf = NumberFormat.getInstance(Constants.DEFAULT_LOCALE);
+ nf.setMaximumFractionDigits(Integer.parseInt(Character
+ .toString(DECIMALCOUNT)));
+ nf.setMinimumFractionDigits(Integer.parseInt(Character
+ .toString(DECIMALCOUNT)));
+ nf.setCurrency(currency);
+
+
+ return nf.format(amount);
+ }
+
+ /**
+ * Returns a formatted amount using Shopizer Currency
+ * requires internal java.util.Currency populated
+ * @param currency
+ * @param amount
+ * @return
+ * @throws Exception
+ */
+ public String getFormatedAmountWithCurrency(com.salesmanager.core.business.reference.currency.model.Currency currency, BigDecimal amount) throws Exception {
+ if(amount==null) {
+ return "";
+ }
+
+ Validate.notNull(currency.getCurrency(),"Currency must be populated with java.util.Currency");
+
+ NumberFormat nf = null;
+
+
+ Currency curr = currency.getCurrency();
+ nf = NumberFormat.getInstance(Constants.DEFAULT_LOCALE);
+ nf.setMaximumFractionDigits(Integer.parseInt(Character
+ .toString(DECIMALCOUNT)));
+ nf.setMinimumFractionDigits(Integer.parseInt(Character
+ .toString(DECIMALCOUNT)));
+ nf.setCurrency(curr);
+
+
+ String stringNumber = nf.format(amount);
+
+ return stringNumber;
+ }
+
+ /**
+ * This amount will be displayed to the end user
+ * @param store
+ * @param amount
+ * @param locale
+ * @return
+ * @throws Exception
+ */
+ public String getFormatedAmountWithCurrency(MerchantStore store, BigDecimal amount, Locale locale)
+ throws Exception {
+
+ NumberFormat nf = null;
+
+ Currency currency = store.getCurrency().getCurrency();
+
+ nf = NumberFormat.getInstance(locale);
+ nf.setCurrency(currency);
+ nf.setMaximumFractionDigits(Integer.parseInt(Character
+ .toString(DECIMALCOUNT)));
+ nf.setMinimumFractionDigits(Integer.parseInt(Character
+ .toString(DECIMALCOUNT)));
+
+
+
+ return nf.format(amount);
+
+ }
+
+ /**
+ * Transformation of an amount of money submited by the admin
+ * user to be inserted as a BigDecimal in the database
+ * @param amount
+ * @param locale
+ * @return
+ * @throws Exception
+ */
+ public BigDecimal getAmount(String amount) throws Exception {
+
+ // validations
+ /**
+ * 1) remove decimal and thousand
+ *
+ * String.replaceAll(decimalPoint, ""); String.replaceAll(thousandPoint,
+ * "");
+ *
+ * Should be able to parse to Integer
+ */
+ StringBuffer newAmount = new StringBuffer();
+ for (int i = 0; i < amount.length(); i++) {
+ if (amount.charAt(i) != DECIMALPOINT
+ && amount.charAt(i) != THOUSANDPOINT) {
+ newAmount.append(amount.charAt(i));
+ }
+ }
+
+ try {
+ Integer.parseInt(newAmount.toString());
+ } catch (Exception e) {
+ throw new Exception("Cannot parse " + amount);
+ }
+
+ if (!amount.contains(Character.toString(DECIMALPOINT))
+ && !amount.contains(Character.toString(THOUSANDPOINT))
+ && !amount.contains(" ")) {
+
+ if (matchPositiveInteger(amount)) {
+ BigDecimalValidator validator = CurrencyValidator.getInstance();
+ BigDecimal bdamount = validator.validate(amount, Locale.US);
+ if (bdamount == null) {
+ throw new Exception("Cannot parse " + amount);
+ } else {
+ return bdamount;
+ }
+ } else {
+ throw new Exception("Not a positive integer "
+ + amount);
+ }
+
+ } else {
+ //TODO should not go this path in this current release
+ StringBuffer pat = new StringBuffer();
+
+ if (!StringUtils.isBlank(Character.toString(THOUSANDPOINT))) {
+ pat.append("\\d{1,3}(" + THOUSANDPOINT + "?\\d{3})*");
+ }
+
+ pat.append("(\\" + DECIMALPOINT + "\\d{1," + DECIMALCOUNT + "})");
+
+ Pattern pattern = Pattern.compile(pat.toString());
+ Matcher matcher = pattern.matcher(amount);
+
+ if (matcher.matches()) {
+
+ Locale locale = Constants.DEFAULT_LOCALE;
+ //TODO validate amount using old test case
+ if (DECIMALPOINT == ',') {
+ locale = Locale.GERMAN;
+ }
+
+ BigDecimalValidator validator = CurrencyValidator.getInstance();
+ BigDecimal bdamount = validator.validate(amount, locale);
+
+ return bdamount;
+ } else {
+ throw new Exception("Cannot parse " + amount);
+ }
+ }
+
+ }
+
+ public BigDecimal getOrderProductTotalPrice(MerchantStore store, OrderProduct orderProduct) {
+
+ BigDecimal finalPrice = orderProduct.getOneTimeCharge();
+ finalPrice = finalPrice.multiply(new BigDecimal(orderProduct.getProductQuantity()));
+ return finalPrice;
+ }
+
+ /**
+ * Determines if a ProductPrice has a discount
+ * @param productPrice
+ * @return
+ */
+ public boolean hasDiscount(ProductPrice productPrice) {
+
+
+ Date today = new Date();
+
+ //calculate discount price
+ boolean hasDiscount = false;
+ if(productPrice.getProductPriceSpecialStartDate()!=null
+ || productPrice.getProductPriceSpecialEndDate()!=null) {
+
+
+ if(productPrice.getProductPriceSpecialStartDate()!=null) {
+ if(productPrice.getProductPriceSpecialStartDate().before(today)) {
+ if(productPrice.getProductPriceSpecialEndDate()!=null) {
+ if(productPrice.getProductPriceSpecialEndDate().after(today)) {
+ hasDiscount = true;
+ }
+ }
+ }
+ }
+ }
+
+ return hasDiscount;
+
+
+
+ }
+
+ private boolean matchPositiveInteger(String amount) {
+
+ Pattern pattern = Pattern.compile("^[+]?\\d*$");
+ Matcher matcher = pattern.matcher(amount);
+ if (matcher.matches()) {
+ return true;
+
+ } else {
+ return false;
+ }
+ }
+
+ private FinalPrice calculateFinalPrice(Product product) {
+
+ FinalPrice finalPrice = null;;
+ List<FinalPrice> otherPrices = null;
+
+
+ Set<ProductAvailability> availabilities = product.getAvailabilities();
+ for(ProductAvailability availability : availabilities) {
+ if(availability.getRegion().equals(Constants.ALL_REGIONS)) {//TODO REL 2.1 accept a region
+ Set<ProductPrice> prices = availability.getPrices();
+ for(ProductPrice price : prices) {
+
+ FinalPrice p = finalPrice(price);
+ if(price.isDefaultPrice()) {
+ finalPrice = p;
+ } else {
+ if(otherPrices==null) {
+ otherPrices = new ArrayList<FinalPrice>();
+ }
+ otherPrices.add(p);
+ }
+ }
+ }
+ }
+
+
+ if(finalPrice!=null) {
+ finalPrice.setAdditionalPrices(otherPrices);
+ } else {
+ if(otherPrices!=null) {
+ finalPrice = otherPrices.get(0);
+ }
+ }
+
+ return finalPrice;
+
+
+ }
+
+ private FinalPrice finalPrice(ProductPrice price) {
+
+ FinalPrice finalPrice = new FinalPrice();
+ BigDecimal fPrice = price.getProductPriceAmount();
+ BigDecimal oPrice = price.getProductPriceAmount();
+
+ Date today = new Date();
+ //calculate discount price
+ boolean hasDiscount = false;
+ if(price.getProductPriceSpecialStartDate()!=null
+ || price.getProductPriceSpecialEndDate()!=null) {
+
+
+ if(price.getProductPriceSpecialStartDate()!=null) {
+ if(price.getProductPriceSpecialStartDate().before(today)) {
+ if(price.getProductPriceSpecialEndDate()!=null) {
+ if(price.getProductPriceSpecialEndDate().after(today)) {
+ hasDiscount = true;
+ fPrice = price.getProductPriceSpecialAmount();
+ finalPrice.setDiscountEndDate(price.getProductPriceSpecialEndDate());
+ }
+ }
+
+ }
+ }
+
+
+ if(!hasDiscount && price.getProductPriceSpecialStartDate()==null && price.getProductPriceSpecialEndDate()!=null) {
+ if(price.getProductPriceSpecialEndDate().after(today)) {
+ hasDiscount = true;
+ fPrice = price.getProductPriceSpecialAmount();
+ finalPrice.setDiscountEndDate(price.getProductPriceSpecialEndDate());
+ }
+ }
+ } else {
+ if(price.getProductPriceSpecialAmount()!=null && price.getProductPriceSpecialAmount().doubleValue()>0) {
+ hasDiscount = true;
+ fPrice = price.getProductPriceSpecialAmount();
+ finalPrice.setDiscountEndDate(price.getProductPriceSpecialEndDate());
+ }
+ }
+
+ finalPrice.setProductPrice(price);
+ finalPrice.setFinalPrice(fPrice);
+ finalPrice.setOriginalPrice(oPrice);
+
+
+ if(price.isDefaultPrice()) {
+ finalPrice.setDefaultPrice(true);
+ }
+ if(hasDiscount) {
+ discountPrice(finalPrice);
+ }
+
+
+ return finalPrice;
+ }
+
+ private void discountPrice(FinalPrice finalPrice) {
+
+ finalPrice.setDiscounted(true);
+
+ double arith = finalPrice.getProductPrice().getProductPriceSpecialAmount().doubleValue() / finalPrice.getProductPrice().getProductPriceAmount().doubleValue();
+ double fsdiscount = 100 - (arith * 100);
+ Float percentagediscount = new Float(fsdiscount);
+ int percent = percentagediscount.intValue();
+ finalPrice.setDiscountPercent(percent);
+
+ //calculate percent
+ BigDecimal price = finalPrice.getOriginalPrice();
+ finalPrice.setDiscountedPrice(finalPrice.getProductPrice().getProductPriceSpecialAmount());
+ }
+
+
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/utils/ProductUtils.java b/sm-core/src/main/java/com/salesmanager/core/utils/ProductUtils.java
new file mode 100644
index 0000000..60950fa
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/utils/ProductUtils.java
@@ -0,0 +1,42 @@
+package com.salesmanager.core.utils;
+
+import java.util.Set;
+
+import com.salesmanager.core.business.order.model.orderproduct.OrderProduct;
+import com.salesmanager.core.business.order.model.orderproduct.OrderProductAttribute;
+
+public class ProductUtils {
+
+ public static String buildOrderProductDisplayName(OrderProduct orderProduct) {
+
+ String pName = orderProduct.getProductName();
+ Set<OrderProductAttribute> oAttributes = orderProduct.getOrderAttributes();
+ StringBuilder attributeName = null;
+ for(OrderProductAttribute oProductAttribute : oAttributes) {
+ if(attributeName == null) {
+ attributeName = new StringBuilder();
+ attributeName.append("[");
+ } else {
+ attributeName.append(", ");
+ }
+ attributeName.append(oProductAttribute.getProductAttributeName())
+ .append(": ")
+ .append(oProductAttribute.getProductAttributeValueName());
+
+ }
+
+
+ StringBuilder productName = new StringBuilder();
+ productName.append(pName);
+
+ if(attributeName!=null) {
+ attributeName.append("]");
+ productName.append(" ").append(attributeName.toString());
+ }
+
+ return productName.toString();
+
+
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/utils/reference/ConfigurationModulesLoader.java b/sm-core/src/main/java/com/salesmanager/core/utils/reference/ConfigurationModulesLoader.java
new file mode 100644
index 0000000..64e7bad
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/utils/reference/ConfigurationModulesLoader.java
@@ -0,0 +1,103 @@
+package com.salesmanager.core.utils.reference;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.system.model.IntegrationConfiguration;
+
+
+public class ConfigurationModulesLoader {
+
+ @SuppressWarnings("unused")
+ private static final Logger LOGGER = LoggerFactory.getLogger(ConfigurationModulesLoader.class);
+
+
+
+ public static String toJSONString(Map<String,IntegrationConfiguration> configurations) throws Exception {
+
+ StringBuilder jsonModules = new StringBuilder();
+ jsonModules.append("[");
+ int count = 0;
+ for(Object key : configurations.keySet()) {
+
+ String k = (String)key;
+ IntegrationConfiguration c = (IntegrationConfiguration)configurations.get(k);
+
+ String jsonString = c.toJSONString();
+ jsonModules.append(jsonString);
+
+ count ++;
+ if(count<configurations.size()) {
+ jsonModules.append(",");
+ }
+ }
+ jsonModules.append("]");
+ return jsonModules.toString();
+
+
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public static Map<String,IntegrationConfiguration> loadIntegrationConfigurations(String value) throws Exception {
+
+
+ Map<String,IntegrationConfiguration> modules = new HashMap<String,IntegrationConfiguration>();
+
+ ObjectMapper mapper = new ObjectMapper();
+
+ try {
+
+
+ Map[] objects = mapper.readValue(value, Map[].class);
+
+ for(int i = 0; i < objects.length; i++) {
+
+
+ Map object = objects[i];
+
+ IntegrationConfiguration configuration = new IntegrationConfiguration();
+
+ String moduleCode = (String)object.get("moduleCode");
+ if(object.get("active")!=null) {
+ configuration.setActive((Boolean)object.get("active"));
+ }
+ if(object.get("defaultSelected")!=null) {
+ configuration.setDefaultSelected((Boolean)object.get("defaultSelected"));
+ }
+ if(object.get("environment")!=null) {
+ configuration.setEnvironment((String)object.get("environment"));
+ }
+ configuration.setModuleCode(moduleCode);
+
+ modules.put(moduleCode, configuration);
+
+ if(object.get("integrationKeys")!=null) {
+ Map<String,String> confs = (Map<String,String> )object.get("integrationKeys");
+ configuration.setIntegrationKeys(confs);
+ }
+
+ if(object.get("integrationKeys")!=null) {
+ Map<String,List<String>> options = (Map<String,List<String>> )object.get("integrationOptions");
+ configuration.setIntegrationOptions(options);
+ }
+
+
+ }
+
+ return modules;
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+
+
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/utils/reference/IntegrationModulesLoader.java b/sm-core/src/main/java/com/salesmanager/core/utils/reference/IntegrationModulesLoader.java
new file mode 100755
index 0000000..48ef1ff
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/utils/reference/IntegrationModulesLoader.java
@@ -0,0 +1,190 @@
+package com.salesmanager.core.utils.reference;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+import com.salesmanager.core.business.system.model.ModuleConfig;
+
+@Component
+public class IntegrationModulesLoader {
+
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(IntegrationModulesLoader.class);
+
+
+ public List<IntegrationModule> loadIntegrationModules(String jsonFilePath) throws Exception {
+
+
+ List<IntegrationModule> modules = new ArrayList<IntegrationModule>();
+
+ ObjectMapper mapper = new ObjectMapper();
+
+ try {
+
+ InputStream in =
+ this.getClass().getClassLoader().getResourceAsStream(jsonFilePath);
+
+
+ @SuppressWarnings("rawtypes")
+ Map[] objects = mapper.readValue(in, Map[].class);
+
+ for(int i = 0; i < objects.length; i++) {
+
+ modules.add(this.loadModule(objects[i]));
+ }
+
+ return modules;
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+
+
+
+
+
+
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ public IntegrationModule loadModule(Map object) throws Exception {
+
+ ObjectMapper mapper = new ObjectMapper();
+ IntegrationModule module = new IntegrationModule();
+ module.setModule((String)object.get("module"));
+ module.setCode((String)object.get("code"));
+ module.setImage((String)object.get("image"));
+
+ if(object.get("type")!=null) {
+ module.setType((String)object.get("type"));
+ }
+
+ if(object.get("customModule")!=null) {
+ Object o = object.get("customModule");
+ Boolean b = false;
+ if(o instanceof Boolean) {
+ b = (Boolean)object.get("customModule");
+ } else {
+ try {
+ b = new Boolean((String)object.get("customModule"));
+ } catch(Exception e) {
+ LOGGER.error("Cannot cast " + o.getClass() + " tp a boolean value");
+ }
+ }
+ module.setCustomModule(b);
+ }
+ //module.setRegions(regions)
+ if(object.get("details")!=null) {
+
+ Map<String,String> details = (Map<String,String>)object.get("details");
+ module.setDetails(details);
+
+ //maintain the original json structure
+ StringBuilder detailsStructure = new StringBuilder();
+ int count = 0;
+ detailsStructure.append("{");
+ for(String key : details.keySet()) {
+ String jsonKeyString = mapper.writeValueAsString(key);
+ detailsStructure.append(jsonKeyString);
+ detailsStructure.append(":");
+ String jsonValueString = mapper.writeValueAsString(details.get(key));
+ detailsStructure.append(jsonValueString);
+ if(count<(details.size()-1)) {
+ detailsStructure.append(",");
+ }
+ count++;
+ }
+ detailsStructure.append("}");
+ module.setConfigDetails(detailsStructure.toString());
+
+ }
+
+
+ List confs = (List)object.get("configuration");
+
+ //convert to json
+
+
+
+ if(confs!=null) {
+ StringBuilder configString = new StringBuilder();
+ configString.append("[");
+ Map<String,ModuleConfig> moduleConfigs = new HashMap<String,ModuleConfig>();
+ int count=0;
+ for(Object oo : confs) {
+
+ Map values = (Map)oo;
+
+ String env = (String)values.get("env");
+
+ ModuleConfig config = new ModuleConfig();
+ config.setScheme((String)values.get("scheme"));
+ config.setHost((String)values.get("host"));
+ config.setPort((String)values.get("port"));
+ config.setUri((String)values.get("uri"));
+ config.setEnv((String)values.get("env"));
+ if((String)values.get("config1")!=null) {
+ config.setConfig1((String)values.get("config1"));
+ }
+ if((String)values.get("config2")!=null) {
+ config.setConfig2((String)values.get("config2"));
+ }
+
+ String jsonConfigString = mapper.writeValueAsString(config);
+ configString.append(jsonConfigString);
+
+ moduleConfigs.put(env, config);
+
+ if(count<(confs.size()-1)) {
+ configString.append(",");
+ }
+ count++;
+
+
+ }
+ configString.append("]");
+ module.setConfiguration(configString.toString());
+ module.setModuleConfigs(moduleConfigs);
+ }
+
+ List<String> regions = (List<String>)object.get("regions");
+ if(regions!=null) {
+
+
+ StringBuilder configString = new StringBuilder();
+ configString.append("[");
+ int count=0;
+ for(String region : regions) {
+
+ module.getRegionsSet().add(region);
+ String jsonConfigString = mapper.writeValueAsString(region);
+ configString.append(jsonConfigString);
+
+ if(count<(regions.size()-1)) {
+ configString.append(",");
+ }
+ count++;
+
+ }
+ configString.append("]");
+ module.setRegions(configString.toString());
+
+ }
+
+ return module;
+
+
+ }
+
+}
diff --git a/sm-core/src/main/java/com/salesmanager/core/utils/reference/ZonesLoader.java b/sm-core/src/main/java/com/salesmanager/core/utils/reference/ZonesLoader.java
new file mode 100755
index 0000000..6df0953
--- /dev/null
+++ b/sm-core/src/main/java/com/salesmanager/core/utils/reference/ZonesLoader.java
@@ -0,0 +1,142 @@
+package com.salesmanager.core.utils.reference;
+
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.country.service.CountryService;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.language.service.LanguageService;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.core.business.reference.zone.model.ZoneDescription;
+
+@Component
+public class ZonesLoader {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(ZonesLoader.class);
+
+ @Autowired
+ private LanguageService languageService;
+
+ @Autowired
+ private CountryService countryService;
+
+ public Map<String, Zone> loadZones(String jsonFilePath) throws Exception {
+
+
+
+List<Language> languages = languageService.list();
+
+ List<Country> countries = countryService.list();
+ Map<String,Country> countriesMap = new HashMap<String,Country>();
+ for(Country country : countries) {
+
+ countriesMap.put(country.getIsoCode(), country);
+
+ }
+
+ ObjectMapper mapper = new ObjectMapper();
+
+ try {
+
+ InputStream in =
+ this.getClass().getClassLoader().getResourceAsStream(jsonFilePath);
+
+ @SuppressWarnings("unchecked")
+ Map<String,Object> data = mapper.readValue(in, Map.class);
+
+ Map<String,Zone> zonesMap = new HashMap<String,Zone>();
+ Map<String,List<ZoneDescription>> zonesDescriptionsMap = new HashMap<String,List<ZoneDescription>>();
+ Map<String,String> zonesMark = new HashMap<String,String>();
+
+ for(Language l : languages) {
+ @SuppressWarnings("rawtypes")
+ List langList = (List)data.get(l.getCode());
+ if(langList!=null) {
+ for(Object z : langList) {
+ @SuppressWarnings("unchecked")
+ Map<String,String> e = (Map<String,String>)z;
+ String zoneCode = e.get("zoneCode");
+ ZoneDescription zoneDescription = new ZoneDescription();
+ zoneDescription.setLanguage(l);
+ zoneDescription.setName(e.get("zoneName"));
+ Zone zone = null;
+ List<ZoneDescription> descriptions = null;
+ if(!zonesMap.containsKey(zoneCode)) {
+ zone = new Zone();
+ Country country = countriesMap.get(e.get("countryCode"));
+ if(country==null) {
+ LOGGER.warn("Country is null for " + zoneCode + " and country code " + e.get("countryCode"));
+ continue;
+ }
+ zone.setCountry(country);
+ zonesMap.put(zoneCode, zone);
+ zone.setCode(zoneCode);
+
+ }
+
+
+ if(zonesMark.containsKey(l.getCode() + "_" + zoneCode)) {
+ LOGGER.warn("This zone seems to be a duplicate ! " + zoneCode + " and language code " + l.getCode());
+ continue;
+ }
+
+ zonesMark.put(l.getCode() + "_" + zoneCode, l.getCode() + "_" + zoneCode);
+
+ if(zonesDescriptionsMap.containsKey(zoneCode)) {
+ descriptions = zonesDescriptionsMap.get(zoneCode);
+ } else {
+ descriptions = new ArrayList<ZoneDescription>();
+ zonesDescriptionsMap.put(zoneCode, descriptions);
+ }
+
+ descriptions.add(zoneDescription);
+
+ }
+ }
+
+ }
+
+
+ for (Map.Entry<String, Zone> entry : zonesMap.entrySet()) {
+ String key = entry.getKey();
+ Zone value = entry.getValue();
+
+ //if(value.getDescriptions()==null) {
+ // LOGGER.warn("This zone " + key + " has no descriptions");
+ // continue;
+ //}
+
+ //get descriptions
+ List<ZoneDescription> descriptions = zonesDescriptionsMap.get(key);
+ if(descriptions!=null) {
+ value.setDescriptons(descriptions);
+ }
+ }
+
+ return zonesMap;
+
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ }
+
+
+
+
+
+
+
+ }
+
+}
diff --git a/sm-core/src/main/resources/cms/infinispan_configuration.xml b/sm-core/src/main/resources/cms/infinispan_configuration.xml
new file mode 100755
index 0000000..c3f4cd0
--- /dev/null
+++ b/sm-core/src/main/resources/cms/infinispan_configuration.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<infinispan xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+
+ xsi:schemaLocation="urn:infinispan:config:5.1 http://www.infinispan.org/schemas/infinispan-config-5.1.xsd"
+
+ xmlns="urn:infinispan:config:5.1">
+
+ <global>
+
+ <globalJmxStatistics enabled="false" jmxDomain="infinispan"/>
+
+ </global>
+
+ <default />
+
+ <namedCache name="StoreRepository">
+ <invocationBatching enabled="true"/>
+ <!-- disable jmx in prod -->
+ <jmxStatistics enabled="false"/>
+ <loaders passivation="false" shared="false" preload="false">
+<!-- <loader class="org.infinispan.loaders.jdbc.mixed.JdbcMixedCacheStore"
+ fetchPersistentState="false" ignoreModifications="false"
+ purgeOnStartup="false">
+ <properties>
+ <property name="tableNamePrefixForStrings" value="ISPN_MIXED_STR_TABLE" />
+ <property name="tableNamePrefixForBinary" value="ISPN_MIXED_BINARY_TABLE" />
+ <property name="idColumnNameForStrings" value="ID_COLUMN" />
+ <property name="idColumnNameForBinary" value="ID_COLUMN" />
+ <property name="dataColumnNameForStrings" value="DATA_COLUMN" />
+ <property name="dataColumnNameForBinary" value="DATA_COLUMN" />
+ <property name="timestampColumnNameForStrings" value="TIMESTAMP_COLUMN" />
+ <property name="timestampColumnNameForBinary" value="TIMESTAMP_COLUMN" />
+ <property name="timestampColumnTypeForStrings" value="BIGINT" />
+ <property name="timestampColumnTypeForBinary" value="BIGINT" />
+ <property name="connectionFactoryClass"
+ value="org.infinispan.loaders.jdbc.connectionfactory.PooledConnectionFactory" />
+ <property name="connectionUrl"
+ value="jdbc:mysql://localhost:3306/salesmanager_cms" />
+ <property name="userName" value="username" />
+ <property name="password" value="password" />
+ <property name="driverClass" value="com.mysql.jdbc.Driver" />
+ <property name="idColumnTypeForStrings" value="VARCHAR(255)" />
+ <property name="idColumnTypeForBinary" value="VARCHAR(255)" />
+ <property name="dataColumnTypeForStrings" value="LONGBLOB" />
+ <property name="dataColumnTypeForBinary" value="LONGBLOB" />
+ <property name="dropTableOnExitForStrings" value="false" />
+ <property name="dropTableOnExitForBinary" value="false" />
+ <property name="createTableOnStartForStrings" value="true" />
+ <property name="createTableOnStartForBinary" value="true" />
+ <property name="createTableOnStartForStrings" value="true" />
+ <property name="createTableOnStartForBinary" value="true" />
+ </properties>
+ </loader> -->
+
+
+
+ <loader class="org.infinispan.loaders.file.FileCacheStore" fetchPersistentState="false"
+ ignoreModifications="false" purgeOnStartup="false">
+ <properties>
+ <property name="location" value="./infinispan/store"/>
+ </properties>
+ </loader>
+
+
+ </loaders>
+
+ <eviction maxEntries="10" strategy="LRU"/>
+
+ <transaction
+ transactionManagerLookupClass="org.infinispan.transaction.lookup.DummyTransactionManagerLookup"
+ transactionMode="TRANSACTIONAL" lockingMode="OPTIMISTIC" />
+
+ </namedCache>
+
+ <namedCache name="FilesRepository">
+ <invocationBatching enabled="true"/>
+ <!-- disable jmx in prod -->
+ <jmxStatistics enabled="true"/>
+ <loaders passivation="false" shared="false" preload="false">
+ <loader class="org.infinispan.loaders.file.FileCacheStore" fetchPersistentState="false"
+ ignoreModifications="false" purgeOnStartup="false">
+ <properties>
+ <property name="location" value="./infinispan/files"/>
+ </properties>
+ </loader>
+ </loaders>
+
+ <transaction
+
+ transactionManagerLookupClass="org.infinispan.transaction.lookup.DummyTransactionManagerLookup"
+ transactionMode="TRANSACTIONAL" lockingMode="OPTIMISTIC" />
+
+ </namedCache>
+
+
+
+</infinispan>
+
diff --git a/sm-core/src/main/resources/configs.properties b/sm-core/src/main/resources/configs.properties
new file mode 100644
index 0000000..531c3ef
--- /dev/null
+++ b/sm-core/src/main/resources/configs.properties
@@ -0,0 +1,2 @@
+#Must be 16 digits (replace with your own creation !)
+secretKey=7070200000000007
\ No newline at end of file
diff --git a/sm-core/src/main/resources/ehcache/smcore-ehcache.xml b/sm-core/src/main/resources/ehcache/smcore-ehcache.xml
new file mode 100644
index 0000000..4a78203
--- /dev/null
+++ b/sm-core/src/main/resources/ehcache/smcore-ehcache.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ehcache name="com.shopizer.core.cache"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">
+
+ <defaultCache
+ maxElementsInMemory="10000"
+ eternal="false"
+ timeToIdleSeconds="120"
+ timeToLiveSeconds="120"
+ overflowToDisk="false"
+ diskSpoolBufferSizeMB="30"
+ maxElementsOnDisk="10000000"
+ diskPersistent="false"
+ diskExpiryThreadIntervalSeconds="120"
+ memoryStoreEvictionPolicy="LRU" />
+
+
+ <cache name="com.shopizer.OBJECT_CACHE"
+ maxElementsInMemory="10000"
+ eternal="false"
+ overflowToDisk="false"
+ timeToIdleSeconds="1200"
+ timeToLiveSeconds="1200"
+ memoryStoreEvictionPolicy="LFU" />
+
+</ehcache>
\ No newline at end of file
diff --git a/sm-core/src/main/resources/email.properties b/sm-core/src/main/resources/email.properties
new file mode 100644
index 0000000..60d6551
--- /dev/null
+++ b/sm-core/src/main/resources/email.properties
@@ -0,0 +1,9 @@
+#GMail sample configuration
+#May require a keystore for certificates
+mailSender.protocol=smtps
+mailSender.host=smtp.gmail.com
+mailSender.port=465
+mailSender.username=test@gmail.com
+mailSender.password=test
+mailSender.mail.smtp.auth=true
+mail.smtp.starttls.enable=true
\ No newline at end of file
sm-core/src/main/resources/log4j.properties 13(+13 -0)
diff --git a/sm-core/src/main/resources/log4j.properties b/sm-core/src/main/resources/log4j.properties
new file mode 100644
index 0000000..2f9c9f6
--- /dev/null
+++ b/sm-core/src/main/resources/log4j.properties
@@ -0,0 +1,13 @@
+log4j.appender.Stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.Stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.Stdout.layout.ConversionPattern=[%d{ISO8601}] %-5p - %-26.26c{1} - %m\n
+
+log4j.rootLogger=WARN,Stdout
+
+
+# hibernate queries
+#log4j.logger.org.hibernate.SQL=DEBUG
+#log4j.logger.org.hibernate.type=INFO
+
+# schema initialization
+#log4j.logger.org.hibernate.tool.hbm2ddl=DEBUG
\ No newline at end of file
diff --git a/sm-core/src/main/resources/META-INF/sm-persistence.xml b/sm-core/src/main/resources/META-INF/sm-persistence.xml
new file mode 100644
index 0000000..c96807f
--- /dev/null
+++ b/sm-core/src/main/resources/META-INF/sm-persistence.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
+ version="2.0">
+ <persistence-unit name="sm-unit">
+ <class>com.salesmanager.core.business.merchant.model.MerchantStore</class>
+ <class>com.salesmanager.core.business.reference.country.model.Country</class>
+ <class>com.salesmanager.core.business.reference.country.model.CountryDescription</class>
+ <class>com.salesmanager.core.business.reference.zone.model.Zone</class>
+ <class>com.salesmanager.core.business.reference.zone.model.ZoneDescription</class>
+ <class>com.salesmanager.core.business.reference.language.model.Language</class>
+ <class>com.salesmanager.core.business.reference.currency.model.Currency</class>
+ <class>com.salesmanager.core.business.reference.geozone.model.GeoZone</class>
+ <class>com.salesmanager.core.business.reference.geozone.model.GeoZoneDescription</class>
+
+
+ <class>com.salesmanager.core.business.tax.model.taxclass.TaxClass</class>
+ <class>com.salesmanager.core.business.tax.model.taxrate.TaxRate</class>
+ <class>com.salesmanager.core.business.tax.model.taxrate.TaxRateDescription</class>
+ <class>com.salesmanager.core.business.system.model.SystemConfiguration</class>
+ <class>com.salesmanager.core.business.system.model.IntegrationModule</class>
+ <class>com.salesmanager.core.business.system.model.MerchantConfiguration</class>
+ <class>com.salesmanager.core.business.system.model.SystemNotification</class>
+ <class>com.salesmanager.core.business.system.model.MerchantLog</class>
+
+ <class>com.salesmanager.core.business.order.model.filehistory.FileHistory</class>
+ <class>com.salesmanager.core.business.order.model.orderproduct.OrderProduct</class>
+ <class>com.salesmanager.core.business.order.model.orderproduct.OrderProductAttribute</class>
+ <class>com.salesmanager.core.business.order.model.orderproduct.OrderProductDownload</class>
+ <class>com.salesmanager.core.business.order.model.orderproduct.OrderProductPrice</class>
+ <class>com.salesmanager.core.business.order.model.orderstatus.OrderStatus</class>
+ <class>com.salesmanager.core.business.order.model.orderstatus.OrderStatusHistory</class>
+ <class>com.salesmanager.core.business.order.model.Order</class>
+ <class>com.salesmanager.core.business.order.model.OrderTotal</class>
+
+ <class>com.salesmanager.core.business.customer.model.Customer</class>
+ <class>com.salesmanager.core.business.customer.model.attribute.CustomerAttribute</class>
+ <class>com.salesmanager.core.business.customer.model.attribute.CustomerOption</class>
+ <class>com.salesmanager.core.business.customer.model.attribute.CustomerOptionDescription</class>
+ <class>com.salesmanager.core.business.customer.model.attribute.CustomerOptionValue</class>
+ <class>com.salesmanager.core.business.customer.model.attribute.CustomerOptionSet</class>
+ <class>com.salesmanager.core.business.customer.model.attribute.CustomerOptionValueDescription</class>
+
+ <class>com.salesmanager.core.business.catalog.category.model.Category</class>
+ <class>com.salesmanager.core.business.catalog.category.model.CategoryDescription</class>
+
+ <class>com.salesmanager.core.business.content.model.Content</class>
+ <class>com.salesmanager.core.business.content.model.ContentDescription</class>
+
+ <class>com.salesmanager.core.business.catalog.product.model.Product</class>
+ <class>com.salesmanager.core.business.catalog.product.model.description.ProductDescription</class>
+ <class>com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute</class>
+ <class>com.salesmanager.core.business.catalog.product.model.attribute.ProductOption</class>
+ <class>com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionDescription</class>
+ <class>com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionValue</class>
+ <class>com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionValueDescription</class>
+
+ <class>com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability</class>
+ <class>com.salesmanager.core.business.catalog.product.model.file.DigitalProduct</class>
+ <class>com.salesmanager.core.business.catalog.product.model.image.ProductImage</class>
+ <class>com.salesmanager.core.business.catalog.product.model.image.ProductImageDescription</class>
+ <class>com.salesmanager.core.business.catalog.product.model.manufacturer.Manufacturer</class>
+ <class>com.salesmanager.core.business.catalog.product.model.manufacturer.ManufacturerDescription</class>
+ <class>com.salesmanager.core.business.catalog.product.model.price.ProductPrice</class>
+ <class>com.salesmanager.core.business.catalog.product.model.price.ProductPriceDescription</class>
+
+ <class>com.salesmanager.core.business.catalog.product.model.relationship.ProductRelationship</class>
+ <class>com.salesmanager.core.business.catalog.product.model.review.ProductReview</class>
+ <class>com.salesmanager.core.business.catalog.product.model.review.ProductReviewDescription</class>
+
+ <class>com.salesmanager.core.business.catalog.product.model.type.ProductType</class>
+
+ <class>com.salesmanager.core.business.user.model.User</class>
+ <class>com.salesmanager.core.business.user.model.Group</class>
+ <class>com.salesmanager.core.business.user.model.Permission</class>
+
+ <class>com.salesmanager.core.business.shoppingcart.model.ShoppingCart</class>
+ <class>com.salesmanager.core.business.shoppingcart.model.ShoppingCartAttributeItem</class>
+ <class>com.salesmanager.core.business.shoppingcart.model.ShoppingCartItem</class>
+
+
+ </persistence-unit>
+</persistence>
diff --git a/sm-core/src/main/resources/reference/GeoLite2-Country.mmdb b/sm-core/src/main/resources/reference/GeoLite2-Country.mmdb
new file mode 100644
index 0000000..1a25eb5
Binary files /dev/null and b/sm-core/src/main/resources/reference/GeoLite2-Country.mmdb differ
diff --git a/sm-core/src/main/resources/reference/integrationmodules.json b/sm-core/src/main/resources/reference/integrationmodules.json
new file mode 100755
index 0000000..cffa8e5
--- /dev/null
+++ b/sm-core/src/main/resources/reference/integrationmodules.json
@@ -0,0 +1,60 @@
+[
+ {
+ "module": "SHIPPING",
+ "code": "usps",
+ "version":"",
+ "regions": ["US"],
+ "image":"usps.jpg",
+ "configuration":[{"env":"TEST","scheme":"http","host":"testing.shippingapis.com","port":"80","uri":"/ShippingAPI.dll"},{"env":"PROD","scheme":"http","host":"production.shippingapis.com","port":"80","uri":"/ShippingAPI.dll"}]
+
+ },
+ {
+ "module": "SHIPPING",
+ "code": "ups",
+ "version":"",
+ "regions": ["US","CA","FR","GB"],
+ "image":"ups.jpg",
+ "configuration":[{"env":"TEST","scheme":"https","host":"wwwcie.ups.com","port":"443","uri":"/ups.app/xml/Rate"},{"env":"PROD","scheme":"https","host":"onlinetools.ups.com","port":"443","uri":"/xml/Rate"}],
+ "details":{"01":"UPS Next Day Air","02":"UPS Second Day Air","03":"UPS Ground","07":"UPS Worldwide Express","08":"UPS Worldwide Expedited","11":"UPS Standard","12":"UPS Three-Day Select","13":"UPS Next Day Air Saver","14":"UPS Next Day Air Early A.M.","54":"UPS Worldwide Express Plus","59":"UPS Second Day Air A.M.","69":"UPS Saver"}
+
+ },
+ {
+ "module": "SHIPPING",
+ "code": "weightBased",
+ "customModule":"true",
+ "version":"1.0",
+ "regions": ["*"]
+ },
+ {
+ "module": "PAYMENT",
+ "code": "moneyorder",
+ "type":"moneyorder",
+ "version":"",
+ "regions": ["*"],
+ "image":"moneyorder.gif"
+ },
+ {
+ "module": "PAYMENT",
+ "code": "paypal-express-checkout",
+ "type":"paypal",
+ "version":"104.0",
+ "regions": ["*"],
+ "image":"icon-paypal.png",
+ "configuration":[{"env":"TEST","scheme":"","host":"","port":"","uri":"","config1":"https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token="},{"env":"PROD","scheme":"","host":"","port":"","uri":"","config1":"https://www.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token="}]
+
+ },
+
+
+ {
+ "module": "PAYMENT",
+ "code": "beanstream",
+ "type":"creditcard",
+ "version":"",
+ "regions": ["US","CA","GB"],
+ "image":"beanstream.gif",
+ "configuration":[{"env":"TEST","scheme":"https","host":"www.beanstream.com","port":"443","uri":"/scripts/process_transaction.asp"},{"env":"PROD","scheme":"https","host":"www.beanstream.com","port":"443","uri":"/scripts/process_transaction.asp"}]
+
+ }
+
+]
+
sm-core/src/main/resources/reference/zoneconfig.json 1888(+1888 -0)
diff --git a/sm-core/src/main/resources/reference/zoneconfig.json b/sm-core/src/main/resources/reference/zoneconfig.json
new file mode 100644
index 0000000..3350c43
--- /dev/null
+++ b/sm-core/src/main/resources/reference/zoneconfig.json
@@ -0,0 +1,1888 @@
+{
+ "en":[
+ {
+ "zoneCode": "AL",
+ "zoneName": "Alabama",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AK",
+ "zoneName": "Alaska",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AS",
+ "zoneName": "American Samoa",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AZ",
+ "zoneName": "Arizona",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AR",
+ "zoneName": "Arkansas",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AF",
+ "zoneName": "Armed Forces Africa",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AA",
+ "zoneName": "Armed Forces Americas",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AC",
+ "zoneName": "Armed Forces Canada",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AE",
+ "zoneName": "Armed Forces Europe",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AM",
+ "zoneName": "Armed Forces Middle East",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AP",
+ "zoneName": "Armed Forces Pacific",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "CA",
+ "zoneName": "California",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "CO",
+ "zoneName": "Colorado",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "CT",
+ "zoneName": "Connecticut",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "DE",
+ "zoneName": "Delaware",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "DC",
+ "zoneName": "District of Columbia",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "FM",
+ "zoneName": "Federated States Of Micronesia",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "FL",
+ "zoneName": "Florida",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "GA",
+ "zoneName": "Georgia",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "GU",
+ "zoneName": "Guam",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "HI",
+ "zoneName": "Hawaii",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "ID",
+ "zoneName": "Idaho",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "IL",
+ "zoneName": "Illinois",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "IN",
+ "zoneName": "Indiana",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "IA",
+ "zoneName": "Iowa",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "KS",
+ "zoneName": "Kansas",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "KY",
+ "zoneName": "Kentucky",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "LA",
+ "zoneName": "Louisiana",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "ME",
+ "zoneName": "Maine",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "MH",
+ "zoneName": "Marshall Islands",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "MD",
+ "zoneName": "Maryland",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "MA",
+ "zoneName": "Massachusetts",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "MI",
+ "zoneName": "Michigan",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "MN",
+ "zoneName": "Minnesota",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "MS",
+ "zoneName": "Mississippi",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "MO",
+ "zoneName": "Missouri",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "MT",
+ "zoneName": "Montana",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "NE",
+ "zoneName": "Nebraska",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "NV",
+ "zoneName": "Nevada",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "NH",
+ "zoneName": "New Hampshire",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "NJ",
+ "zoneName": "New Jersey",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "NM",
+ "zoneName": "New Mexico",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "NY",
+ "zoneName": "New York",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "NC",
+ "zoneName": "North Carolina",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "ND",
+ "zoneName": "North Dakota",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "MP",
+ "zoneName": "Northern Mariana Islands",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "OH",
+ "zoneName": "Ohio",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "OK",
+ "zoneName": "Oklahoma",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "OR",
+ "zoneName": "Oregon",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "PA",
+ "zoneName": "Pennsylvania",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "PR",
+ "zoneName": "Puerto Rico",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "RI",
+ "zoneName": "Rhode Island",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "SC",
+ "zoneName": "South Carolina",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "SD",
+ "zoneName": "South Dakota",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "TN",
+ "zoneName": "Tennessee",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "TX",
+ "zoneName": "Texas",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "UT",
+ "zoneName": "Utah",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "VT",
+ "zoneName": "Vermont",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "VI",
+ "zoneName": "Virgin Islands",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "VA",
+ "zoneName": "Virginia",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "WA",
+ "zoneName": "Washington",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "WV",
+ "zoneName": "West Virginia",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "WI",
+ "zoneName": "Wisconsin",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "WY",
+ "zoneName": "Wyoming",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AB",
+ "zoneName": "Alberta",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "BC",
+ "zoneName": "British Columbia",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "MB",
+ "zoneName": "Manitoba",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "NF",
+ "zoneName": "Newfoundland - Labrador",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "NB",
+ "zoneName": "New Brunswick",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "NS",
+ "zoneName": "Nova Scotia",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "NT",
+ "zoneName": "Northwest Territories",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "NU",
+ "zoneName": "Nunavut",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "ON",
+ "zoneName": "Ontario",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "PE",
+ "zoneName": "Prince Edward Island",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "QC",
+ "zoneName": "Quebec",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "SK",
+ "zoneName": "Saskatchewan",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "YT",
+ "zoneName": "Yukon Territory",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "NDS",
+ "zoneName": "Niedersachsen",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "BAW",
+ "zoneName": "Baden-Wrttemberg",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "BAY",
+ "zoneName": "Bayern",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "BER",
+ "zoneName": "Berlin",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "BRG",
+ "zoneName": "Brandenburg",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "BRE",
+ "zoneName": "Bremen",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "HAM",
+ "zoneName": "Hamburg",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "HES",
+ "zoneName": "Hessen",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "MEC",
+ "zoneName": "Mecklenburg-Vorpommern",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "NRW",
+ "zoneName": "Nordrhein-Westfalen",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "RHE",
+ "zoneName": "Rheinland-Pfalz",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "SAR",
+ "zoneName": "Saarland",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "SAS",
+ "zoneName": "Sachsen",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "SAC",
+ "zoneName": "Sachsen-Anhalt",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "SCN",
+ "zoneName": "Schleswig-Holstein",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "THE",
+ "zoneName": "Thringen",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "WIAT",
+ "zoneName": "Wien",
+ "countryCode": "AT"
+ },
+ {
+ "zoneCode": "NO",
+ "zoneName": "Niederosterreich",
+ "countryCode": "AT"
+ },
+ {
+ "zoneCode": "OO",
+ "zoneName": "Oberosterreich",
+ "countryCode": "AT"
+ },
+ {
+ "zoneCode": "SB",
+ "zoneName": "Salzburg",
+ "countryCode": "AT"
+ },
+ {
+ "zoneCode": "KN",
+ "zoneName": "Katen",
+ "countryCode": "AT"
+ },
+ {
+ "zoneCode": "ST",
+ "zoneName": "Steiermark",
+ "countryCode": "AT"
+ },
+ {
+ "zoneCode": "TIAT",
+ "zoneName": "Tirol",
+ "countryCode": "AT"
+ },
+ {
+ "zoneCode": "BLAT",
+ "zoneName": "Burgenland",
+ "countryCode": "AT"
+ },
+ {
+ "zoneCode": "VB",
+ "zoneName": "Voralberg",
+ "countryCode": "AT"
+ },
+ {
+ "zoneCode": "AG",
+ "zoneName": "Aargau",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "AI",
+ "zoneName": "Appenzell Innerrhoden",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "ARCH",
+ "zoneName": "Appenzell Ausserrhoden",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "BE",
+ "zoneName": "Bern",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "BL",
+ "zoneName": "Basel-Landschaft",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "BS",
+ "zoneName": "Basel-Stadt",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "FR",
+ "zoneName": "Freiburg",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "GE",
+ "zoneName": "Genf",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "GL",
+ "zoneName": "Glarus",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "GR",
+ "zoneName": "Graubnden",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "JU",
+ "zoneName": "Jura",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "LU",
+ "zoneName": "Luzern",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "NECH",
+ "zoneName": "Neuenburg",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "NW",
+ "zoneName": "Nidwalden",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "OW",
+ "zoneName": "Obwalden",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "SG",
+ "zoneName": "St. Gallen",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "SH",
+ "zoneName": "Schaffhausen",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "SO",
+ "zoneName": "Solothurn",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "SZ",
+ "zoneName": "Schwyz",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "TG",
+ "zoneName": "Thurgau",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "TI",
+ "zoneName": "Tessin",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "UR",
+ "zoneName": "Uri",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "VD",
+ "zoneName": "Waadt",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "VS",
+ "zoneName": "Wallis",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "ZG",
+ "zoneName": "Zug",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "ZH",
+ "zoneName": "Zrich",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "ACorua",
+ "zoneName": "A Corua",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Alava",
+ "zoneName": "Alava",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Albacete",
+ "zoneName": "Albacete",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Alicante",
+ "zoneName": "Alicante",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Almeria",
+ "zoneName": "Almeria",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Asturias",
+ "zoneName": "Asturias",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Avila",
+ "zoneName": "Avila",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Badajoz",
+ "zoneName": "Badajoz",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Baleares",
+ "zoneName": "Baleares",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Barcelona",
+ "zoneName": "Barcelona",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Burgos",
+ "zoneName": "Burgos",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Caceres",
+ "zoneName": "Caceres",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Cadiz",
+ "zoneName": "Cadiz",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Cantabria",
+ "zoneName": "Cantabria",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Castellon",
+ "zoneName": "Castellon",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Ceuta",
+ "zoneName": "Ceuta",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "CiudadReal",
+ "zoneName": "Ciudad Real",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Cordoba",
+ "zoneName": "Cordoba",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Cuenca",
+ "zoneName": "Cuenca",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Girona",
+ "zoneName": "Girona",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Granada",
+ "zoneName": "Granada",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Guadalajara",
+ "zoneName": "Guadalajara",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Guipuzcoa",
+ "zoneName": "Guipuzcoa",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Huelva",
+ "zoneName": "Huelva",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Huesca",
+ "zoneName": "Huesca",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Jaen",
+ "zoneName": "Jaen",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "LaRioja",
+ "zoneName": "La Rioja",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "LasPalmas",
+ "zoneName": "Las Palmas",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Leon",
+ "zoneName": "Leon",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Lleida",
+ "zoneName": "Lleida",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Lugo",
+ "zoneName": "Lugo",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Madrid",
+ "zoneName": "Madrid",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Malaga",
+ "zoneName": "Malaga",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Melilla",
+ "zoneName": "Melilla",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Murcia",
+ "zoneName": "Murcia",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Navarra",
+ "zoneName": "Navarra",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Ourense",
+ "zoneName": "Ourense",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Palencia",
+ "zoneName": "Palencia",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Pontevedra",
+ "zoneName": "Pontevedra",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Salamanca",
+ "zoneName": "Salamanca",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "SantaCruzdeTenerife",
+ "zoneName": "Santa Cruz de Tenerife",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Segovia",
+ "zoneName": "Segovia",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Sevilla",
+ "zoneName": "Sevilla",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Soria",
+ "zoneName": "Soria",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Tarragona",
+ "zoneName": "Tarragona",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Teruel",
+ "zoneName": "Teruel",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Toledo",
+ "zoneName": "Toledo",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Valencia",
+ "zoneName": "Valencia",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Valladolid",
+ "zoneName": "Valladolid",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Vizcaya",
+ "zoneName": "Vizcaya",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Zamora",
+ "zoneName": "Zamora",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Zaragoza",
+ "zoneName": "Zaragoza",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "ACT",
+ "zoneName": "Australian Capital Territory",
+ "countryCode": "AU"
+ },
+ {
+ "zoneCode": "NSW",
+ "zoneName": "New South Wales",
+ "countryCode": "AU"
+ },
+ {
+ "zoneCode": "NTAU",
+ "zoneName": "Northern Territory",
+ "countryCode": "AU"
+ },
+ {
+ "zoneCode": "QLD",
+ "zoneName": "Queensland",
+ "countryCode": "AU"
+ },
+ {
+ "zoneCode": "SA",
+ "zoneName": "South Australia",
+ "countryCode": "AU"
+ },
+ {
+ "zoneCode": "TAS",
+ "zoneName": "Tasmania",
+ "countryCode": "AU"
+ },
+ {
+ "zoneCode": "VIC",
+ "zoneName": "Victoria",
+ "countryCode": "AU"
+ },
+ {
+ "zoneCode": "WAAU",
+ "zoneName": "Western Australia",
+ "countryCode": "AU"
+ }
+] ,
+
+ "fr":[
+ {
+ "zoneCode": "AL",
+ "zoneName": "Alabama",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AK",
+ "zoneName": "Alaska",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AS",
+ "zoneName": "American Samoa",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AZ",
+ "zoneName": "Arizona",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AR",
+ "zoneName": "Arkansas",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AF",
+ "zoneName": "Armed Forces Africa",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AA",
+ "zoneName": "Armed Forces Americas",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AC",
+ "zoneName": "Armed Forces Canada",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AE",
+ "zoneName": "Armed Forces Europe",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AM",
+ "zoneName": "Armed Forces Middle East",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AP",
+ "zoneName": "Armed Forces Pacific",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "CA",
+ "zoneName": "California",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "CO",
+ "zoneName": "Colorado",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "CT",
+ "zoneName": "Connecticut",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "DE",
+ "zoneName": "Delaware",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "DC",
+ "zoneName": "District of Columbia",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "FM",
+ "zoneName": "Federated States Of Micronesia",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "FL",
+ "zoneName": "Florida",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "GA",
+ "zoneName": "Georgia",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "GU",
+ "zoneName": "Guam",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "HI",
+ "zoneName": "Hawaii",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "ID",
+ "zoneName": "Idaho",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "IL",
+ "zoneName": "Illinois",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "IN",
+ "zoneName": "Indiana",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "IA",
+ "zoneName": "Iowa",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "KS",
+ "zoneName": "Kansas",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "KY",
+ "zoneName": "Kentucky",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "LA",
+ "zoneName": "Louisiana",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "ME",
+ "zoneName": "Maine",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "MH",
+ "zoneName": "Marshall Islands",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "MD",
+ "zoneName": "Maryland",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "MA",
+ "zoneName": "Massachusetts",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "MI",
+ "zoneName": "Michigan",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "MN",
+ "zoneName": "Minnesota",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "MS",
+ "zoneName": "Mississippi",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "MO",
+ "zoneName": "Missouri",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "MT",
+ "zoneName": "Montana",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "NE",
+ "zoneName": "Nebraska",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "NV",
+ "zoneName": "Nevada",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "NH",
+ "zoneName": "New Hampshire",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "NJ",
+ "zoneName": "New Jersey",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "NM",
+ "zoneName": "New Mexico",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "NY",
+ "zoneName": "New York",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "NC",
+ "zoneName": "North Carolina",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "ND",
+ "zoneName": "North Dakota",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "MP",
+ "zoneName": "Northern Mariana Islands",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "OH",
+ "zoneName": "Ohio",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "OK",
+ "zoneName": "Oklahoma",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "OR",
+ "zoneName": "Oregon",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "PA",
+ "zoneName": "Pennsylvania",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "PR",
+ "zoneName": "Puerto Rico",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "RI",
+ "zoneName": "Rhode Island",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "SC",
+ "zoneName": "South Carolina",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "SD",
+ "zoneName": "South Dakota",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "TN",
+ "zoneName": "Tennessee",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "TX",
+ "zoneName": "Texas",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "UT",
+ "zoneName": "Utah",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "VT",
+ "zoneName": "Vermont",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "VI",
+ "zoneName": "Virgin Islands",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "VA",
+ "zoneName": "Virginia",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "WA",
+ "zoneName": "Washington",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "WV",
+ "zoneName": "West Virginia",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "WI",
+ "zoneName": "Wisconsin",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "WY",
+ "zoneName": "Wyoming",
+ "countryCode": "US"
+ },
+ {
+ "zoneCode": "AB",
+ "zoneName": "Alberta",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "BC",
+ "zoneName": "British Columbia",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "MB",
+ "zoneName": "Manitoba",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "NF",
+ "zoneName": "Newfoundland - Labrador",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "NB",
+ "zoneName": "New Brunswick",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "NS",
+ "zoneName": "Nova Scotia",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "NT",
+ "zoneName": "Northwest Territories",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "NU",
+ "zoneName": "Nunavut",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "ON",
+ "zoneName": "Ontario",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "PE",
+ "zoneName": "Prince Edward Island",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "QC",
+ "zoneName": "Quebec",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "SK",
+ "zoneName": "Saskatchewan",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "YT",
+ "zoneName": "Yukon Territory",
+ "countryCode": "CA"
+ },
+ {
+ "zoneCode": "NDS",
+ "zoneName": "Niedersachsen",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "BAW",
+ "zoneName": "Baden-Wrttemberg",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "BAY",
+ "zoneName": "Bayern",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "BER",
+ "zoneName": "Berlin",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "BRG",
+ "zoneName": "Brandenburg",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "BRE",
+ "zoneName": "Bremen",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "HAM",
+ "zoneName": "Hamburg",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "HES",
+ "zoneName": "Hessen",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "MEC",
+ "zoneName": "Mecklenburg-Vorpommern",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "NRW",
+ "zoneName": "Nordrhein-Westfalen",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "RHE",
+ "zoneName": "Rheinland-Pfalz",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "SAR",
+ "zoneName": "Saarland",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "SAS",
+ "zoneName": "Sachsen",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "SAC",
+ "zoneName": "Sachsen-Anhalt",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "SCN",
+ "zoneName": "Schleswig-Holstein",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "THE",
+ "zoneName": "Thringen",
+ "countryCode": "DE"
+ },
+ {
+ "zoneCode": "WIAT",
+ "zoneName": "Wien",
+ "countryCode": "AT"
+ },
+ {
+ "zoneCode": "NO",
+ "zoneName": "Niederosterreich",
+ "countryCode": "AT"
+ },
+ {
+ "zoneCode": "OO",
+ "zoneName": "Oberosterreich",
+ "countryCode": "AT"
+ },
+ {
+ "zoneCode": "SB",
+ "zoneName": "Salzburg",
+ "countryCode": "AT"
+ },
+ {
+ "zoneCode": "KN",
+ "zoneName": "Karten",
+ "countryCode": "AT"
+ },
+ {
+ "zoneCode": "ST",
+ "zoneName": "Steiermark",
+ "countryCode": "AT"
+ },
+ {
+ "zoneCode": "TIAT",
+ "zoneName": "Tirol",
+ "countryCode": "AT"
+ },
+ {
+ "zoneCode": "BLAT",
+ "zoneName": "Burgenland",
+ "countryCode": "AT"
+ },
+ {
+ "zoneCode": "VB",
+ "zoneName": "Voralberg",
+ "countryCode": "AT"
+ },
+ {
+ "zoneCode": "AG",
+ "zoneName": "Aargau",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "AI",
+ "zoneName": "Appenzell Innerrhoden",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "ARCH",
+ "zoneName": "Appenzell Ausserrhoden",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "BE",
+ "zoneName": "Bern",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "BL",
+ "zoneName": "Basel-Landschaft",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "BS",
+ "zoneName": "Basel-Stadt",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "FR",
+ "zoneName": "Freiburg",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "GE",
+ "zoneName": "Genf",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "GL",
+ "zoneName": "Glarus",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "GR",
+ "zoneName": "Graubnden",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "JU",
+ "zoneName": "Jura",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "LU",
+ "zoneName": "Luzern",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "NECH",
+ "zoneName": "Neuenburg",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "NW",
+ "zoneName": "Nidwalden",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "OW",
+ "zoneName": "Obwalden",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "SG",
+ "zoneName": "St. Gallen",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "SH",
+ "zoneName": "Schaffhausen",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "SO",
+ "zoneName": "Solothurn",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "SZ",
+ "zoneName": "Schwyz",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "TG",
+ "zoneName": "Thurgau",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "TI",
+ "zoneName": "Tessin",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "UR",
+ "zoneName": "Uri",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "VD",
+ "zoneName": "Waadt",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "VS",
+ "zoneName": "Wallis",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "ZG",
+ "zoneName": "Zug",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "ZH",
+ "zoneName": "Zrich",
+ "countryCode": "CH"
+ },
+ {
+ "zoneCode": "A Corua",
+ "zoneName": "A Corua",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Alava",
+ "zoneName": "Alava",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Albacete",
+ "zoneName": "Albacete",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Alicante",
+ "zoneName": "Alicante",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Almeria",
+ "zoneName": "Almeria",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Asturias",
+ "zoneName": "Asturias",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Avila",
+ "zoneName": "Avila",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Badajoz",
+ "zoneName": "Badajoz",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Baleares",
+ "zoneName": "Baleares",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Barcelona",
+ "zoneName": "Barcelona",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Burgos",
+ "zoneName": "Burgos",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Caceres",
+ "zoneName": "Caceres",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Cadiz",
+ "zoneName": "Cadiz",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Cantabria",
+ "zoneName": "Cantabria",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Castellon",
+ "zoneName": "Castellon",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Ceuta",
+ "zoneName": "Ceuta",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "CiudadReal",
+ "zoneName": "Ciudad Real",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Cordoba",
+ "zoneName": "Cordoba",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Cuenca",
+ "zoneName": "Cuenca",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Girona",
+ "zoneName": "Girona",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Granada",
+ "zoneName": "Granada",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Guadalajara",
+ "zoneName": "Guadalajara",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Guipuzcoa",
+ "zoneName": "Guipuzcoa",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Huelva",
+ "zoneName": "Huelva",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Huesca",
+ "zoneName": "Huesca",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Jaen",
+ "zoneName": "Jaen",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "LaRioja",
+ "zoneName": "La Rioja",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "LasPalmas",
+ "zoneName": "Las Palmas",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Leon",
+ "zoneName": "Leon",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Lleida",
+ "zoneName": "Lleida",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Lugo",
+ "zoneName": "Lugo",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Madrid",
+ "zoneName": "Madrid",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Malaga",
+ "zoneName": "Malaga",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Melilla",
+ "zoneName": "Melilla",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Murcia",
+ "zoneName": "Murcia",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Navarra",
+ "zoneName": "Navarra",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Ourense",
+ "zoneName": "Ourense",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Palencia",
+ "zoneName": "Palencia",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Pontevedra",
+ "zoneName": "Pontevedra",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Salamanca",
+ "zoneName": "Salamanca",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "SantaCruzdeTenerife",
+ "zoneName": "Santa Cruz de Tenerife",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Segovia",
+ "zoneName": "Segovia",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Sevilla",
+ "zoneName": "Sevilla",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Soria",
+ "zoneName": "Soria",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Tarragona",
+ "zoneName": "Tarragona",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Teruel",
+ "zoneName": "Teruel",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Toledo",
+ "zoneName": "Toledo",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Valencia",
+ "zoneName": "Valencia",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Valladolid",
+ "zoneName": "Valladolid",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Vizcaya",
+ "zoneName": "Vizcaya",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Zamora",
+ "zoneName": "Zamora",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode": "Zaragoza",
+ "zoneName": "Zaragoza",
+ "countryCode": "ES"
+ },
+ {
+ "zoneCode":"ACT",
+ "zoneName":"Territoire de la capitale australienne",
+ "countryCode":"AU"
+ },
+ {
+ "zoneCode":"WAAU",
+ "zoneName":"Australie-Occidentale",
+ "countryCode":"AU"
+ },
+ {
+ "zoneCode":"SA",
+ "zoneName":"Australie-Mridionale",
+ "countryCode":"AU"
+ },
+ {
+ "zoneCode":"NTAU",
+ "zoneName":"Territoire du Nord",
+ "countryCode":"AU"
+ },
+ {
+ "zoneCode":"VIC",
+ "zoneName":"Victoria",
+ "countryCode":"AU"
+ },
+ {
+ "zoneCode":"TAS",
+ "zoneName":"Tasmanie",
+ "countryCode":"AU"
+ },
+ {
+ "zoneCode":"QLD",
+ "zoneName":"Queensland",
+ "countryCode":"AU"
+ },
+ {
+ "zoneCode":"NSW",
+ "zoneName":"Nouvelle-Galles du Sud",
+ "countryCode":"AU"
+ }
+
+]
+}
\ No newline at end of file
diff --git a/sm-core/src/main/resources/search/product.json b/sm-core/src/main/resources/search/product.json
new file mode 100755
index 0000000..0b2704a
--- /dev/null
+++ b/sm-core/src/main/resources/search/product.json
@@ -0,0 +1,15 @@
+{"product_en": {
+ "properties" : {
+ "name": {"type": "multi_field","fields": {"name_original":{"type":"string","index":"not_analyzed"},"name_searchable":{"type":"string","index":"analyzed","store":"no"}}},
+ "price" : {"type":"string","index":"not_analyzed"},
+ "categories" : {"type":"string","index":"not_analyzed"},
+ "lang" : {"type":"string","index":"not_analyzed"},
+ "store" : {"type":"string","index":"not_analyzed"},
+ "availability" : {"type":"string","index":"not_analyzed"},
+ "manufacturer" : {"type":"string","index":"not_analyzed"},
+ "available" : {"type":"string","index":"not_analyzed"},
+ "description" : {"type":"string","index":"analyzed","index_analyzer":"english"},
+ "tags" : {"type":"string","index":"not_analyzed"}
+ }
+ }
+}
\ No newline at end of file
diff --git a/sm-core/src/main/resources/search/product_fr.json b/sm-core/src/main/resources/search/product_fr.json
new file mode 100644
index 0000000..c7171b4
--- /dev/null
+++ b/sm-core/src/main/resources/search/product_fr.json
@@ -0,0 +1,15 @@
+{"product_fr": {
+ "properties" : {
+ "name": {"type": "multi_field","fields": {"name_original":{"type":"string","index":"not_analyzed"},"name_searchable":{"type":"string","index":"analyzed","store":"no"}}},
+ "price" : {"type":"string","index":"not_analyzed"},
+ "categories" : {"type":"string","index":"not_analyzed"},
+ "lang" : {"type":"string","index":"not_analyzed"},
+ "store" : {"type":"string","index":"not_analyzed"},
+ "availability" : {"type":"string","index":"not_analyzed"},
+ "manufacturer" : {"type":"string","index":"not_analyzed"},
+ "available" : {"type":"string","index":"not_analyzed"},
+ "description" : {"type":"string","index":"analyzed","index_analyzer":"french"},
+ "tags" : {"type":"string","index":"not_analyzed"}
+ }
+ }
+}
\ No newline at end of file
diff --git a/sm-core/src/main/resources/search/settings_product.json b/sm-core/src/main/resources/search/settings_product.json
new file mode 100644
index 0000000..452a01e
--- /dev/null
+++ b/sm-core/src/main/resources/search/settings_product.json
@@ -0,0 +1,11 @@
+ {"index": {
+ "analysis": {
+ "analyzer": {
+ "custom_analyzer": {
+ "type": "snowball",
+ "language": "English"
+ }
+ }
+ }
+ }
+ }
\ No newline at end of file
diff --git a/sm-core/src/main/resources/search/settings_product_fr.json b/sm-core/src/main/resources/search/settings_product_fr.json
new file mode 100644
index 0000000..452a01e
--- /dev/null
+++ b/sm-core/src/main/resources/search/settings_product_fr.json
@@ -0,0 +1,11 @@
+ {"index": {
+ "analysis": {
+ "analyzer": {
+ "custom_analyzer": {
+ "type": "snowball",
+ "language": "English"
+ }
+ }
+ }
+ }
+ }
\ No newline at end of file
diff --git a/sm-core/src/main/resources/spring/datasource-c3p0.xml b/sm-core/src/main/resources/spring/datasource-c3p0.xml
new file mode 100644
index 0000000..89d2af9
--- /dev/null
+++ b/sm-core/src/main/resources/spring/datasource-c3p0.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
+
+ <bean id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
+ p:driverClass="${db.driverClass}" p:jdbcUrl="${db.jdbcUrl}" p:user="${db.user}"
+ p:password="${db.password}" p:initialPoolSize="${db.initialPoolSize}"
+ p:minPoolSize="${db.minPoolSize}" p:maxPoolSize="${db.maxPoolSize}"
+ p:preferredTestQuery="${db.preferredTestQuery}" p:testConnectionOnCheckin="true"
+ p:idleConnectionTestPeriod="300" destroy-method="close" />
+
+</beans>
diff --git a/sm-core/src/main/resources/spring/shopizer-core-config.xml b/sm-core/src/main/resources/spring/shopizer-core-config.xml
new file mode 100644
index 0000000..6b99f37
--- /dev/null
+++ b/sm-core/src/main/resources/spring/shopizer-core-config.xml
@@ -0,0 +1,35 @@
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
+ xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
+ http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">
+
+
+
+
+ <bean id="coreConfiguration" class="com.salesmanager.core.utils.CoreConfiguration">
+ <property name="properties" ref="shopizer-properties"/>
+ </bean>
+
+ <!-- JDBC User -->
+ <bean id="userService" class="com.salesmanager.core.business.user.service.UserServiceImpl"/>
+
+
+ <bean id="secretKey" class="java.lang.String">
+ <constructor-arg value="${secretKey}"/>
+ </bean>
+
+ <bean id="applicationContextListenerUtils" class="com.salesmanager.core.utils.ApplicationContextListenerUtils" />
+
+ <!-- Get the secret key from JNDI -->
+ <!--
+ <jee:jndi-lookup id="secretKey"
+ jndi-name="java:comp/env/secretKey" />
+ -->
+</beans>
\ No newline at end of file
diff --git a/sm-core/src/main/resources/spring/shopizer-core-ehcache.xml b/sm-core/src/main/resources/spring/shopizer-core-ehcache.xml
new file mode 100644
index 0000000..9178535
--- /dev/null
+++ b/sm-core/src/main/resources/spring/shopizer-core-ehcache.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
+ xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
+ http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
+ http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.2.xsd">
+
+
+ <bean id="springCacheManager" class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean">
+ <property name="configLocation" value="classpath:/ehcache/smcore-ehcache.xml" />
+ <property name="shared" value="false" />
+ </bean>
+
+ <bean id="serviceCacheManager" class="org.springframework.cache.ehcache.EhCacheCacheManager">
+ <property name="cacheManager">
+ <ref local="springCacheManager" />
+ </property>
+ </bean>
+
+ <bean id="serviceCache" factory-bean="serviceCacheManager" factory-method="getCache">
+ <constructor-arg value="com.shopizer.OBJECT_CACHE" />
+ </bean>
+
+</beans>
\ No newline at end of file
diff --git a/sm-core/src/main/resources/spring/shopizer-core-modules.xml b/sm-core/src/main/resources/spring/shopizer-core-modules.xml
new file mode 100755
index 0000000..3a3dfd6
--- /dev/null
+++ b/sm-core/src/main/resources/spring/shopizer-core-modules.xml
@@ -0,0 +1,239 @@
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
+ xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
+ http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">
+
+
+ <!-- Shipping integration modules -->
+ <util:map id="shippingModules" map-class="java.util.HashMap" key-type="java.lang.String" value-type="com.salesmanager.core.modules.integration.shipping.model.ShippingQuoteModule">
+ <entry key="canadapost" value-ref="canadapost"/>
+ <entry key="usps" value-ref="usps"/>
+ <entry key="ups" value-ref="ups"/>
+ <entry key="weightBased" value-ref="weightBased"/>
+ </util:map>
+
+ <!-- Payment integration modules -->
+ <util:map id="paymentModules" map-class="java.util.HashMap" key-type="java.lang.String" value-type="com.salesmanager.core.modules.integration.payment.model.PaymentModule">
+ <entry key="beanstream" value-ref="beanstream"/>
+ <entry key="paypal-express-checkout" value-ref="paypal-ec"/>
+ <entry key="moneyorder" value-ref="moneyorder"/>
+ </util:map>
+
+
+ <!-- Shipping -->
+ <bean id="canadapost"
+ class="com.salesmanager.core.modules.integration.shipping.impl.CanadaPostShippingQuote"/>
+ <bean id="usps"
+ class="com.salesmanager.core.modules.integration.shipping.impl.USPSShippingQuote"/>
+ <bean id="ups"
+ class="com.salesmanager.core.modules.integration.shipping.impl.UPSShippingQuote"/>
+ <bean id="weightBased"
+ class="com.salesmanager.core.modules.integration.shipping.impl.CustomWeightBasedShippingQuote"/>
+
+ <!-- Default packaging -->
+ <bean id="boxPackaging"
+ class="com.salesmanager.core.modules.integration.shipping.impl.DefaultPackagingImpl"/>
+
+ <!-- Payment -->
+ <bean id="beanstream"
+ class="com.salesmanager.core.modules.integration.payment.impl.BeanStreamPayment"/>
+ <bean id="moneyorder"
+ class="com.salesmanager.core.modules.integration.payment.impl.MoneyOrderPayment"/>
+ <bean id="paypal-ec"
+ class="com.salesmanager.core.modules.integration.payment.impl.PayPalExpressCheckoutPayment"/>
+
+ <!-- -->
+ <!-- CMS -->
+ <!-- -->
+
+ <!-- Product images manager-->
+ <bean id="productFileManager"
+ class="com.salesmanager.core.modules.cms.product.ProductFileManagerImpl">
+ <property name="uploadImage">
+ <ref bean="cmsProductImage" />
+ </property>
+ <property name="getImage">
+ <ref bean="cmsProductImage" />
+ </property>
+ <property name="removeImage">
+ <ref bean="cmsProductImage" />
+ </property>
+ <property name="configuration">
+ <ref bean="coreConfiguration" />
+ </property>
+ </bean>
+
+ <!-- CMS implementation for product images-->
+ <bean id="cmsProductImage"
+ class="com.salesmanager.core.modules.cms.product.CmsImageFileManagerInfinispanImpl" factory-method="getInstance" >
+ <property name="cacheManager">
+ <ref bean="storeCacheManager" />
+ </property>
+ <property name="rootName" value="product-merchant"/>
+ </bean>
+
+
+
+ <!-- Content images manager (logo, other store artifacts)-->
+ <bean id="contentFileManager"
+ class="com.salesmanager.core.modules.cms.content.StaticContentFileManagerImpl">
+ <property name="uploadFile">
+ <ref bean="cmsStoreFile" />
+ </property>
+ <property name="getFile">
+ <ref bean="cmsStoreFile" />
+ </property>
+ <property name="removeFile">
+ <ref bean="cmsStoreFile" />
+ </property>
+ </bean>
+
+
+ <bean id="cmsStoreFile"
+ class="com.salesmanager.core.modules.cms.content.CmsStaticContentFileManagerInfinispanImpl" factory-method="getInstance" >
+ <property name="cacheManager">
+ <ref bean="storeCacheManager" />
+ </property>
+ <property name="rootName" value="store-merchant"/>
+ </bean>
+
+
+
+
+ <!-- Static content files manager (images, pdf...) -->
+ <bean id="staticContentFileManager" class="com.salesmanager.core.modules.cms.content.StaticContentFileManagerImpl">
+ <property name="uploadFile">
+ <ref bean="cmsStaticFile" />
+ </property>
+ <property name="getFile">
+ <ref bean="cmsStaticFile" />
+ </property>
+ <property name="removeFile">
+ <ref bean="cmsStaticFile" />
+ </property>
+ </bean>
+ <!-- end of CMS implementation for static content data -->
+
+
+ <!-- CMS implementation for static content data -->
+ <bean id="cmsStaticFile" class="com.salesmanager.core.modules.cms.content.CmsStaticContentFileManagerInfinispanImpl" factory-method="getInstance">
+ <property name="cacheManager">
+ <ref bean="filesCacheManager" />
+ </property>
+ <property name="rootName" value="store-merchant"/>
+ </bean>
+
+
+
+
+ <!-- product downloads -->
+ <bean id="productDownloadsFileManager" class="com.salesmanager.core.modules.cms.content.StaticContentFileManagerImpl">
+ <property name="uploadFile">
+ <ref bean="cmsProductFile" />
+ </property>
+ <property name="getFile">
+ <ref bean="cmsProductFile" />
+ </property>
+ <property name="removeFile">
+ <ref bean="cmsProductFile" />
+ </property>
+ </bean>
+ <!-- end of CMS implementation for static content data -->
+
+
+ <!-- CMS implementation for static content data -->
+ <bean id="cmsProductFile" class="com.salesmanager.core.modules.cms.content.CmsStaticContentFileManagerInfinispanImpl" factory-method="getInstance">
+ <property name="cacheManager">
+ <ref bean="storeCacheManager" />
+ </property>
+ <property name="rootName" value="product-file"/>
+ </bean>
+
+
+
+
+ <!-- Store Cache Manager -->
+ <bean id="storeCacheManager"
+ class="com.salesmanager.core.modules.cms.impl.StoreCacheManagerImpl" factory-method="getInstance" >
+ </bean>
+
+ <!-- Invoice -->
+ <bean id="invoiceModule"
+ class="com.salesmanager.core.modules.order.ODSInvoiceModule" >
+ </bean>
+
+
+ <!--
+ Cache manager to handle static content data which includes
+ 1. CSS Files
+ 2. JS Files
+ 2. Digital data
+ -->
+
+ <bean id="filesCacheManager"
+ class="com.salesmanager.core.modules.cms.impl.StaticContentCacheManagerImpl" factory-method="getInstance" >
+ </bean>
+
+ <!-- Encryption -->
+ <bean id="encryption"
+ class="com.salesmanager.core.modules.utils.EncryptionImpl">
+ <property name="secretKey" ref="secretKey"/>
+ </bean>
+
+ <!-- Geo Location -->
+ <bean id="geoLocation"
+ class="com.salesmanager.core.modules.utils.GeoLocationImpl">
+ </bean>
+
+ <!-- Email -->
+ <bean id="freemarkerMailConfiguration" class="org.springframework.ui.freemarker.FreeMarkerConfigurationFactoryBean">
+ <!-- Uses HTML with templates and freemarker template engine -->
+ <property name="templateLoaderPath" value="/templates/email"/>
+ </bean>
+
+
+ <bean id="mailSender"
+ class="org.springframework.mail.javamail.JavaMailSenderImpl">
+
+ <!-- configured in systems.properties -->
+ <property name="protocol" value="${mailSender.protocol}" />
+ <property name="host" value="${mailSender.host}" />
+ <property name="port" value="${mailSender.port}" />
+
+ <property name="username">
+ <value>${mailSender.username}</value>
+ </property>
+
+ <property name="password">
+ <value>${mailSender.password}</value>
+ </property>
+ <property name="javaMailProperties">
+ <props>
+ <prop key="mail.smtp.auth">${mailSender.mail.smtp.auth}</prop>
+ <prop key="mail.smtp.starttls.enable">${mail.smtp.starttls.enable}</prop>
+ </props>
+ </property>
+ </bean>
+
+ <bean id="htmlEmailSender" class="com.salesmanager.core.modules.email.HtmlEmailSenderImpl" >
+ <property name="mailSender" ref="mailSender"/>
+ <property name="freemarkerMailConfiguration" ref="freemarkerMailConfiguration"/>
+ </bean>
+
+
+
+
+
+
+
+
+
+
+</beans>
\ No newline at end of file
diff --git a/sm-core/src/main/resources/spring/shopizer-search.xml b/sm-core/src/main/resources/spring/shopizer-search.xml
new file mode 100755
index 0000000..63027f1
--- /dev/null
+++ b/sm-core/src/main/resources/spring/shopizer-search.xml
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
+
+ <!-- can have different search client for indexing & searching -->
+ <bean id="searchClient" class="com.shopizer.search.utils.SearchClient">
+ <property name="serverConfiguration">
+ <ref bean="serverConfiguration" />
+ </property>
+ </bean>
+
+ <!-- Server configuration -->
+ <bean id="serverConfiguration" class="com.shopizer.search.utils.ServerConfiguration">
+ <property name="clusterName" value="shopizer"/>
+ <!-- local (embedded version, will create new indexes in the working directory) or remote (requires existing server) -->
+ <property name="mode" value="local"/>
+ <!-- those properties are used when configured for remote -->
+ <property name="clusterHost" value="127.0.0.1"/>
+ <property name="clusterPort" value="9300"/>
+ </bean>
+
+ <bean id="searchDelegate" class="com.shopizer.search.services.impl.SearchDelegateImpl">
+ <property name="searchClient">
+ <ref bean="searchClient" />
+ </property>
+ </bean>
+
+
+ <!--
+ This file contains flow definitions for indexing and searching
+ -->
+
+ <bean id="searchService" class="com.shopizer.search.services.SearchService"/>
+
+
+
+ <bean id="searchWorkflow" class="com.shopizer.search.services.workflow.SearchWorkflow">
+ <property name="searchFlow">
+ <list>
+ <bean id="search" class="com.shopizer.search.services.worker.SearchWorkerImpl"/>
+ </list>
+ </property>
+ <property name="searchKeywordWorkflow">
+ <list>
+ <bean id="searchKeyword" class="com.shopizer.search.services.worker.KeywordSearchWorkerImpl"/>
+ </list>
+ </property>
+ <property name="searchClient">
+ <ref bean="searchClient" />
+ </property>
+ </bean>
+
+ <bean id="indexWorkflow" class="com.shopizer.search.services.workflow.IndexWorkflow">
+ <property name="indexWorkflow">
+ <list>
+ <ref bean="index" />
+ <ref bean="keyword" />
+ </list>
+ </property>
+ <property name="searchClient">
+ <ref bean="searchClient" />
+ </property>
+ </bean>
+
+ <bean id="deleteWorkflow" class="com.shopizer.search.services.workflow.DeleteObjectWorkflow">
+ <property name="deleteObjectWorkflow">
+ <list>
+ <bean id="deleteObject" class="com.shopizer.search.services.worker.DeleteObjectImpl"/>
+ <ref bean="deleteKeywords" />
+ </list>
+ </property>
+ <property name="searchClient">
+ <ref bean="searchClient" />
+ </property>
+ </bean>
+
+ <!--<bean id="getWorkflow" class="com.shopizer.search.services.workflow.SearchWorkflow">-->
+ <bean id="getWorkflow" class="com.shopizer.search.services.workflow.GetWorkflow">
+ <property name="searchClient">
+ <ref bean="searchClient" />
+ </property>
+ </bean>
+
+ <bean id="deleteKeywords" class="com.shopizer.search.services.worker.DeleteKeywordsImpl">
+ <property name="indexConfigurations">
+ <list>
+ <ref bean="keywordindex_en" />
+ <ref bean="keywordindex_fr" />
+ </list>
+ </property>
+ </bean>
+
+ <bean id="index" class="com.shopizer.search.services.worker.ObjectIndexerImpl">
+ <property name="indexConfigurations">
+ <list>
+ <ref bean="productindex_en_defaultstore" />
+ <ref bean="productindex_fr_defaultstore" />
+ </list>
+ </property>
+ </bean>
+
+
+
+ <!-- The presence of those properties will allow the creation of mapping files -->
+ <bean id="productindex_en_defaultstore" class="com.shopizer.search.utils.IndexConfiguration">
+ <property name="collectionName" value="product_en_default"/>
+ <property name="indexName" value="product_en"/>
+ <property name="mappingFileName" value="search/product.json"/>
+ <property name="settingsFileName" value="search/settings_product.json"/>
+ </bean>
+
+ <bean id="productindex_fr_defaultstore" class="com.shopizer.search.utils.IndexConfiguration">
+ <property name="collectionName" value="product_fr_default"/>
+ <property name="indexName" value="product_fr"/>
+ <property name="mappingFileName" value="search/product_fr.json"/>
+ <property name="settingsFileName" value="search/settings_product_fr.json"/>
+ </bean>
+
+ <bean id="keyword" class="com.shopizer.search.services.worker.KeywordIndexerImpl">
+ <property name="indexConfigurations">
+ <list>
+ <ref bean="keywordindex_en" />
+ <ref bean="keywordindex_fr" />
+ </list>
+ </property>
+ </bean>
+
+ <bean id="keywordindex_en" class="com.shopizer.search.utils.CustomIndexConfiguration">
+ <property name="collectionName" value="keyword_en_%store%"/>
+ <property name="createOnIndexName" value="product_en"/>
+ <property name="fields">
+ <list>
+ <ref bean="field1" />
+ <ref bean="field2" />
+ </list>
+ </property>
+ <!-- NO FILTERS
+ <property name="filters">
+ <list>
+ <ref bean="filter1" />
+ </list>
+ </property>
+ -->
+ </bean>
+
+
+ <bean id="keywordindex_fr" class="com.shopizer.search.utils.CustomIndexConfiguration">
+ <property name="collectionName" value="keyword_fr_%store%"/>
+ <property name="createOnIndexName" value="product_fr"/>
+ <property name="fields">
+ <list>
+ <ref bean="field1" />
+ <ref bean="field2" />
+ </list>
+ </property>
+ <!-- NO FILTERS
+ <property name="filters">
+ <list>
+ <ref bean="filter1" />
+ </list>
+ </property>
+ -->
+ </bean>
+
+
+ <!-- supported field types List, Integer, Double, Boolean, String -->
+ <bean id="field1" class="com.shopizer.search.utils.CustomIndexFieldConfiguration">
+ <property name="fieldName" value="tags"/>
+ <property name="fieldType" value="List"/>
+ </bean>
+ <bean id="field2" class="com.shopizer.search.utils.CustomIndexFieldConfiguration">
+ <property name="fieldName" value="name"/>
+ <property name="fieldType" value="String"/>
+ </bean>
+ <!--
+ <bean id="filter1" class="com.shopizer.search.utils.CustomIndexFieldConfiguration">
+ <property name="fieldName" value="price"/>
+ <property name="fieldType" value="Double"/>
+ </bean>
+ -->
+
+</beans>
\ No newline at end of file
sm-core/src/main/resources/spring/spring-context.xml 120(+120 -0)
diff --git a/sm-core/src/main/resources/spring/spring-context.xml b/sm-core/src/main/resources/spring/spring-context.xml
new file mode 100644
index 0000000..bc05b2a
--- /dev/null
+++ b/sm-core/src/main/resources/spring/spring-context.xml
@@ -0,0 +1,120 @@
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop"
+ xmlns:context="http://www.springframework.org/schema/context" xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:task="http://www.springframework.org/schema/task"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
+ http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
+ http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
+ http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
+ http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd
+ http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd">
+
+ <context:annotation-config />
+ <context:component-scan base-package="com.salesmanager.core.business" />
+ <context:component-scan base-package="com.salesmanager.core.utils" />
+ <context:component-scan base-package="com.salesmanager.core.modules" />
+
+ <!-- datasource -->
+ <import resource="classpath:/spring/datasource-c3p0.xml" />
+ <!-- cache -->
+ <import resource="classpath:/spring/shopizer-core-ehcache.xml" />
+ <!-- properties -->
+ <import resource="classpath:/spring/shopizer-core-config.xml" />
+ <!-- modules -->
+ <import resource="classpath:/spring/shopizer-core-modules.xml" />
+ <!-- search -->
+ <import resource="classpath:/spring/shopizer-search.xml" />
+
+ <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
+ <property name="persistenceUnitName" value="sm-unit" />
+ <property name="dataSource" ref="datasource" />
+ <property name="persistenceXmlLocation" value="classpath:META-INF/sm-persistence.xml" />
+
+ <!--
+ <property name="namingStrategy">
+ <bean class="org.hibernate.cfg.ImprovedNamingStrategy" />
+ </property>
+ -->
+
+
+ <property name="jpaVendorAdapter">
+ <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
+ <property name="showSql" value="true" />
+ <property name="generateDdl" value="false" />
+ <property name="databasePlatform" value="${hibernate.dialect}" />
+ </bean>
+ </property>
+ <property name="jpaProperties">
+ <util:map>
+ <entry key="hibernate.default_schema" value="${db.schema}" />
+ <entry key="hibernate.hbm2ddl.auto" value="${hibernate.hbm2ddl.auto}" />
+ <entry key="hibernate.show_sql" value="true" />
+ <entry key="hibernate.cache.provider_class" value="org.hibernate.cache.EhCacheProvider" />
+ <entry key="hibernate.cache.use_second_level_cache" value="true" />
+ </util:map>
+ </property>
+
+ <property name="loadTimeWeaver">
+ <bean class="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver" />
+ </property>
+ </bean>
+
+ <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
+
+
+
+ <!-- MBeans statistics [disable in production] only one definition per web app-->
+<!-- <bean id="jmxExporter" class="org.springframework.jmx.export.MBeanExporter">
+ <property name="beans">
+ <map>
+ <entry key="Hibernate:application=Statistics" value-ref="hibernateStatisticsBean"/>
+ </map>
+ </property>
+ </bean>
+
+ <bean id="hibernateStatisticsBean" class="org.hibernate.jmx.StatisticsService">
+ <property name="statisticsEnabled" value="true"/>
+ <property name="sessionFactory">
+ <util:property-path path="entityManagerFactory.sessionFactory" />
+ </property>
+ </bean> -->
+
+
+ <!-- Définition de la gestion des transactions -->
+ <tx:annotation-driven />
+ <bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
+ p:entityManagerFactory-ref="entityManagerFactory">
+ </bean>
+
+ <aop:config>
+ <aop:pointcut id="txPointCutDef" expression="this(com.salesmanager.core.business.generic.service.TransactionalAspectAwareService)" />
+ <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCutDef" />
+ </aop:config>
+
+ <tx:advice id="txAdvice" transaction-manager="transactionManager">
+ <tx:attributes>
+ <tx:method name="get*" read-only="true" />
+ <tx:method name="list*" read-only="true" />
+ <tx:method name="search*" read-only="true" />
+ <tx:method name="*" read-only="false" rollback-for="com.salesmanager.core.business.generic.exception.ServiceException" />
+ </tx:attributes>
+ </tx:advice>
+
+ <!-- traduction des exceptions -->
+ <bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor" />
+
+ <!-- persistence -->
+ <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor" />
+
+ <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
+ <property name="ignoreUnresolvablePlaceholders" value="false"/>
+ <property name="locations">
+ <list>
+ <value>classpath:database.properties</value>
+ <value>classpath:email.properties</value>
+ <value>classpath:configs.properties</value>
+ </list>
+ </property>
+ </bean>
+</beans>
\ No newline at end of file
diff --git a/sm-core/src/main/resources/templates/email/email_template_checkout.ftl b/sm-core/src/main/resources/templates/email/email_template_checkout.ftl
new file mode 100644
index 0000000..0a17d7f
--- /dev/null
+++ b/sm-core/src/main/resources/templates/email/email_template_checkout.ftl
@@ -0,0 +1,417 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html>
+<head>
+<!-- If you delete this meta tag, Earth will fall into the sun. -->
+<meta name="viewport" content="width=device-width" />
+
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title></title>
+
+<style type="text/css">
+
+/* -------------------------------------
+ GLOBAL
+------------------------------------- */
+* {
+ margin:0;
+ padding:0;
+}
+* { font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; }
+
+img {
+ max-width: 100%;
+}
+.collapse {
+ margin:0;
+ padding:0;
+}
+body {
+ -webkit-font-smoothing:antialiased;
+ -webkit-text-size-adjust:none;
+ width: 100%!important;
+ height: 100%;
+}
+
+
+/* -------------------------------------
+ ELEMENTS
+------------------------------------- */
+a { color: #2BA6CB;}
+
+.btn {
+ text-decoration:none;
+ color: #FFF;
+ background-color: #666;
+ padding:10px 16px;
+ font-weight:bold;
+ margin-right:10px;
+ text-align:center;
+ cursor:pointer;
+ display: inline-block;
+}
+
+p.callout {
+ padding:15px;
+ background-color:#ECF8FF;
+ margin-bottom: 15px;
+}
+.callout a {
+ font-weight:bold;
+ color: #2BA6CB;
+}
+
+table.social {
+/* padding:15px; */
+ background-color: #ebebeb;
+
+}
+.social .soc-btn {
+ padding: 3px 7px;
+ font-size:12px;
+ margin-bottom:10px;
+ text-decoration:none;
+ color: #FFF;font-weight:bold;
+ display:block;
+ text-align:center;
+}
+a.fb { background-color: #3B5998!important; }
+a.tw { background-color: #1daced!important; }
+a.gp { background-color: #DB4A39!important; }
+a.ms { background-color: #000!important; }
+
+.sidebar .soc-btn {
+ display:block;
+ width:100%;
+}
+
+/* -------------------------------------
+ HEADER
+------------------------------------- */
+table.head-wrap { width: 100%;}
+
+.header.container table td.logo { padding: 2px; }
+.header.container table td.label { padding: 10fpx; padding-left:0px;}
+
+
+/* -------------------------------------
+ BODY
+------------------------------------- */
+table.body-wrap { width: 100%;}
+
+
+/* -------------------------------------
+ FOOTER
+------------------------------------- */
+table.footer-wrap { width: 100%; clear:both!important;
+}
+.footer-wrap .container td.content p { border-top: 1px solid rgb(215,215,215); padding-top:15px;}
+.footer-wrap .container td.content p {
+ font-size:10px;
+ font-weight: bold;
+
+}
+
+
+/* -------------------------------------
+ TYPOGRAPHY
+------------------------------------- */
+h1,h2,h3,h4,h5,h6 {
+font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 1.1; margin-bottom:15px; color:#000;
+}
+h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { font-size: 60%; color: #6f6f6f; line-height: 0; text-transform: none; }
+
+h1 { font-weight:200; font-size: 44px;}
+h2 { font-weight:200; font-size: 37px;}
+h3 { font-weight:500; font-size: 27px;}
+h4 { font-weight:500; font-size: 23px;}
+h5 { font-weight:900; font-size: 17px;}
+h6 { font-weight:900; font-size: 14px; text-transform: uppercase; color:#444;}
+
+.collapse { margin:0!important;}
+
+p, ul {
+ margin-bottom: 10px;
+ font-weight: normal;
+ font-size:14px;
+ line-height:1.6;
+}
+p.lead { font-size:17px; }
+p.last { margin-bottom:0px;}
+
+ul li {
+ margin-left:5px;
+ list-style-position: inside;
+}
+
+/* -------------------------------------
+ SIDEBAR
+------------------------------------- */
+ul.sidebar {
+ display:block;
+ list-style-type: none;
+}
+ul.sidebar li { display: block; margin:0;}
+ul.sidebar li a {
+ text-decoration:none;
+ color: #666;
+ padding:10px 16px;
+/* font-weight:bold; */
+ margin-right:10px;
+/* text-align:center; */
+ cursor:pointer;
+/** border-bottom: 1px solid #777777;**/
+/** border-top: 1px solid #FFFFFF;**/
+ display:block;
+ margin:0;
+}
+ul.sidebar li a.last { border-bottom-width:0px;}
+ul.sidebar li a h1,ul.sidebar li a h2,ul.sidebar li a h3,ul.sidebar li a h4,ul.sidebar li a h5,ul.sidebar li a h6,ul.sidebar li a p { margin-bottom:0!important;}
+
+
+
+/* ---------------------------------------------------
+ RESPONSIVENESS
+ Nuke it from orbit. It's the only way to be sure.
+------------------------------------------------------ */
+
+/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
+.container {
+ display:block!important;
+ max-width:600px!important;
+ margin:0 auto!important; /* makes it centered */
+ clear:both!important;
+}
+
+/* This should also be a block element, so that it will fill 100% of the .container */
+.content {
+ padding:15px;
+ max-width:600px;
+ margin:0 auto;
+ display:block;
+}
+
+/* Let's make sure tables in the content area are 100% wide */
+.content table { width: 100%; }
+
+
+/* Odds and ends */
+.column {
+ width: 300px;
+ float:left;
+}
+.column tr td { padding: 15px; }
+.column-wrap {
+ padding:0!important;
+ margin:0 auto;
+ max-width:600px!important;
+}
+.column table { width:100%;}
+.social .column {
+ width: 280px;
+ min-width: 279px;
+ float:left;
+}
+
+/* Be sure to place a .clear element after each set of columns, just to be safe */
+.clear { display: block; clear: both; }
+
+.border {border:1px solid}
+
+/* -------------------------------------------
+ PHONE
+ For clients that support media queries.
+ Nothing fancy.
+-------------------------------------------- */
+@media only screen and (max-width: 600px) {
+
+ a[class="btn"] { display:block!important; margin-bottom:10px!important; background-image:none!important; margin-right:0!important;}
+
+ div[class="column"] { width: auto!important; float:none!important;}
+
+ table.social div[class="column"] {
+ width:auto!important;
+ }
+
+}
+
+</style>
+
+</head>
+
+<body bgcolor="#FFFFFF" topmargin="0" leftmargin="0" marginheight="0" marginwidth="0">
+
+<!-- HEADER -->
+<table class="head-wrap">
+ <tr>
+ <td></td>
+ <td class="header container" >
+
+ <p>
+ <table>
+ <tr>
+ <td>
+ ${LOGOPATH}
+ </td>
+ </tr>
+ </table>
+ </p>
+
+ </td>
+ <td></td>
+ </tr>
+</table>
+<!-- /HEADER -->
+
+<!-- BODY -->
+<table class="body-wrap">
+
+ <tr>
+ <td colspan="2">
+ <div class="content">
+ <table>
+ <tr>
+ <td>
+ <h4>${LABEL_HI} ${EMAIL_CUSTOMER_FIRSTNAME} ${EMAIL_CUSTOMER_LASTNAME}<br/></h4>
+ <p class="lead">
+ ${EMAIL_ORDER_NUMBER}
+ </p>
+ <br>
+ <p>
+ ${EMAIL_ORDER_DATE}<br/>
+ ${EMAIL_ORDER_THANKS}
+ </p>
+ </td>
+ </tr>
+ </table>
+ </div><!-- /content -->
+ </td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="container" bgcolor="#FFFFFF">
+
+
+ <p>
+ <h4>${EMAIL_ORDER_DETAILS_TITLE}</h4>
+ </p>
+ <p>
+ ${ORDER_PRODUCTS_DETAILS}
+ </p>
+ </td>
+ <td></td>
+ </tr>
+ <tr>
+ <td></td>
+ <td class="container" bgcolor="#FFFFFF">
+
+ <table>
+ <tr>
+ <td valign="top">
+ <ul class="sidebar">
+ <li>
+ <a>
+ <h5>${ADDRESS_BILLING_TITLE} »</h5>
+ <p>
+ ${ADDRESS_BILLING}
+ </p>
+ </a>
+ </li>
+ </ul>
+ </td>
+ <td valign="top">
+ <ul class="sidebar">
+ <li>
+ <a>
+ <h5>${ADDRESS_DELIVERY_TITLE} »</h5>
+ <p>
+ ${ADDRESS_DELIVERY}
+ </p>
+ </a>
+ </li>
+ </ul>
+ </td>
+ </tr>
+ <tr>
+ <td>
+ <ul class="sidebar">
+ <li>
+ <a>
+ <strong>${PAYMENT_METHOD_TITLE}</strong><br>
+ ${PAYMENT_METHOD_DETAILS}
+ </a>
+ </li>
+
+ </ul>
+ </td>
+ <td>
+ <ul class="sidebar">
+ <li>
+ <a>
+ <strong>${SHIPPING_METHOD_TITLE}</strong><br>
+ ${SHIPPING_METHOD_DETAILS}
+ </a>
+ </li>
+ </ul>
+ </td>
+ </tr>
+ </table>
+ <div class="clear"></div>
+
+ </td>
+ <td></td>
+ </tr>
+</table><!-- /BODY -->
+
+<table class="body-wrap">
+ <tr>
+ <td></td>
+ <td class="container" bgcolor="#FFFFFF">
+ <div class="content">
+ <!-- Callout Panel -->
+ <p class="callout">
+ ${ORDER_STATUS}
+ </p><!-- /Callout Panel -->
+ </div>
+ </td>
+ <td></td>
+ </tr>
+</table>
+
+<!-- FOOTER -->
+<table class="footer-wrap">
+ <tr>
+ <td></td>
+ <td class="container">
+
+ <!-- content -->
+ <div class="content">
+ <p>
+ <table>
+ <tr>
+ <td align="center">
+ <p>
+ ${EMAIL_DISCLAIMER}
+ </p>
+ <p>
+ ${EMAIL_SPAM_DISCLAIMER}
+ </p>
+ <p>
+ ${EMAIL_FOOTER_COPYRIGHT}
+ </p>
+ </td>
+ </tr>
+ </table>
+ </p>
+ </div><!-- /content -->
+
+ </td>
+ <td></td>
+ </tr>
+</table><!-- /FOOTER -->
+
+</body>
+</html>
+
+
+
+
diff --git a/sm-core/src/main/resources/templates/email/email_template_checkout_download.ftl b/sm-core/src/main/resources/templates/email/email_template_checkout_download.ftl
new file mode 100644
index 0000000..69de9d4
--- /dev/null
+++ b/sm-core/src/main/resources/templates/email/email_template_checkout_download.ftl
@@ -0,0 +1,329 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<!-- If you delete this meta tag, Half Life 3 will never be released. -->
+<meta name="viewport" content="width=device-width" />
+
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title></title>
+
+<style type="text/css">
+
+
+/* -------------------------------------
+ GLOBAL
+------------------------------------- */
+* {
+ margin:0;
+ padding:0;
+}
+* { font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; }
+
+img {
+ max-width: 100%;
+}
+.collapse {
+ margin:0;
+ padding:0;
+}
+body {
+ -webkit-font-smoothing:antialiased;
+ -webkit-text-size-adjust:none;
+ width: 100%!important;
+ height: 100%;
+}
+
+
+/* -------------------------------------
+ ELEMENTS
+------------------------------------- */
+a { color: #2BA6CB;}
+
+.btn {
+ text-decoration:none;
+ color: #FFF;
+ background-color: #666;
+ padding:10px 16px;
+ font-weight:bold;
+ margin-right:10px;
+ text-align:center;
+ cursor:pointer;
+ display: inline-block;
+}
+
+p.callout {
+ padding:15px;
+ background-color:#ECF8FF;
+ margin-bottom: 15px;
+}
+.callout a {
+ font-weight:bold;
+ color: #2BA6CB;
+}
+
+table.social {
+/* padding:15px; */
+ background-color: #ebebeb;
+
+}
+.social .soc-btn {
+ padding: 3px 7px;
+ font-size:12px;
+ margin-bottom:10px;
+ text-decoration:none;
+ color: #FFF;font-weight:bold;
+ display:block;
+ text-align:center;
+}
+a.fb { background-color: #3B5998!important; }
+a.tw { background-color: #1daced!important; }
+a.gp { background-color: #DB4A39!important; }
+a.ms { background-color: #000!important; }
+
+.sidebar .soc-btn {
+ display:block;
+ width:100%;
+}
+
+/* -------------------------------------
+ HEADER
+------------------------------------- */
+table.head-wrap { width: 100%;}
+
+.header.container table td.logo { padding: 15px; }
+.header.container table td.label { padding: 15px; padding-left:0px;}
+
+
+/* -------------------------------------
+ BODY
+------------------------------------- */
+table.body-wrap { width: 100%;}
+
+
+/* -------------------------------------
+ FOOTER
+------------------------------------- */
+table.footer-wrap { width: 100%; clear:both!important;
+}
+.footer-wrap .container td.content p { border-top: 1px solid rgb(215,215,215); padding-top:15px;}
+.footer-wrap .container td.content p {
+ font-size:10px;
+ font-weight: bold;
+
+}
+
+
+/* -------------------------------------
+ TYPOGRAPHY
+------------------------------------- */
+h1,h2,h3,h4,h5,h6 {
+font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 1.1; margin-bottom:15px; color:#000;
+}
+h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { font-size: 60%; color: #6f6f6f; line-height: 0; text-transform: none; }
+
+h1 { font-weight:200; font-size: 44px;}
+h2 { font-weight:200; font-size: 37px;}
+h3 { font-weight:500; font-size: 27px;}
+h4 { font-weight:500; font-size: 23px;}
+h5 { font-weight:900; font-size: 17px;}
+h6 { font-weight:900; font-size: 14px; text-transform: uppercase; color:#444;}
+
+.collapse { margin:0!important;}
+
+p, ul {
+ margin-bottom: 10px;
+ font-weight: normal;
+ font-size:14px;
+ line-height:1.6;
+}
+p.lead { font-size:17px; }
+p.last { margin-bottom:0px;}
+
+ul li {
+ margin-left:5px;
+ list-style-position: inside;
+}
+
+/* -------------------------------------
+ SIDEBAR
+------------------------------------- */
+ul.sidebar {
+ background:#ebebeb;
+ display:block;
+ list-style-type: none;
+}
+ul.sidebar li { display: block; margin:0;}
+ul.sidebar li a {
+ text-decoration:none;
+ color: #666;
+ padding:10px 16px;
+/* font-weight:bold; */
+ margin-right:10px;
+/* text-align:center; */
+ cursor:pointer;
+ border-bottom: 1px solid #777777;
+ border-top: 1px solid #FFFFFF;
+ display:block;
+ margin:0;
+}
+ul.sidebar li a.last { border-bottom-width:0px;}
+ul.sidebar li a h1,ul.sidebar li a h2,ul.sidebar li a h3,ul.sidebar li a h4,ul.sidebar li a h5,ul.sidebar li a h6,ul.sidebar li a p { margin-bottom:0!important;}
+
+
+
+/* ---------------------------------------------------
+ RESPONSIVENESS
+ Nuke it from orbit. It's the only way to be sure.
+------------------------------------------------------ */
+
+/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
+.container {
+ display:block!important;
+ max-width:600px!important;
+ margin:0 auto!important; /* makes it centered */
+ clear:both!important;
+}
+
+/* This should also be a block element, so that it will fill 100% of the .container */
+.content {
+ padding:15px;
+ max-width:600px;
+ margin:0 auto;
+ display:block;
+}
+
+/* Let's make sure tables in the content area are 100% wide */
+.content table { width: 100%; }
+
+
+/* Odds and ends */
+.column {
+ width: 300px;
+ float:left;
+}
+.column tr td { padding: 15px; }
+.column-wrap {
+ padding:0!important;
+ margin:0 auto;
+ max-width:600px!important;
+}
+.column table { width:100%;}
+.social .column {
+ width: 280px;
+ min-width: 279px;
+ float:left;
+}
+
+/* Be sure to place a .clear element after each set of columns, just to be safe */
+.clear { display: block; clear: both; }
+
+
+/* -------------------------------------------
+ PHONE
+ For clients that support media queries.
+ Nothing fancy.
+-------------------------------------------- */
+@media only screen and (max-width: 600px) {
+
+ a[class="btn"] { display:block!important; margin-bottom:10px!important; background-image:none!important; margin-right:0!important;}
+
+ div[class="column"] { width: auto!important; float:none!important;}
+
+ table.social div[class="column"] {
+ width:auto!important;
+ }
+
+}
+
+</style>
+
+</head>
+<body bgcolor="#FFFFFF">
+
+<!-- HEADER -->
+<table class="head-wrap">
+ <tr>
+ <td></td>
+ <td class="header container" >
+
+ <p>
+ <table>
+ <tr>
+ <td>
+ <h3>${LOGOPATH}</h3>
+ </td>
+ </tr>
+ </table>
+ </p>
+
+ </td>
+ <td></td>
+ </tr>
+</table>
+<!-- /HEADER -->
+
+
+<!-- BODY -->
+<table class="body-wrap">
+ <tr>
+ <td></td>
+ <td class="container" bgcolor="#FFFFFF">
+
+ <div class="content">
+ <table>
+ <tr>
+ <td>
+ <h4>${LABEL_HI} ${EMAIL_CUSTOMER_FIRSTNAME} ${EMAIL_CUSTOMER_LASTNAME}<br/></h4>
+ <p class="lead">
+ ${EMAIL_ORDER_DOWNLOAD}
+ </p>
+ <!-- Callout Panel -->
+ <p class="callout">
+ ${CUSTOMER_ACCESS_LABEL} <a href="${CUSTOMER_ACCESS_URL}">${ACCESS_NOW_LABEL} »</a>
+ </p><!-- /Callout Panel -->
+
+
+ </td>
+ </tr>
+ </table>
+ </div><!-- /content -->
+
+ </td>
+ <td></td>
+ </tr>
+</table><!-- /BODY -->
+
+<!-- FOOTER -->
+<table class="footer-wrap">
+ <tr>
+ <td></td>
+ <td class="container">
+
+ <!-- content -->
+ <div class="content">
+ <p>
+ <table>
+ <tr>
+ <td align="center">
+ <p>
+ ${EMAIL_DISCLAIMER}
+ </p>
+ <p>
+ ${EMAIL_SPAM_DISCLAIMER}
+ </p>
+ <p>
+ ${EMAIL_FOOTER_COPYRIGHT}
+ </p>
+ </td>
+ </tr>
+ </table>
+ </p>
+ </div><!-- /content -->
+
+ </td>
+ <td></td>
+ </tr>
+</table><!-- /FOOTER -->
+
+</body>
+</html>
diff --git a/sm-core/src/main/resources/templates/email/email_template_contact.ftl b/sm-core/src/main/resources/templates/email/email_template_contact.ftl
new file mode 100644
index 0000000..816b793
--- /dev/null
+++ b/sm-core/src/main/resources/templates/email/email_template_contact.ftl
@@ -0,0 +1,333 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<!-- If you delete this meta tag, Half Life 3 will never be released. -->
+<meta name="viewport" content="width=device-width" />
+
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title></title>
+
+<style type="text/css">
+
+
+/* -------------------------------------
+ GLOBAL
+------------------------------------- */
+* {
+ margin:0;
+ padding:0;
+}
+* { font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; }
+
+img {
+ max-width: 100%;
+}
+.collapse {
+ margin:0;
+ padding:0;
+}
+body {
+ -webkit-font-smoothing:antialiased;
+ -webkit-text-size-adjust:none;
+ width: 100%!important;
+ height: 100%;
+}
+
+
+/* -------------------------------------
+ ELEMENTS
+------------------------------------- */
+a { color: #2BA6CB;}
+
+.btn {
+ text-decoration:none;
+ color: #FFF;
+ background-color: #666;
+ padding:10px 16px;
+ font-weight:bold;
+ margin-right:10px;
+ text-align:center;
+ cursor:pointer;
+ display: inline-block;
+}
+
+p.callout {
+ padding:15px;
+ background-color:#ECF8FF;
+ margin-bottom: 15px;
+}
+.callout a {
+ font-weight:bold;
+ color: #2BA6CB;
+}
+
+table.social {
+/* padding:15px; */
+ background-color: #ebebeb;
+
+}
+.social .soc-btn {
+ padding: 3px 7px;
+ font-size:12px;
+ margin-bottom:10px;
+ text-decoration:none;
+ color: #FFF;font-weight:bold;
+ display:block;
+ text-align:center;
+}
+a.fb { background-color: #3B5998!important; }
+a.tw { background-color: #1daced!important; }
+a.gp { background-color: #DB4A39!important; }
+a.ms { background-color: #000!important; }
+
+.sidebar .soc-btn {
+ display:block;
+ width:100%;
+}
+
+/* -------------------------------------
+ HEADER
+------------------------------------- */
+table.head-wrap { width: 100%;}
+
+.header.container table td.logo { padding: 15px; }
+.header.container table td.label { padding: 15px; padding-left:0px;}
+
+
+/* -------------------------------------
+ BODY
+------------------------------------- */
+table.body-wrap { width: 100%;}
+
+
+/* -------------------------------------
+ FOOTER
+------------------------------------- */
+table.footer-wrap { width: 100%; clear:both!important;
+}
+.footer-wrap .container td.content p { border-top: 1px solid rgb(215,215,215); padding-top:15px;}
+.footer-wrap .container td.content p {
+ font-size:10px;
+ font-weight: bold;
+
+}
+
+
+/* -------------------------------------
+ TYPOGRAPHY
+------------------------------------- */
+h1,h2,h3,h4,h5,h6 {
+font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 1.1; margin-bottom:15px; color:#000;
+}
+h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { font-size: 60%; color: #6f6f6f; line-height: 0; text-transform: none; }
+
+h1 { font-weight:200; font-size: 44px;}
+h2 { font-weight:200; font-size: 37px;}
+h3 { font-weight:500; font-size: 27px;}
+h4 { font-weight:500; font-size: 23px;}
+h5 { font-weight:900; font-size: 17px;}
+h6 { font-weight:900; font-size: 14px; text-transform: uppercase; color:#444;}
+
+.collapse { margin:0!important;}
+
+p, ul {
+ margin-bottom: 10px;
+ font-weight: normal;
+ font-size:14px;
+ line-height:1.6;
+}
+p.lead { font-size:17px; }
+p.last { margin-bottom:0px;}
+
+ul li {
+ margin-left:5px;
+ list-style-position: inside;
+}
+
+/* -------------------------------------
+ SIDEBAR
+------------------------------------- */
+ul.sidebar {
+ background:#ebebeb;
+ display:block;
+ list-style-type: none;
+}
+ul.sidebar li { display: block; margin:0;}
+ul.sidebar li a {
+ text-decoration:none;
+ color: #666;
+ padding:10px 16px;
+/* font-weight:bold; */
+ margin-right:10px;
+/* text-align:center; */
+ cursor:pointer;
+ border-bottom: 1px solid #777777;
+ border-top: 1px solid #FFFFFF;
+ display:block;
+ margin:0;
+}
+ul.sidebar li a.last { border-bottom-width:0px;}
+ul.sidebar li a h1,ul.sidebar li a h2,ul.sidebar li a h3,ul.sidebar li a h4,ul.sidebar li a h5,ul.sidebar li a h6,ul.sidebar li a p { margin-bottom:0!important;}
+
+
+
+/* ---------------------------------------------------
+ RESPONSIVENESS
+ Nuke it from orbit. It's the only way to be sure.
+------------------------------------------------------ */
+
+/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
+.container {
+ display:block!important;
+ max-width:600px!important;
+ margin:0 auto!important; /* makes it centered */
+ clear:both!important;
+}
+
+/* This should also be a block element, so that it will fill 100% of the .container */
+.content {
+ padding:15px;
+ max-width:600px;
+ margin:0 auto;
+ display:block;
+}
+
+/* Let's make sure tables in the content area are 100% wide */
+.content table { width: 100%; }
+
+
+/* Odds and ends */
+.column {
+ width: 300px;
+ float:left;
+}
+.column tr td { padding: 15px; }
+.column-wrap {
+ padding:0!important;
+ margin:0 auto;
+ max-width:600px!important;
+}
+.column table { width:100%;}
+.social .column {
+ width: 280px;
+ min-width: 279px;
+ float:left;
+}
+
+/* Be sure to place a .clear element after each set of columns, just to be safe */
+.clear { display: block; clear: both; }
+
+
+/* -------------------------------------------
+ PHONE
+ For clients that support media queries.
+ Nothing fancy.
+-------------------------------------------- */
+@media only screen and (max-width: 600px) {
+
+ a[class="btn"] { display:block!important; margin-bottom:10px!important; background-image:none!important; margin-right:0!important;}
+
+ div[class="column"] { width: auto!important; float:none!important;}
+
+ table.social div[class="column"] {
+ width:auto!important;
+ }
+
+}
+
+</style>
+
+</head>
+<body bgcolor="#FFFFFF">
+
+<!-- HEADER -->
+<table class="head-wrap">
+ <tr>
+ <td></td>
+ <td class="header container" >
+
+ <p>
+ <table>
+ <tr>
+ <td>
+ <h3>${LOGOPATH}</h3>
+ </td>
+ </tr>
+ </table>
+ </p>
+
+ </td>
+ <td></td>
+ </tr>
+</table>
+<!-- /HEADER -->
+
+
+<!-- BODY -->
+<table class="body-wrap">
+ <tr>
+ <td></td>
+ <td class="container" bgcolor="#FFFFFF">
+
+ <div class="content">
+ <table>
+ <tr>
+ <td>
+ <p class="lead">
+ ${EMAIL_CUSTOMER_CONTACT}
+ </p>
+ <p>
+ ${EMAIL_CONTACT_NAME_LABEL}: ${EMAIL_CONTACT_NAME}<br />
+ ${EMAIL_CONTACT_EMAIL_LABEL}: ${EMAIL_CONTACT_EMAIL}<br />
+
+ </p>
+ <!-- Callout Panel -->
+ <p class="callout">
+ ${EMAIL_CONTACT_CONTENT}
+ </p><!-- /Callout Panel -->
+
+
+ </td>
+ </tr>
+ </table>
+ </div><!-- /content -->
+
+ </td>
+ <td></td>
+ </tr>
+</table><!-- /BODY -->
+
+<!-- FOOTER -->
+<table class="footer-wrap">
+ <tr>
+ <td></td>
+ <td class="container">
+
+ <!-- content -->
+ <div class="content">
+ <p>
+ <table>
+ <tr>
+ <td align="center">
+ <p>
+ ${EMAIL_DISCLAIMER}
+ </p>
+ <p>
+ ${EMAIL_SPAM_DISCLAIMER}
+ </p>
+ <p>
+ ${EMAIL_FOOTER_COPYRIGHT}
+ </p>
+ </td>
+ </tr>
+ </table>
+ </p>
+ </div><!-- /content -->
+
+ </td>
+ <td></td>
+ </tr>
+</table><!-- /FOOTER -->
+
+</body>
+</html>
diff --git a/sm-core/src/main/resources/templates/email/email_template_customer.ftl b/sm-core/src/main/resources/templates/email/email_template_customer.ftl
new file mode 100644
index 0000000..d87d27c
--- /dev/null
+++ b/sm-core/src/main/resources/templates/email/email_template_customer.ftl
@@ -0,0 +1,334 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<!-- If you delete this meta tag, Half Life 3 will never be released. -->
+<meta name="viewport" content="width=device-width" />
+
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title></title>
+
+<style type="text/css">
+
+
+/* -------------------------------------
+ GLOBAL
+------------------------------------- */
+* {
+ margin:0;
+ padding:0;
+}
+* { font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; }
+
+img {
+ max-width: 100%;
+}
+.collapse {
+ margin:0;
+ padding:0;
+}
+body {
+ -webkit-font-smoothing:antialiased;
+ -webkit-text-size-adjust:none;
+ width: 100%!important;
+ height: 100%;
+}
+
+
+/* -------------------------------------
+ ELEMENTS
+------------------------------------- */
+a { color: #2BA6CB;}
+
+.btn {
+ text-decoration:none;
+ color: #FFF;
+ background-color: #666;
+ padding:10px 16px;
+ font-weight:bold;
+ margin-right:10px;
+ text-align:center;
+ cursor:pointer;
+ display: inline-block;
+}
+
+p.callout {
+ padding:15px;
+ background-color:#ECF8FF;
+ margin-bottom: 15px;
+}
+.callout a {
+ font-weight:bold;
+ color: #2BA6CB;
+}
+
+table.social {
+/* padding:15px; */
+ background-color: #ebebeb;
+
+}
+.social .soc-btn {
+ padding: 3px 7px;
+ font-size:12px;
+ margin-bottom:10px;
+ text-decoration:none;
+ color: #FFF;font-weight:bold;
+ display:block;
+ text-align:center;
+}
+a.fb { background-color: #3B5998!important; }
+a.tw { background-color: #1daced!important; }
+a.gp { background-color: #DB4A39!important; }
+a.ms { background-color: #000!important; }
+
+.sidebar .soc-btn {
+ display:block;
+ width:100%;
+}
+
+/* -------------------------------------
+ HEADER
+------------------------------------- */
+table.head-wrap { width: 100%;}
+
+.header.container table td.logo { padding: 15px; }
+.header.container table td.label { padding: 15px; padding-left:0px;}
+
+
+/* -------------------------------------
+ BODY
+------------------------------------- */
+table.body-wrap { width: 100%;}
+
+
+/* -------------------------------------
+ FOOTER
+------------------------------------- */
+table.footer-wrap { width: 100%; clear:both!important;
+}
+.footer-wrap .container td.content p { border-top: 1px solid rgb(215,215,215); padding-top:15px;}
+.footer-wrap .container td.content p {
+ font-size:10px;
+ font-weight: bold;
+
+}
+
+
+/* -------------------------------------
+ TYPOGRAPHY
+------------------------------------- */
+h1,h2,h3,h4,h5,h6 {
+font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 1.1; margin-bottom:15px; color:#000;
+}
+h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { font-size: 60%; color: #6f6f6f; line-height: 0; text-transform: none; }
+
+h1 { font-weight:200; font-size: 44px;}
+h2 { font-weight:200; font-size: 37px;}
+h3 { font-weight:500; font-size: 27px;}
+h4 { font-weight:500; font-size: 23px;}
+h5 { font-weight:900; font-size: 17px;}
+h6 { font-weight:900; font-size: 14px; text-transform: uppercase; color:#444;}
+
+.collapse { margin:0!important;}
+
+p, ul {
+ margin-bottom: 10px;
+ font-weight: normal;
+ font-size:14px;
+ line-height:1.6;
+}
+p.lead { font-size:17px; }
+p.last { margin-bottom:0px;}
+
+ul li {
+ margin-left:5px;
+ list-style-position: inside;
+}
+
+/* -------------------------------------
+ SIDEBAR
+------------------------------------- */
+ul.sidebar {
+ background:#ebebeb;
+ display:block;
+ list-style-type: none;
+}
+ul.sidebar li { display: block; margin:0;}
+ul.sidebar li a {
+ text-decoration:none;
+ color: #666;
+ padding:10px 16px;
+/* font-weight:bold; */
+ margin-right:10px;
+/* text-align:center; */
+ cursor:pointer;
+ border-bottom: 1px solid #777777;
+ border-top: 1px solid #FFFFFF;
+ display:block;
+ margin:0;
+}
+ul.sidebar li a.last { border-bottom-width:0px;}
+ul.sidebar li a h1,ul.sidebar li a h2,ul.sidebar li a h3,ul.sidebar li a h4,ul.sidebar li a h5,ul.sidebar li a h6,ul.sidebar li a p { margin-bottom:0!important;}
+
+
+
+/* ---------------------------------------------------
+ RESPONSIVENESS
+ Nuke it from orbit. It's the only way to be sure.
+------------------------------------------------------ */
+
+/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
+.container {
+ display:block!important;
+ max-width:600px!important;
+ margin:0 auto!important; /* makes it centered */
+ clear:both!important;
+}
+
+/* This should also be a block element, so that it will fill 100% of the .container */
+.content {
+ padding:15px;
+ max-width:600px;
+ margin:0 auto;
+ display:block;
+}
+
+/* Let's make sure tables in the content area are 100% wide */
+.content table { width: 100%; }
+
+
+/* Odds and ends */
+.column {
+ width: 300px;
+ float:left;
+}
+.column tr td { padding: 15px; }
+.column-wrap {
+ padding:0!important;
+ margin:0 auto;
+ max-width:600px!important;
+}
+.column table { width:100%;}
+.social .column {
+ width: 280px;
+ min-width: 279px;
+ float:left;
+}
+
+/* Be sure to place a .clear element after each set of columns, just to be safe */
+.clear { display: block; clear: both; }
+
+
+/* -------------------------------------------
+ PHONE
+ For clients that support media queries.
+ Nothing fancy.
+-------------------------------------------- */
+@media only screen and (max-width: 600px) {
+
+ a[class="btn"] { display:block!important; margin-bottom:10px!important; background-image:none!important; margin-right:0!important;}
+
+ div[class="column"] { width: auto!important; float:none!important;}
+
+ table.social div[class="column"] {
+ width:auto!important;
+ }
+
+}
+
+</style>
+
+</head>
+<body bgcolor="#FFFFFF">
+
+<!-- HEADER -->
+<table class="head-wrap">
+ <tr>
+ <td></td>
+ <td class="header container" >
+
+ <p>
+ <table>
+ <tr>
+ <td>
+ <h3>${LOGOPATH}</h3>
+ </td>
+ </tr>
+ </table>
+ </p>
+
+ </td>
+ <td></td>
+ </tr>
+</table>
+<!-- /HEADER -->
+
+
+<!-- BODY -->
+<table class="body-wrap">
+ <tr>
+ <td></td>
+ <td class="container" bgcolor="#FFFFFF">
+
+ <div class="content">
+ <table>
+ <tr>
+ <td>
+ <h4>${LABEL_HI} ${EMAIL_CUSTOMER_FIRSTNAME} ${EMAIL_CUSTOMER_LASTNAME}<br/></h4>
+ <p class="lead">
+ ${EMAIL_CUSTOMER_GREETING}
+ </p>
+ <p>
+ ${EMAIL_USERNAME_LABEL}: ${EMAIL_USER_NAME}<br />
+ ${EMAIL_PASSWORD_LABEL}: ${EMAIL_CUSTOMER_PASSWORD}<br />
+
+ </p>
+ <!-- Callout Panel -->
+ <p class="callout">
+ ${CUSTOMER_ACCESS_LABEL} <a href="${CUSTOMER_ACCESS_URL}">${ACCESS_NOW_LABEL} »</a>
+ </p><!-- /Callout Panel -->
+
+
+ </td>
+ </tr>
+ </table>
+ </div><!-- /content -->
+
+ </td>
+ <td></td>
+ </tr>
+</table><!-- /BODY -->
+
+<!-- FOOTER -->
+<table class="footer-wrap">
+ <tr>
+ <td></td>
+ <td class="container">
+
+ <!-- content -->
+ <div class="content">
+ <p>
+ <table>
+ <tr>
+ <td align="center">
+ <p>
+ ${EMAIL_DISCLAIMER}
+ </p>
+ <p>
+ ${EMAIL_SPAM_DISCLAIMER}
+ </p>
+ <p>
+ ${EMAIL_FOOTER_COPYRIGHT}
+ </p>
+ </td>
+ </tr>
+ </table>
+ </p>
+ </div><!-- /content -->
+
+ </td>
+ <td></td>
+ </tr>
+</table><!-- /FOOTER -->
+
+</body>
+</html>
diff --git a/sm-core/src/main/resources/templates/email/email_template_lowstock.ftl b/sm-core/src/main/resources/templates/email/email_template_lowstock.ftl
new file mode 100644
index 0000000..e0924e3
--- /dev/null
+++ b/sm-core/src/main/resources/templates/email/email_template_lowstock.ftl
@@ -0,0 +1,50 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+
+
+
+<style type="text/css">
+body {background-color:#ffffff; color:#000000; font-family:Verdana, Arial, Helvetica, sans-serif; text-align:center;}
+a:link {color:#0066cc;}
+a:hover {background-color:#eeeecc; color:#0066cc;}
+a:visited {color:#0066cc;}
+.holder {background-color:#f9f9f9; border:1px solid #9a9a9a; font-size:9px; text-align:left; width:550px;}
+.header {font-size:10px; padding:0px; width:550px;}
+.content {font-size:10px; padding:5px; width:550px;}
+.footer {font-size:9px; margin-top:10px; text-align:center; width:550px;}
+.disclaimer {background-color:#f9f9f9; border:1px solid #cccccc; font-size:10px; margin-top:10px; padding:5px; width:550px;}
+.disclaimer1 {color:#666666; padding:5px;}
+.disclaimer1 a:link {color:#666666;}
+.disclaimer1 a:visited {color:#666666;}
+.disclaimer2 {color:#666666; padding:5px;}
+.copyright {border-bottom:0px solid #9a9a9a; padding:5px;}
+</style>
+
+</head>
+
+<body>
+<div class="holder">
+
+
+ <!-- Content Section -->
+ <div class="content">
+ <div class="content-line">
+ ${EMAIL_STORE_NAME}<br /><br />
+ ${EMAIL_PRODUCT_TEXT}<br/>
+ </div>
+</div>
+
+</div>
+
+ <!-- Footer Section -->
+ <div class="footer">
+ <div class="copyright">${EMAIL_FOOTER_COPYRIGHT}</div>
+ </div>
+
+<div class="disclaimer">
+ <div class="disclaimer1">${EMAIL_DISCLAIMER}</div>
+ <div class="disclaimer2">${EMAIL_SPAM_DISCLAIMER}</div>
+</div>
+</body>
+</html>
diff --git a/sm-core/src/main/resources/templates/email/email_template_new_review.ftl b/sm-core/src/main/resources/templates/email/email_template_new_review.ftl
new file mode 100644
index 0000000..32ba63f
--- /dev/null
+++ b/sm-core/src/main/resources/templates/email/email_template_new_review.ftl
@@ -0,0 +1,52 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+
+
+<style type="text/css">
+body {background-color:#ffffff; color:#000000; font-family:Verdana, Arial, Helvetica, sans-serif; text-align:center;}
+a:link {color:#0066cc;}
+a:hover {background-color:#eeeecc; color:#0066cc;}
+a:visited {color:#0066cc;}
+.holder {background-color:#f9f9f9; border:1px solid #9a9a9a; font-size:9px; text-align:left; width:550px;}
+.header {font-size:10px; padding:0px; width:550px;}
+.content {font-size:10px; padding:5px; width:550px;}
+.footer {font-size:9px; margin-top:10px; text-align:center; width:550px;}
+.disclaimer {background-color:#f9f9f9; border:1px solid #cccccc; font-size:10px; margin-top:10px; padding:5px; width:550px;}
+.disclaimer1 {color:#666666; padding:5px;}
+.disclaimer1 a:link {color:#666666;}
+.disclaimer1 a:visited {color:#666666;}
+.disclaimer2 {color:#666666; padding:5px;}
+.copyright {border-bottom:0px solid #9a9a9a; padding:5px;}
+</style>
+
+</head>
+
+<body>
+<div class="holder">
+
+
+ <!-- Content Section -->
+ <div class="content">
+ <div class="content-line">
+ ${EMAIL_STORE_NAME}<br /><br /><br/>
+ ${EMAIL_SUBJECT} - ${EMAIL_PRODUCT_NAME}<br/>
+ ${EMAIL_CUSTOMER_REVIEW}<br/><br />
+ ${EMAIL_REVIEW_RATING}<br/><br/>
+ ${EMAIL_REVIEW_TEXT}<br/>
+ </div>
+</div>
+
+</div>
+
+ <!-- Footer Section -->
+ <div class="footer">
+ <div class="copyright">${EMAIL_FOOTER_COPYRIGHT}</div>
+ </div>
+
+<div class="disclaimer">
+ <div class="disclaimer1">${EMAIL_DISCLAIMER}</div>
+ <div class="disclaimer2">${EMAIL_SPAM_DISCLAIMER}</div>
+</div>
+</body>
+</html>
diff --git a/sm-core/src/main/resources/templates/email/email_template_new_store.ftl b/sm-core/src/main/resources/templates/email/email_template_new_store.ftl
new file mode 100644
index 0000000..c1c8f29
--- /dev/null
+++ b/sm-core/src/main/resources/templates/email/email_template_new_store.ftl
@@ -0,0 +1,50 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+
+
+<style type="text/css">
+body {background-color:#ffffff; color:#000000; font-family:Verdana, Arial, Helvetica, sans-serif; text-align:center;}
+a:link {color:#0066cc;}
+a:hover {background-color:#eeeecc; color:#0066cc;}
+a:visited {color:#0066cc;}
+.holder {background-color:#f9f9f9; border:1px solid #9a9a9a; font-size:9px; text-align:left; width:550px;}
+.header {font-size:10px; padding:0px; width:550px;}
+.content {font-size:10px; padding:5px; width:550px;}
+.footer {font-size:9px; margin-top:10px; text-align:center; width:550px;}
+.disclaimer {background-color:#f9f9f9; border:1px solid #cccccc; font-size:10px; margin-top:10px; padding:5px; width:550px;}
+.disclaimer1 {color:#666666; padding:5px;}
+.disclaimer1 a:link {color:#666666;}
+.disclaimer1 a:visited {color:#666666;}
+.disclaimer2 {color:#666666; padding:5px;}
+.copyright {border-bottom:0px solid #9a9a9a; padding:5px;}
+</style>
+
+</head>
+
+<body>
+<div class="holder">
+
+ <!-- Content Section -->
+ <div class="content">
+ <div class="content-line">
+ ${EMAIL_NEW_STORE_TEXT}<br /><br /><br />
+ ${EMAIL_STORE_NAME}<br /><br />
+ ${EMAIL_ADMIN_STORE_INFO_LABEL}<br/>
+ ${EMAIL_ADMIN_URL_LABEL}<br /><br />
+ </div>
+</div>
+
+</div>
+
+ <!-- Footer Section -->
+ <div class="footer">
+ <div class="copyright">${EMAIL_FOOTER_COPYRIGHT}</div>
+ </div>
+
+<div class="disclaimer">
+ <div class="disclaimer1">${EMAIL_DISCLAIMER}</div>
+ <div class="disclaimer2">${EMAIL_SPAM_DISCLAIMER}</div>
+</div>
+</body>
+</html>
diff --git a/sm-core/src/main/resources/templates/email/email_template_new_user.ftl b/sm-core/src/main/resources/templates/email/email_template_new_user.ftl
new file mode 100644
index 0000000..bda8dab
--- /dev/null
+++ b/sm-core/src/main/resources/templates/email/email_template_new_user.ftl
@@ -0,0 +1,52 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+
+
+<style type="text/css">
+body {background-color:#ffffff; color:#000000; font-family:Verdana, Arial, Helvetica, sans-serif; text-align:center;}
+a:link {color:#0066cc;}
+a:hover {background-color:#eeeecc; color:#0066cc;}
+a:visited {color:#0066cc;}
+.holder {background-color:#f9f9f9; border:1px solid #9a9a9a; font-size:9px; text-align:left; width:550px;}
+.header {font-size:10px; padding:0px; width:550px;}
+.content {font-size:10px; padding:5px; width:550px;}
+.footer {font-size:9px; margin-top:10px; text-align:center; width:550px;}
+.disclaimer {background-color:#f9f9f9; border:1px solid #cccccc; font-size:10px; margin-top:10px; padding:5px; width:550px;}
+.disclaimer1 {color:#666666; padding:5px;}
+.disclaimer1 a:link {color:#666666;}
+.disclaimer1 a:visited {color:#666666;}
+.disclaimer2 {color:#666666; padding:5px;}
+.copyright {border-bottom:0px solid #9a9a9a; padding:5px;}
+</style>
+
+</head>
+
+<body>
+<div class="holder">
+
+ <!-- Content Section -->
+ <div class="content">
+ <div class="content-line">
+ ${EMAIL_NEW_USER_TEXT}<br /><br />
+ ${EMAIL_STORE_NAME}<br /><br />
+ ${EMAIL_TEXT_NEW_USER_CREATED}<br/>
+ ${EMAIL_ADMIN_USERNAME_LABEL}: ${EMAIL_ADMIN_NAME}<br />
+ ${EMAIL_ADMIN_PASSWORD_LABEL}: ${EMAIL_ADMIN_PASSWORD}</br>
+ ${EMAIL_ADMIN_URL_LABEL}: ${EMAIL_ADMIN_URL}<br /><br />
+ </div>
+</div>
+
+</div>
+
+ <!-- Footer Section -->
+ <div class="footer">
+ <div class="copyright">${EMAIL_FOOTER_COPYRIGHT}</div>
+ </div>
+
+<div class="disclaimer">
+ <div class="disclaimer1">${EMAIL_DISCLAIMER}</div>
+ <div class="disclaimer2">${EMAIL_SPAM_DISCLAIMER}</div>
+</div>
+</body>
+</html>
diff --git a/sm-core/src/main/resources/templates/email/email_template_notification.ftl b/sm-core/src/main/resources/templates/email/email_template_notification.ftl
new file mode 100644
index 0000000..939f97a
--- /dev/null
+++ b/sm-core/src/main/resources/templates/email/email_template_notification.ftl
@@ -0,0 +1,326 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<!-- If you delete this meta tag, Half Life 3 will never be released. -->
+<meta name="viewport" content="width=device-width" />
+
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title></title>
+
+<style type="text/css">
+
+
+/* -------------------------------------
+ GLOBAL
+------------------------------------- */
+* {
+ margin:0;
+ padding:0;
+}
+* { font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; }
+
+img {
+ max-width: 100%;
+}
+.collapse {
+ margin:0;
+ padding:0;
+}
+body {
+ -webkit-font-smoothing:antialiased;
+ -webkit-text-size-adjust:none;
+ width: 100%!important;
+ height: 100%;
+}
+
+
+/* -------------------------------------
+ ELEMENTS
+------------------------------------- */
+a { color: #2BA6CB;}
+
+.btn {
+ text-decoration:none;
+ color: #FFF;
+ background-color: #666;
+ padding:10px 16px;
+ font-weight:bold;
+ margin-right:10px;
+ text-align:center;
+ cursor:pointer;
+ display: inline-block;
+}
+
+p.callout {
+ padding:15px;
+ background-color:#ECF8FF;
+ margin-bottom: 15px;
+}
+.callout a {
+ font-weight:bold;
+ color: #2BA6CB;
+}
+
+table.social {
+/* padding:15px; */
+ background-color: #ebebeb;
+
+}
+.social .soc-btn {
+ padding: 3px 7px;
+ font-size:12px;
+ margin-bottom:10px;
+ text-decoration:none;
+ color: #FFF;font-weight:bold;
+ display:block;
+ text-align:center;
+}
+a.fb { background-color: #3B5998!important; }
+a.tw { background-color: #1daced!important; }
+a.gp { background-color: #DB4A39!important; }
+a.ms { background-color: #000!important; }
+
+.sidebar .soc-btn {
+ display:block;
+ width:100%;
+}
+
+/* -------------------------------------
+ HEADER
+------------------------------------- */
+table.head-wrap { width: 100%;}
+
+.header.container table td.logo { padding: 15px; }
+.header.container table td.label { padding: 15px; padding-left:0px;}
+
+
+/* -------------------------------------
+ BODY
+------------------------------------- */
+table.body-wrap { width: 100%;}
+
+
+/* -------------------------------------
+ FOOTER
+------------------------------------- */
+table.footer-wrap { width: 100%; clear:both!important;
+}
+.footer-wrap .container td.content p { border-top: 1px solid rgb(215,215,215); padding-top:15px;}
+.footer-wrap .container td.content p {
+ font-size:10px;
+ font-weight: bold;
+
+}
+
+
+/* -------------------------------------
+ TYPOGRAPHY
+------------------------------------- */
+h1,h2,h3,h4,h5,h6 {
+font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 1.1; margin-bottom:15px; color:#000;
+}
+h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { font-size: 60%; color: #6f6f6f; line-height: 0; text-transform: none; }
+
+h1 { font-weight:200; font-size: 44px;}
+h2 { font-weight:200; font-size: 37px;}
+h3 { font-weight:500; font-size: 27px;}
+h4 { font-weight:500; font-size: 23px;}
+h5 { font-weight:900; font-size: 17px;}
+h6 { font-weight:900; font-size: 14px; text-transform: uppercase; color:#444;}
+
+.collapse { margin:0!important;}
+
+p, ul {
+ margin-bottom: 10px;
+ font-weight: normal;
+ font-size:14px;
+ line-height:1.6;
+}
+p.lead { font-size:17px; }
+p.last { margin-bottom:0px;}
+
+ul li {
+ margin-left:5px;
+ list-style-position: inside;
+}
+
+/* -------------------------------------
+ SIDEBAR
+------------------------------------- */
+ul.sidebar {
+ background:#ebebeb;
+ display:block;
+ list-style-type: none;
+}
+ul.sidebar li { display: block; margin:0;}
+ul.sidebar li a {
+ text-decoration:none;
+ color: #666;
+ padding:10px 16px;
+/* font-weight:bold; */
+ margin-right:10px;
+/* text-align:center; */
+ cursor:pointer;
+ border-bottom: 1px solid #777777;
+ border-top: 1px solid #FFFFFF;
+ display:block;
+ margin:0;
+}
+ul.sidebar li a.last { border-bottom-width:0px;}
+ul.sidebar li a h1,ul.sidebar li a h2,ul.sidebar li a h3,ul.sidebar li a h4,ul.sidebar li a h5,ul.sidebar li a h6,ul.sidebar li a p { margin-bottom:0!important;}
+
+
+
+/* ---------------------------------------------------
+ RESPONSIVENESS
+ Nuke it from orbit. It's the only way to be sure.
+------------------------------------------------------ */
+
+/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
+.container {
+ display:block!important;
+ max-width:600px!important;
+ margin:0 auto!important; /* makes it centered */
+ clear:both!important;
+}
+
+/* This should also be a block element, so that it will fill 100% of the .container */
+.content {
+ padding:15px;
+ max-width:600px;
+ margin:0 auto;
+ display:block;
+}
+
+/* Let's make sure tables in the content area are 100% wide */
+.content table { width: 100%; }
+
+
+/* Odds and ends */
+.column {
+ width: 300px;
+ float:left;
+}
+.column tr td { padding: 15px; }
+.column-wrap {
+ padding:0!important;
+ margin:0 auto;
+ max-width:600px!important;
+}
+.column table { width:100%;}
+.social .column {
+ width: 280px;
+ min-width: 279px;
+ float:left;
+}
+
+/* Be sure to place a .clear element after each set of columns, just to be safe */
+.clear { display: block; clear: both; }
+
+
+/* -------------------------------------------
+ PHONE
+ For clients that support media queries.
+ Nothing fancy.
+-------------------------------------------- */
+@media only screen and (max-width: 600px) {
+
+ a[class="btn"] { display:block!important; margin-bottom:10px!important; background-image:none!important; margin-right:0!important;}
+
+ div[class="column"] { width: auto!important; float:none!important;}
+
+ table.social div[class="column"] {
+ width:auto!important;
+ }
+
+}
+
+</style>
+
+</head>
+<body bgcolor="#FFFFFF">
+
+<!-- HEADER -->
+<table class="head-wrap">
+ <tr>
+ <td></td>
+ <td class="header container" >
+
+ <p>
+ <table>
+ <tr>
+ <td>
+ <h3>${LOGOPATH}</h3>
+ </td>
+ </tr>
+ </table>
+ </p>
+
+ </td>
+ <td></td>
+ </tr>
+</table>
+<!-- /HEADER -->
+
+
+<!-- BODY -->
+<table class="body-wrap">
+ <tr>
+ <td></td>
+ <td class="container" bgcolor="#FFFFFF">
+
+ <div class="content">
+ <table>
+ <tr>
+ <td>
+ <p class="lead">
+ <h4>${LABEL_HI} ${EMAIL_CUSTOMER_FIRSTNAME} ${EMAIL_CUSTOMER_LASTNAME}<br/></h4>
+ </p>
+ <p>
+ ${EMAIL_NOTIFICATION_MESSAGE}<br />
+
+ </p>
+ </td>
+ </tr>
+ </table>
+ </div><!-- /content -->
+
+ </td>
+ <td></td>
+ </tr>
+</table><!-- /BODY -->
+
+<!-- FOOTER -->
+<table class="footer-wrap">
+ <tr>
+ <td></td>
+ <td class="container">
+
+ <!-- content -->
+ <div class="content">
+ <p>
+ <table>
+ <tr>
+ <td align="center">
+ <p>
+ ${EMAIL_DISCLAIMER}
+ </p>
+ <p>
+ ${EMAIL_SPAM_DISCLAIMER}
+ </p>
+ <p>
+ ${EMAIL_FOOTER_COPYRIGHT}
+ </p>
+ </td>
+ </tr>
+ </table>
+ </p>
+ </div><!-- /content -->
+
+ </td>
+ <td></td>
+ </tr>
+</table><!-- /FOOTER -->
+
+</body>
+</html>
diff --git a/sm-core/src/main/resources/templates/email/email_template_order_status.ftl b/sm-core/src/main/resources/templates/email/email_template_order_status.ftl
new file mode 100644
index 0000000..27dc2a8
--- /dev/null
+++ b/sm-core/src/main/resources/templates/email/email_template_order_status.ftl
@@ -0,0 +1,332 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<!-- If you delete this meta tag, Half Life 3 will never be released. -->
+<meta name="viewport" content="width=device-width" />
+
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title></title>
+
+<style type="text/css">
+
+
+/* -------------------------------------
+ GLOBAL
+------------------------------------- */
+* {
+ margin:0;
+ padding:0;
+}
+* { font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; }
+
+img {
+ max-width: 100%;
+}
+.collapse {
+ margin:0;
+ padding:0;
+}
+body {
+ -webkit-font-smoothing:antialiased;
+ -webkit-text-size-adjust:none;
+ width: 100%!important;
+ height: 100%;
+}
+
+
+/* -------------------------------------
+ ELEMENTS
+------------------------------------- */
+a { color: #2BA6CB;}
+
+.btn {
+ text-decoration:none;
+ color: #FFF;
+ background-color: #666;
+ padding:10px 16px;
+ font-weight:bold;
+ margin-right:10px;
+ text-align:center;
+ cursor:pointer;
+ display: inline-block;
+}
+
+p.callout {
+ padding:15px;
+ background-color:#ECF8FF;
+ margin-bottom: 15px;
+}
+.callout a {
+ font-weight:bold;
+ color: #2BA6CB;
+}
+
+table.social {
+/* padding:15px; */
+ background-color: #ebebeb;
+
+}
+.social .soc-btn {
+ padding: 3px 7px;
+ font-size:12px;
+ margin-bottom:10px;
+ text-decoration:none;
+ color: #FFF;font-weight:bold;
+ display:block;
+ text-align:center;
+}
+a.fb { background-color: #3B5998!important; }
+a.tw { background-color: #1daced!important; }
+a.gp { background-color: #DB4A39!important; }
+a.ms { background-color: #000!important; }
+
+.sidebar .soc-btn {
+ display:block;
+ width:100%;
+}
+
+/* -------------------------------------
+ HEADER
+------------------------------------- */
+table.head-wrap { width: 100%;}
+
+.header.container table td.logo { padding: 15px; }
+.header.container table td.label { padding: 15px; padding-left:0px;}
+
+
+/* -------------------------------------
+ BODY
+------------------------------------- */
+table.body-wrap { width: 100%;}
+
+
+/* -------------------------------------
+ FOOTER
+------------------------------------- */
+table.footer-wrap { width: 100%; clear:both!important;
+}
+.footer-wrap .container td.content p { border-top: 1px solid rgb(215,215,215); padding-top:15px;}
+.footer-wrap .container td.content p {
+ font-size:10px;
+ font-weight: bold;
+
+}
+
+
+/* -------------------------------------
+ TYPOGRAPHY
+------------------------------------- */
+h1,h2,h3,h4,h5,h6 {
+font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 1.1; margin-bottom:15px; color:#000;
+}
+h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { font-size: 60%; color: #6f6f6f; line-height: 0; text-transform: none; }
+
+h1 { font-weight:200; font-size: 44px;}
+h2 { font-weight:200; font-size: 37px;}
+h3 { font-weight:500; font-size: 27px;}
+h4 { font-weight:500; font-size: 23px;}
+h5 { font-weight:900; font-size: 17px;}
+h6 { font-weight:900; font-size: 14px; text-transform: uppercase; color:#444;}
+
+.collapse { margin:0!important;}
+
+p, ul {
+ margin-bottom: 10px;
+ font-weight: normal;
+ font-size:14px;
+ line-height:1.6;
+}
+p.lead { font-size:17px; }
+p.last { margin-bottom:0px;}
+
+ul li {
+ margin-left:5px;
+ list-style-position: inside;
+}
+
+/* -------------------------------------
+ SIDEBAR
+------------------------------------- */
+ul.sidebar {
+ background:#ebebeb;
+ display:block;
+ list-style-type: none;
+}
+ul.sidebar li { display: block; margin:0;}
+ul.sidebar li a {
+ text-decoration:none;
+ color: #666;
+ padding:10px 16px;
+/* font-weight:bold; */
+ margin-right:10px;
+/* text-align:center; */
+ cursor:pointer;
+ border-bottom: 1px solid #777777;
+ border-top: 1px solid #FFFFFF;
+ display:block;
+ margin:0;
+}
+ul.sidebar li a.last { border-bottom-width:0px;}
+ul.sidebar li a h1,ul.sidebar li a h2,ul.sidebar li a h3,ul.sidebar li a h4,ul.sidebar li a h5,ul.sidebar li a h6,ul.sidebar li a p { margin-bottom:0!important;}
+
+
+
+/* ---------------------------------------------------
+ RESPONSIVENESS
+ Nuke it from orbit. It's the only way to be sure.
+------------------------------------------------------ */
+
+/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
+.container {
+ display:block!important;
+ max-width:600px!important;
+ margin:0 auto!important; /* makes it centered */
+ clear:both!important;
+}
+
+/* This should also be a block element, so that it will fill 100% of the .container */
+.content {
+ padding:15px;
+ max-width:600px;
+ margin:0 auto;
+ display:block;
+}
+
+/* Let's make sure tables in the content area are 100% wide */
+.content table { width: 100%; }
+
+
+/* Odds and ends */
+.column {
+ width: 300px;
+ float:left;
+}
+.column tr td { padding: 15px; }
+.column-wrap {
+ padding:0!important;
+ margin:0 auto;
+ max-width:600px!important;
+}
+.column table { width:100%;}
+.social .column {
+ width: 280px;
+ min-width: 279px;
+ float:left;
+}
+
+/* Be sure to place a .clear element after each set of columns, just to be safe */
+.clear { display: block; clear: both; }
+
+
+/* -------------------------------------------
+ PHONE
+ For clients that support media queries.
+ Nothing fancy.
+-------------------------------------------- */
+@media only screen and (max-width: 600px) {
+
+ a[class="btn"] { display:block!important; margin-bottom:10px!important; background-image:none!important; margin-right:0!important;}
+
+ div[class="column"] { width: auto!important; float:none!important;}
+
+ table.social div[class="column"] {
+ width:auto!important;
+ }
+
+}
+
+</style>
+
+</head>
+<body bgcolor="#FFFFFF">
+
+<!-- HEADER -->
+<table class="head-wrap">
+ <tr>
+ <td></td>
+ <td class="header container" >
+
+ <p>
+ <table>
+ <tr>
+ <td>
+ <h3>${LOGOPATH}</h3>
+ </td>
+ </tr>
+ </table>
+ </p>
+
+ </td>
+ <td></td>
+ </tr>
+</table>
+<!-- /HEADER -->
+
+
+<!-- BODY -->
+<table class="body-wrap">
+ <tr>
+ <td></td>
+ <td class="container" bgcolor="#FFFFFF">
+
+ <div class="content">
+ <table>
+ <tr>
+ <td>
+ <h4>${LABEL_HI} ${EMAIL_CUSTOMER_FIRSTNAME} ${EMAIL_CUSTOMER_LASTNAME}<br/></h4>
+ <p class="lead">
+ ${EMAIL_ORDER_STATUS_TEXT}
+ </p>
+ <p>
+ ${EMAIL_ORDER_STATUS}
+ </p>
+ <!-- Callout Panel -->
+ <p class="callout">
+ ${EMAIL_TEXT_STATUS_COMMENTS}
+ </p><!-- /Callout Panel -->
+
+
+ </td>
+ </tr>
+ </table>
+ </div><!-- /content -->
+
+ </td>
+ <td></td>
+ </tr>
+</table><!-- /BODY -->
+
+<!-- FOOTER -->
+<table class="footer-wrap">
+ <tr>
+ <td></td>
+ <td class="container">
+
+ <!-- content -->
+ <div class="content">
+ <p>
+ <table>
+ <tr>
+ <td align="center">
+ <p>
+ ${EMAIL_DISCLAIMER}
+ </p>
+ <p>
+ ${EMAIL_SPAM_DISCLAIMER}
+ </p>
+ <p>
+ ${EMAIL_FOOTER_COPYRIGHT}
+ </p>
+ </td>
+ </tr>
+ </table>
+ </p>
+ </div><!-- /content -->
+
+ </td>
+ <td></td>
+ </tr>
+</table><!-- /FOOTER -->
+
+</body>
+</html>
diff --git a/sm-core/src/main/resources/templates/email/email_template_outofstock.ftl b/sm-core/src/main/resources/templates/email/email_template_outofstock.ftl
new file mode 100644
index 0000000..bd9957f
--- /dev/null
+++ b/sm-core/src/main/resources/templates/email/email_template_outofstock.ftl
@@ -0,0 +1,49 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+
+
+<style type="text/css">
+body {background-color:#ffffff; color:#000000; font-family:Verdana, Arial, Helvetica, sans-serif; text-align:center;}
+a:link {color:#0066cc;}
+a:hover {background-color:#eeeecc; color:#0066cc;}
+a:visited {color:#0066cc;}
+.holder {background-color:#f9f9f9; border:1px solid #9a9a9a; font-size:9px; text-align:left; width:550px;}
+.header {font-size:10px; padding:0px; width:550px;}
+.content {font-size:10px; padding:5px; width:550px;}
+.footer {font-size:9px; margin-top:10px; text-align:center; width:550px;}
+.disclaimer {background-color:#f9f9f9; border:1px solid #cccccc; font-size:10px; margin-top:10px; padding:5px; width:550px;}
+.disclaimer1 {color:#666666; padding:5px;}
+.disclaimer1 a:link {color:#666666;}
+.disclaimer1 a:visited {color:#666666;}
+.disclaimer2 {color:#666666; padding:5px;}
+.copyright {border-bottom:0px solid #9a9a9a; padding:5px;}
+</style>
+
+</head>
+
+<body>
+<div class="holder">
+
+
+ <!-- Content Section -->
+ <div class="content">
+ <div class="content-line">
+ ${EMAIL_STORE_NAME}<br /><br />
+ ${EMAIL_PRODUCT_TEXT}<br/>
+ </div>
+</div>
+
+</div>
+
+ <!-- Footer Section -->
+ <div class="footer">
+ <div class="copyright">${EMAIL_FOOTER_COPYRIGHT}</div>
+ </div>
+
+<div class="disclaimer">
+ <div class="disclaimer1">${EMAIL_DISCLAIMER}</div>
+ <div class="disclaimer2">${EMAIL_SPAM_DISCLAIMER}</div>
+</div>
+</body>
+</html>
diff --git a/sm-core/src/main/resources/templates/email/email_template_password_reset_customer.ftl b/sm-core/src/main/resources/templates/email/email_template_password_reset_customer.ftl
new file mode 100644
index 0000000..467fdf0
--- /dev/null
+++ b/sm-core/src/main/resources/templates/email/email_template_password_reset_customer.ftl
@@ -0,0 +1,334 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<!-- If you delete this meta tag, Half Life 3 will never be released. -->
+<meta name="viewport" content="width=device-width" />
+
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<title></title>
+
+<style type="text/css">
+
+
+/* -------------------------------------
+ GLOBAL
+------------------------------------- */
+* {
+ margin:0;
+ padding:0;
+}
+* { font-family: "Helvetica Neue", "Helvetica", Helvetica, Arial, sans-serif; }
+
+img {
+ max-width: 100%;
+}
+.collapse {
+ margin:0;
+ padding:0;
+}
+body {
+ -webkit-font-smoothing:antialiased;
+ -webkit-text-size-adjust:none;
+ width: 100%!important;
+ height: 100%;
+}
+
+
+/* -------------------------------------
+ ELEMENTS
+------------------------------------- */
+a { color: #2BA6CB;}
+
+.btn {
+ text-decoration:none;
+ color: #FFF;
+ background-color: #666;
+ padding:10px 16px;
+ font-weight:bold;
+ margin-right:10px;
+ text-align:center;
+ cursor:pointer;
+ display: inline-block;
+}
+
+p.callout {
+ padding:15px;
+ background-color:#ECF8FF;
+ margin-bottom: 15px;
+}
+.callout a {
+ font-weight:bold;
+ color: #2BA6CB;
+}
+
+table.social {
+/* padding:15px; */
+ background-color: #ebebeb;
+
+}
+.social .soc-btn {
+ padding: 3px 7px;
+ font-size:12px;
+ margin-bottom:10px;
+ text-decoration:none;
+ color: #FFF;font-weight:bold;
+ display:block;
+ text-align:center;
+}
+a.fb { background-color: #3B5998!important; }
+a.tw { background-color: #1daced!important; }
+a.gp { background-color: #DB4A39!important; }
+a.ms { background-color: #000!important; }
+
+.sidebar .soc-btn {
+ display:block;
+ width:100%;
+}
+
+/* -------------------------------------
+ HEADER
+------------------------------------- */
+table.head-wrap { width: 100%;}
+
+.header.container table td.logo { padding: 15px; }
+.header.container table td.label { padding: 15px; padding-left:0px;}
+
+
+/* -------------------------------------
+ BODY
+------------------------------------- */
+table.body-wrap { width: 100%;}
+
+
+/* -------------------------------------
+ FOOTER
+------------------------------------- */
+table.footer-wrap { width: 100%; clear:both!important;
+}
+.footer-wrap .container td.content p { border-top: 1px solid rgb(215,215,215); padding-top:15px;}
+.footer-wrap .container td.content p {
+ font-size:10px;
+ font-weight: bold;
+
+}
+
+
+/* -------------------------------------
+ TYPOGRAPHY
+------------------------------------- */
+h1,h2,h3,h4,h5,h6 {
+font-family: "HelveticaNeue-Light", "Helvetica Neue Light", "Helvetica Neue", Helvetica, Arial, "Lucida Grande", sans-serif; line-height: 1.1; margin-bottom:15px; color:#000;
+}
+h1 small, h2 small, h3 small, h4 small, h5 small, h6 small { font-size: 60%; color: #6f6f6f; line-height: 0; text-transform: none; }
+
+h1 { font-weight:200; font-size: 44px;}
+h2 { font-weight:200; font-size: 37px;}
+h3 { font-weight:500; font-size: 27px;}
+h4 { font-weight:500; font-size: 23px;}
+h5 { font-weight:900; font-size: 17px;}
+h6 { font-weight:900; font-size: 14px; text-transform: uppercase; color:#444;}
+
+.collapse { margin:0!important;}
+
+p, ul {
+ margin-bottom: 10px;
+ font-weight: normal;
+ font-size:14px;
+ line-height:1.6;
+}
+p.lead { font-size:17px; }
+p.last { margin-bottom:0px;}
+
+ul li {
+ margin-left:5px;
+ list-style-position: inside;
+}
+
+/* -------------------------------------
+ SIDEBAR
+------------------------------------- */
+ul.sidebar {
+ background:#ebebeb;
+ display:block;
+ list-style-type: none;
+}
+ul.sidebar li { display: block; margin:0;}
+ul.sidebar li a {
+ text-decoration:none;
+ color: #666;
+ padding:10px 16px;
+/* font-weight:bold; */
+ margin-right:10px;
+/* text-align:center; */
+ cursor:pointer;
+ border-bottom: 1px solid #777777;
+ border-top: 1px solid #FFFFFF;
+ display:block;
+ margin:0;
+}
+ul.sidebar li a.last { border-bottom-width:0px;}
+ul.sidebar li a h1,ul.sidebar li a h2,ul.sidebar li a h3,ul.sidebar li a h4,ul.sidebar li a h5,ul.sidebar li a h6,ul.sidebar li a p { margin-bottom:0!important;}
+
+
+
+/* ---------------------------------------------------
+ RESPONSIVENESS
+ Nuke it from orbit. It's the only way to be sure.
+------------------------------------------------------ */
+
+/* Set a max-width, and make it display as block so it will automatically stretch to that width, but will also shrink down on a phone or something */
+.container {
+ display:block!important;
+ max-width:600px!important;
+ margin:0 auto!important; /* makes it centered */
+ clear:both!important;
+}
+
+/* This should also be a block element, so that it will fill 100% of the .container */
+.content {
+ padding:15px;
+ max-width:600px;
+ margin:0 auto;
+ display:block;
+}
+
+/* Let's make sure tables in the content area are 100% wide */
+.content table { width: 100%; }
+
+
+/* Odds and ends */
+.column {
+ width: 300px;
+ float:left;
+}
+.column tr td { padding: 15px; }
+.column-wrap {
+ padding:0!important;
+ margin:0 auto;
+ max-width:600px!important;
+}
+.column table { width:100%;}
+.social .column {
+ width: 280px;
+ min-width: 279px;
+ float:left;
+}
+
+/* Be sure to place a .clear element after each set of columns, just to be safe */
+.clear { display: block; clear: both; }
+
+
+/* -------------------------------------------
+ PHONE
+ For clients that support media queries.
+ Nothing fancy.
+-------------------------------------------- */
+@media only screen and (max-width: 600px) {
+
+ a[class="btn"] { display:block!important; margin-bottom:10px!important; background-image:none!important; margin-right:0!important;}
+
+ div[class="column"] { width: auto!important; float:none!important;}
+
+ table.social div[class="column"] {
+ width:auto!important;
+ }
+
+}
+
+</style>
+
+</head>
+
+
+<body bgcolor="#FFFFFF">
+
+<!-- HEADER -->
+<table class="head-wrap">
+ <tr>
+ <td></td>
+ <td class="header container" >
+
+ <p>
+ <table>
+ <tr>
+ <td>
+ ${LOGOPATH}
+ </td>
+ </tr>
+ </table>
+ </p>
+
+ </td>
+ <td></td>
+ </tr>
+</table>
+<!-- /HEADER -->
+
+<!-- BODY -->
+<table class="body-wrap">
+ <tr>
+ <td></td>
+ <td class="container" bgcolor="#FFFFFF">
+
+ <div class="content">
+ <table>
+ <tr>
+ <td>
+ <h4>${LABEL_HI} ${EMAIL_CUSTOMER_FIRSTNAME} ${EMAIL_CUSTOMER_LASTNAME}<br/></h4>
+ <p class="lead">
+ ${EMAIL_RESET_PASSWORD_TXT}
+ </p>
+ <p>
+ ${EMAIL_PASSWORD_LABEL}: ${EMAIL_CUSTOMER_PASSWORD}<br />
+
+ </p>
+ <!-- Callout Panel -->
+ <p class="callout">
+ ${EMAIL_CONTACT_OWNER}
+ </p><!-- /Callout Panel -->
+
+
+ </td>
+ </tr>
+ </table>
+ </div><!-- /content -->
+
+ </td>
+ <td></td>
+ </tr>
+</table><!-- /BODY -->
+
+<!-- FOOTER -->
+<table class="footer-wrap">
+ <tr>
+ <td></td>
+ <td class="container">
+
+ <!-- content -->
+ <div class="content">
+ <p>
+ <table>
+ <tr>
+ <td align="center">
+ <p>
+ ${EMAIL_DISCLAIMER}
+ </p>
+ <p>
+ ${EMAIL_SPAM_DISCLAIMER}
+ </p>
+ <p>
+ ${EMAIL_FOOTER_COPYRIGHT}
+ </p>
+ </td>
+ </tr>
+ </table>
+ </p>
+ </div><!-- /content -->
+
+ </td>
+ <td></td>
+ </tr>
+</table><!-- /FOOTER -->
+
+</body>
+</html>
\ No newline at end of file
diff --git a/sm-core/src/main/resources/templates/email/email_template_password_reset_user.ftl b/sm-core/src/main/resources/templates/email/email_template_password_reset_user.ftl
new file mode 100644
index 0000000..57cfaa3
--- /dev/null
+++ b/sm-core/src/main/resources/templates/email/email_template_password_reset_user.ftl
@@ -0,0 +1,54 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+
+
+<style type="text/css">
+body {background-color:#ffffff; color:#000000; font-family:Verdana, Arial, Helvetica, sans-serif; text-align:center;}
+a:link {color:#0066cc;}
+a:hover {background-color:#eeeecc; color:#0066cc;}
+a:visited {color:#0066cc;}
+.holder {background-color:#f9f9f9; border:1px solid #9a9a9a; font-size:9px; text-align:left; width:550px;}
+.header {font-size:10px; padding:0px; width:550px;}
+.content {font-size:10px; padding:5px; width:550px;}
+.footer {font-size:9px; margin-top:10px; text-align:center; width:550px;}
+.disclaimer {background-color:#f9f9f9; border:1px solid #cccccc; font-size:10px; margin-top:10px; padding:5px; width:550px;}
+.disclaimer1 {color:#666666; padding:5px;}
+.disclaimer1 a:link {color:#666666;}
+.disclaimer1 a:visited {color:#666666;}
+.disclaimer2 {color:#666666; padding:5px;}
+.copyright {border-bottom:0px solid #9a9a9a; padding:5px;}
+</style>
+
+</head>
+
+<body>
+<div class="holder">
+
+ <!-- Header Section -->
+ ${LOGOPATH}
+
+
+ <!-- Content Section -->
+ <div class="content">
+ <div class="content-line">
+ ${EMAIL_STORE_NAME}<br /><br />
+ <p>${EMAIL_RESET_PASSWORD_TXT}</p><br/>
+ ${EMAIL_PASSWORD_LABEL}: ${EMAIL_USER_PASSWORD}<br /><br />
+ ${EMAIL_CONTACT_OWNER}
+ </div>
+</div>
+
+</div>
+
+ <!-- Footer Section -->
+ <div class="footer">
+ <div class="copyright">${EMAIL_FOOTER_COPYRIGHT}</div>
+ </div>
+
+<div class="disclaimer">
+ <div class="disclaimer1">${EMAIL_DISCLAIMER}</div>
+ <div class="disclaimer2">${EMAIL_SPAM_DISCLAIMER}</div>
+</div>
+</body>
+</html>
diff --git a/sm-core/src/main/resources/templates/email/email_template_sentinvoice.ftl b/sm-core/src/main/resources/templates/email/email_template_sentinvoice.ftl
new file mode 100644
index 0000000..ba563a3
--- /dev/null
+++ b/sm-core/src/main/resources/templates/email/email_template_sentinvoice.ftl
@@ -0,0 +1,55 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+
+
+<style type="text/css">
+body {background-color:#ffffff; color:#000000; font-family:Verdana, Arial, Helvetica, sans-serif; text-align:center;}
+a:link {color:#0066cc;}
+a:hover {background-color:#eeeecc; color:#0066cc;}
+a:visited {color:#0066cc;}
+.holder {background-color:#f9f9f9; border:1px solid #9a9a9a; font-size:9px; text-align:left; width:550px;}
+.header {font-size:10px; padding:0px; width:550px;}
+.content {font-size:10px; padding:5px; width:550px;}
+.footer {font-size:9px; margin-top:10px; text-align:center; width:550px;}
+.disclaimer {background-color:#f9f9f9; border:1px solid #cccccc; font-size:10px; margin-top:10px; padding:5px; width:550px;}
+.disclaimer1 {color:#666666; padding:5px;}
+.disclaimer1 a:link {color:#666666;}
+.disclaimer1 a:visited {color:#666666;}
+.disclaimer2 {color:#666666; padding:5px;}
+.copyright {border-bottom:0px solid #9a9a9a; padding:5px;}
+</style>
+
+</head>
+
+<body>
+<div class="holder">
+
+ <!-- Header Section -->
+ ${LOGOPATH}
+
+
+ <!-- Content Section -->
+ <div class="content">
+ <div class="content-line">
+ ${EMAIL_STORE_NAME}<br /><br />
+ ${EMAIL_GREETING} ${EMAIL_CUSTOMER_NAME}<br/><br/>
+ ${EMAIL_INVOICE_MESSAGE}<br /><br />
+ ${EMAIL_INVOICE_PAYMENT_URL}<br /><br />
+ ${EMAIL_CONTACT_OWNER}
+ </div>
+</div>
+
+</div>
+
+ <!-- Footer Section -->
+ <div class="footer">
+ <div class="copyright">${EMAIL_FOOTER_COPYRIGHT}</div>
+ </div>
+
+<div class="disclaimer">
+ <div class="disclaimer1">${EMAIL_DISCLAIMER}</div>
+ <div class="disclaimer2">${EMAIL_SPAM_DISCLAIMER}</div>
+</div>
+</body>
+</html>
diff --git a/sm-core/src/main/resources/templates/email/email_template_user_password_link.ftl b/sm-core/src/main/resources/templates/email/email_template_user_password_link.ftl
new file mode 100644
index 0000000..02cef50
--- /dev/null
+++ b/sm-core/src/main/resources/templates/email/email_template_user_password_link.ftl
@@ -0,0 +1,49 @@
+<html>
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+
+
+<style type="text/css">
+body {background-color:#ffffff; color:#000000; font-family:Verdana, Arial, Helvetica, sans-serif; text-align:center;}
+a:link {color:#0066cc;}
+a:hover {background-color:#eeeecc; color:#0066cc;}
+a:visited {color:#0066cc;}
+.holder {background-color:#f9f9f9; border:1px solid #9a9a9a; font-size:9px; text-align:left; width:550px;}
+.header {font-size:10px; padding:0px; width:550px;}
+.content {font-size:10px; padding:5px; width:550px;}
+.footer {font-size:9px; margin-top:10px; text-align:center; width:550px;}
+.disclaimer {background-color:#f9f9f9; border:1px solid #cccccc; font-size:10px; margin-top:10px; padding:5px; width:550px;}
+.disclaimer1 {color:#666666; padding:5px;}
+.disclaimer1 a:link {color:#666666;}
+.disclaimer1 a:visited {color:#666666;}
+.disclaimer2 {color:#666666; padding:5px;}
+.copyright {border-bottom:0px solid #9a9a9a; padding:5px;}
+</style>
+
+</head>
+
+<body>
+<div class="holder">
+
+ <!-- Content Section -->
+ <div class="content">
+ <div class="content-line">
+ ${EMAIL_PASSWORD_TEXT}<br /><br /><br />
+ ${EMAIL_PASSWORD_LINK}<br /><br />
+ <br /><br />
+ </div>
+</div>
+
+</div>
+
+ <!-- Footer Section -->
+ <div class="footer">
+ <div class="copyright">${EMAIL_FOOTER_COPYRIGHT}</div>
+ </div>
+
+<div class="disclaimer">
+ <div class="disclaimer1">${EMAIL_DISCLAIMER}</div>
+ <div class="disclaimer2">${EMAIL_SPAM_DISCLAIMER}</div>
+</div>
+</body>
+</html>
diff --git a/sm-core/src/main/resources/templates/invoice/Invoice.ods b/sm-core/src/main/resources/templates/invoice/Invoice.ods
new file mode 100755
index 0000000..f936419
Binary files /dev/null and b/sm-core/src/main/resources/templates/invoice/Invoice.ods differ
diff --git a/sm-core/src/main/resources/templates/invoice/Invoice_fr.ods b/sm-core/src/main/resources/templates/invoice/Invoice_fr.ods
new file mode 100644
index 0000000..6c453a5
Binary files /dev/null and b/sm-core/src/main/resources/templates/invoice/Invoice_fr.ods differ
diff --git a/sm-core/src/test/java/com/salesmanager/test/catalog/CatalogSalesManagerTestCase.java b/sm-core/src/test/java/com/salesmanager/test/catalog/CatalogSalesManagerTestCase.java
new file mode 100644
index 0000000..32cb331
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/catalog/CatalogSalesManagerTestCase.java
@@ -0,0 +1,708 @@
+package com.salesmanager.test.catalog;
+
+import java.math.BigDecimal;
+import java.sql.Date;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.salesmanager.core.business.catalog.category.model.Category;
+import com.salesmanager.core.business.catalog.category.model.CategoryDescription;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOption;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionDescription;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionType;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionValue;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionValueDescription;
+import com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability;
+import com.salesmanager.core.business.catalog.product.model.description.ProductDescription;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.Manufacturer;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.ManufacturerDescription;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPrice;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPriceDescription;
+import com.salesmanager.core.business.catalog.product.model.review.ProductReview;
+import com.salesmanager.core.business.catalog.product.model.review.ProductReviewDescription;
+import com.salesmanager.core.business.catalog.product.model.type.ProductType;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.test.core.AbstractSalesManagerCoreTestCase;
+
+public class CatalogSalesManagerTestCase extends AbstractSalesManagerCoreTestCase {
+
+ private static final Date date = new Date(System.currentTimeMillis());
+
+ /**
+ * This method creates multiple products using multiple catelog APIs
+ * @throws ServiceException
+ */
+ @Test
+ public void testCreateProduct() throws ServiceException {
+
+ Language en = languageService.getByCode("en");
+ Language fr = languageService.getByCode("fr");
+
+ MerchantStore store = merchantService.getByCode(MerchantStore.DEFAULT_STORE);
+ ProductType generalType = productTypeService.getProductType(ProductType.GENERAL_TYPE);
+
+ Category book = new Category();
+ book.setMerchantStore(store);
+ book.setCode("book");
+
+ CategoryDescription bookEnglishDescription = new CategoryDescription();
+ bookEnglishDescription.setName("Book");
+ bookEnglishDescription.setCategory(book);
+ bookEnglishDescription.setLanguage(en);
+
+ CategoryDescription bookFrenchDescription = new CategoryDescription();
+ bookFrenchDescription.setName("Livre");
+ bookFrenchDescription.setCategory(book);
+ bookFrenchDescription.setLanguage(fr);
+
+ List<CategoryDescription> descriptions = new ArrayList<CategoryDescription>();
+ descriptions.add(bookEnglishDescription);
+ descriptions.add(bookFrenchDescription);
+
+ book.setDescriptions(descriptions);
+
+ categoryService.create(book);
+
+ Category music = new Category();
+ music.setMerchantStore(store);
+ music.setCode("music");
+
+ CategoryDescription musicEnglishDescription = new CategoryDescription();
+ musicEnglishDescription.setName("Music");
+ musicEnglishDescription.setCategory(music);
+ musicEnglishDescription.setLanguage(en);
+
+ CategoryDescription musicFrenchDescription = new CategoryDescription();
+ musicFrenchDescription.setName("Musique");
+ musicFrenchDescription.setCategory(music);
+ musicFrenchDescription.setLanguage(fr);
+
+ List<CategoryDescription> descriptions2 = new ArrayList<CategoryDescription>();
+ descriptions2.add(musicEnglishDescription);
+ descriptions2.add(musicFrenchDescription);
+
+ music.setDescriptions(descriptions2);
+
+ categoryService.create(music);
+
+ Category novell = new Category();
+ novell.setMerchantStore(store);
+ novell.setCode("novell");
+
+ CategoryDescription novellEnglishDescription = new CategoryDescription();
+ novellEnglishDescription.setName("Novell");
+ novellEnglishDescription.setCategory(novell);
+ novellEnglishDescription.setLanguage(en);
+
+ CategoryDescription novellFrenchDescription = new CategoryDescription();
+ novellFrenchDescription.setName("Roman");
+ novellFrenchDescription.setCategory(novell);
+ novellFrenchDescription.setLanguage(fr);
+
+ List<CategoryDescription> descriptions3 = new ArrayList<CategoryDescription>();
+ descriptions3.add(novellEnglishDescription);
+ descriptions3.add(novellFrenchDescription);
+
+ novell.setDescriptions(descriptions3);
+
+ novell.setParent(book);
+
+ categoryService.create(novell);
+ categoryService.addChild(book, novell);
+
+ Category tech = new Category();
+ tech.setMerchantStore(store);
+ tech.setCode("tech");
+
+ CategoryDescription techEnglishDescription = new CategoryDescription();
+ techEnglishDescription.setName("Technology");
+ techEnglishDescription.setCategory(tech);
+ techEnglishDescription.setLanguage(en);
+
+ CategoryDescription techFrenchDescription = new CategoryDescription();
+ techFrenchDescription.setName("Technologie");
+ techFrenchDescription.setCategory(tech);
+ techFrenchDescription.setLanguage(fr);
+
+ List<CategoryDescription> descriptions4 = new ArrayList<CategoryDescription>();
+ descriptions4.add(techFrenchDescription);
+ descriptions4.add(techFrenchDescription);
+
+ tech.setDescriptions(descriptions4);
+
+ tech.setParent(book);
+
+ categoryService.create(tech);
+ categoryService.addChild(book, tech);
+
+ Category fiction = new Category();
+ fiction.setMerchantStore(store);
+ fiction.setCode("fiction");
+
+ CategoryDescription fictionEnglishDescription = new CategoryDescription();
+ fictionEnglishDescription.setName("Fiction");
+ fictionEnglishDescription.setCategory(fiction);
+ fictionEnglishDescription.setLanguage(en);
+
+ CategoryDescription fictionFrenchDescription = new CategoryDescription();
+ fictionFrenchDescription.setName("Sc Fiction");
+ fictionFrenchDescription.setCategory(fiction);
+ fictionFrenchDescription.setLanguage(fr);
+
+ List<CategoryDescription> fictiondescriptions = new ArrayList<CategoryDescription>();
+ fictiondescriptions.add(fictionEnglishDescription);
+ fictiondescriptions.add(fictionFrenchDescription);
+
+ fiction.setDescriptions(fictiondescriptions);
+
+ fiction.setParent(novell);
+
+ categoryService.create(fiction);
+ categoryService.addChild(book, fiction);
+
+ Manufacturer oreilley = new Manufacturer();
+ oreilley.setMerchantStore(store);
+
+ ManufacturerDescription oreilleyd = new ManufacturerDescription();
+ oreilleyd.setLanguage(en);
+ oreilleyd.setName("O\'reilley");
+ oreilleyd.setManufacturer(oreilley);
+ oreilley.getDescriptions().add(oreilleyd);
+
+ manufacturerService.create(oreilley);
+
+ Manufacturer packed = new Manufacturer();
+ packed.setMerchantStore(store);
+
+ ManufacturerDescription packedd = new ManufacturerDescription();
+ packedd.setLanguage(en);
+ packedd.setManufacturer(packed);
+ packedd.setName("Packed publishing");
+ packed.getDescriptions().add(packedd);
+
+ manufacturerService.create(packed);
+
+ Manufacturer novells = new Manufacturer();
+ novells.setMerchantStore(store);
+
+ ManufacturerDescription novellsd = new ManufacturerDescription();
+ novellsd.setLanguage(en);
+ novellsd.setManufacturer(novells);
+ novellsd.setName("Novells publishing");
+ novells.getDescriptions().add(novellsd);
+
+ manufacturerService.create(novells);
+
+ // PRODUCT 1
+
+ Product product = new Product();
+ product.setProductHeight(new BigDecimal(4));
+ product.setProductLength(new BigDecimal(3));
+ product.setProductWidth(new BigDecimal(1));
+ product.setSku("TB12345");
+ product.setManufacturer(oreilley);
+ product.setType(generalType);
+ product.setMerchantStore(store);
+
+ // Product description
+ ProductDescription description = new ProductDescription();
+ description.setName("Spring in Action");
+ description.setLanguage(en);
+ description.setProduct(product);
+
+ product.getDescriptions().add(description);
+
+ product.getCategories().add(tech);
+
+ productService.create(product);
+
+ // Availability
+ ProductAvailability availability = new ProductAvailability();
+ availability.setProductDateAvailable(date);
+ availability.setProductQuantity(100);
+ availability.setRegion("*");
+ availability.setProduct(product);// associate with product
+
+ productAvailabilityService.create(availability);
+
+ ProductPrice dprice = new ProductPrice();
+ dprice.setDefaultPrice(true);
+ dprice.setProductPriceAmount(new BigDecimal(29.99));
+ dprice.setProductAvailability(availability);
+
+ ProductPriceDescription dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice);
+ dpd.setLanguage(en);
+
+ dprice.getDescriptions().add(dpd);
+
+ productPriceService.create(dprice);
+
+ ProductReview review = new ProductReview();
+ review.setProduct(product);
+ review.setReviewRating(new Double(4));
+
+ ProductReviewDescription reviewDescription = new ProductReviewDescription();
+ reviewDescription.setLanguage(en);
+ reviewDescription.setDescription("This is a product review");
+ reviewDescription.setProductReview(review);
+ review.getDescriptions().add(reviewDescription);
+
+ productReviewService.create(review);
+
+ review = new ProductReview();
+ review.setProduct(product);
+ review.setReviewRating(new Double(5));
+
+ reviewDescription = new ProductReviewDescription();
+ reviewDescription.setLanguage(en);
+ reviewDescription.setDescription("This is a second product review");
+ reviewDescription.setProductReview(review);
+ review.getDescriptions().add(reviewDescription);
+
+ productReviewService.create(review);
+
+
+ // PRODUCT 2
+
+ Product product2 = new Product();
+ product2.setProductHeight(new BigDecimal(4));
+ product2.setProductLength(new BigDecimal(3));
+ product2.setProductWidth(new BigDecimal(1));
+ product2.setSku("TB2468");
+ product2.setManufacturer(packed);
+ product2.setType(generalType);
+ product2.setMerchantStore(store);
+
+ // Product description
+ description = new ProductDescription();
+ description.setName("This is Node.js");
+ description.setLanguage(en);
+ description.setProduct(product2);
+
+ product2.getDescriptions().add(description);
+
+ product2.getCategories().add(tech);
+ productService.create(product2);
+
+ // Availability
+ ProductAvailability availability2 = new ProductAvailability();
+ availability2.setProductDateAvailable(date);
+ availability2.setProductQuantity(100);
+ availability2.setRegion("*");
+ availability2.setProduct(product2);// associate with product
+
+ productAvailabilityService.create(availability2);
+
+ ProductPrice dprice2 = new ProductPrice();
+ dprice2.setDefaultPrice(true);
+ dprice2.setProductPriceAmount(new BigDecimal(39.99));
+ dprice2.setProductAvailability(availability2);
+
+ dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice2);
+ dpd.setLanguage(en);
+
+ dprice2.getDescriptions().add(dpd);
+
+ productPriceService.create(dprice2);
+
+ // PRODUCT 3
+
+ Product product3 = new Product();
+ product3.setProductHeight(new BigDecimal(4));
+ product3.setProductLength(new BigDecimal(3));
+ product3.setProductWidth(new BigDecimal(1));
+ product3.setSku("NB1111");
+ product3.setManufacturer(packed);
+ product3.setType(generalType);
+ product3.setMerchantStore(store);
+
+ // Product description
+ description = new ProductDescription();
+ description.setName("A nice book for you");
+ description.setLanguage(en);
+ description.setProduct(product3);
+
+ product3.getDescriptions().add(description);
+
+ product3.getCategories().add(novell);
+ productService.create(product3);
+
+ // Availability
+ ProductAvailability availability3 = new ProductAvailability();
+ availability3.setProductDateAvailable(date);
+ availability3.setProductQuantity(100);
+ availability3.setRegion("*");
+ availability3.setProduct(product3);// associate with product
+
+ productAvailabilityService.create(availability3);
+
+ ProductPrice dprice3 = new ProductPrice();
+ dprice3.setDefaultPrice(true);
+ dprice3.setProductPriceAmount(new BigDecimal(19.99));
+ dprice3.setProductAvailability(availability3);
+
+ dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice3);
+ dpd.setLanguage(en);
+
+ dprice3.getDescriptions().add(dpd);
+
+ productPriceService.create(dprice3);
+
+ // PRODUCT 4
+
+ Product product4 = new Product();
+ product4.setProductHeight(new BigDecimal(4));
+ product4.setProductLength(new BigDecimal(3));
+ product4.setProductWidth(new BigDecimal(1));
+ product4.setSku("SF333345");
+ product4.setManufacturer(packed);
+ product4.setType(generalType);
+ product4.setMerchantStore(store);
+
+ // Product description
+ description = new ProductDescription();
+ description.setName("Battle of the worlds");
+ description.setLanguage(en);
+ description.setProduct(product4);
+
+ product4.getDescriptions().add(description);
+
+ product4.getCategories().add(fiction);
+ productService.create(product4);
+
+ // Availability
+ ProductAvailability availability4 = new ProductAvailability();
+ availability4.setProductDateAvailable(date);
+ availability4.setProductQuantity(100);
+ availability4.setRegion("*");
+ availability4.setProduct(product4);// associate with product
+
+ productAvailabilityService.create(availability4);
+
+ ProductPrice dprice4 = new ProductPrice();
+ dprice4.setDefaultPrice(true);
+ dprice4.setProductPriceAmount(new BigDecimal(18.99));
+ dprice4.setProductAvailability(availability4);
+
+ dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice4);
+ dpd.setLanguage(en);
+
+ dprice4.getDescriptions().add(dpd);
+
+ productPriceService.create(dprice4);
+
+ // PRODUCT 5
+
+ Product product5 = new Product();
+ product5.setProductHeight(new BigDecimal(4));
+ product5.setProductLength(new BigDecimal(3));
+ product5.setProductWidth(new BigDecimal(1));
+ product5.setSku("SF333346");
+ product5.setManufacturer(packed);
+ product5.setType(generalType);
+ product5.setMerchantStore(store);
+
+ // Product description
+ description = new ProductDescription();
+ description.setName("Battle of the worlds 2");
+ description.setLanguage(en);
+ description.setProduct(product5);
+
+ product5.getDescriptions().add(description);
+
+ product5.getCategories().add(fiction);
+ productService.create(product5);
+
+ // Availability
+ ProductAvailability availability5 = new ProductAvailability();
+ availability5.setProductDateAvailable(date);
+ availability5.setProductQuantity(100);
+ availability5.setRegion("*");
+ availability5.setProduct(product5);// associate with product
+
+ productAvailabilityService.create(availability5);
+
+ ProductPrice dprice5 = new ProductPrice();
+ dprice5.setDefaultPrice(true);
+ dprice5.setProductPriceAmount(new BigDecimal(18.99));
+ dprice5.setProductAvailability(availability5);
+
+ dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice5);
+ dpd.setLanguage(en);
+
+ dprice5.getDescriptions().add(dpd);
+
+ productPriceService.create(dprice5);
+
+ // PRODUCT 6
+
+ Product product6 = new Product();
+ product6.setProductHeight(new BigDecimal(4));
+ product6.setProductLength(new BigDecimal(3));
+ product6.setProductWidth(new BigDecimal(1));
+ product6.setSku("LL333444");
+ product6.setManufacturer(packed);
+ product6.setType(generalType);
+ product6.setMerchantStore(store);
+
+ // Product description
+ description = new ProductDescription();
+ description.setName("Life book");
+ description.setLanguage(en);
+ description.setProduct(product6);
+
+ product6.getDescriptions().add(description);
+
+ product6.getCategories().add(novell);
+ productService.create(product6);
+
+ // Availability
+ ProductAvailability availability6 = new ProductAvailability();
+ availability6.setProductDateAvailable(date);
+ availability6.setProductQuantity(100);
+ availability6.setRegion("*");
+ availability6.setProduct(product6);// associate with product
+
+ productAvailabilityService.create(availability6);
+
+ ProductPrice dprice6 = new ProductPrice();
+ dprice6.setDefaultPrice(true);
+ dprice6.setProductPriceAmount(new BigDecimal(18.99));
+ dprice6.setProductAvailability(availability6);
+
+ dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice6);
+ dpd.setLanguage(en);
+
+ dprice6.getDescriptions().add(dpd);
+
+ productPriceService.create(dprice6);
+
+ //count products by category
+ String lineage = new StringBuilder().append(book.getLineage()).toString();
+
+ List<Category> categories = categoryService.listByLineage(store, lineage);
+
+ List<Long> ids = new ArrayList<Long>();
+ if(categories!=null && categories.size()>0) {
+ for(Category c : categories) {
+ ids.add(c.getId());
+ }
+ }
+
+ List<Object[]> objs = categoryService.countProductsByCategories(store, ids);
+
+ System.out.println(objs.size());
+
+ //get manufacturer for given categories
+ List<Manufacturer> manufacturers = manufacturerService.listByProductsByCategoriesId(store, ids, en);
+
+ System.out.println(manufacturers.size());
+
+ }
+
+
+ /**
+ * This method creates a product and uses the saveOrUpdate on a complex graph object
+ * @throws ServiceException
+ */
+ @Test
+ @Ignore
+ public void testCreateSimpleProduct() throws ServiceException {
+
+
+ Language en = languageService.getByCode("en");
+ Language fr = languageService.getByCode("fr");
+
+ MerchantStore store = merchantService.getByCode(MerchantStore.DEFAULT_STORE);
+ ProductType generalType = productTypeService.getProductType(ProductType.GENERAL_TYPE);
+
+ /**
+ * Create the category
+ */
+ Category book = new Category();
+ book.setMerchantStore(store);
+ book.setCode("book");
+
+ CategoryDescription bookEnglishDescription = new CategoryDescription();
+ bookEnglishDescription.setName("Book");
+ bookEnglishDescription.setCategory(book);
+ bookEnglishDescription.setLanguage(en);
+
+ CategoryDescription bookFrenchDescription = new CategoryDescription();
+ bookFrenchDescription.setName("Livre");
+ bookFrenchDescription.setCategory(book);
+ bookFrenchDescription.setLanguage(fr);
+
+ List<CategoryDescription> descriptions = new ArrayList<CategoryDescription>();
+ descriptions.add(bookEnglishDescription);
+ descriptions.add(bookFrenchDescription);
+
+ book.setDescriptions(descriptions);
+
+ categoryService.create(book);
+
+
+ /**
+ * Create a manufacturer
+ */
+ Manufacturer packed = new Manufacturer();
+ packed.setMerchantStore(store);
+
+ ManufacturerDescription packedd = new ManufacturerDescription();
+ packedd.setLanguage(en);
+ packedd.setManufacturer(packed);
+ packedd.setName("Packed publishing");
+ packed.getDescriptions().add(packedd);
+
+ manufacturerService.create(packed);
+
+ /**
+ * Create an option
+ */
+ ProductOption option = new ProductOption();
+ option.setMerchantStore(store);
+ option.setCode("copy");
+ option.setProductOptionType(ProductOptionType.Radio.name());
+
+ ProductOptionDescription optionDescription = new ProductOptionDescription();
+ optionDescription.setLanguage(en);
+ optionDescription.setName("Book type");
+ optionDescription.setDescription("Offered in hard and soft copy");
+ optionDescription.setProductOption(option);
+
+ option.getDescriptions().add(optionDescription);
+
+ productOptionService.saveOrUpdate(option);
+
+ ProductOptionValue soft = new ProductOptionValue();
+ soft.setMerchantStore(store);
+ soft.setCode("soft");
+
+ ProductOptionValueDescription softDescription = new ProductOptionValueDescription();
+ softDescription.setLanguage(en);
+ softDescription.setName("Soft");
+ softDescription.setDescription("Soft copy");
+ softDescription.setProductOptionValue(soft);
+
+ soft.getDescriptions().add(softDescription);
+
+ productOptionValueService.saveOrUpdate(soft);
+
+
+ ProductOptionValue hard = new ProductOptionValue();
+ hard.setMerchantStore(store);
+ hard.setCode("hard");
+
+ ProductOptionValueDescription hardDescription = new ProductOptionValueDescription();
+ hardDescription.setLanguage(en);
+ hardDescription.setName("Hard");
+ hardDescription.setDescription("Hard copy");
+ hardDescription.setProductOptionValue(hard);
+
+ hard.getDescriptions().add(hardDescription);
+
+ productOptionValueService.saveOrUpdate(hard);
+
+
+ /**
+ * Create a complex product
+ */
+ Product product = new Product();
+ product.setProductHeight(new BigDecimal(4));
+ product.setProductLength(new BigDecimal(3));
+ product.setProductWidth(new BigDecimal(1));
+ product.setSku("TB12345");
+ product.setManufacturer(packed);
+ product.setType(generalType);
+ product.setMerchantStore(store);
+
+ // Product description
+ ProductDescription description = new ProductDescription();
+ description.setName("Spring in Action");
+ description.setLanguage(en);
+ description.setProduct(product);
+
+ product.getDescriptions().add(description);
+ product.getCategories().add(book);
+
+
+ //availability
+ ProductAvailability availability = new ProductAvailability();
+ availability.setProductDateAvailable(date);
+ availability.setProductQuantity(100);
+ availability.setRegion("*");
+ availability.setProduct(product);// associate with product
+
+ //price
+ ProductPrice dprice = new ProductPrice();
+ dprice.setDefaultPrice(true);
+ dprice.setProductPriceAmount(new BigDecimal(29.99));
+ dprice.setProductAvailability(availability);
+
+
+
+ ProductPriceDescription dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice);
+ dpd.setLanguage(en);
+
+ dprice.getDescriptions().add(dpd);
+ availability.getPrices().add(dprice);
+
+
+
+ //attributes
+ ProductAttribute attribute = new ProductAttribute();
+ attribute.setProduct(product);
+ attribute.setProductOption(option);
+ attribute.setAttributeDefault(true);
+ attribute.setProductAttributePrice(new BigDecimal(0));//no price variation
+ attribute.setProductAttributeWeight(new BigDecimal(1));//weight variation
+ attribute.setProductOption(option);
+ attribute.setProductOptionValue(hard);
+
+ product.getAttributes().add(attribute);
+
+ attribute = new ProductAttribute();
+ attribute.setProduct(product);
+ attribute.setProductOption(option);
+ attribute.setProductAttributePrice(new BigDecimal(0));//no price variation
+ attribute.setProductAttributeWeight(new BigDecimal(0));//no weight variation
+ attribute.setProductOption(option);
+ attribute.setProductOptionValue(soft);
+
+ product.getAttributes().add(attribute);
+
+ //relationships
+
+
+
+ productService.create(product);
+
+
+
+ }
+
+
+
+
+}
\ No newline at end of file
diff --git a/sm-core/src/test/java/com/salesmanager/test/catalog/ProductImagesTestCase.java b/sm-core/src/test/java/com/salesmanager/test/catalog/ProductImagesTestCase.java
new file mode 100644
index 0000000..46eb244
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/catalog/ProductImagesTestCase.java
@@ -0,0 +1,214 @@
+package com.salesmanager.test.catalog;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.salesmanager.core.business.catalog.category.model.Category;
+import com.salesmanager.core.business.catalog.category.model.CategoryDescription;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability;
+import com.salesmanager.core.business.catalog.product.model.description.ProductDescription;
+import com.salesmanager.core.business.catalog.product.model.file.ProductImageSize;
+import com.salesmanager.core.business.catalog.product.model.image.ProductImage;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.Manufacturer;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.ManufacturerDescription;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPrice;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPriceDescription;
+import com.salesmanager.core.business.content.model.FileContentType;
+import com.salesmanager.core.business.content.model.ImageContentFile;
+import com.salesmanager.core.business.content.model.OutputContentFile;
+import com.salesmanager.core.business.content.service.ContentService;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.test.core.AbstractSalesManagerCoreTestCase;
+
+public class ProductImagesTestCase extends AbstractSalesManagerCoreTestCase {
+
+ private static final Date date = new Date(System.currentTimeMillis());
+
+ @Autowired
+ private ContentService contentService;
+
+ @Test
+ public void testCreateProductImage() throws ServiceException, FileNotFoundException, IOException {
+
+ Language en = languageService.getByCode("en");
+ Country country = countryService.getByCode("CA");
+ Zone zone = zoneService.getByCode("QC");
+
+
+
+ final MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+
+
+
+
+ /**
+ * Create the category
+ */
+ Category book = new Category();
+ book.setMerchantStore(store);
+ book.setCode("book");
+
+ CategoryDescription bookEnglishDescription = new CategoryDescription();
+ bookEnglishDescription.setName("Book");
+ bookEnglishDescription.setCategory(book);
+ bookEnglishDescription.setLanguage(en);
+
+
+
+ List<CategoryDescription> descriptions = new ArrayList<CategoryDescription>();
+ descriptions.add(bookEnglishDescription);
+
+
+ book.setDescriptions(descriptions);
+
+ categoryService.create(book);
+
+
+ /**
+ * Create a manufacturer
+ */
+ Manufacturer packed = new Manufacturer();
+ packed.setMerchantStore(store);
+
+ ManufacturerDescription packedd = new ManufacturerDescription();
+ packedd.setLanguage(en);
+ packedd.setManufacturer(packed);
+ packedd.setName("Packed publishing");
+ packed.getDescriptions().add(packedd);
+
+ manufacturerService.create(packed);
+
+
+
+
+ /**
+ * Create the product
+ */
+ Product product = new Product();
+ product.setProductHeight(new BigDecimal(4));
+ product.setProductLength(new BigDecimal(3));
+ product.setProductWidth(new BigDecimal(1));
+ product.setSku("TB12345");
+ product.setManufacturer(packed);
+ product.setMerchantStore(store);
+
+ // Product description
+ ProductDescription description = new ProductDescription();
+ description.setName("Spring in Action");
+ description.setLanguage(en);
+ description.setProduct(product);
+
+ product.getDescriptions().add(description);
+ product.getCategories().add(book);
+
+
+ //availability
+ ProductAvailability availability = new ProductAvailability();
+ availability.setProductDateAvailable(date);
+ availability.setProductQuantity(100);
+ availability.setRegion("*");
+ availability.setProduct(product);// associate with product
+
+ //price
+ ProductPrice dprice = new ProductPrice();
+ dprice.setDefaultPrice(true);
+ dprice.setProductPriceAmount(new BigDecimal(29.99));
+ dprice.setProductAvailability(availability);
+
+
+
+ ProductPriceDescription dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice);
+ dpd.setLanguage(en);
+
+ dprice.getDescriptions().add(dpd);
+ availability.getPrices().add(dprice);
+
+
+ productService.create(product);
+
+
+
+
+
+ final File file1 = new File( "/Users/csamson777/Documents/workspace2/files/images/watch.jpg" );
+
+ if ( !file1.exists() || !file1.canRead() )
+ {
+ throw new ServiceException( "Can't read" + file1.getAbsolutePath() );
+ }
+
+ final byte[] is = IOUtils.toByteArray( new FileInputStream( file1 ) );
+ final ByteArrayInputStream inputStream = new ByteArrayInputStream( is );
+ final ImageContentFile cmsContentImage = new ImageContentFile();
+ cmsContentImage.setFileName( file1.getName() );
+ cmsContentImage.setFile( inputStream );
+ cmsContentImage.setFileContentType(FileContentType.PRODUCT);
+
+
+ ProductImage productImage = new ProductImage();
+ productImage.setProductImage(file1.getName());
+ productImage.setProduct(product);
+
+
+ productImageService.addProductImage(product, productImage, cmsContentImage);
+
+ //get productImage
+ productImage = productImageService.getById(productImage.getId());
+
+ //get physical small image
+ OutputContentFile contentFile = productImageService.getProductImage(store.getCode(), product.getSku(), productImage.getProductImage(), ProductImageSize.SMALL);
+
+ Assert.assertNotNull(contentFile);
+
+ //print image
+ OutputStream outputStream = new FileOutputStream ("/Users/csamson777/Documents/workspace2/files/images/small_" + contentFile.getFileName());
+
+ ByteArrayOutputStream baos = contentFile.getFile();
+ baos.writeTo(outputStream);
+
+
+ //get physical original image
+ contentFile = productImageService.getProductImage(store.getCode(), product.getSku(), productImage.getProductImage(), ProductImageSize.LARGE);
+
+ Assert.assertNotNull(contentFile);
+
+ //print image
+ outputStream = new FileOutputStream ("/Users/csamson777/Documents/workspace2/files/images/large_" + contentFile.getFileName());
+
+ baos = contentFile.getFile();
+ baos.writeTo(outputStream);
+
+ //remove productImage
+ productImageService.removeProductImage(productImage);
+
+
+
+
+
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/sm-core/src/test/java/com/salesmanager/test/catalog/ProductPriceTestCase.java b/sm-core/src/test/java/com/salesmanager/test/catalog/ProductPriceTestCase.java
new file mode 100644
index 0000000..cb39d19
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/catalog/ProductPriceTestCase.java
@@ -0,0 +1,60 @@
+package com.salesmanager.test.catalog;
+
+import java.math.BigDecimal;
+import java.util.Currency;
+import java.util.Date;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.utils.ProductPriceUtils;
+import com.salesmanager.test.core.AbstractSalesManagerCoreTestCase;
+
+public class ProductPriceTestCase extends AbstractSalesManagerCoreTestCase {
+
+ private static final Date date = new Date(System.currentTimeMillis());
+
+ @Autowired
+ private ProductPriceUtils productPriceUtils;
+
+ @Test
+ public void testPriceWithCurrency() throws Exception {
+
+
+ MerchantStore store = merchantService.getByCode(MerchantStore.DEFAULT_STORE);
+
+ /** specify currencies **/
+
+ List<com.salesmanager.core.business.reference.currency.model.Currency> currencies = currencyService.list();
+ //countries iso codes -> http://userpage.chemie.fu-berlin.de/diverse/doc/ISO_3166.html
+ Country country = new Country();
+ country.setIsoCode("IN");
+
+
+ //iso languages codes -> http://www.loc.gov/standards/iso639-2/php/code_list.php
+ Language language = new Language();
+ language.setCode("en");
+
+ store = new MerchantStore();
+ store.setCountry(country);
+ store.setDefaultLanguage(language);
+
+ //all codes and examples -> http://www.xe.com/iso4217.php
+ Currency currency = Currency.getInstance("INR");
+ com.salesmanager.core.business.reference.currency.model.Currency c = new com.salesmanager.core.business.reference.currency.model.Currency();
+ c.setCurrency(currency);
+ store.setCurrency(c);
+
+ String amount = productPriceUtils.getStoreFormatedAmountWithCurrency(store, new BigDecimal("12345"));
+
+ Assert.assertNotNull(amount);
+ System.out.println(amount);
+
+ }
+
+}
\ No newline at end of file
diff --git a/sm-core/src/test/java/com/salesmanager/test/catalog/SearchByProductAttributeTestCase.java b/sm-core/src/test/java/com/salesmanager/test/catalog/SearchByProductAttributeTestCase.java
new file mode 100644
index 0000000..b0ccfff
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/catalog/SearchByProductAttributeTestCase.java
@@ -0,0 +1,442 @@
+package com.salesmanager.test.catalog;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.salesmanager.core.business.catalog.category.model.Category;
+import com.salesmanager.core.business.catalog.category.model.CategoryDescription;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.ProductCriteria;
+import com.salesmanager.core.business.catalog.product.model.ProductList;
+import com.salesmanager.core.business.catalog.product.model.attribute.AttributeCriteria;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOption;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionDescription;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionType;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionValue;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionValueDescription;
+import com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability;
+import com.salesmanager.core.business.catalog.product.model.description.ProductDescription;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.Manufacturer;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.ManufacturerDescription;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPrice;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPriceDescription;
+import com.salesmanager.core.business.catalog.product.model.type.ProductType;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.test.core.AbstractSalesManagerCoreTestCase;
+
+public class SearchByProductAttributeTestCase extends AbstractSalesManagerCoreTestCase {
+
+ private static final Date date = new Date(System.currentTimeMillis());
+
+
+ @Test
+ public void testFetchProductByAttribute() throws Exception {
+
+ Language en = languageService.getByCode("en");
+
+
+ MerchantStore store = merchantService.getByCode(MerchantStore.DEFAULT_STORE);
+ ProductType generalType = productTypeService.getProductType(ProductType.GENERAL_TYPE);
+
+
+ /** Categories **/
+
+ Category book = new Category();
+ book.setMerchantStore(store);
+ book.setCode("book");
+
+ CategoryDescription bookEnglishDescription = new CategoryDescription();
+ bookEnglishDescription.setName("Book");
+ bookEnglishDescription.setCategory(book);
+ bookEnglishDescription.setLanguage(en);
+
+ List<CategoryDescription> descriptions = new ArrayList<CategoryDescription>();
+ descriptions.add(bookEnglishDescription);
+
+ book.setDescriptions(descriptions);
+
+ categoryService.create(book);
+
+
+ Category novell = new Category();
+ novell.setMerchantStore(store);
+ novell.setCode("novell");
+
+ CategoryDescription novellEnglishDescription = new CategoryDescription();
+ novellEnglishDescription.setName("Novell");
+ novellEnglishDescription.setCategory(novell);
+ novellEnglishDescription.setLanguage(en);
+
+ List<CategoryDescription> descriptions3 = new ArrayList<CategoryDescription>();
+ descriptions3.add(novellEnglishDescription);
+
+ novell.setDescriptions(descriptions3);
+
+ novell.setParent(book);
+
+ categoryService.create(novell);
+ categoryService.addChild(book, novell);
+
+ Category tech = new Category();
+ tech.setMerchantStore(store);
+ tech.setCode("tech");
+
+ CategoryDescription techEnglishDescription = new CategoryDescription();
+ techEnglishDescription.setName("Technology");
+ techEnglishDescription.setCategory(tech);
+ techEnglishDescription.setLanguage(en);
+
+ List<CategoryDescription> descriptions4 = new ArrayList<CategoryDescription>();
+ descriptions4.add(techEnglishDescription);
+
+ tech.setDescriptions(descriptions4);
+
+ tech.setParent(book);
+
+ categoryService.create(tech);
+ categoryService.addChild(book, tech);
+
+ /** Manufacturers **/
+
+ Manufacturer novells = new Manufacturer();
+ novells.setMerchantStore(store);
+
+ ManufacturerDescription novellsd = new ManufacturerDescription();
+ novellsd.setLanguage(en);
+ novellsd.setManufacturer(novells);
+ novellsd.setName("Novells publishing");
+ novells.getDescriptions().add(novellsd);
+
+ manufacturerService.create(novells);
+
+
+ Manufacturer manning = new Manufacturer();
+ manning.setMerchantStore(store);
+
+ ManufacturerDescription manningd = new ManufacturerDescription();
+ manningd.setLanguage(en);
+ manningd.setManufacturer(manning);
+ manningd.setName("Manning publishing");
+ manning.getDescriptions().add(manningd);
+
+ manufacturerService.create(manning);
+
+ //Author attribute
+ ProductOption author = new ProductOption();
+ author.setCode("author");
+ author.setMerchantStore(store);
+ author.setReadOnly(true);
+ author.setProductOptionType(ProductOptionType.Text.name());
+
+
+ ProductOptionDescription authorEnglishDescription = new ProductOptionDescription();
+ authorEnglishDescription.setLanguage(en);
+ authorEnglishDescription.setName("Author");
+ authorEnglishDescription.setProductOption(author);
+
+ author.getDescriptions().add(authorEnglishDescription);
+
+ productOptionService.create(author);
+
+ //Author name - Jimmy Jones
+ ProductOptionValue jimmyjones = new ProductOptionValue();
+ jimmyjones.setMerchantStore(store);
+ jimmyjones.setCode("jimmyjones");
+ jimmyjones.setProductOptionDisplayOnly(true);
+
+ ProductOptionValueDescription jimmyjonesd = new ProductOptionValueDescription();
+ jimmyjonesd.setLanguage(en);
+ jimmyjonesd.setName("Jimmy Jones");//mandatory
+ jimmyjonesd.setDescription("Jimmy Jones");//query is based on description
+ jimmyjonesd.setProductOptionValue(jimmyjones);
+ jimmyjones.getDescriptions().add(jimmyjonesd);
+
+ productOptionValueService.create(jimmyjones);
+
+
+ //Author name - Lucy Scott
+ ProductOptionValue lucyscott = new ProductOptionValue();
+ lucyscott.setMerchantStore(store);
+ lucyscott.setCode("lucyscott");
+ lucyscott.setProductOptionDisplayOnly(true);
+
+ ProductOptionValueDescription lucyscottd = new ProductOptionValueDescription();
+ lucyscottd.setLanguage(en);
+ lucyscottd.setName("Lucy Scott");//mandatory
+ lucyscottd.setDescription("Lucy Scott");//query is based on description
+ lucyscottd.setProductOptionValue(lucyscott);
+ lucyscott.getDescriptions().add(lucyscottd);
+
+ productOptionValueService.create(lucyscott);
+
+ //Author name - Carlos Santana Scott
+ ProductOptionValue carlossantana = new ProductOptionValue();
+ carlossantana.setMerchantStore(store);
+ carlossantana.setCode("carlossantana");
+ carlossantana.setProductOptionDisplayOnly(true);
+
+ ProductOptionValueDescription carlossantanad = new ProductOptionValueDescription();
+ carlossantanad.setLanguage(en);
+ carlossantanad.setName("Carlos Santana");
+ carlossantanad.setDescription("Carlos Santana");
+ carlossantanad.setProductOptionValue(carlossantana);
+ carlossantana.getDescriptions().add(carlossantanad);
+
+ productOptionValueService.create(carlossantana);
+
+
+ // PRODUCT 1 - technical book
+ Product product = new Product();
+ product.setProductHeight(new BigDecimal(4));
+ product.setProductLength(new BigDecimal(3));
+ product.setProductWidth(new BigDecimal(1));
+ product.setSku("TB12345");
+ product.setManufacturer(manning);
+ product.setType(generalType);
+ product.setMerchantStore(store);
+
+ // Product description
+ ProductDescription description = new ProductDescription();
+ description.setName("Spring in Action");
+ description.setLanguage(en);
+ description.setProduct(product);
+
+ product.getDescriptions().add(description);
+
+ product.getCategories().add(tech);
+
+ productService.create(product);
+
+ // Availability
+ ProductAvailability availability = new ProductAvailability();
+ availability.setProductDateAvailable(date);
+ availability.setProductQuantity(100);
+ availability.setRegion("*");
+ availability.setProduct(product);// associate with product
+
+ productAvailabilityService.create(availability);
+
+ ProductPrice dprice = new ProductPrice();
+ dprice.setDefaultPrice(true);
+ dprice.setProductPriceAmount(new BigDecimal(29.99));
+ dprice.setProductAvailability(availability);
+
+ ProductPriceDescription dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice);
+ dpd.setLanguage(en);
+
+ dprice.getDescriptions().add(dpd);
+
+ productPriceService.create(dprice);
+
+
+ //set author attribute
+ ProductAttribute product1Author = new ProductAttribute();
+ product1Author.setAttributeDisplayOnly(true);
+ product1Author.setProduct(product);
+ product1Author.setProductOption(author);
+ product1Author.setProductOptionValue(jimmyjones);
+
+ productAttributeService.create(product1Author);
+
+
+
+ // PRODUCT 2 - technical book
+
+ Product product2 = new Product();
+ product2.setProductHeight(new BigDecimal(4));
+ product2.setProductLength(new BigDecimal(3));
+ product2.setProductWidth(new BigDecimal(1));
+ product2.setSku("TB2468");
+ product2.setManufacturer(manning);
+ product2.setType(generalType);
+ product2.setMerchantStore(store);
+
+ // Product description
+ description = new ProductDescription();
+ description.setName("This is Node.js");
+ description.setLanguage(en);
+ description.setProduct(product2);
+
+ product2.getDescriptions().add(description);
+
+ product2.getCategories().add(tech);
+ productService.create(product2);
+
+ // Availability
+ ProductAvailability availability2 = new ProductAvailability();
+ availability2.setProductDateAvailable(date);
+ availability2.setProductQuantity(100);
+ availability2.setRegion("*");
+ availability2.setProduct(product2);// associate with product
+
+ productAvailabilityService.create(availability2);
+
+ ProductPrice dprice2 = new ProductPrice();
+ dprice2.setDefaultPrice(true);
+ dprice2.setProductPriceAmount(new BigDecimal(39.99));
+ dprice2.setProductAvailability(availability2);
+
+ dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice2);
+ dpd.setLanguage(en);
+
+ dprice2.getDescriptions().add(dpd);
+
+ productPriceService.create(dprice2);
+
+ //set author attribute
+ ProductAttribute product2Author = new ProductAttribute();
+ product2Author.setAttributeDisplayOnly(true);
+ product2Author.setProduct(product2);
+ product2Author.setProductOption(author);
+ product2Author.setProductOptionValue(jimmyjones);
+
+ productAttributeService.create(product2Author);
+
+ // PRODUCT 3 - Novell
+
+ Product product3 = new Product();
+ product3.setProductHeight(new BigDecimal(4));
+ product3.setProductLength(new BigDecimal(3));
+ product3.setProductWidth(new BigDecimal(1));
+ product3.setSku("NB1111");
+ product3.setManufacturer(novells);
+ product3.setType(generalType);
+ product3.setMerchantStore(store);
+
+ // Product description
+ description = new ProductDescription();
+ description.setName("A nice book for you");
+ description.setLanguage(en);
+ description.setProduct(product3);
+
+ product3.getDescriptions().add(description);
+
+ product3.getCategories().add(novell);
+ productService.create(product3);
+
+ // Availability
+ ProductAvailability availability3 = new ProductAvailability();
+ availability3.setProductDateAvailable(date);
+ availability3.setProductQuantity(100);
+ availability3.setRegion("*");
+ availability3.setProduct(product3);// associate with product
+
+ productAvailabilityService.create(availability3);
+
+ ProductPrice dprice3 = new ProductPrice();
+ dprice3.setDefaultPrice(true);
+ dprice3.setProductPriceAmount(new BigDecimal(19.99));
+ dprice3.setProductAvailability(availability3);
+
+ dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice3);
+ dpd.setLanguage(en);
+
+ dprice3.getDescriptions().add(dpd);
+
+ productPriceService.create(dprice3);
+
+ //set author attribute
+ ProductAttribute product3Author = new ProductAttribute();
+ product3Author.setAttributeDisplayOnly(true);
+ product3Author.setProduct(product3);
+ product3Author.setProductOption(author);
+ product3Author.setProductOptionValue(lucyscott);
+
+ productAttributeService.create(product3Author);
+
+
+ // PRODUCT 4 - Novell
+
+ Product product4 = new Product();
+ product4.setProductHeight(new BigDecimal(4));
+ product4.setProductLength(new BigDecimal(3));
+ product4.setProductWidth(new BigDecimal(1));
+ product4.setSku("NB1111678");
+ product4.setManufacturer(novells);
+ product4.setType(generalType);
+ product4.setMerchantStore(store);
+
+ // Product description
+ description = new ProductDescription();
+ description.setName("Look at the sky");
+ description.setLanguage(en);
+ description.setProduct(product4);
+
+ product4.getDescriptions().add(description);
+
+ product4.getCategories().add(novell);
+ productService.create(product4);
+
+ // Availability
+ ProductAvailability availability4 = new ProductAvailability();
+ availability4.setProductDateAvailable(date);
+ availability4.setProductQuantity(100);
+ availability4.setRegion("*");
+ availability4.setProduct(product4);// associate with product
+
+ productAvailabilityService.create(availability4);
+
+ ProductPrice dprice4 = new ProductPrice();
+ dprice4.setDefaultPrice(true);
+ dprice4.setProductPriceAmount(new BigDecimal(17.99));
+ dprice4.setProductAvailability(availability4);
+
+ dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice4);
+ dpd.setLanguage(en);
+
+ dprice4.getDescriptions().add(dpd);
+
+ productPriceService.create(dprice4);
+
+ //set author attribute
+ ProductAttribute product4Author = new ProductAttribute();
+ product4Author.setAttributeDisplayOnly(true);
+ product4Author.setProduct(product4);
+ product4Author.setProductOption(author);
+ product4Author.setProductOptionValue(carlossantana);
+
+ productAttributeService.create(product4Author);
+
+
+
+ //get product by author Jimmy Jones
+ ProductCriteria fetchCriteria = new ProductCriteria();
+ //fetchCriteria.setCode("TB1234");
+
+ List<AttributeCriteria> attributesCriteriaList = new ArrayList<AttributeCriteria>();
+
+ AttributeCriteria fetchAttributeCriteria = new AttributeCriteria();
+ fetchAttributeCriteria.setAttributeCode("author");
+ fetchAttributeCriteria.setAttributeValue("Jimmy Jones");
+
+ attributesCriteriaList.add(fetchAttributeCriteria);
+
+
+ fetchCriteria.setAttributeCriteria(attributesCriteriaList);
+
+ ProductList productList = productService.listByStore(store, en, fetchCriteria);
+
+ Assert.assertNotNull(productList.getProducts());
+
+ System.out.println(productList.getProducts().size());//should be 2
+
+
+
+ }
+
+}
\ No newline at end of file
diff --git a/sm-core/src/test/java/com/salesmanager/test/content/ContentImagesTestCase.java b/sm-core/src/test/java/com/salesmanager/test/content/ContentImagesTestCase.java
new file mode 100644
index 0000000..921d9df
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/content/ContentImagesTestCase.java
@@ -0,0 +1,220 @@
+package com.salesmanager.test.content;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Date;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.salesmanager.core.business.content.model.FileContentType;
+import com.salesmanager.core.business.content.model.InputContentFile;
+import com.salesmanager.core.business.content.model.OutputContentFile;
+import com.salesmanager.core.business.content.service.ContentService;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.test.core.AbstractSalesManagerCoreTestCase;
+
+
+
+
+/**
+ * Test
+ * store logo
+ * @author Carl Samson
+ *
+ */
+
+public class ContentImagesTestCase extends AbstractSalesManagerCoreTestCase {
+
+ private static final Date date = new Date(System.currentTimeMillis());
+
+ @Autowired
+ private ContentService contentService;
+
+
+
+ @Test
+ public void createStoreLogo()
+ throws ServiceException, FileNotFoundException, IOException
+ {
+
+ MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+ final File file1 = new File( "/Users/csamson777/Pictures/peavey.jpg" );
+
+ if ( !file1.exists() || !file1.canRead() )
+ {
+ throw new ServiceException( "Can't read" + file1.getAbsolutePath() );
+ }
+
+ byte[] is = IOUtils.toByteArray( new FileInputStream( file1 ) );
+ ByteArrayInputStream inputStream = new ByteArrayInputStream( is );
+ InputContentFile cmsContentImage = new InputContentFile();
+
+ cmsContentImage.setFileName( file1.getName() );
+ cmsContentImage.setFile(inputStream);
+
+
+ //logo as a content
+ contentService.addLogo(store.getCode(), cmsContentImage);
+
+ store.setStoreLogo(file1.getName() );
+ merchantService.update(store);
+
+ //query the store
+ store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+
+
+
+ //get the logo
+ String logo = store.getStoreLogo();
+
+ OutputContentFile image =contentService.getContentFile(store.getCode(), FileContentType.LOGO, logo);
+
+ //print image
+ OutputStream outputStream = new FileOutputStream ("/Users/csamson777/Pictures/mexique" + image.getFileName());
+
+ ByteArrayOutputStream baos = image.getFile();
+ baos.writeTo(outputStream);
+
+
+ //remove image
+ contentService.removeFile(store.getCode(), FileContentType.LOGO, store.getStoreLogo());
+
+
+
+ }
+
+
+
+/*
+ @Test
+ public void createContentImages()
+ throws ServiceException, FileNotFoundException, IOException
+ {
+
+ final List<CMSContentImage> contentImagesList=new ArrayList<CMSContentImage>();
+ final MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+ final File file1 = new File( "/Umesh/contentimage/destination.png" );
+
+ if ( !file1.exists() || !file1.canRead() )
+ {
+ throw new ServiceException( "Can't read" + file1.getAbsolutePath() );
+ }
+
+ final byte[] is = IOUtils.toByteArray( new FileInputStream( file1 ) );
+ final ByteArrayInputStream inputStream = new ByteArrayInputStream( is );
+ final CMSContentImage cmsContentImage = new CMSContentImage();
+ cmsContentImage.setImageName( "demoCmsImage3" );
+ cmsContentImage.setFile( inputStream );
+ contentImagesList.add( cmsContentImage);
+
+ final CMSContentImage cmsContentImage1 = new CMSContentImage();
+ cmsContentImage1.setImageName( "demoCmsImage4" );
+ cmsContentImage1.setFile( inputStream );
+
+ contentImagesList.add( cmsContentImage1);
+
+ //contentService.addContentImages( store.getCode(), contentImagesList );
+
+ }
+
+ @Test
+ public void getContentImage()
+ throws ServiceException, FileNotFoundException, IOException
+ {
+
+ final MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+ final String imageName = "demoCmsImage";
+
+ final OutputContentFile outputContentImage = contentService.getContentImage(store.getCode(), FileContentType.IMAGE, imageName );
+ //final OutputContentImage outputContentImage = contentService.getContentImage( store, "" );
+ System.out.println( outputContentImage.getFile() );
+ System.out.println( outputContentImage.getFileName() );
+
+ }
+
+ @Test
+ public void getAllContentImages() throws ServiceException{
+ final MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+ final List<OutputContentFile> contentImagesList= contentService.getContentImages(store.getCode(), null );
+ if(CollectionUtils.isNotEmpty( contentImagesList )){
+ System.out.println("Total " + contentImagesList.size()+ " Images found");
+ for(final OutputContentFile outputContentImage :contentImagesList){
+ System.out.println(outputContentImage.getFileName());
+ }
+ }
+ else{
+ System.out.println("No image found for given merchant store");
+ }
+ }
+
+ @Test
+ public void removeContentImage() throws ServiceException{
+ final MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+ final InputContentFile contentImage = new InputContentFile( );
+ contentImage.setFileContentType(FileContentType.IMAGE );
+ contentImage.setFileName("demoCmsImage");
+ //contentService.removeImage( store.getCode(), contentImage );
+
+ }
+
+ @Test
+ public void removeAllContentImages() throws ServiceException{
+ final MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+ contentService.removeImages( store.getCode());
+ }
+
+
+ @Test
+ public void getContentImagesNames() throws Exception{
+ final MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+ final List<String> imageNames = contentService.getContentImagesNames(store.getCode(),FileContentType.IMAGE);
+ for(final String imageName:imageNames){
+ System.out.println(imageName);
+ }
+ }
+
+ @Test
+ public void testGetImages()
+ throws ServiceException
+ {
+
+ final Product product = productService.getById( 1L );
+
+ final List<OutputContentFile> images = productImageService.getProductImages( product );
+
+ for ( final OutputContentFile image : images )
+ {
+
+ System.out.println( image.getFileName() );
+ System.out.println( image.getFileContentType() );
+ }
+
+ }
+
+
+
+
+ @Test
+ public void testCreateContentImage() throws ServiceException {
+
+ Language en = languageService.getByCode("en");
+ Country country = countryService.getByCode("CA");
+ Zone zone = zoneService.getByCode("QC");
+
+ MerchantStore store = merchantService.getByCode(MerchantStore.DEFAULT_STORE);
+
+
+
+ }
+ */
+
+}
\ No newline at end of file
diff --git a/sm-core/src/test/java/com/salesmanager/test/content/StaticContentTestCase.java b/sm-core/src/test/java/com/salesmanager/test/content/StaticContentTestCase.java
new file mode 100644
index 0000000..3b56cc0
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/content/StaticContentTestCase.java
@@ -0,0 +1,190 @@
+package com.salesmanager.test.content;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.io.IOUtils;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.salesmanager.core.business.content.model.FileContentType;
+import com.salesmanager.core.business.content.model.InputContentFile;
+import com.salesmanager.core.business.content.model.OutputContentFile;
+import com.salesmanager.core.business.content.service.ContentService;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.test.core.AbstractSalesManagerCoreTestCase;
+
+/**
+ * Test
+ *
+ * - static content files (.js, .pdf etc)
+ * - static content images (jpg, gig ...)
+ * @author Carl Samson
+ *
+ */
+public class StaticContentTestCase extends AbstractSalesManagerCoreTestCase {
+
+
+ @Autowired
+ private ContentService contentService;
+
+
+ @Test
+ public void createImage()
+ throws ServiceException, FileNotFoundException, IOException
+ {
+
+ MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+ final File file1 = new File( "c:/doc/carl/shirt3.jpg" );
+
+ if ( !file1.exists() || !file1.canRead() )
+ {
+ throw new ServiceException( "Can't read" + file1.getAbsolutePath() );
+ }
+
+ final byte[] is = IOUtils.toByteArray( new FileInputStream( file1 ) );
+ final ByteArrayInputStream inputStream = new ByteArrayInputStream( is );
+ final InputContentFile cmsContentImage = new InputContentFile();
+ cmsContentImage.setFileName( file1.getName() );
+ cmsContentImage.setFile( inputStream );
+ cmsContentImage.setFileContentType(FileContentType.IMAGE);
+
+ //Add image
+ contentService.addContentFile(store.getCode(), cmsContentImage);
+
+
+ //get image
+ OutputContentFile image = contentService.getContentFile(store.getCode(), FileContentType.IMAGE, file1.getName());
+
+ //print image
+ OutputStream outputStream = new FileOutputStream ("c:/TEMP/" + image.getFileName());
+
+ ByteArrayOutputStream baos = image.getFile();
+ baos.writeTo(outputStream);
+
+
+ //remove image
+ contentService.removeFile(store.getCode(), FileContentType.IMAGE, file1.getName());
+
+
+
+ }
+
+ @Test
+ public void testCreateStaticContent() throws Exception {
+
+ MerchantStore store = merchantService.getByCode(MerchantStore.DEFAULT_STORE);
+
+ final File file = new File( "c:/doc/carl/cdbaby.zip" );
+
+ if ( !file.exists() || !file.canRead() )
+ {
+ throw new ServiceException( "Can't read" + file.getAbsolutePath() );
+ }
+
+ byte[] is;
+ ByteArrayInputStream inputStream = null;
+
+ is = IOUtils.toByteArray( new FileInputStream( file ) );
+ inputStream = new ByteArrayInputStream( is );
+
+ InputContentFile staticContent = new InputContentFile();
+ staticContent.setFile(inputStream);
+ staticContent.setFileName(file.getName());
+ staticContent.setFileContentType(FileContentType.STATIC_FILE);//default to static data
+
+ contentService.addContentFile(store.getCode(), staticContent);
+
+ //staticContentService.getFile(store, FileContentType.STATIC_FILE, file.getName());
+
+ //now get the file
+
+/* OutputStaticContentData getData = staticContentService.getStaticContentData(store, StaticContentType.STATIC_DATA ,file.getName());
+ Assert.assertNotNull(getData);
+ if(getData != null) {
+
+ System.out.println(getData.getFileName());
+ System.out.println(getData.getFileContentType());
+
+ OutputStream outputStream = new FileOutputStream ("c:/tmp/" + getData.getFileName());
+
+ ByteArrayOutputStream baos = getData.getFile();
+ baos.writeTo(outputStream);
+
+ }*/
+
+ //remove the file
+
+ //staticContentService.removeFile(store, FileContentType.STATIC_FILE, file.getName());
+
+ }
+
+ @Test
+ public void testCreateMultipleStaticContent() throws Exception {
+
+
+ MerchantStore store = merchantService.getByCode(MerchantStore.DEFAULT_STORE);
+
+
+ // FILE 1
+ final File file = new File( "c:/doc/carl/cdbaby.zip" );
+
+ if ( !file.exists() || !file.canRead() )
+ {
+ throw new ServiceException( "Can't read" + file.getAbsolutePath() );
+ }
+
+ byte[] is;
+ ByteArrayInputStream inputStream = null;
+
+ is = IOUtils.toByteArray( new FileInputStream( file ) );
+ inputStream = new ByteArrayInputStream( is );
+
+ InputContentFile staticContent = new InputContentFile();
+ staticContent.setFile(inputStream);
+ staticContent.setFileName(file.getName());
+ staticContent.setFileContentType(FileContentType.STATIC_FILE);//default to static data
+
+
+ // FILE 2
+ final File file2 = new File( "c:/doc/carl/Cocoa - Requirements.doc" );
+
+ if ( !file2.exists() || !file2.canRead() )
+ {
+ throw new ServiceException( "Can't read" + file2.getAbsolutePath() );
+ }
+
+ byte[] is2;
+ ByteArrayInputStream inputStream2 = null;
+
+ is2 = IOUtils.toByteArray( new FileInputStream( file2 ) );
+ inputStream2 = new ByteArrayInputStream( is2 );
+
+ InputContentFile staticContent2 = new InputContentFile();
+ staticContent2.setFile(inputStream2);
+ staticContent2.setFileName(file2.getName());
+ staticContent2.setFileContentType(FileContentType.STATIC_FILE);//default to static data
+
+ List<InputContentFile> staticFiles = new ArrayList<InputContentFile>();
+ staticFiles.add(staticContent);
+ staticFiles.add(staticContent2);
+
+ contentService.addContentFiles(store.getCode(), staticFiles);
+
+ //get file names
+ //staticContentService.get
+
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/sm-core/src/test/java/com/salesmanager/test/content/WebsiteContentTestCase.java b/sm-core/src/test/java/com/salesmanager/test/content/WebsiteContentTestCase.java
new file mode 100644
index 0000000..e7483f5
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/content/WebsiteContentTestCase.java
@@ -0,0 +1,55 @@
+package com.salesmanager.test.content;
+
+import java.util.Date;
+
+
+
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.salesmanager.core.business.content.service.ContentService;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.test.core.AbstractSalesManagerCoreTestCase;
+
+
+
+
+
+public class WebsiteContentTestCase extends AbstractSalesManagerCoreTestCase {
+
+ private static final Date date = new Date(System.currentTimeMillis());
+
+ @Autowired
+ private ContentService contentService;
+
+ @Test
+ public void testCreateContentPage() throws ServiceException {
+
+ Language en = languageService.getByCode("en");
+ Country country = countryService.getByCode("CA");
+ Zone zone = zoneService.getByCode("QC");
+
+ MerchantStore store = merchantService.getByCode(MerchantStore.DEFAULT_STORE);
+
+
+
+ }
+
+ public void testCreateContentBox() throws ServiceException {
+
+ Language en = languageService.getByCode("en");
+ Country country = countryService.getByCode("CA");
+ Zone zone = zoneService.getByCode("QC");
+
+ MerchantStore store = merchantService.getByCode(MerchantStore.DEFAULT_STORE);
+
+
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/sm-core/src/test/java/com/salesmanager/test/core/AbstractSalesManagerCoreTestCase.java b/sm-core/src/test/java/com/salesmanager/test/core/AbstractSalesManagerCoreTestCase.java
new file mode 100644
index 0000000..08fbc81
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/core/AbstractSalesManagerCoreTestCase.java
@@ -0,0 +1,178 @@
+package com.salesmanager.test.core;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestExecutionListeners;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
+
+import com.salesmanager.core.business.catalog.category.service.CategoryService;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability;
+import com.salesmanager.core.business.catalog.product.model.description.ProductDescription;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPrice;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPriceDescription;
+import com.salesmanager.core.business.catalog.product.model.type.ProductType;
+import com.salesmanager.core.business.catalog.product.service.ProductService;
+import com.salesmanager.core.business.catalog.product.service.attribute.ProductAttributeService;
+import com.salesmanager.core.business.catalog.product.service.attribute.ProductOptionService;
+import com.salesmanager.core.business.catalog.product.service.attribute.ProductOptionValueService;
+import com.salesmanager.core.business.catalog.product.service.availability.ProductAvailabilityService;
+import com.salesmanager.core.business.catalog.product.service.image.ProductImageService;
+import com.salesmanager.core.business.catalog.product.service.manufacturer.ManufacturerService;
+import com.salesmanager.core.business.catalog.product.service.price.ProductPriceService;
+import com.salesmanager.core.business.catalog.product.service.review.ProductReviewService;
+import com.salesmanager.core.business.catalog.product.service.type.ProductTypeService;
+import com.salesmanager.core.business.customer.service.CustomerService;
+import com.salesmanager.core.business.customer.service.attribute.CustomerOptionService;
+import com.salesmanager.core.business.customer.service.attribute.CustomerOptionSetService;
+import com.salesmanager.core.business.customer.service.attribute.CustomerOptionValueService;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.util.EntityManagerUtils;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.merchant.service.MerchantStoreService;
+import com.salesmanager.core.business.order.service.OrderService;
+import com.salesmanager.core.business.payments.service.PaymentService;
+import com.salesmanager.core.business.reference.country.service.CountryService;
+import com.salesmanager.core.business.reference.currency.service.CurrencyService;
+import com.salesmanager.core.business.reference.init.service.InitializationDatabase;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.language.service.LanguageService;
+import com.salesmanager.core.business.reference.zone.service.ZoneService;
+import com.salesmanager.core.business.shoppingcart.service.ShoppingCartService;
+import com.salesmanager.core.business.system.service.EmailService;
+
+@ContextConfiguration(locations = {
+ "classpath:spring/test-spring-context.xml"
+})
+@RunWith(SpringJUnit4ClassRunner.class)
+@TestExecutionListeners({
+ DependencyInjectionTestExecutionListener.class,
+ SalesManagerCoreTestExecutionListener.class
+})
+public abstract class AbstractSalesManagerCoreTestCase {
+
+
+ @Autowired
+ protected InitializationDatabase initializationDatabase;
+
+
+ protected static final String ENGLISH_LANGUAGE_CODE = "en";
+
+ protected static final String FRENCH_LANGUAGE_CODE = "fr";
+
+ protected static final String EURO_CURRENCY_CODE = "EUR";
+
+ protected static final String FR_COUNTRY_CODE = "FR";
+
+ protected static final String CAD_CURRENCY_CODE = "CAD";
+
+ protected static final String CA_COUNTRY_CODE = "CA";
+
+ protected static final String VT_ZONE_CODE = "VT";
+
+ @Autowired
+ private EntityManagerUtils entityManagerUtils;
+
+ @Autowired
+ protected ProductService productService;
+
+
+ @Autowired
+ protected ProductPriceService productPriceService;
+
+ @Autowired
+ protected ProductAttributeService productAttributeService;
+
+ @Autowired
+ protected ProductOptionService productOptionService;
+
+ @Autowired
+ protected ProductOptionValueService productOptionValueService;
+
+ @Autowired
+ protected ProductAvailabilityService productAvailabilityService;
+
+ @Autowired
+ protected ProductReviewService productReviewService;
+
+ @Autowired
+ protected ProductImageService productImageService;
+
+ @Autowired
+ protected CategoryService categoryService;
+
+ @Autowired
+ protected MerchantStoreService merchantService;
+
+ @Autowired
+ protected ProductTypeService productTypeService;
+
+ @Autowired
+ protected LanguageService languageService;
+
+ @Autowired
+ protected CountryService countryService;
+
+ @Autowired
+ protected CurrencyService currencyService;
+
+ @Autowired
+ protected ManufacturerService manufacturerService;
+
+ @Autowired
+ protected ZoneService zoneService;
+
+ @Autowired
+ protected CustomerService customerService;
+
+ @Autowired
+ protected CustomerOptionService customerOptionService;
+
+ @Autowired
+ protected CustomerOptionValueService customerOptionValueService;
+
+ @Autowired
+ protected CustomerOptionSetService customerOptionSetService;
+
+ @Autowired
+ protected OrderService orderService;
+
+ @Autowired
+ protected PaymentService paymentService;
+
+ @Autowired
+ protected ShoppingCartService shoppingCartService;
+
+ @Autowired
+ protected EmailService emailService;
+
+
+ @Before
+ public void init() throws ServiceException {
+
+ populate();
+
+ }
+
+ @After
+ public void close() throws ServiceException {
+
+ }
+
+
+
+ private void populate() throws ServiceException {
+
+
+ initializationDatabase.populate("TEST");
+
+
+ }
+}
diff --git a/sm-core/src/test/java/com/salesmanager/test/core/SalesManagerCoreTestExecutionListener.java b/sm-core/src/test/java/com/salesmanager/test/core/SalesManagerCoreTestExecutionListener.java
new file mode 100644
index 0000000..a7ea63e
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/core/SalesManagerCoreTestExecutionListener.java
@@ -0,0 +1,29 @@
+package com.salesmanager.test.core;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.TestContext;
+import org.springframework.test.context.support.AbstractTestExecutionListener;
+
+import com.salesmanager.core.business.generic.util.EntityManagerUtils;
+
+public class SalesManagerCoreTestExecutionListener extends AbstractTestExecutionListener {
+
+ @Autowired
+ private EntityManagerUtils entityManagerUtils;
+
+ @Override
+ public void beforeTestClass(TestContext testContext) throws Exception {
+ testContext.getApplicationContext().getAutowireCapableBeanFactory().autowireBean(this);
+ }
+
+ @Override
+ public void beforeTestMethod(TestContext testContext) throws Exception {
+ entityManagerUtils.openEntityManager();
+ }
+
+ @Override
+ public void afterTestMethod(TestContext testContext) throws Exception {
+ entityManagerUtils.closeEntityManager();
+ }
+
+}
diff --git a/sm-core/src/test/java/com/salesmanager/test/customer/CustomerOptionsTestCase.java b/sm-core/src/test/java/com/salesmanager/test/customer/CustomerOptionsTestCase.java
new file mode 100644
index 0000000..d50facb
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/customer/CustomerOptionsTestCase.java
@@ -0,0 +1,198 @@
+package com.salesmanager.test.customer;
+
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import junit.framework.Assert;
+
+import org.junit.Test;
+
+import com.salesmanager.core.business.common.model.Billing;
+import com.salesmanager.core.business.common.model.Delivery;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.customer.model.CustomerGender;
+import com.salesmanager.core.business.customer.model.attribute.CustomerOption;
+import com.salesmanager.core.business.customer.model.attribute.CustomerOptionDescription;
+import com.salesmanager.core.business.customer.model.attribute.CustomerOptionSet;
+import com.salesmanager.core.business.customer.model.attribute.CustomerOptionValue;
+import com.salesmanager.core.business.customer.model.attribute.CustomerOptionValueDescription;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.test.core.AbstractSalesManagerCoreTestCase;
+
+public class CustomerOptionsTestCase extends AbstractSalesManagerCoreTestCase {
+
+ @Test
+ public void testCreateAndGetCustomerOptions() throws ServiceException {
+
+
+ MerchantStore store = merchantService.getByCode(MerchantStore.DEFAULT_STORE);
+ Country country = countryService.getByCode("CA");
+ Zone zone = zoneService.getByCode("VT");
+ Language en = languageService.getByCode("en");
+
+ Customer customer = new Customer();
+ customer.setMerchantStore(store);
+ customer.setEmailAddress("test@test.com");
+ customer.setGender(CustomerGender.M);
+
+ customer.setAnonymous(true);
+ customer.setCompany("ifactory");
+ customer.setDateOfBirth(new Date());
+ customer.setNick("My nick");
+ customer.setPassword("123456");
+
+ customer.setDefaultLanguage(store.getDefaultLanguage());
+
+ Delivery delivery = new Delivery();
+ delivery.setAddress("Shipping address");
+ delivery.setCountry(country);
+ delivery.setZone(zone);
+
+
+ Billing billing = new Billing();
+ billing.setAddress("Billing address");
+ billing.setCountry(country);
+ billing.setZone(zone);
+
+ customer.setBilling(billing);
+ customer.setDelivery(delivery);
+
+ customerService.create(customer);
+ customer = customerService.getById(customer.getId());
+
+
+ //create option value
+ CustomerOptionValue yes = new CustomerOptionValue();
+ yes.setCode("yes");
+ yes.setMerchantStore(store);
+ CustomerOptionValueDescription yesDescription = new CustomerOptionValueDescription();
+ yesDescription.setLanguage(en);
+ yesDescription.setCustomerOptionValue(yes);
+
+ customerOptionValueService.create(yes);
+
+ CustomerOptionValue no = new CustomerOptionValue();
+ no.setCode("no");
+ no.setMerchantStore(store);
+ CustomerOptionValueDescription noDescription = new CustomerOptionValueDescription();
+ noDescription.setLanguage(en);
+ noDescription.setCustomerOptionValue(no);
+
+ customerOptionValueService.create(no);
+
+ CustomerOption subscribedToMailingList = new CustomerOption();
+ subscribedToMailingList.setActive(true);
+ subscribedToMailingList.setPublicOption(true);
+ subscribedToMailingList.setCode("subscribedToMailingList");
+ subscribedToMailingList.setMerchantStore(store);
+
+ CustomerOptionDescription mailingListDesciption= new CustomerOptionDescription();
+ mailingListDesciption.setName("Subscribed to mailing list");
+ mailingListDesciption.setDescription("Subscribed to mailing list");
+ mailingListDesciption.setLanguage(en);
+ mailingListDesciption.setCustomerOption(subscribedToMailingList);
+
+ Set<CustomerOptionDescription> mailingListDesciptionList = new HashSet<CustomerOptionDescription>();
+ mailingListDesciptionList.add(mailingListDesciption);
+ subscribedToMailingList.setDescriptions(mailingListDesciptionList);
+
+ customerOptionService.create(subscribedToMailingList);
+
+
+
+ CustomerOption hasReturnedItems = new CustomerOption();
+ hasReturnedItems.setActive(true);
+ hasReturnedItems.setPublicOption(true);
+ hasReturnedItems.setCode("hasReturnedItems");
+ hasReturnedItems.setMerchantStore(store);
+
+ CustomerOptionDescription hasReturnedItemsDesciption= new CustomerOptionDescription();
+ hasReturnedItemsDesciption.setName("Has returned items");
+ hasReturnedItemsDesciption.setDescription("Has returned items");
+ hasReturnedItemsDesciption.setLanguage(en);
+ hasReturnedItemsDesciption.setCustomerOption(hasReturnedItems);
+
+ Set<CustomerOptionDescription> hasReturnedItemsList = new HashSet<CustomerOptionDescription>();
+ hasReturnedItemsList.add(hasReturnedItemsDesciption);
+ hasReturnedItems.setDescriptions(hasReturnedItemsList);
+
+ customerOptionService.create(hasReturnedItems);
+
+ subscribedToMailingList.setSortOrder(3);
+
+ customerOptionService.update(subscribedToMailingList);
+
+
+/* CustomerOptionSetId mailingListSetYesId = new CustomerOptionSetId();
+ mailingListSetYesId.setCustomerOption(subscribedToMailingList);
+ mailingListSetYesId.setCustomerOptionValue(yes);*/
+
+ CustomerOptionSet mailingListSetYes = new CustomerOptionSet();
+
+ //mailingListSetYes.setPk(mailingListSetYesId);
+ mailingListSetYes.setSortOrder(0);
+ mailingListSetYes.setCustomerOption(subscribedToMailingList);
+ mailingListSetYes.setCustomerOptionValue(yes);
+
+ customerOptionSetService.create(mailingListSetYes);
+ //subscribedToMailingList.getCustomerOptions().add(mailingListSetYes);
+ //customerOptionService.update(subscribedToMailingList);
+
+/* CustomerOptionSetId mailingListSetNoId = new CustomerOptionSetId();
+ mailingListSetNoId.setCustomerOption(subscribedToMailingList);
+ mailingListSetNoId.setCustomerOptionValue(no);*/
+
+ CustomerOptionSet mailingListSetNo = new CustomerOptionSet();
+ //mailingListSetNo.setPk(mailingListSetNoId);
+ mailingListSetNo.setSortOrder(1);
+ mailingListSetNo.setCustomerOption(subscribedToMailingList);
+ mailingListSetNo.setCustomerOptionValue(no);
+
+ customerOptionSetService.create(mailingListSetNo);
+
+ //subscribedToMailingList.getCustomerOptions().add(mailingListSetNo);
+ //customerOptionService.update(subscribedToMailingList);
+
+
+/* CustomerOptionSetId hasReturnedItemsYesId = new CustomerOptionSetId();
+ hasReturnedItemsYesId.setCustomerOption(hasReturnedItems);
+ hasReturnedItemsYesId.setCustomerOptionValue(yes);*/
+
+ CustomerOptionSet hasReturnedItemsYes = new CustomerOptionSet();
+ //hasReturnedItemsYes.setPk(hasReturnedItemsYesId);
+ hasReturnedItemsYes.setSortOrder(0);
+ hasReturnedItemsYes.setCustomerOption(hasReturnedItems);
+ hasReturnedItemsYes.setCustomerOptionValue(yes);
+
+ customerOptionSetService.create(hasReturnedItemsYes);
+
+
+ //hasReturnedItems.getCustomerOptions().add(hasReturnedItemsYes);
+ //customerOptionService.update(hasReturnedItems);
+
+ subscribedToMailingList.setSortOrder(2);
+ customerOptionService.update(subscribedToMailingList);
+
+ CustomerOption option = customerOptionService.getById(subscribedToMailingList.getId());
+
+ option.setSortOrder(4);
+ customerOptionService.update(option);
+
+ List<CustomerOptionSet> optionSetList = customerOptionSetService.listByStore(store, en);
+
+ //Assert.assertEquals(3, optionSetList.size());
+ System.out.println("Size of options : " + optionSetList.size());
+
+
+
+
+
+
+ }
+}
diff --git a/sm-core/src/test/java/com/salesmanager/test/customer/CustomerSalesManagerTestCase.java b/sm-core/src/test/java/com/salesmanager/test/customer/CustomerSalesManagerTestCase.java
new file mode 100644
index 0000000..d686c8e
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/customer/CustomerSalesManagerTestCase.java
@@ -0,0 +1,69 @@
+package com.salesmanager.test.customer;
+
+import java.util.Date;
+
+import junit.framework.Assert;
+
+import org.junit.Test;
+
+import com.salesmanager.core.business.common.model.Billing;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.customer.model.CustomerGender;
+import com.salesmanager.core.business.common.model.Delivery;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.test.core.AbstractSalesManagerCoreTestCase;
+
+public class CustomerSalesManagerTestCase extends AbstractSalesManagerCoreTestCase {
+
+ @Test
+ public void createCustomer() throws ServiceException {
+
+
+ MerchantStore store = merchantService.getByCode(MerchantStore.DEFAULT_STORE);
+ Country country = countryService.getByCode("CA");
+ Zone zone = zoneService.getByCode("VT");
+
+ Customer customer = new Customer();
+ customer.setMerchantStore(store);
+ customer.setEmailAddress("test@test.com");
+ customer.setGender(CustomerGender.M);
+
+ customer.setAnonymous(true);
+ customer.setCompany("ifactory");
+ customer.setDateOfBirth(new Date());
+ customer.setNick("My nick");
+ customer.setPassword("123456");
+ customer.setDefaultLanguage(store.getDefaultLanguage());
+
+ Delivery delivery = new Delivery();
+ delivery.setAddress("Shipping address");
+ delivery.setCountry(country);
+ delivery.setZone(zone);
+
+
+ Billing billing = new Billing();
+ billing.setFirstName("John");
+ billing.setLastName("Bossanova");
+ billing.setAddress("Billing address");
+ billing.setCountry(country);
+ billing.setZone(zone);
+
+ customer.setBilling(billing);
+ customer.setDelivery(delivery);
+
+ customerService.create(customer);
+ customer = customerService.getById(customer.getId());
+ String countryCode = customer.getBilling().getCountry().getIsoCode();
+ String zoneCode = customer.getBilling().getZone().getCode();
+ System.out.println(countryCode + zoneCode);
+
+ Assert.assertEquals(countryCode, "CA");
+ Assert.assertEquals(zoneCode, "VT");
+ Assert.assertTrue(customerService.count() == 1);
+ Assert.assertNotNull(customerService.getByName("Leonardo"));
+
+ }
+}
diff --git a/sm-core/src/test/java/com/salesmanager/test/email/EmailTestCase.java b/sm-core/src/test/java/com/salesmanager/test/email/EmailTestCase.java
new file mode 100644
index 0000000..500d211
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/email/EmailTestCase.java
@@ -0,0 +1,47 @@
+package com.salesmanager.test.email;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.modules.email.Email;
+import com.salesmanager.test.core.AbstractSalesManagerCoreTestCase;
+
+public class EmailTestCase extends AbstractSalesManagerCoreTestCase {
+
+ @Test
+ public void sendHtmlEmail() throws Exception {
+
+ Map<String, String> templateTokens = new HashMap<String, String>();
+ templateTokens.put("EMAIL_NEW_USER_TEXT", "Hi My Friend,");
+ templateTokens.put("EMAIL_STORE_NAME", "Shopizer Store");
+ templateTokens.put("EMAIL_ADMIN_LABEL", "Adminstrator:");
+ templateTokens.put("EMAIL_TEXT_NEW_USER_CREATED", "New user created");
+ templateTokens.put("EMAIL_CUSTOMER_FIRSTNAME", "The");
+ templateTokens.put("EMAIL_CUSTOMER_LAST", "Rock");
+ templateTokens.put("EMAIL_ADMIN_USERNAME_LABEL", "UserName:");
+ templateTokens.put("EMAIL_ADMIN_NAME", "Admin");
+ templateTokens.put("EMAIL_ADMIN_PASSWORD_LABEL", "Password:");
+ templateTokens.put("EMAIL_ADMIN_PASSWORD", "12345");
+ templateTokens.put("EMAIL_ADMIN_URL_LABEL", "URL:");
+ templateTokens.put("EMAIL_ADMIN_URL", "http://www.shopizer.com");
+ templateTokens.put("EMAIL_FOOTER_COPYRIGHT", "Copyright @ Shopizer 2013, All Rights Reserved!");
+ templateTokens.put("EMAIL_DISCLAIMER", "Disclaimer text goes here...");
+ templateTokens.put("EMAIL_SPAM_DISCLAIMER", "Spam Disclaimer text goes here...");
+
+
+ Email email = new Email();
+ email.setFrom("Shopizer");
+ email.setFromEmail("admin@shopizer.com");
+ email.setSubject("HTML Test Mail");
+ email.setTo("carl@csticonsulting.com");
+ email.setTemplateName("email_template_new_user.ftl");
+ email.setTemplateTokens(templateTokens);
+
+ MerchantStore store = merchantService.getById(1);
+
+ emailService.sendHtmlEmail(store, email);
+ }
+}
diff --git a/sm-core/src/test/java/com/salesmanager/test/init/AbstractInitSalesManagerCore.java b/sm-core/src/test/java/com/salesmanager/test/init/AbstractInitSalesManagerCore.java
new file mode 100644
index 0000000..26a047f
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/init/AbstractInitSalesManagerCore.java
@@ -0,0 +1,204 @@
+package com.salesmanager.test.init;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import javax.persistence.EntityManager;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.metamodel.EntityType;
+
+import org.codehaus.jackson.JsonParseException;
+import org.codehaus.jackson.map.JsonMappingException;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestExecutionListeners;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.util.EntityManagerUtils;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.country.model.CountryDescription;
+import com.salesmanager.core.business.reference.country.service.CountryService;
+import com.salesmanager.core.business.reference.currency.model.Currency;
+import com.salesmanager.core.business.reference.currency.service.CurrencyService;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.language.service.LanguageService;
+import com.salesmanager.core.business.reference.zone.imports.ZoneLoader;
+import com.salesmanager.core.business.reference.zone.imports.ZoneTransient;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.core.business.reference.zone.model.ZoneDescription;
+import com.salesmanager.core.business.reference.zone.service.ZoneService;
+import com.salesmanager.core.constants.SchemaConstant;
+import com.salesmanager.test.core.SalesManagerCoreTestExecutionListener;
+
+@ContextConfiguration(locations = {
+ "classpath:spring/test-spring-context.xml"
+})
+@TestExecutionListeners({
+ DependencyInjectionTestExecutionListener.class,
+ SalesManagerCoreTestExecutionListener.class
+})
+@RunWith(SpringJUnit4ClassRunner.class)
+public class AbstractInitSalesManagerCore {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(AbstractInitSalesManagerCore.class);
+
+ @Autowired
+ private EntityManagerUtils entityManagerUtils;
+
+ @Autowired
+ protected LanguageService languageService;
+
+ @Autowired
+ protected CountryService countryService;
+
+ @Autowired
+ protected ZoneService zoneService;
+
+ @Autowired
+ protected CurrencyService currencyService;
+
+ @Before
+ public void clean() throws ServiceException {
+ cleanAll();
+ checkEmptyDatabase();
+ }
+
+ @Test
+ public void init() throws ServiceException, JsonParseException, JsonMappingException, IOException {
+ initLanguages();
+ initCountries();
+// initCurrencies();
+ initZones();
+ }
+
+ private void initZones() throws JsonParseException, JsonMappingException, IOException, ServiceException {
+ Map<String, List<ZoneTransient>> loadZones = new ZoneLoader().loadZoneConfigurations();
+ for(String languageCode : loadZones.keySet()) {
+ Language language = languageService.getByCode(languageCode);
+ List<ZoneTransient> transients = loadZones.get(languageCode);
+
+ for(ZoneTransient zoneTransient : transients) {
+ String code = zoneTransient.getZoneCode();
+ String name = zoneTransient.getZoneName();
+ Country country = countryService.getByCode(zoneTransient.getCountryCode());
+
+ if (country != null) {
+ Zone zone = zoneService.getByCode(code);
+ if (zone == null) {
+ zone = new Zone(country, name, code);
+ zoneService.create(zone);
+ }
+
+ ZoneDescription description = new ZoneDescription(zone, language, name);
+ zoneService.addDescription(zone, description);
+ } else {
+ LOGGER.info("Import Zone : bad country code");
+ }
+ }
+ }
+ }
+
+ public void initCountries() throws ServiceException {
+ for(String code : SchemaConstant.COUNTRY_ISO_CODE) {
+ Locale locale = SchemaConstant.LOCALES.get(code);
+ if (locale != null) {
+ Country country = new Country(locale.getCountry());
+ countryService.create(country);
+
+ for (Language language : languageService.list()) {
+ String name = locale.getDisplayCountry(new Locale(language.getCode()));
+ CountryDescription description = new CountryDescription(language, name);
+ countryService.addCountryDescription(country, description);
+ }
+ }
+ }
+ }
+
+ public void initLanguages() throws ServiceException {
+ for(String code : SchemaConstant.LANGUAGE_ISO_CODE) {
+ Language language = new Language(code);
+ languageService.create(language);
+ }
+ }
+
+ private void initCurrencies() throws ServiceException {
+ for (String code : SchemaConstant.CURRENCY_MAP.keySet()) {
+ Currency currency = new Currency();
+ try {
+ currency.setCurrency(java.util.Currency.getInstance(code));
+ currency.setName(SchemaConstant.CURRENCY_MAP.get(code));
+ currencyService.create(currency);
+ } catch (IllegalArgumentException e) {
+ LOGGER.info("Import Currency : bad currency code" + code);
+ }
+
+ }
+ }
+
+ private void cleanAll() throws ServiceException {
+ cleanCurrency();
+ cleanCountry();
+ cleanLanguage();
+ cleanZone();
+ }
+
+ private void cleanZone() throws ServiceException {
+ for(Zone zone : zoneService.list()) {
+ zoneService.delete(zone);
+ }
+ }
+
+ private void cleanCurrency() throws ServiceException {
+ for(Currency currency : currencyService.list()) {
+ currencyService.delete(currency);
+ }
+ }
+
+ private void cleanCountry() throws ServiceException {
+ for(Country country : countryService.list()) {
+ countryService.delete(country);
+ }
+ }
+
+ private void cleanLanguage() throws ServiceException {
+ List<Language> languages = languageService.list();
+ for (Language language : languages) {
+ languageService.delete(language);
+ }
+ }
+
+ private void checkEmptyDatabase() {
+ Set<EntityType<?>> entityTypes = getEntityManager().getEntityManagerFactory().getMetamodel().getEntities();
+ for (EntityType<?> entityType : entityTypes) {
+ List<?> entities = listEntities(entityType.getBindableJavaType());
+
+ if (entities.size() > 0) {
+ Assert.fail(String.format("Remaining objects of type %1$s ", entities.get(0).getClass().getSimpleName()));
+ }
+ }
+ }
+
+ protected <E> List<E> listEntities(Class<E> clazz) {
+ CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
+ CriteriaQuery<E> cq = cb.createQuery(clazz);
+ cq.from(clazz);
+
+ return entityManagerUtils.getEntityManager().createQuery(cq).getResultList();
+ }
+
+ private EntityManager getEntityManager() {
+ return entityManagerUtils.getEntityManager();
+ }
+}
diff --git a/sm-core/src/test/java/com/salesmanager/test/isolated/IsolatedTestCase.java b/sm-core/src/test/java/com/salesmanager/test/isolated/IsolatedTestCase.java
new file mode 100644
index 0000000..6967f23
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/isolated/IsolatedTestCase.java
@@ -0,0 +1,1378 @@
+package com.salesmanager.test.isolated;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.sql.Date;
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.log4j.Logger;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestExecutionListeners;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
+
+import com.salesmanager.core.business.catalog.category.model.Category;
+import com.salesmanager.core.business.catalog.category.model.CategoryDescription;
+import com.salesmanager.core.business.catalog.category.service.CategoryService;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.ProductCriteria;
+import com.salesmanager.core.business.catalog.product.model.ProductList;
+import com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability;
+import com.salesmanager.core.business.catalog.product.model.description.ProductDescription;
+import com.salesmanager.core.business.catalog.product.model.image.ProductImage;
+import com.salesmanager.core.business.catalog.product.model.image.ProductImageDescription;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.Manufacturer;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.ManufacturerDescription;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPrice;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPriceDescription;
+import com.salesmanager.core.business.catalog.product.model.type.ProductType;
+import com.salesmanager.core.business.catalog.product.service.ProductService;
+import com.salesmanager.core.business.catalog.product.service.attribute.ProductAttributeService;
+import com.salesmanager.core.business.catalog.product.service.attribute.ProductOptionService;
+import com.salesmanager.core.business.catalog.product.service.attribute.ProductOptionValueService;
+import com.salesmanager.core.business.catalog.product.service.availability.ProductAvailabilityService;
+import com.salesmanager.core.business.catalog.product.service.image.ProductImageService;
+import com.salesmanager.core.business.catalog.product.service.manufacturer.ManufacturerService;
+import com.salesmanager.core.business.catalog.product.service.price.ProductPriceService;
+import com.salesmanager.core.business.catalog.product.service.type.ProductTypeService;
+import com.salesmanager.core.business.content.service.ContentService;
+import com.salesmanager.core.business.customer.service.CustomerService;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.generic.util.EntityManagerUtils;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.merchant.service.MerchantStoreService;
+import com.salesmanager.core.business.order.service.OrderService;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.country.service.CountryService;
+import com.salesmanager.core.business.reference.currency.model.Currency;
+import com.salesmanager.core.business.reference.currency.service.CurrencyService;
+import com.salesmanager.core.business.reference.init.service.InitializationDatabase;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.language.service.LanguageService;
+import com.salesmanager.core.business.reference.zone.service.ZoneService;
+import com.salesmanager.core.business.system.model.IntegrationConfiguration;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+import com.salesmanager.core.business.system.service.ModuleConfigurationService;
+import com.salesmanager.core.business.user.model.Group;
+import com.salesmanager.core.business.user.model.Permission;
+import com.salesmanager.core.business.user.service.GroupService;
+import com.salesmanager.core.business.user.service.PermissionService;
+import com.salesmanager.core.business.user.service.UserService;
+import com.salesmanager.core.utils.reference.ConfigurationModulesLoader;
+import com.salesmanager.test.core.SalesManagerCoreTestExecutionListener;
+
+@ContextConfiguration( locations = { "classpath:spring/test-spring-context.xml" } )
+@RunWith( SpringJUnit4ClassRunner.class )
+@TestExecutionListeners( { DependencyInjectionTestExecutionListener.class, SalesManagerCoreTestExecutionListener.class } )
+public class IsolatedTestCase
+{
+
+ private static final Logger log = Logger.getLogger( IsolatedTestCase.class );
+
+ private static final Date date = new Date( System.currentTimeMillis() );
+
+ @Autowired
+ private EntityManagerUtils entityManagerUtils;
+
+ @Autowired
+ protected ProductService productService;
+
+ @Autowired
+ protected ProductPriceService productPriceService;
+
+ @Autowired
+ protected ProductAttributeService productAttributeService;
+
+ @Autowired
+ protected ProductOptionService productOptionService;
+
+
+ @Autowired
+ protected ProductOptionValueService productOptionValueService;
+
+ @Autowired
+ protected ProductAvailabilityService productAvailabilityService;
+
+ @Autowired
+ protected ProductImageService productImageService;
+
+ @Autowired
+ protected ContentService contentService;
+
+ @Autowired
+ protected CategoryService categoryService;
+
+ @Autowired
+ protected MerchantStoreService merchantService;
+
+ @Autowired
+ protected ProductTypeService productTypeService;
+
+ @Autowired
+ protected LanguageService languageService;
+
+ @Autowired
+ protected CountryService countryService;
+
+ @Autowired
+ protected ZoneService zoneService;
+
+ @Autowired
+ protected CustomerService customerService;
+
+ @Autowired
+ protected ManufacturerService manufacturerService;
+
+ @Autowired
+ protected CurrencyService currencyService;
+
+ @Autowired
+ protected OrderService orderService;
+
+ @Autowired
+ protected GroupService groupService;
+
+ @Autowired
+ protected PermissionService permissionService;
+
+ @Autowired
+ protected UserService userService;
+
+ @Autowired
+ protected InitializationDatabase initializationDatabase;
+
+ @Autowired
+ protected ModuleConfigurationService moduleConfigurationService;
+
+
+
+ // @Autowired
+ protected TestSupportFactory testSupportFactory;
+
+ @Test
+ public void test1CreateReferences()
+ throws ServiceException
+ {
+
+ initializationDatabase.populate( "TEST" );
+
+
+
+ }
+
+ @Test
+ public void testSearchProduct()
+ throws ServiceException
+ {
+
+ final MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+ final Language en = languageService.getByCode( "en" );
+
+ final ProductCriteria criteria = new ProductCriteria();
+ criteria.setStartIndex( 0 );
+ criteria.setMaxCount( 75 );
+
+ final List<Long> categoryIds = new ArrayList<Long>();
+ categoryIds.add( 1L );
+ categoryIds.add( 2L );
+ categoryIds.add( 3L );
+ categoryIds.add( 5L );
+ categoryIds.add( 4L );
+
+ criteria.setAvailable( new Boolean( false ) );
+
+ criteria.setCategoryIds( categoryIds );
+
+ final ProductList l = productService.listByStore( store, en, criteria );
+
+ System.out.println( "done" );
+
+ }
+
+ @Test
+ public void testGetMerchant()
+ throws ServiceException
+ {
+
+ final MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+ System.out.println( "done" );
+
+ }
+
+ @Test
+ public void testCreateProductWithImage()
+ throws ServiceException, IOException
+ {
+
+ final Language en = languageService.getByCode( "en" );
+ final Language fr = languageService.getByCode( "fr" );
+ final Country ca = countryService.getByCode( "CA" );
+ final Currency currency = currencyService.getByCode( "CAD" );
+ final MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+
+ final ProductType generalType = productTypeService.getProductType( ProductType.GENERAL_TYPE );
+
+ final Category book = categoryService.getByCode( store, "book" );
+ final Product product = productService.getById( 1L );
+
+
+ final File file1 = new File( "/Users/csamson777/Documents/csti/cocoacart/ktm.png" );
+ if ( !file1.exists() || !file1.canRead() )
+ {
+ throw new ServiceException( "Can't read" + file1.getAbsolutePath() );
+ }
+
+ // FileInputStream is1 = new FileInputStream(file1);
+ // FileInputStream is2 = new FileInputStream(file2);
+
+ final byte[] is = IOUtils.toByteArray( new FileInputStream( file1 ) );
+ final ByteArrayInputStream is1 = new ByteArrayInputStream( is );
+
+ final ProductImage productImage1 = new ProductImage();
+ productImage1.setDefaultImage( true );
+ productImage1.setProductImage( file1.getName() );
+
+ final ProductImageDescription desc1 = new ProductImageDescription();
+ desc1.setLanguage( en );
+ desc1.setAltTag( "ALT IMAGE 1 en" );
+ desc1.setName( "A beautifill Thing" );
+ desc1.setProductImage( productImage1 );
+
+ final ProductImageDescription desc2 = new ProductImageDescription();
+ desc2.setLanguage( fr );
+ desc2.setAltTag( "ALT IMAGE 1 fr" );
+ desc2.setName( "Superbe chose" );
+ desc2.setProductImage( productImage1 );
+
+ final List image1descriptions = new ArrayList();
+ image1descriptions.add( desc1 );
+ image1descriptions.add( desc2 );
+
+ productImage1.setDescriptions( image1descriptions );
+ productImage1.setImage( is1 );
+
+ //productImageService.addProductImage( product, productImage1 );
+
+ }
+
+ @Test
+ public void createProduct()
+ throws Exception
+ {
+
+ final Language en = languageService.getByCode( "en" );
+ final Language fr = languageService.getByCode( "fr" );
+ final Country ca = countryService.getByCode( "CA" );
+ final Currency currency = currencyService.getByCode( "CAD" );
+ final MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+ final ProductType generalType = productTypeService.getProductType( ProductType.GENERAL_TYPE );
+
+ // Category book = categoryService.getByCode(store, "book");
+
+ // Manufacturer manufacturer = manufacturerService.getById(1L);
+
+ // PRODUCT 1
+
+ final Product product = new Product();
+ product.setProductHeight( new BigDecimal( 4 ) );
+ product.setProductLength( new BigDecimal( 3 ) );
+ product.setProductWidth( new BigDecimal( 1 ) );
+ product.setSku( "XYZTEST" );
+ // product.setManufacturer(manufacturer);
+ product.setType( generalType );
+ product.setMerchantStore( store );
+
+ // Product description
+ final ProductDescription description = new ProductDescription();
+ description.setName( "Test with image" );
+ description.setLanguage( en );
+ description.setProduct( product );
+
+ product.getDescriptions().add( description );
+ // product.getCategories().add(book);
+
+ final Set<ProductAvailability> availabilities = new HashSet<ProductAvailability>();
+
+ final ProductPrice dprice = new ProductPrice();
+ dprice.setDefaultPrice( true );
+ dprice.setProductPriceAmount( new BigDecimal( 29.99 ) );
+
+ final Set<ProductPrice> prices = new HashSet<ProductPrice>();
+ prices.add( dprice );
+
+ // Availability
+ final ProductAvailability availability = new ProductAvailability();
+ availability.setProductDateAvailable( date );
+ availability.setProductQuantity( 100 );
+ availability.setRegion( "*" );
+
+ availability.setPrices( prices );
+
+ availabilities.add( availability );
+
+ product.setAvailabilities( availabilities );
+
+ final File file1 = new File( "/Users/csamson777/Documents/csti/cocoacart/ktm.png" );
+ if ( !file1.exists() || !file1.canRead() )
+ {
+ throw new ServiceException( "Can't read" + file1.getAbsolutePath() );
+ }
+
+ // FileInputStream is1 = new FileInputStream(file1);
+
+ final byte[] is = IOUtils.toByteArray( new FileInputStream( file1 ) );
+ final ByteArrayInputStream is1 = new ByteArrayInputStream( is );
+
+ final ProductImage productImage = new ProductImage();
+ productImage.setDefaultImage( true );
+ productImage.setProductImage( file1.getName() );
+
+ final ProductImageDescription desc1 = new ProductImageDescription();
+ desc1.setLanguage( en );
+ desc1.setAltTag( "ALT IMAGE 1 en" );
+ desc1.setName( "Product image" );
+
+ final ProductImageDescription desc2 = new ProductImageDescription();
+ desc2.setLanguage( fr );
+ desc2.setAltTag( "ALT IMAGE 1 fr" );
+ desc2.setName( "Image du produit" );
+
+ final List<ProductImageDescription> imagedescriptions = new ArrayList<ProductImageDescription>();
+ imagedescriptions.add( desc1 );
+ imagedescriptions.add( desc2 );
+
+ productImage.setDescriptions( imagedescriptions );
+ productImage.setImage( is1 );
+
+ product.getImages().add( productImage );
+
+ productService.saveOrUpdate( product );
+
+ }
+
+
+
+/* @Test
+ public void addStaticContentData() throws ServiceException, FileNotFoundException{
+
+ final MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+ final File file1 = new File( "D:/wamp/www/travellingrants/wp-content/themes/TravelPro/style.css" );
+
+ if ( !file1.exists() || !file1.canRead() )
+ {
+ throw new ServiceException( "Can't read" + file1.getAbsolutePath() );
+ }
+
+ InputStaticContentData staticData=new InputStaticContentData();
+ staticData.setFileName( file1.getName() );
+ staticData.setFile( new FileInputStream( file1 ) );
+ staticData.setContentType( StaticContentType.STATIC_DATA );
+ staticContentService.addStaticContentData( store.getCode(), staticData );
+
+
+
+ }
+
+ @Test
+ public void addStaticContentDataFiles() throws ServiceException, FileNotFoundException{
+
+ List<InputStaticContentData> inputStaticContentDataList=new ArrayList<InputStaticContentData>();
+ final MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+ final File file1 = new File( "D:/wamp/www/travellingrants/wp-content/themes/TravelPro/style.css" );
+
+ if ( !file1.exists() || !file1.canRead() )
+ {
+ throw new ServiceException( "Can't read" + file1.getAbsolutePath() );
+ }
+
+ InputStaticContentData staticData=new InputStaticContentData();
+ staticData.setFileName( file1.getName() );
+ staticData.setFile( new FileInputStream( file1 ) );
+ staticData.setContentType( StaticContentType.STATIC_DATA );
+ inputStaticContentDataList.add( staticData );
+
+ final File file2= new File( "D:/personal/songs/Bahut der kardi.mp3" );
+
+ if ( !file2.exists() || !file2.canRead() )
+ {
+ throw new ServiceException( "Can't read" + file2.getAbsolutePath() );
+ }
+
+ InputStaticContentData staticData1=new InputStaticContentData();
+ staticData1.setFileName( file2.getName() );
+ staticData1.setFile( new FileInputStream( file2 ) );
+ staticData1.setContentType( StaticContentType.DIGITAL_DATA );
+ inputStaticContentDataList.add( staticData1 );
+ staticContentService.addStaticContentDataFiles( store.getCode(), inputStaticContentDataList );
+
+ }
+
+ @Test
+ public void getStaticContentData() throws ServiceException{
+ final MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+ String fileName="style.css";
+ OutputStaticContentData data=staticContentService.getStaticContentData( store.getCode(), fileName );
+ System.out.println(data.getContentType());
+ //System.out.println(data.getFile().);
+
+ }*/
+
+/* @Test
+ public void testGetUser() throws Exception {
+
+ List<Integer> groups = new ArrayList<Integer>();
+ User user = userService.getByUserName("admin");
+ for(Group group : user.getGroups()) {
+
+ System.out.println(group.getGroupName());
+ groups.add(group.getId());
+ for(Permission permission : group.getPermissions()) {
+
+ System.out.println(permission.getPermissionName());
+
+
+ }
+
+ }
+
+ List<Permission> permissions = permissionService.getPermissions(groups);
+ for(Permission permission : permissions) {
+ System.out.println(permission.getPermissionName());
+ }
+
+ }*/
+
+ @Test
+ public void test2CreateProducts()
+ throws ServiceException
+ {
+
+ final Language en = languageService.getByCode( "en" );
+ final Language fr = languageService.getByCode( "fr" );
+ final Country ca = countryService.getByCode( "CA" );
+ final Currency currency = currencyService.getByCode( "CAD" );
+ final MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+ final ProductType generalType = productTypeService.getProductType( ProductType.GENERAL_TYPE );
+
+ final Category book = new Category();
+ book.setMerchantStore( store );
+ book.setCode( "book" );
+
+ final CategoryDescription bookEnglishDescription = new CategoryDescription();
+ bookEnglishDescription.setName( "Book" );
+ bookEnglishDescription.setCategory( book );
+ bookEnglishDescription.setLanguage( en );
+
+ final CategoryDescription bookFrenchDescription = new CategoryDescription();
+ bookFrenchDescription.setName( "Livre" );
+ bookFrenchDescription.setCategory( book );
+ bookFrenchDescription.setLanguage( fr );
+
+ final List<CategoryDescription> descriptions = new ArrayList<CategoryDescription>();
+ descriptions.add( bookEnglishDescription );
+ descriptions.add( bookFrenchDescription );
+
+ book.setDescriptions( descriptions );
+
+ categoryService.create( book );
+
+ final Category music = new Category();
+ music.setMerchantStore( store );
+ music.setCode( "music" );
+
+ final CategoryDescription musicEnglishDescription = new CategoryDescription();
+ musicEnglishDescription.setName( "Music" );
+ musicEnglishDescription.setCategory( music );
+ musicEnglishDescription.setLanguage( en );
+
+ final CategoryDescription musicFrenchDescription = new CategoryDescription();
+ musicFrenchDescription.setName( "Musique" );
+ musicFrenchDescription.setCategory( music );
+ musicFrenchDescription.setLanguage( fr );
+
+ final List<CategoryDescription> descriptions2 = new ArrayList<CategoryDescription>();
+ descriptions2.add( musicEnglishDescription );
+ descriptions2.add( musicFrenchDescription );
+
+ music.setDescriptions( descriptions2 );
+
+ categoryService.create( music );
+
+ final Category novell = new Category();
+ novell.setMerchantStore( store );
+ novell.setCode( "novell" );
+
+ final CategoryDescription novellEnglishDescription = new CategoryDescription();
+ novellEnglishDescription.setName( "Novell" );
+ novellEnglishDescription.setCategory( novell );
+ novellEnglishDescription.setLanguage( en );
+
+ final CategoryDescription novellFrenchDescription = new CategoryDescription();
+ novellFrenchDescription.setName( "Roman" );
+ novellFrenchDescription.setCategory( novell );
+ novellFrenchDescription.setLanguage( fr );
+
+ final List<CategoryDescription> descriptions3 = new ArrayList<CategoryDescription>();
+ descriptions3.add( novellEnglishDescription );
+ descriptions3.add( novellFrenchDescription );
+
+ novell.setDescriptions( descriptions3 );
+
+ novell.setParent( book );
+
+ categoryService.create( novell );
+ categoryService.addChild( book, novell );
+
+ final Category tech = new Category();
+ tech.setMerchantStore( store );
+ tech.setCode( "tech" );
+
+ final CategoryDescription techEnglishDescription = new CategoryDescription();
+ techEnglishDescription.setName( "Technology" );
+ techEnglishDescription.setCategory( tech );
+ techEnglishDescription.setLanguage( en );
+
+ final CategoryDescription techFrenchDescription = new CategoryDescription();
+ techFrenchDescription.setName( "Technologie" );
+ techFrenchDescription.setCategory( tech );
+ techFrenchDescription.setLanguage( fr );
+
+ final List<CategoryDescription> descriptions4 = new ArrayList<CategoryDescription>();
+ descriptions4.add( techFrenchDescription );
+ descriptions4.add( techFrenchDescription );
+
+ tech.setDescriptions( descriptions4 );
+
+ tech.setParent( book );
+
+ categoryService.create( tech );
+ categoryService.addChild( book, tech );
+
+ final Category fiction = new Category();
+ fiction.setMerchantStore( store );
+ fiction.setCode( "fiction" );
+
+ final CategoryDescription fictionEnglishDescription = new CategoryDescription();
+ fictionEnglishDescription.setName( "Fiction" );
+ fictionEnglishDescription.setCategory( fiction );
+ fictionEnglishDescription.setLanguage( en );
+
+ final CategoryDescription fictionFrenchDescription = new CategoryDescription();
+ fictionFrenchDescription.setName( "Sc Fiction" );
+ fictionFrenchDescription.setCategory( fiction );
+ fictionFrenchDescription.setLanguage( fr );
+
+ final List<CategoryDescription> fictiondescriptions = new ArrayList<CategoryDescription>();
+ fictiondescriptions.add( fictionEnglishDescription );
+ fictiondescriptions.add( fictionFrenchDescription );
+
+ fiction.setDescriptions( fictiondescriptions );
+
+ fiction.setParent( novell );
+
+ categoryService.create( fiction );
+ categoryService.addChild( book, fiction );
+
+ // Add products
+ // ProductType generalType = productTypeService.
+
+ final Manufacturer oreilley = new Manufacturer();
+ oreilley.setMerchantStore( store );
+
+ final ManufacturerDescription oreilleyd = new ManufacturerDescription();
+ oreilleyd.setLanguage( en );
+ oreilleyd.setName( "O\'reilley" );
+ oreilleyd.setManufacturer( oreilley );
+ oreilley.getDescriptions().add( oreilleyd );
+
+ manufacturerService.create( oreilley );
+
+ final Manufacturer packed = new Manufacturer();
+ packed.setMerchantStore( store );
+
+ final ManufacturerDescription packedd = new ManufacturerDescription();
+ packedd.setLanguage( en );
+ packedd.setManufacturer( packed );
+ packedd.setName( "Packed publishing" );
+ packed.getDescriptions().add( packedd );
+
+ manufacturerService.create( packed );
+
+ final Manufacturer novells = new Manufacturer();
+ novells.setMerchantStore( store );
+
+ final ManufacturerDescription novellsd = new ManufacturerDescription();
+ novellsd.setLanguage( en );
+ novellsd.setManufacturer( novells );
+ novellsd.setName( "Novells publishing" );
+ novells.getDescriptions().add( novellsd );
+
+ manufacturerService.create( novells );
+
+ // PRODUCT 1
+
+ final Product product = new Product();
+ product.setProductHeight( new BigDecimal( 4 ) );
+ product.setProductLength( new BigDecimal( 3 ) );
+ product.setProductWidth( new BigDecimal( 1 ) );
+ product.setSku( "TB12345" );
+ product.setManufacturer( oreilley );
+ product.setType( generalType );
+ product.setMerchantStore( store );
+
+ // Product description
+ ProductDescription description = new ProductDescription();
+ description.setName( "Spring in Action" );
+ description.setLanguage( en );
+ description.setProduct( product );
+
+ product.getDescriptions().add( description );
+
+ product.getCategories().add( tech );
+
+ productService.create( product );
+
+ // Availability
+ final ProductAvailability availability = new ProductAvailability();
+ availability.setProductDateAvailable( date );
+ availability.setProductQuantity( 100 );
+ availability.setRegion( "*" );
+ availability.setProduct( product );// associate with product
+
+ productAvailabilityService.create( availability );
+
+ final ProductPrice dprice = new ProductPrice();
+ dprice.setDefaultPrice( true );
+ dprice.setProductPriceAmount( new BigDecimal( 29.99 ) );
+ dprice.setProductAvailability( availability );
+
+ ProductPriceDescription dpd = new ProductPriceDescription();
+ dpd.setName( "Base price" );
+ dpd.setProductPrice( dprice );
+ dpd.setLanguage( en );
+
+ dprice.getDescriptions().add( dpd );
+
+ productPriceService.create( dprice );
+
+ // PRODUCT 2
+
+ final Product product2 = new Product();
+ product2.setProductHeight( new BigDecimal( 4 ) );
+ product2.setProductLength( new BigDecimal( 3 ) );
+ product2.setProductWidth( new BigDecimal( 1 ) );
+ product2.setSku( "TB2468" );
+ product2.setManufacturer( packed );
+ product2.setType( generalType );
+ product2.setMerchantStore( store );
+
+ // Product description
+ description = new ProductDescription();
+ description.setName( "This is Node.js" );
+ description.setLanguage( en );
+ description.setProduct( product2 );
+
+ product2.getDescriptions().add( description );
+
+ product2.getCategories().add( tech );
+ productService.create( product2 );
+
+ // Availability
+ final ProductAvailability availability2 = new ProductAvailability();
+ availability2.setProductDateAvailable( date );
+ availability2.setProductQuantity( 100 );
+ availability2.setRegion( "*" );
+ availability2.setProduct( product2 );// associate with product
+
+ productAvailabilityService.create( availability2 );
+
+ final ProductPrice dprice2 = new ProductPrice();
+ dprice2.setDefaultPrice( true );
+ dprice2.setProductPriceAmount( new BigDecimal( 39.99 ) );
+ dprice2.setProductAvailability( availability2 );
+
+ dpd = new ProductPriceDescription();
+ dpd.setName( "Base price" );
+ dpd.setProductPrice( dprice2 );
+ dpd.setLanguage( en );
+
+ dprice2.getDescriptions().add( dpd );
+
+ productPriceService.create( dprice2 );
+
+ // PRODUCT 3
+
+ final Product product3 = new Product();
+ product3.setProductHeight( new BigDecimal( 4 ) );
+ product3.setProductLength( new BigDecimal( 3 ) );
+ product3.setProductWidth( new BigDecimal( 1 ) );
+ product3.setSku( "NB1111" );
+ product3.setManufacturer( packed );
+ product3.setType( generalType );
+ product3.setMerchantStore( store );
+
+ // Product description
+ description = new ProductDescription();
+ description.setName( "A nice book for you" );
+ description.setLanguage( en );
+ description.setProduct( product3 );
+
+ product3.getDescriptions().add( description );
+
+ product3.getCategories().add( novell );
+ productService.create( product3 );
+
+ // Availability
+ final ProductAvailability availability3 = new ProductAvailability();
+ availability3.setProductDateAvailable( date );
+ availability3.setProductQuantity( 100 );
+ availability3.setRegion( "*" );
+ availability3.setProduct( product3 );// associate with product
+
+ productAvailabilityService.create( availability3 );
+
+ final ProductPrice dprice3 = new ProductPrice();
+ dprice3.setDefaultPrice( true );
+ dprice3.setProductPriceAmount( new BigDecimal( 19.99 ) );
+ dprice3.setProductAvailability( availability3 );
+
+ dpd = new ProductPriceDescription();
+ dpd.setName( "Base price" );
+ dpd.setProductPrice( dprice3 );
+ dpd.setLanguage( en );
+
+ dprice3.getDescriptions().add( dpd );
+
+ productPriceService.create( dprice3 );
+
+ // PRODUCT 4
+
+ final Product product4 = new Product();
+ product4.setProductHeight( new BigDecimal( 4 ) );
+ product4.setProductLength( new BigDecimal( 3 ) );
+ product4.setProductWidth( new BigDecimal( 1 ) );
+ product4.setSku( "SF333345" );
+ product4.setManufacturer( packed );
+ product4.setType( generalType );
+ product4.setMerchantStore( store );
+
+ // Product description
+ description = new ProductDescription();
+ description.setName( "Battle of the worlds" );
+ description.setLanguage( en );
+ description.setProduct( product4 );
+
+ product4.getDescriptions().add( description );
+
+ product4.getCategories().add( fiction );
+ productService.create( product4 );
+
+ // Availability
+ final ProductAvailability availability4 = new ProductAvailability();
+ availability4.setProductDateAvailable( date );
+ availability4.setProductQuantity( 100 );
+ availability4.setRegion( "*" );
+ availability4.setProduct( product4 );// associate with product
+
+ productAvailabilityService.create( availability4 );
+
+ final ProductPrice dprice4 = new ProductPrice();
+ dprice4.setDefaultPrice( true );
+ dprice4.setProductPriceAmount( new BigDecimal( 18.99 ) );
+ dprice4.setProductAvailability( availability4 );
+
+ dpd = new ProductPriceDescription();
+ dpd.setName( "Base price" );
+ dpd.setProductPrice( dprice4 );
+ dpd.setLanguage( en );
+
+ dprice4.getDescriptions().add( dpd );
+
+ productPriceService.create( dprice4 );
+
+ // PRODUCT 5
+
+ final Product product5 = new Product();
+ product5.setProductHeight( new BigDecimal( 4 ) );
+ product5.setProductLength( new BigDecimal( 3 ) );
+ product5.setProductWidth( new BigDecimal( 1 ) );
+ product5.setSku( "SF333346" );
+ product5.setManufacturer( packed );
+ product5.setType( generalType );
+ product5.setMerchantStore( store );
+
+ // Product description
+ description = new ProductDescription();
+ description.setName( "Battle of the worlds 2" );
+ description.setLanguage( en );
+ description.setProduct( product5 );
+
+ product5.getDescriptions().add( description );
+
+ product5.getCategories().add( fiction );
+ productService.create( product5 );
+
+ // Availability
+ final ProductAvailability availability5 = new ProductAvailability();
+ availability5.setProductDateAvailable( date );
+ availability5.setProductQuantity( 100 );
+ availability5.setRegion( "*" );
+ availability5.setProduct( product5 );// associate with product
+
+ productAvailabilityService.create( availability5 );
+
+ final ProductPrice dprice5 = new ProductPrice();
+ dprice5.setDefaultPrice( true );
+ dprice5.setProductPriceAmount( new BigDecimal( 18.99 ) );
+ dprice5.setProductAvailability( availability5 );
+
+ dpd = new ProductPriceDescription();
+ dpd.setName( "Base price" );
+ dpd.setProductPrice( dprice5 );
+ dpd.setLanguage( en );
+
+ dprice5.getDescriptions().add( dpd );
+
+ productPriceService.create( dprice5 );
+
+ // PRODUCT 6
+
+ final Product product6 = new Product();
+ product6.setProductHeight( new BigDecimal( 4 ) );
+ product6.setProductLength( new BigDecimal( 3 ) );
+ product6.setProductWidth( new BigDecimal( 1 ) );
+ product6.setSku( "LL333444" );
+ product6.setManufacturer( packed );
+ product6.setType( generalType );
+ product6.setMerchantStore( store );
+
+ // Product description
+ description = new ProductDescription();
+ description.setName( "Life book" );
+ description.setLanguage( en );
+ description.setProduct( product6 );
+
+ product6.getDescriptions().add( description );
+
+ product6.getCategories().add( novell );
+ productService.create( product6 );
+
+ // Availability
+ final ProductAvailability availability6 = new ProductAvailability();
+ availability6.setProductDateAvailable( date );
+ availability6.setProductQuantity( 100 );
+ availability6.setRegion( "*" );
+ availability6.setProduct( product6 );// associate with product
+
+ productAvailabilityService.create( availability6 );
+
+ final ProductPrice dprice6 = new ProductPrice();
+ dprice6.setDefaultPrice( true );
+ dprice6.setProductPriceAmount( new BigDecimal( 18.99 ) );
+ dprice6.setProductAvailability( availability6 );
+
+ dpd = new ProductPriceDescription();
+ dpd.setName( "Base price" );
+ dpd.setProductPrice( dprice6 );
+ dpd.setLanguage( en );
+
+ dprice6.getDescriptions().add( dpd );
+
+ productPriceService.create( dprice6 );
+
+ }
+
+ @Test
+ public void test3CreateUser()
+ throws ServiceException
+ {
+
+ final MerchantStore store = merchantService.getMerchantStore(MerchantStore.DEFAULT_STORE);
+
+ final Group gsuperadmin = new Group("SUPERADMIN");
+ final Group gadmin = new Group("ADMIN");
+ final Group gcatalogue = new Group("GROUP_CATALOGUE");
+ final Group gstore = new Group("GROUP_STORE");
+ final Group gorder = new Group("GROUP_ORDER");
+
+ groupService.create(gsuperadmin);
+ groupService.create(gadmin);
+ groupService.create(gcatalogue);
+ groupService.create(gstore);
+ groupService.create(gorder);
+
+ groupService.create(gsuperadmin);
+ groupService.create(gadmin);
+ groupService.create(gcatalogue);
+ groupService.create(gstore);
+ groupService.create(gorder);
+
+ final Permission auth = new Permission("AUTH");//Authenticated
+ auth.getGroups().add(gsuperadmin);
+ auth.getGroups().add(gadmin);
+ permissionService.create(auth);
+
+ final Permission categories = new Permission("CATEGORIES");
+ categories.getGroups().add(gsuperadmin);
+ categories.getGroups().add(gadmin);
+ permissionService.create(categories);
+
+ final Permission products = new Permission("PRODUCTS");
+ products.getGroups().add(gsuperadmin);
+ products.getGroups().add(gadmin);
+ permissionService.create(products);
+
+ final Permission attributes = new Permission("ATTRIBUTES");
+ attributes.getGroups().add(gsuperadmin);
+ permissionService.create(attributes);
+
+ final Permission featured = new Permission("FEATURED");
+ featured.getGroups().add(gsuperadmin);
+ permissionService.create(featured);
+
+ final Permission order = new Permission("ORDER");
+ order.getGroups().add(gsuperadmin);
+ permissionService.create(order);
+
+ final Permission content = new Permission("CONTENT");
+ content.getGroups().add(gsuperadmin);
+ permissionService.create(content);
+ final Permission pstore = new Permission("STORE");
+ pstore.getGroups().add(gsuperadmin);
+ permissionService.create(pstore);
+
+ final Permission tax = new Permission("TAX");
+ tax.getGroups().add(gsuperadmin);
+ permissionService.create(tax);
+ final Permission payment = new Permission("PAYMENT");
+ payment.getGroups().add(gsuperadmin);
+ permissionService.create(payment);
+ final Permission shipping = new Permission("SHIPPING");
+ shipping.getGroups().add(gsuperadmin);
+ permissionService.create(shipping);
+
+
+
+ }
+
+ @Test
+ public void testGetProduct()
+ throws ServiceException
+ {
+
+ final Language language = languageService.getByCode( "en" );
+
+ final Locale locale = new Locale( "en", "CA" );
+
+
+ final Product p = productService.getById(50L);
+
+ //final Product p = productService.getProductForLocale( 1L, language, locale );
+
+
+ if ( p != null )
+ {
+
+ System.out.println( p.getDescriptions().size() );
+
+ }
+
+ }
+
+ @Test
+ public void testGetProducts()
+ throws ServiceException
+ {
+ final Language language = languageService.getByCode( "en" );
+ final Locale locale = new Locale( "en", "CA" );
+
+ final MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+
+ final Category category = categoryService.getByCode( store, "book" );
+
+ final int nrOfIterations = 1;
+
+ for ( int i = 1; i <= nrOfIterations; i++ )
+ {
+ final List<Product> products = productService.getProductsForLocale( category, language, locale );
+ for ( final Product product : products )
+ {
+ log.info( MessageFormat.format( "product found:{0}:iteration{1}", product.getId(), i ) );
+ }
+ }
+ }
+
+ @Test
+ public void testGetProductsByCategories()
+ throws ServiceException
+ {
+ final Language language = languageService.getByCode( "en" );
+ final Locale locale = new Locale( "en", "CA" );
+ final MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+
+ // Category category = categoryService.getByCode(store, "novell");
+
+ final Category category = categoryService.getByCode( store, "book" );
+
+ categoryService.delete( category );
+
+ System.out.println( "done" );
+
+ /*
+ * List<Long> ids = new ArrayList<Long>(); ids.add(1L); ids.add(2L); ids.add(3L); List<Product> products =
+ * productService.getProducts(ids); System.out.println(products.size());
+ */
+
+ }
+
+ @Test
+ public void testCategory()
+ throws ServiceException
+ {
+
+ /**
+ * Creates a category hierarchy Music Books Novell Science-Fiction Technology Business
+ */
+
+ final Language en = languageService.getByCode( "en" );
+ final Language fr = languageService.getByCode( "fr" );
+ final Country ca = countryService.getByCode( "CA" );
+ final Currency currency = currencyService.getByCode( "CAD" );
+ final MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+
+ final Category book = new Category();
+ book.setDepth( 0 );
+ book.setLineage( "/" );
+ book.setMerchantStore( store );
+ book.setCode( "book" );
+
+ final CategoryDescription bookEnglishDescription = new CategoryDescription();
+ bookEnglishDescription.setName( "Book" );
+ bookEnglishDescription.setCategory( book );
+ bookEnglishDescription.setLanguage( en );
+
+ final CategoryDescription bookFrenchDescription = new CategoryDescription();
+ bookFrenchDescription.setName( "Livre" );
+ bookFrenchDescription.setCategory( book );
+ bookFrenchDescription.setLanguage( fr );
+
+ final List<CategoryDescription> descriptions = new ArrayList<CategoryDescription>();
+ descriptions.add( bookEnglishDescription );
+ descriptions.add( bookFrenchDescription );
+
+ book.setDescriptions( descriptions );
+
+ categoryService.create( book );
+
+ final Category music = new Category();
+ music.setDepth( 0 );
+ music.setLineage( "/" );
+ music.setMerchantStore( store );
+ music.setCode( "music" );
+
+ final CategoryDescription musicEnglishDescription = new CategoryDescription();
+ musicEnglishDescription.setName( "Music" );
+ musicEnglishDescription.setCategory( music );
+ musicEnglishDescription.setLanguage( en );
+
+ final CategoryDescription musicFrenchDescription = new CategoryDescription();
+ musicFrenchDescription.setName( "Musique" );
+ musicFrenchDescription.setCategory( music );
+ musicFrenchDescription.setLanguage( fr );
+
+ final List<CategoryDescription> descriptions2 = new ArrayList<CategoryDescription>();
+ descriptions2.add( musicEnglishDescription );
+ descriptions2.add( musicFrenchDescription );
+
+ music.setDescriptions( descriptions2 );
+
+ categoryService.create( music );
+
+ final Category novell = new Category();
+ novell.setDepth( 1 );
+ novell.setLineage( "/" + book.getId() + "/" );
+ novell.setMerchantStore( store );
+ novell.setCode( "novell" );
+
+ final CategoryDescription novellEnglishDescription = new CategoryDescription();
+ novellEnglishDescription.setName( "Novell" );
+ novellEnglishDescription.setCategory( novell );
+ novellEnglishDescription.setLanguage( en );
+
+ final CategoryDescription novellFrenchDescription = new CategoryDescription();
+ novellFrenchDescription.setName( "Roman" );
+ novellFrenchDescription.setCategory( novell );
+ novellFrenchDescription.setLanguage( fr );
+
+ final List<CategoryDescription> descriptions3 = new ArrayList<CategoryDescription>();
+ descriptions3.add( novellEnglishDescription );
+ descriptions3.add( novellFrenchDescription );
+
+ novell.setDescriptions( descriptions3 );
+
+ categoryService.create( novell );
+ categoryService.addChild( book, novell );
+
+ final Category tech = new Category();
+ tech.setDepth( 1 );
+ tech.setLineage( "/" + book.getId() + "/" );
+ tech.setMerchantStore( store );
+ tech.setCode( "tech" );
+
+ final CategoryDescription techEnglishDescription = new CategoryDescription();
+ techEnglishDescription.setName( "Technology" );
+ techEnglishDescription.setCategory( tech );
+ techEnglishDescription.setLanguage( en );
+
+ final CategoryDescription techFrenchDescription = new CategoryDescription();
+ techFrenchDescription.setName( "Technologie" );
+ techFrenchDescription.setCategory( tech );
+ techFrenchDescription.setLanguage( fr );
+
+ final List<CategoryDescription> descriptions4 = new ArrayList<CategoryDescription>();
+ descriptions4.add( techFrenchDescription );
+ descriptions4.add( techFrenchDescription );
+
+ tech.setDescriptions( descriptions4 );
+
+ categoryService.create( tech );
+ categoryService.addChild( book, tech );
+
+ }
+
+ @Test
+ public void testGetModules()
+ throws ServiceException
+ {
+
+ final List<IntegrationModule> shippingModules = moduleConfigurationService.getIntegrationModules( "SHIPPING" );
+
+ for ( final IntegrationModule module : shippingModules )
+ {
+
+ System.out.println( module.getCode() );
+ }
+ System.out.println( "Done" );
+
+ }
+
+
+ @Test
+ public void testCreateModules()
+ throws ServiceException
+ {
+
+ Map<String,IntegrationConfiguration> modules = new HashMap<String,IntegrationConfiguration>();
+
+ IntegrationConfiguration canadaPost = new IntegrationConfiguration();
+ canadaPost.setActive(true);
+ canadaPost.setModuleCode("canadapost");
+
+ Map<String,String> integrationKeys= new HashMap<String,String>();
+ integrationKeys.put("userName", "cpUserName");
+ integrationKeys.put("password", "cpPassword");
+
+ canadaPost.setIntegrationKeys(integrationKeys);
+
+ //String cpOptions[] = {"A","B"};
+
+ List<String> cpOptions = new ArrayList<String>();
+ cpOptions.add("A");
+ cpOptions.add("B");
+
+ //String cpOptions = "A,B";
+
+ Map<String,List<String>> integrationOptions= new HashMap<String,List<String>>();
+ integrationOptions.put("cpExpress", cpOptions);
+
+ canadaPost.setIntegrationOptions(integrationOptions);
+ modules.put("canadapost", canadaPost);
+
+
+
+ IntegrationConfiguration usps = new IntegrationConfiguration();
+ usps.setActive(false);
+ usps.setModuleCode("usps");
+
+ integrationKeys= new HashMap<String,String>();
+ integrationKeys.put("userName", "uspsUserName");
+ integrationKeys.put("password", "uspsPassword");
+
+ usps.setIntegrationKeys(integrationKeys);
+
+ //String uspsOptions[] = {"X","Y"};
+ List<String> uspsOptions = new ArrayList<String>();
+ uspsOptions.add("X");
+ uspsOptions.add("Y");
+
+ //String uspsOptions = "X,Y";
+
+ integrationOptions= new HashMap<String,List<String>>();
+ integrationOptions.put("uspsExpress", uspsOptions);
+
+ usps.setIntegrationOptions(integrationOptions);
+ modules.put("usps", usps);
+
+
+
+ try {
+ String json = ConfigurationModulesLoader.toJSONString(modules);
+
+
+
+ System.out.println(json);
+
+
+ //re-create object
+ Map<String,IntegrationConfiguration> configs = ConfigurationModulesLoader.loadIntegrationConfigurations(json);
+
+ for(String key : configs.keySet()) {
+
+ IntegrationConfiguration c = (IntegrationConfiguration)configs.get(key);
+ System.out.println(c.getModuleCode());
+
+
+ }
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ @Test
+ public void testCreateManufacturer()
+ throws ServiceException
+ {
+
+ final Language english = new Language();
+ english.setCode( "en" );
+ languageService.create( english );
+
+ final Language french = new Language();
+ french.setCode( "fr" );
+ languageService.create( french );
+
+ final Currency euro = new Currency();
+ euro.setCurrency( java.util.Currency.getInstance( "EUR" ) );
+ currencyService.create( euro );
+
+ final Currency cad = new Currency();
+ cad.setCurrency( java.util.Currency.getInstance( "CAD" ) );
+ currencyService.create( cad );
+
+ final Country fr = new Country( "FR" );
+ countryService.create( fr );
+
+ final Country ca = new Country( "CA" );
+ countryService.create( ca );
+
+ final Language DEFAULT_LANGUAGE = languageService.getByCode( "en" );
+ final Language FRENCH = languageService.getByCode( "fr" );
+ final Currency currency = currencyService.getByCode( "CAD" );
+
+ // create a merchant
+ final MerchantStore store = new MerchantStore();
+ store.setCountry( ca );
+ store.setCurrency( currency );
+ store.setDefaultLanguage( DEFAULT_LANGUAGE );
+ store.setInBusinessSince( date );
+ store.setStorename( "store name" );
+ store.setStoreEmailAddress( "test@test.com" );
+ merchantService.create( store );
+
+ final Manufacturer manufacturer = new Manufacturer();
+ // store.getManufacturers().add(manufacturer);
+
+ // merchantService.update(store);
+
+ // Manufacturer manufacturer = new Manufacturer();
+ manufacturer.setMerchantStore( store );
+
+ final ManufacturerDescription fd = new ManufacturerDescription();
+ fd.setLanguage( FRENCH );
+ fd.setName( "Sony french" );
+ fd.setManufacturer( manufacturer );
+
+ final ManufacturerDescription ed = new ManufacturerDescription();
+ ed.setLanguage( DEFAULT_LANGUAGE );
+ ed.setName( "Sony english" );
+ ed.setManufacturer( manufacturer );
+
+ final Set descriptions = new HashSet();
+ descriptions.add( fd );
+ descriptions.add( ed );
+
+ manufacturer.setDescriptions( descriptions );
+
+ manufacturerService.create( manufacturer );
+
+ // manufacturerService.delete(manufacturer);
+ // merchantService.delete(store);
+
+ }
+
+ @Test
+ public void testDeleteManufacturerService()
+ throws ServiceException
+ {
+
+ final Manufacturer manufacturer = manufacturerService.getById( 1L );
+ manufacturerService.delete( manufacturer );
+
+ }
+
+ @Test
+ public void testStoreRandomProducts()
+ throws ServiceException
+ {
+
+ final Language en = testSupportFactory.createLanguage( "en" );
+ languageService.save( en );
+
+ final Language fr = testSupportFactory.createLanguage( "fr" );
+ languageService.save( fr );
+
+ final Language[] languages = { en, fr };
+
+ final ProductType generalType = testSupportFactory.createProductType();
+ productTypeService.save( generalType );
+
+ final Country country = testSupportFactory.createCountry( en );
+ countryService.save( country );
+
+ final Currency currency = testSupportFactory.createCurrency();
+ currencyService.save( currency );
+
+ final MerchantStore store =
+ testSupportFactory.createMerchantStore( MerchantStore.DEFAULT_STORE, country, currency, en );
+ merchantService.save( store );
+
+ final Manufacturer manufacturer = testSupportFactory.createRandomManufacturer( store, en );
+ manufacturerService.save( manufacturer );
+
+ final Category category = testSupportFactory.createCategory( null, store, languages );
+ categoryService.save( category );
+
+ final int nrOfProducts = 300;
+
+ for ( int i = 1; i <= nrOfProducts; i++ )
+ {
+ log.info( MessageFormat.format( "adding product nr:{0}", i ) );
+ testSupportFactory.createAndStoreRandomProduct( manufacturer, generalType, category, store, en );
+ }
+ }
+}
diff --git a/sm-core/src/test/java/com/salesmanager/test/isolated/TestSupportFactory.java b/sm-core/src/test/java/com/salesmanager/test/isolated/TestSupportFactory.java
new file mode 100644
index 0000000..8fd449e
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/isolated/TestSupportFactory.java
@@ -0,0 +1,213 @@
+package com.salesmanager.test.isolated;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.Random;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.salesmanager.core.business.catalog.category.model.Category;
+import com.salesmanager.core.business.catalog.category.model.CategoryDescription;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability;
+import com.salesmanager.core.business.catalog.product.model.description.ProductDescription;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.Manufacturer;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.ManufacturerDescription;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPrice;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPriceDescription;
+import com.salesmanager.core.business.catalog.product.model.type.ProductType;
+import com.salesmanager.core.business.catalog.product.service.ProductService;
+import com.salesmanager.core.business.catalog.product.service.availability.ProductAvailabilityService;
+import com.salesmanager.core.business.catalog.product.service.manufacturer.ManufacturerService;
+import com.salesmanager.core.business.catalog.product.service.price.ProductPriceService;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.merchant.service.MerchantStoreService;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.country.model.CountryDescription;
+import com.salesmanager.core.business.reference.country.service.CountryService;
+import com.salesmanager.core.business.reference.currency.model.Currency;
+import com.salesmanager.core.business.reference.currency.service.CurrencyService;
+import com.salesmanager.core.business.reference.language.model.Language;
+
+@Component
+public class TestSupportFactory {
+
+ @Autowired
+ protected ProductService productService;
+
+ @Autowired
+ protected ProductAvailabilityService productAvailabilityService;
+
+ @Autowired
+ protected ProductPriceService productPriceService;
+
+ @Autowired
+ protected ManufacturerService manufacturerService;
+
+ @Autowired
+ protected MerchantStoreService merchantStoreService;
+
+ @Autowired
+ protected CountryService countryService;
+
+ @Autowired
+ protected CurrencyService currencyService;
+
+ public Product createAndStoreRandomProduct(Manufacturer manufacturer, ProductType type, Category category, MerchantStore store,
+ Language language) throws ServiceException {
+ Random rnd = new Random();
+
+ String[] descriptions = { "Live Book", "Nature Book", "Science Book", "Mathematics Book", "Physics Book" };
+
+ Product product = new Product();
+ product.setProductHeight(new BigDecimal(rnd.nextInt(100000)));
+ product.setProductLength(new BigDecimal(rnd.nextInt(100000)));
+ product.setProductWidth(new BigDecimal(rnd.nextInt(100000)));
+ product.setSku("LL" + rnd.nextLong());
+ product.setManufacturer(manufacturer);
+ product.setType(type);
+ product.setMerchantStore(store);
+
+ // Product description
+ ProductDescription description = new ProductDescription();
+ description.setName(getRandomString(descriptions));
+ description.setLanguage(language);
+ description.setProduct(product);
+
+ product.getDescriptions().add(description);
+
+ product.getCategories().add(category);
+ productService.create(product);
+
+ // Availability
+ ProductAvailability availability = new ProductAvailability();
+ availability.setProductDateAvailable(new Date());
+ availability.setProductQuantity(rnd.nextInt(200));
+ availability.setRegion("*");
+ availability.setProduct(product);// associate with product
+
+ productAvailabilityService.create(availability);
+
+ ProductPrice price = new ProductPrice();
+ price.setDefaultPrice(true);
+ price.setProductPriceAmount(new BigDecimal(18.99));
+ price.setProductAvailability(availability);
+
+ ProductPriceDescription dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(price);
+ dpd.setLanguage(language);
+
+ price.getDescriptions().add(dpd);
+
+ productPriceService.create(price);
+
+ return product;
+ }
+
+ public Category createCategory(Category parent, MerchantStore store, Language[] languages) {
+
+ String[] categoryDescriptions = { "Novell", "Roman", "Thriller", "Comedy", "Fantasy", "Horror", "Comics" };
+
+ Category cat = new Category();
+ if (parent == null) {
+ cat.setDepth(0);
+ cat.setLineage("/");
+ } else {
+ cat.setDepth(parent.getDepth());
+ cat.setLineage("/" + parent.getId() + "/");
+ }
+
+ cat.setMerchantStore(store);
+
+ List<CategoryDescription> descriptions = new ArrayList<CategoryDescription>();
+
+ String name = getRandomString(categoryDescriptions);
+ cat.setCode(name);
+
+ for (Language language : languages) {
+
+ CategoryDescription desc = new CategoryDescription();
+ desc.setName(name);
+ desc.setCategory(cat);
+ desc.setLanguage(language);
+ descriptions.add(desc);
+
+ }
+ cat.setDescriptions(descriptions);
+ return cat;
+ }
+
+ public Country createCountry(Language language) throws ServiceException {
+ Country ca = new Country();
+ ca.setIsoCode("CA");
+
+ CountryDescription countryDescription = new CountryDescription();
+ countryDescription.setCountry(ca);
+ countryDescription.setLanguage(language);
+ countryDescription.setName("Canada");
+ countryDescription.setDescription("Canada Country");
+
+ List<CountryDescription> descriptions = new ArrayList<CountryDescription>();
+ descriptions.add(countryDescription);
+ ca.setDescriptions(descriptions);
+
+ return ca;
+ }
+
+ public Currency createCurrency() throws ServiceException {
+ Currency currency = new Currency();
+ currency.setCurrency(java.util.Currency.getInstance(Locale.CANADA));
+ currency.setSupported(true);
+ return currency;
+ }
+
+ public Language createLanguage(String code) {
+ Language language = new Language();
+ language.setCode(code);
+ return language;
+ }
+
+ public MerchantStore createMerchantStore(String storeName, Country ca, Currency currency, Language language)
+ throws ServiceException {
+ MerchantStore store = new MerchantStore();
+ store.setCountry(ca);
+ store.setCurrency(currency);
+ store.setDefaultLanguage(language);
+ store.setInBusinessSince(new Date());
+ store.setStorename(storeName);
+ store.setCode(storeName);
+ store.setStoreEmailAddress("test@test.com");
+ return store;
+ }
+
+ public ProductType createProductType() {
+ ProductType generalType = new ProductType();
+ generalType.setCode(ProductType.GENERAL_TYPE);
+ return generalType;
+ }
+
+ public Manufacturer createRandomManufacturer(MerchantStore store, Language language) throws ServiceException {
+ String[] manufacturers = { "O\'reilley", "Hueber", "Langenscheidt", "Readers Digest", "Klett Verlag" };
+
+ Manufacturer manufacturer = new Manufacturer();
+ manufacturer.setMerchantStore(store);
+
+ ManufacturerDescription oreilleyd = new ManufacturerDescription();
+ oreilleyd.setLanguage(language);
+ oreilleyd.setName(getRandomString(manufacturers));
+ oreilleyd.setManufacturer(manufacturer);
+ manufacturer.getDescriptions().add(oreilleyd);
+
+ return manufacturer;
+ }
+
+ private String getRandomString(String[] strings) {
+ return strings[new Random().nextInt(strings.length)];
+ }
+}
diff --git a/sm-core/src/test/java/com/salesmanager/test/manufacturer/ManufacturerTestCase.java b/sm-core/src/test/java/com/salesmanager/test/manufacturer/ManufacturerTestCase.java
new file mode 100644
index 0000000..f8e5a9d
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/manufacturer/ManufacturerTestCase.java
@@ -0,0 +1,78 @@
+package com.salesmanager.test.manufacturer;
+
+import java.sql.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.Test;
+
+import com.salesmanager.core.business.catalog.product.model.manufacturer.Manufacturer;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.ManufacturerDescription;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.currency.model.Currency;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.test.core.AbstractSalesManagerCoreTestCase;
+
+
+
+public class ManufacturerTestCase extends AbstractSalesManagerCoreTestCase {
+
+ private static final Date date = new Date(System.currentTimeMillis());
+
+
+
+ @Test
+ public void testCreateManufacturerService() throws ServiceException {
+
+
+
+
+ Language DEFAULT_LANGUAGE = languageService.getByCode("en");
+ Language FRENCH = languageService.getByCode("fr");
+ Currency currency = currencyService.getByCode("CAD");
+ Country ca = super.countryService.getByCode("CA");
+
+
+
+ //create a merchant
+ MerchantStore store = new MerchantStore();
+ store.setCountry(ca);
+ store.setCurrency(currency);
+ store.setDefaultLanguage(DEFAULT_LANGUAGE);
+ store.setInBusinessSince(date);
+ store.setStorename("store name");
+ store.setStoreEmailAddress("test@test.com");
+ merchantService.create(store);
+
+ Manufacturer manufacturer = new Manufacturer();
+ manufacturer.setMerchantStore(store);
+
+ ManufacturerDescription fd = new ManufacturerDescription();
+ fd.setLanguage(FRENCH);
+ fd.setName("Sony french");
+ fd.setManufacturer(manufacturer);
+
+ ManufacturerDescription ed = new ManufacturerDescription();
+ ed.setLanguage(DEFAULT_LANGUAGE);
+ ed.setName("Sony english");
+ ed.setManufacturer(manufacturer);
+
+ Set descriptions = new HashSet();
+ descriptions.add(fd);
+ descriptions.add(ed);
+
+ manufacturer.setDescriptions(descriptions);
+
+
+ manufacturerService.create(manufacturer);
+
+ manufacturerService.delete(manufacturer);
+ //merchantService.delete(store);
+
+ }
+
+
+
+}
diff --git a/sm-core/src/test/java/com/salesmanager/test/merchant/MerchantSalesManagerTestCase.java b/sm-core/src/test/java/com/salesmanager/test/merchant/MerchantSalesManagerTestCase.java
new file mode 100644
index 0000000..e7e2206
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/merchant/MerchantSalesManagerTestCase.java
@@ -0,0 +1,41 @@
+package com.salesmanager.test.merchant;
+
+import java.util.Date;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.test.core.AbstractSalesManagerCoreTestCase;
+
+public class MerchantSalesManagerTestCase extends AbstractSalesManagerCoreTestCase {
+
+ @Test
+ public void createMerchant() throws Exception {
+ Country country = countryService.getByCode("CA");
+ Language lang = languageService.getByCode("en");
+ List<Language> langs = languageService.list();
+
+ //create a merchant
+ MerchantStore store = new MerchantStore();
+ store.setCountry(country);
+ store.setCurrency(currencyService.getByCode("CAD"));
+ store.setDefaultLanguage(lang);
+ store.setInBusinessSince(new Date());
+ store.setStorename("store name");
+ store.setCode("STORE");
+ store.setLanguages(langs);
+ store.setStoreEmailAddress("test@test.com");
+
+ merchantService.create(store);
+ store = merchantService.getById(store.getId());
+ Assert.assertTrue(store!=null);
+ System.out.println(store.getId());
+ System.out.println(store.getDomainName());
+ System.out.println(store.getDefaultLanguage().getId());
+ System.out.println(store.getLanguages().size());
+ }
+}
diff --git a/sm-core/src/test/java/com/salesmanager/test/order/InvoiceTestCase.java b/sm-core/src/test/java/com/salesmanager/test/order/InvoiceTestCase.java
new file mode 100644
index 0000000..a001e95
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/order/InvoiceTestCase.java
@@ -0,0 +1,698 @@
+package com.salesmanager.test.order;
+
+import java.awt.Graphics2D;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.lang3.StringUtils;
+import org.jopendocument.dom.OOUtils;
+import org.jopendocument.dom.spreadsheet.Sheet;
+import org.jopendocument.dom.spreadsheet.SpreadSheet;
+import org.jopendocument.model.OpenDocument;
+import org.jopendocument.renderer.ODTRenderer;
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.lowagie.text.Document;
+import com.lowagie.text.PageSize;
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.pdf.PdfContentByte;
+import com.lowagie.text.pdf.PdfDocument;
+import com.lowagie.text.pdf.PdfTemplate;
+import com.lowagie.text.pdf.PdfWriter;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOption;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionDescription;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionValue;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionValueDescription;
+import com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability;
+import com.salesmanager.core.business.catalog.product.model.description.ProductDescription;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPrice;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPriceDescription;
+import com.salesmanager.core.business.catalog.product.model.type.ProductType;
+import com.salesmanager.core.business.common.model.Billing;
+import com.salesmanager.core.business.common.model.Delivery;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.customer.model.CustomerGender;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.business.order.model.OrderTotal;
+import com.salesmanager.core.business.order.model.orderproduct.OrderProduct;
+import com.salesmanager.core.business.order.model.orderproduct.OrderProductAttribute;
+import com.salesmanager.core.business.order.model.orderproduct.OrderProductDownload;
+import com.salesmanager.core.business.order.model.orderproduct.OrderProductPrice;
+import com.salesmanager.core.business.order.model.orderstatus.OrderStatus;
+import com.salesmanager.core.business.order.model.orderstatus.OrderStatusHistory;
+import com.salesmanager.core.business.payments.model.PaymentType;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.currency.model.Currency;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.core.constants.Constants;
+import com.salesmanager.core.utils.ProductPriceUtils;
+import com.salesmanager.test.core.AbstractSalesManagerCoreTestCase;
+
+
+public class InvoiceTestCase extends AbstractSalesManagerCoreTestCase {
+
+ @Autowired
+ private ProductPriceUtils priceUtil;
+
+
+ @Test
+ public void createInvoice() throws ServiceException {
+
+
+ MerchantStore store = merchantService.getByCode(MerchantStore.DEFAULT_STORE);
+
+ //create a product
+ ProductType generalType = productTypeService.getProductType(ProductType.GENERAL_TYPE);
+
+ Language en = languageService.getByCode("en");
+
+
+ /**
+ * 1) Create an order
+ *
+ */
+
+ //1.1 create a product
+
+ //create an option
+ ProductOption color = new ProductOption();
+ color.setMerchantStore(store);
+ color.setCode("color");
+ color.setProductOptionType("SELECT");
+
+ ProductOptionDescription colorDescription = new ProductOptionDescription();
+ colorDescription.setDescription("Color");
+ colorDescription.setName("Color");
+ colorDescription.setLanguage(en);
+ colorDescription.setProductOption(color);
+
+ Set<ProductOptionDescription> colorDescriptions = new HashSet<ProductOptionDescription>();
+ colorDescriptions.add(colorDescription);
+
+ color.setDescriptions(colorDescriptions);
+
+ productOptionService.create(color);
+
+ //create an option value
+ ProductOptionValue red = new ProductOptionValue();
+ red.setMerchantStore(store);
+ red.setCode("red");
+
+ ProductOptionValueDescription redDescription = new ProductOptionValueDescription();
+ redDescription.setDescription("Red");
+ redDescription.setLanguage(en);
+ redDescription.setName("Red");
+ redDescription.setProductOptionValue(red);
+
+ Set<ProductOptionValueDescription> redDescriptions = new HashSet<ProductOptionValueDescription>();
+ redDescriptions.add(redDescription);
+
+ red.setDescriptions(redDescriptions);
+
+ productOptionValueService.create(red);
+
+ //create a product
+ Product product = new Product();
+ product.setProductHeight(new BigDecimal(4));
+ product.setProductLength(new BigDecimal(3));
+ product.setProductWidth(new BigDecimal(5));
+ product.setProductWeight(new BigDecimal(8));
+ product.setSku("TESTSKU");
+ product.setType(generalType);
+ product.setMerchantStore(store);
+
+ // Product description
+ ProductDescription description = new ProductDescription();
+ description.setName("Product 1");
+ description.setLanguage(en);
+ description.setProduct(product);
+
+ product.getDescriptions().add(description);
+
+
+ // Availability
+ ProductAvailability availability = new ProductAvailability();
+ availability.setProductDateAvailable(new Date());
+ availability.setProductQuantity(100);
+ availability.setRegion("*");
+ availability.setProduct(product);// associate with product
+
+ //price
+ ProductPrice dprice = new ProductPrice();
+ dprice.setDefaultPrice(true);
+ dprice.setProductPriceAmount(new BigDecimal(29.99));
+ dprice.setProductAvailability(availability);
+
+ ProductPriceDescription dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice);
+ dpd.setLanguage(en);
+
+ dprice.getDescriptions().add(dpd);
+
+
+ //create an attribute
+ ProductAttribute colorAttribute = new ProductAttribute();
+ colorAttribute.setProduct(product);
+ colorAttribute.setProductAttributePrice(new BigDecimal(5));
+ colorAttribute.setProductOption(color);
+ colorAttribute.setProductOptionValue(red);
+
+ Set<ProductAttribute> productAttributes = new HashSet<ProductAttribute>();
+ productAttributes.add(colorAttribute);
+
+ product.setAttributes(productAttributes);
+
+ productService.saveOrUpdate(product);
+
+
+ //1.2 create a Customer
+ Country country = countryService.getByCode("CA");
+ Zone zone = zoneService.getByCode("QC");
+
+ Customer customer = new Customer();
+ customer.setMerchantStore(store);
+ customer.setEmailAddress("test@test.com");
+ customer.setGender(CustomerGender.M);
+ customer.setAnonymous(true);
+ customer.setCompany("ifactory");
+ customer.setDateOfBirth(new Date());
+ customer.setNick("My nick");
+ customer.setDefaultLanguage(en);
+
+
+ Delivery delivery = new Delivery();
+ delivery.setAddress("358 Du Languadoc");
+ delivery.setCity( "Boucherville" );
+ delivery.setCountry(country);
+// delivery.setCountryCode(CA_COUNTRY_CODE);
+ delivery.setFirstName("First" );
+ delivery.setLastName("Last" );
+ delivery.setPostalCode("J4B-8J9" );
+ delivery.setZone(zone);
+
+ Billing billing = new Billing();
+ billing.setAddress("358 Du Languadoc");
+ billing.setCity("Boucherville");
+ billing.setCompany("CSTI Consulting");
+ billing.setCountry(country);
+// billing.setCountryCode(CA_COUNTRY_CODE);
+ billing.setFirstName("Carl" );
+ billing.setLastName("Samson" );
+ billing.setPostalCode("J4B-8J9");
+ billing.setZone(zone);
+
+ customer.setBilling(billing);
+ customer.setDelivery(delivery);
+ customerService.create(customer);
+
+ Currency currency = currencyService.getByCode(CAD_CURRENCY_CODE);
+
+ //1.3 create an order
+ OrderStatusHistory orderStatusHistory = new OrderStatusHistory();
+
+
+ Order order = new Order();
+ order.setDatePurchased(new Date());
+ order.setCurrency(currency);
+ order.setLastModified(new Date());
+ order.setBilling(billing);
+
+ Locale l = Locale.CANADA;
+ order.setLocale(l);
+
+
+ order.setCurrencyValue(new BigDecimal(0.98));//compared to based currency (not necessary)
+ order.setCustomerId(customer.getId());
+ order.setDelivery(delivery);
+ order.setIpAddress("ipAddress" );
+ order.setMerchant(store);
+ order.setCustomerEmailAddress(customer.getEmailAddress());
+ order.setOrderDateFinished(new Date());//committed date
+
+ orderStatusHistory.setComments("We received your order");
+ orderStatusHistory.setCustomerNotified(1);
+ orderStatusHistory.setStatus(OrderStatus.ORDERED);
+ orderStatusHistory.setDateAdded(new Date() );
+ orderStatusHistory.setOrder(order);
+ order.getOrderHistory().add( orderStatusHistory );
+
+
+ order.setPaymentType(PaymentType.PAYPAL);
+ order.setPaymentModuleCode("paypal");
+ order.setStatus( OrderStatus.DELIVERED);
+ order.setTotal(new BigDecimal(23.99));
+
+
+ //OrderProductDownload - Digital download
+ OrderProductDownload orderProductDownload = new OrderProductDownload();
+ orderProductDownload.setDownloadCount(1);
+ orderProductDownload.setMaxdays(31);
+ orderProductDownload.setOrderProductFilename("Your digital file name");
+
+ //OrderProductPrice
+ OrderProductPrice oproductprice = new OrderProductPrice();
+ oproductprice.setDefaultPrice(true);
+ oproductprice.setProductPrice(new BigDecimal(19.99) );
+ oproductprice.setProductPriceCode("baseprice" );
+ oproductprice.setProductPriceName("Base Price" );
+
+ //OrderProduct
+ OrderProduct oproduct = new OrderProduct();
+ oproduct.getDownloads().add( orderProductDownload);
+ oproduct.setOneTimeCharge( new BigDecimal(19.99) );
+ oproduct.setOrder(order);
+ oproduct.setProductName( "Product name" );
+ oproduct.setProductQuantity(2);
+ oproduct.setSku("TB12345" );
+ oproduct.getPrices().add(oproductprice ) ;
+
+
+ //an attribute to the OrderProduct
+ OrderProductAttribute orderAttribute = new OrderProductAttribute();
+ orderAttribute.setOrderProduct(oproduct);
+ orderAttribute.setProductAttributeName(colorDescription.getName());
+ orderAttribute.setProductAttributeValueName(redDescription.getName());
+ orderAttribute.setProductOptionId(color.getId());
+ orderAttribute.setProductOptionValueId(red.getId());
+ orderAttribute.setProductAttributePrice(colorAttribute.getProductAttributePrice());
+
+ Set<OrderProductAttribute> orderAttributes = new HashSet<OrderProductAttribute>();
+ orderAttributes.add(orderAttribute);
+
+ oproduct.setOrderAttributes(orderAttributes);
+
+ oproductprice.setOrderProduct(oproduct);
+ orderProductDownload.setOrderProduct(oproduct);
+ order.getOrderProducts().add(oproduct);
+
+
+ //product #2
+ OrderProductPrice oproductprice2 = new OrderProductPrice();
+ oproductprice2.setDefaultPrice(true);
+ oproductprice2.setProductPrice(new BigDecimal(9.99) );
+ oproductprice2.setProductPriceCode("baseprice" );
+ oproductprice2.setProductPriceName("Base Price" );
+
+ //OrderProduct
+ OrderProduct oproduct2 = new OrderProduct();
+ oproduct2.setOneTimeCharge( new BigDecimal(9.99) );
+ oproduct2.setOrder(order);
+ oproduct2.setProductName( "Additional item name" );
+ oproduct2.setProductQuantity(1);
+ oproduct2.setSku("TB12346" );
+ oproduct2.getPrices().add(oproductprice2 ) ;
+
+ oproductprice2.setOrderProduct(oproduct2);
+ order.getOrderProducts().add(oproduct2);
+
+
+
+
+
+ //requires
+ //OrderProduct
+ //OrderProductPrice
+ //OrderTotal
+
+
+
+ //OrderTotal
+ OrderTotal subtotal = new OrderTotal();
+ subtotal.setModule("summary" );
+ subtotal.setSortOrder(0);
+ subtotal.setText("Summary" );
+ subtotal.setTitle("Summary" );
+ subtotal.setValue(new BigDecimal(19.99 ) );
+ subtotal.setOrder(order);
+
+ order.getOrderTotal().add(subtotal);
+
+ OrderTotal tax = new OrderTotal();
+ tax.setModule("tax" );
+ tax.setSortOrder(1);
+ tax.setText("Tax" );
+ tax.setTitle("Tax" );
+ tax.setValue(new BigDecimal(4) );
+ tax.setOrder(order);
+
+ order.getOrderTotal().add(tax);
+
+ OrderTotal total = new OrderTotal();
+ total.setModule("total" );
+ total.setSortOrder(2);
+ total.setText("Total" );
+ total.setTitle("Total" );
+ total.setValue(new BigDecimal(23.99) );
+ total.setOrder(order);
+
+ order.getOrderTotal().add(total);
+
+ orderService.create(order);
+ Assert.assertTrue(orderService.count() == 1);
+
+ Locale locale = Locale.ENGLISH;
+
+
+ order = orderService.getById(order.getId());
+
+ /**
+ * 2 Create an invoice
+ */
+ try {
+ URL resource = getClass().getResource("/templates/invoice/invoice.ods");
+ File file = new File(resource.toURI());
+ //File file = new File("templates/invoice/invoice.ods");
+
+ Sheet sheet = SpreadSheet.createFromFile(file).getSheet(0);
+
+
+ //Store name
+ sheet.setValueAt(store.getStorename(), 0, 0);
+
+ store.setStoreaddress("2001 zoo avenue");
+ store.setCurrencyFormatNational(true);//use $ instead of USD
+
+
+ //Address
+ //count store address cell
+ int storeAddressCell = 2;
+ //if(!StringUtils.isBlank(store.getStoreaddress())) {
+ // sheet.setValueAt(store.getStoreaddress(), 0, storeAddressCell);
+ // storeAddressCell ++;
+ //}
+
+ //3
+ StringBuilder storeAddress = null;
+ if(!StringUtils.isBlank(store.getStoreaddress())) {
+ storeAddress = new StringBuilder();
+ storeAddress.append(store.getStoreaddress());
+ }
+ if(!StringUtils.isBlank(store.getStorecity())) {
+ if(storeAddress==null) {
+ storeAddress = new StringBuilder();
+ } else {
+ storeAddress.append(", ");
+ }
+ storeAddress.append(store.getStorecity());
+ }
+ if(storeAddress!=null) {
+ sheet.setValueAt(storeAddress.toString(), 0, storeAddressCell);
+ storeAddressCell ++;
+ }
+
+ //4
+ StringBuilder storeProvince = null;
+ if(store.getZone()!=null) {
+ storeProvince = new StringBuilder();
+ List<Zone> zones = zoneService.getZones(store.getCountry(), en);
+ for(Zone z : zones) {
+ if(z.getCode().equals(store.getZone().getCode())) {
+ storeProvince.append(store.getZone().getName());
+ break;
+ }
+ }
+
+ } else {
+ if(!StringUtils.isBlank(store.getStorestateprovince())) {
+ storeProvince = new StringBuilder();
+ storeProvince.append(store.getStorestateprovince());
+ }
+ }
+ if(store.getCountry()!=null) {
+ if(storeProvince==null) {
+ storeProvince = new StringBuilder();
+ } else {
+ storeProvince.append(", ");
+ }
+ Map<String,Country> countries = countryService.getCountriesMap(en);
+ Country c = countries.get(store.getCountry().getIsoCode());
+ if(c!=null) {
+ storeProvince.append(c.getName());
+ } else {
+ storeProvince.append(store.getCountry().getIsoCode());
+ }
+
+ }
+ if(storeProvince!=null) {
+ sheet.setValueAt(storeProvince.toString(), 0, storeAddressCell);
+ storeAddressCell ++;
+ }
+
+ //5
+ if(!StringUtils.isBlank(store.getStorepostalcode())) {
+ sheet.setValueAt(store.getStorepostalcode(), 0, storeAddressCell);
+ storeAddressCell ++;
+ }
+
+ //6
+ if(!StringUtils.isBlank(store.getStorephone())) {
+ sheet.setValueAt(store.getStorephone(), 0, storeAddressCell);
+ }
+
+ //delete address blank lines
+ for(int i = storeAddressCell; i<5; i++) {
+ sheet.setValueAt("", 0, i);
+ }
+
+ //invoice date
+ SimpleDateFormat format = new SimpleDateFormat(Constants.DEFAULT_DATE_FORMAT);
+ sheet.setValueAt(format.format(order.getDatePurchased()), 3, 2);
+
+ //invoice number
+ sheet.setValueAt(order.getId(), 3, 3);
+
+ //bill to
+ //count bill to address cell
+ int billToCell = 8;
+ if(!StringUtils.isBlank(customer.getBilling().getFirstName())) {
+ sheet.setValueAt(customer.getBilling().getFirstName() + " " + customer.getBilling().getLastName(), 0, billToCell);
+ billToCell ++;
+ }
+
+ //9
+ if(!StringUtils.isBlank(customer.getBilling().getCompany())) {
+ sheet.setValueAt(customer.getBilling().getCompany(), 0, billToCell);
+ billToCell ++;
+ }
+
+ //10
+ StringBuilder billToAddress = null;
+ if(!StringUtils.isBlank(customer.getBilling().getAddress())) {
+ billToAddress = new StringBuilder();
+ billToAddress.append(customer.getBilling().getAddress());
+ }
+ if(!StringUtils.isBlank(customer.getBilling().getCity())) {
+ if(billToAddress==null) {
+ billToAddress = new StringBuilder();
+ } else {
+ billToAddress.append(", ");
+ }
+ billToAddress.append(customer.getBilling().getCity());
+ }
+ if(billToAddress!=null) {
+ sheet.setValueAt(billToAddress.toString(), 0, billToCell);
+ billToCell ++;
+ }
+
+ //11
+ StringBuilder billToProvince = null;
+ if(customer.getBilling().getZone()!=null) {
+ billToProvince = new StringBuilder();
+ List<Zone> zones = zoneService.getZones(customer.getBilling().getCountry(), en);
+ for(Zone z : zones) {
+ if(z.getCode().equals(customer.getBilling().getZone().getCode())) {
+ billToProvince.append(customer.getBilling().getZone().getName());
+ break;
+ }
+ }
+
+ } else {
+ if(!StringUtils.isBlank(customer.getBilling().getState())) {
+ billToProvince = new StringBuilder();
+ billToProvince.append(customer.getBilling().getState());
+ }
+ }
+ if(customer.getBilling().getCountry()!=null) {
+ if(billToProvince==null) {
+ billToProvince = new StringBuilder();
+ } else {
+ billToProvince.append(", ");
+ }
+ Map<String,Country> countries = countryService.getCountriesMap(en);
+ Country c = countries.get(customer.getBilling().getCountry().getIsoCode());
+ if(c!=null) {
+ billToProvince.append(c.getName());
+ } else {
+ billToProvince.append(customer.getBilling().getCountry().getIsoCode());
+ }
+
+ }
+ if(billToProvince!=null) {
+ sheet.setValueAt(billToProvince.toString(), 0, billToCell);
+ billToCell ++;
+ }
+
+ //12
+ if(!StringUtils.isBlank(customer.getBilling().getPostalCode())) {
+ sheet.setValueAt(customer.getBilling().getPostalCode(), 0, billToCell);
+ billToCell ++;
+ }
+
+ //13
+ if(!StringUtils.isBlank(customer.getBilling().getTelephone())) {
+ sheet.setValueAt(customer.getBilling().getTelephone(), 0, billToCell);
+ }
+
+ //delete address blank lines
+ for(int i = billToCell; i<13; i++) {
+ sheet.setValueAt("", 0, i);
+ }
+
+ //products
+ Set<OrderProduct> orderProducts = order.getOrderProducts();
+ int productCell = 16;
+ for(OrderProduct orderProduct : orderProducts) {
+
+ //product name
+ String pName = orderProduct.getProductName();
+ Set<OrderProductAttribute> oAttributes = orderProduct.getOrderAttributes();
+ StringBuilder attributeName = null;
+ for(OrderProductAttribute oProductAttribute : oAttributes) {
+ if(attributeName == null) {
+ attributeName = new StringBuilder();
+ attributeName.append("[");
+ } else {
+ attributeName.append(", ");
+ }
+ attributeName.append(oProductAttribute.getProductAttributeName())
+ .append(": ")
+ .append(oProductAttribute.getProductAttributeValueName());
+
+ }
+
+
+ StringBuilder productName = new StringBuilder();
+ productName.append(pName);
+
+ if(attributeName!=null) {
+ attributeName.append("]");
+ productName.append(" ").append(attributeName.toString());
+ }
+
+
+
+
+ sheet.setValueAt(productName.toString(), 0, productCell);
+
+ int quantity = orderProduct.getProductQuantity();
+ sheet.setValueAt(quantity, 1, productCell);
+ String amount = priceUtil.getStoreFormatedAmountWithCurrency(store, orderProduct.getOneTimeCharge());
+ sheet.setValueAt(amount, 2, productCell);
+ String t = priceUtil.getStoreFormatedAmountWithCurrency(store, priceUtil.getOrderProductTotalPrice(store, orderProduct));
+ sheet.setValueAt(t, 3, productCell);
+
+ productCell++;
+
+ }
+
+ //print totals
+ productCell++;
+ Set<OrderTotal> totals = order.getOrderTotal();
+ for(OrderTotal orderTotal : totals) {
+
+ String totalName = orderTotal.getText();
+ String totalValue = priceUtil.getStoreFormatedAmountWithCurrency(store,orderTotal.getValue());
+ sheet.setValueAt(totalName, 2, productCell);
+ sheet.setValueAt(totalValue, 3, productCell);
+ productCell++;
+ }
+
+ //sheet.getCellAt(0, 0).setImage(arg0)
+ //sheet.getCellAt(0, 0).setStyleName(arg0)
+ //sheet.getCellAt(0, 0).getStyle().
+
+
+
+ File outputFile = new File(order.getId() + "_invoice.ods");
+ OOUtils.open(sheet.getSpreadSheet().saveAs(outputFile));
+
+
+ final OpenDocument doc = new OpenDocument();
+ doc.loadFrom(order.getId() + "_invoice.ods");
+
+ // Open the PDF document
+ Document document = new Document(PageSize.A4);
+ File outFile = new File("invoice.pdf");
+
+ PdfDocument pdf = new PdfDocument();
+
+ document.addDocListener(pdf);
+
+ FileOutputStream fileOutputStream = new FileOutputStream(outFile);
+ PdfWriter writer = PdfWriter.getInstance(pdf, fileOutputStream);
+ pdf.addWriter(writer);
+
+ document.open();
+
+ // Create a template and a Graphics2D object
+ Rectangle pageSize = document.getPageSize();
+ int w = (int) (pageSize.getWidth() * 0.9);
+ int h = (int) (pageSize.getHeight() * 0.95);
+ PdfContentByte cb = writer.getDirectContent();
+ PdfTemplate tp = cb.createTemplate(w, h);
+
+ Graphics2D g2 = tp.createPrinterGraphics(w, h, null);
+ // If you want to prevent copy/paste, you can use
+ // g2 = tp.createGraphicsShapes(w, h, true, 0.9f);
+
+ tp.setWidth(w);
+ tp.setHeight(h);
+
+ // Configure the renderer
+ ODTRenderer renderer = new ODTRenderer(doc);
+ renderer.setIgnoreMargins(true);
+ renderer.setPaintMaxResolution(true);
+
+ // Scale the renderer to fit width
+ renderer.setResizeFactor(renderer.getPrintWidth() / w);
+ // Render
+ renderer.paintComponent(g2);
+ g2.dispose();
+
+ // Add our spreadsheet in the middle of the page
+ float offsetX = (pageSize.getWidth() - w) / 2;
+ float offsetY = (pageSize.getHeight() - h) / 2;
+ cb.addTemplate(tp, offsetX, offsetY);
+ // Close the PDF document
+ document.close();
+
+ outputFile.delete();//remove temp file
+
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/sm-core/src/test/java/com/salesmanager/test/order/OrderSalesManagerTestCase.java b/sm-core/src/test/java/com/salesmanager/test/order/OrderSalesManagerTestCase.java
new file mode 100644
index 0000000..3d5c166
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/order/OrderSalesManagerTestCase.java
@@ -0,0 +1,550 @@
+package com.salesmanager.test.order;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability;
+import com.salesmanager.core.business.catalog.product.model.description.ProductDescription;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPrice;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPriceDescription;
+import com.salesmanager.core.business.catalog.product.model.type.ProductType;
+import com.salesmanager.core.business.common.model.Billing;
+import com.salesmanager.core.business.common.model.Delivery;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.customer.model.CustomerGender;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.business.order.model.OrderCriteria;
+import com.salesmanager.core.business.order.model.OrderList;
+import com.salesmanager.core.business.order.model.OrderTotal;
+import com.salesmanager.core.business.order.model.orderproduct.OrderProduct;
+import com.salesmanager.core.business.order.model.orderproduct.OrderProductDownload;
+import com.salesmanager.core.business.order.model.orderproduct.OrderProductPrice;
+import com.salesmanager.core.business.order.model.orderstatus.OrderStatus;
+import com.salesmanager.core.business.order.model.orderstatus.OrderStatusHistory;
+import com.salesmanager.core.business.order.model.payment.CreditCard;
+import com.salesmanager.core.business.payments.model.CreditCardType;
+import com.salesmanager.core.business.payments.model.PaymentType;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.currency.model.Currency;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.test.core.AbstractSalesManagerCoreTestCase;
+
+public class OrderSalesManagerTestCase extends AbstractSalesManagerCoreTestCase {
+
+// @Ignore
+ @Test
+ public void createOrder() throws ServiceException {
+
+
+ MerchantStore store = merchantService.getByCode(MerchantStore.DEFAULT_STORE);
+
+ //create a product
+ ProductType generalType = productTypeService.getProductType(ProductType.GENERAL_TYPE);
+
+ Language en = languageService.getByCode("en");
+
+ Product product = new Product();
+ product.setProductHeight(new BigDecimal(4));
+ product.setProductLength(new BigDecimal(3));
+ product.setProductWidth(new BigDecimal(5));
+ product.setProductWeight(new BigDecimal(8));
+ product.setSku("TESTSKU");
+ product.setType(generalType);
+ product.setMerchantStore(store);
+
+ // Product description
+ ProductDescription description = new ProductDescription();
+ description.setName("Product 1");
+ description.setLanguage(en);
+ description.setProduct(product);
+
+ product.getDescriptions().add(description);
+
+
+ // Availability
+ ProductAvailability availability = new ProductAvailability();
+ availability.setProductDateAvailable(new Date());
+ availability.setProductQuantity(100);
+ availability.setRegion("*");
+ availability.setProduct(product);// associate with product
+
+ product.getAvailabilities().add(availability);
+
+ ProductPrice dprice = new ProductPrice();
+ dprice.setDefaultPrice(true);
+ dprice.setProductPriceAmount(new BigDecimal(29.99));
+ dprice.setProductAvailability(availability);
+
+ availability.getPrices().add(dprice);
+
+ ProductPriceDescription dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice);
+ dpd.setLanguage(en);
+
+ dprice.getDescriptions().add(dpd);
+
+ productService.saveOrUpdate(product);
+
+ //create a Customer
+ Country country = countryService.getByCode("CA");
+ Zone zone = zoneService.getByCode("QC");
+
+ Customer customer = new Customer();
+ customer.setMerchantStore(store);
+ customer.setEmailAddress("test@test.com");
+ customer.setGender(CustomerGender.M);
+ customer.setAnonymous(true);
+ customer.setCompany("ifactory");
+ customer.setDateOfBirth(new Date());
+ customer.setNick("My nick");
+ customer.setDefaultLanguage(en);
+
+ Delivery delivery = new Delivery();
+ delivery.setAddress("358 Du Languadoc");
+ delivery.setCity( "Boucherville" );
+ delivery.setCountry(country);
+// delivery.setCountryCode(CA_COUNTRY_CODE);
+ delivery.setPostalCode("J4B-8J9" );
+ delivery.setFirstName("Carl");
+ delivery.setLastName("Samson");
+ delivery.setZone(zone);
+
+ Billing billing = new Billing();
+ billing.setAddress("358 Du Languadoc");
+ billing.setCity("Boucherville");
+ billing.setCompany("CSTI Consulting");
+ billing.setCountry(country);
+// billing.setCountryCode(CA_COUNTRY_CODE);
+ billing.setFirstName("Carl");
+ billing.setLastName("Samson");
+ billing.setPostalCode("J4B-8J9");
+ billing.setZone(zone);
+
+ customer.setBilling(billing);
+ customer.setDelivery(delivery);
+ customerService.create(customer);
+
+ Currency currency = currencyService.getByCode(CAD_CURRENCY_CODE);
+
+ OrderStatusHistory orderStatusHistory = new OrderStatusHistory();
+
+
+
+
+ Order order = new Order();
+ order.setDatePurchased(new Date());
+ order.setCurrency(currency);
+ order.setLastModified(new Date());
+ order.setBilling(billing);
+
+ Locale l = Locale.CANADA;
+ order.setLocale(l);
+
+
+ order.setCurrencyValue(new BigDecimal(0.98));//compared to based currency (not necessary)
+ order.setCustomerId(customer.getId());
+ order.setDelivery(delivery);
+ order.setIpAddress("ipAddress" );
+ order.setMerchant(store);
+ order.setCustomerEmailAddress(customer.getEmailAddress());
+
+ order.setOrderDateFinished(new Date());//committed date
+
+ orderStatusHistory.setComments("We received your order");
+ orderStatusHistory.setCustomerNotified(1);
+ orderStatusHistory.setStatus(OrderStatus.ORDERED);
+ orderStatusHistory.setDateAdded(new Date() );
+ orderStatusHistory.setOrder(order);
+ order.getOrderHistory().add( orderStatusHistory );
+
+ order.setPaymentType(PaymentType.PAYPAL);
+ order.setPaymentModuleCode("paypal");
+ order.setStatus( OrderStatus.DELIVERED);
+ order.setTotal(new BigDecimal(23.99));
+
+
+ //OrderProductDownload - Digital download
+ OrderProductDownload orderProductDownload = new OrderProductDownload();
+ orderProductDownload.setDownloadCount(1);
+ orderProductDownload.setMaxdays(31);
+ orderProductDownload.setOrderProductFilename("Your digital file name");
+
+ //OrderProductPrice
+ OrderProductPrice oproductprice = new OrderProductPrice();
+ oproductprice.setDefaultPrice(true);
+ oproductprice.setProductPrice(new BigDecimal(19.99) );
+ oproductprice.setProductPriceCode("baseprice" );
+ oproductprice.setProductPriceName("Base Price" );
+
+ //OrderProduct
+ OrderProduct oproduct = new OrderProduct();
+ oproduct.getDownloads().add( orderProductDownload);
+ oproduct.setOneTimeCharge( new BigDecimal(19.99) );
+ oproduct.setOrder(order);
+ oproduct.setProductName( "Product name" );
+ oproduct.setProductQuantity(1);
+ oproduct.setSku("TB12345" );
+ oproduct.getPrices().add(oproductprice ) ;
+
+ oproductprice.setOrderProduct(oproduct);
+ orderProductDownload.setOrderProduct(oproduct);
+ order.getOrderProducts().add(oproduct);
+
+ //requires
+ //OrderProduct
+ //OrderProductPrice
+ //OrderTotal
+
+
+
+ //OrderTotal
+ OrderTotal subtotal = new OrderTotal();
+ subtotal.setModule("summary" );
+ subtotal.setSortOrder(0);
+ subtotal.setText("Summary" );
+ subtotal.setTitle("Summary" );
+ subtotal.setOrderTotalCode("summary");
+ subtotal.setValue(new BigDecimal(19.99 ) );
+ subtotal.setOrder(order);
+
+ order.getOrderTotal().add(subtotal);
+
+ OrderTotal tax = new OrderTotal();
+ tax.setModule("tax" );
+ tax.setSortOrder(1);
+ tax.setText("Tax" );
+ tax.setTitle("Tax" );
+ tax.setOrderTotalCode("tax");
+ tax.setValue(new BigDecimal(4) );
+ tax.setOrder(order);
+
+ order.getOrderTotal().add(tax);
+
+ OrderTotal total = new OrderTotal();
+ total.setModule("total" );
+ total.setSortOrder(2);
+ total.setText("Total" );
+ total.setTitle("Total" );
+ total.setOrderTotalCode("total");
+ total.setValue(new BigDecimal(23.99) );
+ total.setOrder(order);
+
+ order.getOrderTotal().add(total);
+
+ orderService.create(order);
+ Assert.assertTrue(orderService.count() == 1);
+ }
+
+ @Ignore
+ @Test
+ public void getMerchantOrders() throws ServiceException {
+
+ List<Order> merchantOrders= new ArrayList<Order>();
+
+ Language language = languageService.getByCode(ENGLISH_LANGUAGE_CODE);
+ Currency currency = currencyService.getByCode(EURO_CURRENCY_CODE);
+ Country country = countryService.getByCode(FR_COUNTRY_CODE);
+ Zone zone = zoneService.getByCode("VT");
+
+ MerchantStore merchant = new MerchantStore();
+ merchant.setCurrency(currency);
+ merchant.setStorename("Test Store");
+ merchant.setCountry(country);
+ merchant.setDefaultLanguage(language);
+ merchant.setStorecity("Test Store City");
+ merchant.setCode( merchantService.count()+"");
+ Language en = languageService.getByCode("en");
+ Language fr = languageService.getByCode("fr");
+ List<Language> supportedLanguages = new ArrayList<Language>();
+ supportedLanguages.add(en);
+ supportedLanguages.add(fr);
+ merchant.setLanguages( supportedLanguages );
+ merchant.setStoreEmailAddress("store_email@email.com");
+ merchant.setStorephone("Merchant Store Phone");
+ merchant.setStorepostalcode("12061");
+ merchantService.create(merchant);
+
+
+ Customer customer = new Customer();
+ customer.setMerchantStore(merchant);
+ customer.setEmailAddress("email@email.com");
+ customer.setPassword("-1999");
+ customer.setNick("My New nick");
+ customer.setCompany(" Apple");
+ customer.setGender(CustomerGender.M);
+ customer.setDateOfBirth(new Date());
+
+ Billing billing = new Billing();
+ billing.setAddress("Billing address");
+ billing.setCity("Billing city");
+ billing.setCompany("Billing company");
+ billing.setCountry(country);
+// billing.setCountryCode(CA_COUNTRY_CODE);
+ billing.setFirstName("Carl");
+ billing.setLastName("Samson");
+ billing.setPostalCode("Billing postal code");
+ billing.setState("Billing state");
+ billing.setZone(zone);
+
+ Delivery delivery = new Delivery();
+ delivery.setAddress("Shipping address");
+ delivery.setCountry(country);
+ delivery.setZone(zone);
+
+ customer.setBilling(billing);
+ customer.setDelivery(delivery);
+
+ customerService.create(customer);
+
+ OrderStatusHistory orderStatusHistory = new OrderStatusHistory();
+ Order order = new Order();
+ order.setDatePurchased(new Date());
+ order.setCurrency(currency);
+ order.setMerchant(merchant);
+ order.setLastModified(new Date());
+
+ CreditCard creditCard = new CreditCard();
+ creditCard.setCardType(CreditCardType.VISA);
+
+ creditCard.setCcCvv("123");
+ creditCard.setCcExpires("12/30/2020" );
+ creditCard.setCcNumber( "123456789");
+ creditCard.setCcOwner("ccOwner" );
+
+ order.setCreditCard(creditCard);
+
+ order.setCurrencyValue(new BigDecimal(19.99));
+ order.setCustomerId(new Long(1) );
+ order.setDelivery(delivery);
+ order.setIpAddress("ipAddress" );
+ order.setMerchant(merchant);
+ order.setOrderDateFinished(new Date());
+ orderStatusHistory.setDateAdded(new Date() );
+ orderStatusHistory.setOrder(order);
+ order.setPaymentType(PaymentType.CREDITCARD);
+ order.setPaymentModuleCode("payment Module Code");
+ order.setShippingModuleCode("UPS" );
+ order.setStatus( OrderStatus.ORDERED);
+ order.setTotal(new BigDecimal(23.99));
+
+ //OrderProduct
+ OrderProduct oproduct = new OrderProduct();
+ oproduct.setDownloads(null);
+ oproduct.setOneTimeCharge( new BigDecimal(16.99) );
+ oproduct.setOrder(order);
+ oproduct.setProductName( "Order Product Name" );
+ oproduct.setProductQuantity(5);
+ oproduct.setSku("Order Product sku" );
+
+
+ orderService.create(order);
+
+
+ merchantOrders = orderService.listByStore(merchant);
+
+
+ Assert.assertTrue("Merchant Orders are null." , merchantOrders != null);
+ Assert.assertTrue("Merchant Orders count is not one." , (merchantOrders != null && merchantOrders.size() == 1) );
+ }
+
+
+ @Test
+ public void testSearchOrders() throws ServiceException {
+
+ MerchantStore store = merchantService.getByCode(MerchantStore.DEFAULT_STORE);
+ Country country = countryService.getByCode("CA");
+ Zone zone = zoneService.getByCode("VT");
+
+ //create 3 customers
+ Customer firstCustomer = new Customer();
+ firstCustomer.setMerchantStore(store);
+ firstCustomer.setEmailAddress("test@test.com");
+ firstCustomer.setGender(CustomerGender.M);
+ firstCustomer.setAnonymous(true);
+ firstCustomer.setCompany("ifactory");
+ firstCustomer.setDateOfBirth(new Date());
+ firstCustomer.setNick("My nick");
+ firstCustomer.setPassword("123456");
+
+ Delivery delivery = new Delivery();
+ delivery.setAddress("Shipping address");
+ delivery.setCountry(country);
+ delivery.setZone(zone);
+
+
+ Billing billing = new Billing();
+ billing.setAddress("Billing address");
+ billing.setCountry(country);
+ billing.setZone(zone);
+
+ firstCustomer.setBilling(billing);
+ firstCustomer.setDelivery(delivery);
+
+ customerService.create(firstCustomer);
+
+ Customer secondCustomer = new Customer();
+ secondCustomer.setMerchantStore(store);
+ secondCustomer.setEmailAddress("test@test.com");
+ secondCustomer.setGender(CustomerGender.M);
+ secondCustomer.setDateOfBirth(new Date());
+ secondCustomer.setPassword("123456");
+
+
+ secondCustomer.setBilling(billing);
+ secondCustomer.setDelivery(delivery);
+
+ customerService.create(secondCustomer);
+
+ Customer thirdCustomer = new Customer();
+ thirdCustomer.setMerchantStore(store);
+ thirdCustomer.setEmailAddress("test@test.com");
+ thirdCustomer.setGender(CustomerGender.M);
+ thirdCustomer.setDateOfBirth(new Date());
+ thirdCustomer.setPassword("123456");
+
+
+ thirdCustomer.setBilling(billing);
+ thirdCustomer.setDelivery(delivery);
+
+ customerService.create(thirdCustomer);
+
+ //create a few orders
+ Order order = new Order();
+ order.setDatePurchased(new Date());
+ order.setCurrency(store.getCurrency());
+ order.setMerchant(store);
+ order.setLastModified(new Date());
+
+ CreditCard creditCard = new CreditCard();
+ creditCard.setCardType(CreditCardType.VISA);
+
+ creditCard.setCcCvv("123");
+ creditCard.setCcExpires("12/30/2020" );
+ creditCard.setCcNumber( "123456789");
+ creditCard.setCcOwner("ccOwner" );
+
+ order.setCreditCard(creditCard);
+ order.setCurrencyValue(new BigDecimal(19.99));
+ order.setCustomerId(new Long(1) );
+ order.setDelivery(delivery);
+ order.setIpAddress("ipAddress" );
+
+ order.setPaymentType(PaymentType.CREDITCARD);
+ order.setPaymentModuleCode("beanstream");
+ order.setShippingModuleCode("ups" );
+ order.setStatus( OrderStatus.ORDERED);
+ order.setTotal(new BigDecimal(23.99));
+
+ OrderProductPrice oproductprice = new OrderProductPrice();
+ oproductprice.setDefaultPrice(true);
+ oproductprice.setProductPrice(new BigDecimal(19.99) );
+ oproductprice.setProductPriceCode("baseprice" );
+ oproductprice.setProductPriceName("Base Price" );
+
+ //OrderProduct
+ OrderProduct oproduct = new OrderProduct();
+ oproduct.setOneTimeCharge( new BigDecimal(19.99) );
+ oproduct.setOrder(order);
+ oproduct.setProductName( "Product name" );
+ oproduct.setProductQuantity(1);
+ oproduct.setSku("TB12345" );
+ oproduct.getPrices().add(oproductprice ) ;
+
+ oproductprice.setOrderProduct(oproduct);
+ order.getOrderProducts().add(oproduct);
+
+ OrderTotal orderTotal = new OrderTotal();
+ orderTotal.setModule("total");
+ orderTotal.setOrder(order);
+ orderTotal.setText("Total");
+ orderTotal.setTitle("total");
+ orderTotal.setValue(new BigDecimal(23.99));
+
+ order.getOrderTotal().add(orderTotal);
+
+ orderService.create(order);
+
+
+ Order secondOrder = new Order();
+ secondOrder.setDatePurchased(new Date());
+ secondOrder.setCurrency(store.getCurrency());
+ secondOrder.setMerchant(store);
+ secondOrder.setLastModified(new Date());
+
+ creditCard = new CreditCard();
+ creditCard.setCardType(CreditCardType.VISA);
+
+ creditCard.setCcCvv("123");
+ creditCard.setCcExpires("12/30/2020" );
+ creditCard.setCcNumber( "123456789");
+ creditCard.setCcOwner("ccOwner" );
+
+ order.setCreditCard(creditCard);
+ secondOrder.setCurrencyValue(new BigDecimal(19.99));
+ secondOrder.setCustomerId(secondCustomer.getId() );
+ secondOrder.setDelivery(delivery);
+ secondOrder.setIpAddress("ipAddress" );
+ order.setPaymentType(PaymentType.CREDITCARD);
+ order.setPaymentModuleCode("beanstream");
+ order.setShippingModuleCode("ups" );
+ secondOrder.setShippingModuleCode("ups" );
+ secondOrder.setStatus( OrderStatus.ORDERED);
+ secondOrder.setTotal(new BigDecimal(23.99));
+
+ oproductprice = new OrderProductPrice();
+ oproductprice.setDefaultPrice(true);
+ oproductprice.setProductPrice(new BigDecimal(19.99) );
+ oproductprice.setProductPriceCode("baseprice" );
+ oproductprice.setProductPriceName("Base Price" );
+
+ //OrderProduct
+ oproduct = new OrderProduct();
+ oproduct.setOneTimeCharge( new BigDecimal(19.99) );
+ oproduct.setOrder(secondOrder);
+ oproduct.setProductName( "Product name" );
+ oproduct.setProductQuantity(1);
+ oproduct.setSku("TB12345" );
+ oproduct.getPrices().add(oproductprice ) ;
+
+ oproductprice.setOrderProduct(oproduct);
+ secondOrder.getOrderProducts().add(oproduct);
+
+ orderTotal = new OrderTotal();
+ orderTotal.setModule("total");
+ orderTotal.setOrder(secondOrder);
+ orderTotal.setText("Total");
+ orderTotal.setTitle("total");
+ orderTotal.setValue(new BigDecimal(23.99));
+
+ order.getOrderTotal().add(orderTotal);
+
+
+ orderService.create(secondOrder);
+
+ OrderCriteria orderCriteria = new OrderCriteria();
+ orderCriteria.setCustomerName("Cruise");
+ orderCriteria.setStartIndex(0);
+ orderCriteria.setMaxCount(5);
+
+ OrderList orderList = orderService.listByStore(store, orderCriteria);
+
+ Assert.assertNotNull(orderList);
+
+ System.out.println("Total count " + orderList.getTotalCount());
+
+
+ }
+
+}
\ No newline at end of file
diff --git a/sm-core/src/test/java/com/salesmanager/test/payment/PaymentTestCase.java b/sm-core/src/test/java/com/salesmanager/test/payment/PaymentTestCase.java
new file mode 100644
index 0000000..19e2dcc
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/payment/PaymentTestCase.java
@@ -0,0 +1,113 @@
+package com.salesmanager.test.payment;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+
+import com.salesmanager.core.business.common.model.Billing;
+import com.salesmanager.core.business.common.model.Delivery;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.customer.model.CustomerGender;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.Order;
+import com.salesmanager.core.business.payments.model.CreditCardType;
+import com.salesmanager.core.business.payments.model.CreditCardPayment;
+import com.salesmanager.core.business.payments.model.PaymentType;
+import com.salesmanager.core.business.payments.model.TransactionType;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.core.business.system.model.IntegrationConfiguration;
+import com.salesmanager.test.core.AbstractSalesManagerCoreTestCase;
+
+public class PaymentTestCase extends AbstractSalesManagerCoreTestCase {
+
+ private static final Date date = new Date(System.currentTimeMillis());
+
+
+
+ @Test
+ public void testBeanStreamPayment() throws ServiceException {
+
+ Language en = languageService.getByCode("en");
+ Country country = countryService.getByCode("CA");
+ Zone zone = zoneService.getByCode("QC");
+
+ MerchantStore store = merchantService.getByCode(MerchantStore.DEFAULT_STORE);
+
+
+ //create customer
+ Customer customer = new Customer();
+ customer.setMerchantStore(store);
+ customer.setEmailAddress("test@test.com");
+ customer.setGender(CustomerGender.M);
+ customer.setAnonymous(true);
+ customer.setCompany("ifactory");
+ customer.setDateOfBirth(new Date());
+ customer.setNick("My nick");
+ customer.setPassword("123456");
+
+
+ Delivery delivery = new Delivery();
+ delivery.setAddress("Shipping address");
+ delivery.setCity("Boucherville");
+ delivery.setCountry(country);
+ delivery.setZone(zone);
+ delivery.setPostalCode("J4B-8J9");
+
+ Billing billing = new Billing();
+ billing.setAddress("Billing address");
+ billing.setCountry(country);
+ billing.setZone(zone);
+ billing.setPostalCode("J4B-8J9");
+
+ customer.setBilling(billing);
+ customer.setDelivery(delivery);
+
+
+
+ //create Payment
+ CreditCardPayment payment = new CreditCardPayment();
+ payment.setModuleName("beanstream");
+ payment.setPaymentType(PaymentType.CREDITCARD);
+ payment.setCardOwner("Test User");
+ payment.setCredidCardValidationNumber("0421");
+ payment.setCreditCardNumber("545412345678");
+ payment.setExpirationMonth("04");
+ payment.setExpirationYear("16");
+ payment.setCreditCard(CreditCardType.MASTERCARD);
+ payment.setTransactionType(TransactionType.AUTHORIZECAPTURE);
+
+
+ IntegrationConfiguration paymentConfiguration = new IntegrationConfiguration();
+
+ paymentConfiguration.setActive(true);
+ paymentConfiguration.setEnvironment(IntegrationConfiguration.TEST_ENVIRONMENT);
+ paymentConfiguration.setModuleCode("beanstream");
+
+ Map<String,String> integrationKeys = new HashMap<String,String>();
+ integrationKeys.put("merchantid", "123456");
+ integrationKeys.put("username", "accnt");
+ integrationKeys.put("password", "pass123");
+ integrationKeys.put("transaction", "CAPTURE");
+
+ paymentConfiguration.setIntegrationKeys(integrationKeys);
+
+ paymentService.savePaymentModuleConfiguration(paymentConfiguration, store);
+
+ Order order = new Order();
+ order.setTotal(new BigDecimal(20));
+
+ //paypal requires item list List<ShoppinCartItem> for the rest i set null
+ paymentService.processPayment(customer, store, payment, null, order);
+
+
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/sm-core/src/test/java/com/salesmanager/test/search/IndexProductTestCase.java b/sm-core/src/test/java/com/salesmanager/test/search/IndexProductTestCase.java
new file mode 100644
index 0000000..d189d5c
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/search/IndexProductTestCase.java
@@ -0,0 +1,153 @@
+package com.salesmanager.test.search;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.junit.Test;
+
+import com.salesmanager.core.business.catalog.category.model.Category;
+import com.salesmanager.core.business.catalog.category.model.CategoryDescription;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOption;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionDescription;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionType;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionValue;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionValueDescription;
+import com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability;
+import com.salesmanager.core.business.catalog.product.model.description.ProductDescription;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.Manufacturer;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.ManufacturerDescription;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPrice;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPriceDescription;
+import com.salesmanager.core.business.catalog.product.model.type.ProductType;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.test.core.AbstractSalesManagerCoreTestCase;
+
+public class IndexProductTestCase extends AbstractSalesManagerCoreTestCase {
+
+ private static final Date date = new Date(System.currentTimeMillis());
+
+
+
+ @Test
+ public void testIndexProduct() throws ServiceException {
+
+ Language en = languageService.getByCode("en");
+ Language fr = languageService.getByCode("fr");
+
+ MerchantStore store = merchantService.getByCode(MerchantStore.DEFAULT_STORE);
+ ProductType generalType = productTypeService.getProductType(ProductType.GENERAL_TYPE);
+
+ /**
+ * Create the category
+ */
+ Category book = new Category();
+ book.setMerchantStore(store);
+ book.setCode("book");
+
+ CategoryDescription bookEnglishDescription = new CategoryDescription();
+ bookEnglishDescription.setName("Book");
+ bookEnglishDescription.setCategory(book);
+ bookEnglishDescription.setLanguage(en);
+
+ CategoryDescription bookFrenchDescription = new CategoryDescription();
+ bookFrenchDescription.setName("Livre");
+ bookFrenchDescription.setCategory(book);
+ bookFrenchDescription.setLanguage(fr);
+
+ List<CategoryDescription> descriptions = new ArrayList<CategoryDescription>();
+ descriptions.add(bookEnglishDescription);
+ descriptions.add(bookFrenchDescription);
+
+ book.setDescriptions(descriptions);
+
+ categoryService.create(book);
+
+
+ /**
+ * Create a manufacturer
+ */
+ Manufacturer packed = new Manufacturer();
+ packed.setMerchantStore(store);
+
+ ManufacturerDescription packedd = new ManufacturerDescription();
+ packedd.setLanguage(en);
+ packedd.setManufacturer(packed);
+ packedd.setName("Packed publishing");
+ packed.getDescriptions().add(packedd);
+
+ manufacturerService.create(packed);
+
+
+
+
+
+
+ /**
+ * Create a simple product
+ */
+ Product product = new Product();
+ product.setProductHeight(new BigDecimal(4));
+ product.setProductLength(new BigDecimal(3));
+ product.setProductWidth(new BigDecimal(1));
+ product.setSku("TB12345");
+ product.setManufacturer(packed);
+ product.setType(generalType);
+ product.setMerchantStore(store);
+
+ // Product description
+ ProductDescription description = new ProductDescription();
+ description.setName("Spring in Action");
+ description.setLanguage(en);
+ description.setProduct(product);
+
+ product.getDescriptions().add(description);
+
+ ProductDescription descriptionF = new ProductDescription();
+ descriptionF.setName("Spring en plein action");
+ descriptionF.setLanguage(fr);
+ descriptionF.setProduct(product);
+
+ product.getDescriptions().add(descriptionF);
+ product.getCategories().add(book);
+
+
+ //availability
+ ProductAvailability availability = new ProductAvailability();
+ availability.setProductDateAvailable(date);
+ availability.setProductQuantity(100);
+ availability.setRegion("*");
+ availability.setProduct(product);// associate with product
+
+ //price
+ ProductPrice dprice = new ProductPrice();
+ dprice.setDefaultPrice(true);
+ dprice.setProductPriceAmount(new BigDecimal(29.99));
+ dprice.setProductAvailability(availability);
+
+
+
+ ProductPriceDescription dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice);
+ dpd.setLanguage(en);
+
+ dprice.getDescriptions().add(dpd);
+ availability.getPrices().add(dprice);
+
+
+ productService.create(product);//this will index the product
+
+
+
+
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/sm-core/src/test/java/com/salesmanager/test/shipping/ShippingTestCase.java b/sm-core/src/test/java/com/salesmanager/test/shipping/ShippingTestCase.java
new file mode 100644
index 0000000..e73281f
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/shipping/ShippingTestCase.java
@@ -0,0 +1,568 @@
+package com.salesmanager.test.shipping;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.Assert;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute;
+import com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability;
+import com.salesmanager.core.business.catalog.product.model.description.ProductDescription;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPrice;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPriceDescription;
+import com.salesmanager.core.business.catalog.product.model.type.ProductType;
+import com.salesmanager.core.business.common.model.Billing;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.customer.model.CustomerGender;
+import com.salesmanager.core.business.common.model.Delivery;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.language.service.LanguageService;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.core.business.shipping.model.PackageDetails;
+import com.salesmanager.core.business.shipping.model.ShippingBasisType;
+import com.salesmanager.core.business.shipping.model.ShippingConfiguration;
+import com.salesmanager.core.business.shipping.model.ShippingPackageType;
+import com.salesmanager.core.business.shipping.model.ShippingProduct;
+import com.salesmanager.core.business.shipping.model.ShippingQuote;
+import com.salesmanager.core.business.shipping.model.ShippingType;
+import com.salesmanager.core.business.shipping.service.ShippingService;
+import com.salesmanager.core.business.system.model.Environment;
+import com.salesmanager.core.business.system.model.IntegrationConfiguration;
+import com.salesmanager.core.modules.integration.shipping.model.CustomShippingQuoteWeightItem;
+import com.salesmanager.core.modules.integration.shipping.model.CustomShippingQuotesConfiguration;
+import com.salesmanager.core.modules.integration.shipping.model.CustomShippingQuotesRegion;
+import com.salesmanager.test.core.AbstractSalesManagerCoreTestCase;
+
+public class ShippingTestCase extends AbstractSalesManagerCoreTestCase {
+
+ private static final Date date = new Date(System.currentTimeMillis());
+
+ @Autowired
+ private ShippingService shippingService;
+
+ @Autowired
+ private LanguageService languageService;
+
+ /**
+ * This test will invoke a shipping module to get real time shipping quotes
+ * @throws ServiceException
+ */
+ @Test
+ public void testGetShippingPackages() throws ServiceException {
+
+ Language en = languageService.getByCode("en");
+
+ MerchantStore store = merchantService.getByCode(MerchantStore.DEFAULT_STORE);
+ ProductType generalType = productTypeService.getProductType(ProductType.GENERAL_TYPE);
+
+ //generate 2 products
+
+ // PRODUCT 1 (height 4 inches x 3 inches length + 5 inches width) 1 pound
+ Product product = new Product();
+ product.setProductHeight(new BigDecimal(4));
+ product.setProductLength(new BigDecimal(3));
+ product.setProductWidth(new BigDecimal(5));
+ product.setProductWeight(new BigDecimal(8));
+ product.setSku("TB12345");
+ product.setType(generalType);
+ product.setMerchantStore(store);
+
+ // Product description
+ ProductDescription description = new ProductDescription();
+ description.setName("Product 1");
+ description.setLanguage(en);
+ description.setProduct(product);
+
+ product.getDescriptions().add(description);
+ //productService.create(product);
+
+ // Availability
+ ProductAvailability availability = new ProductAvailability();
+ availability.setProductDateAvailable(date);
+ availability.setProductQuantity(100);
+ availability.setRegion("*");
+ availability.setProduct(product);// associate with product
+
+ //productAvailabilityService.create(availability);
+
+ ProductPrice dprice = new ProductPrice();
+ dprice.setDefaultPrice(true);
+ dprice.setProductPriceAmount(new BigDecimal(29.99));
+ dprice.setProductAvailability(availability);
+
+ ProductPriceDescription dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice);
+ dpd.setLanguage(en);
+
+ dprice.getDescriptions().add(dpd);
+
+
+ // PRODUCT 2 (height 3 inches x 4 inches length x 5 inches width) 2 pounds
+
+ Product product2 = new Product();
+ product2.setProductHeight(new BigDecimal(3));
+ product2.setProductLength(new BigDecimal(4));
+ product2.setProductWidth(new BigDecimal(5));
+ product2.setProductWeight(new BigDecimal(2));
+ product2.setSku("TB2468");
+ product2.setType(generalType);
+ product2.setMerchantStore(store);
+
+ // Product description
+ description = new ProductDescription();
+ description.setName("Product 2");
+ description.setLanguage(en);
+ description.setProduct(product2);
+
+ product2.getDescriptions().add(description);
+
+
+ // Availability
+ ProductAvailability availability2 = new ProductAvailability();
+ availability2.setProductDateAvailable(date);
+ availability2.setProductQuantity(100);
+ availability2.setRegion("*");
+ availability2.setProduct(product2);// associate with product
+
+ //productAvailabilityService.create(availability2);
+
+ ProductPrice dprice2 = new ProductPrice();
+ dprice2.setDefaultPrice(true);
+ dprice2.setProductPriceAmount(new BigDecimal(39.99));
+ dprice2.setProductAvailability(availability2);
+
+ dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice2);
+ dpd.setLanguage(en);
+
+ dprice2.getDescriptions().add(dpd);
+
+ //add an attribute to product 2 that will augment weight of 1 pound
+ ProductAttribute attribute = new ProductAttribute();
+ attribute.setProduct(product2);
+ attribute.setAttributeDefault(true);
+ attribute.setProductAttributePrice(new BigDecimal(0));//no price variation
+ attribute.setProductAttributeWeight(new BigDecimal(1));//weight variation
+
+
+ product2.getAttributes().add(attribute);
+
+ //create an integration configuration
+ IntegrationConfiguration configuration = new IntegrationConfiguration();
+ configuration.setActive(true);
+ configuration.setEnvironment(Environment.TEST.name());
+ configuration.setModuleCode("canadapost");
+
+ //configure shipping
+ ShippingConfiguration shippingConfiguration = new ShippingConfiguration();
+ shippingConfiguration.setShippingBasisType(ShippingBasisType.SHIPPING);
+ shippingConfiguration.setShippingType(ShippingType.INTERNATIONAL);
+ shippingConfiguration.setShippingPackageType(ShippingPackageType.ITEM);
+ shippingConfiguration.setBoxHeight(5);
+ shippingConfiguration.setBoxLength(5);
+ shippingConfiguration.setBoxWidth(5);
+ shippingConfiguration.setBoxWeight(1);
+ shippingConfiguration.setMaxWeight(10);
+
+ //configure module
+ List<String> options = new ArrayList<String>();
+ options.add("PACKAGE");
+ configuration.getIntegrationKeys().put("account", "CPC_CS_TI_INC");
+ configuration.getIntegrationOptions().put("packages",options);
+
+ shippingService.saveShippingConfiguration(shippingConfiguration, store);
+ shippingService.saveShippingQuoteModuleConfiguration(configuration, store);
+
+ //now create ShippingProduct
+ ShippingProduct shippingProduct1 = new ShippingProduct(product);
+ ShippingProduct shippingProduct2 = new ShippingProduct(product2);
+ List<ShippingProduct> shippingProducts = new ArrayList<ShippingProduct>();
+ shippingProducts.add(shippingProduct1);
+ shippingProducts.add(shippingProduct2);
+
+ List<PackageDetails> details = shippingService.getPackagesDetails(shippingProducts, store);
+
+ Assert.notNull(details);
+
+ for(PackageDetails pack : details) {
+ System.out.println("Height " + pack.getShippingHeight());
+ System.out.println("Length " + pack.getShippingLength());
+ System.out.println("Width " + pack.getShippingWidth());
+ System.out.println("Weight " + pack.getShippingWeight());
+ }
+
+
+ }
+
+ @Test
+ public void testGetShippingQuotes() throws ServiceException {
+
+ Language en = languageService.getByCode("en");
+ Country country = countryService.getByCode("CA");
+ Zone zone = zoneService.getByCode("QC");
+
+ MerchantStore store = merchantService.getByCode(MerchantStore.DEFAULT_STORE);
+ ProductType generalType = productTypeService.getProductType(ProductType.GENERAL_TYPE);
+
+ //set valid store postal code
+ store.setStorepostalcode("J4B-9J9");
+
+ Product product = new Product();
+ product.setProductHeight(new BigDecimal(4));
+ product.setProductLength(new BigDecimal(3));
+ product.setProductWidth(new BigDecimal(5));
+ product.setProductWeight(new BigDecimal(8));
+ product.setSku("TESTSKU");
+ product.setType(generalType);
+ product.setMerchantStore(store);
+
+ // Product description
+ ProductDescription description = new ProductDescription();
+ description.setName("Product 1");
+ description.setLanguage(en);
+ description.setProduct(product);
+
+ product.getDescriptions().add(description);
+
+
+ // Availability
+ ProductAvailability availability = new ProductAvailability();
+ availability.setProductDateAvailable(new Date());
+ availability.setProductQuantity(100);
+ availability.setRegion("*");
+ availability.setProduct(product);// associate with product
+
+ ProductPrice dprice = new ProductPrice();
+ dprice.setDefaultPrice(true);
+ dprice.setProductPriceAmount(new BigDecimal(29.99));
+ dprice.setProductAvailability(availability);
+
+ ProductPriceDescription dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice);
+ dpd.setLanguage(en);
+
+ dprice.getDescriptions().add(dpd);
+ availability.getPrices().add(dprice);
+
+ product.getAvailabilities().add(availability);
+
+ productService.saveOrUpdate(product);
+
+
+
+
+ //configure shipping
+ ShippingConfiguration shippingConfiguration = new ShippingConfiguration();
+ shippingConfiguration.setShippingBasisType(ShippingBasisType.SHIPPING);//based on shipping or billing address
+ shippingConfiguration.setShippingType(ShippingType.INTERNATIONAL);
+ shippingConfiguration.setShippingPackageType(ShippingPackageType.ITEM);//individual item pricing or box packaging (see unit test above)
+ //only if package type is package
+ shippingConfiguration.setBoxHeight(5);
+ shippingConfiguration.setBoxLength(5);
+ shippingConfiguration.setBoxWidth(5);
+ shippingConfiguration.setBoxWeight(1);
+ shippingConfiguration.setMaxWeight(10);
+
+ List<String> supportedCountries = new ArrayList<String>();
+ supportedCountries.add("CA");
+ supportedCountries.add("US");
+ supportedCountries.add("UK");
+ supportedCountries.add("FR");
+
+ shippingService.setSupportedCountries(store, supportedCountries);
+
+ //create an integration configuration - CANADA POST
+ /*
+ IntegrationConfiguration configuration = new IntegrationConfiguration();
+ configuration.setActive(true);
+ configuration.setEnvironment(Environment.TEST.name());
+ configuration.setModuleCode("canadapost");
+
+ //configure module
+ List<String> options = new ArrayList<String>();
+ options.add("PACKAGE");//PACKAGE or ENVELOPE (supported by Canadapost)
+ configuration.getIntegrationKeys().put("account", "CPC_CS_TI_INC");//CPC_DEMO_HTML
+ configuration.getIntegrationOptions().put("packages",options);*/
+
+ //create an integration configuration - USPS
+
+ //overwrite shipping US
+/* Country us = countryService.getByCode("US");
+ Zone NY = zoneService.getByCode("NY");//store (origin) has to be in the US
+ store.setCountry(us);
+ store.setZone(NY);
+ store.setStorepostalcode("10451");*/
+
+/* IntegrationConfiguration configuration = new IntegrationConfiguration();
+ configuration.setActive(true);
+ configuration.setEnvironment(Environment.TEST.name());
+ configuration.setModuleCode("usps");
+
+ //configure module
+ List<String> options = new ArrayList<String>();
+ options.add("Package");//Package or Envelope (supported by USPS)
+ configuration.getIntegrationKeys().put("account", "636CSTIC6187");
+ configuration.getIntegrationOptions().put("packages",options);*/
+
+
+ //create an integration configuration - USPS
+
+ IntegrationConfiguration configuration = new IntegrationConfiguration();
+ configuration.setActive(true);
+ configuration.setEnvironment(Environment.TEST.name());
+ configuration.setModuleCode("ups");
+
+ //configure module
+
+ configuration.getIntegrationKeys().put("userId", "csamson777");
+ configuration.getIntegrationKeys().put("accessKey", "AC66279FF8020AE0");
+ configuration.getIntegrationKeys().put("password", "william");
+
+ List<String> options = new ArrayList<String>();
+ options.add("21");
+ configuration.getIntegrationOptions().put("packages",options);
+
+ shippingService.saveShippingConfiguration(shippingConfiguration, store);
+ shippingService.saveShippingQuoteModuleConfiguration(configuration, store);
+
+ //now create ShippingProduct
+ ShippingProduct shippingProduct1 = new ShippingProduct(product);
+ List<ShippingProduct> shippingProducts = new ArrayList<ShippingProduct>();
+ shippingProducts.add(shippingProduct1);
+
+ Customer customer = new Customer();
+ customer.setMerchantStore(store);
+ customer.setEmailAddress("test@test.com");
+ customer.setGender(CustomerGender.M);
+ customer.setAnonymous(true);
+ customer.setCompany("ifactory");
+ customer.setDateOfBirth(new Date());
+ customer.setNick("My nick");
+ customer.setPassword("123456");
+
+
+ Delivery delivery = new Delivery();
+ delivery.setAddress("Shipping address");
+ delivery.setCity("Boucherville");
+ delivery.setCountry(country);
+ delivery.setZone(zone);
+ delivery.setPostalCode("J4B-8J9");
+
+ //overwrite delivery to US (USPS)
+/* delivery.setPostalCode("90002");
+ delivery.setCountry(us);
+ Zone california = zoneService.getByCode("CA");
+ delivery.setZone(california);*/
+
+
+ Billing billing = new Billing();
+ billing.setAddress("Billing address");
+ billing.setCountry(country);
+ billing.setZone(zone);
+ billing.setPostalCode("J4B-8J9");
+
+ customer.setBilling(billing);
+ customer.setDelivery(delivery);
+
+ customerService.create(customer);
+
+ ShippingQuote shippingQuote = shippingService.getShippingQuote(store, delivery, shippingProducts, en);
+
+ Assert.notNull(shippingQuote);
+
+ }
+
+
+
+
+
+
+ @Test
+ public void testGetCustomShippingQuotesByWeight() throws ServiceException {
+
+ Language en = languageService.getByCode("en");
+ Country country = countryService.getByCode("CA");
+ Zone zone = zoneService.getByCode("QC");
+
+ MerchantStore store = merchantService.getByCode(MerchantStore.DEFAULT_STORE);
+ ProductType generalType = productTypeService.getProductType(ProductType.GENERAL_TYPE);
+
+ //set valid store postal code
+ store.setStorepostalcode("J4B-9J9");
+
+ Product product = new Product();
+ product.setProductHeight(new BigDecimal(4));
+ product.setProductLength(new BigDecimal(3));
+ product.setProductWidth(new BigDecimal(5));
+ product.setProductWeight(new BigDecimal(8));
+ product.setSku("TESTSKU");
+ product.setType(generalType);
+ product.setMerchantStore(store);
+
+ // Product description
+ ProductDescription description = new ProductDescription();
+ description.setName("Product 1");
+ description.setLanguage(en);
+ description.setProduct(product);
+
+ product.getDescriptions().add(description);
+
+
+ // Availability
+ ProductAvailability availability = new ProductAvailability();
+ availability.setProductDateAvailable(new Date());
+ availability.setProductQuantity(100);
+ availability.setRegion("*");
+ availability.setProduct(product);// associate with product
+
+ ProductPrice dprice = new ProductPrice();
+ dprice.setDefaultPrice(true);
+ dprice.setProductPriceAmount(new BigDecimal(29.99));
+ dprice.setProductAvailability(availability);
+
+ ProductPriceDescription dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice);
+ dpd.setLanguage(en);
+
+ dprice.getDescriptions().add(dpd);
+ availability.getPrices().add(dprice);
+
+ product.getAvailabilities().add(availability);
+
+ productService.saveOrUpdate(product);
+
+
+
+
+ //configure shipping
+ ShippingConfiguration shippingConfiguration = new ShippingConfiguration();
+ shippingConfiguration.setShippingBasisType(ShippingBasisType.SHIPPING);//based on shipping or billing address
+ shippingConfiguration.setShippingType(ShippingType.INTERNATIONAL);
+ shippingConfiguration.setShippingPackageType(ShippingPackageType.ITEM);//individual item pricing or box packaging (see unit test above)
+ //only if package type is package
+ shippingConfiguration.setBoxHeight(5);
+ shippingConfiguration.setBoxLength(5);
+ shippingConfiguration.setBoxWidth(5);
+ shippingConfiguration.setBoxWeight(1);
+ shippingConfiguration.setMaxWeight(10);
+
+ List<String> supportedCountries = new ArrayList<String>();
+ supportedCountries.add("CA");
+ supportedCountries.add("US");
+ supportedCountries.add("UK");
+ supportedCountries.add("FR");
+
+ shippingService.setSupportedCountries(store, supportedCountries);
+
+
+ CustomShippingQuotesConfiguration customConfiguration = new CustomShippingQuotesConfiguration();
+ customConfiguration.setModuleCode("weightBased");
+ customConfiguration.setActive(true);
+
+ CustomShippingQuotesRegion northRegion = new CustomShippingQuotesRegion();
+ northRegion.setCustomRegionName("NORTH");
+
+ List<String> countries = new ArrayList<String>();
+ countries.add("CA");
+ countries.add("US");
+
+ northRegion.setCountries(countries);
+
+ CustomShippingQuoteWeightItem caQuote4 = new CustomShippingQuoteWeightItem();
+ caQuote4.setMaximumWeight(4);
+ caQuote4.setPrice(new BigDecimal(20));
+ CustomShippingQuoteWeightItem caQuote10 = new CustomShippingQuoteWeightItem();
+ caQuote10.setMaximumWeight(10);
+ caQuote10.setPrice(new BigDecimal(50));
+ CustomShippingQuoteWeightItem caQuote100 = new CustomShippingQuoteWeightItem();
+ caQuote100.setMaximumWeight(100);
+ caQuote100.setPrice(new BigDecimal(120));
+ List<CustomShippingQuoteWeightItem> quotes = new ArrayList<CustomShippingQuoteWeightItem>();
+ quotes.add(caQuote4);
+ quotes.add(caQuote10);
+ quotes.add(caQuote100);
+
+ northRegion.setQuoteItems(quotes);
+
+ customConfiguration.getRegions().add(northRegion);
+
+
+ //create an integration configuration - USPS
+
+ IntegrationConfiguration configuration = new IntegrationConfiguration();
+ configuration.setActive(true);
+ configuration.setEnvironment(Environment.TEST.name());
+ configuration.setModuleCode("weightBased");
+
+ //configure module
+
+
+
+ shippingService.saveShippingConfiguration(shippingConfiguration, store);
+ shippingService.saveShippingQuoteModuleConfiguration(configuration, store);//create the basic configuration
+ shippingService.saveCustomShippingConfiguration("weightBased", customConfiguration, store);//and the custom configuration
+
+ //now create ShippingProduct
+ ShippingProduct shippingProduct1 = new ShippingProduct(product);
+ List<ShippingProduct> shippingProducts = new ArrayList<ShippingProduct>();
+ shippingProducts.add(shippingProduct1);
+
+ Customer customer = new Customer();
+ customer.setMerchantStore(store);
+ customer.setEmailAddress("test@test.com");
+ customer.setGender(CustomerGender.M);
+
+ customer.setAnonymous(true);
+ customer.setCompany("ifactory");
+ customer.setDateOfBirth(new Date());
+ customer.setNick("My nick");
+ customer.setPassword("123456");
+
+
+ Delivery delivery = new Delivery();
+ delivery.setAddress("Shipping address");
+ delivery.setCity("Boucherville");
+ delivery.setCountry(country);
+ delivery.setZone(zone);
+ delivery.setPostalCode("J4B-8J9");
+
+ //overwrite delivery to US
+/* delivery.setPostalCode("90002");
+ delivery.setCountry(us);
+ Zone california = zoneService.getByCode("CA");
+ delivery.setZone(california);*/
+
+
+ Billing billing = new Billing();
+ billing.setAddress("Billing address");
+ billing.setCountry(country);
+ billing.setZone(zone);
+ billing.setPostalCode("J4B-8J9");
+
+ customer.setBilling(billing);
+ customer.setDelivery(delivery);
+
+ customerService.create(customer);
+
+ ShippingQuote shippingQuote = shippingService.getShippingQuote(store, delivery, shippingProducts, en);
+
+ Assert.notNull(shippingQuote);
+
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/sm-core/src/test/java/com/salesmanager/test/shoppingcart/ShoppingCartTestCase.java b/sm-core/src/test/java/com/salesmanager/test/shoppingcart/ShoppingCartTestCase.java
new file mode 100644
index 0000000..a67a394
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/shoppingcart/ShoppingCartTestCase.java
@@ -0,0 +1,481 @@
+package com.salesmanager.test.shoppingcart;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.salesmanager.core.business.catalog.category.model.Category;
+import com.salesmanager.core.business.catalog.category.model.CategoryDescription;
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductAttribute;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOption;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionDescription;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionType;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionValue;
+import com.salesmanager.core.business.catalog.product.model.attribute.ProductOptionValueDescription;
+import com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability;
+import com.salesmanager.core.business.catalog.product.model.description.ProductDescription;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.Manufacturer;
+import com.salesmanager.core.business.catalog.product.model.manufacturer.ManufacturerDescription;
+import com.salesmanager.core.business.catalog.product.model.price.FinalPrice;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPrice;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPriceDescription;
+import com.salesmanager.core.business.catalog.product.model.type.ProductType;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCart;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartAttributeItem;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartItem;
+import com.salesmanager.core.utils.ProductPriceUtils;
+import com.salesmanager.test.core.AbstractSalesManagerCoreTestCase;
+
+/**
+ * Test
+ *
+ * - Add a product to persistent shopping cart
+ * - Retrieve an item from the persistent shopping cart
+ * - Rebuild a shopping cart item after the product definition has been modified
+ * @author Carl Samson
+ *
+ */
+public class ShoppingCartTestCase extends AbstractSalesManagerCoreTestCase {
+
+ @Autowired
+ private ProductPriceUtils productPriceUtil;
+
+ @Test
+ public void createShoppingCart()
+ throws ServiceException
+ {
+
+ MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+
+
+ Language en = languageService.getByCode("en");
+
+
+ /** CATALOG CREATION **/
+
+ ProductType generalType = productTypeService.getProductType(ProductType.GENERAL_TYPE);
+
+ /**
+ * Create the category
+ */
+ Category shirts = new Category();
+ shirts.setMerchantStore(store);
+ shirts.setCode("shirts");
+
+ CategoryDescription shirtsEnglishDescription = new CategoryDescription();
+ shirtsEnglishDescription.setName("Shirts");
+ shirtsEnglishDescription.setCategory(shirts);
+ shirtsEnglishDescription.setLanguage(en);
+
+ List<CategoryDescription> descriptions = new ArrayList<CategoryDescription>();
+ descriptions.add(shirtsEnglishDescription);
+
+
+ shirts.setDescriptions(descriptions);
+ categoryService.create(shirts);
+
+
+ /**
+ * Create a manufacturer
+ */
+ Manufacturer addidas = new Manufacturer();
+ addidas.setMerchantStore(store);
+
+ ManufacturerDescription addidasDesc = new ManufacturerDescription();
+ addidasDesc.setLanguage(en);
+ addidasDesc.setManufacturer(addidas);
+ addidasDesc.setName("Addidas");
+ addidas.getDescriptions().add(addidasDesc);
+
+ manufacturerService.create(addidas);
+
+ /**
+ * Create an option
+ */
+ ProductOption option = new ProductOption();
+ option.setMerchantStore(store);
+ option.setCode("color");
+ option.setProductOptionType(ProductOptionType.Radio.name());
+
+ ProductOptionDescription optionDescription = new ProductOptionDescription();
+ optionDescription.setLanguage(en);
+ optionDescription.setName("Color");
+ optionDescription.setDescription("Item color");
+ optionDescription.setProductOption(option);
+
+ option.getDescriptions().add(optionDescription);
+
+ productOptionService.saveOrUpdate(option);
+
+
+ /** first option value **/
+ ProductOptionValue white = new ProductOptionValue();
+ white.setMerchantStore(store);
+ white.setCode("white");
+
+ ProductOptionValueDescription whiteDescription = new ProductOptionValueDescription();
+ whiteDescription.setLanguage(en);
+ whiteDescription.setName("White");
+ whiteDescription.setDescription("White color");
+ whiteDescription.setProductOptionValue(white);
+
+ white.getDescriptions().add(whiteDescription);
+
+ productOptionValueService.saveOrUpdate(white);
+
+
+ ProductOptionValue black = new ProductOptionValue();
+ black.setMerchantStore(store);
+ black.setCode("black");
+
+ /** second option value **/
+ ProductOptionValueDescription blackDesc = new ProductOptionValueDescription();
+ blackDesc.setLanguage(en);
+ blackDesc.setName("Black");
+ blackDesc.setDescription("Black color");
+ blackDesc.setProductOptionValue(black);
+
+ black.getDescriptions().add(blackDesc);
+
+ productOptionValueService.saveOrUpdate(black);
+
+
+ /**
+ * Create a complex product
+ */
+ Product product = new Product();
+ product.setProductHeight(new BigDecimal(4));
+ product.setProductLength(new BigDecimal(3));
+ product.setProductWidth(new BigDecimal(1));
+ product.setSku("TB12345");
+ product.setManufacturer(addidas);
+ product.setType(generalType);
+ product.setMerchantStore(store);
+
+ // Product description
+ ProductDescription description = new ProductDescription();
+ description.setName("Short sleeves shirt");
+ description.setLanguage(en);
+ description.setProduct(product);
+
+ product.getDescriptions().add(description);
+ product.getCategories().add(shirts);
+
+
+ //availability
+ ProductAvailability availability = new ProductAvailability();
+ availability.setProductDateAvailable(new Date());
+ availability.setProductQuantity(100);
+ availability.setRegion("*");
+ availability.setProduct(product);// associate with product
+
+ //price
+ ProductPrice dprice = new ProductPrice();
+ dprice.setDefaultPrice(true);
+ dprice.setProductPriceAmount(new BigDecimal(29.99));
+ dprice.setProductAvailability(availability);
+
+
+
+ ProductPriceDescription dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice);
+ dpd.setLanguage(en);
+
+ dprice.getDescriptions().add(dpd);
+ availability.getPrices().add(dprice);
+ product.getAvailabilities().add(availability);
+
+
+ //attributes
+ //white
+ ProductAttribute whiteAttribute = new ProductAttribute();
+ whiteAttribute.setProduct(product);
+ whiteAttribute.setProductOption(option);
+ whiteAttribute.setAttributeDefault(true);
+ whiteAttribute.setProductAttributePrice(new BigDecimal(0));//no price variation
+ whiteAttribute.setProductAttributeWeight(new BigDecimal(0));//no weight variation
+ whiteAttribute.setProductOption(option);
+ whiteAttribute.setProductOptionValue(white);
+
+ product.getAttributes().add(whiteAttribute);
+ //black
+ ProductAttribute blackAttribute = new ProductAttribute();
+ blackAttribute.setProduct(product);
+ blackAttribute.setProductOption(option);
+ blackAttribute.setProductAttributePrice(new BigDecimal(5));//5 + dollars
+ blackAttribute.setProductAttributeWeight(new BigDecimal(0));//no weight variation
+ blackAttribute.setProductOption(option);
+ blackAttribute.setProductOptionValue(black);
+
+ product.getAttributes().add(blackAttribute);
+
+ productService.saveOrUpdate(product);
+
+ /** Create Shopping cart **/
+
+ ShoppingCart shoppingCart = new ShoppingCart();
+ shoppingCart.setMerchantStore(store);
+
+ UUID cartCode = UUID.randomUUID();
+ shoppingCart.setShoppingCartCode(cartCode.toString());
+
+ ShoppingCartItem item = new ShoppingCartItem(shoppingCart,product);
+ item.setShoppingCart(shoppingCart);
+ FinalPrice price = productPriceUtil.getFinalPrice(product);
+
+ item.setItemPrice(price.getFinalPrice());
+ item.setQuantity(1);
+
+ /** user selects black **/
+ ShoppingCartAttributeItem attributeItem = new ShoppingCartAttributeItem(item,blackAttribute);
+ item.getAttributes().add(attributeItem);
+
+ shoppingCart.getLineItems().add(item);
+
+
+ shoppingCartService.create(shoppingCart);
+
+ /** Retrieve cart **/
+
+ ShoppingCart retrievedCart = shoppingCartService.getByCode(cartCode.toString(), store);
+
+ Assert.assertNotNull(retrievedCart);
+
+
+
+
+ }
+
+ @Test
+ public void retrieveAlteredShoppingCart() throws Exception {
+
+ MerchantStore store = merchantService.getByCode( MerchantStore.DEFAULT_STORE );
+
+
+ Language en = languageService.getByCode("en");
+
+
+ /** CATALOG CREATION **/
+
+ ProductType generalType = productTypeService.getProductType(ProductType.GENERAL_TYPE);
+
+ /**
+ * Create the category
+ */
+ Category shirts = new Category();
+ shirts.setMerchantStore(store);
+ shirts.setCode("shirts");
+
+ CategoryDescription shirtsEnglishDescription = new CategoryDescription();
+ shirtsEnglishDescription.setName("Shirts");
+ shirtsEnglishDescription.setCategory(shirts);
+ shirtsEnglishDescription.setLanguage(en);
+
+ List<CategoryDescription> descriptions = new ArrayList<CategoryDescription>();
+ descriptions.add(shirtsEnglishDescription);
+
+
+ shirts.setDescriptions(descriptions);
+ categoryService.create(shirts);
+
+
+ /**
+ * Create a manufacturer
+ */
+ Manufacturer addidas = new Manufacturer();
+ addidas.setMerchantStore(store);
+
+ ManufacturerDescription addidasDesc = new ManufacturerDescription();
+ addidasDesc.setLanguage(en);
+ addidasDesc.setManufacturer(addidas);
+ addidasDesc.setName("Addidas");
+ addidas.getDescriptions().add(addidasDesc);
+
+ manufacturerService.create(addidas);
+
+ /**
+ * Create an option
+ */
+ ProductOption option = new ProductOption();
+ option.setMerchantStore(store);
+ option.setCode("color");
+ option.setProductOptionType(ProductOptionType.Radio.name());
+
+ ProductOptionDescription optionDescription = new ProductOptionDescription();
+ optionDescription.setLanguage(en);
+ optionDescription.setName("Color");
+ optionDescription.setDescription("Item color");
+ optionDescription.setProductOption(option);
+
+ option.getDescriptions().add(optionDescription);
+
+ productOptionService.saveOrUpdate(option);
+
+
+ /** first option value **/
+ ProductOptionValue white = new ProductOptionValue();
+ white.setMerchantStore(store);
+ white.setCode("white");
+
+ ProductOptionValueDescription whiteDescription = new ProductOptionValueDescription();
+ whiteDescription.setLanguage(en);
+ whiteDescription.setName("White");
+ whiteDescription.setDescription("White color");
+ whiteDescription.setProductOptionValue(white);
+
+ white.getDescriptions().add(whiteDescription);
+
+ productOptionValueService.saveOrUpdate(white);
+
+
+ ProductOptionValue black = new ProductOptionValue();
+ black.setMerchantStore(store);
+ black.setCode("black");
+
+ /** second option value **/
+ ProductOptionValueDescription blackDesc = new ProductOptionValueDescription();
+ blackDesc.setLanguage(en);
+ blackDesc.setName("Black");
+ blackDesc.setDescription("Black color");
+ blackDesc.setProductOptionValue(black);
+
+ black.getDescriptions().add(blackDesc);
+
+ productOptionValueService.saveOrUpdate(black);
+
+
+ /**
+ * Create a complex product
+ */
+ Product product = new Product();
+ product.setProductHeight(new BigDecimal(4));
+ product.setProductLength(new BigDecimal(3));
+ product.setProductWidth(new BigDecimal(1));
+ product.setSku("TB12345");
+ product.setManufacturer(addidas);
+ product.setType(generalType);
+ product.setMerchantStore(store);
+
+ // Product description
+ ProductDescription description = new ProductDescription();
+ description.setName("Short sleeves shirt");
+ description.setLanguage(en);
+ description.setProduct(product);
+
+ product.getDescriptions().add(description);
+ product.getCategories().add(shirts);
+
+
+ //availability
+ ProductAvailability availability = new ProductAvailability();
+ availability.setProductDateAvailable(new Date());
+ availability.setProductQuantity(100);
+ availability.setRegion("*");
+ availability.setProduct(product);// associate with product
+
+ //price
+ ProductPrice dprice = new ProductPrice();
+ dprice.setDefaultPrice(true);
+ dprice.setProductPriceAmount(new BigDecimal(29.99));
+ dprice.setProductAvailability(availability);
+
+
+
+ ProductPriceDescription dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice);
+ dpd.setLanguage(en);
+
+ dprice.getDescriptions().add(dpd);
+ availability.getPrices().add(dprice);
+ product.getAvailabilities().add(availability);
+
+
+ //attributes
+ //white
+ ProductAttribute whiteAttribute = new ProductAttribute();
+ whiteAttribute.setProduct(product);
+ whiteAttribute.setProductOption(option);
+ whiteAttribute.setAttributeDefault(true);
+ whiteAttribute.setProductAttributePrice(new BigDecimal(0));//no price variation
+ whiteAttribute.setProductAttributeWeight(new BigDecimal(0));//no weight variation
+ whiteAttribute.setProductOption(option);
+ whiteAttribute.setProductOptionValue(white);
+
+ product.getAttributes().add(whiteAttribute);
+ //black
+ ProductAttribute blackAttribute = new ProductAttribute();
+ blackAttribute.setProduct(product);
+ blackAttribute.setProductOption(option);
+ blackAttribute.setProductAttributePrice(new BigDecimal(5));//5 + dollars
+ blackAttribute.setProductAttributeWeight(new BigDecimal(0));//no weight variation
+ blackAttribute.setProductOption(option);
+ blackAttribute.setProductOptionValue(black);
+
+ product.getAttributes().add(blackAttribute);
+
+ productService.saveOrUpdate(product);
+
+ /** Create Shopping cart **/
+
+ ShoppingCart shoppingCart = new ShoppingCart();
+ shoppingCart.setMerchantStore(store);
+
+ UUID cartCode = UUID.randomUUID();
+ shoppingCart.setShoppingCartCode(cartCode.toString());
+
+ ShoppingCartItem item = new ShoppingCartItem(shoppingCart,product);
+ item.setShoppingCart(shoppingCart);
+ FinalPrice price = productPriceUtil.getFinalPrice(product);
+
+ item.setItemPrice(price.getFinalPrice());
+ item.setQuantity(1);
+
+ /** user selects black **/
+ ShoppingCartAttributeItem attributeItem = new ShoppingCartAttributeItem(item,blackAttribute);
+ item.getAttributes().add(attributeItem);
+
+ shoppingCart.getLineItems().add(item);
+
+
+ shoppingCartService.create(shoppingCart);
+
+
+ /** Modify product definition **/
+
+ Product retrievedProduct = productService.getById(product.getId());
+
+ Set<ProductAttribute> attributes = retrievedProduct.getAttributes();
+
+ Assert.assertNotNull(attributes);
+
+ for(ProductAttribute attr : attributes) {
+ productAttributeService.delete(attr);
+ }
+
+
+
+ /** Retrieve cart **/
+
+ ShoppingCart retrievedCart = shoppingCartService.getByCode(cartCode.toString(), store);
+
+ Assert.assertNotNull(retrievedCart);
+
+
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/sm-core/src/test/java/com/salesmanager/test/tax/TaxTestCase.java b/sm-core/src/test/java/com/salesmanager/test/tax/TaxTestCase.java
new file mode 100644
index 0000000..b8194cb
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/tax/TaxTestCase.java
@@ -0,0 +1,235 @@
+package com.salesmanager.test.tax;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.salesmanager.core.business.catalog.product.model.Product;
+import com.salesmanager.core.business.catalog.product.model.availability.ProductAvailability;
+import com.salesmanager.core.business.catalog.product.model.description.ProductDescription;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPrice;
+import com.salesmanager.core.business.catalog.product.model.price.ProductPriceDescription;
+import com.salesmanager.core.business.common.model.Delivery;
+import com.salesmanager.core.business.customer.model.Customer;
+import com.salesmanager.core.business.customer.model.CustomerGender;
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.merchant.model.MerchantStore;
+import com.salesmanager.core.business.order.model.OrderSummary;
+import com.salesmanager.core.business.reference.country.model.Country;
+import com.salesmanager.core.business.reference.language.model.Language;
+import com.salesmanager.core.business.reference.zone.model.Zone;
+import com.salesmanager.core.business.shipping.model.ShippingConfiguration;
+import com.salesmanager.core.business.shipping.model.ShippingSummary;
+import com.salesmanager.core.business.shipping.service.ShippingService;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCart;
+import com.salesmanager.core.business.shoppingcart.model.ShoppingCartItem;
+import com.salesmanager.core.business.tax.model.TaxBasisCalculation;
+import com.salesmanager.core.business.tax.model.TaxConfiguration;
+import com.salesmanager.core.business.tax.model.TaxItem;
+import com.salesmanager.core.business.tax.model.taxclass.TaxClass;
+import com.salesmanager.core.business.tax.model.taxrate.TaxRate;
+import com.salesmanager.core.business.tax.model.taxrate.TaxRateDescription;
+import com.salesmanager.core.business.tax.service.TaxClassService;
+import com.salesmanager.core.business.tax.service.TaxRateService;
+import com.salesmanager.core.business.tax.service.TaxService;
+import com.salesmanager.test.core.AbstractSalesManagerCoreTestCase;
+
+public class TaxTestCase extends AbstractSalesManagerCoreTestCase {
+
+ private static final Date date = new Date(System.currentTimeMillis());
+
+ @Autowired
+ private TaxService taxService;
+
+ @Autowired
+ private TaxRateService taxRateService;
+
+ @Autowired
+ private ShippingService shippingService;
+
+ @Autowired
+ private TaxClassService taxClassService;
+
+ /**
+ * Test tax calculation
+ * @throws ServiceException
+ */
+ @Test
+ public void testCanadianSalesTax() throws ServiceException {
+
+ Language en = languageService.getByCode("en");
+ Country country = countryService.getByCode("CA");
+ Zone zone = zoneService.getByCode("QC");
+ Zone on = zoneService.getByCode("ON");
+ TaxClass defaultTaxClass = taxClassService.getByCode(TaxClass.DEFAULT_TAX_CLASS);
+
+ MerchantStore store = merchantService.getByCode(MerchantStore.DEFAULT_STORE);
+
+ //create tax configuration based on store location in the admin
+
+ TaxConfiguration taxConfiguration = new TaxConfiguration();
+ taxConfiguration.setTaxBasisCalculation(TaxBasisCalculation.STOREADDRESS);
+
+ taxService.saveTaxConfiguration(taxConfiguration, store);
+
+ //tax on shipping
+ ShippingConfiguration shippingConfiguration = new ShippingConfiguration();
+ shippingConfiguration.setTaxOnShipping(true);
+ shippingService.saveShippingConfiguration(shippingConfiguration, store);
+
+ OrderSummary orderSummary = new OrderSummary();
+
+ ShippingSummary shippingSummary = new ShippingSummary();
+ shippingSummary.setShipping(new BigDecimal(10));
+
+ orderSummary.setShippingSummary(shippingSummary);
+
+
+
+ Product product = new Product();
+ product.setProductHeight(new BigDecimal(4));
+ product.setProductLength(new BigDecimal(3));
+ product.setProductWidth(new BigDecimal(5));
+ product.setProductWeight(new BigDecimal(8));
+ product.setSku("TB12345");
+ product.setMerchantStore(store);
+ product.setTaxClass(defaultTaxClass);
+
+ // Product description
+ ProductDescription description = new ProductDescription();
+ description.setName("Product 1");
+ description.setLanguage(en);
+ description.setProduct(product);
+
+ product.getDescriptions().add(description);
+ //productService.create(product);
+
+ // Availability
+ ProductAvailability availability = new ProductAvailability();
+ availability.setProductDateAvailable(date);
+ availability.setProductQuantity(100);
+ availability.setRegion("*");
+ availability.setProduct(product);// associate with product
+
+ //productAvailabilityService.create(availability);
+
+ ProductPrice dprice = new ProductPrice();
+ dprice.setDefaultPrice(true);
+ dprice.setProductPriceAmount(new BigDecimal(29.99));
+ dprice.setProductAvailability(availability);
+
+ ProductPriceDescription dpd = new ProductPriceDescription();
+ dpd.setName("Base price");
+ dpd.setProductPrice(dprice);
+ dpd.setLanguage(en);
+
+ dprice.getDescriptions().add(dpd);
+
+ ShoppingCartItem shoppingCartItem = new ShoppingCartItem(new ShoppingCart(),product);
+
+ shoppingCartItem.setItemPrice(new BigDecimal(29.99));
+ shoppingCartItem.setProduct(product);
+
+ orderSummary.getProducts().add(shoppingCartItem);
+
+ //create tax rates in the admin for QC - CA
+ TaxRate tps = new TaxRate();
+ tps.setCode("TPS");
+ tps.setCountry(country);
+ tps.setZone(zone);
+ tps.setMerchantStore(store);
+ tps.setTaxClass(defaultTaxClass);
+ tps.setTaxPriority(0);
+ tps.setTaxRate(new BigDecimal(5));
+
+ TaxRateDescription tpsDescription = new TaxRateDescription();
+ tpsDescription.setName("TPS");
+ tpsDescription.setDescription("TPS Sales Tax");
+ tpsDescription.setLanguage(en);
+ tpsDescription.setTaxRate(tps);
+
+ tps.getDescriptions().add(tpsDescription);
+
+ taxRateService.create(tps);
+
+
+ TaxRate tvq = new TaxRate();
+ tvq.setCode("TVQ");
+ tvq.setCountry(country);
+ tvq.setZone(zone);
+ tvq.setMerchantStore(store);
+ tvq.setTaxClass(defaultTaxClass);
+ tvq.setTaxPriority(1);
+ tvq.setTaxRate(new BigDecimal(7));
+ tvq.setPiggyback(true);
+ tvq.setParent(tps);
+
+ TaxRateDescription tvqDescription = new TaxRateDescription();
+ tvqDescription.setName("TVQ");
+ tvqDescription.setDescription("TVQ Sales Tax");
+ tvqDescription.setLanguage(en);
+ tvqDescription.setTaxRate(tvq);
+
+ tvq.getDescriptions().add(tvqDescription);
+
+ taxRateService.create(tvq);
+
+
+ TaxRate hst = new TaxRate();
+ hst.setCode("HST");
+ hst.setCountry(country);
+ hst.setZone(on);
+ hst.setMerchantStore(store);
+ hst.setTaxClass(defaultTaxClass);
+ hst.setTaxPriority(0);
+ hst.setTaxRate(new BigDecimal(14));
+
+
+ TaxRateDescription hstDescription = new TaxRateDescription();
+ hstDescription.setName("HST");
+ hstDescription.setDescription("Harmonized Sales Tax");
+ hstDescription.setLanguage(en);
+ hstDescription.setTaxRate(hst);
+
+ hst.getDescriptions().add(hstDescription);
+
+ taxRateService.create(hst);
+
+ //create a Customer with origin QC - CA
+ Customer customer = new Customer();
+ customer.setMerchantStore(store);
+ customer.setEmailAddress("test@test.com");
+ customer.setGender(CustomerGender.M);
+ customer.setAnonymous(true);
+ customer.setCompany("ifactory");
+ customer.setDateOfBirth(new Date());
+ customer.setNick("My nick");
+ customer.setPassword("123456");
+
+
+ Delivery delivery = new Delivery();
+ delivery.setAddress("Shipping address");
+ delivery.setCity("Boucherville");
+ delivery.setCountry(country);
+ delivery.setZone(on);
+ delivery.setPostalCode("J4B-8J9");
+
+ List<TaxItem> taxLines = taxService.calculateTax(orderSummary, customer, store, en);
+
+ Assert.assertNotNull(taxLines);
+
+ for(TaxItem taxItem : taxLines) {
+
+ System.out.println(taxItem.getLabel() + " " + taxItem.getItemPrice().toPlainString());
+
+ }
+
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/sm-core/src/test/java/com/salesmanager/test/utils/ExportSchema.java b/sm-core/src/test/java/com/salesmanager/test/utils/ExportSchema.java
new file mode 100644
index 0000000..ba1a1ea
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/utils/ExportSchema.java
@@ -0,0 +1,50 @@
+package com.salesmanager.test.utils;
+
+import java.util.Map;
+
+import javax.persistence.spi.PersistenceUnitInfo;
+
+import org.hibernate.ejb.Ejb3Configuration;
+import org.hibernate.tool.hbm2ddl.SchemaExport;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
+
+import com.salesmanager.test.core.AbstractSalesManagerCoreTestCase;
+
+
+
+
+public class ExportSchema extends AbstractSalesManagerCoreTestCase {
+
+ @Autowired
+ private LocalContainerEntityManagerFactoryBean entityManagerFactory;
+
+ /**
+ * Create a sql script with create tables, indexes and fk
+ * from annotated POJOs
+ * You must copy resources/META-INF/sm-persistence.xml to persistence.xml
+ * before you run this class
+ * Once generated, remove the persistence.xml copy from META-INF
+ * @throws Exception
+ */
+ @Test
+ @Ignore
+ public void createSchema() throws Exception {
+
+
+ PersistenceUnitInfo persistenceUnitInfo = entityManagerFactory.getPersistenceUnitInfo();
+ Map jpaPropertyMap = entityManagerFactory.getJpaPropertyMap();
+
+ @SuppressWarnings("deprecation")
+ org.hibernate.cfg.Configuration configuration = new Ejb3Configuration().configure( persistenceUnitInfo, jpaPropertyMap ).getHibernateConfiguration();
+
+ SchemaExport schema = new SchemaExport(configuration);
+ schema.setOutputFile("c:/schema.sql");
+ schema.create(true, false);
+
+
+ }
+
+}
diff --git a/sm-core/src/test/java/com/salesmanager/test/utils/ImportIntegrationModule.java b/sm-core/src/test/java/com/salesmanager/test/utils/ImportIntegrationModule.java
new file mode 100644
index 0000000..1e388bc
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/utils/ImportIntegrationModule.java
@@ -0,0 +1,101 @@
+package com.salesmanager.test.utils;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.Map;
+
+import org.codehaus.jackson.map.ObjectMapper;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.TestExecutionListeners;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
+
+import com.salesmanager.core.business.generic.exception.ServiceException;
+import com.salesmanager.core.business.system.model.IntegrationModule;
+import com.salesmanager.core.business.system.service.ModuleConfigurationService;
+import com.salesmanager.core.utils.reference.IntegrationModulesLoader;
+
+
+
+
+@ContextConfiguration( locations = { "classpath:spring/test-spring-context.xml" } )
+@RunWith( SpringJUnit4ClassRunner.class )
+@TestExecutionListeners( { DependencyInjectionTestExecutionListener.class } )
+public class ImportIntegrationModule {
+
+ @Autowired
+ private IntegrationModulesLoader integrationModulesLoader;
+
+
+ @Autowired
+ private ModuleConfigurationService moduleCongigurationService;
+
+ /**
+ * Import an integration module
+ * @throws Exception
+ */
+ @Ignore
+ public void importIntegrationModule() throws Exception {
+
+
+ ObjectMapper mapper = new ObjectMapper();
+ File file = new File("/Users/csamson777/Documents/workspace2/sm-core/src/main/resources/reference/integrationmodules.json");
+
+ InputStream in = null;
+
+
+ try {
+
+
+
+
+ in = new FileInputStream(file);
+
+ if(in==null) {
+ throw new Exception("File not found");
+ }
+ @SuppressWarnings("rawtypes")
+ Map[] objects = mapper.readValue(in, Map[].class);
+
+ IntegrationModule module = null;
+ //get the module to be loaded
+ for(int i = 0; i < objects.length; i++) {
+ @SuppressWarnings("rawtypes")
+ Map o = objects[i];
+ //load that specific module
+ if(o.get("code").equals("beanstream")) {
+ //get module object
+ module = integrationModulesLoader.loadModule(o);
+ break;
+ }
+ }
+
+ if(module!=null) {
+ IntegrationModule m = moduleCongigurationService.getByCode(module.getCode());
+ if(m!=null) {
+ moduleCongigurationService.delete(m);
+ }
+
+ moduleCongigurationService.create(module);
+ }
+
+ } catch (Exception e) {
+ throw new ServiceException(e);
+ } finally {
+ if(in !=null) {
+ try {
+ in.close();
+ } catch(Exception ignore) {}
+ }
+ }
+
+
+
+ }
+
+}
diff --git a/sm-core/src/test/java/com/salesmanager/test/utils/UtilsTestCase.java b/sm-core/src/test/java/com/salesmanager/test/utils/UtilsTestCase.java
new file mode 100644
index 0000000..627a142
--- /dev/null
+++ b/sm-core/src/test/java/com/salesmanager/test/utils/UtilsTestCase.java
@@ -0,0 +1,90 @@
+package com.salesmanager.test.utils;
+
+
+
+import java.text.NumberFormat;
+import java.util.List;
+import java.util.Locale;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+
+import com.salesmanager.core.business.common.model.Address;
+import com.salesmanager.core.business.reference.country.service.CountryService;
+import com.salesmanager.core.business.reference.currency.model.Currency;
+import com.salesmanager.core.business.reference.currency.service.CurrencyService;
+import com.salesmanager.core.modules.utils.Encryption;
+import com.salesmanager.core.modules.utils.GeoLocation;
+import com.salesmanager.core.utils.CacheUtils;
+import com.salesmanager.test.core.AbstractSalesManagerCoreTestCase;
+
+public class UtilsTestCase extends AbstractSalesManagerCoreTestCase {
+
+
+ @Autowired
+ private CountryService countryService;
+
+
+
+ @Autowired
+ private CurrencyService currencyService;
+
+ @Autowired
+ private Encryption encryption;
+
+ @Autowired
+ private CacheUtils cache;
+
+ @Autowired
+ private GeoLocation geoLoaction;
+
+
+
+ @Test
+ public void testCache() throws Exception {
+
+
+
+ @SuppressWarnings("rawtypes")
+ List countries = countryService.list();
+
+
+
+
+ //CacheUtils cache = CacheUtils.getInstance();
+ cache.putInCache(countries, "COUNTRIES");
+
+ @SuppressWarnings("rawtypes")
+ List objects = (List) cache.getFromCache("COUNTRIES");
+
+ Assert.assertNotNull(objects);
+
+ }
+
+ @Test
+ public void testCurrency() throws Exception {
+
+ Currency currency = currencyService.getByCode("BGN");
+
+ java.util.Currency c = currency.getCurrency();
+
+ NumberFormat numberFormat = NumberFormat.getCurrencyInstance(Locale.US);
+ numberFormat.setCurrency(c);
+
+ System.out.println("Done");
+
+ }
+
+ @Test
+ public void testGeoLocation() throws Exception {
+
+ Address address = geoLoaction.getAddress("96.21.132.0");
+ if(address!=null) {
+ System.out.println(address.getCountry());
+ }
+
+ }
+
+
+}
diff --git a/sm-core/src/test/resources/database.properties b/sm-core/src/test/resources/database.properties
new file mode 100644
index 0000000..798fdab
--- /dev/null
+++ b/sm-core/src/test/resources/database.properties
@@ -0,0 +1,29 @@
+##
+## db configuration for test
+##
+db.jdbcUrl=jdbc\:h2\:file\:SALESMANAGER-TEST;AUTOCOMMIT=OFF;INIT\=RUNSCRIPT FROM 'src/test/resources/sql/create_schema.sql'
+db.user=test
+db.password=password
+db.driverClass=org.h2.Driver
+#hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
+hibernate.dialect=org.hibernate.dialect.H2Dialect
+
+#db.jdbcUrl=jdbc:mysql://localhost:3306/SALESMANAGER?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
+#db.user=carlito
+#db.password=ninetrails
+#hibernate.hbm2ddl.auto=create
+#db.driverClass=com.mysql.jdbc.Driver
+#hibernate.dialect=org.hibernate.dialect.MySQL5InnoDBDialect
+db.preferredTestQuery=SELECT 1
+db.schema=SALESMANAGER
+hibernate.hbm2ddl.auto=update
+
+
+
+
+##
+## configuration pooling base de donn�es
+##
+db.initialPoolSize=10
+db.minPoolSize=5
+db.maxPoolSize=50
\ No newline at end of file
diff --git a/sm-core/src/test/resources/hbm2dll.properties b/sm-core/src/test/resources/hbm2dll.properties
new file mode 100755
index 0000000..13a3da4
--- /dev/null
+++ b/sm-core/src/test/resources/hbm2dll.properties
@@ -0,0 +1 @@
+hibernate.dialect=org.hibernate.dialect.Oracle10gDialect
\ No newline at end of file
sm-core/src/test/resources/log4j.properties 14(+14 -0)
diff --git a/sm-core/src/test/resources/log4j.properties b/sm-core/src/test/resources/log4j.properties
new file mode 100644
index 0000000..38d6d36
--- /dev/null
+++ b/sm-core/src/test/resources/log4j.properties
@@ -0,0 +1,14 @@
+log4j.appender.Stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.Stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.Stdout.layout.ConversionPattern=[%d{ISO8601}] %-5p - %-26.26c{1} - %m\n
+
+log4j.rootLogger=WARN,Stdout
+
+# hibernate queries
+log4j.logger.org.hibernate.SQL=DEBUG
+log4j.logger.org.hibernate.type=INFO
+
+# schema initialization
+log4j.logger.org.hibernate.tool.hbm2ddl=DEBUG
+
+log4j.logger.org.springframework.transaction=DEBUG
diff --git a/sm-core/src/test/resources/spring/test-datasource.xml b/sm-core/src/test/resources/spring/test-datasource.xml
new file mode 100644
index 0000000..55dbe6a
--- /dev/null
+++ b/sm-core/src/test/resources/spring/test-datasource.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
+
+ <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
+ <property name="driverClassName" value="${db.driverClass}" />
+ <property name="url" value="${db.jdbcUrl}" />
+ <property name="username" value="${db.user}" />
+ <property name="password" value="${db.password}" />
+ </bean>
+
+</beans>
diff --git a/sm-core/src/test/resources/spring/test-spring-context.xml b/sm-core/src/test/resources/spring/test-spring-context.xml
new file mode 100644
index 0000000..a672df3
--- /dev/null
+++ b/sm-core/src/test/resources/spring/test-spring-context.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context-3.0.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util-3.0.xsd
+ ">
+
+ <import resource="classpath:/spring/spring-context.xml" />
+
+
+ <bean id="datasource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
+ <property name="driverClassName" value="${db.driverClass}" />
+ <property name="url" value="${db.jdbcUrl}" />
+ <property name="username" value="${db.user}" />
+ <property name="password" value="${db.password}" />
+ </bean>
+
+
+ <context:component-scan base-package="com.salesmanager.test" />
+
+ <util:properties id="shopizer-properties">
+ <prop key="MULTIPLE_PRICE_AVAILABILITY">false</prop>
+ <prop key="INDEX_PRODUCTS">false</prop>
+ <!-- Images -->
+ <prop key="PRODUCT_IMAGE_WIDTH_SIZE">350</prop>
+ <prop key="PRODUCT_IMAGE_HEIGHT_SIZE">375</prop>
+ <prop key="CROP_UPLOADED_IMAGES">false</prop>
+
+ <!-- upload image validations -->
+ <prop key="PRODUCT_IMAGE_MAX_HEIGHT_SIZE">2000</prop>
+ <prop key="PRODUCT_IMAGE_MAX_WIDTH_SIZE">4000</prop>
+ <prop key="PRODUCT_IMAGE_MAX_SIZE">9000000</prop>
+ <prop key="IMAGE_FORMATS">jpg|png|gif</prop>
+
+ <prop key="POPULATE_TEST_DATA">true</prop>
+
+ </util:properties>
+
+</beans>