Subversion Repositories SmartDukaan

Rev

Rev 22581 | Rev 22927 | 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 java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import com.google.gson.Gson;
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
import com.spice.profitmandi.common.model.CartFofo;
import com.spice.profitmandi.common.model.CustomCurrentInventorySnapshot;
import com.spice.profitmandi.common.model.InventoryItemAgingModel;
import com.spice.profitmandi.common.model.PriceModel;
import com.spice.profitmandi.common.model.ProfitMandiConstants;
import com.spice.profitmandi.common.util.ExcelUtils;
import com.spice.profitmandi.common.util.StringUtils;
import com.spice.profitmandi.common.util.Utils;
import com.spice.profitmandi.common.web.util.ResponseSender;
import com.spice.profitmandi.dao.entity.catalog.Item;
import com.spice.profitmandi.dao.entity.fofo.CurrentInventorySnapshot;
import com.spice.profitmandi.dao.entity.fofo.InventoryItem;
import com.spice.profitmandi.dao.entity.fofo.Purchase;
import com.spice.profitmandi.dao.entity.transaction.LineItem;
import com.spice.profitmandi.dao.entity.transaction.Order;
import com.spice.profitmandi.dao.repository.catalog.ItemRepository;
import com.spice.profitmandi.dao.repository.fofo.CurrentInventorySnapshotRepository;
import com.spice.profitmandi.dao.repository.fofo.InventoryItemRepository;
import com.spice.profitmandi.dao.repository.fofo.PurchaseRepository;
import com.spice.profitmandi.dao.repository.transaction.OrderRepository;
import com.spice.profitmandi.service.aging.InventoryItemAgingService;
import com.spice.profitmandi.service.pricing.PricingService;
import com.spice.profitmandi.web.model.LoginDetails;
import com.spice.profitmandi.web.response.ValidateCart;
import com.spice.profitmandi.web.util.CookiesProcessor;
import com.spice.profitmandi.web.util.MVCResponseSender;

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

        private static final Logger LOGGER = LoggerFactory.getLogger(InventoryController.class);

        @Autowired
        CurrentInventorySnapshotRepository  currentInventorySnapshotRepository;

        @Autowired
        InventoryItemRepository inventoryItemRepository;

        @Autowired
        PurchaseRepository purchaseRepository;

        @Autowired
        ItemRepository itemRepository;

        @Autowired
        OrderRepository orderRepository;

        @Autowired
        MVCResponseSender mvcResponseSender;

        @Autowired
        CookiesProcessor cookiesProcessor;
        
        @Autowired
        PricingService pricingService;
        
        @Autowired
        InventoryItemAgingService inventoryItemAgingService;
        
        @Autowired
        ResponseSender<?> responseSender;
        
        @Value("${saholic.api.host}")
        private String host;
        @Value("${saholic.api.port}")
        private int port;
        @Value("${saholic.api.webapp}")
        private String webapp;

        
        @RequestMapping(value = "/getCurrentInventorySnapshot")
        public String getCurrentAvailability(HttpServletRequest request,@RequestParam(name = "offset",defaultValue="0") int offset, @RequestParam(name = "limit", defaultValue="10") int limit , @RequestParam(name = "searchTerm", required=false, defaultValue="") String searchTerm ,Model model) throws Exception{
                LoginDetails fofoDetails;
                try {
                        fofoDetails = cookiesProcessor.getCookiesObject(request);
                } catch (ProfitMandiBusinessException e) {
                        model.addAttribute("loginResponse", mvcResponseSender.createResponseString("RTLR_1009", false, "/login"));
                        return "response";
                }
                List<CurrentInventorySnapshot> currentInventorySnapshot = currentInventorySnapshotRepository.getCurrentInventorySnapshot(fofoDetails.getFofoId(), offset, limit, searchTerm);
                
                long countItems = currentInventorySnapshotRepository.getCurrentInventorySnapshotCount(fofoDetails.getFofoId(), searchTerm);
                model.addAttribute("currentInventorySnapshot",currentInventorySnapshot);
                model.addAttribute("start",offset+1);
                model.addAttribute("size",countItems);
                model.addAttribute("searchTerm",searchTerm);
                if (currentInventorySnapshot.size() < limit){
                        model.addAttribute("end",offset+currentInventorySnapshot.size());
                }
                else{
                        model.addAttribute("end",offset+limit);
                }
                return "inventory-snapshot";
        }

        @RequestMapping(value = "/getBadInventorySnapshot")
        public String getBadAvailability(HttpServletRequest request,@RequestParam(name = "offset",defaultValue="0") int offset, @RequestParam(name = "limit", defaultValue="10") int limit , @RequestParam(name = "searchTerm", required=false, defaultValue="") String searchTerm ,Model model) throws Exception{
                try {
                        cookiesProcessor.getCookiesObject(request);
                } catch (ProfitMandiBusinessException e) {
                        model.addAttribute("loginResponse", mvcResponseSender.createResponseString("RTLR_1009", false, "/login"));
                        return "response";
                }
                model.addAttribute("badInventorySnapshot",new ArrayList<>());
                model.addAttribute("searchTerm",searchTerm);
                return "bad-inventory-snapshot";
        }

        @RequestMapping(value = "/getPaginatedCurrentInventorySnapshot")
        public String getCurrentAvailabilityPaginated(HttpServletRequest request, @RequestParam(name = "offset", defaultValue="0") int offset, @RequestParam(name = "limit", defaultValue="10") int limit, @RequestParam(name = "searchTerm", required=false, defaultValue="") String searchTerm , Model model) throws Exception{
                LoginDetails fofoDetails;
                try {
                        fofoDetails = cookiesProcessor.getCookiesObject(request);
                } catch (ProfitMandiBusinessException e) {
                        model.addAttribute("loginResponse", mvcResponseSender.createResponseString("RTLR_1009", false, "/login"));
                        return "response";
                }
                List<CurrentInventorySnapshot> currentInventorySnapshot = currentInventorySnapshotRepository.getCurrentInventorySnapshot(fofoDetails.getFofoId(), offset, limit, searchTerm);
                model.addAttribute("currentInventorySnapshot",currentInventorySnapshot);
                return "inventory-snapshot-paginated";
        }
        
        @RequestMapping(value = "/getCatalog")
        public String getCatalog(HttpServletRequest request,@RequestParam(name = "offset",defaultValue="0") int offset, @RequestParam(name = "limit", defaultValue="10") int limit , @RequestParam(name = "searchTerm", required=false, defaultValue="") String searchTerm ,Model model) throws Exception{
                LoginDetails fofoDetails;
                try {
                        fofoDetails = cookiesProcessor.getCookiesObject(request);
                } catch (ProfitMandiBusinessException e) {
                        model.addAttribute("loginResponse", mvcResponseSender.createResponseString("RTLR_1009", false, "/login"));
                        return "response";
                }
                List<CurrentInventorySnapshot> currentInventorySnapshots = currentInventorySnapshotRepository.getCurrentInventorySnapshot(fofoDetails.getFofoId(), offset, limit, searchTerm);
                long countItems = currentInventorySnapshotRepository.getCurrentInventorySnapshotCount(fofoDetails.getFofoId(), searchTerm);
                Set<Integer> itemIds = new HashSet<>();
                for(CurrentInventorySnapshot currentInventorySnapshot : currentInventorySnapshots ){
                        itemIds.add(currentInventorySnapshot.getItemId());
                }
                Map<Integer, PriceModel> mopPriceMap = pricingService.getPurchasePriceMopPriceNotFound(itemIds, fofoDetails.getFofoId());
                List<InventoryItem> inventoryItems = inventoryItemRepository.selectByFofoIdItemIds(fofoDetails.getFofoId(), itemIds);
                Map<Integer, Set<String>> itemIdSerialNumbers = new HashMap<>();
                for(InventoryItem inventoryItem : inventoryItems){
                        if(inventoryItem.getSerialNumber() != null && !inventoryItem.getSerialNumber().isEmpty()){
                                if(!itemIdSerialNumbers.containsKey(inventoryItem.getItemId())){
                                        Set<String> serialNumbers = new HashSet<>();
                                        serialNumbers.add(inventoryItem.getSerialNumber());
                                        itemIdSerialNumbers.put(inventoryItem.getItemId(), serialNumbers);
                                }else{
                                        itemIdSerialNumbers.get(inventoryItem.getItemId()).add(inventoryItem.getSerialNumber());
                                }
                        }
                }
                model.addAttribute("currentInventorySnapshot",currentInventorySnapshots);
                LOGGER.info("mopPriceMap [{}]", mopPriceMap);
                LOGGER.info("itemIdSerialNumbers [{}]", itemIdSerialNumbers);
                model.addAttribute("mopPriceMap", mopPriceMap);
                model.addAttribute("itemIdSerialNumbers", itemIdSerialNumbers);
                model.addAttribute("start", offset + 1);
                model.addAttribute("size", countItems);
                model.addAttribute("searchTerm", searchTerm);
                if (currentInventorySnapshots.size() < limit){
                        model.addAttribute("end", offset + currentInventorySnapshots.size());
                }
                else{
                        model.addAttribute("end",offset + limit);
                }
                return "catalog";
        }
        
        @RequestMapping(value = "/getPaginatedCatalog")
        public String getCatalogPaginated(HttpServletRequest request,@RequestParam(name = "offset",defaultValue="0") int offset, @RequestParam(name = "limit", defaultValue="10") int limit, @RequestParam(name = "searchTerm", required=false, defaultValue="") String searchTerm , Model model) throws Exception{
                LoginDetails fofoDetails;
                try {
                        fofoDetails = cookiesProcessor.getCookiesObject(request);
                } catch (ProfitMandiBusinessException e) {
                        model.addAttribute("loginResponse", mvcResponseSender.createResponseString("RTLR_1009", false, "/login"));
                        return "response";
                }
                List<CurrentInventorySnapshot> currentInventorySnapshots = currentInventorySnapshotRepository.getCurrentInventorySnapshot(fofoDetails.getFofoId(), offset, limit, searchTerm);
                Set<Integer> itemIds = new HashSet<>();
                for(CurrentInventorySnapshot currentInventorySnapshot : currentInventorySnapshots ){
                        itemIds.add(currentInventorySnapshot.getItemId());
                }
                Map<Integer, PriceModel> mopPriceMap = pricingService.getPurchasePriceMopPriceNotFound(itemIds, fofoDetails.getFofoId());
                model.addAttribute("currentInventorySnapshot",currentInventorySnapshots);
                model.addAttribute("mopPriceMap", mopPriceMap);
                return "catalog-paginated";
        }

        
        private String getVaildName(String name){
                return name!=null?name:"";
        }

        private CustomCurrentInventorySnapshot createCustomCurrentInventorySnapshop(Object[] row)
        {
                CustomCurrentInventorySnapshot currentInventorySnapshot = new CustomCurrentInventorySnapshot();
                currentInventorySnapshot.setItemId((Integer)row[0]);
                currentInventorySnapshot.setAvailability((Integer)row[1]);
                currentInventorySnapshot.setBrand((String)row[2]);
                currentInventorySnapshot.setModelName((String)row[3]);
                currentInventorySnapshot.setModelNumber((String)row[4]);
                currentInventorySnapshot.setColor((String)row[5]);
                currentInventorySnapshot.setCatalogItemId((Integer)row[6]);
                currentInventorySnapshot.setDisplayName((getVaildName((String)row[2])+" "+getVaildName((String)row[3])+" "+getVaildName((String)row[4])+" "+getVaildName((String)row[5])).replaceAll("\\s+", " "));
                currentInventorySnapshot.setIconUrl(Utils.getIconUrl(currentInventorySnapshot.getCatalogItemId(), host, port, webapp));
                return currentInventorySnapshot;
        }
        @RequestMapping(value = "/checkItemAvailability")
        public String getItemAvailability(HttpServletRequest request, @RequestParam(name = ProfitMandiConstants.ITEM_ID) int itemId, Model model) throws Exception{
                LoginDetails fofoDetails;
                try {
                        fofoDetails = cookiesProcessor.getCookiesObject(request);
                } catch (ProfitMandiBusinessException e) {
                        model.addAttribute("loginResponse", mvcResponseSender.createResponseString("RTLR_1009", false, "/login"));
                        return "response";
                }
                try{
                        Object[] row = currentInventorySnapshotRepository.selectCustomByItemIdAndFofoId(itemId, fofoDetails.getFofoId());
                        model.addAttribute("currentInventorySnapshot", new Gson().toJson(this.createCustomCurrentInventorySnapshop(row)));
                        return "current-item-availability";
                }catch(ProfitMandiBusinessException profitMandiBusinessException){
                        model.addAttribute("loginResponse", mvcResponseSender.createResponseString("INVNTRY_SNPSHT", false, "/dashboard"));
                        return "response";
                }
        }
        
        @RequestMapping(value = "/cart")
        public String addToCart(HttpServletRequest request, @RequestParam(name = "cartData") String cartData, Model model) throws Exception{
                LoginDetails fofoDetails;
                try {
                        fofoDetails = cookiesProcessor.getCookiesObject(request);
                } catch (ProfitMandiBusinessException e) {
                        model.addAttribute("loginResponse", mvcResponseSender.createResponseString("RTLR_1009", false, "/login"));
                        return "response";
                }
                
                JSONObject cartObject = new JSONObject(cartData);
                Iterator<?> keys = cartObject.keys();
                
                Set<Integer> itemIds = new HashSet<>();
                List<CartFofo> cartItems = new ArrayList<CartFofo>();
                
                while( keys.hasNext() ) {
                    String key = (String)keys.next();
                    if ( cartObject.get(key) instanceof JSONObject ) {
                        System.out.println(cartObject.get(key));
                    }
                    CartFofo cf = new CartFofo();
                    cf.setItemId(cartObject.getJSONObject(key).getInt("itemId"));
                    cf.setQuantity(cartObject.getJSONObject(key).getInt("quantity"));
                    cf.setDisplayName(cartObject.getJSONObject(key).getString("displayName"));
                    cf.setIconUrl(cartObject.getJSONObject(key).getString("iconUrl"));
                    cf.setAvailability(0);
                    cartItems.add(cf);
                    itemIds.add(cartObject.getJSONObject(key).getInt("itemId"));
                }
                if (itemIds.size() > 0){
                        List<CurrentInventorySnapshot> cisList = currentInventorySnapshotRepository.selectByFofoItemIds(fofoDetails.getFofoId(), itemIds);
                        for (CurrentInventorySnapshot cis: cisList ){
                                for (CartFofo cartItem : cartItems){
                                        if (cartItem.getItemId() == cis.getItem().getId()){
                                                cartItem.setAvailability(cis.getAvailability());
                                        }
                                }
                        }
                        for (CartFofo cartItem : cartItems){
                                if (cartItem.getAvailability() < cartItem.getQuantity() && cartItem.getAvailability()!=0){
                                        cartItem.setQuantity(cartItem.getAvailability());
                                        cartItem.setMessage("Item quantity changed.Less stock available");
                                }
                                if (cartItem.getAvailability() == 0){
                                        cartItem.setQuantity(0);
                                        cartItem.setMessage("You don't have stock for this item");
                                }
                        }
                }
                model.addAttribute("cartObj", cartItems);
                return "cart";
        }
        
        @RequestMapping(value = "/validate-cart")
        public String validateCart(HttpServletRequest request, HttpServletResponse response,@RequestParam(name = "cartData") String cartData, Model model) throws Exception{
                LoginDetails fofoDetails = null;
                try {
                        fofoDetails = cookiesProcessor.getCookiesObject(request);
                } catch (ProfitMandiBusinessException e) {
                        model.addAttribute("loginResponse", mvcResponseSender.createResponseString("RTLR_1009", false, "/login"));
                        return "response";
                }
                
                JSONObject cartObject = new JSONObject(cartData);
                Iterator<?> keys = cartObject.keys();
                
                Set<Integer> itemIds = new HashSet<>();
                List<CartFofo> cartItems = new ArrayList<CartFofo>();
                
                if (cartObject.keySet().size() == 0){
                        model.addAttribute("validateCartResponse",new Gson().toJson(new ValidateCart("POST", "/cart", false, cartData)));
                        return "validate-cart";
                }
                
                while( keys.hasNext() ) {
                    String key = (String)keys.next();
                    if ( cartObject.get(key) instanceof JSONObject ) {
                        System.out.println(cartObject.get(key));
                    }
                    CartFofo cf = new CartFofo();
                    cf.setItemId(cartObject.getJSONObject(key).getInt("itemId"));
                    cf.setQuantity(cartObject.getJSONObject(key).getInt("quantity"));
                    cf.setDisplayName(cartObject.getJSONObject(key).getString("displayName"));
                    cf.setIconUrl(cartObject.getJSONObject(key).getString("iconUrl"));
                    cf.setAvailability(0);
                    cartItems.add(cf);
                    itemIds.add(cartObject.getJSONObject(key).getInt("itemId"));
                }
                if (itemIds.size() > 0){
                        List<CurrentInventorySnapshot> cisList = currentInventorySnapshotRepository.selectByFofoItemIds(fofoDetails.getFofoId(), itemIds);
                        for (CurrentInventorySnapshot cis: cisList ){
                                for (CartFofo cartItem : cartItems){
                                        if (cartItem.getItemId() == cis.getItem().getId()){
                                                cartItem.setAvailability(cis.getAvailability());
                                        }
                                }
                        }
                        for (CartFofo cartItem : cartItems){
                                if (cartItem.getAvailability() < cartItem.getQuantity()){
                                        model.addAttribute("validateCartResponse",new Gson().toJson(new ValidateCart("POST", "/cart", false, cartData)));
                                        return "validate-cart";
                                }
                        }
                }
                else{
                        model.addAttribute("validateCartResponse",new Gson().toJson(new ValidateCart("POST", "/cart", false, cartData)));
                        return "validate-cart";
                }
                model.addAttribute("validateCartResponse",new Gson().toJson(new ValidateCart("POST", "/order", true, cartData)));
                return "validate-cart";
        }

        @RequestMapping(value = "/grnHistory")
        public String grnHistoryByFofoId(HttpServletRequest request, @RequestParam(name = ProfitMandiConstants.START_TIME, required = false) String startTimeString, @RequestParam(name = ProfitMandiConstants.END_TIME, required = false) String endTimeString, @RequestParam(name = "offset",defaultValue="0") int offset, @RequestParam(name = "limit", defaultValue="10") int limit, @RequestParam(name = ProfitMandiConstants.PURCHASE_REFERENCE,defaultValue="") String purchaseReference, @RequestParam(name = "searchType",defaultValue="") String searchType,Model model) throws Exception{
                LoginDetails fofoDetails;
                try {
                        fofoDetails = cookiesProcessor.getCookiesObject(request);
                } catch (ProfitMandiBusinessException e) {
                        model.addAttribute("loginResponse", mvcResponseSender.createResponseString("RTLR_1009", false, "/login"));
                        return "response";
                }

                LocalDateTime startDateTime = StringUtils.toDateTime(startTimeString);
                LocalDateTime endDateTime = StringUtils.toDateTime(endTimeString);
                
                List<Purchase> grnHistory = new ArrayList<Purchase>();
                long countItems = 0;
                if (searchType.equalsIgnoreCase("purchaseReference") && purchaseReference.trim().length() > 0){
                        try{
                                Purchase purchase = purchaseRepository.selectByPurchaseReference(purchaseReference);
                                grnHistory.add(purchase);
                                countItems = 1;
                        }
                        catch(Exception | ProfitMandiBusinessException e){
                                LOGGER.info("Unable to get purchase reference "+purchaseReference);
                        }
                }
                else{
                        grnHistory = purchaseRepository.selectByFofoId(fofoDetails.getFofoId(), startDateTime, endDateTime, offset, limit);
                        countItems = purchaseRepository.getPurchaseCount(fofoDetails.getFofoId(), startDateTime, endDateTime, purchaseReference, searchType);
                }
                model.addAttribute("grnHistories", grnHistory);
                model.addAttribute("start",offset+1);
                model.addAttribute("size",countItems);
                model.addAttribute("searchType",searchType);
                model.addAttribute(ProfitMandiConstants.START_TIME, startTimeString);
                model.addAttribute(ProfitMandiConstants.END_TIME, endTimeString);
                if (grnHistory.size() < limit){
                        model.addAttribute("end",offset+grnHistory.size());
                }
                else{
                        model.addAttribute("end",offset+limit);
                }
                return "grn-history";
        }

        @RequestMapping(value = "/getPaginatedGrnHistory")
        public String getGrnHistoryPaginated(HttpServletRequest request, @RequestParam(name = ProfitMandiConstants.START_TIME, required = false) String startTimeString, @RequestParam(name = ProfitMandiConstants.END_TIME, required = false) String endTimeString, @RequestParam(name = "offset",defaultValue="0") int offset, @RequestParam(name = "limit", defaultValue="10") int limit, @RequestParam(name = ProfitMandiConstants.PURCHASE_REFERENCE,defaultValue="") String purchaseReference, @RequestParam(name = "searchType",defaultValue="") String searchType,Model model) throws Exception{
                LoginDetails fofoDetails;
                try {
                        fofoDetails = cookiesProcessor.getCookiesObject(request);
                } catch (ProfitMandiBusinessException e) {
                        model.addAttribute("loginResponse", mvcResponseSender.createResponseString("RTLR_1009", false, "/login"));
                        return "response";
                }
                LocalDateTime startDateTime = StringUtils.toDateTime(startTimeString);
                LocalDateTime endDateTime = StringUtils.toDateTime(endTimeString);

                List<Purchase> grnHistory = purchaseRepository.selectByFofoId(fofoDetails.getFofoId(), startDateTime, endDateTime, offset, limit);
                model.addAttribute("grnHistories", grnHistory);
                return "grn-history-paginated";
        }

        @RequestMapping(value = "/grnHistoryDetailByPurchaseId")
        public String grnHistoryByPurchaseId(HttpServletRequest request, @RequestParam(name = ProfitMandiConstants.PURCHASE_ID) int purchaseId, Model model) throws Exception{
                LoginDetails fofoDetails;
                try {
                        fofoDetails = cookiesProcessor.getCookiesObject(request);
                } catch (ProfitMandiBusinessException e) {
                        model.addAttribute("loginResponse", mvcResponseSender.createResponseString("RTLR_1009", false, "/login"));
                        return "response";
                }
                Purchase purchase = null;
                try {
                        purchase = purchaseRepository.selectById(purchaseId);
                } catch (ProfitMandiBusinessException e) {

                }
                model.addAttribute("grnDetails", this.grnHistoryDetails(purchase, fofoDetails.getFofoId()));
                model.addAttribute("purchaseId",purchase.getId());
                model.addAttribute("purchaseReference",purchase.getPurchaseReference());
                return "grn-details";
        }

        @RequestMapping(value = "/grnHistoryDetailByPurchaseReference")
        public String grnHistoryByPurchaseReference(HttpServletRequest request, @RequestParam(name = ProfitMandiConstants.PURCHASE_REFERENCE) String purchaseReference, Model model) throws Exception{
                LoginDetails fofoDetails;
                try {
                        fofoDetails = cookiesProcessor.getCookiesObject(request);
                } catch (ProfitMandiBusinessException e) {
                        model.addAttribute("loginResponse", mvcResponseSender.createResponseString("RTLR_1009", false, "/login"));
                        return "response";
                }
                Purchase purchase = null;
                try {
                        purchase = purchaseRepository.selectByPurchaseReference(purchaseReference);
                } catch (ProfitMandiBusinessException e) {

                }
                model.addAttribute("grnDetails", this.grnHistoryDetails(purchase, fofoDetails.getFofoId()));
                model.addAttribute("purchaseId",purchase.getId());
                model.addAttribute("purchaseReference",purchase.getPurchaseReference());
                return "grn-details";
        }
        
        @RequestMapping(value = "/getInventoryItemAgingByInterval", method = RequestMethod.POST)
        public String getInventoryItemAgingByInterval(HttpServletRequest request, @RequestBody List<Integer> intervals, Model model, @RequestParam(name = "searchContent", defaultValue = "") String searchContent, @RequestParam(name = "offset",defaultValue="0") int offset, @RequestParam(name = "limit", defaultValue="10") int limit) throws Exception{
                LoginDetails fofoDetails;
                try {
                        fofoDetails = cookiesProcessor.getCookiesObject(request);
                } catch (ProfitMandiBusinessException e) {
                        model.addAttribute("loginResponse", mvcResponseSender.createResponseString("RTLR_1009", false, "/login"));
                        return "response";
                }
                try{
                        this.validateIntervals(intervals);
                } catch (ProfitMandiBusinessException e) {
                        LOGGER.error("Unable to get valid interval values", e);
                        return "response";
                }
                
                List<InventoryItemAgingModel> inventoryItemAgingModels = inventoryItemAgingService.getItemAgingByInterval(fofoDetails.getFofoId(), intervals);
                
                if(!searchContent.isEmpty()){
                        Predicate<InventoryItemAgingModel> searchContentPredicate = new Predicate<InventoryItemAgingModel>() {
                                @Override
                                public boolean test(InventoryItemAgingModel inventoryItemAgingModel) {
                                        if(!searchContent.contains(" ")){
                                                return this.search(inventoryItemAgingModel, searchContent);
                                        }else{
                                                String[] searchContents = searchContent.split(" ");
                                                for(String element : searchContents){
                                                        return this.search(inventoryItemAgingModel, element);
                                                }
                                        }
                                        return false;
                                }
                                private boolean search(InventoryItemAgingModel inventoryItemAgingModel, String searchContent){
                                        if(inventoryItemAgingModel.getBrand() != null && !inventoryItemAgingModel.getBrand().isEmpty() && inventoryItemAgingModel.getBrand().contains(searchContent)){
                                                return true;
                                        }
                                        if(inventoryItemAgingModel.getModelName() != null && !inventoryItemAgingModel.getModelName().isEmpty() && inventoryItemAgingModel.getModelName().contains(searchContent)){
                                                return true;
                                        }
                                        if(inventoryItemAgingModel.getModelNumber() != null && !inventoryItemAgingModel.getModelNumber().isEmpty() && inventoryItemAgingModel.getModelNumber().contains(searchContent)){
                                                return true;
                                        }
                                        if(inventoryItemAgingModel.getColor() != null && !inventoryItemAgingModel.getColor().isEmpty() && inventoryItemAgingModel.getColor().contains(searchContent)){
                                                return true;
                                        }
                                        return false;
                                }
                        };
                        inventoryItemAgingModels = inventoryItemAgingModels.stream().filter(searchContentPredicate).collect(Collectors.toList());
                }
                
                List<InventoryItemAgingModel> paginatedInventoryItemModels = new ArrayList<>();
                if((offset + limit) > inventoryItemAgingModels.size()){
                        limit = inventoryItemAgingModels.size();
                }
                for(int index = offset; index < limit; index++){
                        paginatedInventoryItemModels.add(inventoryItemAgingModels.get(index));
                }
                
                model.addAttribute("inventoryItemAgingModels", paginatedInventoryItemModels);
                model.addAttribute("intervals", intervals);
                model.addAttribute("start", offset);
                model.addAttribute("size", inventoryItemAgingModels.size());
                int end = 0;
                if (paginatedInventoryItemModels.size() < limit){
                        end = offset + paginatedInventoryItemModels.size();
                }else{
                        end = offset + limit;
                }
                model.addAttribute("end", end);
                return "item-aging";
        }
        
        @RequestMapping(value = "/downloadInventoryItemAgingByInterval", method = RequestMethod.POST)
        public ResponseEntity<?> downloadInventoryItemAgingByInterval(HttpServletRequest request, @RequestBody List<Integer> intervals, Model model) throws Exception{
                LoginDetails fofoDetails;
                try {
                        fofoDetails = cookiesProcessor.getCookiesObject(request);
                } catch (ProfitMandiBusinessException e) {
                        //model.addAttribute("loginResponse", mvcResponseSender.createResponseString("RTLR_1009", false, "/login"));
                        return responseSender.badRequest(e);
                }
                try{
                        this.validateIntervals(intervals);
                } catch (ProfitMandiBusinessException e) {
                        LOGGER.error("Unable to get valid interval values", e);
                        return responseSender.badRequest(e);
                }
                List<InventoryItemAgingModel> inventoryItemAgingModels = inventoryItemAgingService.getItemAgingByInterval(fofoDetails.getFofoId(), intervals);
                //return responseSender.ok(inventoryItemAgingModels);
                ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                ExcelUtils.writeInventoryItemAgingModels(inventoryItemAgingModels, intervals, byteArrayOutputStream);
                
                final HttpHeaders headers=new HttpHeaders();
                //private static final String CONTENT_TYPE_XLSX = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
        headers.set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        //headers.set("Content-Type", "application/vnd.ms-excel");
                headers.set("Content-disposition", "inline; filename=InventoryItemAging.xlsx");
        headers.setContentLength(byteArrayOutputStream.toByteArray().length);
        final InputStream inputStream=new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
        final InputStreamResource inputStreamResource=new InputStreamResource(inputStream);
        return new ResponseEntity<InputStreamResource>(inputStreamResource, headers, HttpStatus.OK);
                
                //return responseSender.ok(ResponseCodeHolder.getMessage("ITM_AGNG_OK_1000"));
        }
        
        
        private void validateIntervals(List<Integer> intervals)throws ProfitMandiBusinessException{
                if(intervals.isEmpty()){
                        throw new ProfitMandiBusinessException(ProfitMandiConstants.INTERVAL, intervals , "VE_1010");
                }
                int max = intervals.get(0);
                for(int index = 1; index < intervals.size(); index++){
                        if(intervals.get(index) <= max){
                                throw new ProfitMandiBusinessException(ProfitMandiConstants.INTERVAL, intervals, "VE_1011");
                        }
                        max = intervals.get(index);
                }
        }

        private Map<Integer, Map<String, Object>> grnHistoryDetails(Purchase purchase, int fofoId){
                Set<Integer> itemIds = new HashSet<>();
                Set<Item> inventoryItemDetails = new HashSet<>();
                List<InventoryItem> inventoryItems = inventoryItemRepository.selectByPurchaseId(purchase.getId());
                for(InventoryItem inventoryItem : inventoryItems){
                        inventoryItemDetails.add(inventoryItem.getItem());
                        itemIds.add(inventoryItem.getItemId());
                }
                
                Map<Integer, Map<String, Object>> grnHistoryDetails = new HashMap<>();
                this.createGrnHistoryDetails(grnHistoryDetails, inventoryItems);
                Map<Integer, Map<String, Object>> completedItemDetails = this.toMap(inventoryItemDetails, purchase);

                this.writeItemDetailstoGrnHistories(grnHistoryDetails, completedItemDetails);

                if(purchase.getCompleteTimestamp() != null){
                        List<Order> orders = orderRepository.selectByInvoiceNumberRetailerIdNotItemIds(purchase.getPurchaseReference(), fofoId, itemIds);
                        for(Order order : orders){
                                LineItem lineItem = order.getLineItem();
                                //orderItemDetails.add(lineItem.getItem());
                                Item item = lineItem.getItem();
                                if(!grnHistoryDetails.containsKey(item.getId())){
                                        Map<String, Object> grnHistoryDetail = new HashMap<>();
                                        grnHistoryDetail.put(ProfitMandiConstants.QUANTITY, lineItem.getQuantity());
                                        grnHistoryDetail.put(ProfitMandiConstants.BRAND, item.getBrand());
                                        grnHistoryDetail.put(ProfitMandiConstants.MODEL_NAME, item.getModelName());
                                        grnHistoryDetail.put(ProfitMandiConstants.MODEL_NUMBER, item.getModelNumber());
                                        grnHistoryDetail.put(ProfitMandiConstants.COLOR, item.getColor());
                                        grnHistoryDetail.put(ProfitMandiConstants.CATALOG_ITEM_ID, item.getCatalogItemId());
                                        grnHistoryDetail.put("iconUrl",Utils.getIconUrl(item.getCatalogItemId(), host, port, webapp));
                                        grnHistoryDetail.put(ProfitMandiConstants.COMPLETED, false);
                                        grnHistoryDetail.put("purchaseReference", purchase.getPurchaseReference());
                                        if(lineItem.getSerialNumber() == null || lineItem.getSerialNumber().equals("")){
                                                grnHistoryDetail.put(ProfitMandiConstants.SERIALIZED, false);
                                        }else{
                                                grnHistoryDetail.put(ProfitMandiConstants.SERIALIZED, true);
                                                Set<String> serialNumbers = new HashSet<>();
                                                serialNumbers.add(lineItem.getSerialNumber());
                                                grnHistoryDetail.put(ProfitMandiConstants.SERIAL_NUMBERS, serialNumbers);
                                        }
                                        grnHistoryDetails.put(item.getId(), grnHistoryDetail);
                                }else{
                                        Map<String, Object> grnHistoryDetail = grnHistoryDetails.get(item.getId());
                                        if((boolean)grnHistoryDetail.get(ProfitMandiConstants.SERIALIZED)){
                                                @SuppressWarnings("unchecked")
                                                Set<String> serialNumbers = (Set<String>)grnHistoryDetail.get(ProfitMandiConstants.SERIAL_NUMBERS);
                                                serialNumbers.add(lineItem.getSerialNumber());
                                        }
                                }
                        }
                }
                return grnHistoryDetails;
        }

        private void writeItemDetailstoGrnHistories(Map<Integer, Map<String, Object>> grnHistoryDetails, Map<Integer, Map<String, Object>> itemDetails){
                for(int key : grnHistoryDetails.keySet()){
                        Map<String, Object> grnHistoryDetail = grnHistoryDetails.get(key);
                        grnHistoryDetail.putAll(itemDetails.get(key));
                }
        }

        private Map<Integer, Map<String, Object>> toMap(Set<Item> items, Purchase purchase){
                Map<Integer, Map<String, Object>> map = new HashMap<>();
                for(Item item : items){
                        Map<String, Object> detailMap = new HashMap<>();
                        detailMap.put(ProfitMandiConstants.BRAND, item.getBrand());
                        detailMap.put(ProfitMandiConstants.MODEL_NAME, item.getModelName());
                        detailMap.put(ProfitMandiConstants.MODEL_NUMBER, item.getModelNumber());
                        detailMap.put(ProfitMandiConstants.COLOR, item.getColor());
                        detailMap.put(ProfitMandiConstants.CATALOG_ITEM_ID, item.getCatalogItemId());
                        detailMap.put("iconUrl",Utils.getIconUrl(item.getCatalogItemId(), host, port, webapp));
                        detailMap.put("purchaseReference", purchase.getPurchaseReference());
                        map.put(item.getId(), detailMap);
                }
                return map;
        }

        private void createGrnHistoryDetails(Map<Integer, Map<String, Object>> grnHistoryDetails, List<InventoryItem> inventoryItems){
                //Map<Integer, Map<String, Object>> grnHistoryDetails = new HashMap<>();
                for(InventoryItem inventoryItem : inventoryItems){
                        if(!grnHistoryDetails.containsKey(inventoryItem.getItemId())){
                                Map<String, Object> grnHistoryDetail = new HashMap<>();
                                grnHistoryDetail.put(ProfitMandiConstants.QUANTITY, inventoryItem.getInitialQuantity());
                                grnHistoryDetail.put(ProfitMandiConstants.COMPLETED, true);
                                if(inventoryItem.getSerialNumber() == null || inventoryItem.getSerialNumber().equals("")){
                                        grnHistoryDetail.put(ProfitMandiConstants.SERIALIZED, false);
                                }else{
                                        grnHistoryDetail.put(ProfitMandiConstants.SERIALIZED, true);
                                        Set<String> serialNumbers = new HashSet<>();
                                        serialNumbers.add(inventoryItem.getSerialNumber());
                                        grnHistoryDetail.put(ProfitMandiConstants.SERIAL_NUMBERS, serialNumbers);
                                        grnHistoryDetail.put("formattedSerialNumbers", String.join(", ", serialNumbers));
                                }
                                grnHistoryDetails.put(inventoryItem.getItemId(), grnHistoryDetail);
                                //itemIds.add(inventoryItem.getItemId());
                        }else{
                                Map<String, Object> grnHistoryDetail = grnHistoryDetails.get(inventoryItem.getItemId());
                                if((boolean)grnHistoryDetail.get(ProfitMandiConstants.SERIALIZED)){
                                        @SuppressWarnings("unchecked")
                                        Set<String> serialNumbers = (Set<String>)grnHistoryDetail.get(ProfitMandiConstants.SERIAL_NUMBERS);
                                        LOGGER.info("serialNumbers {}", serialNumbers);
                                        serialNumbers.add(inventoryItem.getSerialNumber());
                                        grnHistoryDetail.put("formattedSerialNumbers", String.join(", ", serialNumbers));
                                        grnHistoryDetail.put(ProfitMandiConstants.QUANTITY, (int)grnHistoryDetail.get(ProfitMandiConstants.QUANTITY) + inventoryItem.getInitialQuantity());
                                }
                        }

                }
                //return null;
        }

        public List<Item> getItemsByItemIds(Set<Integer> itemIds){
                return null;
        }

}