Subversion Repositories SmartDukaan

Rev

Rev 37156 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
22980 ashik.ali 1
package com.spice.profitmandi.service.user;
2
 
35289 amit 3
import com.fasterxml.jackson.databind.ObjectMapper;
26528 amit.gupta 4
import com.google.common.hash.Hashing;
35289 amit 5
import com.google.gson.Gson;
30097 tejbeer 6
import com.spice.profitmandi.common.enumuration.ActivationType;
7
import com.spice.profitmandi.common.enumuration.FofoType;
22980 ashik.ali 8
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
30017 amit.gupta 9
import com.spice.profitmandi.common.model.*;
23329 ashik.ali 10
import com.spice.profitmandi.common.util.StringUtils;
11
import com.spice.profitmandi.common.util.Utils;
35418 aman 12
import com.spice.profitmandi.dao.entity.catalog.BrandCatalog;
35203 amit 13
import com.spice.profitmandi.dao.entity.dtr.*;
22980 ashik.ali 14
import com.spice.profitmandi.dao.entity.dtr.User;
30017 amit.gupta 15
import com.spice.profitmandi.dao.entity.fofo.*;
24349 amit.gupta 16
import com.spice.profitmandi.dao.entity.inventory.State;
33124 ranu 17
import com.spice.profitmandi.dao.entity.logistics.AST;
18
import com.spice.profitmandi.dao.entity.logistics.ASTRepository;
30017 amit.gupta 19
import com.spice.profitmandi.dao.entity.user.*;
23063 ashik.ali 20
import com.spice.profitmandi.dao.enumuration.dtr.AccountType;
23106 ashik.ali 21
import com.spice.profitmandi.dao.enumuration.dtr.RetailerType;
23136 ashik.ali 22
import com.spice.profitmandi.dao.enumuration.dtr.RoleType;
23365 ashik.ali 23
import com.spice.profitmandi.dao.enumuration.fofo.PaymentOptionType;
29042 tejbeer 24
import com.spice.profitmandi.dao.enumuration.transaction.PartnerVerificationApprovalStatus;
34813 aman 25
import com.spice.profitmandi.dao.model.LastMonthCreditedIncomeModel;
35203 amit 26
import com.spice.profitmandi.dao.repository.dtr.*;
22980 ashik.ali 27
import com.spice.profitmandi.dao.repository.dtr.UserRepository;
34813 aman 28
import com.spice.profitmandi.dao.repository.fofo.*;
24349 amit.gupta 29
import com.spice.profitmandi.dao.repository.inventory.StateRepository;
35289 amit 30
import com.spice.profitmandi.dao.repository.trialOnboarding.TrialFormRepository;
30017 amit.gupta 31
import com.spice.profitmandi.dao.repository.user.*;
33124 ranu 32
import com.spice.profitmandi.service.PostOfficeService;
35203 amit 33
import com.spice.profitmandi.service.catalog.BrandsService;
23043 ashik.ali 34
import in.shop2020.model.v1.user.CartStatus;
30017 amit.gupta 35
import org.apache.logging.log4j.LogManager;
36
import org.apache.logging.log4j.Logger;
37
import org.springframework.beans.factory.annotation.Autowired;
38
import org.springframework.beans.factory.annotation.Qualifier;
39
import org.springframework.cache.annotation.Cacheable;
35289 amit 40
import org.springframework.mail.javamail.JavaMailSender;
30017 amit.gupta 41
import org.springframework.stereotype.Component;
37156 amit 42
import org.springframework.transaction.annotation.Transactional;
23043 ashik.ali 43
 
30017 amit.gupta 44
import java.nio.charset.StandardCharsets;
34813 aman 45
import java.time.LocalDate;
30017 amit.gupta 46
import java.time.LocalDateTime;
34813 aman 47
import java.time.YearMonth;
48
import java.time.format.DateTimeFormatter;
30017 amit.gupta 49
import java.util.*;
50
import java.util.function.Function;
51
import java.util.stream.Collectors;
52
import java.util.stream.Stream;
53
 
22980 ashik.ali 54
@Component
55
public class RetailerServiceImpl implements RetailerService {
23955 govind 56
 
31734 tejbeer 57
    private static final Logger LOGGER = LogManager.getLogger(RetailerServiceImpl.class);
35289 amit 58
    private static final String[] TRIAL_CODE_CREATION_AUDIENCE = new String[]{"amit.gupta@smartdukaan.com"};
59
    //private static final String [] TRIAL_CODE_CREATION_AUDIENCE = new String[]{};
23955 govind 60
 
31734 tejbeer 61
    @Autowired
62
    private RetailerRepository retailerRepository;
23955 govind 63
 
31734 tejbeer 64
    @Autowired
65
    private RetailerBlockBrandsRepository retailerBlockBrandsRepository;
28024 tejbeer 66
 
31734 tejbeer 67
    @Autowired
68
    private UserAccountRepository userAccountRepository;
23955 govind 69
 
31734 tejbeer 70
    @Autowired
71
    private Mongo mongoClient;
28024 tejbeer 72
 
31734 tejbeer 73
    @Autowired
35289 amit 74
    Gson gson;
75
 
76
    @Autowired
31734 tejbeer 77
    private UserRepository userRepository;
35289 amit 78
    @Autowired
79
    ObjectMapper objectMapper;
23955 govind 80
 
35289 amit 81
 
31734 tejbeer 82
    @Autowired
83
    private CartRepository cartRepository;
23955 govind 84
 
31734 tejbeer 85
    @Autowired
86
    private RetailerRegisteredAddressRepository retailerRegisteredAddressRepository;
23955 govind 87
 
31734 tejbeer 88
    @Autowired
89
    private AddressRepository addressRepository;
23955 govind 90
 
31734 tejbeer 91
    @Autowired
92
    private ShopRepository shopRepository;
23955 govind 93
 
31734 tejbeer 94
    @Autowired
95
    private ShopAddressRepository shopAddressRepository;
23955 govind 96
 
31734 tejbeer 97
    @Autowired
98
    private UserRoleRepository userRoleRepository;
23955 govind 99
 
31734 tejbeer 100
    @Autowired
101
    private DocumentRepository documentRepository;
23955 govind 102
 
31734 tejbeer 103
    @Autowired
104
    private PrivateDealUserRepository privateDealUserRepository;
23955 govind 105
 
31734 tejbeer 106
    @Autowired
32737 amit.gupta 107
    private RetailerContactRepository retailerContactRepository;
108
 
109
    @Autowired
31734 tejbeer 110
    private PrivateDealUserAddressMappingRepository privateDealUserAddressMappingRepository;
23955 govind 111
 
31734 tejbeer 112
    @Autowired
113
    private CounterRepository counterRepository;
25295 amit.gupta 114
 
31734 tejbeer 115
    @Autowired
116
    private StateRepository stateRepository;
35289 amit 117
    @Autowired
118
    private TrialFormRepository trialFormRepository;
23955 govind 119
 
31734 tejbeer 120
    @Autowired
121
    @Qualifier("userUserRepository")
122
    private com.spice.profitmandi.dao.repository.user.UserRepository userUserRepository;
23955 govind 123
 
31734 tejbeer 124
    @Autowired
125
    private DistrictMasterRepository districtMasterRepository;
23955 govind 126
 
31734 tejbeer 127
    @Autowired
128
    private FofoStoreRepository fofoStoreRepository;
23955 govind 129
 
31734 tejbeer 130
    @Autowired
33124 ranu 131
    private ASTRepository aSTRepository;
132
 
133
    @Autowired
134
    private PostOfficeService postOfficeService;
135
 
136
    @Autowired
31734 tejbeer 137
    private PaymentOptionRepository paymentOptionRepository;
23955 govind 138
 
31734 tejbeer 139
    @Autowired
140
    private FofoPartnerPaymentOptionRepository fofoPartnerPaymentOptionRepository;
23955 govind 141
 
31734 tejbeer 142
    @Autowired
143
    private RoleRepository roleRepository;
23955 govind 144
 
31734 tejbeer 145
    @Autowired
146
    private StoreTimelineTatService storeTimelineTatService;
28908 tejbeer 147
 
31734 tejbeer 148
    @Autowired
149
    private PartnerOnBoardingPanelRepository partnerOnBoardingPanelRepository;
28908 tejbeer 150
 
31734 tejbeer 151
    @Autowired
152
    private PartnerOnboardingVerificationRepository partnerOnboardingVerificationRepository;
29042 tejbeer 153
 
31734 tejbeer 154
    @Autowired
155
    private PincodePartnerRepository pincodePartnerRepository;
30719 tejbeer 156
 
34813 aman 157
    @Autowired
158
    SchemeInOutRepository schemeInOutRepository;
159
 
160
    @Autowired
161
    OfferPayoutRepository offerPayoutRepository;
162
 
163
    @Autowired
164
    PartnerTypeChangeService partnerTypeChangeService;
165
 
35203 amit 166
    @Autowired
167
    BrandsService brandsService;
35289 amit 168
    @Autowired
169
    private JavaMailSender googleMailSender;
35203 amit 170
 
31734 tejbeer 171
    @Override
172
    public Map<String, Object> getByEmailIdOrMobileNumber(String emailIdOrMobileNumber) throws ProfitMandiBusinessException {
173
        User user = null;
28024 tejbeer 174
 
31734 tejbeer 175
        try {
176
            user = userRepository.selectByEmailIdOrMobileNumber(emailIdOrMobileNumber);
177
        } catch (ProfitMandiBusinessException profitMandiBusinessException) {
23955 govind 178
 
31734 tejbeer 179
        }
180
        if (user == null) {
181
            try {
182
                user = userRepository.selectBySecondryEmailId(emailIdOrMobileNumber);
183
            } catch (ProfitMandiBusinessException profitMandiBusinessException) {
23955 govind 184
 
31734 tejbeer 185
            }
186
        }
187
        Map<String, Object> map = new HashMap<>();
35394 amit 188
        map.put("stateNames", stateRepository.selectAll().stream().map(State::getName).collect(Collectors.toList()));
35289 amit 189
        LOGGER.info("user - {}", user);
31734 tejbeer 190
        if (user != null) {
23955 govind 191
 
31734 tejbeer 192
            List<UserRole> userRoles = userRoleRepository.selectByUserId(user.getId());
23955 govind 193
 
31734 tejbeer 194
            Role role = roleRepository.selectByName(RoleType.FOFO.toString());
23955 govind 195
 
31734 tejbeer 196
            map.put("userRoles", userRoles);
197
            map.put("user", user);
198
            // map.put("retailer", retailer);
199
            map.put("fofoRole", this.containsRoleType(userRoles, role.getId()));
23955 govind 200
 
31734 tejbeer 201
            map.put("userRoleNames", this.toString(userRoles));
202
            try {
203
                int retailerId = userAccountRepository.selectRetailerIdByUserId(user.getId());
204
                Retailer retailer = retailerRepository.selectById(retailerId);
23955 govind 205
 
31734 tejbeer 206
                map.put("retailer", retailer);
23955 govind 207
 
37102 amit 208
                // This screen edits manual brand blocks only. Ineligibility (commitment/DMS) is
209
                // derived and enforced at order time, so the dropdown offers every brand.
210
                Set<String> brands = brandsService.getBrandsToDisplay(3).stream()
211
                        .map(BrandCatalog::getName).collect(Collectors.toSet());
212
                List<String> retailerBlockBrands = retailerBlockBrandsRepository.selectAllByRetailer(retailer.getId())
213
                        .stream().map(x -> x.getBlockBrands()).collect(Collectors.toList());
31734 tejbeer 214
                map.put("brands", brands);
215
                map.put("retailerBlockBrands", retailerBlockBrands);
23955 govind 216
 
31734 tejbeer 217
                try {
35896 amit 218
                    FofoStore gstStore = fofoStoreRepository.selectByRetailerId(retailer.getId());
219
                    map.put("gstNumber", gstStore != null ? gstStore.getGstNumber() : null);
220
                } catch (ProfitMandiBusinessException e) {
221
                    LOGGER.error("FofoStore not found for GST lookup");
31734 tejbeer 222
                }
223
                try {
224
                    int retailerAddressId = retailerRegisteredAddressRepository.selectAddressIdByRetailerId(retailer.getId());
225
                    Address retailerAddress = addressRepository.selectById(retailerAddressId);
226
                    map.put("retailerAddress", retailerAddress);
227
                    State state = stateRepository.selectByName(retailerAddress.getState());
228
                    // LOGGER.info("retailerAddress.." + retailerAddress);
229
                    List<DistrictMaster> districtMasters = districtMasterRepository.selectByStateShortName(state.getShortName());
230
                    map.put("districtMasters", districtMasters);
231
                    // LOGGER.info("districtMasters" + districtMasters);
232
                    List<Shop> shops = shopRepository.selectByRetailerId(retailer.getId());
233
                    map.put("shops", shops);
234
                    this.addAddress(shops);
33128 amit.gupta 235
 
236
                    if (this.containsRoleType(userRoles, role.getId())) {
237
                        try {
238
                            FofoStore fofoStore = fofoStoreRepository.selectByRetailerId(retailerId);
239
                            map.put("fofoStore", fofoStore);
240
                            List<AST> astDetail = postOfficeService.getAreasAndTerritoriesByStateName(retailerAddress.getState());
241
                            LOGGER.info("astDetail {}", astDetail);
242
                            map.put("astDetail", astDetail);
243
 
244
 
245
                            // map.put("counterSize", fofoStore.getCounterSize().toString());
246
                            // LOGGER.info("fofoStore" + fofoStore);
247
                        } catch (ProfitMandiBusinessException profitMandiBusinessException) {
248
                            LOGGER.error("FofoStore code not found");
249
                        }
250
                    }
31734 tejbeer 251
                    // LOGGER.info("shops" + shops);
252
                } catch (ProfitMandiBusinessException profitMandiBusinessException) {
253
                    LOGGER.error("Retailer Registered Address not found");
254
                }
255
            } catch (ProfitMandiBusinessException profitMandiBusinessException) {
256
                LOGGER.error("Retailer not found in user_account");
257
            }
35289 amit 258
        } else {
259
            try {
260
                TrialForm trialForm = trialFormRepository.selectByEmailOrMobile(emailIdOrMobileNumber);
35372 aman 261
                LOGGER.info("trialForm - {}", trialForm);
35289 amit 262
                map.put("trialForm", gson.toJson(trialForm));
263
            } catch (Exception e) {
264
                LOGGER.error("Retailer not found in user_account");
265
            }
31734 tejbeer 266
        }
23955 govind 267
 
31734 tejbeer 268
        return map;
269
    }
23955 govind 270
 
31734 tejbeer 271
    private boolean containsRoleType(List<UserRole> userRoles, int roleId) {
35394 amit 272
        return userRoles != null && userRoles.stream().anyMatch(ur -> ur.getRoleId() == roleId);
31734 tejbeer 273
    }
23955 govind 274
 
31734 tejbeer 275
    private List<UserRole> addRole(List<UserRole> userRoles, int userId, int roleId) {
276
        if (userRoles == null) {
277
            userRoles = new ArrayList<>();
278
        }
279
        if (!this.containsRoleType(userRoles, roleId)) {
280
            UserRole userRole = new UserRole();
281
            userRole.setUserId(userId);
282
            userRole.setRoleId(roleId);
283
            try {
284
                userRoleRepository.persist(userRole);
285
            } catch (ProfitMandiBusinessException e) {
286
                LOGGER.error("UserRole is already exist");
287
            }
288
            userRoles.add(userRole);
289
        }
290
        return userRoles;
23955 govind 291
 
31734 tejbeer 292
    }
23955 govind 293
 
31734 tejbeer 294
    private List<UserRole> removeRole(List<UserRole> userRoles, int userId, int roleId) {
295
        if (userRoles == null) {
296
            userRoles = new ArrayList<>();
297
            return userRoles;
298
        }
299
        try {
300
            userRoles.remove(userRoleRepository.deleteByRoleUserId(userId, roleId));
301
        } catch (Exception e) {
25295 amit.gupta 302
 
31734 tejbeer 303
        }
304
        return userRoles;
25295 amit.gupta 305
 
31734 tejbeer 306
    }
25295 amit.gupta 307
 
31734 tejbeer 308
    @SuppressWarnings("unchecked")
309
    @Override
37156 amit 310
    @Transactional(rollbackFor = Throwable.class)
33128 amit.gupta 311
    public Map<String, Object> updateRetailerDetails(UpdateRetailerRequest updateRetailerRequest) throws
312
            ProfitMandiBusinessException {
31734 tejbeer 313
        Map<String, Object> map = this.getByEmailIdOrMobileNumber(updateRetailerRequest.getEmailIdOrMobileNumber());
32953 amit.gupta 314
        User dtrUser = (User) map.get("user");
28024 tejbeer 315
 
37156 amit 316
        if (updateRetailerRequest.isFofo()) {
317
            Retailer resolvedRetailer = (Retailer) map.get("retailer");
318
            if (resolvedRetailer == null) {
319
                // This save would mint a brand-new identity chain. Mandate: a partner
320
                // gets a new store code only after the old store is closed, and the
321
                // re-onboarding must reuse the partner's real email (takeover below) —
322
                // never a variant email that forks a duplicate chain.
323
                this.guardAgainstDuplicatePartnerChain(updateRetailerRequest);
324
            } else if (updateRetailerRequest.isActive()) {
325
                FofoStore existingStore = this.selectStoreOrNull(resolvedRetailer.getId());
326
                if (existingStore != null && existingStore.isClosed()) {
327
                    this.takeoverClosedStoreIdentity(existingStore, map);
328
                }
329
            }
330
        }
331
 
32953 amit.gupta 332
        dtrUser = this.createUser(dtrUser, updateRetailerRequest);
28024 tejbeer 333
 
32953 amit.gupta 334
        map.put("user", dtrUser);
31734 tejbeer 335
        List<UserRole> userRoles = (List<UserRole>) map.get("userRoles");
336
        Role roleUser = roleRepository.selectByName(RoleType.USER.toString());
32953 amit.gupta 337
        userRoles = this.addRole(userRoles, dtrUser.getId(), roleUser.getId());
31734 tejbeer 338
        Retailer retailer = (Retailer) map.get("retailer");
32953 amit.gupta 339
        retailer = this.updateRetailer(dtrUser, retailer, updateRetailerRequest);
28024 tejbeer 340
 
31734 tejbeer 341
        map.put("retailer", retailer);
23955 govind 342
 
37156 amit 343
        // Ensure the dtr login's bridge rows point at the current identity. Repairs
344
        // recreated logins and repoints the login after a closed-store takeover.
345
        userAccountRepository.upsert(dtrUser.getId(), AccountType.saholic, retailer.getId());
35971 aman 346
        try {
37156 amit 347
            com.spice.profitmandi.dao.entity.user.User identity = userUserRepository.selectById(retailer.getId());
348
            if (identity.getActiveCartId() > 0) {
349
                userAccountRepository.upsert(dtrUser.getId(), AccountType.cartId, identity.getActiveCartId());
350
            }
35971 aman 351
        } catch (ProfitMandiBusinessException e) {
37156 amit 352
            LOGGER.error("Error ensuring cartId UserAccount for userId: {}", dtrUser.getId(), e);
35971 aman 353
        }
354
 
31734 tejbeer 355
        List<String> retailerBlockBrands = retailerBlockBrandsRepository.selectAllByRetailer(retailer.getId()).stream().map(x -> x.getBlockBrands()).collect(Collectors.toList());
28024 tejbeer 356
 
31734 tejbeer 357
        LOGGER.info("retailerBlockBrands" + retailerBlockBrands);
28189 tejbeer 358
 
31734 tejbeer 359
        if (!retailerBlockBrands.isEmpty()) {
360
            retailerBlockBrandsRepository.deleteBrands(retailer.getId());
361
        }
28024 tejbeer 362
 
37102 amit 363
        List<String> requestedBlockBrands = updateRetailerRequest.getBlocksBrands() != null
364
                ? updateRetailerRequest.getBlocksBrands() : new ArrayList<>();
365
 
366
        for (String blockBrand : requestedBlockBrands) {
31734 tejbeer 367
            RetailerBlockBrands retailerBlockBrand = new RetailerBlockBrands();
28024 tejbeer 368
 
31734 tejbeer 369
            retailerBlockBrand.setFofoId(retailer.getId());
370
            retailerBlockBrand.setBlockBrands(blockBrand);
371
            retailerBlockBrandsRepository.persist(retailerBlockBrand);
28024 tejbeer 372
 
31734 tejbeer 373
        }
374
        map.put("retailerBlockBrands", retailerBlockBrands);
28024 tejbeer 375
 
31734 tejbeer 376
        Role roleRetailer = roleRepository.selectByName(RoleType.RETAILER.toString());
23955 govind 377
 
32953 amit.gupta 378
        userRoles = this.addRole(userRoles, dtrUser.getId(), roleRetailer.getId());
23955 govind 379
 
31734 tejbeer 380
        Role roleFofo = roleRepository.selectByName(RoleType.FOFO.toString());
23955 govind 381
 
31734 tejbeer 382
        if (updateRetailerRequest.isFofo()) {
32953 amit.gupta 383
            userRoles = this.addRole(userRoles, dtrUser.getId(), roleFofo.getId());
31734 tejbeer 384
        } else {
32953 amit.gupta 385
            userRoles = this.removeRole(userRoles, dtrUser.getId(), roleFofo.getId());
31734 tejbeer 386
        }
387
        map.put("fofoRole", this.containsRoleType(userRoles, roleFofo.getId()));
23955 govind 388
 
31734 tejbeer 389
        if (this.containsRoleType(userRoles, roleFofo.getId())) {
390
            this.createDefaultPaymentOption(retailer.getId());
391
        }
23955 govind 392
 
31734 tejbeer 393
        map.put("userRoles", userRoles);
394
        map.put("userRoleNames", this.toString(userRoles));
23955 govind 395
 
31734 tejbeer 396
        Address retailerAddress = (Address) map.get("retailerAddress");
397
        retailerAddress = this.updateRetailerAddress(retailerAddress, updateRetailerRequest.getAddress(), retailer.getId());
398
        map.put("retailerAddress", retailerAddress);
23955 govind 399
 
31734 tejbeer 400
        if (updateRetailerRequest.isFofo()) {
401
            FofoStore fofoStore = this.createFofoStoreCodeByRetailerId(retailer.getId(), updateRetailerRequest.getDistrictName(), retailerAddress.getState(), updateRetailerRequest);
402
            map.put("fofoStore", fofoStore);
35956 amit 403
            if (fofoStore.isClosed() && updateRetailerRequest.isActive()) {
404
                throw new ProfitMandiBusinessException("Store Closed", "Store Permanently Closed",
405
                        "This store is permanently closed and cannot be reactivated");
406
            }
31734 tejbeer 407
            fofoStore.setActive(updateRetailerRequest.isActive());
33131 ranu 408
            List<AST> astDetail = postOfficeService.getAreasAndTerritoriesByStateName(retailerAddress.getState());
409
            map.put("astDetail", astDetail);
31734 tejbeer 410
        }
23955 govind 411
 
37102 amit 412
        this.createPrivateDealUser(dtrUser, updateRetailerRequest.getGstNumber(), retailer, retailerAddress.getId());
31734 tejbeer 413
        map.put("gstNumber", updateRetailerRequest.getGstNumber());
414
        this.updateSaholicUser(retailer.getId(), retailerAddress.getId());
23955 govind 415
 
31734 tejbeer 416
        List<Shop> shops = (List<Shop>) map.get("shops");
417
        if (shops == null) {
418
            shops = new ArrayList<>();
419
            map.put("shops", shops);
420
        }
421
        this.updateRetailerShops(shops, updateRetailerRequest.getShops(), retailer.getId(), retailerAddress);
23955 govind 422
 
31734 tejbeer 423
        return map;
23955 govind 424
 
31734 tejbeer 425
    }
23955 govind 426
 
37156 amit 427
    private FofoStore selectStoreOrNull(int retailerId) {
428
        try {
429
            return fofoStoreRepository.selectByRetailerId(retailerId);
430
        } catch (ProfitMandiBusinessException e) {
431
            return null;
432
        }
433
    }
434
 
435
    private void guardAgainstDuplicatePartnerChain(UpdateRetailerRequest updateRetailerRequest)
436
            throws ProfitMandiBusinessException {
437
        User byMobile = null;
438
        try {
439
            byMobile = userRepository.selectByMobileNumber(updateRetailerRequest.getUserMobileNumber());
440
        } catch (ProfitMandiBusinessException e) {
441
            // no dtr user with this mobile
442
        }
443
        if (byMobile != null) {
444
            Integer accountKey = userAccountRepository.selectSaholicAccountKeySafe(byMobile.getId());
445
            FofoStore store = accountKey != null ? this.selectStoreOrNull(accountKey) : null;
446
            if (store != null) {
447
                if (!store.isClosed()) {
448
                    throw new ProfitMandiBusinessException("Open store exists", store.getCode(),
449
                            "Partner mobile " + updateRetailerRequest.getUserMobileNumber()
450
                                    + " already owns open store " + store.getCode()
451
                                    + ". Close it first, or use email-change to keep the same code.");
452
                }
453
                throw new ProfitMandiBusinessException("Closed store exists", store.getCode(),
454
                        "Old store " + store.getCode() + " is closed. Re-onboard using the partner's existing email "
455
                                + byMobile.getEmailId() + " and a new code will be issued automatically.");
456
            }
457
        }
37168 amit 458
        // Same GST is normal (one GSTIN per entity per state; parallel outlets share it).
459
        // Block only when a sibling store is in limbo: dormant (REVIVAL) or deactivated
460
        // without being closed — the signature of a revival being forked instead of the
461
        // old code being closed or revived in place.
462
        List<FofoStore> limboGstStores = fofoStoreRepository.selectAllOpenByGstNumber(updateRetailerRequest.getGstNumber())
463
                .stream()
464
                .filter(s -> !s.isInternal())
465
                .filter(s -> s.getActivationType() == ActivationType.REVIVAL || !s.isActive())
466
                .collect(Collectors.toList());
467
        if (!limboGstStores.isEmpty()) {
468
            String codes = limboGstStores.stream().map(FofoStore::getCode).collect(Collectors.joining(", "));
469
            throw new ProfitMandiBusinessException("Dormant store exists for GST", codes,
470
                    "GST " + updateRetailerRequest.getGstNumber() + " has store(s) " + codes
471
                            + " that are dormant or deactivated but not closed. Close them or revive them on the same code before creating a new store.");
37156 amit 472
        }
473
    }
474
 
475
    private void takeoverClosedStoreIdentity(FofoStore oldStore, Map<String, Object> map) {
476
        // Mandate: closed stores are never reopened. Re-onboarding with the partner's
477
        // real contacts issues a fresh code on the same dtr login: free the old
478
        // identity's email so the new user.user can take it over, then drop the old
479
        // chain from the resolution map so the save proceeds as a fresh onboarding.
480
        try {
481
            com.spice.profitmandi.dao.entity.user.User oldIdentity = userUserRepository.selectById(oldStore.getId());
482
            String tombstone = "closed." + oldStore.getId() + "." + oldIdentity.getEmailId();
483
            if (tombstone.length() > 128) {
484
                tombstone = tombstone.substring(0, 128);
485
            }
486
            oldIdentity.setEmailId(tombstone);
487
        } catch (ProfitMandiBusinessException e) {
488
            LOGGER.error("Takeover: identity not found for closed store {}", oldStore.getId(), e);
489
        }
490
        LOGGER.info("Takeover: closed store {} ({}) — issuing new code on the same login", oldStore.getCode(), oldStore.getId());
491
        map.remove("retailer");
492
        map.remove("retailerAddress");
493
        map.remove("shops");
494
        map.remove("fofoStore");
495
    }
496
 
31734 tejbeer 497
    private void createDefaultPaymentOption(int fofoId) {
498
        List<Integer> paymentOptionIds = fofoPartnerPaymentOptionRepository.selectPaymentOptionIdsByFofoId(fofoId);
499
        if (paymentOptionIds.isEmpty()) {
500
            PaymentOption paymentOption = null;
501
            try {
502
                paymentOption = paymentOptionRepository.selectByName(PaymentOptionType.CASH.toString());
503
            } catch (ProfitMandiBusinessException profitMandiBusinessException) {
504
                paymentOption = new PaymentOption();
505
                paymentOption.setName(PaymentOptionType.CASH.toString());
506
                paymentOptionRepository.persist(paymentOption);
507
            }
508
            FofoPartnerPaymentOption fofoPartnerPaymentOption = new FofoPartnerPaymentOption();
509
            fofoPartnerPaymentOption.setFofoId(fofoId);
510
            fofoPartnerPaymentOption.setPaymentOptionId(paymentOption.getId());
511
            fofoPartnerPaymentOptionRepository.persist(fofoPartnerPaymentOption);
512
        }
23955 govind 513
 
31734 tejbeer 514
    }
23955 govind 515
 
33128 amit.gupta 516
    private User createUser(User user, UpdateRetailerRequest updateRetailerRequest) throws
517
            ProfitMandiBusinessException {
32965 amit.gupta 518
 
519
        User dtrUser = null;
520
        try {
521
            dtrUser = userRepository.selectByMobileNumber(updateRetailerRequest.getUserMobileNumber());
522
        } catch (ProfitMandiBusinessException e) {
523
            //Ignore the exception
524
        }
33140 ranu 525
        if (dtrUser != null && (user == null || user.getId() != dtrUser.getId()))
526
            throw new ProfitMandiBusinessException("Mobile already exist", updateRetailerRequest.getUserMobileNumber(), dtrUser.getEmailId());
32966 amit.gupta 527
 
528
        User dtrUserByEmail = null;
529
        try {
530
            dtrUserByEmail = userRepository.selectByEmailId(updateRetailerRequest.getUserEmailId());
531
        } catch (ProfitMandiBusinessException e) {
532
            //ignore the exception
533
        }
33025 amit.gupta 534
        if (user != null && dtrUserByEmail != null && user.getId() != dtrUserByEmail.getId())
32965 amit.gupta 535
            throw new ProfitMandiBusinessException("Email already exist", updateRetailerRequest.getUserEmailId(), "");
32953 amit.gupta 536
 
537
 
31734 tejbeer 538
        if (user == null) {
539
            user = new User();
540
            user.setCity("");
541
            user.setPinCode(0);
542
            user.setState("");
543
            user.setPassword("");
544
            user.setMobile_verified(false);
545
            user.setReferral_url("");
546
            user.setGroup_id(1);
547
            user.setStatus(1);
548
            user.setActivated(true);
549
            user.setCreateTimestamp(LocalDateTime.now());
550
        }
551
        user.setActivated(updateRetailerRequest.isActive());
552
        user.setFirstName(updateRetailerRequest.getUserFirstName());
553
        user.setLastName(updateRetailerRequest.getUserLastName());
554
        user.setMobileNumber(updateRetailerRequest.getUserMobileNumber());
555
        user.setEmailId(updateRetailerRequest.getUserEmailId());
556
        user.setUsername(updateRetailerRequest.getUserEmailId());
557
        user.setUpdateTimestamp(LocalDateTime.now());
558
        userRepository.persist(user);
559
        return user;
23955 govind 560
 
31734 tejbeer 561
    }
23955 govind 562
 
31734 tejbeer 563
    private int createSaholicUser(User user, String retailerName) {
564
        com.spice.profitmandi.dao.entity.user.User saholicUser = null;
565
        try {
566
            saholicUser = userUserRepository.selectByEmailId(user.getEmailId());
567
        } catch (ProfitMandiBusinessException e) {
568
            LOGGER.info("User doesnt exist in old system");
569
        }
570
        if (saholicUser == null) {
571
            Cart cart = new Cart();
572
            cart.setCartStatus(CartStatus.ACTIVE);
573
            cartRepository.persist(cart);
574
            saholicUser = new com.spice.profitmandi.dao.entity.user.User();
575
            saholicUser.setEmailId(user.getEmailId());
576
            saholicUser.setName(retailerName);
577
            saholicUser.setActiveCartId(cart.getId());
578
            saholicUser.setCreateTimestamp(LocalDateTime.now());
579
            userUserRepository.persist(saholicUser);
23955 govind 580
 
37156 amit 581
            userAccountRepository.upsert(user.getId(), AccountType.saholic, saholicUser.getId());
582
            userAccountRepository.upsert(user.getId(), AccountType.cartId, saholicUser.getActiveCartId());
31734 tejbeer 583
            LOGGER.info("created....");
584
        }
585
        return saholicUser.getId();
586
    }
23955 govind 587
 
31734 tejbeer 588
    private com.spice.profitmandi.dao.entity.user.User createSaholicUser(
32953 amit.gupta 589
            LoginRequestResponseModel loginRequestResponseModel) {
31734 tejbeer 590
        com.spice.profitmandi.dao.entity.user.User saholicUser = null;
591
        try {
592
            saholicUser = userUserRepository.selectByEmailId(loginRequestResponseModel.getEmail());
593
            saholicUser.setCreateTimestamp(LocalDateTime.now());
594
        } catch (ProfitMandiBusinessException e) {
595
            LOGGER.info("User doesnt exist in old system");
596
        }
597
        if (saholicUser == null) {
598
            Cart cart = new Cart();
599
            cart.setCartStatus(CartStatus.ACTIVE);
600
            cartRepository.persist(cart);
601
            saholicUser = new com.spice.profitmandi.dao.entity.user.User();
602
            saholicUser.setPassword(getHash256(loginRequestResponseModel.getPassword()));
603
            saholicUser.setEmailId(loginRequestResponseModel.getEmail());
604
            saholicUser.setName(loginRequestResponseModel.getCustomerName());
605
            saholicUser.setActiveCartId(cart.getId());
606
            saholicUser.setCreateTimestamp(LocalDateTime.now());
607
            loginRequestResponseModel.setPassword(null);
608
            userUserRepository.persist(saholicUser);
609
        }
610
        return saholicUser;
611
    }
26522 amit.gupta 612
 
33128 amit.gupta 613
    private Retailer updateRetailer(User user, Retailer retailer, UpdateRetailerRequest updateRetailerRequest) throws
614
            ProfitMandiBusinessException {
31734 tejbeer 615
        if (retailer == null) {
616
            LOGGER.info("createSaholicUser.....");
617
            int saholicUserId = this.createSaholicUser(user, updateRetailerRequest.getName());
618
            retailer = new Retailer();
619
            retailer.setId(saholicUserId);
620
        }
621
        retailer.setActive(updateRetailerRequest.isActive());
622
        user.setActivated(updateRetailerRequest.isActive());//
623
        // this.createRole(user.getId(), RoleType.RETAILER);
624
        retailer.setName(updateRetailerRequest.getName());
625
        retailer.setNumber(updateRetailerRequest.getNumber());
626
        if (updateRetailerRequest.getNumber() == null || updateRetailerRequest.getNumber().isEmpty()) {
627
            retailer.setType(RetailerType.UNREGISTERED_SHOP);
628
        } else {
629
            retailer.setType(RetailerType.GSTIN);
630
        }
631
        if (updateRetailerRequest.getDocumentId() > 0) {
632
            if (retailer.getDocumentId() != null && retailer.getDocumentId() != updateRetailerRequest.getDocumentId()) {
633
                try {
634
                    documentRepository.deleteById(retailer.getDocumentId());
635
                } catch (Exception e) {
636
                    e.printStackTrace();
637
                }
638
            }
639
            retailer.setDocumentId(updateRetailerRequest.getDocumentId());
640
            documentRepository.markDocumentAsPersisted(updateRetailerRequest.getDocumentId());
641
        }
642
        retailerRepository.persist(retailer);
643
        return retailer;
644
    }
23955 govind 645
 
31734 tejbeer 646
    private void updateSaholicUser(int retailerId, int retailerAddressId) {
647
        try {
648
            com.spice.profitmandi.dao.entity.user.User user = userUserRepository.selectById(retailerId);
649
            user.setAddressId(retailerAddressId);
32555 amit.gupta 650
            Cart cart = cartRepository.selectById(user.getActiveCartId());
651
            cart.setAddressId(retailerAddressId);
31734 tejbeer 652
        } catch (ProfitMandiBusinessException e) {
23955 govind 653
 
31734 tejbeer 654
        }
655
    }
23955 govind 656
 
37102 amit 657
    private void createPrivateDealUser(User user, String gstNumber, Retailer retailer,
33128 amit.gupta 658
                                       int retailerAddressId) {
31734 tejbeer 659
        PrivateDealUser privateDealUser = null;
660
        try {
661
            privateDealUser = privateDealUserRepository.selectById(retailer.getId());
662
        } catch (ProfitMandiBusinessException profitMandiBusinessException) {
663
            LOGGER.error("PrivateDealUser not found");
664
        }
23955 govind 665
 
31734 tejbeer 666
        // = privateDealUserRepository.selectById(saholicUser.getId());
667
        if (privateDealUser == null) {
668
            Integer counterId = this.createCounter(user.getEmailId(), gstNumber, user.getMobileNumber(), retailer.getName(), retailerAddressId);
669
            try {
37102 amit 670
                this.createPrivateDealUser(retailer.getId(), counterId);
31734 tejbeer 671
            } catch (Exception e) {
672
                LOGGER.error("ERROR : ", e);
673
            }
674
        } else {
675
            if (privateDealUser.getCounterId() == null) {
676
                Integer counterId = this.createCounter(user.getEmailId(), gstNumber, user.getMobileNumber(), retailer.getName(), retailerAddressId);
677
                privateDealUser.setCounterId(counterId);
678
                privateDealUserRepository.persist(privateDealUser);
679
            } else {
680
                Counter counter = null;
681
                try {
682
                    counter = counterRepository.selectById(privateDealUser.getCounterId());
683
                } catch (ProfitMandiBusinessException profitMandiBusinessException) {
684
                    LOGGER.error("Counter not found with id [{}]", privateDealUser.getCounterId());
685
                }
686
                if (counter == null) {
687
                    this.createCounter(user.getEmailId(), gstNumber, user.getMobileNumber(), retailer.getName(), retailerAddressId);
688
                } else {
689
                    counter.setGstin(gstNumber);
690
                    counterRepository.persist(counter);
691
                }
692
                privateDealUserRepository.persist(privateDealUser);
693
            }
694
        }
23955 govind 695
 
31734 tejbeer 696
        PrivateDealUserAddressMapping privateDealUserAddressMapping = new PrivateDealUserAddressMapping();
697
        privateDealUserAddressMapping.setUserId(retailer.getId());
698
        privateDealUserAddressMapping.setAddressId(retailerAddressId);
699
        privateDealUserAddressMappingRepository.persist(privateDealUserAddressMapping);
700
    }
23955 govind 701
 
37102 amit 702
    private void createPrivateDealUser(int retailerId, int counterId) {
31734 tejbeer 703
        PrivateDealUser privateDealUser = new PrivateDealUser();
704
        privateDealUser.setActive(true);
705
        privateDealUser.setId(retailerId);
706
        privateDealUser.setCounterId(counterId);
707
        privateDealUserRepository.persist(privateDealUser);
708
    }
23955 govind 709
 
31734 tejbeer 710
    private Integer createCounter(String emailId, String gstNumber, String mobileNumber, String name, int addressId) {
711
        if (gstNumber != null && !gstNumber.isEmpty()) {
712
            Counter counter = new Counter();
713
            counter.setEmailId(emailId);
714
            counter.setGstin(gstNumber);
715
            counter.setMobileNumber(mobileNumber);
716
            counter.setName(name);
717
            counter.setAddressId(addressId);
718
            counterRepository.persist(counter);
719
            return counter.getId();
720
        } else {
721
            return null;
722
        }
723
    }
23955 govind 724
 
33128 amit.gupta 725
    private Address updateRetailerAddress(Address address, CustomAddress customAddress, int retailerId) throws
726
            ProfitMandiBusinessException {
31734 tejbeer 727
        if (address == null) {
35971 aman 728
            // Try to find existing address via RetailerRegisteredAddress (handles case where
729
            // dtr.user was deleted but retailer/address still exist in database)
730
            try {
731
                int existingAddressId = retailerRegisteredAddressRepository.selectAddressIdByRetailerId(retailerId);
732
                address = addressRepository.selectById(existingAddressId);
733
            } catch (ProfitMandiBusinessException e) {
734
                // No existing address found for this retailer
735
            }
23955 govind 736
 
35971 aman 737
            if (address != null) {
738
                // Existing address found - update it
739
                this.updateAddress(address, customAddress);
740
                RetailerRegisteredAddress retailerRegisteredAddress = retailerRegisteredAddressRepository.selectByRetailerId(retailerId);
741
                retailerRegisteredAddress.setAddressId(address.getId());
742
                retailerRegisteredAddressRepository.persist(retailerRegisteredAddress);
743
            } else {
744
                // Truly new address
745
                address = new Address();
746
                address.setRetaierId(retailerId);
747
                this.updateAddress(address, customAddress);
748
 
749
                final RetailerRegisteredAddress retailerRegisteredAddress = new RetailerRegisteredAddress();
750
                retailerRegisteredAddress.setRetailerId(retailerId);
751
                retailerRegisteredAddress.setAddressId(address.getId());
752
                retailerRegisteredAddressRepository.persist(retailerRegisteredAddress);
753
            }
31734 tejbeer 754
        } else {
755
            this.updateAddress(address, customAddress);
756
            RetailerRegisteredAddress retailerRegisteredAddress = retailerRegisteredAddressRepository.selectByRetailerId(retailerId);
757
            retailerRegisteredAddress.setAddressId(address.getId());
758
            retailerRegisteredAddressRepository.persist(retailerRegisteredAddress);
759
        }
760
        return address;
761
    }
23955 govind 762
 
31734 tejbeer 763
    private void updateAddress(Address address, CustomAddress customAddress) throws ProfitMandiBusinessException {
764
        address.setName(customAddress.getName());
765
        address.setPhoneNumber(customAddress.getPhoneNumber());
766
        address.setLine1(customAddress.getLine1());
767
        address.setLine2(customAddress.getLine2());
768
        address.setCity(customAddress.getCity());
769
        address.setPinCode(customAddress.getPinCode());
770
        State state = stateRepository.selectByName(customAddress.getState());
771
        if (state == null) {
772
            throw new ProfitMandiBusinessException("State name", "Invalid State - Pls Contact Technology", "Invalid State - Pls Contact Technology");
773
        }
774
        address.setState(state.getName());
775
        addressRepository.persist(address);
776
        LOGGER.info("Address Updated" + address);
777
    }
23955 govind 778
 
33128 amit.gupta 779
    private void updateRetailerShops(List<Shop> shops, Set<CustomShop> customShops, int retailerId, Address
780
            sameAsRetailerAddressValue) throws ProfitMandiBusinessException {
31734 tejbeer 781
        if (shops.isEmpty()) {
782
            for (CustomShop customShop : customShops) {
783
                Shop shop = new Shop();
784
                this.createOrUpdateShop(shop, customShop, retailerId, sameAsRetailerAddressValue);
785
                shops.add(shop);
786
            }
787
        } else {
788
            for (Shop shop : shops) {
789
                for (CustomShop customShop : customShops) {
790
                    if (shop.getId() == customShop.getShopId()) {
791
                        this.createOrUpdateShop(shop, customShop, retailerId, sameAsRetailerAddressValue);
792
                    }
793
                }
794
            }
795
            for (CustomShop customShop : customShops) {
796
                if (customShop.getShopId() == 0) {
797
                    Shop shop = new Shop();
798
                    this.createOrUpdateShop(shop, customShop, retailerId, sameAsRetailerAddressValue);
799
                    shops.add(shop);
800
                }
801
            }
802
        }
803
    }
23955 govind 804
 
33128 amit.gupta 805
    private void createOrUpdateShop(Shop shop, CustomShop customShop, int retailerId, Address
806
            sameAsRetailerAddressValue) throws ProfitMandiBusinessException {
31734 tejbeer 807
        shop.setRetailerId(retailerId);
808
        shop.setName(customShop.getName());
809
        if (customShop.getDocumentId() > 0) {
810
            if (shop.getDocumentId() != null && shop.getDocumentId() != customShop.getDocumentId()) {
811
                try {
812
                    documentRepository.deleteById(shop.getDocumentId());
813
                } catch (Exception e) {
814
                    e.printStackTrace();
815
                }
816
            }
817
            shop.setDocumentId(customShop.getDocumentId());
818
            documentRepository.markDocumentAsPersisted(customShop.getDocumentId());
819
        }
820
        if (shop.getAddressId() == null) {
821
            Address address = null;
822
            if (customShop.isSameAsRetailerAddress()) {
823
                address = sameAsRetailerAddressValue;
824
            } else {
825
                // shop.setDocumentId(customShop.getDocumentId());
826
                address = new Address();
827
                this.updateAddress(address, customShop.getAddress());
828
            }
829
            shop.setAddressId(address.getId());
830
            shop.setAddress(address);
831
            shopRepository.persist(shop);
832
            ShopAddress shopAddress = null;
833
            try {
834
                shopAddress = shopAddressRepository.selectByShopId(shop.getId());
835
                shopAddress.setAddressId(address.getId());
836
            } catch (ProfitMandiBusinessException profitMandiBusinessException) {
837
                shopAddress = new ShopAddress();
838
                shopAddress.setAddressId(address.getId());
839
                shopAddress.setShopId(shop.getId());
840
            }
841
            shopAddressRepository.persist(shopAddress);
842
        } else {
843
            Address address = null;
844
            try {
845
                address = addressRepository.selectById(shop.getAddressId());
846
                CustomAddress customAddress = customShop.getAddress();
847
                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()))) {
848
                    address = new Address();
849
                    ShopAddress shopAddress = shopAddressRepository.selectByShopId(shop.getId());
850
                    this.updateAddress(address, customAddress);
851
                    shopAddress.setAddressId(address.getId());
852
                    shopAddressRepository.persist(shopAddress);
853
                    shop.setAddress(address);
854
                    shopRepository.persist(shop);
855
                }
856
            } catch (Exception e) {
857
                if (customShop.isSameAsRetailerAddress()) {
858
                    address = sameAsRetailerAddressValue;
859
                } else {
860
                    // shop.setDocumentId(customShop.getDocumentId());
861
                    address = new Address();
862
                    this.updateAddress(address, customShop.getAddress());
863
                }
864
                shop.setAddressId(address.getId());
865
                shop.setAddress(address);
866
                shopRepository.persist(shop);
867
                ShopAddress shopAddress = null;
868
                try {
869
                    shopAddress = shopAddressRepository.selectByShopId(shop.getId());
870
                    shopAddress.setAddressId(address.getId());
871
                } catch (ProfitMandiBusinessException profitMandiBusinessException) {
872
                    shopAddress = new ShopAddress();
873
                    shopAddress.setAddressId(address.getId());
874
                    shopAddress.setShopId(shop.getId());
875
                }
876
                shopAddressRepository.persist(shopAddress);
877
            }
23955 govind 878
 
31734 tejbeer 879
        }
23955 govind 880
 
31734 tejbeer 881
    }
23955 govind 882
 
33247 ranu 883
    private void addAddress(List<Shop> shops) throws ProfitMandiBusinessException {
31734 tejbeer 884
        Set<Integer> shopIds = this.toShopIds(shops);
885
        if (shopIds.isEmpty()) {
886
            return;
887
        }
888
        List<ShopAddress> shopAddresses = shopAddressRepository.selectByShopIds(shopIds);
889
        Map<Integer, Address> addressIdAddressMap = this.toAddressIdAddressMap(shopAddresses);
23955 govind 890
 
31734 tejbeer 891
        for (Shop shop : shops) {
892
            shop.setAddress(addressIdAddressMap.get(shop.getAddressId()));
893
        }
894
    }
22980 ashik.ali 895
 
33247 ranu 896
    private Map<Integer, Address> toAddressIdAddressMap(List<ShopAddress> shopAddresses) throws ProfitMandiBusinessException {
31734 tejbeer 897
        Map<Integer, Address> addressIdAddressMap = new HashMap<>();
898
        List<Integer> addressIds = this.toAddressIds(shopAddresses);
899
        List<Address> addresses = addressRepository.selectByIds(addressIds);
900
        for (Address address : addresses) {
901
            addressIdAddressMap.put(address.getId(), address);
902
        }
903
        return addressIdAddressMap;
904
    }
23955 govind 905
 
31734 tejbeer 906
    private List<Integer> toAddressIds(List<ShopAddress> shopAddresses) {
35394 amit 907
        return shopAddresses.stream()
908
                .map(ShopAddress::getAddressId)
909
                .collect(Collectors.toList());
31734 tejbeer 910
    }
23955 govind 911
 
31734 tejbeer 912
    private Set<Integer> toShopIds(List<Shop> shops) {
35394 amit 913
        return shops.stream()
914
                .map(Shop::getId)
915
                .collect(Collectors.toSet());
31734 tejbeer 916
    }
23955 govind 917
 
33247 ranu 918
    private String toString(List<UserRole> userRoles) throws ProfitMandiBusinessException {
31734 tejbeer 919
        Set<Integer> roleIds = new HashSet<>();
920
        for (UserRole userRole : userRoles) {
921
            roleIds.add(userRole.getRoleId());
922
        }
923
        List<Role> roles = roleRepository.selectByIds(roleIds);
31735 amit.gupta 924
        Function<Role, String> roleToNameFunction = role -> String.valueOf(role.getName());
31734 tejbeer 925
        Set<String> userRoleStrings = roles.stream().map(roleToNameFunction).collect(Collectors.toSet());
926
        return String.join(", ", userRoleStrings);
927
    }
23955 govind 928
 
33128 amit.gupta 929
    private FofoStore createFofoStoreCodeByRetailerId(int retailerId, String districtName, String
930
            stateName, UpdateRetailerRequest updateRetailerRequest) throws ProfitMandiBusinessException {
31734 tejbeer 931
        FofoStore fofoStore = null;
932
        try {
933
            fofoStore = fofoStoreRepository.selectByRetailerId(retailerId);
934
            fofoStore.setActivationType(ActivationType.ACTIVE);
30097 tejbeer 935
 
31734 tejbeer 936
        } catch (ProfitMandiBusinessException profitMandiBusinessException) {
23955 govind 937
 
31734 tejbeer 938
        }
23955 govind 939
 
31734 tejbeer 940
        if (fofoStore != null) {
941
            fofoStore.setCounterSize(updateRetailerRequest.getCountersize());
33124 ranu 942
            fofoStore.setAstId(updateRetailerRequest.getAstId());
31734 tejbeer 943
            fofoStore.setMinimumInvestment(updateRetailerRequest.getMinInvestment());
944
            fofoStore.setWarehouseId(updateRetailerRequest.getWarehouseId());
945
            fofoStore.setCounterPotential(updateRetailerRequest.getCounterPotential());
946
            fofoStore.setFofoType(updateRetailerRequest.getFofoType());
35896 amit 947
            fofoStore.setGstNumber(updateRetailerRequest.getGstNumber());
37151 aman 948
 
949
            // The store already exists but its code may never have reached the onboarding
950
            // panel (e.g. verification approved while another dtr user held the partner's
951
            // mobile, so the approval-time linker resolved the wrong account). Re-saving the
952
            // form previously did nothing for the panel because linking only ran on NEW
953
            // store creation. Link here too; the method is a no-op if the panel already
954
            // has a code.
955
            this.linkStoreCodeToOnboardingPanel(fofoStore, updateRetailerRequest.getUserMobileNumber(), retailerId);
31734 tejbeer 956
        } else {
957
            int retailerAddressId = retailerRegisteredAddressRepository.selectAddressIdByRetailerId(retailerId);
958
            Address retailerAddress = addressRepository.selectById(retailerAddressId);
23955 govind 959
 
31734 tejbeer 960
            // StateInfo stateInfo = null;
961
            State stateInfo = null;
962
            try {
30527 tejbeer 963
 
31734 tejbeer 964
                stateInfo = stateRepository.selectByName(retailerAddress.getState());
965
                // stateInfo = Utils.getStateInfo(retailerAddress.getState());
966
            } catch (Exception e) {
967
                // TODO Auto-generated catch block
968
                e.printStackTrace();
969
                // throw new ProfitMandiBusinessException();
970
            }
971
            DistrictMaster districtMaster = districtMasterRepository.selectByNameAndStateShortName(districtName, stateInfo.getShortName());
23955 govind 972
 
31734 tejbeer 973
            fofoStore = new FofoStore();
974
            fofoStore.setId(retailerId);
975
            fofoStore.setCounterSize(updateRetailerRequest.getCountersize());
976
            fofoStore.setMinimumInvestment(updateRetailerRequest.getMinInvestment());
31730 tejbeer 977
 
31734 tejbeer 978
            fofoStore.setCounterPotential(updateRetailerRequest.getCounterPotential());
979
            fofoStore.setWarehouseId(updateRetailerRequest.getWarehouseId());
35289 amit 980
 
981
            //Check for Trial users here
32615 raveendra. 982
            int nextStoreCodeInt = fofoStoreRepository.selectLatestStore().getCodeInt() + 1;
983
 
31734 tejbeer 984
            String fofoStoreCode = StringUtils.generateFofoStoreSequence(
32615 raveendra. 985
                    districtMaster.getStateShortName() + districtMaster.getShortName(), nextStoreCodeInt);
35306 amit 986
            try {
987
                TrialForm trialForm = trialFormRepository.selectByEmailOrMobile(updateRetailerRequest.getUserMobileNumber());
988
                if (trialForm != null) {
989
                    fofoStoreCode = "T-" + fofoStoreCode;
990
                    fofoStore.setTrial(true);
991
                    fofoStore.setTrialStart(LocalDate.now());
992
                    fofoStore.setTrialEnd(LocalDate.now().plusDays(31));
35360 aman 993
                    trialForm.setStatus(ProfitMandiConstants.Status.TMP_STORE_CODE_CREATED);
35306 amit 994
                    //TODO:Amit G, Send store code notification to retailer.
995
                }
996
            } catch (ProfitMandiBusinessException e) {
35289 amit 997
            }
31734 tejbeer 998
            fofoStore.setCode(fofoStoreCode);
32615 raveendra. 999
            fofoStore.setCodeInt(nextStoreCodeInt);
31734 tejbeer 1000
            fofoStore.setBagsLastCredited(LocalDateTime.now());
35203 amit 1001
            if (retailerAddress.getName().contains(ProfitMandiConstants.COMPANY_NAME) || retailerAddress.getName().contains(ProfitMandiConstants.COMPANY_SHORT_NAME)) {
1002
                fofoStore.setInternal(true);
1003
            } else {
1004
                fofoStore.setInternal(false);
1005
            }
1006
            fofoStore.setFofoType(FofoType.FRANCHISE);
31734 tejbeer 1007
            fofoStore.setFofoType(updateRetailerRequest.getFofoType());
1008
            fofoStore.setActivationType(ActivationType.ACTIVE);
35896 amit 1009
            fofoStore.setGstNumber(updateRetailerRequest.getGstNumber());
36439 amit 1010
            fofoStore.setOutletName(retailerAddress.getName());
31734 tejbeer 1011
            fofoStoreRepository.persist(fofoStore);
28908 tejbeer 1012
 
37151 aman 1013
            // Link store code to onboarding panel
1014
            this.linkStoreCodeToOnboardingPanel(fofoStore, retailerAddress.getPhoneNumber(), retailerId);
35971 aman 1015
 
36064 aman 1016
            PincodePartner pincodePartner = pincodePartnerRepository.selectPartnerByPincode(retailerAddress.getPinCode(), fofoStore.getId());
1017
            if (pincodePartner == null) {
1018
                PincodePartner pinPartner = new PincodePartner();
1019
                pinPartner.setFofoId(fofoStore.getId());
1020
                pinPartner.setPincode(retailerAddress.getPinCode());
1021
                pincodePartnerRepository.perist(pinPartner);
1022
            }
35418 aman 1023
 
36064 aman 1024
            if (fofoStore.isTrial()) {
1025
                storeTimelineTatService.sendTrialStoreCreationMail(fofoStore, updateRetailerRequest);
1026
                storeTimelineTatService.sendTrialActivationMail(fofoStore, updateRetailerRequest);
1027
            }
35289 amit 1028
        }
1029
 
31734 tejbeer 1030
        return fofoStore;
1031
    }
23955 govind 1032
 
37151 aman 1033
    /**
1034
     * Copies an existing fofo_store code onto the partner_onboarding_panel row for the
1035
     * given mobile number, provided verification is approved and the panel does not
1036
     * already hold a code. Called for BOTH new and existing stores: the approval-time
1037
     * linker in PartnerOnBoardingPanelController can miss (e.g. kyc=0, or a legacy dtr
1038
     * user squatting on the partner's mobile made selectByMobileNumber resolve the
1039
     * wrong account), and before this method existed a form re-save silently skipped
1040
     * linking whenever the store already existed. Best-effort: never fails the save.
1041
     */
1042
    private void linkStoreCodeToOnboardingPanel(FofoStore fofoStore, String phoneNumber, int retailerId) {
1043
        if (fofoStore == null || fofoStore.getCode() == null || fofoStore.getCode().isEmpty()
1044
                || phoneNumber == null || phoneNumber.isEmpty()) {
1045
            return;
1046
        }
1047
        try {
1048
            PartnerOnBoardingPanel pobp = partnerOnBoardingPanelRepository.selectByPhoneNumber(
1049
                    Long.parseLong(phoneNumber));
1050
            if (pobp == null) {
1051
                return;
1052
            }
1053
            // Never overwrite: multi-store / GST-change onboardings keep their own codes.
1054
            if (pobp.getCode() != null && !pobp.getCode().isEmpty()) {
1055
                return;
1056
            }
1057
            PartnerVerificationpanel pvp = partnerOnboardingVerificationRepository
1058
                    .selectByOnboardingId(pobp.getId());
1059
            if (pvp != null && PartnerVerificationApprovalStatus.YES.equals(pvp.getApproval())) {
1060
                pobp.setCode(fofoStore.getCode());
1061
                storeTimelineTatService.onCodeCreated(pobp.getId());
1062
                PartnerVerificationCheckboxes cb = partnerOnboardingVerificationRepository
1063
                        .selectVerifiCheckboxByOnboardingId(pobp.getId());
1064
                if (cb == null) {
1065
                    cb = new PartnerVerificationCheckboxes();
1066
                    cb.setOnboardingId(pobp.getId());
1067
                    partnerOnboardingVerificationRepository.persist(cb);
1068
                }
1069
                LOGGER.info("Linked store code {} to onboardingId {} for retailerId {}",
1070
                        fofoStore.getCode(), pobp.getId(), retailerId);
1071
            }
1072
        } catch (Exception e) {
1073
            LOGGER.error("Error linking store code to onboarding for retailerId: {}", retailerId, e);
1074
        }
1075
    }
1076
 
31734 tejbeer 1077
    @Override
33128 amit.gupta 1078
    public FofoStore createFofoStoreCodeByUserId(int userId, String districtName, String
1079
            stateName, UpdateRetailerRequest updateRetailerRequest) throws ProfitMandiBusinessException {
31734 tejbeer 1080
        User user = userRepository.selectById(userId);
1081
        // = userAccountRepository.selectRetailerIdByUserId(user.getId());
1082
        UserAccount userAccounts = userAccountRepository.selectSaholicByUserId(user.getId());
1083
        Retailer retailer = retailerRepository.selectById(userAccounts.getAccountKey());
1084
        Role roleFofo = roleRepository.selectByName(RoleType.FOFO.toString());
1085
        try {
1086
            userRoleRepository.selectByUserIdAndRoleId(user.getId(), roleFofo.getId());
1087
        } catch (ProfitMandiBusinessException profitMandiBusinessException) {
1088
            throw new ProfitMandiBusinessException(ProfitMandiConstants.USER_ID, user.getId(), "USR_1013");
1089
        }
1090
        return this.createFofoStoreCodeByRetailerId(retailer.getId(), districtName, stateName, updateRetailerRequest);
23955 govind 1091
 
31734 tejbeer 1092
    }
23955 govind 1093
 
31734 tejbeer 1094
    @Override
1095
    public List<DistrictMaster> getAllDistrictMaster(String stateName) {
1096
        // StateInfo stateInfo = null;
1097
        State stateInfo = null;
1098
        try {
1099
            // stateInfo = Utils.getStateInfo(stateName);
30525 tejbeer 1100
 
31734 tejbeer 1101
            stateInfo = stateRepository.selectByName(stateName);
1102
        } catch (Exception e) {
1103
            e.printStackTrace();
1104
            // throw new ProfitMandiBusinessException();
1105
        }
1106
        return districtMasterRepository.selectByStateShortName(stateInfo.getShortName());
1107
    }
22980 ashik.ali 1108
 
31734 tejbeer 1109
    @Override
34149 tejus.loha 1110
    @Cacheable(value = "getFofoRetailer", cacheManager = "thirtyMinsTimeOutCacheManager")
33247 ranu 1111
    public Map<Integer, CustomRetailer> getFofoRetailers(List<Integer> fofoIds) throws ProfitMandiBusinessException {
35394 amit 1112
        if (fofoIds == null || fofoIds.isEmpty()) {
1113
            return new HashMap<>();
1114
        }
1115
 
31734 tejbeer 1116
        List<com.spice.profitmandi.dao.entity.user.User> saholicUsers = userUserRepository.selectByIds(fofoIds);
35440 amit 1117
 
1118
        // Check for saholicUsers without corresponding dtrUser
1119
        List<String> saholicEmails = saholicUsers.stream()
1120
                .map(com.spice.profitmandi.dao.entity.user.User::getEmailId)
1121
                .filter(email -> email != null)
1122
                .collect(Collectors.toList());
1123
        Set<String> dtrUserEmails = userRepository.selectAllByEmailIds(saholicEmails).stream()
1124
                .map(User::getEmailId)
1125
                .collect(Collectors.toSet());
1126
        for (com.spice.profitmandi.dao.entity.user.User saholicUser : saholicUsers) {
1127
            if (saholicUser.getEmailId() != null && !dtrUserEmails.contains(saholicUser.getEmailId())) {
1128
                LOGGER.warn("dtrUser not found for saholicUser - id: {}, email: {}", saholicUser.getId(), saholicUser.getEmailId());
1129
            }
1130
        }
1131
 
35394 amit 1132
        Map<Integer, com.spice.profitmandi.dao.entity.user.User> userAddressMap = saholicUsers.stream()
1133
                .filter(x -> x.getAddressId() != null)
1134
                .collect(Collectors.toMap(com.spice.profitmandi.dao.entity.user.User::getAddressId, x -> x));
31734 tejbeer 1135
        List<Address> addresses = addressRepository.selectByIds(new ArrayList<>(userAddressMap.keySet()));
35394 amit 1136
 
1137
        // Batch fetch all FofoStores to avoid N+1 queries
1138
        Set<Integer> retailerIds = addresses.stream().map(Address::getRetaierId).collect(Collectors.toSet());
1139
        Map<Integer, FofoStore> fofoStoreMap = fofoStoreRepository.selectByRetailerIds(new ArrayList<>(retailerIds))
1140
                .stream().collect(Collectors.toMap(FofoStore::getId, fs -> fs));
1141
 
31734 tejbeer 1142
        Map<Integer, CustomRetailer> customRetailersMap = new HashMap<>();
1143
        for (Address address : addresses) {
1144
            com.spice.profitmandi.dao.entity.user.User user = userAddressMap.get(address.getId());
35394 amit 1145
            FofoStore fs = fofoStoreMap.get(address.getRetaierId());
1146
            if (fs == null) {
31734 tejbeer 1147
                continue;
1148
            }
35394 amit 1149
 
35896 amit 1150
            CustomRetailer customRetailer = buildCustomRetailer(user, address, fs);
31734 tejbeer 1151
            customRetailersMap.put(customRetailer.getPartnerId(), customRetailer);
1152
        }
1153
        return customRetailersMap;
1154
    }
25295 amit.gupta 1155
 
35394 amit 1156
    /**
1157
     * Helper method to build CustomRetailer from fetched entities
1158
     */
1159
    private CustomRetailer buildCustomRetailer(com.spice.profitmandi.dao.entity.user.User user, Address address,
35896 amit 1160
                                               FofoStore fs) {
35394 amit 1161
        CustomRetailer customRetailer = new CustomRetailer();
1162
        customRetailer.setEmail(user.getEmailId());
1163
        customRetailer.setBusinessName(address.getName());
1164
        customRetailer.setMobileNumber(address.getPhoneNumber());
1165
        customRetailer.setCode(fs.getCode());
1166
        customRetailer.setAstId(fs.getAstId());
1167
        customRetailer.setActivationType(fs.getActivationType());
1168
        customRetailer.setCounterSize(fs.getCounterSize());
1169
        customRetailer.setCounterPotential(fs.getCounterPotential());
1170
        customRetailer.setWarehouseId(fs.getWarehouseId());
1171
        customRetailer.setPartnerId(fs.getId());
1172
        customRetailer.setFofoType(fs.getFofoType());
1173
        customRetailer.setCartId(user.getActiveCartId());
1174
 
35896 amit 1175
        customRetailer.setGstNumber(fs.getGstNumber());
35394 amit 1176
 
1177
        CustomAddress customAddress = buildCustomAddress(address);
1178
        customRetailer.setAddress(customAddress);
1179
        customRetailer.setDisplayName(customRetailer.getBusinessName() + "-" + customRetailer.getCode() + "- " + customAddress.getCity());
1180
        return customRetailer;
1181
    }
1182
 
1183
    /**
1184
     * Helper method to build CustomAddress from Address entity
1185
     */
1186
    private CustomAddress buildCustomAddress(Address address) {
1187
        CustomAddress customAddress = new CustomAddress();
1188
        customAddress.setCity(address.getCity());
1189
        customAddress.setState(address.getState());
1190
        customAddress.setLine1(address.getLine1());
1191
        customAddress.setLine2(address.getLine2());
1192
        customAddress.setPinCode(address.getPinCode());
1193
        customAddress.setName(address.getName());
1194
        customAddress.setPhoneNumber(address.getPhoneNumber());
1195
        return customAddress;
1196
    }
1197
 
31734 tejbeer 1198
    @Override
1199
    @Cacheable(value = "getFofoRetailer", cacheManager = "thirtyMinsTimeOutCacheManager")
1200
    public CustomRetailer getFofoRetailer(int fofoId) throws ProfitMandiBusinessException {
1201
        com.spice.profitmandi.dao.entity.user.User saholicUser = userUserRepository.selectById(fofoId);
35440 amit 1202
        User dtrUser = null;
1203
        try {
1204
            dtrUser = userRepository.selectByEmailId(saholicUser.getEmailId());
1205
        } catch (ProfitMandiBusinessException e) {
1206
            LOGGER.info("User not found for emailId: {} and id is : {}", saholicUser.getEmailId(), saholicUser.getId());
1207
        }
31734 tejbeer 1208
        FofoStore store = fofoStoreRepository.selectByRetailerId(fofoId);
35394 amit 1209
        Address address = addressRepository.selectById(saholicUser.getAddressId());
1210
 
31734 tejbeer 1211
        CustomRetailer customRetailer = new CustomRetailer();
1212
        customRetailer.setEmail(saholicUser.getEmailId());
1213
        customRetailer.setBusinessName(address.getName());
1214
        customRetailer.setMobileNumber(address.getPhoneNumber());
31862 tejbeer 1215
        customRetailer.setFirstName(dtrUser.getFirstName());
1216
        customRetailer.setLastName(dtrUser.getLastName());
35394 amit 1217
        customRetailer.setCartId(saholicUser.getActiveCartId());
1218
        customRetailer.setPartnerId(address.getRetaierId());
1219
        customRetailer.setCode(store.getCode());
1220
        customRetailer.setAstId(store.getAstId());
1221
        customRetailer.setActivationType(store.getActivationType());
1222
        customRetailer.setWarehouseId(store.getWarehouseId());
1223
 
35896 amit 1224
        customRetailer.setGstNumber(store.getGstNumber());
35394 amit 1225
 
1226
        // Reuse helper method for CustomAddress
1227
        CustomAddress customAddress = buildCustomAddress(address);
1228
        customRetailer.setAddress(customAddress);
31734 tejbeer 1229
        customRetailer.setDisplayName(address.getName() + " - " + address.getCity());
35394 amit 1230
 
31734 tejbeer 1231
        return customRetailer;
1232
    }
26125 amit.gupta 1233
 
31734 tejbeer 1234
    @Override
33247 ranu 1235
    public Map<Integer, CustomRetailer> getFofoRetailerUserId(List<Integer> fofoIds) throws ProfitMandiBusinessException {
35394 amit 1236
        if (fofoIds == null || fofoIds.isEmpty()) {
1237
            return new HashMap<>();
1238
        }
1239
 
31734 tejbeer 1240
        List<com.spice.profitmandi.dao.entity.user.User> saholicUsers = userUserRepository.selectByIds(fofoIds);
35394 amit 1241
        Map<Integer, com.spice.profitmandi.dao.entity.user.User> userAddressMap = saholicUsers.stream()
1242
                .filter(x -> x.getAddressId() != null)
1243
                .collect(Collectors.toMap(com.spice.profitmandi.dao.entity.user.User::getAddressId, x -> x));
31734 tejbeer 1244
        List<Address> addresses = addressRepository.selectByIds(new ArrayList<>(userAddressMap.keySet()));
35394 amit 1245
 
1246
        // Batch fetch all retailerIds to userIds mapping to avoid N+1
1247
        Set<Integer> retailerIds = addresses.stream().map(Address::getRetaierId).collect(Collectors.toSet());
1248
        Map<Integer, Integer> retailerIdToUserIdMap = getUserIdRetailerIdMapReverse(retailerIds);
1249
 
35896 amit 1250
        // Batch fetch FofoStores for GST numbers
1251
        Map<Integer, FofoStore> fofoStoreMap = fofoStoreRepository.selectByRetailerIds(new ArrayList<>(retailerIds))
1252
                .stream().collect(Collectors.toMap(FofoStore::getId, fs -> fs));
35394 amit 1253
 
31734 tejbeer 1254
        Map<Integer, CustomRetailer> customRetailersMap = new HashMap<>();
1255
        for (Address address : addresses) {
1256
            com.spice.profitmandi.dao.entity.user.User user = userAddressMap.get(address.getId());
35394 amit 1257
            Integer userId = retailerIdToUserIdMap.get(user.getId());
1258
            if (userId == null) {
1259
                continue;
1260
            }
1261
 
31734 tejbeer 1262
            CustomRetailer customRetailer = new CustomRetailer();
1263
            customRetailer.setEmail(user.getEmailId());
1264
            customRetailer.setBusinessName(address.getName());
1265
            customRetailer.setMobileNumber(address.getPhoneNumber());
35394 amit 1266
            customRetailer.setCartId(user.getActiveCartId());
1267
            customRetailer.setPartnerId(address.getRetaierId());
1268
 
35896 amit 1269
            FofoStore fs = fofoStoreMap.get(address.getRetaierId());
1270
            customRetailer.setGstNumber(fs != null ? fs.getGstNumber() : null);
35394 amit 1271
 
1272
            CustomAddress customAddress = buildCustomAddress(address);
1273
            customRetailer.setAddress(customAddress);
1274
            customRetailer.setDisplayName(customRetailer.getBusinessName() + "-" + customAddress.getCity());
31734 tejbeer 1275
            customRetailersMap.put(userId, customRetailer);
1276
        }
1277
        return customRetailersMap;
1278
    }
25295 amit.gupta 1279
 
35394 amit 1280
    /**
1281
     * Helper method to get retailerId to userId mapping
1282
     */
1283
    private Map<Integer, Integer> getUserIdRetailerIdMapReverse(Set<Integer> retailerIds) {
1284
        List<UserAccount> userAccounts = userAccountRepository.selectAllSaholicByRetailerIds(retailerIds);
1285
        return userAccounts.stream().collect(Collectors.toMap(UserAccount::getAccountKey, UserAccount::getUserId));
1286
    }
1287
 
31734 tejbeer 1288
    @Override
33247 ranu 1289
    public Map<Integer, String> getAllFofoRetailerIdEmailIdMap() throws ProfitMandiBusinessException {
31734 tejbeer 1290
        Role roleFofo = null;
1291
        try {
1292
            roleFofo = roleRepository.selectByName(RoleType.FOFO.toString());
1293
        } catch (ProfitMandiBusinessException e) {
1294
            // TODO Auto-generated catch block
1295
            e.printStackTrace();
1296
        }
1297
        Role roleRetailer = null;
1298
        try {
1299
            roleRetailer = roleRepository.selectByName(RoleType.RETAILER.toString());
1300
        } catch (ProfitMandiBusinessException e) {
1301
            // TODO Auto-generated catch block
1302
            e.printStackTrace();
1303
        }
1304
        Set<Integer> roleIds = new HashSet<>();
1305
        roleIds.add(roleFofo.getId());
1306
        roleIds.add(roleRetailer.getId());
1307
        List<Integer> userIds = userRoleRepository.selectUserIdsByRoleIds(roleIds);
1308
        List<User> users = userRepository.selectAllByIds(new HashSet<>(userIds));
1309
        Map<Integer, Integer> userIdRetailerIdMap = this.getUserIdRetailerIdMap(userIds);
1310
        Map<Integer, String> retailerIdEmailIdMap = new HashMap<>();
1311
        for (User user : users) {
1312
            retailerIdEmailIdMap.put(userIdRetailerIdMap.get(user.getId()), user.getEmailId());
1313
        }
1314
        return retailerIdEmailIdMap;
1315
    }
23955 govind 1316
 
31734 tejbeer 1317
    private Map<Integer, Integer> getUserIdRetailerIdMap(List<Integer> userIds) {
1318
        List<UserAccount> userAccounts = userAccountRepository.selectAllSaholicByUserIds(new HashSet<>(userIds));
1319
        Map<Integer, Integer> userIdRetailerIdMap = new HashMap<>();
1320
        for (UserAccount userAccount : userAccounts) {
1321
            userIdRetailerIdMap.put(userAccount.getUserId(), userAccount.getAccountKey());
1322
        }
1323
        return userIdRetailerIdMap;
1324
    }
25295 amit.gupta 1325
 
33247 ranu 1326
    private Map<Integer, String> getUserIdEmailIdMap(Set<Integer> userIds) throws ProfitMandiBusinessException {
31734 tejbeer 1327
        List<User> users = userRepository.selectAllByIds(userIds);
1328
        Map<Integer, String> userIdEmailIdMap = new HashMap<>();
1329
        for (User user : users) {
1330
            userIdEmailIdMap.put(user.getId(), user.getEmailId());
1331
        }
1332
        return userIdEmailIdMap;
1333
    }
23509 amit.gupta 1334
 
31734 tejbeer 1335
    @Override
33247 ranu 1336
    public Map<Integer, String> getAllFofoRetailerIdEmailIdMap(Set<Integer> retailerIds) throws ProfitMandiBusinessException {
31734 tejbeer 1337
        List<UserAccount> userAccounts = userAccountRepository.selectAllSaholicByRetailerIds(retailerIds);
1338
        Set<Integer> userIds = new HashSet<>();
1339
        for (UserAccount userAccount : userAccounts) {
1340
            userIds.add(userAccount.getUserId());
1341
        }
1342
        Map<Integer, String> retailerIdEmailIdMap = new HashMap<>();
1343
        Map<Integer, String> userIdEmailIdMap = this.getUserIdEmailIdMap(userIds);
1344
        for (UserAccount userAccount : userAccounts) {
1345
            retailerIdEmailIdMap.put(userAccount.getAccountKey(), userIdEmailIdMap.get(userAccount.getUserId()));
1346
        }
1347
        return retailerIdEmailIdMap;
1348
    }
25295 amit.gupta 1349
 
31734 tejbeer 1350
    @Override
33247 ranu 1351
    public Map<Integer, String> getAllFofoRetailerIdNameMap(List<Integer> storeIds) throws ProfitMandiBusinessException {
31734 tejbeer 1352
        Map<Integer, CustomRetailer> retailersMap = this.getFofoRetailers(storeIds);
1353
        Map<Integer, String> retailerIdNameMap = new HashMap<>();
1354
        for (Map.Entry<Integer, CustomRetailer> entry : retailersMap.entrySet()) {
1355
            retailerIdNameMap.put(entry.getKey(), entry.getValue().getBusinessName() + "-" + entry.getValue().getAddress().getCity());
1356
        }
1357
        return retailerIdNameMap;
1358
    }
24168 amit.gupta 1359
 
31734 tejbeer 1360
    @Override
1361
    @Cacheable(value = "FofoRetailerIdNameMap", cacheManager = "thirtyMinsTimeOutCacheManager")
33247 ranu 1362
    public Map<Integer, String> getAllFofoRetailerIdNameMap() throws ProfitMandiBusinessException {
31734 tejbeer 1363
        List<FofoStore> stores = fofoStoreRepository.selectAll();
1364
        List<Integer> storeIds = stores.stream().map(x -> x.getId()).collect(Collectors.toList());
1365
        return this.getAllFofoRetailerIdNameMap(storeIds);
1366
    }
24349 amit.gupta 1367
 
31734 tejbeer 1368
    @Override
33247 ranu 1369
    public List<MapWrapper<Integer, String>> getAllFofoRetailerIdNameList() throws ProfitMandiBusinessException {
31734 tejbeer 1370
        List<MapWrapper<Integer, String>> mapWrappers = new ArrayList<>();
1371
        // TODO Auto-generated method stub
1372
        Map<Integer, String> fofoIdNameMap = this.getAllFofoRetailerIdNameMap();
1373
        fofoIdNameMap.forEach((fofoId, name) -> {
1374
            MapWrapper<Integer, String> idWrapper = new MapWrapper<>();
1375
            idWrapper.setKey(fofoId);
1376
            idWrapper.setValue(name);
1377
            mapWrappers.add(idWrapper);
1378
        });
1379
        return mapWrappers;
1380
    }
24349 amit.gupta 1381
 
31734 tejbeer 1382
    @Override
1383
    @Cacheable(value = "retailerNames", cacheManager = "thirtyMinsTimeOutCacheManager")
33247 ranu 1384
    public Map<Integer, CustomRetailer> getFofoRetailers(boolean activeOnly) throws ProfitMandiBusinessException {
35394 amit 1385
        Stream<FofoStore> storeStream = fofoStoreRepository.selectAll().stream()
1386
                .filter(fs -> fs.getFofoType().equals(FofoType.FRANCHISE));
31734 tejbeer 1387
        if (activeOnly) {
35394 amit 1388
            storeStream = storeStream.filter(FofoStore::isActive);
31734 tejbeer 1389
        }
35394 amit 1390
        List<Integer> storeIds = storeStream.map(FofoStore::getId).collect(Collectors.toList());
31734 tejbeer 1391
        return this.getFofoRetailers(storeIds);
1392
    }
25295 amit.gupta 1393
 
31734 tejbeer 1394
    @Override
33367 ranu 1395
    @Cacheable(value = "retailerNames", cacheManager = "thirtyMinsTimeOutCacheManager")
1396
    public Map<Integer, CustomRetailer> getFofoRetailers(boolean activeOnly, String pinCode) throws ProfitMandiBusinessException {
1397
        List<PincodePartner> pincodePartners = pincodePartnerRepository.selectPartnersByPincode(pinCode);
1398
        List<Integer> storeIds = new ArrayList<>();
35394 amit 1399
        if (!pincodePartners.isEmpty()) {
1400
            List<Integer> fofoIds = pincodePartners.stream().map(PincodePartner::getFofoId).collect(Collectors.toList());
33367 ranu 1401
            List<FofoStore> fofoStores = fofoStoreRepository.selectActivePartnersByRetailerIds(fofoIds);
35394 amit 1402
            storeIds = fofoStores.stream().map(FofoStore::getId).collect(Collectors.toList());
33367 ranu 1403
        }
1404
        return this.getFofoRetailers(storeIds);
1405
    }
1406
 
1407
    @Override
31734 tejbeer 1408
    @Cacheable(value = "allFofoRetailers", cacheManager = "thirtyMinsTimeOutCacheManager")
33247 ranu 1409
    public Map<Integer, CustomRetailer> getAllFofoRetailers() throws ProfitMandiBusinessException {
35394 amit 1410
        List<Integer> storeIds = fofoStoreRepository.selectAll().stream()
1411
                .map(FofoStore::getId)
1412
                .collect(Collectors.toList());
31734 tejbeer 1413
        return this.getFofoRetailers(storeIds);
1414
    }
27861 tejbeer 1415
 
31734 tejbeer 1416
    @Override
34619 ranu 1417
    @Cacheable(value = "allFofoRetailersInternalFalse", cacheManager = "thirtyMinsTimeOutCacheManager")
1418
    public Map<Integer, CustomRetailer> getAllFofoRetailersInternalFalse() throws ProfitMandiBusinessException {
35394 amit 1419
        List<Integer> storeIds = fofoStoreRepository.selectAll().stream()
1420
                .filter(fs -> fs.getFofoType().equals(FofoType.FRANCHISE))
1421
                .map(FofoStore::getId)
1422
                .collect(Collectors.toList());
34619 ranu 1423
        return this.getFofoRetailers(storeIds);
1424
    }
1425
 
1426
    @Override
33128 amit.gupta 1427
    public LoginRequestResponseModel registerWebUser(LoginRequestResponseModel loginRequestModel) throws
1428
            ProfitMandiBusinessException {
26522 amit.gupta 1429
 
31734 tejbeer 1430
        com.spice.profitmandi.dao.entity.user.User saholicUser = this.createSaholicUser(loginRequestModel);
1431
        loginRequestModel.setUserId(saholicUser.getId());
26522 amit.gupta 1432
 
31734 tejbeer 1433
        this.createRetailerAddress(loginRequestModel);
26522 amit.gupta 1434
 
31734 tejbeer 1435
        this.createPrivateDealUser(loginRequestModel);
1436
        this.updateSaholicUser(saholicUser.getId(), loginRequestModel.getBusinessAddress().getId());
26522 amit.gupta 1437
 
31734 tejbeer 1438
        return loginRequestModel;
26522 amit.gupta 1439
 
31734 tejbeer 1440
    }
26522 amit.gupta 1441
 
31734 tejbeer 1442
    private void createPrivateDealUser(LoginRequestResponseModel loginRequestModel) {
26522 amit.gupta 1443
 
31734 tejbeer 1444
        Integer counterId = this.createCounter(loginRequestModel.getEmail(), loginRequestModel.getGstNumber(), loginRequestModel.getBusinessAddress().getPhoneNumber(), loginRequestModel.getBusinessAddress().getName(), loginRequestModel.getBusinessAddress().getId());
1445
        try {
37102 amit 1446
            this.createPrivateDealUser(loginRequestModel.getUserId(), counterId);
31734 tejbeer 1447
        } catch (Exception e) {
1448
            LOGGER.error("ERROR : ", e);
1449
        }
26522 amit.gupta 1450
 
31734 tejbeer 1451
        PrivateDealUserAddressMapping privateDealUserAddressMapping = new PrivateDealUserAddressMapping();
1452
        privateDealUserAddressMapping.setUserId(loginRequestModel.getUserId());
1453
        privateDealUserAddressMapping.setAddressId(loginRequestModel.getBusinessAddress().getId());
1454
        privateDealUserAddressMappingRepository.persist(privateDealUserAddressMapping);
26522 amit.gupta 1455
 
31734 tejbeer 1456
    }
26522 amit.gupta 1457
 
33128 amit.gupta 1458
    private void createRetailerAddress(LoginRequestResponseModel loginRequestResponseModel) throws
1459
            ProfitMandiBusinessException {
31734 tejbeer 1460
        Address businessAddress = loginRequestResponseModel.getBusinessAddress();
1461
        businessAddress.setRetaierId(loginRequestResponseModel.getUserId());
1462
        addressRepository.persist(businessAddress);
1463
    }
26536 amit.gupta 1464
 
31734 tejbeer 1465
    private String getHash256(String originalString) {
1466
        String hashString = Hashing.sha256().hashString(originalString, StandardCharsets.UTF_8).toString();
1467
        LOGGER.info("Hash String {}", hashString);
1468
        return hashString;
1469
    }
26533 amit.gupta 1470
 
31734 tejbeer 1471
    @Override
1472
    @Cacheable(value = "fofoIdUrl", cacheManager = "thirtyMinsTimeOutCacheManager")
1473
    public Map<Integer, String> getAllFofoRetailerIdUrlMap() {
1474
        Map<Integer, String> fofoRetailerUrlMap = new HashMap<>();
35394 amit 1475
        List<FofoStore> stores = fofoStoreRepository.selectAll().stream()
1476
                .filter(FofoStore::isActive)
1477
                .collect(Collectors.toList());
1478
 
1479
        // Batch fetch all district masters to avoid N+1 queries
1480
        List<DistrictMaster> allDistrictMasters = districtMasterRepository.selectAll();
1481
        Map<String, DistrictMaster> districtMasterMap = allDistrictMasters.stream()
1482
                .collect(Collectors.toMap(
1483
                        dm -> dm.getStateShortName() + "_" + dm.getShortName(),
1484
                        dm -> dm,
1485
                        (existing, replacement) -> existing));
1486
 
1487
        // Get fallback district master
1488
        DistrictMaster fallbackDistrict = districtMasterMap.get("HR_FB");
1489
 
31734 tejbeer 1490
        for (FofoStore store : stores) {
35394 amit 1491
            String codeWithoutDigits = store.getCode().replaceAll("\\d+", "");
1492
            if (codeWithoutDigits.length() < 3) {
1493
                LOGGER.warn("Invalid store code format: {}", store.getCode());
1494
                continue;
1495
            }
1496
            String stateShortName = codeWithoutDigits.substring(0, 2);
1497
            String districtShortName = codeWithoutDigits.substring(2);
1498
 
1499
            // Use pre-fetched map instead of N+1 query
1500
            String key = stateShortName + "_" + districtShortName;
1501
            DistrictMaster districtMaster = districtMasterMap.getOrDefault(key, fallbackDistrict);
1502
 
31734 tejbeer 1503
            if (districtMaster == null) {
35394 amit 1504
                LOGGER.warn("No district master found for key: {} and no fallback available", key);
1505
                continue;
31734 tejbeer 1506
            }
35394 amit 1507
 
1508
            String urlString = districtMaster.getStateShortName() + "/" +
1509
                    Utils.getHyphenatedString(districtMaster.getName()) + "/" + store.getCode();
31734 tejbeer 1510
            fofoRetailerUrlMap.put(store.getId(), urlString.toLowerCase());
1511
        }
1512
        return fofoRetailerUrlMap;
1513
    }
26533 amit.gupta 1514
 
31734 tejbeer 1515
    @Override
1516
    @Cacheable(value = "storeCodeRetailerMap", cacheManager = "thirtyMinsTimeOutCacheManager")
1517
    public Map<String, Integer> getStoreCodeRetailerMap() {
1518
        Map<Integer, String> map = this.getAllFofoRetailerIdUrlMap();
1519
        Map<String, Integer> returnMap = map.entrySet().stream().collect(Collectors.toMap(x -> {
1520
            String[] splitString = x.getValue().split("/");
1521
            return splitString[splitString.length - 1];
1522
        }, x -> x.getKey()));
1523
        LOGGER.info("returnMap {}", returnMap);
1524
        return returnMap;
1525
    }
27877 amit.gupta 1526
 
1527
 
31734 tejbeer 1528
    @Override
32668 raveendra. 1529
    public User getEmail() {
1530
        return null;
1531
    }
1532
 
1533
    @Override
1534
    public void update(com.spice.profitmandi.dao.entity.user.User user) {
1535
    }
1536
 
1537
    @Override
1538
    public void updateRetailerEmail(int fofoId, String newEmail) throws ProfitMandiBusinessException {
1539
        User dtrUser = null;
1540
        com.spice.profitmandi.dao.entity.user.User user = null;
1541
 
1542
        try {
1543
            dtrUser = userRepository.selectByEmailId(newEmail);
1544
        } catch (Exception e) {
1545
        }
1546
 
1547
        try {
1548
            user = userUserRepository.selectByEmailId(newEmail);
1549
        } catch (Exception e) {
1550
        }
1551
 
1552
        if (user != null || dtrUser != null) {
1553
            throw new ProfitMandiBusinessException("Email", newEmail, "Email already exist");
1554
        }
1555
        com.spice.profitmandi.dao.entity.user.User fofoUser = userUserRepository.selectById(fofoId);
1556
        String oldEmail = fofoUser.getEmailId();
1557
        LOGGER.info("old email {}", oldEmail);
1558
        User thisDtrUser = userRepository.selectByEmailId(oldEmail);
1559
 
1560
        fofoUser.setEmailId(newEmail);
1561
        thisDtrUser.setEmailId(newEmail);
1562
    }
1563
 
1564
 
32953 amit.gupta 1565
    //    @Override
32737 amit.gupta 1566
    @Cacheable(value = "getContactsByFofoId", cacheManager = "oneDayCacheManager")
33128 amit.gupta 1567
    public List<RetailerContact> getContactsByFofoId(int fofoId, boolean activeOnly) throws
1568
            ProfitMandiBusinessException {
32737 amit.gupta 1569
        List<RetailerContact> retailerContacts = retailerContactRepository.selectAllByRetailerId(fofoId, activeOnly);
1570
        com.spice.profitmandi.dao.entity.user.User user = userUserRepository.selectById(fofoId);
1571
        RetailerContact retailerContact = new RetailerContact();
1572
        retailerContact.setMobile(user.getMobileNumber());
1573
        retailerContact.setName(user.getName());
1574
        retailerContact.setActive(true);
1575
        retailerContact.setFofoId(fofoId);
1576
        retailerContacts.add(retailerContact);
1577
        return retailerContacts;
1578
    }
1579
 
1580
 
1581
    @Override
33128 amit.gupta 1582
    public Map<Integer, CustomRetailer> getFofoRetailersPaginated(boolean activeOnly, int offset,
33247 ranu 1583
                                                                  int limit, FofoType fofoType) throws ProfitMandiBusinessException {
30097 tejbeer 1584
 
31734 tejbeer 1585
        Stream<FofoStore> storeStream = fofoStoreRepository.selectByStatusFofoType(activeOnly, fofoType, offset, limit).stream();
30219 tejbeer 1586
 
31734 tejbeer 1587
        List<Integer> storeIds = storeStream.map(x -> x.getId()).collect(Collectors.toList());
1588
        return this.getFofoRetailers(storeIds);
1589
    }
30219 tejbeer 1590
 
34813 aman 1591
    @Override
1592
    public Map<String, Object> computeIncomeMap(int fofoId, int yearMonth) {
1593
        LocalDateTime startOfMonth = LocalDate.now().minusMonths(yearMonth).withDayOfMonth(1).atStartOfDay();
1594
        LocalDateTime endOfMonth = startOfMonth.plusMonths(1);
1595
        YearMonth monthYear = YearMonth.now();
1596
 
1597
 
1598
        // 3) Fetch brand-wise data (same as original)
1599
        List<LastMonthCreditedIncomeModel> lastMonthPendingIncomeModels = schemeInOutRepository
1600
                .selectLastMonthPendingIncomeByFofoId(fofoId, startOfMonth, endOfMonth);
1601
 
1602
        List<LastMonthCreditedIncomeModel> lastMonthPurchaseInMargins = schemeInOutRepository
1603
                .selectLastMonthPurchaseInMarginByFofoId(fofoId, startOfMonth, endOfMonth);
1604
 
1605
        List<LastMonthCreditedIncomeModel> lastMonthFrontEndIncomes = schemeInOutRepository
1606
                .selectFrontIncomeByBrand(fofoId, startOfMonth, endOfMonth);
1607
 
1608
        List<LastMonthCreditedIncomeModel> lastMonthSaleMargins = schemeInOutRepository
1609
                .selectLastMonthCreditedIncomeByFofoId(fofoId, startOfMonth, endOfMonth);
1610
 
1611
        List<OfferPayoutImeiIncomeModel> offerPayoutImeiIncomeModels = offerPayoutRepository
1612
                .getTotalPayoutsByPartnerPeriod(
1613
                        YearMonth.of(startOfMonth.getYear(), startOfMonth.getMonth()),
1614
                        fofoId, null, null);
1615
 
1616
        // 4) Convert to maps for brand-wise access
1617
        Map<String, LastMonthCreditedIncomeModel> lastMonthPendingIncomeMap =
1618
                lastMonthPendingIncomeModels.stream()
1619
                        .collect(Collectors.toMap(x -> x.getBrand(), x -> x));
1620
 
1621
        Map<String, LastMonthCreditedIncomeModel> lastMonthPurchaseInMarginMap =
1622
                lastMonthPurchaseInMargins.stream()
1623
                        .collect(Collectors.toMap(x -> x.getBrand(), x -> x));
1624
 
1625
        Map<String, LastMonthCreditedIncomeModel> lastMonthFrontEndIncomeMap =
1626
                lastMonthFrontEndIncomes.stream()
1627
                        .collect(Collectors.toMap(x -> x.getBrand(), x -> x));
1628
 
1629
        Map<String, LastMonthCreditedIncomeModel> lastMonthSaleMarginMap =
1630
                lastMonthSaleMargins.stream()
1631
                        .collect(Collectors.toMap(x -> x.getBrand(), x -> x));
1632
 
1633
        Map<String, Double> additionalPurchasePayout = offerPayoutImeiIncomeModels.stream()
1634
                .collect(Collectors.groupingBy(OfferPayoutImeiIncomeModel::getBrand,
1635
                        Collectors.summingDouble(OfferPayoutImeiIncomeModel::getPurchasePayout)));
1636
 
1637
        Map<String, Double> additionSalePayout = offerPayoutImeiIncomeModels.stream()
1638
                .collect(Collectors.groupingBy(OfferPayoutImeiIncomeModel::getBrand,
1639
                        Collectors.summingDouble(OfferPayoutImeiIncomeModel::getSalePayout)));
1640
 
1641
        // 5) Get all unique brands
1642
        Set<String> brandSet = new HashSet<>();
1643
        brandSet.addAll(lastMonthPurchaseInMarginMap.keySet());
1644
        brandSet.addAll(lastMonthSaleMarginMap.keySet());
1645
        brandSet.addAll(lastMonthPendingIncomeMap.keySet());
1646
        brandSet.addAll(additionalPurchasePayout.keySet());
1647
        brandSet.addAll(additionSalePayout.keySet());
1648
        brandSet.addAll(lastMonthFrontEndIncomeMap.keySet());
1649
 
1650
        // 6) Calculate total amount per brand (same logic as original)
1651
        Map<String, Float> totalAmountMap = new HashMap<>();
1652
        brandSet.forEach(brand -> {
1653
            float total =
1654
                    (lastMonthSaleMarginMap.get(brand) == null ? 0 : lastMonthSaleMarginMap.get(brand).getAmount()) +
1655
                            (lastMonthPurchaseInMarginMap.get(brand) == null ? 0 : lastMonthPurchaseInMarginMap.get(brand).getAmount()) +
1656
                            (lastMonthPendingIncomeMap.get(brand) == null ? 0 : lastMonthPendingIncomeMap.get(brand).getAmount()) +
1657
                            (additionalPurchasePayout.get(brand) == null ? 0 : additionalPurchasePayout.get(brand).floatValue()) +
1658
                            (additionSalePayout.get(brand) == null ? 0 : additionSalePayout.get(brand).floatValue()) +
1659
                            (lastMonthFrontEndIncomeMap.get(brand) == null ? 0 : lastMonthFrontEndIncomeMap.get(brand).getAmount());
1660
            totalAmountMap.put(brand, total);
1661
        });
1662
 
1663
        // 7) Calculate aggregated totals
1664
        float totalIncome = totalAmountMap.values().stream()
1665
                .reduce(0f, Float::sum);
1666
 
1667
        float pendingIncome = lastMonthPendingIncomeMap.values().stream()
1668
                .map(LastMonthCreditedIncomeModel::getAmount)
1669
                .reduce(0f, Float::sum);
1670
 
1671
        float creditedIncome = totalIncome - pendingIncome;
1672
 
1673
        // 8) Build month labels
1674
        Map<Integer, String> monthValueMap = new HashMap<>();
1675
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("MMM''uu");
1676
        for (int i = 0; i <= 5; i++) {
1677
            LocalDateTime m = LocalDateTime.now()
1678
                    .withDayOfMonth(1)
1679
                    .minusMonths(i);
1680
            monthValueMap.put(i, m.format(fmt));
1681
        }
1682
 
1683
        // 9) Assemble result with all brand-wise data
1684
        Map<String, Object> result = new HashMap<>();
1685
        result.put("totalIncome", totalIncome);
1686
        result.put("creditedIncome", creditedIncome);
1687
        result.put("pendingIncome", pendingIncome);
1688
        result.put("monthIndex", yearMonth);
1689
        result.put("monthValueMap", monthValueMap);
1690
 
1691
        // Include brand-wise data for detailed analysis
1692
        result.put("brandSet", brandSet);
1693
        result.put("totalAmountMap", totalAmountMap);
1694
        result.put("lastMonthPurchaseInMarginMap", lastMonthPurchaseInMarginMap);
1695
        result.put("lastMonthSaleMarginMap", lastMonthSaleMarginMap);
1696
        result.put("lastMonthPendingIncomeMap", lastMonthPendingIncomeMap);
1697
        result.put("additionalPurchasePayoutMap", additionalPurchasePayout);
1698
        result.put("additionalSalePayoutMap", additionSalePayout);
1699
        result.put("lastMonthFrontEndIncomeMap", lastMonthFrontEndIncomeMap);
1700
 
1701
        return result;
1702
    }
1703
 
22980 ashik.ali 1704
}