Subversion Repositories SmartDukaan

Rev

Rev 34729 | View as "text/plain" | Blame | Compare with Previous | Last modification | View Log | RSS feed

package com.spice.profitmandi.service;

import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.stream.Collectors;

import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;

import com.spice.profitmandi.dao.model.*;
import com.spice.profitmandi.service.transaction.SDCreditService;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.InputStreamSource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;

import com.spice.profitmandi.common.model.CustomRetailer;
import com.spice.profitmandi.common.util.FileUtil;
import com.spice.profitmandi.dao.entity.fofo.PartnerDailyInvestment;
import com.spice.profitmandi.dao.entity.fofo.RetailerFilter;
import com.spice.profitmandi.dao.entity.transaction.Loan;
import com.spice.profitmandi.dao.repository.cs.CsService;
import com.spice.profitmandi.dao.repository.dtr.RetailerFilterRepository;
import com.spice.profitmandi.dao.repository.fofo.FofoOrderItemRepository;
import com.spice.profitmandi.dao.repository.fofo.FofoOrderRepository;
import com.spice.profitmandi.dao.repository.fofo.PartnerDailyInvestmentRepository;
import com.spice.profitmandi.dao.repository.transaction.OrderRepository;
import com.spice.profitmandi.service.user.RetailerService;

@Component
public class PerformanceServiceImpl implements PerformanceService {


    @Autowired
    private PartnerDailyInvestmentRepository partnerDailyInvestmentRepository;

    @Autowired
    private OrderRepository orderRepository;

    @Autowired
    private FofoOrderRepository fofoOrderRepository;

    @Autowired
    private FofoOrderItemRepository fofoOrderItemRepository;

    @Autowired
    private SDCreditService sdCreditService;

    @Autowired
    private RetailerService retailerService;

    @Autowired
    private CsService csService;

    @Autowired
    private JavaMailSender gmailRelaySender;

    @Autowired
    private RetailerFilterRepository retailerFilterRepository;


    private static final Logger LOGGER = LogManager.getLogger(PerformanceServiceImpl.class);


    @Override
    public List<RetailerPeformanceFilterModel> getPerformance(RetailerFilterModel retailerFilter, Map<Integer, CustomRetailer> customRetailers) {
        LocalDateTime curDate = LocalDate.now().atStartOfDay();
        LocalDateTime startDate = curDate.minusMonths(3);
        List<RetailerPeformanceFilterModel> retailerPerPeformanceFilterModels = new ArrayList<RetailerPeformanceFilterModel>();
        DecimalFormat decimalFormatter = new DecimalFormat("0.#");

        Map<Integer, List<Loan>> duedateMap = new HashMap<Integer, List<Loan>>();

        Map<Integer, List<Loan>> defaultdateMap = new HashMap<Integer, List<Loan>>();

        Map<Integer, BillingDaysAvg> billingDeliverAvgMap = new HashMap<Integer, BillingDaysAvg>();
        Map<Integer, Long> lastPurchaseMap = new HashMap<Integer, Long>();
        Map<Integer, Long> lastSaleMap = new HashMap<Integer, Long>();
        Map<Integer, PartnerDailyInvestment> partnerDailyInvestmentMap = new HashMap<Integer, PartnerDailyInvestment>();
        Map<Integer, Double> secondaryPartner = new HashMap<Integer, Double>();

        Map<Integer, Double> tertiaryPartner = new HashMap<Integer, Double>();


        if (retailerFilter.isCredit()) {
            List<Loan> dueDateLoans = sdCreditService.getDueDateCrossLoan();
            List<Loan> defaultLoans = sdCreditService.getDefaultLoans();

            if (!defaultLoans.isEmpty()) {
                defaultdateMap = defaultLoans.stream().collect(Collectors.groupingBy(x -> x.getFofoId()));
            }
            if (!dueDateLoans.isEmpty()) {
                duedateMap = dueDateLoans.stream().collect(Collectors.groupingBy(x -> x.getFofoId()));
            }
        }


        if (retailerFilter.isBilling()) {
            List<BillingDaysAvg> billingDeliveryAvg = orderRepository.selectBillingToDeliverAvg(startDate, LocalDateTime.now());
            if (!billingDeliveryAvg.isEmpty()) {
                billingDeliverAvgMap = billingDeliveryAvg.stream().filter(x -> x.getAvg() > 1).collect(Collectors.toMap(x -> x.getFofoId(), x -> x));
            }
        }


        if (retailerFilter.getSecondaryDays() != null) {
            List<LastSaleDateModel> purchaseOrders = orderRepository.getLastOrders();
            for (LastSaleDateModel purchaseOrder : purchaseOrders) {
                long daysBetween = Duration.between(purchaseOrder.getDateTime().plusDays(1), LocalDateTime.now()).toDays();
                if (daysBetween >= retailerFilter.getSecondaryDays()) {
                    lastPurchaseMap.put(purchaseOrder.getFofoId(), daysBetween);
                }
            }
        }


        if (retailerFilter.getTertiaryDays() != null) {
            List<LastSaleDateModel> saleOrders = fofoOrderRepository.getLastTertiaryOrders();
            for (LastSaleDateModel saleOrder : saleOrders) {
                long daysBetween = Duration.between(saleOrder.getDateTime().plusDays(1), LocalDateTime.now()).toDays();
                if (daysBetween >= retailerFilter.getTertiaryDays()) {
                    lastSaleMap.put(saleOrder.getFofoId(), daysBetween);
                }
            }
        }


        if (retailerFilter.getInvestmentPct() != null) {
            List<PartnerDailyInvestment> partnerDailyInvestments = partnerDailyInvestmentRepository.selectAll(LocalDate.now().minusDays(1));
            partnerDailyInvestmentMap = partnerDailyInvestments.stream().filter(x -> (100 - retailerFilter.getInvestmentPct()) <= x.getShortPercentage()).collect(Collectors.toMap(x -> x.getFofoId(), x -> x));
        }


        if (retailerFilter.getMtdsPct() != null) {
            Map<Integer, Double> secondaryMtd = orderRepository.selectBillingDatesBetweenSumGroupByRetailerId(curDate.withDayOfMonth(1), curDate.with(LocalTime.MAX));
            Map<Integer, Double> secondarylmtd = orderRepository.selectBillingDatesBetweenSumGroupByRetailerId(
                    curDate.withDayOfMonth(1).minusMonths(1), curDate.with(LocalTime.MAX).minusMonths(1));

            Set<Integer> fofoIds = new HashSet<>();
            fofoIds.addAll(secondaryMtd.keySet());
            fofoIds.addAll(secondarylmtd.keySet());


            for (Integer fofoId : fofoIds) {
                double mtdVal = 0;
                double lmtdVal = 0;
                if (secondaryMtd.get(fofoId) != null) {
                    mtdVal = secondaryMtd.get(fofoId);
                }
                if (secondarylmtd.get(fofoId) != null) {
                    lmtdVal = secondarylmtd.get(fofoId);
                }

                double value = ((lmtdVal - mtdVal) / lmtdVal) * 100;
                if (value >= retailerFilter.getMtdsPct()) {
                    secondaryPartner.put(fofoId, value);
                }


            }

        }


        if (retailerFilter.getMtdtPct() != null) {
            Map<Integer, Double> lmtdSale = fofoOrderItemRepository.selectSumMopGroupByRetailer(
                    curDate.withDayOfMonth(1).minusMonths(1), curDate.with(LocalTime.MAX).minusMonths(1), 0, false);
            Map<Integer, Double> mtdSale = fofoOrderItemRepository.selectSumMopGroupByRetailer(curDate.withDayOfMonth(1), curDate.with(LocalTime.MAX), 0, false);

            Set<Integer> fofoIds = new HashSet<>();
            fofoIds.addAll(lmtdSale.keySet());
            fofoIds.addAll(mtdSale.keySet());

            for (Integer fofoId : fofoIds) {
                double mtdVal = 0;
                double lmtdVal = 0;
                if (mtdSale.get(fofoId) != null) {
                    mtdVal = mtdSale.get(fofoId);
                }
                if (lmtdSale.get(fofoId) != null) {
                    lmtdVal = lmtdSale.get(fofoId);
                }

                double value = ((lmtdVal - mtdVal) / lmtdVal) * 100;
                if (value >= retailerFilter.getMtdtPct()) {
                    tertiaryPartner.put(fofoId, value);
                }
            }


        }

        LOGGER.info("tertiaryPartner {}", tertiaryPartner);

        LOGGER.info("secondaryPartner {}", secondaryPartner);


        NumberFormat numberformat = NumberFormat.getNumberInstance(new Locale("en", "IN"));


        for (Entry<Integer, CustomRetailer> customRetailerEntry : customRetailers.entrySet()) {
            int fofoId = customRetailerEntry.getKey();
            RetailerPeformanceFilterModel retailerPeformanceFilterModel = new RetailerPeformanceFilterModel();
            if (retailerFilter.isCredit()) {

                if (!duedateMap.isEmpty()) {
                    if (duedateMap.containsKey(fofoId)) {
                        retailerPeformanceFilterModel.setCredit("Due");
                    }
                }
                if (!defaultdateMap.isEmpty()) {
                    if (defaultdateMap.containsKey(fofoId)) {

                        retailerPeformanceFilterModel.setCredit("Default");
                    }

                }
            }

            if (retailerFilter.isBilling()) {
                if (!billingDeliverAvgMap.isEmpty()) {
                    if (billingDeliverAvgMap.containsKey(fofoId)) {
                        retailerPeformanceFilterModel.setBilling(billingDeliverAvgMap.get(fofoId).getAvg());
                    }
                }
            }

            if (retailerFilter.getInvestmentPct() != null) {

                if (!partnerDailyInvestmentMap.isEmpty()) {
                    if (partnerDailyInvestmentMap.containsKey(fofoId)) {
                        retailerPeformanceFilterModel.setInvestment(100 - partnerDailyInvestmentMap.get(fofoId).getShortPercentage());
                    }
                }

            }

            if (retailerFilter.getSecondaryDays() != null) {
                if (!lastPurchaseMap.isEmpty()) {
                    if (lastPurchaseMap.containsKey(fofoId)) {
                        retailerPeformanceFilterModel.setSecondaryDays(lastPurchaseMap.get(fofoId));
                    }
                }

            }


            if (retailerFilter.getTertiaryDays() != null) {
                if (!lastSaleMap.isEmpty()) {
                    if (lastSaleMap.containsKey(fofoId)) {
                        retailerPeformanceFilterModel.setTertiaryDays(lastSaleMap.get(fofoId));
                    }
                }
            }


            if (retailerFilter.getMtdsPct() != null) {
                if (!secondaryPartner.isEmpty()) {
                    if (secondaryPartner.containsKey(fofoId)) {
                        retailerPeformanceFilterModel.setMtds(Double.valueOf(numberformat.format(secondaryPartner.get(fofoId))));
                    }
                }
            }


            if (retailerFilter.getMtdtPct() != null) {
                if (!tertiaryPartner.isEmpty()) {
                    if (tertiaryPartner.containsKey(fofoId)) {
                        retailerPeformanceFilterModel.setMtdt(Double.valueOf(numberformat.format(tertiaryPartner.get(fofoId))));
                    }
                }
            }

            if (retailerPeformanceFilterModel.getBilling() != null || retailerPeformanceFilterModel.getCredit() != null || retailerPeformanceFilterModel.getInvestment() != null || retailerPeformanceFilterModel.getSecondaryDays() != null || retailerPeformanceFilterModel.getTertiaryDays() != null || retailerPeformanceFilterModel.getMtds() != null || retailerPeformanceFilterModel.getMtdt() != null) {

                retailerPeformanceFilterModel.setFofoId(fofoId);
                retailerPerPeformanceFilterModels.add(retailerPeformanceFilterModel);
            }


        }

        return retailerPerPeformanceFilterModels;
    }

    public void sendPartnerPerformanceEmail(Map<Integer, RetailerPeformanceFilterModel> partnersPerformanceMap, RetailerFilterModel retailerFilterModel, Map<Integer, CustomRetailer> customRetailers) throws Exception {
        Map<String, Set<Integer>> storeGuyMap = csService.getAuthUserPartnerIdMapping();
        Map<Integer, FofoReportingModel> fofoReportingModelMap = csService.getPartnerIdSalesHeaders();

        LOGGER.info("retailerFilterModel {}", retailerFilterModel);
        for (Entry<String, Set<Integer>> storeGuyEntry : storeGuyMap.entrySet()) {

            Set<Integer> fofoIds = storeGuyEntry.getValue();
            List<List<?>> rows = new ArrayList<>();
            List<String> headers = Arrays.asList("Partner Name", "Code","Territory Manager","Regional Manager","Credit- Due/Default", "Billing To Deliver", "Investment- Lower Than " + retailerFilterModel.getInvestmentPct() + "%", "Last Secondary-" + retailerFilterModel.getSecondaryDays() + "days", "Last Tertiary-" + retailerFilterModel.getTertiaryDays() + "days", "MTD Secondary < LMTD-" + retailerFilterModel.getMtdsPct() + "%", "MTD Tertiary < LMTD-" + retailerFilterModel.getMtdtPct() + "%");

            LOGGER.info("headers {}", headers);

            for (Integer fofoId : fofoIds) {
                RetailerPeformanceFilterModel retailerPerformanceFilterModel = partnersPerformanceMap.get(fofoId);

                LOGGER.info("retailerPerformanceFilterModel {}", retailerPerformanceFilterModel);

                if (retailerPerformanceFilterModel != null) {
                    rows.add(Arrays.asList(customRetailers.get(fofoId).getBusinessName(), customRetailers.get(fofoId).getCode(), fofoReportingModelMap.get(fofoId).getTerritoryManager(),fofoReportingModelMap.get(fofoId).getRegionalManager(), retailerPerformanceFilterModel.getCredit(), retailerPerformanceFilterModel.getBilling(), retailerPerformanceFilterModel.getInvestment(), retailerPerformanceFilterModel.getSecondaryDays(),retailerPerformanceFilterModel.getTertiaryDays(), retailerPerformanceFilterModel.getMtds(), retailerPerformanceFilterModel.getMtdt()));
                }

            }
            if (!rows.isEmpty()) {
                ByteArrayOutputStream baos = FileUtil.getCSVByteStream(headers, rows);
                this.sendMailWithAttachment(gmailRelaySender, new String[]{storeGuyEntry.getKey()}, null, "Partner Performance", "PFA", "PartnerPerformance.csv", new ByteArrayResource(baos.toByteArray()));
            }

        }
    }

    public void sendMailWithAttachment(JavaMailSender mailSender, String[] emailTo, String[] cc, String subject, String body, String fileName, InputStreamSource inputStreamSource) throws Exception {
        MimeMessage message = mailSender.createMimeMessage();
        MimeMessageHelper helper = new MimeMessageHelper(message, true);
        helper.setSubject(subject);
        helper.setText(body);
        if (cc != null) {
            helper.setCc(cc);
        }
        helper.setTo(emailTo);
        helper.addAttachment(fileName, inputStreamSource);
        InternetAddress senderAddress = new InternetAddress("noreply@smartdukaan.com", "SmartDukaan Care");
        helper.setFrom(senderAddress);
        mailSender.send(message);
    }


    public RetailerFilterModel getRetailerFilterModel() {
        List<RetailerFilter> retailerFilters = retailerFilterRepository.selectAll();

        RetailerFilterModel retailerFilterModel = new RetailerFilterModel();

        for (RetailerFilter retailerFilter : retailerFilters) {
            if (retailerFilter.getName().equals("BillingToDeliverAvg")) {
                retailerFilterModel.setBilling(true);
            }

            if (retailerFilter.getName().equals("credit due/default")) {
                retailerFilterModel.setCredit(true);
            }
            if (retailerFilter.getName().equals("Investment")) {
                retailerFilterModel.setInvestmentPct(retailerFilter.getValue());
            }
            if (retailerFilter.getName().equals("Last Secondary")) {
                retailerFilterModel.setSecondaryDays(retailerFilter.getValue());
            }
            if (retailerFilter.getName().equals("Last Tertiary")) {
                retailerFilterModel.setTertiaryDays(retailerFilter.getValue());
            }
            if (retailerFilter.getName().equals("Secondary")) {
                retailerFilterModel.setMtdsPct(20);
            }
            if (retailerFilter.getName().equals("Tertiary")) {
                retailerFilterModel.setMtdtPct(20);
            }


        }
        return retailerFilterModel;
    }


}