Subversion Repositories SmartDukaan

Rev

Rev 23880 | Rev 23942 | Go to most recent revision | View as "text/plain" | Blame | Compare with Previous | Last modification | View Log | RSS feed

package com.spice.profitmandi.service.user;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import com.spice.profitmandi.common.ResponseCodeHolder;
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
import com.spice.profitmandi.common.model.CustomAddress;
import com.spice.profitmandi.common.model.CustomRetailer;
import com.spice.profitmandi.common.model.CustomShop;
import com.spice.profitmandi.common.model.MapWrapper;
import com.spice.profitmandi.common.model.ProfitMandiConstants;
import com.spice.profitmandi.common.model.UpdateRetailerRequest;
import com.spice.profitmandi.common.util.StringUtils;
import com.spice.profitmandi.common.util.Utils;
import com.spice.profitmandi.dao.entity.dtr.DistrictMaster;
import com.spice.profitmandi.dao.entity.dtr.Retailer;
import com.spice.profitmandi.dao.entity.dtr.RetailerRegisteredAddress;
import com.spice.profitmandi.dao.entity.dtr.Role;
import com.spice.profitmandi.dao.entity.dtr.Shop;
import com.spice.profitmandi.dao.entity.dtr.ShopAddress;
import com.spice.profitmandi.dao.entity.dtr.User;
import com.spice.profitmandi.dao.entity.dtr.UserAccount;
import com.spice.profitmandi.dao.entity.dtr.UserRole;
import com.spice.profitmandi.dao.entity.fofo.FofoPartnerPaymentOption;
import com.spice.profitmandi.dao.entity.fofo.FofoStore;
import com.spice.profitmandi.dao.entity.fofo.PaymentOption;
import com.spice.profitmandi.dao.entity.user.Address;
import com.spice.profitmandi.dao.entity.user.Cart;
import com.spice.profitmandi.dao.entity.user.Counter;
import com.spice.profitmandi.dao.entity.user.PrivateDealUser;
import com.spice.profitmandi.dao.entity.user.PrivateDealUserAddressMapping;
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.repository.dtr.DistrictMasterRepository;
import com.spice.profitmandi.dao.repository.dtr.DocumentRepository;
import com.spice.profitmandi.dao.repository.dtr.FofoStoreRepository;
import com.spice.profitmandi.dao.repository.dtr.RetailerRegisteredAddressRepository;
import com.spice.profitmandi.dao.repository.dtr.RetailerRepository;
import com.spice.profitmandi.dao.repository.dtr.RoleRepository;
import com.spice.profitmandi.dao.repository.dtr.ShopAddressRepository;
import com.spice.profitmandi.dao.repository.dtr.ShopRepository;
import com.spice.profitmandi.dao.repository.dtr.UserAccountRepository;
import com.spice.profitmandi.dao.repository.dtr.UserRepository;
import com.spice.profitmandi.dao.repository.dtr.UserRoleRepository;
import com.spice.profitmandi.dao.repository.fofo.FofoPartnerPaymentOptionRepository;
import com.spice.profitmandi.dao.repository.fofo.PaymentOptionRepository;
import com.spice.profitmandi.dao.repository.user.AddressRepository;
import com.spice.profitmandi.dao.repository.user.CartRepository;
import com.spice.profitmandi.dao.repository.user.CounterRepository;
import com.spice.profitmandi.dao.repository.user.PrivateDealUserAddressMappingRepository;
import com.spice.profitmandi.dao.repository.user.PrivateDealUserRepository;

import in.shop2020.model.v1.inventory.StateInfo;
import in.shop2020.model.v1.user.CartStatus;

@Component
public class RetailerServiceImpl implements RetailerService {
        
        private static final Logger LOGGER = LogManager.getLogger(RetailerServiceImpl.class);
        
        @Autowired
        private RetailerRepository retailerRepository;
        
        @Autowired
        private UserAccountRepository userAccountRepository;
        
        @Autowired
        private UserRepository userRepository;
        
        @Autowired
        private CartRepository cartRepository;
        
        @Autowired
        private RetailerRegisteredAddressRepository retailerRegisteredAddressRepository;
        
        @Autowired
        private AddressRepository addressRepository;
        
        @Autowired
        private ShopRepository shopRepository;
        
        @Autowired
        private ShopAddressRepository shopAddressRepository;
        
        @Autowired
        private UserRoleRepository userRoleRepository;
        
        @Autowired
        private DocumentRepository documentRepository;
        
        @Autowired
        private PrivateDealUserRepository privateDealUserRepository;
        
        @Autowired
        private PrivateDealUserAddressMappingRepository privateDealUserAddressMappingRepository;
        
        @Autowired
        private CounterRepository counterRepository;
        
        @Autowired
        @Qualifier("userUserRepository")
        private com.spice.profitmandi.dao.repository.user.UserRepository userUserRepository;
        
        @Autowired
        private DistrictMasterRepository districtMasterRepository;
        
        @Autowired
        private FofoStoreRepository fofoStoreRepository;
        
        @Autowired
        private PaymentOptionRepository paymentOptionRepository;
        
        @Autowired
        private FofoPartnerPaymentOptionRepository fofoPartnerPaymentOptionRepository;
        
        @Autowired
        private RoleRepository roleRepository;
        
        
        @Override
        public Map<String, Object> getByEmailIdOrMobileNumber(String emailIdOrMobileNumber)
                        throws ProfitMandiBusinessException {
                User user = null;
                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", Utils.getAllStateNames());
                
                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);
                                
                                if(this.containsRoleType(userRoles, role.getId())){
                                        try{
                                                FofoStore fofoStore = fofoStoreRepository.selectByRetailerId(retailerId);
                                                map.put("fofoStore", fofoStore);
                                        }catch(ProfitMandiBusinessException profitMandiBusinessException){
                                                LOGGER.error("FofoStore code not found");
                                        }
                                }
                                
                                
                                try{
                                        PrivateDealUser privateDealUser = privateDealUserRepository.selectById(retailer.getId());
                                        if(privateDealUser.getCounterId() != null){
                                                Counter counter = counterRepository.selectById(privateDealUser.getCounterId());
                                                map.put("gstNumber", counter.getGstin());
                                        }
                                }catch(ProfitMandiBusinessException profitMandiBusinessException){
                                        LOGGER.error("PrivateDealUser not found");
                                }
                                try{
                                        int retailerAddressId = retailerRegisteredAddressRepository.selectAddressIdByRetailerId(retailer.getId());
                                        Address retailerAddress = addressRepository.selectById(retailerAddressId);
                                        map.put("retailerAddress", retailerAddress);
                                        StateInfo stateInfo = null;
                                        try {
                                                stateInfo = Utils.getStateInfo(retailerAddress.getState());
                                        } catch (Exception e) {
                                                e.printStackTrace();
                                                //throw new ProfitMandiBusinessException();
                                        }
                                        List<DistrictMaster> districtMasters = districtMasterRepository.selectByStateShortName(stateInfo.getShortName());
                                        map.put("districtMasters", districtMasters);
                                        
                                        List<Shop> shops = shopRepository.selectByRetailerId(retailer.getId());
                                map.put("shops", shops);
                                        this.addAddress(shops);
                                }catch(ProfitMandiBusinessException profitMandiBusinessException){
                                        LOGGER.error("Retailer Registered Address not found");
                                }
                        }catch(ProfitMandiBusinessException profitMandiBusinessException){
                                LOGGER.error("Retailer not found in user_account");
                        }
                }
                
                return map;
        }
        
        private boolean containsRoleType(List<UserRole> userRoles, int roleId){
                for(UserRole userRole : userRoles){
                        if(userRole.getRoleId() == roleId){
                                return true;
                        }
                }
                return false;
        }
        
        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;
                
        }
        
        @SuppressWarnings("unchecked")
        @Override
        public Map<String, Object> updateRetailerDetails(UpdateRetailerRequest updateRetailerRequest)
                        throws ProfitMandiBusinessException {
                Map<String, Object> map = this.getByEmailIdOrMobileNumber(updateRetailerRequest.getEmailIdOrMobileNumber());
                
                User user = (User)map.get("user");
                user = this.createUser(user, updateRetailerRequest);
                map.put("user", user);
                
                List<UserRole> userRoles = (List<UserRole>)map.get("userRoles");
                
                Role roleUser = roleRepository.selectByName(RoleType.USER.toString());
                
                userRoles = this.addRole(userRoles, user.getId(), roleUser.getId());
                
                Retailer retailer = (Retailer)map.get("retailer");
                retailer = this.updateRetailer(user, retailer, updateRetailerRequest);
                map.put("retailer", retailer);
                
                Role roleRetailer = roleRepository.selectByName(RoleType.RETAILER.toString());
                
                userRoles = this.addRole(userRoles, user.getId(), roleRetailer.getId());
                
                Role roleFofo = roleRepository.selectByName(RoleType.FOFO.toString());
                
                if(updateRetailerRequest.isFofo()){
                        
                        
                        userRoles = this.addRole(userRoles, user.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());
                        map.put("fofoStore", fofoStore);
                }
                
                this.createPrivateDealUser(user, 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){
                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.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);
                }
                return saholicUser.getId();
        }
        
        private Retailer updateRetailer(User user, Retailer retailer, UpdateRetailerRequest updateRetailerRequest) throws ProfitMandiBusinessException{
                if(retailer == null){
                        int saholicUserId = this.createSaholicUser(user, updateRetailerRequest.getName());
                        retailer = new Retailer();
                        retailer.setId(saholicUserId);
                }
                retailer.setActive(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()) {
                                documentRepository.deleteById(retailer.getDocumentId());
                        }
                        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);
                        userUserRepository.persist(user);
                } 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 system
        private 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) throws ProfitMandiBusinessException{
                if(address == null){
                        address = new Address();
                        address.setRetaierId(retailerId);
                        this.updateAddress(address, customAddress);
                        //addressRepository.persist(addressRetailer);
                        
                        final RetailerRegisteredAddress retailerRegisteredAddress = new RetailerRegisteredAddress();
                        retailerRegisteredAddress.setRetailerId(retailerId);
                        retailerRegisteredAddress.setAddressId(address.getId());
                        retailerRegisteredAddressRepository.persist(retailerRegisteredAddress);
                }
                return address;
        }
        
        private void updateAddress(Address address, CustomAddress customAddress){
                address.setName(customAddress.getName());
                address.setPhoneNumber(customAddress.getPhoneNumber());
                address.setLine1(customAddress.getLine1());
                address.setLine2(customAddress.getLine2());
                address.setCity(customAddress.getCity());
                address.setPinCode(customAddress.getPinCode());
                address.setState(customAddress.getState());
                addressRepository.persist(address);
        }
        
        private void updateRetailerShops(List<Shop> shops, Set<CustomShop> customShops, int retailerId, Address sameAsRetailerAddressValue) 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, Address sameAsRetailerAddressValue) throws ProfitMandiBusinessException{
                shop.setRetailerId(retailerId);
                shop.setName(customShop.getName());
                if(customShop.getDocumentId() > 0){
                        if(shop.getDocumentId() != null && shop.getDocumentId() != customShop.getDocumentId()) {
                                documentRepository.deleteById(shop.getDocumentId());
                        }
                        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 = addressRepository.selectById(shop.getAddressId());
                        LOGGER.info("found address : {}", address);
                        CustomAddress customAddress = customShop.getAddress();
                        LOGGER.info("requested address : {}", customAddress);
                        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);
                }
                
        }
        
        
        private void addAddress(List<Shop> shops){
                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){
                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){
                Function<ShopAddress, Integer> shopAddressToAddressIdFunction = new Function<ShopAddress, Integer>(){
                        @Override
                        public Integer apply(ShopAddress shopAddress) {
                                return shopAddress.getAddressId();
                        }
                };
                return shopAddresses.stream().map(shopAddressToAddressIdFunction).collect(Collectors.toList());
        }
        
        private Set<Integer> toShopIds(List<Shop> shops){
                Function<Shop, Integer> shopToAddressIdFunction = new Function<Shop, Integer>(){
                        @Override
                        public Integer apply(Shop shop) {
                                return shop.getId();
                        }
                };
                return shops.stream().map(shopToAddressIdFunction).collect(Collectors.toSet());
        }
        
        private String toString(List<UserRole> userRoles){
                Set<Integer> roleIds = new HashSet<>();
                for(UserRole userRole : userRoles) {
                        roleIds.add(userRole.getRoleId());
                }
                List<Role> roles = roleRepository.selectByIds(roleIds);
                Function<Role, String> roleToNameFunction = new Function<Role, String>(){
                        public String apply(Role role) {
                                return 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, String stateName) throws ProfitMandiBusinessException{
                FofoStore fofoStore = null;
                try{
                        fofoStore = fofoStoreRepository.selectByRetailerId(retailerId);
                }catch (ProfitMandiBusinessException profitMandiBusinessException) {
                        
                }
                
                if(fofoStore != null){
                        LOGGER.error(ResponseCodeHolder.getMessage("USR_1014"));
                        //throw new ProfitMandiBusinessException(ProfitMandiConstants.RETAILER_ID, retailer.getId(), "USR_1014");
                }else {
                        int retailerAddressId = retailerRegisteredAddressRepository.selectAddressIdByRetailerId(retailerId);
                        Address retailerAddress = addressRepository.selectById(retailerAddressId);
                        
                        StateInfo stateInfo = null;
                        try {
                                stateInfo = Utils.getStateInfo(retailerAddress.getState());
                        } catch (Exception e) {
                                // TODO Auto-generated catch block
                                e.printStackTrace();
                                //throw new ProfitMandiBusinessException();
                        }
                        DistrictMaster districtMaster = districtMasterRepository.selectByNameAndStateShortName(districtName, stateInfo.getShortName());
                        
                        fofoStore = new FofoStore();
                        fofoStore.setId(retailerId);
                        String latestStoreCode = fofoStoreRepository.selectLatestStore().getCode();
                        int latestCodeCounter = Integer.parseInt(latestStoreCode.replaceAll("[A-Z]", ""));
                        String fofoStoreCode = StringUtils.generateFofoStoreSequence(districtMaster.getStateShortName() + districtMaster.getShortName(), latestCodeCounter+1);
                        fofoStore.setCode(fofoStoreCode);
                        fofoStoreRepository.persist(fofoStore);
                }
                
                return fofoStore;
        }
        
        @Override
        public FofoStore createFofoStoreCodeByUserId(int userId, String districtName, String stateName) 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);
                
        }
        
        @Override
        public List<DistrictMaster> getAllDistrictMaster(String stateName) {
                StateInfo stateInfo = null;
                try {
                        stateInfo = Utils.getStateInfo(stateName);
                } catch (Exception e) {
                        e.printStackTrace();
                        //throw new ProfitMandiBusinessException();
                }
                return districtMasterRepository.selectByStateShortName(stateInfo.getShortName());
        }

        @Override
        public Map<Integer, CustomRetailer> getFofoRetailers(List<Integer> fofoIds) {
                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(x->x.getAddressId(), x->x));
                List<Address> addresses = addressRepository.selectByIds(new ArrayList<>(userAddressMap.keySet()));
                Map<Integer, CustomRetailer> customRetailersMap = new HashMap<>();
                for(Address address: addresses) {
                        com.spice.profitmandi.dao.entity.user.User user = userAddressMap.get(address.getId());
                        CustomRetailer customRetailer = new CustomRetailer();
                        customRetailer.setEmail(user.getEmailId());
                        customRetailer.setBusinessName(address.getName());
                        customRetailer.setMobileNumber(address.getPhoneNumber());
                        try {
                                customRetailer.setCartId(user.getActiveCartId());
                                PrivateDealUser pdu = privateDealUserRepository.selectById(address.getRetaierId());
                                Counter counter = counterRepository.selectById(pdu.getCounterId());
                                customRetailer.setGstNumber(counter.getGstin());
                        } catch(Exception e) {
                                customRetailer.setGstNumber(null);
                        }
                        CustomAddress address1 = new CustomAddress();
                        address1.setCity(address.getCity());
                        address1.setState(address.getState());
                        address1.setLine1(address.getLine1());
                        address1.setLine2(address.getLine2());
                        address1.setPinCode(address.getPinCode());
                        address1.setName(address.getName());
                        customRetailer.setAddress(address1);
                        customRetailer.setPartnerId(address.getRetaierId());
                        customRetailersMap.put(address.getRetaierId(), customRetailer);
                }
                return customRetailersMap;
        }
        
        @Override
        public Map<Integer, String> getAllFofoRetailerIdEmailIdMap() {
                Role roleFofo = null;
                try {
                        roleFofo = roleRepository.selectByName(RoleType.FOFO.toString());
                } catch (ProfitMandiBusinessException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }
                Role roleRetailer = null;
                try {
                        roleRetailer = roleRepository.selectByName(RoleType.RETAILER.toString());
                } catch (ProfitMandiBusinessException e) {
                        // TODO Auto-generated catch block
                        e.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;
        }
        
        @Override
        public List<MapWrapper<Integer, String>> getFofoRetailerIdEmailIdMap() {
                List<MapWrapper<Integer, String>> mapWrappers = new ArrayList<>();
                for(Map.Entry<Integer, String> retailerIdEmailIdEntry : this.getAllFofoRetailerIdEmailIdMap().entrySet()) {
                        MapWrapper<Integer, String> mapWrapper = new MapWrapper<>();
                        mapWrapper.setKey(retailerIdEmailIdEntry.getKey());
                        mapWrapper.setValue(retailerIdEmailIdEntry.getValue());
                        mapWrappers.add(mapWrapper);
                }
                return mapWrappers;
        }
        
        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){
                List<User> users = userRepository.selectAllByIds(userIds);
                Map<Integer, String> userIdEmailIdMap = new HashMap<>();
                for(User user : users) {
                        userIdEmailIdMap.put(user.getId(), user.getEmailId());
                }
                return userIdEmailIdMap;
        }

        @Override
        public Map<Integer, String> getAllFofoRetailerIdEmailIdMap(Set<Integer> retailerIds) {
                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;
        }

}