Subversion Repositories SmartDukaan

Rev

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

package com.spice.profitmandi.web.controller;

import com.google.gson.Gson;
import com.spice.profitmandi.common.enumuration.OfferType;
import com.spice.profitmandi.common.enumuration.ReporticoProject;
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
import com.spice.profitmandi.common.model.*;
import com.spice.profitmandi.common.services.ReporticoService;
import com.spice.profitmandi.common.util.ExcelUtils;
import com.spice.profitmandi.common.util.FileUtil;
import com.spice.profitmandi.common.util.FormattingUtils;
import com.spice.profitmandi.common.web.util.ResponseSender;
import com.spice.profitmandi.dao.entity.catalog.*;
import com.spice.profitmandi.dao.entity.cs.Region;
import com.spice.profitmandi.dao.entity.fofo.*;
import com.spice.profitmandi.dao.entity.transaction.PriceDrop;
import com.spice.profitmandi.dao.entity.transaction.PriceDropIMEI;
import com.spice.profitmandi.dao.enumuration.catalog.AmountType;
import com.spice.profitmandi.dao.enumuration.catalog.SchemeType;
import com.spice.profitmandi.dao.enumuration.catalog.UpgradeOfferStatus;
import com.spice.profitmandi.dao.enumuration.cs.EscalationType;
import com.spice.profitmandi.dao.enumuration.transaction.SchemePayoutStatus;
import com.spice.profitmandi.dao.model.*;
import com.spice.profitmandi.dao.repository.catalog.*;
import com.spice.profitmandi.dao.repository.cs.CsService;
import com.spice.profitmandi.dao.repository.cs.RegionRepository;
import com.spice.profitmandi.dao.repository.dtr.FofoStoreRepository;
import com.spice.profitmandi.dao.repository.dtr.Mongo;
import com.spice.profitmandi.dao.repository.fofo.*;
import com.spice.profitmandi.dao.repository.transaction.PriceDropIMEIRepository;
import com.spice.profitmandi.dao.repository.transaction.PriceDropRepository;
import com.spice.profitmandi.dao.repository.transaction.TransactionRepository;
import com.spice.profitmandi.service.authentication.RoleManager;
import com.spice.profitmandi.service.inventory.InventoryService;
import com.spice.profitmandi.service.offers.OfferService;
import com.spice.profitmandi.service.offers.PartnerCriteria;
import com.spice.profitmandi.service.pricecircular.PriceCircularModel;
import com.spice.profitmandi.service.pricecircular.PriceCircularService;
import com.spice.profitmandi.service.scheme.SchemeService;
import com.spice.profitmandi.service.user.RetailerService;
import com.spice.profitmandi.service.wallet.WalletService;
import com.spice.profitmandi.web.model.LoginDetails;
import com.spice.profitmandi.web.util.CookiesProcessor;
import com.spice.profitmandi.web.util.MVCResponseSender;
import in.shop2020.model.v1.order.WalletReferenceType;
import org.apache.commons.csv.CSVRecord;
import org.apache.commons.lang.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Controller
@Transactional(rollbackFor = Throwable.class)
public class SchemeController {
    // LED TV
    private static final List<Integer> categoryIds = Arrays.asList(ProfitMandiConstants.MOBILE_CATEGORY_ID,
            ProfitMandiConstants.TABLET_CATEGORY_ID, 14202);

    private static List<SchemeType> EXCLUDE_EXTEND_SCHEMES = Arrays.asList(SchemeType.SELLOUT, SchemeType.SPECIAL_SUPPORT, SchemeType.SELLIN);

    private static final Logger LOGGER = LogManager.getLogger(SchemeController.class);
    @Autowired
    WalletService walletService;
    @Autowired
    PartnerDailyInvestmentRepository partnerDailyInvestmentRepository;
    @Autowired
    InventoryItemRepository inventoryItemRepository;
    @Autowired
    PriceDropIMEIRepository priceDropIMEIRepository;
    @Autowired
    PriceDropRepository priceDropRepository;
    @Autowired
    SchemeInOutRepository schemeInOutRepository;
    List<String> adminEmail = Arrays.asList("tarun.verma@smartdukaan.com", "neeraj.gupta@smartdukaan.com", "amit.gupta@smartdukaan.com", "vikas.jangra@smartdukaan.com", "deena.nath@smartdukaan.com");
    @Autowired
    SchemeRegionRepository schemeRegionRepository;
    @Autowired
    RegionRepository regionRepository;
    @Autowired
    TransactionRepository transactionRepository;
    @Autowired
    private SchemeService schemeService;
    @Autowired
    private OfferService offerService;
    @Autowired
    private StateGstRateRepository stateGstRateRepository;
    @Autowired
    private ItemRepository itemRepository;
    @Autowired
    private ReporticoService reporticoService;
    @Autowired
    private SchemeRepository schemeRepository;
    @Autowired
    private SchemeItemRepository schemeItemRepository;
    @Autowired
    private MVCResponseSender mvcResponseSender;
    @Autowired
    private CookiesProcessor cookiesProcessor;
    @Autowired
    @Qualifier("fofoInventoryService")
    private InventoryService inventoryService;
    @Autowired
    private TagListingRepository tagListingRepository;
    @Autowired
    private RoleManager roleManager;
    @Autowired
    private ResponseSender<?> responseSender;
    @Autowired
    private FofoStoreRepository fofoStoreRepository;
    @Autowired
    private OfferPayoutRepository offerPayoutRepository;
    @Autowired
    private RetailerService retailerService;
    @Autowired
    private Mongo mongoClient;
    @Autowired
    private PartnerTypeChangeService partnerTypeChangeService;
    @Autowired
    private CustomerOfferRepository customerOfferRepository;
    @Autowired
    private CustomerOfferItemRepository customerOfferItemRepository;
    @Autowired
    private SamsungUpgradeOfferRepository samsungUpgradeOfferRepository;
    @Autowired
    private CsService csService;
    @Autowired
    private CategoryRepository categoryRepository;

    @Autowired
    PriceCircularService priceCircularService;
    @Autowired
    private FofoOrderRepository fofoOrderRepository;
    @Autowired
    private PurchaseRepository purchaseRepository;


    @Autowired
    private Gson gson;

    private boolean getAccess(String emailId) {

        boolean fullAccesss = false;
        List<String> emails = csService
                .getAuthUserByCategoryId(ProfitMandiConstants.TICKET_CATEGORY_CATEGORY, EscalationType.L3).stream()
                .map(x -> x.getEmailId()).collect(Collectors.toList());

        emails.addAll(
                csService.getAuthUserByCategoryId(ProfitMandiConstants.TICKET_CATEGORY_CATEGORY, EscalationType.L2)
                        .stream().map(x -> x.getEmailId()).collect(Collectors.toList()));

        if (adminEmail.contains(emailId)) {
            fullAccesss = true;
        }

        if (emails.contains(emailId)) {
            fullAccesss = false;
        }

        return fullAccesss;

    }

    @RequestMapping(value = "/getBrandsByCategory", method = RequestMethod.GET)
    public String getTagListingItemsByBrand(HttpServletRequest request, @RequestParam int categoryId, Model model)
            throws Exception {
        Set<String> brands = inventoryService.getAllTagListingBrands(categoryId);
        model.addAttribute("brands", brands);
        model.addAttribute("categoryId", categoryId);

        return "tag-listing-brands";
    }

    @RequestMapping(value = "/schemes/update-schemes-page", method = RequestMethod.GET)
    public String updateShcemes(HttpServletRequest request) throws ProfitMandiBusinessException {
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
        if (!roleManager.isAdmin(loginDetails.getRoleIds())) {
            throw new ProfitMandiBusinessException("User", loginDetails.getEmailId(), "Unauthorised access");
        }
        return "update-schemes-page";
    }

    @RequestMapping(value = "/schemes/process-sellout", method = RequestMethod.POST)
    public String processSellout(HttpServletRequest request, Model model, @RequestBody List<String> invoiceNumbers) throws Exception {
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
        if (!roleManager.isAdmin(loginDetails.getRoleIds())) {
            throw new ProfitMandiBusinessException("User", loginDetails.getEmailId(), "Unauthorised access");
        }
        for (String invoiceNumber : invoiceNumbers) {
            FofoOrder fofoOrder = fofoOrderRepository.selectByInvoiceNumber(invoiceNumber);
            schemeService.processSchemeOut(fofoOrder.getId(), fofoOrder.getFofoId());
        }
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
        return "response";
    }

    @RequestMapping(value = "/schemes/process-sellin", method = RequestMethod.POST)
    public String processSellin(HttpServletRequest request, Model model, @RequestBody List<String> invoiceNumbers) throws Exception {
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
        if (!roleManager.isAdmin(loginDetails.getRoleIds())) {
            throw new ProfitMandiBusinessException("User", loginDetails.getEmailId(), "Unauthorised access");
        }
        for (String invoiceNumber : invoiceNumbers) {
            Purchase purchase = purchaseRepository.selectByPurchaseReference(invoiceNumber);
            schemeService.processSchemeIn(purchase.getId(), purchase.getFofoId());
        }
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
        return "response";
    }

    @RequestMapping(value = "/payMonthlyInvestment", method = RequestMethod.POST)
    public void payMonthlyInvestment(HttpServletRequest request, Model model) throws ProfitMandiBusinessException {

        LocalDate firstDateOfCurrentMonth = LocalDateTime.now().withDayOfMonth(1).toLocalDate();
        LocalDate startOfPreviousMonth = firstDateOfCurrentMonth.minusMonths(1);
        int referenceId = Integer.parseInt(FormattingUtils.getYearMonth(startOfPreviousMonth.atStartOfDay()));
        LocalDate lastOfPreviousMonth = firstDateOfCurrentMonth.minusDays(1);
        List<PartnerDailyInvestment> partnerDailyInvestments = partnerDailyInvestmentRepository
                .selectAll(startOfPreviousMonth, lastOfPreviousMonth);
        Map<Integer, Long> investmentMaintainedDaysMap = partnerDailyInvestments.stream()
                .filter(x -> x.getShortPercentage() <= 10)
                .collect(Collectors.groupingBy(x -> x.getFofoId(), Collectors.counting()));
        LOGGER.info("investmentMaintainedDaysMap {}", investmentMaintainedDaysMap);
        List<SchemeInOut> schemeInOuts = schemeInOutRepository.selectAllPending(SchemeType.INVESTMENT,
                startOfPreviousMonth.atStartOfDay(), firstDateOfCurrentMonth.atStartOfDay());

        if (schemeInOuts.isEmpty()) {
            throw new ProfitMandiBusinessException("Investment Payout", "", "No data Found");
        }

        Map<Integer, List<SchemeInOut>> inventoryItemIdSchemeMap = schemeInOuts.stream()
                .collect(Collectors.groupingBy(x -> x.getInventoryItemId()));
        List<InventoryItem> inventoryItems = inventoryItemRepository.selectByIds(inventoryItemIdSchemeMap.keySet());
        Map<Integer, List<Integer>> retailerInventoryItemIdMap = inventoryItems.stream().collect(
                Collectors.groupingBy(x -> x.getFofoId(), Collectors.mapping(x -> x.getId(), Collectors.toList())));
        System.out.println("Fofo Id\tInvestment Maintained Days\tEligible payout");
        for (Map.Entry<Integer, List<Integer>> retailerEntry : retailerInventoryItemIdMap.entrySet()) {
            int fofoId = retailerEntry.getKey();
            long investmentMaintainedDays = investmentMaintainedDaysMap.get(fofoId) == null ? 0
                    : investmentMaintainedDaysMap.get(fofoId);

            List<SchemeInOut> schemeInouts = retailerEntry.getValue().stream().map(x -> inventoryItemIdSchemeMap.get(x))
                    .flatMap(List::stream)
                    .filter(x -> x.getStatus().equals(SchemePayoutStatus.PENDING) && x.getRolledBackTimestamp() == null)
                    .collect(Collectors.toList());
            float totalAmount = 0;
            LocalDateTime firstBillingDate = transactionRepository.getFirstBillingDate(fofoId);
            boolean sameYearMonth = firstBillingDate.getMonth() == startOfPreviousMonth.getMonth()
                    && firstBillingDate.getYear() == startOfPreviousMonth.getYear();
            for (SchemeInOut sio : schemeInouts) {
                if (sameYearMonth) {
                    sio.setStatusDescription("Investment payout fully disbursed for first month");
                    sio.setStatus(SchemePayoutStatus.CREDITED);
                    sio.setCreditTimestamp(LocalDateTime.now());
                    totalAmount += sio.getAmount();
                } else {
                    if (investmentMaintainedDays < 8) {
                        sio.setStatus(SchemePayoutStatus.REJECTED);
                        // sio.setRolledBackTimestamp(LocalDateTime.now());
                        sio.setStatusDescription(
                                "Investment maintained for " + investmentMaintainedDays + "(< 8) days");
                    } else if (investmentMaintainedDays < 12) {
                        sio.setStatus(SchemePayoutStatus.CREDITED);
                        sio.setAmount(sio.getAmount() / 2);
                        sio.setCreditTimestamp(LocalDateTime.now());
                        sio.setStatusDescription(
                                "Investment maintained for " + investmentMaintainedDays + "(< 12) days");
                        totalAmount += sio.getAmount();
                    } else {
                        sio.setStatus(SchemePayoutStatus.CREDITED);
                        sio.setCreditTimestamp(LocalDateTime.now());
                        totalAmount += sio.getAmount();
                    }
                }
            }
            if (totalAmount > 0) {
                String description = "Investment margin paid for "
                        + FormattingUtils.formatYearMonth(startOfPreviousMonth.atStartOfDay());
                if (investmentMaintainedDays < 12) {
                    description += ", as maintained for " + investmentMaintainedDays + "(< 12) days";
                }
                walletService.addAmountToWallet(fofoId, referenceId, WalletReferenceType.INVESTMENT_PAYOUT, description,
                        totalAmount, lastOfPreviousMonth.atTime(LocalTime.MAX));
            }
            // Its ok to process Margins Pending for activation
            schemeService.processActivation();
            System.out.printf("%d\t%d\t%f%n", fofoId, investmentMaintainedDays, totalAmount);
        }

    }

    @RequestMapping(value = "/evaluateActualInvestmentPayout", method = RequestMethod.GET)
    public ResponseEntity<?> evaluateActualInvestmentPayout(HttpServletRequest request, Model model) throws Exception {

        List<List<?>> rows = new ArrayList<>();
        LocalDate firstDateOfCurrentMonth = LocalDateTime.now().withDayOfMonth(1).toLocalDate();
        LocalDate startOfPreviousMonth = firstDateOfCurrentMonth.minusMonths(1);
        LocalDate lastOfPreviousMonth = firstDateOfCurrentMonth.minusDays(1);
        List<PartnerDailyInvestment> partnerDailyInvestments = partnerDailyInvestmentRepository
                .selectAll(startOfPreviousMonth, lastOfPreviousMonth);
        Map<Integer, Long> investmentMaintainedDaysMap = partnerDailyInvestments.stream()
                .filter(x -> x.getShortPercentage() <= 10)
                .collect(Collectors.groupingBy(x -> x.getFofoId(), Collectors.counting()));
        LOGGER.info("investmentMaintainedDaysMap {}", investmentMaintainedDaysMap);
        List<SchemeInOut> schemeInOuts = schemeInOutRepository.selectAllPending(SchemeType.INVESTMENT,
                startOfPreviousMonth.atStartOfDay(), firstDateOfCurrentMonth.atStartOfDay());
        Map<Integer, List<SchemeInOut>> inventoryItemIdSchemeMap = schemeInOuts.stream()
                .collect(Collectors.groupingBy(x -> x.getInventoryItemId()));
        List<InventoryItem> inventoryItems = inventoryItemRepository.selectByIds(inventoryItemIdSchemeMap.keySet());
        Map<Integer, List<Integer>> retailerInventoryItemIdMap = inventoryItems.stream().collect(
                Collectors.groupingBy(x -> x.getFofoId(), Collectors.mapping(x -> x.getId(), Collectors.toList())));
        System.out.println("Fofo Id\tInvestment Maintained Days\tEligible payout");
        for (Map.Entry<Integer, List<Integer>> retailerEntry : retailerInventoryItemIdMap.entrySet()) {
            int fofoId = retailerEntry.getKey();
            List<SchemeInOut> schemeInouts = retailerEntry.getValue().stream().map(x -> inventoryItemIdSchemeMap.get(x))
                    .flatMap(List::stream).collect(Collectors.toList());
            double totalAmount = schemeInouts.stream().filter(x -> x.getRolledBackTimestamp() == null)
                    .collect(Collectors.summingDouble(x -> x.getAmount()));
            long investmentMaintainedDays = investmentMaintainedDaysMap.get(fofoId) == null ? 0
                    : investmentMaintainedDaysMap.get(fofoId);
            if (investmentMaintainedDays < 8) {
                totalAmount = 0;
            } else if (investmentMaintainedDays < 12) {
                totalAmount = totalAmount / 2;
            }
            System.out.printf("%d\t%d\t%f%n", fofoId, investmentMaintainedDays, totalAmount);
            CustomRetailer customRetailer = retailerService.getFofoRetailer(fofoId);

            rows.add(Arrays.asList(fofoId, customRetailer.getBusinessName(), customRetailer.getCode(),
                    investmentMaintainedDays, totalAmount));
        }

        org.apache.commons.io.output.ByteArrayOutputStream baos = FileUtil.getCSVByteStream(
                Arrays.asList("fofoId", "Name", "Code", "investmentMaintainedDays", "totalAmount"), rows);

        final HttpHeaders headers = new HttpHeaders();
        headers.set("Content-Type", "text/csv");
        headers.set("Content-disposition", "inline; filename=investmentMaintainedDays.csv");
        headers.setContentLength(baos.toByteArray().length);

        final InputStream inputStream = new ByteArrayInputStream(baos.toByteArray());
        final InputStreamResource inputStreamResource = new InputStreamResource(inputStream);

        return new ResponseEntity<InputStreamResource>(inputStreamResource, headers, HttpStatus.OK);

    }

    @RequestMapping(value = "/processInvestmentDryRun", method = RequestMethod.GET)
    public ResponseEntity<?> processInvestmentDryRun(HttpServletRequest request, Model model) throws Exception {

        LocalDate firstDateOfCurrentMonth = LocalDateTime.now().withDayOfMonth(1).toLocalDate();
        LocalDate startOfPreviousMonth = firstDateOfCurrentMonth.minusMonths(1);
        LocalDate lastOfPreviousMonth = firstDateOfCurrentMonth.minusDays(1);
        List<List<?>> rows = new ArrayList<>();

        Map<String, String> params = new HashMap<>();

        params.put("MANUAL_datesBetween_FROMDATE", startOfPreviousMonth.toString());
        params.put("MANUAL_datesBetween_TODATE", lastOfPreviousMonth.toString());

        params.put("type", "INVESTMENT");

        List<EvaluateSchemeInvestmentPayoutModel> evaluateSchemeInvestmentPayouts = reporticoService.getReports(
                EvaluateSchemeInvestmentPayoutModel.class, ReporticoProject.FOCO, "schemepayout.xml", params);

        int referenceId = Integer.parseInt(FormattingUtils.getYearMonth(startOfPreviousMonth.atStartOfDay()));
        List<PartnerDailyInvestment> partnerDailyInvestments = partnerDailyInvestmentRepository
                .selectAll(startOfPreviousMonth, lastOfPreviousMonth);
        Map<Integer, Long> investmentMaintainedDaysMap = partnerDailyInvestments.stream()
                .filter(x -> x.getShortPercentage() <= 10)
                .collect(Collectors.groupingBy(x -> x.getFofoId(), Collectors.counting()));

        for (EvaluateSchemeInvestmentPayoutModel esip : evaluateSchemeInvestmentPayouts) {

            long investmentMaintainedDays = investmentMaintainedDaysMap.get(esip.getFofoId()) == null ? 0
                    : investmentMaintainedDaysMap.get(esip.getFofoId());

            esip.setInvestmentDays(investmentMaintainedDays);

            float processAmount = esip.getPaidAmount();
            if (investmentMaintainedDays < 8) {
                processAmount = 0;
            } else if (investmentMaintainedDays < 12) {
                processAmount = processAmount / 2;
            }

            esip.setProcessAmount(processAmount);

            rows.add(Arrays.asList(esip.getCode(), esip.getStoreName(), esip.getFofoId(), esip.getItemId(),
                    esip.getBrand(), esip.getModelName(), esip.getModelNumber(), esip.getColor(), esip.getSchemeInDp(),
                    esip.getSchemeOutDp(), esip.getSchemeId(), esip.getName(), esip.getType(), esip.getPartnerType(),
                    esip.getAmountType(), esip.getAmount(), esip.getPurchaseInvoice(), esip.getSaleInovoice(),
                    esip.getPaidAmount(), esip.getCreateTimestamp(), esip.getRolledBackTimestamp(),
                    esip.getSerialNumber(), esip.getInRef(), esip.getOutRef(), esip.getBusinessDate(), esip.getStatus(),
                    esip.getDescription(), esip.getProcessAmount(), esip.getInvestmentDays()));
        }

        org.apache.commons.io.output.ByteArrayOutputStream baos = FileUtil
                .getCSVByteStream(Arrays.asList("Code", "Store Name", "Fofo Id", "Item Id", "Brand", "Model Name",
                        "Model Number", "Color", "Scheme In Dp", "Scheme Out Dp", "Scheme Id", "Name", "Type",
                        "Partner Type", "Amount Type", "Amount", "Purchase Invoice", "Sale Inovoice", "Paid Amount",
                        "Create Timestamp", "Rolled Back Timestamp", "Serial Number", "In Ref", "Out Ref",
                        "Business Date", "Status", "Description", "Process Amount", "Investment Days"), rows);

        final HttpHeaders headers = new HttpHeaders();
        headers.set("Content-Type", "text/csv");
        headers.set("Content-disposition", "inline; filename=schemePayout.csv");
        headers.setContentLength(baos.toByteArray().length);

        final InputStream inputStream = new ByteArrayInputStream(baos.toByteArray());
        final InputStreamResource inputStreamResource = new InputStreamResource(inputStream);

        return new ResponseEntity<>(inputStreamResource, headers, HttpStatus.OK);

    }

    @RequestMapping(value = "/schemes/update", method = RequestMethod.POST)
    public String updateShcemes(HttpServletRequest request, @RequestBody SchemeItems schemeItems, Model model)
            throws Exception {
        for (int schemeId : schemeItems.getSchemeIds()) {
            if (schemeRepository.selectById(schemeId) != null)
                for (int catalogId : schemeItems.getCatalogIds()) {
                    if (tagListingRepository.selectAllByCatalogIds(Arrays.asList(catalogId)).size() > 0) {
                        SchemeItem si = new SchemeItem();
                        si.setCatalogId(catalogId);
                        si.setSchemeId(schemeId);
                        si.setCreateTimestamp(LocalDateTime.now());
                        try {
                            schemeItemRepository.persist(si);
                        } catch (Exception e) {
                            LOGGER.info("Scheme aleady exist");
                        }
                        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
                    } else {
                        LOGGER.info("Invalid catalog Id - {}", catalogId);
                    }
                }
        }
        return "response";
    }

    @RequestMapping(value = "/addItemToScheme", method = RequestMethod.POST)
    public String updateScheme(HttpServletRequest request, @RequestBody SchemeItems schemeItems, Model model)
            throws Exception {
        for (int schemeId : schemeItems.getSchemeIds()) {
            List<Integer> catalogIds = schemeItemRepository.selectCatalogIdsBySchemeId(schemeId);
            if (schemeRepository.selectById(schemeId) != null)
                for (int catalogId : schemeItems.getCatalogIds()) {
                    if (!(catalogIds.contains(catalogId))) {
                        SchemeItem si = new SchemeItem();
                        si.setCatalogId(catalogId);
                        si.setSchemeId(schemeId);
                        si.setCreateTimestamp(LocalDateTime.now());
                        try {
                            schemeItemRepository.persist(si);
                        } catch (Exception e) {
                            LOGGER.info("Scheme already exist");
                        }
                        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
                    } else {
                        throw new ProfitMandiBusinessException("Catalog exist for scheme",
                                "SchemeId= " + schemeId + ", CatalogId= " + catalogId, "Catalog exist for scheme");
                    }
                }
        }
        return "response";
    }

    @RequestMapping(value = "/createScheme", method = RequestMethod.GET)
    public String createScheme(HttpServletRequest request, Model model) throws ProfitMandiBusinessException {
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);

        LocalDate currentdate = LocalDate.now();
        Month month = currentdate.getMonth().minus(1);
        model.addAttribute("month", month);

        // Map<Integer, String> itemIdItemDescriptionMap =
        // inventoryService.getAllItemIdItemDescriptionMap();
        // model.addAttribute("itemIdItemDescriptionMap", itemIdItemDescriptionMap);
        // List<Category> categories = inventoryService.getAllCategories();
        List<Category> categories = categoryRepository.selectByIds(categoryIds);
        categories = categories.stream().sorted(Comparator.comparing(Category::getId)).collect(Collectors.toList());
        // Set<String> brands =
        // inventoryService.getAllTagListingBrands(ProfitMandiConstants.MOBILE_CATEGORY_ID);
        // brands.addAll(inventoryService.getAllTagListingBrands(14206));

        boolean fullAccesss = this.getAccess(loginDetails.getEmailId());

        List<Region> regionList = regionRepository.selectAll();

        List<SchemeType> schemeTypes = fullAccesss ? Arrays.stream(SchemeType.values()).collect(Collectors.toList()) : SchemeType.RESTRICTED_SCHEMES_TYPES;
        model.addAttribute("schemeTypes", schemeTypes);
        model.addAttribute("regionList", regionList);

        model.addAttribute("categories", categories);
        model.addAttribute("retailerTypes", PartnerType.values());
        return "create-scheme";
    }

    @RequestMapping(value = "/extendAllSchemes", method = RequestMethod.POST)
    public String extendAllScheme(HttpServletRequest request, @RequestBody LocalDateTime extendDatetime, Model model)
            throws Exception {
        List<Scheme> schemes = schemeRepository.selectActiveAll();
        //Filter scheme types ACTIVATION/SPECIAL SUPPORT/SELLOUT from extending
        schemes = schemes.stream().filter(x -> !EXCLUDE_EXTEND_SCHEMES.contains(x.getType())).collect(Collectors.toList());
        if (schemes.size() > 0) {
            for (Scheme scheme : schemes) {
                if (scheme.getExpireTimestamp() == null) {
                    scheme.setEndDateTime(extendDatetime);
                    schemeRepository.persist(scheme);
                }
            }
            model.addAttribute("response1", mvcResponseSender.createResponseString(true));
            return "response";
        }
        model.addAttribute("response1", mvcResponseSender.createResponseString(false));
        return "response";
    }

    @RequestMapping(value = "/getCatalogDescriptionByBrands", method = RequestMethod.GET)
    public String getTagListingItemsByBrand(HttpServletRequest request, @RequestParam int categoryId,
                                            @RequestParam List<String> brands, Model model) throws Exception {
        Map<Integer, String> catalogIdItemDescriptionMap = inventoryService.getModelDescriptionMap(categoryId, brands);
        model.addAttribute("catalogIdItemDescriptionMap", catalogIdItemDescriptionMap);
        // model.addAttribute("brands", inventoryService.getAllBrands());

        return "tag-listing-items-description";
    }

    @RequestMapping(value = "/createScheme", method = RequestMethod.POST)
    public String createScheme(HttpServletRequest request, @RequestBody CreateSchemeRequest createSchemeRequest,
                               Model model) throws ProfitMandiBusinessException {
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
        LOGGER.info("CreateSchemeRequest {}", createSchemeRequest);
        schemeService.saveScheme(loginDetails.getFofoId(), createSchemeRequest);
        return getDefaultSchemes(request, model);
    }

    private String getDefaultSchemes(HttpServletRequest request, Model model) throws ProfitMandiBusinessException {
        return getSchemes(request, 0, null, 30, 0, 0, PartnerType.ALL, "", model);
    }

    private List<Scheme> setSchemeAmountModel(List<Scheme> schemes) {
        for (Scheme scheme : schemes) {
            if (scheme.getAmountType().equals(AmountType.PERCENTAGE)) {
                scheme.setAmountModel(scheme.getAmount() + "%");
            } else {
                scheme.setAmountModel(scheme.getAmount() + "");
            }
        }
        return schemes;
    }

    // Show 20 recents

    @RequestMapping(value = "/schemes/delete", method = RequestMethod.DELETE)
    public String deleteShcemes(HttpServletRequest request,
                                @RequestParam(name = "schemeId", required = false, defaultValue = "0") int schemeId,
                                @RequestParam(name = "catalogId", required = false, defaultValue = "0") int catalogId, Model model)
            throws Exception {
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
        if (schemeId > 0 && catalogId > 0) {
            schemeItemRepository.deleteByCatalogIdsAndSchemeIds(catalogId, schemeId);

            model.addAttribute("response1", mvcResponseSender.createResponseString(true));

            model.addAttribute("roleType", roleManager.isAdmin(loginDetails.getRoleIds()));

        }
        return "response";
    }

    @RequestMapping(value = "/extendSchemeById", method = RequestMethod.POST)
    public String extendSchemeById(HttpServletRequest request,

                                   @RequestParam(name = ProfitMandiConstants.SCHEME_ID) int schemeId,
                                   @RequestBody LocalDateTime extendDatetime, Model model) throws Exception {
        Scheme scheme = schemeRepository.selectById(schemeId);
        if ((!(scheme.getActiveTimestamp() == null)) && scheme.getExpireTimestamp() == null) {
            scheme.setEndDateTime(extendDatetime);
            schemeRepository.persist(scheme);
            model.addAttribute("response1", mvcResponseSender.createResponseString(true));
            return "response";
        }
        model.addAttribute("response1", mvcResponseSender.createResponseString(false));
        return "response";
    }

    @RequestMapping(value = "/getSchemesByImei", method = RequestMethod.GET)
    public String getSchemesByImei(HttpServletRequest request,
                                   @RequestParam(defaultValue = "") String searchImei,
                                   @RequestParam(defaultValue = "false") boolean modal, Model model) throws ProfitMandiBusinessException {
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(searchImei)) {

            List<Scheme> schemes = null;
            List<SchemeInOut> schemeInOuts = null;

            InventoryItem inventoryItem = inventoryItemRepository.selectBySerialNumber(searchImei);
            int fofoId = inventoryItem.getFofoId();
           List<ItemPurchaseSummaryModel> itemPurchaseSummaryModels = inventoryItemRepository.selectPurchaseSummary(new ArrayList<>(Arrays.asList(inventoryItem.getId())));

            List<FofoOrder> fofoOrders=fofoOrderRepository.selectByFofoIdAndSerialNumber(fofoId, searchImei ,null, null, 0, 0);
            LOGGER.info("fofoOrder {}", fofoOrders);
            List<FofoOrder> filterOrders = fofoOrders.stream().filter(x -> x.getCancelledTimestamp() == null).collect(Collectors.toList());
            CustomRetailer customRetailer = retailerService.getFofoRetailer(fofoId);
            Item item = itemRepository.selectById(inventoryItem.getItemId());
            Map<Integer, Scheme> schemeMap = new HashMap<>();
            double netEarnings = 0;
            if (inventoryItem != null) {
                // Offer payout
                List<OfferPayout> offerPayouts = offerPayoutRepository.selectAllBySerialNumber(fofoId, searchImei);
                Map<Integer, CreateOfferRequest> offerRequestMap = offerPayouts.stream().map(x -> x.getOfferId())
                        .distinct().map(offerId -> {
                            try {
                                return offerService.getOffer(fofoId, offerId.intValue());
                            } catch (ProfitMandiBusinessException e) {
                                throw new RuntimeException(e);
                            }
                        }).collect(Collectors.toMap(x -> x.getId(), x -> x));

                schemeInOuts = schemeInOutRepository.selectByInventoryItemIds(new HashSet<>(Arrays.asList(inventoryItem.getId())));
                ActivatedImei activatedImei = activatedImeiRepository.selectBySerialNumber(searchImei);

                if (!schemeInOuts.isEmpty()) {
                    netEarnings += schemeInOuts.stream().filter(x -> x.getStatus().equals(SchemePayoutStatus.CREDITED)).collect(Collectors.summingDouble(x -> x.getAmount()));
                    List<Integer> schemeIds = schemeInOuts.stream().map(x -> x.getSchemeId()).collect(Collectors.toList());

                    schemes = schemeRepository.selectBySchemeIds(schemeIds);
                    for (Scheme scheme : schemes) {
                        if (scheme.getAmountType().equals(AmountType.PERCENTAGE)) {
                            scheme.setAmountModel(scheme.getAmount() + "%");
                        } else {
                            scheme.setAmountModel(scheme.getAmount() + "");
                        }
                    }

                    schemeMap = schemes.stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
                }
                List<PriceDropIMEI> priceDropImeis = priceDropIMEIRepository.selectByFofoIdImei(fofoId, searchImei);
                if (priceDropImeis.size() > 0) {

                    for (PriceDropIMEI priceDropIMEI : priceDropImeis) {
                        int priceDropId = priceDropIMEI.getPriceDropId();
                        PriceDrop pd = priceDropRepository.selectById(priceDropId);
                        priceDropIMEI.setPriceDrop(pd);
                    }
                    model.addAttribute("priceDropImeis", priceDropImeis);
                }
                netEarnings += offerPayouts.stream().collect(Collectors.summingDouble(x -> x.getAmount()));
                model.addAttribute("offerPayouts", offerPayouts);
                model.addAttribute("offerRequestMap", offerRequestMap);
                model.addAttribute("inventoryItem", inventoryItem);
                model.addAttribute("itemPurchaseSummaryModels", itemPurchaseSummaryModels);
                model.addAttribute("fofoOrders", filterOrders);
                model.addAttribute("activatedImei", activatedImei);



            }
            LOGGER.info("Net Earnings {}", netEarnings);
            model.addAttribute("netEarnings", netEarnings);
            model.addAttribute("fofoId", fofoId);
            model.addAttribute("schemeMap", schemeMap);
            model.addAttribute("item", item);
            model.addAttribute("schemeInOut", schemeInOuts);
            model.addAttribute("schemes", schemes);
            model.addAttribute("customRetailer", customRetailer);
            model.addAttribute("searchImei", searchImei);
        }
        if (modal) {
            return "scheme-imei-history-modal";
        }
        return "scheme-imei-history";
    }


    @Autowired
    PriceDropController priceDropController;

    @Autowired
    ActivatedImeiRepository activatedImeiRepository;

    @RequestMapping(value = "/getSchemes", method = RequestMethod.GET)
    public String getSchemes(HttpServletRequest request, @RequestParam(name = "offset", defaultValue = "0") int offset,
                             @RequestParam(required = false) LocalDate date,
                             @RequestParam(name = "limit", required = false, defaultValue = "30") int limit,
                             @RequestParam(name = "searchModel", required = false, defaultValue = "0") int searchModel,
                             @RequestParam(name = "searchScheme", required = false, defaultValue = "0") int searchScheme,
                             @RequestParam(name = "partnerType", required = false, defaultValue = "ALL") PartnerType partnerType,
                             @RequestParam(name = "searchImei", required = false, defaultValue = "") String searchImei, Model model)
            throws ProfitMandiBusinessException {
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
        boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());
        if (date != null) {
            date = date.isAfter(LocalDate.now()) ? LocalDate.now() : date;
        } else if (!isAdmin) {
            date = LocalDate.now();
        }

        List<Scheme> schemes = null;
        List<SchemeInOut> schemeInOuts = null;

        boolean fullAccess = this.getAccess(loginDetails.getEmailId());

        model.addAttribute("fullAccess", fullAccess);
        model.addAttribute("searchImei", searchImei);
        model.addAttribute("isAdmin", isAdmin);
        model.addAttribute("searchModel", searchModel);
        model.addAttribute("searchScheme", searchScheme);
        model.addAttribute("partnerType", partnerType);
        model.addAttribute("date", date);

        final LocalDate date1 = date;
        if (searchScheme > 0) {
            schemes = Arrays.asList(schemeRepository.selectById(searchScheme));
            this.setSchemeAmountModel(schemes);
            if (schemes.size() > 0) {
                model.addAttribute("schemes", schemes);
                List<SchemeRegion> schemeRegionList = schemeRegionRepository.selectAllBySchemeIds(schemes.stream().map(x -> x.getId()).collect(Collectors.toList()));
                Map<Integer, String> schemeRegionMap = schemeRegionList.stream().collect(Collectors.groupingBy(x -> x.getSchemeId(), Collectors.mapping(y -> regionRepository.selectById(y.getRegionId()).getName(), Collectors.joining(","))));
                model.addAttribute("schemeRegionMap", schemeRegionMap);
                return "schemes";
            } else {
                throw new ProfitMandiBusinessException("SchemeId", searchScheme, "SchemeId Not Found");
            }
        } else if (searchModel > 0) {
            Item item = itemRepository.selectAllByCatalogItemId(searchModel).get(0);
            TagListing tagListing = tagListingRepository.selectByItemId(item.getId());
            LOGGER.info("tagListing {}", tagListing);
            if (tagListing != null) {
                model.addAttribute("dp", tagListing.getSellingPrice());
                model.addAttribute("mop", tagListing.getMop());
            }
            model.addAttribute("modelName", item.getItemDescriptionNoColor());
            if (isAdmin) {
                schemes = schemeService
                        .selectSchemeByPartnerType(partnerType, date, searchModel, isAdmin, offset, limit).stream()
                        .filter(x -> x.getId() != 411 && x.getId() != 612).collect(Collectors.toList());
                this.setSchemeAmountModel(schemes);
                model.addAttribute("schemes", schemes);
                List<SchemeRegion> schemeRegionList = schemeRegionRepository.selectAllBySchemeIds(schemes.stream().map(x -> x.getId()).collect(Collectors.toList()));
                Map<Integer, String> schemeRegionMap = schemeRegionList.stream().collect(Collectors.groupingBy(x -> x.getSchemeId(), Collectors.mapping(y -> regionRepository.selectById(y.getRegionId()).getName(), Collectors.joining(" ,"))));
                model.addAttribute("schemeRegionMap", schemeRegionMap);
                return "schemes";
            } else {
                PriceCircularModel priceCircularModel = priceCircularService.getPriceCircularByOffer(loginDetails.getFofoId(), Arrays.asList(searchModel), date);
                FofoStore fs = fofoStoreRepository.selectByRetailerId(loginDetails.getFofoId());
                priceDropController.getPriceCircularView(priceCircularModel, model, fs.getCode());
            }

        } else if (org.apache.commons.lang3.StringUtils.isNotEmpty(searchImei)) {

            LOGGER.info("searchImei" + searchImei);

            InventoryItem inventoryItem = inventoryItemRepository.selectBySerialNumberFofoId(searchImei,
                    loginDetails.getFofoId());
            Item item = itemRepository.selectById(inventoryItem.getItemId());
            Map<Integer, Scheme> schemeMap = new HashMap<>();
            double netEarnings = 0;
            if (inventoryItem != null) {
                /*date = inventoryItem.getCreateTimestamp().toLocalDate();
                PriceCircularModel priceCircularModel = priceCircularService.getPriceCircularByOffer(loginDetails.getFofoId(), Arrays.asList(item.getCatalogItemId()), date);
                priceDropController.getPriceCircularView(priceCircularModel, model);*/
                // Offer payout
                List<OfferPayout> offerPayouts = offerPayoutRepository.selectAllBySerialNumber(loginDetails.getFofoId(),
                        searchImei);
                Map<Integer, CreateOfferRequest> offerRequestMap = offerPayouts.stream()
                        .map(x -> {
                            try {
                                return offerService.getOffer(loginDetails.getFofoId(), (int) x.getOfferId());
                            } catch (ProfitMandiBusinessException e) {
                                throw new RuntimeException(e);
                            }
                        })
                        .collect(Collectors.toMap(x -> x.getId(), x -> x));

                schemeInOuts = schemeInOutRepository
                        .selectByInventoryItemIds(new HashSet<>(Arrays.asList(inventoryItem.getId())));

                if (!schemeInOuts.isEmpty()) {
                    netEarnings += schemeInOuts.stream().filter(x -> x.getStatus().equals(SchemePayoutStatus.CREDITED))
                            .collect(Collectors.summingDouble(x -> x.getAmount()));
                    List<Integer> schemeIds = schemeInOuts.stream().map(x -> x.getSchemeId())
                            .collect(Collectors.toList());

                    schemes = schemeRepository.selectBySchemeIds(schemeIds);
                    for (Scheme scheme : schemes) {
                        if (scheme.getAmountType().equals(AmountType.PERCENTAGE)) {
                            scheme.setAmountModel(scheme.getAmount() + "%");
                        } else {
                            scheme.setAmountModel(scheme.getAmount() + "");
                        }
                    }

                    schemeMap = schemes.stream().collect(Collectors.toMap(x -> x.getId(), x -> x));
                }
                netEarnings += offerPayouts.stream().collect(Collectors.summingDouble(x -> x.getAmount()));

                List<PriceDropIMEI> priceDropImeis = priceDropIMEIRepository
                        .selectByFofoIdImei(loginDetails.getFofoId(), searchImei);
                if (priceDropImeis.size() > 0) {

                    for (PriceDropIMEI priceDropIMEI : priceDropImeis) {
                        int priceDropId = priceDropIMEI.getPriceDropId();
                        PriceDrop pd = priceDropRepository.selectById(priceDropId);
                        priceDropIMEI.setPriceDrop(pd);
                    }
                    model.addAttribute("priceDropImeis", priceDropImeis);
                }

                model.addAttribute("offerPayouts", offerPayouts);
                model.addAttribute("offerRequestMap", offerRequestMap);
                model.addAttribute("inventoryItem", inventoryItem);

            }
            model.addAttribute("netEarnings", netEarnings);
            model.addAttribute("schemeMap", schemeMap);
            model.addAttribute("item", item);
            model.addAttribute("schemeInOut", schemeInOuts);
        }

        if (isAdmin) {
            schemes = schemeRepository.selectAll(0, 300);
            this.setSchemeAmountModel(schemes);
            List<SchemeRegion> schemeRegionList = schemeRegionRepository.selectAllBySchemeIds(schemes.stream().map(x -> x.getId()).collect(Collectors.toList()));
            Map<Integer, String> schemeRegionMap = schemeRegionList.stream().collect(Collectors.groupingBy(x -> x.getSchemeId(), Collectors.mapping(y -> regionRepository.selectById(y.getRegionId()).getName(), Collectors.joining(","))));
            model.addAttribute("schemes", schemes);
            model.addAttribute("schemeRegionMap", schemeRegionMap);

            return "schemes";
        } else {
            FofoStore fs = fofoStoreRepository.selectByRetailerId(loginDetails.getFofoId());
            model.addAttribute("partnerCode", fs.getCode());
            model.addAttribute("fofoId", fs.getId());
            return "schemes-partner";
        }

    }

    private int getNlc(Item item, int fofoId, List<Scheme> schemes, TagListing tagListing) {
        /*if (item.getBrand().equals("Vivo") && fofoStoreRepository.getWarehousePartnerMap().get(7720).stream()
                .filter(x -> x.getId() == fofoId).count() > 0) {
            schemes = schemes.stream().filter(x -> !x.getType().equals(SchemeType.INVESTMENT))
                    .collect(Collectors.toList());
        }*/
        float nlc = tagListing.getSellingPrice();
        for (Scheme scheme : schemes) {
            if (scheme.getAmountType().equals(AmountType.PERCENTAGE)) {
                if (tagListing != null) {
                    float amount = tagListing.getSellingPrice() * scheme.getAmount() / 100;
                    scheme.setAmountModel(FormattingUtils.formatDecimal(amount) + " (" + scheme.getAmount() + "%)");
                    nlc -= amount;
                } else {
                    scheme.setAmountModel(scheme.getAmount() + "%");
                }
            } else {
                scheme.setAmountModel(scheme.getAmount() + "");
                nlc -= scheme.getAmount();
            }
        }

        return Math.round(nlc);

    }

    @RequestMapping(value = "/getLastMonthCreditIncome", method = RequestMethod.GET)
    public String getLastMonthCreditIncome(HttpServletRequest request, Model model) throws Exception {

        String status = "CREDITED";
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);

        LocalDateTime currentStartMonth = LocalDate.now().atStartOfDay().withDayOfMonth(1);
        LocalDateTime currentDate = LocalDate.now().atStartOfDay();

        YearMonth yearMonth = YearMonth.now();
        LOGGER.info("yearMonth" + yearMonth);

        boolean partnerType = partnerTypeChangeService.isPartnerTypeUpgraded(loginDetails.getFofoId(), yearMonth);

        LOGGER.info("partnerType" + partnerType);

        Map<String, Double> lastMonthCategoryUpgradeMarginMap = new HashMap<>();

        if (partnerType) {
            lastMonthCategoryUpgradeMarginMap = schemeInOutRepository
                    .selectLastMonthCategoryUpgradeMarginByBrand(loginDetails.getFofoId(), currentStartMonth,
                            currentDate)
                    .stream().collect(Collectors.toMap(x -> x.getBrand(), x -> x.getAmount()));
        }
        List<LastMonthCreditedIncomeModel> lastMonthCreditedIncomeModels = schemeInOutRepository
                .selectLastMonthCreditedIncomeByFofoId(loginDetails.getFofoId(), currentStartMonth, currentDate);

        List<LastMonthCreditedIncomeModel> lastMonthPurchaseInMargins = schemeInOutRepository
                .selectLastMonthPurchaseInMarginByFofoId(loginDetails.getFofoId(), currentStartMonth, currentDate);

        List<LastMonthCreditedIncomeModel> lastMonthFrontEndIncomes = schemeInOutRepository
                .selectFrontIncomeByBrand(loginDetails.getFofoId(), currentStartMonth, currentDate);

        Map<String, LastMonthCreditedIncomeModel> lastMonthPendingIncomeMap = schemeInOutRepository
                .selectLastMonthPendingIncomeByFofoId(loginDetails.getFofoId(), currentStartMonth, currentDate).stream()
                .collect(Collectors.toMap(x -> x.getBrand(), x -> x));

        Map<String, LastMonthCreditedIncomeModel> lastMonthPurchaseInMarginMap = lastMonthPurchaseInMargins.stream()
                .collect(Collectors.toMap(x -> x.getBrand(), x -> x));

        Map<String, LastMonthCreditedIncomeModel> lastMonthSaleMarginMap = lastMonthCreditedIncomeModels.stream()
                .collect(Collectors.toMap(x -> x.getBrand(), x -> x));

        lastMonthFrontEndIncomes.stream().forEach(x -> {
            if (lastMonthSaleMarginMap.containsKey(x.getBrand())) {
                x.setAmount(lastMonthSaleMarginMap.get(x.getBrand()).getAmount() + x.getAmount());
                lastMonthSaleMarginMap.put(x.getBrand(), x);
            } else {
                lastMonthSaleMarginMap.put(x.getBrand(), x);
            }

        });
        Map<String, Float> totalAmountMap = lastMonthSaleMarginMap.entrySet().stream()
                .collect(Collectors.toMap(x -> x.getKey(), x -> x.getValue().getAmount()));

        Set<String> keySet = new HashSet<>();
        keySet.addAll(lastMonthPurchaseInMarginMap.keySet());
        keySet.addAll(lastMonthSaleMarginMap.keySet());
        keySet.addAll(lastMonthPendingIncomeMap.keySet());

        lastMonthPurchaseInMarginMap.entrySet().stream().forEach(x -> {
            String brand = x.getKey();
            float amount = x.getValue().getAmount();
            if (!totalAmountMap.containsKey(brand)) {
                totalAmountMap.put(brand, 0f);
            }
            totalAmountMap.put(brand, totalAmountMap.get(brand) + amount);

        });

        lastMonthPendingIncomeMap.entrySet().stream().forEach(x -> {
            String brand = x.getKey();
            float amount = x.getValue().getAmount();
            if (!totalAmountMap.containsKey(brand)) {
                totalAmountMap.put(brand, 0f);
            }
            totalAmountMap.put(brand, totalAmountMap.get(brand) + amount);

        });


        Map<Integer, String> monthValueMap = new HashMap<>();
        for (int i = 0; i <= 5; i++) {
            LocalDateTime startOfMonth = LocalDateTime.now().withDayOfMonth(1).minusMonths(i);
            monthValueMap.put(i, startOfMonth.format(DateTimeFormatter.ofPattern("MMM''uu")));
        }
        model.addAttribute("month", 0);
        model.addAttribute("monthValueMap", monthValueMap);
        model.addAttribute("keySet", keySet);
        model.addAttribute("lastMonthPendingIncomeMap", lastMonthPendingIncomeMap);

        model.addAttribute("lastMonthCategoryUpgradeMarginMap", lastMonthCategoryUpgradeMarginMap);
        model.addAttribute("lastMonthPurchaseInMarginMap", lastMonthPurchaseInMarginMap);
        model.addAttribute("lastMonthSaleMarginMap", lastMonthSaleMarginMap);
        model.addAttribute("status", status);
        model.addAttribute("totalAmountMap", totalAmountMap);

        return "last-month-credited-income";
    }

    @RequestMapping(value = "/getLastMonthPendingIncome", method = RequestMethod.GET)
    public String getLastMonthPendingIncome(HttpServletRequest request, Model model) throws Exception {

        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);

        LocalDateTime currentStartMonth = LocalDate.now().atStartOfDay().withDayOfMonth(1);
        LocalDateTime currentDate = LocalDate.now().atStartOfDay();
        String status = "PENDING";

        LOGGER.info("currentStartMonth" + currentStartMonth);
        LOGGER.info("currentDate" + currentDate);

        List<LastMonthCreditedIncomeModel> lastMonthPendingIncomeModels = schemeInOutRepository
                .selectLastMonthPendingIncomeByFofoId(loginDetails.getFofoId(), currentStartMonth, currentDate);

        Map<String, LastMonthCreditedIncomeModel> lastMonthMarginMap = new HashMap<>();

        for (LastMonthCreditedIncomeModel lastMonthPendingIncomeModel : lastMonthPendingIncomeModels) {

            lastMonthMarginMap.put(lastMonthPendingIncomeModel.getBrand(), lastMonthPendingIncomeModel);
        }
        LOGGER.info("lastMonthPendingIncomeModel" + lastMonthPendingIncomeModels);
        LOGGER.info("lastMonthMarginMap" + lastMonthMarginMap);
        model.addAttribute("lastMonthCreditedIncomeModels", lastMonthPendingIncomeModels);
        model.addAttribute("lastMonthMarginMap", lastMonthMarginMap);
        model.addAttribute("status", status);

        return "last-month-credited-income";
    }

    @RequestMapping(value = "/getLastMonthImeiWiseIncome", method = RequestMethod.GET)
    public String getLastMonthImeiWiseIncome(HttpServletRequest request,
                                             @RequestParam(name = "catalogItemId", required = false, defaultValue = "") int catalogItemId,
                                             @RequestParam(name = "month", required = false, defaultValue = "") int month, Model model)
            throws Exception {

        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);

        LocalDateTime lastMonthStart = LocalDate.now().minusMonths(month).withDayOfMonth(1).atStartOfDay();
        LocalDateTime lastMonthEnd = lastMonthStart.plusMonths(1);

        HashSet<String> allImeiSet = new LinkedHashSet<>();

        List<LastMonthFrontEndImeiModel> lmfi = schemeInOutRepository
                .selectLastMonthFrontEndImei(loginDetails.getFofoId(), catalogItemId, lastMonthStart, lastMonthEnd);
        List<LastMonthImeiModel> lmpi = schemeInOutRepository.selectLastMonthPurchaseInImei(loginDetails.getFofoId(),
                catalogItemId, lastMonthStart, lastMonthEnd);
        List<LastMonthImeiModel> lmci = schemeInOutRepository.selectLastMonthCreditedImei(loginDetails.getFofoId(),
                catalogItemId, lastMonthStart, lastMonthEnd);

        List<OfferPayoutImeiIncomeModel> offerPayoutImeiIncomeModels = offerPayoutRepository.getTotalPayoutsByPartnerPeriod(YearMonth.of(lastMonthStart.getYear(),
                lastMonthStart.getMonth()), loginDetails.getFofoId(), null, catalogItemId);

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

        Map<String, Double> lastmonthCategoryUpgradeMargin = schemeInOutRepository
                .selectLastMonthCategoryUpgradeMarginByImei(loginDetails.getFofoId(), catalogItemId, lastMonthStart,
                        lastMonthEnd)
                .stream().collect(Collectors.toMap(x -> x.getBrand(), x -> x.getAmount()));

        allImeiSet.addAll(lmpi.stream().map(x -> x.getImei()).collect(Collectors.toList()));
        allImeiSet.addAll(lmci.stream().map(x -> x.getImei()).collect(Collectors.toList()));
        allImeiSet.addAll(lmfi.stream().map(x -> x.getImei()).collect(Collectors.toList()));
        allImeiSet.addAll(offerPayoutImeiIncomeModels.stream().map(x -> x.getImei()).collect(Collectors.toList()));

        List<String> allImeiList = new ArrayList<>(allImeiSet);

        LOGGER.info("allImeiList" + allImeiList);
        LOGGER.info("lmcm" + lastmonthCategoryUpgradeMargin);

        List<LastMonthFrontEndImeiModel> lastMonthFrontEndImeis = schemeInOutRepository
                .selectLastMonthFrontEndByImei(loginDetails.getFofoId(), allImeiList);
        Map<String, LastMonthFrontEndImeiModel> soldMap = lastMonthFrontEndImeis.stream().collect(Collectors.toMap(x -> x.getImei(), x -> x));


        List<LastMonthImeiModel> lastMonthPurchaseInImeis = schemeInOutRepository
                .selectLastMonthPurchaseInByImei(loginDetails.getFofoId(), allImeiList);

        List<LastMonthImeiModel> lastMonthCreditedImeis = schemeInOutRepository
                .selectLastMonthCreditedByImei(loginDetails.getFofoId(), allImeiList);
        List<OfferPayoutImeiIncomeModel> allOfferPayoutImeiIncomeModels = offerPayoutRepository.getTotalPayoutsByImei(allImeiList);

        //Map<String, OfferPayoutImeiIncomeModel> imeisOfferPayoutMap = allOfferPayoutImeiIncomeModels.stream().collect(Collectors.toMap(x->x.getImei(), x->x));
        Map<String, Double> imeiWisePendingSaleAmount = lastMonthCreditedImeis.stream()
                .filter(x -> x.getStatus().equals(SchemePayoutStatus.PENDING)).collect(Collectors
                        .groupingBy(x -> x.getImei(), Collectors.summingDouble(x -> x.getPendingSaleAmount())));

        allOfferPayoutImeiIncomeModels.stream().forEach(x -> {
            if (x.getSaleDate() != null) {
                LastMonthImeiModel lastMonthImeiModel = new LastMonthImeiModel(x.getImei(), (float) x.getSalePayout(),
                        0, "Addnl Margin", x.getSaleDate(), SchemePayoutStatus.CREDITED);
                lastMonthCreditedImeis.add(lastMonthImeiModel);
            }
            if (x.getGrnDate() != null) {
                LastMonthImeiModel lastMonthImeiModel = new LastMonthImeiModel(x.getImei(), (float) x.getPurchasePayout(),
                        0, "Booster Payout", x.getGrnDate(), SchemePayoutStatus.CREDITED);
                lastMonthPurchaseInImeis.add(lastMonthImeiModel);
            }
        });

        Map<String, Map<String, Double>> lastMonthPurchaseInMapPairMap = lastMonthPurchaseInImeis.stream()
                .collect(Collectors.groupingBy(x -> x.getImei(),
                        Collectors.groupingBy(x -> x.getDescription(), Collectors.summingDouble(x -> x.getAmount()))));
        Map<String, LocalDate> imeiPurchaseDateMap = lastMonthPurchaseInImeis.stream().collect(Collectors.toMap(x -> x.getImei(), x -> x.getCreateTimeStamp().toLocalDate(), (x, y) -> x));
        LOGGER.info("Last month front end imeis - {}", lastMonthFrontEndImeis);
        Map<String, LocalDate> imeiSaleDateMap = lastMonthFrontEndImeis.stream().collect(Collectors.toMap(x -> x.getImei(), x -> x.getCreated()));
        Map<String, Map<String, Double>> lastMonthCreditedMapPairMap = lastMonthCreditedImeis.stream()
                .collect(Collectors.groupingBy(x -> x.getImei(),
                        Collectors.groupingBy(x -> x.getDescription(), Collectors.summingDouble(x -> x.getAmount()))));

        // descriptionSet.add("")

        List<String> purchaseList = lastMonthPurchaseInImeis.stream().map(x -> x.getDescription()).distinct().collect(Collectors.toList());
        List<String> saleList = lastMonthCreditedImeis.stream().map(x -> x.getDescription()).distinct().collect(Collectors.toList());

        Map<String, ImeiWiseIncomePairAndMapModel> imeiWiseIncomeMapOfMap = new HashMap<>();

        for (Map.Entry<String, Map<String, Double>> entry : lastMonthPurchaseInMapPairMap.entrySet()) {

            String imei = entry.getKey();
            ImeiWiseIncomePairAndMapModel modelImeiMap = new ImeiWiseIncomePairAndMapModel(imei,
                    imeiPurchaseDateMap.get(imei), null);
            imeiWiseIncomeMapOfMap.put(imei, modelImeiMap);
            double totalAmount = entry.getValue().entrySet().stream()
                    .collect(Collectors.summingDouble(x -> x.getValue()));
            imeiWiseIncomeMapOfMap.get(imei).setTotalIncome(totalAmount);
        }

        for (Map.Entry<String, Map<String, Double>> entry : lastMonthCreditedMapPairMap.entrySet()) {
            Map<String, Double> descriptionAmountMap = entry.getValue();
            if (!imeiWiseIncomeMapOfMap.containsKey(entry.getKey())) {
                imeiWiseIncomeMapOfMap.put(entry.getKey(), new ImeiWiseIncomePairAndMapModel(entry.getKey(), null, null));
            }
            ImeiWiseIncomePairAndMapModel modelImeiMap = imeiWiseIncomeMapOfMap.get(entry.getKey());
            ;
            modelImeiMap.setSaleDate(imeiSaleDateMap.get(entry.getKey()));

            double totalAmount = descriptionAmountMap.entrySet().stream()
                    .collect(Collectors.summingDouble(x -> x.getValue()));
            imeiWiseIncomeMapOfMap.get(entry.getKey())
                    .setTotalIncome(totalAmount + imeiWiseIncomeMapOfMap.get(entry.getKey()).getTotalIncome());
        }

        //Imeis for pending activation
        lastMonthCreditedImeis.stream().filter(x -> x.getStatus().equals(SchemePayoutStatus.PENDING)).forEach(x -> {
            if (!imeiWiseIncomeMapOfMap.containsKey(x.getImei())) {
                imeiWiseIncomeMapOfMap.put(x.getImei(), new ImeiWiseIncomePairAndMapModel(x.getImei()));
            }
            ImeiWiseIncomePairAndMapModel imeiWiseIncomePairAndMapModel = imeiWiseIncomeMapOfMap
                    .get(x.getImei());
            imeiWiseIncomePairAndMapModel.setSaleDate(x.getCreateTimeStamp().toLocalDate());
            imeiWiseIncomePairAndMapModel.setTotalIncome(x.getPendingSaleAmount() + imeiWiseIncomePairAndMapModel.getTotalIncome());
        });

        lastMonthFrontEndImeis.stream().forEach(lastMonthFrontEndImeiModel -> {
            if (!imeiWiseIncomeMapOfMap.containsKey(lastMonthFrontEndImeiModel.getImei())) {
                imeiWiseIncomeMapOfMap.put(lastMonthFrontEndImeiModel.getImei(), new ImeiWiseIncomePairAndMapModel(lastMonthFrontEndImeiModel.getImei()));
            }
            ImeiWiseIncomePairAndMapModel imeiWiseIncomePairAndMapModel = imeiWiseIncomeMapOfMap
                    .get(lastMonthFrontEndImeiModel.getImei());
            lastMonthFrontEndImeiModel.setNlc(lastMonthFrontEndImeiModel.getDp()
                    - (float) imeiWiseIncomeMapOfMap.get(lastMonthFrontEndImeiModel.getImei()).getTotalIncome());
            lastMonthFrontEndImeiModel.setNetIncome(lastMonthFrontEndImeiModel.getSellingPrice() - lastMonthFrontEndImeiModel.getNlc());
            imeiWiseIncomePairAndMapModel.setSaleDate(lastMonthFrontEndImeiModel.getCreated());
        });

        model.addAttribute("imeiWisePendingSaleAmount", imeiWisePendingSaleAmount);
        model.addAttribute("month", month);
        model.addAttribute("purchaseList", purchaseList);
        model.addAttribute("saleList", saleList);
        model.addAttribute("lastMonthPurchaseInMapPairMap", lastMonthPurchaseInMapPairMap);
        model.addAttribute("lastMonthCreditedMapPairMap", lastMonthCreditedMapPairMap);
        model.addAttribute("imeiWiseIncomeMapOfMap", imeiWiseIncomeMapOfMap);
        model.addAttribute("lastmonthCategoryUpgradeMargin", lastmonthCategoryUpgradeMargin);
        model.addAttribute("soldMap", soldMap);
        model.addAttribute("allOfferPayoutImeiIncomeModels", allOfferPayoutImeiIncomeModels);
        //model.addAttribute("iimeiSaleDateMap", imeiSaleDateMap);
        //model.addAttribute("imeiPurchaseDateMap", imeiPurchaseDateMap);

        return "last-month-imei-wise-income";
    }

    @RequestMapping(value = "/brandWiseIncome", method = RequestMethod.GET)
    public String getBrandWiseIncome(HttpServletRequest request,
                                     @RequestParam(name = "brand", required = false, defaultValue = "") String brand,
                                     @RequestParam(name = "month", required = false, defaultValue = "") int month,
                                     Model model)
            throws ProfitMandiBusinessException {
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
        LOGGER.info("loginDetails {}", loginDetails);
        LOGGER.info("brand" + brand);
        LOGGER.info("month {}", month);

        LocalDateTime monthStart = LocalDate.now().minusMonths(month).withDayOfMonth(1).atStartOfDay();
        LocalDateTime monthEnd = monthStart.plusMonths(1);

        List<OfferPayoutImeiIncomeModel> offerPayoutImeiIncomeModels = offerPayoutRepository.getTotalPayoutsByPartnerPeriod(
                YearMonth.of(monthStart.getYear(), monthStart.getMonth()), loginDetails.getFofoId(), brand, null);
        LOGGER.info("offerPayoutImeiIncomeModels - {}", offerPayoutImeiIncomeModels);
        Map<Integer, Double> additionalPurchasePayout = offerPayoutImeiIncomeModels.stream().filter(x -> x.getPurchasePayout() > 0).collect(Collectors.groupingBy(x -> x.getCatalogId(), Collectors.summingDouble(x -> x.getPurchasePayout())));
        Map<Integer, Integer> additionalPurchaseQty = offerPayoutImeiIncomeModels.stream().filter(x -> x.getPurchasePayout() > 0).collect(Collectors.groupingBy(x -> x.getCatalogId(), Collectors.summingInt(x -> 1)));
        Map<Integer, Double> additionalSalePayoutMap = offerPayoutImeiIncomeModels.stream().filter(x -> x.getSalePayout() > 0).collect(Collectors.groupingBy(x -> x.getCatalogId(), Collectors.summingDouble(x -> x.getSalePayout())));
        Map<Integer, Integer> additionalSaleQty = offerPayoutImeiIncomeModels.stream().filter(x -> x.getSalePayout() > 0).collect(Collectors.groupingBy(x -> x.getCatalogId(), Collectors.summingInt(x -> 1)));

        Set<Integer> allCatalogIds = offerPayoutImeiIncomeModels.stream().map(x -> x.getCatalogId()).collect(Collectors.toSet());
        boolean partnerTypeUpgraded = partnerTypeChangeService.isPartnerTypeUpgraded(loginDetails.getFofoId(),
                YearMonth.now());

        LOGGER.info("partnerType" + partnerTypeUpgraded);

        Map<String, Double> categoryUpgradeBrandModelMap = null;
        if (partnerTypeUpgraded) {
            categoryUpgradeBrandModelMap = schemeInOutRepository
                    .selectLastMonthCategoryUpgradeMarginByBrandModel(loginDetails.getFofoId(), brand, monthStart,
                            monthEnd)
                    .stream().collect(Collectors.toMap(x -> x.getBrand(), x -> x.getAmount()));
        }

        List<LastMonthFrontEndBrandWiseIncome> modelWiseSalesMargins = schemeInOutRepository
                .selectFrontIncomeBrandWise(loginDetails.getFofoId(), brand, monthStart, monthEnd);
        Map<Integer, LastMonthFrontEndBrandWiseIncome> modelWiseSalesMarginsMap = modelWiseSalesMargins.stream().collect(Collectors.toMap(x -> x.getCatalogItemId(), x -> x));


        List<LastMonthBrandWiseIncomeModel> modelWiseSchemeOutMargins = schemeInOutRepository
                .selectLastMonthBrandWiseIncome(loginDetails.getFofoId(), brand, monthStart, monthEnd);
        Map<Integer, LastMonthBrandWiseIncomeModel> modelWiseSchemeOutMarginsMap = modelWiseSchemeOutMargins.stream()
                .collect(Collectors.toMap(x -> x.getCatalogItemId(), x -> x));

        List<LastMonthBrandWiseIncomeModel> modelWiseSchemeInMargins = schemeInOutRepository
                .selectLastMonthPurchaseBrandWiseIncome(loginDetails.getFofoId(), brand, monthStart, monthEnd);
        Map<Integer, LastMonthBrandWiseIncomeModel> modelWiseSchemeInMarginsMap = modelWiseSchemeInMargins.stream()
                .collect(Collectors.toMap(x -> x.getCatalogItemId(), x -> x));

        allCatalogIds.addAll(modelWiseSalesMargins.stream().map(x -> x.getCatalogItemId()).collect(Collectors.toSet()));
        allCatalogIds.addAll(modelWiseSchemeInMargins.stream().map(x -> x.getCatalogItemId()).collect(Collectors.toSet()));
        allCatalogIds.addAll(modelWiseSchemeOutMargins.stream().map(x -> x.getCatalogItemId()).collect(Collectors.toSet()));

        Map<Integer, String> modelNameMap = itemRepository.selectAllByCatalogIds(allCatalogIds).stream().collect(Collectors.toMap(x -> x.getCatalogItemId(), x -> x.getModel(), (u, v) -> u));
        Map<Integer, Double> modelIncomeMap = new HashMap<>();
        Map<Integer, Integer> modelPurchaseQtyMap = new HashMap<>();
        Map<Integer, Integer> modelSaleQtyMap = new HashMap<>();
        for (int catalogItemId : modelNameMap.keySet()) {
            int saleQty = 0;
            int purchaseQty = 0;
            double income = 0;

            if (modelWiseSchemeInMarginsMap.containsKey(catalogItemId)) {
                income += (modelWiseSchemeInMarginsMap.get(catalogItemId).getAmount()) + modelWiseSchemeInMarginsMap.get(catalogItemId).getPendingSaleAmount();
                purchaseQty += modelWiseSchemeInMarginsMap.get(catalogItemId).getQty();
            }
            if (modelWiseSchemeOutMarginsMap.containsKey(catalogItemId)) {
                income += modelWiseSchemeOutMarginsMap.get(catalogItemId).getAmount() + modelWiseSchemeOutMarginsMap.get(catalogItemId).getPendingSaleAmount();
            }
            if (additionalSalePayoutMap.containsKey(catalogItemId)) {
                income += additionalSalePayoutMap.get(catalogItemId);
            }
            if (additionalPurchasePayout.containsKey(catalogItemId)) {
                income += additionalPurchasePayout.get(catalogItemId);
            }
            if (modelWiseSalesMarginsMap.containsKey(catalogItemId)) {
                income += modelWiseSalesMarginsMap.get(catalogItemId).getAmount();
                saleQty = (int) modelWiseSalesMarginsMap.get(catalogItemId).getQty();
            }
            if (additionalPurchaseQty.containsKey(catalogItemId)) {
                purchaseQty = Math.max(additionalPurchaseQty.get(catalogItemId), purchaseQty);

            }
            modelIncomeMap.put(catalogItemId, income);
            modelSaleQtyMap.put(catalogItemId, saleQty);
            modelPurchaseQtyMap.put(catalogItemId, purchaseQty);

        }

        model.addAttribute("month", month);
        model.addAttribute("modelWiseSalesMarginsMap", modelWiseSalesMarginsMap);
        model.addAttribute("modelWiseSchemeOutMarginsMap", modelWiseSchemeOutMarginsMap);
        model.addAttribute("modelWiseSchemeInMarginsMap", modelWiseSchemeInMarginsMap);
        model.addAttribute("modelNameMap", modelNameMap);
        model.addAttribute("modelPurchaseQtyMap", modelPurchaseQtyMap);
        model.addAttribute("modelSaleQtyMap", modelSaleQtyMap);
        model.addAttribute("modelIncomeMap", modelIncomeMap);
        model.addAttribute("categoryUpgradeBrandModelMap", categoryUpgradeBrandModelMap);
        model.addAttribute("additionalPurchasePayoutMap", additionalPurchasePayout);
        model.addAttribute("additionalSalePayoutMap", additionalSalePayoutMap);

        return "monthly-brand-wise-income";

    }

    @RequestMapping(value = "/monthWisePartnerIncome/{yearMonth}", method = RequestMethod.GET)
    public String publishedOffersOnMonthBefore(HttpServletRequest request, @RequestParam(required = false) boolean partnerTask, @PathVariable int yearMonth, Model model)
            throws ProfitMandiBusinessException {
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);

        LocalDateTime startOfMonth = LocalDate.now().minusMonths(yearMonth).withDayOfMonth(1).atStartOfDay();
        LocalDateTime lastMonthEnd = startOfMonth.plusMonths(1);

        YearMonth monthYear = YearMonth.now();

        boolean partnerType = partnerTypeChangeService.isPartnerTypeUpgraded(loginDetails.getFofoId(), monthYear);

        LOGGER.info("partnerType" + partnerType);

        Map<String, Double> lastMonthCategoryUpgradeMarginMap = new HashMap<>();

        if (partnerType) {
            lastMonthCategoryUpgradeMarginMap = schemeInOutRepository
                    .selectLastMonthCategoryUpgradeMarginByBrand(loginDetails.getFofoId(), startOfMonth,
                            lastMonthEnd)
                    .stream().collect(Collectors.toMap(x -> x.getBrand(), x -> x.getAmount()));
        }

        List<LastMonthCreditedIncomeModel> lastMonthPendingIncomeModels = schemeInOutRepository
                .selectLastMonthPendingIncomeByFofoId(loginDetails.getFofoId(), startOfMonth, lastMonthEnd);

        List<LastMonthCreditedIncomeModel> lastMonthPurchaseInMargins = schemeInOutRepository
                .selectLastMonthPurchaseInMarginByFofoId(loginDetails.getFofoId(), startOfMonth, lastMonthEnd);

        List<LastMonthCreditedIncomeModel> lastMonthFrontEndIncomes = schemeInOutRepository
                .selectFrontIncomeByBrand(loginDetails.getFofoId(), startOfMonth, lastMonthEnd);
        Map<String, LastMonthCreditedIncomeModel> lastMonthFrontEndIncomeMap = lastMonthFrontEndIncomes.stream().collect(Collectors.toMap(x -> x.getBrand(), x -> x));

        List<OfferPayoutImeiIncomeModel> offerPayoutImeiIncomeModels = offerPayoutRepository.getTotalPayoutsByPartnerPeriod(
                YearMonth.of(startOfMonth.getYear(), startOfMonth.getMonth()), loginDetails.getFofoId(), null, null);

        Map<String, Double> additionalPurchasePayout = offerPayoutImeiIncomeModels.stream().collect(Collectors.groupingBy(OfferPayoutImeiIncomeModel::getBrand, Collectors.summingDouble(OfferPayoutImeiIncomeModel::getPurchasePayout)));
        Map<String, Double> additionSalePayout = offerPayoutImeiIncomeModels.stream().collect(Collectors.groupingBy(OfferPayoutImeiIncomeModel::getBrand, Collectors.summingDouble(OfferPayoutImeiIncomeModel::getSalePayout)));


        Map<String, LastMonthCreditedIncomeModel> lastMonthPurchaseInMarginMap = lastMonthPurchaseInMargins.stream()
                .collect(Collectors.toMap(x -> x.getBrand(), x -> x));

        Map<String, LastMonthCreditedIncomeModel> lastMonthSaleMarginMap = schemeInOutRepository
                .selectLastMonthCreditedIncomeByFofoId(loginDetails.getFofoId(), startOfMonth, lastMonthEnd).stream()
                .collect(Collectors.toMap(x -> x.getBrand(), x -> x));


        Map<String, LastMonthCreditedIncomeModel> lastMonthPendingIncomeMap = lastMonthPendingIncomeModels.stream()
                .collect(Collectors.toMap(x -> x.getBrand(), x -> x));

        Map<String, Float> totalAmountMap = lastMonthSaleMarginMap.entrySet().stream()
                .collect(Collectors.toMap(x -> x.getKey(), x -> x.getValue().getAmount()));
        Set<String> brandSet = new HashSet<>();
        brandSet.addAll(lastMonthPurchaseInMarginMap.keySet());
        brandSet.addAll(lastMonthSaleMarginMap.keySet());
        brandSet.addAll(lastMonthPendingIncomeMap.keySet());
        brandSet.addAll(additionalPurchasePayout.keySet());
        brandSet.addAll(additionSalePayout.keySet());
        brandSet.addAll(lastMonthFrontEndIncomeMap.keySet());
        brandSet.stream().forEach(brand -> {
            totalAmountMap.put(brand,
                    (lastMonthSaleMarginMap.get(brand) == null ? 0 : lastMonthSaleMarginMap.get(brand).getAmount()) +
                            (lastMonthPurchaseInMarginMap.get(brand) == null ? 0 : lastMonthPurchaseInMarginMap.get(brand).getAmount()) +
                            (lastMonthPendingIncomeMap.get(brand) == null ? 0 : lastMonthPendingIncomeMap.get(brand).getAmount()) +
                            (additionalPurchasePayout.get(brand) == null ? 0 : additionalPurchasePayout.get(brand).longValue()) +
                            (additionSalePayout.get(brand) == null ? 0 : additionSalePayout.get(brand).longValue()) +
                            (lastMonthFrontEndIncomeMap.get(brand) == null ? 0 : lastMonthFrontEndIncomeMap.get(brand).getAmount())
            );
        });

        Map<Integer, String> monthValueMap = new HashMap<>();
        for (int i = 0; i <= 5; i++) {
            LocalDateTime monthStart = LocalDateTime.now().withDayOfMonth(1).minusMonths(i);
            monthValueMap.put(i, monthStart.format(DateTimeFormatter.ofPattern("MMM''uu")));
        }
        model.addAttribute("monthValueMap", monthValueMap);

        model.addAttribute("brandSet", brandSet);
        model.addAttribute("lastMonthPurchaseInMarginMap", lastMonthPurchaseInMarginMap);
        model.addAttribute("lastMonthSaleMarginMap", lastMonthSaleMarginMap);
        model.addAttribute("lastMonthPendingIncomeMap", lastMonthPendingIncomeMap);
        model.addAttribute("additionalPurchasePayoutMap", additionalPurchasePayout);
        model.addAttribute("additionalSalePayoutMap", additionSalePayout);
        model.addAttribute("lastMonthFrontEndIncomeMap", lastMonthFrontEndIncomeMap);

        model.addAttribute("totalAmountMap", totalAmountMap);
        model.addAttribute("month", yearMonth);
        model.addAttribute("lastMonthCategoryUpgradeMarginMap", lastMonthCategoryUpgradeMarginMap);
        LOGGER.info("totalAmountMap {}", totalAmountMap);
        LOGGER.info("lastMonthSaleMarginMap {}", lastMonthSaleMarginMap);

        if (partnerTask) {
            return "monthly-credited-income";
        } else return "last-month-credited-income";
    }

    @RequestMapping(value = "/schemes/downloadPage", method = RequestMethod.GET)
    public String downloadPage(HttpServletRequest request, Model model) {
        return "schemes-download";
    }

    @RequestMapping(value = "/schemes/download", method = RequestMethod.GET)
    public ResponseEntity<?> downloadInventoryItemAgingByInterval(HttpServletRequest request,
                                                                  @RequestParam LocalDateTime startDateTime, @RequestParam LocalDateTime endDateTime)
            throws ProfitMandiBusinessException {

        List<SchemeModel> schemeModels = schemeService.getAllSchemeModels(startDateTime, endDateTime);

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        ExcelUtils.writeSchemeModels(schemeModels, byteArrayOutputStream);

        final HttpHeaders headers = new HttpHeaders();
        headers.set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        headers.set("Content-disposition", "inline; filename=SchemesReport.xlsx");
        headers.setContentLength(byteArrayOutputStream.toByteArray().length);
        final InputStream inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        final InputStreamResource inputStreamResource = new InputStreamResource(inputStream);
        return new ResponseEntity<InputStreamResource>(inputStreamResource, headers, HttpStatus.OK);
    }

    @RequestMapping(value = "/getSchemeById", method = RequestMethod.GET)
    public String getSchemeById(HttpServletRequest request,
                                @RequestParam(name = ProfitMandiConstants.SCHEME_ID) int schemeId, Model model)
            throws ProfitMandiBusinessException {
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);

        boolean fullAccess = this.getAccess(loginDetails.getEmailId());
        Scheme scheme = schemeService.getSchemeById(schemeId);
        model.addAttribute("fullAccess", fullAccess);
        model.addAttribute("scheme", scheme);
        model.addAttribute("isAdmin", roleManager.isAdmin(loginDetails.getRoleIds()));
        return "scheme-details";
    }

    @RequestMapping(value = "/activeSchemeById", method = RequestMethod.PUT)
    public String activeSchemeById(@RequestParam(name = ProfitMandiConstants.SCHEME_ID) int schemeId,
                                   @RequestParam(name = "offset", defaultValue = "0") int offset,
                                   @RequestParam(name = "limit", defaultValue = "10") int limit, Model model)
            throws ProfitMandiBusinessException {
        schemeService.activeSchemeById(schemeId);
        List<Scheme> schemes = schemeRepository.selectAll(offset, limit);
        for (Scheme scheme : schemes) {
            if (scheme.getAmountType().equals(AmountType.PERCENTAGE)) {
                scheme.setAmountModel(scheme.getAmount() + "%");
            } else {
                scheme.setAmountModel(scheme.getAmount() + "");
            }
        }
        return "schemes";
    }

    @RequestMapping(value = "/activeSchemeByIds", method = RequestMethod.PUT)
    public String activeSchemeByIds(@RequestParam(name = ProfitMandiConstants.SCHEME_ID) String schemeIds, @RequestParam(name = "offset", defaultValue = "0") int offset, @RequestParam(name = "limit", defaultValue = "10") int limit, Model model) throws Exception {
        List<Integer> ids = Arrays.stream(schemeIds.split(",")).map(String::trim).filter(s -> !s.isEmpty()).map(Integer::parseInt).collect(Collectors.toList());
        List<Scheme> schemes = schemeRepository.selectBySchemeIds(ids);
        schemeService.activeSchemeByIds(schemes);
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
        return "response";
    }

    @RequestMapping(value = "/expireSchemeByIds", method = RequestMethod.PUT)
    public String expireSchemeByIds(@RequestParam(name = ProfitMandiConstants.SCHEME_ID) String schemeIds, @RequestParam(name = "offset", defaultValue = "0") int offset, @RequestParam(name = "limit", defaultValue = "10") int limit, Model model) throws Exception {
        List<Integer> ids = Arrays.stream(schemeIds.split(",")).map(String::trim).filter(s -> !s.isEmpty()).map(Integer::parseInt).collect(Collectors.toList());
        List<Scheme> schemes = schemeRepository.selectBySchemeIds(ids);
        schemeService.expireSchemeByIds(schemes);
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
        return "response";
    }

    @RequestMapping(value = "/expireSchemeById", method = RequestMethod.PUT)
    public String expireSchemeById(HttpServletRequest request,
                                   @RequestParam(name = ProfitMandiConstants.SCHEME_ID) int schemeId,
                                   @RequestParam(name = ProfitMandiConstants.EXPIRE_TIMESTAMP) LocalDateTime expiryTimestamp, Model model)
            throws ProfitMandiBusinessException {
        schemeService.expireSchemeById(schemeId, expiryTimestamp);
        return getDefaultSchemes(request, model);
    }

    @RequestMapping(value = "/getSchemesJson", method = RequestMethod.GET)
    public ResponseEntity<?> getSchemesJson(HttpServletRequest request,
                                            @RequestParam(name = "offset", defaultValue = "0") int offset,
                                            @RequestParam(name = "limit", defaultValue = "10") int limit, Model model)
            throws ProfitMandiBusinessException {
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
        return responseSender.ok(schemeService.getSchemes(loginDetails.getRoleIds(), offset, limit));
    }

    @RequestMapping(value = "/getCustomerOffer", method = RequestMethod.GET)
    public String getCustomerOffer(HttpServletRequest request,
                                   @RequestParam(name = "searchModel", required = false, defaultValue = "0") int searchModel, @RequestParam(name = "startDate", required = false) LocalDateTime startDate, @RequestParam(name = "endDate", required = false) LocalDateTime endDate, Model model)
            throws ProfitMandiBusinessException {
        List<CustomerOffer> customerOffers = null;
        if (searchModel > 0) {

            Item item = itemRepository.selectAllByCatalogItemId(searchModel).get(0);
            customerOffers = customerOfferRepository.selectActiveOfferByModel(searchModel, LocalDate.now());
            model.addAttribute("modelName", item.getItemDescriptionNoColor());
        } else if (startDate != null && endDate != null) {
            customerOffers = customerOfferRepository.selectOffersByDates(startDate, endDate);
        } else {
            if (startDate == null) {
                startDate = LocalDateTime.now().minusMonths(1);  // One month ago from today
            }
            if (endDate == null) {
                endDate = LocalDateTime.now();  // Current date and time
            }
            customerOffers = customerOfferRepository.selectOffersByDates(startDate, endDate);
        }

        LOGGER.info("customerOffers" + customerOffers);

        for (CustomerOffer customerOffer : customerOffers) {

            LOGGER.info("ss" + searchModel);

            if (!StringUtils.isEmpty(customerOffer.getPartnerCriteria())) {
                String partnerCriteria = offerService.getPartnerCriteriaString(gson.fromJson(customerOffer.getPartnerCriteria(), PartnerCriteria.class));
                customerOffer.setPartnerCriteriaString(partnerCriteria);
            }

        }

        List<Integer> fofoIds = fofoStoreRepository.selectActiveStores().stream().map(x -> x.getId())
                .collect(Collectors.toList());

        Map<Integer, CustomRetailer> customRetailerMap = retailerService.getAllFofoRetailers();

        Map<Integer, CustomRetailer> customRetailersMap = fofoIds.stream().map(x -> customRetailerMap.get(x))
                .filter(x -> x != null).collect(Collectors.toList()).stream()
                .collect(Collectors.toMap(x -> x.getPartnerId(), x -> x));

        model.addAttribute("customRetailersMap", customRetailersMap);
        model.addAttribute("warehouseRegion", ProfitMandiConstants.WAREHOUSE_MAP);
        model.addAttribute("searchModel", searchModel);

        model.addAttribute("customerOffers", customerOffers);
        return "customer-offer";

    }

    @RequestMapping(value = "/createCustomerOffer", method = RequestMethod.POST)
    public String createCustomerOffer(HttpServletRequest request, @RequestBody CustomerOfferModel customerOfferModel,
                                      Model model) throws Exception {

        CustomerOffer co = new CustomerOffer();
        co.setOfferName(customerOfferModel.getOfferName());
        co.setStartDate(customerOfferModel.getStartDate());
        co.setEndDate(customerOfferModel.getEndDate());
        co.setPartnerCriteria(gson.toJson(customerOfferModel.getPartnerCriteria()));
        co.setCreatedTimestamp(LocalDateTime.now());
        co.setUpdatedTimestamp(LocalDateTime.now());
        customerOfferRepository.persist(co);

        model.addAttribute("response1", mvcResponseSender.createResponseString(true));

        return "response";

    }

    @RequestMapping(value = "/customerOffer/downloadTemplate", method = RequestMethod.GET)
    public ResponseEntity<?> downloadCustomerOfferTemplate(HttpServletRequest request) throws Exception {
        List<List<?>> rows = new ArrayList<>();

        org.apache.commons.io.output.ByteArrayOutputStream baos = FileUtil.getCSVByteStream(Arrays.asList("id",
                        "Catalog Id", "Scheme Payout", "Dealer Payout", "Start Date (dd-mm-yyyy)", "End Date (dd-mm-yyyy)", "Offer Type"),
                rows);

        final HttpHeaders headers = new HttpHeaders();
        headers.set("Content-Type", "text/csv");
        headers.set("Content-disposition", "inline; filename=customer-offer-template.csv");
        headers.setContentLength(baos.toByteArray().length);

        final InputStream inputStream = new ByteArrayInputStream(baos.toByteArray());
        final InputStreamResource inputStreamResource = new InputStreamResource(inputStream);
        return new ResponseEntity<InputStreamResource>(inputStreamResource, headers, HttpStatus.OK);

    }

    @RequestMapping(value = "/customerOfferItem/upload", method = RequestMethod.POST)
    public String uploadCustomerOfferItem(HttpServletRequest request, Model model, @RequestParam int offerId,
                                          HttpServletResponse response, @RequestPart MultipartFile file) throws Throwable {

        List<CSVRecord> records = FileUtil.readFile(file);
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");

        CustomerOffer customerOffer = customerOfferRepository.selectById(offerId);
        List<Integer> catalogIds = new ArrayList<>();
        for (CSVRecord record : records) {

            CustomerOfferItem coi = customerOfferItemRepository.selectById(Integer.parseInt(record.get(0)));

            if (coi == null) {
                coi = new CustomerOfferItem();
                coi.setCatalogId(Integer.parseInt(record.get(1)));
                coi.setSchemePayout(Integer.parseInt(record.get(2)));
                coi.setDealerPayout(Integer.parseInt(record.get(3)));
                coi.setOfferType(OfferType.valueOf(record.get(6)));
                coi.setCustomerOfferId(offerId);
                coi.setAdditionalInfo(String.valueOf(record.get(7)));
                coi.setCreatedTimestamp(LocalDateTime.now());

                customerOfferItemRepository.persist(coi);

            }
            coi.setSchemePayout(Integer.parseInt(record.get(2)));
            coi.setDealerPayout(Integer.parseInt(record.get(3)));
            coi.setOfferType(OfferType.valueOf(record.get(6)));
            coi.setAdditionalInfo(String.valueOf(record.get(7)));
            coi.setCustomerOfferId(offerId);
            coi.setUpdatedTimestamp(LocalDateTime.now());

            LOGGER.info(record.get(4));

            LocalDate startDate = LocalDate.parse(record.get(4), formatter);
            LocalDate endDate = LocalDate.parse(record.get(5), formatter);

            if ((startDate.equals(customerOffer.getStartDate().toLocalDate())
                    || startDate.isAfter(customerOffer.getStartDate().toLocalDate()))
                    && (startDate.isEqual(customerOffer.getEndDate().toLocalDate())
                    || startDate.isBefore(customerOffer.getEndDate().toLocalDate()))) {
                coi.setStartDate(startDate);

            } else {

                catalogIds.add(coi.getCatalogId());
            }

            if ((endDate.equals(customerOffer.getStartDate().toLocalDate())
                    || endDate.isAfter(customerOffer.getStartDate().toLocalDate()))
                    && (endDate.isEqual(customerOffer.getEndDate().toLocalDate())
                    || endDate.isBefore(customerOffer.getEndDate().toLocalDate()))) {

                coi.setEndDate(endDate);

            } else {
                catalogIds.add(coi.getCatalogId());
            }

        }

        if (!catalogIds.isEmpty()) {
            throw new ProfitMandiBusinessException("Please set accurate start and end date", catalogIds,
                    "Please set accurate start and end date");
        }
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));

        return "response";

    }


    @RequestMapping(value = "/CheckIfExistCustomerOfferItem", method = RequestMethod.POST)
    public String CheckIfExistCustomerOfferItem(HttpServletRequest request,
                                                @RequestBody CustomerOfferItemModel customerOfferItemModel, Model model) throws Throwable {

        CustomerOffer customerOffer = customerOfferRepository.selectById(customerOfferItemModel.getOfferId());

        if (!(customerOffer.getEndDate().toLocalDate().equals(LocalDate.now()))
                && customerOffer.getEndDate().isBefore(LocalDateTime.now())) {
            throw new ProfitMandiBusinessException("Catalog Id", customerOffer.getOfferName(), "Offer is Expired");

        }

        List<CustomerOfferItem> customerOfferItems = customerOfferItemRepository
                .selectByOfferAndCatalogId(customerOfferItemModel.getOfferId(), customerOfferItemModel.getCatalogId());
        boolean response = true;
        if (!customerOfferItems.isEmpty()) {
            for (CustomerOfferItem coi : customerOfferItems) {
                if (!(coi.getEndDate().equals(LocalDate.now())) && coi.getEndDate().isAfter(LocalDate.now())) {
                    response = false;

                }
            }
        }
        model.addAttribute("response1", mvcResponseSender.createResponseString(response));
        return "response";

    }

    @RequestMapping(value = "/addCustomerOfferItem", method = RequestMethod.POST)
    public String addCustomerOfferItem(HttpServletRequest request,
                                       @RequestBody CustomerOfferItemModel customerOfferItemModel, Model model) throws Throwable {

        CustomerOffer customerOffer = customerOfferRepository.selectById(customerOfferItemModel.getOfferId());

        if (!(customerOffer.getEndDate().toLocalDate().equals(LocalDate.now()))
                && customerOffer.getEndDate().isBefore(LocalDateTime.now())) {
            throw new ProfitMandiBusinessException("Catalog Id", customerOffer.getOfferName(), "Offer is Expired");

        }

       /* List<CustomerOfferItem> customerOfferItems = customerOfferItemRepository
                .selectByOfferAndCatalogId(customerOfferItemModel.getOfferId(), customerOfferItemModel.getCatalogId());

        if (!customerOfferItems.isEmpty()) {

            for (CustomerOfferItem coi : customerOfferItems) {
                if (!(coi.getEndDate().equals(LocalDate.now())) && coi.getEndDate().isAfter(LocalDate.now())) {
                    throw new ProfitMandiBusinessException("Catalog Id", coi.getCatalogId(), "Item is already exist.");
                }
            }

        }*/

        LocalDate startDate = customerOfferItemModel.getStartDate().toLocalDate();
        LocalDate endDate = customerOfferItemModel.getEndDate().toLocalDate();
        CustomerOfferItem coi = new CustomerOfferItem();
        coi.setCatalogId(customerOfferItemModel.getCatalogId());
        coi.setSchemePayout(customerOfferItemModel.getSchemePayout());
        coi.setAdditionalInfo(customerOfferItemModel.getAdditionalInfo());
        coi.setDealerPayout(customerOfferItemModel.getDealerPayout());
        coi.setOfferType(customerOfferItemModel.getOfferType());
        coi.setCustomerOfferId(customerOfferItemModel.getOfferId());
        coi.setUpdatedTimestamp(LocalDateTime.now());
        coi.setCreatedTimestamp(LocalDateTime.now());

        if ((startDate.equals(customerOffer.getStartDate().toLocalDate())
                || startDate.isAfter(customerOffer.getStartDate().toLocalDate()))
                && (startDate.isEqual(customerOffer.getEndDate().toLocalDate())
                || startDate.isBefore(customerOffer.getEndDate().toLocalDate()))) {

            coi.setStartDate(startDate);

        } else {

            throw new ProfitMandiBusinessException("Catalog Id", customerOffer.getOfferName(),
                    "Please select accurate duration between " + customerOffer.getStartDate().toLocalDate() + " - "
                            + customerOffer.getEndDate());

        }

        if ((endDate.equals(customerOffer.getStartDate().toLocalDate())
                || endDate.isAfter(customerOffer.getStartDate().toLocalDate()))
                && (endDate.isEqual(customerOffer.getEndDate().toLocalDate())
                || endDate.isBefore(customerOffer.getEndDate().toLocalDate()))) {

            coi.setEndDate(endDate);

        } else {
            throw new ProfitMandiBusinessException("Catalog Id", customerOffer.getOfferName(),
                    "Please select accurate duration between " + customerOffer.getStartDate().toLocalDate() + " - "
                            + customerOffer.getEndDate());
        }

        customerOfferItemRepository.persist(coi);

        model.addAttribute("response1", mvcResponseSender.createResponseString(true));

        return "response";

    }

    @RequestMapping(value = "/customerOfferItem/download", method = RequestMethod.GET)
    public ResponseEntity<?> downloadOfferItem(HttpServletRequest request, @RequestParam int offerId) throws Exception {

        List<CustomerOfferItem> cois = customerOfferItemRepository.selectByOfferId(offerId);
        List<List<?>> rows = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");

        for (CustomerOfferItem coi : cois) {
            rows.add(Arrays.asList(coi.getId(), coi.getCatalogId(), coi.getSchemePayout(), coi.getDealerPayout(),
                    coi.getStartDate().format(formatter), coi.getEndDate().format(formatter), coi.getOfferType(), coi.getAdditionalInfo()));

        }

        org.apache.commons.io.output.ByteArrayOutputStream baos = FileUtil.getCSVByteStream(
                Arrays.asList("id", "Catalog Id", "Scheme Payout", "Dealer Payout", "Start Date", "End Date", "Offer Type", "Additional Info"), rows);

        final HttpHeaders headers = new HttpHeaders();
        headers.set("Content-Type", "text/csv");
        headers.set("Content-disposition", "inline; filename=customer-offer-template.csv");
        headers.setContentLength(baos.toByteArray().length);

        final InputStream inputStream = new ByteArrayInputStream(baos.toByteArray());
        final InputStreamResource inputStreamResource = new InputStreamResource(inputStream);
        return new ResponseEntity<InputStreamResource>(inputStreamResource, headers, HttpStatus.OK);

    }

    @RequestMapping(value = "/getCustomerOfferItem", method = RequestMethod.GET)
    public String getCustomerOfferItem(HttpServletRequest request, @RequestParam int offerId, Model model)
            throws Exception {

        List<CustomerOfferItem> customerOfferItems = customerOfferItemRepository.selectByOfferId(offerId);
        List<Integer> catalogIds = customerOfferItems.stream().map(x -> x.getCatalogId()).collect(Collectors.toList());

        Map<Integer, List<Item>> catalogItemMap = itemRepository.selectAllByCatalogIds(new HashSet<>(catalogIds))
                .stream().collect(Collectors.groupingBy(x -> x.getCatalogItemId()));

        List<OfferType> offerTypes = Arrays.asList(OfferType.values());

        model.addAttribute("catalogItemMap", catalogItemMap);

        model.addAttribute("offerId", offerId);

        model.addAttribute("customerOfferItems", customerOfferItems);

        model.addAttribute("offerTypes", offerTypes);

        return "customer-offer-item";

    }

    @RequestMapping(value = "/expiredCustomerOfferItem", method = RequestMethod.POST)
    public String expiredCustomerOfferItem(HttpServletRequest request, @RequestParam int id,
                                           @RequestParam LocalDateTime endDate, Model model) throws Exception {

        CustomerOfferItem customerOfferItem = customerOfferItemRepository.selectById(id);

        CustomerOffer customerOffer = customerOfferRepository.selectById(customerOfferItem.getCustomerOfferId());

        if ((endDate.toLocalDate().equals(customerOffer.getStartDate().toLocalDate())
                || endDate.toLocalDate().isAfter(customerOffer.getStartDate().toLocalDate()))
                && (endDate.toLocalDate().isEqual(customerOffer.getEndDate().toLocalDate())
                || endDate.toLocalDate().isBefore(customerOffer.getEndDate().toLocalDate()))) {

            customerOfferItem.setEndDate(endDate.toLocalDate());

        } else {
            throw new ProfitMandiBusinessException("Date", customerOffer.getOfferName(),
                    "customer offer expired on " + customerOffer.getEndDate());
        }
        Map<Integer, List<Item>> catalogItemMap = itemRepository
                .selectAllByCatalogItemId(customerOfferItem.getCatalogId()).stream()
                .collect(Collectors.groupingBy(x -> x.getCatalogItemId()));
        model.addAttribute("catalogItemMap", catalogItemMap);

        model.addAttribute("coi", customerOfferItem);

        return "customer-offer-item-index";

    }

    @RequestMapping(value = "/extendCustomerOffer", method = RequestMethod.POST)
    public String extendCustomerOffer(HttpServletRequest request, @RequestParam int id,
                                      @RequestParam LocalDateTime endDate, Model model) throws ProfitMandiBusinessException {

        CustomerOffer co = customerOfferRepository.selectById(id);
        co.setEndDate(endDate);
        co.setUpdatedTimestamp(LocalDateTime.now());

        model.addAttribute("co", co);

        return "customer-index-offer";

    }

    @RequestMapping(value = "/getSamsungUpgradeOffer", method = RequestMethod.GET)
    public String getSamsungUpgradeOffer(HttpServletRequest request, Model model) throws ProfitMandiBusinessException {

        List<UpgradeOfferStatus> uos = UpgradeOfferStatus.offerStatus;
        List<SamsungUpgradeOffer> samsungUpgradeOffers = samsungUpgradeOfferRepository.selectByStatus(
                uos.stream().filter(x -> !x.equals(UpgradeOfferStatus.rejected)).collect(Collectors.toList()));

        model.addAttribute("samsungUpgradeOffers", samsungUpgradeOffers);
        return "samsung-upgrade-offer";

    }

    @RequestMapping(value = "/approveSamsungUpgradeOffer", method = RequestMethod.POST)
    public String approveSamsungUpgradeOffer(HttpServletRequest request, @RequestParam int id, Model model)
            throws ProfitMandiBusinessException {

        SamsungUpgradeOffer suo = samsungUpgradeOfferRepository.selectById(id);
        suo.setStatus(UpgradeOfferStatus.approved);
        suo.setApprovedTimestamp(LocalDateTime.now());
        model.addAttribute("suo", suo);
        return "samsung-upgrade-offer-index";

    }

    @RequestMapping(value = "/rejectSamsungUpgradeOffer", method = RequestMethod.POST)
    public String rejectSamsungUpgradeOffer(HttpServletRequest request, @RequestParam int id, Model model)
            throws ProfitMandiBusinessException {

        SamsungUpgradeOffer suo = samsungUpgradeOfferRepository.selectById(id);
        suo.setStatus(UpgradeOfferStatus.rejected);

        model.addAttribute("suo", suo);
        return "samsung-upgrade-offer-index";

    }

    @RequestMapping(value = "/schemes/rejectActivatedSchemeIds", method = RequestMethod.GET)
    public String rejectActivatedSchemeIds(HttpServletRequest request, @RequestParam String schemeIds, Model model)
            throws Exception {
        LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
        String emailId = loginDetails.getEmailId();

        List<String> techEmails = new ArrayList<>();
        for (EscalationType et : Arrays.asList(EscalationType.L2, EscalationType.L3, EscalationType.L4, EscalationType.L5)) {
            techEmails.addAll(csService.getAuthUserByCategoryId(ProfitMandiConstants.TICKET_CATEGORY_TECHNOLOGY, et)
                    .stream().map(x -> x.getEmailId()).collect(Collectors.toList()));
        }
        if (!techEmails.contains(emailId)) {
            throw new ProfitMandiBusinessException("User", emailId, "Unauthorised access");
        }

        List<Integer> schemeIdList = Arrays.stream(schemeIds.split(","))
                .map(String::trim).filter(s -> !s.isEmpty())
                .map(Integer::parseInt).collect(Collectors.toList());

        schemeService.rejectActivatedSchemeIds(schemeIdList);
        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
        return "response";
    }

}