Rev 34606 | Rev 34641 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed
package com.smartdukaan.cron.scheduled;import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;import com.spice.profitmandi.common.model.BrandStockPrice;import com.spice.profitmandi.common.model.CustomRetailer;import com.spice.profitmandi.common.model.ProfitMandiConstants;import com.spice.profitmandi.common.util.FileUtil;import com.spice.profitmandi.common.util.FormattingUtils;import com.spice.profitmandi.common.util.Utils;import com.spice.profitmandi.dao.cart.CartService;import com.spice.profitmandi.dao.cart.SmartCartService;import com.spice.profitmandi.dao.entity.auth.AuthUser;import com.spice.profitmandi.dao.entity.fofo.*;import com.spice.profitmandi.dao.entity.logistics.AST;import com.spice.profitmandi.dao.entity.logistics.ASTRepository;import com.spice.profitmandi.dao.entity.logistics.AreaRepository;import com.spice.profitmandi.dao.entity.transaction.*;import com.spice.profitmandi.dao.entity.user.User;import com.spice.profitmandi.dao.enumuration.cs.EscalationType;import com.spice.profitmandi.dao.enumuration.transaction.LoanReferenceType;import com.spice.profitmandi.dao.model.BIRetailerModel;import com.spice.profitmandi.dao.model.BiSecondaryModel;import com.spice.profitmandi.dao.model.BrandWiseModel;import com.spice.profitmandi.dao.model.ReturnOrderInfoModel;import com.spice.profitmandi.dao.repository.auth.AuthRepository;import com.spice.profitmandi.dao.repository.cs.CsService;import com.spice.profitmandi.dao.repository.dtr.FofoStoreRepository;import com.spice.profitmandi.dao.repository.fofo.*;import com.spice.profitmandi.dao.repository.inventory.StateRepository;import com.spice.profitmandi.dao.repository.transaction.*;import com.spice.profitmandi.dao.repository.user.UserRepository;import com.spice.profitmandi.service.inventory.InventoryService;import com.spice.profitmandi.service.transaction.SDCreditService;import com.spice.profitmandi.service.user.RetailerService;import com.spice.profitmandi.service.wallet.WalletService;import in.shop2020.model.v1.order.OrderStatus;import in.shop2020.model.v1.order.WalletReferenceType;import org.apache.commons.io.output.ByteArrayOutputStream;import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;import org.apache.poi.ss.usermodel.Row;import org.apache.poi.ss.usermodel.Sheet;import org.apache.poi.ss.usermodel.Workbook;import org.apache.poi.xssf.usermodel.XSSFWorkbook;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Qualifier;import org.springframework.beans.factory.annotation.Value;import org.springframework.core.io.ByteArrayResource;import org.springframework.mail.javamail.JavaMailSender;import org.springframework.mail.javamail.MimeMessageHelper;import org.springframework.stereotype.Component;import org.springframework.transaction.annotation.Transactional;import javax.mail.MessagingException;import javax.mail.internet.InternetAddress;import javax.mail.internet.MimeMessage;import java.io.*;import java.math.BigDecimal;import java.time.LocalDate;import java.time.LocalDateTime;import java.time.LocalTime;import java.time.YearMonth;import java.time.temporal.ChronoUnit;import java.util.*;import java.util.stream.Collectors;import java.util.stream.Stream;@Component@Transactional(rollbackFor = {Throwable.class, ProfitMandiBusinessException.class})public class ScheduledTasksTest {private static final Logger LOGGER = LogManager.getLogger(ScheduledTasksTest.class);@AutowiredTransactionRepository transactionRepository;@Autowired@Qualifier(value = "googleMailSender")private JavaMailSender googleMailSender;@AutowiredLoanRepository loanRepository;@AutowiredSDCreditService sdCreditService;@AutowiredUserRepository userRepository;@AutowiredCsService csService;@AutowiredRbmRatingRepository rbmRatingRepository;@Autowiredprivate JavaMailSender mailSender;@AutowiredSalesRatingRepository salesRatingRepository;@AutowiredFofoStoreRepository fofoStoreRepository;@AutowiredSmartCartService smartCartService;@AutowiredRetailerService retailerService;@AutowiredASTRepository astRepository;@AutowiredAuthRepository authRepository;@AutowiredStateRepository stateRepository;@AutowiredMonthlyTargetRepository monthlyTargetRepository;@AutowiredPartnerTypeChangeService partnerTypeChangeService;@AutowiredReturnOrderInfoRepository returnOrderInfoRepository;@AutowiredOrderRepository orderRepository;@AutowiredFofoOrderItemRepository fofoOrderItemRepository;@AutowiredInventoryService inventoryService;@AutowiredUserWalletRepository userWalletRepository;@AutowiredLoanStatementRepository loanStatementRepository;@AutowiredWalletService walletService;public void test() throws Exception {System.out.println("test start");//this.generateBiReportExcel();this.loanSettle();System.out.println("test end");}public void createLoanForBillingByTransactionIdAndInvoiceNumber(int transactionId, double invoiceAmount, String invoiceNumber) throws Exception {sdCreditService.createLoanForBilling(transactionId, invoiceAmount, invoiceNumber);}public void loanSettle() throws Exception {List<Integer> refrences = Arrays.asList(25807,36003,38938,39506,42219,45084);for(Integer ref : refrences){List<LoanStatement> loanStatements = loanStatementRepository.selectByLoanId(ref);double amountSum = loanStatements.stream().map(LoanStatement::getAmount).mapToDouble(BigDecimal::doubleValue).sum();if(amountSum > 0){walletService.addAmountToWallet(loanStatements.get(0).getFofoId(),ref, WalletReferenceType.CREDIT_LIMIT,"Amount reversal against credit limit deduction",(float) amountSum,LocalDateTime.now());// Loan statement entryBigDecimal adjustAmount = BigDecimal.valueOf(amountSum).negate(); // or multiply by -1LoanStatement loanStatement = new LoanStatement();loanStatement.setAmount(adjustAmount);loanStatement.setFofoId(loanStatements.get(0).getFofoId());loanStatement.setLoanReferenceType(LoanReferenceType.PRINCIPAL);loanStatement.setCreatedAt(LocalDateTime.now());loanStatement.setDescription("Amount reversal due to access debit against limit");loanStatement.setLoanId(ref);loanStatement.setBusinessDate(LocalDateTime.now());loanStatementRepository.persist(loanStatement);Loan loan = loanRepository.selectByLoanId(ref);loan.setPendingAmount(BigDecimal.valueOf(0));loan.setSettledOn(LocalDateTime.now());}}}private void sendMailHtmlFormat(String email[], String body, String cc[], String bcc[], String subject)throws MessagingException, ProfitMandiBusinessException, IOException {MimeMessage message = mailSender.createMimeMessage();MimeMessageHelper helper = new MimeMessageHelper(message);helper.setSubject(subject);helper.setText(body, true);helper.setTo(email);if (cc != null) {helper.setCc(cc);}if (bcc != null) {helper.setBcc(bcc);}InternetAddress senderAddress = new InternetAddress("noreply@smartdukaan.com", "Smart Dukaan");helper.setFrom(senderAddress);mailSender.send(message);}public Map<Integer,Integer> findLoanTransactionMapingAccordingLoan(List<Integer> loanIds) throws ProfitMandiBusinessException {Map<Integer, Integer> transactionLoanMap = new HashMap<>();for(int loanId : loanIds){Transaction transaction = null;Loan loan = loanRepository.selectByLoanId(loanId);List<Transaction> transactions = transactionRepository.selectByRetailerId(loan.getFofoId());LocalDateTime nearestDateTime = transactions.stream().map(x -> x.getCreateTimestamp()).min(Comparator.comparingLong(x -> Math.abs(ChronoUnit.MILLIS.between(x, loan.getCreatedOn())))).orElse(null);if (nearestDateTime != null && loan.getCreatedOn().plusMinutes(2).isAfter(nearestDateTime) &&loan.getCreatedOn().minusMinutes(1).isBefore(nearestDateTime)) {// Here transaction is still nulltransaction = transactions.stream().filter(x -> x.getCreateTimestamp().equals(nearestDateTime)).findFirst().get();transactionLoanMap.put(transaction.getId(), loanId);}}LOGGER.info("transactionLoanMap {}",transactionLoanMap);return transactionLoanMap;}public void sendRbmFeedbackSummaryEmail() throws MessagingException, ProfitMandiBusinessException, IOException {LocalDateTime startOfMonth = LocalDate.now().withDayOfMonth(1).atStartOfDay();LocalDateTime endOfMonth = LocalDateTime.now();String[] bcc = {"tarun.verma@smartdukaan.com"};// Get all RBM usersList<AuthUser> authUsers = csService.getAuthUserIds(ProfitMandiConstants.TICKET_CATEGORY_RBM,Arrays.asList(EscalationType.L1));if (authUsers.isEmpty()) {LOGGER.info("No RBMs found.");return;}List<Integer> rbmIds = authUsers.stream().map(AuthUser::getId).collect(Collectors.toList());// Fetch ratings for all RBMs for current monthList<RbmRating> feedbackList = rbmRatingRepository.selectByRbmIdsAndDateRange(rbmIds, startOfMonth, endOfMonth);if (feedbackList.isEmpty()) {LOGGER.info("No feedback entries found for RBMs.");return;}// Sort feedback by createTimeStamp DESCfeedbackList.sort((a, b) -> b.getCreateTimeStamp().compareTo(a.getCreateTimeStamp()));// Fetch and map FOFO (partner) namesMap<Integer, String> fofoNameMap = new HashMap<>();for (RbmRating rating : feedbackList) {int fofoId = rating.getFofoId();if (!fofoNameMap.containsKey(fofoId)) {User fofoUser = userRepository.selectById(fofoId);FofoStore fofoStore = fofoStoreRepository.selectByRetailerId(fofoId);String partnerName = fofoUser != null ? fofoUser.getName() : "Unknown Partner";String storeCode = fofoStore != null ? fofoStore.getCode() : "Unknown Code";String displayName = partnerName + " (" + storeCode + ")";fofoNameMap.put(fofoId, displayName);}}// Map RBM ID to name for quick lookupMap<Integer, String> rbmNameMap = authUsers.stream().collect(Collectors.toMap(AuthUser::getId, AuthUser::getFullName));// Generate HTML contentStringBuilder emailContent = new StringBuilder();emailContent.append("<html><body>");emailContent.append("<p>Dear Team,</p>");emailContent.append("<p>Here is the <b>latest RBM Rating and Feedback Summary</b> for ").append(LocalDate.now().getMonth()).append(":</p>");emailContent.append("<table border='1' cellspacing='0' cellpadding='5'>");emailContent.append("<tr>").append("<th>RBM Name</th>").append("<th>Partner Name</th>").append("<th>Rating</th>").append("<th>Comment</th>").append("<th>Date</th>").append("</tr>");for (RbmRating rating : feedbackList) {String rbmName = rbmNameMap.getOrDefault(rating.getRbmId(), "Unknown RBM");String partnerName = fofoNameMap.getOrDefault(rating.getFofoId(), "Unknown Partner");emailContent.append("<tr>").append("<td>").append(rbmName).append("</td>").append("<td>").append(partnerName).append("</td>").append("<td>").append(rating.getRating()).append("</td>").append("<td>").append(rating.getComment() != null ? rating.getComment() : "-").append("</td>").append("<td>").append(rating.getCreateTimeStamp().toLocalDate()).append("</td>").append("</tr>");}emailContent.append("</table>");emailContent.append("<br><p>Regards,<br>Smart Dukaan Team</p>");emailContent.append("</body></html>");String subject = "Monthly RBM Feedback Summary - " + LocalDate.now().getMonth();List<String> sendTo = new ArrayList<>();sendTo.add("sm@smartdukaan.com"); //sendTo.add("chiranjib.sarkar@smartdukaan.com"); //sendTo.add("kamini.sharma@smartdukaan.com"); //String[] emailRecipients = sendTo.toArray(new String[0]);this.sendMailHtmlFormat(emailRecipients, emailContent.toString(), null, bcc, subject);LOGGER.info("Consolidated RBM feedback summary email sent.");}public void sendSalesFeedbackSummaryEmail() throws MessagingException, ProfitMandiBusinessException, IOException {LocalDateTime startOfMonth = LocalDate.now().withDayOfMonth(1).atStartOfDay();LocalDateTime endOfMonth = LocalDateTime.now();String[] bcc = {"tarun.verma@smartdukaan.com"};// String[] bcc = {"tejus.lohani@smartdukaan.com"};// Get all RBM usersList<AuthUser> authUsers = csService.getAuthUserIds(ProfitMandiConstants.TICKET_CATEGORY_SALES,Arrays.asList(EscalationType.L1));if (authUsers.isEmpty()) {LOGGER.info("No sales person found.");return;}List<Integer> salesL1Ids = authUsers.stream().map(AuthUser::getId).collect(Collectors.toList());// Fetch ratings for all RBMs for current monthList<SalesRating> feedbackList = salesRatingRepository.selectBySalesL1IdsAndDateRange(salesL1Ids, startOfMonth, endOfMonth);if (feedbackList.isEmpty()) {LOGGER.info("No feedback entries found for Sales.");return;}// Sort feedback by createTimeStamp DESCfeedbackList.sort((a, b) -> b.getCreateTimeStamp().compareTo(a.getCreateTimeStamp()));// Fetch and map FOFO (partner) namesMap<Integer, String> fofoNameMap = new HashMap<>();for (SalesRating rating : feedbackList) {int fofoId = rating.getFofoId();if (!fofoNameMap.containsKey(fofoId)) {User fofoUser = userRepository.selectById(fofoId);FofoStore fofoStore = fofoStoreRepository.selectByRetailerId(fofoId);String partnerName = fofoUser != null ? fofoUser.getName() : "Unknown Partner";String storeCode = fofoStore != null ? fofoStore.getCode() : "Unknown Code";String displayName = partnerName + " (" + storeCode + ")";fofoNameMap.put(fofoId, displayName);}}// Map RBM ID to name for quick lookupMap<Integer, String> salesL1NameMap = authUsers.stream().collect(Collectors.toMap(AuthUser::getId, AuthUser::getFullName));// Generate HTML contentStringBuilder emailContent = new StringBuilder();emailContent.append("<html><body>");emailContent.append("<p>Dear Team,</p>");emailContent.append("<p>Here is the <b>latest Sales L1 Rating and Feedback Summary</b> for ").append(LocalDate.now().getMonth()).append(":</p>");emailContent.append("<table border='1' cellspacing='0' cellpadding='5'>");emailContent.append("<tr>").append("<th>Sales L1 Name</th>").append("<th>Partner Name</th>").append("<th>Partner Category</th>").append("<th>Rating</th>").append("<th>Comment</th>").append("<th>Date</th>").append("</tr>");for (SalesRating rating : feedbackList) {String salesL1 = salesL1NameMap.getOrDefault(rating.getSalesL1Id(), "Unknown Sales Person");String partnerName = fofoNameMap.getOrDefault(rating.getFofoId(), "Unknown Partner");PartnerType partnerType = partnerTypeChangeService.getTypeOnDate(rating.getFofoId(), LocalDate.now());emailContent.append("<tr>").append("<td>").append(salesL1).append("</td>").append("<td>").append(partnerName).append("</td>").append("<td>").append(partnerType).append("</td>").append("<td>").append(rating.getRating()).append("</td>").append("<td>").append(rating.getComment() != null ? rating.getComment() : "-").append("</td>").append("<td>").append(rating.getCreateTimeStamp().toLocalDate()).append("</td>").append("</tr>");}emailContent.append("</table>");emailContent.append("<br><p>Regards,<br>Smartdukaan Team</p>");emailContent.append("</body></html>");String subject = "Monthly Sales L1 Feedback Summary Test test - " + LocalDate.now().getMonth();List<String> sendTo = new ArrayList<>();sendTo.add("sm@smartdukaan.com"); //sendTo.add("chiranjib.sarkar@smartdukaan.com"); //sendTo.add("kamini.sharma@smartdukaan.com"); //String[] emailRecipients = sendTo.toArray(new String[0]);this.sendMailHtmlFormat(emailRecipients, emailContent.toString(), null, bcc, subject);LOGGER.info("Consolidated Sales L1 feedback summary email sent.");}public void generateBiReportExcel() throws Exception {LocalDateTime startOfToday = LocalDate.now().atStartOfDay();Map<Integer, CustomRetailer> customRetailers = retailerService.getAllFofoRetailersInternalFalse();List<Integer> retailerIds = customRetailers.values().stream().map(CustomRetailer::getPartnerId).collect(Collectors.toList());// this month return dataYearMonth currentMonth = YearMonth.now();String currentMonthStringValue = String.valueOf(currentMonth);LocalDateTime currentMonthStartDate = YearMonth.now().atDay(1).atStartOfDay();LocalDateTime currentMonthEndDate = LocalDateTime.now();List<ReturnOrderInfoModel> currentMonthReturnOrderInfoModels = returnOrderInfoRepository.selectAllByBetweenDate(currentMonthStartDate, currentMonthEndDate);Map<Integer, Long> currentMonthPartnerReturnOrderInfoModelMap = currentMonthReturnOrderInfoModels.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getRefundAmount()))));List<Order> currentMonthRtoRefundOrders = orderRepository.selectAllOrderDatesBetweenByStatus(currentMonthStartDate, currentMonthEndDate, OrderStatus.RTO_REFUNDED);Map<Integer, Long> currentMonthRtoRefundOrderMap = currentMonthRtoRefundOrders.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getTotalAmount()))));// last month return dataYearMonth lastMonth = YearMonth.now().minusMonths(1);String lastMonthStringValue = String.valueOf(lastMonth);LocalDateTime lastMontStartDate = lastMonth.atDay(1).atStartOfDay();LocalDateTime lastMonthEndDate = lastMonth.atEndOfMonth().atTime(23, 59, 59);List<ReturnOrderInfoModel> lastMonthReturnOrderInfoModels = returnOrderInfoRepository.selectAllByBetweenDate(lastMontStartDate, lastMonthEndDate);Map<Integer, Long> lastMonthPartnerReturnOrderInfoModelMap = lastMonthReturnOrderInfoModels.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getRefundAmount()))));List<Order> lastMonthRtoRefundOrders = orderRepository.selectAllOrderDatesBetweenByStatus(lastMontStartDate, lastMonthEndDate, OrderStatus.RTO_REFUNDED);Map<Integer, Long> lastMonthRtoRefundOrderMap = lastMonthRtoRefundOrders.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getTotalAmount()))));// twoMonthsAgo return dataYearMonth twoMonthsAgo = YearMonth.now().minusMonths(2);String twoMonthAgoStringValue = String.valueOf(twoMonthsAgo);LocalDateTime twoMonthsAgoStartDate = twoMonthsAgo.atDay(1).atStartOfDay();LocalDateTime twoMonthsAgoEndDate = twoMonthsAgo.atEndOfMonth().atTime(23, 59, 59);List<ReturnOrderInfoModel> twoMonthAgoReturnOrderInfoModels = returnOrderInfoRepository.selectAllByBetweenDate(twoMonthsAgoStartDate, twoMonthsAgoEndDate);Map<Integer, Long> twoMonthAgoPartnerReturnOrderInfoModelMap = twoMonthAgoReturnOrderInfoModels.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getRefundAmount()))));List<Order> twoMonthRtoRefundOrders = orderRepository.selectAllOrderDatesBetweenByStatus(twoMonthsAgoStartDate, twoMonthsAgoEndDate, OrderStatus.RTO_REFUNDED);Map<Integer, Long> twoMonthAgoRtoRefundOrderMap = twoMonthRtoRefundOrders.stream().collect(Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingLong(x -> Math.round(x.getTotalAmount()))));Map<Integer , BIRetailerModel> biRetailerModelMap = new HashMap<>();Map<Integer, Map<YearMonth, BiSecondaryModel>> allRetailerMonthlyData = new HashMap<>();Map<Integer,Double> fofoTotalStockPriceMap = new HashMap<>();Map<Integer,Map<String, BrandStockPrice>> fofoBrandStockPriceMap = new HashMap<>();Map<Integer,Double> fofoTotalTertiaryMap = new HashMap<>();Map<Integer,Map<String, Double>> fofoBrandTertiaryMap = new HashMap<>();for(Integer fofoId: retailerIds){String rbmName = "";int rbmL1 = csService.getAuthUserId(ProfitMandiConstants.TICKET_CATEGORY_RBM,EscalationType.L1,fofoId);if(rbmL1 != 0){rbmName = authRepository.selectById(rbmL1).getFullName();}String bmName ="";int bmId = csService.getAuthUserId(ProfitMandiConstants.TICKET_CATEGORY_SALES,EscalationType.L2,fofoId);if(bmId !=0){bmName = authRepository.selectById(bmId).getFullName();}int managerId = csService.getAuthUserId(ProfitMandiConstants.TICKET_CATEGORY_SALES,EscalationType.L1,fofoId);String managerName = " ";if(managerId != 0){managerName = authRepository.selectById(managerId).getFullName();}else {managerName = bmName;}AST ast = astRepository.selectById(customRetailers.get(fofoId).getAstId());PartnerType partnerTypeThisMonth = partnerTypeChangeService.getTypeOnMonth(fofoId, YearMonth.now());// generate retaile detailBIRetailerModel biRetailerModel = new BIRetailerModel();biRetailerModel.setBmName(bmName);biRetailerModel.setCode(customRetailers.get(fofoId).getCode());if(ast != null){biRetailerModel.setArea(ast.getArea());}else {biRetailerModel.setArea("-");}biRetailerModel.setCity(customRetailers.get(fofoId).getAddress().getCity());biRetailerModel.setStoreName(customRetailers.get(fofoId).getBusinessName());biRetailerModel.setStatus(String.valueOf(customRetailers.get(fofoId).getActivationType()));biRetailerModel.setCategory(String.valueOf(partnerTypeThisMonth));biRetailerModel.setSalesManager(managerName);biRetailerModel.setRbm(rbmName);biRetailerModelMap.put(fofoId,biRetailerModel);// generate secondary data// this month secondary targetdouble currentSecondaryTarget = monthlyTargetRepository.selectByDateAndFofoId(YearMonth.now(), fofoId) != null ? monthlyTargetRepository.selectByDateAndFofoId(YearMonth.now(), fofoId).getPurchaseTarget() : 0;long currentMonthReturn = currentMonthPartnerReturnOrderInfoModelMap.getOrDefault(fofoId, 0L) + currentMonthRtoRefundOrderMap.getOrDefault(fofoId, 0L);Map<Integer, Double> secondaryMtd = orderRepository.selectOrderValueBetweenDatesGroupByFofoId(Arrays.asList(fofoId),Arrays.asList(OrderStatus.BILLED, OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.DELIVERY_SUCCESS, OrderStatus.ACCEPTED, OrderStatus.SUBMITTED_FOR_PROCESSING),startOfToday.withDayOfMonth(1), startOfToday.with(LocalTime.MAX)).stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getAmount()));double secondaryAchievedMtd = secondaryMtd.getOrDefault(fofoId, 0.0);double currentMonthNetSecondary = secondaryAchievedMtd - currentMonthReturn;double currentMonthSecondaryPercent = currentSecondaryTarget == 0 ? 0.0 : (secondaryAchievedMtd / currentSecondaryTarget) * 100;double currentMonthUnbilled = 0;// this month tertiary----------LocalDateTime now = LocalDateTime.now();double todaySale = fofoOrderItemRepository.selectSumMopGroupByRetailer(startOfToday, now, fofoId, false).get(fofoId);double mtdSaleTillYesterDay = fofoOrderItemRepository.selectSumMopGroupByRetailer(startOfToday.withDayOfMonth(1), startOfToday, fofoId, false).get(fofoId);double mtdSale = mtdSaleTillYesterDay + todaySale;// last month secondary targetdouble lastMonthSecondaryTarget = monthlyTargetRepository.selectByDateAndFofoId(lastMonth, fofoId) != null ? monthlyTargetRepository.selectByDateAndFofoId(lastMonth, fofoId).getPurchaseTarget() : 0;long lastMonthReturn = (lastMonthPartnerReturnOrderInfoModelMap.getOrDefault(fofoId,0L) + lastMonthRtoRefundOrderMap.getOrDefault(fofoId,0L));Map<Integer, Double> lastMonthSecondary = orderRepository.selectOrderValueBetweenDatesGroupByFofoId(Arrays.asList(fofoId),Arrays.asList(OrderStatus.BILLED, OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.DELIVERY_SUCCESS, OrderStatus.ACCEPTED, OrderStatus.SUBMITTED_FOR_PROCESSING),lastMontStartDate, lastMonthEndDate).stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getAmount()));double lastMonthSecondaryAchieved = lastMonthSecondary.getOrDefault(fofoId, 0.0);double lastMonthNetSecondary = lastMonthSecondaryAchieved - lastMonthReturn;double lastMonthSecondaryPercent = lastMonthSecondaryTarget == 0 ? 0.0 : (lastMonthSecondaryAchieved / lastMonthSecondaryTarget) * 100;double lastMonthUnbilled = 0;// last month tertiaryDouble lastMonthSale = fofoOrderItemRepository.selectSumMopGroupByRetailer(lastMontStartDate, lastMonthEndDate, fofoId, false).get(fofoId);// two month ago secondary targetdouble twoMonthAgoSecondaryTarget = monthlyTargetRepository.selectByDateAndFofoId(lastMonth, fofoId) != null ? monthlyTargetRepository.selectByDateAndFofoId(lastMonth, fofoId).getPurchaseTarget() : 0;long twoMonthAgoReturn = (twoMonthAgoPartnerReturnOrderInfoModelMap.getOrDefault(fofoId,0L) + twoMonthAgoRtoRefundOrderMap.getOrDefault(fofoId,0L));Map<Integer, Double> twoMonthAgoSecondary = orderRepository.selectOrderValueBetweenDatesGroupByFofoId(Arrays.asList(fofoId),Arrays.asList(OrderStatus.BILLED, OrderStatus.SHIPPED_FROM_WH, OrderStatus.SHIPPED_TO_LOGST, OrderStatus.DELIVERY_SUCCESS, OrderStatus.ACCEPTED, OrderStatus.SUBMITTED_FOR_PROCESSING),twoMonthsAgoStartDate, twoMonthsAgoEndDate).stream().collect(Collectors.toMap(x -> x.getId(), x -> x.getAmount()));double twoMonthAgoSecondaryAchieved = twoMonthAgoSecondary.getOrDefault(fofoId, 0.0);double twoMonthAgoNetSecondary = twoMonthAgoSecondaryAchieved - twoMonthAgoReturn;double twoMonthAgoSecondaryPercent = twoMonthAgoSecondaryTarget == 0 ? 0.0 : (twoMonthAgoSecondaryAchieved / twoMonthAgoSecondaryTarget) * 100;double twoMonthAgoUnbilled = 0;// second Month Tertiarydouble twoMonthAgoSale = fofoOrderItemRepository.selectSumMopGroupByRetailer(twoMonthsAgoStartDate, twoMonthsAgoEndDate, fofoId, false).get(fofoId);Map<YearMonth, BiSecondaryModel> monthlySecondaryModels = new HashMap<>();BiSecondaryModel currentMonthSecondaryModel = new BiSecondaryModel(currentSecondaryTarget,secondaryAchievedMtd,currentMonthReturn,currentMonthNetSecondary,currentMonthSecondaryPercent,mtdSale,currentMonthUnbilled // for now, unbilled tertiary value);BiSecondaryModel lastMonthSecondaryModel = new BiSecondaryModel(lastMonthSecondaryTarget,lastMonthSecondaryAchieved,lastMonthReturn,lastMonthNetSecondary,lastMonthSecondaryPercent,lastMonthSale,lastMonthUnbilled // for now, unbilled tertiary value);BiSecondaryModel twoMonthAgoSecondaryModel = new BiSecondaryModel(twoMonthAgoSecondaryTarget,twoMonthAgoSecondaryAchieved,twoMonthAgoReturn,twoMonthAgoNetSecondary,twoMonthAgoSecondaryPercent,twoMonthAgoSale,twoMonthAgoUnbilled // for now, unbilled tertiary value);monthlySecondaryModels.put(currentMonth, currentMonthSecondaryModel);monthlySecondaryModels.put(lastMonth, lastMonthSecondaryModel);monthlySecondaryModels.put(twoMonthsAgo, twoMonthAgoSecondaryModel);allRetailerMonthlyData.put(fofoId, monthlySecondaryModels);// brandwiseStock value priceMap<String, BrandStockPrice> brandStockPriceMap = inventoryService.getBrandWiseStockValue(fofoId);fofoBrandStockPriceMap.put(fofoId,brandStockPriceMap);double totalStockPrice = brandStockPriceMap.values().stream().mapToDouble(x->x.getTotalValue()).sum();fofoTotalStockPriceMap.put(fofoId,totalStockPrice);Map<String, Double> brandMtdTertiaryAmount = fofoOrderItemRepository.selectSumAmountGroupByBrand(currentMonthStartDate, currentMonthEndDate, fofoId);fofoBrandTertiaryMap.put(fofoId,brandMtdTertiaryAmount);double totalMtdTertiaryAmount = brandMtdTertiaryAmount.values().stream().mapToDouble(Double::doubleValue).sum();fofoTotalTertiaryMap.put(fofoId,totalMtdTertiaryAmount);// List<BrandWiseModel> brandMtdSecondary = orderRepository.selectAllBilledOrderGroupByBrandFofoId(fofoId, curDate.withDayOfMonth(1).minusMonths(6));}LOGGER.info("Total BI Retailers processed: {}", biRetailerModelMap.size());//generate excel and sent to mailList<List<String>> headerGroup = new ArrayList<>();List<String> headers1 = Arrays.asList("Retailer Detail", "", "", "", "", "", "", "", "", "",currentMonthStringValue, "", "", "", "", "", "",lastMonthStringValue, "", "", "", "", "", "",twoMonthAgoStringValue, "", "", "", "", "", "");List<String> headers2 = Arrays.asList("Code", "Store Name", "City", "Area", "BM", "Sales Manager", "RBM", "Status", "Category","Secondary Target", "Secondary Achieved", "Returns", "Net Secondary", "Secondary %","Tertiary Sale", "Unbilled","Secondary Target", "Secondary Achieved", "Returns", "Net Secondary", "Secondary %","Tertiary Sale", "Unbilled","Secondary Target", "Secondary Achieved", "Returns", "Net Secondary", "Secondary %","Tertiary Sale", "Unbilled","Total Stock", "Apple","Xiaomi","Vivo","Tecno","Samsung","Realme","Oppo","OnePlus","Poco","Lava","Itel","Almost New");headerGroup.add(headers1);headerGroup.add(headers2);List<List<?>> rows = new ArrayList<>();for (Map.Entry<Integer, BIRetailerModel> entry : biRetailerModelMap.entrySet()) {Integer fofoId = entry.getKey();BIRetailerModel retailer = entry.getValue();Map<YearMonth, BiSecondaryModel> monthlyData = allRetailerMonthlyData.get(fofoId);BiSecondaryModel current = monthlyData.getOrDefault(YearMonth.now(), new BiSecondaryModel(0,0,0,0,0,0,0));BiSecondaryModel last = monthlyData.getOrDefault(YearMonth.now().minusMonths(1), new BiSecondaryModel(0,0,0,0,0,0,0));BiSecondaryModel twoAgo = monthlyData.getOrDefault(YearMonth.now().minusMonths(2), new BiSecondaryModel(0,0,0,0,0,0,0));List<Object> row = new ArrayList<>();row.addAll(Arrays.asList(retailer.getCode(), retailer.getStoreName(), retailer.getCity(), retailer.getArea(),retailer.getBmName(), retailer.getSalesManager(), retailer.getRbm(),retailer.getStatus(), retailer.getCategory()));// Current Monthrow.addAll(Arrays.asList(current.getSecondaryTarget(),current.getSecondaryAchieved(),current.getSecondaryReturn(),current.getNetSecondary(),current.getSecondaryAchievedPercent(),current.getTertiary(),current.getTertiaryUnBilled()));// Last Monthrow.addAll(Arrays.asList(last.getSecondaryTarget(),last.getSecondaryAchieved(),last.getSecondaryReturn(),last.getNetSecondary(),last.getSecondaryAchievedPercent(),last.getTertiary(),last.getTertiaryUnBilled()));// Two Months Agorow.addAll(Arrays.asList(twoAgo.getSecondaryTarget(),twoAgo.getSecondaryAchieved(),twoAgo.getSecondaryReturn(),twoAgo.getNetSecondary(),twoAgo.getSecondaryAchievedPercent(),twoAgo.getTertiary(),twoAgo.getTertiaryUnBilled()));Map<String, BrandStockPrice> brandMap = fofoBrandStockPriceMap.get(fofoId);row.addAll(Arrays.asList(fofoTotalStockPriceMap.getOrDefault(fofoId, 0.0),brandMap.get("Apple") != null ? brandMap.get("Apple").getTotalValue() : 0.0,brandMap.get("Xiaomi") != null ? brandMap.get("Xiaomi").getTotalValue() : 0.0,brandMap.get("Vivo") != null ? brandMap.get("Vivo").getTotalValue() : 0.0,brandMap.get("Tecno") != null ? brandMap.get("Tecno").getTotalValue() : 0.0,brandMap.get("Samsung") != null ? brandMap.get("Samsung").getTotalValue() : 0.0,brandMap.get("Realme") != null ? brandMap.get("Realme").getTotalValue() : 0.0,brandMap.get("Oppo") != null ? brandMap.get("Oppo").getTotalValue() : 0.0,brandMap.get("OnePlus") != null ? brandMap.get("OnePlus").getTotalValue() : 0.0,brandMap.get("Poco") != null ? brandMap.get("Poco").getTotalValue() : 0.0,brandMap.get("Lava") != null ? brandMap.get("Lava").getTotalValue() : 0.0,brandMap.get("Itel") != null ? brandMap.get("Itel").getTotalValue() : 0.0,brandMap.get("Almost New") != null ? brandMap.get("Almost New").getTotalValue() : 0.0));rows.add(row);}// Send to emailByteArrayOutputStream csvStream = FileUtil.getCSVByteStreamWithMultiHeaders(headerGroup, rows);String fileName = "BI-Retailer-Monthly-Report-" + FormattingUtils.formatDate(LocalDateTime.now()) + ".csv";String[] sendToArray = new String[]{"ranu.rajput@smartdukaan.com"};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()));}}