Subversion Repositories SmartDukaan

Rev

Rev 24785 | Go to most recent revision | View as "text/plain" | Blame | Compare with Previous | Last modification | View Log | RSS feed

package com.smartdukaan.cron.scheduled;

import java.text.Normalizer.Form;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.logging.SimpleFormatter;
import java.util.stream.Collectors;

import org.apache.commons.io.output.ByteArrayOutputStream;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;

import com.spice.profitmandi.common.util.FileUtil;
import com.spice.profitmandi.common.util.FormattingUtils;
import com.spice.profitmandi.common.util.Utils;
import com.spice.profitmandi.dao.entity.transaction.Order;
import com.spice.profitmandi.dao.entity.transaction.ReturnOrder;
import com.spice.profitmandi.dao.entity.transaction.UserWallet;
import com.spice.profitmandi.dao.entity.transaction.UserWalletHistory;
import com.spice.profitmandi.dao.repository.dtr.FofoStoreRepository;
import com.spice.profitmandi.dao.repository.transaction.OrderRepository;
import com.spice.profitmandi.dao.repository.transaction.ReturnOrderRepository;
import com.spice.profitmandi.dao.repository.transaction.UserWalletHistoryRepository;
import com.spice.profitmandi.dao.repository.transaction.UserWalletRepository;
import com.spice.profitmandi.service.user.RetailerService;

import in.shop2020.model.v1.order.OrderStatus;
import in.shop2020.model.v1.order.WalletReferenceType;

@Component
public class Reconciliation {
        @Autowired
        private FofoStoreRepository fofoStoreRepository;
        @Autowired
        private UserWalletRepository userWalletRepository;
        @Autowired
        private UserWalletHistoryRepository userWalletHistoryRepository;
        @Autowired
        private RetailerService retailerService;
        @Autowired
        private ReturnOrderRepository returnOrderRepository;
        @Autowired
        private OrderRepository orderRepository;
        @Autowired
        private JavaMailSender mailSender;

        public void dailyReconciliation() throws Exception {
                boolean reconciled = true;
                Map<Integer, String> stores = fofoStoreRepository.getStoresMap();
                List<List<?>> rows = new ArrayList<>();
                LocalDate yesterday = LocalDate.now().minusDays(1);
                Map<Integer, String> retailerNameMap = retailerService
                                .getAllFofoRetailerIdNameMap(new ArrayList<>(stores.keySet()));
                for (int partnerId : stores.keySet()) {
                        UserWallet uw = userWalletRepository.selectByRetailerId(partnerId);
                        List<UserWalletHistory> walletHistory = userWalletHistoryRepository.selectByWalletIdAndDate(uw.getId(),
                                        yesterday);
                        Map<LocalDate, List<UserWalletHistory>> dateWiseWalletHistory = walletHistory.stream()
                                        .collect(Collectors.groupingBy(x -> x.getTimestamp().toLocalDate(), Collectors.toList()));
                        for (Map.Entry<LocalDate, List<UserWalletHistory>> entry : dateWiseWalletHistory.entrySet()) {
                                LocalDate dateToReconcile = entry.getKey();
                                List<UserWalletHistory> history = entry.getValue();
                                List<?> reconciliation = reconcileOrdersAndWallet(uw.getUserId(), retailerNameMap.get(partnerId), dateToReconcile,history);
                                reconciled = reconciled || (boolean)reconciliation.remove(0);
                                rows.add(reconciliation);
                        }
                }
                ByteArrayOutputStream baos = FileUtil.getCSVByteStream(Arrays.asList("Store Code", "Date",
                                "Wallet amount consumed", "Ordered Total", "Cancelled Total", "Refunded Total"), rows);

                Utils.sendMailWithAttachment(mailSender, new String[] { "amit.gupta@shop2020.in" }, new String[] {}, 
                                reconciled ? "Reconciled Successfully": "Reconciliation failed",
                                "Report attached", String.format("reconciliation-%s.csv", FormattingUtils.formatDate(yesterday.atStartOfDay())), new ByteArrayResource(baos.toByteArray()));
        }

        private List<?> reconcileOrdersAndWallet(int fofoId, String storeName, LocalDate localDate, List<UserWalletHistory> history)
                        throws Exception {
                Map<Integer, Integer> transactionsOnThatDate = history.stream()
                                .filter(x -> x.getReferenceType().equals(WalletReferenceType.PURCHASE))
                                .collect(Collectors.groupingBy(x -> x.getReference(), Collectors.summingInt(x -> x.getAmount())));

                int totalWalletConsumed = 0;
                float cancelledAmount = 0;
                float returnedAmount = 0;
                float totalDeductedAmount = 0;
                for (int transactionId : transactionsOnThatDate.keySet()) {
                        List<Order> orders = orderRepository.selectAllByTransactionId(transactionId);
                        for (Order o : orders) {
                                if (o.getCreateTimestamp().toLocalDate().equals(localDate)) {
                                        if (Arrays.asList(OrderStatus.PAYMENT_PENDING, OrderStatus.PAYMENT_FAILED)
                                                        .contains(o.getStatus())) {
                                                cancelledAmount += o.getWalletAmount();
                                        } else if (o.getRefundTimestamp() != null
                                                        && o.getRefundTimestamp().toLocalDate().equals(localDate)) {
                                                ReturnOrder returnedOrder = returnOrderRepository.selectByOrderId(o.getId());
                                                if (returnedOrder == null) {
                                                        cancelledAmount += o.getWalletAmount();
                                                } else {
                                                        returnedAmount += returnedOrder.getTotalPrice();
                                                }
                                        }
                                        totalDeductedAmount += o.getWalletAmount();

                                } else if (o.getRefundTimestamp() != null && o.getRefundTimestamp().toLocalDate().equals(localDate)) {
                                        ReturnOrder returnedOrder = returnOrderRepository.selectByOrderId(o.getId());
                                        if (returnedOrder == null) {
                                                cancelledAmount += o.getWalletAmount();
                                        } else {
                                                returnedAmount += returnedOrder.getTotalPrice();
                                        }
                                }
                        }
                        totalWalletConsumed -= transactionsOnThatDate.get(transactionId);
                        
                }
                boolean reconciled = Math.abs(totalWalletConsumed - (totalDeductedAmount-cancelledAmount - returnedAmount) ) < 2;

                return Arrays.asList(reconciled, localDate, storeName, totalWalletConsumed, totalDeductedAmount, cancelledAmount, returnedAmount);

        }

        private void reconcileDailySchemeIn() {

        }

        private void reconcileDailySchemeOut() {

        }
}