Rev 24245 | Rev 24268 | Go to most recent revision | View as "text/plain" | Blame | Compare with Previous | Last modification | View Log | RSS feed
package com.spice.profitmandi.service.scheme;import java.time.LocalDateTime;import java.util.ArrayList;import java.util.HashMap;import java.util.HashSet;import java.util.List;import java.util.Map;import java.util.Set;import java.util.stream.Collectors;import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.stereotype.Component;import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;import com.spice.profitmandi.common.model.CreateSchemeRequest;import com.spice.profitmandi.common.model.ProfitMandiConstants;import com.spice.profitmandi.common.model.SchemeModel;import com.spice.profitmandi.common.util.StringUtils;import com.spice.profitmandi.dao.entity.catalog.Item;import com.spice.profitmandi.dao.entity.catalog.RetailerScheme;import com.spice.profitmandi.dao.entity.catalog.Scheme;import com.spice.profitmandi.dao.entity.fofo.FofoLineItem;import com.spice.profitmandi.dao.entity.fofo.FofoOrder;import com.spice.profitmandi.dao.entity.fofo.FofoOrderItem;import com.spice.profitmandi.dao.entity.fofo.InventoryItem;import com.spice.profitmandi.dao.entity.fofo.Purchase;import com.spice.profitmandi.dao.entity.fofo.SchemeInOut;import com.spice.profitmandi.dao.entity.fofo.SchemeItem;import com.spice.profitmandi.dao.entity.transaction.Order;import com.spice.profitmandi.dao.enumuration.catalog.AmountType;import com.spice.profitmandi.dao.enumuration.catalog.SchemeType;import com.spice.profitmandi.dao.repository.catalog.ItemRepository;import com.spice.profitmandi.dao.repository.catalog.RetailerSchemeRepository;import com.spice.profitmandi.dao.repository.catalog.SchemeRepository;import com.spice.profitmandi.dao.repository.catalog.TagListingRepository;import com.spice.profitmandi.dao.repository.dtr.RetailerRepository;import com.spice.profitmandi.dao.repository.fofo.FofoLineItemRepository;import com.spice.profitmandi.dao.repository.fofo.FofoOrderItemRepository;import com.spice.profitmandi.dao.repository.fofo.FofoOrderRepository;import com.spice.profitmandi.dao.repository.fofo.InventoryItemRepository;import com.spice.profitmandi.dao.repository.fofo.PurchaseRepository;import com.spice.profitmandi.dao.repository.fofo.SchemeInOutRepository;import com.spice.profitmandi.dao.repository.fofo.SchemeItemRepository;import com.spice.profitmandi.dao.repository.transaction.OrderRepository;import com.spice.profitmandi.service.authentication.RoleManager;import com.spice.profitmandi.service.order.OrderService;import com.spice.profitmandi.service.wallet.WalletService;import in.shop2020.model.v1.catalog.ItemType;import in.shop2020.model.v1.order.WalletReferenceType;@Componentpublic class SchemeServiceImpl implements SchemeService {private static final Logger LOGGER = LogManager.getLogger(SchemeServiceImpl.class);@Autowired@Qualifier("fofoInventoryItemRepository")private InventoryItemRepository inventoryItemRepository;@Autowiredprivate OrderService orderService;@Autowiredprivate SchemeRepository schemeRepository;@Autowiredprivate RoleManager roleManager;@Autowiredprivate RetailerRepository retailerRepository;@Autowiredprivate TagListingRepository tagListingRepository;@Autowiredprivate RetailerSchemeRepository retailerSchemeRepository;@Autowiredprivate SchemeInOutRepository schemeInOutRepository;@Autowired@Qualifier("catalogItemRepository")private ItemRepository itemRepository;@Autowiredprivate SchemeItemRepository schemeItemRepository;@Autowiredprivate WalletService walletService;@Autowiredprivate FofoOrderItemRepository fofoOrderItemRepository;@Autowiredprivate FofoLineItemRepository fofoLineItemRepository;@Autowiredprivate PurchaseRepository purchaseRepository;@Autowiredprivate OrderRepository orderRepository;@Autowiredprivate FofoOrderRepository fofoOrderRepository;@Overridepublic void saveScheme(int creatorId, CreateSchemeRequest createSchemeRequest) throws ProfitMandiBusinessException {this.validateCreateSchemeRequest(createSchemeRequest);Scheme scheme = this.toScheme(creatorId, createSchemeRequest);if (scheme.getStartDateTime().isAfter(scheme.getEndDateTime())) {throw new ProfitMandiBusinessException(ProfitMandiConstants.START_DATE + ", " + ProfitMandiConstants.END_DATE,scheme.getStartDateTime() + ", " + scheme.getEndDateTime(), "SCHM_VE_1005");}this.validateItemIds(createSchemeRequest);schemeRepository.persist(scheme);if (!createSchemeRequest.isRetailerAll()) {this.validateRetailerIds(createSchemeRequest);for (int retailerId : createSchemeRequest.getRetailerIds()) {RetailerScheme retailerScheme = new RetailerScheme();retailerScheme.setRetailerId(retailerId);retailerScheme.setSchemeId(scheme.getId());retailerSchemeRepository.persist(retailerScheme);}}for (int itemId : createSchemeRequest.getItemIds()) {SchemeItem schemeItem = new SchemeItem();schemeItem.setSchemeId(scheme.getId());schemeItem.setItemId(itemId);schemeItemRepository.persist(schemeItem);}}private void validateCreateSchemeRequest(CreateSchemeRequest createSchemeRequest)throws ProfitMandiBusinessException {if (createSchemeRequest.getName() == null || createSchemeRequest.getName().isEmpty()) {throw new ProfitMandiBusinessException(ProfitMandiConstants.NAME, createSchemeRequest.getName(),"SCHM_VE_1000");}if (createSchemeRequest.getAmount() <= 0) {throw new ProfitMandiBusinessException(ProfitMandiConstants.AMOUNT, createSchemeRequest.getAmount(),"SCHM_VE_1001");}if (AmountType.valueOf(createSchemeRequest.getAmountType()) == AmountType.PERCENTAGE&& createSchemeRequest.getAmount() > 100) {throw new ProfitMandiBusinessException(ProfitMandiConstants.AMOUNT, createSchemeRequest.getAmount(),"SCHM_VE_1002");}if (createSchemeRequest.getStartDate() == null) {throw new ProfitMandiBusinessException(ProfitMandiConstants.START_DATE, createSchemeRequest.getStartDate(),"SCHM_VE_1003");}if (createSchemeRequest.getEndDate() == null) {throw new ProfitMandiBusinessException(ProfitMandiConstants.END_DATE, createSchemeRequest.getEndDate(),"SCHM_VE_1004");}}private Scheme toScheme(int creatorId, CreateSchemeRequest createSchemeRequest) {Scheme scheme = new Scheme();scheme.setName(createSchemeRequest.getName());scheme.setDescription(createSchemeRequest.getDescription());scheme.setType(SchemeType.valueOf(createSchemeRequest.getType()));scheme.setAmountType(AmountType.valueOf(createSchemeRequest.getAmountType()));scheme.setAmount(createSchemeRequest.getAmount());scheme.setStartDateTime(createSchemeRequest.getStartDate());scheme.setEndDateTime(createSchemeRequest.getEndDate());scheme.setCreatedBy(creatorId);scheme.setRetailerAll(createSchemeRequest.isRetailerAll());return scheme;}private void validateRetailerIds(CreateSchemeRequest createSchemeRequest) throws ProfitMandiBusinessException {if (createSchemeRequest.getRetailerIds() == null || createSchemeRequest.getRetailerIds().isEmpty()) {throw new ProfitMandiBusinessException(ProfitMandiConstants.RETAILER_ID,createSchemeRequest.getRetailerIds(), "SCHM_1001");}List<Integer> foundRetailerIds = retailerRepository.selectIdsByIds(createSchemeRequest.getRetailerIds());if (foundRetailerIds.size() != createSchemeRequest.getRetailerIds().size()) {createSchemeRequest.getRetailerIds().removeAll(foundRetailerIds);throw new ProfitMandiBusinessException(ProfitMandiConstants.RETAILER_ID,createSchemeRequest.getRetailerIds(), "SCHM_1002");}}private void validateItemIds(CreateSchemeRequest createSchemeRequest) throws ProfitMandiBusinessException {if (createSchemeRequest.getItemIds() == null || createSchemeRequest.getItemIds().isEmpty()) {throw new ProfitMandiBusinessException(ProfitMandiConstants.ITEM_ID, createSchemeRequest.getItemIds(),"SCHM_1003");}List<Integer> foundItemIds = itemRepository.selectIdsByIdsAndType(createSchemeRequest.getItemIds(),ItemType.SERIALIZED);if (foundItemIds.size() != createSchemeRequest.getItemIds().size()) {createSchemeRequest.getItemIds().removeAll(foundItemIds);throw new ProfitMandiBusinessException(ProfitMandiConstants.ITEM_ID, createSchemeRequest.getItemIds(),"SCHM_1004");}}@Overridepublic Scheme getSchemeById(int schemeId) throws ProfitMandiBusinessException {Scheme scheme = schemeRepository.selectById(schemeId);if (!scheme.isRetailerAll()) {List<Integer> retailerIds = retailerSchemeRepository.selectRetailerIdsBySchemeId(scheme.getId());scheme.getRetailerIds().addAll(retailerIds);}List<Integer> itemIds = schemeItemRepository.selectItemIdsBySchemeId(scheme.getId());if (itemIds.size() > 0) {List<Item> items = itemRepository.selectByIds(new HashSet<>(itemIds));scheme.setItemStringMap(this.toItemStringMap(items));}return scheme;}public Map<Integer, String> toItemStringMap(List<Item> items) {Map<Integer, String> itemMap = new HashMap<>();for (Item item : items) {itemMap.put(item.getId(), this.getItemString(item));}return itemMap;}public String getItemString(Item item) {StringBuilder itemString = new StringBuilder();if (item.getBrand() != null && !item.getBrand().isEmpty()) {itemString.append(item.getBrand().trim());}itemString.append(" ");if (item.getModelName() != null && !item.getModelName().isEmpty()) {itemString.append(item.getModelName().trim());}itemString.append(" ");if (item.getModelNumber() != null && !item.getModelNumber().isEmpty()) {itemString.append(item.getModelNumber().trim());}itemString.append(" ");if (item.getColor() != null && !item.getColor().isEmpty()) {itemString.append(item.getColor().trim());}return itemString.toString();}private Set<Integer> schemeItemsToItemIds(List<SchemeItem> schemeItems) {Set<Integer> itemIds = new HashSet<>();for (SchemeItem schemeItem : schemeItems) {itemIds.add(schemeItem.getItemId());}return itemIds;}@Overridepublic List<SchemeModel> getAllSchemeModels(LocalDateTime startDateTime, LocalDateTime endDateTime) {List<Scheme> schemes = schemeRepository.selectAllBetweenCreateTimestamp(startDateTime, endDateTime);Map<Integer, Scheme> schemeIdSchemeMap = this.toSchemeIdSchemeMap(schemes);List<SchemeItem> schemeItems = schemeItemRepository.selectBySchemeIds(schemeIdSchemeMap.keySet());Set<Integer> itemIds = this.schemeItemsToItemIds(schemeItems);List<Item> items = itemRepository.selectByIds(itemIds);Map<Integer, String> itemStringMap = this.toItemStringMap(items);this.addItemIdsToSchemes(schemeItems, schemeIdSchemeMap, itemStringMap);List<RetailerScheme> retailerSchemes = retailerSchemeRepository.selectBySchemeIds(schemeIdSchemeMap.keySet());this.addRetailerIdsToSchemes(retailerSchemes, schemeIdSchemeMap);return this.toSchemeModels(schemeIdSchemeMap);}private void addItemIdsToSchemes(List<SchemeItem> schemeItems, Map<Integer, Scheme> schemeIdSchemeMap,Map<Integer, String> itemStringMap) {for (SchemeItem schemeItem : schemeItems) {schemeIdSchemeMap.get(schemeItem.getSchemeId()).getItemStringMap().put(schemeItem.getItemId(),itemStringMap.get(schemeItem.getItemId()));}}private void addRetailerIdsToSchemes(List<RetailerScheme> retailerSchemes, Map<Integer, Scheme> schemeIdSchemeMap) {for (RetailerScheme retailerScheme : retailerSchemes) {schemeIdSchemeMap.get(retailerScheme.getSchemeId()).getRetailerIds().add(retailerScheme.getRetailerId());}}private List<SchemeModel> toSchemeModels(Map<Integer, Scheme> schemeIdSchemeMap) {List<SchemeModel> schemeModels = new ArrayList<>();for (Map.Entry<Integer, Scheme> schemeIdSchemeEntry : schemeIdSchemeMap.entrySet()) {schemeModels.add(this.toSchemeModel(schemeIdSchemeEntry.getValue()));}return schemeModels;}private SchemeModel toSchemeModel(Scheme scheme) {SchemeModel schemeModel = new SchemeModel();schemeModel.setSchemeId(scheme.getId());schemeModel.setName(scheme.getName());schemeModel.setDescription(scheme.getDescription());schemeModel.setSchemeType(scheme.getType().toString());schemeModel.setAmountType(scheme.getAmountType().toString());schemeModel.setAmount(scheme.getAmount());schemeModel.setStartDateTime(StringUtils.toString(scheme.getStartDateTime()));schemeModel.setEndDateTime(StringUtils.toString(scheme.getEndDateTime()));schemeModel.setCreateTimestamp(StringUtils.toString(scheme.getCreateTimestamp()));schemeModel.setActiveTimestamp(StringUtils.toString(scheme.getActiveTimestamp()));schemeModel.setExpireTimestamp(StringUtils.toString(scheme.getExpireTimestamp()));schemeModel.setCreatedBy(scheme.getCreatedBy());schemeModel.setItemStringMap(scheme.getItemStringMap());schemeModel.setRetailerIds(scheme.getRetailerIds());return schemeModel;}@Overridepublic void activeSchemeById(int schemeId) throws ProfitMandiBusinessException {Scheme scheme = schemeRepository.selectById(schemeId);if (scheme.getActiveTimestamp() != null) {throw new ProfitMandiBusinessException(ProfitMandiConstants.ACTIVE_TIMESTAMP, scheme.getActiveTimestamp(),"SCHM_1005");}if (scheme.getExpireTimestamp() != null) {throw new ProfitMandiBusinessException(ProfitMandiConstants.EXPIRE_TIMESTAMP, scheme.getExpireTimestamp(),"SCHM_1006");}scheme.setActiveTimestamp(LocalDateTime.now());schemeRepository.persist(scheme);if (scheme.getType() == SchemeType.IN) {this.processPreviousPurchases(scheme);} else if (scheme.getType() == SchemeType.OUT) {this.processPreviousSales(scheme);}}private void processPreviousPurchases(Scheme scheme) throws ProfitMandiBusinessException {List<InventoryItem> inventoryItems = inventoryItemRepository.selectBetweenDates(scheme.getStartDateTime(),scheme.getEndDateTime());if (inventoryItems.isEmpty()) {return;}List<Integer> itemIds = schemeItemRepository.selectItemIdsBySchemeId(scheme.getId());if (itemIds.isEmpty()) {return;}List<Item> items = itemRepository.selectByIds(new HashSet<>(itemIds));Map<Integer, String> itemStringMap = this.toItemStringMap(items);List<InventoryItem> completedInventoryItems = this.toFilteredPurchaseCompletedInventoryItems(inventoryItems,itemIds, true);if (completedInventoryItems.isEmpty()) {return;}if (scheme.isRetailerAll()) {for (InventoryItem inventoryItem : completedInventoryItems) {float cashback = this.createSchemeInOut(scheme, inventoryItem);walletService.addAmountToWallet(inventoryItem.getFofoId(), inventoryItem.getPurchaseId(),WalletReferenceType.SCHEME_IN,"Added SCHEME_IN for item " + itemStringMap.get(inventoryItem.getItemId())+ " against invoiceNumber " + inventoryItem.getPurchase().getPurchaseReference(),cashback);}} else {List<Integer> retailerIds = retailerSchemeRepository.selectRetailerIdsBySchemeId(scheme.getId());for (InventoryItem inventoryItem : completedInventoryItems) {if (retailerIds.contains(inventoryItem.getFofoId())) {float cashback = this.createSchemeInOut(scheme, inventoryItem);walletService.addAmountToWallet(inventoryItem.getFofoId(), inventoryItem.getPurchaseId(),WalletReferenceType.SCHEME_IN,"Added SCHEME_IN for item " + itemStringMap.get(inventoryItem.getItemId())+ " against invoiceNumber " + inventoryItem.getPurchase().getPurchaseReference(),cashback);}}}}private Map<Integer, Integer> toInventoryItemIdFofoOrderIdMap(List<FofoLineItem> fofoLineItems,Map<Integer, FofoOrderItem> fofoOrderItemIdFofoOrderItemMap) {Map<Integer, Integer> inventoryItemIdFofoOrderIdMap = new HashMap<>();for (FofoLineItem fofoLineItem : fofoLineItems) {inventoryItemIdFofoOrderIdMap.put(fofoLineItem.getInventoryItemId(),fofoOrderItemIdFofoOrderItemMap.get(fofoLineItem.getFofoOrderItemId()).getOrderId());}return inventoryItemIdFofoOrderIdMap;}private void processPreviousSales(Scheme scheme) throws ProfitMandiBusinessException {List<FofoOrderItem> fofoOrderItems = fofoOrderItemRepository.selectBetweenDates(scheme.getStartDateTime(),scheme.getEndDateTime());if (fofoOrderItems.isEmpty()) {return;}Map<Integer, FofoOrderItem> fofoOrderItemIdFofoOrderItemMap = this.toFofoOrderItemIdFofoOrderItemMap(fofoOrderItems);List<FofoLineItem> fofoLineItems = fofoLineItemRepository.selectByFofoOrderItemIds(fofoOrderItemIdFofoOrderItemMap.keySet());if (fofoLineItems.isEmpty()) {return;}Map<Integer, Integer> inventoryItemIdFofoOrderIdMap = this.toInventoryItemIdFofoOrderIdMap(fofoLineItems,fofoOrderItemIdFofoOrderItemMap);List<InventoryItem> inventoryItems = inventoryItemRepository.selectByIds(inventoryItemIdFofoOrderIdMap.keySet());if (inventoryItems.isEmpty()) {return;}List<Integer> itemIds = schemeItemRepository.selectItemIdsBySchemeId(scheme.getId());if (itemIds.isEmpty()) {return;}List<InventoryItem> completedInventoryItems = this.toFilteredPurchaseCompletedInventoryItems(inventoryItems,itemIds, false);if (scheme.isRetailerAll()) {for (InventoryItem inventoryItem : completedInventoryItems) {float cashback = this.createSchemeInOut(scheme, inventoryItem);walletService.addAmountToWallet(inventoryItem.getFofoId(), inventoryItem.getPurchaseId(),WalletReferenceType.SCHEME_OUT, "Added for SCHEME_OUT", cashback);}} else {List<Integer> retailerIds = retailerSchemeRepository.selectRetailerIdsBySchemeId(scheme.getId());for (InventoryItem inventoryItem : completedInventoryItems) {if (retailerIds.contains(inventoryItem.getFofoId())) {float cashback = this.createSchemeInOut(scheme, inventoryItem);walletService.addAmountToWallet(inventoryItem.getFofoId(),inventoryItemIdFofoOrderIdMap.get(inventoryItem.getId()), WalletReferenceType.SCHEME_OUT,"Added for SCHEME_OUT", cashback);}}}}private Map<Integer, FofoOrderItem> toFofoOrderItemIdFofoOrderItemMap(List<FofoOrderItem> fofoOrderItems) {Map<Integer, FofoOrderItem> fofoOrderItemIdFofoOrderItemMap = new HashMap<>();for (FofoOrderItem fofoOrderItem : fofoOrderItems) {fofoOrderItemIdFofoOrderItemMap.put(fofoOrderItem.getId(), fofoOrderItem);}return fofoOrderItemIdFofoOrderItemMap;}private List<InventoryItem> toFilteredPurchaseCompletedInventoryItems(List<InventoryItem> inventoryItems,List<Integer> itemIds, boolean purchase) {List<InventoryItem> completedInventoryItems = new ArrayList<>();for (InventoryItem inventoryItem : inventoryItems) {if (purchase && inventoryItem.getPurchase().getCompleteTimestamp() != null&& itemIds.contains(inventoryItem.getItemId())) {completedInventoryItems.add(inventoryItem);} else if (!purchase && itemIds.contains(inventoryItem.getItemId())) {completedInventoryItems.add(inventoryItem);}}return completedInventoryItems;}@Overridepublic void expireSchemeById(int schemeId) throws ProfitMandiBusinessException {Scheme scheme = schemeRepository.selectById(schemeId);if (scheme.getActiveTimestamp() == null) {throw new ProfitMandiBusinessException(ProfitMandiConstants.ACTIVE_TIMESTAMP, scheme.getActiveTimestamp(),"SCHM_1007");}if (scheme.getExpireTimestamp() != null) {throw new ProfitMandiBusinessException(ProfitMandiConstants.EXPIRE_TIMESTAMP, scheme.getExpireTimestamp(),"SCHM_1008");}scheme.setExpireTimestamp(LocalDateTime.now());schemeRepository.persist(scheme);}private Map<Integer, Scheme> toSchemeIdSchemeMap(List<Scheme> schemes) {Map<Integer, Scheme> schemeIdSchemeMap = new HashMap<>();for (Scheme scheme : schemes) {schemeIdSchemeMap.put(scheme.getId(), scheme);}return schemeIdSchemeMap;}private Set<Integer> inventoryItemSchemesMapToSchemeIds(Map<InventoryItem, Set<Scheme>> inventoryItemSchemesMap) {Set<Integer> schemeIds = new HashSet<>();for (Map.Entry<InventoryItem, Set<Scheme>> inventoryItemSchemesEntry : inventoryItemSchemesMap.entrySet()) {for (Scheme scheme : inventoryItemSchemesEntry.getValue()) {schemeIds.add(scheme.getId());}}return schemeIds;}private Set<Integer> fofoLineItemSchemesMapToSchemeIds(Map<FofoOrderItem, Set<Scheme>> fofoLineItemSchemesMap) {Set<Integer> schemeIds = new HashSet<>();for (Map.Entry<FofoOrderItem, Set<Scheme>> inventoryItemSchemesEntry : fofoLineItemSchemesMap.entrySet()) {for (Scheme scheme : inventoryItemSchemesEntry.getValue()) {schemeIds.add(scheme.getId());}}return schemeIds;}private Set<Integer> inventoryItemsToItemIds(List<InventoryItem> inventoryItems) {Set<Integer> itemIds = new HashSet<>();for (InventoryItem inventoryItem : inventoryItems) {itemIds.add(inventoryItem.getItemId());}return itemIds;}private Set<Integer> fofoOrderItemsToItemIds(List<FofoOrderItem> fofoOrderItems) {Set<Integer> itemIds = new HashSet<>();for (FofoOrderItem fofoOrderItem : fofoOrderItems) {itemIds.add(fofoOrderItem.getItemId());}return itemIds;}private Map<Integer, Set<Scheme>> toItemIdSchemesMap(List<SchemeItem> schemeItems, List<Scheme> schemes) {Map<Integer, Scheme> schemeIdSchemesMap = this.toSchemeIdSchemeMap(schemes);Map<Integer, Set<Scheme>> itemIdSchemesMap = new HashMap<>();for (SchemeItem schemeItem : schemeItems) {if (!itemIdSchemesMap.containsKey(schemeItem.getItemId())) {Set<Scheme> schemesSet = new HashSet<>();schemesSet.add(schemeIdSchemesMap.get(schemeItem.getSchemeId()));itemIdSchemesMap.put(schemeItem.getItemId(), schemesSet);} else {itemIdSchemesMap.get(schemeItem.getItemId()).add(schemeIdSchemesMap.get(schemeItem.getSchemeId()));}}return itemIdSchemesMap;}private Map<InventoryItem, Set<Scheme>> toInventoryItemSchemesMap(List<Scheme> schemes,List<InventoryItem> inventoryItems) {Set<Integer> schemeIds = new HashSet<>();for (Scheme scheme : schemes) {schemeIds.add(scheme.getId());}Set<Integer> itemIds = this.inventoryItemsToItemIds(inventoryItems);List<SchemeItem> schemeItems = schemeItemRepository.selectBySchemeIdsAndItemIds(schemeIds, itemIds);Map<Integer, Set<Scheme>> itemIdSchemesMap = this.toItemIdSchemesMap(schemeItems, schemes);Map<InventoryItem, Set<Scheme>> inventoryItemSchemsMap = new HashMap<>();for (InventoryItem inventoryItem : inventoryItems) {if (itemIdSchemesMap.containsKey(inventoryItem.getItemId())) {inventoryItemSchemsMap.put(inventoryItem, itemIdSchemesMap.get(inventoryItem.getItemId()));}}return inventoryItemSchemsMap;}private Map<FofoOrderItem, Set<Scheme>> toFofoOrderItemSchemesMap(List<Scheme> schemes,List<FofoOrderItem> fofoOrderItems) {Set<Integer> schemeIds = new HashSet<>();for (Scheme scheme : schemes) {schemeIds.add(scheme.getId());}Set<Integer> itemIds = this.fofoOrderItemsToItemIds(fofoOrderItems);List<SchemeItem> schemeItems = schemeItemRepository.selectBySchemeIdsAndItemIds(schemeIds, itemIds);Map<FofoOrderItem, Set<Scheme>> fofoOrderItemSchemsMap = new HashMap<>();if (!schemeItems.isEmpty()) {Map<Integer, Set<Scheme>> itemIdSchemesMap = this.toItemIdSchemesMap(schemeItems, schemes);for (FofoOrderItem fofoOrderItem : fofoOrderItems) {if (itemIdSchemesMap.containsKey(fofoOrderItem.getItemId())) {fofoOrderItemSchemsMap.put(fofoOrderItem, itemIdSchemesMap.get(fofoOrderItem.getItemId()));}}}return fofoOrderItemSchemsMap;}@Overridepublic void processSchemeIn(int purchaseId, int retailerId) throws ProfitMandiBusinessException {LOGGER.info("Trying to process SchemeIn with purchaseId [{}] and retailerId [{}]", purchaseId, retailerId);Purchase purchase = purchaseRepository.selectByIdAndFofoId(purchaseId, retailerId);LOGGER.info("purchase is completed = {}", (purchase.getCompleteTimestamp() != null));if (purchase.getCompleteTimestamp() != null) {List<Order> orders = orderRepository.selectByAirwayBillOrInvoiceNumber(purchase.getPurchaseReference(),retailerId);LocalDateTime billingTimestamp = purchase.getCreateTimestamp();if (!orders.isEmpty()) {billingTimestamp = orders.get(0).getBillingTimestamp();}List<Scheme> schemes = schemeRepository.selectActiveAll(SchemeType.IN, billingTimestamp);float totalCashback = 0;if (schemes.isEmpty()) {return;}List<InventoryItem> inventoryItems = inventoryItemRepository.selectByPurchaseId(purchaseId);Map<InventoryItem, Set<Scheme>> inventoryItemSchemesMap = this.toInventoryItemSchemesMap(schemes,inventoryItems);if (inventoryItemSchemesMap.isEmpty()) {return;}Map<InventoryItem, Set<Scheme>> notAllInventoryItemSchemesMap = new HashMap<>();Map<InventoryItem, Set<Scheme>> allInventoryItemSchemesMap = new HashMap<>();Set<Integer> itemIds = new HashSet<>();for (Map.Entry<InventoryItem, Set<Scheme>> inventoryItemSchemesEntry : inventoryItemSchemesMap.entrySet()) {Set<Scheme> notAllSchemes = new HashSet<>();Set<Scheme> allSchemes = new HashSet<>();for (Scheme scheme : inventoryItemSchemesEntry.getValue()) {if (!scheme.isRetailerAll()) {notAllSchemes.add(scheme);} else {allSchemes.add(scheme);}}notAllInventoryItemSchemesMap.put(inventoryItemSchemesEntry.getKey(), notAllSchemes);allInventoryItemSchemesMap.put(inventoryItemSchemesEntry.getKey(), allSchemes);itemIds.add(inventoryItemSchemesEntry.getKey().getItemId());}int itemsCount = 0;for (Map.Entry<InventoryItem, Set<Scheme>> allInventoryItemSchemesEntry : allInventoryItemSchemesMap.entrySet()) {float inventoryItemCashback = 0;for (Scheme scheme : allInventoryItemSchemesEntry.getValue()) {InventoryItem inventoryItem = allInventoryItemSchemesEntry.getKey();float cashback = this.createSchemeInOut(scheme, inventoryItem);inventoryItemCashback += cashback;}if (inventoryItemCashback > 0) {totalCashback += inventoryItemCashback;itemsCount++;}}Set<Integer> schemeIds = this.inventoryItemSchemesMapToSchemeIds(notAllInventoryItemSchemesMap);if (!schemeIds.isEmpty()) {List<Integer> foundSchemeIds = retailerSchemeRepository.selectSchemeIds(schemeIds, retailerId);for (Map.Entry<InventoryItem, Set<Scheme>> notAllInventoryItemSchemesEntry : notAllInventoryItemSchemesMap.entrySet()) {float inventoryItemCashback = 0;for (Scheme scheme : notAllInventoryItemSchemesEntry.getValue()) {if (foundSchemeIds.contains(scheme.getId())) {InventoryItem inventoryItem = notAllInventoryItemSchemesEntry.getKey();float cashback = this.createSchemeInOut(scheme, inventoryItem);inventoryItemCashback += cashback;}}if (inventoryItemCashback > 0) {totalCashback += inventoryItemCashback;itemsCount++;}}}LOGGER.info("Items count for purchase id {} is {}", purchaseId, itemsCount);if (itemsCount > 0) {walletService.addAmountToWallet(retailerId, purchaseId, WalletReferenceType.SCHEME_IN,"Added for SCHEME IN against invoice " + purchase.getPurchaseReference() + " (total "+ itemsCount + " pcs)",totalCashback);LOGGER.info("Added Rs.{} for SCHEME IN against invoice {} total pcs({}) {}", totalCashback,purchase.getPurchaseReference(), itemsCount);purchase.setCashback(purchase.getCashback() + totalCashback);purchaseRepository.persist(purchase);}}}private float createSchemeInOut(Scheme scheme, InventoryItem inventoryItem) {SchemeInOut schemeInOut = schemeInOutRepository.selectByScheme(scheme.getId(), inventoryItem.getId());float amount = 0;if (schemeInOut == null) {schemeInOut = new SchemeInOut();amount = this.getAmount(inventoryItem, scheme);schemeInOut.setSchemeId(scheme.getId());schemeInOut.setInventoryItemId(inventoryItem.getId());schemeInOut.setAmount(amount);schemeInOutRepository.persist(schemeInOut);}return amount;}private float getAmount(InventoryItem inventoryItem, Scheme scheme) {float amount = 0;float totalTaxRate = inventoryItem.getIgstRate() + inventoryItem.getSgstRate() + inventoryItem.getCgstRate();if (scheme.getAmountType() == AmountType.PERCENTAGE) {if(scheme.getType().equals(SchemeType.IN)) {amount = inventoryItem.getUnitPrice() - inventoryItem.getPriceDropAmount();} else {try {amount = tagListingRepository.selectByItemId(inventoryItem.getItemId()).getSellingPrice();} catch(Exception e) {LOGGER.info("Could not find tag Listing entry in {}", inventoryItem.getItemId());e.printStackTrace();}}float taxableSellingPrice = amount / (1 + totalTaxRate / 100);amount = taxableSellingPrice * scheme.getAmount() / 100;} else {amount = scheme.getAmount();}return amount;}private Map<Integer, InventoryItem> toInventoryItemIdInventoryItemMap(List<InventoryItem> inventoryItems) {Map<Integer, InventoryItem> itemIdInventoryItemMap = new HashMap<>();for (InventoryItem inventoryItem : inventoryItems) {itemIdInventoryItemMap.put(inventoryItem.getId(), inventoryItem);}return itemIdInventoryItemMap;}private Set<Integer> toInventoryItemIds(Set<FofoOrderItem> fofoOrderItems) {Set<Integer> inventoryItemIds = new HashSet<>();// Map<Integer, Set<FofoLineItem>> fofoOrderItemIdFofoLineItemsMap =// this.toFofoOrderItemIdFofoLineItems(fofoOrderItems);for (FofoOrderItem fofoOrderItem : fofoOrderItems) {for (FofoLineItem fofoLineItem : fofoOrderItem.getFofoLineItems()) {inventoryItemIds.add(fofoLineItem.getInventoryItemId());}}return inventoryItemIds;}@Overridepublic void processSchemeOut(int fofoOrderId, int retailerId) throws ProfitMandiBusinessException {FofoOrder fofoOrder = fofoOrderRepository.selectByFofoIdAndOrderId(retailerId, fofoOrderId);List<Scheme> schemes = schemeRepository.selectActiveAll(SchemeType.OUT, fofoOrder.getCreateTimestamp());LOGGER.info("Active Schemes {}", schemes);float totalCashback = 0;int count = 0;if (schemes.isEmpty()) {return;}List<FofoOrderItem> fofoOrderItems = orderService.getByOrderId(fofoOrderId);// LOGGER.info("fofoOrderItems {}", fofoOrderItems);Map<FofoOrderItem, Set<Scheme>> fofoOrderItemSchemesMap = this.toFofoOrderItemSchemesMap(schemes,fofoOrderItems);LOGGER.info("fofoOrderItemSchemesMap {}", fofoOrderItemSchemesMap);if (fofoOrderItemSchemesMap.isEmpty()) {return;}Set<Integer> inventoryItemIds = this.toInventoryItemIds(fofoOrderItemSchemesMap.keySet());List<InventoryItem> inventoryItems = inventoryItemRepository.selectByIds(inventoryItemIds);Map<Integer, InventoryItem> inventoryItemIdInventoryItemMap = this.toInventoryItemIdInventoryItemMap(inventoryItems);Map<FofoOrderItem, Set<Scheme>> notAllFofoOrderItemSchemesMap = new HashMap<>();Map<FofoOrderItem, Set<Scheme>> allFofoOrderItemSchemesMap = new HashMap<>();for (Map.Entry<FofoOrderItem, Set<Scheme>> fofoOrderItemSchemesEntry : fofoOrderItemSchemesMap.entrySet()) {Set<Scheme> notAllSchemes = new HashSet<>();Set<Scheme> allSchemes = new HashSet<>();for (Scheme scheme : fofoOrderItemSchemesEntry.getValue()) {if (!scheme.isRetailerAll()) {notAllSchemes.add(scheme);} else {allSchemes.add(scheme);}}notAllFofoOrderItemSchemesMap.put(fofoOrderItemSchemesEntry.getKey(), notAllSchemes);allFofoOrderItemSchemesMap.put(fofoOrderItemSchemesEntry.getKey(), allSchemes);}for (Map.Entry<FofoOrderItem, Set<Scheme>> allFofoOrderItemSchemesEntry : allFofoOrderItemSchemesMap.entrySet()) {for (FofoLineItem fofoLineItem : allFofoOrderItemSchemesEntry.getKey().getFofoLineItems()) {float itemCashback = 0;for (Scheme scheme : allFofoOrderItemSchemesEntry.getValue()) {itemCashback += this.createSchemeInOut(scheme,inventoryItemIdInventoryItemMap.get(fofoLineItem.getInventoryItemId()));}if (itemCashback > 0) {totalCashback += itemCashback;count += 1;}}}Set<Integer> schemeIds = this.fofoLineItemSchemesMapToSchemeIds(notAllFofoOrderItemSchemesMap);if (!schemeIds.isEmpty()) {List<Integer> foundSchemeIds = retailerSchemeRepository.selectSchemeIds(schemeIds, retailerId);for (Map.Entry<FofoOrderItem, Set<Scheme>> notAllFofoOrderItemSchemesEntry : notAllFofoOrderItemSchemesMap.entrySet()) {for (FofoLineItem fofoLineItem : notAllFofoOrderItemSchemesEntry.getKey().getFofoLineItems()) {float itemCashback = 0;for (Scheme scheme : notAllFofoOrderItemSchemesEntry.getValue()) {if (foundSchemeIds.contains(scheme.getId())) {itemCashback += this.createSchemeInOut(scheme,inventoryItemIdInventoryItemMap.get(fofoLineItem.getInventoryItemId()));}}if (itemCashback > 0) {totalCashback += itemCashback;count += 1;}}}}if (totalCashback > 0) {walletService.addAmountToWallet(retailerId, fofoOrderId, WalletReferenceType.SCHEME_OUT,"Sales margin for invoice number " + fofoOrder.getInvoiceNumber() + ". Total " + count + " pc(s)",totalCashback);fofoOrder.setCashback(totalCashback);fofoOrderRepository.persist(fofoOrder);}}@Overridepublic void rollbackSchemes(List<Integer> inventoryItemIds, int rollbackReference, String rollbackReason)throws Exception {Set<Integer> inventoryItemIdSet = new HashSet<>(inventoryItemIds);float amountToRollback = 0;List<SchemeInOut> schemes = schemeInOutRepository.selectByInventoryItemIds(inventoryItemIdSet);for (SchemeInOut schemeInOut : schemes) {if (schemeInOut.getRolledBackTimestamp() == null) {schemeInOut.setRolledBackTimestamp(LocalDateTime.now());schemeInOutRepository.persist(schemeInOut);amountToRollback += schemeInOut.getAmount();}}if (amountToRollback > 0) {int inventoryItemId = inventoryItemIds.get(0);Integer fofoId = inventoryItemRepository.selectById(inventoryItemId).getFofoId();walletService.rollbackAmountFromWallet(fofoId, amountToRollback, rollbackReference,WalletReferenceType.SCHEME_IN, rollbackReason);}}@Overridepublic Map<String, Object> getSchemes(Set<Integer> roleIds, int offset, int limit)throws ProfitMandiBusinessException {Map<String, Object> map = new HashMap<>();List<Scheme> schemes = null;long size = 0;if (roleManager.isAdmin(roleIds)) {schemes = schemeRepository.selectAll(offset, limit);size = schemeRepository.selectAllCount();} else {schemes = schemeRepository.selectActiveAll(offset, limit);size = schemeRepository.selectAllActiveCount();}map.put("schemes", schemes);map.put("start", offset + 1);map.put("size", size);if (schemes.size() < limit) {map.put("end", offset + schemes.size());} else {map.put("end", offset + limit);}return map;}@Overridepublic List<Scheme> getPaginatedSchemes(Set<Integer> roleIds, int offset, int limit)throws ProfitMandiBusinessException {LOGGER.info("requested offset=[{}], limit = [{}]", offset, limit);List<Scheme> schemes = null;if (roleManager.isAdmin(roleIds)) {schemes = schemeRepository.selectAll(offset, limit);} else {schemes = schemeRepository.selectActiveAll(offset, limit);}return schemes;}@Overridepublic void reverseSchemes(List<InventoryItem> inventoryItems, int reversalReference, String reversalReason)throws Exception {float amountToCredit = 0;float amountToDebit = 0;Map<Integer, InventoryItem> inventoryItemsMap = inventoryItems.stream().collect(Collectors.toMap(x -> x.getId(), x -> x));List<SchemeInOut> schemeInOuts = schemeInOutRepository.selectByInventoryItemIds(inventoryItemsMap.keySet());List<Integer> schemeIds = schemeInOuts.stream().map(x -> x.getSchemeId()).collect(Collectors.toList());Map<Integer, Scheme> schemesMap = schemeRepository.selectBySchemeIds(schemeIds, 0, schemeIds.size()).stream().collect(Collectors.toMap(x -> x.getId(), x -> x));for (SchemeInOut schemeInOut : schemeInOuts) {InventoryItem ii = inventoryItemsMap.get(schemeInOut.getInventoryItemId());Scheme scheme = schemesMap.get(schemeInOut.getSchemeId());if (scheme.getAmountType().equals(AmountType.FIXED)) {continue;}if(schemeInOut.getRolledBackTimestamp() == null) {float newAmount = getAmount(ii, scheme);if(schemeInOut.getAmount() - newAmount >= 0.01f) {schemeInOut.setRolledBackTimestamp(LocalDateTime.now());schemeInOutRepository.persist(schemeInOut);SchemeInOut sioNew = new SchemeInOut();sioNew.setAmount(newAmount);sioNew.setInventoryItemId(schemeInOut.getInventoryItemId());sioNew.setSchemeId(schemeInOut.getSchemeId());schemeInOutRepository.persist(sioNew);amountToCredit += sioNew.getAmount();amountToDebit += schemeInOut.getAmount();}}}int fofoId = inventoryItems.get(0).getFofoId();if (amountToDebit > 0) {walletService.addAmountToWallet(fofoId, reversalReference, WalletReferenceType.PRICE_DROP, reversalReason,-amountToDebit);}if (amountToCredit > 0) {walletService.addAmountToWallet(fofoId, reversalReference, WalletReferenceType.PRICE_DROP, reversalReason,amountToCredit);}}@Overridepublic void reverseSchemes(List<InventoryItem> inventoryItems, int reversalReference, String reversalReason, SchemeType schemeType) throws ProfitMandiBusinessException{Map<Integer, InventoryItem> inventoryItemsMap = inventoryItems.stream().collect(Collectors.toMap(x -> x.getId(), x -> x));List<SchemeInOut> schemeInOuts = schemeInOutRepository.selectByInventoryItemIds(inventoryItemsMap.keySet());List<Integer> schemeIds = schemeInOuts.stream().map(x -> x.getSchemeId()).collect(Collectors.toList());float amount = 0;Map<Integer, Scheme> schemesMap = schemeRepository.selectBySchemeIds(schemeIds, 0, schemeIds.size()).stream().collect(Collectors.toMap(x -> x.getId(), x -> x));for (SchemeInOut schemeInOut : schemeInOuts) {Scheme scheme = schemesMap.get(schemeInOut.getSchemeId());if(scheme.getType().equals(schemeType)) {if(schemeInOut.getRolledBackTimestamp() == null) {schemeInOut.setRolledBackTimestamp(LocalDateTime.now());schemeInOutRepository.persist(schemeInOut);amount += schemeInOut.getAmount();}}}int fofoId = inventoryItems.get(0).getFofoId();WalletReferenceType walletReferenceType = schemeType.equals(SchemeType.OUT)?WalletReferenceType.SCHEME_OUT:WalletReferenceType.SCHEME_IN;walletService.rollbackAmountFromWallet(fofoId, amount, reversalReference, walletReferenceType, reversalReason);}}