Subversion Repositories SmartDukaan

Rev

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

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