Rev 35971 | View as "text/plain" | Blame | Compare with Previous | Last modification | View Log | RSS feed
package com.spice.profitmandi.service.user;import com.fasterxml.jackson.databind.ObjectMapper;import com.google.common.hash.Hashing;import com.google.gson.Gson;import com.spice.profitmandi.common.enumuration.ActivationType;import com.spice.profitmandi.common.enumuration.FofoType;import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;import com.spice.profitmandi.common.model.*;import com.spice.profitmandi.common.util.StringUtils;import com.spice.profitmandi.common.util.Utils;import com.spice.profitmandi.dao.entity.catalog.BrandCatalog;import com.spice.profitmandi.dao.entity.dtr.*;import com.spice.profitmandi.dao.entity.dtr.User;import com.spice.profitmandi.dao.entity.fofo.*;import com.spice.profitmandi.dao.entity.inventory.State;import com.spice.profitmandi.dao.entity.logistics.AST;import com.spice.profitmandi.dao.entity.logistics.ASTRepository;import com.spice.profitmandi.dao.entity.user.*;import com.spice.profitmandi.dao.enumuration.dtr.AccountType;import com.spice.profitmandi.dao.enumuration.dtr.RetailerType;import com.spice.profitmandi.dao.enumuration.dtr.RoleType;import com.spice.profitmandi.dao.enumuration.fofo.PaymentOptionType;import com.spice.profitmandi.dao.enumuration.transaction.PartnerVerificationApprovalStatus;import com.spice.profitmandi.dao.model.LastMonthCreditedIncomeModel;import com.spice.profitmandi.dao.repository.dtr.*;import com.spice.profitmandi.dao.repository.dtr.UserRepository;import com.spice.profitmandi.dao.repository.fofo.*;import com.spice.profitmandi.dao.repository.inventory.StateRepository;import com.spice.profitmandi.dao.repository.trialOnboarding.TrialFormRepository;import com.spice.profitmandi.dao.repository.user.*;import com.spice.profitmandi.service.PostOfficeService;import com.spice.profitmandi.service.catalog.BrandsService;import in.shop2020.model.v1.user.CartStatus;import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.cache.annotation.Cacheable;import org.springframework.mail.javamail.JavaMailSender;import org.springframework.stereotype.Component;import java.nio.charset.StandardCharsets;import java.time.LocalDate;import java.time.LocalDateTime;import java.time.YearMonth;import java.time.format.DateTimeFormatter;import java.util.*;import java.util.function.Function;import java.util.stream.Collectors;import java.util.stream.Stream;@Componentpublic class RetailerServiceImpl implements RetailerService {private static final Logger LOGGER = LogManager.getLogger(RetailerServiceImpl.class);private static final String[] TRIAL_CODE_CREATION_AUDIENCE = new String[]{"amit.gupta@smartdukaan.com"};//private static final String [] TRIAL_CODE_CREATION_AUDIENCE = new String[]{};@Autowiredprivate RetailerRepository retailerRepository;@Autowiredprivate RetailerBlockBrandsRepository retailerBlockBrandsRepository;@Autowiredprivate UserAccountRepository userAccountRepository;@Autowiredprivate Mongo mongoClient;@AutowiredGson gson;@Autowiredprivate UserRepository userRepository;@AutowiredObjectMapper objectMapper;@Autowiredprivate CartRepository cartRepository;@Autowiredprivate RetailerRegisteredAddressRepository retailerRegisteredAddressRepository;@Autowiredprivate AddressRepository addressRepository;@Autowiredprivate ShopRepository shopRepository;@Autowiredprivate ShopAddressRepository shopAddressRepository;@Autowiredprivate UserRoleRepository userRoleRepository;@Autowiredprivate DocumentRepository documentRepository;@Autowiredprivate PrivateDealUserRepository privateDealUserRepository;@Autowiredprivate RetailerContactRepository retailerContactRepository;@Autowiredprivate PrivateDealUserAddressMappingRepository privateDealUserAddressMappingRepository;@Autowiredprivate CounterRepository counterRepository;@Autowiredprivate StateRepository stateRepository;@Autowiredprivate TrialFormRepository trialFormRepository;@Autowired@Qualifier("userUserRepository")private com.spice.profitmandi.dao.repository.user.UserRepository userUserRepository;@Autowiredprivate DistrictMasterRepository districtMasterRepository;@Autowiredprivate FofoStoreRepository fofoStoreRepository;@Autowiredprivate ASTRepository aSTRepository;@Autowiredprivate PostOfficeService postOfficeService;@Autowiredprivate PaymentOptionRepository paymentOptionRepository;@Autowiredprivate FofoPartnerPaymentOptionRepository fofoPartnerPaymentOptionRepository;@Autowiredprivate RoleRepository roleRepository;@Autowiredprivate StoreTimelineTatService storeTimelineTatService;@Autowiredprivate PartnerOnBoardingPanelRepository partnerOnBoardingPanelRepository;@Autowiredprivate PartnerOnboardingVerificationRepository partnerOnboardingVerificationRepository;@Autowiredprivate PincodePartnerRepository pincodePartnerRepository;@AutowiredSchemeInOutRepository schemeInOutRepository;@AutowiredOfferPayoutRepository offerPayoutRepository;@AutowiredPartnerTypeChangeService partnerTypeChangeService;@AutowiredBrandsService brandsService;@Autowiredprivate JavaMailSender googleMailSender;@Overridepublic Map<String, Object> getByEmailIdOrMobileNumber(String emailIdOrMobileNumber) throws ProfitMandiBusinessException {User user = null;int fofoId = Utils.SYSTEM_PARTNER_ID;try {user = userRepository.selectByEmailIdOrMobileNumber(emailIdOrMobileNumber);} catch (ProfitMandiBusinessException profitMandiBusinessException) {}if (user == null) {try {user = userRepository.selectBySecondryEmailId(emailIdOrMobileNumber);} catch (ProfitMandiBusinessException profitMandiBusinessException) {}}Map<String, Object> map = new HashMap<>();map.put("stateNames", stateRepository.selectAll().stream().map(State::getName).collect(Collectors.toList()));LOGGER.info("user - {}", user);if (user != null) {List<UserRole> userRoles = userRoleRepository.selectByUserId(user.getId());Role role = roleRepository.selectByName(RoleType.FOFO.toString());map.put("userRoles", userRoles);map.put("user", user);// map.put("retailer", retailer);map.put("fofoRole", this.containsRoleType(userRoles, role.getId()));map.put("userRoleNames", this.toString(userRoles));try {int retailerId = userAccountRepository.selectRetailerIdByUserId(user.getId());Retailer retailer = retailerRepository.selectById(retailerId);map.put("retailer", retailer);List<String> retailerBlockBrands = null;Set<String> brands = null;if (retailer.getId() != fofoId) {brands = brandsService.getBrands(retailer.getId(), null, 3).stream().map(BrandCatalog::getName).collect(Collectors.toSet());retailerBlockBrands = brandsService.partnerIneligibleBrands(fofoId);} else {LOGGER.info("fofoId" + fofoId);brands = brandsService.getBrands(fofoId, null, 3).stream().map(BrandCatalog::getName).collect(Collectors.toSet());}map.put("brands", brands);map.put("retailerBlockBrands", retailerBlockBrands);try {FofoStore gstStore = fofoStoreRepository.selectByRetailerId(retailer.getId());map.put("gstNumber", gstStore != null ? gstStore.getGstNumber() : null);} catch (ProfitMandiBusinessException e) {LOGGER.error("FofoStore not found for GST lookup");}try {int retailerAddressId = retailerRegisteredAddressRepository.selectAddressIdByRetailerId(retailer.getId());Address retailerAddress = addressRepository.selectById(retailerAddressId);map.put("retailerAddress", retailerAddress);State state = stateRepository.selectByName(retailerAddress.getState());// LOGGER.info("retailerAddress.." + retailerAddress);List<DistrictMaster> districtMasters = districtMasterRepository.selectByStateShortName(state.getShortName());map.put("districtMasters", districtMasters);// LOGGER.info("districtMasters" + districtMasters);List<Shop> shops = shopRepository.selectByRetailerId(retailer.getId());map.put("shops", shops);this.addAddress(shops);if (this.containsRoleType(userRoles, role.getId())) {try {FofoStore fofoStore = fofoStoreRepository.selectByRetailerId(retailerId);map.put("fofoStore", fofoStore);List<AST> astDetail = postOfficeService.getAreasAndTerritoriesByStateName(retailerAddress.getState());LOGGER.info("astDetail {}", astDetail);map.put("astDetail", astDetail);// map.put("counterSize", fofoStore.getCounterSize().toString());// LOGGER.info("fofoStore" + fofoStore);} catch (ProfitMandiBusinessException profitMandiBusinessException) {LOGGER.error("FofoStore code not found");}}// LOGGER.info("shops" + shops);} catch (ProfitMandiBusinessException profitMandiBusinessException) {LOGGER.error("Retailer Registered Address not found");}} catch (ProfitMandiBusinessException profitMandiBusinessException) {LOGGER.error("Retailer not found in user_account");}} else {try {TrialForm trialForm = trialFormRepository.selectByEmailOrMobile(emailIdOrMobileNumber);LOGGER.info("trialForm - {}", trialForm);map.put("trialForm", gson.toJson(trialForm));} catch (Exception e) {LOGGER.error("Retailer not found in user_account");}}return map;}private boolean containsRoleType(List<UserRole> userRoles, int roleId) {return userRoles != null && userRoles.stream().anyMatch(ur -> ur.getRoleId() == roleId);}private List<UserRole> addRole(List<UserRole> userRoles, int userId, int roleId) {if (userRoles == null) {userRoles = new ArrayList<>();}if (!this.containsRoleType(userRoles, roleId)) {UserRole userRole = new UserRole();userRole.setUserId(userId);userRole.setRoleId(roleId);try {userRoleRepository.persist(userRole);} catch (ProfitMandiBusinessException e) {LOGGER.error("UserRole is already exist");}userRoles.add(userRole);}return userRoles;}private List<UserRole> removeRole(List<UserRole> userRoles, int userId, int roleId) {if (userRoles == null) {userRoles = new ArrayList<>();return userRoles;}try {userRoles.remove(userRoleRepository.deleteByRoleUserId(userId, roleId));} catch (Exception e) {}return userRoles;}@SuppressWarnings("unchecked")@Overridepublic Map<String, Object> updateRetailerDetails(UpdateRetailerRequest updateRetailerRequest) throwsProfitMandiBusinessException {Map<String, Object> map = this.getByEmailIdOrMobileNumber(updateRetailerRequest.getEmailIdOrMobileNumber());User dtrUser = (User) map.get("user");dtrUser = this.createUser(dtrUser, updateRetailerRequest);map.put("user", dtrUser);List<UserRole> userRoles = (List<UserRole>) map.get("userRoles");Role roleUser = roleRepository.selectByName(RoleType.USER.toString());userRoles = this.addRole(userRoles, dtrUser.getId(), roleUser.getId());Retailer retailer = (Retailer) map.get("retailer");retailer = this.updateRetailer(dtrUser, retailer, updateRetailerRequest);map.put("retailer", retailer);// Ensure UserAccount links new dtr user to retailer (handles case where// dtr.user was deleted and re-created with a new ID)try {userAccountRepository.selectSaholicByUserId(dtrUser.getId());} catch (ProfitMandiBusinessException e) {try {UserAccount ua = new UserAccount();ua.setAccountKey(retailer.getId());ua.setUserId(dtrUser.getId());ua.setType(AccountType.saholic);userAccountRepository.persist(ua);} catch (Exception ex) {LOGGER.error("Error creating saholic UserAccount for userId: {}", dtrUser.getId(), ex);}}List<String> retailerBlockBrands = retailerBlockBrandsRepository.selectAllByRetailer(retailer.getId()).stream().map(x -> x.getBlockBrands()).collect(Collectors.toList());LOGGER.info("retailerBlockBrands" + retailerBlockBrands);if (!retailerBlockBrands.isEmpty()) {retailerBlockBrandsRepository.deleteBrands(retailer.getId());}for (String blockBrand : updateRetailerRequest.getBlocksBrands()) {RetailerBlockBrands retailerBlockBrand = new RetailerBlockBrands();retailerBlockBrand.setFofoId(retailer.getId());retailerBlockBrand.setBlockBrands(blockBrand);retailerBlockBrandsRepository.persist(retailerBlockBrand);}map.put("retailerBlockBrands", retailerBlockBrands);Role roleRetailer = roleRepository.selectByName(RoleType.RETAILER.toString());userRoles = this.addRole(userRoles, dtrUser.getId(), roleRetailer.getId());Role roleFofo = roleRepository.selectByName(RoleType.FOFO.toString());if (updateRetailerRequest.isFofo()) {userRoles = this.addRole(userRoles, dtrUser.getId(), roleFofo.getId());} else {userRoles = this.removeRole(userRoles, dtrUser.getId(), roleFofo.getId());}map.put("fofoRole", this.containsRoleType(userRoles, roleFofo.getId()));if (this.containsRoleType(userRoles, roleFofo.getId())) {this.createDefaultPaymentOption(retailer.getId());}map.put("userRoles", userRoles);map.put("userRoleNames", this.toString(userRoles));Address retailerAddress = (Address) map.get("retailerAddress");retailerAddress = this.updateRetailerAddress(retailerAddress, updateRetailerRequest.getAddress(), retailer.getId());map.put("retailerAddress", retailerAddress);if (updateRetailerRequest.isFofo()) {FofoStore fofoStore = this.createFofoStoreCodeByRetailerId(retailer.getId(), updateRetailerRequest.getDistrictName(), retailerAddress.getState(), updateRetailerRequest);map.put("fofoStore", fofoStore);if (fofoStore.isClosed() && updateRetailerRequest.isActive()) {throw new ProfitMandiBusinessException("Store Closed", "Store Permanently Closed","This store is permanently closed and cannot be reactivated");}fofoStore.setActive(updateRetailerRequest.isActive());List<AST> astDetail = postOfficeService.getAreasAndTerritoriesByStateName(retailerAddress.getState());map.put("astDetail", astDetail);}this.createPrivateDealUser(dtrUser, updateRetailerRequest.isFofo(), updateRetailerRequest.getGstNumber(), retailer, retailerAddress.getId());map.put("gstNumber", updateRetailerRequest.getGstNumber());this.updateSaholicUser(retailer.getId(), retailerAddress.getId());List<Shop> shops = (List<Shop>) map.get("shops");if (shops == null) {shops = new ArrayList<>();map.put("shops", shops);}this.updateRetailerShops(shops, updateRetailerRequest.getShops(), retailer.getId(), retailerAddress);return map;}private void createDefaultPaymentOption(int fofoId) {List<Integer> paymentOptionIds = fofoPartnerPaymentOptionRepository.selectPaymentOptionIdsByFofoId(fofoId);if (paymentOptionIds.isEmpty()) {PaymentOption paymentOption = null;try {paymentOption = paymentOptionRepository.selectByName(PaymentOptionType.CASH.toString());} catch (ProfitMandiBusinessException profitMandiBusinessException) {paymentOption = new PaymentOption();paymentOption.setName(PaymentOptionType.CASH.toString());paymentOptionRepository.persist(paymentOption);}FofoPartnerPaymentOption fofoPartnerPaymentOption = new FofoPartnerPaymentOption();fofoPartnerPaymentOption.setFofoId(fofoId);fofoPartnerPaymentOption.setPaymentOptionId(paymentOption.getId());fofoPartnerPaymentOptionRepository.persist(fofoPartnerPaymentOption);}}private User createUser(User user, UpdateRetailerRequest updateRetailerRequest) throwsProfitMandiBusinessException {User dtrUser = null;try {dtrUser = userRepository.selectByMobileNumber(updateRetailerRequest.getUserMobileNumber());} catch (ProfitMandiBusinessException e) {//Ignore the exception}if (dtrUser != null && (user == null || user.getId() != dtrUser.getId()))throw new ProfitMandiBusinessException("Mobile already exist", updateRetailerRequest.getUserMobileNumber(), dtrUser.getEmailId());User dtrUserByEmail = null;try {dtrUserByEmail = userRepository.selectByEmailId(updateRetailerRequest.getUserEmailId());} catch (ProfitMandiBusinessException e) {//ignore the exception}if (user != null && dtrUserByEmail != null && user.getId() != dtrUserByEmail.getId())throw new ProfitMandiBusinessException("Email already exist", updateRetailerRequest.getUserEmailId(), "");if (user == null) {user = new User();user.setCity("");user.setPinCode(0);user.setState("");user.setPassword("");user.setMobile_verified(false);user.setReferral_url("");user.setGroup_id(1);user.setStatus(1);user.setActivated(true);user.setCreateTimestamp(LocalDateTime.now());}user.setActivated(updateRetailerRequest.isActive());user.setFirstName(updateRetailerRequest.getUserFirstName());user.setLastName(updateRetailerRequest.getUserLastName());user.setMobileNumber(updateRetailerRequest.getUserMobileNumber());user.setEmailId(updateRetailerRequest.getUserEmailId());user.setUsername(updateRetailerRequest.getUserEmailId());user.setUpdateTimestamp(LocalDateTime.now());userRepository.persist(user);return user;}private int createSaholicUser(User user, String retailerName) {com.spice.profitmandi.dao.entity.user.User saholicUser = null;try {saholicUser = userUserRepository.selectByEmailId(user.getEmailId());} catch (ProfitMandiBusinessException e) {LOGGER.info("User doesnt exist in old system");}if (saholicUser == null) {Cart cart = new Cart();cart.setCartStatus(CartStatus.ACTIVE);cartRepository.persist(cart);saholicUser = new com.spice.profitmandi.dao.entity.user.User();saholicUser.setEmailId(user.getEmailId());saholicUser.setName(retailerName);saholicUser.setActiveCartId(cart.getId());saholicUser.setCreateTimestamp(LocalDateTime.now());userUserRepository.persist(saholicUser);UserAccount ua = new UserAccount();ua.setAccountKey(saholicUser.getId());ua.setUserId(user.getId());ua.setType(AccountType.saholic);userAccountRepository.persist(ua);UserAccount ua2 = new UserAccount();ua2.setAccountKey(saholicUser.getActiveCartId());ua2.setUserId(user.getId());ua2.setType(AccountType.cartId);userAccountRepository.persist(ua2);LOGGER.info("created....");}return saholicUser.getId();}private com.spice.profitmandi.dao.entity.user.User createSaholicUser(LoginRequestResponseModel loginRequestResponseModel) {com.spice.profitmandi.dao.entity.user.User saholicUser = null;try {saholicUser = userUserRepository.selectByEmailId(loginRequestResponseModel.getEmail());saholicUser.setCreateTimestamp(LocalDateTime.now());} catch (ProfitMandiBusinessException e) {LOGGER.info("User doesnt exist in old system");}if (saholicUser == null) {Cart cart = new Cart();cart.setCartStatus(CartStatus.ACTIVE);cartRepository.persist(cart);saholicUser = new com.spice.profitmandi.dao.entity.user.User();saholicUser.setPassword(getHash256(loginRequestResponseModel.getPassword()));saholicUser.setEmailId(loginRequestResponseModel.getEmail());saholicUser.setName(loginRequestResponseModel.getCustomerName());saholicUser.setActiveCartId(cart.getId());saholicUser.setCreateTimestamp(LocalDateTime.now());loginRequestResponseModel.setPassword(null);userUserRepository.persist(saholicUser);}return saholicUser;}private Retailer updateRetailer(User user, Retailer retailer, UpdateRetailerRequest updateRetailerRequest) throwsProfitMandiBusinessException {if (retailer == null) {LOGGER.info("createSaholicUser.....");int saholicUserId = this.createSaholicUser(user, updateRetailerRequest.getName());retailer = new Retailer();retailer.setId(saholicUserId);}retailer.setActive(updateRetailerRequest.isActive());user.setActivated(updateRetailerRequest.isActive());//// this.createRole(user.getId(), RoleType.RETAILER);retailer.setName(updateRetailerRequest.getName());retailer.setNumber(updateRetailerRequest.getNumber());if (updateRetailerRequest.getNumber() == null || updateRetailerRequest.getNumber().isEmpty()) {retailer.setType(RetailerType.UNREGISTERED_SHOP);} else {retailer.setType(RetailerType.GSTIN);}if (updateRetailerRequest.getDocumentId() > 0) {if (retailer.getDocumentId() != null && retailer.getDocumentId() != updateRetailerRequest.getDocumentId()) {try {documentRepository.deleteById(retailer.getDocumentId());} catch (Exception e) {e.printStackTrace();}}retailer.setDocumentId(updateRetailerRequest.getDocumentId());documentRepository.markDocumentAsPersisted(updateRetailerRequest.getDocumentId());}retailerRepository.persist(retailer);return retailer;}private void updateSaholicUser(int retailerId, int retailerAddressId) {try {com.spice.profitmandi.dao.entity.user.User user = userUserRepository.selectById(retailerId);user.setAddressId(retailerAddressId);Cart cart = cartRepository.selectById(user.getActiveCartId());cart.setAddressId(retailerAddressId);} catch (ProfitMandiBusinessException e) {}}private void createPrivateDealUser(User user, boolean fofo, String gstNumber, Retailer retailer,int retailerAddressId) {PrivateDealUser privateDealUser = null;try {privateDealUser = privateDealUserRepository.selectById(retailer.getId());} catch (ProfitMandiBusinessException profitMandiBusinessException) {LOGGER.error("PrivateDealUser not found");}// = privateDealUserRepository.selectById(saholicUser.getId());if (privateDealUser == null) {Integer counterId = this.createCounter(user.getEmailId(), gstNumber, user.getMobileNumber(), retailer.getName(), retailerAddressId);try {this.createPrivateDealUser(retailer.getId(), counterId, fofo);} catch (Exception e) {LOGGER.error("ERROR : ", e);}} else {if (privateDealUser.getCounterId() == null) {Integer counterId = this.createCounter(user.getEmailId(), gstNumber, user.getMobileNumber(), retailer.getName(), retailerAddressId);privateDealUser.setCounterId(counterId);privateDealUser.setFofo(fofo);privateDealUserRepository.persist(privateDealUser);} else {Counter counter = null;try {counter = counterRepository.selectById(privateDealUser.getCounterId());} catch (ProfitMandiBusinessException profitMandiBusinessException) {LOGGER.error("Counter not found with id [{}]", privateDealUser.getCounterId());}if (counter == null) {this.createCounter(user.getEmailId(), gstNumber, user.getMobileNumber(), retailer.getName(), retailerAddressId);} else {counter.setGstin(gstNumber);counterRepository.persist(counter);}privateDealUser.setFofo(fofo);privateDealUserRepository.persist(privateDealUser);}}PrivateDealUserAddressMapping privateDealUserAddressMapping = new PrivateDealUserAddressMapping();privateDealUserAddressMapping.setUserId(retailer.getId());privateDealUserAddressMapping.setAddressId(retailerAddressId);privateDealUserAddressMappingRepository.persist(privateDealUserAddressMapping);}// Specifically set isFofo to true that has to be used by old systemprivate void createPrivateDealUser(int retailerId, int counterId, boolean fofo) {PrivateDealUser privateDealUser = new PrivateDealUser();privateDealUser.setActive(true);privateDealUser.setBulkShipmentAmountLimit(fofo ? 1000000 : 50000);privateDealUser.setId(retailerId);privateDealUser.setCounterId(counterId);privateDealUser.setFofo(fofo);privateDealUserRepository.persist(privateDealUser);}private Integer createCounter(String emailId, String gstNumber, String mobileNumber, String name, int addressId) {if (gstNumber != null && !gstNumber.isEmpty()) {Counter counter = new Counter();counter.setEmailId(emailId);counter.setGstin(gstNumber);counter.setMobileNumber(mobileNumber);counter.setName(name);counter.setAddressId(addressId);counterRepository.persist(counter);return counter.getId();} else {return null;}}private Address updateRetailerAddress(Address address, CustomAddress customAddress, int retailerId) throwsProfitMandiBusinessException {if (address == null) {// Try to find existing address via RetailerRegisteredAddress (handles case where// dtr.user was deleted but retailer/address still exist in database)try {int existingAddressId = retailerRegisteredAddressRepository.selectAddressIdByRetailerId(retailerId);address = addressRepository.selectById(existingAddressId);} catch (ProfitMandiBusinessException e) {// No existing address found for this retailer}if (address != null) {// Existing address found - update itthis.updateAddress(address, customAddress);RetailerRegisteredAddress retailerRegisteredAddress = retailerRegisteredAddressRepository.selectByRetailerId(retailerId);retailerRegisteredAddress.setAddressId(address.getId());retailerRegisteredAddressRepository.persist(retailerRegisteredAddress);} else {// Truly new addressaddress = new Address();address.setRetaierId(retailerId);this.updateAddress(address, customAddress);final RetailerRegisteredAddress retailerRegisteredAddress = new RetailerRegisteredAddress();retailerRegisteredAddress.setRetailerId(retailerId);retailerRegisteredAddress.setAddressId(address.getId());retailerRegisteredAddressRepository.persist(retailerRegisteredAddress);}} else {this.updateAddress(address, customAddress);RetailerRegisteredAddress retailerRegisteredAddress = retailerRegisteredAddressRepository.selectByRetailerId(retailerId);retailerRegisteredAddress.setAddressId(address.getId());retailerRegisteredAddressRepository.persist(retailerRegisteredAddress);}return address;}private void updateAddress(Address address, CustomAddress customAddress) throws ProfitMandiBusinessException {address.setName(customAddress.getName());address.setPhoneNumber(customAddress.getPhoneNumber());address.setLine1(customAddress.getLine1());address.setLine2(customAddress.getLine2());address.setCity(customAddress.getCity());address.setPinCode(customAddress.getPinCode());State state = stateRepository.selectByName(customAddress.getState());if (state == null) {throw new ProfitMandiBusinessException("State name", "Invalid State - Pls Contact Technology", "Invalid State - Pls Contact Technology");}address.setState(state.getName());addressRepository.persist(address);LOGGER.info("Address Updated" + address);}private void updateRetailerShops(List<Shop> shops, Set<CustomShop> customShops, int retailerId, AddresssameAsRetailerAddressValue) throws ProfitMandiBusinessException {if (shops.isEmpty()) {for (CustomShop customShop : customShops) {Shop shop = new Shop();this.createOrUpdateShop(shop, customShop, retailerId, sameAsRetailerAddressValue);shops.add(shop);}} else {for (Shop shop : shops) {for (CustomShop customShop : customShops) {if (shop.getId() == customShop.getShopId()) {this.createOrUpdateShop(shop, customShop, retailerId, sameAsRetailerAddressValue);}}}for (CustomShop customShop : customShops) {if (customShop.getShopId() == 0) {Shop shop = new Shop();this.createOrUpdateShop(shop, customShop, retailerId, sameAsRetailerAddressValue);shops.add(shop);}}}}private void createOrUpdateShop(Shop shop, CustomShop customShop, int retailerId, AddresssameAsRetailerAddressValue) throws ProfitMandiBusinessException {shop.setRetailerId(retailerId);shop.setName(customShop.getName());if (customShop.getDocumentId() > 0) {if (shop.getDocumentId() != null && shop.getDocumentId() != customShop.getDocumentId()) {try {documentRepository.deleteById(shop.getDocumentId());} catch (Exception e) {e.printStackTrace();}}shop.setDocumentId(customShop.getDocumentId());documentRepository.markDocumentAsPersisted(customShop.getDocumentId());}if (shop.getAddressId() == null) {Address address = null;if (customShop.isSameAsRetailerAddress()) {address = sameAsRetailerAddressValue;} else {// shop.setDocumentId(customShop.getDocumentId());address = new Address();this.updateAddress(address, customShop.getAddress());}shop.setAddressId(address.getId());shop.setAddress(address);shopRepository.persist(shop);ShopAddress shopAddress = null;try {shopAddress = shopAddressRepository.selectByShopId(shop.getId());shopAddress.setAddressId(address.getId());} catch (ProfitMandiBusinessException profitMandiBusinessException) {shopAddress = new ShopAddress();shopAddress.setAddressId(address.getId());shopAddress.setShopId(shop.getId());}shopAddressRepository.persist(shopAddress);} else {Address address = null;try {address = addressRepository.selectById(shop.getAddressId());CustomAddress customAddress = customShop.getAddress();if (!(address.getName().equals(customAddress.getName()) && address.getLine1().equals(customAddress.getLine1()) && address.getLine2().equals(customAddress.getLine2()) && address.getCity().equals(customAddress.getCity()) && address.getPinCode().equals(customAddress.getPinCode()) && address.getState().equals(customAddress.getState()))) {address = new Address();ShopAddress shopAddress = shopAddressRepository.selectByShopId(shop.getId());this.updateAddress(address, customAddress);shopAddress.setAddressId(address.getId());shopAddressRepository.persist(shopAddress);shop.setAddress(address);shopRepository.persist(shop);}} catch (Exception e) {if (customShop.isSameAsRetailerAddress()) {address = sameAsRetailerAddressValue;} else {// shop.setDocumentId(customShop.getDocumentId());address = new Address();this.updateAddress(address, customShop.getAddress());}shop.setAddressId(address.getId());shop.setAddress(address);shopRepository.persist(shop);ShopAddress shopAddress = null;try {shopAddress = shopAddressRepository.selectByShopId(shop.getId());shopAddress.setAddressId(address.getId());} catch (ProfitMandiBusinessException profitMandiBusinessException) {shopAddress = new ShopAddress();shopAddress.setAddressId(address.getId());shopAddress.setShopId(shop.getId());}shopAddressRepository.persist(shopAddress);}}}private void addAddress(List<Shop> shops) throws ProfitMandiBusinessException {Set<Integer> shopIds = this.toShopIds(shops);if (shopIds.isEmpty()) {return;}List<ShopAddress> shopAddresses = shopAddressRepository.selectByShopIds(shopIds);Map<Integer, Address> addressIdAddressMap = this.toAddressIdAddressMap(shopAddresses);for (Shop shop : shops) {shop.setAddress(addressIdAddressMap.get(shop.getAddressId()));}}private Map<Integer, Address> toAddressIdAddressMap(List<ShopAddress> shopAddresses) throws ProfitMandiBusinessException {Map<Integer, Address> addressIdAddressMap = new HashMap<>();List<Integer> addressIds = this.toAddressIds(shopAddresses);List<Address> addresses = addressRepository.selectByIds(addressIds);for (Address address : addresses) {addressIdAddressMap.put(address.getId(), address);}return addressIdAddressMap;}private List<Integer> toAddressIds(List<ShopAddress> shopAddresses) {return shopAddresses.stream().map(ShopAddress::getAddressId).collect(Collectors.toList());}private Set<Integer> toShopIds(List<Shop> shops) {return shops.stream().map(Shop::getId).collect(Collectors.toSet());}private String toString(List<UserRole> userRoles) throws ProfitMandiBusinessException {Set<Integer> roleIds = new HashSet<>();for (UserRole userRole : userRoles) {roleIds.add(userRole.getRoleId());}List<Role> roles = roleRepository.selectByIds(roleIds);Function<Role, String> roleToNameFunction = role -> String.valueOf(role.getName());Set<String> userRoleStrings = roles.stream().map(roleToNameFunction).collect(Collectors.toSet());return String.join(", ", userRoleStrings);}private FofoStore createFofoStoreCodeByRetailerId(int retailerId, String districtName, StringstateName, UpdateRetailerRequest updateRetailerRequest) throws ProfitMandiBusinessException {FofoStore fofoStore = null;try {fofoStore = fofoStoreRepository.selectByRetailerId(retailerId);fofoStore.setActivationType(ActivationType.ACTIVE);} catch (ProfitMandiBusinessException profitMandiBusinessException) {}if (fofoStore != null) {fofoStore.setCounterSize(updateRetailerRequest.getCountersize());fofoStore.setAstId(updateRetailerRequest.getAstId());fofoStore.setMinimumInvestment(updateRetailerRequest.getMinInvestment());fofoStore.setWarehouseId(updateRetailerRequest.getWarehouseId());fofoStore.setCounterPotential(updateRetailerRequest.getCounterPotential());fofoStore.setFofoType(updateRetailerRequest.getFofoType());fofoStore.setGstNumber(updateRetailerRequest.getGstNumber());} else {int retailerAddressId = retailerRegisteredAddressRepository.selectAddressIdByRetailerId(retailerId);Address retailerAddress = addressRepository.selectById(retailerAddressId);// StateInfo stateInfo = null;State stateInfo = null;try {stateInfo = stateRepository.selectByName(retailerAddress.getState());// stateInfo = Utils.getStateInfo(retailerAddress.getState());} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();// throw new ProfitMandiBusinessException();}DistrictMaster districtMaster = districtMasterRepository.selectByNameAndStateShortName(districtName, stateInfo.getShortName());fofoStore = new FofoStore();fofoStore.setId(retailerId);fofoStore.setCounterSize(updateRetailerRequest.getCountersize());fofoStore.setMinimumInvestment(updateRetailerRequest.getMinInvestment());fofoStore.setCounterPotential(updateRetailerRequest.getCounterPotential());fofoStore.setWarehouseId(updateRetailerRequest.getWarehouseId());//Check for Trial users hereint nextStoreCodeInt = fofoStoreRepository.selectLatestStore().getCodeInt() + 1;String fofoStoreCode = StringUtils.generateFofoStoreSequence(districtMaster.getStateShortName() + districtMaster.getShortName(), nextStoreCodeInt);try {TrialForm trialForm = trialFormRepository.selectByEmailOrMobile(updateRetailerRequest.getUserMobileNumber());if (trialForm != null) {fofoStoreCode = "T-" + fofoStoreCode;fofoStore.setTrial(true);fofoStore.setTrialStart(LocalDate.now());fofoStore.setTrialEnd(LocalDate.now().plusDays(31));trialForm.setStatus(ProfitMandiConstants.Status.TMP_STORE_CODE_CREATED);//TODO:Amit G, Send store code notification to retailer.}} catch (ProfitMandiBusinessException e) {}fofoStore.setCode(fofoStoreCode);fofoStore.setCodeInt(nextStoreCodeInt);fofoStore.setBagsLastCredited(LocalDateTime.now());if (retailerAddress.getName().contains(ProfitMandiConstants.COMPANY_NAME) || retailerAddress.getName().contains(ProfitMandiConstants.COMPANY_SHORT_NAME)) {fofoStore.setInternal(true);} else {fofoStore.setInternal(false);}fofoStore.setFofoType(FofoType.FRANCHISE);fofoStore.setFofoType(updateRetailerRequest.getFofoType());fofoStore.setActivationType(ActivationType.ACTIVE);fofoStore.setGstNumber(updateRetailerRequest.getGstNumber());fofoStoreRepository.persist(fofoStore);// Link store code to onboarding panel (only for NEW store creation)try {PartnerOnBoardingPanel pobp = partnerOnBoardingPanelRepository.selectByPhoneNumber(Long.parseLong(retailerAddress.getPhoneNumber()));if (pobp != null) {PartnerVerificationpanel pvp = partnerOnboardingVerificationRepository.selectByOnboardingId(pobp.getId());if (pvp != null && PartnerVerificationApprovalStatus.YES.equals(pvp.getApproval())) {pobp.setCode(fofoStore.getCode());storeTimelineTatService.onCodeCreated(pobp.getId());PartnerVerificationCheckboxes cb = partnerOnboardingVerificationRepository.selectVerifiCheckboxByOnboardingId(pobp.getId());if (cb == null) {cb = new PartnerVerificationCheckboxes();cb.setOnboardingId(pobp.getId());partnerOnboardingVerificationRepository.persist(cb);}}}} catch (Exception e) {LOGGER.error("Error linking store code to onboarding for retailerId: {}", retailerId, e);}PincodePartner pincodePartner = pincodePartnerRepository.selectPartnerByPincode(retailerAddress.getPinCode(), fofoStore.getId());if (pincodePartner == null) {PincodePartner pinPartner = new PincodePartner();pinPartner.setFofoId(fofoStore.getId());pinPartner.setPincode(retailerAddress.getPinCode());pincodePartnerRepository.perist(pinPartner);}if (fofoStore.isTrial()) {storeTimelineTatService.sendTrialStoreCreationMail(fofoStore, updateRetailerRequest);storeTimelineTatService.sendTrialActivationMail(fofoStore, updateRetailerRequest);}}return fofoStore;}@Overridepublic FofoStore createFofoStoreCodeByUserId(int userId, String districtName, StringstateName, UpdateRetailerRequest updateRetailerRequest) throws ProfitMandiBusinessException {User user = userRepository.selectById(userId);// = userAccountRepository.selectRetailerIdByUserId(user.getId());UserAccount userAccounts = userAccountRepository.selectSaholicByUserId(user.getId());Retailer retailer = retailerRepository.selectById(userAccounts.getAccountKey());Role roleFofo = roleRepository.selectByName(RoleType.FOFO.toString());try {userRoleRepository.selectByUserIdAndRoleId(user.getId(), roleFofo.getId());} catch (ProfitMandiBusinessException profitMandiBusinessException) {throw new ProfitMandiBusinessException(ProfitMandiConstants.USER_ID, user.getId(), "USR_1013");}return this.createFofoStoreCodeByRetailerId(retailer.getId(), districtName, stateName, updateRetailerRequest);}@Overridepublic List<DistrictMaster> getAllDistrictMaster(String stateName) {// StateInfo stateInfo = null;State stateInfo = null;try {// stateInfo = Utils.getStateInfo(stateName);stateInfo = stateRepository.selectByName(stateName);} catch (Exception e) {e.printStackTrace();// throw new ProfitMandiBusinessException();}return districtMasterRepository.selectByStateShortName(stateInfo.getShortName());}@Override@Cacheable(value = "getFofoRetailer", cacheManager = "thirtyMinsTimeOutCacheManager")public Map<Integer, CustomRetailer> getFofoRetailers(List<Integer> fofoIds) throws ProfitMandiBusinessException {if (fofoIds == null || fofoIds.isEmpty()) {return new HashMap<>();}List<com.spice.profitmandi.dao.entity.user.User> saholicUsers = userUserRepository.selectByIds(fofoIds);// Check for saholicUsers without corresponding dtrUserList<String> saholicEmails = saholicUsers.stream().map(com.spice.profitmandi.dao.entity.user.User::getEmailId).filter(email -> email != null).collect(Collectors.toList());Set<String> dtrUserEmails = userRepository.selectAllByEmailIds(saholicEmails).stream().map(User::getEmailId).collect(Collectors.toSet());for (com.spice.profitmandi.dao.entity.user.User saholicUser : saholicUsers) {if (saholicUser.getEmailId() != null && !dtrUserEmails.contains(saholicUser.getEmailId())) {LOGGER.warn("dtrUser not found for saholicUser - id: {}, email: {}", saholicUser.getId(), saholicUser.getEmailId());}}Map<Integer, com.spice.profitmandi.dao.entity.user.User> userAddressMap = saholicUsers.stream().filter(x -> x.getAddressId() != null).collect(Collectors.toMap(com.spice.profitmandi.dao.entity.user.User::getAddressId, x -> x));List<Address> addresses = addressRepository.selectByIds(new ArrayList<>(userAddressMap.keySet()));// Batch fetch all FofoStores to avoid N+1 queriesSet<Integer> retailerIds = addresses.stream().map(Address::getRetaierId).collect(Collectors.toSet());Map<Integer, FofoStore> fofoStoreMap = fofoStoreRepository.selectByRetailerIds(new ArrayList<>(retailerIds)).stream().collect(Collectors.toMap(FofoStore::getId, fs -> fs));Map<Integer, CustomRetailer> customRetailersMap = new HashMap<>();for (Address address : addresses) {com.spice.profitmandi.dao.entity.user.User user = userAddressMap.get(address.getId());FofoStore fs = fofoStoreMap.get(address.getRetaierId());if (fs == null) {continue;}CustomRetailer customRetailer = buildCustomRetailer(user, address, fs);customRetailersMap.put(customRetailer.getPartnerId(), customRetailer);}return customRetailersMap;}/*** Helper method to build CustomRetailer from fetched entities*/private CustomRetailer buildCustomRetailer(com.spice.profitmandi.dao.entity.user.User user, Address address,FofoStore fs) {CustomRetailer customRetailer = new CustomRetailer();customRetailer.setEmail(user.getEmailId());customRetailer.setBusinessName(address.getName());customRetailer.setMobileNumber(address.getPhoneNumber());customRetailer.setCode(fs.getCode());customRetailer.setAstId(fs.getAstId());customRetailer.setActivationType(fs.getActivationType());customRetailer.setCounterSize(fs.getCounterSize());customRetailer.setCounterPotential(fs.getCounterPotential());customRetailer.setWarehouseId(fs.getWarehouseId());customRetailer.setPartnerId(fs.getId());customRetailer.setFofoType(fs.getFofoType());customRetailer.setCartId(user.getActiveCartId());customRetailer.setGstNumber(fs.getGstNumber());CustomAddress customAddress = buildCustomAddress(address);customRetailer.setAddress(customAddress);customRetailer.setDisplayName(customRetailer.getBusinessName() + "-" + customRetailer.getCode() + "- " + customAddress.getCity());return customRetailer;}/*** Helper method to build CustomAddress from Address entity*/private CustomAddress buildCustomAddress(Address address) {CustomAddress customAddress = new CustomAddress();customAddress.setCity(address.getCity());customAddress.setState(address.getState());customAddress.setLine1(address.getLine1());customAddress.setLine2(address.getLine2());customAddress.setPinCode(address.getPinCode());customAddress.setName(address.getName());customAddress.setPhoneNumber(address.getPhoneNumber());return customAddress;}@Override@Cacheable(value = "getFofoRetailer", cacheManager = "thirtyMinsTimeOutCacheManager")public CustomRetailer getFofoRetailer(int fofoId) throws ProfitMandiBusinessException {com.spice.profitmandi.dao.entity.user.User saholicUser = userUserRepository.selectById(fofoId);User dtrUser = null;try {dtrUser = userRepository.selectByEmailId(saholicUser.getEmailId());} catch (ProfitMandiBusinessException e) {LOGGER.info("User not found for emailId: {} and id is : {}", saholicUser.getEmailId(), saholicUser.getId());}FofoStore store = fofoStoreRepository.selectByRetailerId(fofoId);Address address = addressRepository.selectById(saholicUser.getAddressId());CustomRetailer customRetailer = new CustomRetailer();customRetailer.setEmail(saholicUser.getEmailId());customRetailer.setBusinessName(address.getName());customRetailer.setMobileNumber(address.getPhoneNumber());customRetailer.setFirstName(dtrUser.getFirstName());customRetailer.setLastName(dtrUser.getLastName());customRetailer.setCartId(saholicUser.getActiveCartId());customRetailer.setPartnerId(address.getRetaierId());customRetailer.setCode(store.getCode());customRetailer.setAstId(store.getAstId());customRetailer.setActivationType(store.getActivationType());customRetailer.setWarehouseId(store.getWarehouseId());customRetailer.setGstNumber(store.getGstNumber());// Reuse helper method for CustomAddressCustomAddress customAddress = buildCustomAddress(address);customRetailer.setAddress(customAddress);customRetailer.setDisplayName(address.getName() + " - " + address.getCity());return customRetailer;}@Overridepublic Map<Integer, CustomRetailer> getFofoRetailerUserId(List<Integer> fofoIds) throws ProfitMandiBusinessException {if (fofoIds == null || fofoIds.isEmpty()) {return new HashMap<>();}List<com.spice.profitmandi.dao.entity.user.User> saholicUsers = userUserRepository.selectByIds(fofoIds);Map<Integer, com.spice.profitmandi.dao.entity.user.User> userAddressMap = saholicUsers.stream().filter(x -> x.getAddressId() != null).collect(Collectors.toMap(com.spice.profitmandi.dao.entity.user.User::getAddressId, x -> x));List<Address> addresses = addressRepository.selectByIds(new ArrayList<>(userAddressMap.keySet()));// Batch fetch all retailerIds to userIds mapping to avoid N+1Set<Integer> retailerIds = addresses.stream().map(Address::getRetaierId).collect(Collectors.toSet());Map<Integer, Integer> retailerIdToUserIdMap = getUserIdRetailerIdMapReverse(retailerIds);// Batch fetch FofoStores for GST numbersMap<Integer, FofoStore> fofoStoreMap = fofoStoreRepository.selectByRetailerIds(new ArrayList<>(retailerIds)).stream().collect(Collectors.toMap(FofoStore::getId, fs -> fs));Map<Integer, CustomRetailer> customRetailersMap = new HashMap<>();for (Address address : addresses) {com.spice.profitmandi.dao.entity.user.User user = userAddressMap.get(address.getId());Integer userId = retailerIdToUserIdMap.get(user.getId());if (userId == null) {continue;}CustomRetailer customRetailer = new CustomRetailer();customRetailer.setEmail(user.getEmailId());customRetailer.setBusinessName(address.getName());customRetailer.setMobileNumber(address.getPhoneNumber());customRetailer.setCartId(user.getActiveCartId());customRetailer.setPartnerId(address.getRetaierId());FofoStore fs = fofoStoreMap.get(address.getRetaierId());customRetailer.setGstNumber(fs != null ? fs.getGstNumber() : null);CustomAddress customAddress = buildCustomAddress(address);customRetailer.setAddress(customAddress);customRetailer.setDisplayName(customRetailer.getBusinessName() + "-" + customAddress.getCity());customRetailersMap.put(userId, customRetailer);}return customRetailersMap;}/*** Helper method to get retailerId to userId mapping*/private Map<Integer, Integer> getUserIdRetailerIdMapReverse(Set<Integer> retailerIds) {List<UserAccount> userAccounts = userAccountRepository.selectAllSaholicByRetailerIds(retailerIds);return userAccounts.stream().collect(Collectors.toMap(UserAccount::getAccountKey, UserAccount::getUserId));}@Overridepublic Map<Integer, String> getAllFofoRetailerIdEmailIdMap() throws ProfitMandiBusinessException {Role roleFofo = null;try {roleFofo = roleRepository.selectByName(RoleType.FOFO.toString());} catch (ProfitMandiBusinessException e) {// TODO Auto-generated catch blocke.printStackTrace();}Role roleRetailer = null;try {roleRetailer = roleRepository.selectByName(RoleType.RETAILER.toString());} catch (ProfitMandiBusinessException e) {// TODO Auto-generated catch blocke.printStackTrace();}Set<Integer> roleIds = new HashSet<>();roleIds.add(roleFofo.getId());roleIds.add(roleRetailer.getId());List<Integer> userIds = userRoleRepository.selectUserIdsByRoleIds(roleIds);List<User> users = userRepository.selectAllByIds(new HashSet<>(userIds));Map<Integer, Integer> userIdRetailerIdMap = this.getUserIdRetailerIdMap(userIds);Map<Integer, String> retailerIdEmailIdMap = new HashMap<>();for (User user : users) {retailerIdEmailIdMap.put(userIdRetailerIdMap.get(user.getId()), user.getEmailId());}return retailerIdEmailIdMap;}private Map<Integer, Integer> getUserIdRetailerIdMap(List<Integer> userIds) {List<UserAccount> userAccounts = userAccountRepository.selectAllSaholicByUserIds(new HashSet<>(userIds));Map<Integer, Integer> userIdRetailerIdMap = new HashMap<>();for (UserAccount userAccount : userAccounts) {userIdRetailerIdMap.put(userAccount.getUserId(), userAccount.getAccountKey());}return userIdRetailerIdMap;}private Map<Integer, String> getUserIdEmailIdMap(Set<Integer> userIds) throws ProfitMandiBusinessException {List<User> users = userRepository.selectAllByIds(userIds);Map<Integer, String> userIdEmailIdMap = new HashMap<>();for (User user : users) {userIdEmailIdMap.put(user.getId(), user.getEmailId());}return userIdEmailIdMap;}@Overridepublic Map<Integer, String> getAllFofoRetailerIdEmailIdMap(Set<Integer> retailerIds) throws ProfitMandiBusinessException {List<UserAccount> userAccounts = userAccountRepository.selectAllSaholicByRetailerIds(retailerIds);Set<Integer> userIds = new HashSet<>();for (UserAccount userAccount : userAccounts) {userIds.add(userAccount.getUserId());}Map<Integer, String> retailerIdEmailIdMap = new HashMap<>();Map<Integer, String> userIdEmailIdMap = this.getUserIdEmailIdMap(userIds);for (UserAccount userAccount : userAccounts) {retailerIdEmailIdMap.put(userAccount.getAccountKey(), userIdEmailIdMap.get(userAccount.getUserId()));}return retailerIdEmailIdMap;}@Overridepublic Map<Integer, String> getAllFofoRetailerIdNameMap(List<Integer> storeIds) throws ProfitMandiBusinessException {Map<Integer, CustomRetailer> retailersMap = this.getFofoRetailers(storeIds);Map<Integer, String> retailerIdNameMap = new HashMap<>();for (Map.Entry<Integer, CustomRetailer> entry : retailersMap.entrySet()) {retailerIdNameMap.put(entry.getKey(), entry.getValue().getBusinessName() + "-" + entry.getValue().getAddress().getCity());}return retailerIdNameMap;}@Override@Cacheable(value = "FofoRetailerIdNameMap", cacheManager = "thirtyMinsTimeOutCacheManager")public Map<Integer, String> getAllFofoRetailerIdNameMap() throws ProfitMandiBusinessException {List<FofoStore> stores = fofoStoreRepository.selectAll();List<Integer> storeIds = stores.stream().map(x -> x.getId()).collect(Collectors.toList());return this.getAllFofoRetailerIdNameMap(storeIds);}@Overridepublic List<MapWrapper<Integer, String>> getAllFofoRetailerIdNameList() throws ProfitMandiBusinessException {List<MapWrapper<Integer, String>> mapWrappers = new ArrayList<>();// TODO Auto-generated method stubMap<Integer, String> fofoIdNameMap = this.getAllFofoRetailerIdNameMap();fofoIdNameMap.forEach((fofoId, name) -> {MapWrapper<Integer, String> idWrapper = new MapWrapper<>();idWrapper.setKey(fofoId);idWrapper.setValue(name);mapWrappers.add(idWrapper);});return mapWrappers;}@Override@Cacheable(value = "retailerNames", cacheManager = "thirtyMinsTimeOutCacheManager")public Map<Integer, CustomRetailer> getFofoRetailers(boolean activeOnly) throws ProfitMandiBusinessException {Stream<FofoStore> storeStream = fofoStoreRepository.selectAll().stream().filter(fs -> fs.getFofoType().equals(FofoType.FRANCHISE));if (activeOnly) {storeStream = storeStream.filter(FofoStore::isActive);}List<Integer> storeIds = storeStream.map(FofoStore::getId).collect(Collectors.toList());return this.getFofoRetailers(storeIds);}@Override@Cacheable(value = "retailerNames", cacheManager = "thirtyMinsTimeOutCacheManager")public Map<Integer, CustomRetailer> getFofoRetailers(boolean activeOnly, String pinCode) throws ProfitMandiBusinessException {List<PincodePartner> pincodePartners = pincodePartnerRepository.selectPartnersByPincode(pinCode);List<Integer> storeIds = new ArrayList<>();if (!pincodePartners.isEmpty()) {List<Integer> fofoIds = pincodePartners.stream().map(PincodePartner::getFofoId).collect(Collectors.toList());List<FofoStore> fofoStores = fofoStoreRepository.selectActivePartnersByRetailerIds(fofoIds);storeIds = fofoStores.stream().map(FofoStore::getId).collect(Collectors.toList());}return this.getFofoRetailers(storeIds);}@Override@Cacheable(value = "allFofoRetailers", cacheManager = "thirtyMinsTimeOutCacheManager")public Map<Integer, CustomRetailer> getAllFofoRetailers() throws ProfitMandiBusinessException {List<Integer> storeIds = fofoStoreRepository.selectAll().stream().map(FofoStore::getId).collect(Collectors.toList());return this.getFofoRetailers(storeIds);}@Override@Cacheable(value = "allFofoRetailersInternalFalse", cacheManager = "thirtyMinsTimeOutCacheManager")public Map<Integer, CustomRetailer> getAllFofoRetailersInternalFalse() throws ProfitMandiBusinessException {List<Integer> storeIds = fofoStoreRepository.selectAll().stream().filter(fs -> fs.getFofoType().equals(FofoType.FRANCHISE)).map(FofoStore::getId).collect(Collectors.toList());return this.getFofoRetailers(storeIds);}@Overridepublic LoginRequestResponseModel registerWebUser(LoginRequestResponseModel loginRequestModel) throwsProfitMandiBusinessException {com.spice.profitmandi.dao.entity.user.User saholicUser = this.createSaholicUser(loginRequestModel);loginRequestModel.setUserId(saholicUser.getId());this.createRetailerAddress(loginRequestModel);this.createPrivateDealUser(loginRequestModel);this.updateSaholicUser(saholicUser.getId(), loginRequestModel.getBusinessAddress().getId());return loginRequestModel;}private void createPrivateDealUser(LoginRequestResponseModel loginRequestModel) {Integer counterId = this.createCounter(loginRequestModel.getEmail(), loginRequestModel.getGstNumber(), loginRequestModel.getBusinessAddress().getPhoneNumber(), loginRequestModel.getBusinessAddress().getName(), loginRequestModel.getBusinessAddress().getId());try {this.createPrivateDealUser(loginRequestModel.getUserId(), counterId, false);} catch (Exception e) {LOGGER.error("ERROR : ", e);}PrivateDealUserAddressMapping privateDealUserAddressMapping = new PrivateDealUserAddressMapping();privateDealUserAddressMapping.setUserId(loginRequestModel.getUserId());privateDealUserAddressMapping.setAddressId(loginRequestModel.getBusinessAddress().getId());privateDealUserAddressMappingRepository.persist(privateDealUserAddressMapping);}private void createRetailerAddress(LoginRequestResponseModel loginRequestResponseModel) throwsProfitMandiBusinessException {Address businessAddress = loginRequestResponseModel.getBusinessAddress();businessAddress.setRetaierId(loginRequestResponseModel.getUserId());addressRepository.persist(businessAddress);}private String getHash256(String originalString) {String hashString = Hashing.sha256().hashString(originalString, StandardCharsets.UTF_8).toString();LOGGER.info("Hash String {}", hashString);return hashString;}@Override@Cacheable(value = "fofoIdUrl", cacheManager = "thirtyMinsTimeOutCacheManager")public Map<Integer, String> getAllFofoRetailerIdUrlMap() {Map<Integer, String> fofoRetailerUrlMap = new HashMap<>();List<FofoStore> stores = fofoStoreRepository.selectAll().stream().filter(FofoStore::isActive).collect(Collectors.toList());// Batch fetch all district masters to avoid N+1 queriesList<DistrictMaster> allDistrictMasters = districtMasterRepository.selectAll();Map<String, DistrictMaster> districtMasterMap = allDistrictMasters.stream().collect(Collectors.toMap(dm -> dm.getStateShortName() + "_" + dm.getShortName(),dm -> dm,(existing, replacement) -> existing));// Get fallback district masterDistrictMaster fallbackDistrict = districtMasterMap.get("HR_FB");for (FofoStore store : stores) {String codeWithoutDigits = store.getCode().replaceAll("\\d+", "");if (codeWithoutDigits.length() < 3) {LOGGER.warn("Invalid store code format: {}", store.getCode());continue;}String stateShortName = codeWithoutDigits.substring(0, 2);String districtShortName = codeWithoutDigits.substring(2);// Use pre-fetched map instead of N+1 queryString key = stateShortName + "_" + districtShortName;DistrictMaster districtMaster = districtMasterMap.getOrDefault(key, fallbackDistrict);if (districtMaster == null) {LOGGER.warn("No district master found for key: {} and no fallback available", key);continue;}String urlString = districtMaster.getStateShortName() + "/" +Utils.getHyphenatedString(districtMaster.getName()) + "/" + store.getCode();fofoRetailerUrlMap.put(store.getId(), urlString.toLowerCase());}return fofoRetailerUrlMap;}@Override@Cacheable(value = "storeCodeRetailerMap", cacheManager = "thirtyMinsTimeOutCacheManager")public Map<String, Integer> getStoreCodeRetailerMap() {Map<Integer, String> map = this.getAllFofoRetailerIdUrlMap();Map<String, Integer> returnMap = map.entrySet().stream().collect(Collectors.toMap(x -> {String[] splitString = x.getValue().split("/");return splitString[splitString.length - 1];}, x -> x.getKey()));LOGGER.info("returnMap {}", returnMap);return returnMap;}@Overridepublic User getEmail() {return null;}@Overridepublic void update(com.spice.profitmandi.dao.entity.user.User user) {}@Overridepublic void updateRetailerEmail(int fofoId, String newEmail) throws ProfitMandiBusinessException {User dtrUser = null;com.spice.profitmandi.dao.entity.user.User user = null;try {dtrUser = userRepository.selectByEmailId(newEmail);} catch (Exception e) {}try {user = userUserRepository.selectByEmailId(newEmail);} catch (Exception e) {}if (user != null || dtrUser != null) {throw new ProfitMandiBusinessException("Email", newEmail, "Email already exist");}com.spice.profitmandi.dao.entity.user.User fofoUser = userUserRepository.selectById(fofoId);String oldEmail = fofoUser.getEmailId();LOGGER.info("old email {}", oldEmail);User thisDtrUser = userRepository.selectByEmailId(oldEmail);fofoUser.setEmailId(newEmail);thisDtrUser.setEmailId(newEmail);}// @Override@Cacheable(value = "getContactsByFofoId", cacheManager = "oneDayCacheManager")public List<RetailerContact> getContactsByFofoId(int fofoId, boolean activeOnly) throwsProfitMandiBusinessException {List<RetailerContact> retailerContacts = retailerContactRepository.selectAllByRetailerId(fofoId, activeOnly);com.spice.profitmandi.dao.entity.user.User user = userUserRepository.selectById(fofoId);RetailerContact retailerContact = new RetailerContact();retailerContact.setMobile(user.getMobileNumber());retailerContact.setName(user.getName());retailerContact.setActive(true);retailerContact.setFofoId(fofoId);retailerContacts.add(retailerContact);return retailerContacts;}@Overridepublic Map<Integer, CustomRetailer> getFofoRetailersPaginated(boolean activeOnly, int offset,int limit, FofoType fofoType) throws ProfitMandiBusinessException {Stream<FofoStore> storeStream = fofoStoreRepository.selectByStatusFofoType(activeOnly, fofoType, offset, limit).stream();List<Integer> storeIds = storeStream.map(x -> x.getId()).collect(Collectors.toList());return this.getFofoRetailers(storeIds);}@Overridepublic Map<String, Object> computeIncomeMap(int fofoId, int yearMonth) {LocalDateTime startOfMonth = LocalDate.now().minusMonths(yearMonth).withDayOfMonth(1).atStartOfDay();LocalDateTime endOfMonth = startOfMonth.plusMonths(1);YearMonth monthYear = YearMonth.now();// 3) Fetch brand-wise data (same as original)List<LastMonthCreditedIncomeModel> lastMonthPendingIncomeModels = schemeInOutRepository.selectLastMonthPendingIncomeByFofoId(fofoId, startOfMonth, endOfMonth);List<LastMonthCreditedIncomeModel> lastMonthPurchaseInMargins = schemeInOutRepository.selectLastMonthPurchaseInMarginByFofoId(fofoId, startOfMonth, endOfMonth);List<LastMonthCreditedIncomeModel> lastMonthFrontEndIncomes = schemeInOutRepository.selectFrontIncomeByBrand(fofoId, startOfMonth, endOfMonth);List<LastMonthCreditedIncomeModel> lastMonthSaleMargins = schemeInOutRepository.selectLastMonthCreditedIncomeByFofoId(fofoId, startOfMonth, endOfMonth);List<OfferPayoutImeiIncomeModel> offerPayoutImeiIncomeModels = offerPayoutRepository.getTotalPayoutsByPartnerPeriod(YearMonth.of(startOfMonth.getYear(), startOfMonth.getMonth()),fofoId, null, null);// 4) Convert to maps for brand-wise accessMap<String, LastMonthCreditedIncomeModel> lastMonthPendingIncomeMap =lastMonthPendingIncomeModels.stream().collect(Collectors.toMap(x -> x.getBrand(), x -> x));Map<String, LastMonthCreditedIncomeModel> lastMonthPurchaseInMarginMap =lastMonthPurchaseInMargins.stream().collect(Collectors.toMap(x -> x.getBrand(), x -> x));Map<String, LastMonthCreditedIncomeModel> lastMonthFrontEndIncomeMap =lastMonthFrontEndIncomes.stream().collect(Collectors.toMap(x -> x.getBrand(), x -> x));Map<String, LastMonthCreditedIncomeModel> lastMonthSaleMarginMap =lastMonthSaleMargins.stream().collect(Collectors.toMap(x -> x.getBrand(), x -> x));Map<String, Double> additionalPurchasePayout = offerPayoutImeiIncomeModels.stream().collect(Collectors.groupingBy(OfferPayoutImeiIncomeModel::getBrand,Collectors.summingDouble(OfferPayoutImeiIncomeModel::getPurchasePayout)));Map<String, Double> additionSalePayout = offerPayoutImeiIncomeModels.stream().collect(Collectors.groupingBy(OfferPayoutImeiIncomeModel::getBrand,Collectors.summingDouble(OfferPayoutImeiIncomeModel::getSalePayout)));// 5) Get all unique brandsSet<String> brandSet = new HashSet<>();brandSet.addAll(lastMonthPurchaseInMarginMap.keySet());brandSet.addAll(lastMonthSaleMarginMap.keySet());brandSet.addAll(lastMonthPendingIncomeMap.keySet());brandSet.addAll(additionalPurchasePayout.keySet());brandSet.addAll(additionSalePayout.keySet());brandSet.addAll(lastMonthFrontEndIncomeMap.keySet());// 6) Calculate total amount per brand (same logic as original)Map<String, Float> totalAmountMap = new HashMap<>();brandSet.forEach(brand -> {float total =(lastMonthSaleMarginMap.get(brand) == null ? 0 : lastMonthSaleMarginMap.get(brand).getAmount()) +(lastMonthPurchaseInMarginMap.get(brand) == null ? 0 : lastMonthPurchaseInMarginMap.get(brand).getAmount()) +(lastMonthPendingIncomeMap.get(brand) == null ? 0 : lastMonthPendingIncomeMap.get(brand).getAmount()) +(additionalPurchasePayout.get(brand) == null ? 0 : additionalPurchasePayout.get(brand).floatValue()) +(additionSalePayout.get(brand) == null ? 0 : additionSalePayout.get(brand).floatValue()) +(lastMonthFrontEndIncomeMap.get(brand) == null ? 0 : lastMonthFrontEndIncomeMap.get(brand).getAmount());totalAmountMap.put(brand, total);});// 7) Calculate aggregated totalsfloat totalIncome = totalAmountMap.values().stream().reduce(0f, Float::sum);float pendingIncome = lastMonthPendingIncomeMap.values().stream().map(LastMonthCreditedIncomeModel::getAmount).reduce(0f, Float::sum);float creditedIncome = totalIncome - pendingIncome;// 8) Build month labelsMap<Integer, String> monthValueMap = new HashMap<>();DateTimeFormatter fmt = DateTimeFormatter.ofPattern("MMM''uu");for (int i = 0; i <= 5; i++) {LocalDateTime m = LocalDateTime.now().withDayOfMonth(1).minusMonths(i);monthValueMap.put(i, m.format(fmt));}// 9) Assemble result with all brand-wise dataMap<String, Object> result = new HashMap<>();result.put("totalIncome", totalIncome);result.put("creditedIncome", creditedIncome);result.put("pendingIncome", pendingIncome);result.put("monthIndex", yearMonth);result.put("monthValueMap", monthValueMap);// Include brand-wise data for detailed analysisresult.put("brandSet", brandSet);result.put("totalAmountMap", totalAmountMap);result.put("lastMonthPurchaseInMarginMap", lastMonthPurchaseInMarginMap);result.put("lastMonthSaleMarginMap", lastMonthSaleMarginMap);result.put("lastMonthPendingIncomeMap", lastMonthPendingIncomeMap);result.put("additionalPurchasePayoutMap", additionalPurchasePayout);result.put("additionalSalePayoutMap", additionSalePayout);result.put("lastMonthFrontEndIncomeMap", lastMonthFrontEndIncomeMap);return result;}}