Subversion Repositories SmartDukaan

Rev

Rev 34648 | Rev 34655 | 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");
34653 ranu 152
        this.generateBiReportExcel();
34366 ranu 153
        System.out.println("test end");
34306 ranu 154
 
155
    }
156
 
34648 ranu 157
    public void generateBiReport() throws Exception {
158
        LOGGER.info("bi report started {-----}");
159
        this.generateBiReportExcel();
160
        LOGGER.info("bi report ended {-----}");
161
    }
162
 
34308 ranu 163
    public void createLoanForBillingByTransactionIdAndInvoiceNumber(int transactionId, double invoiceAmount, String invoiceNumber) throws Exception {
164
        sdCreditService.createLoanForBilling(transactionId, invoiceAmount, invoiceNumber);
34306 ranu 165
 
34308 ranu 166
    }
34306 ranu 167
 
34619 ranu 168
    public void loanSettle() throws Exception {
169
        List<Integer> refrences = Arrays.asList(25807,36003,38938,39506,42219,45084);
170
        for(Integer ref : refrences){
171
            List<LoanStatement> loanStatements = loanStatementRepository.selectByLoanId(ref);
172
            double amountSum = loanStatements.stream().map(LoanStatement::getAmount).mapToDouble(BigDecimal::doubleValue).sum();
173
            if(amountSum > 0){
174
                walletService.addAmountToWallet(loanStatements.get(0).getFofoId(),ref, WalletReferenceType.CREDIT_LIMIT,"Amount reversal against credit limit deduction",(float) amountSum,LocalDateTime.now());
34308 ranu 175
 
34619 ranu 176
//                Loan statement entry
177
                    BigDecimal adjustAmount = BigDecimal.valueOf(amountSum).negate(); // or multiply by -1
178
                    LoanStatement loanStatement = new LoanStatement();
179
                    loanStatement.setAmount(adjustAmount);
180
                    loanStatement.setFofoId(loanStatements.get(0).getFofoId());
181
                    loanStatement.setLoanReferenceType(LoanReferenceType.PRINCIPAL);
182
                    loanStatement.setCreatedAt(LocalDateTime.now());
183
                    loanStatement.setDescription("Amount reversal due to access debit against limit");
184
                    loanStatement.setLoanId(ref);
185
                    loanStatement.setBusinessDate(LocalDateTime.now());
186
                    loanStatementRepository.persist(loanStatement);
187
 
188
                    Loan loan = loanRepository.selectByLoanId(ref);
189
                    loan.setPendingAmount(BigDecimal.valueOf(0));
190
                    loan.setSettledOn(LocalDateTime.now());
191
                }
192
 
193
 
194
        }
195
    }
196
 
197
 
198
 
34321 ranu 199
    private void sendMailHtmlFormat(String email[], String body, String cc[], String bcc[], String subject)
200
            throws MessagingException, ProfitMandiBusinessException, IOException {
201
        MimeMessage message = mailSender.createMimeMessage();
202
        MimeMessageHelper helper = new MimeMessageHelper(message);
203
        helper.setSubject(subject);
204
        helper.setText(body, true);
205
        helper.setTo(email);
206
        if (cc != null) {
207
            helper.setCc(cc);
208
        }
209
        if (bcc != null) {
210
            helper.setBcc(bcc);
34308 ranu 211
 
34321 ranu 212
        }
213
 
214
        InternetAddress senderAddress = new InternetAddress("noreply@smartdukaan.com", "Smart Dukaan");
215
        helper.setFrom(senderAddress);
216
        mailSender.send(message);
217
    }
218
 
34307 ranu 219
    public Map<Integer,Integer> findLoanTransactionMapingAccordingLoan(List<Integer> loanIds) throws ProfitMandiBusinessException {
34306 ranu 220
 
221
        Map<Integer, Integer> transactionLoanMap = new HashMap<>();
222
 
223
        for(int loanId : loanIds){
224
            Transaction transaction = null;
225
            Loan loan = loanRepository.selectByLoanId(loanId);
226
            List<Transaction> transactions = transactionRepository.selectByRetailerId(loan.getFofoId());
227
 
228
            LocalDateTime nearestDateTime = transactions.stream().map(x -> x.getCreateTimestamp())
229
                    .min(Comparator.comparingLong(x -> Math.abs(ChronoUnit.MILLIS.between(x, loan.getCreatedOn()))))
230
                    .orElse(null);
231
 
232
            if (nearestDateTime != null && loan.getCreatedOn().plusMinutes(2).isAfter(nearestDateTime) &&
233
                    loan.getCreatedOn().minusMinutes(1).isBefore(nearestDateTime)) {
234
                // Here transaction is still null
235
                transaction = transactions.stream()
236
                        .filter(x -> x.getCreateTimestamp().equals(nearestDateTime))
237
                        .findFirst().get();
238
                transactionLoanMap.put(transaction.getId(), loanId);
239
            }
240
 
241
        }
242
        LOGGER.info("transactionLoanMap {}",transactionLoanMap);
243
        return transactionLoanMap;
244
    }
34321 ranu 245
 
246
 
247
 
248
    public void sendRbmFeedbackSummaryEmail() throws MessagingException, ProfitMandiBusinessException, IOException {
249
        LocalDateTime startOfMonth = LocalDate.now().withDayOfMonth(1).atStartOfDay();
250
        LocalDateTime endOfMonth = LocalDateTime.now();
34323 ranu 251
        String[] bcc = {"tarun.verma@smartdukaan.com"};
34321 ranu 252
 
253
        // Get all RBM users
254
        List<AuthUser> authUsers = csService.getAuthUserIds(
255
                ProfitMandiConstants.TICKET_CATEGORY_RBM,
256
                Arrays.asList(EscalationType.L1)
257
        );
258
 
259
        if (authUsers.isEmpty()) {
260
            LOGGER.info("No RBMs found.");
261
            return;
262
        }
263
 
264
        List<Integer> rbmIds = authUsers.stream().map(AuthUser::getId).collect(Collectors.toList());
265
 
266
        // Fetch ratings for all RBMs for current month
267
        List<RbmRating> feedbackList = rbmRatingRepository.selectByRbmIdsAndDateRange(rbmIds, startOfMonth, endOfMonth);
268
 
269
        if (feedbackList.isEmpty()) {
270
            LOGGER.info("No feedback entries found for RBMs.");
271
            return;
272
        }
273
 
274
        // Sort feedback by createTimeStamp DESC
275
        feedbackList.sort((a, b) -> b.getCreateTimeStamp().compareTo(a.getCreateTimeStamp()));
276
 
277
        // Fetch and map FOFO (partner) names
278
        Map<Integer, String> fofoNameMap = new HashMap<>();
279
        for (RbmRating rating : feedbackList) {
280
            int fofoId = rating.getFofoId();
281
            if (!fofoNameMap.containsKey(fofoId)) {
282
                User fofoUser = userRepository.selectById(fofoId);
283
                FofoStore fofoStore = fofoStoreRepository.selectByRetailerId(fofoId);
284
 
285
                String partnerName = fofoUser != null ? fofoUser.getName() : "Unknown Partner";
286
                String storeCode = fofoStore != null ? fofoStore.getCode() : "Unknown Code";
287
 
288
                String displayName = partnerName + " (" + storeCode + ")";
289
                fofoNameMap.put(fofoId, displayName);
290
            }
291
        }
292
 
293
        // Map RBM ID to name for quick lookup
294
        Map<Integer, String> rbmNameMap = authUsers.stream()
295
                .collect(Collectors.toMap(AuthUser::getId, AuthUser::getFullName));
296
 
297
        // Generate HTML content
298
        StringBuilder emailContent = new StringBuilder();
299
        emailContent.append("<html><body>");
300
        emailContent.append("<p>Dear Team,</p>");
301
        emailContent.append("<p>Here is the <b>latest RBM Rating and Feedback Summary</b> for ")
302
                .append(LocalDate.now().getMonth()).append(":</p>");
303
 
304
        emailContent.append("<table border='1' cellspacing='0' cellpadding='5'>");
305
        emailContent.append("<tr>")
306
                .append("<th>RBM Name</th>")
307
                .append("<th>Partner Name</th>")
308
                .append("<th>Rating</th>")
309
                .append("<th>Comment</th>")
310
                .append("<th>Date</th>")
311
                .append("</tr>");
312
 
313
        for (RbmRating rating : feedbackList) {
314
            String rbmName = rbmNameMap.getOrDefault(rating.getRbmId(), "Unknown RBM");
315
            String partnerName = fofoNameMap.getOrDefault(rating.getFofoId(), "Unknown Partner");
316
            emailContent.append("<tr>")
317
                    .append("<td>").append(rbmName).append("</td>")
318
                    .append("<td>").append(partnerName).append("</td>")
319
                    .append("<td>").append(rating.getRating()).append("</td>")
320
                    .append("<td>").append(rating.getComment() != null ? rating.getComment() : "-").append("</td>")
321
                    .append("<td>").append(rating.getCreateTimeStamp().toLocalDate()).append("</td>")
322
                    .append("</tr>");
323
        }
324
 
325
        emailContent.append("</table>");
326
        emailContent.append("<br><p>Regards,<br>Smart Dukaan Team</p>");
327
        emailContent.append("</body></html>");
328
 
329
        String subject = "Monthly RBM Feedback Summary - " + LocalDate.now().getMonth();
330
 
331
        List<String> sendTo = new ArrayList<>();
34323 ranu 332
        sendTo.add("sm@smartdukaan.com"); //
333
        sendTo.add("chiranjib.sarkar@smartdukaan.com"); //
334
        sendTo.add("kamini.sharma@smartdukaan.com"); //
34321 ranu 335
 
336
        String[] emailRecipients = sendTo.toArray(new String[0]);
337
 
338
 
339
        this.sendMailHtmlFormat(emailRecipients, emailContent.toString(), null, bcc, subject);
340
 
341
        LOGGER.info("Consolidated RBM feedback summary email sent.");
342
    }
343
 
344
 
345
    public void sendSalesFeedbackSummaryEmail() throws MessagingException, ProfitMandiBusinessException, IOException {
346
        LocalDateTime startOfMonth = LocalDate.now().withDayOfMonth(1).atStartOfDay();
347
        LocalDateTime endOfMonth = LocalDateTime.now();
34323 ranu 348
        String[] bcc = {"tarun.verma@smartdukaan.com"};
34411 tejus.loha 349
//        String[] bcc = {"tejus.lohani@smartdukaan.com"};
34321 ranu 350
 
351
        // Get all RBM users
352
        List<AuthUser> authUsers = csService.getAuthUserIds(
353
                ProfitMandiConstants.TICKET_CATEGORY_SALES,
354
                Arrays.asList(EscalationType.L1)
355
        );
356
 
357
        if (authUsers.isEmpty()) {
358
            LOGGER.info("No sales person found.");
359
            return;
360
        }
361
 
362
        List<Integer> salesL1Ids = authUsers.stream().map(AuthUser::getId).collect(Collectors.toList());
363
 
364
        // Fetch ratings for all RBMs for current month
365
        List<SalesRating> feedbackList = salesRatingRepository.selectBySalesL1IdsAndDateRange(salesL1Ids, startOfMonth, endOfMonth);
366
 
367
        if (feedbackList.isEmpty()) {
368
            LOGGER.info("No feedback entries found for Sales.");
369
            return;
370
        }
371
 
372
        // Sort feedback by createTimeStamp DESC
373
        feedbackList.sort((a, b) -> b.getCreateTimeStamp().compareTo(a.getCreateTimeStamp()));
374
 
375
        // Fetch and map FOFO (partner) names
376
        Map<Integer, String> fofoNameMap = new HashMap<>();
377
        for (SalesRating rating : feedbackList) {
378
            int fofoId = rating.getFofoId();
379
            if (!fofoNameMap.containsKey(fofoId)) {
380
                User fofoUser = userRepository.selectById(fofoId);
381
                FofoStore fofoStore = fofoStoreRepository.selectByRetailerId(fofoId);
382
 
383
                String partnerName = fofoUser != null ? fofoUser.getName() : "Unknown Partner";
384
                String storeCode = fofoStore != null ? fofoStore.getCode() : "Unknown Code";
385
 
386
                String displayName = partnerName + " (" + storeCode + ")";
387
                fofoNameMap.put(fofoId, displayName);
388
            }
389
        }
390
 
391
        // Map RBM ID to name for quick lookup
392
        Map<Integer, String> salesL1NameMap = authUsers.stream()
393
                .collect(Collectors.toMap(AuthUser::getId, AuthUser::getFullName));
394
 
395
        // Generate HTML content
396
        StringBuilder emailContent = new StringBuilder();
397
        emailContent.append("<html><body>");
398
        emailContent.append("<p>Dear Team,</p>");
399
        emailContent.append("<p>Here is the <b>latest Sales L1 Rating and Feedback Summary</b> for ")
400
                .append(LocalDate.now().getMonth()).append(":</p>");
401
 
402
        emailContent.append("<table border='1' cellspacing='0' cellpadding='5'>");
403
        emailContent.append("<tr>")
404
                .append("<th>Sales L1 Name</th>")
405
                .append("<th>Partner Name</th>")
34411 tejus.loha 406
                .append("<th>Partner Category</th>")
34321 ranu 407
                .append("<th>Rating</th>")
408
                .append("<th>Comment</th>")
409
                .append("<th>Date</th>")
410
                .append("</tr>");
411
 
412
        for (SalesRating rating : feedbackList) {
413
            String salesL1 = salesL1NameMap.getOrDefault(rating.getSalesL1Id(), "Unknown Sales Person");
414
            String partnerName = fofoNameMap.getOrDefault(rating.getFofoId(), "Unknown Partner");
34411 tejus.loha 415
            PartnerType partnerType = partnerTypeChangeService.getTypeOnDate(rating.getFofoId(), LocalDate.now());
34321 ranu 416
            emailContent.append("<tr>")
417
                    .append("<td>").append(salesL1).append("</td>")
418
                    .append("<td>").append(partnerName).append("</td>")
34411 tejus.loha 419
                    .append("<td>").append(partnerType).append("</td>")
34321 ranu 420
                    .append("<td>").append(rating.getRating()).append("</td>")
421
                    .append("<td>").append(rating.getComment() != null ? rating.getComment() : "-").append("</td>")
422
                    .append("<td>").append(rating.getCreateTimeStamp().toLocalDate()).append("</td>")
423
                    .append("</tr>");
424
        }
425
 
426
        emailContent.append("</table>");
427
        emailContent.append("<br><p>Regards,<br>Smartdukaan Team</p>");
428
        emailContent.append("</body></html>");
429
 
34411 tejus.loha 430
        String subject = "Monthly Sales L1 Feedback Summary Test test - " + LocalDate.now().getMonth();
34321 ranu 431
 
432
        List<String> sendTo = new ArrayList<>();
34323 ranu 433
         sendTo.add("sm@smartdukaan.com"); //
434
         sendTo.add("chiranjib.sarkar@smartdukaan.com"); //
34606 ranu 435
         sendTo.add("kamini.sharma@smartdukaan.com"); //
34321 ranu 436
 
437
        String[] emailRecipients = sendTo.toArray(new String[0]);
438
 
439
 
440
        this.sendMailHtmlFormat(emailRecipients, emailContent.toString(), null, bcc, subject);
441
 
442
        LOGGER.info("Consolidated Sales L1 feedback summary email sent.");
443
    }
444
 
445
 
34606 ranu 446
    public void generateBiReportExcel() throws Exception {
34619 ranu 447
 
34606 ranu 448
        LocalDateTime startOfToday = LocalDate.now().atStartOfDay();
34321 ranu 449
 
34653 ranu 450
        /*Map<Integer, CustomRetailer> customRetailers = retailerService.getAllFofoRetailersInternalFalse();
34321 ranu 451
 
34653 ranu 452
        List<Integer> retailerIds = customRetailers.values().stream().map(CustomRetailer::getPartnerId).collect(Collectors.toList());*/
34606 ranu 453
 
34653 ranu 454
        List<Integer> retailerIds = Arrays.asList(175139401,175139400,175139381,175139667,175139662,175139661,175130896,175139323,175139452);
455
        Map<Integer,CustomRetailer> customRetailers = retailerService.getFofoRetailers(retailerIds);
34648 ranu 456
 
34641 ranu 457
        //partner daily investment
458
        List<Loan> defaultLoans = sdCreditService.getDefaultLoan();
459
        Map<Integer,List<Loan>> defaultLoanMap = defaultLoans.stream().collect(Collectors.groupingBy(Loan::getFofoId));
34619 ranu 460
 
34641 ranu 461
        Map<Integer, PartnerDailyInvestment> partnerDailyInvestmentMap = new HashMap<>();
462
        List<PartnerDailyInvestment> partnerDailyInvestments = partnerDailyInvestmentRepository
463
                .selectAll(new ArrayList<>(retailerIds), LocalDate.now().minusDays(1));
464
        if (!partnerDailyInvestments.isEmpty()) {
465
            partnerDailyInvestmentMap = partnerDailyInvestments.stream()
466
                    .collect(Collectors.toMap(x -> x.getFofoId(), x -> x));
467
        }
468
 
34648 ranu 469
    //  this month return data
34619 ranu 470
        YearMonth currentMonth = YearMonth.now();
471
        String currentMonthStringValue = String.valueOf(currentMonth);
34606 ranu 472
        LocalDateTime currentMonthStartDate = YearMonth.now().atDay(1).atStartOfDay();
473
        LocalDateTime currentMonthEndDate = LocalDateTime.now();
474
 
475
        List<ReturnOrderInfoModel> currentMonthReturnOrderInfoModels = returnOrderInfoRepository.selectAllByBetweenDate(currentMonthStartDate, currentMonthEndDate);
476
        Map<Integer, Long> currentMonthPartnerReturnOrderInfoModelMap = currentMonthReturnOrderInfoModels.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getRefundAmount()))));
477
 
478
        List<Order> currentMonthRtoRefundOrders = orderRepository.selectAllOrderDatesBetweenByStatus(currentMonthStartDate, currentMonthEndDate, OrderStatus.RTO_REFUNDED);
479
        Map<Integer, Long> currentMonthRtoRefundOrderMap = currentMonthRtoRefundOrders.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getTotalAmount()))));
480
 
481
 
34619 ranu 482
//  last month return data
34606 ranu 483
        YearMonth lastMonth = YearMonth.now().minusMonths(1);
34619 ranu 484
        String lastMonthStringValue = String.valueOf(lastMonth);
34606 ranu 485
        LocalDateTime lastMontStartDate = lastMonth.atDay(1).atStartOfDay();
486
        LocalDateTime lastMonthEndDate = lastMonth.atEndOfMonth().atTime(23, 59, 59);
487
 
488
        List<ReturnOrderInfoModel> lastMonthReturnOrderInfoModels = returnOrderInfoRepository.selectAllByBetweenDate(lastMontStartDate, lastMonthEndDate);
489
        Map<Integer, Long> lastMonthPartnerReturnOrderInfoModelMap = lastMonthReturnOrderInfoModels.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getRefundAmount()))));
490
 
491
        List<Order> lastMonthRtoRefundOrders = orderRepository.selectAllOrderDatesBetweenByStatus(lastMontStartDate, lastMonthEndDate, OrderStatus.RTO_REFUNDED);
492
        Map<Integer, Long> lastMonthRtoRefundOrderMap = lastMonthRtoRefundOrders.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getTotalAmount()))));
493
 
494
 
34619 ranu 495
//  twoMonthsAgo return data
34606 ranu 496
        YearMonth twoMonthsAgo = YearMonth.now().minusMonths(2);
34619 ranu 497
        String twoMonthAgoStringValue = String.valueOf(twoMonthsAgo);
34606 ranu 498
        LocalDateTime twoMonthsAgoStartDate = twoMonthsAgo.atDay(1).atStartOfDay();
499
        LocalDateTime twoMonthsAgoEndDate = twoMonthsAgo.atEndOfMonth().atTime(23, 59, 59);
500
 
501
        List<ReturnOrderInfoModel> twoMonthAgoReturnOrderInfoModels = returnOrderInfoRepository.selectAllByBetweenDate(twoMonthsAgoStartDate, twoMonthsAgoEndDate);
502
        Map<Integer, Long> twoMonthAgoPartnerReturnOrderInfoModelMap = twoMonthAgoReturnOrderInfoModels.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getRefundAmount()))));
503
 
504
        List<Order> twoMonthRtoRefundOrders = orderRepository.selectAllOrderDatesBetweenByStatus(twoMonthsAgoStartDate, twoMonthsAgoEndDate, OrderStatus.RTO_REFUNDED);
34619 ranu 505
        Map<Integer, Long> twoMonthAgoRtoRefundOrderMap = twoMonthRtoRefundOrders.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getTotalAmount()))));
34606 ranu 506
 
34648 ranu 507
        Map<Integer , String> assessmentMap = new HashMap<>();
508
        Map<Integer , String> zeroBillingMap = new HashMap<>();
509
        Map<Integer , Float> billingNeededMap = new HashMap<>();
510
        Map<Integer , Integer> countAMap = new HashMap<>();
34606 ranu 511
 
34619 ranu 512
        Map<Integer , BIRetailerModel> biRetailerModelMap = new HashMap<>();
34606 ranu 513
 
34641 ranu 514
        Map<Integer , FofoInvestmentModel> biInvestmentModelMap = new HashMap<>();
515
 
34619 ranu 516
        Map<Integer, Map<YearMonth, BiSecondaryModel>> allRetailerMonthlyData = new HashMap<>();
34606 ranu 517
 
34619 ranu 518
        Map<Integer,Double> fofoTotalStockPriceMap = new HashMap<>();
519
 
520
        Map<Integer,Map<String, BrandStockPrice>> fofoBrandStockPriceMap = new HashMap<>();
521
 
34641 ranu 522
        Map<Integer,Long> fofoTotalMtdSecondaryMap = new HashMap<>();
34619 ranu 523
 
524
 
34641 ranu 525
        Map<Integer,Map<String, Long>> fofoBrandWiseMtdSecondaryMap = new HashMap<>();
34619 ranu 526
 
34641 ranu 527
        Map<Integer,Double> fofoTotalMtdTertiaryMap = new HashMap<>();
528
 
529
        Map<Integer,Map<String, Double>> fofoBrandMtdTertiaryMap = new HashMap<>();
530
 
34606 ranu 531
        for(Integer fofoId: retailerIds){
34619 ranu 532
            String rbmName = "";
34606 ranu 533
            int rbmL1 = csService.getAuthUserId(ProfitMandiConstants.TICKET_CATEGORY_RBM,EscalationType.L1,fofoId);
34619 ranu 534
            if(rbmL1 != 0){
535
                 rbmName = authRepository.selectById(rbmL1).getFullName();
536
            }
537
            String bmName ="";
34606 ranu 538
            int bmId = csService.getAuthUserId(ProfitMandiConstants.TICKET_CATEGORY_SALES,EscalationType.L2,fofoId);
34619 ranu 539
            if(bmId !=0){
540
                bmName = authRepository.selectById(bmId).getFullName();
541
            }
34606 ranu 542
 
543
            int managerId = csService.getAuthUserId(ProfitMandiConstants.TICKET_CATEGORY_SALES,EscalationType.L1,fofoId);
544
            String managerName = " ";
545
            if(managerId != 0){
546
                 managerName = authRepository.selectById(managerId).getFullName();
547
            }else {
548
                managerName = bmName;
549
            }
550
 
551
            AST ast = astRepository.selectById(customRetailers.get(fofoId).getAstId());
552
 
553
            PartnerType partnerTypeThisMonth = partnerTypeChangeService.getTypeOnMonth(fofoId, YearMonth.now());
554
 
555
//            generate retaile detail
556
 
557
            BIRetailerModel biRetailerModel = new BIRetailerModel();
558
            biRetailerModel.setBmName(bmName);
559
            biRetailerModel.setCode(customRetailers.get(fofoId).getCode());
34619 ranu 560
            if(ast != null){
561
                biRetailerModel.setArea(ast.getArea());
562
            }else {
563
                biRetailerModel.setArea("-");
564
            }
34606 ranu 565
            biRetailerModel.setCity(customRetailers.get(fofoId).getAddress().getCity());
566
            biRetailerModel.setStoreName(customRetailers.get(fofoId).getBusinessName());
34619 ranu 567
            biRetailerModel.setStatus(String.valueOf(customRetailers.get(fofoId).getActivationType()));
34606 ranu 568
            biRetailerModel.setCategory(String.valueOf(partnerTypeThisMonth));
569
            biRetailerModel.setSalesManager(managerName);
570
            biRetailerModel.setRbm(rbmName);
571
 
34619 ranu 572
            biRetailerModelMap.put(fofoId,biRetailerModel);
573
 
34641 ranu 574
 
34606 ranu 575
//            generate secondary data
576
 
34641 ranu 577
            List<PartnerWiseActivatedNotBilledTotal> partnerWiseActivatedNotBilledMonthlyTotals = activatedImeiRepository.getTotalMonthlyActivatedNotBilled(fofoId,twoMonthsAgoStartDate);
578
            Map<YearMonth , PartnerWiseActivatedNotBilledTotal> partnerWiseActivatedNotBilledTotalMap = partnerWiseActivatedNotBilledMonthlyTotals.stream().collect(Collectors.toMap(x-> YearMonth.parse(x.getYearMonth()),x->x));
579
 
34606 ranu 580
//            this month secondary target
581
 
34619 ranu 582
            double currentSecondaryTarget =  monthlyTargetRepository.selectByDateAndFofoId(YearMonth.now(), fofoId) != null ? monthlyTargetRepository.selectByDateAndFofoId(YearMonth.now(), fofoId).getPurchaseTarget() : 0;
34606 ranu 583
 
34619 ranu 584
 
585
            long currentMonthReturn = currentMonthPartnerReturnOrderInfoModelMap.getOrDefault(fofoId, 0L) + currentMonthRtoRefundOrderMap.getOrDefault(fofoId, 0L);
586
 
587
 
34606 ranu 588
            Map<Integer, Double> secondaryMtd = orderRepository.selectOrderValueBetweenDatesGroupByFofoId(Arrays.asList(fofoId),
589
                    Arrays.asList(OrderStatus.BILLED, OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.DELIVERY_SUCCESS, OrderStatus.ACCEPTED, OrderStatus.SUBMITTED_FOR_PROCESSING),
590
                    startOfToday.withDayOfMonth(1), startOfToday.with(LocalTime.MAX)).stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getAmount()));
591
 
592
            double secondaryAchievedMtd = secondaryMtd.getOrDefault(fofoId, 0.0);
593
 
34619 ranu 594
            double currentMonthNetSecondary = secondaryAchievedMtd - currentMonthReturn;
34606 ranu 595
 
34619 ranu 596
            double currentMonthSecondaryPercent = currentSecondaryTarget == 0 ? 0.0 : (secondaryAchievedMtd / currentSecondaryTarget) * 100;
597
 
34641 ranu 598
            double currentMonthUnbilled = partnerWiseActivatedNotBilledTotalMap.get(currentMonth) != null ? partnerWiseActivatedNotBilledTotalMap.get(currentMonth).getTotalUnbilledAmount() : 0d;
34619 ranu 599
 
600
//          this month tertiary----------
601
 
602
            LocalDateTime now = LocalDateTime.now();
603
            double todaySale = fofoOrderItemRepository.selectSumMopGroupByRetailer(startOfToday, now, fofoId, false).get(fofoId);
604
            double mtdSaleTillYesterDay = fofoOrderItemRepository.selectSumMopGroupByRetailer(startOfToday.withDayOfMonth(1), startOfToday, fofoId, false).get(fofoId);
605
            double mtdSale = mtdSaleTillYesterDay + todaySale;
606
 
607
 
34606 ranu 608
//            last month secondary target
609
 
34619 ranu 610
            double lastMonthSecondaryTarget = monthlyTargetRepository.selectByDateAndFofoId(lastMonth, fofoId) != null ?  monthlyTargetRepository.selectByDateAndFofoId(lastMonth, fofoId).getPurchaseTarget() : 0;
34606 ranu 611
 
34619 ranu 612
            long lastMonthReturn = (lastMonthPartnerReturnOrderInfoModelMap.getOrDefault(fofoId,0L) + lastMonthRtoRefundOrderMap.getOrDefault(fofoId,0L));
613
 
34606 ranu 614
            Map<Integer, Double> lastMonthSecondary = orderRepository.selectOrderValueBetweenDatesGroupByFofoId(Arrays.asList(fofoId),
615
                    Arrays.asList(OrderStatus.BILLED, OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.DELIVERY_SUCCESS, OrderStatus.ACCEPTED, OrderStatus.SUBMITTED_FOR_PROCESSING),
616
                    lastMontStartDate, lastMonthEndDate).stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getAmount()));
617
 
618
            double lastMonthSecondaryAchieved = lastMonthSecondary.getOrDefault(fofoId, 0.0);
619
 
34619 ranu 620
            double lastMonthNetSecondary = lastMonthSecondaryAchieved - lastMonthReturn;
34606 ranu 621
 
34619 ranu 622
            double lastMonthSecondaryPercent = lastMonthSecondaryTarget == 0 ? 0.0 : (lastMonthSecondaryAchieved / lastMonthSecondaryTarget) * 100;
34606 ranu 623
 
34641 ranu 624
            double lastMonthUnbilled = partnerWiseActivatedNotBilledTotalMap.get(lastMonth) != null ? partnerWiseActivatedNotBilledTotalMap.get(lastMonth).getTotalUnbilledAmount() : 0d;
34606 ranu 625
 
34619 ranu 626
//           last month tertiary
627
            Double lastMonthSale = fofoOrderItemRepository.selectSumMopGroupByRetailer(
628
                    lastMontStartDate, lastMonthEndDate, fofoId, false).get(fofoId);
629
 
630
 
631
//            two month ago secondary target
632
 
633
            double twoMonthAgoSecondaryTarget = monthlyTargetRepository.selectByDateAndFofoId(lastMonth, fofoId) != null ? monthlyTargetRepository.selectByDateAndFofoId(lastMonth, fofoId).getPurchaseTarget() : 0;
634
 
635
            long twoMonthAgoReturn = (twoMonthAgoPartnerReturnOrderInfoModelMap.getOrDefault(fofoId,0L) + twoMonthAgoRtoRefundOrderMap.getOrDefault(fofoId,0L));
636
 
34606 ranu 637
            Map<Integer, Double> twoMonthAgoSecondary = orderRepository.selectOrderValueBetweenDatesGroupByFofoId(Arrays.asList(fofoId),
638
                    Arrays.asList(OrderStatus.BILLED, OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.DELIVERY_SUCCESS, OrderStatus.ACCEPTED, OrderStatus.SUBMITTED_FOR_PROCESSING),
639
                    twoMonthsAgoStartDate, twoMonthsAgoEndDate).stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getAmount()));
640
 
641
            double twoMonthAgoSecondaryAchieved = twoMonthAgoSecondary.getOrDefault(fofoId, 0.0);
642
 
34619 ranu 643
            double twoMonthAgoNetSecondary = twoMonthAgoSecondaryAchieved - twoMonthAgoReturn;
34606 ranu 644
 
34619 ranu 645
            double twoMonthAgoSecondaryPercent = twoMonthAgoSecondaryTarget == 0 ? 0.0 : (twoMonthAgoSecondaryAchieved / twoMonthAgoSecondaryTarget) * 100;
646
 
34641 ranu 647
            double twoMonthAgoUnbilled = partnerWiseActivatedNotBilledTotalMap.get(twoMonthsAgo) != null ? partnerWiseActivatedNotBilledTotalMap.get(twoMonthsAgo).getTotalUnbilledAmount() : 0d;
34619 ranu 648
 
649
//          second Month Tertiary
650
            double twoMonthAgoSale = fofoOrderItemRepository.selectSumMopGroupByRetailer(
651
                    twoMonthsAgoStartDate, twoMonthsAgoEndDate, fofoId, false).get(fofoId);
652
 
653
 
654
            Map<YearMonth, BiSecondaryModel> monthlySecondaryModels = new HashMap<>();
655
 
656
            BiSecondaryModel currentMonthSecondaryModel = new BiSecondaryModel(
657
                    currentSecondaryTarget,
658
                    secondaryAchievedMtd,
659
                    currentMonthReturn,
660
                    currentMonthNetSecondary,
661
                    currentMonthSecondaryPercent,
662
                    mtdSale,
663
                    currentMonthUnbilled // for now, unbilled tertiary value
664
            );
665
 
666
            BiSecondaryModel lastMonthSecondaryModel = new BiSecondaryModel(
667
                    lastMonthSecondaryTarget,
668
                    lastMonthSecondaryAchieved,
669
                    lastMonthReturn,
670
                    lastMonthNetSecondary,
671
                    lastMonthSecondaryPercent,
672
                    lastMonthSale,
673
                    lastMonthUnbilled // for now, unbilled tertiary value
674
            );
675
 
676
            BiSecondaryModel twoMonthAgoSecondaryModel = new BiSecondaryModel(
677
                    twoMonthAgoSecondaryTarget,
678
                    twoMonthAgoSecondaryAchieved,
679
                    twoMonthAgoReturn,
680
                    twoMonthAgoNetSecondary,
681
                    twoMonthAgoSecondaryPercent,
682
                    twoMonthAgoSale,
683
                    twoMonthAgoUnbilled // for now, unbilled tertiary value
684
            );
685
 
686
            monthlySecondaryModels.put(currentMonth, currentMonthSecondaryModel);
687
            monthlySecondaryModels.put(lastMonth, lastMonthSecondaryModel);
688
            monthlySecondaryModels.put(twoMonthsAgo, twoMonthAgoSecondaryModel);
689
 
690
            allRetailerMonthlyData.put(fofoId, monthlySecondaryModels);
691
 
692
//            brandwiseStock value price
693
 
694
            Map<String, BrandStockPrice> brandStockPriceMap = inventoryService.getBrandWiseStockValue(fofoId);
695
 
696
            fofoBrandStockPriceMap.put(fofoId,brandStockPriceMap);
697
 
698
            double totalStockPrice = brandStockPriceMap.values().stream().mapToDouble(x->x.getTotalValue()).sum();
699
 
700
            fofoTotalStockPriceMap.put(fofoId,totalStockPrice);
701
 
702
            Map<String, Double> brandMtdTertiaryAmount = fofoOrderItemRepository.selectSumAmountGroupByBrand(
703
                    currentMonthStartDate, currentMonthEndDate, fofoId);
704
 
34641 ranu 705
            fofoBrandMtdTertiaryMap.put(fofoId,brandMtdTertiaryAmount);
34619 ranu 706
 
707
            double totalMtdTertiaryAmount = brandMtdTertiaryAmount.values().stream().mapToDouble(Double::doubleValue).sum();
708
 
34641 ranu 709
            fofoTotalMtdTertiaryMap.put(fofoId,totalMtdTertiaryAmount);
34619 ranu 710
 
34641 ranu 711
            List<BrandWiseModel> brandWiseMtdSecondary = orderRepository.selectAllBilledOrderGroupByBrandFofoId(fofoId, currentMonthStartDate);
712
            Map<String,Long> brandWiseMtdSecondaryMap = brandWiseMtdSecondary.stream().collect(Collectors.toMap(BrandWiseModel::getBrand,BrandWiseModel::getAmount));
713
            fofoBrandWiseMtdSecondaryMap.put(fofoId,brandWiseMtdSecondaryMap);
34619 ranu 714
 
34641 ranu 715
            long mtdTotalSecondary = brandWiseMtdSecondary.stream().mapToLong(x -> x.getAmount() != 0 ? x.getAmount() : 0L).sum();
34619 ranu 716
 
34641 ranu 717
            fofoTotalMtdSecondaryMap.put(fofoId,mtdTotalSecondary);
718
 
719
            //            generate investment info
720
            FofoStore fofoStore = fofoStoreRepository.selectByRetailerId(fofoId);
721
            float shortInvestment = partnerDailyInvestmentMap.get(fofoId) != null ? partnerDailyInvestmentMap.get(fofoId).getShortInvestment() : 0f;
722
            float agreedInvestment = partnerDailyInvestmentMap.get(fofoId) != null ? partnerDailyInvestmentMap.get(fofoId).getMinInvestment() : 0f;
723
            float investmentLevel = partnerDailyInvestmentMap.get(fofoId) != null ? ((shortInvestment-agreedInvestment)/agreedInvestment)*100 : 0f;
724
 
725
            List<Loan> fofoDefaultLoans = new ArrayList<>();
726
            if(defaultLoanMap != null){
727
                 fofoDefaultLoans  =  defaultLoanMap.get(fofoId);
728
                LOGGER.info("fofoDefaultLoans {}",fofoDefaultLoans);
729
            }
730
 
731
            float defaultLoanAmount = 0f;
732
            if(fofoDefaultLoans != null ){
733
                if (!fofoDefaultLoans.isEmpty()) {
734
                    defaultLoanAmount =  fofoDefaultLoans.stream().map(Loan::getPendingAmount).reduce(BigDecimal.ZERO, BigDecimal::add).floatValue(); // or .floatValue() directly
735
                }
736
            }
737
 
738
            float activeLoan = loanRepository.selectActiveLoan(fofoId).stream().map(Loan::getPendingAmount).reduce(BigDecimal.ZERO,BigDecimal::add).floatValue();
739
 
740
 
741
            float poValue = partnerDailyInvestmentMap.get(fofoId) != null ?  partnerDailyInvestmentMap.get(fofoId).getUnbilledAmount() : 0f;
742
 
743
            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));
744
            float poAndBilledValue = (float) billedAndPoOrder.stream().map(Order::getTotalAmount).reduce(0f,Float::sum);
745
 
746
            double purchaseMtd = secondaryMtd.getOrDefault(fofoId, 0.0);
747
 
748
            double todayRequiredDrr = rbmTargetService.calculateFofoIdTodayTarget(fofoId, purchaseMtd,LocalDate.now());
749
 
750
            double monthDay1Drr = rbmTargetService.calculateFofoIdTodayTarget(fofoId,0d,YearMonth.now().atDay(1));
751
 
752
 
753
            double gotDrrPercent = (todayRequiredDrr / monthDay1Drr) * 100;
754
 
755
            int orderId = orderRepository.getLastOrderByFofoId(fofoId);
756
 
34644 ranu 757
            // Determine alert level
758
            String alertLevel = "-";
759
            int lastPurchaseDays = 0;
34641 ranu 760
            if (orderId != 0) {
761
                Order order = orderRepository.selectById(orderId);
762
 
763
                // Calculate the number of days since the last purchase (billing)
34644 ranu 764
                lastPurchaseDays = (int) Duration.between(order.getCreateTimestamp().plusDays(1), LocalDateTime.now()).toDays();
34641 ranu 765
 
766
                if (lastPurchaseDays >= 11) {
767
                    alertLevel = "Alert for Management";
768
                } else if (lastPurchaseDays >= 8) {
769
                    alertLevel = " Alert for RSM/SH";
770
                } else if (lastPurchaseDays >= 6) {
771
                    alertLevel = "Must be Billed";
772
                } else if (lastPurchaseDays >= 3) {
773
                    alertLevel = "OK";
774
                } else {
775
                    alertLevel = "No Action Needed";
776
                }
34644 ranu 777
            }
34641 ranu 778
 
34644 ranu 779
            //investment modal set all related value
780
            FofoInvestmentModel fofoInvestmentModel = new FofoInvestmentModel();
34641 ranu 781
 
34644 ranu 782
            fofoInvestmentModel.setCounterPotential(fofoStore.getCounterPotential());
783
            fofoInvestmentModel.setShortInvestment(shortInvestment);
784
            fofoInvestmentModel.setDefaultLoan(defaultLoanAmount);
785
            fofoInvestmentModel.setInvestmentLevel(investmentLevel);
786
            fofoInvestmentModel.setActiveLoan(activeLoan);
787
            fofoInvestmentModel.setPoValue(poValue);
788
            fofoInvestmentModel.setPoAndBilled(poAndBilledValue);
789
            fofoInvestmentModel.setAgreedInvestment(agreedInvestment);
790
            fofoInvestmentModel.setWallet(partnerDailyInvestmentMap.get(fofoId) != null ? partnerDailyInvestmentMap.get(fofoId).getWalletAmount() : 0);
791
            fofoInvestmentModel.setMonthBeginingDrr(monthDay1Drr);
792
            fofoInvestmentModel.setRequiredDrr(todayRequiredDrr);
793
            fofoInvestmentModel.setDrrPercent(gotDrrPercent);
794
            fofoInvestmentModel.setLastBillingDone(lastPurchaseDays);
795
            fofoInvestmentModel.setSlab(alertLevel);
34641 ranu 796
 
34644 ranu 797
            biInvestmentModelMap.put(fofoId, fofoInvestmentModel);
34641 ranu 798
                String assessment = "";
799
                if(defaultLoanAmount > 0 ){
800
                    assessment = "Loan Default";
801
                }else if(investmentLevel <= 75 && defaultLoanAmount < 1){
802
                    assessment = "Low Invest";
803
                }else {
804
                    assessment = "-";
805
                }
806
                assessmentMap.put(fofoId,assessment);
807
 
808
                String zeroBilling = "";
809
                if(currentMonthNetSecondary <= 100000 ){
810
                    zeroBilling = "Zero Billing";
811
                }else {
812
                    zeroBilling = "-";
813
                }
814
                zeroBillingMap.put(fofoId,zeroBilling);
815
 
816
                float billingNeeded = 0f;
817
                if(gotDrrPercent >= 110 ){
818
                    billingNeeded = (float) todayRequiredDrr;
819
                }else {
820
                    billingNeeded = 0f;
821
                }
822
                billingNeededMap.put(fofoId,billingNeeded);
823
 
824
                int counta = 0;
825
                if(defaultLoanAmount > 0 || investmentLevel <= 75 || currentMonthNetSecondary <= 100000 || gotDrrPercent >= 110 ){
826
                    counta = 1;
827
                }else {
828
                    counta = 0;
829
                }
830
                countAMap.put(fofoId,counta);
831
 
34606 ranu 832
        }
833
 
34619 ranu 834
        LOGGER.info("Total BI Retailers processed: {}", biRetailerModelMap.size());
34606 ranu 835
 
34619 ranu 836
        //generate excel and sent to mail
837
        List<List<String>> headerGroup = new ArrayList<>();
34606 ranu 838
 
34619 ranu 839
        List<String> headers1 = Arrays.asList(
34641 ranu 840
                "","","","",
841
                "Retailer Detail", "", "", "", "", "", "", "", "",
34619 ranu 842
                currentMonthStringValue, "", "", "", "", "", "",
843
                lastMonthStringValue, "", "", "", "", "", "",
34641 ranu 844
                twoMonthAgoStringValue, "", "", "", "", "", "",
845
 
846
                "","", "", "", "", "", "", "", "", "", "", "", "", "",
847
 
848
                "", "", "", "", "", "", "", "", "", "", "", "", "",
849
                "", "", "", "", "", "", "", "", "", "", "", "", ""
850
 
34619 ranu 851
        );
34606 ranu 852
 
34619 ranu 853
        List<String> headers2 = Arrays.asList(
34641 ranu 854
                "Assessment","Zero billing","Billing needed","Counta",
34619 ranu 855
                "Code", "Store Name", "City", "Area", "BM", "Sales Manager", "RBM", "Status", "Category",
856
                "Secondary Target", "Secondary Achieved", "Returns", "Net Secondary", "Secondary %",
857
                "Tertiary Sale", "Unbilled",
858
                "Secondary Target", "Secondary Achieved", "Returns", "Net Secondary", "Secondary %",
859
                "Tertiary Sale", "Unbilled",
860
                "Secondary Target", "Secondary Achieved", "Returns", "Net Secondary", "Secondary %",
861
                "Tertiary Sale", "Unbilled",
34641 ranu 862
                "Counter Potential", "Short investment", "Default", "INVESTMENT LEVEL", "Loan", "PO value", "Agreed investment",
863
                "Wallet", "po+bill", "MONTH BEGINNING DRR", "REQ DRR", "Drr %", "Last billing Done", "Slab",
34606 ranu 864
 
34641 ranu 865
              "Total Stock",  "Apple","Xiaomi", "Vivo", "Tecno", "Samsung", "Realme", "Oppo", "OnePlus", "Poco", "Lava", "Itel", "Almost New",
866
              "Total Secondary", "Apple", "Xiaomi", "Vivo", "Tecno", "Samsung", "Realme", "Oppo", "OnePlus", "Poco", "Lava", "Itel", "Almost New",
867
              "Total Tertiary",  "Apple", "Xiaomi", "Vivo", "Tecno", "Samsung", "Realme", "Oppo", "OnePlus", "Poco", "Lava", "Itel", "Almost New"
34619 ranu 868
        );
869
 
870
        headerGroup.add(headers1);
871
        headerGroup.add(headers2);
872
 
873
 
874
        List<List<?>> rows = new ArrayList<>();
875
        for (Map.Entry<Integer, BIRetailerModel> entry : biRetailerModelMap.entrySet()) {
876
            Integer fofoId = entry.getKey();
877
            BIRetailerModel retailer = entry.getValue();
34641 ranu 878
 
34619 ranu 879
            Map<YearMonth, BiSecondaryModel> monthlyData = allRetailerMonthlyData.get(fofoId);
880
 
881
            BiSecondaryModel current = monthlyData.getOrDefault(YearMonth.now(), new BiSecondaryModel(0,0,0,0,0,0,0));
882
            BiSecondaryModel last = monthlyData.getOrDefault(YearMonth.now().minusMonths(1), new BiSecondaryModel(0,0,0,0,0,0,0));
883
            BiSecondaryModel twoAgo = monthlyData.getOrDefault(YearMonth.now().minusMonths(2), new BiSecondaryModel(0,0,0,0,0,0,0));
884
 
885
            List<Object> row = new ArrayList<>();
886
            row.addAll(Arrays.asList(
34641 ranu 887
                    assessmentMap.get(fofoId),zeroBillingMap.get(fofoId),billingNeededMap.get(fofoId),countAMap.get(fofoId),
34619 ranu 888
                    retailer.getCode(), retailer.getStoreName(), retailer.getCity(), retailer.getArea(),
889
                    retailer.getBmName(), retailer.getSalesManager(), retailer.getRbm(),
890
                    retailer.getStatus(), retailer.getCategory()
891
            ));
892
 
893
            // Current Month
894
            row.addAll(Arrays.asList(
895
                    current.getSecondaryTarget(),
896
                    current.getSecondaryAchieved(),
897
                    current.getSecondaryReturn(),
898
                    current.getNetSecondary(),
899
                    current.getSecondaryAchievedPercent(),
900
                    current.getTertiary(),
901
                    current.getTertiaryUnBilled()
902
            ));
903
 
904
            // Last Month
905
            row.addAll(Arrays.asList(
906
                    last.getSecondaryTarget(),
907
                    last.getSecondaryAchieved(),
908
                    last.getSecondaryReturn(),
909
                    last.getNetSecondary(),
910
                    last.getSecondaryAchievedPercent(),
911
                    last.getTertiary(),
912
                    last.getTertiaryUnBilled()
913
            ));
914
 
915
            // Two Months Ago
916
            row.addAll(Arrays.asList(
917
                    twoAgo.getSecondaryTarget(),
918
                    twoAgo.getSecondaryAchieved(),
919
                    twoAgo.getSecondaryReturn(),
920
                    twoAgo.getNetSecondary(),
921
                    twoAgo.getSecondaryAchievedPercent(),
922
                    twoAgo.getTertiary(),
923
                    twoAgo.getTertiaryUnBilled()
924
            ));
34641 ranu 925
            FofoInvestmentModel fofoInvestmentModelValue = biInvestmentModelMap.get(fofoId);
926
            if(fofoInvestmentModelValue != null){
927
                row.addAll(Arrays.asList(
928
                        fofoInvestmentModelValue.getCounterPotential(),
929
                        fofoInvestmentModelValue.getShortInvestment(),
930
                        fofoInvestmentModelValue.getDefaultLoan(),
931
                        fofoInvestmentModelValue.getInvestmentLevel(),
932
                        fofoInvestmentModelValue.getActiveLoan(),
933
                        fofoInvestmentModelValue.getPoValue(),
934
                        fofoInvestmentModelValue.getAgreedInvestment(),
935
                        fofoInvestmentModelValue.getWallet(),
936
                        fofoInvestmentModelValue.getPoAndBilled(),
937
                        fofoInvestmentModelValue.getMonthBeginingDrr(),
938
                        fofoInvestmentModelValue.getRequiredDrr(),
939
                        fofoInvestmentModelValue.getDrrPercent(),
940
                        fofoInvestmentModelValue.getLastBillingDone(),
941
                        fofoInvestmentModelValue.getSlab()
942
                ));
943
            }else {
944
                row.addAll(Arrays.asList(
945
                        "-","-","-","-","-","-","-","-","-","-","-",""
946
                ));
947
            }
948
 
949
            Map<String, BrandStockPrice> brandStockMap = fofoBrandStockPriceMap.get(fofoId);
34619 ranu 950
            row.addAll(Arrays.asList(
951
                    fofoTotalStockPriceMap.getOrDefault(fofoId, 0.0),
34641 ranu 952
                    brandStockMap.get("Apple") != null ? brandStockMap.get("Apple").getTotalValue() : 0.0,
953
                    brandStockMap.get("Xiaomi") != null ? brandStockMap.get("Xiaomi").getTotalValue() : 0.0,
954
                    brandStockMap.get("Vivo") != null ? brandStockMap.get("Vivo").getTotalValue() : 0.0,
955
                    brandStockMap.get("Tecno") != null ? brandStockMap.get("Tecno").getTotalValue() : 0.0,
956
                    brandStockMap.get("Samsung") != null ? brandStockMap.get("Samsung").getTotalValue() : 0.0,
957
                    brandStockMap.get("Realme") != null ? brandStockMap.get("Realme").getTotalValue() : 0.0,
958
                    brandStockMap.get("Oppo") != null ? brandStockMap.get("Oppo").getTotalValue() : 0.0,
959
                    brandStockMap.get("OnePlus") != null ? brandStockMap.get("OnePlus").getTotalValue() : 0.0,
960
                    brandStockMap.get("Poco") != null ? brandStockMap.get("Poco").getTotalValue() : 0.0,
961
                    brandStockMap.get("Lava") != null ? brandStockMap.get("Lava").getTotalValue() : 0.0,
962
                    brandStockMap.get("Itel") != null ? brandStockMap.get("Itel").getTotalValue() : 0.0,
963
                    brandStockMap.get("Almost New") != null ? brandStockMap.get("Almost New").getTotalValue() : 0.0
34619 ranu 964
            ));
965
 
34641 ranu 966
            Map<String, Long> brandSecondaryMap = fofoBrandWiseMtdSecondaryMap.get(fofoId);
967
            row.addAll(Arrays.asList(
34648 ranu 968
                    fofoTotalMtdSecondaryMap.get(fofoId),
34641 ranu 969
                    brandSecondaryMap.getOrDefault("Apple", 0L),
970
                    brandSecondaryMap.getOrDefault("Xiaomi", 0L),
971
                    brandSecondaryMap.getOrDefault("Vivo", 0L),
972
                    brandSecondaryMap.getOrDefault("Tecno", 0L),
973
                    brandSecondaryMap.getOrDefault("Samsung", 0L),
974
                    brandSecondaryMap.getOrDefault("Realme", 0L),
975
                    brandSecondaryMap.getOrDefault("Oppo", 0L),
976
                    brandSecondaryMap.getOrDefault("OnePlus", 0L),
977
                    brandSecondaryMap.getOrDefault("Poco", 0L),
978
                    brandSecondaryMap.getOrDefault("Lava", 0L),
979
                    brandSecondaryMap.getOrDefault("Itel", 0L),
980
                    brandSecondaryMap.getOrDefault("Almost New", 0L)
981
            ));
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
}