Subversion Repositories SmartDukaan

Rev

Rev 34619 | Rev 34644 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
34306 ranu 1
package com.smartdukaan.cron.scheduled;
2
 
3
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
34619 ranu 4
import com.spice.profitmandi.common.model.BrandStockPrice;
34606 ranu 5
import com.spice.profitmandi.common.model.CustomRetailer;
34321 ranu 6
import com.spice.profitmandi.common.model.ProfitMandiConstants;
34619 ranu 7
import com.spice.profitmandi.common.util.FileUtil;
8
import com.spice.profitmandi.common.util.FormattingUtils;
9
import com.spice.profitmandi.common.util.Utils;
34321 ranu 10
import com.spice.profitmandi.dao.cart.CartService;
34450 ranu 11
import com.spice.profitmandi.dao.cart.SmartCartService;
34321 ranu 12
import com.spice.profitmandi.dao.entity.auth.AuthUser;
34606 ranu 13
import com.spice.profitmandi.dao.entity.fofo.*;
14
import com.spice.profitmandi.dao.entity.logistics.AST;
15
import com.spice.profitmandi.dao.entity.logistics.ASTRepository;
16
import com.spice.profitmandi.dao.entity.logistics.AreaRepository;
34619 ranu 17
import com.spice.profitmandi.dao.entity.transaction.*;
34321 ranu 18
import com.spice.profitmandi.dao.entity.user.User;
19
import com.spice.profitmandi.dao.enumuration.cs.EscalationType;
34619 ranu 20
import com.spice.profitmandi.dao.enumuration.transaction.LoanReferenceType;
34641 ranu 21
import com.spice.profitmandi.dao.model.*;
34606 ranu 22
import com.spice.profitmandi.dao.repository.auth.AuthRepository;
34321 ranu 23
import com.spice.profitmandi.dao.repository.cs.CsService;
24
import com.spice.profitmandi.dao.repository.dtr.FofoStoreRepository;
34606 ranu 25
import com.spice.profitmandi.dao.repository.fofo.*;
26
import com.spice.profitmandi.dao.repository.inventory.StateRepository;
34619 ranu 27
import com.spice.profitmandi.dao.repository.transaction.*;
34321 ranu 28
import com.spice.profitmandi.dao.repository.user.UserRepository;
34641 ranu 29
import com.spice.profitmandi.service.RbmTargetService;
34619 ranu 30
import com.spice.profitmandi.service.inventory.InventoryService;
34308 ranu 31
import com.spice.profitmandi.service.transaction.SDCreditService;
34606 ranu 32
import com.spice.profitmandi.service.user.RetailerService;
34619 ranu 33
import com.spice.profitmandi.service.wallet.WalletService;
34606 ranu 34
import in.shop2020.model.v1.order.OrderStatus;
34619 ranu 35
import in.shop2020.model.v1.order.WalletReferenceType;
36
import org.apache.commons.io.output.ByteArrayOutputStream;
34306 ranu 37
import org.apache.logging.log4j.LogManager;
38
import org.apache.logging.log4j.Logger;
34641 ranu 39
import org.apache.poi.ss.usermodel.*;
40
import org.apache.poi.xssf.usermodel.XSSFColor;
34619 ranu 41
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
34306 ranu 42
import org.springframework.beans.factory.annotation.Autowired;
34619 ranu 43
import org.springframework.beans.factory.annotation.Qualifier;
34306 ranu 44
import org.springframework.beans.factory.annotation.Value;
34619 ranu 45
import org.springframework.core.io.ByteArrayResource;
34321 ranu 46
import org.springframework.mail.javamail.JavaMailSender;
47
import org.springframework.mail.javamail.MimeMessageHelper;
34306 ranu 48
import org.springframework.stereotype.Component;
49
import org.springframework.transaction.annotation.Transactional;
50
 
34321 ranu 51
import javax.mail.MessagingException;
52
import javax.mail.internet.InternetAddress;
53
import javax.mail.internet.MimeMessage;
34619 ranu 54
import java.io.*;
55
import java.math.BigDecimal;
34641 ranu 56
import java.time.*;
34306 ranu 57
import java.time.temporal.ChronoUnit;
58
import java.util.*;
34321 ranu 59
import java.util.stream.Collectors;
34619 ranu 60
import java.util.stream.Stream;
34306 ranu 61
 
62
@Component
63
@Transactional(rollbackFor = {Throwable.class, ProfitMandiBusinessException.class})
64
public class ScheduledTasksTest {
65
 
66
    private static final Logger LOGGER = LogManager.getLogger(ScheduledTasksTest.class);
67
 
68
    @Autowired
69
    TransactionRepository transactionRepository;
70
 
71
    @Autowired
34619 ranu 72
    @Qualifier(value = "googleMailSender")
73
    private JavaMailSender googleMailSender;
74
 
75
    @Autowired
34306 ranu 76
    LoanRepository loanRepository;
77
 
34308 ranu 78
    @Autowired
79
    SDCreditService sdCreditService;
80
 
34321 ranu 81
    @Autowired
82
    UserRepository userRepository;
83
 
84
    @Autowired
85
    CsService csService;
86
 
87
    @Autowired
88
    RbmRatingRepository rbmRatingRepository;
89
 
90
    @Autowired
91
    private JavaMailSender mailSender;
92
 
93
    @Autowired
94
    SalesRatingRepository salesRatingRepository;
95
 
96
    @Autowired
97
    FofoStoreRepository fofoStoreRepository;
98
 
34450 ranu 99
    @Autowired
100
    SmartCartService smartCartService;
101
 
34606 ranu 102
    @Autowired
103
    RetailerService retailerService;
104
 
105
    @Autowired
106
    ASTRepository astRepository;
107
 
108
    @Autowired
109
    AuthRepository authRepository;
110
 
111
    @Autowired
112
    StateRepository stateRepository;
113
 
114
    @Autowired
115
    MonthlyTargetRepository monthlyTargetRepository;
116
 
117
    @Autowired
118
    PartnerTypeChangeService partnerTypeChangeService;
119
 
120
    @Autowired
121
    ReturnOrderInfoRepository returnOrderInfoRepository;
122
 
123
    @Autowired
124
    OrderRepository orderRepository;
125
 
34619 ranu 126
    @Autowired
127
    FofoOrderItemRepository fofoOrderItemRepository;
128
 
129
    @Autowired
130
    InventoryService inventoryService;
131
 
132
    @Autowired
133
    UserWalletRepository userWalletRepository;
134
 
135
    @Autowired
136
    LoanStatementRepository loanStatementRepository;
137
 
138
    @Autowired
34641 ranu 139
    ActivatedImeiRepository activatedImeiRepository;
140
 
141
    @Autowired
142
    PartnerDailyInvestmentRepository partnerDailyInvestmentRepository;
143
 
144
    @Autowired
34619 ranu 145
    WalletService walletService;
146
 
34641 ranu 147
    @Autowired
148
    RbmTargetService rbmTargetService;
149
 
34321 ranu 150
    public void test() throws Exception {
34366 ranu 151
        System.out.println("test start");
34641 ranu 152
        this.generateBiReportExcel();
34366 ranu 153
        System.out.println("test end");
34306 ranu 154
 
155
    }
156
 
34308 ranu 157
    public void createLoanForBillingByTransactionIdAndInvoiceNumber(int transactionId, double invoiceAmount, String invoiceNumber) throws Exception {
158
        sdCreditService.createLoanForBilling(transactionId, invoiceAmount, invoiceNumber);
34306 ranu 159
 
34308 ranu 160
    }
34306 ranu 161
 
34619 ranu 162
    public void loanSettle() throws Exception {
163
        List<Integer> refrences = Arrays.asList(25807,36003,38938,39506,42219,45084);
164
        for(Integer ref : refrences){
165
            List<LoanStatement> loanStatements = loanStatementRepository.selectByLoanId(ref);
166
            double amountSum = loanStatements.stream().map(LoanStatement::getAmount).mapToDouble(BigDecimal::doubleValue).sum();
167
            if(amountSum > 0){
168
                walletService.addAmountToWallet(loanStatements.get(0).getFofoId(),ref, WalletReferenceType.CREDIT_LIMIT,"Amount reversal against credit limit deduction",(float) amountSum,LocalDateTime.now());
34308 ranu 169
 
34619 ranu 170
//                Loan statement entry
171
                    BigDecimal adjustAmount = BigDecimal.valueOf(amountSum).negate(); // or multiply by -1
172
                    LoanStatement loanStatement = new LoanStatement();
173
                    loanStatement.setAmount(adjustAmount);
174
                    loanStatement.setFofoId(loanStatements.get(0).getFofoId());
175
                    loanStatement.setLoanReferenceType(LoanReferenceType.PRINCIPAL);
176
                    loanStatement.setCreatedAt(LocalDateTime.now());
177
                    loanStatement.setDescription("Amount reversal due to access debit against limit");
178
                    loanStatement.setLoanId(ref);
179
                    loanStatement.setBusinessDate(LocalDateTime.now());
180
                    loanStatementRepository.persist(loanStatement);
181
 
182
                    Loan loan = loanRepository.selectByLoanId(ref);
183
                    loan.setPendingAmount(BigDecimal.valueOf(0));
184
                    loan.setSettledOn(LocalDateTime.now());
185
                }
186
 
187
 
188
        }
189
    }
190
 
191
 
192
 
34321 ranu 193
    private void sendMailHtmlFormat(String email[], String body, String cc[], String bcc[], String subject)
194
            throws MessagingException, ProfitMandiBusinessException, IOException {
195
        MimeMessage message = mailSender.createMimeMessage();
196
        MimeMessageHelper helper = new MimeMessageHelper(message);
197
        helper.setSubject(subject);
198
        helper.setText(body, true);
199
        helper.setTo(email);
200
        if (cc != null) {
201
            helper.setCc(cc);
202
        }
203
        if (bcc != null) {
204
            helper.setBcc(bcc);
34308 ranu 205
 
34321 ranu 206
        }
207
 
208
        InternetAddress senderAddress = new InternetAddress("noreply@smartdukaan.com", "Smart Dukaan");
209
        helper.setFrom(senderAddress);
210
        mailSender.send(message);
211
    }
212
 
34307 ranu 213
    public Map<Integer,Integer> findLoanTransactionMapingAccordingLoan(List<Integer> loanIds) throws ProfitMandiBusinessException {
34306 ranu 214
 
215
        Map<Integer, Integer> transactionLoanMap = new HashMap<>();
216
 
217
        for(int loanId : loanIds){
218
            Transaction transaction = null;
219
            Loan loan = loanRepository.selectByLoanId(loanId);
220
            List<Transaction> transactions = transactionRepository.selectByRetailerId(loan.getFofoId());
221
 
222
            LocalDateTime nearestDateTime = transactions.stream().map(x -> x.getCreateTimestamp())
223
                    .min(Comparator.comparingLong(x -> Math.abs(ChronoUnit.MILLIS.between(x, loan.getCreatedOn()))))
224
                    .orElse(null);
225
 
226
            if (nearestDateTime != null && loan.getCreatedOn().plusMinutes(2).isAfter(nearestDateTime) &&
227
                    loan.getCreatedOn().minusMinutes(1).isBefore(nearestDateTime)) {
228
                // Here transaction is still null
229
                transaction = transactions.stream()
230
                        .filter(x -> x.getCreateTimestamp().equals(nearestDateTime))
231
                        .findFirst().get();
232
                transactionLoanMap.put(transaction.getId(), loanId);
233
            }
234
 
235
        }
236
        LOGGER.info("transactionLoanMap {}",transactionLoanMap);
237
        return transactionLoanMap;
238
    }
34321 ranu 239
 
240
 
241
 
242
    public void sendRbmFeedbackSummaryEmail() throws MessagingException, ProfitMandiBusinessException, IOException {
243
        LocalDateTime startOfMonth = LocalDate.now().withDayOfMonth(1).atStartOfDay();
244
        LocalDateTime endOfMonth = LocalDateTime.now();
34323 ranu 245
        String[] bcc = {"tarun.verma@smartdukaan.com"};
34321 ranu 246
 
247
        // Get all RBM users
248
        List<AuthUser> authUsers = csService.getAuthUserIds(
249
                ProfitMandiConstants.TICKET_CATEGORY_RBM,
250
                Arrays.asList(EscalationType.L1)
251
        );
252
 
253
        if (authUsers.isEmpty()) {
254
            LOGGER.info("No RBMs found.");
255
            return;
256
        }
257
 
258
        List<Integer> rbmIds = authUsers.stream().map(AuthUser::getId).collect(Collectors.toList());
259
 
260
        // Fetch ratings for all RBMs for current month
261
        List<RbmRating> feedbackList = rbmRatingRepository.selectByRbmIdsAndDateRange(rbmIds, startOfMonth, endOfMonth);
262
 
263
        if (feedbackList.isEmpty()) {
264
            LOGGER.info("No feedback entries found for RBMs.");
265
            return;
266
        }
267
 
268
        // Sort feedback by createTimeStamp DESC
269
        feedbackList.sort((a, b) -> b.getCreateTimeStamp().compareTo(a.getCreateTimeStamp()));
270
 
271
        // Fetch and map FOFO (partner) names
272
        Map<Integer, String> fofoNameMap = new HashMap<>();
273
        for (RbmRating rating : feedbackList) {
274
            int fofoId = rating.getFofoId();
275
            if (!fofoNameMap.containsKey(fofoId)) {
276
                User fofoUser = userRepository.selectById(fofoId);
277
                FofoStore fofoStore = fofoStoreRepository.selectByRetailerId(fofoId);
278
 
279
                String partnerName = fofoUser != null ? fofoUser.getName() : "Unknown Partner";
280
                String storeCode = fofoStore != null ? fofoStore.getCode() : "Unknown Code";
281
 
282
                String displayName = partnerName + " (" + storeCode + ")";
283
                fofoNameMap.put(fofoId, displayName);
284
            }
285
        }
286
 
287
        // Map RBM ID to name for quick lookup
288
        Map<Integer, String> rbmNameMap = authUsers.stream()
289
                .collect(Collectors.toMap(AuthUser::getId, AuthUser::getFullName));
290
 
291
        // Generate HTML content
292
        StringBuilder emailContent = new StringBuilder();
293
        emailContent.append("<html><body>");
294
        emailContent.append("<p>Dear Team,</p>");
295
        emailContent.append("<p>Here is the <b>latest RBM Rating and Feedback Summary</b> for ")
296
                .append(LocalDate.now().getMonth()).append(":</p>");
297
 
298
        emailContent.append("<table border='1' cellspacing='0' cellpadding='5'>");
299
        emailContent.append("<tr>")
300
                .append("<th>RBM Name</th>")
301
                .append("<th>Partner Name</th>")
302
                .append("<th>Rating</th>")
303
                .append("<th>Comment</th>")
304
                .append("<th>Date</th>")
305
                .append("</tr>");
306
 
307
        for (RbmRating rating : feedbackList) {
308
            String rbmName = rbmNameMap.getOrDefault(rating.getRbmId(), "Unknown RBM");
309
            String partnerName = fofoNameMap.getOrDefault(rating.getFofoId(), "Unknown Partner");
310
            emailContent.append("<tr>")
311
                    .append("<td>").append(rbmName).append("</td>")
312
                    .append("<td>").append(partnerName).append("</td>")
313
                    .append("<td>").append(rating.getRating()).append("</td>")
314
                    .append("<td>").append(rating.getComment() != null ? rating.getComment() : "-").append("</td>")
315
                    .append("<td>").append(rating.getCreateTimeStamp().toLocalDate()).append("</td>")
316
                    .append("</tr>");
317
        }
318
 
319
        emailContent.append("</table>");
320
        emailContent.append("<br><p>Regards,<br>Smart Dukaan Team</p>");
321
        emailContent.append("</body></html>");
322
 
323
        String subject = "Monthly RBM Feedback Summary - " + LocalDate.now().getMonth();
324
 
325
        List<String> sendTo = new ArrayList<>();
34323 ranu 326
        sendTo.add("sm@smartdukaan.com"); //
327
        sendTo.add("chiranjib.sarkar@smartdukaan.com"); //
328
        sendTo.add("kamini.sharma@smartdukaan.com"); //
34321 ranu 329
 
330
        String[] emailRecipients = sendTo.toArray(new String[0]);
331
 
332
 
333
        this.sendMailHtmlFormat(emailRecipients, emailContent.toString(), null, bcc, subject);
334
 
335
        LOGGER.info("Consolidated RBM feedback summary email sent.");
336
    }
337
 
338
 
339
    public void sendSalesFeedbackSummaryEmail() throws MessagingException, ProfitMandiBusinessException, IOException {
340
        LocalDateTime startOfMonth = LocalDate.now().withDayOfMonth(1).atStartOfDay();
341
        LocalDateTime endOfMonth = LocalDateTime.now();
34323 ranu 342
        String[] bcc = {"tarun.verma@smartdukaan.com"};
34411 tejus.loha 343
//        String[] bcc = {"tejus.lohani@smartdukaan.com"};
34321 ranu 344
 
345
        // Get all RBM users
346
        List<AuthUser> authUsers = csService.getAuthUserIds(
347
                ProfitMandiConstants.TICKET_CATEGORY_SALES,
348
                Arrays.asList(EscalationType.L1)
349
        );
350
 
351
        if (authUsers.isEmpty()) {
352
            LOGGER.info("No sales person found.");
353
            return;
354
        }
355
 
356
        List<Integer> salesL1Ids = authUsers.stream().map(AuthUser::getId).collect(Collectors.toList());
357
 
358
        // Fetch ratings for all RBMs for current month
359
        List<SalesRating> feedbackList = salesRatingRepository.selectBySalesL1IdsAndDateRange(salesL1Ids, startOfMonth, endOfMonth);
360
 
361
        if (feedbackList.isEmpty()) {
362
            LOGGER.info("No feedback entries found for Sales.");
363
            return;
364
        }
365
 
366
        // Sort feedback by createTimeStamp DESC
367
        feedbackList.sort((a, b) -> b.getCreateTimeStamp().compareTo(a.getCreateTimeStamp()));
368
 
369
        // Fetch and map FOFO (partner) names
370
        Map<Integer, String> fofoNameMap = new HashMap<>();
371
        for (SalesRating rating : feedbackList) {
372
            int fofoId = rating.getFofoId();
373
            if (!fofoNameMap.containsKey(fofoId)) {
374
                User fofoUser = userRepository.selectById(fofoId);
375
                FofoStore fofoStore = fofoStoreRepository.selectByRetailerId(fofoId);
376
 
377
                String partnerName = fofoUser != null ? fofoUser.getName() : "Unknown Partner";
378
                String storeCode = fofoStore != null ? fofoStore.getCode() : "Unknown Code";
379
 
380
                String displayName = partnerName + " (" + storeCode + ")";
381
                fofoNameMap.put(fofoId, displayName);
382
            }
383
        }
384
 
385
        // Map RBM ID to name for quick lookup
386
        Map<Integer, String> salesL1NameMap = authUsers.stream()
387
                .collect(Collectors.toMap(AuthUser::getId, AuthUser::getFullName));
388
 
389
        // Generate HTML content
390
        StringBuilder emailContent = new StringBuilder();
391
        emailContent.append("<html><body>");
392
        emailContent.append("<p>Dear Team,</p>");
393
        emailContent.append("<p>Here is the <b>latest Sales L1 Rating and Feedback Summary</b> for ")
394
                .append(LocalDate.now().getMonth()).append(":</p>");
395
 
396
        emailContent.append("<table border='1' cellspacing='0' cellpadding='5'>");
397
        emailContent.append("<tr>")
398
                .append("<th>Sales L1 Name</th>")
399
                .append("<th>Partner Name</th>")
34411 tejus.loha 400
                .append("<th>Partner Category</th>")
34321 ranu 401
                .append("<th>Rating</th>")
402
                .append("<th>Comment</th>")
403
                .append("<th>Date</th>")
404
                .append("</tr>");
405
 
406
        for (SalesRating rating : feedbackList) {
407
            String salesL1 = salesL1NameMap.getOrDefault(rating.getSalesL1Id(), "Unknown Sales Person");
408
            String partnerName = fofoNameMap.getOrDefault(rating.getFofoId(), "Unknown Partner");
34411 tejus.loha 409
            PartnerType partnerType = partnerTypeChangeService.getTypeOnDate(rating.getFofoId(), LocalDate.now());
34321 ranu 410
            emailContent.append("<tr>")
411
                    .append("<td>").append(salesL1).append("</td>")
412
                    .append("<td>").append(partnerName).append("</td>")
34411 tejus.loha 413
                    .append("<td>").append(partnerType).append("</td>")
34321 ranu 414
                    .append("<td>").append(rating.getRating()).append("</td>")
415
                    .append("<td>").append(rating.getComment() != null ? rating.getComment() : "-").append("</td>")
416
                    .append("<td>").append(rating.getCreateTimeStamp().toLocalDate()).append("</td>")
417
                    .append("</tr>");
418
        }
419
 
420
        emailContent.append("</table>");
421
        emailContent.append("<br><p>Regards,<br>Smartdukaan Team</p>");
422
        emailContent.append("</body></html>");
423
 
34411 tejus.loha 424
        String subject = "Monthly Sales L1 Feedback Summary Test test - " + LocalDate.now().getMonth();
34321 ranu 425
 
426
        List<String> sendTo = new ArrayList<>();
34323 ranu 427
         sendTo.add("sm@smartdukaan.com"); //
428
         sendTo.add("chiranjib.sarkar@smartdukaan.com"); //
34606 ranu 429
         sendTo.add("kamini.sharma@smartdukaan.com"); //
34321 ranu 430
 
431
        String[] emailRecipients = sendTo.toArray(new String[0]);
432
 
433
 
434
        this.sendMailHtmlFormat(emailRecipients, emailContent.toString(), null, bcc, subject);
435
 
436
        LOGGER.info("Consolidated Sales L1 feedback summary email sent.");
437
    }
438
 
439
 
34606 ranu 440
    public void generateBiReportExcel() throws Exception {
34619 ranu 441
 
34606 ranu 442
        LocalDateTime startOfToday = LocalDate.now().atStartOfDay();
34321 ranu 443
 
34619 ranu 444
        Map<Integer, CustomRetailer> customRetailers = retailerService.getAllFofoRetailersInternalFalse();
34321 ranu 445
 
34606 ranu 446
        List<Integer> retailerIds = customRetailers.values().stream().map(CustomRetailer::getPartnerId).collect(Collectors.toList());
447
 
34641 ranu 448
        //partner daily investment
449
        List<Loan> defaultLoans = sdCreditService.getDefaultLoan();
450
        Map<Integer,List<Loan>> defaultLoanMap = defaultLoans.stream().collect(Collectors.groupingBy(Loan::getFofoId));
34619 ranu 451
 
34641 ranu 452
        Map<Integer, PartnerDailyInvestment> partnerDailyInvestmentMap = new HashMap<>();
453
        List<PartnerDailyInvestment> partnerDailyInvestments = partnerDailyInvestmentRepository
454
                .selectAll(new ArrayList<>(retailerIds), LocalDate.now().minusDays(1));
455
        if (!partnerDailyInvestments.isEmpty()) {
456
            partnerDailyInvestmentMap = partnerDailyInvestments.stream()
457
                    .collect(Collectors.toMap(x -> x.getFofoId(), x -> x));
458
        }
459
 
34619 ranu 460
//  this month return data
461
        YearMonth currentMonth = YearMonth.now();
462
        String currentMonthStringValue = String.valueOf(currentMonth);
34606 ranu 463
        LocalDateTime currentMonthStartDate = YearMonth.now().atDay(1).atStartOfDay();
464
        LocalDateTime currentMonthEndDate = LocalDateTime.now();
465
 
466
        List<ReturnOrderInfoModel> currentMonthReturnOrderInfoModels = returnOrderInfoRepository.selectAllByBetweenDate(currentMonthStartDate, currentMonthEndDate);
467
        Map<Integer, Long> currentMonthPartnerReturnOrderInfoModelMap = currentMonthReturnOrderInfoModels.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getRefundAmount()))));
468
 
469
        List<Order> currentMonthRtoRefundOrders = orderRepository.selectAllOrderDatesBetweenByStatus(currentMonthStartDate, currentMonthEndDate, OrderStatus.RTO_REFUNDED);
470
        Map<Integer, Long> currentMonthRtoRefundOrderMap = currentMonthRtoRefundOrders.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getTotalAmount()))));
471
 
472
 
34619 ranu 473
//  last month return data
34606 ranu 474
        YearMonth lastMonth = YearMonth.now().minusMonths(1);
34619 ranu 475
        String lastMonthStringValue = String.valueOf(lastMonth);
34606 ranu 476
        LocalDateTime lastMontStartDate = lastMonth.atDay(1).atStartOfDay();
477
        LocalDateTime lastMonthEndDate = lastMonth.atEndOfMonth().atTime(23, 59, 59);
478
 
479
        List<ReturnOrderInfoModel> lastMonthReturnOrderInfoModels = returnOrderInfoRepository.selectAllByBetweenDate(lastMontStartDate, lastMonthEndDate);
480
        Map<Integer, Long> lastMonthPartnerReturnOrderInfoModelMap = lastMonthReturnOrderInfoModels.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getRefundAmount()))));
481
 
482
        List<Order> lastMonthRtoRefundOrders = orderRepository.selectAllOrderDatesBetweenByStatus(lastMontStartDate, lastMonthEndDate, OrderStatus.RTO_REFUNDED);
483
        Map<Integer, Long> lastMonthRtoRefundOrderMap = lastMonthRtoRefundOrders.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getTotalAmount()))));
484
 
485
 
34619 ranu 486
//  twoMonthsAgo return data
34606 ranu 487
        YearMonth twoMonthsAgo = YearMonth.now().minusMonths(2);
34619 ranu 488
        String twoMonthAgoStringValue = String.valueOf(twoMonthsAgo);
34606 ranu 489
        LocalDateTime twoMonthsAgoStartDate = twoMonthsAgo.atDay(1).atStartOfDay();
490
        LocalDateTime twoMonthsAgoEndDate = twoMonthsAgo.atEndOfMonth().atTime(23, 59, 59);
491
 
492
        List<ReturnOrderInfoModel> twoMonthAgoReturnOrderInfoModels = returnOrderInfoRepository.selectAllByBetweenDate(twoMonthsAgoStartDate, twoMonthsAgoEndDate);
493
        Map<Integer, Long> twoMonthAgoPartnerReturnOrderInfoModelMap = twoMonthAgoReturnOrderInfoModels.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getRefundAmount()))));
494
 
495
        List<Order> twoMonthRtoRefundOrders = orderRepository.selectAllOrderDatesBetweenByStatus(twoMonthsAgoStartDate, twoMonthsAgoEndDate, OrderStatus.RTO_REFUNDED);
34619 ranu 496
        Map<Integer, Long> twoMonthAgoRtoRefundOrderMap = twoMonthRtoRefundOrders.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getTotalAmount()))));
34606 ranu 497
 
498
 
34619 ranu 499
        Map<Integer , BIRetailerModel> biRetailerModelMap = new HashMap<>();
34606 ranu 500
 
34641 ranu 501
        Map<Integer , FofoInvestmentModel> biInvestmentModelMap = new HashMap<>();
502
 
34619 ranu 503
        Map<Integer, Map<YearMonth, BiSecondaryModel>> allRetailerMonthlyData = new HashMap<>();
34606 ranu 504
 
34619 ranu 505
        Map<Integer,Double> fofoTotalStockPriceMap = new HashMap<>();
506
 
507
        Map<Integer,Map<String, BrandStockPrice>> fofoBrandStockPriceMap = new HashMap<>();
508
 
34641 ranu 509
        Map<Integer,Long> fofoTotalMtdSecondaryMap = new HashMap<>();
34619 ranu 510
 
34641 ranu 511
        Map<Integer , String> assessmentMap = new HashMap<>();
512
        Map<Integer , String> zeroBillingMap = new HashMap<>();
513
        Map<Integer , Float> billingNeededMap = new HashMap<>();
514
        Map<Integer , Integer> countAMap = new HashMap<>();
34619 ranu 515
 
34641 ranu 516
        Map<Integer,Map<String, Long>> fofoBrandWiseMtdSecondaryMap = new HashMap<>();
34619 ranu 517
 
34641 ranu 518
 
519
 
520
        Map<Integer,Double> fofoTotalMtdTertiaryMap = new HashMap<>();
521
 
522
        Map<Integer,Map<String, Double>> fofoBrandMtdTertiaryMap = new HashMap<>();
523
 
34606 ranu 524
        for(Integer fofoId: retailerIds){
34619 ranu 525
            String rbmName = "";
34606 ranu 526
            int rbmL1 = csService.getAuthUserId(ProfitMandiConstants.TICKET_CATEGORY_RBM,EscalationType.L1,fofoId);
34619 ranu 527
            if(rbmL1 != 0){
528
                 rbmName = authRepository.selectById(rbmL1).getFullName();
529
            }
530
            String bmName ="";
34606 ranu 531
            int bmId = csService.getAuthUserId(ProfitMandiConstants.TICKET_CATEGORY_SALES,EscalationType.L2,fofoId);
34619 ranu 532
            if(bmId !=0){
533
                bmName = authRepository.selectById(bmId).getFullName();
534
            }
34606 ranu 535
 
536
            int managerId = csService.getAuthUserId(ProfitMandiConstants.TICKET_CATEGORY_SALES,EscalationType.L1,fofoId);
537
            String managerName = " ";
538
            if(managerId != 0){
539
                 managerName = authRepository.selectById(managerId).getFullName();
540
            }else {
541
                managerName = bmName;
542
            }
543
 
544
            AST ast = astRepository.selectById(customRetailers.get(fofoId).getAstId());
545
 
546
            PartnerType partnerTypeThisMonth = partnerTypeChangeService.getTypeOnMonth(fofoId, YearMonth.now());
547
 
548
//            generate retaile detail
549
 
550
            BIRetailerModel biRetailerModel = new BIRetailerModel();
551
            biRetailerModel.setBmName(bmName);
552
            biRetailerModel.setCode(customRetailers.get(fofoId).getCode());
34619 ranu 553
            if(ast != null){
554
                biRetailerModel.setArea(ast.getArea());
555
            }else {
556
                biRetailerModel.setArea("-");
557
            }
34606 ranu 558
            biRetailerModel.setCity(customRetailers.get(fofoId).getAddress().getCity());
559
            biRetailerModel.setStoreName(customRetailers.get(fofoId).getBusinessName());
34619 ranu 560
            biRetailerModel.setStatus(String.valueOf(customRetailers.get(fofoId).getActivationType()));
34606 ranu 561
            biRetailerModel.setCategory(String.valueOf(partnerTypeThisMonth));
562
            biRetailerModel.setSalesManager(managerName);
563
            biRetailerModel.setRbm(rbmName);
564
 
34619 ranu 565
            biRetailerModelMap.put(fofoId,biRetailerModel);
566
 
34641 ranu 567
 
34606 ranu 568
//            generate secondary data
569
 
34641 ranu 570
            List<PartnerWiseActivatedNotBilledTotal> partnerWiseActivatedNotBilledMonthlyTotals = activatedImeiRepository.getTotalMonthlyActivatedNotBilled(fofoId,twoMonthsAgoStartDate);
571
            Map<YearMonth , PartnerWiseActivatedNotBilledTotal> partnerWiseActivatedNotBilledTotalMap = partnerWiseActivatedNotBilledMonthlyTotals.stream().collect(Collectors.toMap(x-> YearMonth.parse(x.getYearMonth()),x->x));
572
 
34606 ranu 573
//            this month secondary target
574
 
34619 ranu 575
            double currentSecondaryTarget =  monthlyTargetRepository.selectByDateAndFofoId(YearMonth.now(), fofoId) != null ? monthlyTargetRepository.selectByDateAndFofoId(YearMonth.now(), fofoId).getPurchaseTarget() : 0;
34606 ranu 576
 
34619 ranu 577
 
578
            long currentMonthReturn = currentMonthPartnerReturnOrderInfoModelMap.getOrDefault(fofoId, 0L) + currentMonthRtoRefundOrderMap.getOrDefault(fofoId, 0L);
579
 
580
 
34606 ranu 581
            Map<Integer, Double> secondaryMtd = orderRepository.selectOrderValueBetweenDatesGroupByFofoId(Arrays.asList(fofoId),
582
                    Arrays.asList(OrderStatus.BILLED, OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.DELIVERY_SUCCESS, OrderStatus.ACCEPTED, OrderStatus.SUBMITTED_FOR_PROCESSING),
583
                    startOfToday.withDayOfMonth(1), startOfToday.with(LocalTime.MAX)).stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getAmount()));
584
 
585
            double secondaryAchievedMtd = secondaryMtd.getOrDefault(fofoId, 0.0);
586
 
34619 ranu 587
            double currentMonthNetSecondary = secondaryAchievedMtd - currentMonthReturn;
34606 ranu 588
 
34619 ranu 589
            double currentMonthSecondaryPercent = currentSecondaryTarget == 0 ? 0.0 : (secondaryAchievedMtd / currentSecondaryTarget) * 100;
590
 
34641 ranu 591
            double currentMonthUnbilled = partnerWiseActivatedNotBilledTotalMap.get(currentMonth) != null ? partnerWiseActivatedNotBilledTotalMap.get(currentMonth).getTotalUnbilledAmount() : 0d;
34619 ranu 592
 
593
//          this month tertiary----------
594
 
595
            LocalDateTime now = LocalDateTime.now();
596
            double todaySale = fofoOrderItemRepository.selectSumMopGroupByRetailer(startOfToday, now, fofoId, false).get(fofoId);
597
            double mtdSaleTillYesterDay = fofoOrderItemRepository.selectSumMopGroupByRetailer(startOfToday.withDayOfMonth(1), startOfToday, fofoId, false).get(fofoId);
598
            double mtdSale = mtdSaleTillYesterDay + todaySale;
599
 
600
 
34606 ranu 601
//            last month secondary target
602
 
34619 ranu 603
            double lastMonthSecondaryTarget = monthlyTargetRepository.selectByDateAndFofoId(lastMonth, fofoId) != null ?  monthlyTargetRepository.selectByDateAndFofoId(lastMonth, fofoId).getPurchaseTarget() : 0;
34606 ranu 604
 
34619 ranu 605
            long lastMonthReturn = (lastMonthPartnerReturnOrderInfoModelMap.getOrDefault(fofoId,0L) + lastMonthRtoRefundOrderMap.getOrDefault(fofoId,0L));
606
 
34606 ranu 607
            Map<Integer, Double> lastMonthSecondary = orderRepository.selectOrderValueBetweenDatesGroupByFofoId(Arrays.asList(fofoId),
608
                    Arrays.asList(OrderStatus.BILLED, OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.DELIVERY_SUCCESS, OrderStatus.ACCEPTED, OrderStatus.SUBMITTED_FOR_PROCESSING),
609
                    lastMontStartDate, lastMonthEndDate).stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getAmount()));
610
 
611
            double lastMonthSecondaryAchieved = lastMonthSecondary.getOrDefault(fofoId, 0.0);
612
 
34619 ranu 613
            double lastMonthNetSecondary = lastMonthSecondaryAchieved - lastMonthReturn;
34606 ranu 614
 
34619 ranu 615
            double lastMonthSecondaryPercent = lastMonthSecondaryTarget == 0 ? 0.0 : (lastMonthSecondaryAchieved / lastMonthSecondaryTarget) * 100;
34606 ranu 616
 
34641 ranu 617
            double lastMonthUnbilled = partnerWiseActivatedNotBilledTotalMap.get(lastMonth) != null ? partnerWiseActivatedNotBilledTotalMap.get(lastMonth).getTotalUnbilledAmount() : 0d;
34606 ranu 618
 
34619 ranu 619
//           last month tertiary
620
            Double lastMonthSale = fofoOrderItemRepository.selectSumMopGroupByRetailer(
621
                    lastMontStartDate, lastMonthEndDate, fofoId, false).get(fofoId);
622
 
623
 
624
//            two month ago secondary target
625
 
626
            double twoMonthAgoSecondaryTarget = monthlyTargetRepository.selectByDateAndFofoId(lastMonth, fofoId) != null ? monthlyTargetRepository.selectByDateAndFofoId(lastMonth, fofoId).getPurchaseTarget() : 0;
627
 
628
            long twoMonthAgoReturn = (twoMonthAgoPartnerReturnOrderInfoModelMap.getOrDefault(fofoId,0L) + twoMonthAgoRtoRefundOrderMap.getOrDefault(fofoId,0L));
629
 
34606 ranu 630
            Map<Integer, Double> twoMonthAgoSecondary = orderRepository.selectOrderValueBetweenDatesGroupByFofoId(Arrays.asList(fofoId),
631
                    Arrays.asList(OrderStatus.BILLED, OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.DELIVERY_SUCCESS, OrderStatus.ACCEPTED, OrderStatus.SUBMITTED_FOR_PROCESSING),
632
                    twoMonthsAgoStartDate, twoMonthsAgoEndDate).stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getAmount()));
633
 
634
            double twoMonthAgoSecondaryAchieved = twoMonthAgoSecondary.getOrDefault(fofoId, 0.0);
635
 
34619 ranu 636
            double twoMonthAgoNetSecondary = twoMonthAgoSecondaryAchieved - twoMonthAgoReturn;
34606 ranu 637
 
34619 ranu 638
            double twoMonthAgoSecondaryPercent = twoMonthAgoSecondaryTarget == 0 ? 0.0 : (twoMonthAgoSecondaryAchieved / twoMonthAgoSecondaryTarget) * 100;
639
 
34641 ranu 640
            double twoMonthAgoUnbilled = partnerWiseActivatedNotBilledTotalMap.get(twoMonthsAgo) != null ? partnerWiseActivatedNotBilledTotalMap.get(twoMonthsAgo).getTotalUnbilledAmount() : 0d;
34619 ranu 641
 
642
//          second Month Tertiary
643
            double twoMonthAgoSale = fofoOrderItemRepository.selectSumMopGroupByRetailer(
644
                    twoMonthsAgoStartDate, twoMonthsAgoEndDate, fofoId, false).get(fofoId);
645
 
646
 
647
            Map<YearMonth, BiSecondaryModel> monthlySecondaryModels = new HashMap<>();
648
 
649
            BiSecondaryModel currentMonthSecondaryModel = new BiSecondaryModel(
650
                    currentSecondaryTarget,
651
                    secondaryAchievedMtd,
652
                    currentMonthReturn,
653
                    currentMonthNetSecondary,
654
                    currentMonthSecondaryPercent,
655
                    mtdSale,
656
                    currentMonthUnbilled // for now, unbilled tertiary value
657
            );
658
 
659
            BiSecondaryModel lastMonthSecondaryModel = new BiSecondaryModel(
660
                    lastMonthSecondaryTarget,
661
                    lastMonthSecondaryAchieved,
662
                    lastMonthReturn,
663
                    lastMonthNetSecondary,
664
                    lastMonthSecondaryPercent,
665
                    lastMonthSale,
666
                    lastMonthUnbilled // for now, unbilled tertiary value
667
            );
668
 
669
            BiSecondaryModel twoMonthAgoSecondaryModel = new BiSecondaryModel(
670
                    twoMonthAgoSecondaryTarget,
671
                    twoMonthAgoSecondaryAchieved,
672
                    twoMonthAgoReturn,
673
                    twoMonthAgoNetSecondary,
674
                    twoMonthAgoSecondaryPercent,
675
                    twoMonthAgoSale,
676
                    twoMonthAgoUnbilled // for now, unbilled tertiary value
677
            );
678
 
679
            monthlySecondaryModels.put(currentMonth, currentMonthSecondaryModel);
680
            monthlySecondaryModels.put(lastMonth, lastMonthSecondaryModel);
681
            monthlySecondaryModels.put(twoMonthsAgo, twoMonthAgoSecondaryModel);
682
 
683
            allRetailerMonthlyData.put(fofoId, monthlySecondaryModels);
684
 
685
//            brandwiseStock value price
686
 
687
            Map<String, BrandStockPrice> brandStockPriceMap = inventoryService.getBrandWiseStockValue(fofoId);
688
 
689
            fofoBrandStockPriceMap.put(fofoId,brandStockPriceMap);
690
 
691
            double totalStockPrice = brandStockPriceMap.values().stream().mapToDouble(x->x.getTotalValue()).sum();
692
 
693
            fofoTotalStockPriceMap.put(fofoId,totalStockPrice);
694
 
695
            Map<String, Double> brandMtdTertiaryAmount = fofoOrderItemRepository.selectSumAmountGroupByBrand(
696
                    currentMonthStartDate, currentMonthEndDate, fofoId);
697
 
34641 ranu 698
            fofoBrandMtdTertiaryMap.put(fofoId,brandMtdTertiaryAmount);
34619 ranu 699
 
700
            double totalMtdTertiaryAmount = brandMtdTertiaryAmount.values().stream().mapToDouble(Double::doubleValue).sum();
701
 
34641 ranu 702
            fofoTotalMtdTertiaryMap.put(fofoId,totalMtdTertiaryAmount);
34619 ranu 703
 
34641 ranu 704
            List<BrandWiseModel> brandWiseMtdSecondary = orderRepository.selectAllBilledOrderGroupByBrandFofoId(fofoId, currentMonthStartDate);
705
            Map<String,Long> brandWiseMtdSecondaryMap = brandWiseMtdSecondary.stream().collect(Collectors.toMap(BrandWiseModel::getBrand,BrandWiseModel::getAmount));
706
            fofoBrandWiseMtdSecondaryMap.put(fofoId,brandWiseMtdSecondaryMap);
34619 ranu 707
 
34641 ranu 708
            long mtdTotalSecondary = brandWiseMtdSecondary.stream().mapToLong(x -> x.getAmount() != 0 ? x.getAmount() : 0L).sum();
34619 ranu 709
 
34641 ranu 710
            fofoTotalMtdSecondaryMap.put(fofoId,mtdTotalSecondary);
711
 
712
            //            generate investment info
713
            FofoStore fofoStore = fofoStoreRepository.selectByRetailerId(fofoId);
714
            float shortInvestment = partnerDailyInvestmentMap.get(fofoId) != null ? partnerDailyInvestmentMap.get(fofoId).getShortInvestment() : 0f;
715
            float agreedInvestment = partnerDailyInvestmentMap.get(fofoId) != null ? partnerDailyInvestmentMap.get(fofoId).getMinInvestment() : 0f;
716
            float investmentLevel = partnerDailyInvestmentMap.get(fofoId) != null ? ((shortInvestment-agreedInvestment)/agreedInvestment)*100 : 0f;
717
 
718
            List<Loan> fofoDefaultLoans = new ArrayList<>();
719
            if(defaultLoanMap != null){
720
                 fofoDefaultLoans  =  defaultLoanMap.get(fofoId);
721
                LOGGER.info("fofoDefaultLoans {}",fofoDefaultLoans);
722
            }
723
 
724
            float defaultLoanAmount = 0f;
725
            if(fofoDefaultLoans != null ){
726
                if (!fofoDefaultLoans.isEmpty()) {
727
                    defaultLoanAmount =  fofoDefaultLoans.stream().map(Loan::getPendingAmount).reduce(BigDecimal.ZERO, BigDecimal::add).floatValue(); // or .floatValue() directly
728
                }
729
            }
730
 
731
            float activeLoan = loanRepository.selectActiveLoan(fofoId).stream().map(Loan::getPendingAmount).reduce(BigDecimal.ZERO,BigDecimal::add).floatValue();
732
 
733
 
734
            float poValue = partnerDailyInvestmentMap.get(fofoId) != null ?  partnerDailyInvestmentMap.get(fofoId).getUnbilledAmount() : 0f;
735
 
736
            List<Order> billedAndPoOrder = orderRepository.selectOrders(Arrays.asList(fofoId),Arrays.asList(OrderStatus.SUBMITTED_FOR_PROCESSING, OrderStatus.ACCEPTED, OrderStatus.BILLED, OrderStatus.SHIPPED_FROM_WH, OrderStatus.DELIVERY_SUCCESS),startOfToday,startOfToday.plusDays(1));
737
            float poAndBilledValue = (float) billedAndPoOrder.stream().map(Order::getTotalAmount).reduce(0f,Float::sum);
738
 
739
            double purchaseMtd = secondaryMtd.getOrDefault(fofoId, 0.0);
740
 
741
            double todayRequiredDrr = rbmTargetService.calculateFofoIdTodayTarget(fofoId, purchaseMtd,LocalDate.now());
742
 
743
            double monthDay1Drr = rbmTargetService.calculateFofoIdTodayTarget(fofoId,0d,YearMonth.now().atDay(1));
744
 
745
 
746
            double gotDrrPercent = (todayRequiredDrr / monthDay1Drr) * 100;
747
 
748
            int orderId = orderRepository.getLastOrderByFofoId(fofoId);
749
 
750
            if (orderId != 0) {
751
                Order order = orderRepository.selectById(orderId);
752
 
753
                // Calculate the number of days since the last purchase (billing)
754
                int lastPurchaseDays = (int) Duration.between(order.getCreateTimestamp().plusDays(1), LocalDateTime.now()).toDays();
755
 
756
                // Determine alert level
757
                String alertLevel = "";
758
                if (lastPurchaseDays >= 11) {
759
                    alertLevel = "Alert for Management";
760
                } else if (lastPurchaseDays >= 8) {
761
                    alertLevel = " Alert for RSM/SH";
762
                } else if (lastPurchaseDays >= 6) {
763
                    alertLevel = "Must be Billed";
764
                } else if (lastPurchaseDays >= 3) {
765
                    alertLevel = "OK";
766
                } else {
767
                    alertLevel = "No Action Needed";
768
                }
769
 
770
 
771
                //          investment modal set all related value
772
                FofoInvestmentModel fofoInvestmentModel = new FofoInvestmentModel();
773
 
774
                fofoInvestmentModel.setCounterPotential(fofoStore.getCounterPotential());
775
                fofoInvestmentModel.setShortInvestment(shortInvestment);
776
                fofoInvestmentModel.setDefaultLoan(defaultLoanAmount);
777
                fofoInvestmentModel.setInvestmentLevel(investmentLevel);
778
                fofoInvestmentModel.setActiveLoan(activeLoan);
779
                fofoInvestmentModel.setPoValue(poValue);
780
                fofoInvestmentModel.setPoAndBilled(poAndBilledValue);
781
                fofoInvestmentModel.setAgreedInvestment(agreedInvestment);
782
                fofoInvestmentModel.setWallet(partnerDailyInvestmentMap.get(fofoId) != null ? partnerDailyInvestmentMap.get(fofoId).getWalletAmount() : 0);
783
                fofoInvestmentModel.setMonthBeginingDrr(monthDay1Drr);
784
                fofoInvestmentModel.setRequiredDrr(todayRequiredDrr);
785
                fofoInvestmentModel.setDrrPercent(gotDrrPercent);
786
                fofoInvestmentModel.setLastBillingDone(lastPurchaseDays);
787
                fofoInvestmentModel.setSlab(alertLevel);
788
 
789
                biInvestmentModelMap.put(fofoId, fofoInvestmentModel);
790
            }
791
                String assessment = "";
792
                if(defaultLoanAmount > 0 ){
793
                    assessment = "Loan Default";
794
                }else if(investmentLevel <= 75 && defaultLoanAmount < 1){
795
                    assessment = "Low Invest";
796
                }else {
797
                    assessment = "-";
798
                }
799
                assessmentMap.put(fofoId,assessment);
800
 
801
                String zeroBilling = "";
802
                if(currentMonthNetSecondary <= 100000 ){
803
                    zeroBilling = "Zero Billing";
804
                }else {
805
                    zeroBilling = "-";
806
                }
807
                zeroBillingMap.put(fofoId,zeroBilling);
808
 
809
                float billingNeeded = 0f;
810
                if(gotDrrPercent >= 110 ){
811
                    billingNeeded = (float) todayRequiredDrr;
812
                }else {
813
                    billingNeeded = 0f;
814
                }
815
                billingNeededMap.put(fofoId,billingNeeded);
816
 
817
                int counta = 0;
818
                if(defaultLoanAmount > 0 || investmentLevel <= 75 || currentMonthNetSecondary <= 100000 || gotDrrPercent >= 110 ){
819
                    counta = 1;
820
                }else {
821
                    counta = 0;
822
                }
823
                countAMap.put(fofoId,counta);
824
 
34606 ranu 825
        }
826
 
34619 ranu 827
        LOGGER.info("Total BI Retailers processed: {}", biRetailerModelMap.size());
34606 ranu 828
 
34619 ranu 829
        //generate excel and sent to mail
830
        List<List<String>> headerGroup = new ArrayList<>();
34606 ranu 831
 
34619 ranu 832
        List<String> headers1 = Arrays.asList(
34641 ranu 833
                "","","","",
834
                "Retailer Detail", "", "", "", "", "", "", "", "",
34619 ranu 835
                currentMonthStringValue, "", "", "", "", "", "",
836
                lastMonthStringValue, "", "", "", "", "", "",
34641 ranu 837
                twoMonthAgoStringValue, "", "", "", "", "", "",
838
 
839
                "","", "", "", "", "", "", "", "", "", "", "", "", "",
840
 
841
                "", "", "", "", "", "", "", "", "", "", "", "", "",
842
                "", "", "", "", "", "", "", "", "", "", "", "", ""
843
 
34619 ranu 844
        );
34606 ranu 845
 
34619 ranu 846
        List<String> headers2 = Arrays.asList(
34641 ranu 847
                "Assessment","Zero billing","Billing needed","Counta",
34619 ranu 848
                "Code", "Store Name", "City", "Area", "BM", "Sales Manager", "RBM", "Status", "Category",
849
                "Secondary Target", "Secondary Achieved", "Returns", "Net Secondary", "Secondary %",
850
                "Tertiary Sale", "Unbilled",
851
                "Secondary Target", "Secondary Achieved", "Returns", "Net Secondary", "Secondary %",
852
                "Tertiary Sale", "Unbilled",
853
                "Secondary Target", "Secondary Achieved", "Returns", "Net Secondary", "Secondary %",
854
                "Tertiary Sale", "Unbilled",
34641 ranu 855
                "Counter Potential", "Short investment", "Default", "INVESTMENT LEVEL", "Loan", "PO value", "Agreed investment",
856
                "Wallet", "po+bill", "MONTH BEGINNING DRR", "REQ DRR", "Drr %", "Last billing Done", "Slab",
34606 ranu 857
 
34641 ranu 858
              "Total Stock",  "Apple","Xiaomi", "Vivo", "Tecno", "Samsung", "Realme", "Oppo", "OnePlus", "Poco", "Lava", "Itel", "Almost New",
859
              "Total Secondary", "Apple", "Xiaomi", "Vivo", "Tecno", "Samsung", "Realme", "Oppo", "OnePlus", "Poco", "Lava", "Itel", "Almost New",
860
              "Total Tertiary",  "Apple", "Xiaomi", "Vivo", "Tecno", "Samsung", "Realme", "Oppo", "OnePlus", "Poco", "Lava", "Itel", "Almost New"
34619 ranu 861
        );
862
 
863
        headerGroup.add(headers1);
864
        headerGroup.add(headers2);
865
 
866
 
867
        List<List<?>> rows = new ArrayList<>();
868
        for (Map.Entry<Integer, BIRetailerModel> entry : biRetailerModelMap.entrySet()) {
869
            Integer fofoId = entry.getKey();
870
            BIRetailerModel retailer = entry.getValue();
34641 ranu 871
 
34619 ranu 872
            Map<YearMonth, BiSecondaryModel> monthlyData = allRetailerMonthlyData.get(fofoId);
873
 
874
            BiSecondaryModel current = monthlyData.getOrDefault(YearMonth.now(), new BiSecondaryModel(0,0,0,0,0,0,0));
875
            BiSecondaryModel last = monthlyData.getOrDefault(YearMonth.now().minusMonths(1), new BiSecondaryModel(0,0,0,0,0,0,0));
876
            BiSecondaryModel twoAgo = monthlyData.getOrDefault(YearMonth.now().minusMonths(2), new BiSecondaryModel(0,0,0,0,0,0,0));
877
 
878
            List<Object> row = new ArrayList<>();
879
            row.addAll(Arrays.asList(
34641 ranu 880
                    assessmentMap.get(fofoId),zeroBillingMap.get(fofoId),billingNeededMap.get(fofoId),countAMap.get(fofoId),
34619 ranu 881
                    retailer.getCode(), retailer.getStoreName(), retailer.getCity(), retailer.getArea(),
882
                    retailer.getBmName(), retailer.getSalesManager(), retailer.getRbm(),
883
                    retailer.getStatus(), retailer.getCategory()
884
            ));
885
 
886
            // Current Month
887
            row.addAll(Arrays.asList(
888
                    current.getSecondaryTarget(),
889
                    current.getSecondaryAchieved(),
890
                    current.getSecondaryReturn(),
891
                    current.getNetSecondary(),
892
                    current.getSecondaryAchievedPercent(),
893
                    current.getTertiary(),
894
                    current.getTertiaryUnBilled()
895
            ));
896
 
897
            // Last Month
898
            row.addAll(Arrays.asList(
899
                    last.getSecondaryTarget(),
900
                    last.getSecondaryAchieved(),
901
                    last.getSecondaryReturn(),
902
                    last.getNetSecondary(),
903
                    last.getSecondaryAchievedPercent(),
904
                    last.getTertiary(),
905
                    last.getTertiaryUnBilled()
906
            ));
907
 
908
            // Two Months Ago
909
            row.addAll(Arrays.asList(
910
                    twoAgo.getSecondaryTarget(),
911
                    twoAgo.getSecondaryAchieved(),
912
                    twoAgo.getSecondaryReturn(),
913
                    twoAgo.getNetSecondary(),
914
                    twoAgo.getSecondaryAchievedPercent(),
915
                    twoAgo.getTertiary(),
916
                    twoAgo.getTertiaryUnBilled()
917
            ));
34641 ranu 918
            FofoInvestmentModel fofoInvestmentModelValue = biInvestmentModelMap.get(fofoId);
919
            if(fofoInvestmentModelValue != null){
920
                row.addAll(Arrays.asList(
921
                        fofoInvestmentModelValue.getCounterPotential(),
922
                        fofoInvestmentModelValue.getShortInvestment(),
923
                        fofoInvestmentModelValue.getDefaultLoan(),
924
                        fofoInvestmentModelValue.getInvestmentLevel(),
925
                        fofoInvestmentModelValue.getActiveLoan(),
926
                        fofoInvestmentModelValue.getPoValue(),
927
                        fofoInvestmentModelValue.getAgreedInvestment(),
928
                        fofoInvestmentModelValue.getWallet(),
929
                        fofoInvestmentModelValue.getPoAndBilled(),
930
                        fofoInvestmentModelValue.getMonthBeginingDrr(),
931
                        fofoInvestmentModelValue.getRequiredDrr(),
932
                        fofoInvestmentModelValue.getDrrPercent(),
933
                        fofoInvestmentModelValue.getLastBillingDone(),
934
                        fofoInvestmentModelValue.getSlab()
935
                ));
936
            }else {
937
                row.addAll(Arrays.asList(
938
                        "-","-","-","-","-","-","-","-","-","-","-",""
939
                ));
940
            }
941
 
942
            Map<String, BrandStockPrice> brandStockMap = fofoBrandStockPriceMap.get(fofoId);
34619 ranu 943
            row.addAll(Arrays.asList(
944
                    fofoTotalStockPriceMap.getOrDefault(fofoId, 0.0),
34641 ranu 945
                    brandStockMap.get("Apple") != null ? brandStockMap.get("Apple").getTotalValue() : 0.0,
946
                    brandStockMap.get("Xiaomi") != null ? brandStockMap.get("Xiaomi").getTotalValue() : 0.0,
947
                    brandStockMap.get("Vivo") != null ? brandStockMap.get("Vivo").getTotalValue() : 0.0,
948
                    brandStockMap.get("Tecno") != null ? brandStockMap.get("Tecno").getTotalValue() : 0.0,
949
                    brandStockMap.get("Samsung") != null ? brandStockMap.get("Samsung").getTotalValue() : 0.0,
950
                    brandStockMap.get("Realme") != null ? brandStockMap.get("Realme").getTotalValue() : 0.0,
951
                    brandStockMap.get("Oppo") != null ? brandStockMap.get("Oppo").getTotalValue() : 0.0,
952
                    brandStockMap.get("OnePlus") != null ? brandStockMap.get("OnePlus").getTotalValue() : 0.0,
953
                    brandStockMap.get("Poco") != null ? brandStockMap.get("Poco").getTotalValue() : 0.0,
954
                    brandStockMap.get("Lava") != null ? brandStockMap.get("Lava").getTotalValue() : 0.0,
955
                    brandStockMap.get("Itel") != null ? brandStockMap.get("Itel").getTotalValue() : 0.0,
956
                    brandStockMap.get("Almost New") != null ? brandStockMap.get("Almost New").getTotalValue() : 0.0
34619 ranu 957
            ));
958
 
34641 ranu 959
            Map<String, Long> brandSecondaryMap = fofoBrandWiseMtdSecondaryMap.get(fofoId);
960
            row.addAll(Arrays.asList(
961
                    current.getSecondaryAchieved(),
962
                    brandSecondaryMap.getOrDefault("Apple", 0L),
963
                    brandSecondaryMap.getOrDefault("Xiaomi", 0L),
964
                    brandSecondaryMap.getOrDefault("Vivo", 0L),
965
                    brandSecondaryMap.getOrDefault("Tecno", 0L),
966
                    brandSecondaryMap.getOrDefault("Samsung", 0L),
967
                    brandSecondaryMap.getOrDefault("Realme", 0L),
968
                    brandSecondaryMap.getOrDefault("Oppo", 0L),
969
                    brandSecondaryMap.getOrDefault("OnePlus", 0L),
970
                    brandSecondaryMap.getOrDefault("Poco", 0L),
971
                    brandSecondaryMap.getOrDefault("Lava", 0L),
972
                    brandSecondaryMap.getOrDefault("Itel", 0L),
973
                    brandSecondaryMap.getOrDefault("Almost New", 0L)
974
            ));
34619 ranu 975
            rows.add(row);
34641 ranu 976
 
977
            Map<String, Double> brandTertiaryMap = fofoBrandMtdTertiaryMap.get(fofoId);
978
            row.addAll(Arrays.asList(
979
                    current.getTertiary(),
980
                    brandTertiaryMap.getOrDefault("Apple", 0d),
981
                    brandTertiaryMap.getOrDefault("Xiaomi", 0d),
982
                    brandTertiaryMap.getOrDefault("Vivo", 0d),
983
                    brandTertiaryMap.getOrDefault("Tecno", 0d),
984
                    brandTertiaryMap.getOrDefault("Samsung", 0d),
985
                    brandTertiaryMap.getOrDefault("Realme", 0d),
986
                    brandTertiaryMap.getOrDefault("Oppo", 0d),
987
                    brandTertiaryMap.getOrDefault("OnePlus", 0d),
988
                    brandTertiaryMap.getOrDefault("Poco", 0d),
989
                    brandTertiaryMap.getOrDefault("Lava", 0d),
990
                    brandTertiaryMap.getOrDefault("Itel", 0d),
991
                    brandTertiaryMap.getOrDefault("Almost New", 0d)
992
            ));
993
            rows.add(row);
34619 ranu 994
        }
995
 
996
 
34641 ranu 997
        // Send to email
998
//        ByteArrayOutputStream csvStream = FileUtil.getCSVByteStreamWithMultiHeaders(headerGroup, rows);
999
        ByteArrayOutputStream csvStream = getExcelStreamWithMultiHeaders(headerGroup, rows);
1000
        String fileName = "BI-Retailer-Monthly-Report-" + FormattingUtils.formatDate(LocalDateTime.now()) + ".xlsx";
34619 ranu 1001
        String[] sendToArray = new String[]{"ranu.rajput@smartdukaan.com"};
1002
 
1003
        Utils.sendMailWithAttachment(googleMailSender, sendToArray, new String[]{}, "BI Retailer Monthly Report", "Please find attached the BI retailer secondary/tertiary monthly report.", fileName, new ByteArrayResource(csvStream.toByteArray()));
1004
 
1005
 
34606 ranu 1006
    }
1007
 
34641 ranu 1008
    public static ByteArrayOutputStream getExcelStreamWithMultiHeaders(List<List<String>> headerGroup, List<List<?>> rows) {
1009
        Workbook workbook = new XSSFWorkbook();
1010
        Sheet sheet = workbook.createSheet("BI Report");
1011
        int rowIndex = 0;
34606 ranu 1012
 
34641 ranu 1013
        CellStyle centeredStyle = workbook.createCellStyle();
1014
        centeredStyle.setAlignment(HorizontalAlignment.CENTER); // Center horizontally
1015
        centeredStyle.setVerticalAlignment(VerticalAlignment.CENTER); // Center vertically
34606 ranu 1016
 
34641 ranu 1017
    // Optional: bold font
1018
        Font font1 = workbook.createFont();
1019
        font1.setBold(true);
1020
        centeredStyle.setFont(font1);
34606 ranu 1021
 
34619 ranu 1022
 
34641 ranu 1023
 
1024
        // Create styles
1025
        Map<String, CellStyle> headerStyles = new HashMap<>();
1026
 
1027
        // fontPurpleStyle
1028
        CellStyle purpleStyle = workbook.createCellStyle();
1029
        purpleStyle.setFillForegroundColor(IndexedColors.ROSE.getIndex());
1030
        purpleStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
1031
        purpleStyle.setFont(font1);
1032
        headerStyles.put("Assessment", purpleStyle);
1033
        headerStyles.put("Zero billing", purpleStyle);
1034
        headerStyles.put("Billing needed", purpleStyle);
1035
        headerStyles.put("Counta", purpleStyle);
1036
        headerStyles.put("MONTH BEGINNING DRR", purpleStyle);
1037
        headerStyles.put("REQ DRR", purpleStyle);
1038
        headerStyles.put("Drr %", purpleStyle);
1039
 
1040
        // Light Blue
1041
        CellStyle blueStyle = workbook.createCellStyle();
1042
        blueStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
1043
        blueStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
1044
        blueStyle.setFont(font1);
1045
        headerStyles.put("Code", blueStyle);
1046
        headerStyles.put("Store Name", blueStyle);
1047
        headerStyles.put("City", blueStyle);
1048
        headerStyles.put("Area", blueStyle);
1049
        headerStyles.put("BM", blueStyle);
1050
        headerStyles.put("RBM", blueStyle);
1051
        headerStyles.put("Sales Manager", blueStyle);
1052
        headerStyles.put("Status", blueStyle);
1053
        headerStyles.put("Category", blueStyle);
1054
 
1055
        // Light Yellow
1056
        CellStyle yellowStyle = workbook.createCellStyle();
1057
        yellowStyle.setFillForegroundColor(IndexedColors.YELLOW.getIndex());
1058
        yellowStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
1059
        yellowStyle.setFont(font1);
1060
        headerStyles.put("Last billing Done", yellowStyle);
1061
        headerStyles.put("Total Stock", yellowStyle);
1062
 
1063
        // Light Orange
1064
        CellStyle orangeStyle = workbook.createCellStyle();
1065
        orangeStyle.setFillForegroundColor(IndexedColors.LIGHT_ORANGE.getIndex());
1066
        orangeStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
1067
        orangeStyle.setFont(font1);
1068
        headerStyles.put("Total Tertiary", orangeStyle);
1069
        headerStyles.put("Total Secondary", orangeStyle);
1070
        headerStyles.put("Default", orangeStyle);
1071
 
1072
 
1073
        // Light green
1074
        CellStyle lightGreenStyle = workbook.createCellStyle();
1075
        lightGreenStyle.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex());
1076
        lightGreenStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
1077
        lightGreenStyle.setFont(font1);
1078
        headerStyles.put("Short investment", lightGreenStyle);
1079
        headerStyles.put("INVESTMENT LEVEL", lightGreenStyle);
1080
        headerStyles.put("Loan", lightGreenStyle);
1081
        headerStyles.put("PO value", lightGreenStyle);
1082
        headerStyles.put("Agreed investment", lightGreenStyle);
1083
        headerStyles.put("Wallet", lightGreenStyle);
1084
        headerStyles.put("po+bill", lightGreenStyle);
1085
 
1086
        // Light Green
1087
        CellStyle secondary1 = createStyle(workbook, IndexedColors.LIGHT_GREEN);
1088
        CellStyle secondary2 = createStyle(workbook, IndexedColors.LIGHT_YELLOW);
1089
        CellStyle secondary3 = createStyle(workbook, IndexedColors.LIGHT_ORANGE);
1090
 
1091
        Map<String, CellStyle> brandStyles = new HashMap<>();
1092
        brandStyles.put("Apple", createStyle(workbook, IndexedColors.GREY_25_PERCENT));
1093
        brandStyles.put("Xiaomi", createStyle(workbook, IndexedColors.ORANGE));
1094
        brandStyles.put("Vivo", createStyle(workbook, IndexedColors.SKY_BLUE));
1095
        brandStyles.put("Tecno", createStyle(workbook, IndexedColors.LIGHT_BLUE));
1096
        brandStyles.put("Samsung", createStyle(workbook, IndexedColors.ROYAL_BLUE));
1097
        brandStyles.put("Realme", createStyle(workbook, IndexedColors.YELLOW));
1098
        brandStyles.put("Oppo", createStyle(workbook, IndexedColors.LIGHT_GREEN));
1099
        brandStyles.put("OnePlus", createStyle(workbook, IndexedColors.RED));
1100
        brandStyles.put("Poco", createStyle(workbook, IndexedColors.ORANGE));
1101
        brandStyles.put("Lava", createStyle(workbook, IndexedColors.LIGHT_YELLOW));
1102
        brandStyles.put("Itel", createStyle(workbook, IndexedColors.LIGHT_YELLOW));
1103
        brandStyles.put("Almost New", createStyle(workbook, IndexedColors.WHITE));
1104
 
1105
 
1106
        CellStyle defaultHeaderStyle = workbook.createCellStyle();
1107
        defaultHeaderStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
1108
        defaultHeaderStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
1109
        defaultHeaderStyle.setFont(font1);
1110
 
1111
 
1112
        Map<String, Integer> headerCount = new HashMap<>();
1113
 
1114
        for (int headerRowIndex = 0; headerRowIndex < headerGroup.size(); headerRowIndex++) {
1115
            List<String> headerRow = headerGroup.get(headerRowIndex);
1116
            Row row = sheet.createRow(rowIndex++);
1117
 
1118
            for (int i = 0; i < headerRow.size(); i++) {
1119
                String headerText = headerRow.get(i);
1120
                sheet.setColumnWidth(i, 25 * 256);
1121
                row.setHeightInPoints(20); // 25-point height
1122
                Cell cell = row.createCell(i);
1123
                cell.setCellValue(headerText);
1124
                cell.setCellStyle(centeredStyle);
1125
                // Count how many times this header has appeared
1126
                int count = headerCount.getOrDefault(headerText, 0) + 1;
1127
                headerCount.put(headerText, count);
1128
                // Apply special style for repeated headers
1129
                if (headerText.equals("Secondary Target") || headerText.equals("Secondary Achieved") || headerText.equals("Returns") || headerText.equals("Net Secondary") || headerText.equals("Secondary %") || headerText.equals("Tertiary Sale") || headerText.equals("Unbilled")) {
1130
                    if (count == 1) {
1131
                        cell.setCellStyle(secondary1);
1132
                    } else if (count == 2) {
1133
                        cell.setCellStyle(secondary2);
1134
                    } else if (count == 3) {
1135
                        cell.setCellStyle(secondary3);
1136
                    }
1137
                }
1138
                // Brand header styling (apply only for the 2nd row of headers)
1139
                else if (headerRowIndex == 1 && brandStyles.containsKey(headerText)) {
1140
                    cell.setCellStyle(brandStyles.get(headerText));
1141
                }else if (headerStyles.containsKey(headerText)) {
1142
                    cell.setCellStyle(headerStyles.get(headerText));
1143
                } else {
1144
                    cell.setCellStyle(defaultHeaderStyle); // default style for others
1145
                }
1146
            }
1147
        }
1148
 
1149
        // Write data rows
1150
        for (List<?> dataRow : rows) {
1151
            Row row = sheet.createRow(rowIndex++);
1152
            for (int i = 0; i < dataRow.size(); i++) {
1153
                Cell cell = row.createCell(i);
1154
                Object value = dataRow.get(i);
1155
                if (value instanceof Number) {
1156
                    cell.setCellValue(((Number) value).doubleValue());
1157
                } else {
1158
                    cell.setCellValue(value != null ? value.toString() : "");
1159
                }
1160
            }
1161
        }
1162
 
1163
        // Auto-size columns
1164
        if (!rows.isEmpty()) {
1165
            for (int i = 0; i < rows.get(0).size(); i++) {
1166
                sheet.autoSizeColumn(i);
1167
            }
1168
        }
1169
 
1170
        // Output as ByteArray
1171
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
1172
            workbook.write(outputStream);
1173
            workbook.close();
1174
            return outputStream;
1175
        } catch (IOException e) {
1176
            throw new RuntimeException("Failed to generate Excel file", e);
1177
        }
1178
    }
1179
 
1180
 
1181
    private static CellStyle createStyle(Workbook workbook, IndexedColors color) {
1182
        CellStyle style = workbook.createCellStyle();
1183
        style.setFillForegroundColor(color.getIndex());
1184
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
1185
        Font font = workbook.createFont();
1186
        font.setBold(true);
1187
        style.setFont(font);
1188
        return style;
1189
    }
1190
 
1191
 
1192
 
1193
 
34306 ranu 1194
}