Subversion Repositories SmartDukaan

Rev

Rev 4657 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

package in.shop2020.support.controllers;

import in.shop2020.model.v1.order.LineItem;
import in.shop2020.model.v1.order.Order;
import in.shop2020.model.v1.order.OrderStatus;
import in.shop2020.model.v1.user.Affiliate;
import in.shop2020.model.v1.user.MasterAffiliate;
import in.shop2020.model.v1.user.TrackLog;
import in.shop2020.model.v1.user.TrackLogType;
import in.shop2020.model.v1.user.UserAffiliateException;
import in.shop2020.model.v1.user.UserContextService.Client;
import in.shop2020.payments.Payment;
import in.shop2020.support.utils.ReportsUtils;
import in.shop2020.thrift.clients.PaymentClient;
import in.shop2020.thrift.clients.TransactionClient;
import in.shop2020.thrift.clients.UserClient;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedSet;
import java.util.TimeZone;
import java.util.TreeSet;

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.CellStyle;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.CellRangeAddress;
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.thrift.TException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Provides reports about successful registrations and orders place through an
 * affiliate.
 * 
 * @author Vikas Malik
 * 
 */
@InterceptorRefs({
    @InterceptorRef("defaultStack"),
    @InterceptorRef("login")
})
@Results({
    @Result(name="authfail", type="redirectAction", params = {"actionName" , "reports"})
})
public class AffiliateController implements ServletRequestAware, ServletResponseAware{

    private static Logger log = LoggerFactory.getLogger(AffiliateController.class);
    
        private HttpServletResponse response;
        private HttpServletRequest request;
        private HttpSession session;
    
        private String errorMsg = "";
        private List<MasterAffiliate> masterAffiliates;
        private Date startDate = null;
        private Date endDate = null;
        
        @Override
        public void setServletResponse(HttpServletResponse res) {
                this.response = res;
        }

        @Override
    public void setServletRequest(HttpServletRequest req) {
            this.request = req;
        this.session = req.getSession();
    }
        
        public String index()  {
            log.info(request.getServletPath());
        if (!ReportsUtils.canAccessReport(
                (Long) session.getAttribute(ReportsUtils.ROLE),
                request.getServletPath())) 
        {
            return "authfail";
        }
        try {
                UserClient userContextServiceClient = new UserClient();
            Client userClient = userContextServiceClient.getClient();
            masterAffiliates = userClient.getAllMasterAffiliates();
        } catch (Exception e) {
            log.error("Error while getting all affiliates", e);
        }
        return "report";
    }
        
        public String create()  {
            try   {
                long mAfId = Long.parseLong(request.getParameter("masterAffiliate"));
                String mAffName;
                String startDateStr = request.getParameter("startDate");
                String endDateStr = request.getParameter("endDate");
                
                DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
                df.setTimeZone(TimeZone.getTimeZone("IST"));
                try {
                    startDate = df.parse(startDateStr);
                    endDate = df.parse(endDateStr);
                    Calendar cal = Calendar.getInstance();
                    cal.setTime(endDate);
                    endDate.setTime(cal.getTimeInMillis());
                } catch (ParseException pe) {
                    errorMsg = "Please enter start and end dates in format MM/dd/yyyy";
                    return "report";
                }
                
                UserClient userContextServiceClient = new UserClient();
            PaymentClient paymentServiceClient = new PaymentClient();
            TransactionClient transactionServiceClient = new TransactionClient();
            
            Client userClient = userContextServiceClient.getClient();
            in.shop2020.payments.PaymentService.Client paymentClient = paymentServiceClient.getClient();
            
            List<Affiliate> affiliates;
            if (mAfId == -1) {
                mAffName = "All";
                affiliates = new ArrayList<Affiliate>();
                for(MasterAffiliate mAffiliate : userClient.getAllMasterAffiliates()) {
                    affiliates.addAll(userClient.getAffiliatesByMasterAffiliate(mAffiliate.getId()));
                }
            }
            else {
                affiliates = userClient.getAffiliatesByMasterAffiliate(mAfId);
                mAffName = userClient.getMasterAffiliateById(mAfId).getName();
            }
            
            SortedSet<Date> dates = new TreeSet<Date>();
            Map<Date, Long> registerCountMap = new HashMap<Date, Long>();
            Map<Date, Double> saleQuantityMap = new HashMap<Date, Double>();
            Map<Date, Double> saleAmountMap = new HashMap<Date, Double>();
            
            Map<Date, Map<String, Double>> productQuantityMap = new HashMap<Date, Map<String, Double>>();
            Map<Date, Map<Long, ArrayList<String>>> dateTxnProductMap = new HashMap<Date, Map<Long, ArrayList<String>>>();
            Map<Date, Map<String, Double>> productAmountMap = new HashMap<Date, Map<String,Double>>();
            
            for (Affiliate aff : affiliates) {
                Set<Long> Payments = new HashSet<Long>(); // To deal with multiple refreshes on pay-success page.
                for (TrackLog tracklog : userClient.getTrackLogsByAffiliate(aff.getId(), startDate.getTime(), endDate.getTime())) {
                    Date date = df.parse(df.format(new Date(tracklog.getAddedOn())));
                    dates.add(date);
                    if (tracklog.getEventType() == TrackLogType.NEW_REGISTRATION) {
                        if (registerCountMap.containsKey(date)) {
                            Long count = registerCountMap.get(date);
                            registerCountMap.put(date, ++count);
                        }
                        else {
                            registerCountMap.put(date, 1l);
                        }
                    }
                    else if (tracklog.getEventType() == TrackLogType.PAYMENT_SUCCESS) {
                        long paymentId = Long.parseLong(tracklog.getData().replaceAll("\\(.*\\)", ""));
                        if (Payments.contains(paymentId)) {
                            continue;
                        }
                        Payments.add(paymentId);
                        Payment payment = paymentClient.getPayment(paymentId);
                        List<Order> orders = transactionServiceClient.getClient().getOrdersForTransaction(
                                        payment.getMerchantTxnId(),
                                        payment.getUserId());
                        for (Order order : orders) {
                            if (order.getStatus() == OrderStatus.DELIVERY_SUCCESS) {
                                List<LineItem> items = order.getLineitems();
                                if (saleAmountMap.containsKey(date)) {
                                    Double amount = saleAmountMap.get(date);
                                    amount += order.getTotal_amount();
                                    saleAmountMap.put(date, amount);
                                }
                                else {
                                    saleAmountMap.put(date, order.getTotal_amount());
                                }
                                for (LineItem item : items) {
                                    if (saleQuantityMap.containsKey(date)) {
                                        Double quantity = saleQuantityMap.get(date);
                                        quantity += item.getQuantity();
                                        saleQuantityMap.put(date, quantity);
                                    }
                                    else {
                                        saleQuantityMap.put(date, item.getQuantity());
                                    }
                                    
                                    String productName = item.getBrand() + " "
                                            + item.getModel_name() + " "
                                            + item.getModel_number();
                                    productName = productName.replace("null", "").replaceAll("  ", " ").trim();
                                    
                                    if (productQuantityMap.containsKey(date)) {
                                        Map<String, Double> pQuantityMap = productQuantityMap.get(date);
                                        if (pQuantityMap.containsKey(productName)) {
                                            Double quantity = pQuantityMap.get(productName);
                                            quantity += item.getQuantity();
                                            pQuantityMap.put(productName, quantity);
                                        }
                                        else {
                                            pQuantityMap.put(productName, item.getQuantity());
                                        }
                                    }
                                    else {
                                        Map<String, Double> pQuantityMap = new HashMap<String, Double>();
                                        pQuantityMap.put(productName, item.getQuantity());
                                        productQuantityMap.put(date, pQuantityMap);
                                    }
                                    
                                    if (dateTxnProductMap.containsKey(date)) {
                                        Map<Long, ArrayList<String>> txnProductMap = dateTxnProductMap.get(date);
                                        if (txnProductMap.containsKey(order.getTransactionId())) {
                                            ArrayList<String> productList = txnProductMap.get(order.getTransactionId());
                                            productList.add(productName); 
                                        } else {
                                            ArrayList<String> productList = new ArrayList<String>();
                                            productList.add(productName);
                                            txnProductMap.put(order.getTransactionId(), productList);
                                        }
                                    }
                                    else {
                                        Map<Long, ArrayList<String>> txnProductMap = new HashMap<Long, ArrayList<String>>();
                                        ArrayList<String> productList = new ArrayList<String>();
                                        productList.add(productName);
                                        txnProductMap.put(order.getTransactionId(), productList);
                                        dateTxnProductMap.put(date, txnProductMap);
                                    }
                                    
                                    if (productAmountMap.containsKey(date)) {
                                        Map<String, Double> pAmountMap = productAmountMap.get(date);
                                        if (pAmountMap.containsKey(productName)) {
                                            Double amount = pAmountMap.get(productName);
                                            amount += item.getTotal_price();
                                            pAmountMap.put(productName, amount);
                                        }
                                        else {
                                            pAmountMap.put(productName, item.getTotal_price());
                                        }
                                    }
                                    else {
                                        Map<String, Double> pAmountMap = new HashMap<String, Double>();
                                        pAmountMap.put(productName, item.getTotal_price());
                                        productAmountMap.put(date, pAmountMap);
                                    }
                                }
                            }
                        }
                    }
                }
            }
            
            // Preparing XLS file for output
            response.setContentType("application/vnd.ms-excel");
            
            response.setHeader("Content-disposition", "inline; filename=" + mAffName + "-affiliate-report" + ".xls");
            
            ServletOutputStream sos;
            try {
                ByteArrayOutputStream baos = getSpreadSheetData(mAffName,
                                                                   dates,
                                                                   registerCountMap, 
                                                                   saleQuantityMap, 
                                                                   saleAmountMap, 
                                                                   productQuantityMap, 
                                                                   dateTxnProductMap, 
                                                                   productAmountMap);
                sos = response.getOutputStream();
                baos.writeTo(sos);
                sos.flush();
            } catch (IOException e) {
                log.error("Unable to stream the affiliates report", e);
                errorMsg = "Failed to write to response.";
            }
        } catch (UserAffiliateException e) {
            log.error("Error while getting affiliated users", e);
            errorMsg = e.getMessage();
        } catch (TException e) {
            log.error("Unable to get affiliated users", e);
            errorMsg = e.getMessage();
        } catch (Exception e) {
            log.error("Unexpected exception", e);
            errorMsg = e.getMessage();
        }
        return null;
        }
        
    // Prepares the XLS worksheet object and fills in the data with proper formatting
        private ByteArrayOutputStream getSpreadSheetData(String mAffName, 
                SortedSet<Date> dates,
            Map<Date, Long> registerCountMap,
            Map<Date, Double> saleQuantityMap,
            Map<Date, Double> saleAmountMap,
            Map<Date, Map<String, Double>> productQuantityMap,
            Map<Date, Map<Long, ArrayList<String>>> dateTxnProductMap,
            Map<Date, Map<String, Double>> productAmountMap)
        {
            ByteArrayOutputStream baosXLS = new ByteArrayOutputStream();

                Workbook wb = new HSSFWorkbook();
            
            Font font = wb.createFont();
            font.setBoldweight(Font.BOLDWEIGHT_BOLD);
            CellStyle style = wb.createCellStyle();
            style.setFont(font);
            
            CreationHelper createHelper = wb.getCreationHelper();
            CellStyle dateCellStyle = wb.createCellStyle();
            dateCellStyle.setDataFormat(createHelper.createDataFormat().getFormat("DD/MM/YYYY"));
            
            createSummarySheet(mAffName, dates, registerCountMap, saleQuantityMap, saleAmountMap, wb, style, dateCellStyle);
            createSaleDetailSheet(mAffName, dates, dateTxnProductMap, productQuantityMap, productAmountMap, wb, style, dateCellStyle);
                        
                // Write the workbook to the output stream
                try {
                        wb.write(baosXLS);
                        baosXLS.close();
                } catch (IOException e) {
                        log.error("Unable to get the byte array for the affiliate report", e);
                }               
                return baosXLS;
        }
        
    private void createSaleDetailSheet(String mAffName, SortedSet<Date> dates,
            Map<Date, Map<Long, ArrayList<String>>> dateTxnProductMap,
            Map<Date, Map<String, Double>> productQuantityMap,
            Map<Date, Map<String, Double>> productAmountMap, Workbook wb,
            CellStyle style, CellStyle dateCellStyle) {
        // Product Sales SHEET
        Sheet affSheet = wb.createSheet("Product Sales Report");
        short affSerialNo = 0;
        
        DateFormat df = new SimpleDateFormat("MM/dd/yyyy");

        Row affTitleRow = affSheet.createRow(affSerialNo ++);
        Cell affTitleCell = affTitleRow.createCell(0);
        affTitleCell.setCellValue("Modelwise Sales Report");
        affTitleCell.setCellStyle(style);
        affSheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 6));
        
        affSheet.createRow(affSerialNo ++);
        Row affNameRow = affSheet.createRow(affSerialNo ++);
        Cell affNameCell = affNameRow.createCell(0);
        affNameCell.setCellValue("Affiliate : " + mAffName);
        affNameCell.setCellStyle(style);
        affSheet.addMergedRegion(new CellRangeAddress(2, 2, 0, 6));
        
        Row affDateRangeRow = affSheet.createRow(affSerialNo ++);
        Cell affDateRangeCell = affDateRangeRow.createCell(0);
        affDateRangeCell.setCellValue("Date Range : " + df.format(startDate) + " - " + df.format(endDate));
        affDateRangeCell.setCellStyle(style);
        affSheet.addMergedRegion(new CellRangeAddress(3, 3, 0, 6));
        
        affSheet.createRow(affSerialNo ++);affSheet.createRow(affSerialNo ++);
        
        Row affHeaderRow = affSheet.createRow(affSerialNo++);
        affHeaderRow.createCell(0).setCellValue("Date");
        affHeaderRow.createCell(1).setCellValue("ProductName");
        affHeaderRow.createCell(2).setCellValue("Transaction Id");
        affHeaderRow.createCell(3).setCellValue("Amount");
        for (int i=0; i<4 ;i++) {
            affHeaderRow.getCell(i).setCellStyle(style);
        }
        
        Double totalQuantity = 0d;
        Double totalAmount = 0d;
        for(Date date : dates) {
            if (!dateTxnProductMap.containsKey(date)) {
                continue;
            }
            //HashSet<String> tmpProductSet = new HashSet<String>();
            ArrayList<String> prodList = new ArrayList<String>();
            Row commContentRow = null;
            for (Entry<Long, ArrayList<String>> txnEntry : dateTxnProductMap.get(date).entrySet()) {
                prodList = txnEntry.getValue();
                Long txn = txnEntry.getKey();
                for (String prodName : prodList) {
                    affSerialNo++;
                    commContentRow = affSheet.createRow(affSerialNo);
                    commContentRow.createCell(0).setCellValue(date);
                    commContentRow.getCell(0).setCellStyle(dateCellStyle);
                    commContentRow.createCell(1).setCellValue(prodName);
                    commContentRow.createCell(2).setCellValue(txn);
                    Double amount = productAmountMap.get(date).get(prodName);
                    amount = amount/(productQuantityMap.get(date).get(prodName));
                    totalAmount += amount;
                    commContentRow.createCell(3).setCellValue(amount);
                    totalQuantity++;
                }
            }
        }
        affSerialNo+=2;
        Row commContentRow = affSheet.createRow(affSerialNo);
        commContentRow.createCell(0).setCellValue("Total");
        commContentRow.createCell(1).setCellValue("");
        commContentRow.createCell(2).setCellValue(totalQuantity);
        commContentRow.createCell(3).setCellValue(totalAmount);
        
        for (int i = 0; i<4; i++) {
            affSheet.autoSizeColumn(i);
        }
    }

    private void createSummarySheet(String mAffName, 
            SortedSet<Date> dates,
            Map<Date, Long> registerCountMap,
            Map<Date, Double> saleQuantityMap,
            Map<Date, Double> saleAmountMap, 
            Workbook wb, 
            CellStyle style,
            CellStyle dateCellStyle) 
    {
                // Summary SHEET
            Sheet affSheet = wb.createSheet("Summary Report");
            short affSerialNo = 0;
            
            DateFormat df = new SimpleDateFormat("MM/dd/yyyy");

            Row affTitleRow = affSheet.createRow(affSerialNo ++);
            Cell affTitleCell = affTitleRow.createCell(0);
            affTitleCell.setCellValue("Daily Stats Report");
            affTitleCell.setCellStyle(style);
            affSheet.addMergedRegion(new CellRangeAddress(0, 0, 0, 6));
            
            affSheet.createRow(affSerialNo ++);
            Row affNameRow = affSheet.createRow(affSerialNo ++);
        Cell affNameCell = affNameRow.createCell(0);
        affNameCell.setCellValue("Affiliate : " + mAffName);
        affNameCell.setCellStyle(style);
        affSheet.addMergedRegion(new CellRangeAddress(2, 2, 0, 6));
        
        Row affDateRangeRow = affSheet.createRow(affSerialNo ++);
        Cell affDateRangeCell = affDateRangeRow.createCell(0);
        affDateRangeCell.setCellValue("Date Range : " + df.format(startDate) + " - " + df.format(endDate));
        affDateRangeCell.setCellStyle(style);
        affSheet.addMergedRegion(new CellRangeAddress(3, 3, 0, 6));
        
            affSheet.createRow(affSerialNo ++);affSheet.createRow(affSerialNo ++);
                
            Row affHeaderRow = affSheet.createRow(affSerialNo++);
            affHeaderRow.createCell(0).setCellValue("Date");
            affHeaderRow.createCell(1).setCellValue("New Registrations");
            affHeaderRow.createCell(2).setCellValue("Sales Count");
            affHeaderRow.createCell(3).setCellValue("Amount");
            for (int i=0; i<4 ;i++) {
                affHeaderRow.getCell(i).setCellStyle(style);
            }
            
            Double totalregisterCount = 0d;
        Double totalQuantity = 0d;
            Double totalAmount = 0d;
        for(Date date : dates) {
                    affSerialNo++;
                        Row commContentRow = affSheet.createRow(affSerialNo);
                        Long registerCount = registerCountMap.get(date);
                        Double saleQuantity = saleQuantityMap.get(date);
                        Double saleAmount = saleAmountMap.get(date);
                        if (registerCount == null) {
                            registerCount = 0l;
                        }
                        if (saleQuantity == null) {
                saleQuantity = 0d;
            }
                        if (saleAmount == null) {
                saleAmount = 0d;
            }
                        totalregisterCount += registerCount;
            totalQuantity += saleQuantity;
                        totalAmount += saleAmount;
            commContentRow.createCell(0).setCellValue(date);
                        commContentRow.getCell(0).setCellStyle(dateCellStyle);
            commContentRow.createCell(1).setCellValue(registerCount);
                        commContentRow.createCell(2).setCellValue(saleQuantity);
                        commContentRow.createCell(3).setCellValue(saleAmount);
                }
        affSerialNo+=2;
        Row commContentRow = affSheet.createRow(affSerialNo);
        commContentRow.createCell(0).setCellValue("Total");
        commContentRow.createCell(1).setCellValue(totalregisterCount);
        commContentRow.createCell(2).setCellValue(totalQuantity);
        commContentRow.createCell(3).setCellValue(totalAmount);
        
        for (int i = 0; i<4; i++) {
            affSheet.autoSizeColumn(i);
        }
        }

        public String getErrorMsg() {
                return errorMsg;
        }
        
        public List<MasterAffiliate> getMasterAffiliates() {
        return masterAffiliates;
    }
}