Subversion Repositories SmartDukaan

Rev

Rev 36028 | 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.FormattingUtils;
8
import com.spice.profitmandi.common.util.Utils;
34450 ranu 9
import com.spice.profitmandi.dao.cart.SmartCartService;
34321 ranu 10
import com.spice.profitmandi.dao.entity.auth.AuthUser;
34758 ranu 11
import com.spice.profitmandi.dao.entity.catalog.TagListing;
34606 ranu 12
import com.spice.profitmandi.dao.entity.fofo.*;
13
import com.spice.profitmandi.dao.entity.logistics.AST;
14
import com.spice.profitmandi.dao.entity.logistics.ASTRepository;
34619 ranu 15
import com.spice.profitmandi.dao.entity.transaction.*;
34321 ranu 16
import com.spice.profitmandi.dao.entity.user.User;
17
import com.spice.profitmandi.dao.enumuration.cs.EscalationType;
34619 ranu 18
import com.spice.profitmandi.dao.enumuration.transaction.LoanReferenceType;
34641 ranu 19
import com.spice.profitmandi.dao.model.*;
34606 ranu 20
import com.spice.profitmandi.dao.repository.auth.AuthRepository;
34758 ranu 21
import com.spice.profitmandi.dao.repository.catalog.TagListingRepository;
34321 ranu 22
import com.spice.profitmandi.dao.repository.cs.CsService;
23
import com.spice.profitmandi.dao.repository.dtr.FofoStoreRepository;
34606 ranu 24
import com.spice.profitmandi.dao.repository.fofo.*;
25
import com.spice.profitmandi.dao.repository.inventory.StateRepository;
34619 ranu 26
import com.spice.profitmandi.dao.repository.transaction.*;
34321 ranu 27
import com.spice.profitmandi.dao.repository.user.UserRepository;
35358 ranu 28
import com.spice.profitmandi.dao.service.solr.FofoSolr;
34655 ranu 29
import com.spice.profitmandi.service.PartnerStatsService;
34641 ranu 30
import com.spice.profitmandi.service.RbmTargetService;
34758 ranu 31
import com.spice.profitmandi.service.inventory.*;
34308 ranu 32
import com.spice.profitmandi.service.transaction.SDCreditService;
34606 ranu 33
import com.spice.profitmandi.service.user.RetailerService;
34619 ranu 34
import com.spice.profitmandi.service.wallet.WalletService;
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;
34715 ranu 39
import org.apache.poi.common.usermodel.HyperlinkType;
34641 ranu 40
import org.apache.poi.ss.usermodel.*;
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;
44
import org.springframework.core.io.ByteArrayResource;
34321 ranu 45
import org.springframework.mail.javamail.JavaMailSender;
46
import org.springframework.mail.javamail.MimeMessageHelper;
34306 ranu 47
import org.springframework.stereotype.Component;
48
import org.springframework.transaction.annotation.Transactional;
49
 
34321 ranu 50
import javax.mail.MessagingException;
51
import javax.mail.internet.InternetAddress;
52
import javax.mail.internet.MimeMessage;
34619 ranu 53
import java.io.*;
54
import java.math.BigDecimal;
34641 ranu 55
import java.time.*;
34749 ranu 56
import java.time.format.DateTimeFormatter;
34306 ranu 57
import java.time.temporal.ChronoUnit;
36113 ranu 58
import java.time.temporal.TemporalAdjusters;
59
import java.time.DayOfWeek;
34306 ranu 60
import java.util.*;
34321 ranu 61
import java.util.stream.Collectors;
34306 ranu 62
 
34939 ranu 63
import static java.util.stream.Collectors.toList;
64
 
34306 ranu 65
@Component
66
@Transactional(rollbackFor = {Throwable.class, ProfitMandiBusinessException.class})
67
public class ScheduledTasksTest {
68
 
69
    private static final Logger LOGGER = LogManager.getLogger(ScheduledTasksTest.class);
70
 
71
    @Autowired
72
    TransactionRepository transactionRepository;
73
 
74
    @Autowired
34619 ranu 75
    @Qualifier(value = "googleMailSender")
76
    private JavaMailSender googleMailSender;
77
 
78
    @Autowired
34306 ranu 79
    LoanRepository loanRepository;
80
 
34308 ranu 81
    @Autowired
82
    SDCreditService sdCreditService;
83
 
34321 ranu 84
    @Autowired
34939 ranu 85
    SmartCartSuggestionRepository smartCartSuggestionRepository;
86
 
87
    @Autowired
34321 ranu 88
    UserRepository userRepository;
89
 
90
    @Autowired
91
    CsService csService;
92
 
93
    @Autowired
94
    RbmRatingRepository rbmRatingRepository;
95
 
96
    @Autowired
97
    private JavaMailSender mailSender;
98
 
99
    @Autowired
100
    SalesRatingRepository salesRatingRepository;
101
 
102
    @Autowired
103
    FofoStoreRepository fofoStoreRepository;
104
 
34450 ranu 105
    @Autowired
106
    SmartCartService smartCartService;
107
 
34606 ranu 108
    @Autowired
109
    RetailerService retailerService;
110
 
111
    @Autowired
112
    ASTRepository astRepository;
113
 
114
    @Autowired
115
    AuthRepository authRepository;
116
 
117
    @Autowired
118
    StateRepository stateRepository;
119
 
120
    @Autowired
121
    MonthlyTargetRepository monthlyTargetRepository;
122
 
123
    @Autowired
124
    PartnerTypeChangeService partnerTypeChangeService;
125
 
126
    @Autowired
127
    ReturnOrderInfoRepository returnOrderInfoRepository;
128
 
129
    @Autowired
130
    OrderRepository orderRepository;
131
 
34619 ranu 132
    @Autowired
133
    FofoOrderItemRepository fofoOrderItemRepository;
134
 
135
    @Autowired
136
    InventoryService inventoryService;
137
 
138
    @Autowired
139
    UserWalletRepository userWalletRepository;
140
 
141
    @Autowired
142
    LoanStatementRepository loanStatementRepository;
143
 
144
    @Autowired
34641 ranu 145
    ActivatedImeiRepository activatedImeiRepository;
146
 
147
    @Autowired
148
    PartnerDailyInvestmentRepository partnerDailyInvestmentRepository;
149
 
150
    @Autowired
34758 ranu 151
    SaholicInventoryService saholicInventoryService;
152
 
153
    @Autowired
34619 ranu 154
    WalletService walletService;
155
 
34641 ranu 156
    @Autowired
157
    RbmTargetService rbmTargetService;
158
 
34655 ranu 159
    @Autowired
160
    PartnerStatsService partnerStatsService;
161
 
34715 ranu 162
    @Autowired
34758 ranu 163
    AgeingService ageingService;
164
 
165
    @Autowired
166
    TagListingRepository tagListingRepository;
167
 
168
    @Autowired
34715 ranu 169
    UserWalletHistoryRepository userWalletHistoryRepository;
170
 
35358 ranu 171
    @Autowired
172
    FofoSolr fofoSolr;
173
 
34321 ranu 174
    public void test() throws Exception {
35358 ranu 175
 
176
        fofoSolr.populateTagItems();
177
 
34366 ranu 178
        System.out.println("test end");
34306 ranu 179
 
180
    }
181
 
34648 ranu 182
    public void generateBiReport() throws Exception {
34912 ranu 183
        this.generateBiReportExcel();
34648 ranu 184
    }
185
 
34308 ranu 186
    public void createLoanForBillingByTransactionIdAndInvoiceNumber(int transactionId, double invoiceAmount, String invoiceNumber) throws Exception {
187
        sdCreditService.createLoanForBilling(transactionId, invoiceAmount, invoiceNumber);
34306 ranu 188
 
34308 ranu 189
    }
34306 ranu 190
 
34619 ranu 191
    public void loanSettle() throws Exception {
192
        List<Integer> refrences = Arrays.asList(25807,36003,38938,39506,42219,45084);
193
        for(Integer ref : refrences){
194
            List<LoanStatement> loanStatements = loanStatementRepository.selectByLoanId(ref);
195
            double amountSum = loanStatements.stream().map(LoanStatement::getAmount).mapToDouble(BigDecimal::doubleValue).sum();
196
            if(amountSum > 0){
197
                walletService.addAmountToWallet(loanStatements.get(0).getFofoId(),ref, WalletReferenceType.CREDIT_LIMIT,"Amount reversal against credit limit deduction",(float) amountSum,LocalDateTime.now());
34308 ranu 198
 
34619 ranu 199
//                Loan statement entry
200
                    BigDecimal adjustAmount = BigDecimal.valueOf(amountSum).negate(); // or multiply by -1
201
                    LoanStatement loanStatement = new LoanStatement();
202
                    loanStatement.setAmount(adjustAmount);
203
                    loanStatement.setFofoId(loanStatements.get(0).getFofoId());
204
                    loanStatement.setLoanReferenceType(LoanReferenceType.PRINCIPAL);
205
                    loanStatement.setCreatedAt(LocalDateTime.now());
206
                    loanStatement.setDescription("Amount reversal due to access debit against limit");
207
                    loanStatement.setLoanId(ref);
208
                    loanStatement.setBusinessDate(LocalDateTime.now());
209
                    loanStatementRepository.persist(loanStatement);
210
 
211
                    Loan loan = loanRepository.selectByLoanId(ref);
212
                    loan.setPendingAmount(BigDecimal.valueOf(0));
213
                    loan.setSettledOn(LocalDateTime.now());
214
                }
215
 
216
 
217
        }
218
    }
219
 
220
 
221
 
34321 ranu 222
    private void sendMailHtmlFormat(String email[], String body, String cc[], String bcc[], String subject)
223
            throws MessagingException, ProfitMandiBusinessException, IOException {
224
        MimeMessage message = mailSender.createMimeMessage();
225
        MimeMessageHelper helper = new MimeMessageHelper(message);
226
        helper.setSubject(subject);
227
        helper.setText(body, true);
228
        helper.setTo(email);
229
        if (cc != null) {
230
            helper.setCc(cc);
231
        }
232
        if (bcc != null) {
233
            helper.setBcc(bcc);
34308 ranu 234
 
34321 ranu 235
        }
236
 
237
        InternetAddress senderAddress = new InternetAddress("noreply@smartdukaan.com", "Smart Dukaan");
238
        helper.setFrom(senderAddress);
239
        mailSender.send(message);
240
    }
241
 
34307 ranu 242
    public Map<Integer,Integer> findLoanTransactionMapingAccordingLoan(List<Integer> loanIds) throws ProfitMandiBusinessException {
34306 ranu 243
 
244
        Map<Integer, Integer> transactionLoanMap = new HashMap<>();
245
 
246
        for(int loanId : loanIds){
247
            Transaction transaction = null;
248
            Loan loan = loanRepository.selectByLoanId(loanId);
249
            List<Transaction> transactions = transactionRepository.selectByRetailerId(loan.getFofoId());
250
 
251
            LocalDateTime nearestDateTime = transactions.stream().map(x -> x.getCreateTimestamp())
252
                    .min(Comparator.comparingLong(x -> Math.abs(ChronoUnit.MILLIS.between(x, loan.getCreatedOn()))))
253
                    .orElse(null);
254
 
255
            if (nearestDateTime != null && loan.getCreatedOn().plusMinutes(2).isAfter(nearestDateTime) &&
256
                    loan.getCreatedOn().minusMinutes(1).isBefore(nearestDateTime)) {
257
                // Here transaction is still null
258
                transaction = transactions.stream()
259
                        .filter(x -> x.getCreateTimestamp().equals(nearestDateTime))
260
                        .findFirst().get();
261
                transactionLoanMap.put(transaction.getId(), loanId);
262
            }
263
 
264
        }
265
        LOGGER.info("transactionLoanMap {}",transactionLoanMap);
266
        return transactionLoanMap;
267
    }
34321 ranu 268
 
269
 
270
 
271
    public void sendRbmFeedbackSummaryEmail() throws MessagingException, ProfitMandiBusinessException, IOException {
36113 ranu 272
        // Weekly date range: Previous Monday to Sunday
273
        LocalDate today = LocalDate.now();
274
        LocalDate previousMonday = today.with(TemporalAdjusters.previous(DayOfWeek.MONDAY));
275
        LocalDate previousSunday = previousMonday.plusDays(6);
276
        LocalDateTime startOfWeek = previousMonday.atStartOfDay();
277
        LocalDateTime endOfWeek = previousSunday.atTime(23, 59, 59);
278
 
34323 ranu 279
        String[] bcc = {"tarun.verma@smartdukaan.com"};
36113 ranu 280
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy");
34321 ranu 281
 
282
        // Get all RBM users
283
        List<AuthUser> authUsers = csService.getAuthUserIds(
284
                ProfitMandiConstants.TICKET_CATEGORY_RBM,
285
                Arrays.asList(EscalationType.L1)
286
        );
287
 
288
        if (authUsers.isEmpty()) {
289
            LOGGER.info("No RBMs found.");
290
            return;
291
        }
292
 
293
        List<Integer> rbmIds = authUsers.stream().map(AuthUser::getId).collect(Collectors.toList());
294
 
36113 ranu 295
        // Fetch ratings for all RBMs for the week
296
        List<RbmRating> feedbackList = rbmRatingRepository.selectByRbmIdsAndDateRange(rbmIds, startOfWeek, endOfWeek);
34321 ranu 297
 
298
        if (feedbackList.isEmpty()) {
36113 ranu 299
            LOGGER.info("No feedback entries found for RBMs for the week.");
34321 ranu 300
            return;
301
        }
302
 
303
        // Sort feedback by createTimeStamp DESC
304
        feedbackList.sort((a, b) -> b.getCreateTimeStamp().compareTo(a.getCreateTimeStamp()));
305
 
306
        // Fetch and map FOFO (partner) names
307
        Map<Integer, String> fofoNameMap = new HashMap<>();
308
        for (RbmRating rating : feedbackList) {
309
            int fofoId = rating.getFofoId();
310
            if (!fofoNameMap.containsKey(fofoId)) {
311
                User fofoUser = userRepository.selectById(fofoId);
312
                FofoStore fofoStore = fofoStoreRepository.selectByRetailerId(fofoId);
313
 
314
                String partnerName = fofoUser != null ? fofoUser.getName() : "Unknown Partner";
315
                String storeCode = fofoStore != null ? fofoStore.getCode() : "Unknown Code";
316
 
317
                String displayName = partnerName + " (" + storeCode + ")";
318
                fofoNameMap.put(fofoId, displayName);
319
            }
320
        }
321
 
322
        // Map RBM ID to name for quick lookup
323
        Map<Integer, String> rbmNameMap = authUsers.stream()
324
                .collect(Collectors.toMap(AuthUser::getId, AuthUser::getFullName));
325
 
36113 ranu 326
        // Calculate RBM statistics: average rating and unique partner count
327
        Map<Integer, List<RbmRating>> feedbackByRbm = feedbackList.stream()
328
                .collect(Collectors.groupingBy(RbmRating::getRbmId));
329
 
330
        List<RbmWeeklyStats> rbmStatsList = new ArrayList<>();
331
        for (Map.Entry<Integer, List<RbmRating>> entry : feedbackByRbm.entrySet()) {
332
            int rbmId = entry.getKey();
333
            List<RbmRating> ratings = entry.getValue();
334
 
335
            double avgRating = ratings.stream()
336
                    .mapToInt(RbmRating::getRating)
337
                    .average()
338
                    .orElse(0.0);
339
 
340
            long uniquePartnerCount = ratings.stream()
341
                    .map(RbmRating::getFofoId)
342
                    .distinct()
343
                    .count();
344
 
345
            String rbmName = rbmNameMap.getOrDefault(rbmId, "Unknown RBM");
346
            rbmStatsList.add(new RbmWeeklyStats(rbmId, rbmName, avgRating, (int) uniquePartnerCount));
347
        }
348
 
349
        // Find max partner count for normalization
350
        int maxPartnerCount = rbmStatsList.stream()
351
                .mapToInt(RbmWeeklyStats::getPartnerCount)
352
                .max()
353
                .orElse(1);
354
 
355
        // Calculate combined score: 65% partner count + 35% rating
356
        // Score = (0.65 × partnerCount/maxPartnerCount) + (0.35 × avgRating/5)
357
        for (RbmWeeklyStats stats : rbmStatsList) {
358
            double partnerScore = (double) stats.getPartnerCount() / maxPartnerCount;
359
            double ratingScore = stats.getAvgRating() / 5.0;
360
            double combinedScore = (0.65 * partnerScore) + (0.35 * ratingScore);
361
            stats.setCombinedScore(combinedScore);
362
        }
363
 
364
        // Sort by combined score DESC and assign rank
365
        rbmStatsList.sort((a, b) -> Double.compare(b.getCombinedScore(), a.getCombinedScore()));
366
        for (int i = 0; i < rbmStatsList.size(); i++) {
367
            rbmStatsList.get(i).setRank(i + 1);
368
        }
369
 
370
        // Create map for quick lookup of stats by RBM ID
371
        Map<Integer, RbmWeeklyStats> rbmStatsMap = rbmStatsList.stream()
372
                .collect(Collectors.toMap(RbmWeeklyStats::getRbmId, s -> s));
373
 
34321 ranu 374
        // Generate HTML content
375
        StringBuilder emailContent = new StringBuilder();
376
        emailContent.append("<html><body>");
377
        emailContent.append("<p>Dear Team,</p>");
36113 ranu 378
        emailContent.append("<p>Here is the <b>Weekly RBM Rating and Feedback Summary</b> for the week: <b>")
379
                .append(previousMonday.format(dateFormatter))
380
                .append(" to ")
381
                .append(previousSunday.format(dateFormatter))
382
                .append("</b></p>");
34321 ranu 383
 
36113 ranu 384
        // RBM Ranking Summary Table
385
        emailContent.append("<h3>RBM Weekly Rankings</h3>");
386
        emailContent.append("<p style='font-size: 12px; color: #666;'>Rank = 65% Partner Count + 35% Avg Rating</p>");
387
        emailContent.append("<table border='1' cellspacing='0' cellpadding='5' style='border-collapse: collapse;'>");
388
        emailContent.append("<tr style='background-color: #4CAF50; color: white;'>")
389
                .append("<th>Rank</th>")
34321 ranu 390
                .append("<th>RBM Name</th>")
36113 ranu 391
                .append("<th>Partner Count</th>")
392
                .append("<th>Avg Rating</th>")
393
                .append("<th>Score</th>")
394
                .append("</tr>");
395
 
396
        // Already sorted by rank (combined score DESC)
397
        for (RbmWeeklyStats stats : rbmStatsList) {
398
            emailContent.append("<tr>")
399
                    .append("<td style='text-align: center; font-weight: bold;'>").append(stats.getRank()).append("</td>")
400
                    .append("<td>").append(stats.getRbmName()).append("</td>")
401
                    .append("<td style='text-align: center;'>").append(stats.getPartnerCount()).append("</td>")
402
                    .append("<td style='text-align: center;'>").append(String.format("%.2f", stats.getAvgRating())).append("</td>")
403
                    .append("<td style='text-align: center;'>").append(String.format("%.2f", stats.getCombinedScore())).append("</td>")
404
                    .append("</tr>");
405
        }
406
        emailContent.append("</table>");
407
 
408
        // Detailed Feedback Table
409
        emailContent.append("<br><h3>Detailed Feedback</h3>");
410
        emailContent.append("<table border='1' cellspacing='0' cellpadding='5' style='border-collapse: collapse;'>");
411
        emailContent.append("<tr style='background-color: #2196F3; color: white;'>")
412
                .append("<th>RBM Name</th>")
413
                .append("<th>Rank</th>")
34321 ranu 414
                .append("<th>Partner Name</th>")
415
                .append("<th>Rating</th>")
416
                .append("<th>Comment</th>")
417
                .append("<th>Date</th>")
418
                .append("</tr>");
419
 
420
        for (RbmRating rating : feedbackList) {
36113 ranu 421
            int rbmId = rating.getRbmId();
422
            String rbmName = rbmNameMap.getOrDefault(rbmId, "Unknown RBM");
34321 ranu 423
            String partnerName = fofoNameMap.getOrDefault(rating.getFofoId(), "Unknown Partner");
36113 ranu 424
            RbmWeeklyStats stats = rbmStatsMap.get(rbmId);
425
 
34321 ranu 426
            emailContent.append("<tr>")
427
                    .append("<td>").append(rbmName).append("</td>")
36113 ranu 428
                    .append("<td style='text-align: center; font-weight: bold;'>").append(stats != null ? stats.getRank() : "-").append("</td>")
34321 ranu 429
                    .append("<td>").append(partnerName).append("</td>")
36113 ranu 430
                    .append("<td style='text-align: center;'>").append(rating.getRating()).append("</td>")
34321 ranu 431
                    .append("<td>").append(rating.getComment() != null ? rating.getComment() : "-").append("</td>")
432
                    .append("<td>").append(rating.getCreateTimeStamp().toLocalDate()).append("</td>")
433
                    .append("</tr>");
434
        }
435
 
436
        emailContent.append("</table>");
437
        emailContent.append("<br><p>Regards,<br>Smart Dukaan Team</p>");
438
        emailContent.append("</body></html>");
439
 
36113 ranu 440
        String subject = "Weekly RBM Feedback Summary - " + previousMonday.format(dateFormatter) + " to " + previousSunday.format(dateFormatter);
34321 ranu 441
 
442
        List<String> sendTo = new ArrayList<>();
36113 ranu 443
        sendTo.add("sm@smartdukaan.com");
444
        sendTo.add("chiranjib.sarkar@smartdukaan.com");
445
        sendTo.add("kamini.sharma@smartdukaan.com");
34321 ranu 446
 
447
        String[] emailRecipients = sendTo.toArray(new String[0]);
448
 
449
        this.sendMailHtmlFormat(emailRecipients, emailContent.toString(), null, bcc, subject);
450
 
36113 ranu 451
        LOGGER.info("Weekly RBM feedback summary email sent for week: {} to {}", previousMonday, previousSunday);
34321 ranu 452
    }
453
 
36113 ranu 454
    // Inner class to hold RBM weekly statistics
455
    private static class RbmWeeklyStats {
456
        private final int rbmId;
457
        private final String rbmName;
458
        private final double avgRating;
459
        private final int partnerCount;
460
        private double combinedScore;
461
        private int rank;
34321 ranu 462
 
36113 ranu 463
        public RbmWeeklyStats(int rbmId, String rbmName, double avgRating, int partnerCount) {
464
            this.rbmId = rbmId;
465
            this.rbmName = rbmName;
466
            this.avgRating = avgRating;
467
            this.partnerCount = partnerCount;
468
        }
469
 
470
        public int getRbmId() { return rbmId; }
471
        public String getRbmName() { return rbmName; }
472
        public double getAvgRating() { return avgRating; }
473
        public int getPartnerCount() { return partnerCount; }
474
        public double getCombinedScore() { return combinedScore; }
475
        public void setCombinedScore(double combinedScore) { this.combinedScore = combinedScore; }
476
        public int getRank() { return rank; }
477
        public void setRank(int rank) { this.rank = rank; }
478
    }
479
 
480
 
34321 ranu 481
    public void sendSalesFeedbackSummaryEmail() throws MessagingException, ProfitMandiBusinessException, IOException {
36113 ranu 482
        // Weekly date range: Previous Monday to Sunday
483
        LocalDate today = LocalDate.now();
484
        LocalDate previousMonday = today.with(TemporalAdjusters.previous(DayOfWeek.MONDAY));
485
        LocalDate previousSunday = previousMonday.plusDays(6);
486
        LocalDateTime startOfWeek = previousMonday.atStartOfDay();
487
        LocalDateTime endOfWeek = previousSunday.atTime(23, 59, 59);
488
 
34323 ranu 489
        String[] bcc = {"tarun.verma@smartdukaan.com"};
36113 ranu 490
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("dd-MMM-yyyy");
34321 ranu 491
 
34903 ranu 492
        // Get all Sales users
34321 ranu 493
        List<AuthUser> authUsers = csService.getAuthUserIds(
494
                ProfitMandiConstants.TICKET_CATEGORY_SALES,
495
                Arrays.asList(EscalationType.L1)
496
        );
497
 
498
        if (authUsers.isEmpty()) {
499
            LOGGER.info("No sales person found.");
500
            return;
501
        }
502
 
503
        List<Integer> salesL1Ids = authUsers.stream().map(AuthUser::getId).collect(Collectors.toList());
504
 
36113 ranu 505
        // Fetch ratings for all Sales L1 for the week
506
        List<SalesRating> feedbackList = salesRatingRepository.selectBySalesL1IdsAndDateRange(salesL1Ids, startOfWeek, endOfWeek);
34321 ranu 507
 
508
        if (feedbackList.isEmpty()) {
36113 ranu 509
            LOGGER.info("No feedback entries found for Sales for the week.");
34321 ranu 510
            return;
511
        }
512
 
513
        // Sort feedback by createTimeStamp DESC
514
        feedbackList.sort((a, b) -> b.getCreateTimeStamp().compareTo(a.getCreateTimeStamp()));
515
 
516
        // Fetch and map FOFO (partner) names
517
        Map<Integer, String> fofoNameMap = new HashMap<>();
518
        for (SalesRating rating : feedbackList) {
519
            int fofoId = rating.getFofoId();
520
            if (!fofoNameMap.containsKey(fofoId)) {
521
                User fofoUser = userRepository.selectById(fofoId);
522
                FofoStore fofoStore = fofoStoreRepository.selectByRetailerId(fofoId);
523
 
524
                String partnerName = fofoUser != null ? fofoUser.getName() : "Unknown Partner";
525
                String storeCode = fofoStore != null ? fofoStore.getCode() : "Unknown Code";
526
 
527
                String displayName = partnerName + " (" + storeCode + ")";
528
                fofoNameMap.put(fofoId, displayName);
529
            }
530
        }
531
 
36113 ranu 532
        // Map Sales L1 ID to name for quick lookup
34321 ranu 533
        Map<Integer, String> salesL1NameMap = authUsers.stream()
534
                .collect(Collectors.toMap(AuthUser::getId, AuthUser::getFullName));
535
 
36113 ranu 536
        // Calculate Sales L1 statistics: average rating and unique partner count
537
        Map<Integer, List<SalesRating>> feedbackBySales = feedbackList.stream()
538
                .collect(Collectors.groupingBy(SalesRating::getSalesL1Id));
539
 
540
        List<SalesWeeklyStats> salesStatsList = new ArrayList<>();
541
        for (Map.Entry<Integer, List<SalesRating>> entry : feedbackBySales.entrySet()) {
542
            int salesL1Id = entry.getKey();
543
            List<SalesRating> ratings = entry.getValue();
544
 
545
            double avgRating = ratings.stream()
546
                    .mapToInt(SalesRating::getRating)
547
                    .average()
548
                    .orElse(0.0);
549
 
550
            long uniquePartnerCount = ratings.stream()
551
                    .map(SalesRating::getFofoId)
552
                    .distinct()
553
                    .count();
554
 
555
            String salesL1Name = salesL1NameMap.getOrDefault(salesL1Id, "Unknown Sales Person");
556
            salesStatsList.add(new SalesWeeklyStats(salesL1Id, salesL1Name, avgRating, (int) uniquePartnerCount));
557
        }
558
 
559
        // Find max partner count for normalization
560
        int maxPartnerCount = salesStatsList.stream()
561
                .mapToInt(SalesWeeklyStats::getPartnerCount)
562
                .max()
563
                .orElse(1);
564
 
565
        // Calculate combined score: 65% partner count + 35% rating
566
        // Score = (0.65 × partnerCount/maxPartnerCount) + (0.35 × avgRating/5)
567
        for (SalesWeeklyStats stats : salesStatsList) {
568
            double partnerScore = (double) stats.getPartnerCount() / maxPartnerCount;
569
            double ratingScore = stats.getAvgRating() / 5.0;
570
            double combinedScore = (0.65 * partnerScore) + (0.35 * ratingScore);
571
            stats.setCombinedScore(combinedScore);
572
        }
573
 
574
        // Sort by combined score DESC and assign rank
575
        salesStatsList.sort((a, b) -> Double.compare(b.getCombinedScore(), a.getCombinedScore()));
576
        for (int i = 0; i < salesStatsList.size(); i++) {
577
            salesStatsList.get(i).setRank(i + 1);
578
        }
579
 
580
        // Create map for quick lookup of stats by Sales L1 ID
581
        Map<Integer, SalesWeeklyStats> salesStatsMap = salesStatsList.stream()
582
                .collect(Collectors.toMap(SalesWeeklyStats::getSalesL1Id, s -> s));
583
 
34321 ranu 584
        // Generate HTML content
585
        StringBuilder emailContent = new StringBuilder();
586
        emailContent.append("<html><body>");
587
        emailContent.append("<p>Dear Team,</p>");
36113 ranu 588
        emailContent.append("<p>Here is the <b>Weekly Sales L1 Rating and Feedback Summary</b> for the week: <b>")
589
                .append(previousMonday.format(dateFormatter))
590
                .append(" to ")
591
                .append(previousSunday.format(dateFormatter))
592
                .append("</b></p>");
34321 ranu 593
 
36113 ranu 594
        // Sales L1 Ranking Summary Table
595
        emailContent.append("<h3>Sales L1 Weekly Rankings</h3>");
596
        emailContent.append("<p style='font-size: 12px; color: #666;'>Rank = 65% Partner Count + 35% Avg Rating</p>");
597
        emailContent.append("<table border='1' cellspacing='0' cellpadding='5' style='border-collapse: collapse;'>");
598
        emailContent.append("<tr style='background-color: #4CAF50; color: white;'>")
599
                .append("<th>Rank</th>")
34321 ranu 600
                .append("<th>Sales L1 Name</th>")
36113 ranu 601
                .append("<th>Partner Count</th>")
602
                .append("<th>Avg Rating</th>")
603
                .append("<th>Score</th>")
604
                .append("</tr>");
605
 
606
        // Already sorted by rank (combined score DESC)
607
        for (SalesWeeklyStats stats : salesStatsList) {
608
            emailContent.append("<tr>")
609
                    .append("<td style='text-align: center; font-weight: bold;'>").append(stats.getRank()).append("</td>")
610
                    .append("<td>").append(stats.getSalesL1Name()).append("</td>")
611
                    .append("<td style='text-align: center;'>").append(stats.getPartnerCount()).append("</td>")
612
                    .append("<td style='text-align: center;'>").append(String.format("%.2f", stats.getAvgRating())).append("</td>")
613
                    .append("<td style='text-align: center;'>").append(String.format("%.2f", stats.getCombinedScore())).append("</td>")
614
                    .append("</tr>");
615
        }
616
        emailContent.append("</table>");
617
 
618
        // Detailed Feedback Table
619
        emailContent.append("<br><h3>Detailed Feedback</h3>");
620
        emailContent.append("<table border='1' cellspacing='0' cellpadding='5' style='border-collapse: collapse;'>");
621
        emailContent.append("<tr style='background-color: #2196F3; color: white;'>")
622
                .append("<th>Sales L1 Name</th>")
623
                .append("<th>Rank</th>")
34321 ranu 624
                .append("<th>Partner Name</th>")
34411 tejus.loha 625
                .append("<th>Partner Category</th>")
34321 ranu 626
                .append("<th>Rating</th>")
627
                .append("<th>Comment</th>")
628
                .append("<th>Date</th>")
629
                .append("</tr>");
630
 
631
        for (SalesRating rating : feedbackList) {
36113 ranu 632
            int salesL1Id = rating.getSalesL1Id();
633
            String salesL1Name = salesL1NameMap.getOrDefault(salesL1Id, "Unknown Sales Person");
34321 ranu 634
            String partnerName = fofoNameMap.getOrDefault(rating.getFofoId(), "Unknown Partner");
36113 ranu 635
            SalesWeeklyStats stats = salesStatsMap.get(salesL1Id);
34411 tejus.loha 636
            PartnerType partnerType = partnerTypeChangeService.getTypeOnDate(rating.getFofoId(), LocalDate.now());
36113 ranu 637
 
34321 ranu 638
            emailContent.append("<tr>")
36113 ranu 639
                    .append("<td>").append(salesL1Name).append("</td>")
640
                    .append("<td style='text-align: center; font-weight: bold;'>").append(stats != null ? stats.getRank() : "-").append("</td>")
34321 ranu 641
                    .append("<td>").append(partnerName).append("</td>")
34411 tejus.loha 642
                    .append("<td>").append(partnerType).append("</td>")
36113 ranu 643
                    .append("<td style='text-align: center;'>").append(rating.getRating()).append("</td>")
34321 ranu 644
                    .append("<td>").append(rating.getComment() != null ? rating.getComment() : "-").append("</td>")
645
                    .append("<td>").append(rating.getCreateTimeStamp().toLocalDate()).append("</td>")
646
                    .append("</tr>");
647
        }
648
 
649
        emailContent.append("</table>");
36113 ranu 650
        emailContent.append("<br><p>Regards,<br>Smart Dukaan Team</p>");
34321 ranu 651
        emailContent.append("</body></html>");
652
 
36113 ranu 653
        String subject = "Weekly Sales L1 Feedback Summary - " + previousMonday.format(dateFormatter) + " to " + previousSunday.format(dateFormatter);
34321 ranu 654
 
655
        List<String> sendTo = new ArrayList<>();
36113 ranu 656
        sendTo.add("sm@smartdukaan.com");
657
        sendTo.add("chiranjib.sarkar@smartdukaan.com");
658
        sendTo.add("kamini.sharma@smartdukaan.com");
34321 ranu 659
 
660
        String[] emailRecipients = sendTo.toArray(new String[0]);
661
 
662
        this.sendMailHtmlFormat(emailRecipients, emailContent.toString(), null, bcc, subject);
663
 
36113 ranu 664
        LOGGER.info("Weekly Sales L1 feedback summary email sent for week: {} to {}", previousMonday, previousSunday);
34321 ranu 665
    }
666
 
36113 ranu 667
    // Inner class to hold Sales L1 weekly statistics
668
    private static class SalesWeeklyStats {
669
        private final int salesL1Id;
670
        private final String salesL1Name;
671
        private final double avgRating;
672
        private final int partnerCount;
673
        private double combinedScore;
674
        private int rank;
675
 
676
        public SalesWeeklyStats(int salesL1Id, String salesL1Name, double avgRating, int partnerCount) {
677
            this.salesL1Id = salesL1Id;
678
            this.salesL1Name = salesL1Name;
679
            this.avgRating = avgRating;
680
            this.partnerCount = partnerCount;
681
        }
682
 
683
        public int getSalesL1Id() { return salesL1Id; }
684
        public String getSalesL1Name() { return salesL1Name; }
685
        public double getAvgRating() { return avgRating; }
686
        public int getPartnerCount() { return partnerCount; }
687
        public double getCombinedScore() { return combinedScore; }
688
        public void setCombinedScore(double combinedScore) { this.combinedScore = combinedScore; }
689
        public int getRank() { return rank; }
690
        public void setRank(int rank) { this.rank = rank; }
691
    }
692
 
34912 ranu 693
    public Map<String, Set<Integer>> generateBiReportHierarchyWise() throws Exception{
694
        List<Integer> categoryIds = Arrays.asList(ProfitMandiConstants.TICKET_CATEGORY_RBM, ProfitMandiConstants.TICKET_CATEGORY_SALES,ProfitMandiConstants.TICKET_CATEGORY_ABM,ProfitMandiConstants.TICKET_CATEGORY_BUSINESSINTELLIGENT);
695
        Map<String, Set<Integer>> storeGuyEntry = csService.getAuthUserPartnerIdMappingByCategoryIds(categoryIds, false);
696
        return storeGuyEntry;
34911 ranu 697
    }
698
 
699
 
700
 
34912 ranu 701
    public void generateBiReportExcel() throws Exception {
34911 ranu 702
 
34741 ranu 703
        LocalDateTime startOfToday;
704
        LocalDateTime previousDay;
34321 ranu 705
 
34741 ranu 706
        if (LocalDate.now().getDayOfMonth() == 1) {
707
            // If today is 1st, go to yesterday (i.e., last day of previous month)
708
            startOfToday = LocalDate.now().minusDays(1).atStartOfDay();
709
            previousDay = startOfToday.with(LocalTime.MAX);
710
 
711
        } else {
712
            // Otherwise, use today
713
            startOfToday = LocalDate.now().atStartOfDay();
714
            previousDay = startOfToday.with(LocalTime.MAX).minusDays(1);
715
        }
716
 
35239 ranu 717
        Map<Integer, CustomRetailer> customRetailers = retailerService.getAllFofoRetailersInternalFalse();
34912 ranu 718
 
35239 ranu 719
        List<Integer> retailerIds = customRetailers.values().stream()
34903 ranu 720
                .filter(retailer -> {
721
                    String storeCode = retailer.getCode(); // adjust method name if different
722
                    return !storeCode.equalsIgnoreCase("UPGBN640") && !storeCode.equalsIgnoreCase("HRYN039");
723
                })
724
                .map(CustomRetailer::getPartnerId)
35239 ranu 725
                .collect(Collectors.toList());
34606 ranu 726
 
35239 ranu 727
//        List<Integer> retailerIds = Arrays.asList(175139993,175139441,175139442,175140143,175140146);
728
//        Map<Integer,CustomRetailer> customRetailers = retailerService.getFofoRetailers(retailerIds);
34903 ranu 729
 
34641 ranu 730
        //partner daily investment
34729 amit.gupta 731
        List<Loan> defaultLoans = sdCreditService.getDefaultLoans();
34641 ranu 732
        Map<Integer,List<Loan>> defaultLoanMap = defaultLoans.stream().collect(Collectors.groupingBy(Loan::getFofoId));
34619 ranu 733
 
34641 ranu 734
        Map<Integer, PartnerDailyInvestment> partnerDailyInvestmentMap = new HashMap<>();
735
        List<PartnerDailyInvestment> partnerDailyInvestments = partnerDailyInvestmentRepository
34741 ranu 736
                .selectAll(new ArrayList<>(retailerIds), previousDay.toLocalDate());
34641 ranu 737
        if (!partnerDailyInvestments.isEmpty()) {
738
            partnerDailyInvestmentMap = partnerDailyInvestments.stream()
739
                    .collect(Collectors.toMap(x -> x.getFofoId(), x -> x));
740
        }
741
 
34648 ranu 742
    //  this month return data
34741 ranu 743
 
744
        YearMonth currentMonth;
745
        LocalDateTime currentMonthStartDate;
746
        LocalDateTime currentMonthEndDate;
747
 
748
        if (LocalDate.now().getDayOfMonth() == 1) {
749
            // If today is the 1st, use previous month
750
            currentMonth = YearMonth.now().minusMonths(1);
751
            currentMonthStartDate = currentMonth.atDay(1).atStartOfDay();
752
            currentMonthEndDate = currentMonth.atEndOfMonth().atTime(23, 59, 59);
753
        } else {
754
            // Otherwise, use this month up to yesterday
755
            currentMonth = YearMonth.now();
756
            currentMonthStartDate = currentMonth.atDay(1).atStartOfDay();
757
            currentMonthEndDate = LocalDate.now().minusDays(1).atTime(23, 59, 59);
758
        }
759
 
34619 ranu 760
        String currentMonthStringValue = String.valueOf(currentMonth);
34606 ranu 761
 
762
        List<ReturnOrderInfoModel> currentMonthReturnOrderInfoModels = returnOrderInfoRepository.selectAllByBetweenDate(currentMonthStartDate, currentMonthEndDate);
763
        Map<Integer, Long> currentMonthPartnerReturnOrderInfoModelMap = currentMonthReturnOrderInfoModels.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getRefundAmount()))));
764
 
34782 ranu 765
        List<Order> currentMonthRtoRefundOrders = orderRepository.selectAllRefundOrderDatesBetween(currentMonthStartDate, currentMonthEndDate);
34606 ranu 766
        Map<Integer, Long> currentMonthRtoRefundOrderMap = currentMonthRtoRefundOrders.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getTotalAmount()))));
767
 
34749 ranu 768
 
769
        List<ReturnOrderInfoModel> yesterdayReturnOrderInfoModels = returnOrderInfoRepository.selectAllByBetweenDate(previousDay.toLocalDate().atStartOfDay(), previousDay);
770
        Map<Integer, Long> yesterdayReturnOrderInfoModelMap = yesterdayReturnOrderInfoModels.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getRefundAmount()))));
771
 
34782 ranu 772
        List<Order> yesterdayRtoRefundOrders = orderRepository.selectAllRefundOrderDatesBetween(previousDay.toLocalDate().atStartOfDay(), previousDay);
34749 ranu 773
        Map<Integer, Long> yesterdayRtoRefundOrderMap = yesterdayRtoRefundOrders.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getTotalAmount()))));
774
 
775
        List<ReturnOrderInfoModel> dayBeforeYesterdayReturnOrderInfoModels = returnOrderInfoRepository.selectAllByBetweenDate(previousDay.toLocalDate().atStartOfDay().minusDays(1), previousDay.minusDays(1));
776
        Map<Integer, Long> dayBeforeYesterdayReturnOrderInfoModelMap = dayBeforeYesterdayReturnOrderInfoModels.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getRefundAmount()))));
777
 
34782 ranu 778
        List<Order> dayBeforeYesterdayRtoRefundOrders = orderRepository.selectAllRefundOrderDatesBetween(previousDay.toLocalDate().atStartOfDay().minusDays(1), previousDay.minusDays(1));
34749 ranu 779
        Map<Integer, Long> dayBeforeYesterdayRtoRefundOrderMap = dayBeforeYesterdayRtoRefundOrders.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getTotalAmount()))));
780
 
781
 
782
 
783
        //  last month return data
34741 ranu 784
        YearMonth lastMonth = currentMonth.minusMonths(1);
34619 ranu 785
        String lastMonthStringValue = String.valueOf(lastMonth);
34606 ranu 786
        LocalDateTime lastMontStartDate = lastMonth.atDay(1).atStartOfDay();
787
        LocalDateTime lastMonthEndDate = lastMonth.atEndOfMonth().atTime(23, 59, 59);
788
 
789
        List<ReturnOrderInfoModel> lastMonthReturnOrderInfoModels = returnOrderInfoRepository.selectAllByBetweenDate(lastMontStartDate, lastMonthEndDate);
790
        Map<Integer, Long> lastMonthPartnerReturnOrderInfoModelMap = lastMonthReturnOrderInfoModels.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getRefundAmount()))));
791
 
34782 ranu 792
        List<Order> lastMonthRtoRefundOrders = orderRepository.selectAllRefundOrderDatesBetween(lastMontStartDate, lastMonthEndDate);
34606 ranu 793
        Map<Integer, Long> lastMonthRtoRefundOrderMap = lastMonthRtoRefundOrders.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getTotalAmount()))));
794
 
795
 
34741 ranu 796
    //  twoMonthsAgo return data
797
        YearMonth twoMonthsAgo = currentMonth.minusMonths(2);
34619 ranu 798
        String twoMonthAgoStringValue = String.valueOf(twoMonthsAgo);
34606 ranu 799
        LocalDateTime twoMonthsAgoStartDate = twoMonthsAgo.atDay(1).atStartOfDay();
800
        LocalDateTime twoMonthsAgoEndDate = twoMonthsAgo.atEndOfMonth().atTime(23, 59, 59);
801
 
802
        List<ReturnOrderInfoModel> twoMonthAgoReturnOrderInfoModels = returnOrderInfoRepository.selectAllByBetweenDate(twoMonthsAgoStartDate, twoMonthsAgoEndDate);
803
        Map<Integer, Long> twoMonthAgoPartnerReturnOrderInfoModelMap = twoMonthAgoReturnOrderInfoModels.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getRefundAmount()))));
34749 ranu 804
 
34782 ranu 805
        List<Order> twoMonthRtoRefundOrders = orderRepository.selectAllRefundOrderDatesBetween(twoMonthsAgoStartDate, twoMonthsAgoEndDate);
34619 ranu 806
        Map<Integer, Long> twoMonthAgoRtoRefundOrderMap = twoMonthRtoRefundOrders.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getTotalAmount()))));
34606 ranu 807
 
34749 ranu 808
 
34648 ranu 809
        Map<Integer , String> assessmentMap = new HashMap<>();
810
        Map<Integer , String> zeroBillingMap = new HashMap<>();
811
        Map<Integer , Float> billingNeededMap = new HashMap<>();
812
        Map<Integer , Integer> countAMap = new HashMap<>();
34606 ranu 813
 
34619 ranu 814
        Map<Integer , BIRetailerModel> biRetailerModelMap = new HashMap<>();
34606 ranu 815
 
34641 ranu 816
        Map<Integer , FofoInvestmentModel> biInvestmentModelMap = new HashMap<>();
817
 
34619 ranu 818
        Map<Integer, Map<YearMonth, BiSecondaryModel>> allRetailerMonthlyData = new HashMap<>();
34606 ranu 819
 
34619 ranu 820
        Map<Integer,Double> fofoTotalStockPriceMap = new HashMap<>();
821
 
822
        Map<Integer,Map<String, BrandStockPrice>> fofoBrandStockPriceMap = new HashMap<>();
823
 
34641 ranu 824
        Map<Integer,Long> fofoTotalMtdSecondaryMap = new HashMap<>();
34619 ranu 825
 
34749 ranu 826
        Map<Integer,Long> fofoYesterdaySecondaryMap = new HashMap<>();
34619 ranu 827
 
34749 ranu 828
        Map<Integer,Long> fofoDayBeforeYesterdaySecondaryMap = new HashMap<>();
829
 
34641 ranu 830
        Map<Integer,Map<String, Long>> fofoBrandWiseMtdSecondaryMap = new HashMap<>();
34619 ranu 831
 
34641 ranu 832
        Map<Integer,Double> fofoTotalMtdTertiaryMap = new HashMap<>();
833
 
834
        Map<Integer,Map<String, Double>> fofoBrandMtdTertiaryMap = new HashMap<>();
835
 
34606 ranu 836
        for(Integer fofoId: retailerIds){
34619 ranu 837
            String rbmName = "";
34920 ranu 838
            int rbmL1 = csService.getAuthUserIdWithoutTicketAssignee(ProfitMandiConstants.TICKET_CATEGORY_RBM,EscalationType.L1,fofoId);
34619 ranu 839
            if(rbmL1 != 0){
840
                 rbmName = authRepository.selectById(rbmL1).getFullName();
34677 ranu 841
            }else {
34920 ranu 842
                int rbmL2 = csService.getAuthUserIdWithoutTicketAssignee(ProfitMandiConstants.TICKET_CATEGORY_RBM, EscalationType.L2, fofoId);
34677 ranu 843
                if(rbmL2 != 0){
844
                    rbmName = authRepository.selectById(rbmL2).getFullName();
845
                }
34619 ranu 846
            }
847
            String bmName ="";
34920 ranu 848
            int bmId = csService.getAuthUserIdWithoutTicketAssignee(ProfitMandiConstants.TICKET_CATEGORY_SALES,EscalationType.L2,fofoId);
34619 ranu 849
            if(bmId !=0){
850
                bmName = authRepository.selectById(bmId).getFullName();
851
            }
34606 ranu 852
 
34920 ranu 853
            int managerId = csService.getAuthUserIdWithoutTicketAssignee(ProfitMandiConstants.TICKET_CATEGORY_SALES,EscalationType.L1,fofoId);
34606 ranu 854
            String managerName = " ";
34919 ranu 855
            LOGGER.info("managerId {}",managerId);
34606 ranu 856
            if(managerId != 0){
857
                 managerName = authRepository.selectById(managerId).getFullName();
858
            }else {
859
                managerName = bmName;
860
            }
34915 ranu 861
            String abmName ="";
34920 ranu 862
            int abmId = csService.getAuthUserIdWithoutTicketAssignee(ProfitMandiConstants.TICKET_CATEGORY_ABM,EscalationType.L1,fofoId);
863
            int abmL2Id = csService.getAuthUserIdWithoutTicketAssignee(ProfitMandiConstants.TICKET_CATEGORY_ABM,EscalationType.L2,fofoId);
864
            int abmL3Id = csService.getAuthUserIdWithoutTicketAssignee(ProfitMandiConstants.TICKET_CATEGORY_ABM,EscalationType.L3,fofoId);
34915 ranu 865
            if(abmId !=0){
866
                abmName = authRepository.selectById(abmId).getFullName();
34918 ranu 867
            }else if(abmL2Id != 0){
34916 ranu 868
                abmName = authRepository.selectById(abmL2Id).getFullName();
34919 ranu 869
            }else if(abmL3Id != 0){
34918 ranu 870
                abmName = authRepository.selectById(abmL3Id).getFullName();
34915 ranu 871
            }
34606 ranu 872
            AST ast = astRepository.selectById(customRetailers.get(fofoId).getAstId());
873
 
34927 ranu 874
            LOGGER.info("fofoID--11 {}",fofoId);
36028 ranu 875
            PartnerType partnerTypeThisMonth = partnerTypeChangeService.getTypeOnDate(fofoId, LocalDate.now());
34606 ranu 876
 
877
//            generate retaile detail
878
 
879
            BIRetailerModel biRetailerModel = new BIRetailerModel();
880
            biRetailerModel.setBmName(bmName);
881
            biRetailerModel.setCode(customRetailers.get(fofoId).getCode());
34619 ranu 882
            if(ast != null){
883
                biRetailerModel.setArea(ast.getArea());
884
            }else {
885
                biRetailerModel.setArea("-");
886
            }
34738 ranu 887
            String retailerStatus = "";
888
            FofoStore fofoStore1 = fofoStoreRepository.selectByRetailerId(fofoId);
889
            if(!fofoStore1.isActive()){
890
                retailerStatus = "INACTIVE";
891
            }else{
892
                retailerStatus =  String.valueOf(fofoStore1.getActivationType());
893
            }
34606 ranu 894
            biRetailerModel.setCity(customRetailers.get(fofoId).getAddress().getCity());
895
            biRetailerModel.setStoreName(customRetailers.get(fofoId).getBusinessName());
34738 ranu 896
            biRetailerModel.setStatus(retailerStatus);
34606 ranu 897
            biRetailerModel.setCategory(String.valueOf(partnerTypeThisMonth));
898
            biRetailerModel.setSalesManager(managerName);
899
            biRetailerModel.setRbm(rbmName);
34915 ranu 900
            biRetailerModel.setAbm(abmName);
34606 ranu 901
 
34619 ranu 902
            biRetailerModelMap.put(fofoId,biRetailerModel);
903
 
34641 ranu 904
 
34606 ranu 905
//            generate secondary data
906
 
34641 ranu 907
            List<PartnerWiseActivatedNotBilledTotal> partnerWiseActivatedNotBilledMonthlyTotals = activatedImeiRepository.getTotalMonthlyActivatedNotBilled(fofoId,twoMonthsAgoStartDate);
908
            Map<YearMonth , PartnerWiseActivatedNotBilledTotal> partnerWiseActivatedNotBilledTotalMap = partnerWiseActivatedNotBilledMonthlyTotals.stream().collect(Collectors.toMap(x-> YearMonth.parse(x.getYearMonth()),x->x));
909
 
34606 ranu 910
//            this month secondary target
911
 
34741 ranu 912
            double currentSecondaryTarget =  monthlyTargetRepository.selectByDateAndFofoId(currentMonth, fofoId) != null ? monthlyTargetRepository.selectByDateAndFofoId(currentMonth, fofoId).getPurchaseTarget() : 0;
34606 ranu 913
 
34619 ranu 914
 
915
            long currentMonthReturn = currentMonthPartnerReturnOrderInfoModelMap.getOrDefault(fofoId, 0L) + currentMonthRtoRefundOrderMap.getOrDefault(fofoId, 0L);
916
 
917
 
34715 ranu 918
            Map<Integer, Double> secondaryMtd = orderRepository.selectOrderValueBetweenBillingDatesGroupByFofoId(Arrays.asList(fofoId),
34741 ranu 919
                    startOfToday.withDayOfMonth(1), previousDay).stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getAmount()));
34606 ranu 920
 
34749 ranu 921
 
922
            //yesterday secondary
923
            Map<Integer, Double> dayBeforeYesterdaySecondary = orderRepository.selectOrderValueBetweenBillingDatesGroupByFofoId(Arrays.asList(fofoId),
924
                    previousDay.toLocalDate().atStartOfDay().minusDays(1), previousDay.minusDays(1)).stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getAmount()));
925
            double dayBeforeYesterdayAfterReturnSecondary = dayBeforeYesterdaySecondary.getOrDefault(fofoId,0d) - (dayBeforeYesterdayReturnOrderInfoModelMap.getOrDefault(fofoId,0l) + dayBeforeYesterdayRtoRefundOrderMap.getOrDefault(fofoId,0l));
926
            fofoDayBeforeYesterdaySecondaryMap.put(fofoId, (long) dayBeforeYesterdayAfterReturnSecondary);
927
 
928
 
929
            //day before secondary
930
            Map<Integer, Double> yesterDaySecondary = orderRepository.selectOrderValueBetweenBillingDatesGroupByFofoId(Arrays.asList(fofoId),
931
                    previousDay.toLocalDate().atStartOfDay(), previousDay).stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getAmount()));
932
            double yesterDayAfterReturnSecondary = yesterDaySecondary.getOrDefault(fofoId,0d) - (yesterdayReturnOrderInfoModelMap.getOrDefault(fofoId,0l) + yesterdayRtoRefundOrderMap.getOrDefault(fofoId,0l));
933
            fofoYesterdaySecondaryMap.put(fofoId, (long) yesterDayAfterReturnSecondary);
934
 
34606 ranu 935
            double secondaryAchievedMtd = secondaryMtd.getOrDefault(fofoId, 0.0);
936
 
34619 ranu 937
            double currentMonthNetSecondary = secondaryAchievedMtd - currentMonthReturn;
34606 ranu 938
 
34701 ranu 939
            double currentMonthSecondaryPercent = currentSecondaryTarget == 0 ? 0.0 : Math.round(Math.abs((secondaryAchievedMtd / currentSecondaryTarget) * 100));
34619 ranu 940
 
34641 ranu 941
            double currentMonthUnbilled = partnerWiseActivatedNotBilledTotalMap.get(currentMonth) != null ? partnerWiseActivatedNotBilledTotalMap.get(currentMonth).getTotalUnbilledAmount() : 0d;
34619 ranu 942
 
943
//          this month tertiary----------
944
 
945
            LocalDateTime now = LocalDateTime.now();
946
            double todaySale = fofoOrderItemRepository.selectSumMopGroupByRetailer(startOfToday, now, fofoId, false).get(fofoId);
34741 ranu 947
            double mtdSaleTillYesterDay = fofoOrderItemRepository.selectSumMopGroupByRetailer(startOfToday.withDayOfMonth(1), previousDay, fofoId, false).get(fofoId);
34724 ranu 948
            double mtdSale = mtdSaleTillYesterDay;
34619 ranu 949
 
950
 
34606 ranu 951
//            last month secondary target
952
 
34619 ranu 953
            double lastMonthSecondaryTarget = monthlyTargetRepository.selectByDateAndFofoId(lastMonth, fofoId) != null ?  monthlyTargetRepository.selectByDateAndFofoId(lastMonth, fofoId).getPurchaseTarget() : 0;
34606 ranu 954
 
34619 ranu 955
            long lastMonthReturn = (lastMonthPartnerReturnOrderInfoModelMap.getOrDefault(fofoId,0L) + lastMonthRtoRefundOrderMap.getOrDefault(fofoId,0L));
956
 
34715 ranu 957
            Map<Integer, Double> lastMonthSecondary = orderRepository.selectOrderValueBetweenBillingDatesGroupByFofoId(Arrays.asList(fofoId),
34606 ranu 958
                    lastMontStartDate, lastMonthEndDate).stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getAmount()));
959
 
960
            double lastMonthSecondaryAchieved = lastMonthSecondary.getOrDefault(fofoId, 0.0);
961
 
34619 ranu 962
            double lastMonthNetSecondary = lastMonthSecondaryAchieved - lastMonthReturn;
34606 ranu 963
 
34701 ranu 964
            double lastMonthSecondaryPercent = lastMonthSecondaryTarget == 0 ? 0.0 : Math.round(Math.abs((lastMonthSecondaryAchieved / lastMonthSecondaryTarget) * 100));
34606 ranu 965
 
34641 ranu 966
            double lastMonthUnbilled = partnerWiseActivatedNotBilledTotalMap.get(lastMonth) != null ? partnerWiseActivatedNotBilledTotalMap.get(lastMonth).getTotalUnbilledAmount() : 0d;
34606 ranu 967
 
34619 ranu 968
//           last month tertiary
969
            Double lastMonthSale = fofoOrderItemRepository.selectSumMopGroupByRetailer(
970
                    lastMontStartDate, lastMonthEndDate, fofoId, false).get(fofoId);
971
 
972
 
973
//            two month ago secondary target
974
 
34703 ranu 975
            double twoMonthAgoSecondaryTarget = monthlyTargetRepository.selectByDateAndFofoId(twoMonthsAgo, fofoId) != null ? monthlyTargetRepository.selectByDateAndFofoId(twoMonthsAgo, fofoId).getPurchaseTarget() : 0;
34619 ranu 976
 
977
            long twoMonthAgoReturn = (twoMonthAgoPartnerReturnOrderInfoModelMap.getOrDefault(fofoId,0L) + twoMonthAgoRtoRefundOrderMap.getOrDefault(fofoId,0L));
978
 
34715 ranu 979
            Map<Integer, Double> twoMonthAgoSecondary = orderRepository.selectOrderValueBetweenBillingDatesGroupByFofoId(Arrays.asList(fofoId),
34606 ranu 980
                    twoMonthsAgoStartDate, twoMonthsAgoEndDate).stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getAmount()));
981
 
982
            double twoMonthAgoSecondaryAchieved = twoMonthAgoSecondary.getOrDefault(fofoId, 0.0);
983
 
34619 ranu 984
            double twoMonthAgoNetSecondary = twoMonthAgoSecondaryAchieved - twoMonthAgoReturn;
34606 ranu 985
 
34701 ranu 986
            double twoMonthAgoSecondaryPercent = twoMonthAgoSecondaryTarget == 0 ? 0.0 : Math.round(Math.abs((twoMonthAgoSecondaryAchieved / twoMonthAgoSecondaryTarget) * 100));
34619 ranu 987
 
34641 ranu 988
            double twoMonthAgoUnbilled = partnerWiseActivatedNotBilledTotalMap.get(twoMonthsAgo) != null ? partnerWiseActivatedNotBilledTotalMap.get(twoMonthsAgo).getTotalUnbilledAmount() : 0d;
34619 ranu 989
 
990
//          second Month Tertiary
991
            double twoMonthAgoSale = fofoOrderItemRepository.selectSumMopGroupByRetailer(
992
                    twoMonthsAgoStartDate, twoMonthsAgoEndDate, fofoId, false).get(fofoId);
993
 
994
 
995
            Map<YearMonth, BiSecondaryModel> monthlySecondaryModels = new HashMap<>();
996
 
997
            BiSecondaryModel currentMonthSecondaryModel = new BiSecondaryModel(
998
                    currentSecondaryTarget,
999
                    secondaryAchievedMtd,
1000
                    currentMonthReturn,
1001
                    currentMonthNetSecondary,
1002
                    currentMonthSecondaryPercent,
1003
                    mtdSale,
1004
                    currentMonthUnbilled // for now, unbilled tertiary value
1005
            );
1006
 
1007
            BiSecondaryModel lastMonthSecondaryModel = new BiSecondaryModel(
1008
                    lastMonthSecondaryTarget,
1009
                    lastMonthSecondaryAchieved,
1010
                    lastMonthReturn,
1011
                    lastMonthNetSecondary,
1012
                    lastMonthSecondaryPercent,
1013
                    lastMonthSale,
1014
                    lastMonthUnbilled // for now, unbilled tertiary value
1015
            );
1016
 
1017
            BiSecondaryModel twoMonthAgoSecondaryModel = new BiSecondaryModel(
1018
                    twoMonthAgoSecondaryTarget,
1019
                    twoMonthAgoSecondaryAchieved,
1020
                    twoMonthAgoReturn,
1021
                    twoMonthAgoNetSecondary,
1022
                    twoMonthAgoSecondaryPercent,
1023
                    twoMonthAgoSale,
1024
                    twoMonthAgoUnbilled // for now, unbilled tertiary value
1025
            );
1026
 
1027
            monthlySecondaryModels.put(currentMonth, currentMonthSecondaryModel);
1028
            monthlySecondaryModels.put(lastMonth, lastMonthSecondaryModel);
1029
            monthlySecondaryModels.put(twoMonthsAgo, twoMonthAgoSecondaryModel);
1030
 
1031
            allRetailerMonthlyData.put(fofoId, monthlySecondaryModels);
1032
 
1033
//            brandwiseStock value price
1034
 
1035
            Map<String, BrandStockPrice> brandStockPriceMap = inventoryService.getBrandWiseStockValue(fofoId);
1036
 
1037
            fofoBrandStockPriceMap.put(fofoId,brandStockPriceMap);
1038
 
1039
            double totalStockPrice = brandStockPriceMap.values().stream().mapToDouble(x->x.getTotalValue()).sum();
1040
 
1041
            fofoTotalStockPriceMap.put(fofoId,totalStockPrice);
1042
 
1043
            Map<String, Double> brandMtdTertiaryAmount = fofoOrderItemRepository.selectSumAmountGroupByBrand(
34722 ranu 1044
                    currentMonthStartDate, currentMonthEndDate, fofoId);
34619 ranu 1045
 
34719 ranu 1046
 
34641 ranu 1047
            fofoBrandMtdTertiaryMap.put(fofoId,brandMtdTertiaryAmount);
34619 ranu 1048
 
1049
            double totalMtdTertiaryAmount = brandMtdTertiaryAmount.values().stream().mapToDouble(Double::doubleValue).sum();
1050
 
34641 ranu 1051
            fofoTotalMtdTertiaryMap.put(fofoId,totalMtdTertiaryAmount);
34619 ranu 1052
 
34849 ranu 1053
            List<BrandWiseModel> brandWiseMtdSecondary = orderRepository.selectAllBilledByCategoryOrderGroupByBrandFofoId(fofoId, currentMonthStartDate,currentMonthEndDate, Arrays.asList(10006,10001));
34641 ranu 1054
            Map<String,Long> brandWiseMtdSecondaryMap = brandWiseMtdSecondary.stream().collect(Collectors.toMap(BrandWiseModel::getBrand,BrandWiseModel::getAmount));
34619 ranu 1055
 
34730 ranu 1056
            //retrunInfo
1057
            List<BrandWiseReturnInfo> brandWiseReturnInfos = returnOrderInfoRepository.selectAllBrandWiseByBetweenDate(currentMonthStartDate,currentMonthEndDate.plusDays(1),fofoId);
1058
            Map<String,Double> brandWiseReturnInfoMap = brandWiseReturnInfos.stream().collect(Collectors.toMap(BrandWiseReturnInfo::getBrand, x->x.getReturnAmount()));
34619 ranu 1059
 
34730 ranu 1060
            LOGGER.info("brandWiseReturnInfos {}",brandWiseReturnInfos);
34758 ranu 1061
 
34730 ranu 1062
            //Rto retrunInfo
1063
            List<BrandWiseReturnInfo> brandWiseRTOReturnInfos = returnOrderInfoRepository.selectAllBrandWiseRTORefundByBetweenDate(currentMonthStartDate,currentMonthEndDate.plusDays(1),fofoId);
1064
            Map<String,Double> brandWiseRTOReturnInfoMap = brandWiseRTOReturnInfos.stream().collect(Collectors.toMap(BrandWiseReturnInfo::getBrand, x->x.getReturnAmount()));
1065
 
1066
            // Step 1: Get union of all brand keys
1067
            Set<String> allBrands = new HashSet<>();
1068
            allBrands.addAll(brandWiseMtdSecondaryMap.keySet());
1069
            allBrands.addAll(brandWiseReturnInfoMap.keySet());
1070
            allBrands.addAll(brandWiseRTOReturnInfoMap.keySet());
1071
 
1072
            // Step 2: Calculate net secondary for each brand
1073
            Map<String, Long> brandWiseMtdNetSecondaryMap = new HashMap<>();
1074
 
1075
            for (String brand : allBrands) {
1076
                Long billedAmount = brandWiseMtdSecondaryMap.getOrDefault(brand, 0L);
1077
                Double returnAmount = brandWiseReturnInfoMap.getOrDefault(brand, 0d);
1078
                Double rtoReturnAmount = brandWiseRTOReturnInfoMap.getOrDefault(brand, 0d);
1079
 
1080
                double netSecondary = billedAmount - (returnAmount + rtoReturnAmount);
1081
                brandWiseMtdNetSecondaryMap.put(brand, (long) Math.round(netSecondary));
1082
            }
1083
 
1084
 
1085
            LOGGER.info("brandWiseMtdNetSecondaryMap {}",brandWiseMtdNetSecondaryMap );
1086
 
1087
 
1088
            fofoBrandWiseMtdSecondaryMap.put(fofoId,brandWiseMtdNetSecondaryMap);
1089
 
1090
            long mtdTotalSecondary = brandWiseMtdNetSecondaryMap.values().stream().mapToLong(Long::longValue).sum();
1091
 
34641 ranu 1092
            fofoTotalMtdSecondaryMap.put(fofoId,mtdTotalSecondary);
1093
 
1094
            //            generate investment info
1095
            FofoStore fofoStore = fofoStoreRepository.selectByRetailerId(fofoId);
1096
            float shortInvestment = partnerDailyInvestmentMap.get(fofoId) != null ? partnerDailyInvestmentMap.get(fofoId).getShortInvestment() : 0f;
1097
            float agreedInvestment = partnerDailyInvestmentMap.get(fofoId) != null ? partnerDailyInvestmentMap.get(fofoId).getMinInvestment() : 0f;
34677 ranu 1098
            float investmentLevel = partnerDailyInvestmentMap.get(fofoId) != null
1099
                    ? Math.abs(((shortInvestment - agreedInvestment) / agreedInvestment) * 100)
1100
                    : 0f;
34641 ranu 1101
 
34677 ranu 1102
 
34641 ranu 1103
            List<Loan> fofoDefaultLoans = new ArrayList<>();
1104
            if(defaultLoanMap != null){
1105
                 fofoDefaultLoans  =  defaultLoanMap.get(fofoId);
1106
                LOGGER.info("fofoDefaultLoans {}",fofoDefaultLoans);
1107
            }
1108
 
1109
            float defaultLoanAmount = 0f;
1110
            if(fofoDefaultLoans != null ){
1111
                if (!fofoDefaultLoans.isEmpty()) {
34743 ranu 1112
                    for (Loan entry : fofoDefaultLoans) {
1113
 
1114
                        List<LoanStatement> loanStatements = loanStatementRepository.selectByLoanId(entry.getId());
1115
 
1116
                        double amount = loanStatements.stream().map(x -> x.getAmount()).collect(Collectors.summingDouble(x -> x.doubleValue()));
1117
 
1118
                        defaultLoanAmount += amount;
1119
                    }
34641 ranu 1120
                }
1121
            }
1122
 
34719 ranu 1123
            List<Loan> activeLoans = loanRepository.selectAllActiveLoan(fofoId);
34641 ranu 1124
 
34719 ranu 1125
            LOGGER.info("activeLoans- {}",activeLoans);
34641 ranu 1126
 
34743 ranu 1127
            float activeLoan = 0f;
34719 ranu 1128
 
34743 ranu 1129
            for (Loan entry : activeLoans) {
1130
 
1131
                List<LoanStatement> loanStatements = loanStatementRepository.selectByLoanId(entry.getId());
1132
 
1133
                double pendingAmount = loanStatements.stream().map(x -> x.getAmount()).collect(Collectors.summingDouble(x -> x.doubleValue()));
1134
 
1135
                activeLoan += pendingAmount;
1136
            }
1137
 
34641 ranu 1138
            float poValue = partnerDailyInvestmentMap.get(fofoId) != null ?  partnerDailyInvestmentMap.get(fofoId).getUnbilledAmount() : 0f;
1139
 
34719 ranu 1140
            float poAndBilledValue = (float) (currentMonthNetSecondary + poValue);
34641 ranu 1141
 
34741 ranu 1142
            double monthDay1Drr = rbmTargetService.calculateFofoIdTodayTarget(fofoId,0d,currentMonth.atDay(1));
34897 ranu 1143
            double todayRequiredDrr = 0;
34641 ranu 1144
 
34897 ranu 1145
            if(monthDay1Drr != 0d){
1146
                todayRequiredDrr = rbmTargetService.calculateFofoIdTodayTarget(fofoId, currentMonthNetSecondary,startOfToday.toLocalDate());
1147
            }
34641 ranu 1148
 
1149
            double gotDrrPercent = (todayRequiredDrr / monthDay1Drr) * 100;
1150
 
34701 ranu 1151
            long drrPercentDisplay = Math.round(Math.abs(gotDrrPercent));
1152
 
1153
 
34641 ranu 1154
            int orderId = orderRepository.getLastOrderByFofoId(fofoId);
1155
 
34644 ranu 1156
            // Determine alert level
1157
            String alertLevel = "-";
1158
            int lastPurchaseDays = 0;
34641 ranu 1159
            if (orderId != 0) {
1160
                Order order = orderRepository.selectById(orderId);
1161
 
34715 ranu 1162
                LOGGER.info("last billing order - {}",order);
1163
 
34641 ranu 1164
                // Calculate the number of days since the last purchase (billing)
34644 ranu 1165
                lastPurchaseDays = (int) Duration.between(order.getCreateTimestamp().plusDays(1), LocalDateTime.now()).toDays();
34641 ranu 1166
 
1167
                if (lastPurchaseDays >= 11) {
1168
                    alertLevel = "Alert for Management";
34676 ranu 1169
                } else if (lastPurchaseDays >= 10) {
34641 ranu 1170
                    alertLevel = " Alert for RSM/SH";
34676 ranu 1171
                } else if (lastPurchaseDays >= 7) {
34641 ranu 1172
                    alertLevel = "Must be Billed";
1173
                } else if (lastPurchaseDays >= 3) {
1174
                    alertLevel = "OK";
1175
                } else {
34676 ranu 1176
                    alertLevel = "OK";
34641 ranu 1177
                }
34644 ranu 1178
            }
34641 ranu 1179
 
34644 ranu 1180
            //investment modal set all related value
1181
            FofoInvestmentModel fofoInvestmentModel = new FofoInvestmentModel();
34641 ranu 1182
 
34644 ranu 1183
            fofoInvestmentModel.setCounterPotential(fofoStore.getCounterPotential());
1184
            fofoInvestmentModel.setShortInvestment(shortInvestment);
1185
            fofoInvestmentModel.setDefaultLoan(defaultLoanAmount);
1186
            fofoInvestmentModel.setInvestmentLevel(investmentLevel);
1187
            fofoInvestmentModel.setActiveLoan(activeLoan);
1188
            fofoInvestmentModel.setPoValue(poValue);
1189
            fofoInvestmentModel.setPoAndBilled(poAndBilledValue);
1190
            fofoInvestmentModel.setAgreedInvestment(agreedInvestment);
1191
            fofoInvestmentModel.setWallet(partnerDailyInvestmentMap.get(fofoId) != null ? partnerDailyInvestmentMap.get(fofoId).getWalletAmount() : 0);
1192
            fofoInvestmentModel.setMonthBeginingDrr(monthDay1Drr);
1193
            fofoInvestmentModel.setRequiredDrr(todayRequiredDrr);
34701 ranu 1194
            fofoInvestmentModel.setDrrPercent(drrPercentDisplay);
34644 ranu 1195
            fofoInvestmentModel.setLastBillingDone(lastPurchaseDays);
1196
            fofoInvestmentModel.setSlab(alertLevel);
34641 ranu 1197
 
34644 ranu 1198
            biInvestmentModelMap.put(fofoId, fofoInvestmentModel);
34641 ranu 1199
                String assessment = "";
34763 ranu 1200
                if(defaultLoanAmount < 0 ){
34641 ranu 1201
                    assessment = "Loan Default";
34763 ranu 1202
                }else if(investmentLevel <= 75 && defaultLoanAmount >= 0){
34641 ranu 1203
                    assessment = "Low Invest";
1204
                }else {
1205
                    assessment = "-";
1206
                }
1207
                assessmentMap.put(fofoId,assessment);
1208
 
1209
                String zeroBilling = "";
1210
                if(currentMonthNetSecondary <= 100000 ){
1211
                    zeroBilling = "Zero Billing";
1212
                }else {
1213
                    zeroBilling = "-";
1214
                }
1215
                zeroBillingMap.put(fofoId,zeroBilling);
1216
 
1217
                float billingNeeded = 0f;
34749 ranu 1218
                if(drrPercentDisplay >= 110 && todayRequiredDrr > 0 ){
34641 ranu 1219
                    billingNeeded = (float) todayRequiredDrr;
1220
                }else {
1221
                    billingNeeded = 0f;
1222
                }
1223
                billingNeededMap.put(fofoId,billingNeeded);
1224
 
1225
                int counta = 0;
34701 ranu 1226
                if(defaultLoanAmount > 0 || investmentLevel <= 75 || currentMonthNetSecondary <= 100000 || drrPercentDisplay >= 110 ){
34641 ranu 1227
                    counta = 1;
1228
                }else {
1229
                    counta = 0;
1230
                }
1231
                countAMap.put(fofoId,counta);
1232
 
34606 ranu 1233
        }
1234
 
34619 ranu 1235
        LOGGER.info("Total BI Retailers processed: {}", biRetailerModelMap.size());
34606 ranu 1236
 
34619 ranu 1237
        //generate excel and sent to mail
1238
        List<List<String>> headerGroup = new ArrayList<>();
34606 ranu 1239
 
34619 ranu 1240
        List<String> headers1 = Arrays.asList(
34641 ranu 1241
                "","","","",
34916 ranu 1242
                "Retailer Detail", "","", "", "", "", "", "", "", "","","","","",
34677 ranu 1243
 
1244
                twoMonthAgoStringValue, "", "", "", "", "", "",
1245
                lastMonthStringValue, "", "", "", "", "", "",
34619 ranu 1246
                currentMonthStringValue, "", "", "", "", "", "",
34641 ranu 1247
 
1248
                "","", "", "", "", "", "", "", "", "", "", "", "", "",
1249
 
1250
                "", "", "", "", "", "", "", "", "", "", "", "", "",
34749 ranu 1251
                "", "", "", "", "", "", "", "", "", "", "", "", "","",""
34641 ranu 1252
 
34619 ranu 1253
        );
34606 ranu 1254
 
34619 ranu 1255
        List<String> headers2 = Arrays.asList(
34641 ranu 1256
                "Assessment","Zero billing","Billing needed","Counta",
34916 ranu 1257
                "BM","Partner Id","Link","Wallet Date","Creation Date","Code","Area",  "City", "Store Name", "Status","Category","Sales Manager", "RBM","ABM",
34619 ranu 1258
                "Secondary Target", "Secondary Achieved", "Returns", "Net Secondary", "Secondary %",
1259
                "Tertiary Sale", "Unbilled",
1260
                "Secondary Target", "Secondary Achieved", "Returns", "Net Secondary", "Secondary %",
1261
                "Tertiary Sale", "Unbilled",
1262
                "Secondary Target", "Secondary Achieved", "Returns", "Net Secondary", "Secondary %",
1263
                "Tertiary Sale", "Unbilled",
34641 ranu 1264
                "Counter Potential", "Short investment", "Default", "INVESTMENT LEVEL", "Loan", "PO value", "Agreed investment",
1265
                "Wallet", "po+bill", "MONTH BEGINNING DRR", "REQ DRR", "Drr %", "Last billing Done", "Slab",
34606 ranu 1266
 
34721 ranu 1267
              "Total Stock",  "Apple","Xiaomi", "Vivo", "Tecno", "Samsung", "Realme", "Oppo", "OnePlus", "POCO", "Lava", "Itel", "Almost New",
1268
              "Total Secondary", "Apple", "Xiaomi", "Vivo", "Tecno", "Samsung", "Realme", "Oppo", "OnePlus", "POCO", "Lava", "Itel", "Almost New",
34749 ranu 1269
              "Total Tertiary",  "Apple", "Xiaomi", "Vivo", "Tecno", "Samsung", "Realme", "Oppo", "OnePlus", "POCO", "Lava", "Itel", "Almost New",
1270
                "YesterDay Seconday","Day Before Yesterday Secondary"
34619 ranu 1271
        );
1272
 
1273
        headerGroup.add(headers1);
1274
        headerGroup.add(headers2);
1275
 
1276
 
1277
        List<List<?>> rows = new ArrayList<>();
1278
        for (Map.Entry<Integer, BIRetailerModel> entry : biRetailerModelMap.entrySet()) {
34749 ranu 1279
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
34619 ranu 1280
            Integer fofoId = entry.getKey();
34715 ranu 1281
            User user = userRepository.selectById(fofoId);
1282
            LocalDateTime walletCreationDate = userWalletHistoryRepository.selectFirstCreatedDate(fofoId);
34758 ranu 1283
            if(walletCreationDate == null){
1284
                walletCreationDate = user.getCreateTimestamp();
1285
            }
34619 ranu 1286
            BIRetailerModel retailer = entry.getValue();
34641 ranu 1287
 
34619 ranu 1288
            Map<YearMonth, BiSecondaryModel> monthlyData = allRetailerMonthlyData.get(fofoId);
1289
 
34741 ranu 1290
            BiSecondaryModel current = monthlyData.getOrDefault(currentMonth, new BiSecondaryModel(0,0,0,0,0,0,0));
1291
            BiSecondaryModel last = monthlyData.getOrDefault(currentMonth.minusMonths(1), new BiSecondaryModel(0,0,0,0,0,0,0));
1292
            BiSecondaryModel twoAgo = monthlyData.getOrDefault(currentMonth.minusMonths(2), new BiSecondaryModel(0,0,0,0,0,0,0));
34619 ranu 1293
 
1294
            List<Object> row = new ArrayList<>();
34758 ranu 1295
            LOGGER.info("fofoId-11 {}",fofoId);
1296
 
34619 ranu 1297
            row.addAll(Arrays.asList(
34758 ranu 1298
                    assessmentMap.get(fofoId),
1299
                    zeroBillingMap.get(fofoId),
1300
                    billingNeededMap.get(fofoId),
1301
                    countAMap.get(fofoId),
1302
                    retailer.getBmName(),
1303
                    fofoId ,
1304
                    "https://partners.smartdukaan.com/partnerPerformance?fofoId="+fofoId,
1305
                    walletCreationDate.format(formatter),
1306
                    user.getCreateTimestamp() != null ? (user.getCreateTimestamp()).format(formatter) : "-",
1307
                    retailer.getCode(),
1308
                    retailer.getArea(),
1309
                    retailer.getCity(),
1310
                    retailer.getStoreName(),
1311
                    retailer.getStatus(),
1312
                    retailer.getCategory(),
1313
                    retailer.getSalesManager(),
34915 ranu 1314
                    retailer.getRbm(),
1315
                    retailer.getAbm()
34677 ranu 1316
 
34619 ranu 1317
            ));
1318
 
34677 ranu 1319
 
1320
            // Two Months Ago
34619 ranu 1321
            row.addAll(Arrays.asList(
34677 ranu 1322
                    twoAgo.getSecondaryTarget(),
1323
                    twoAgo.getSecondaryAchieved(),
1324
                    twoAgo.getSecondaryReturn(),
1325
                    twoAgo.getNetSecondary(),
34704 ranu 1326
                    twoAgo.getSecondaryAchievedPercent()+"%",
34677 ranu 1327
                    twoAgo.getTertiary(),
1328
                    twoAgo.getTertiaryUnBilled()
34619 ranu 1329
            ));
1330
 
1331
            // Last Month
1332
            row.addAll(Arrays.asList(
1333
                    last.getSecondaryTarget(),
1334
                    last.getSecondaryAchieved(),
1335
                    last.getSecondaryReturn(),
1336
                    last.getNetSecondary(),
34704 ranu 1337
                    last.getSecondaryAchievedPercent()+"%",
34619 ranu 1338
                    last.getTertiary(),
1339
                    last.getTertiaryUnBilled()
1340
            ));
1341
 
34677 ranu 1342
            // Current Month
34619 ranu 1343
            row.addAll(Arrays.asList(
34677 ranu 1344
                    current.getSecondaryTarget(),
1345
                    current.getSecondaryAchieved(),
1346
                    current.getSecondaryReturn(),
1347
                    current.getNetSecondary(),
34704 ranu 1348
                    current.getSecondaryAchievedPercent()+"%",
34677 ranu 1349
                    current.getTertiary(),
1350
                    current.getTertiaryUnBilled()
34619 ranu 1351
            ));
34677 ranu 1352
 
1353
 
1354
 
34641 ranu 1355
            FofoInvestmentModel fofoInvestmentModelValue = biInvestmentModelMap.get(fofoId);
1356
            if(fofoInvestmentModelValue != null){
1357
                row.addAll(Arrays.asList(
1358
                        fofoInvestmentModelValue.getCounterPotential(),
1359
                        fofoInvestmentModelValue.getShortInvestment(),
1360
                        fofoInvestmentModelValue.getDefaultLoan(),
34730 ranu 1361
                        fofoInvestmentModelValue.getInvestmentLevel() +"%",
34743 ranu 1362
                        fofoInvestmentModelValue.getActiveLoan(),
34641 ranu 1363
                        fofoInvestmentModelValue.getPoValue(),
1364
                        fofoInvestmentModelValue.getAgreedInvestment(),
1365
                        fofoInvestmentModelValue.getWallet(),
1366
                        fofoInvestmentModelValue.getPoAndBilled(),
1367
                        fofoInvestmentModelValue.getMonthBeginingDrr(),
1368
                        fofoInvestmentModelValue.getRequiredDrr(),
34704 ranu 1369
                        fofoInvestmentModelValue.getDrrPercent()+"%",
34641 ranu 1370
                        fofoInvestmentModelValue.getLastBillingDone(),
1371
                        fofoInvestmentModelValue.getSlab()
1372
                ));
1373
            }else {
1374
                row.addAll(Arrays.asList(
1375
                        "-","-","-","-","-","-","-","-","-","-","-",""
1376
                ));
1377
            }
1378
 
1379
            Map<String, BrandStockPrice> brandStockMap = fofoBrandStockPriceMap.get(fofoId);
34619 ranu 1380
            row.addAll(Arrays.asList(
1381
                    fofoTotalStockPriceMap.getOrDefault(fofoId, 0.0),
34641 ranu 1382
                    brandStockMap.get("Apple") != null ? brandStockMap.get("Apple").getTotalValue() : 0.0,
1383
                    brandStockMap.get("Xiaomi") != null ? brandStockMap.get("Xiaomi").getTotalValue() : 0.0,
1384
                    brandStockMap.get("Vivo") != null ? brandStockMap.get("Vivo").getTotalValue() : 0.0,
1385
                    brandStockMap.get("Tecno") != null ? brandStockMap.get("Tecno").getTotalValue() : 0.0,
1386
                    brandStockMap.get("Samsung") != null ? brandStockMap.get("Samsung").getTotalValue() : 0.0,
1387
                    brandStockMap.get("Realme") != null ? brandStockMap.get("Realme").getTotalValue() : 0.0,
1388
                    brandStockMap.get("Oppo") != null ? brandStockMap.get("Oppo").getTotalValue() : 0.0,
1389
                    brandStockMap.get("OnePlus") != null ? brandStockMap.get("OnePlus").getTotalValue() : 0.0,
34721 ranu 1390
                    brandStockMap.get("POCO") != null ? brandStockMap.get("POCO").getTotalValue() : 0.0,
34641 ranu 1391
                    brandStockMap.get("Lava") != null ? brandStockMap.get("Lava").getTotalValue() : 0.0,
1392
                    brandStockMap.get("Itel") != null ? brandStockMap.get("Itel").getTotalValue() : 0.0,
1393
                    brandStockMap.get("Almost New") != null ? brandStockMap.get("Almost New").getTotalValue() : 0.0
34619 ranu 1394
            ));
1395
 
34641 ranu 1396
            Map<String, Long> brandSecondaryMap = fofoBrandWiseMtdSecondaryMap.get(fofoId);
1397
            row.addAll(Arrays.asList(
34648 ranu 1398
                    fofoTotalMtdSecondaryMap.get(fofoId),
34641 ranu 1399
                    brandSecondaryMap.getOrDefault("Apple", 0L),
1400
                    brandSecondaryMap.getOrDefault("Xiaomi", 0L),
1401
                    brandSecondaryMap.getOrDefault("Vivo", 0L),
1402
                    brandSecondaryMap.getOrDefault("Tecno", 0L),
1403
                    brandSecondaryMap.getOrDefault("Samsung", 0L),
1404
                    brandSecondaryMap.getOrDefault("Realme", 0L),
1405
                    brandSecondaryMap.getOrDefault("Oppo", 0L),
1406
                    brandSecondaryMap.getOrDefault("OnePlus", 0L),
34721 ranu 1407
                    brandSecondaryMap.getOrDefault("POCO", 0L),
34641 ranu 1408
                    brandSecondaryMap.getOrDefault("Lava", 0L),
1409
                    brandSecondaryMap.getOrDefault("Itel", 0L),
1410
                    brandSecondaryMap.getOrDefault("Almost New", 0L)
1411
            ));
1412
 
1413
            Map<String, Double> brandTertiaryMap = fofoBrandMtdTertiaryMap.get(fofoId);
1414
            row.addAll(Arrays.asList(
34648 ranu 1415
                    fofoTotalMtdTertiaryMap.get(fofoId),
34641 ranu 1416
                    brandTertiaryMap.getOrDefault("Apple", 0d),
1417
                    brandTertiaryMap.getOrDefault("Xiaomi", 0d),
1418
                    brandTertiaryMap.getOrDefault("Vivo", 0d),
1419
                    brandTertiaryMap.getOrDefault("Tecno", 0d),
1420
                    brandTertiaryMap.getOrDefault("Samsung", 0d),
1421
                    brandTertiaryMap.getOrDefault("Realme", 0d),
1422
                    brandTertiaryMap.getOrDefault("Oppo", 0d),
1423
                    brandTertiaryMap.getOrDefault("OnePlus", 0d),
34721 ranu 1424
                    brandTertiaryMap.getOrDefault("POCO", 0d),
34641 ranu 1425
                    brandTertiaryMap.getOrDefault("Lava", 0d),
1426
                    brandTertiaryMap.getOrDefault("Itel", 0d),
1427
                    brandTertiaryMap.getOrDefault("Almost New", 0d)
1428
            ));
34749 ranu 1429
 
1430
            row.addAll(Arrays.asList(
1431
                    fofoYesterdaySecondaryMap.get(fofoId),
1432
                    fofoDayBeforeYesterdaySecondaryMap.get(fofoId)
1433
            ));
34641 ranu 1434
            rows.add(row);
34619 ranu 1435
        }
1436
 
34912 ranu 1437
        Map<String, Set<Integer>> storeGuyMap = this.generateBiReportHierarchyWise();
34619 ranu 1438
 
35239 ranu 1439
        for (Map.Entry<String, Set<Integer>> storeGuyEntry : storeGuyMap.entrySet()) {
34912 ranu 1440
            String storeGuyEmail = storeGuyEntry.getKey();
1441
            Set<Integer> fofoIds = storeGuyEntry.getValue();
1442
            String[] sendToArray = new String[]{storeGuyEmail};
34911 ranu 1443
 
34912 ranu 1444
            List<List<?>> filteredRows = rows.stream()
1445
                    .filter(row -> row.size() > 5 && fofoIds.contains((Integer) row.get(5)))
1446
                    .collect(Collectors.toList());
1447
            this.sendMailToUser(headerGroup,filteredRows,sendToArray);
35239 ranu 1448
        }
34912 ranu 1449
 
1450
        this.sendMailToUser(headerGroup,rows,new String[]{"ranu.rajput@smartdukaan.com"});
1451
 
1452
 
34911 ranu 1453
    }
1454
 
1455
    private  void sendMailToUser(List<List<String>> headerGroup,List<List<?>> rows, String[] sendToArray ) throws Exception {
34641 ranu 1456
        // Send to email
1457
//        ByteArrayOutputStream csvStream = FileUtil.getCSVByteStreamWithMultiHeaders(headerGroup, rows);
1458
        ByteArrayOutputStream csvStream = getExcelStreamWithMultiHeaders(headerGroup, rows);
1459
        String fileName = "BI-Retailer-Monthly-Report-" + FormattingUtils.formatDate(LocalDateTime.now()) + ".xlsx";
34619 ranu 1460
        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()));
34911 ranu 1461
    }
34619 ranu 1462
 
1463
 
34641 ranu 1464
    public static ByteArrayOutputStream getExcelStreamWithMultiHeaders(List<List<String>> headerGroup, List<List<?>> rows) {
1465
        Workbook workbook = new XSSFWorkbook();
1466
        Sheet sheet = workbook.createSheet("BI Report");
34715 ranu 1467
        CreationHelper creationHelper = workbook.getCreationHelper();
34641 ranu 1468
        int rowIndex = 0;
34606 ranu 1469
 
34641 ranu 1470
        CellStyle centeredStyle = workbook.createCellStyle();
1471
        centeredStyle.setAlignment(HorizontalAlignment.CENTER); // Center horizontally
1472
        centeredStyle.setVerticalAlignment(VerticalAlignment.CENTER); // Center vertically
34606 ranu 1473
 
34641 ranu 1474
    // Optional: bold font
1475
        Font font1 = workbook.createFont();
1476
        font1.setBold(true);
1477
        centeredStyle.setFont(font1);
34606 ranu 1478
 
34619 ranu 1479
 
34641 ranu 1480
 
1481
        // Create styles
1482
        Map<String, CellStyle> headerStyles = new HashMap<>();
1483
 
1484
        // fontPurpleStyle
1485
        CellStyle purpleStyle = workbook.createCellStyle();
1486
        purpleStyle.setFillForegroundColor(IndexedColors.ROSE.getIndex());
1487
        purpleStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
1488
        purpleStyle.setFont(font1);
1489
        headerStyles.put("Assessment", purpleStyle);
1490
        headerStyles.put("Zero billing", purpleStyle);
1491
        headerStyles.put("Billing needed", purpleStyle);
1492
        headerStyles.put("Counta", purpleStyle);
1493
        headerStyles.put("MONTH BEGINNING DRR", purpleStyle);
1494
        headerStyles.put("REQ DRR", purpleStyle);
1495
        headerStyles.put("Drr %", purpleStyle);
1496
 
1497
        // Light Blue
1498
        CellStyle blueStyle = workbook.createCellStyle();
1499
        blueStyle.setFillForegroundColor(IndexedColors.SKY_BLUE.getIndex());
1500
        blueStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
1501
        blueStyle.setFont(font1);
1502
        headerStyles.put("Code", blueStyle);
1503
        headerStyles.put("Store Name", blueStyle);
1504
        headerStyles.put("City", blueStyle);
1505
        headerStyles.put("Area", blueStyle);
1506
        headerStyles.put("BM", blueStyle);
1507
        headerStyles.put("RBM", blueStyle);
1508
        headerStyles.put("Sales Manager", blueStyle);
1509
        headerStyles.put("Status", blueStyle);
1510
        headerStyles.put("Category", blueStyle);
34715 ranu 1511
        headerStyles.put("Wallet Date", blueStyle);
1512
        headerStyles.put("Creation Date", blueStyle);
1513
        headerStyles.put("Partner Id", blueStyle);
34641 ranu 1514
 
34715 ranu 1515
        //for link
1516
        // Create hyperlink style
1517
        CellStyle hyperlinkStyle = workbook.createCellStyle();
1518
        Font hlinkFont = workbook.createFont();
1519
        hlinkFont.setUnderline(Font.U_SINGLE);
1520
        hlinkFont.setColor(IndexedColors.BLUE.getIndex());
1521
        hyperlinkStyle.setFont(hlinkFont);
1522
 
1523
 
34641 ranu 1524
        // Light Yellow
1525
        CellStyle yellowStyle = workbook.createCellStyle();
1526
        yellowStyle.setFillForegroundColor(IndexedColors.YELLOW.getIndex());
1527
        yellowStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
1528
        yellowStyle.setFont(font1);
1529
        headerStyles.put("Last billing Done", yellowStyle);
1530
        headerStyles.put("Total Stock", yellowStyle);
1531
 
1532
        // Light Orange
1533
        CellStyle orangeStyle = workbook.createCellStyle();
1534
        orangeStyle.setFillForegroundColor(IndexedColors.LIGHT_ORANGE.getIndex());
1535
        orangeStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
1536
        orangeStyle.setFont(font1);
1537
        headerStyles.put("Total Tertiary", orangeStyle);
1538
        headerStyles.put("Total Secondary", orangeStyle);
1539
        headerStyles.put("Default", orangeStyle);
1540
 
1541
 
1542
        // Light green
1543
        CellStyle lightGreenStyle = workbook.createCellStyle();
1544
        lightGreenStyle.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex());
1545
        lightGreenStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
1546
        lightGreenStyle.setFont(font1);
1547
        headerStyles.put("Short investment", lightGreenStyle);
1548
        headerStyles.put("INVESTMENT LEVEL", lightGreenStyle);
1549
        headerStyles.put("Loan", lightGreenStyle);
1550
        headerStyles.put("PO value", lightGreenStyle);
1551
        headerStyles.put("Agreed investment", lightGreenStyle);
1552
        headerStyles.put("Wallet", lightGreenStyle);
1553
        headerStyles.put("po+bill", lightGreenStyle);
1554
 
1555
        // Light Green
1556
        CellStyle secondary1 = createStyle(workbook, IndexedColors.LIGHT_GREEN);
1557
        CellStyle secondary2 = createStyle(workbook, IndexedColors.LIGHT_YELLOW);
1558
        CellStyle secondary3 = createStyle(workbook, IndexedColors.LIGHT_ORANGE);
1559
 
1560
        Map<String, CellStyle> brandStyles = new HashMap<>();
1561
        brandStyles.put("Apple", createStyle(workbook, IndexedColors.GREY_25_PERCENT));
1562
        brandStyles.put("Xiaomi", createStyle(workbook, IndexedColors.ORANGE));
1563
        brandStyles.put("Vivo", createStyle(workbook, IndexedColors.SKY_BLUE));
1564
        brandStyles.put("Tecno", createStyle(workbook, IndexedColors.LIGHT_BLUE));
1565
        brandStyles.put("Samsung", createStyle(workbook, IndexedColors.ROYAL_BLUE));
1566
        brandStyles.put("Realme", createStyle(workbook, IndexedColors.YELLOW));
1567
        brandStyles.put("Oppo", createStyle(workbook, IndexedColors.LIGHT_GREEN));
1568
        brandStyles.put("OnePlus", createStyle(workbook, IndexedColors.RED));
34721 ranu 1569
        brandStyles.put("POCO", createStyle(workbook, IndexedColors.ORANGE));
34641 ranu 1570
        brandStyles.put("Lava", createStyle(workbook, IndexedColors.LIGHT_YELLOW));
1571
        brandStyles.put("Itel", createStyle(workbook, IndexedColors.LIGHT_YELLOW));
1572
        brandStyles.put("Almost New", createStyle(workbook, IndexedColors.WHITE));
1573
 
1574
 
1575
        CellStyle defaultHeaderStyle = workbook.createCellStyle();
1576
        defaultHeaderStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
1577
        defaultHeaderStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);
1578
        defaultHeaderStyle.setFont(font1);
1579
 
34749 ranu 1580
        CellStyle numberStyle = workbook.createCellStyle();
1581
        DataFormat format = workbook.createDataFormat();
1582
        numberStyle.setDataFormat(format.getFormat("#,##0")); // or "#,##0.00" for two decimals
34641 ranu 1583
 
34749 ranu 1584
 
1585
 
34641 ranu 1586
        Map<String, Integer> headerCount = new HashMap<>();
1587
 
1588
        for (int headerRowIndex = 0; headerRowIndex < headerGroup.size(); headerRowIndex++) {
1589
            List<String> headerRow = headerGroup.get(headerRowIndex);
1590
            Row row = sheet.createRow(rowIndex++);
1591
 
1592
            for (int i = 0; i < headerRow.size(); i++) {
1593
                String headerText = headerRow.get(i);
1594
                sheet.setColumnWidth(i, 25 * 256);
1595
                row.setHeightInPoints(20); // 25-point height
1596
                Cell cell = row.createCell(i);
1597
                cell.setCellValue(headerText);
1598
                cell.setCellStyle(centeredStyle);
1599
                // Count how many times this header has appeared
1600
                int count = headerCount.getOrDefault(headerText, 0) + 1;
1601
                headerCount.put(headerText, count);
1602
                // Apply special style for repeated headers
1603
                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")) {
1604
                    if (count == 1) {
1605
                        cell.setCellStyle(secondary1);
1606
                    } else if (count == 2) {
1607
                        cell.setCellStyle(secondary2);
1608
                    } else if (count == 3) {
1609
                        cell.setCellStyle(secondary3);
1610
                    }
1611
                }
1612
                // Brand header styling (apply only for the 2nd row of headers)
1613
                else if (headerRowIndex == 1 && brandStyles.containsKey(headerText)) {
1614
                    cell.setCellStyle(brandStyles.get(headerText));
1615
                }else if (headerStyles.containsKey(headerText)) {
1616
                    cell.setCellStyle(headerStyles.get(headerText));
1617
                } else {
1618
                    cell.setCellStyle(defaultHeaderStyle); // default style for others
1619
                }
1620
            }
1621
        }
1622
 
1623
        // Write data rows
1624
        for (List<?> dataRow : rows) {
1625
            Row row = sheet.createRow(rowIndex++);
1626
            for (int i = 0; i < dataRow.size(); i++) {
1627
                Cell cell = row.createCell(i);
1628
                Object value = dataRow.get(i);
34715 ranu 1629
 
1630
                if (i == 6 && value != null) { // Assuming column 6 is "Link"
1631
                    Hyperlink hyperlink = creationHelper.createHyperlink(HyperlinkType.URL);
1632
                    hyperlink.setAddress(value.toString());
34719 ranu 1633
                    cell.setCellValue("View Link"); // Display text
34715 ranu 1634
                    cell.setHyperlink(hyperlink);
1635
                    cell.setCellStyle(hyperlinkStyle);
34719 ranu 1636
                } else if (value instanceof Number) {
34749 ranu 1637
                    double numeric = ((Number) value).doubleValue();
1638
                    cell.setCellValue(Math.round(numeric));
1639
                    cell.setCellStyle(numberStyle);
34715 ranu 1640
                } else {
1641
                    cell.setCellValue(value != null ? value.toString() : "");
1642
                }
34641 ranu 1643
            }
34719 ranu 1644
 
34641 ranu 1645
        }
1646
 
1647
        // Auto-size columns
1648
        if (!rows.isEmpty()) {
1649
            for (int i = 0; i < rows.get(0).size(); i++) {
1650
                sheet.autoSizeColumn(i);
1651
            }
1652
        }
1653
 
1654
        // Output as ByteArray
1655
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
1656
            workbook.write(outputStream);
1657
            workbook.close();
1658
            return outputStream;
1659
        } catch (IOException e) {
1660
            throw new RuntimeException("Failed to generate Excel file", e);
1661
        }
1662
    }
1663
 
1664
 
1665
    private static CellStyle createStyle(Workbook workbook, IndexedColors color) {
1666
        CellStyle style = workbook.createCellStyle();
1667
        style.setFillForegroundColor(color.getIndex());
1668
        style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
1669
        Font font = workbook.createFont();
1670
        font.setBold(true);
1671
        style.setFont(font);
1672
        return style;
1673
    }
1674
 
1675
 
34758 ranu 1676
    public void stockAlertMailToRetailer() throws Exception {
1677
 
1678
        Map<Integer, CustomRetailer> customRetailers = retailerService.getFofoRetailers(true);
1679
 
1680
        List<Integer> retailerIds = customRetailers.values().stream().map(CustomRetailer::getPartnerId).collect(Collectors.toList());
1681
 
1682
        for(Integer fofoId : retailerIds){
1683
            List<String> statusOrder = Arrays.asList("HID", "FASTMOVING", "RUNNING", "SLOWMOVING", "OTHER");
1684
            FofoStore fofoStore = fofoStoreRepository.selectByRetailerId(fofoId);
1685
            List<PartnerWarehouseStockSummaryModel> partnerWarehouseStockSummaryModels = saholicInventoryService.getSaholicAndPartnerStock(fofoId, fofoStore.getWarehouseId());
1686
 
1687
            List<PartnerWarehouseStockAgingSummaryModel> partnerWarehouseStockAgingSummaryModelList = new ArrayList<>();
1688
 
1689
            Set<Integer> catalogIds = partnerWarehouseStockSummaryModels.stream().map(x -> x.getCatalogId()).collect(Collectors.toSet());
1690
 
1691
            List<Integer> catalogsList = new ArrayList<>(catalogIds);
1692
 
1693
            Map<Integer, TagListing> tagListingsMap = tagListingRepository.selectAllByCatalogIds(catalogsList);
1694
 
1695
            List<CatalogAgingModel> catalogAgingModels = ageingService.getCatalogsAgingByWarehouse(catalogIds, fofoStore.getWarehouseId());
1696
 
1697
            Map<Integer, CatalogAgingModel> catalogAgingModelMap = catalogAgingModels.stream().collect(Collectors.toMap(x -> x.getCatalogId(), x -> x));
1698
 
1699
            for (PartnerWarehouseStockSummaryModel stockSummary : partnerWarehouseStockSummaryModels) {
1700
 
1701
                PartnerWarehouseStockAgingSummaryModel partnerWarehouseStockAgingSummaryModel = new PartnerWarehouseStockAgingSummaryModel();
1702
                partnerWarehouseStockAgingSummaryModel.setCatalogId(stockSummary.getCatalogId());
1703
                partnerWarehouseStockAgingSummaryModel.setBrand(stockSummary.getBrand());
1704
                partnerWarehouseStockAgingSummaryModel.setModelNumber(stockSummary.getModelNumber());
1705
                partnerWarehouseStockAgingSummaryModel.setNetAvailability(stockSummary.getShaholicNetAvailability());
1706
                partnerWarehouseStockAgingSummaryModel.setPartnerStockAvailability(stockSummary.getPartnerFullFilledQty());
1707
                partnerWarehouseStockAgingSummaryModel.setPartnerCurrentAvailability(stockSummary.getPartnerCurrentQty());
1708
                partnerWarehouseStockAgingSummaryModel.setPartnerShortageStock(stockSummary.getPartnerShortageQty());
1709
                if (catalogAgingModelMap.get(stockSummary.getCatalogId()) != null) {
1710
                    partnerWarehouseStockAgingSummaryModel.setExceedDays(catalogAgingModelMap.get(stockSummary.getCatalogId()).getExceedDays());
1711
                } else {
1712
                    partnerWarehouseStockAgingSummaryModel.setExceedDays(0);
1713
 
1714
                }
1715
                partnerWarehouseStockAgingSummaryModel.setStatus(stockSummary.getStatus());
1716
 
1717
                partnerWarehouseStockAgingSummaryModelList.add(partnerWarehouseStockAgingSummaryModel);
1718
            }
1719
 
1720
            Set<Integer> existingCatalogIdsInAgingSummaryList = partnerWarehouseStockAgingSummaryModelList.stream()
1721
                    .map(PartnerWarehouseStockAgingSummaryModel::getCatalogId)
1722
                    .collect(Collectors.toSet());
1723
        }
1724
 
1725
    }
1726
 
34939 ranu 1727
    public void createFofoSmartCartSuggestion(){
34758 ranu 1728
 
34939 ranu 1729
        List<Integer> fofoIds = fofoStoreRepository.selectActiveStores().stream().map(x->x.getId()).collect(toList());
1730
        LocalDateTime todayDate = LocalDate.now().atStartOfDay();
1731
        LocalDateTime fortyFiveAgoDate = todayDate.minusDays(45).with(LocalTime.MAX);
1732
        for(Integer fofoId :fofoIds){
1733
            smartCartSuggestionRepository.deleteByFofoId(fofoId);
1734
            List<SoldAllCatalogitemQtyByPartnerModel> soldAllCatalogitemQtyByPartnerModels = smartCartService.getAllSoldCatalogItemByPartner(fofoId,fortyFiveAgoDate,todayDate);
1735
            for(SoldAllCatalogitemQtyByPartnerModel soldAllCatalogitemQtyByPartnerModel : soldAllCatalogitemQtyByPartnerModels){
1736
               SmartCartSuggestion smartCartSuggestion = new SmartCartSuggestion();
34941 ranu 1737
 
1738
                // weekly average = total sold qty / 6 weeks
1739
                long avgWeeklyQty = Math.round((float) soldAllCatalogitemQtyByPartnerModel.getSoldQty() / 6);
1740
 
1741
                // ensure minimum 2
1742
                long suggestedQty = Math.max(1, avgWeeklyQty);
1743
 
34939 ranu 1744
               smartCartSuggestion.setCatalogId(soldAllCatalogitemQtyByPartnerModel.getCatalogId());
1745
               smartCartSuggestion.setFofoId(fofoId);
1746
               smartCartSuggestion.setSoldQty(soldAllCatalogitemQtyByPartnerModel.getSoldQty());
34941 ranu 1747
               smartCartSuggestion.setSuggestedQty(suggestedQty);
34939 ranu 1748
               smartCartSuggestion.setCreationDate(LocalDate.now());
1749
               smartCartSuggestionRepository.persist(smartCartSuggestion);
1750
            }
1751
        }
1752
 
1753
    }
1754
 
1755
 
34306 ranu 1756
}