Subversion Repositories SmartDukaan

Rev

Rev 31416 | Rev 31459 | Go to most recent revision | 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.SearchType;
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
import com.spice.profitmandi.common.model.*;
import com.spice.profitmandi.common.solr.SolrService;
import com.spice.profitmandi.common.util.FileUtil;
import com.spice.profitmandi.common.util.PdfUtils;
import com.spice.profitmandi.common.util.StringUtils;
import com.spice.profitmandi.common.web.util.ResponseSender;
import com.spice.profitmandi.dao.entity.catalog.Item;
import com.spice.profitmandi.dao.entity.catalog.TagListing;
import com.spice.profitmandi.dao.entity.dtr.InsurancePolicy;
import com.spice.profitmandi.dao.entity.dtr.InsuranceProvider;
import com.spice.profitmandi.dao.entity.dtr.PaymentOptionTransaction;
import com.spice.profitmandi.dao.entity.fofo.*;
import com.spice.profitmandi.dao.entity.user.Address;
import com.spice.profitmandi.dao.enumuration.dtr.PaymentOptionReferenceType;
import com.spice.profitmandi.dao.enumuration.transaction.OrderStatus;
import com.spice.profitmandi.dao.model.*;
import com.spice.profitmandi.dao.repository.catalog.ItemRepository;
import com.spice.profitmandi.dao.repository.catalog.TagListingRepository;
import com.spice.profitmandi.dao.repository.dtr.*;
import com.spice.profitmandi.dao.repository.fofo.*;
import com.spice.profitmandi.dao.repository.inventory.StateRepository;
import com.spice.profitmandi.dao.repository.transaction.OrderRepository;
import com.spice.profitmandi.dao.repository.user.AddressRepository;
import com.spice.profitmandi.service.EmailService;
import com.spice.profitmandi.service.authentication.RoleManager;
import com.spice.profitmandi.service.integrations.zest.InsuranceService;
import com.spice.profitmandi.service.integrations.zest.MobileInsurancePlan;
import com.spice.profitmandi.service.order.OrderService;
import com.spice.profitmandi.service.pricing.PricingService;
import com.spice.profitmandi.service.user.RetailerService;
import com.spice.profitmandi.web.model.LoginDetails;
import com.spice.profitmandi.web.util.CookiesProcessor;
import com.spice.profitmandi.web.util.MVCResponseSender;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
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 javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

@Controller
@Transactional(rollbackFor = Throwable.class)
public class OrderController {

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

        private static final List<String> offlineOrders = Arrays.asList("EMIOD", "POD");

        @Autowired
        private CustomerRepository customerRepository;

        private boolean accessoriesDeals = true;

        @Autowired
        private RoleManager roleManager;

        @Autowired
        private Gson gson;

        @Autowired
        private CustomerReturnItemRepository customerReturnItemRepository;

        @Autowired
        private FofoOrderItemRepository fofoOrderItemRepository;

        private static final List<String> allowedDoaImeis = Arrays.asList("863903054378477");

        @Autowired
        private PaymentOptionRepository paymentOptionRepository;

        @Autowired
        private StateRepository stateRepository;

        @Autowired
        private ItemRepository itemRepository;

        @Autowired
        private MVCResponseSender mvcResponseSender;

        @Autowired
        private InsuranceService insuranceService;

        @Autowired
        private FofoOrderRepository fofoOrderRepository;

        @Autowired
        private CustomerAddressRepository customerAddressRepository;

        @Autowired
        private InsurancePolicyRepository insurancePolicyRepository;

        @Autowired
        private InsuranceProviderRepository insuranceProviderRepository;

        @Autowired
        private CookiesProcessor cookiesProcessor;

        @Autowired
        private PricingService pricingService;

        @Autowired
        private OrderService orderService;

        @Autowired
        private RetailerRegisteredAddressRepository retailerRegisteredAddressRepository;

        @Autowired
        private AddressRepository addressRepository;

        @Autowired
        private PaymentOptionTransactionRepository paymentOptionTransactionRepository;

        @Autowired
        private FofoPartnerPaymentOptionRepository fofoPartnerPaymentOptionRepository;

        @Autowired
        private ResponseSender<?> responseSender;

        @Autowired
        private PendingOrderRepository pendingOrderRepository;

        @Autowired
        private OrderRepository orderRepository;

        @Autowired
        private PendingOrderItemRepository pendingOrderItemRepository;

        @Autowired
        private FofoStoreRepository fofoStoreRepository;

        @Autowired
        private RetailerService retailerService;

        @Autowired
        private CurrentInventorySnapshotRepository currentInventorySnapshotRepository;

        @Autowired
        private TagListingRepository tagListingRepository;

        @Autowired
        private PendingOrderService pendingOrderService;

        @Autowired
        private EmailService emailService;

        @Autowired
        private SolrService commonSolrService;

        @Autowired
        private MouRepository mouRepository;

        @RequestMapping(value = "/order")
        public String orderIndex(HttpServletRequest request, @RequestParam(name = "cartData") String cartData, Model model)
                        throws ProfitMandiBusinessException {
                LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);

                int addressId = retailerRegisteredAddressRepository.selectAddressIdByRetailerId(loginDetails.getFofoId());
                Address address = addressRepository.selectById(addressId);

                List<CartFofo> cartItems = orderService.cartCheckout(cartData);
                Set<Integer> itemIds = new HashSet<>();
                List<Integer> poIds = new ArrayList<>();
                List<Integer> poItemIds = new ArrayList<>();
                for (CartFofo cartFofo : cartItems) {
                        itemIds.add(cartFofo.getItemId());
                        if (cartFofo.getPoId() != 0) {
                                poIds.add(cartFofo.getPoId());
                                poItemIds.add(cartFofo.getPoItemId());
                        }
                }

                PendingOrder po = null;
                Customer customer = null;
                PendingOrderItem poi = null;
                Map<Integer, PriceModel> mopPriceMap = pricingService.getPurchasePriceMopPriceNotFound(itemIds,
                                loginDetails.getFofoId());
                List<Integer> paymentOptionIds = fofoPartnerPaymentOptionRepository
                                .selectPaymentOptionIdsByFofoId(loginDetails.getFofoId());

                if (!poIds.isEmpty()) {
                        po = pendingOrderRepository.selectById(poIds.get(0));
                        customer = customerRepository.selectById(po.getCustomerId());
                        if (!offlineOrders.contains(po.getPayMethod())) {
                                paymentOptionIds.add(23);
                        }
                }

                if (!poItemIds.isEmpty()) {
                        poi = pendingOrderItemRepository.selectById(poItemIds.get(0));
                }

                // List<PaymentOption> paymentOptions = paymentOptionRepository.selectByIds(new
                // HashSet<>(paymentOptionIds));

                List<PaymentOption> paymentOptions = paymentOptionRepository.selectActiveOption();

                LOGGER.info("pendingOrder" + po);
                LOGGER.info("pendingOrderItem" + poi);

                LOGGER.info("mopPriceMap {}", mopPriceMap);
                model.addAttribute("stateNames",
                                stateRepository.selectAll().stream().map(x -> x.getName()).collect(Collectors.toList()));
                model.addAttribute("retailerStateName", address.getState());
                model.addAttribute("pendingPOCustomer", gson.toJson(customer));
                model.addAttribute("pendingPO", gson.toJson(po));

                model.addAttribute("cartItems", cartItems);
                model.addAttribute("pendingOrder", po);
                model.addAttribute("pendingOrderItem", poi);

                model.addAttribute("mopPriceMap", mopPriceMap);
                model.addAttribute("paymentOptions", paymentOptions);
                model.addAttribute("accessoriesDeals", accessoriesDeals);
                return "order-index";
        }

        @RequestMapping(value = "/checkplans", method = RequestMethod.GET)
        public String getInsurancePrices(HttpServletRequest request, @RequestParam float price, Model model,
                        @RequestParam int itemId) throws ProfitMandiBusinessException {
                LOGGER.info("Request received at url : {}", request.getRequestURI());

                try {
                        String response = mvcResponseSender.createResponseString(this.getPlans(price, itemId));
                        model.addAttribute("response1", response);
                } catch (Exception e) {
                        // TODO Auto-generated catch block
                        LOGGER.info(e.getMessage(), e);
                        throw new ProfitMandiBusinessException("Plans", "Plans API", "Error formatting insurance plans");
                }

                return "response";
        }

        @RequestMapping(value = "/get-order", method = RequestMethod.GET)
        public String getOrder(HttpServletRequest request, @RequestParam(name = ProfitMandiConstants.ORDER_ID) int orderId,
                        Model model) throws ProfitMandiBusinessException {
                LoginDetails fofoDetails = cookiesProcessor.getCookiesObject(request);
                FofoOrder fofoOrder = fofoOrderRepository.selectByFofoIdAndOrderId(fofoDetails.getFofoId(), orderId);
                List<FofoOrderItem> fofoLineItems = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());
                CustomerAddress customerAddress = customerAddressRepository.selectById(fofoOrder.getCustomerAddressId());
                Customer customer = customerRepository.selectById(fofoOrder.getCustomerId());
                customerAddress.setPhoneNumber(customer.getMobileNumber());
                List<PaymentOptionTransaction> paymentOptionTransactions = paymentOptionTransactionRepository
                                .selectByReferenceIdAndType(fofoOrder.getId(), PaymentOptionReferenceType.ORDER);
                Map<Integer, PaymentOption> paymentOptionIdPaymentOptionMap = this
                                .paymentOptionIdPaymentOptionMap(paymentOptionTransactions);
                List<InsurancePolicy> insurancePolicies = insurancePolicyRepository
                                .selectByRetailerIdInvoiceNumber(fofoOrder.getInvoiceNumber());
                this.addInsuranceProvider(insurancePolicies);

                model.addAttribute("fofoOrder", fofoOrder);
                model.addAttribute("fofoLineItems", fofoLineItems);
                model.addAttribute("customerBillingAddress", orderService.getBillingAddress(customerAddress));
                model.addAttribute("customerBillingAddressObj", customerAddress);
                model.addAttribute("paymentOptionTransactions", paymentOptionTransactions);
                model.addAttribute("paymentOptionIdPaymentOptionMap", paymentOptionIdPaymentOptionMap);
                model.addAttribute("insurancePolicies", insurancePolicies);
                return "order-details";
        }

        private Map<Integer, InsuranceProvider> toInsuranceProviderIdInsuranceProvider(
                        List<InsuranceProvider> insuranceProviders) {
                Map<Integer, InsuranceProvider> insuranceProviderIdInsuranceProviderMap = new HashMap<>();
                for (InsuranceProvider insuranceProvider : insuranceProviders) {
                        insuranceProviderIdInsuranceProviderMap.put(insuranceProvider.getId(), insuranceProvider);
                }
                return insuranceProviderIdInsuranceProviderMap;
        }

        private void addInsuranceProvider(List<InsurancePolicy> insurancePolicies) {
                if (insurancePolicies.isEmpty()) {
                        return;
                }
                Set<Integer> insuranceProviderIds = new HashSet<>();
                for (InsurancePolicy insurancePolicy : insurancePolicies) {
                        insuranceProviderIds.add(insurancePolicy.getProviderId());
                }
                LOGGER.info("insuranceProviderIds {}", insuranceProviderIds);
                List<InsuranceProvider> insuranceProviders = insuranceProviderRepository.selectByIds(insuranceProviderIds);
                Map<Integer, InsuranceProvider> insuranceProviderIdInsuranceProviderMap = this
                                .toInsuranceProviderIdInsuranceProvider(insuranceProviders);
                for (InsurancePolicy insurancePolicy : insurancePolicies) {
                        insurancePolicy
                                        .setInsuranceProvider(insuranceProviderIdInsuranceProviderMap.get(insurancePolicy.getProviderId()));
                }
        }

        @RequestMapping(value = "/saleDetails", method = RequestMethod.GET)
        public String getSaleDetails(HttpServletRequest request,
                        @RequestParam(name = ProfitMandiConstants.ORDER_ID) int orderId, Model model) throws Exception {
                LoginDetails fofoDetails = cookiesProcessor.getCookiesObject(request);
                boolean isAdmin = roleManager.isAdmin(fofoDetails.getRoleIds());
                FofoOrder fofoOrder = fofoOrderRepository.selectByFofoIdAndOrderId(fofoDetails.getFofoId(), orderId);
                List<FofoOrderItem> fofoOrderItems = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());
                CustomerAddress customerAddress = customerAddressRepository.selectById(fofoOrder.getCustomerAddressId());
                List<PaymentOptionTransaction> paymentOptionTransactions = paymentOptionTransactionRepository
                                .selectByReferenceIdAndType(fofoOrder.getId(), PaymentOptionReferenceType.ORDER);

                // Added Migration info as we lost it.
                if (paymentOptionTransactions == null || paymentOptionTransactions.size() == 0) {
                        PaymentOptionTransaction pot = new PaymentOptionTransaction();
                        pot.setAmount(fofoOrder.getTotalAmount());
                        pot.setCreateTimestamp(fofoOrder.getCreateTimestamp());
                        // Mark it paid through cash
                        pot.setPaymentOptionId(1);
                        pot.setReferenceType(PaymentOptionReferenceType.ORDER);
                        paymentOptionTransactionRepository.persist(pot);
                        paymentOptionTransactions.add(pot);
                        LOGGER.info("Added to get invoice");
                }
                Map<Integer, PaymentOption> paymentOptionIdPaymentOptionMap = this
                                .paymentOptionIdPaymentOptionMap(paymentOptionTransactions);
                List<InsurancePolicy> insurancePolicies = insurancePolicyRepository
                                .selectByRetailerIdInvoiceNumber(fofoOrder.getInvoiceNumber());
                this.addInsuranceProvider(insurancePolicies);
                Map<Integer, Item> itemsMap = fofoOrderItems.stream().collect(Collectors.toMap(x -> x.getItemId(), x -> {
                        try {
                                return itemRepository.selectById(x.getItemId());
                        } catch (ProfitMandiBusinessException e) {
                                // TODO Auto-generated catch block
                                return null;
                        }
                }));
                Map<Integer, Set<FofoLineItem>> fofoOrderItemIdLineItemMap = fofoOrderItems.stream()
                                .collect(Collectors.toMap(FofoOrderItem::getId, FofoOrderItem::getFofoLineItems));

                Map<Integer, List<CustomerReturnItem>> foiIdCustomerReturnInventoryItemsMap = fofoOrderItems.stream()
                                .collect(Collectors.toMap(foi -> foi.getId(),
                                                foi -> customerReturnItemRepository.selectAllByOrderItemId(foi.getId())));

                Map<Integer, Integer> inventoryItemBilledQtyMap = new HashMap<>();

                for (FofoOrderItem foi : fofoOrderItems) {
                        for (FofoLineItem fli : foi.getFofoLineItems()) {
                                inventoryItemBilledQtyMap.put(fli.getInventoryItemId(), fli.getQuantity());
                        }
                        List<CustomerReturnItem> customerReturnItems = customerReturnItemRepository
                                        .selectAllByOrderItemId(foi.getId());
                        this.markDoa(fofoOrder, foi, isAdmin);
                        for (CustomerReturnItem customerReturnItem : customerReturnItems) {
                                inventoryItemBilledQtyMap.put(customerReturnItem.getInventoryItemId(),
                                                inventoryItemBilledQtyMap.get(customerReturnItem.getInventoryItemId()) - 1);
                        }
                }

                LOGGER.info("fofoOrderItemIdLineItemMap {}", fofoOrderItemIdLineItemMap);
                model.addAttribute("fofoOrder", fofoOrder);
                model.addAttribute("itemsMap", itemsMap);
                model.addAttribute("fofoOrderItemIdLineItemsMap", StringUtils.toString(fofoOrderItemIdLineItemMap));
                model.addAttribute("foiIdCustomerReturnInventoryItemsMap",
                                StringUtils.toString(foiIdCustomerReturnInventoryItemsMap));
                model.addAttribute("fofoOrderItemIdLineItemMap", fofoOrderItemIdLineItemMap);

                model.addAttribute("fofoOrderItems", fofoOrderItems);
                model.addAttribute("inventoryItemBilledQtyMap", StringUtils.toString(inventoryItemBilledQtyMap));
                model.addAttribute("customerBillingAddress", orderService.getBillingAddress(customerAddress));
                model.addAttribute("customerBillingAddressObj", customerAddress);
                model.addAttribute("paymentOptionTransactions", paymentOptionTransactions);
                model.addAttribute("paymentOptionIdPaymentOptionMap", paymentOptionIdPaymentOptionMap);
                model.addAttribute("insurancePolicies", insurancePolicies);
                model.addAttribute("markDefective", this.markDefective(fofoOrder));
                return "sale-details";
        }

        private void markDoa(FofoOrder fofoOrder, FofoOrderItem foi, boolean isAdmin) {
                if (isAdmin) {
                        foi.setDoa(true);
                        return;
                }
                boolean isImei = foi.getFofoLineItems().stream()
                                .anyMatch(x -> org.apache.commons.lang3.StringUtils.isNotEmpty(x.getSerialNumber())
                                                && allowedDoaImeis.contains(x.getSerialNumber()));
                LocalDateTime buyDate = fofoOrder.getCreateTimestamp().truncatedTo(ChronoUnit.DAYS);
                LocalDateTime curDate = LocalDateTime.now().truncatedTo(ChronoUnit.DAYS);
                if (buyDate.isAfter(curDate.minusDays(45)) || isImei) {
                        foi.setDoa(true);
                } else
                        foi.setDoa(
                                        foi.getBrand().equals("Nokia") && foi.getCost() < 4990 && buyDate.isAfter(curDate.minusYears(1)));
        }

        private boolean markDefective(FofoOrder fofoOrder) {
                return fofoOrder.getCreateTimestamp().truncatedTo(ChronoUnit.DAYS).plusDays(180)
                                .isAfter(LocalDateTime.now().truncatedTo(ChronoUnit.DAYS));

        }

        @RequestMapping(value = "/getSearchOrder")
        public String getSearchOrder(HttpServletRequest request, Model model) throws ProfitMandiBusinessException {
                return "search-order";
        }

        @RequestMapping(value = "/getInvoiceSearchOrder")
        public String getInvoiceSearchOrder(HttpServletRequest request, Model model) throws ProfitMandiBusinessException {
                return "invoices-cancel";
        }

        @RequestMapping(value = "/customerDetails", method = RequestMethod.PUT)
        public String updateCustomerDetails(HttpServletRequest request, @RequestBody CustomCustomer customCustomer,
                        @RequestParam(name = ProfitMandiConstants.INVOICE_NUMBER) String invoiceNumber, Model model)
                        throws Exception {

                orderService.updateCustomerDetails(customCustomer, invoiceNumber);
                return this.getSearchOrderDetails(request, invoiceNumber, model);
        }

        @RequestMapping(value = "/searchOrderDetails", method = RequestMethod.GET)
        public String getSearchOrderDetails(HttpServletRequest request,
                        @RequestParam(name = ProfitMandiConstants.INVOICE_NUMBER) String invoiceNumber, Model model)
                        throws Exception {

                FofoOrder fofoOrder = fofoOrderRepository.selectByInvoiceNumber(invoiceNumber);
                List<FofoOrderItem> fofoOrderItems = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());
                Customer customer = customerRepository.selectById(fofoOrder.getCustomerId());
                CustomerAddress customerAddress = customerAddressRepository.selectById(fofoOrder.getCustomerAddressId());
                List<Integer> fofoPartnerPaymentOptions = fofoPartnerPaymentOptionRepository
                                .selectPaymentOptionIdsByFofoId(fofoOrder.getFofoId());
                Map<Integer, Item> itemsMap = fofoOrderItems.stream().collect(Collectors.toMap(x -> x.getItemId(), x -> {
                        try {
                                return itemRepository.selectById(x.getItemId());
                        } catch (ProfitMandiBusinessException e) {
                                // TODO Auto-generated catch block
                                return null;
                        }
                }));
                LOGGER.info("fofoPartnerPaymentOptions" + fofoPartnerPaymentOptions);
                List<PaymentOptionTransaction> paymentOptionTransactions = paymentOptionTransactionRepository
                                .selectByReferenceIdAndType(fofoOrder.getId(), PaymentOptionReferenceType.ORDER);
                LOGGER.info("paymentOptionTransactions" + paymentOptionTransactions);
                Map<Integer, PaymentOption> paymentOptionIdPaymentOptionMap = this
                                .paymentOptionIdPaymentOptionMapUsingPaymentOptions(fofoPartnerPaymentOptions);
                Map<Integer, PaymentOptionTransaction> paymentOptionIdPaymentOptionTransactionMap = this
                                .paymentOptionIdPaymentOptionTransactionMap(paymentOptionTransactions);
                LOGGER.info("paymentOptionIdPaymentOptionTransactionMap" + paymentOptionIdPaymentOptionTransactionMap.keySet());
                List<InsurancePolicy> insurancePolicies = insurancePolicyRepository
                                .selectByRetailerIdInvoiceNumber(fofoOrder.getInvoiceNumber());
                this.addInsuranceProvider(insurancePolicies);
                model.addAttribute("fofoOrder", fofoOrder);
                for (FofoOrderItem fofoOrderItem : fofoOrderItems) {
                        fofoOrderItem.setDoa(true);
                }

                Map<Integer, Set<FofoLineItem>> fofoOrderItemIdLineItemMap = fofoOrderItems.stream()
                                .collect(Collectors.toMap(FofoOrderItem::getId, FofoOrderItem::getFofoLineItems));

                Map<Integer, List<CustomerReturnItem>> foiIdCustomerReturnInventoryItemsMap = fofoOrderItems.stream()
                                .collect(Collectors.toMap(foi -> foi.getId(),
                                                foi -> customerReturnItemRepository.selectAllByOrderItemId(foi.getId())));

                Map<Integer, Integer> inventoryItemBilledQtyMap = new HashMap<>();

                for (FofoOrderItem foi : fofoOrderItems) {
                        for (FofoLineItem fli : foi.getFofoLineItems()) {
                                inventoryItemBilledQtyMap.put(fli.getInventoryItemId(), fli.getQuantity());
                        }
                        List<CustomerReturnItem> customerReturnItems = customerReturnItemRepository
                                        .selectAllByOrderItemId(foi.getId());
                        for (CustomerReturnItem customerReturnItem : customerReturnItems) {
                                inventoryItemBilledQtyMap.put(customerReturnItem.getInventoryItemId(),
                                                inventoryItemBilledQtyMap.get(customerReturnItem.getInventoryItemId()) - 1);
                        }
                }
                model.addAttribute("foiIdCustomerReturnInventoryItemsMap",
                                StringUtils.toString(foiIdCustomerReturnInventoryItemsMap));
                model.addAttribute("fofoOrderItems", fofoOrderItems);
                model.addAttribute("inventoryItemBilledQtyMap", StringUtils.toString(inventoryItemBilledQtyMap));
                model.addAttribute("fofoOrderItemIdLineItemsMap", StringUtils.toString(fofoOrderItemIdLineItemMap));
                model.addAttribute("itemsMap", itemsMap);
                model.addAttribute("markDefective", true);
                model.addAttribute("customer", customer);
                model.addAttribute("customerAddress", customerAddress);
                model.addAttribute("paymentOptionTransactions", paymentOptionTransactions);
                model.addAttribute("paymentOptionIdPaymentOptionMap", paymentOptionIdPaymentOptionMap);
                model.addAttribute("paymentOptionIdPaymentOptionTransactionMap", paymentOptionIdPaymentOptionTransactionMap);
                model.addAttribute("insurancePolicies", insurancePolicies);
                model.addAttribute("fofoPartnerPaymentOptions", fofoPartnerPaymentOptions);
                model.addAttribute("totalNumberOfPaymentOptionId", fofoPartnerPaymentOptions.size());
                model.addAttribute("stateNames",
                                stateRepository.selectAll().stream().map(x -> x.getName()).collect(Collectors.toList()));
                return "search-order-details";
        }

        private Map<Integer, PaymentOption> paymentOptionIdPaymentOptionMap(
                        List<PaymentOptionTransaction> paymentOptionTransactions) {
                Set<Integer> paymentOptionIds = new HashSet<>();
                for (PaymentOptionTransaction paymentOptionTransaction : paymentOptionTransactions) {
                        paymentOptionIds.add(paymentOptionTransaction.getPaymentOptionId());
                }
                List<PaymentOption> paymentOptions = paymentOptionRepository.selectByIds(paymentOptionIds);
                Map<Integer, PaymentOption> paymentOptionIdPaymentOptionMap = new HashMap<>();
                for (PaymentOption paymentOption : paymentOptions) {
                        paymentOptionIdPaymentOptionMap.put(paymentOption.getId(), paymentOption);
                }
                return paymentOptionIdPaymentOptionMap;
        }

        private Map<Integer, PaymentOption> paymentOptionIdPaymentOptionMapUsingPaymentOptions(
                        List<Integer> fofoPartnerPaymentOptions) {
                List<PaymentOption> paymentOptions = paymentOptionRepository
                                .selectByIds(new HashSet<>(fofoPartnerPaymentOptions));
                Map<Integer, PaymentOption> paymentOptionIdPaymentOptionMap = new HashMap<>();
                for (PaymentOption paymentOption : paymentOptions) {
                        paymentOptionIdPaymentOptionMap.put(paymentOption.getId(), paymentOption);
                }
                return paymentOptionIdPaymentOptionMap;
        }

        private Map<Integer, PaymentOptionTransaction> paymentOptionIdPaymentOptionTransactionMap(
                        List<PaymentOptionTransaction> paymentOptionTransactions) {
                Map<Integer, PaymentOptionTransaction> paymentOptionIdPaymentOptionTransactionMap = new HashMap<>();
                for (PaymentOptionTransaction paymentOptionTransaction : paymentOptionTransactions) {
                        paymentOptionIdPaymentOptionTransactionMap.put(paymentOptionTransaction.getPaymentOptionId(),
                                        paymentOptionTransaction);
                }
                return paymentOptionIdPaymentOptionTransactionMap;
        }

        @RequestMapping(value = "/create-order", method = RequestMethod.POST)
        public String createOrder(HttpServletRequest request, @RequestBody CreateOrderRequest createOrderRequest,
                        Model model) throws ProfitMandiBusinessException {
                // throw new ProfitMandiBusinessException("Billing is on hold temporarily",
                // "Billing is on hold temporarily", "Billing is on hold temporarily");
                LOGGER.info("request at uri {} body {}", request.getRequestURI(), createOrderRequest);
                LoginDetails fofoDetails = cookiesProcessor.getCookiesObject(request);

                int fofoOrderId = orderService.createOrder(createOrderRequest, fofoDetails.getFofoId(), accessoriesDeals);

                LOGGER.info("Order has been created successfully...");
                return "redirect:/get-order/?orderId=" + fofoOrderId;
        }

        @RequestMapping(value = "/order/bad_return", method = RequestMethod.POST)
        public ResponseEntity<?> badReturn(HttpServletRequest request, @RequestBody FoiBadReturnRequest foiBadReturnRequest,
                        Model model) throws ProfitMandiBusinessException {
                LOGGER.info("request at uri {} body {}", request.getRequestURI(), foiBadReturnRequest);
                LoginDetails fofoDetails = cookiesProcessor.getCookiesObject(request);
                CustomerCreditNote custmoerCreditNote;
                if (roleManager.isAdmin(fofoDetails.getRoleIds())) {
                        FofoOrderItem foi = fofoOrderItemRepository.selectById(foiBadReturnRequest.getFofoOrderItemId());
                        FofoOrder fo = fofoOrderRepository.selectByOrderId(foi.getOrderId());
                        custmoerCreditNote = orderService.badReturn(fo.getFofoId(), foiBadReturnRequest);
                } else {
                        custmoerCreditNote = orderService.badReturn(fofoDetails.getFofoId(), foiBadReturnRequest);
                }
                return responseSender.ok(custmoerCreditNote.getId());
        }

        @RequestMapping(value = "/generateInvoice")
        public ResponseEntity<?> generateInvoice(HttpServletRequest request, HttpServletResponse response,
                        @RequestParam(name = ProfitMandiConstants.ORDER_ID) int orderId) throws ProfitMandiBusinessException {
                LOGGER.info("Request received at url {} with params [{}={}] ", request.getRequestURI(),
                                ProfitMandiConstants.ORDER_ID, orderId);
                LoginDetails fofoDetails = cookiesProcessor.getCookiesObject(request);
                InvoicePdfModel pdfModel = null;
                if (roleManager.isAdmin(fofoDetails.getRoleIds())) {
                        pdfModel = orderService.getInvoicePdfModel(orderId);
                } else {
                        pdfModel = orderService.getInvoicePdfModel(fofoDetails.getFofoId(), orderId);
                }
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                PdfUtils.generateAndWrite(Arrays.asList(pdfModel), byteArrayOutputStream);
                LOGGER.info("Pdf Stream length {}", byteArrayOutputStream.toByteArray().length);
                final HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_PDF);
                headers.setContentDispositionFormData("inline", "invoice-" + pdfModel.getInvoiceNumber() + ".pdf");
                headers.setContentLength(byteArrayOutputStream.toByteArray().length);
                final InputStream inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
                final InputStreamResource inputStreamResource = new InputStreamResource(inputStream);
                return new ResponseEntity<>(inputStreamResource, headers, HttpStatus.OK);
        }

        @RequestMapping(value = "/generateInvoices")
        public ResponseEntity<?> generateInvoice(HttpServletRequest request, HttpServletResponse response,
                        @RequestParam LocalDateTime startDate, @RequestParam LocalDateTime endDate, @RequestParam int partnerId)
                        throws ProfitMandiBusinessException {
                LoginDetails fofoDetails = cookiesProcessor.getCookiesObject(request);
                List<InvoicePdfModel> pdfModels = new ArrayList<>();
                if (roleManager.isAdmin(fofoDetails.getRoleIds())) {
                        List<Integer> orderIds = fofoOrderRepository.selectByFofoId(partnerId, startDate, endDate, 0, 0).stream()
                                        .map(x -> x.getId()).collect(Collectors.toList());
                        for (int orderId : orderIds) {
                                pdfModels.add(orderService.getInvoicePdfModel(orderId));
                        }
                        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                        PdfUtils.generateAndWrite(pdfModels, byteArrayOutputStream);
                        LOGGER.info("Pdf Stream length {}", byteArrayOutputStream.toByteArray().length);
                        final HttpHeaders headers = new HttpHeaders();
                        headers.setContentType(MediaType.APPLICATION_PDF);
                        headers.set("Content-disposition", "inline; filename=invoice-" + partnerId + ".pdf");
                        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);
                } else {
                        throw new ProfitMandiBusinessException("Auth", fofoDetails.getEmailId(), "Unauthorised access");
                }
        }

        @RequestMapping(value = "/saleHistory")
        public String saleHistory(HttpServletRequest request,
                        @RequestParam(name = "searchValue", defaultValue = "") String searchValue,
                        @RequestParam(name = "searchType", defaultValue = "") SearchType searchType,
                        @RequestParam(required = false) LocalDateTime startTime,
                        @RequestParam(required = false) LocalDateTime endTime,
                        @RequestParam(name = "offset", defaultValue = "0") int offset,
                        @RequestParam(name = "limit", defaultValue = "10") int limit, Model model)
                        throws ProfitMandiBusinessException {
                LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);

                Map<String, Object> map = orderService.getSaleHistory(loginDetails.getFofoId(), searchType, searchValue,
                                startTime, endTime, offset, limit);
                model.addAllAttributes(map);
                return "sale-history";
        }

        @RequestMapping(value = "/downloadInvoices")
        public ResponseEntity<?> downloadInvoices(HttpServletRequest request,
                        @RequestParam(name = "searchValue", defaultValue = "") String searchValue,
                        @RequestParam(name = "searchType", defaultValue = "") SearchType searchType,
                        @RequestParam(required = false) LocalDateTime startTime,
                        @RequestParam(required = false) LocalDateTime endTime,
                        @RequestParam(name = "offset", defaultValue = "0") int offset,
                        @RequestParam(name = "limit", defaultValue = "10") int limit, Model model)
                        throws ProfitMandiBusinessException {
                LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);

                Map<String, Object> map = orderService.getSaleHistory(loginDetails.getFofoId(), searchType, searchValue,
                                startTime, endTime, offset, 100);
                List<FofoOrder> fofoOrders = (List<FofoOrder>) map.get("saleHistories");

                if (fofoOrders.size() == 0) {
                        throw new ProfitMandiBusinessException("Search criteria", "", "No orders found for criteria");
                }

                final HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_PDF);
                headers.set("Content-disposition", "inline; filename=invoices.pdf");
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                List<InvoicePdfModel> pdfModels = new ArrayList<>();
                for (FofoOrder fofoOrder : fofoOrders) {
                        try {
                                pdfModels.add(orderService.getInvoicePdfModel(fofoOrder.getId()));
                        } catch (Exception e) {
                                LOGGER.info("could not create invoice for {}, invoice number {}", fofoOrder.getId(),
                                                fofoOrder.getInvoiceNumber());
                        }
                }
                PdfUtils.generateAndWrite(pdfModels, byteArrayOutputStream);
                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 = "/credit-note/{creditNoteId}")
        public ResponseEntity<?> downloadCreditNote(HttpServletRequest request, @PathVariable int creditNoteId)
                        throws ProfitMandiBusinessException {
                CreditNotePdfModel creditNotePdfModel = orderService.getCreditNotePdfModel(creditNoteId);
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                PdfUtils.generateAndWriteCustomerCreditNotes(Arrays.asList(creditNotePdfModel), byteArrayOutputStream);
                LOGGER.info("Pdf Stream length {}", byteArrayOutputStream.toByteArray().length);
                final HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_PDF);
                headers.set("Content-disposition",
                                "inline; filename=invoice-" + creditNotePdfModel.getCreditNoteNumber() + ".pdf");
                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 = "/getPaginatedSaleHistory")
        public String getSaleHistoryPaginated(HttpServletRequest request,
                        @RequestParam(name = "searchValue", defaultValue = "") String searchValue,
                        @RequestParam(name = "searchType", defaultValue = "") SearchType searchType,
                        @RequestParam(required = false) LocalDateTime startTime,
                        @RequestParam(required = false) LocalDateTime endTime,
                        @RequestParam(name = "offset", defaultValue = "0") int offset,
                        @RequestParam(name = "limit", defaultValue = "10") int limit, Model model)
                        throws ProfitMandiBusinessException {
                LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
                Map<String, Object> map = orderService.getSaleHistoryPaginated(loginDetails.getFofoId(), searchType,
                                searchValue, startTime, endTime, offset, limit);
                model.addAllAttributes(map);
                return "sale-history-paginated";
        }

        @PutMapping(value = "/updatePaymentTransaction")
        public String updateTransactionDetails(HttpServletRequest request, @RequestParam String referenceType,
                        @RequestParam int fofoId, @RequestParam int referenceId,
                        @RequestBody PartnerOptionsAndItemAmountModel partnerOptionsAndItemAmountModel,
                        @RequestParam float totalAmount, Model model) throws Exception {

                List<PaymentOptionTransactionModel> paymentOptionTransactionModels = partnerOptionsAndItemAmountModel
                                .getPaymentOptionTransactionModel();
                LOGGER.info(paymentOptionTransactionModels);
                FofoOrder fofoOrder = fofoOrderRepository.selectByFofoIdAndOrderId(fofoId, referenceId);
                LOGGER.info("sdssd" + fofoOrder);
                fofoOrder.setTotalAmount(totalAmount);
                List<FofoItemIdAmountModel> fofoItemIdAmountModel = partnerOptionsAndItemAmountModel.getItemAmountModel();
                for (FofoItemIdAmountModel fim : fofoItemIdAmountModel) {
                        LOGGER.info("fim" + fim.getFofoItemId());

                        LOGGER.info("fimAmount" + fim.getAmount());
                        Item item = itemRepository.selectById(fim.getItemId());
                        TagListing tagListing = tagListingRepository.selectByItemId(item.getId());
                        FofoOrderItem fofoOrderItem = fofoOrderItemRepository.selectById(fim.getFofoItemId());
                        LOGGER.info("category" + item.getCategoryId());
                        if (item.getCategoryId() == ProfitMandiConstants.MOBILE_CATEGORY_ID) {
                                if (fofoOrderItem.getMop() <= fim.getAmount()) {

                                        if (fim.getAmount() <= tagListing.getMrp()) {
                                                fofoOrderItem.setSellingPrice(fim.getAmount());
                                        } else {
                                                throw new ProfitMandiBusinessException("Amount", fim.getAmount(),
                                                                "Sum of amount is not less than  to MRP");
                                        }

                                        LOGGER.info("fofoOrderItem2" + fofoOrderItem);

                                } else {
                                        // TODO below mop condition need to added added
                                        fofoOrderItem.setSellingPrice(fim.getAmount());
                                }

                        } else {
                                fofoOrderItem.setSellingPrice(fim.getAmount());
                                LOGGER.info("fofoOrderItem1" + fofoOrderItem);

                        }
                        LOGGER.info("fofoOrderItem" + fofoOrderItem);

                }

                /*
                 * for (PaymentOptionTransactionModel paymentOptionTransactionModel :
                 * paymentOptionTransactionModels) { amount = amount +
                 * paymentOptionTransactionModel.getAmount(); } LOGGER.info("FofoOrder amount" +
                 * fofoOrder.getUnitPrice() + "amount" + amount); if (amount ==
                 * fofoOrder.getUnitPrice()) {
                 */
                if (paymentOptionTransactionModels.size() > 0) {
                        List<PaymentOptionTransaction> paymentOptionTransactions = paymentOptionTransactionRepository
                                        .selectByReferenceIdAndType(referenceId, PaymentOptionReferenceType.ORDER);
                        Map<Integer, PaymentOptionTransaction> paymentOptionIdPaymentOptionTransactionMap = this
                                        .paymentOptionIdPaymentOptionTransactionMap(paymentOptionTransactions);
                        LOGGER.info(
                                        "paymentOptionIdPaymentOptionTransactionMap" + paymentOptionIdPaymentOptionTransactionMap.keySet());
                        for (PaymentOptionTransactionModel paymentOptionTransactionModel : paymentOptionTransactionModels) {
                                if (paymentOptionIdPaymentOptionTransactionMap
                                                .containsKey(paymentOptionTransactionModel.getPaymentOptionId())) {

                                        PaymentOptionTransaction paymentOptionTransaction = paymentOptionIdPaymentOptionTransactionMap
                                                        .get(paymentOptionTransactionModel.getPaymentOptionId());

                                        if (paymentOptionTransactionModel.getAmount() == 0) {
                                                paymentOptionTransactionRepository.delete(paymentOptionTransaction);
                                                LOGGER.info("deleted successfully");
                                        } else {

                                                paymentOptionTransaction.setAmount(paymentOptionTransactionModel.getAmount());
                                                paymentOptionTransactionRepository.persist(paymentOptionTransaction);
                                                LOGGER.info("updated successfully");

                                        }
                                } else {
                                        if (paymentOptionTransactionModel.getAmount() > 0) {
                                                PaymentOptionTransaction paymentOptionTransaction = new PaymentOptionTransaction();
                                                paymentOptionTransaction.setReferenceId(referenceId);
                                                paymentOptionTransaction.setReferenceType(PaymentOptionReferenceType.ORDER);
                                                paymentOptionTransaction.setPaymentOptionId(paymentOptionTransactionModel.getPaymentOptionId());
                                                paymentOptionTransaction.setAmount(paymentOptionTransactionModel.getAmount());
                                                paymentOptionTransaction.setFofoId(fofoId);
                                                paymentOptionTransaction.setCreateTimestamp(fofoOrder.getCreateTimestamp());
                                                paymentOptionTransactionRepository.persist(paymentOptionTransaction);
                                                LOGGER.info("inserted successfully");
                                        }
                                }

                        }

                        model.addAttribute("response1", mvcResponseSender.createResponseString(true));
                }
                /*
                 * else
                 * 
                 * { throw new ProfitMandiBusinessException("Amount", amount,
                 * "Sum of amount is not equal to total amount"); }
                 */

                return "response";

        }

        private Map<String, List<MobileInsurancePlan>> getPlans(float sellingPrice, int itemId)
                        throws ProfitMandiBusinessException {
                try {
                        Map<String, List<MobileInsurancePlan>> productDurationPlans = insuranceService.getAllPlans(itemId,
                                        sellingPrice);
                        return productDurationPlans;
                } catch (Exception e) {
                        LOGGER.info(e, e);
                        throw new ProfitMandiBusinessException("Fetch Insurance Plans", "Insurance",
                                        "Could not fetch insurance Plans");
                }

        }

        @GetMapping("/insuranceDetails")
        public String getInsuranceDetails(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);
                long size = 0;
                List<InsurancePolicy> insurancePolicies = insurancePolicyRepository.selectByRetailerId(loginDetails.getFofoId(),
                                offset, limit);
                size = insurancePolicyRepository.selectCountByRetailerId(loginDetails.getFofoId());
                Map<Integer, String> providerPolicyNameAndIdMap = insuranceProviderRepository
                                .selectByIds(insurancePolicies.stream().map(x -> x.getProviderId()).collect(Collectors.toSet()))
                                .stream().collect(Collectors.toMap(InsuranceProvider::getId, InsuranceProvider::getName));
                if (size < limit) {
                        model.addAttribute("end", offset + size);
                } else {
                        model.addAttribute("end", offset + limit);
                }
                model.addAttribute("start", offset + 1);
                model.addAttribute("size", size);
                model.addAttribute("insurancePolicies", insurancePolicies);
                model.addAttribute("providerPolicyNameAndIdMap", providerPolicyNameAndIdMap);
                return "insurance-details";
        }

        @GetMapping("/insuranceDetailsPaginated")
        public String getInsuranceDetailsPaginated(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);
                List<InsurancePolicy> insurancePolicies = insurancePolicyRepository.selectByRetailerId(loginDetails.getFofoId(),
                                offset, limit);
                Map<Integer, String> providerPolicyNameAndIdMap = insuranceProviderRepository
                                .selectByIds(insurancePolicies.stream().map(x -> x.getProviderId()).collect(Collectors.toSet()))
                                .stream().collect(Collectors.toMap(InsuranceProvider::getId, InsuranceProvider::getName));
                model.addAttribute("insurancePolicies", insurancePolicies);
                model.addAttribute("providerPolicyNameAndIdMap", providerPolicyNameAndIdMap);
                return "insurance-details-paginated";
        }

        @GetMapping("/getMouForm")
        public String getMouForm(HttpServletRequest request, Model model) throws Exception {
                LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);

                Mou mou = mouRepository.selectByFofoId(loginDetails.getFofoId());
                if (mou != null) {
                        if (mou.getUpdateTimestamp().getMonth().equals(LocalDateTime.now().getMonth())) {
                                model.addAttribute("response1", mvcResponseSender.createResponseString(true));
                        } else {
                                model.addAttribute("response1", mvcResponseSender.createResponseString(false));
                        }

                } else {
                        model.addAttribute("response1", mvcResponseSender.createResponseString(false));

                }
                return "response";

        }

        @GetMapping("/pendingOrders")
        public String getPendingOrders(HttpServletRequest request, Model model) throws ProfitMandiBusinessException {
                LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
                boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());
                Mou mou = mouRepository.selectByFofoId(loginDetails.getFofoId());
                if (mou == null) {
                        mou = new Mou();
                        mou.setFofoId(loginDetails.getFofoId());
                        mou.setCreateTimestamp(LocalDateTime.now());
                        mou.setUpdateTimestamp(LocalDateTime.now());
                        mouRepository.persist(mou);
                } else if (!mou.getUpdateTimestamp().getMonth().equals(LocalDateTime.now().getMonth())) {
                        mou.setUpdateTimestamp(LocalDateTime.now());
                }

                List<PendingOrderItem> pendingOrderItem = null;

                pendingOrderItem = pendingOrderItemRepository.selectOrderItemByStatusAndFofoId(OrderStatus.PROCESSING,
                                loginDetails.getFofoId());

                Map<String, Object> map = null;

                map = pendingOrderService.getItemOrders(pendingOrderItem, loginDetails.getFofoId());
                model.addAttribute("inventoryMap", map.get("inventoryMap"));

                model.addAttribute("pendingOrderItem", map.get("pendingOrderItem"));

                LOGGER.info("partnerInventoryMap" + map.get("partnerInventoryMap"));
                model.addAttribute("isAdmin", isAdmin);
                return "pending_fofo_order";

        }

        @GetMapping("/billedOrders")
        public String getBilledOrders(HttpServletRequest request, Model model) throws ProfitMandiBusinessException {
                LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
                boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());

                List<PendingOrderItem> pendingOrderItem = null;

                if (isAdmin) {

                        pendingOrderItem = pendingOrderItemRepository.selectOrderItemByStatus(OrderStatus.BILLED);

                } else {
                        pendingOrderItem = pendingOrderItemRepository.selectOrderItemByStatusAndFofoId(OrderStatus.BILLED,
                                        loginDetails.getFofoId());
                }

                Map<String, Object> map = pendingOrderService.getItemOrders(pendingOrderItem, loginDetails.getFofoId());

                model.addAttribute("pendingOrderItem", map.get("pendingOrderItem"));
                model.addAttribute("isAdmin", isAdmin);
                return "billed_order_item";
        }

        @GetMapping("/settledOrders")
        public String getSettledOrders(HttpServletRequest request, Model model) throws ProfitMandiBusinessException {
                LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
                boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());

                List<PendingOrderItem> pendingOrderItem = null;

                if (isAdmin) {

                        pendingOrderItem = pendingOrderItemRepository.selectOrderItemByStatus(OrderStatus.SETTLED);

                } else {
                        pendingOrderItem = pendingOrderItemRepository.selectOrderItemByStatusAndFofoId(OrderStatus.SETTLED,
                                        loginDetails.getFofoId());
                }

                Map<String, Object> map = pendingOrderService.getItemOrders(pendingOrderItem, loginDetails.getFofoId());

                model.addAttribute("pendingOrderItem", map.get("pendingOrderItem"));
                model.addAttribute("isAdmin", isAdmin);
                return "settled_order_item";
        }

        @GetMapping("/unsettledOrders")
        public String getunsettledOrders(HttpServletRequest request, Model model) throws ProfitMandiBusinessException {
                LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
                boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());

                List<PendingOrderItem> pendingOrderItem = null;

                if (isAdmin) {

                        pendingOrderItem = pendingOrderItemRepository.selectOrderItemByStatus(OrderStatus.UNSETTLED);

                } else {
                        pendingOrderItem = pendingOrderItemRepository.selectOrderItemByStatusAndFofoId(OrderStatus.UNSETTLED,
                                        loginDetails.getFofoId());
                }

                Map<String, Object> map = pendingOrderService.getItemOrders(pendingOrderItem, loginDetails.getFofoId());

                model.addAttribute("pendingOrderItem", map.get("pendingOrderItem"));
                model.addAttribute("isAdmin", isAdmin);
                return "unsettled_order_item";
        }

        @GetMapping("/claimedOrders")
        public String getclaimedOrders(HttpServletRequest request, Model model) throws ProfitMandiBusinessException {
                LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
                boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());
                List<Integer> fofoIds = fofoStoreRepository.selectActiveStores().stream().map(x -> x.getId())
                                .collect(Collectors.toList());

                List<PendingOrderItem> pendingOrderItem = null;

                if (isAdmin) {

                        pendingOrderItem = pendingOrderItemRepository.selectOrderItemByStatus(OrderStatus.CLAIMED);
                        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);

                } else {
                        pendingOrderItem = pendingOrderItemRepository.selectOrderItemByStatusAndFofoId(OrderStatus.CLAIMED,
                                        loginDetails.getFofoId());
                }

                Map<String, Object> map = pendingOrderService.getItemOrders(pendingOrderItem, loginDetails.getFofoId());

                model.addAttribute("pendingOrderItem", map.get("pendingOrderItem"));
                model.addAttribute("isAdmin", isAdmin);
                return "claim_raised_order_item";
        }

        @GetMapping("/getPendingOrderItem")
        public String getPendingOrderItem(HttpServletRequest request, @RequestParam int orderId, Model model)
                        throws ProfitMandiBusinessException {
                LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
                Map<Integer, Item> itemMap = new HashMap<>();
                Map<Integer, CurrentInventorySnapshot> inventoryMap = new HashMap<>();
                PendingOrder pendingPO = pendingOrderRepository.selectById(orderId);
                Customer customer = customerRepository.selectById(pendingPO.getCustomerId());
                List<PendingOrderItem> pendingOrderItems = pendingOrderItemRepository.selectByOrderId(orderId);
                for (PendingOrderItem pendingOrderItem : pendingOrderItems) {
                        Item item = itemRepository.selectById(pendingOrderItem.getItemId());
                        CurrentInventorySnapshot cis = currentInventorySnapshotRepository
                                        .selectByItemAndFofoId(pendingOrderItem.getItemId(), pendingPO.getFofoId());
                        itemMap.put(pendingOrderItem.getItemId(), item);
                        LOGGER.info("cis" + cis);
                        inventoryMap.put(pendingOrderItem.getItemId(), cis);
                }

                LOGGER.info("inventoryMap" + inventoryMap);
                model.addAttribute("pendingOrderItems", pendingOrderItems);
                model.addAttribute("itemMap", itemMap);
                model.addAttribute("inventoryMap", inventoryMap);
                model.addAttribute("pendingPO", gson.toJson(pendingPO));
                model.addAttribute("pendingPOCustomer", gson.toJson(customer));
                model.addAttribute("isAdmin", roleManager.isAdmin(loginDetails.getRoleIds()));
                return "pending-order-item";
        }

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

                PendingOrderItem pendingOrderItem = pendingOrderItemRepository.selectById(id);
                model.addAttribute("pendingOrderItem", pendingOrderItem);
                return "cancel-pending-order";
        }

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

                PendingOrder pendingOrder = pendingOrderRepository.selectById(id);
                Map<Integer, CustomRetailer> customRetailersMap = retailerService.getFofoRetailers(true);
                model.addAttribute("customRetailersMap", customRetailersMap);
                model.addAttribute("pendingOrder", pendingOrder);
                return "change-partner-po";
        }

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

                PendingOrder pendingOrder = pendingOrderRepository.selectById(id);
                pendingOrder.setFofoId(fofoId);
                model.addAttribute("response1", mvcResponseSender.createResponseString(true));

                return "response";
        }

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

                LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
                PendingOrderItem pendingOrderItem = pendingOrderItemRepository.selectById(id);

                pendingOrderItem.setStatus(OrderStatus.CANCELLED);
                pendingOrderItem.setStatusDescription(loginDetails.getEmailId());
                pendingOrderItem.setRemark(reason);
                pendingOrderItem.setCancelledTimestamp(LocalDateTime.now());
                PendingOrder pendingOrder = pendingOrderRepository.selectById(pendingOrderItem.getOrderId());

                List<OrderStatus> status = pendingOrderItemRepository.selectByOrderId(pendingOrderItem.getOrderId()).stream()
                                .map(x -> x.getStatus()).collect(Collectors.toList());

                Customer customer = customerRepository.selectById(pendingOrder.getCustomerId());

                List<Integer> catalogIds = new ArrayList<>();

                Item item = itemRepository.selectById(pendingOrderItem.getItemId());
                pendingOrderItem.setItemName(item.getItemDescription());
                catalogIds.add(item.getCatalogItemId());

                Map<Integer, JSONObject> contentMap = commonSolrService.getContentByCatalogIds(catalogIds);
                JSONObject jsonObj = contentMap.get(item.getCatalogItemId());
                pendingOrderItem.setImgUrl(jsonObj.getString("imageUrl_s"));
                pendingOrder.setPendingOrderItems(Arrays.asList(pendingOrderItem));
                CustomerAddress customerAddress = customerAddressRepository.selectById(pendingOrder.getCustomerAddressId());

                DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy h:mm a");

                Map<String, Object> emailModel = new HashMap<>();
                emailModel.put("customer", customerAddress);
                emailModel.put("pendingOrder", pendingOrder);
                emailModel.put("date", dateTimeFormatter);
                LOGGER.info("emal" + customer.getEmailId());
                String[] customerEmail = null;
                if (customer.getEmailId() != null && !customer.getEmailId().isEmpty()) {
                        customerEmail = new String[] { customer.getEmailId() };

                        List<String> bccTo = Arrays.asList("tejbeer.kaur@smartdukaan.com");

                        emailService.sendMailWithAttachments("Order Cancellation", "order-cancellation.vm", emailModel,
                                        customerEmail, null, bccTo.toArray(new String[0]));

                }

                if (!status.contains(OrderStatus.PENDING) && !status.contains(OrderStatus.PROCESSING)
                                && !status.contains(OrderStatus.BILLED) && !status.contains(OrderStatus.UNSETTLED)
                                && !status.contains(OrderStatus.CLAIMED)) {
                        pendingOrder.setStatus(OrderStatus.CLOSED);
                }
                pendingOrderItemRepository.persist(pendingOrderItem);

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

                return "response";
        }

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

                LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
                PendingOrderItem pendingOrderItem = pendingOrderItemRepository.selectById(id);
                PendingOrder pendingOrder = pendingOrderRepository.selectById(pendingOrderItem.getOrderId());

                if (pendingOrder.getTotalAmount() == pendingOrder.getPaidAmount()) {
                        pendingOrderItem.setStatus(OrderStatus.UNSETTLED);
                        pendingOrderItem.setDeliveredTimestamp(LocalDateTime.now());

                } else {
                        pendingOrderItem.setStatus(OrderStatus.SETTLED);
                        pendingOrderItem.setDeliveredTimestamp(LocalDateTime.now());

                }

                List<OrderStatus> status = pendingOrderItemRepository.selectByOrderId(pendingOrderItem.getOrderId()).stream()
                                .map(x -> x.getStatus()).collect(Collectors.toList());

                List<Integer> catalogIds = new ArrayList<>();

                Item item = itemRepository.selectById(pendingOrderItem.getItemId());
                pendingOrderItem.setItemName(item.getItemDescription());
                catalogIds.add(item.getCatalogItemId());

                Map<Integer, JSONObject> contentMap = commonSolrService.getContentByCatalogIds(catalogIds);
                JSONObject jsonObj = contentMap.get(item.getCatalogItemId());
                pendingOrderItem.setImgUrl(jsonObj.getString("imageUrl_s"));
                pendingOrder.setPendingOrderItems(Arrays.asList(pendingOrderItem));
                CustomerAddress customerAddress = customerAddressRepository.selectById(pendingOrder.getCustomerAddressId());

                DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy h:mm a");

                Map<String, Object> emailModel = new HashMap<>();
                emailModel.put("customer", customerAddress);
                emailModel.put("pendingOrder", pendingOrder);
                emailModel.put("date", dateTimeFormatter);
                Customer customer = customerRepository.selectById(pendingOrder.getCustomerId());
                String[] customerEmail = null;
                if (customer.getEmailId() != null && !customer.getEmailId().isEmpty()) {
                        customerEmail = new String[] { customer.getEmailId() };
                        List<String> bccTo = Arrays.asList("tejbeer.kaur@smartdukaan.com");

                        emailService.sendMailWithAttachments("Order Delivered with SmartDukaan", "order-delivered.vm", emailModel,
                                        customerEmail, null, bccTo.toArray(new String[0]));

                }
                if (!status.contains(OrderStatus.PENDING) && !status.contains(OrderStatus.PROCESSING)
                                && !status.contains(OrderStatus.BILLED) && !status.contains(OrderStatus.UNSETTLED)
                                && !status.contains(OrderStatus.CLAIMED))

                {
                        pendingOrder.setStatus(OrderStatus.CLOSED);
                }
                pendingOrderItemRepository.persist(pendingOrderItem);
                model.addAttribute("response1", mvcResponseSender.createResponseString(true));

                return "response";
        }

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

                LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
                PendingOrderItem pendingOrderItem = pendingOrderItemRepository.selectById(id);
                PendingOrder pendingOrder = pendingOrderRepository.selectById(pendingOrderItem.getOrderId());

                if (pendingOrder.getTotalAmount() == pendingOrder.getPaidAmount()) {
                        pendingOrderItem.setStatus(OrderStatus.CLAIMED);
                        pendingOrderItem.setClaimedTimestamp(LocalDateTime.now());

                }
                pendingOrderItemRepository.persist(pendingOrderItem);
                model.addAttribute("response1", mvcResponseSender.createResponseString(true));

                return "response";
        }

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

                LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
                PendingOrderItem pendingOrderItem = pendingOrderItemRepository.selectById(id);
                pendingOrderItem.setVerifiedTimestamp(LocalDateTime.now());

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

                return "response";
        }

        @RequestMapping(value = "/cancelOrderByInvoice", method = RequestMethod.POST)
        public String cancelOrder(HttpServletRequest request, @RequestParam List<String> invoiceNumbers, Model model)
                        throws Exception {
                orderService.cancelOrder(invoiceNumbers);
                model.addAttribute("response1", mvcResponseSender.createResponseString(true));

                return "response";
        }

        @RequestMapping(value = "/getOnlineOrder", method = RequestMethod.GET)
        public String cancelOrder(HttpServletRequest request, Model model) throws Exception {
                return "online-order";
        }

        @GetMapping("/getAllOrdersByStatus")
        public String getAllOrdersByStatus(HttpServletRequest request, @RequestParam OrderStatus status,
                        @RequestParam(required = false) LocalDateTime startTime,
                        @RequestParam(required = false) LocalDateTime endTime, Model model) throws ProfitMandiBusinessException {
                LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
                boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());

                LOGGER.info("startTime" + startTime);

                LOGGER.info("endTime" + endTime);

                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);

                List<PendingOrderItem> pendingOrderItem = null;
                if (startTime == null) {
                        pendingOrderItem = pendingOrderItemRepository.selectOrderItemByStatus(status);
                } else {
                        List<OrderStatus> statusList = new ArrayList<>();
                        if (status.equals(OrderStatus.DELIVERED)) {
                                statusList.add(OrderStatus.SETTLED);
                                statusList.add(OrderStatus.UNSETTLED);
                        } else {
                                statusList.add(status);
                        }
                        pendingOrderItem = pendingOrderItemRepository.selectByStatusAndCreateTimestamp(statusList,
                                        startTime.toLocalDate().atStartOfDay(), endTime);
                }
                Map<String, Object> map = pendingOrderService.getItemOrders(pendingOrderItem, 0);

                model.addAttribute("pendingOrderItem", map.get("pendingOrderItem"));
                model.addAttribute("partnerInventoryMap", map.get("partnerInventoryMap"));

                model.addAttribute("isAdmin", isAdmin);
                return "online-order-item";
        }

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

                LocalDateTime currentDate = LocalDate.now().atStartOfDay();
                LocalDateTime currentStartMonth = currentDate.minusDays(30).toLocalDate().atStartOfDay();
                FofoStore fs = fofoStoreRepository.selectByRetailerId(fofoDetails.getFofoId());

                List<FocoSaleReportModel> focoSaleReportList = fofoOrderRepository.selectFocoSaleReport(fofoDetails.getFofoId(),
                                fs.getCode(), currentStartMonth, currentDate);

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

                model.addAttribute("startDate", currentDate.minusDays(30).toLocalDate());
                model.addAttribute("endDate", LocalDate.now());
                model.addAttribute("focoSaleReportList", focoSaleReportList);
                return "foco-sale-report";
        }

        @RequestMapping(value = "/downloadFranchiseeSales", method = RequestMethod.GET)
        public ResponseEntity<?> getdownloadFranchiseeSales(HttpServletRequest request,
                        @RequestParam(name = "startDate", required = true, defaultValue = "") LocalDate startDate,
                        @RequestParam(name = "endDate", required = true, defaultValue = "") LocalDate endDate, Model model)
                        throws Exception {
                LoginDetails fofoDetails = cookiesProcessor.getCookiesObject(request);
                List<List<?>> rows = new ArrayList<>();

                FofoStore fs = fofoStoreRepository.selectByRetailerId(fofoDetails.getFofoId());
                List<FocoSaleReportModel> focoSaleReportList = fofoOrderRepository.selectFocoSaleReport(fofoDetails.getFofoId(),
                                fs.getCode(), startDate.atStartOfDay(), endDate.atStartOfDay());
                LOGGER.info("FocoSaleReportList {}", focoSaleReportList);
                DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");

                for (FocoSaleReportModel fsr : focoSaleReportList) {

                        rows.add(Arrays.asList(fsr.getCode(), fsr.getName(), fsr.getCity(), fsr.getState(), fsr.getRegion(),
                                        fsr.getItemId(), fsr.getBrand(), fsr.getModelName(), fsr.getModelNumber(), fsr.getColor(),
                                        fsr.getQuantity(), fsr.getDp(), fsr.getSellingPrice(), fsr.getMop(), fsr.getSerialNumber(),
                                        fsr.getCreateDate().format(dateTimeFormatter), fsr.getCustomerName(), fsr.getCustomerPhone(),
                                        fsr.getCustomerCity(), fsr.getCustomerPincode(), fsr.getInvoiceNumber(), fsr.getPurchaseReference(),
                                        fsr.getCustomerGstNumber(), fsr.getCancelledTimestamp().format(dateTimeFormatter),
                                        fsr.getGrnCompleteDate().format(dateTimeFormatter), fsr.getHygieneRating(), fsr.getRating(),
                                        fsr.getStatus(), fsr.getRemark(), fsr.getCreatedTimestamp().format(dateTimeFormatter),
                                        fsr.getDisposedTimestamp().format(dateTimeFormatter),
                                        fsr.getNextTimestamp().format(dateTimeFormatter),
                                        fsr.getActivationTimestamp().format(dateTimeFormatter),
                                        fsr.getActivationTimestamp().format(dateTimeFormatter), fsr.getLabel()));

                }

                org.apache.commons.io.output.ByteArrayOutputStream baos = FileUtil.getCSVByteStream(
                                Arrays.asList("Code", "Name", "City", "State", "Region", "Item Id", "Brand", "Model Name",
                                                "Model Number", "Color", "Quantity", "Dp", "Selling_Price", "mop", "Serial Number",
                                                "Create Date", "Customer Name", "Customer Phone", "Customer City", " Customer Pincode",
                                                "Invoice  Number", "Purchase Reference", "Customer Gst Number", " Cancelled Timestamp",
                                                "GRN Complete Date", "Hygiene Rating", "Rating", "Status", "Remark", "Created Timestamp",
                                                "Disposed Timestamp", " Next Timestamp", "Activation Timestamp", "Create Timestamp", "Label"),
                                rows);

                ResponseEntity<?> responseEntity = orderService.downloadReportInCsv(baos, rows, "Franchisee Sales Report");

                return responseEntity;

        }

        @RequestMapping(value = "/downloadWalletSummaryReport", method = RequestMethod.GET)
        public ResponseEntity<?> getDownloadWalletSummaryReport(HttpServletRequest request,
                        @RequestParam(name = "startDate", required = true, defaultValue = "") LocalDate startDate,
                        @RequestParam(name = "endDate", required = true, defaultValue = "") LocalDate endDate, Model model)
                        throws Exception {

                List<List<?>> rows = new ArrayList<>();
                LoginDetails fofoDetails = cookiesProcessor.getCookiesObject(request);
                List<WalletSummaryReportModel> walletSummartList = fofoOrderRepository.selectWalletSummaryReport(
                                fofoDetails.getFofoId(), startDate.atStartOfDay(), endDate.atTime(LocalTime.MAX));
                LOGGER.info("walletSummartList {}", walletSummartList);
                DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");

                for (WalletSummaryReportModel walletSummart : walletSummartList) {

                        rows.add(Arrays.asList(walletSummart.getId(), walletSummart.getCode(), walletSummart.getName(),
                                        walletSummart.getEmail(), walletSummart.getPhone(), walletSummart.getAmount(),
                                        walletSummart.getRefundableAmount(), walletSummart.getReference(), walletSummart.getReferenceType(),
                                        walletSummart.getBusinessTimestamp().format(dateTimeFormatter), walletSummart.getDescription()));

                }

                org.apache.commons.io.output.ByteArrayOutputStream baos = FileUtil
                                .getCSVByteStream(Arrays.asList("Id", "Code", "Name", "Email", "Phone", "Amount", "Refundable_amount",
                                                "Reference", "Reference_type", "Business_timestamp", "Description"), rows);

                ResponseEntity<?> responseEntity = orderService.downloadReportInCsv(baos, rows, "Wallet Statement Report");

                return responseEntity;

        }

        @RequestMapping(value = "/walletSummaryReport", method = RequestMethod.GET)
        public String getWalletSummaryReport(HttpServletRequest request, Model model) throws Exception {
                LoginDetails fofoDetails = cookiesProcessor.getCookiesObject(request);

                LocalDateTime currentDate = LocalDate.now().atStartOfDay();
                LocalDateTime currentStartMonth = currentDate.minusDays(30).toLocalDate().atStartOfDay();

                List<WalletSummaryReportModel> walletSummartList = fofoOrderRepository
                                .selectWalletSummaryReport(fofoDetails.getFofoId(), currentStartMonth, currentDate);
                LOGGER.info("walletSummartList {}", walletSummartList);

                model.addAttribute("startDate", currentDate.minusDays(30).toLocalDate());
                model.addAttribute("endDate", LocalDate.now());
                model.addAttribute("walletSummartList", walletSummartList);

                return "wallet-summary-report";
        }

        @RequestMapping(value = "/pendingIndentReport", method = RequestMethod.GET)
        public String getPendingIndentReport(HttpServletRequest request, Model model) throws Exception {
                LoginDetails fofoDetails = cookiesProcessor.getCookiesObject(request);

                LocalDateTime currentDate = LocalDate.now().atStartOfDay();
                LocalDateTime currentStartMonth = currentDate.minusMonths(2).toLocalDate().atStartOfDay();

                List<PendingIndentReportModel> pendingIndentReports = fofoOrderRepository
                                .selectPendingIndentReport(fofoDetails.getFofoId(), currentStartMonth, currentDate);
                LOGGER.info("pendingIndentReports {}", pendingIndentReports);

                model.addAttribute("startDate", currentDate.minusMonths(2).toLocalDate());
                model.addAttribute("endDate", LocalDate.now());
                model.addAttribute("pendingIndentReports", pendingIndentReports);

                return "pending-indent-report";
        }

        @RequestMapping(value = "/pendingIndentReportDownload", method = RequestMethod.GET)
        public ResponseEntity<?> getPendingIndentReportDownload(HttpServletRequest request, Model model) throws Exception {
                LoginDetails fofoDetails = cookiesProcessor.getCookiesObject(request);
                LocalDateTime currentDate = LocalDate.now().atStartOfDay();
                LocalDateTime currentStartMonth = currentDate.minusMonths(2).toLocalDate().atStartOfDay();
                List<List<?>> rows = new ArrayList<>();
                List<PendingIndentReportModel> pendingIndentReports = fofoOrderRepository
                                .selectPendingIndentReport(fofoDetails.getFofoId(), currentStartMonth, currentDate);
                LOGGER.info("pendingIndentReports {}", pendingIndentReports);
                DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");

                for (PendingIndentReportModel pir : pendingIndentReports) {

                        rows.add(Arrays.asList(pir.getTransactionId(), pir.getOrderId(),
                                        pir.getCreatTimestamp().format(dateTimeFormatter), pir.getItemId(), pir.getBrand(),
                                        pir.getModelName(), pir.getModelNumber(), pir.getColor(), pir.getQuantity(), pir.getUnitPrice(),
                                        pir.getWalletAmount(), pir.getStatus(), pir.getInvoiceNumber(),
                                        pir.getBillingTimestamp().format(dateTimeFormatter)));

                }

                org.apache.commons.io.output.ByteArrayOutputStream baos = FileUtil.getCSVByteStream(Arrays.asList(
                                "Transaction Id", "Order Id", "Created_At", "Item_Id", "Brand", "Model Name", "Model Number", "Color",
                                "Quantity", "Unit Price", "Wallet Deduction", "Status", "Invoice Number", "Billing Timestamp"), rows);

                ResponseEntity<?> responseEntity = orderService.downloadReportInCsv(baos, rows, "Order Status Summary Report");

                return responseEntity;
        }

        @RequestMapping(value = "/schemePayoutReport", method = RequestMethod.GET)
        public String getSchemePayoutReport(HttpServletRequest request, Model model) throws Exception {
                LoginDetails fofoDetails = cookiesProcessor.getCookiesObject(request);

                LocalDateTime currentDate = LocalDate.now().atStartOfDay();
                LocalDateTime startDate = currentDate.minusMonths(3).toLocalDate().atStartOfDay();

                List<SchemePayoutReportModel> schemePayoutReports = fofoOrderRepository
                                .selectSchemePayoutReport(fofoDetails.getFofoId(), startDate, currentDate);
                LOGGER.info("schemePayoutReports {}", schemePayoutReports);

                model.addAttribute("startDate", currentDate.minusMonths(3).toLocalDate());
                model.addAttribute("endDate", LocalDate.now());
                model.addAttribute("schemePayoutReports", schemePayoutReports);

                return "scheme-payout-report";
        }

        @RequestMapping(value = "/selectPartnerBillingSummaryReport", method = RequestMethod.GET)
        public String getselectPartnerBillingSummaryReport(HttpServletRequest request, Model model) throws Exception {
                LoginDetails fofoDetails = cookiesProcessor.getCookiesObject(request);

                LocalDateTime currentDate = LocalDate.now().atStartOfDay();
                LocalDateTime currentStartMonth = currentDate.minusMonths(3).toLocalDate().atStartOfDay();

                List<PartnerBillingSummaryModel> partnerBillingSummaryReports = fofoOrderRepository
                                .selectPartnerBillingSummaryReport(fofoDetails.getFofoId(), currentStartMonth, currentDate);

                model.addAttribute("startDate", currentDate.minusMonths(3).toLocalDate());
                model.addAttribute("endDate", LocalDate.now());
                model.addAttribute("partnerBillingSummaryReports", partnerBillingSummaryReports);

                return "partner-billing-summary-report";
        }

        @RequestMapping(value = "/priceDropReport", method = RequestMethod.GET)
        public String getSelectPriceDropReport(HttpServletRequest request, Model model) throws Exception {
                LoginDetails fofoDetails = cookiesProcessor.getCookiesObject(request);

                LocalDateTime currentDate = LocalDate.now().atStartOfDay();
                LocalDateTime currentStartMonth = currentDate.minusMonths(3).toLocalDate().atStartOfDay();

                List<PriceDropReportModel> priceDropReports = orderRepository.selectPriceDropReport(fofoDetails.getFofoId(),
                                currentStartMonth, currentDate);

                model.addAttribute("startDate", currentDate.minusMonths(3).toLocalDate());
                model.addAttribute("endDate", LocalDate.now());
                model.addAttribute("priceDropReports", priceDropReports);

                return "price-drop-report";
        }

        @RequestMapping(value = "/downloadPriceDropReport", method = RequestMethod.GET)
        public ResponseEntity<?> getSelectDownloadPriceDropReport(HttpServletRequest request,
                        @RequestParam(name = "startDate", required = true, defaultValue = "") LocalDate startDate,
                        @RequestParam(name = "endDate", required = true, defaultValue = "") LocalDate endDate, Model model)
                        throws Exception {
                LoginDetails fofoDetails = cookiesProcessor.getCookiesObject(request);

                List<List<?>> rows = new ArrayList<>();
                List<PriceDropReportModel> priceDropReports = orderRepository.selectPriceDropReport(fofoDetails.getFofoId(),
                                startDate.atStartOfDay(), endDate.atTime(LocalTime.MAX));

                for (PriceDropReportModel pdr : priceDropReports) {

                        rows.add(Arrays.asList(pdr.getCode(), pdr.getId(), pdr.getBrand(), pdr.getModelName(), pdr.getModelNumber(),
                                        pdr.getAffectedOn(), pdr.getAmount(), pdr.getPartnerPayout(), pdr.getImei(), pdr.getStatus(),
                                        pdr.getUpdateTimestamp(), pdr.getRejectionReason()));

                }
                org.apache.commons.io.output.ByteArrayOutputStream baos = FileUtil
                                .getCSVByteStream(Arrays.asList("code", "Price_Drop_Id", "brand", "model_name", "model_number",
                                                "affected_on", "amount", "partner_payout", "Imei", "status", "processed_on", "Reason"), rows);

                ResponseEntity<?> responseEntity = orderService.downloadReportInCsv(baos, rows, "price drop report");

                return responseEntity;

        }

        @RequestMapping(value = "/downloadPartnerBillingSummaryReport", method = RequestMethod.GET)
        public ResponseEntity<?> getdownloadPartnerBillingSummaryReport(HttpServletRequest request,
                        @RequestParam(name = "startDate", required = true, defaultValue = "") LocalDate startDate,
                        @RequestParam(name = "endDate", required = true, defaultValue = "") LocalDate endDate, Model model)
                        throws Exception {

                List<List<?>> rows = new ArrayList<>();
                LoginDetails fofoDetails = cookiesProcessor.getCookiesObject(request);

                LocalDateTime currentDate = LocalDate.now().atStartOfDay();
                LocalDateTime currentStartMonth = currentDate.minusMonths(3).toLocalDate().atStartOfDay();

                List<PartnerBillingSummaryModel> partnerBillingSummaryReports = fofoOrderRepository
                                .selectPartnerBillingSummaryReport(fofoDetails.getFofoId(), startDate.atStartOfDay(),
                                                endDate.atTime(LocalTime.MAX));
                DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");

                for (PartnerBillingSummaryModel pbsr : partnerBillingSummaryReports) {

                        rows.add(Arrays.asList(pbsr.getId(), pbsr.getCreateTimestamp().format(dateTimeFormatter),
                                        pbsr.getBillingTimestamp().format(dateTimeFormatter),
                                        pbsr.getDeliveryTimestamp().format(dateTimeFormatter),
                                        pbsr.getDeliveryTimestamp().format(dateTimeFormatter),
                                        pbsr.getPartnerGrnTimestamp().format(dateTimeFormatter), pbsr.getTransactionId(),
                                        pbsr.getLogisticsTransactionId(), pbsr.getAirwayBillNumber(), pbsr.getStatusSubGroup(),
                                        pbsr.getStatusName(), pbsr.getRetailerId(), pbsr.getRetailerName(), pbsr.getItemId(),
                                        pbsr.getBrand(), pbsr.getModelName(), pbsr.getModelNumber(), pbsr.getColor(), pbsr.getUnitPrice(),
                                        pbsr.getQuantity(), pbsr.getTotalPrice(), pbsr.getInvoiceNumber(), pbsr.getIgstRate(),
                                        pbsr.getCgstRate(), pbsr.getSgstRate()));

                }

                org.apache.commons.io.output.ByteArrayOutputStream baos = FileUtil.getCSVByteStream(Arrays.asList("OrderId",
                                "CREATION_DATE", "BILLING_DATE", "DELIVERED_ON", "SCANNED_IN_ON", "Transaction_id", "master_order_id",
                                "airwaybill_no", "statusSubGroupp", "statusName", "customer_id", "customer_name", "Item_Id", "brand",
                                "model_name", "model_number", "color", "selling_price", "Quantity", "total_price", "invoice_number",
                                "igstrate", "cgstrate", "sgstrate"), rows);

                ResponseEntity<?> responseEntity = orderService.downloadReportInCsv(baos, rows, "Billing Statement Report");

                return responseEntity;

        }

        @RequestMapping(value = "/invoiceSchemeOutSummaryReport", method = RequestMethod.GET)
        public String getInvoiceSchemeOutSummaryReport(HttpServletRequest request, Model model) throws Exception {
                LoginDetails fofoDetails = cookiesProcessor.getCookiesObject(request);

                LocalDateTime currentDate = LocalDate.now().atStartOfDay();
                LocalDateTime currentStartMonth = currentDate.minusMonths(3).toLocalDate().atStartOfDay();

                List<FocoSchemeOutReportModel> focoSchemeOutReports = fofoOrderRepository
                                .selectInvoiceSchemeOutSummaryReport(fofoDetails.getFofoId(), currentStartMonth, currentDate);
                LOGGER.info("focoSchemeOutReportModel {}", focoSchemeOutReports);

                model.addAttribute("startDate", currentDate.minusMonths(3).toLocalDate());
                model.addAttribute("endDate", LocalDate.now());
                model.addAttribute("focoSchemeOutReports", focoSchemeOutReports);

                return "invoicewise-scheme-out-report";
        }

        @RequestMapping(value = "/downloadInvoiceSchemeOutSummaryReport", method = RequestMethod.GET)
        public ResponseEntity<?> getDownloadInvoiceSchemeOutSummaryReport(HttpServletRequest request, Model model)
                        throws Exception {
                LoginDetails fofoDetails = cookiesProcessor.getCookiesObject(request);

                List<List<?>> rows = new ArrayList<>();
                LocalDateTime currentDate = LocalDate.now().atStartOfDay();
                LocalDateTime currentStartMonth = currentDate.minusMonths(3).toLocalDate().atStartOfDay();

                List<FocoSchemeOutReportModel> focoSchemeOutReports = fofoOrderRepository
                                .selectInvoiceSchemeOutSummaryReport(fofoDetails.getFofoId(), currentStartMonth, currentDate);
                LOGGER.info("focoSchemeOutReportModel {}", focoSchemeOutReports);

                for (FocoSchemeOutReportModel fsor : focoSchemeOutReports) {
                        rows.add(Arrays.asList(fsor.getInvoiceNumber(), fsor.getQuantity(), fsor.getBrand(), fsor.getModelName(),
                                        fsor.getModelNumber(), fsor.getColor(), fsor.getAmount()));

                }

                org.apache.commons.io.output.ByteArrayOutputStream baos = FileUtil.getCSVByteStream(
                                Arrays.asList("InvoiceNumber", "Quantity", "Brand", "Model Name", "Model Number", "Color", "Amount"),
                                rows);

                ResponseEntity<?> responseEntity = orderService.downloadReportInCsv(baos, rows,
                                "invoice wise scheme out Summary Report");

                return responseEntity;
        }

        @RequestMapping(value = "/schemePayoutReportDownload", method = RequestMethod.GET)
        public ResponseEntity<?> getSchemePayoutReportDownload(HttpServletRequest request,
                        @RequestParam(name = "startDate", required = true, defaultValue = "") LocalDate startDate,
                        @RequestParam(name = "endDate", required = true, defaultValue = "") LocalDate endDate, Model model)
                        throws Exception {
                LoginDetails fofoDetails = cookiesProcessor.getCookiesObject(request);

                List<List<?>> rows = new ArrayList<>();
                LocalDateTime currentDate = LocalDate.now().atStartOfDay();
                LocalDateTime currentStartMonth = currentDate.minusMonths(3).toLocalDate().atStartOfDay();

                List<SchemePayoutReportModel> schemePayoutReports = fofoOrderRepository
                                .selectSchemePayoutReport(fofoDetails.getFofoId(), currentStartMonth, currentDate);
                LOGGER.info("schemePayoutReports {}", schemePayoutReports);

                for (SchemePayoutReportModel spr : schemePayoutReports) {

                        rows.add(Arrays.asList(spr.getId(), spr.getSerialNumber(), spr.getBrand(), spr.getModelName(),
                                        spr.getModelNumber(), spr.getColor(), spr.getSchemeInDp(), spr.getSchemeOutDp(), spr.getSchemeId(),
                                        spr.getName(), spr.getType(), spr.getAmountType(), spr.getPurchaseReference(),
                                        spr.getInvoiceNumber(), spr.getSioAmount(), spr.getStatus(), spr.getStatusDescription(),
                                        spr.getCreateTimestamp(), spr.getRolledBackTimestamp()));

                }
                org.apache.commons.io.output.ByteArrayOutputStream baos = FileUtil.getCSVByteStream(Arrays.asList("Item_Id",
                                "serial_number", "Brand", "Model Name", "Model Number", "Color", "Scheme_IN_DP", "Scheme_out_dp",
                                "Scheme_Id", "Name", "Type", "amount", "Purchase_Invoice", "SALE_INOVOICE", "Amount", "status",
                                "description", "create_timestamp", "rolled_back_timestamp"), rows);

                ResponseEntity<?> responseEntity = orderService.downloadReportInCsv(baos, rows, "Scheme Payout Summary Report");

                return responseEntity;
        }

        @GetMapping("/getAllOnlineOrder")
        public String getAllOrders(HttpServletRequest request, @RequestParam(required = false) LocalDate date, Model model)
                        throws ProfitMandiBusinessException {
                LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
                boolean isAdmin = roleManager.isAdmin(loginDetails.getRoleIds());
                if (date == null) {
                        date = LocalDate.now().minusDays(3);
                }

                LOGGER.info("date" + date);
                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);

                List<PendingOrderItem> pendingOrderItem = null;

                pendingOrderItem = pendingOrderItemRepository.selectAll(date.atStartOfDay(), LocalDateTime.now());

                Map<String, Object> map = pendingOrderService.getItemOrders(pendingOrderItem, 0);

                model.addAttribute("pendingOrderItem", map.get("pendingOrderItem"));
                model.addAttribute("partnerInventoryMap", map.get("partnerInventoryMap"));
                model.addAttribute("date", date);
                model.addAttribute("isAdmin", isAdmin);
                return "online-all-order-item";
        }
}