Java tutorial
/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package com.spstudio.modules.sales.service.impl; import com.spstudio.common.search.Page; import com.spstudio.common.search.SearchCriteria; import com.spstudio.common.service.ConfigConditions; import com.spstudio.common.service.SystemConfigService; import com.spstudio.common.service.entity.SystemConfig; import com.spstudio.modules.member.entity.Member; import com.spstudio.modules.member.entity.MemberAsset; import com.spstudio.modules.member.entity.MemberType; import com.spstudio.modules.member.service.AssetType; import com.spstudio.modules.member.service.MemberService; import com.spstudio.modules.product.entity.PackageProductMapping; import com.spstudio.modules.product.entity.Product; import com.spstudio.modules.product.entity.ProductPackage; import com.spstudio.modules.product.entity.ProductType; import com.spstudio.modules.sales.config.Configuration; import com.spstudio.modules.sales.dao.SaleDAO; import com.spstudio.modules.sales.dao.SaleDiscountDAO; import com.spstudio.modules.sales.entity.SaleDiscount; import com.spstudio.modules.sales.entity.Sales; import com.spstudio.modules.sales.exception.InsufficientBonusPointException; import com.spstudio.modules.sales.exception.InsufficientDepositException; import com.spstudio.modules.sales.service.PaymentMethodType; import com.spstudio.modules.sales.service.SaleService; import com.spstudio.modules.stock.exceptions.StockNotEnoughException; import com.spstudio.modules.stock.service.StockService; import org.apache.commons.lang3.Validate; import org.springframework.transaction.annotation.Transactional; import java.util.Iterator; import java.util.List; /** * * @author wewezhu */ public class SaleServiceImpl implements SaleService { private final static String CASH_PAYMENT_METHOD = "CASH"; private final static String DEPOSIT_PAYMENT_METHOD = "DEPOSIT"; private final static String BONUSPOINT_PAYMENT_METHOD = "BONUSPOINT"; private MemberService memberService; // For stock deduction private StockService stockService; private SaleDAO saleDAO; private SaleDiscountDAO saleDiscountDAO; public SaleDAO getSaleDAO() { return saleDAO; } public void setSaleDAO(SaleDAO saleDAO) { this.saleDAO = saleDAO; } public SaleDiscountDAO getSaleDiscountDAO() { return saleDiscountDAO; } public void setSaleDiscountDAO(SaleDiscountDAO saleDiscountDAO) { this.saleDiscountDAO = saleDiscountDAO; } public MemberService getMemberService() { return memberService; } public void setMemberService(MemberService memberService) { this.memberService = memberService; } public StockService getStockService() { return stockService; } public void setStockService(StockService stockService) { this.stockService = stockService; } /* * Config operations */ SystemConfigService configService; public SystemConfigService getConfigService() { return configService; } public void setConfigService(SystemConfigService configService) { this.configService = configService; } @Override // public Float getGlobalDepositRate() { SystemConfig config = configService.findModuleSingleConfig(Configuration.SALE_MODULE_NAME, Configuration.CONFIG_GLOBAL_DEPOSIT_BONUSRATE); if (config == null) { return 0.0f; } try { float bonusRate = Float.valueOf(config.getConfigValue()); return bonusRate; } catch (NumberFormatException ex) { ex.printStackTrace(); return 0.0f; } } @Override public void createOrUpdateGlobalDepositRate(Float depositRate) { SystemConfig config = configService.findModuleSingleConfig(Configuration.SALE_MODULE_NAME, Configuration.CONFIG_GLOBAL_DEPOSIT_BONUSRATE); if (config == null) { config = new SystemConfig(); config.setConfigModule(Configuration.SALE_MODULE_NAME); config.setConfigName(Configuration.CONFIG_GLOBAL_DEPOSIT_BONUSRATE); } config.setConfigValue(String.valueOf(depositRate)); configService.addConfig(config); } @Override // ? public Float getDepositRate(MemberType memberType) { List<SystemConfig> configs = configService.findModuleConfig(Configuration.SALE_MODULE_NAME, Configuration.CONFIG_MEMBER_TYPE_DEPOSIT_BONUSRATE); if (configs == null || configs.size() == 0) { return getGlobalDepositRate(); } for (SystemConfig config : configs) { String condition = config.getConfigCondition(); if (condition.startsWith(ConfigConditions.EQUAL)) { String memberTypeId = condition.replace(ConfigConditions.EQUAL, ""); if (memberType.getMemberTypeId().equalsIgnoreCase(memberTypeId)) { try { float bonusRate = Float.valueOf(config.getConfigValue()); return bonusRate; } catch (NumberFormatException ex) { ex.printStackTrace(); } } } } return getGlobalDepositRate(); } @Override public void createOrUpdateDepositRate(MemberType memberType, Float depositRate) { SystemConfig config = configService.findModuleSingleConfig(Configuration.SALE_MODULE_NAME, Configuration.CONFIG_MEMBER_TYPE_DEPOSIT_BONUSRATE); if (config == null) { config = new SystemConfig(); config.setConfigModule(Configuration.SALE_MODULE_NAME); config.setConfigName(Configuration.CONFIG_MEMBER_TYPE_DEPOSIT_BONUSRATE); } config.setConfigCondition(ConfigConditions.EQUAL + memberType.getMemberTypeId()); config.setConfigValue(String.valueOf(depositRate)); configService.addConfig(config); } /* * Sales operations */ private Sales _getNewSaleRecord(Member member, int assetType, Product product, SaleDiscount discount, ProductPackage pkg, int deposit, int count, float price, String saler, int paymentType) { Sales returnSale = new Sales(); returnSale.setSaleType(assetType); returnSale.setProduct(product); returnSale.setProductPackage(pkg); returnSale.setDeposit(deposit); returnSale.setDiscount(discount); returnSale.setPrice(price); returnSale.setMember(member); returnSale.setSalesCount(count); returnSale.setSaler(saler); returnSale.setPaymentMethodType(paymentType); return returnSale; } @Override public Sales findSaleRecordById(String saleId) { return saleDAO.findSaleRecordsById(saleId); } @Override public List<Sales> findSaleRecordOfMember(Member member) { return saleDAO.findSaleRecordsByMember(member); } private Sales _addProductSaleRecord(Member member, Product product, int count, int deposit, float price, String saler, PaymentMethodType type) { SaleDiscount discount = _getDiscount(product, member.getMemberType()); Sales saleRec = _getNewSaleRecord(member, AssetType.ASSET_PRODUCT_TYPE.ordinal(), product, discount, null, deposit, count, price, saler, type.ordinal()); Sales retSale = saleDAO.addSalesRecord(saleRec); return retSale; } private Sales _addProductPackageSaleRecord(Member member, ProductPackage pkg, int count, float price, String saler, PaymentMethodType type) { Sales saleRec = _getNewSaleRecord(member, AssetType.ASSET_PACKAGE_TYPE.ordinal(), null, null, pkg, 0, count, price, saler, type.ordinal()); Sales retSale = saleDAO.addSalesRecord(saleRec); return retSale; } private Sales _addDepositSaleRecord(Member member, int deposit, String saler, PaymentMethodType type) { Sales saleRec = _getNewSaleRecord(member, AssetType.ASSET_DEPOSIT_TYPE.ordinal(), null, null, null, deposit, 1, deposit, saler, type.ordinal()); Sales retSale = saleDAO.addSalesRecord(saleRec); return retSale; } @Override public boolean removeSaleRecord(Sales salerec) { Sales sale = saleDAO.removeSalesRecord(salerec); return sale != null; } @Override public boolean removeSaleRecordList(List<String> assetIdList) { return saleDAO.removeSalesRecords(assetIdList); } @Override public boolean removeSaleRecordsOfMember(Member member) { List<Sales> sales = saleDAO.findSaleRecordsByMember(member); return sales.size() > 0; } @Override public Sales updateSaleRecord(Sales salerec) { return saleDAO.updateSalesRecord(salerec); } @Override public boolean zapSaleRecordOfMember(Member member) { return saleDAO.zapSalesRecordOfMember(member); } @Override public void zapSalesRecord(Sales sales) { saleDAO.zapSalesRecord(sales); } @Override public Page<Sales> querySalesForPage(int currentPage, int pageSize, SearchCriteria criteria) { // int allRow = saleDAO.getQueryCount(criteria); Page<Sales> page = new Page<Sales>(); //? int offset = page.countOffset(currentPage, pageSize); // List<Sales> list = saleDAO.queryForPage(currentPage, pageSize, criteria); page.setPageNo(currentPage); page.setPageSize(pageSize); page.setTotalRecords(allRow); page.setList(list); return page; } /* * Discount operations */ private SaleDiscount _getDiscount(Product product, MemberType memberType) { SaleDiscount discount = saleDiscountDAO.getDiscountByProduct(product, memberType); if (discount == null) { discount = saleDiscountDAO.getDiscountByProductType(product.getType(), memberType); } return discount; } @Override public SaleDiscount createDiscountForProduct(Product product, MemberType type, float discount) { return saleDiscountDAO.createDiscount(product, type, discount); } @Override public SaleDiscount createDiscountForProductType(ProductType productType, MemberType type, float discount) { return saleDiscountDAO.createDiscount(productType, type, discount); } @Override public SaleDiscount findDiscountById(String discountId) { return saleDiscountDAO.getDiscountByProduct(discountId); } @Override public SaleDiscount findDiscount(Product product, MemberType type) { return saleDiscountDAO.getDiscountByProduct(product, type); } @Override public SaleDiscount findDiscount(ProductType productType, MemberType type) { return saleDiscountDAO.getDiscountByProductType(productType, type); } @Override public void updateDiscount(SaleDiscount discount) { saleDiscountDAO.updateDiscountByProduct(discount); } @Override public boolean deleteDiscount(SaleDiscount discount) { return saleDiscountDAO.zapDiscount(discount); } @Override public boolean deleteDiscountByProduct(Product product) { return saleDiscountDAO.zapDiscountsByProduct(product); } @Override public boolean deleteDiscountByProductType(ProductType productType) { return saleDiscountDAO.zapDiscountsByProductType(productType); } @Override public boolean deleteDiscountByMemberType(MemberType type) { return saleDiscountDAO.zapDiscountsByMemberType(type); } @Override public Page<SaleDiscount> queryDiscountForPage(int currentPage, int pageSize, SearchCriteria criteria) { // int allRow = saleDiscountDAO.getQueryCount(criteria); Page<SaleDiscount> page = new Page<SaleDiscount>(); //? int offset = page.countOffset(currentPage, pageSize); // List<SaleDiscount> list = saleDiscountDAO.queryForPage(currentPage, pageSize, criteria); page.setPageNo(currentPage); page.setPageSize(pageSize); page.setTotalRecords(allRow); page.setList(list); return page; } boolean _checkStock(Product product, int count) { return stockService.isStockEnoughForDecrease(product, count); } boolean _checkStock(ProductPackage pkg, int count) { boolean isEnoughStock = true; Iterator iter = pkg.getProductMappingSet().iterator(); while (isEnoughStock && iter.hasNext()) { PackageProductMapping mapping = (PackageProductMapping) iter.next(); isEnoughStock = stockService.isStockEnoughForDecrease(mapping.getProduct(), mapping.getCount() * count); } return isEnoughStock; } boolean _checkDeposit(Member member, int price) { MemberAsset depositAsset = memberService.getDepositAssetOfMember(member); int deposit = (depositAsset == null) ? 0 : depositAsset.getDeposit(); return (deposit >= price); } boolean _checkDeposit(Member member, ProductPackage pkg, int count) { MemberAsset depositAsset = memberService.getDepositAssetOfMember(member); int deposit = (depositAsset == null) ? 0 : depositAsset.getDeposit(); return (deposit >= pkg.getUnitPrice() * count); } boolean _checkBonusPoint(Member member, Product product, int count) { int restBp = memberService.getBonusPoint(member); int toSpendBp = product.getBonusePoint() * count; return (restBp >= toSpendBp); } /** * Buy Deposit, pay with cash */ @Transactional(rollbackFor = Exception.class) private boolean _buyDepositPayWithCash(Member member, int deposit, String saler) { // add record _addDepositSaleRecord(member, deposit, saler, PaymentMethodType.PAYMENT_METHOD_CASH); // add memeber asset memberService.increaseOrAddDepositAsset(member, deposit); // this will cause member type change MemberType newMemberType = memberService.getDepositMemberTypeRank(deposit); if (newMemberType != null) { if (!member.getMemberType().getMemberTypeId().equalsIgnoreCase(newMemberType.getMemberTypeId()) && (newMemberType.getPriority() > member.getMemberType().getPriority())) { // TODO: this logic is wrong, ????? member.setMemberType(newMemberType); memberService.updateMember(member); } } else { // means this deposit charge does not tigger any rule, // so the member type won't change } // this will generate bonus point float bonusRate = getDepositRate(member.getMemberType()); int bonusPoint = (int) (bonusRate * (float) deposit); if (bonusPoint > 0) { memberService.increaseBonusPoint(member, bonusPoint); } return true; } /** * Buy product and pay with cash * ??? */ private void _buyProductPayWithCash(Member member, Product product, int count, String saler) throws StockNotEnoughException { float price = this.GetProductPrice(PaymentMethodType.PAYMENT_METHOD_CASH, null, product, 1); _buyProductPayWithCash(member, product, count, price, saler); } @Transactional(rollbackFor = Exception.class) private void _buyProductPayWithCash(Member member, Product product, int count, float price, String saler) throws StockNotEnoughException { // boolean isEnoughStock = _checkStock(product, count); // if(isEnoughStock){ // decrease stock first stockService.decreaseStockNum(product, count); // add record _addProductSaleRecord(member, product, count, 0, price, saler, PaymentMethodType.PAYMENT_METHOD_CASH); // add memeber asset memberService.addProductAsset(member, product, count); // }else{ // throw new StockNotEnoughException(); // } } /** * Buy package and pay with cash * ??? */ @Transactional(rollbackFor = Exception.class) private void _buyPackagePayWithCash(Member member, ProductPackage pkg, int count, String saler) throws StockNotEnoughException { float price = this.GetPackagePrice(pkg, count); _buyPackagePayWithCash(member, pkg, count, price, saler); } @Transactional(rollbackFor = Exception.class) private void _buyPackagePayWithCash(Member member, ProductPackage pkg, int count, float price, String saler) throws StockNotEnoughException { // boolean isEnoughStock = _checkStock(pkg, count); // if(isEnoughStock){ // try { // decrease stock first Iterator iter = pkg.getProductMappingSet().iterator(); while (iter.hasNext()) { PackageProductMapping mapping = (PackageProductMapping) iter.next(); stockService.decreaseStockNum(mapping.getProduct(), mapping.getCount() * count); } // add record _addProductPackageSaleRecord(member, pkg, count, price, saler, PaymentMethodType.PAYMENT_METHOD_CASH); // add memeber asset memberService.addPackageAsset(member, pkg, count); // return true; // } catch (StockNotEnoughException e) { // e.printStackTrace(); // } // } // return false; } /** * Buy product and pay with deposit * ??? */ private void _buyProductPayWithDeposit(Member member, Product product, int count, String saler) throws StockNotEnoughException, InsufficientDepositException { float price = this.GetProductPrice(PaymentMethodType.PAYMENT_METHOD_DEPOSIT, member, product, count); _buyProductPayWithDeposit(member, product, count, price, saler); } @Transactional(rollbackFor = Exception.class) private void _buyProductPayWithDeposit(Member member, Product product, int count, float price, String saler) throws StockNotEnoughException, InsufficientDepositException { //boolean isEnoughStock = _checkStock(product, count); boolean isEnoughDeposit = _checkDeposit(member, (int) price); if (isEnoughDeposit) { //try { // decrease stock stockService.decreaseStockNum(product, count); // decrease deposit MemberAsset depositAsset = memberService.getDepositAssetOfMember(member); int deposit = (depositAsset == null) ? 0 : depositAsset.getDeposit(); depositAsset.setDeposit(deposit - (int) price); memberService.updateDepositAsset(depositAsset); // add record this._addProductSaleRecord(member, product, count, (int) price, 0.0f, saler, PaymentMethodType.PAYMENT_METHOD_DEPOSIT); // add memeber asset memberService.addProductAsset(member, product, count); // } catch (StockNotEnoughException e) { // e.printStackTrace(); // return false; // } } else { throw new InsufficientDepositException(); } } /** * Buy package and pay with deposit */ @Transactional(rollbackFor = Exception.class) private void _buyPackagePayWithDeposit(Member member, ProductPackage pkg, int count, String saler) throws StockNotEnoughException, InsufficientDepositException { float price = GetPackagePrice(pkg, count); _buyPackagePayWithDeposit(member, pkg, count, price, saler); } @Transactional(rollbackFor = Exception.class) private void _buyPackagePayWithDeposit(Member member, ProductPackage pkg, int count, float price, String saler) throws StockNotEnoughException, InsufficientDepositException { //boolean isEnoughStock = _checkStock(pkg, count); boolean isEnoughDeposit = _checkDeposit(member, pkg, count); if (isEnoughDeposit) { // try { // decrease stock first Iterator iter = pkg.getProductMappingSet().iterator(); while (iter.hasNext()) { PackageProductMapping mapping = (PackageProductMapping) iter.next(); stockService.decreaseStockNum(mapping.getProduct(), mapping.getCount() * count); } // decrease deposit MemberAsset depositAsset = memberService.getDepositAssetOfMember(member); int deposit = (depositAsset == null) ? 0 : depositAsset.getDeposit(); int cost = this.GetPackagePrice(pkg, count); depositAsset.setDeposit(deposit - cost); memberService.updateDepositAsset(depositAsset); // add record _addProductPackageSaleRecord(member, pkg, count, price, saler, PaymentMethodType.PAYMENT_METHOD_DEPOSIT); // add memeber asset memberService.addPackageAsset(member, pkg, count); // return true; // } catch (StockNotEnoughException e) { // e.printStackTrace(); // return false; // } } else { throw new InsufficientDepositException(); } } /** * Buy product and pay with bonus point */ @Transactional(rollbackFor = Exception.class) private void _buyProductPayWithBonusPoint(Member member, Product product, int count, String saler) throws StockNotEnoughException, InsufficientBonusPointException { int cost = this.GetProductBonusPoint(product, count); _buyProductPayWithBonusPoint(member, product, count, cost, saler); } @Transactional(rollbackFor = Exception.class) private void _buyProductPayWithBonusPoint(Member member, Product product, int count, int cost, String saler) throws StockNotEnoughException, InsufficientBonusPointException { boolean isEnoughBonusPoint = _checkBonusPoint(member, product, count); if (isEnoughBonusPoint) { // decrease stock stockService.decreaseStockNum(product, count); // decrease bonus point int bp = memberService.getBonusPoint(member); int restBp = bp - cost; memberService.updateBonusPoint(member, restBp); // add record _addProductSaleRecord(member, product, count, 0, 0, saler, PaymentMethodType.PAYMENT_METHOD_BONUSPOINT); // add memeber asset memberService.addProductAsset(member, product, count); } else { throw new InsufficientBonusPointException(); } } @Override public boolean BuyDeposit(Member member, int deposit, String saler) { return _buyDepositPayWithCash(member, deposit, saler); } @Override public void BuyProduct(PaymentMethodType type, Member member, Product product, int count, String saler) throws StockNotEnoughException, InsufficientDepositException, InsufficientBonusPointException { switch (type) { case PAYMENT_METHOD_CASH: _buyProductPayWithCash(member, product, count, saler); break; case PAYMENT_METHOD_BONUSPOINT: _buyProductPayWithBonusPoint(member, product, count, saler); break; case PAYMENT_METHOD_DEPOSIT: _buyProductPayWithDeposit(member, product, count, saler); break; } } @Override public void BuyProduct(PaymentMethodType type, Member member, Product product, int count, float price, String saler) throws StockNotEnoughException, InsufficientDepositException, InsufficientBonusPointException { switch (type) { case PAYMENT_METHOD_CASH: _buyProductPayWithCash(member, product, count, price, saler); break; case PAYMENT_METHOD_BONUSPOINT: int cost = (int) price; _buyProductPayWithBonusPoint(member, product, count, cost, saler); break; case PAYMENT_METHOD_DEPOSIT: _buyProductPayWithDeposit(member, product, count, price, saler); break; } } @Override public void BuyPackage(PaymentMethodType type, Member member, ProductPackage pkg, int count, String saler) throws StockNotEnoughException, InsufficientDepositException { switch (type) { case PAYMENT_METHOD_CASH: { _buyPackagePayWithCash(member, pkg, count, saler); break; } case PAYMENT_METHOD_DEPOSIT: { _buyPackagePayWithDeposit(member, pkg, count, saler); break; } } } @Override public void BuyPackage(PaymentMethodType type, Member member, ProductPackage pkg, int count, float price, String saler) throws StockNotEnoughException, InsufficientDepositException { switch (type) { case PAYMENT_METHOD_CASH: { _buyPackagePayWithCash(member, pkg, count, price, saler); break; } case PAYMENT_METHOD_DEPOSIT: { _buyPackagePayWithDeposit(member, pkg, count, price, saler); break; } } } @Override public float GetProductPrice(PaymentMethodType type, Member member, Product product, int count) { Validate.notNull(product, "product should not be null"); switch (type) { case PAYMENT_METHOD_CASH: { // should not add discount logic float price = product.getUnitPrice() * count; return price; } case PAYMENT_METHOD_DEPOSIT: { Validate.notNull(member, "member should not be null"); SaleDiscount discount = saleDiscountDAO.getDiscountByProduct(product, member.getMemberType()); // Discount logic float rawPrice = product.getUnitPrice() * count; float price = rawPrice; if (discount != null && discount.getDiscountValue() < 1.0f) { price = rawPrice * discount.getDiscountValue(); } return price; } default: return 0.0f; } } @Override public float GetProductDiscount(PaymentMethodType type, Member member, Product product) { Validate.notNull(product, "product should not be null"); switch (type) { case PAYMENT_METHOD_DEPOSIT: { Validate.notNull(member, "member should not be null"); SaleDiscount discount = saleDiscountDAO.getDiscountByProduct(product, member.getMemberType()); return discount.getDiscountValue(); } default: return 1.0f; } } @Override public int GetProductBonusPoint(Product product, int count) { Validate.notNull(product, "product should not be null"); return product.getBonusePoint() * count; } @Override public int GetPackagePrice(ProductPackage pkg, int count) { Validate.notNull(pkg, "package should not be null"); return pkg.getUnitPrice() * count; } }