Rev 35034 | Rev 35097 | Go to most recent revision | View as "text/plain" | Blame | Compare with Previous | Last modification | View Log | RSS feed
package com.spice.profitmandi.service.order;import com.spice.profitmandi.common.enumuration.ItemType;import com.spice.profitmandi.common.enumuration.SearchType;import com.spice.profitmandi.common.enumuration.UpgradeOfferPaymentStatus;import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;import com.spice.profitmandi.common.model.*;import com.spice.profitmandi.common.util.FormattingUtils;import com.spice.profitmandi.common.util.StringUtils;import com.spice.profitmandi.common.util.Utils;import com.spice.profitmandi.common.web.client.RestClient;import com.spice.profitmandi.dao.cart.SmartCartService;import com.spice.profitmandi.dao.entity.catalog.Item;import com.spice.profitmandi.dao.entity.catalog.TagListing;import com.spice.profitmandi.dao.entity.catalog.UpgradeOffer;import com.spice.profitmandi.dao.entity.dtr.*;import com.spice.profitmandi.dao.entity.fofo.*;import com.spice.profitmandi.dao.entity.inventory.State;import com.spice.profitmandi.dao.entity.transaction.Order;import com.spice.profitmandi.dao.entity.user.Address;import com.spice.profitmandi.dao.entity.user.Counter;import com.spice.profitmandi.dao.entity.user.PrivateDealUser;import com.spice.profitmandi.dao.entity.warehouse.WarehouseInventoryItem;import com.spice.profitmandi.dao.enumuration.catalog.SchemeType;import com.spice.profitmandi.dao.enumuration.dtr.PaymentOptionReferenceType;import com.spice.profitmandi.dao.enumuration.fofo.ReturnType;import com.spice.profitmandi.dao.enumuration.fofo.ScanType;import com.spice.profitmandi.dao.enumuration.fofo.SettlementType;import com.spice.profitmandi.dao.enumuration.inventory.ScratchedGift;import com.spice.profitmandi.dao.enumuration.transaction.OrderStatus;import com.spice.profitmandi.dao.repository.catalog.*;import com.spice.profitmandi.dao.repository.dtr.*;import com.spice.profitmandi.dao.repository.fofo.*;import com.spice.profitmandi.dao.repository.inventory.StateRepository;import com.spice.profitmandi.dao.repository.transaction.OrderRepository;import com.spice.profitmandi.dao.repository.user.AddressRepository;import com.spice.profitmandi.dao.repository.user.CounterRepository;import com.spice.profitmandi.dao.repository.user.PrivateDealUserRepository;import com.spice.profitmandi.dao.repository.warehouse.WarehouseInventoryItemRepository;import com.spice.profitmandi.service.integrations.bharti.model.PlanVariant;import com.spice.profitmandi.service.integrations.zest.InsuranceService;import com.spice.profitmandi.service.integrations.zest.MobileInsurancePlan;import com.spice.profitmandi.service.inventory.InventoryService;import com.spice.profitmandi.service.inventory.PurchaseReturnService;import com.spice.profitmandi.service.inventory.SaholicInventoryService;import com.spice.profitmandi.service.offers.ItemCriteria;import com.spice.profitmandi.service.pricing.PricingService;import com.spice.profitmandi.service.scheme.SchemeService;import com.spice.profitmandi.service.user.RetailerService;import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.json.JSONObject;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.beans.factory.annotation.Value;import org.springframework.cache.annotation.Cacheable;import org.springframework.core.io.InputStreamResource;import org.springframework.http.HttpHeaders;import org.springframework.http.HttpStatus;import org.springframework.http.ResponseEntity;import org.springframework.stereotype.Component;import javax.persistence.criteria.CriteriaBuilder;import javax.persistence.criteria.CriteriaQuery;import javax.persistence.criteria.Predicate;import javax.persistence.criteria.Root;import java.io.ByteArrayInputStream;import java.io.InputStream;import java.time.LocalDate;import java.time.LocalDateTime;import java.time.LocalTime;import java.util.AbstractMap.SimpleEntry;import java.util.*;import java.util.function.Function;import java.util.stream.Collectors;@Componentpublic class OrderServiceImpl implements OrderService {private static final Logger LOGGER = LogManager.getLogger(OrderServiceImpl.class);private static Map<String, Integer> serialNumberOrderIdMap = new HashMap<>();static {serialNumberOrderIdMap.put("862897055749275", 67228);}@Autowired@Qualifier("fofoInventoryItemRepository")private InventoryItemRepository inventoryItemRepository;@Autowiredprivate StateGstRateRepository stateGstRateRepository;@Autowiredprivate SaholicInventoryService saholicInventoryService;@Autowiredprivate LiveDemoBillingRespository liveDemoBillingRespository;@Autowiredprivate InsuranceService insuranceService;@Autowired@Qualifier("fofoCurrentInventorySnapshotRepository")private CurrentInventorySnapshotRepository currentInventorySnapshotRepository;@Autowiredprivate InvoiceNumberGenerationSequenceRepository invoiceNumberGenerationSequenceRepository;@Autowiredprivate PurchaseReturnService purchaseReturnService;@Autowiredprivate RetailerService retailerService;@Autowiredprivate CustomerRepository customerRepository;@Autowiredprivate PurchaseReturnItemRepository purchaseReturnItemRepository;@Autowiredprivate AddressRepository addressRepository;@Autowiredprivate FofoLineItemRepository fofoLineItemRepository;@Autowiredprivate FofoNonSerializeSerialRepository fofoNonSerializeSerialRepository;@Autowiredprivate WarehouseInventoryItemRepository warehouseInventoryItemRepository;@Autowiredprivate FofoOrderItemRepository fofoOrderItemRepository;@Autowiredprivate PaymentOptionRepository paymentOptionRepository;@Autowiredprivate CustomerReturnItemRepository customerReturnItemRepository;@Autowired@Qualifier("fofoScanRecordRepository")private ScanRecordRepository scanRecordRepository;@Autowiredprivate FofoOrderRepository fofoOrderRepository;@Autowiredprivate RetailerRepository retailerRepository;@Autowiredprivate UserRepository userRepository;@Autowiredprivate UserAccountRepository userAccountRepository;@Autowiredprivate RetailerRegisteredAddressRepository retailerRegisteredAddressRepository;@Autowiredprivate CustomerAddressRepository customerAddressRepository;@Autowired@Qualifier("catalogItemRepository")private ItemRepository itemRepository;@Autowiredprivate InsuranceProviderRepository insuranceProviderRepository;@Autowiredprivate InsurancePolicyRepository insurancePolicyRepository;@Autowiredprivate StateRepository stateRepository;@Autowiredprivate PolicyNumberGenerationSequenceRepository policyNumberGenerationSequenceRepository;@Autowiredprivate PricingService pricingService;@Autowiredprivate PrivateDealUserRepository privateDealUserRepository;@Autowiredprivate TagListingRepository tagListingRepository;@Autowiredprivate CounterRepository counterRepository;@Autowiredprivate FofoStoreRepository fofoStoreRepository;@Autowiredprivate PaymentOptionTransactionRepository paymentOptionTransactionRepository;@Autowiredprivate SchemeService schemeService;private static final List<Integer> orderIdsConsumed = new ArrayList<>();@Autowired@Qualifier("fofoInventoryService")private InventoryService inventoryService;@Autowiredprivate CustomerCreditNoteRepository customerCreditNoteRepository;@Autowiredprivate OrderRepository orderRepository;@Autowiredprivate HygieneDataRepository hygieneDataRepository;@Autowiredprivate SessionFactory sessionFactory;@Autowiredprivate Mongo mongoClient;@Autowiredprivate PendingOrderRepository pendingOrderRepository;@Autowiredprivate PendingOrderService pendingOrderService;@Autowiredprivate PendingOrderItemRepository pendingOrderItemRepository;@Autowiredprivate ScratchOfferRepository scratchOfferRepository;@AutowiredRestClient restClient;@AutowiredUpSaleOrderRepository upSaleOrderRepository;@Autowiredprivate CustomerOfferRepository customerOfferRepository;@Autowiredprivate CustomerOfferItemRepository customerOfferItemRepository;@Autowiredprivate UpgradeOfferRepository upgradeOfferRepository;@Autowiredprivate SmartCartService smartCartService;@Autowiredprivate PartnerTypeChangeService partnerTypeChangeService;@Value("${prod}")private boolean prodEnv;private static final String SMS_GATEWAY = "http://api.pinnacle.in/index.php/sms/send";private static final String SENDER = "SMTDKN";public static final String APP_DOWNLOAD_BILLING_TEMPLATE_ID = "1507163542403945677";public static final String APP_DOWNLOAD_BILLING_OFFER = "Dear Customer, Thank you for purchasing from SmartDukaan pls click %s to download our app to see you invoice and special offers. SmartDukaan";static Map<Double, List<ScratchedGift>> GIFT_SERIES = new TreeMap<>(Comparator.reverseOrder());// Define eligible partners for LED & Microwave Ovenprivate static final Set<Integer> PREMIUM_ELIGIBLE_PARTNERS = new HashSet<>(Arrays.asList(175139615, 175139583));private static Map<ScratchedGift, Integer> GIFT_QUANTITIES = new HashMap<>();List<Double> PRICE_RANGE = Arrays.asList(0.0, Double.MAX_VALUE);static {GIFT_QUANTITIES.put(ScratchedGift.ACCESSORIES_50_PERCENT_OFF, 500);GIFT_QUANTITIES.put(ScratchedGift.NECK_BAND, 280);GIFT_QUANTITIES.put(ScratchedGift.LED, 1);GIFT_QUANTITIES.put(ScratchedGift.MICROWAVE_OVEN, 1);}static {GIFT_SERIES.put(0.0, Arrays.asList(ScratchedGift.ACCESSORIES_50_PERCENT_OFF, ScratchedGift.NECK_BAND));GIFT_SERIES.put(30001.0, Arrays.asList(ScratchedGift.NECK_BAND, ScratchedGift.MICROWAVE_OVEN, ScratchedGift.LED));}private void persistNonSerializedWithCustomSerialNumber(CustomFofoOrderItem customFofoOrderItem, int orderItemId) {// Create a new instance of FofoNonSerializeSerialfor (String accSerialNumber : customFofoOrderItem.getCustomSerialNumbers()) {if (!accSerialNumber.isEmpty()) {FofoNonSerializeSerial nonSerializeSerial = new FofoNonSerializeSerial();// Populate the entity with relevant informationnonSerializeSerial.setOrderItemId(orderItemId);nonSerializeSerial.setSerialNumber(accSerialNumber);// Save the entity to the databasefofoNonSerializeSerialRepository.persist(nonSerializeSerial);}}}public void sendAppDownloadBillingOffer(String mobileNumber) throws Exception {String sdurl = "http://surl.li/anhfn";try {if (prodEnv) {this.sendSms(APP_DOWNLOAD_BILLING_TEMPLATE_ID, String.format(APP_DOWNLOAD_BILLING_OFFER, sdurl), mobileNumber);}} catch (Exception e) {e.printStackTrace();}}public void sendSms(String dltTemplateId, String message, String mobileNumber) throws Exception {Map<String, String> map = new HashMap<>();map.put("sender", SENDER);map.put("messagetype", "TXT");map.put("apikey", "b866f7-c6c483-682ff5-054420-ad9e2c");map.put("numbers", "91" + mobileNumber);LOGGER.info("Message {}", message);// OTP Message Templatemap.put("message", message);map.put("dlttempid", dltTemplateId);String response = restClient.post(SMS_GATEWAY, map, new HashMap<>());LOGGER.info(response);}private void createScratchOffer(int fofoId, String invoiceNumber, int customerId) {//ScratchedGift gift = getScratchedGiftRandom(fofoId, customerId);// LocalDateTime endDate = LocalDateTime.of(LocalDate.now().getYear(), LocalDate.now().getMonth(), 27, 21, 00);List<ScratchOffer> scratchOffers = scratchOfferRepository.selectBycCustomerIdAndDate(customerId, ProfitMandiConstants.SCRATCH_OFFER_START_DATE, ProfitMandiConstants.SCRATCH_OFFER_END_DATE);if (scratchOffers.size() == 0) {ScratchOffer so2 = new ScratchOffer();so2.setInvoiceNumber(invoiceNumber);so2.setScratched(false);so2.setCreatedTimestamp(LocalDateTime.now());so2.setExpiredTimestamp(ProfitMandiConstants.SCRATCH_OFFER_END_DATE.plusDays(1).atTime(LocalTime.MAX));so2.setOfferName(String.valueOf(ScratchedGift.BLNT));so2.setCustomerId(customerId);LocalDateTime today830PM = LocalDate.now().atTime(20, 30);LocalDateTime today9PM = LocalDate.now().atTime(21, 0);so2.setUnlockedAt(LocalDateTime.now());// if (LocalDateTime.now().isAfter(today830PM)) {// so2.setUnlockedAt(today9PM.plusDays(0));// } else {// so2.setUnlockedAt(today9PM);// }scratchOfferRepository.persist(so2);}}@Overridepublic int createOrder(CreateOrderRequest createOrderRequest, int fofoId, boolean accessoriesDeals) throws Exception {LOGGER.info("fofoId -- {} Order Request -- {}", fofoId, createOrderRequest);CustomCustomer customCustomer = createOrderRequest.getCustomer();Customer customer = customerRepository.selectById(customCustomer.getCustomerId());if (!StringUtils.isValidGstNumber(customCustomer.getGstNumber())) {LOGGER.error("invalid customer gstNumber {} ", customCustomer.getGstNumber());throw new ProfitMandiBusinessException(ProfitMandiConstants.CUSTOMER_GST_NUMBER, customCustomer.getGstNumber(), "VE_1072");}Map<Integer, Integer> itemIdQuantity = new HashMap<>(); // this is for errorMap<Integer, CustomFofoOrderItem> itemIdCustomFofoOrderItemMap = new HashMap<>();Map<Integer, Float> lineItemPrice = new HashMap<>(); // this is for pricing errorfloat totalAmount = 0;boolean noGST = false;int changedTotalBillAmount = 0;for (CustomPaymentOption cpo : createOrderRequest.getPaymentOptions()) {changedTotalBillAmount += cpo.getAmount();}for (CustomFofoOrderItem customFofoOrderItem : createOrderRequest.getFofoOrderItems()) {if (customFofoOrderItem.getPoiId() > 0) {PendingOrderItem pendingOrderItem = pendingOrderItemRepository.selectById(customFofoOrderItem.getPoiId());if (customFofoOrderItem.getQuantity() > pendingOrderItem.getQuantity()) {throw new ProfitMandiBusinessException("itemIdQuantity", customFofoOrderItem.getItemId(), "Quantity should not be greater than order item quantity");}if (pendingOrderItem.getQuantity() > customFofoOrderItem.getQuantity()) {pendingOrderService.duplicatePendingOrder(pendingOrderItem, customFofoOrderItem.getQuantity());}}// itemIds.add(customFofoOrderItem.getItemId());Set<String> serialNumbers = this.serialNumberDetailsToSerialNumbers(customFofoOrderItem.getSerialNumberDetails());if (!serialNumbers.isEmpty() && customFofoOrderItem.getQuantity() != serialNumbers.size()) {itemIdQuantity.put(customFofoOrderItem.getItemId(), customFofoOrderItem.getQuantity());}if (!(customFofoOrderItem.getSellingPrice() > 0)) {lineItemPrice.put(customFofoOrderItem.getItemId(), customFofoOrderItem.getSellingPrice());} else {totalAmount = totalAmount + customFofoOrderItem.getSellingPrice() * customFofoOrderItem.getQuantity();for (SerialNumberDetail serialNumberDetail : customFofoOrderItem.getSerialNumberDetails()) {if (serialNumberDetail.getAmount() > 0) {totalAmount = totalAmount + serialNumberDetail.getAmount();}}}itemIdCustomFofoOrderItemMap.put(customFofoOrderItem.getItemId(), customFofoOrderItem);}if (!itemIdQuantity.isEmpty()) {// if item quantity does not match with given serialnumbers sizeLOGGER.error("itemId's quantity should be equal to given serialnumber size {} ", itemIdQuantity);throw new ProfitMandiBusinessException("itemIdQuantity", itemIdQuantity, "FFORDR_1001");// return "error";}this.validatePaymentOptionsAndTotalAmount(createOrderRequest.getPaymentOptions(), totalAmount);if (!lineItemPrice.isEmpty()) {// given fofo line item price must be greater than zeroLOGGER.error("requested itemId's selling price must greater than 0");throw new ProfitMandiBusinessException(ProfitMandiConstants.PRICE, lineItemPrice, "FFORDR_1002");}List<CurrentInventorySnapshot> currentInventorySnapshots = currentInventorySnapshotRepository.selectByFofoItemIds(fofoId, itemIdCustomFofoOrderItemMap.keySet());this.validateCurrentInventorySnapshotQuantities(currentInventorySnapshots, itemIdCustomFofoOrderItemMap);List<Item> items = itemRepository.selectByIds(itemIdCustomFofoOrderItemMap.keySet());if (items.size() != itemIdCustomFofoOrderItemMap.keySet().size()) {LOGGER.error("Requested ItemIds not found in catalog");// invalid itemIdsthrow new ProfitMandiBusinessException("invalidItemIds", itemIdCustomFofoOrderItemMap.keySet(), "FFORDR_1003");}Map<Integer, Item> itemMap = this.toItemMap(items);Set<Integer> nonSerializedItemIds = new HashSet<>();Set<String> serialNumbers = new HashSet<>();List<InsuranceModel> insuredModels = new ArrayList<>();for (CustomFofoOrderItem customFofoOrderItem : createOrderRequest.getFofoOrderItems()) {Item item = itemMap.get(customFofoOrderItem.getItemId());noGST = item.getHsnCode().equals("NOGST");if (item.getType().equals(ItemType.SERIALIZED)) {for (SerialNumberDetail serialNumberDetail : customFofoOrderItem.getSerialNumberDetails()) {serialNumbers.add(serialNumberDetail.getSerialNumber());if (serialNumberDetail.getAmount() > 0) {if (customer.getEmailId() == null || customer.getEmailId().equals("")) {throw new ProfitMandiBusinessException("Email Id is required for insurance", "Email Id is required for insurance", "Email Id is required for insurance");}InsuranceModel im = new InsuranceModel();im.setBrand(item.getBrand());im.setColor(item.getColor());im.setModelName(item.getModelName() + item.getModelNumber());im.setInsuranceAmount(serialNumberDetail.getAmount());im.setDeviceSellingPrice(customFofoOrderItem.getSellingPrice());im.setInsuranceUId(serialNumberDetail.getInsurance());im.setCorrelationId(serialNumberDetail.getCorrelationId());PlanVariant oneAssistpremium = insuranceService.getOneAssistPremiumByVariantId(serialNumberDetail.getInsurance());if (oneAssistpremium != null) {im.setInsuranceId(String.valueOf(oneAssistpremium.getId()));} else {im.setInsuranceId(String.valueOf(insuranceService.getICICIPremiumByVariantId(serialNumberDetail.getInsurance()).getId()));}im.setSerialNumber(serialNumberDetail.getSerialNumber());im.setMemory(serialNumberDetail.getMemory());im.setRam(serialNumberDetail.getRam());im.setMfgDate(serialNumberDetail.getMfgDate());insuredModels.add(im);// Check for free insurance codetry {Map<String, List<MobileInsurancePlan>> mobileInsurancePlanMap = insuranceService.getAllPlans(item.getId(), im.getDeviceSellingPrice(), false);MobileInsurancePlan mobileInsurancePlan = mobileInsurancePlanMap.entrySet().stream().flatMap(x -> x.getValue().stream()).filter(x -> x.getProductId().equals(serialNumberDetail.getInsurance())).findFirst().get();/* if (mobileInsurancePlan.getPlanName().equals("OneAssist Damage Protection Plan")) {MobileInsurancePlan freePlan = mobileInsurancePlanMap.get("Prolong Extendended Warranty(SmartDukaan Special Price)").get(0);InsuranceModel imFree = new InsuranceModel();imFree.setBrand(item.getBrand());imFree.setColor(item.getColor());imFree.setModelName(item.getModelName() + item.getModelNumber());imFree.setInsuranceAmount(0);imFree.setDeviceSellingPrice(customFofoOrderItem.getSellingPrice());LOGGER.info("freePlan.getProductId() {}", freePlan.getProductId());imFree.setInsuranceUId(freePlan.getProductId());imFree.setInsuranceId(String.valueOf(insuranceService.getOneAssistPremiumByVariantId(freePlan.getProductId()).getId()));imFree.setSerialNumber(serialNumberDetail.getSerialNumber());imFree.setMemory(serialNumberDetail.getMemory());imFree.setRam(serialNumberDetail.getRam());imFree.setMfgDate(serialNumberDetail.getMfgDate());insuredModels.add(imFree);}*/} catch (Exception e) {LOGGER.error("Exception - {}", e);throw new ProfitMandiBusinessException("problem fetching plans", "problem fetching plans", "problem fetching plans");}}}} else {nonSerializedItemIds.add(customFofoOrderItem.getItemId());}}Map<Integer, Set<InventoryItem>> serializedInventoryItemMap = new HashMap<>();Map<Integer, Set<InventoryItem>> nonSerializedInventoryItemMap = new HashMap<>();// Map<String, Float> serialNumberItemPrice = new HashMap<>();if (!serialNumbers.isEmpty()) {List<InventoryItem> serializedInventoryItems = inventoryItemRepository.selectByFofoIdSerialNumbers(fofoId, serialNumbers, false);LOGGER.info("serializedInventoryItems {}", serializedInventoryItems);for (InventoryItem inventoryItem : serializedInventoryItems) {if (inventoryItem.getGoodQuantity() == 1) {if (serializedInventoryItemMap.containsKey(inventoryItem.getItemId())) {serializedInventoryItemMap.get(inventoryItem.getItemId()).add(inventoryItem);} else {Set<InventoryItem> itemIdInventoryItems = new HashSet<>();itemIdInventoryItems.add(inventoryItem);serializedInventoryItemMap.put(inventoryItem.getItemId(), itemIdInventoryItems);}}}}if (!nonSerializedItemIds.isEmpty()) {List<InventoryItem> nonSerializedInventoryItems = inventoryItemRepository.selectByFofoIdItemIds(fofoId, nonSerializedItemIds);LOGGER.info("nonSerializedInventoryItems {}", nonSerializedInventoryItems);for (InventoryItem it : nonSerializedInventoryItems) {if (it.getGoodQuantity() > 0) {if (nonSerializedInventoryItemMap.containsKey(it.getItemId())) {nonSerializedInventoryItemMap.get(it.getItemId()).add(it);} else {Set<InventoryItem> tmp = new HashSet<>();tmp.add(it);nonSerializedInventoryItemMap.put(it.getItemId(), tmp);}}}}this.validateItemsSerializedNonSerialized(items, itemIdCustomFofoOrderItemMap);Map<Integer, Set<InventoryItem>> inventoryItemsToBill = new HashMap<>();Map<Integer, Integer> inventoryItemIdQuantityUsed = new HashMap<>(); // to keep track of inventoryitem quanity// used for scan records insertionLOGGER.info("itemMap keys {}", itemMap.keySet());// Lets reduce quantity and decide what inventory items to use.for (Item item : items) {if (item.getType().equals(ItemType.SERIALIZED)) {// TODO:handle nullif (serializedInventoryItemMap.get(item.getId()) == null || itemIdCustomFofoOrderItemMap.get(item.getId()).getSerialNumberDetails().size() != serializedInventoryItemMap.get(item.getId()).size()) {List<String> invalidSerialNumbers = itemIdCustomFofoOrderItemMap.get(item.getId()).getSerialNumberDetails().stream().map(x -> x.getSerialNumber()).collect(Collectors.toList());throw new ProfitMandiBusinessException("invalidSerialNumbers", invalidSerialNumbers, "FFORDR_1004");}List<String> serialNumberList = liveDemoBillingRespository.selectAllSerialNumber();Set<InventoryItem> inventoryItemsSerializedserialized = serializedInventoryItemMap.get(item.getId());for (InventoryItem inventoryItem : inventoryItemsSerializedserialized) {inventoryItem.setGoodQuantity(0);inventoryItemIdQuantityUsed.put(inventoryItem.getId(), 1);if (serialNumberList.contains(inventoryItem.getSerialNumber())) {LiveDemoSerialNumber liveDemoSerialNumber = liveDemoBillingRespository.selectBySerialNumber(inventoryItem.getSerialNumber());liveDemoBillingRespository.delete(liveDemoSerialNumber);}}inventoryItemsToBill.put(item.getId(), inventoryItemsSerializedserialized);} else {Set<InventoryItem> inventoryItemsNonSerialized = nonSerializedInventoryItemMap.get(item.getId());int quantityToBill = itemIdCustomFofoOrderItemMap.get(item.getId()).getQuantity();int totalLeft = quantityToBill;Set<InventoryItem> inventoryItemsNonSerializedUsed = new HashSet<>();if (inventoryItemsNonSerialized != null) {for (InventoryItem inventoryItem : inventoryItemsNonSerialized) {if (totalLeft > 0) {int toUse = Math.min(totalLeft, inventoryItem.getGoodQuantity());inventoryItemIdQuantityUsed.put(inventoryItem.getId(), toUse);inventoryItem.setGoodQuantity(inventoryItem.getGoodQuantity() - toUse);totalLeft = totalLeft - toUse;inventoryItemsNonSerializedUsed.add(inventoryItem);}}}if (totalLeft > 0) {// not enough quanity for non-serializedLOGGER.error("not enough quanity for non-serialized");throw new ProfitMandiBusinessException("notEnoughQuantityForNonSerialized", totalLeft, "FFORDR_1005");}inventoryItemsToBill.put(item.getId(), inventoryItemsNonSerializedUsed);}}Map<Integer, PriceModel> itemIdMopPriceMap = pricingService.getPurchasePriceMopPriceNotFound(itemIdCustomFofoOrderItemMap.keySet(), fofoId);LOGGER.info("itemIdMopMap {}", itemIdMopPriceMap);if (accessoriesDeals) {this.validateDpPrice(fofoId, itemIdMopPriceMap, itemIdCustomFofoOrderItemMap);} else {this.validateMopPrice(fofoId, itemIdMopPriceMap, itemIdCustomFofoOrderItemMap);}String fofoStoreCode = this.getFofoStoreCode(fofoId);String documentNumber = null;if (noGST) {documentNumber = this.getSecurityDepositNumber(fofoId, fofoStoreCode);} else {documentNumber = this.getInvoiceNumber(fofoId, fofoStoreCode);}CustomerAddress customerAddress = null;if (customCustomer.getCustomerAddressId() != 0) {customerAddress = customer.getCustomerAddress().stream().filter(x -> x.getId() == customCustomer.getCustomerAddressId()).findFirst().get();}FofoOrder fofoOrder = this.createAndGetFofoOrder(customer.getId(), customCustomer.getGstNumber(), fofoId, documentNumber, totalAmount, customCustomer.getCustomerAddressId(), createOrderRequest.getPoId());this.createPaymentOptions(fofoOrder, createOrderRequest.getPaymentOptions());int retailerAddressId = retailerRegisteredAddressRepository.selectAddressIdByRetailerId(fofoId);Address retailerAddress = addressRepository.selectById(retailerAddressId);Integer stateId = null;if (customerAddress == null || customerAddress.getState() == null || customerAddress.getState().equals(retailerAddress.getState())) {try {State state = stateRepository.selectByName(retailerAddress.getState());stateId = Long.valueOf(state.getId()).intValue();} catch (Exception e) {LOGGER.error("Unable to get state rates");}}for (CustomFofoOrderItem customFofoOrderItem : createOrderRequest.getFofoOrderItems()) {FofoOrderItem fofoOrderItem = this.createAndGetFofoOrderItem(customFofoOrderItem, fofoOrder.getId(), itemMap, inventoryItemsToBill.get(customFofoOrderItem.getItemId()), stateId);Item item = itemMap.get(customFofoOrderItem.getItemId());if (item.getType().equals(ItemType.NON_SERIALIZED)) {if (customFofoOrderItem.getCustomSerialNumbers() != null && !customFofoOrderItem.getCustomSerialNumbers().isEmpty()) {persistNonSerializedWithCustomSerialNumber(customFofoOrderItem, fofoOrderItem.getId());} else {LOGGER.info("Custom serial numbers are empty. Not persisting data.");}}Set<InventoryItem> inventoryItems = inventoryItemsToBill.get(customFofoOrderItem.getItemId());this.createFofoLineItem(fofoOrderItem.getId(), inventoryItems, inventoryItemIdQuantityUsed);this.updateCurrentInventorySnapshot(currentInventorySnapshots, fofoId, customFofoOrderItem.getItemId(), customFofoOrderItem.getQuantity());this.updateInventoryItemsAndScanRecord(inventoryItems, fofoId, inventoryItemIdQuantityUsed, fofoOrder.getId());}List<FofoOrderItem> fofoItems = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());boolean smartPhone = false;for (FofoOrderItem fofoOrderItem : fofoItems) {Item item = itemRepository.selectById(fofoOrderItem.getItemId());if (item.isSmartPhone()) {LOGGER.info("fofoItem {}", fofoOrderItem);smartPhone = true;}}if (!smartPhone) {LOGGER.warn("No smartphones found in fofoItems.");}if (smartPhone) {this.createAndGetHygieneData(fofoOrder.getId(), fofoOrder.getFofoId());}// insurance calculation is insurance flag is enabled//if (insuredModels.size() > 0) {LOGGER.info("Processing insurane for serialNumbers");LOGGER.info("InsuranceModels {}", insuredModels);LocalDate customerDateOfBirth = LocalDate.from(createOrderRequest.getCustomer().getDateOfBirth());fofoOrder.setDateOfBirth(customerDateOfBirth);for (InsuranceModel insuranceModel : insuredModels) {LOGGER.info("G- {}", insuranceModel.getInsuranceId());LOGGER.info("insuranceModel- {}", insuranceModel);insuranceService.createInsurance(fofoOrder, insuranceModel, false);}}schemeService.processSchemeOut(fofoOrder.getId(), fofoId);if (createOrderRequest.getPoId() != 0) {PendingOrder po = pendingOrderRepository.selectById(createOrderRequest.getPoId());po.setBilledAmount(po.getBilledAmount() + totalAmount);for (CustomFofoOrderItem cfoi : createOrderRequest.getFofoOrderItems()) {PendingOrderItem poi = pendingOrderItemRepository.selectById(cfoi.getPoiId());poi.setStatus(OrderStatus.BILLED);poi.setBilledTimestamp(LocalDateTime.now());}po.setStatus(OrderStatus.BILLED);}//Process scratchthis.processScratchOffer(fofoOrder);// persist the data of upgrade offer tablefor (CustomFofoOrderItem customFofoOrderItem : createOrderRequest.getFofoOrderItems()) {if (customFofoOrderItem.getCustomerOfferItemId().size() > 0) {for (Integer customerOfferItemId : customFofoOrderItem.getCustomerOfferItemId()) {UpgradeOffer upgradeOffer = new UpgradeOffer();upgradeOffer.setOrderId(fofoOrder.getId());upgradeOffer.setCustomerOfferItemId(customerOfferItemId);upgradeOffer.setItemId(customFofoOrderItem.getItemId());Set<SerialNumberDetail> serialNumberDetails = customFofoOrderItem.getSerialNumberDetails();if (!customFofoOrderItem.getSerialNumberDetails().isEmpty()) {String serialNumber = serialNumberDetails.iterator().next().getSerialNumber();upgradeOffer.setSerialNumber(serialNumber);// Set<String> serialNumbersSet = this.serialNumberDetailsToSerialNumbers(customFofoOrderItem.getSerialNumberDetails());// LOGGER.info("serialNumbersSet.toString() {}",serialNumbersSet.toString());// upgradeOffer.setSerialNumber(serialNumbersSet.toString());} else {upgradeOffer.setSerialNumber(null); // Handle case where there is no serial number detail}upgradeOffer.setCreatedTimestamp(LocalDateTime.now());upgradeOffer.setPaymentStatus(UpgradeOfferPaymentStatus.PENDING);upgradeOffer.setStatusDescription(UpgradeOfferPaymentStatus.PENDING.getValue());upgradeOfferRepository.persist(upgradeOffer);}}}// enable it fo upsell callif (smartPhone) {if (fofoOrder.getId() > 0) {List<InsurancePolicy> insurancePolicies = insurancePolicyRepository.selectByRetailerIdInvoiceNumber(fofoOrder.getInvoiceNumber());if (insurancePolicies.isEmpty()) {List<FofoOrderItem> fofoOrderItems = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());for (FofoOrderItem fofoOrderItem : fofoOrderItems) {Item item = itemRepository.selectById(fofoOrderItem.getItemId());if (item.isSmartPhone()) {UpSaleOrder upSaleOrder = new UpSaleOrder();upSaleOrder.setCreatedTimestamp(LocalDateTime.now());upSaleOrder.setOrderId(fofoOrder.getId());upSaleOrder.setFofoId(fofoOrder.getFofoId());upSaleOrderRepository.persist(upSaleOrder);break; // Exit the loop after persisting the UpSaleOrder for the first smartphone}}}}}// Update Partner Opening Stock current qtyif (fofoOrder.getId() > 0) {List<FofoOrderItem> fofoOrderItems = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());for (FofoOrderItem fofoOrderItem : fofoOrderItems) {Item item = itemRepository.selectById(fofoOrderItem.getItemId());smartCartService.minusOpeningStock(item.getId(), fofoOrder.getFofoId(), fofoOrderItem.getQuantity());}}return fofoOrder.getId();}@Overridepublic void processScratchOffer(FofoOrder fofoOrder) throws ProfitMandiBusinessException {boolean isSmartPhonePurchased = false;float maxPurchaseValue = 0;List<FofoOrderItem> fofoOrderItems = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());for (FofoOrderItem fofoOrderItem : fofoOrderItems) {Item item = itemRepository.selectById(fofoOrderItem.getItemId());if (item.isSmartPhone()) {LOGGER.info("fofoItem {}", fofoOrderItem);isSmartPhonePurchased = true;maxPurchaseValue = Math.max(fofoOrderItem.getSellingPrice(), maxPurchaseValue);}}LocalDate startDate = ProfitMandiConstants.SCRATCH_OFFER_START_DATE;LocalDate endDate = ProfitMandiConstants.SCRATCH_OFFER_END_DATE;boolean specificPriceOffer = ProfitMandiConstants.SPECIFIC_PRICE_OFFER;boolean randomOffer = ProfitMandiConstants.RANDOM_OFFER;if (isSmartPhonePurchased) {if (LocalDateTime.now().isAfter(startDate.atStartOfDay()) && LocalDateTime.now().isBefore(endDate.atTime(Utils.MAX_TIME))) {Customer customer = customerRepository.selectById(fofoOrder.getCustomerId());try {this.sendAppDownloadBillingOffer(customer.getMobileNumber());} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}if (specificPriceOffer) {this.createSpecificPriceScratchOffer(fofoOrder.getInvoiceNumber(), fofoOrder.getCustomerId(), fofoOrder.getFofoId(), maxPurchaseValue);} else if (randomOffer) {this.createRandomScratchOffer(fofoOrder.getInvoiceNumber(), fofoOrder.getCustomerId());LOGGER.info("randomOffer {}", randomOffer);} else {this.createScratchOffer(fofoOrder.getFofoId(), fofoOrder.getInvoiceNumber(), fofoOrder.getCustomerId());}}}}@Overridepublic ScratchedGift getSelectedGift(double purchaseAmount, int fofoId) throws ProfitMandiBusinessException {Map<ScratchedGift, Long> scratchOfferCountMap = scratchOfferRepository.countOffersByDateRange(ProfitMandiConstants.SCRATCH_OFFER_START_DATE, ProfitMandiConstants.SCRATCH_OFFER_END_DATE);LOGGER.info("scratchOfferCountMap {}", scratchOfferCountMap);LocalDateTime startDateTime = ProfitMandiConstants.SCRATCH_OFFER_START_DATE.atStartOfDay();LocalDateTime endDateTime = ProfitMandiConstants.SCRATCH_OFFER_START_DATE.atTime(LocalTime.MAX);LOGGER.info("start date {}", startDateTime);LOGGER.info("end date {}", endDateTime);RandomCollection<ScratchedGift> giftRandomCollection = createDynamicGiftSeries(scratchOfferCountMap, purchaseAmount, fofoId);if (giftRandomCollection.size() > 0) {ScratchedGift selectedGift = giftRandomCollection.next();// Ensure one LED for 175139615 and one Oven for 175139583if (selectedGift == ScratchedGift.LED || selectedGift == ScratchedGift.MICROWAVE_OVEN) {if (!PREMIUM_ELIGIBLE_PARTNERS.contains(fofoId)) {LOGGER.info("Partner {} not eligible for {}", fofoId, selectedGift);return ScratchedGift.ACCESSORIES_50_PERCENT_OFF; // Default alternate gift}// Restrict LED to Partner 175139615 and Oven to Partner 175139583if ((selectedGift == ScratchedGift.LED && fofoId != 175139615) ||(selectedGift == ScratchedGift.MICROWAVE_OVEN && fofoId != 175139583)) {LOGGER.info("Partner {} not eligible for {}", fofoId, selectedGift);return ScratchedGift.ACCESSORIES_50_PERCENT_OFF;}// Ensure only one LED and one Microwave Oven per daylong ledCount = scratchOfferCountMap.getOrDefault(ScratchedGift.LED, 0L);long ovenCount = scratchOfferCountMap.getOrDefault(ScratchedGift.MICROWAVE_OVEN, 0L);if ((selectedGift == ScratchedGift.LED || selectedGift == ScratchedGift.MICROWAVE_OVEN)&& (ledCount > 0 && ovenCount > 0)) {LOGGER.info("Both LED and Microwave Oven already given today.");return ScratchedGift.ACCESSORIES_50_PERCENT_OFF;}if ((selectedGift == ScratchedGift.LED && ledCount > 0)) {LOGGER.info("LED already given today.");return ScratchedGift.ACCESSORIES_50_PERCENT_OFF;}if ((selectedGift == ScratchedGift.LED)) {LOGGER.info("LED already given today.");return ScratchedGift.ACCESSORIES_50_PERCENT_OFF;}if ((selectedGift == ScratchedGift.MICROWAVE_OVEN && ovenCount > 0)) {LOGGER.info("Oven already given today.");return ScratchedGift.ACCESSORIES_50_PERCENT_OFF;}}// Ensure only one Neckband per partner per dayif (selectedGift == ScratchedGift.NECK_BAND) {List<FofoOrder> fofoOrders = fofoOrderRepository.selectByFofoId(fofoId, startDateTime, endDateTime, 0, 0);List<String> invoiceNumbers = fofoOrders.stream().map(FofoOrder::getInvoiceNumber).collect(Collectors.toList());List<ScratchOffer> offers = scratchOfferRepository.selectByInvoiceNumbers(invoiceNumbers);LOGGER.info("offers for partner {}", offers);boolean neckbandGivenToday = offers.stream().anyMatch(offer -> offer.getOfferName().equals(ScratchedGift.NECK_BAND));if (neckbandGivenToday) {LOGGER.info("Neckband already given today for partner {}", fofoId);return ScratchedGift.ACCESSORIES_50_PERCENT_OFF;}}return selectedGift;}return ScratchedGift.ACCESSORIES_50_PERCENT_OFF;}public RandomCollection<ScratchedGift> createDynamicGiftSeries(Map<ScratchedGift, Long> soldGiftContMap, Double sellingPrice, int fofoId) throws ProfitMandiBusinessException {int index = 0;RandomCollection<ScratchedGift> randomCollection = new RandomCollection<>();PartnerType partnerType = partnerTypeChangeService.getTypeOnDate(fofoId, LocalDate.now());LOGGER.info("partnerType {}", partnerType);if (partnerType.equals(PartnerType.BRONZE)) {LOGGER.info("partnerType if- {}", partnerType);sellingPrice = 0.0;}for (int i = 0; i < PRICE_RANGE.size(); i++) {Double price = PRICE_RANGE.get(i);Double nextPrice = Double.MAX_VALUE;if (i != PRICE_RANGE.size() - 1) {nextPrice = PRICE_RANGE.get(i + 1);}if (sellingPrice >= price && sellingPrice < nextPrice) {int divisor = PRICE_RANGE.size() - index;LOGGER.info("Processing price range: {}, sellingPrice: {}", price, sellingPrice);for (ScratchedGift gift : GIFT_SERIES.get(price)) {int remainingQty = GIFT_QUANTITIES.get(gift) - soldGiftContMap.getOrDefault(gift, 0L).intValue();LOGGER.info("Checking gift: {}, remainingQty: {}", gift, remainingQty);if (remainingQty > 0) {int weight = (remainingQty > divisor) ? remainingQty / divisor : remainingQty;randomCollection.add(weight, gift);LOGGER.info("Added gift: {}, weight: {}", gift, weight);}}break; // Exit the loop once the correct price range is processed}index++;}// If no gifts were added, log and handle potential issues hereif (randomCollection.size() == 0) {LOGGER.info("No gifts added for sellingPrice: {} in createDynamicGiftSeries", sellingPrice);}LOGGER.info("randomCollectionSize {}, partnerType {}, sellingPrice {}", randomCollection.size(), partnerType, sellingPrice);return randomCollection;}/*static {RandomCollection<ScratchedGift> map1 = new RandomCollection<ScratchedGift>().add(100d, ScratchedGift.GIFT_BOWL);GIFT_SERIES.put(0.0, map1);//Map<ScratchedGift, Double> map2 = new HashMap<>();RandomCollection<ScratchedGift> map2 = new RandomCollection<ScratchedGift>().add(40d, ScratchedGift.GIFT_BOWL).add(20d, ScratchedGift.NECK_BAND).add(30d, ScratchedGift.FLASKNMUG).add(10d, ScratchedGift.ELECTRIC_KETTLE);GIFT_SERIES.put(10001.0, map2);RandomCollection<ScratchedGift> map3 = new RandomCollection<ScratchedGift>().add(25d, ScratchedGift.GIFT_BOWL).add(30d, ScratchedGift.NECK_BAND).add(10d, ScratchedGift.SPEAKER).add(25d, ScratchedGift.FLASKNMUG).add(10d, ScratchedGift.ELECTRIC_KETTLE);GIFT_SERIES.put(18001.0, map3);RandomCollection<ScratchedGift> map4 = new RandomCollection<ScratchedGift>().add(30d, ScratchedGift.NECK_BAND).add(20d, ScratchedGift.SPEAKER).add(20d, ScratchedGift.FLASKNMUG).add(30d, ScratchedGift.ELECTRIC_KETTLE);GIFT_SERIES.put(25001.0, map4);RandomCollection<ScratchedGift> map5 = new RandomCollection<ScratchedGift>().add(40d, ScratchedGift.SPEAKER).add(60d, ScratchedGift.SMART_WATCH);GIFT_SERIES.put(50001.0, map5);}*/private void createSpecificPriceScratchOffer(String invoiceNumber, int customerId, int fofoId, float purchaseAmount) throws ProfitMandiBusinessException {ScratchedGift selectedGift = getSelectedGift(purchaseAmount, fofoId);List<ScratchOffer> scratchOffers = scratchOfferRepository.selectBycCustomerIdAndDate(customerId, ProfitMandiConstants.SCRATCH_OFFER_START_DATE, ProfitMandiConstants.SCRATCH_OFFER_END_DATE);if (scratchOffers.size() == 0) {ScratchOffer so2 = new ScratchOffer();so2.setInvoiceNumber(invoiceNumber);so2.setScratched(false);so2.setCreatedTimestamp(LocalDateTime.now());so2.setExpiredTimestamp(ProfitMandiConstants.SCRATCH_OFFER_END_DATE.plusDays(1).atTime(LocalTime.MAX));so2.setOfferName(String.valueOf(selectedGift));so2.setCustomerId(customerId);so2.setUnlockedAt(LocalDateTime.now());scratchOfferRepository.persist(so2);}}private void createRandomScratchOffer(String invoiceNumber, int customerId) {ScratchedGift selectedGift = getScratchedGiftRandomAccordingQuantity(customerId);List<ScratchOffer> scratchOffers = scratchOfferRepository.selectBycCustomerIdAndDate(customerId, ProfitMandiConstants.SCRATCH_OFFER_START_DATE, ProfitMandiConstants.SCRATCH_OFFER_END_DATE);if (scratchOffers.size() == 0) {ScratchOffer so2 = new ScratchOffer();so2.setInvoiceNumber(invoiceNumber);so2.setScratched(false);so2.setCreatedTimestamp(LocalDateTime.now());so2.setExpiredTimestamp(ProfitMandiConstants.SCRATCH_OFFER_END_DATE.plusDays(1).atTime(LocalTime.MAX));so2.setOfferName(String.valueOf(selectedGift));so2.setCustomerId(customerId);so2.setUnlockedAt(LocalDateTime.now());scratchOfferRepository.persist(so2);}}private ScratchedGift getScratchedGiftRandom(int fofoId, int customerId) throws ProfitMandiBusinessException {Map<Integer, ScratchedGift> giftSeries = new HashMap<>();giftSeries.put(1, ScratchedGift.MINI_CHOPPER);giftSeries.put(2, ScratchedGift.FRUIT_JUICER);giftSeries.put(3, ScratchedGift.STEAM_IRON);List<FofoOrder> fofoOrders = fofoOrderRepository.selectByFofoIdBetweenCreatedTimeStamp(fofoId, ProfitMandiConstants.SCRATCH_OFFER_START_DATE.atStartOfDay(),ProfitMandiConstants.SCRATCH_OFFER_END_DATE.atTime(Utils.MAX_TIME));ScratchedGift gift = ScratchedGift.BLNT;Random random = new Random();int rand;while (true) {rand = random.nextInt(4);if (rand != 0) break;}if (fofoOrders.isEmpty()) {gift = giftSeries.get(rand);} else {List<String> invoiceNumbers = fofoOrders.stream().filter(x -> x.getCancelledTimestamp() == null).map(x -> x.getInvoiceNumber()).collect(Collectors.toList());List<ScratchOffer> scratchOffers = scratchOfferRepository.selectByInvoiceNumbers(invoiceNumbers);if (scratchOffers.isEmpty()) {gift = giftSeries.get(rand);} else {List<ScratchOffer> bigGifts = scratchOffers.stream().filter(x -> !x.getOfferName().equals(ScratchedGift.BLNT) && !x.getOfferName().equals(ScratchedGift.EW)).collect(Collectors.toList());if (bigGifts.size() <= 10) {List<Integer> scratchCustomerIds = scratchOffers.stream().map(x -> x.getCustomerId()).collect(Collectors.toList());if (scratchCustomerIds.contains(customerId)) {gift = ScratchedGift.BLNT;LOGGER.info("gift2 {}", gift);} else {int miniChopper = (int) bigGifts.stream().filter(x -> x.getOfferName().equals(ScratchedGift.MINI_CHOPPER)).count();int fruitJuicer = (int) bigGifts.stream().filter(x -> x.getOfferName().equals(ScratchedGift.FRUIT_JUICER)).count();int streanIron = (int) bigGifts.stream().filter(x -> x.getOfferName().equals(ScratchedGift.STEAM_IRON)).count();if (rand == 1) {if (miniChopper < 4) {LOGGER.info("miniChopper {}", miniChopper);gift = giftSeries.get(rand);}}if (rand == 2) {if (fruitJuicer < 3) {LOGGER.info("fruitJuicer {}", fruitJuicer);gift = giftSeries.get(rand);}}if (rand == 3) {if (streanIron < 3) {LOGGER.info("streanIron {}", streanIron);gift = giftSeries.get(rand);}}LOGGER.info("gift4 {}", gift);}}}}return gift;}private ScratchedGift getScratchedGiftRandomAccordingQuantity(int customerId) {RandomCollection<ScratchedGift> map1 = new RandomCollection<ScratchedGift>().add(50d, ScratchedGift.SOLOR_LAMP).add(100d, ScratchedGift.BLUETOOTH_SPEAKER).add(150d, ScratchedGift.RED_WATER_BOTTLE).add(200d, ScratchedGift.GIFT_BOWL).add(100d, ScratchedGift.EARBUDS);ScratchedGift gift;List<ScratchOffer> lastScratchOffers = scratchOfferRepository.selectBycCustomerIdAndDate(customerId, ProfitMandiConstants.LAST_SCRATCH_OFFER_START_DATE, ProfitMandiConstants.LAST_SCRATCH_OFFER_END_DATE);if (lastScratchOffers.isEmpty()) {gift = map1.next();} else {gift = ScratchedGift.RED_WATER_BOTTLE;LOGGER.info("RED_WATER_BOTTLE {}", gift);}return gift;}private HygieneData createAndGetHygieneData(int id, int fofoId) {HygieneData hygieneData = new HygieneData();hygieneData.setOrderId(id);hygieneData.setFofoId(fofoId);hygieneData.setCreatedTimestamp(LocalDateTime.now());hygieneDataRepository.persist(hygieneData);return hygieneData;}@Overridepublic String getInvoiceNumber(int fofoId, String fofoStoreCode) {InvoiceNumberGenerationSequence invoiceNumberGenerationSequence = null;try {invoiceNumberGenerationSequence = invoiceNumberGenerationSequenceRepository.selectByFofoId(fofoId);invoiceNumberGenerationSequence.setSequence(invoiceNumberGenerationSequence.getSequence() + 1);} catch (ProfitMandiBusinessException profitMandiBusinessException) {invoiceNumberGenerationSequence = new InvoiceNumberGenerationSequence();invoiceNumberGenerationSequence.setFofoId(fofoId);invoiceNumberGenerationSequence.setPrefix(fofoStoreCode);invoiceNumberGenerationSequence.setSequence(1);}invoiceNumberGenerationSequenceRepository.persist(invoiceNumberGenerationSequence);return invoiceNumberGenerationSequence.getPrefix() + "/" + invoiceNumberGenerationSequence.getSequence();}private String getSecurityDepositNumber(int fofoId, String fofoStoreCode) {InvoiceNumberGenerationSequence invoiceNumberGenerationSequence = null;try {invoiceNumberGenerationSequence = invoiceNumberGenerationSequenceRepository.selectByFofoId(fofoId);invoiceNumberGenerationSequence.setChallanNumberSequence(invoiceNumberGenerationSequence.getChallanNumberSequence() + 1);} catch (ProfitMandiBusinessException profitMandiBusinessException) {invoiceNumberGenerationSequence = new InvoiceNumberGenerationSequence();invoiceNumberGenerationSequence.setFofoId(fofoId);invoiceNumberGenerationSequence.setPrefix(fofoStoreCode);invoiceNumberGenerationSequence.setChallanNumberSequence(1);}invoiceNumberGenerationSequenceRepository.persist(invoiceNumberGenerationSequence);return invoiceNumberGenerationSequence.getPrefix() + "/SEC" + invoiceNumberGenerationSequence.getChallanNumberSequence();}private Set<String> serialNumberDetailsToSerialNumbers(Set<SerialNumberDetail> serialNumberDetails) {Set<String> serialNumbers = new HashSet<>();for (SerialNumberDetail serialNumberDetail : serialNumberDetails) {if (serialNumberDetail.getSerialNumber() != null && !serialNumberDetail.getSerialNumber().isEmpty()) {serialNumbers.add(serialNumberDetail.getSerialNumber());}}return serialNumbers;}@Overridepublic InvoicePdfModel getInvoicePdfModel(int orderId) throws ProfitMandiBusinessException {FofoOrder fofoOrder = fofoOrderRepository.selectByOrderId(orderId);return this.getInvoicePdfModel(fofoOrder);}@Override@Cacheable(value = "order.dummymodel", cacheManager = "oneDayCacheManager")public InvoicePdfModel getDummyPdfModel(String serialNumber) throws ProfitMandiBusinessException {List<WarehouseInventoryItem> warehouseInventoryItems = warehouseInventoryItemRepository.selectWarehouseInventoryItemBySerailNumbers(Arrays.asList(serialNumber));if (warehouseInventoryItems.size() > 0) {WarehouseInventoryItem warehouseInventoryItem = warehouseInventoryItems.get(0);int currentQuantity = warehouseInventoryItems.get(0).getCurrentQuantity();if (currentQuantity > 0) {throw new ProfitMandiBusinessException("Serial Number", serialNumber, "Serial Number exist in our warehouse");} else {try {InventoryItem inventoryItem = inventoryItemRepository.selectBySerialNumber(serialNumber);if (inventoryItem.getGoodQuantity() > 0) {throw new ProfitMandiBusinessException("Serial Number", serialNumber, "Serial Number is not yet billed by the partner");} else {List<ScanRecord> scanRecords = scanRecordRepository.selectByInventoryItemId(inventoryItem.getId());Optional<ScanRecord> scanRecord = scanRecords.stream().filter(x -> x.getOrderId() != 0).findFirst();if (scanRecord.isPresent()) {FofoOrder fofoOrder = fofoOrderRepository.selectByOrderId(scanRecord.get().getOrderId());orderIdsConsumed.add(fofoOrder.getId());return this.getInvoicePdfModel(fofoOrder);} else {throw new ProfitMandiBusinessException("Serial Number", serialNumber, "Serial Number returned by partner, but in transit");}}} catch (Exception e) {int itemId = warehouseInventoryItem.getItemId();if (serialNumberOrderIdMap.containsKey(serialNumber)) {FofoOrder fofoOrder = fofoOrderRepository.selectByOrderId(serialNumberOrderIdMap.get(serialNumber));InvoicePdfModel pdfModel = this.getInvoicePdfModel(fofoOrder.getId());this.modifyDummyModel(fofoOrder, pdfModel, itemId, serialNumber);return pdfModel;}// Map this serialNumber for dummy billingLocalDateTime grnDate = warehouseInventoryItem.getCreated();Random random = new Random();int randomDays = random.ints(2, 15).findFirst().getAsInt();LocalDateTime saleDate = grnDate.plusDays(randomDays);if (saleDate.isAfter(LocalDate.now().atStartOfDay())) {saleDate = LocalDateTime.now().minusDays(2);}Random offsetRandom = new Random();int offset = offsetRandom.ints(2, 100).findFirst().getAsInt();FofoOrder fofoOrder = fofoOrderRepository.selectFirstOrderAfterDate(saleDate, offset);while (orderIdsConsumed.contains(fofoOrder.getId())) {Random offsetRandom2 = new Random();int offset2 = offsetRandom2.ints(2, 100).findFirst().getAsInt();FofoOrder fofoOrder2 = fofoOrderRepository.selectFirstOrderAfterDate(saleDate, offset2);if (fofoOrder2 != null) {fofoOrder = fofoOrder2;}}InvoicePdfModel pdfModel = this.getInvoicePdfModel(fofoOrder.getId());orderIdsConsumed.add(fofoOrder.getId());this.modifyDummyModel(fofoOrder, pdfModel, itemId, serialNumber);return pdfModel;}}} else {throw new ProfitMandiBusinessException("Serial Number", serialNumber, "Serial Number does not exist in our warehouse");}}void modifyDummyModel(FofoOrder fofoOrder, InvoicePdfModel pdfModel, int itemId, String serialNumber) throwsProfitMandiBusinessException {int retailerAddressId = retailerRegisteredAddressRepository.selectAddressIdByRetailerId(fofoOrder.getFofoId());Address retailerAddress = addressRepository.selectById(retailerAddressId);Customer customer = customerRepository.selectById(fofoOrder.getCustomerId());CustomerAddress customerAddress = customer.getCustomerAddress().stream().filter(x -> x.getId() == fofoOrder.getCustomerAddressId()).findFirst().get();Integer stateId = null;if (customerAddress.getState().equals(retailerAddress.getState())) {try {// stateId =// Long.valueOf(Utils.getStateInfo(customerAddress.getState()).getId()).intValue();stateId = Long.valueOf(stateRepository.selectByName(customerAddress.getState()).getId()).intValue();} catch (Exception e) {LOGGER.error("Unable to get state rates");}}CustomOrderItem cli = pdfModel.getOrderItems().stream().findFirst().get();List<FofoOrderItem> fofoOrderItems = Arrays.asList(this.getDummyFofoOrderItem(itemId, fofoOrder.getId(), serialNumber, stateId));pdfModel.setPaymentOptions(pdfModel.getPaymentOptions().stream().limit(1).collect(Collectors.toList()));CustomPaymentOption paymentOption = pdfModel.getPaymentOptions().get(0);paymentOption.setAmount(fofoOrderItems.get(0).getMop());List<CustomOrderItem> customerFofoOrderItems = new ArrayList<>();for (FofoOrderItem fofoOrderItem : fofoOrderItems) {CustomOrderItem customFofoOrderItem = new CustomOrderItem();float totalTaxRate = fofoOrderItem.getIgstRate() + fofoOrderItem.getSgstRate() + fofoOrderItem.getCgstRate();float taxableSellingPrice = fofoOrderItem.getSellingPrice() / (1 + totalTaxRate / 100);float taxableDiscountPrice = fofoOrderItem.getDiscount() / (1 + totalTaxRate / 100);customFofoOrderItem.setAmount(fofoOrderItem.getQuantity() * (taxableSellingPrice - taxableDiscountPrice));customFofoOrderItem.setDescription(fofoOrderItem.getBrand() + " " + fofoOrderItem.getModelName() + " " + fofoOrderItem.getModelNumber() + "-" + fofoOrderItem.getColor());Set<String> serialNumbers = this.toSerialNumbers(fofoOrderItem.getFofoLineItems());// LOGGER.info("serialNumbers {}", serialNumbers);// LOGGER.info("serialNumbers is empty {}", serialNumbers.isEmpty());if (!serialNumbers.isEmpty()) {customFofoOrderItem.setDescription(customFofoOrderItem.getDescription() + "\n IMEIS - " + String.join(", ", serialNumbers));}customFofoOrderItem.setRate(taxableSellingPrice);customFofoOrderItem.setDiscount(taxableDiscountPrice);customFofoOrderItem.setQuantity(fofoOrderItem.getQuantity());customFofoOrderItem.setNetAmount((fofoOrderItem.getSellingPrice() - fofoOrderItem.getDiscount()) * fofoOrderItem.getQuantity());float igstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getIgstRate()) / 100;float cgstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getCgstRate()) / 100;float sgstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getSgstRate()) / 100;customFofoOrderItem.setIgstRate(fofoOrderItem.getIgstRate());customFofoOrderItem.setIgstAmount(igstAmount);customFofoOrderItem.setCgstRate(fofoOrderItem.getCgstRate());customFofoOrderItem.setCgstAmount(cgstAmount);customFofoOrderItem.setSgstRate(fofoOrderItem.getSgstRate());customFofoOrderItem.setSgstAmount(sgstAmount);customFofoOrderItem.setHsnCode(fofoOrderItem.getHsnCode());customerFofoOrderItems.add(customFofoOrderItem);}pdfModel.setTotalAmount(paymentOption.getAmount());pdfModel.setOrderItems(customerFofoOrderItems);}@Overridepublic InvoicePdfModel getInvoicePdfModel(FofoOrder fofoOrder) throws ProfitMandiBusinessException {List<PaymentOptionTransaction> paymentOptionTransactions = paymentOptionTransactionRepository.selectByReferenceIdAndTypes(fofoOrder.getId(), Arrays.asList(PaymentOptionReferenceType.ORDER, PaymentOptionReferenceType.INSURANCE));List<CustomPaymentOption> paymentOptions = new ArrayList<>();InvoicePdfModel pdfModel = new InvoicePdfModel();List<FofoOrderItem> fofoOrderItems = this.getByOrderId(fofoOrder.getId());double upgradePartnerDiscount = 0;/* for (FofoOrderItem fofoOrderItem : fofoOrderItems) {Set<String> serialNumbers = this.toSerialNumbers(fofoOrderItem.getFofoLineItems());for (String serialNumber : serialNumbers) {UpgradeOffer upgradeOffer = upgradeOfferRepository.selectBySerialNumber(serialNumber);if (upgradeOffer != null) {CustomerOfferItem customerOfferItem = customerOfferItemRepository.selectById(upgradeOffer.getCustomerOfferItemId());upgradePartnerDiscount += customerOfferItem.getDealerPayout();} else {upgradePartnerDiscount += 0;}}}*/boolean hasSamsungUpgrade = paymentOptionTransactions.stream().anyMatch(transaction ->"SAMSUNG UPGRADE".equals(paymentOptionRepository.selectById(transaction.getPaymentOptionId()).getName()));LOGGER.info("paymentOptionTransactions - {}", paymentOptionTransactions);LOGGER.info("hasSamsungUpgrade - {}", hasSamsungUpgrade);double cashDiscount = paymentOptionTransactions.stream().filter(x -> "CASH DISCOUNT".equals(paymentOptionRepository.selectById(x.getPaymentOptionId()).getName())).mapToDouble(x -> x.getAmount()).findFirst().orElse(0);LOGGER.info("cashDiscount - {}", cashDiscount);for (PaymentOptionTransaction paymentOptionTransaction : paymentOptionTransactions) {String paymentOptionName = paymentOptionRepository.selectById(paymentOptionTransaction.getPaymentOptionId()).getName();CustomPaymentOption cpi = new CustomPaymentOption();LOGGER.info("paymentOptionName {}", paymentOptionName);float amountToSet = paymentOptionTransaction.getAmount();if ("SAMSUNG UPGRADE".equals(paymentOptionName) && hasSamsungUpgrade) {if (cashDiscount > upgradePartnerDiscount) {amountToSet += (float) upgradePartnerDiscount;} else {amountToSet += (float) cashDiscount;}} else if ("CASH".equals(paymentOptionName) && !hasSamsungUpgrade) {amountToSet += ((float) cashDiscount - (float) upgradePartnerDiscount);} else if ("CASH".equals(paymentOptionName) && hasSamsungUpgrade && (cashDiscount > upgradePartnerDiscount)) {amountToSet += ((float) cashDiscount - (float) upgradePartnerDiscount);}cpi.setAmount(amountToSet);cpi.setPaymentOption(paymentOptionName);paymentOptions.add(cpi);}pdfModel.setTitle("Retailer Invoice");Optional<FofoOrderItem> fofoOrderItemOptional = fofoOrderItems.stream().findAny();if (fofoOrderItemOptional.isPresent() && fofoOrderItemOptional.get().equals("NOGST")) {pdfModel.setTitle("Security Deposit Receipt");}pdfModel.setPaymentOptions(paymentOptions);pdfModel.setAuther("SmartDukaan");pdfModel.setInvoiceDate(FormattingUtils.formatDate(fofoOrder.getCreateTimestamp()));// insurance calculationList<InsurancePolicy> insurancePolicies = insurancePolicyRepository.selectByRetailerIdInvoiceNumber(fofoOrder.getInvoiceNumber());List<CustomInsurancePolicy> customInsurancePolicies = new ArrayList<>();final float totalInsuranceTaxRate = 18;for (InsurancePolicy insurancePolicy : insurancePolicies) {float taxableInsurancePrice = insurancePolicy.getSaleAmount() / (1 + totalInsuranceTaxRate / 100);CustomInsurancePolicy customInsurancePolicy = new CustomInsurancePolicy();customInsurancePolicy.setDescription(insurancePolicy.getPolicyPlan() + " for Device #" + insurancePolicy.getSerialNumber() + "\n Plan Reference - " + insurancePolicy.getPolicyNumber());customInsurancePolicy.setHsnCode("998716");customInsurancePolicy.setRate(taxableInsurancePrice);customInsurancePolicy.setIgstRate(18);customInsurancePolicy.setIgstAmount(taxableInsurancePrice * 18 / 100);customInsurancePolicy.setCgstRate(9);customInsurancePolicy.setCgstAmount(taxableInsurancePrice * 9 / 100);customInsurancePolicy.setSgstRate(9);customInsurancePolicy.setSgstAmount(taxableInsurancePrice * 9 / 100);customInsurancePolicy.setNetAmount(insurancePolicy.getSaleAmount());customInsurancePolicies.add(customInsurancePolicy);}pdfModel.setInsurancePolicies(customInsurancePolicies);Retailer retailer = retailerRepository.selectById(fofoOrder.getFofoId());PrivateDealUser privateDealUser = null;try {privateDealUser = privateDealUserRepository.selectById(retailer.getId());} catch (ProfitMandiBusinessException profitMandiBusinessException) {LOGGER.error("Private Deal User not found : ", profitMandiBusinessException);}User user = userRepository.selectById(userAccountRepository.selectUserIdByRetailerId(retailer.getId()));CustomRetailer customRetailer = new CustomRetailer();customRetailer.setBusinessName(retailer.getName());customRetailer.setMobileNumber(user.getMobileNumber());// customRetailer.setTinNumber(retailer.getNumber());if (privateDealUser == null) {customRetailer.setGstNumber(null);} else {if (null != privateDealUser.getCounterId()) {Counter counter = counterRepository.selectById(privateDealUser.getCounterId());customRetailer.setGstNumber(counter.getGstin());} else {customRetailer.setGstNumber(null);}}Address retailerAddress = addressRepository.selectById(retailerRegisteredAddressRepository.selectAddressIdByRetailerId(retailer.getId()));customRetailer.setAddress(this.createCustomAddress(retailerAddress));pdfModel.setRetailer(customRetailer);pdfModel.setCustomer(getCustomCustomer(fofoOrder, customRetailer.getAddress()));pdfModel.setInvoiceNumber(fofoOrder.getInvoiceNumber());pdfModel.setTotalAmount(fofoOrder.getTotalAmount());List<CustomOrderItem> customerFofoOrderItems = new ArrayList<>();for (FofoOrderItem fofoOrderItem : fofoOrderItems) {float discount = fofoOrderItem.getDiscount();CustomOrderItem customFofoOrderItem = new CustomOrderItem();float totalTaxRate = fofoOrderItem.getIgstRate() + fofoOrderItem.getSgstRate() + fofoOrderItem.getCgstRate();float taxableSellingPrice = (fofoOrderItem.getSellingPrice() + discount) / (1 + totalTaxRate / 100);float taxableDiscountPrice = discount / (1 + totalTaxRate / 100);customFofoOrderItem.setAmount(fofoOrderItem.getQuantity() * (taxableSellingPrice - taxableDiscountPrice));customFofoOrderItem.setDescription(fofoOrderItem.getBrand() + " " + fofoOrderItem.getModelName() + " " + fofoOrderItem.getModelNumber() + "-" + fofoOrderItem.getColor());Set<String> serialNumbers = this.toSerialNumbers(fofoOrderItem.getFofoLineItems());List<FofoNonSerializeSerial> nonSerializeSerials = fofoNonSerializeSerialRepository.selectByItemIdAndOrderId(fofoOrderItem.getId());// Extract serial numbers from FofoNonSerializeSerial entitiesList<String> customSerialNumbers = nonSerializeSerials.stream().map(FofoNonSerializeSerial::getSerialNumber).collect(Collectors.toList());LOGGER.info("nonSerializeSerials {}", nonSerializeSerials);if (!serialNumbers.isEmpty()) {customFofoOrderItem.setDescription(customFofoOrderItem.getDescription() + "\n IMEIS - " + String.join(", ", serialNumbers));}if (!customSerialNumbers.isEmpty()) {customFofoOrderItem.setDescription(customFofoOrderItem.getDescription() + "\n SerialNumber - " + String.join(", ", customSerialNumbers));}customFofoOrderItem.setRate(taxableSellingPrice);customFofoOrderItem.setDiscount(taxableDiscountPrice);customFofoOrderItem.setQuantity(fofoOrderItem.getQuantity());customFofoOrderItem.setNetAmount(fofoOrderItem.getSellingPrice() * fofoOrderItem.getQuantity());float igstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getIgstRate()) / 100;float cgstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getCgstRate()) / 100;float sgstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getSgstRate()) / 100;customFofoOrderItem.setIgstRate(fofoOrderItem.getIgstRate());customFofoOrderItem.setIgstAmount(igstAmount);customFofoOrderItem.setCgstRate(fofoOrderItem.getCgstRate());customFofoOrderItem.setCgstAmount(cgstAmount);customFofoOrderItem.setSgstRate(fofoOrderItem.getSgstRate());customFofoOrderItem.setSgstAmount(sgstAmount);customFofoOrderItem.setHsnCode(fofoOrderItem.getHsnCode());customerFofoOrderItems.add(customFofoOrderItem);}pdfModel.setOrderItems(customerFofoOrderItems);String customerAddressStateCode = "";String partnerAddressStateCode = stateRepository.selectByName(pdfModel.getRetailer().getAddress().getState()).getCode();if (pdfModel.getCustomer() != null && pdfModel.getCustomer().getAddress() != null &&pdfModel.getCustomer().getAddress().getState() != null &&!pdfModel.getCustomer().getAddress().getState().trim().isEmpty()) {customerAddressStateCode = stateRepository.selectByName(pdfModel.getCustomer().getAddress().getState()).getCode();}pdfModel.setPartnerAddressStateCode(partnerAddressStateCode);if (!customerAddressStateCode.equals("")) {pdfModel.setCustomerAddressStateCode(customerAddressStateCode);}pdfModel.setCancelled(fofoOrder.getCancelledTimestamp() != null);List<String> tncs = new ArrayList<>();tncs.add("I agree that goods received are in good working condition.");tncs.add("Goods once sold cannot be exchanged or taken back.");tncs.add("Warranty for the goods received by me is the responsibility of the manufacturer only.");if (pdfModel.getInsurancePolicies() != null && pdfModel.getInsurancePolicies().size() > 0) {tncs.add("Extended Warranty/ Damage Protection related issues are to be handled directly by the respective providers.");}pdfModel.setTncs(tncs);return pdfModel;}private CustomCustomer getCustomCustomer(FofoOrder fofoOrder, CustomAddress retailerAddress) throwsProfitMandiBusinessException {Customer customer = customerRepository.selectById(fofoOrder.getCustomerId());CustomCustomer customCustomer = new CustomCustomer();customCustomer.setFirstName(customer.getFirstName());customCustomer.setLastName(customer.getLastName());customCustomer.setEmailId(customer.getEmailId());customCustomer.setMobileNumber(customer.getMobileNumber());customCustomer.setGstNumber(fofoOrder.getCustomerGstNumber());if (fofoOrder.getCustomerAddressId() != 0) {CustomerAddress customerAddress = customerAddressRepository.selectById(fofoOrder.getCustomerAddressId());customCustomer.setAddress(this.createCustomAddress(customerAddress));} else {customCustomer.setAddress(this.createCustomAddressWithoutId(customCustomer, retailerAddress));}return customCustomer;}@Overridepublic InvoicePdfModel getInvoicePdfModel(int fofoId, int orderId) throws ProfitMandiBusinessException {FofoOrder fofoOrder = fofoOrderRepository.selectByFofoIdAndOrderId(fofoId, orderId);return this.getInvoicePdfModel(fofoOrder);}public String getBillingAddress(CustomerAddress customerAddress) {StringBuilder address = new StringBuilder();if ((customerAddress.getLine1() != null) && (!customerAddress.getLine1().isEmpty())) {address.append(customerAddress.getLine1());address.append(", ");}if ((customerAddress.getLine2() != null) && (!customerAddress.getLine2().isEmpty())) {address.append(customerAddress.getLine2());address.append(", ");}if ((customerAddress.getLandmark() != null) && (!customerAddress.getLandmark().isEmpty())) {address.append(customerAddress.getLandmark());address.append(", ");}if ((customerAddress.getCity() != null) && (!customerAddress.getCity().isEmpty())) {address.append(customerAddress.getCity());address.append(", ");}if ((customerAddress.getState() != null) && (!customerAddress.getState().isEmpty())) {address.append(customerAddress.getState());}if ((customerAddress.getPinCode() != null) && (!customerAddress.getPinCode().isEmpty())) {address.append("- ");address.append(customerAddress.getPinCode());}return address.toString();}@Overridepublic List<CartFofo> cartCheckout(String cartJson) throws ProfitMandiBusinessException {try {JSONObject cartObject = new JSONObject(cartJson);Iterator<?> keys = cartObject.keys();Set<Integer> itemIds = new HashSet<>();List<CartFofo> cartItems = new ArrayList<CartFofo>();while (keys.hasNext()) {String key = (String) keys.next();if (cartObject.get(key) instanceof JSONObject) {LOGGER.info(cartObject.get(key).toString());}CartFofo cf = new CartFofo();cf.setItemId(cartObject.getJSONObject(key).getInt("itemId"));cf.setQuantity(cartObject.getJSONObject(key).getInt("quantity"));if (cartObject.getJSONObject(key).has("poId")) {cf.setPoId(cartObject.getJSONObject(key).getInt("poId"));cf.setPoItemId(cartObject.getJSONObject(key).getInt("poItemId"));}if (cf.getQuantity() <= 0) {continue;}cartItems.add(cf);itemIds.add(cartObject.getJSONObject(key).getInt("itemId"));}Map<Integer, Item> itemMap = new HashMap<Integer, Item>();if (itemIds.size() > 0) {List<Item> items = itemRepository.selectByIds(itemIds);for (Item i : items) {itemMap.put(i.getId(), i);}}for (CartFofo cf : cartItems) {Item i = itemMap.get(cf.getItemId());if (i == null) {continue;}cf.setDisplayName(getValidName(i.getBrand()) + " " + getValidName(i.getModelName()) + " " + getValidName(i.getModelNumber()) + " " + getValidName(i.getColor()).replaceAll("\\s+", " "));cf.setItemType(i.getType());}return cartItems;} catch (Exception e) {LOGGER.error("Unable to Prepare cart to place order...", e);throw new ProfitMandiBusinessException("cartData", cartJson, "FFORDR_1006");}}@Overridepublic Map<String, Object> getSaleHistory(int fofoId, SearchType searchType, String searchValue, LocalDateTimestartDate, LocalDateTime endDate, int offset, int limit) throws ProfitMandiBusinessException {long countItems = 0;List<FofoOrder> fofoOrders = new ArrayList<>();if (searchType == SearchType.CUSTOMER_MOBILE_NUMBER && !searchValue.isEmpty()) {fofoOrders = fofoOrderRepository.selectByFofoIdAndCustomerMobileNumber(fofoId, searchValue, null, null, offset, limit);countItems = fofoOrderRepository.selectCountByCustomerMobileNumber(fofoId, searchValue, null, null);} else if (searchType == SearchType.CUSTOMER_NAME && !searchValue.isEmpty()) {fofoOrders = fofoOrderRepository.selectByFofoIdAndCustomerName(fofoId, searchValue, null, null, offset, limit);countItems = fofoOrderRepository.selectCountByCustomerName(fofoId, searchValue, null, null);} else if (searchType == SearchType.IMEI && !searchValue.isEmpty()) {fofoOrders = fofoOrderRepository.selectByFofoIdAndSerialNumber(fofoId, searchValue, null, null, offset, limit);countItems = fofoOrderRepository.selectCountBySerialNumber(fofoId, searchValue, null, null);} else if (searchType == SearchType.ITEM_NAME && !searchValue.isEmpty()) {fofoOrders = fofoOrderRepository.selectByFofoIdAndItemName(fofoId, searchValue, null, null, offset, limit);countItems = fofoOrderRepository.selectCountByItemName(fofoId, searchValue, null, null);} else if (searchType == SearchType.INVOICE_NUMBER && !searchValue.isEmpty()) {fofoOrders = Arrays.asList(fofoOrderRepository.selectByFofoIdAndInvoiceNumber(fofoId, searchValue));countItems = fofoOrders.size();} else if (searchType == SearchType.DATE_RANGE) {fofoOrders = fofoOrderRepository.selectByFofoId(fofoId, startDate, endDate, offset, limit);countItems = fofoOrderRepository.selectCountByFofoId(fofoId, startDate, endDate);}Map<String, Object> map = new HashMap<>();map.put("saleHistories", fofoOrders);map.put("start", offset + 1);map.put("size", countItems);map.put("searchType", searchType);map.put("searchTypes", SearchType.values());map.put("startDate", startDate);map.put("searchValue", searchValue);map.put(ProfitMandiConstants.END_TIME, endDate);if (fofoOrders.size() < limit) {map.put("end", offset + fofoOrders.size());} else {map.put("end", offset + limit);}return map;}public ResponseEntity<?> downloadReportInCsv(org.apache.commons.io.output.ByteArrayOutputStreambaos, List<List<?>> rows, String fileName) {final HttpHeaders headers = new HttpHeaders();headers.set("Content-Type", "text/csv");headers.set("Content-disposition", "inline; filename=" + fileName + ".csv");headers.setContentLength(baos.toByteArray().length);final InputStream inputStream = new ByteArrayInputStream(baos.toByteArray());final InputStreamResource inputStreamResource = new InputStreamResource(inputStream);return new ResponseEntity<>(inputStreamResource, headers, HttpStatus.OK);}@Overridepublic Map<String, Object> getSaleHistoryPaginated(int fofoId, SearchType searchType, StringsearchValue, LocalDateTime startDate, LocalDateTime endDate, int offset, int limit) throwsProfitMandiBusinessException {List<FofoOrder> fofoOrders = new ArrayList<>();if (searchType == SearchType.CUSTOMER_MOBILE_NUMBER && !searchValue.isEmpty()) {fofoOrders = fofoOrderRepository.selectByFofoIdAndCustomerMobileNumber(fofoId, searchValue, startDate, endDate, offset, limit);} else if (searchType == SearchType.CUSTOMER_NAME && !searchValue.isEmpty()) {fofoOrders = fofoOrderRepository.selectByFofoIdAndCustomerName(fofoId, searchValue, startDate, endDate, offset, limit);} else if (searchType == SearchType.IMEI && !searchValue.isEmpty()) {fofoOrders = fofoOrderRepository.selectByFofoIdAndSerialNumber(fofoId, searchValue, startDate, endDate, offset, limit);} else if (searchType == SearchType.ITEM_NAME && !searchValue.isEmpty()) {fofoOrders = fofoOrderRepository.selectByFofoIdAndItemName(fofoId, searchValue, startDate, endDate, offset, limit);} else if (searchType == SearchType.DATE_RANGE) {fofoOrders = fofoOrderRepository.selectByFofoId(fofoId, startDate, endDate, offset, limit);}Map<String, Object> map = new HashMap<>();map.put("saleHistories", fofoOrders);map.put("searchType", searchType);map.put("searchTypes", SearchType.values());map.put("startDate", startDate);map.put("searchValue", searchValue);map.put(ProfitMandiConstants.END_TIME, endDate);return map;}private String getFofoStoreCode(int fofoId) throws ProfitMandiBusinessException {FofoStore fofoStore = fofoStoreRepository.selectByRetailerId(fofoId);return fofoStore.getCode();}private String getValidName(String name) {return name != null ? name : "";}private Set<String> toSerialNumbers(Set<FofoLineItem> fofoLineItems) {Set<String> serialNumbers = new HashSet<>();for (FofoLineItem fofoLineItem : fofoLineItems) {if (fofoLineItem.getSerialNumber() != null && !fofoLineItem.getSerialNumber().isEmpty()) {serialNumbers.add(fofoLineItem.getSerialNumber());}}return serialNumbers;}static final List<String> MOP_VOILATED_BRANDS = Arrays.asList("Live Demo", "Almost New");private void validateDpPrice(int fofoId, Map<Integer, PriceModel> itemIdMopPriceMap, Map<Integer, CustomFofoOrderItem> itemIdCustomFofoLineItemMap) throwsProfitMandiBusinessException {if (pricingService.getMopVoilatedRetailerIds().contains(fofoId)) return;for (Map.Entry<Integer, CustomFofoOrderItem> entry : itemIdCustomFofoLineItemMap.entrySet()) {int itemId = entry.getKey();CustomFofoOrderItem customFofoOrderItem = entry.getValue();LOGGER.info("CustomFofoOrderItem -- {}", customFofoOrderItem);PriceModel priceModel = itemIdMopPriceMap.get(itemId);Item item = itemRepository.selectById(itemId);// Comment this as of now 11 sep 2025 as per tarun sir/*if (!MOP_VOILATED_BRANDS.contains(item.getBrand()) && (item.getCategoryId() == ProfitMandiConstants.MOBILE_CATEGORY_ID || item.getCategoryId() == ProfitMandiConstants.TABLET_CATEGORY_ID || item.getCategoryId() == ProfitMandiConstants.LED_CATEGORY_ID) && customFofoOrderItem.getSerialNumberDetails().stream().filter(x -> org.apache.commons.lang.StringUtils.isNotEmpty(x.getSerialNumber())).collect(Collectors.toList()).size() > 0) {if (Utils.compareFloat(priceModel.getPrice(), customFofoOrderItem.getSellingPrice() + customFofoOrderItem.getDiscountAmount()) > 0) {throw new ProfitMandiBusinessException("Selling Price for ", item.getItemDescription(), "FFORDR_1010");}} else {if (!MOP_VOILATED_BRANDS.contains(item.getBrand()) && priceModel.getPurchasePrice() > customFofoOrderItem.getSellingPrice()) {throw new ProfitMandiBusinessException("Selling Price", itemRepository.selectById(itemId).getItemDescription(), "Selling Price should not be less than DP");}}*/}}private void validateMopPrice(int fofoId, Map<Integer, PriceModel> itemIdMopPriceMap, Map<Integer, CustomFofoOrderItem> itemIdCustomFofoLineItemMap) throwsProfitMandiBusinessException {if (pricingService.getMopVoilatedRetailerIds().contains(fofoId)) return;Map<Integer, Float> invalidMopItemIdPriceMap = new HashMap<>();for (Map.Entry<Integer, PriceModel> entry : itemIdMopPriceMap.entrySet()) {CustomFofoOrderItem customFofoOrderItem = itemIdCustomFofoLineItemMap.get(entry.getKey());Item item = itemRepository.selectById(customFofoOrderItem.getItemId());if (!(MOP_VOILATED_BRANDS.contains(item.getBrand()) || item.getCategoryId() != ProfitMandiConstants.MOBILE_CATEGORY_ID || item.getCategoryId() != ProfitMandiConstants.TABLET_CATEGORY_ID) && customFofoOrderItem.getSellingPrice() + customFofoOrderItem.getDiscountAmount() < entry.getValue().getPrice()) {invalidMopItemIdPriceMap.put(entry.getKey(), customFofoOrderItem.getSellingPrice());}}// Comment this as of now 11 sep 2025 as per tarun sir/*if (!invalidMopItemIdPriceMap.isEmpty()) {LOGGER.error("Invalid itemIds selling prices{} should be greater than mop prices {}", invalidMopItemIdPriceMap, itemIdMopPriceMap);throw new ProfitMandiBusinessException("invalidMopItemIdPrice", invalidMopItemIdPriceMap, "FFORDR_1010");}*/}private void updateInventoryItemsAndScanRecord(Set<InventoryItem> inventoryItems, int fofoId, Map<Integer, Integer> inventoryItemQuantityUsed, int fofoOrderId) {for (InventoryItem inventoryItem : inventoryItems) {inventoryItem.setLastScanType(ScanType.SALE);inventoryItem.setUpdateTimestamp(LocalDateTime.now());ScanRecord scanRecord = new ScanRecord();scanRecord.setInventoryItemId(inventoryItem.getId());scanRecord.setFofoId(fofoId);scanRecord.setOrderId(fofoOrderId);// correct thisscanRecord.setQuantity(inventoryItemQuantityUsed.get(inventoryItem.getId()));scanRecord.setType(ScanType.SALE);scanRecordRepository.persist(scanRecord);purchaseReturnItemRepository.deleteById(inventoryItem.getId());}}private void createFofoLineItem(int fofoOrderItemId, Set<InventoryItem> inventoryItems, Map<Integer, Integer> inventoryItemIdQuantityUsed) {for (InventoryItem inventoryItem : inventoryItems) {FofoLineItem fofoLineItem = new FofoLineItem();fofoLineItem.setFofoOrderItemId(fofoOrderItemId);fofoLineItem.setSerialNumber(inventoryItem.getSerialNumber());fofoLineItem.setInventoryItemId(inventoryItem.getId());fofoLineItem.setQuantity(inventoryItemIdQuantityUsed.get(inventoryItem.getId()));fofoLineItemRepository.persist(fofoLineItem);}}private FofoOrderItem createAndGetFofoOrderItem(CustomFofoOrderItem customFofoOrderItem, int fofoOrderId, Map<Integer, Item> itemMap, Set<InventoryItem> inventoryItems, Integer stateId) throwsProfitMandiBusinessException {FofoOrderItem fofoOrderItem = new FofoOrderItem();fofoOrderItem.setItemId(customFofoOrderItem.getItemId());fofoOrderItem.setQuantity(customFofoOrderItem.getQuantity());fofoOrderItem.setSellingPrice(customFofoOrderItem.getSellingPrice());fofoOrderItem.setPendingOrderItemId(customFofoOrderItem.getPoiId());fofoOrderItem.setOrderId(fofoOrderId);TagListing tl = tagListingRepository.selectByItemId(customFofoOrderItem.getItemId());// In case listing gets removed rebill it using the selling priceif (tl != null) {fofoOrderItem.setDp(tl.getSellingPrice());fofoOrderItem.setMop(tl.getMop());} else {fofoOrderItem.setDp(customFofoOrderItem.getSellingPrice());fofoOrderItem.setMop(customFofoOrderItem.getSellingPrice());}fofoOrderItem.setDiscount(customFofoOrderItem.getDiscountAmount());Item item = itemMap.get(customFofoOrderItem.getItemId());Map<Integer, GstRate> itemIdStateTaxRateMap = null;if (stateId != null) {itemIdStateTaxRateMap = stateGstRateRepository.getStateTaxRate(new ArrayList<>(itemMap.keySet()), stateId);} else {itemIdStateTaxRateMap = stateGstRateRepository.getIgstTaxRate(new ArrayList<>(itemMap.keySet()));}for (InventoryItem inventoryItem : inventoryItems) {fofoOrderItem.setIgstRate(itemIdStateTaxRateMap.get(inventoryItem.getItemId()).getIgstRate());fofoOrderItem.setCgstRate(itemIdStateTaxRateMap.get(inventoryItem.getItemId()).getCgstRate());fofoOrderItem.setSgstRate(itemIdStateTaxRateMap.get(inventoryItem.getItemId()).getSgstRate());fofoOrderItem.setHsnCode(inventoryItem.getHsnCode());break;}fofoOrderItem.setBrand(item.getBrand());fofoOrderItem.setModelName(item.getModelName());fofoOrderItem.setModelNumber(item.getModelNumber());fofoOrderItem.setColor(item.getColor());fofoOrderItemRepository.persist(fofoOrderItem);return fofoOrderItem;}private FofoOrderItem getDummyFofoOrderItem(int itemId, int fofoOrderId, String serialNumber, Integer stateId) throwsProfitMandiBusinessException {Item item = itemRepository.selectById(itemId);TagListing tl = tagListingRepository.selectByItemId(itemId);FofoOrderItem fofoOrderItem = new FofoOrderItem();fofoOrderItem.setItemId(itemId);fofoOrderItem.setQuantity(1);fofoOrderItem.setSellingPrice(tl.getMop());fofoOrderItem.setOrderId(fofoOrderId);// In case listing gets removed rebill it using the selling pricefofoOrderItem.setDp(tl.getSellingPrice());fofoOrderItem.setMop(tl.getMop());fofoOrderItem.setDiscount(0);Map<Integer, GstRate> itemIdStateTaxRateMap = null;if (stateId != null) {itemIdStateTaxRateMap = stateGstRateRepository.getStateTaxRate(Arrays.asList(itemId), stateId);} else {itemIdStateTaxRateMap = stateGstRateRepository.getIgstTaxRate(Arrays.asList(itemId));}fofoOrderItem.setIgstRate(itemIdStateTaxRateMap.get(itemId).getIgstRate());fofoOrderItem.setCgstRate(itemIdStateTaxRateMap.get(itemId).getCgstRate());fofoOrderItem.setSgstRate(itemIdStateTaxRateMap.get(itemId).getSgstRate());fofoOrderItem.setHsnCode(item.getHsnCode());fofoOrderItem.setBrand(item.getBrand());fofoOrderItem.setModelName(item.getModelName());fofoOrderItem.setModelNumber(item.getModelNumber());fofoOrderItem.setColor(item.getColor());Set<FofoLineItem> fofoLineItems = new HashSet<>();FofoLineItem fli = new FofoLineItem();fli.setQuantity(1);fli.setSerialNumber(serialNumber);fofoLineItems.add(fli);fofoOrderItem.setFofoLineItems(fofoLineItems);return fofoOrderItem;}private void updateCurrentInventorySnapshot(List<CurrentInventorySnapshot> currentInventorySnapshots,int fofoId, int itemId, int quantity) throws ProfitMandiBusinessException {for (CurrentInventorySnapshot currentInventorySnapshot : currentInventorySnapshots) {if (currentInventorySnapshot.getItemId() == itemId && currentInventorySnapshot.getFofoId() == fofoId) {currentInventorySnapshotRepository.updateAvailabilityByItemIdAndFofoId(itemId, fofoId, currentInventorySnapshot.getAvailability() - quantity);}}}private void createPaymentOptions(FofoOrder fofoOrder, Set<CustomPaymentOption> customPaymentOptions) throwsProfitMandiBusinessException {for (CustomPaymentOption customPaymentOption : customPaymentOptions) {if (customPaymentOption.getAmount() > 0) {PaymentOptionTransaction paymentOptionTransaction = new PaymentOptionTransaction();paymentOptionTransaction.setReferenceId(fofoOrder.getId());paymentOptionTransaction.setPaymentOptionId(customPaymentOption.getPaymentOptionId());paymentOptionTransaction.setReferenceType(PaymentOptionReferenceType.ORDER);paymentOptionTransaction.setAmount(customPaymentOption.getAmount());paymentOptionTransaction.setFofoId(fofoOrder.getFofoId());paymentOptionTransactionRepository.persist(paymentOptionTransaction);}}}private FofoOrder createAndGetFofoOrder(int customerId, String customerGstNumber, int fofoId, StringdocumentNumber, float totalAmount, int customerAddressId, int poId) {FofoOrder fofoOrder = new FofoOrder();fofoOrder.setCustomerGstNumber(customerGstNumber);fofoOrder.setCustomerId(customerId);fofoOrder.setFofoId(fofoId);fofoOrder.setPendingOrderId(poId);fofoOrder.setInvoiceNumber(documentNumber);fofoOrder.setTotalAmount(totalAmount);fofoOrder.setCustomerAddressId(customerAddressId);fofoOrderRepository.persist(fofoOrder);return fofoOrder;}private void validateItemsSerializedNonSerialized(List<Item> items, Map<Integer, CustomFofoOrderItem> customFofoOrderItemMap) throwsProfitMandiBusinessException {List<Integer> invalidItemIdSerialNumbers = new ArrayList<Integer>();List<Integer> itemIdNonSerializedSerialNumbers = new ArrayList<Integer>();for (Item i : items) {CustomFofoOrderItem customFofoOrderItem = customFofoOrderItemMap.get(i.getId());if (i.getType().equals(ItemType.SERIALIZED)) {if (customFofoOrderItem == null || customFofoOrderItem.getSerialNumberDetails().isEmpty()) {invalidItemIdSerialNumbers.add(i.getId());}} else {Set<String> serialNumbers = this.serialNumberDetailsToSerialNumbers(customFofoOrderItem.getSerialNumberDetails());if (customFofoOrderItem == null || !serialNumbers.isEmpty()) {itemIdNonSerializedSerialNumbers.add(i.getId());}}}if (!invalidItemIdSerialNumbers.isEmpty()) {LOGGER.error("Invalid itemId's serialNumbers for serialized{}", invalidItemIdSerialNumbers);// itemId's are serialized you are saying these are not serializedthrow new ProfitMandiBusinessException("invalidItemIdSerialNumbers", invalidItemIdSerialNumbers, "FFORDR_1013");}if (!itemIdNonSerializedSerialNumbers.isEmpty()) {LOGGER.error("Invalid itemId's serialNumbers for non serialized{}", itemIdNonSerializedSerialNumbers);// itemId's are non serialized you are saying these are serializedthrow new ProfitMandiBusinessException("itemIdNonSerializedSerialNumbers", itemIdNonSerializedSerialNumbers, "FFORDR_1014");}}private void validateCurrentInventorySnapshotQuantities(List<CurrentInventorySnapshot> currentInventorySnapshots, Map<Integer, CustomFofoOrderItem> itemIdCustomFofoOrderItemMap) throwsProfitMandiBusinessException {if (itemIdCustomFofoOrderItemMap.keySet().size() != currentInventorySnapshots.size()) {throw new ProfitMandiBusinessException("quantiiesSize", currentInventorySnapshots.size(), "");}List<ItemIdQuantityAvailability> itemIdQuantityAvailabilities = new ArrayList<>(); // this is for errorLOGGER.info("currentInventorySnapshots " + currentInventorySnapshots);LOGGER.info("CustomFofoLineItemMap {}", itemIdCustomFofoOrderItemMap);for (CurrentInventorySnapshot currentInventorySnapshot : currentInventorySnapshots) {CustomFofoOrderItem customFofoOrderItem = itemIdCustomFofoOrderItemMap.get(currentInventorySnapshot.getItemId());LOGGER.info("customFofoOrderItem {}", customFofoOrderItem);if (customFofoOrderItem.getQuantity() > currentInventorySnapshot.getAvailability()) {ItemIdQuantityAvailability itemIdQuantityAvailability = new ItemIdQuantityAvailability();itemIdQuantityAvailability.setItemId(customFofoOrderItem.getItemId());Quantity quantity = new Quantity();quantity.setAvailable(currentInventorySnapshot.getAvailability());quantity.setRequested(customFofoOrderItem.getQuantity());itemIdQuantityAvailability.setQuantity(quantity);itemIdQuantityAvailabilities.add(itemIdQuantityAvailability);}}if (!itemIdQuantityAvailabilities.isEmpty()) {// itemIdQuantity request is not validLOGGER.error("Requested quantities should not be greater than currently available quantities {}", itemIdQuantityAvailabilities);throw new ProfitMandiBusinessException("itemIdQuantityAvailabilities", itemIdQuantityAvailabilities, "FFORDR_1015");}}private int getItemIdFromSerialNumber(Map<Integer, CustomFofoOrderItem> itemIdCustomFofoOrderItemMap, StringserialNumber) {int itemId = 0;for (Map.Entry<Integer, CustomFofoOrderItem> entry : itemIdCustomFofoOrderItemMap.entrySet()) {Set<SerialNumberDetail> serialNumberDetails = entry.getValue().getSerialNumberDetails();for (SerialNumberDetail serialNumberDetail : serialNumberDetails) {if (serialNumberDetail.getSerialNumber().equals(serialNumber)) {itemId = entry.getKey();break;}}}return itemId;}private Map<Integer, Item> toItemMap(List<Item> items) {Function<Item, Integer> itemIdFunction = new Function<Item, Integer>() {@Overridepublic Integer apply(Item item) {return item.getId();}};Function<Item, Item> itemFunction = new Function<Item, Item>() {@Overridepublic Item apply(Item item) {return item;}};return items.stream().collect(Collectors.toMap(itemIdFunction, itemFunction));}private void setCustomerAddress(CustomerAddress customerAddress, CustomAddress customAddress) {customerAddress.setName(customAddress.getName());customerAddress.setLastName(customAddress.getLastName());customerAddress.setLine1(customAddress.getLine1());customerAddress.setLine2(customAddress.getLine2());customerAddress.setLandmark(customAddress.getLandmark());customerAddress.setCity(customAddress.getCity());customerAddress.setPinCode(customAddress.getPinCode());customerAddress.setState(customAddress.getState());customerAddress.setCountry(customAddress.getCountry());customerAddress.setPhoneNumber(customAddress.getPhoneNumber());}private CustomAddress createCustomAddress(Address address) {CustomAddress customAddress = new CustomAddress();customAddress.setName(address.getName());customAddress.setLine1(address.getLine1());customAddress.setLine2(address.getLine2());customAddress.setLandmark(address.getLandmark());customAddress.setCity(address.getCity());customAddress.setPinCode(address.getPinCode());customAddress.setState(address.getState());customAddress.setCountry(address.getCountry());customAddress.setPhoneNumber(address.getPhoneNumber());return customAddress;}private CustomAddress createCustomAddress(CustomerAddress customerAddress) {CustomAddress customAddress = new CustomAddress();customAddress.setName(customerAddress.getName());customAddress.setLastName(customerAddress.getLastName());customAddress.setLine1(customerAddress.getLine1());customAddress.setLine2(customerAddress.getLine2());customAddress.setLandmark(customerAddress.getLandmark());customAddress.setCity(customerAddress.getCity());customAddress.setPinCode(customerAddress.getPinCode());customAddress.setState(customerAddress.getState());customAddress.setCountry(customerAddress.getCountry());customAddress.setPhoneNumber(customerAddress.getPhoneNumber());return customAddress;}private CustomAddress createCustomAddressWithoutId(CustomCustomer customerAddress, CustomAddressretailerAddress) {CustomAddress customAddress = new CustomAddress();customAddress.setName(customerAddress.getFirstName());customAddress.setLastName(customerAddress.getLastName());customAddress.setLine1("");customAddress.setLine2("");customAddress.setLandmark("");customAddress.setCity(retailerAddress.getCity());customAddress.setPinCode(retailerAddress.getPinCode());customAddress.setState(retailerAddress.getState());customAddress.setCountry("");customAddress.setPhoneNumber(customerAddress.getMobileNumber());return customAddress;}private void validatePaymentOptionsAndTotalAmount(Set<CustomPaymentOption> customPaymentOptions,float totalAmount) throws ProfitMandiBusinessException {Set<Integer> paymentOptionIds = new HashSet<>();float calculatedAmount = 0;for (CustomPaymentOption customPaymentOption : customPaymentOptions) {paymentOptionIds.add(customPaymentOption.getPaymentOptionId());calculatedAmount = calculatedAmount + customPaymentOption.getAmount();}if (calculatedAmount != totalAmount) {LOGGER.warn("Error occured while validating payment options amount - {} != TotalAmount {}", calculatedAmount, totalAmount);throw new ProfitMandiBusinessException(ProfitMandiConstants.PAYMENT_OPTION_CALCULATED_AMOUNT, calculatedAmount, "FFORDR_1016");}List<Integer> foundPaymentOptionIds = paymentOptionRepository.selectIdsByIds(paymentOptionIds);if (foundPaymentOptionIds.size() != paymentOptionIds.size()) {paymentOptionIds.removeAll(foundPaymentOptionIds);throw new ProfitMandiBusinessException(ProfitMandiConstants.PAYMENT_OPTION_ID, paymentOptionIds, "FFORDR_1017");}}@Overridepublic List<FofoOrderItem> getByOrderId(int orderId) throws ProfitMandiBusinessException {List<FofoOrderItem> fofoOrderItems = fofoOrderItemRepository.selectByOrderId(orderId);if (!fofoOrderItems.isEmpty()) {List<FofoOrderItem> newFofoOrderItems = new ArrayList<>();Map<Integer, Set<FofoLineItem>> fofoOrderItemIdFofoLineItemsMap = this.toFofoOrderItemIdFofoLineItems(fofoOrderItems);Iterator<FofoOrderItem> fofoOrderItemsIterator = fofoOrderItems.iterator();while (fofoOrderItemsIterator.hasNext()) {FofoOrderItem fofoOrderItem = fofoOrderItemsIterator.next();fofoOrderItem.setFofoLineItems(fofoOrderItemIdFofoLineItemsMap.get(fofoOrderItem.getId()));newFofoOrderItems.add(fofoOrderItem);fofoOrderItemsIterator.remove();}fofoOrderItems = newFofoOrderItems;}return fofoOrderItems;}private Set<Integer> toFofoOrderItemIds(List<FofoOrderItem> fofoOrderItems) {Function<FofoOrderItem, Integer> fofoOrderItemToFofoOrderItemIdFunction = new Function<FofoOrderItem, Integer>() {@Overridepublic Integer apply(FofoOrderItem fofoOrderItem) {return fofoOrderItem.getId();}};return fofoOrderItems.stream().map(fofoOrderItemToFofoOrderItemIdFunction).collect(Collectors.toSet());}private Map<Integer, Set<FofoLineItem>> toFofoOrderItemIdFofoLineItems(List<FofoOrderItem> fofoOrderItems) throwsProfitMandiBusinessException {Set<Integer> fofoOrderItemIds = this.toFofoOrderItemIds(fofoOrderItems);List<FofoLineItem> fofoLineItems = fofoLineItemRepository.selectByFofoOrderItemIds(fofoOrderItemIds);Map<Integer, Set<FofoLineItem>> fofoOrderItemIdFofoLineItemsMap = new HashMap<>();for (FofoLineItem fofoLineItem : fofoLineItems) {if (!fofoOrderItemIdFofoLineItemsMap.containsKey(fofoLineItem.getFofoOrderItemId())) {Set<FofoLineItem> fofoLineItems2 = new HashSet<>();fofoLineItems2.add(fofoLineItem);fofoOrderItemIdFofoLineItemsMap.put(fofoLineItem.getFofoOrderItemId(), fofoLineItems2);} else {fofoOrderItemIdFofoLineItemsMap.get(fofoLineItem.getFofoOrderItemId()).add(fofoLineItem);}}return fofoOrderItemIdFofoLineItemsMap;}@Overridepublic void updateCustomerDetails(CustomCustomer customCustomer, String invoiceNumber) throwsProfitMandiBusinessException {FofoOrder fofoOrder = fofoOrderRepository.selectByInvoiceNumber(invoiceNumber);LOGGER.info("fofoOrder{}", fofoOrder);Customer customer = customerRepository.selectById(fofoOrder.getCustomerId());LOGGER.info("customer{}", customer);customer.setFirstName(customCustomer.getFirstName());customer.setLastName(customCustomer.getLastName());customer.setMobileNumber(customCustomer.getMobileNumber());customer.setEmailId(customCustomer.getEmailId());customerRepository.persist(customer);if (fofoOrder.getCustomerAddressId() == 0) {CustomAddress customAddress = customCustomer.getAddress();if (customAddress == null ||isNullOrEmpty(customAddress.getName()) ||isNullOrEmpty(customAddress.getLastName()) ||isNullOrEmpty(customAddress.getLine1()) ||isNullOrEmpty(customAddress.getCity()) ||isNullOrEmpty(customAddress.getPinCode()) ||isNullOrEmpty(customAddress.getState()) ||// isNullOrEmpty(customAddress.getCountry()) ||isNullOrEmpty(customAddress.getPhoneNumber())) {throw new IllegalArgumentException("Required customer address fields are missing.");}CustomerAddress customerAddress = new CustomerAddress();customerAddress.setCustomerId(fofoOrder.getCustomerId());customerAddress.setName(customAddress.getName());customerAddress.setLastName(customAddress.getLastName());customerAddress.setLine1(customAddress.getLine1());customerAddress.setLine2(customAddress.getLine2());customerAddress.setLandmark(customAddress.getLandmark());customerAddress.setCity(customAddress.getCity());customerAddress.setPinCode(customAddress.getPinCode());customerAddress.setState(customAddress.getState());// customerAddress.setCountry(customAddress.getCountry());customerAddress.setPhoneNumber(customAddress.getPhoneNumber());customerAddressRepository.persist(customerAddress);fofoOrder.setCustomerAddressId(customerAddress.getId());}CustomerAddress customerAddress = customerAddressRepository.selectById(fofoOrder.getCustomerAddressId());if (!customerAddress.getState().equalsIgnoreCase(customCustomer.getAddress().getState())) {List<FofoOrderItem> fofoOrderItems = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());resetTaxation(fofoOrder.getFofoId(), customerAddress, fofoOrderItems);}this.setCustomerAddress(customerAddress, customCustomer.getAddress());fofoOrder.setCustomerGstNumber(customCustomer.getGstNumber());}private boolean isNullOrEmpty(String str) {return str == null || str.trim().isEmpty();}private void resetTaxation(int fofoId, CustomerAddress customerAddress, List<FofoOrderItem> fofoOrderItems) throwsProfitMandiBusinessException {int retailerAddressId = retailerRegisteredAddressRepository.selectAddressIdByRetailerId(fofoId);Address retailerAddress = addressRepository.selectById(retailerAddressId);Integer stateId = null;if (customerAddress.getState().equalsIgnoreCase(retailerAddress.getState())) {try {stateId = Long.valueOf(stateRepository.selectByName(customerAddress.getState()).getId()).intValue();} catch (Exception e) {LOGGER.error("Unable to get state rates");}}List<Integer> itemIds = fofoOrderItems.stream().map(x -> x.getItemId()).collect(Collectors.toList());final Map<Integer, GstRate> gstRates;if (stateId != null) {gstRates = stateGstRateRepository.getStateTaxRate(itemIds, stateId);} else {gstRates = stateGstRateRepository.getIgstTaxRate(itemIds);}for (FofoOrderItem fofoOrderItem : fofoOrderItems) {GstRate rate = gstRates.get(fofoOrderItem.getItemId());fofoOrderItem.setCgstRate(rate.getCgstRate());fofoOrderItem.setSgstRate(rate.getSgstRate());fofoOrderItem.setIgstRate(rate.getIgstRate());}}@Overridepublic CustomerCreditNote badReturn(int fofoId, FoiBadReturnRequest foiBadReturnRequest) throwsProfitMandiBusinessException {return this.badReturn(null, fofoId, foiBadReturnRequest);}@Overridepublic CustomerCreditNote badReturn(String loginMail,int fofoId, FoiBadReturnRequest foiBadReturnRequest) throwsProfitMandiBusinessException {FofoOrderItem foi = fofoOrderItemRepository.selectById(foiBadReturnRequest.getFofoOrderItemId());FofoOrder fofoOrder = fofoOrderRepository.selectByOrderId(foi.getOrderId());if (fofoOrder.getFofoId() != fofoId) {throw new ProfitMandiBusinessException("Partner Auth", "", "Invalid Order");}int billedQty = foi.getQuantity() - customerReturnItemRepository.selectAllByOrderItemId(foi.getId()).size();if (foiBadReturnRequest.getMarkedBadArr().size() > billedQty) {throw new ProfitMandiBusinessException("Cant bad return more than what is billed", "", "Invalid Quantity");}List<CustomerReturnItem> customerReturnItems = new ArrayList<>();for (BadReturnRequest badReturnRequest : foiBadReturnRequest.getMarkedBadArr()) {CustomerReturnItem customerReturnItem = new CustomerReturnItem();customerReturnItem.setFofoId(fofoId);customerReturnItem.setFofoOrderItemId(foiBadReturnRequest.getFofoOrderItemId());customerReturnItem.setFofoOrderId(fofoOrder.getId());customerReturnItem.setRemarks(badReturnRequest.getRemarks());customerReturnItem.setInventoryItemId(badReturnRequest.getInventoryItemId());customerReturnItem.setQuantity(1);customerReturnItem.setType(ReturnType.BAD);// customerReturnItemRepository.persist(customerReturnItem);inventoryService.saleReturnInventoryItem(customerReturnItem);customerReturnItems.add(customerReturnItem);}CustomerCreditNote creditNote = generateCreditNote(fofoOrder, customerReturnItems);for (CustomerReturnItem customerReturnItem : customerReturnItems) {purchaseReturnService.returnInventoryItem(fofoId, false, customerReturnItem.getInventoryItemId(), ReturnType.BAD);}// This should cancel the orderfofoOrder.setCancelledTimestamp(LocalDateTime.now());this.reverseScheme(fofoOrder);return creditNote;}private CustomerCreditNote generateCreditNote(FofoOrderfofoOrder, List<CustomerReturnItem> customerReturnItems) throws ProfitMandiBusinessException {InvoiceNumberGenerationSequence sequence = invoiceNumberGenerationSequenceRepository.selectByFofoId(fofoOrder.getFofoId());sequence.setCreditNoteSequence(sequence.getCreditNoteSequence() + 1);invoiceNumberGenerationSequenceRepository.persist(sequence);String creditNoteNumber = sequence.getPrefix() + "/" + sequence.getCreditNoteSequence();CustomerCreditNote creditNote = new CustomerCreditNote();creditNote.setCreditNoteNumber(creditNoteNumber);creditNote.setFofoId(fofoOrder.getFofoId());creditNote.setFofoOrderId(fofoOrder.getId());creditNote.setFofoOrderItemId(customerReturnItems.get(0).getFofoOrderItemId());creditNote.setSettlementType(SettlementType.UNSETTLED);customerCreditNoteRepository.persist(creditNote);for (CustomerReturnItem customerReturnItem : customerReturnItems) {customerReturnItem.setCreditNoteId(creditNote.getId());customerReturnItemRepository.persist(customerReturnItem);}// this.returnInventoryItems(inventoryItems, debitNote);return creditNote;}@Overridepublic CreditNotePdfModel getCreditNotePdfModel(int customerCreditNoteId) throws ProfitMandiBusinessException {CustomerCreditNote creditNote = customerCreditNoteRepository.selectById(customerCreditNoteId);return getCreditNotePdfModel(creditNote);}private CreditNotePdfModel getCreditNotePdfModel(CustomerCreditNote creditNote) throwsProfitMandiBusinessException {FofoOrder fofoOrder = fofoOrderRepository.selectByOrderId(creditNote.getFofoOrderId());List<CustomerReturnItem> customerReturnItems = customerReturnItemRepository.selectAllByCreditNoteId(creditNote.getId());CustomRetailer customRetailer = retailerService.getFofoRetailer(fofoOrder.getFofoId());CustomCustomer customCustomer = getCustomCustomer(fofoOrder, customRetailer.getAddress());List<CustomOrderItem> customerFofoOrderItems = new ArrayList<>();FofoOrderItem fofoOrderItem = fofoOrderItemRepository.selectById(creditNote.getFofoOrderItemId());float totalTaxRate = fofoOrderItem.getIgstRate() + fofoOrderItem.getSgstRate() + fofoOrderItem.getCgstRate();float taxableSellingPrice = fofoOrderItem.getSellingPrice() / (1 + totalTaxRate / 100);float taxableDiscountPrice = fofoOrderItem.getDiscount() / (1 + totalTaxRate / 100);CustomOrderItem customFofoOrderItem = new CustomOrderItem();customFofoOrderItem.setAmount(customerReturnItems.size() * (taxableSellingPrice - taxableDiscountPrice));customFofoOrderItem.setDescription(fofoOrderItem.getBrand() + " " + fofoOrderItem.getModelName() + " " + fofoOrderItem.getModelNumber() + "-" + fofoOrderItem.getColor());if (ItemType.SERIALIZED.equals(itemRepository.selectById(fofoOrderItem.getItemId()).getType())) {Set<Integer> inventoryItemIds = customerReturnItems.stream().map(x -> x.getInventoryItemId()).collect(Collectors.toSet());List<String> serialNumbers = inventoryItemRepository.selectByIds(inventoryItemIds).stream().map(x -> x.getSerialNumber()).collect(Collectors.toList());customFofoOrderItem.setDescription(customFofoOrderItem.getDescription() + "\n IMEIS - " + String.join(", ", serialNumbers));}customFofoOrderItem.setRate(taxableSellingPrice);customFofoOrderItem.setDiscount(taxableDiscountPrice);customFofoOrderItem.setQuantity(customerReturnItems.size());customFofoOrderItem.setNetAmount((fofoOrderItem.getSellingPrice() - fofoOrderItem.getDiscount()) * customFofoOrderItem.getQuantity());float igstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getIgstRate()) / 100;float cgstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getCgstRate()) / 100;float sgstAmount = (customFofoOrderItem.getAmount() * fofoOrderItem.getSgstRate()) / 100;LOGGER.info("fofoOrderItem - {}", fofoOrderItem);customFofoOrderItem.setIgstRate(fofoOrderItem.getIgstRate());customFofoOrderItem.setIgstAmount(igstAmount);customFofoOrderItem.setCgstRate(fofoOrderItem.getCgstRate());customFofoOrderItem.setCgstAmount(cgstAmount);customFofoOrderItem.setSgstRate(fofoOrderItem.getSgstRate());customFofoOrderItem.setSgstAmount(sgstAmount);customFofoOrderItem.setHsnCode(fofoOrderItem.getHsnCode());customFofoOrderItem.setOrderId(1);customerFofoOrderItems.add(customFofoOrderItem);InvoicePdfModel pdfModel = new InvoicePdfModel();pdfModel.setAuther("NSSPL");pdfModel.setCustomer(customCustomer);pdfModel.setInvoiceNumber(fofoOrder.getInvoiceNumber());pdfModel.setInvoiceDate(FormattingUtils.formatDate(fofoOrder.getCreateTimestamp()));pdfModel.setTitle("Credit Note");pdfModel.setRetailer(customRetailer);pdfModel.setTotalAmount(customFofoOrderItem.getNetAmount());pdfModel.setOrderItems(customerFofoOrderItems);CreditNotePdfModel creditNotePdfModel = new CreditNotePdfModel();creditNotePdfModel.setCreditNoteDate(FormattingUtils.formatDate(creditNote.getCreateTimestamp()));creditNotePdfModel.setCreditNoteNumber(creditNote.getCreditNoteNumber());creditNotePdfModel.setPdfModel(pdfModel);return creditNotePdfModel;}// This will remove the order and maintain order record and reverse inventory// and scheme@Overridepublic void cancelOrder(List<String> invoiceNumbers) throws ProfitMandiBusinessException {for (String invoiceNumber : invoiceNumbers) {// Cancel only when not cancelledFofoOrder fofoOrder = fofoOrderRepository.selectByInvoiceNumber(invoiceNumber);if (fofoOrder.getCancelledTimestamp() == null) {fofoOrder.setCancelledTimestamp(LocalDateTime.now());PaymentOptionTransaction paymentTransaction = new PaymentOptionTransaction();paymentTransaction.setAmount(-fofoOrder.getTotalAmount());paymentTransaction.setFofoId(fofoOrder.getFofoId());paymentTransaction.setReferenceId(fofoOrder.getId());paymentTransaction.setReferenceType(PaymentOptionReferenceType.ORDER);paymentTransaction.setPaymentOptionId(1);paymentOptionTransactionRepository.persist(paymentTransaction);List<FofoOrderItem> fois = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());if (fois.size() > 0) {List<InventoryItem> inventoryItems = new ArrayList<>();fois.stream().forEach(x -> {x.getFofoLineItems().stream().forEach(y -> {inventoryService.rollbackInventory(y.getInventoryItemId(), y.getQuantity(), fofoOrder.getFofoId());inventoryItems.add(inventoryItemRepository.selectById(y.getInventoryItemId()));});});// if(invoice)this.reverseScheme(fofoOrder);}insuranceService.cancelInsurance(fofoOrder);}}}@Overridepublic void reverseScheme(FofoOrder fofoOrder) throws ProfitMandiBusinessException {String reversalReason = "Order Rolledback/Cancelled/Returned for Invoice #" + fofoOrder.getInvoiceNumber();List<FofoOrderItem> fois = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());Set<Integer> inventoryItemIds = fois.stream().flatMap(x -> x.getFofoLineItems().stream().map(y -> y.getInventoryItemId())).collect(Collectors.toSet());List<InventoryItem> inventoryItems = inventoryItemRepository.selectByIds(inventoryItemIds);schemeService.reverseSchemes(inventoryItems, fofoOrder.getId(), reversalReason, SchemeType.OUT_SCHEME_TYPES);//schemeService.reverseSchemes(inventoryItems, fofoOrder.getId(), reversalReason, Arrays.asList(SchemeType.INVESTMENT));schemeService.reverseSchemes(inventoryItems, fofoOrder.getId(), reversalReason, Arrays.asList(SchemeType.SPECIAL_SUPPORT));}@Overridepublic void reverseActivationScheme(List<Integer> inventoryItemIds) throws ProfitMandiBusinessException {List<InventoryItem> inventoryItems = inventoryItemRepository.selectAllByIds(inventoryItemIds);for (InventoryItem inventoryItem : inventoryItems) {List<FofoLineItem> fofoLineItems = fofoLineItemRepository.selectByInventoryItemId(inventoryItem.getId());FofoLineItem fofoLineItem = fofoLineItems.get(0);FofoOrderItem fofoOrderItem = fofoOrderItemRepository.selectById(fofoLineItem.getFofoOrderItemId());FofoOrder fofoOrder = fofoOrderRepository.selectByOrderId(fofoOrderItem.getOrderId());String reversalReason = "Scheme rolled back as activation date is invalid for imei " + inventoryItem.getSerialNumber();//schemeService.reverseSchemes(Arrays.asList(inventoryItem), fofoOrder.getId(), reversalReason, Arrays.asList(SchemeType.ACTIVATION));schemeService.reverseSchemes(Arrays.asList(inventoryItem), fofoOrder.getId(), reversalReason, Arrays.asList(SchemeType.SPECIAL_SUPPORT));}}@Overridepublic float getSales(int fofoId, LocalDateTime startDate, LocalDateTime endDate) {Float sales = fofoOrderRepository.selectSaleSumGroupByFofoIds(startDate, endDate).get(fofoId);return sales == null ? 0f : sales;}@Overridepublic LocalDateTime getMaxSalesDate(int fofoId, LocalDateTime startDate, LocalDateTime endDate) {LocalDateTime dateTime = fofoOrderRepository.selectMaxSaleDateGroupByFofoIds(startDate, endDate).get(fofoId);return dateTime;}@Override// Only being used internallypublic float getSales(int fofoId, LocalDate onDate) {LocalDateTime startTime = LocalDateTime.of(onDate, LocalTime.MIDNIGHT);LocalDateTime endTime = LocalDateTime.of(onDate, LocalTime.MIDNIGHT).plusDays(1);return this.getSales(fofoId, startTime, endTime);}@Overridepublic float getSales(LocalDateTime onDate) {// TODO Auto-generated method stubreturn 0;}@Overridepublic float getSales(LocalDateTime startDate, LocalDateTime endDate) {// TODO Auto-generated method stubreturn 0;}@Overridepublic boolean notifyColorChange(int orderId, int itemId) throws ProfitMandiBusinessException {Order order = orderRepository.selectById(orderId);saholicInventoryService.reservationCountByColor(itemId, order);order.getLineItem().setItemId(itemId);Item item = itemRepository.selectById(itemId);order.getLineItem().setColor(item.getColor());return true;}@Overridepublic FofoOrder getOrderByInventoryItemId(int inventoryItemId) throws Exception {List<FofoLineItem> lineItems = fofoLineItemRepository.selectByInventoryItemId(inventoryItemId);if (lineItems.size() > 0) {FofoOrderItem fofoOrderItem = fofoOrderItemRepository.selectById(lineItems.get(0).getFofoOrderItemId());fofoOrderItem.setFofoLineItems(new HashSet<>(lineItems));FofoOrder fofoOrder = fofoOrderRepository.selectByOrderId(fofoOrderItem.getOrderId());fofoOrder.setOrderItem(fofoOrderItem);return fofoOrder;} else {throw new Exception(String.format("Could not find inventoryItemId - %s", inventoryItemId));}}@Overridepublic Map<Integer, Long> carryBagCreditCount(int fofoId) throws ProfitMandiBusinessException {FofoStore fs = fofoStoreRepository.selectByRetailerId(fofoId);LocalDateTime lastCredit = fs.getBagsLastCredited();/** long carryBagCount = 0; List<FofoOrder> fofoOrders =* fofoOrderRepository.selectByFofoIdBetweenCreatedTimeStamp(fofoId,* lastCredit.atStartOfDay(), LocalDate.now().plusDays(1).atStartOfDay()); for* (FofoOrder fo : fofoOrders) { carryBagCount +=* fofoOrderItemRepository.selectByOrderId(fo.getId()).stream() .filter(x ->* x.getSellingPrice() >= 12000).count();** }*/Session session = sessionFactory.getCurrentSession();CriteriaBuilder cb = session.getCriteriaBuilder();CriteriaQuery<SimpleEntry> query = cb.createQuery(SimpleEntry.class);Root<FofoOrder> fofoOrder = query.from(FofoOrder.class);Root<FofoOrderItem> fofoOrderItem = query.from(FofoOrderItem.class);Root<TagListing> tagListingRoot = query.from(TagListing.class);Root<Item> itemRoot = query.from(Item.class);Predicate p2 = cb.between(fofoOrder.get(ProfitMandiConstants.CREATE_TIMESTAMP), lastCredit, LocalDate.now().atStartOfDay());Predicate p3 = cb.isNull(fofoOrder.get("cancelledTimestamp"));Predicate joinPredicate = cb.and(cb.equal(fofoOrder.get(ProfitMandiConstants.ID), fofoOrderItem.get(ProfitMandiConstants.ORDER_ID)), cb.equal(fofoOrderItem.get("itemId"), tagListingRoot.get("itemId")), cb.equal(itemRoot.get("id"), tagListingRoot.get("itemId")), cb.equal(fofoOrder.get(ProfitMandiConstants.FOFO_ID), fofoId));ItemCriteria itemCriteria = new ItemCriteria();itemCriteria.setBrands(mongoClient.getMongoBrands(fofoId, null, 3).stream().map(x -> (String) x.get("name")).collect(Collectors.toList()));float startValue = 12000;itemCriteria.setStartPrice(startValue);itemCriteria.setEndPrice(0);itemCriteria.setFeaturedPhone(false);itemCriteria.setSmartPhone(true);itemCriteria.setCatalogIds(new ArrayList<>());itemCriteria.setExcludeCatalogIds(new ArrayList<>());Predicate itemPredicate = itemRepository.getItemPredicate(itemCriteria, cb, itemRoot, tagListingRoot.get("itemId"), tagListingRoot.get("sellingPrice"));Predicate finalPredicate = cb.and(itemPredicate, p2, p3, joinPredicate);query = query.multiselect(fofoOrder.get(ProfitMandiConstants.FOFO_ID), cb.count(fofoOrder)).where(finalPredicate).groupBy(fofoOrder.get(ProfitMandiConstants.FOFO_ID));List<SimpleEntry> simpleEntries = session.createQuery(query).getResultList();Map<Integer, Long> returnMap = new HashMap<>();for (SimpleEntry simpleEntry : simpleEntries) {returnMap.put((Integer) simpleEntry.getKey(), (Long) simpleEntry.getValue());}return returnMap;}@Overridepublic void createMissingScratchOffers() {List<FofoOrder> fofoOrders = fofoOrderRepository.selectFromSaleDate(LocalDate.of(2023, 11, 6).atStartOfDay());for (FofoOrder fofoOrder : fofoOrders) {if (fofoOrder.getCancelledTimestamp() == null) { // Check if cancelled_timestamp is not nulltry {this.createScratchOffer(fofoOrder.getFofoId(), fofoOrder.getInvoiceNumber(), fofoOrder.getCustomerId());} catch (Exception e) {LOGGER.error("Error while processing missing scratch offer invoice orderId", fofoOrder.getId());}}}}@Overridepublic boolean refundOrder(int orderId, String refundedBy, String refundReason) throwsProfitMandiBusinessException {/*def refund_order(order_id, refunded_by, reason):"""If the order is in RTO_RECEIVED_PRESTINE, DOA_CERT_VALID or DOA_CERT_INVALID state, it does the following:1. Creates a refund request for batch processing.2. Creates a return order for the warehouse executive to return the shipped material.3. Marks the current order as RTO_REFUNDED, DOA_VALID_REFUNDED or DOA_INVALID_REFUNDED final states.If the order is in SUBMITTED_FOR_PROCESSING or INVENTORY_LOW state, it does the following:1. Creates a refund request for batch processing.2. Cancels the reservation of the item in the warehouse.3. Marks the current order as the REFUNDED final state.For all COD orders, if the order is in INIT, SUBMITTED_FOR_PROCESSING or INVENTORY_LOW state, it does the following:1. Cancels the reservation of the item in the warehouse.2. Marks the current order as CANCELED.In all cases, it updates the reason for cancellation or refund and the person who performed the action.Returns True if it is successful, False otherwise.Throws an exception if the order with the given id couldn't be found.Parameters:- order_id- refunded_by- reason"""LOGGER.info("Refunding order id: {}", orderId);Order order = orderRepository.selectById(orderId);if order.cod:logging.info("Refunding COD order with status " + str(order.status))status_transition = refund_status_transitionif order.status not in status_transition.keys():raise TransactionServiceException(114, "This order can't be refunded")if order.status in [OrderStatus.COD_VERIFICATION_PENDING, OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT, OrderStatus.ACCEPTED]:__update_inventory_reservation(order, refund=True)order.statusDescription = "Order Cancelled"#Shipment Id and Airway Bill No should be none in case of Cancellationorder.logisticsTransactionId = Noneorder.tracking_id = Noneorder.airwaybill_no = Noneelif order.status == OrderStatus.BILLED:__create_return_order(order)order.statusDescription = "Order Cancelled"elif order.status in [OrderStatus.RTO_RECEIVED_PRESTINE, OrderStatus.RTO_RECEIVED_DAMAGED, OrderStatus.RTO_LOST_IN_TRANSIT]:if order.status != OrderStatus.RTO_LOST_IN_TRANSIT:__create_return_order(order)order.statusDescription = "RTO Refunded"elif order.status in [OrderStatus.LOST_IN_TRANSIT]:#__create_return_order(order)order.statusDescription = "Lost in Transit Refunded"elif order.status in [OrderStatus.DOA_CERT_INVALID, OrderStatus.DOA_CERT_VALID, OrderStatus.DOA_RECEIVED_DAMAGED, OrderStatus.DOA_LOST_IN_TRANSIT] :if order.status != OrderStatus.DOA_LOST_IN_TRANSIT:__create_return_order(order)__create_refund(order, 0, 'Should be unreachable for now')order.statusDescription = "DOA Refunded"elif order.status in [OrderStatus.RET_PRODUCT_UNUSABLE, OrderStatus.RET_PRODUCT_USABLE, OrderStatus.RET_RECEIVED_DAMAGED, OrderStatus.RET_LOST_IN_TRANSIT] :if order.status != OrderStatus.RET_LOST_IN_TRANSIT:__create_return_order(order)__create_refund(order, 0, 'Should be unreachable for now')order.statusDescription = "Return Refunded"elif order.status == OrderStatus.CANCEL_REQUEST_CONFIRMED:if order.previousStatus in [OrderStatus.COD_VERIFICATION_PENDING, OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT, OrderStatus.ACCEPTED]:__update_inventory_reservation(order, refund=True)order.statusDescription = "Order Cancelled on customer request"elif order.previousStatus == OrderStatus.BILLED:__create_return_order(order)order.statusDescription = "Order Cancelled on customer request"order.received_return_timestamp = datetime.datetime.now()else:status_transition = {OrderStatus.LOST_IN_TRANSIT : OrderStatus.LOST_IN_TRANSIT_REFUNDED,OrderStatus.RTO_RECEIVED_PRESTINE : OrderStatus.RTO_REFUNDED,OrderStatus.RTO_RECEIVED_DAMAGED : OrderStatus.RTO_DAMAGED_REFUNDED,OrderStatus.RTO_LOST_IN_TRANSIT : OrderStatus.RTO_LOST_IN_TRANSIT_REFUNDED,OrderStatus.DOA_CERT_INVALID : OrderStatus.DOA_INVALID_REFUNDED,OrderStatus.DOA_CERT_VALID : OrderStatus.DOA_VALID_REFUNDED,OrderStatus.DOA_RECEIVED_DAMAGED : OrderStatus.DOA_REFUNDED_RCVD_DAMAGED,OrderStatus.DOA_LOST_IN_TRANSIT : OrderStatus.DOA_REFUNDED_LOST_IN_TRANSIT,OrderStatus.RET_PRODUCT_UNUSABLE : OrderStatus.RET_PRODUCT_UNUSABLE_REFUNDED,OrderStatus.RET_PRODUCT_USABLE : OrderStatus.RET_PRODUCT_USABLE_REFUNDED,OrderStatus.RET_RECEIVED_DAMAGED : OrderStatus.RET_REFUNDED_RCVD_DAMAGED,OrderStatus.RET_LOST_IN_TRANSIT : OrderStatus.RET_REFUNDED_LOST_IN_TRANSIT,OrderStatus.SUBMITTED_FOR_PROCESSING : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,OrderStatus.INVENTORY_LOW : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,OrderStatus.LOW_INV_PO_RAISED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,OrderStatus.LOW_INV_REVERSAL_IN_PROCESS : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,OrderStatus.ACCEPTED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,OrderStatus.BILLED : OrderStatus.CANCELLED_DUE_TO_LOW_INVENTORY,OrderStatus.CANCEL_REQUEST_CONFIRMED : OrderStatus.CANCELLED_ON_CUSTOMER_REQUEST,OrderStatus.PAYMENT_FLAGGED : OrderStatus.PAYMENT_FLAGGED_DENIED}if order.status not in status_transition.keys():raise TransactionServiceException(114, "This order can't be refunded")if order.status in [OrderStatus.RTO_RECEIVED_PRESTINE, OrderStatus.RTO_RECEIVED_DAMAGED, OrderStatus.RTO_LOST_IN_TRANSIT] :if order.status != OrderStatus.RTO_LOST_IN_TRANSIT:__create_return_order(order)__create_refund(order, order.wallet_amount, 'Order #{0} is RTO refunded'.format(order.id))order.statusDescription = "RTO Refunded"#Start:- Added By Manish Sharma for Creating a new Ticket: Category- RTO Refund on 21-Jun-2013try:crmServiceClient = CRMClient().get_client()ticket =Ticket()activity = Activity()description = "Creating Ticket for " + order.statusDescription + " Order"ticket.creatorId = 1ticket.assigneeId = 34ticket.category = TicketCategory.RTO_REFUNDticket.priority = TicketPriority.MEDIUMticket.status = TicketStatus.OPENticket.description = descriptionticket.orderId = order.idactivity.creatorId = 1activity.ticketAssigneeId = ticket.assigneeIdactivity.type = ActivityType.OTHERactivity.description = descriptionactivity.ticketCategory = ticket.categoryactivity.ticketDescription = ticket.descriptionactivity.ticketPriority = ticket.priorityactivity.ticketStatus = ticket.statusticket.customerId= order.customer_idticket.customerEmailId = order.customer_emailticket.customerMobileNumber = order.customer_mobilenumberticket.customerName = order.customer_nameactivity.customerId = ticket.customerIdactivity.customerEmailId = order.customer_emailactivity.customerMobileNumber = order.customer_mobilenumberactivity.customerName = order.customer_namecrmServiceClient.insertTicket(ticket, activity)except:print "Ticket for RTO Refund is not created."#End:- Added By Manish Sharma for Creating a new Ticket: Category- RTO Refund on 21-Jun-2013elif order.status in [OrderStatus.LOST_IN_TRANSIT]:#__create_return_order(order)__create_refund(order, order.wallet_amount, 'Order #{0} is Lost in Transit'.format(order.id))order.statusDescription = "Lost in Transit Refunded"elif order.status in [OrderStatus.DOA_CERT_INVALID, OrderStatus.DOA_CERT_VALID, OrderStatus.DOA_RECEIVED_DAMAGED, OrderStatus.DOA_LOST_IN_TRANSIT] :if order.status != OrderStatus.DOA_LOST_IN_TRANSIT:__create_return_order(order)__create_refund(order, 0, 'This should be unreachable')order.statusDescription = "DOA Refunded"elif order.status in [OrderStatus.RET_PRODUCT_UNUSABLE, OrderStatus.RET_PRODUCT_USABLE, OrderStatus.RET_RECEIVED_DAMAGED, OrderStatus.RET_LOST_IN_TRANSIT] :if order.status != OrderStatus.RET_LOST_IN_TRANSIT:__create_return_order(order)__create_refund(order, 0, 'This should be unreachable')order.statusDescription = "Return Refunded"elif order.status in [OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT, OrderStatus.ACCEPTED]:__update_inventory_reservation(order, refund=True)order.statusDescription = "Order Refunded"elif order.status == OrderStatus.CANCEL_REQUEST_CONFIRMED:if order.previousStatus in [OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.INVENTORY_LOW, OrderStatus.LOW_INV_PO_RAISED, OrderStatus.LOW_INV_REVERSAL_IN_PROCESS, OrderStatus.LOW_INV_NOT_AVAILABLE_AT_HOTSPOT, OrderStatus.PAYMENT_FLAGGED, OrderStatus.ACCEPTED]:__update_inventory_reservation(order, refund=True)order.statusDescription = "Order Cancelled on customer request"elif order.previousStatus == OrderStatus.BILLED:__create_refund(order, order.wallet_amount, 'Order #{0} Cancelled on customer request'.format(order.id))order.statusDescription = "Order Cancelled on customer request"elif order.status == OrderStatus.PAYMENT_FLAGGED:__update_inventory_reservation(order, refund=True)order.statusDescription = "Order Cancelled due to payment flagged"# For orders that are cancelled after being billed, we need to scan in the scanned out# inventory item and change availability accordinglyinventoryClient = InventoryClient().get_client()warehouse = inventoryClient.getWarehouse(order.warehouse_id)if warehouse.billingType == BillingType.OURS or warehouse.billingType == BillingType.OURS_EXTERNAL:#Now BILLED orders can also be refunded directly with low inventory cancellationsif order.status in [OrderStatus.BILLED, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_FROM_WH]:__create_refund(order, order.wallet_amount, reason)if order.status in [OrderStatus.BILLED, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_FROM_WH] or (order.status == OrderStatus.CANCEL_REQUEST_CONFIRMED and order.previousStatus in [OrderStatus.BILLED, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.SHIPPED_FROM_WH]):lineitem = order.lineitems[0]catalogClient = CatalogClient().get_client()item = catalogClient.getItem(lineitem.item_id)warehouseClient = WarehouseClient().get_client()if warehouse.billingType == BillingType.OURS:if ItemType.SERIALIZED == item.type:for serial_number in str(lineitem.serial_number).split(','):warehouseClient.scanSerializedItemForOrder(serial_number, ScanType.SALE_RET, order.id, order.fulfilmentWarehouseId, 1, order.warehouse_id)else:warehouseClient.scanForOrder(None, ScanType.SALE_RET, lineitem.quantity, order.id, order.fulfilmentWarehouseId, order.warehouse_id)if warehouse.billingType == BillingType.OURS_EXTERNAL:warehouseClient.scanForOursExternalSaleReturn(order.id, lineitem.transfer_price)if order.freebieItemId:warehouseClient.scanfreebie(order.id, order.freebieItemId, 0, ScanType.SALE_RET)order.status = status_transition[order.status]order.statusDescription = OrderStatus._VALUES_TO_NAMES[order.status]order.refund_timestamp = datetime.datetime.now()order.refunded_by = refunded_byorder.refund_reason = reason#to re evaluate the shipping charge if any order is being cancelled.#_revaluate_shiping(order_id)session.commit()return True*/return true;}@AutowiredDebitNoteRepository debitNoteRepository;//initiate refund only if the stock is returned}