Subversion Repositories SmartDukaan

Rev

Rev 35415 | 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.spice.profitmandi.common.exception.ProfitMandiBusinessException;
import com.spice.profitmandi.common.model.CustomAddress;
import com.spice.profitmandi.common.model.CustomCustomer;
import com.spice.profitmandi.common.model.ProfitMandiConstants;
import com.spice.profitmandi.common.solr.SolrService;
import com.spice.profitmandi.common.web.util.ResponseSender;
import com.spice.profitmandi.dao.entity.catalog.CustomerOffer;
import com.spice.profitmandi.dao.entity.catalog.CustomerOfferItem;
import com.spice.profitmandi.dao.entity.catalog.Item;
import com.spice.profitmandi.dao.entity.fofo.*;
import com.spice.profitmandi.dao.model.CustomerOrderDetail;
import com.spice.profitmandi.dao.model.UserCart;
import com.spice.profitmandi.dao.repository.catalog.CustomerOfferItemRepository;
import com.spice.profitmandi.dao.repository.catalog.CustomerOfferRepository;
import com.spice.profitmandi.dao.repository.catalog.ItemRepository;
import com.spice.profitmandi.dao.repository.catalog.SamsungUpgradeOfferRepository;
import com.spice.profitmandi.dao.repository.dtr.UserAccountRepository;
import com.spice.profitmandi.dao.repository.fofo.*;
import com.spice.profitmandi.service.CustomerService;
import com.spice.profitmandi.service.inventory.InventoryService;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
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 javax.servlet.http.HttpServletRequest;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.HashSet;
import java.util.function.Function;
import java.util.stream.Collectors;

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

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

        @Autowired
        private ResponseSender<?> responseSender;

        @Autowired
        private UserAccountRepository userAccountRepository;

        @Autowired
        private CustomerRepository customerRepository;

        @Autowired
        private InventoryService inventoryService;

        @Autowired
        private CustomerService customerService;

        @Autowired
        private CustomerAddressRepository customerAddressRepository;

        @Autowired
        private FofoOrderItemRepository fofoOrderItemRepository;

        @Autowired
        private SolrService commonSolrService;

        @Autowired
        private FofoLineItemRepository fofoLineItemRepository;

        @Autowired
        private ItemRepository itemRepository;

        @Autowired
        private FofoOrderRepository fofoOrderRepository;

        @Autowired
        private CustomerOfferRepository customerOfferRepository;

        @Autowired
        private CustomerOfferItemRepository customerOfferItemRepository;

        @Autowired
        private SamsungUpgradeOfferRepository samsungUpgradeOfferRepository;

        @RequestMapping(value = "/customer/mobileNumber", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
        @ApiImplicitParams({
                        @ApiImplicitParam(name = "Auth-Token", value = "Auth-Token", required = true, dataType = "string", paramType = "header") })
        @Transactional(readOnly = true)
        public ResponseEntity<?> getCustomerByMobileNumber(HttpServletRequest request,
                        @RequestParam(name = ProfitMandiConstants.MOBILE_NUMBER) String mobileNumber)
                        throws ProfitMandiBusinessException {
                CustomCustomer customCustomer = null;
                LOGGER.info("Request Received at url {}", request.getRequestURI());
                try {
                        Customer customer = customerRepository.selectByMobileNumber(mobileNumber);
                        customCustomer = new CustomCustomer();
                        customCustomer.setCustomerId(customer.getId());
                        customCustomer.setEmailId(customer.getEmailId());
                        customCustomer.setFirstName(customer.getFirstName());
                        customCustomer.setLastName(customer.getLastName());
                        customCustomer.setMobileNumber(customer.getMobileNumber());
                        LOGGER.info(customer.getCustomerAddress());
                        List<CustomerAddress> customerAddresses = customer.getCustomerAddress().stream().filter(c -> Boolean.TRUE.equals(c.getActive())).collect(Collectors.toList());
                        LOGGER.info(customerAddresses);
                        if (!customerAddresses.isEmpty()) {
                                List<CustomAddress> customAddresses = new ArrayList<>();
                                for (CustomerAddress customerAddress : customerAddresses) {
                                        customAddresses.add(this.toCustomAddress(customerAddress));
                                }
                                customCustomer.setAddresses(customAddresses);
                        }
                } catch (Exception e) {
                        e.printStackTrace();
                }
                return responseSender.ok(customCustomer);
        }

        private CustomAddress toCustomAddress(CustomerAddress customerAddress) {
                CustomAddress customAddress = new CustomAddress();
                customAddress.setCity(customerAddress.getCity());
                customAddress.setCountry(customerAddress.getCountry());
                customAddress.setLandmark(customerAddress.getLandmark());
                customAddress.setLine1(customerAddress.getLine1());
                customAddress.setLine2(customerAddress.getLine2());
                customAddress.setName(customerAddress.getName());
                customAddress.setLastName(customerAddress.getLastName());
                customAddress.setPhoneNumber(customerAddress.getPhoneNumber());
                customAddress.setPinCode(customerAddress.getPinCode());
                customAddress.setState(customerAddress.getState());
                customAddress.setId(customerAddress.getId());
                customAddress.setDefaultAddress(customerAddress.getDefault());
                return customAddress;
        }

        @RequestMapping(value = "/customer/add", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
        @ApiImplicitParams({
                        @ApiImplicitParam(name = "Auth-Token", value = "Auth-Token", required = true, dataType = "string", paramType = "header") })
        public ResponseEntity<?> addCustomer(HttpServletRequest request, @RequestBody CustomCustomer customCustomer)
                        throws ProfitMandiBusinessException {
                Customer customer = new Customer();
                if (StringUtils.isEmpty(customCustomer.getFirstName())) {
                        throw new ProfitMandiBusinessException("First Name", "Empty", "First Name required");
                }
                customer.setEmailId(customCustomer.getEmailId());
                customer.setFirstName(customCustomer.getFirstName());
                customer.setLastName(customCustomer.getLastName());
                customer.setMobileNumber(customCustomer.getMobileNumber());
                customer = customerService.addCustomer(customer);
                customCustomer.setCustomerId(customer.getId());
                return responseSender.ok(customCustomer);

        }

        @RequestMapping(value = "/customer/address", method = RequestMethod.POST)
        public ResponseEntity<?> addAddress(HttpServletRequest request, @RequestParam int customerId,
                        @RequestBody CustomAddress customAddress) {
                CustomerAddress customerAddress = this.toCustomerAddress(customerId, customAddress);
                customerAddress.setActive(true);
                customerAddressRepository.persist(customerAddress);
                return responseSender.ok(this.toCustomAddress(customerAddress));

        }

        private CustomerAddress toCustomerAddress(int customerId, CustomAddress customAddress) {
                CustomerAddress customerAddress = new CustomerAddress();
                customerAddress.setCustomerId(customerId);
                customerAddress.setName(customAddress.getName());
                customerAddress.setLastName(customAddress.getLastName());
                customerAddress.setLine1(customAddress.getLine1());
                customerAddress.setLine2(customAddress.getLine2());
                customerAddress.setLandmark(customAddress.getLandmark());
                customerAddress.setCity(customAddress.getCity());
                customerAddress.setPinCode(customAddress.getPinCode());
                customerAddress.setState(customAddress.getState());
                customerAddress.setCountry(customAddress.getCountry());
                customerAddress.setPhoneNumber(customAddress.getPhoneNumber());

                return customerAddress;
        }

        @RequestMapping(value = "/customer/order", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
        @ApiImplicitParams({
                        @ApiImplicitParam(name = "Auth-Token", value = "Auth-Token", required = true, dataType = "string", paramType = "header") })
        @Transactional(readOnly = true)
        public ResponseEntity<?> getOrderInvoiceDetail(HttpServletRequest request,
                        @RequestParam(name = "offset") int offset, @RequestParam(name = "limit") int limit) throws Exception {

                int userId = (int) request.getAttribute("userId");
                UserCart uc = userAccountRepository.getUserCart(userId);

                List<CustomerOrderDetail> customerOrderDetails = new ArrayList<>();
                List<FofoOrder> fofoOrders = fofoOrderRepository.selectOrderByFofoId(uc.getUserId(), offset, limit);

                if (fofoOrders.isEmpty()) {
                        return responseSender.ok(customerOrderDetails);
                }

                // Filter out cancelled orders
                List<FofoOrder> activeOrders = fofoOrders.stream()
                                .filter(fo -> fo.getCancelledTimestamp() == null)
                                .collect(Collectors.toList());

                if (activeOrders.isEmpty()) {
                        return responseSender.ok(customerOrderDetails);
                }

                // Batch fetch all order items for all orders at once
                List<Integer> orderIds = activeOrders.stream().map(FofoOrder::getId).collect(Collectors.toList());
                List<FofoOrderItem> allOrderItems = fofoOrderItemRepository.selectByOrderIds(orderIds);
                Map<Integer, List<FofoOrderItem>> orderItemsByOrderId = allOrderItems.stream()
                                .collect(Collectors.groupingBy(FofoOrderItem::getOrderId));

                // Batch fetch all customers
                List<Integer> customerIds = activeOrders.stream().map(FofoOrder::getCustomerId).distinct().collect(Collectors.toList());
                Map<Integer, Customer> customerMap = customerRepository.selectAllByIds(customerIds).stream()
                                .collect(Collectors.toMap(Customer::getId, Function.identity()));

                // Batch fetch all customer addresses
                List<Integer> addressIds = activeOrders.stream().map(FofoOrder::getCustomerAddressId).distinct().collect(Collectors.toList());
                Map<Integer, CustomerAddress> addressMap = customerAddressRepository.selectAllByIds(addressIds).stream()
                                .collect(Collectors.toMap(CustomerAddress::getId, Function.identity()));

                // Batch fetch all items
                Set<Integer> itemIds = allOrderItems.stream().map(FofoOrderItem::getItemId).collect(Collectors.toSet());
                Map<Integer, Item> itemMap = itemRepository.selectByIds(new ArrayList<>(itemIds)).stream()
                                .collect(Collectors.toMap(Item::getId, Function.identity()));

                // Batch fetch all line items
                Set<Integer> orderItemIds = allOrderItems.stream().map(FofoOrderItem::getId).collect(Collectors.toSet());
                List<FofoLineItem> allLineItems = fofoLineItemRepository.selectByFofoOrderItemIds(orderItemIds);
                Map<Integer, List<FofoLineItem>> lineItemsByOrderItemId = allLineItems.stream()
                                .collect(Collectors.groupingBy(FofoLineItem::getFofoOrderItemId));

                // Fetch customer offers once outside the loops
                Map<Integer, List<CustomerOffer>> customerOffersMap = customerOfferRepository.getCustomerOffer(LocalDate.now().atStartOfDay());
                List<CustomerOffer> customerOffers = customerOffersMap.get(uc.getUserId());
                List<Integer> offerIds = (customerOffers != null && !customerOffers.isEmpty())
                                ? customerOffers.stream().map(CustomerOffer::getId).collect(Collectors.toList())
                                : new ArrayList<>();

                // Process orders using pre-fetched data
                for (FofoOrder fo : activeOrders) {
                        List<FofoOrderItem> fofoOrderItems = orderItemsByOrderId.getOrDefault(fo.getId(), new ArrayList<>());
                        Customer customer = customerMap.get(fo.getCustomerId());
                        CustomerAddress customerAddress = addressMap.get(fo.getCustomerAddressId());

                        for (FofoOrderItem foi : fofoOrderItems) {
                                Item item = itemMap.get(foi.getItemId());
                                if (item != null) {
                                        foi.setItemName(item.getItemDescription());
                                }

                                List<FofoLineItem> fofoLineItems = lineItemsByOrderItemId.getOrDefault(foi.getId(), new ArrayList<>());

                                CustomerOrderDetail customerOrderDetail = new CustomerOrderDetail();

                                List<String> serialNumbers = fofoLineItems.stream()
                                                .map(FofoLineItem::getSerialNumber)
                                                .filter(x -> x != null)
                                                .collect(Collectors.toList());

                                customerOrderDetail.setSerialNumber(serialNumbers);

                                if (customerAddress != null) {
                                        customerOrderDetail.setCustomerName(customerAddress.getName());
                                        customerOrderDetail.setCustomerMobile(customerAddress.getPhoneNumber());
                                        customerOrderDetail.setCustomerEmail(customer != null ? customer.getEmailId() : null);
                                        customerOrderDetail.setCustomerCity(customerAddress.getCity());
                                        customerOrderDetail.setCustomerState(customerAddress.getState());
                                }

                                if (item != null) {
                                        customerOrderDetail.setBrand(item.getBrand());
                                        customerOrderDetail.setColor(item.getColor());
                                        customerOrderDetail.setModelName(item.getModelName());
                                        customerOrderDetail.setModelNumber(item.getModelNumber());
                                }
                                customerOrderDetail.setFofoOrderItemId(foi.getId());
                                customerOrderDetail.setFofoOrderId(foi.getOrderId());
                                customerOrderDetail.setItemId(foi.getItemId());
                                customerOrderDetail.setQuantity(foi.getQuantity());
                                customerOrderDetail.setTotalPrice(foi.getSellingPrice());
                                customerOrderDetail.setCreatedTimeStamp(foi.getCreateTimestamp());
                                customerOrderDetail.setInvoiceNumber(fo.getInvoiceNumber());
                                customerOrderDetail.setCancelledTimestamp(fo.getCancelledTimestamp());
                                customerOrderDetail.setInsurance(false);

                                if (!serialNumbers.isEmpty() && item != null) {
                                        if ("85171300".equals(item.getHsnCode())) {
                                                customerOrderDetail.setInsurance(true);
                                        }
                                }

                                long offerCount = 0;
                                if (!offerIds.isEmpty() && item != null) {
                                        List<CustomerOfferItem> customerOfferItems = customerOfferItemRepository
                                                        .selectByOfferIds(offerIds, item.getCatalogItemId(), LocalDate.now());
                                        offerCount = customerOfferItems.size();
                                }

                                customerOrderDetail.setOfferCount(offerCount);
                                customerOrderDetails.add(customerOrderDetail);
                        }
                }

                return responseSender.ok(customerOrderDetails);
        }

}