Subversion Repositories SmartDukaan

Rev

Rev 5931 | Blame | Compare with Previous | Last modification | View Log | RSS feed

package in.shop2020.support.controllers;

import in.shop2020.logistics.DeliveryType;
import in.shop2020.logistics.LogisticsService.Client;
import in.shop2020.logistics.LogisticsServiceException;
import in.shop2020.model.v1.catalog.CatalogServiceException;
import in.shop2020.model.v1.catalog.Item;
import in.shop2020.model.v1.catalog.status;
import in.shop2020.model.v1.inventory.InventoryServiceException;
import in.shop2020.model.v1.inventory.ItemInventory;
import in.shop2020.support.utils.FileUtils;
import in.shop2020.support.utils.ReportsUtils;
import in.shop2020.thrift.clients.CatalogClient;
import in.shop2020.thrift.clients.InventoryClient;
import in.shop2020.thrift.clients.LogisticsClient;
import in.shop2020.utils.CategoryManager;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.struts2.convention.annotation.InterceptorRef;
import org.apache.struts2.convention.annotation.InterceptorRefs;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.util.ServletContextAware;
import org.apache.thrift.TException;
import org.apache.thrift.transport.TTransportException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


@InterceptorRefs({
    @InterceptorRef("defaultStack"),
    @InterceptorRef("login")
})
@Results({
    @Result(name="authfail", type="redirectAction", params = {"actionName" , "reports"})
})
public class StockReportsController implements ServletRequestAware, ServletResponseAware, ServletContextAware{

    private static Logger logger = LoggerFactory.getLogger(StockReportsController.class);    

    private static final String REPORT_DIR = "/inventory-report";
    
    private static final String DEFAULT_PINCODE = "110001"; 
    private static final long REPORT_GENERATION_INTERVAL = 3;
    private static final long CUT_OFF_TIME = 15;
    private static long NEXT_DAY_DELAY = 1;

    private static final int ID = 0, BRAND = 1, MODEL_NUMBER = 2, MODEL_NAME = 3, COLOR = 4, DELIVERY_DAYS = 5, TOTAL_AVAILABILITY = 6, TOTAL_RESERVED = 7;
        private static final int WH1_AVAILABILITY = 8, WH1_RESERVED = 9, WH5_AVALABILITY = 10, WH5_RESERVED = 11, WH7_AVALABILITY = 12, WH7_RESERVED = 13, RISKY = 14, EXPECTED_DELAY = 15, STICKY = 16, SIMILAR_ITEMS = 17;
                
    private HttpSession session;
    private HttpServletRequest request;
    private HttpServletResponse response;
    private ServletContext context;
    
    private String errorMsg = "";
    
    public String index(){
        if(!ReportsUtils.canAccessReport((Long)session.getAttribute(ReportsUtils.ROLE), request.getServletPath())) {
            return "authfail";
        }
        return "index";
    }
    
    public String create() throws NumberFormatException, IOException{
        
        Calendar date = new GregorianCalendar();
        int year = date.get(Calendar.YEAR);
        int month = date.get(Calendar.MONTH) +1;
        int day = date.get(Calendar.DAY_OF_MONTH);
        int hour = date.get(Calendar.HOUR_OF_DAY);
        long currentTimestamp = date.getTimeInMillis();
        String lastTimestampString = org.apache.commons.io.FileUtils.readFileToString(new File(REPORT_DIR + File.separator + "last.timestamp"));
        lastTimestampString = lastTimestampString.replace("\"", "").replace("\n", "");
        long lastTimestamp = Long.parseLong(lastTimestampString);
        
        String filename = "inventory-report." + year + "-" + month + "-" + day + "-" + lastTimestamp + ".xls";
        if(hour >= CUT_OFF_TIME){
                NEXT_DAY_DELAY = 2;
        }else{
                NEXT_DAY_DELAY = 1;
        }
        if(currentTimestamp - lastTimestamp > REPORT_GENERATION_INTERVAL*60*60*1000){
                filename = "inventory-report." + year + "-" + month + "-" + day + "-" + currentTimestamp + ".xls";
                File inventoryReportFile = new File(REPORT_DIR + File.separator + filename);
            ByteArrayOutputStream baosXLS = generateInventoryStockReport();
            if (baosXLS == null) {
                errorMsg = "Could not get output";
                return "index";
            }
            
            try {
                FileOutputStream f = new FileOutputStream(inventoryReportFile);
                baosXLS.writeTo(f);
                f.close();
                org.apache.commons.io.FileUtils.writeStringToFile(new File(REPORT_DIR + File.separator + "last.timestamp"), currentTimestamp+"");
            } catch (FileNotFoundException e) {
                logger.error("Error while writing the inventory report", e);
                return "index";
            } catch (IOException e) {
                logger.error("Error while writing the inventory report", e);
                return "index";
            }
        }
        
        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-disposition", "inline; filename=" + filename);
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            baos.write(FileUtils.getBytesFromFile(new File(REPORT_DIR + File.separator + filename)));
            ServletOutputStream sos = response.getOutputStream();
            baos.writeTo(sos);
            sos.flush();
            errorMsg = "Report generated";
        } catch (IOException e) {
            logger.error("Unable to stream the inventory stock report", e);
            errorMsg = "Failed to write to response.";
        }
        return "index";
    }
    
    private ByteArrayOutputStream generateInventoryStockReport(){
        Map<String, Map<String, List<RowItem>>> categoryWiseStock = new LinkedHashMap<String, Map<String, List<RowItem>>>();
        String nextDay = "Deliverable on Next Day";
        String notNextDay = "Not Deliverable on Next Day";
        String notAvailable = "Out of Stock";
        LogisticsClient logisticsServiceClient;
        CatalogClient catalogClientService;
        try {
            catalogClientService = new CatalogClient();
            InventoryClient inventoryClientService = new InventoryClient();
            logisticsServiceClient = new LogisticsClient();
            in.shop2020.model.v1.catalog.CatalogService.Client client = catalogClientService.getClient();
            in.shop2020.model.v1.inventory.InventoryService.Client iclient = inventoryClientService.getClient();
            List<Item> items = client.getAllItems(false);
                        Client logisticsClient = logisticsServiceClient.getClient();

                        CategoryManager catm = CategoryManager.getCategoryManager();
                        for(Item item : items){
                                status state = item.getItemStatus();
                switch(state){
                case IN_PROCESS:
                case CONTENT_COMPLETE:
                case DELETED:
                case PHASED_OUT:
                    continue;
                case PAUSED:
                case PAUSED_BY_RISK:
                case ACTIVE:
                        if(item.getCategory() == -1 || item.getCategory() == 0){
                                continue;
                        }
                        String category = catm.getCategory(catm.getCategory(item.getCategory()).getParent_category_id()).getLabel();
                        
                        Map<String, List<RowItem>> sheetsMap = categoryWiseStock.get(category);
                        if(sheetsMap ==  null){
                                sheetsMap = new HashMap<String, List<RowItem>>();
                                categoryWiseStock.put(category, sheetsMap);
                                sheetsMap.put(nextDay, new ArrayList<RowItem>());
                                sheetsMap.put(notNextDay, new ArrayList<RowItem>());
                                sheetsMap.put(notAvailable, new ArrayList<RowItem>());
                        }
                        
                        
                        long deliveryDays = 3;
                        try{
                                
                                deliveryDays = logisticsClient.getLogisticsEstimation(item.getId(), DEFAULT_PINCODE, DeliveryType.PREPAID).getDeliveryTime();
                        }catch (LogisticsServiceException e) {
                                logger.error("Error while getting estimate of the inventory for item " + item.getId(), e);
                        }
                        ItemInventory inventory = iclient.getItemInventoryByItemId(item.getId());
                        RowItem rowItem = new RowItem(item, deliveryDays, inventory);
                        if(state == status.ACTIVE){
                        if(deliveryDays == NEXT_DAY_DELAY)
                                sheetsMap.get(nextDay).add(rowItem);
                        else
                                sheetsMap.get(notNextDay).add(rowItem);    
                    }else{
                        sheetsMap.get(notAvailable).add(rowItem);
                        List<Item> similaritems= client.getAllSimilarItems(item.getId());
                        if(similaritems!=null){
                                boolean isFirst = true;
                                for(Item item1: similaritems){
                                        if(isFirst){
                                                isFirst = false;
                                        }else{
                                                rowItem.similarItems += "\n";
                                        }
                                        rowItem.similarItems += item1.getBrand() + " " + item1.getModelName() + " " + item1.getModelNumber() + " " + item1.getColor();
                                }
                        }
                    }
                }
            }
        } catch (TTransportException e) {
            logger.error("Unable to get the items from the inventory", e);
            return null;
        } catch (CatalogServiceException e) {
            logger.error("Error while getting the items from the inventory", e);
            return null;
        } catch (TException e) {
            logger.error("Error while getting the items from the inventory", e);
            return null;
                } catch (InventoryServiceException e) {
                    logger.error("Error while getting the items from the inventory", e);
            return null;
        }
        
        ByteArrayOutputStream baosXLS = new ByteArrayOutputStream();

        Workbook wb = new HSSFWorkbook();
        
//        for(String category: categoryWiseStock.keySet()){
//              Map<String, List<RowItem>> value = categoryWiseStock.get(category);  
//              createSheet(wb, category + " - " + nextDay, value.get(nextDay));
//              createSheet(wb, category + " - " + notNextDay, value.get(notNextDay));
//              createSheet(wb, category + " - " + notAvailable, value.get(notAvailable));
//        }
        
        //Hardcoding to maintain category
        List<String> categories = new ArrayList<String>();
        categories.add("Mobile Phones");
        categories.add("Tablets");
        categories.add("Mobile Accessories");
        categories.add("Laptops");
        categories.add("Laptop Accessories");
        for(String category: categories){
                Map<String, List<RowItem>> value = categoryWiseStock.get(category);  
                createSheet(wb, category + " - " + nextDay, value.get(nextDay));
                createSheet(wb, category + " - " + notNextDay, value.get(notNextDay));
                createSheet(wb, category + " - " + notAvailable, value.get(notAvailable));
        }
        
        
        try {
            wb.write(baosXLS);
            baosXLS.close();
        } catch (IOException e) {
            logger.error("Error while streaming inventory stock report", e);
            return null;
        }
        return baosXLS;
    }
    
    private void createSheet(Workbook wb, String name, List<RowItem> items){
        Sheet sheet = wb.createSheet(name);
        short serialNo = 0;
        Row headerRow = sheet.createRow(serialNo++);
        headerRow.createCell(ID).setCellValue("Item Id");
        headerRow.createCell(BRAND).setCellValue("Brand");
        headerRow.createCell(MODEL_NUMBER).setCellValue("Model Number");
        headerRow.createCell(MODEL_NAME).setCellValue("Model Name");
        headerRow.createCell(COLOR).setCellValue("Color");
        headerRow.createCell(DELIVERY_DAYS).setCellValue("Delivery Days");
        headerRow.createCell(TOTAL_AVAILABILITY).setCellValue("Total Availability");
        headerRow.createCell(TOTAL_RESERVED).setCellValue("Total Reserved");
        headerRow.createCell(WH1_AVAILABILITY).setCellValue("901 Availabality");
        headerRow.createCell(WH1_RESERVED).setCellValue("901 Reserved");
        headerRow.createCell(WH5_AVALABILITY).setCellValue("9D2 Availabality");
        headerRow.createCell(WH5_RESERVED).setCellValue("9D2 Reserved");
        headerRow.createCell(WH7_AVALABILITY).setCellValue("MP Availabality");
        headerRow.createCell(WH7_RESERVED).setCellValue("MP Reserved");
        headerRow.createCell(RISKY).setCellType(Cell.CELL_TYPE_STRING);
        headerRow.getCell(RISKY).setCellValue("Risky");
        headerRow.createCell(EXPECTED_DELAY).setCellValue("Expected Delay");
        headerRow.createCell(STICKY).setCellType(Cell.CELL_TYPE_STRING);
        headerRow.getCell(STICKY).setCellValue("Sticky");
        headerRow.createCell(SIMILAR_ITEMS).setCellType(Cell.CELL_TYPE_STRING);
        headerRow.getCell(SIMILAR_ITEMS).setCellValue("Similar Items");
        
        //        headerRow.createCell(WH2_A).setCellValue("WH2 Availabality");
        //        headerRow.createCell(WH3_A).setCellValue("WH3 Availabality");
        //        headerRow.createCell(WH4_A).setCellValue("WH4 Availabality");     
        //        headerRow.createCell(WH2_R).setCellValue("WH2 Reserved");
        //        headerRow.createCell(WH3_R).setCellValue("WH3 Reserved");
        //        headerRow.createCell(WH4_R).setCellValue("WH4 Reserved");

        for(RowItem item : items){
            Row contentRow = sheet.createRow(serialNo++);
            contentRow.createCell(ID).setCellValue(item.id);
            contentRow.createCell(BRAND).setCellValue(item.brand);
            contentRow.createCell(MODEL_NUMBER).setCellValue(item.modelNumber);
            contentRow.createCell(MODEL_NAME).setCellValue(item.modelName);
            contentRow.createCell(COLOR).setCellValue(item.color);
            contentRow.createCell(DELIVERY_DAYS).setCellValue(item.deliveryEstimate);
            contentRow.createCell(TOTAL_AVAILABILITY).setCellValue(item.totalAvailability);
            contentRow.createCell(TOTAL_RESERVED).setCellValue(item.totalReserved);
            contentRow.createCell(WH1_AVAILABILITY).setCellValue(item.wh1Availability);
            contentRow.createCell(WH1_RESERVED).setCellValue(item.wh1Reserved);
            contentRow.createCell(WH5_AVALABILITY).setCellValue(item.wh5Availability);
            contentRow.createCell(WH5_RESERVED).setCellValue(item.wh5Reserved);
            contentRow.createCell(WH7_AVALABILITY).setCellValue(item.wh7Availability);
            contentRow.createCell(WH7_RESERVED).setCellValue(item.wh7Reserved);
            contentRow.createCell(RISKY).setCellValue(item.risky);
            contentRow.createCell(EXPECTED_DELAY).setCellValue(item.expectedDelay);
            contentRow.createCell(STICKY).setCellValue(item.sticky);
            contentRow.createCell(SIMILAR_ITEMS).setCellValue(item.similarItems);
        }
        sheet.autoSizeColumn(SIMILAR_ITEMS);

    }
    
    public String getErrorMsg() {
        return errorMsg;
    }

    @Override
    public void setServletRequest(HttpServletRequest req) {
        this.request = req;
        this.session = req.getSession();
    }

    @Override
    public void setServletResponse(HttpServletResponse res) {
        this.response = res;
    }
    
    @Override
    public void setServletContext(ServletContext context) {
        this.context = context;
    }

    public String getServletContextPath() {
        return context.getContextPath();
    }
    
    public static void main(String[] args) {
        StockReportsController src = new StockReportsController();
        try {
            String userHome = System.getProperty("user.home");
            FileOutputStream f = new FileOutputStream(userHome + "/stock-report.xls");
            ByteArrayOutputStream baosXLS = src.generateInventoryStockReport();
            baosXLS.writeTo(f);
            f.close();
        } catch (FileNotFoundException e) {
            logger.error("Error creating inventory stock report", e);
        } catch (IOException e) {
            logger.error("IO error while creating inventory stock report", e);
        }
        System.out.println("Successfully generated the inventory stock report");
    }
    
    class RowItem {
        public long id;
        public String brand;
        public String modelNumber;
        public String modelName;
        public String color;
        public long deliveryEstimate = 0;
        public long totalAvailability = 0;
        public long totalReserved = 0;
        public long wh1Availability = 0;
        public long wh1Reserved = 0;
        public long wh5Availability = 0;
        public long wh5Reserved = 0;
        public long wh7Availability = 0;
        public long wh7Reserved = 0;
        public String similarItems = "";
        public String risky;
        public String sticky;
        public long expectedDelay = 0;
        
        public RowItem(Item item, long estimate, ItemInventory itemInventory){
           id = item.getId();
           brand = item.getBrand();
           modelNumber = item.getModelNumber();
           modelName = item.getModelName();
           color = item.getColor();
           deliveryEstimate = estimate;
           risky = item.isRisky() ? "True" : "False";
           sticky = item.isIsWarehousePreferenceSticky() ? "True" : "False";
           expectedDelay = item.getExpectedDelay();
           totalAvailability = 0;
           for(Map.Entry<Long, Long> entry : itemInventory.getAvailability().entrySet()){
                   long value = entry.getValue();
                   switch (entry.getKey().intValue()) {
                   case 1:
                           wh1Availability = value;
                           break;
                   case 5:
                           wh5Availability = value;
                           break;
                   case 7:
                           wh7Availability = value;
                           break;
                   default:
                           break;
                   }
                   totalAvailability += value;
           }
           for(Map.Entry<Long, Long> entry : itemInventory.getReserved().entrySet()){
                   long value = entry.getValue();
                   switch (entry.getKey().intValue()) {
                   case 1:
                           wh1Reserved = value;
                           break;
                   case 5:
                           wh5Reserved = value;
                           break;
                   case 7:
                           wh7Reserved = value;
                           break;
                   default:
                           break;
                   }
                   totalReserved += value;
           }
        }
    }
}