Subversion Repositories SmartDukaan

Rev

Rev 31238 | Rev 31362 | 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.MessageType;
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
import com.spice.profitmandi.common.model.CustomRetailer;
import com.spice.profitmandi.common.model.ProfitMandiConstants;
import com.spice.profitmandi.common.model.SendNotificationModel;
import com.spice.profitmandi.common.util.FileUtil;
import com.spice.profitmandi.dao.entity.auth.AuthUser;
import com.spice.profitmandi.dao.entity.cs.Position;
import com.spice.profitmandi.dao.entity.logistics.Provider;
import com.spice.profitmandi.dao.entity.logistics.ProviderDetails;
import com.spice.profitmandi.dao.entity.logistics.ProviderTat;
import com.spice.profitmandi.dao.entity.logistics.PublicHolidays;
import com.spice.profitmandi.dao.entity.transaction.Order;
import com.spice.profitmandi.dao.entity.user.Address;
import com.spice.profitmandi.dao.model.*;
import com.spice.profitmandi.dao.repository.auth.AuthRepository;
import com.spice.profitmandi.dao.repository.cs.CsService;
import com.spice.profitmandi.dao.repository.cs.PositionRepository;
import com.spice.profitmandi.dao.repository.dtr.UserAccountRepository;
import com.spice.profitmandi.dao.repository.logistics.ProviderDetailsRepository;
import com.spice.profitmandi.dao.repository.logistics.ProviderRepository;
import com.spice.profitmandi.dao.repository.logistics.ProviderTatRepository;
import com.spice.profitmandi.dao.repository.logistics.PublicHolidaysRepository;
import com.spice.profitmandi.dao.repository.transaction.OrderRepository;
import com.spice.profitmandi.dao.repository.user.AddressRepository;
import com.spice.profitmandi.dao.repository.user.UserRepository;
import com.spice.profitmandi.dao.service.biuedart.BluedartService;
import com.spice.profitmandi.service.LogisticsService;
import com.spice.profitmandi.service.NotificationService;
import com.spice.profitmandi.web.model.LoginDetails;
import com.spice.profitmandi.web.util.CookiesProcessor;
import com.spice.profitmandi.web.util.MVCResponseSender;
import in.shop2020.logistics.DeliveryType;
import in.shop2020.logistics.PickUpType;
import in.shop2020.model.v1.order.OrderStatus;
import org.apache.commons.csv.CSVRecord;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONArray;
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.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.transaction.Transactional;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;

@Controller
@Transactional(rollbackOn = Throwable.class)
public class LogisticsController {

        @Autowired
        private OrderRepository orderRepository;

        @Autowired
        private ProviderRepository providerRepository;

        @Autowired
        private ProviderDetailsRepository providerDetailsRepository;

        @Autowired
        private MVCResponseSender mvcResponseSender;

        @Autowired
        private ProviderTatRepository providerTatRepository;

        @Autowired
        private PublicHolidaysRepository publicHolidaysRepository;

        @Autowired
        private LogisticsService logisticsService;

        @Autowired
        private UserAccountRepository userAccountRepository;

        @Autowired
        private NotificationService notificationService;

        @Autowired
        private AuthRepository authRepository;

        @Autowired
        private PositionRepository positionRepository;

        @Autowired
        private CookiesProcessor cookiesProcessor;

        @Autowired
        CsService csService;

        @Autowired
        private Gson gson;

        @Autowired
        private AddressRepository addressRepository;

        @Autowired
        private UserRepository userUserRepository;

        @Autowired
        private BluedartService blueDartService;

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

        @RequestMapping(value = "/logistics", method = RequestMethod.GET)
        public String logistics(HttpServletRequest request, Model model) throws Exception {
                ProviderTat pt = providerTatRepository.selectByProviderId(1, 7678, "110018");

                return "logistics";

        }

        @RequestMapping(value = "/authorisedWarehouses")
        public String authorisedWarehouses(HttpServletRequest request, Model model) throws ProfitMandiBusinessException {

                LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
                String email = loginDetails.getEmailId();

                AuthUser authUser = authRepository.selectByEmailOrMobile(email);
                List<Position> positions = positionRepository.selectAll(authUser.getId());

                List<Position> warehousePositions = positions.stream()
                                .filter(x -> x.getCategoryId() == ProfitMandiConstants.TICKET_CATEGORY_WAREHOUSE)
                                .collect(Collectors.toList());
                Set<CustomRetailer> positionRetailers = new HashSet<>();
                csService.getPositionCustomRetailerMap(warehousePositions).values().forEach(customRetailers -> {
                        positionRetailers.addAll(customRetailers);

                });

                Map<Integer, String> warehouseMap = this.getWarehouses(positionRetailers);
                JSONArray response = new JSONArray();

                warehouseMap.keySet().stream().filter(x -> warehouseMap.get(x) != null).forEach(x -> {
                        response.put(new JSONObject().put("id", x).put("name", warehouseMap.get(x)));
                });

                LOGGER.info("response1", response.toString());

                model.addAttribute("response1", response.toString());

                return "response";
        }

        @RequestMapping(value = "/billedOrderFileUploader", method = RequestMethod.POST)
        public String getBilledOrderFileUploader(HttpServletRequest request, Model model, HttpServletResponse response,
                        @RequestPart MultipartFile file) throws Throwable {

                LOGGER.info("file" + file.toString());
                String fileName = file.getName();

                String fileNames = file.getOriginalFilename();

                LOGGER.info("fileName" + fileName);
                LOGGER.info("fileNames" + fileNames);

                List<CSVRecord> records = FileUtil.readFile(file);

                List<BilledOrderListModel> billedOrderList = new ArrayList<BilledOrderListModel>();
                for (CSVRecord record : records) {
                        BilledOrderListModel blm = createBilleOrder(record);
                        billedOrderList.add(blm);
                        LOGGER.info("records" + record.get(1));
                }

                LoginDetails loginDetails = cookiesProcessor.getCookiesObject(request);
                String email = loginDetails.getEmailId();

                AuthUser authUser = authRepository.selectByEmailOrMobile(email);
                List<Position> positions = positionRepository.selectAll(authUser.getId());

                List<Position> warehousePositions = positions.stream()
                                .filter(x -> x.getCategoryId() == ProfitMandiConstants.TICKET_CATEGORY_WAREHOUSE)
                                .collect(Collectors.toList());
                Set<CustomRetailer> positionRetailers = new HashSet<>();
                csService.getPositionCustomRetailerMap(warehousePositions).values().forEach(customRetailers -> {
                        positionRetailers.addAll(customRetailers);

                });

                LOGGER.info("positionRetailers" + positionRetailers);
                List<Integer> fofoIds = new ArrayList<>();
                List<Integer> warehouseIds = new ArrayList<>();
                if (!positionRetailers.isEmpty()) {
                        fofoIds.addAll(positionRetailers.stream().map(x -> x.getPartnerId()).collect(Collectors.toList()));

                        warehouseIds = this.getWarehouses(positionRetailers).entrySet().stream().map(x -> x.getKey())
                                        .collect(Collectors.toList());

                }

                LOGGER.info("fofoIds" + fofoIds);

                LOGGER.info("warehouseIds" + warehouseIds);

                Map<String, DispatchNotificationModel> dispatchNotication = new HashMap<>();

                if (!billedOrderList.isEmpty()) {
                        List<Order> ords = orderRepository.selectByInvoiceNumbers(
                                        billedOrderList.stream().map(x -> x.getInvoiceNumber()).collect(Collectors.toList()));

                        List<Integer> shippingWarehouseIds = ords.stream().map(x -> x.getWarehouseId())
                                        .collect(Collectors.toList());

                        if (!warehouseIds.containsAll(shippingWarehouseIds)) {
                                throw new ProfitMandiBusinessException("Uploaded File", "",
                                                "Partners are not belong to the same warehouse");

                        }

                        Map<String, Set<Integer>> invoicefofoIdmap = ords.stream().collect(Collectors.groupingBy(
                                        x -> x.getInvoiceNumber(), Collectors.mapping(Order::getRetailerId, Collectors.toSet())));

                        LOGGER.info("invoicefofoIdmap" + invoicefofoIdmap);

                        Map<String, Set<String>> airbillInvoiceNumberMap = billedOrderList.stream()
                                        .collect(Collectors.groupingBy(x -> x.getAirwayBillNumber(),
                                                        Collectors.mapping(BilledOrderListModel::getInvoiceNumber, Collectors.toSet())));

                        LOGGER.info("airbillInvoiceNumberMap" + airbillInvoiceNumberMap);

                        for (Entry<String, Set<String>> aim : airbillInvoiceNumberMap.entrySet()) {
                                Set<String> InvoceNumbers = aim.getValue();
                                Set<Integer> fofoId = new HashSet<>();
                                for (String InvoceNumber : InvoceNumbers) {
                                        if (invoicefofoIdmap.get(InvoceNumber) != null) {
                                                fofoId.addAll(invoicefofoIdmap.get(InvoceNumber));
                                        }
                                }
                                LOGGER.info("fofoId" + fofoId);

                                if (fofoId.size() > 1) {
                                        throw new ProfitMandiBusinessException("Uploaded File", "",
                                                        "Waybill " + aim.getKey() + " number cannot have invoices with different Retailers");
                                }
                        }

                        Map<String, List<BilledOrderListModel>> blueDartAirbillBilledOrderMap = billedOrderList.stream()
                                        .filter(x -> x.getLogisticsProviderName().equals("BlueDart"))
                                        .collect(Collectors.groupingBy(x -> x.getAirwayBillNumber(), Collectors.toList()));

                        List<BilledOrderListModel> orderList = billedOrderList.stream()
                                        .filter(x -> !x.getLogisticsProviderName().equals("BlueDart")).collect(Collectors.toList());

                        if (!blueDartAirbillBilledOrderMap.isEmpty()) {
                                List<BilledOrderListModel> blueDartorderList = billedOrderList.stream()
                                                .filter(x -> x.getLogisticsProviderName().equals("BlueDart")).collect(Collectors.toList());

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

                                for (BilledOrderListModel billedOrder : blueDartorderList) {

                                        Provider provider = providerRepository.selectByName(billedOrder.getLogisticsProviderName());

                                        List<Order> orders = orderRepository.selectByInvoiceNumber(billedOrder.getInvoiceNumber());

                                        for (Order order : orders) {
                                                ProviderTat providerTat = providerTatRepository.selectByProviderId(provider.getId(),
                                                                order.getWarehouseId(), order.getRetailerPinCode());
                                                if (providerTat == null) {
                                                        unserviceablePincode.add(order.getId());
                                                }
                                        }

                                }

                                if (!unserviceablePincode.isEmpty()) {
                                        throw new ProfitMandiBusinessException("Uploaded File", "",
                                                        "Orders " + unserviceablePincode + " Unserviceable Pincode");

                                }

                                List<BilledOrderListModel> blueDartOrders = blueDartService
                                                .getAirwayBillNo(blueDartAirbillBilledOrderMap, authUser.getEmailId());

                                orderList.addAll(blueDartOrders);
                        }

                        for (BilledOrderListModel bl : orderList) {
                                List<Order> orders = orderRepository.selectByInvoiceNumber(bl.getInvoiceNumber());

                                Provider provider = providerRepository.selectByName(bl.getLogisticsProviderName());

                                if (provider == null) {
                                        throw new ProfitMandiBusinessException("Uploaded File", "", "Provider is not Available");
                                }
                                if (!orders.isEmpty()) {
                                        dispatchNotication = logisticsService.markedOrderShippedDetail(orders, provider, dispatchNotication,
                                                        bl.getAirwayBillNumber());

                                } else {
                                        throw new ProfitMandiBusinessException("Uploaded File", "", "No Order Found");
                                }

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

                        if (!dispatchNotication.isEmpty()) {

                                for (Entry<String, DispatchNotificationModel> dn : dispatchNotication.entrySet()) {

                                        Provider pr = providerRepository.selectById(dn.getValue().getProviderId());

                                        String title = "Order Shipped";

                                        com.spice.profitmandi.dao.entity.user.User user = userUserRepository
                                                        .selectById(dn.getValue().getFofoId());

                                        Address address = addressRepository.selectById(user.getAddressId());

                                        Set<String> invoiceNumber = new HashSet<>();
                                        invoiceNumber.addAll(dn.getValue().getInvoiceNumber());

                                        String message = String.format("Dear partner, your items with Invoice Number "
                                                        + String.join(",", invoiceNumber) + " worth Rs." + dn.getValue().getTotalAmount()
                                                        + " and qty " + dn.getValue().getTotalQty() + " has been shipped through " + pr.getName()
                                                        + " via your track id " + dn.getKey() + " and will be delivered by "
                                                        + dn.getValue().getDate().format(DateTimeFormatter.ofPattern("dd-MM-yyyy")) + ".");

                                        SendNotificationModel sendNotificationModel = new SendNotificationModel();
                                        sendNotificationModel.setCampaignName("Order Shipped");
                                        sendNotificationModel.setTitle(title);
                                        sendNotificationModel.setMessage(message);
                                        sendNotificationModel.setType("url");
                                        sendNotificationModel.setUrl("https://app.smartdukaan.com/pages/home/notifications");
                                        sendNotificationModel.setExpiresat(LocalDateTime.now().plusDays(1));
                                        sendNotificationModel.setMessageType(MessageType.notification);
                                        int userId = userAccountRepository.selectUserIdByRetailerId(dn.getValue().getFofoId());
                                        sendNotificationModel.setUserIds(Arrays.asList(userId));
                                        notificationService.sendNotification(sendNotificationModel);
                                        notificationService.sendWhatsappMessage(message, title, address.getPhoneNumber());
                                }

                        }
                }

                LOGGER.info("dispatchNotication" + dispatchNotication);
                LOGGER.info("billedOrderList" + billedOrderList);
                model.addAttribute("response1", mvcResponseSender.createResponseString(true));
                return "response";

        }

        private BilledOrderListModel createBilleOrder(CSVRecord record) {
                BilledOrderListModel bol = new BilledOrderListModel();
                bol.setInvoiceNumber(record.get(0));
                bol.setLogisticsProviderName(record.get(1));
                bol.setAirwayBillNumber(record.get(2));
                bol.setWeight(Double.valueOf(record.get(3)));

                return bol;
        }

        @RequestMapping(value = "/provider", method = RequestMethod.GET)
        public String provider(HttpServletRequest request, Model model) throws Exception {
                List<Provider> providers = providerRepository.selectAll();
                List<Integer> providerIds = providers.stream().map(x -> x.getId()).collect(Collectors.toList());
                Map<Integer, ProviderDetails> providerDetails = providerDetailsRepository
                                .selectByProviderIds(providerIds, DeliveryType.PREPAID, true).stream()
                                .collect(Collectors.toMap(x -> x.getProviderId(), x -> x));
                model.addAttribute("providers", providers);
                model.addAttribute("providerDetails", providerDetails);

                model.addAttribute("deliveryTypes", DeliveryType.values());

                return "provider";

        }

        @RequestMapping(value = "/createProvider", method = RequestMethod.POST)
        public String createProvider(HttpServletRequest request, @RequestBody ProviderDetailModel providerDetailModel,
                        Model model) throws Exception {

                Provider provider = new Provider();
                provider.setName(providerDetailModel.getName());
                provider.setActive(providerDetailModel.isProvideractive());
                provider.setBundleWeightLimit(0);
                provider.setGroupShipmentAllowed(true);
                provider.setPickupType(PickUpType.COURIER);
                provider.setMaxCODLimit(0);

                providerRepository.persist(provider);

                ProviderDetails pd = new ProviderDetails();
                pd.setAccountNo(providerDetailModel.getAccountNo());
                pd.setEmail(providerDetailModel.getEmail());
                pd.setPhone(providerDetailModel.getMobile());
                pd.setProviderId(provider.getId());
                pd.setActive(true);
                pd.setType(DeliveryType.PREPAID);
                providerDetailsRepository.persist(pd);
                model.addAttribute("response1", mvcResponseSender.createResponseString(true));

                return "response";

        }

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

                List<Provider> providers = providerRepository.selectAll();
                model.addAttribute("providers", providers);
                return "provider-tat";

        }

        @RequestMapping(value = "/getProviderTat", method = RequestMethod.GET)
        public String getProviderTat(HttpServletRequest request, @RequestParam int providerId, Model model)
                        throws Exception {
                List<ProviderTat> providerTat = providerTatRepository.selectByProviderId(providerId);
                Map<Integer, String> warehouseMap = ProfitMandiConstants.WAREHOUSE_MAP;

                providerTat = providerTat.stream().filter(x -> warehouseMap.containsKey(x.getWarehouseLocation()))
                                .collect(Collectors.toList());

                Map<Integer, Provider> providerIdMap = new HashMap<>();
                Provider provider = providerRepository.selectById(providerId);
                providerIdMap.put(provider.getId(), provider);

                LOGGER.info("providerTat" + providerTat);
                model.addAttribute("providerTat", providerTat);
                model.addAttribute("warehouseMap", warehouseMap);
                model.addAttribute("providerIdMap", providerIdMap);

                return "provider-tat-detail";

        }

        @RequestMapping(value = "/providerTatFileUploader", method = RequestMethod.POST)
        public String providerTatFileUploader(HttpServletRequest request, Model model, HttpServletResponse response,
                        @RequestPart MultipartFile file) throws Throwable {

                LOGGER.info("file" + file.toString());
                String fileName = file.getName();

                String fileNames = file.getOriginalFilename();

                LOGGER.info("fileName" + fileName);
                LOGGER.info("fileNames" + fileNames);
                List<CSVRecord> records = FileUtil.readFile(file);

                List<ProviderTatModel> providerTatList = new ArrayList<>();
                for (CSVRecord record : records) {
                        ProviderTatModel sgr = createProviderTat(record);
                        providerTatList.add(sgr);

                }
                if (!providerTatList.isEmpty()) {

                        for (ProviderTatModel pt : providerTatList) {

                                Provider provider = providerRepository.selectByName(pt.getProviderName());

                                if (provider == null) {
                                        throw new ProfitMandiBusinessException("Uploaded File", "", "Provider is not Available");
                                }

                                Map<String, Integer> warehouseMap = ProfitMandiConstants.WAREHOUSE_NAME_MAP;
                                ProviderTat providerTat = providerTatRepository.selectByProviderId(provider.getId(),
                                                warehouseMap.get(pt.getWarehouseName()), pt.getPincode());

                                LOGGER.info("providerTat" + providerTat);
                                if (providerTat == null) {
                                        LOGGER.info("providerTat" + providerTat);
                                        providerTat = new ProviderTat();
                                        providerTat.setDestinationPin(pt.getPincode());
                                        providerTat.setProviderId(provider.getId());
                                        providerTat.setWarehouseLocation(warehouseMap.get(pt.getWarehouseName()));
                                        providerTat.setDeliveryTime(pt.getTat());
                                        providerTatRepository.persist(providerTat);
                                } else {
                                        LOGGER.info("providerTat else" + providerTat);
                                        providerTat.setDeliveryTime(pt.getTat());
                                }

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

        }

        private ProviderTatModel createProviderTat(CSVRecord record) {
                ProviderTatModel ptm = new ProviderTatModel();
                ptm.setProviderName(record.get(0));
                ptm.setWarehouseName(record.get(1));
                ptm.setPincode(record.get(2));
                ptm.setTat(Integer.parseInt(record.get(3)));

                return ptm;
        }

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

                List<PublicHolidays> publicHolidays = publicHolidaysRepository
                                .selectAllByDate(LocalDate.of(LocalDate.now().getYear(), 1, 1));

                model.addAttribute("publicHolidays", publicHolidays);
                return "public-provider-holiday";

        }

        @RequestMapping(value = "/createPublicHoliday", method = RequestMethod.POST)
        public String createPublicHoliday(HttpServletRequest request, @RequestParam LocalDate date,
                        @RequestParam String occassion, Model model) throws Exception {

                PublicHolidays ph = new PublicHolidays();
                ph.setDate(date);
                ph.setHolidayDate(LocalDate.now().atStartOfDay());
                ph.setOccasion(occassion);
                publicHolidaysRepository.persist(ph);

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

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

                List<List<?>> rows = new ArrayList<>();

                List<Order> orders = orderRepository.selectAllByWarehouseAndStatus(warehouseId, OrderStatus.BILLED);

                if (orders.isEmpty()) {
                        throw new ProfitMandiBusinessException("Template File", "", "No order has been billed");

                }
                Set<String> invoiceNumbers = orders.stream().map(x -> x.getInvoiceNumber()).collect(Collectors.toSet());

                for (String invoiceNumber : invoiceNumbers) {
                        rows.add(Arrays.asList(invoiceNumber));

                }

                org.apache.commons.io.output.ByteArrayOutputStream baos = FileUtil
                                .getCSVByteStream(Arrays.asList("Invoice Number", "Provider", "AWB", "Weight(Kg)"), rows);

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

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

        }

        private Map<Integer, String> getWarehouses(Set<CustomRetailer> positionRetailers) {
                Map<Integer, String> warehouses = new HashMap<>();
                positionRetailers.stream().forEach(x -> {
                        if (x.getWarehouseId() != 0) {
                                warehouses.put(x.getWarehouseId(), ProfitMandiConstants.WAREHOUSE_MAP.get(x.getWarehouseId()));
                        }
                });
                return warehouses;

        }

        @RequestMapping(value = "/downloadProviderTatTemplate", method = RequestMethod.GET)
        public ResponseEntity<?> downloadProviderTatTemplate(HttpServletRequest request) throws Exception {
                List<List<?>> rows = new ArrayList<>();
                Map<Integer, String> warehouseMap = ProfitMandiConstants.WAREHOUSE_MAP;
                for (Entry<Integer, String> warehouse : warehouseMap.entrySet()) {
                        rows.add(Arrays.asList("Delhivery", warehouse.getValue(), "110018", "-"));
                }
                org.apache.commons.io.output.ByteArrayOutputStream baos = FileUtil.getCSVByteStream(
                                Arrays.asList("Provider Name", "Source Warehouse", "Destination Pincode", "TAT in days"), rows);

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

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

        }

        @RequestMapping(value = "/downloadDelayDayTemplate", method = RequestMethod.GET)
        public ResponseEntity<?> downloadDelayDayTemplate(HttpServletRequest request) throws Exception {
                List<List<?>> rows = new ArrayList<>();
                rows.add(Arrays.asList("-", "-", "Vehicle Delay"));
                rows.add(Arrays.asList("-", "-", "Vehicle Breakdown"));

                org.apache.commons.io.output.ByteArrayOutputStream baos = FileUtil
                                .getCSVByteStream(Arrays.asList("AirwayBillNumber", "Delay Day", "Reason"), rows);

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

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

        }

        @RequestMapping(value = "/delayDayFileUpload", method = RequestMethod.POST)
        public String delayDayFileUpload(HttpServletRequest request, Model model, HttpServletResponse response,
                        @RequestPart MultipartFile file) throws Throwable {

                List<CSVRecord> records = FileUtil.readFile(file);

                List<DelayDayModel> delayDayList = new ArrayList<>();
                for (CSVRecord record : records) {
                        DelayDayModel ddm = createDelayDay(record);
                        delayDayList.add(ddm);

                }

                if (!delayDayList.isEmpty()) {

                        List<Order> vorders = orderRepository.selectByAirwayBillNumber(
                                        delayDayList.stream().map(x -> x.getAirwayBIllNumber()).collect(Collectors.toList()));

                        List<Order> filteredorders = vorders.stream().filter(x -> x.getStatus() != (OrderStatus.SHIPPED_FROM_WH))
                                        .collect(Collectors.toList());

                        if (!filteredorders.isEmpty()) {
                                throw new ProfitMandiBusinessException("Upload File",
                                                String.join(",",
                                                                filteredorders.stream().map(x -> x.getAirwayBillNumber()).collect(Collectors.toList())),
                                                "Order status should be shipped from warehouse");

                        }

                        Map<String, List<Order>> airwayBillOrderMap = vorders.stream()
                                        .collect(Collectors.groupingBy(Order::getAirwayBillNumber));

                        for (DelayDayModel ddm : delayDayList) {
                                List<Order> orders = airwayBillOrderMap.get(ddm.getAirwayBIllNumber());

                                if (!orders.isEmpty()) {

                                        Double totalAmount = orders.stream().mapToDouble(x -> x.getTotalAmount()).sum();

                                        List<String> invoiceNumbers = orders.stream().map(x -> x.getInvoiceNumber())
                                                        .collect(Collectors.toList());

                                        int totalQty = orders.stream().mapToInt(x -> x.getLineItem().getQuantity()).sum();

                                        Order order = orders.get(0);
                                        ProviderTat pt = providerTatRepository.selectByProviderId(order.getLogisticsProviderId(),
                                                        order.getWarehouseId(), order.getRetailerPinCode());

                                        LocalDate deliveryDate = logisticsService.calculateDeliveryTimeline(
                                                        order.getShippingTimestamp().toLocalDate(), pt, ddm.getDelayDay());

                                        orders.forEach(x -> x.setExpectedDeliveryTime(deliveryDate.atStartOfDay()));

                                        String title = "Order Update";
                                        String message = String
                                                        .format("Dear partner, your items with Invoice Number " + String.join(",", invoiceNumbers)
                                                                        + " worth Rs." + totalAmount + " and qty " + totalQty + " has been shipped through "
                                                                        + providerRepository.selectById(order.getLogisticsProviderId()).getName()
                                                                        + " via your track id " + ddm.getAirwayBIllNumber() + " has been delayed due to "
                                                                        + ddm.getReason() + " and will be delivered by "
                                                                        + deliveryDate.format(DateTimeFormatter.ofPattern("dd-MM-yyyy")))
                                                        + ".";

                                        com.spice.profitmandi.dao.entity.user.User user = userUserRepository
                                                        .selectById(order.getRetailerId());

                                        Address address = addressRepository.selectById(user.getAddressId());

                                        SendNotificationModel sendNotificationModel = new SendNotificationModel();
                                        sendNotificationModel.setCampaignName("Order Update");
                                        sendNotificationModel.setTitle(title);
                                        sendNotificationModel.setMessage(message);
                                        sendNotificationModel.setType("url");
                                        sendNotificationModel.setUrl("https://app.smartdukaan.com/pages/home/notifications");
                                        sendNotificationModel.setExpiresat(LocalDateTime.now().plusDays(1));
                                        sendNotificationModel.setMessageType(MessageType.notification);
                                        int userId = userAccountRepository.selectUserIdByRetailerId(order.getRetailerId());
                                        sendNotificationModel.setUserIds(Arrays.asList(userId));
                                        notificationService.sendNotification(sendNotificationModel);
                                        notificationService.sendWhatsappMessage(message, title, address.getPhoneNumber());
                                } else {
                                        throw new ProfitMandiBusinessException("Upload File", "",
                                                        "No order available for " + ddm.getAirwayBIllNumber() + " airwaybill Number");

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

        }

        private DelayDayModel createDelayDay(CSVRecord record) {
                DelayDayModel ddm = new DelayDayModel();
                ddm.setAirwayBIllNumber(record.get(0));
                ddm.setDelayDay(Integer.parseInt(record.get(1)));
                ddm.setReason(record.get(2));
                return ddm;
        }

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

                org.apache.commons.io.output.ByteArrayOutputStream baos = FileUtil
                                .getCSVByteStream(Arrays.asList("AirwayBillNumber", "Delivered On", "Delivered By"), rows);

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

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

        }

        @RequestMapping(value = "/markDeliveredFileUpload", method = RequestMethod.POST)
        public String markDeliveredFileUpload(HttpServletRequest request, Model model, HttpServletResponse response,
                        @RequestPart MultipartFile file) throws Throwable {

                List<CSVRecord> records = FileUtil.readFile(file);

                List<MarkDeliveredModel> deliveredList = new ArrayList<>();
                for (CSVRecord record : records) {
                        MarkDeliveredModel ddm = createMarkDeliveredModel(record);
                        deliveredList.add(ddm);

                }

                if (!deliveredList.isEmpty()) {

                        List<Order> vorders = orderRepository.selectByAirwayBillNumber(
                                        deliveredList.stream().map(x -> x.getAirwayBillNumber()).collect(Collectors.toList()));

                        List<Order> filteredorders = vorders.stream().filter(x -> (x.getStatus().equals(OrderStatus.SHIPPED_FROM_WH)
                                        && !x.getStatus().equals(OrderStatus.DELIVERY_SUCCESS))).collect(Collectors.toList());

                        LOGGER.info("filteredOrder" + filteredorders);

                        if (!filteredorders.isEmpty()) {
                                throw new ProfitMandiBusinessException("Upload File",
                                                String.join(",",
                                                                filteredorders.stream().map(x -> x.getAirwayBillNumber()).collect(Collectors.toList())),
                                                "Order status should be shipped from warehouse");

                        }

                        Map<String, List<Order>> airwayBillOrderMap = vorders.stream()
                                        .collect(Collectors.groupingBy(Order::getAirwayBillNumber));

                        for (MarkDeliveredModel dl : deliveredList) {

                                List<Order> orders = airwayBillOrderMap.get(dl.getAirwayBillNumber());
                                if (orders != null) {
                                        for (Order order : orders) {
                                                order.setDeliveryTimestamp(dl.getDeliveredOn());
                                                order.setStatus(OrderStatus.DELIVERY_SUCCESS);
                                                order.setStatusDescription("Order Delivered");

                                        }

                                        com.spice.profitmandi.dao.entity.user.User user = userUserRepository
                                                        .selectById(orders.get(0).getRetailerId());

                                        Address address = addressRepository.selectById(user.getAddressId());

                                        String title = "Order Delivered";

                                        SendNotificationModel sendNotificationModel = new SendNotificationModel();
                                        sendNotificationModel.setCampaignName("Order Delivered");
                                        sendNotificationModel.setTitle(title);
                                        sendNotificationModel.setMessage(String.format("Dear partner, your SmartDukaan Order "
                                                        + dl.getAirwayBillNumber() + "has been delivered to you in a safe, sealed bag by "
                                                        + dl.getDeliveredBy() + "."));
                                        sendNotificationModel.setType("url");
                                        sendNotificationModel.setUrl("https://app.smartdukaan.com/pages/home/notifications");
                                        sendNotificationModel.setExpiresat(LocalDateTime.now().plusDays(1));
                                        sendNotificationModel.setMessageType(MessageType.notification);
                                        int userId = userAccountRepository.selectUserIdByRetailerId(orders.get(0).getRetailerId());
                                        sendNotificationModel.setUserIds(Arrays.asList(userId));
                                        notificationService.sendNotification(sendNotificationModel);

                                        String message = String.format("Dear partner, Your SmartDukaan Order " + dl.getAirwayBillNumber()
                                                        + " has been delivered to you in a safe sealed bag.");

                                        notificationService.sendWhatsappMessage(message, title, address.getPhoneNumber());

                                } else {
                                        throw new ProfitMandiBusinessException("Upload File", "",
                                                        "No order available for " + dl.getAirwayBillNumber() + " airwaybill Number");

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

        }

        private MarkDeliveredModel createMarkDeliveredModel(CSVRecord record) {
                MarkDeliveredModel mdm = new MarkDeliveredModel();
                mdm.setAirwayBillNumber(record.get(0));
                DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy");
                LOGGER.info(record.get(1));
                LocalDate dateTime = LocalDate.parse(record.get(1), formatter);
                mdm.setDeliveredOn(dateTime.atStartOfDay());
                mdm.setDeliveredBy(record.get(2));
                return mdm;
        }

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

                rows.add(Arrays.asList("-",
                                "Shipment on hold, low invoice value, please ensure order value of minimum Rs. 40,000."));

                rows.add(Arrays.asList("-", "Order Billed,Shipping will be done tomorrow."));

                org.apache.commons.io.output.ByteArrayOutputStream baos = FileUtil
                                .getCSVByteStream(Arrays.asList("Invoice Number", "Reason"), rows);

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

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

        }

        @RequestMapping(value = "/getDelayBillingFileUploader", method = RequestMethod.POST)
        public String getDelayBillingFileUploader(HttpServletRequest request, Model model, HttpServletResponse response,
                                                                                          @RequestPart MultipartFile file) throws Throwable {

                LOGGER.info("file" + file.toString());
                String fileName = file.getName();

                String fileNames = file.getOriginalFilename();

                LOGGER.info("fileName" + fileName);
                LOGGER.info("fileNames" + fileNames);

                List<CSVRecord> records = FileUtil.readFile(file);

                List<DelayBillingModel> delayBillingModel = new ArrayList<DelayBillingModel>();
                for (CSVRecord record : records) {
                        DelayBillingModel dbm = new DelayBillingModel();
                        dbm.setInvoiceNumber(record.get(0));
                        dbm.setReason(record.get(1));
                        delayBillingModel.add(dbm);

                }

                if (!delayBillingModel.isEmpty()) {
                        for (DelayBillingModel delayBilling : delayBillingModel) {

                                List<Order> orders = orderRepository.selectByInvoiceNumber(delayBilling.getInvoiceNumber());

                                for (Order order : orders) {
                                        order.setDelayReasonText(delayBilling.getReason());

                                        if (!order.getStatus().equals(OrderStatus.BILLED)) {
                                                throw new ProfitMandiBusinessException("Upload File", "",
                                                                "Order" + order.getInvoiceNumber() + "status should be Billed");

                                        }
                                }

                                SendNotificationModel sendNotificationModel = new SendNotificationModel();
                                sendNotificationModel.setCampaignName("Order Hold");
                                sendNotificationModel.setTitle("Order Hold");
                                sendNotificationModel.setMessage(
                                                String.format("Dear partner, your SmartDukaan order " + delayBilling.getInvoiceNumber()
                                                                + " has been delayed due to" + delayBilling.getReason() + "."));
                                sendNotificationModel.setType("url");
                                sendNotificationModel.setUrl("https://app.smartdukaan.com/pages/home/notifications");
                                sendNotificationModel.setExpiresat(LocalDateTime.now().plusDays(1));
                                sendNotificationModel.setMessageType(MessageType.notification);
                                int userId = userAccountRepository.selectUserIdByRetailerId(orders.get(0).getRetailerId());
                                sendNotificationModel.setUserIds(Arrays.asList(userId));
                                notificationService.sendNotification(sendNotificationModel);
                        }
                }
                model.addAttribute("response1", mvcResponseSender.createResponseString(true));

                return "response";
        }

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

                List<Order> orders = orderRepository.selectByInvoiceNumber("NSLCK7931");

                // blueDartService.getAirwayBillNo(orders.2);
                model.addAttribute("response1", mvcResponseSender.createResponseString(true));

                return "response";
        }
}