Subversion Repositories SmartDukaan

Rev

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

package com.smartdukaan.cron.scheduled;

import com.google.common.collect.Lists;
import com.google.gson.Gson;
import com.razorpay.Payment;
import com.smartdukaan.cron.itelImeiActivation.ItelImeiActivationService;
import com.smartdukaan.cron.itelImeiActivation.TecnoImeiActivation;
import com.spice.profitmandi.common.enumuration.MessageType;
import com.spice.profitmandi.common.enumuration.RechargeStatus;
import com.spice.profitmandi.common.enumuration.ReporticoProject;
import com.spice.profitmandi.common.exception.ProfitMandiBusinessException;
import com.spice.profitmandi.common.model.*;
import com.spice.profitmandi.common.services.ReporticoService;
import com.spice.profitmandi.common.services.mandii.AccountStatusResponseOut;
import com.spice.profitmandi.common.services.mandii.EligibilityStatusEnum;
import com.spice.profitmandi.common.services.mandii.MandiiService;
import com.spice.profitmandi.common.util.FileUtil;
import com.spice.profitmandi.common.util.FormattingUtils;
import com.spice.profitmandi.common.util.PdfUtils;
import com.spice.profitmandi.common.util.Utils;
import com.spice.profitmandi.common.util.Utils.Attachment;
import com.spice.profitmandi.common.web.client.RestClient;
import com.spice.profitmandi.dao.Interface.Campaign;
import com.spice.profitmandi.dao.entity.auth.AuthUser;
import com.spice.profitmandi.dao.entity.catalog.FocusedModel;
import com.spice.profitmandi.dao.entity.catalog.Item;
import com.spice.profitmandi.dao.entity.catalog.Scheme;
import com.spice.profitmandi.dao.entity.cs.Position;
import com.spice.profitmandi.dao.entity.cs.Ticket;
import com.spice.profitmandi.dao.entity.dtr.User;
import com.spice.profitmandi.dao.entity.dtr.*;
import com.spice.profitmandi.dao.entity.fofo.*;
import com.spice.profitmandi.dao.entity.inventory.SaholicCIS;
import com.spice.profitmandi.dao.entity.inventory.SaholicPOItem;
import com.spice.profitmandi.dao.entity.transaction.*;
import com.spice.profitmandi.dao.entity.user.*;
import com.spice.profitmandi.dao.enumuration.catalog.SchemeType;
import com.spice.profitmandi.dao.enumuration.cs.EscalationType;
import com.spice.profitmandi.dao.enumuration.dtr.RefferalStatus;
import com.spice.profitmandi.dao.enumuration.fofo.Gateway;
import com.spice.profitmandi.dao.enumuration.fofo.ScanType;
import com.spice.profitmandi.dao.enumuration.transaction.PriceDropImeiStatus;
import com.spice.profitmandi.dao.model.SimpleCampaign;
import com.spice.profitmandi.dao.model.SimpleCampaignParams;
import com.spice.profitmandi.dao.repository.auth.AuthRepository;
import com.spice.profitmandi.dao.repository.catalog.*;
import com.spice.profitmandi.dao.repository.cs.*;
import com.spice.profitmandi.dao.repository.dtr.*;
import com.spice.profitmandi.dao.repository.fofo.*;
import com.spice.profitmandi.dao.repository.inventory.StateRepository;
import com.spice.profitmandi.dao.repository.inventory.WarehouseRepository;
import com.spice.profitmandi.dao.repository.transaction.*;
import com.spice.profitmandi.dao.repository.user.AddressRepository;
import com.spice.profitmandi.dao.repository.user.UserRepository;
import com.spice.profitmandi.service.NotificationService;
import com.spice.profitmandi.service.PartnerInvestmentService;
import com.spice.profitmandi.service.integrations.RazorpayPaymentService;
import com.spice.profitmandi.service.integrations.toffee.ToffeeService;
import com.spice.profitmandi.service.inventory.InventoryService;
import com.spice.profitmandi.service.inventory.SaholicInventoryService;
import com.spice.profitmandi.service.order.OrderService;
import com.spice.profitmandi.service.pricing.PriceDropService;
import com.spice.profitmandi.service.recharge.provider.OxigenRechargeProviderService;
import com.spice.profitmandi.service.recharge.provider.ThinkWalnutDigitalRechargeProviderService;
import com.spice.profitmandi.service.scheme.SchemeService;
import com.spice.profitmandi.service.serviceConfig.ServiceConfigService;
import com.spice.profitmandi.service.transaction.TransactionService;
import com.spice.profitmandi.service.user.RetailerService;
import com.spice.profitmandi.service.wallet.WalletService;
import in.shop2020.model.v1.order.OrderStatus;
import in.shop2020.model.v1.order.WalletReferenceType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.commons.lang.StringUtils;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.InputStreamSource;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.mail.MessagingException;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.io.IOException;
import java.io.Serializable;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.sql.Timestamp;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoField;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;

@Component
@Transactional(rollbackFor = Throwable.class)
public class ScheduledTasks {

        @Value("${oxigen.recharge.transaction.url}")
        private String oxigenRechargeTransactionUrl;

        @Value("${oxigen.recharge.enquiry.url}")
        private String oxigenRechargeEnquiryUrl;

        @Autowired
        private RegionRepository regionRepository;

        @Autowired
        private ServiceConfigService serviceConfigService;

        @Autowired
        private TecnoImeiActivation tecnoImeiActivation;

        private static final DateTimeFormatter leadTimeFormatter = DateTimeFormatter.ofPattern("d LLL, hh:mm a");

        @Autowired
        private PartnerRegionRepository partnerRegionRepository;

        @Autowired
        private EmployeeAttendanceRepository employeeAttendanceRepository;

        @Autowired
        VivoImeiActivationService vivoImeiActivationService;

        @Autowired
        ItelImeiActivationService itelImeiActivationService;

        @Autowired
        private PartnerTypeChangeService partnerTypeChangeService;

        @Autowired
        private ActivatedImeiRepository activatedImeiRepository;

        @Autowired
        private LineItemRepository lineItemRepository;

        @Autowired
        private LeadRepository leadRepository;

        @Autowired
        private AuthRepository authRepository;

        @Autowired
        private PriceDropService priceDropService;

        @Autowired
        private FranchiseeVisitRepository franchiseeVisitRepository;

        @Autowired
        private FranchiseeActivityRepository franchiseeActivityRepository;

        @Autowired
        private HdfcPaymentRepository hdfcPaymentRepository;

        @Autowired
        private CsService csService;

        @Autowired
        private SaholicInventoryService saholicInventoryService;

        @Autowired
        private InsurancePolicyRepository insurancePolicyRepository;

        @Autowired
        private ToffeeService toffeeService;

        @Value("${oxigen.recharge.auth.key}")
        private String oxigenRechargeAuthKey;

        @Value("${oxigen.recharge.validation.url}")
        private String oxigenRechargeValidationUrl;

        @Value("${oxigen.recharge.validation.auth.key}")
        private String oxigenRechargeValidationAuthKey;

        @Value("${think.walnut.digital.recharge.transaction.mobile.url}")
        private String thinkWalnutDigitalRechargeTransactionMobileUrl;

        @Value("${think.walnut.digital.recharge.transaction.dth.url}")
        private String thinkWalnutDigitalRechargeTransactionDthUrl;

        @Value("${think.walnut.digital.recharge.enquiry.url}")
        private String thinkWalnutDigitalRechargeEnquiryUrl;

        @Value("${think.walnut.digital.recharge.balance.url}")
        private String thinkWalnutDigitalRechargeBalanceUrl;

        @Value("${think.walnut.digital.recharge.username}")
        private String thinkWalnutDigitalRechargeUserName;

        @Value("${think.walnut.digital.recharge.password}")
        private String thinkWalnutDigitalRechargePassword;

        @Value("${think.walnut.digital.recharge.auth.key}")
        private String thinkWalnutDigitalRechargeAuthKey;

        @Autowired
        private PurchaseRepository purchaseRepository;

        @Autowired
        private PriceDropIMEIRepository priceDropIMEIRepository;

        @Autowired
        PriceDropRepository priceDropRepository;

        @Autowired
        private PartnerTypeChangeRepository partnerTypeChangeRepository;

        @Autowired
        private SchemeService schemeService;

        @Autowired
        private ServiceConfigRepository serviceConfigRepository;

        @Value("${delhivery.tracking.token}")
        private String token;

        private static final String[] STOCK_AGEING_MAIL_LIST = new String[] { "uday.singh@smartudkaan.com",
                        "mohinder.mutreja@smartdukaan.com", "ankit.bhatia@smartdukaan.com", "tarun.verma@smartdukaan.com",
                        "kuldeep.kumar@smartdukaan.com", "manish.gupta@smartdukaan.com" };

        private static final String[] ITEMWISE_PENDING_INDENT_MAIL_LIST = new String[] { "kamini.sharma@smartdukaan.com",
                        "tarun.verma@smartdukaan.com", "uday.singh@smartdukaan.com", "kuldeep.kumar@smartdukaan.com",
                        "niranjan.kala@smartdukaan.com" };

        private static final String[] INDENT_TERTIARY_MAIL_LIST = new String[] { "uday.singh@smartdukaan.com",
                        "kuldeep.kumar@smartdukaan.com" };

        private static final String[] EMPLOYEE_ATTENDANCE_MAIL_LIST = new String[] { "jyoti.rawat@smartdukaan.com",
                        "sm@smartdukaan.com" };

        private List<OrderStatus> orderStatusList = Arrays.asList(OrderStatus.SUBMITTED_FOR_PROCESSING);

        @Autowired
        private ReporticoService reporticoService;

        @Autowired
        private PartnerInvestmentService partnerInvestmentService;

        @Autowired
        private PositionRepository positionRepository;

        @Autowired
        private FofoOrderItemRepository fofoOrderItemRepository;

        @Autowired
        private NotificationService notificationService;

        @Autowired
        private PartnerDailyInvestmentRepository partnerDailyInvestmentRepository;

        @Autowired
        private SchemeInOutRepository schemeInOutRepository;

        @Autowired
        private RechargeTransactionRepository rechargeTransactionRepository;

        @Autowired
        private CustomerAddressRepository customerAddressRepository;

        @Autowired
        private RechargeProviderCreditWalletHistoryRepository rechargeProviderCreditWalletHistoryRepository;

        @Autowired
        private FofoLineItemRepository fofoLineItemRepository;

        @Autowired
        private FofoOrderRepository fofoOrderRepository;

        @Autowired
        private UserWalletHistoryRepository userWalletHistoryRepository;

        @Autowired
        private UserWalletRepository userWalletRepository;

        @Autowired
        private InventoryItemRepository inventoryItemRepository;

        @Autowired
        private WalletService walletService;

        @Autowired
        private ThinkWalnutDigitalRechargeProviderService thinkWalnutDigitalRechargeProviderService;

        @Autowired
        private OxigenRechargeProviderService oxigenRechargeProviderService;

        @Autowired
        private RechargeProviderRepository rechargeProviderRepository;

        @Autowired
        private ScanRecordRepository scanRecordRepository;

        @Autowired
        private DailyRechargeRepository dailyRechargeRepository;

        @Autowired
        private FofoStoreRepository fofoStoreRepository;

        @Value("${prod}")
        private boolean prod;

        @Autowired
        private StateGstRateRepository stateGstRateRepository;

        @Autowired
        private RetailerService retailerService;

        @Autowired
        private TransactionService transactionService;

        @Autowired
        private ItemRepository itemRepository;

        @Autowired
        private OrderRepository orderRepository;

        @Autowired
        private OrderService orderService;

        @Autowired
        private SchemeRepository schemeRepository;

        @Autowired
        private JavaMailSender mailSender;

        @Autowired
        private PartnerTargetRepository partnerTargetRepository;

        @Autowired
        @Qualifier(value = "googleMailSender")
        private JavaMailSender googleMailSender;

        @Autowired
        private InventoryService inventoryService;

        @Autowired
        private AddressRepository addressRepository;

        @Autowired
        private RetailerRegisteredAddressRepository retailerRegisteredAddressRepository;

        @Autowired
        private Mongo mongoClient;

        @Autowired
        private DeviceRepository deviceRepository;

        @Autowired
        private PushNotificationRepository pushNotificationRepository;

        @Autowired
        private NotificationCampaignRepository notificationCampaignRepository;

        @Autowired
        private CurrentInventorySnapshotRepository currentInventorySnapshotRepository;

        @Autowired
        private FocusedModelRepository focusedModelRepository;

        @Autowired
        private UserAccountRepository userAccountRepository;

        @Autowired
        private UserRepository userUserRepository;

        @Autowired
        private com.spice.profitmandi.dao.repository.dtr.UserRepository dtrUserRepository;

        @Autowired
        private UserCampaignRepository userCampaignRepository;

        @Autowired
        private Gson gson;

        @Autowired
        private TicketRepository ticketRepository;

        @Autowired
        private RefferalRepository refferalRepository;

        @Autowired
        private PartnerProblemRepository partnerProblemRepository;

        @Autowired
        private PendingOrderRepository pendingOrderRepository;

        @Autowired
        private PendingOrderItemRepository pendingOrderItemRepository;

        @Value("${razorpay.account.keyId}")
        private String keyId;

        @Value("${razorpay.account.keySecret}")
        private String keySecret;

        @Autowired
        private RazorpayPaymentService razorPaymentService;

        @Autowired
        private RazorPayRepository razorPayRepository;

        @Autowired
        private PendingOrderService pendingOrderService;

        @Autowired
        private CustomerRepository customerRepository;

        @Autowired
        private RestClient restClient;

        @Autowired
        private MandiiService mandiiService;

        @Autowired
        CreditAccountRepository creditAccountRepository;
        private static final Logger LOGGER = LogManager.getLogger(ScheduledTasks.class);

        private String FCM_URL = "https://fcm.googleapis.com/fcm/send";
        private String FCM_API_KEY = "AAAASAjNcn4:APA91bG6fWRIgYJI0L9gCjP5ynaXz2hJHYKtD9dfH7Depdv31Nd9APJwhx-OPkAJ1WSz4BGNYG8lHThLFSjDGFxIwUZv241YcAJEGDLgt86mxq9FXJe-yBRu-S0_ZwHqmX-QaVKl5F_A";

        public void generateDailyRecharge() {
                List<RechargeProviderCreditWalletHistory> allCreditHistory = rechargeProviderCreditWalletHistoryRepository
                                .selectAll(0, 2000);
                List<RechargeProvider> rechargeProviders = rechargeProviderRepository.selectAll();
                rechargeProviders.stream().forEach(x -> x.setAmount(0));

                rechargeProviders.stream().forEach(x -> {
                        Map<LocalDate, List<RechargeProviderCreditWalletHistory>> dateWiseProviderCreditsMap = allCreditHistory
                                        .stream().filter(z -> z.getProviderId() == x.getId())
                                        .collect(Collectors.groupingBy(x1 -> x1.getReceiveTimestamp().toLocalDate()));

                        LOGGER.info("dateWiseProviderCreditsMap -{}", dateWiseProviderCreditsMap);
                        LocalDate endDate = LocalDate.now().plusDays(1);
                        float previousDayClosing = 0;
                        LocalDate date = LocalDate.of(2018, 4, 6);
                        while (date.isBefore(endDate)) {
                                List<RechargeTransaction> dateWiseRechargeTransactions = rechargeTransactionRepository
                                                .selectAllBetweenTimestamp(Arrays.asList(RechargeStatus.values()), date.atStartOfDay(),
                                                                date.plusDays(1).atStartOfDay());

                                List<RechargeTransaction> successfulTransactions = dateWiseRechargeTransactions.stream()
                                                .filter(y -> y.getStatus().equals(RechargeStatus.SUCCESS)).collect(Collectors.toList());

                                float dailyAmount = 0;
                                float totalCommission = 0;
                                for (RechargeTransaction rechargeTransaction : successfulTransactions) {
                                        if (rechargeTransaction.getProviderId() == x.getId()) {
                                                dailyAmount += rechargeTransaction.getAmount();
                                                totalCommission += rechargeTransaction.getCommission();
                                        }
                                }

                                List<RechargeProviderCreditWalletHistory> rechargeHistoryList = dateWiseProviderCreditsMap.get(date);
                                float dailyWalletRecharge = 0;
                                if (rechargeHistoryList != null) {
                                        for (RechargeProviderCreditWalletHistory rechargeProviderCreditWalletHistory : rechargeHistoryList) {
                                                if (rechargeProviderCreditWalletHistory.getProviderId() == x.getId()) {
                                                        dailyWalletRecharge += rechargeProviderCreditWalletHistory.getAmount();
                                                }
                                        }
                                }
                                if (dailyAmount > 0 || dailyWalletRecharge > 0) {
                                        DailyRecharge dailyRecharge = null;
                                        try {
                                                dailyRecharge = dailyRechargeRepository.selectByProviderIdAndCreateDate(x.getId(), date);
                                        } catch (Exception e) {
                                                LOGGER.info("Could not find Recharge entry");
                                        }
                                        if (dailyRecharge == null) {
                                                dailyRecharge = new DailyRecharge();
                                                dailyRecharge.setCreateDate(date);
                                        }
                                        dailyRecharge.setOpeningBalance(previousDayClosing);
                                        dailyRecharge.setProviderId(x.getId());
                                        dailyRecharge.setWalletRechargeAmount(dailyWalletRecharge);
                                        dailyRecharge.setTotalAmount(dailyAmount);
                                        dailyRecharge.setTotalCommission(totalCommission);
                                        float closingBalance = dailyRecharge.getOpeningBalance() + dailyWalletRecharge - dailyAmount;
                                        dailyRecharge.setClosingBalance(closingBalance);
                                        dailyRechargeRepository.persist(dailyRecharge);
                                        x.setAmount(x.getAmount() + dailyRecharge.getClosingBalance() - dailyRecharge.getOpeningBalance());
                                        previousDayClosing = dailyRecharge.getClosingBalance();
                                }
                                date = date.plusDays(1);
                        }
                        rechargeProviderRepository.persist(x);
                });
                LOGGER.info("finished generating daily recharge");
        }

        public void reconcileRecharge() throws Exception {
                LocalDateTime fromDate = LocalDateTime.now().truncatedTo(ChronoUnit.DAYS).minusDays(30);
                LocalDateTime toDate = LocalDateTime.now().truncatedTo(ChronoUnit.DAYS);
                List<RechargeStatus> nonSuccessRechargeStatuses = new ArrayList<>(Arrays.asList(RechargeStatus.values()));
                LOGGER.info("nonSuccessRechargeStatuses {} ", nonSuccessRechargeStatuses);
                nonSuccessRechargeStatuses.remove(RechargeStatus.SUCCESS);
                nonSuccessRechargeStatuses.remove(RechargeStatus.FAILED);
                RechargeCredential thinkWalnutDigitalRechargeEnquiryCredential = new RechargeCredential();
                thinkWalnutDigitalRechargeEnquiryCredential.setRechargeUrl(thinkWalnutDigitalRechargeEnquiryUrl);
                thinkWalnutDigitalRechargeEnquiryCredential.setRechargeUserName(thinkWalnutDigitalRechargeUserName);
                thinkWalnutDigitalRechargeEnquiryCredential.setRechargePassword(thinkWalnutDigitalRechargePassword);
                thinkWalnutDigitalRechargeEnquiryCredential.setRechargeAuthKey(thinkWalnutDigitalRechargeAuthKey);
                Map<String, RechargeStatus> requestRechargeStatusChanged = new HashMap<>();
                List<RechargeTransaction> rechargeTransactions = rechargeTransactionRepository
                                .selectAllBetweenTimestamp(nonSuccessRechargeStatuses, fromDate, toDate);
                for (RechargeTransaction rechargeTransaction : rechargeTransactions) {
                        try {
                                int providerId = rechargeTransaction.getProviderId();
                                if (providerId == 1) {
                                        oxigenRechargeProviderService.doCheckStatusRequest(oxigenRechargeEnquiryUrl, oxigenRechargeAuthKey,
                                                        rechargeTransaction);
                                } else if (providerId == 2) {
                                        thinkWalnutDigitalRechargeProviderService
                                                        .doCheckStatusRequest(thinkWalnutDigitalRechargeEnquiryCredential, rechargeTransaction);
                                }
                                if (rechargeTransaction.getStatus().equals(RechargeStatus.SUCCESS)
                                                || rechargeTransaction.getStatus().equals(RechargeStatus.FAILED)) {
                                        requestRechargeStatusChanged.put(rechargeTransaction.getRequestId(),
                                                        rechargeTransaction.getStatus());
                                }
                        } catch (Exception e) {
                                LOGGER.info("Could not check status for Request {}", rechargeTransaction.getRequestId());
                        }
                }
                LOGGER.info("Reconcile recharge ran successfully");
        }

        public void processActivation() throws Exception {
                schemeService.processActivation();
        }

        // TemporaryMethod
        public void migrateInvoice() {
                List<FofoOrder> fofoOrders = fofoOrderRepository.selectFromSaleDate(LocalDateTime.now().minusDays(3));
                Map<Integer, List<FofoOrder>> partnerOrdersMap = new HashMap<>();
                partnerOrdersMap = fofoOrders.stream()
                                .collect(Collectors.groupingBy(FofoOrder::getFofoId, Collectors.toList()));
                for (List<FofoOrder> orderList : partnerOrdersMap.values()) {
                        int sequence = 0;
                        String prefix = "";
                        List<FofoOrder> sortedList = orderList.stream().sorted((x1, x2) -> x1.getId() - x2.getId())
                                        .collect(Collectors.toList());
                        for (FofoOrder order : sortedList) {

                                LOGGER.info("Order Id is {}, partner Id is {}", order.getId(), order.getFofoId());
                                if (!order.getInvoiceNumber().contains("SEC")) {
                                        sequence = Integer.parseInt(order.getInvoiceNumber().split("/")[1]);
                                        prefix = order.getInvoiceNumber().split("/")[0];
                                } else {
                                        sequence += 1;
                                        String invoiceNumber = prefix + "/" + sequence;
                                        order.setInvoiceNumber(invoiceNumber);
                                        fofoOrderRepository.persist(order);
                                }
                        }

                }
        }

        // Temporary Method
        public void evaluateExcessSchemeOut() throws Exception {
                Map<Integer, String> userNameMap = retailerService.getAllFofoRetailerIdNameMap();
                Map<Integer, Float> userAmountMap = new HashMap<>();

                List<List<?>> rows = new ArrayList<>();
                List<String> headers = Arrays.asList("Scheme", "Item", "Partner", "Amount", "Credited On", "Invoice Number",
                                "Sale On", "Scheme Start", "Scheme End", "Active On", "Expired On");
                schemeRepository.selectAll().stream().forEach(x -> {
                        if (x.getType().equals(SchemeType.OUT)) {
                                List<SchemeInOut> sioList = schemeInOutRepository
                                                .selectBySchemeIds(new HashSet<>(Arrays.asList(x.getId())));
                                if (x.getActiveTimestamp() != null) {
                                        LocalDateTime endDateTime = x.getEndDateTime();
                                        if (x.getExpireTimestamp() != null && x.getExpireTimestamp().isBefore(x.getEndDateTime())) {
                                                endDateTime = x.getExpireTimestamp();
                                        }
                                        for (SchemeInOut sio : sioList) {
                                                InventoryItem inventoryItem = null;
                                                inventoryItem = inventoryItemRepository.selectById(sio.getInventoryItemId());
                                                FofoOrder fofoOrder = fofoOrderRepository.selectByFofoIdAndSerialNumber(
                                                                inventoryItem.getFofoId(), inventoryItem.getSerialNumber(), null, null, 0, 1).get(0);
                                                Optional<ScanRecord> record = scanRecordRepository
                                                                .selectByInventoryItemId(sio.getInventoryItemId()).stream()
                                                                .filter(y -> y.getType().equals(ScanType.SALE)).findFirst();
                                                if (record.isPresent()) {
                                                        int fofoId = record.get().getFofoId();
                                                        if (record.get().getCreateTimestamp().isAfter(endDateTime)
                                                                        || record.get().getCreateTimestamp().isBefore(x.getStartDateTime())) {
                                                                if (!userAmountMap.containsKey(fofoId)) {
                                                                        userAmountMap.put(fofoId, 0f);
                                                                }
                                                                userAmountMap.put(fofoId, sio.getAmount() + userAmountMap.get(fofoId));
                                                                try {
                                                                        rows.add(Arrays.asList(x.getDescription(),
                                                                                        itemRepository.selectById(inventoryItem.getItemId()).getItemDescription(),
                                                                                        userNameMap.get(fofoId), sio.getAmount(),
                                                                                        FormattingUtils.formatDate(sio.getCreateTimestamp()),
                                                                                        fofoOrder.getInvoiceNumber(),
                                                                                        FormattingUtils.formatDate(record.get().getCreateTimestamp()),
                                                                                        FormattingUtils.formatDate(x.getStartDateTime()),
                                                                                        FormattingUtils.formatDate(x.getEndDateTime()),
                                                                                        FormattingUtils.formatDate(x.getActiveTimestamp()),
                                                                                        FormattingUtils.formatDate(x.getExpireTimestamp())));
                                                                } catch (Exception e) {
                                                                        e.printStackTrace();
                                                                }
                                                        }
                                                }
                                        }
                                }
                        }
                });
                userAmountMap.entrySet().stream()
                                .forEach(x -> LOGGER.info("{} to be deducted from {}({}) for wrongly disbursed due to technical error.",
                                                x.getValue(), userNameMap.get(x.getKey())));

                ByteArrayOutputStream baos = FileUtil.getCSVByteStream(headers, rows);
                Utils.sendMailWithAttachment(googleMailSender,
                                new String[] { "amit.gupta@shop2020.in", "adeel.yazdani@smartdukaan.com" }, null,
                                "Partner Excess Amount", "PFA", "ListofSchemes.csv", new ByteArrayResource(baos.toByteArray()));

        }

        public void processScheme(int offset, boolean dryRun) throws Exception {
                LocalDateTime startDate = LocalDateTime.of(LocalDate.now(), LocalTime.MIDNIGHT).minusDays(offset);
                LocalDateTime endDate = startDate.plusDays(30);
                processScheme(startDate, endDate, dryRun);
        }

        public void processSchemeOut(List<String> invoiceNumbers) throws Exception {
                for (String invoiceNumber : invoiceNumbers) {
                        System.out.println("Invoice Number - " + invoiceNumber);
                        FofoOrder fofoOrder = fofoOrderRepository.selectByInvoiceNumber(invoiceNumber);
                        schemeService.processSchemeOut(fofoOrder.getId(), fofoOrder.getFofoId());
                }
        }

        public void processSchemeIn(List<String> invoiceNumbers) throws Exception {
                for (String invoiceNumber : invoiceNumbers) {
                        System.out.println("Invoice Number - " + invoiceNumber);
                        Purchase purchase = purchaseRepository.selectByPurchaseReference(invoiceNumber);
                        schemeService.processSchemeIn(purchase.getId(), purchase.getFofoId());
                }
        }

        public void processScheme(int offset, int durationDays, boolean dryRun) throws Exception {
                LocalDateTime startDate = LocalDateTime.of(LocalDate.now(), LocalTime.MIDNIGHT).minusDays(offset);
                LocalDateTime endDate = startDate.plusDays(durationDays);
                processScheme(startDate, endDate, dryRun);
        }

        public void processScheme(boolean dryRun) throws Exception {
                LocalDateTime fromDate = LocalDateTime.now().minusDays(30);
                processScheme(fromDate, LocalDateTime.now(), dryRun);
        }

        public void processScheme(LocalDateTime startDate, LocalDateTime endDate, boolean dryRun) throws Exception {
                LOGGER.info("Started execution at {}", LocalDateTime.now());
                System.out.println(
                                "InventoryId\tSerialNumber\tItem Id\tScheme Id\tScheme Name\tScheme Type\tAmount Type\tDP\tTaxable\tScheme Amount\tAmount Paid");
                try {
                        List<Purchase> purchases = purchaseRepository.selectAllBetweenPurchaseDate(startDate, endDate);
                        for (Purchase purchase : purchases) {
                                schemeService.processSchemeIn(purchase.getId(), purchase.getFofoId());
                        }

                        List<FofoOrder> fofoOrders = fofoOrderRepository.selectBetweenSaleDate(startDate, endDate);
                        for (FofoOrder fofoOrder : fofoOrders) {
                                schemeService.processSchemeOut(fofoOrder.getId(), fofoOrder.getFofoId());
                        }
                } catch (Exception e) {
                        e.printStackTrace();
                        throw e;
                }
                List<UserWalletHistory> uwhs = userWalletHistoryRepository.selectAllByDateType(LocalDate.now().atStartOfDay(),
                                endDate, Arrays.asList(WalletReferenceType.SCHEME_IN, WalletReferenceType.SCHEME_OUT));
                System.out.println("Amount\tReference\tReferenceType\tTimestamp\tDescription");
                for (UserWalletHistory uwh : uwhs) {
                        System.out.println(String.format("%d\t%d\t%s\t%s\t%s", uwh.getAmount(), uwh.getReference(),
                                        uwh.getReferenceType(), uwh.getTimestamp().toString(), uwh.getDescription()));
                }
                LOGGER.info("Schemes process successfully.");
                if (dryRun) {
                        throw new Exception();
                }
        }

        public void processRechargeCashback() throws Throwable {
                LocalDateTime cashbackTime = LocalDateTime.now();
                int referenceId = (int) Timestamp.valueOf(cashbackTime).getTime() / 1000;
                List<RechargeTransaction> pendingTransactions = rechargeTransactionRepository
                                .getPendingCashBackRehargeTransactions();
                Map<Object, Double> totalRetailerCashbacks = pendingTransactions.stream().collect(
                                Collectors.groupingBy(x -> x.getRetailerId(), Collectors.summingDouble(x -> x.getCommission())));
                for (Map.Entry<Object, Double> totalRetailerCashback : totalRetailerCashbacks.entrySet()) {
                        int retailerId = (Integer) totalRetailerCashback.getKey();
                        float amount = totalRetailerCashback.getValue().floatValue();
                        if (Math.round(amount) > 0) {
                                walletService.addAmountToWallet(retailerId, referenceId, WalletReferenceType.CASHBACK,
                                                "Recharge Cashback", Math.round(amount), LocalDateTime.now());
                        }
                }
                for (RechargeTransaction rt : pendingTransactions) {
                        rt.setCashbackTimestamp(cashbackTime);
                        rt.setCashbackReference(referenceId);
                        rechargeTransactionRepository.persist(rt);
                }
                LOGGER.info("Cashbacks for Recharge processed Successfully");
        }

        public void rollOutUpgardedMarginsNextMonth() throws Exception {
                LocalDate startOfPreviousMonth = LocalDate.now().with(ChronoField.DAY_OF_MONTH, 1).minusMonths(1);

                List<FofoStore> stores = fofoStoreRepository.selectActiveStores();
                for (FofoStore store : stores) {
                        int fofoId = store.getId();

                        PartnerType startOfPreviousMonthPartnerType = partnerTypeChangeService.getTypeOnDate(fofoId, startOfPreviousMonth);
                        PartnerType todayPartnerType = partnerTypeChangeService.getTypeOnMonth(fofoId,
                                        YearMonth.from(startOfPreviousMonth.atStartOfDay()));
                        if (!startOfPreviousMonthPartnerType.nextPartnerTypes().contains(todayPartnerType)) {
                                continue;
                        }
                        if (!startOfPreviousMonthPartnerType.equals(todayPartnerType)) {
                                LOGGER.info("Partner Type has been changed for code {} from {} to {}", store.getCode(),
                                                startOfPreviousMonthPartnerType, todayPartnerType);
                                List<FofoOrder> fofoOrders = fofoOrderRepository.selectByFofoId(fofoId,
                                                startOfPreviousMonth.atStartOfDay(), startOfPreviousMonth.plusMonths(1).atStartOfDay(), 0, 0);
                                for (FofoOrder fofoOrder : fofoOrders) {
                                        schemeService.processSchemeOut(fofoOrder.getId(), fofoId);
                                }

                        }
                }
        }

        public void rollOutUpgardedMargins() throws Exception {
                LocalDate today = LocalDate.now();
                LocalDate yesterday = today.minusDays(1);
                int upgradedCount = 0;
                List<FofoStore> stores = fofoStoreRepository.selectActiveStores();
                StringBuilder sb = new StringBuilder();
                for (FofoStore store : stores) {
                        int fofoId = store.getId();

                        PartnerType yesterdayPartnerType = partnerTypeChangeService.getTypeOnDate(fofoId, yesterday);
                        PartnerType todayPartnerType = partnerTypeChangeService.getTypeOnDate(fofoId, today);
                        if (!yesterdayPartnerType.nextPartnerTypes().contains(todayPartnerType)) {
                                continue;
                        }
                        if (!yesterdayPartnerType.equals(todayPartnerType)) {
                                upgradedCount++;
                                sb.append(String.format("Partner Type has been changed for code %s from %s to %s", store.getCode(),
                                                yesterdayPartnerType.toString(), todayPartnerType.toString()));
                                sb.append("<br>");
                                LOGGER.info("Partner Type has been changed for code {} from {} to {}", store.getCode(),
                                                yesterdayPartnerType, todayPartnerType);
                                List<FofoOrder> fofoOrders = fofoOrderRepository.selectByFofoId(fofoId,
                                                yesterday.withDayOfMonth(1).atStartOfDay(), yesterday.atStartOfDay(), 0, 0);
                                for (FofoOrder fofoOrder : fofoOrders) {
                                        schemeService.processSchemeOut(fofoOrder.getId(), fofoId);
                                }

                        }
                }
                if (upgradedCount > 0) {
                        sendMailHtmlFormat(
                                        new String[] { "amit.gupta@smartdukaan.com", "tarun.verma@smartdukaan.com",
                                                        "neeraj.gupta@smartdukaan.com" },
                                        sb.toString(), null, "Few Partners Category have been Upgraded");
                } else {
                        sendMailHtmlFormat(
                                        new String[] { "amit.gupta@smartdukaan.com", "tarun.verma@smartdukaan.com",
                                                        "neeraj.gupta@smartdukaan.com" },
                                        sb.toString(), null, "No partners Category have been upgraded today");
                }
        }

        private class SaleRoles {

                private List<String> l1;
                private List<String> l2;

                public SaleRoles() {
                        l1 = new ArrayList<>();
                        l2 = new ArrayList<>();
                }

                public List<String> getL1() {
                        return l1;
                }

                public List<String> getL2() {
                        return l2;
                }

        }

        private class FofoReportingModel {
                private String code;
                private int fofoId;
                private String businessName;
                private String territoryManager;
                private String regionalManager;

                @Override
                public String toString() {
                        return "FofoReportingModel [code=" + code + ", fofoId=" + fofoId + ", businessName=" + businessName
                                        + ", territoryManager=" + territoryManager + ", regionalManager=" + regionalManager + "]";
                }

                public String getCode() {
                        return code;
                }

                public void setCode(String code) {
                        this.code = code;
                }

                public String getBusinessName() {
                        return businessName;
                }

                public void setBusinessName(String businessName) {
                        this.businessName = businessName;
                }

                public String getTerritoryManager() {
                        return territoryManager;
                }

                public void setTerritoryManager(String territoryManager) {
                        this.territoryManager = territoryManager;
                }

                public String getRegionalManager() {
                        return regionalManager;
                }

                public void setRegionalManager(String regionalManager) {
                        this.regionalManager = regionalManager;
                }

                private ScheduledTasks getOuterType() {
                        return ScheduledTasks.this;
                }

                @Override
                public int hashCode() {
                        final int prime = 31;
                        int result = 1;
                        result = prime * result + getOuterType().hashCode();
                        result = prime * result + ((businessName == null) ? 0 : businessName.hashCode());
                        result = prime * result + ((code == null) ? 0 : code.hashCode());
                        result = prime * result + fofoId;
                        result = prime * result + ((regionalManager == null) ? 0 : regionalManager.hashCode());
                        result = prime * result + ((territoryManager == null) ? 0 : territoryManager.hashCode());
                        return result;
                }

                @Override
                public boolean equals(Object obj) {
                        if (this == obj)
                                return true;
                        if (obj == null)
                                return false;
                        if (getClass() != obj.getClass())
                                return false;
                        FofoReportingModel other = (FofoReportingModel) obj;
                        if (!getOuterType().equals(other.getOuterType()))
                                return false;
                        if (businessName == null) {
                                if (other.businessName != null)
                                        return false;
                        } else if (!businessName.equals(other.businessName))
                                return false;
                        if (code == null) {
                                if (other.code != null)
                                        return false;
                        } else if (!code.equals(other.code))
                                return false;
                        if (fofoId != other.fofoId)
                                return false;
                        if (regionalManager == null) {
                                if (other.regionalManager != null)
                                        return false;
                        } else if (!regionalManager.equals(other.regionalManager))
                                return false;
                        if (territoryManager == null) {
                                if (other.territoryManager != null)
                                        return false;
                        } else if (!territoryManager.equals(other.territoryManager))
                                return false;
                        return true;
                }

                public int getFofoId() {
                        return fofoId;
                }

                public void setFofoId(int fofoId) {
                        this.fofoId = fofoId;
                }

        }

        public void sendPartnerInvestmentDetails(List<String> sendTo) throws Exception {
                LocalDate yesterDay = LocalDate.now().minusDays(1);
                List<FofoStore> fofoStores = fofoStoreRepository.selectActiveStores();
                Map<Integer, CustomRetailer> customRetailerMap = retailerService
                                .getFofoRetailers(fofoStores.stream().map(x -> x.getId()).collect(Collectors.toList()));

                List<String> headers = Arrays.asList("Code", "Outlet name", "State Manager", "Teritory/Team Lead",
                                "Wallet Amount", "In Stock Amount", "Activated Stock", "Return In Transit Stock", "Unbilled Amount",
                                "Grn Pending Amount", "Min Investment", "Investment Amount", "Investment Short", "Unbilled Qty",
                                "Short Days");
                List<List<?>> rows = new ArrayList<>();
                Map<Integer, List<?>> partnerRowsMap = new HashMap<>();

                Map<Integer, FofoReportingModel> partnerIdSalesHeaderMap = this.getPartnerIdSalesHeaders();

                Map<Integer, Integer> shortDaysMap = partnerDailyInvestmentRepository
                                .selectAll(LocalDate.now().withDayOfMonth(1), LocalDate.now()).stream().collect(Collectors.groupingBy(
                                                x -> x.getFofoId(), Collectors.summingInt(x -> x.getShortPercentage() > 10 ? 1 : 0)));

                for (FofoStore fofoStore : fofoStores) {
                        LOGGER.info("Fofo Store {},  {}", fofoStore.getId(), fofoStore.getCode());
                        int fofoId = fofoStore.getId();
                        PartnerDailyInvestment partnerDailyInvestment = partnerInvestmentService.getInvestment(fofoId, 1);
                        partnerDailyInvestment.setDate(yesterDay);

                        try {
                                partnerDailyInvestmentRepository.persist(partnerDailyInvestment);
                                shortDaysMap.put(fofoId,
                                                shortDaysMap.get(fofoId) + (partnerDailyInvestment.getShortPercentage() > 10 ? 1 : 0));
                        } catch (Exception e) {
                                // ignore the exceptions during persist
                        }

                        CustomRetailer retailer = customRetailerMap.get(fofoStore.getId());
                        if (retailer == null || partnerIdSalesHeaderMap.get(fofoStore.getId()) == null) {
                                LOGGER.info("Could not find retailer with retailer Id {}", fofoStore.getId());
                                continue;
                        }
                        FofoReportingModel reportingModel = partnerIdSalesHeaderMap.get(fofoStore.getId());
                        List<Serializable> row = new ArrayList<>();
                        row.addAll(Arrays.asList(reportingModel.getCode(), reportingModel.getBusinessName(),
                                        reportingModel.getRegionalManager(), reportingModel.getTerritoryManager()));
                        row.addAll(
                                        Arrays.asList(partnerDailyInvestment.getWalletAmount(), partnerDailyInvestment.getInStockAmount(),
                                                        partnerDailyInvestment.getActivatedStockAmount() == 0 ? "-"
                                                                        : "(" + partnerDailyInvestment.getActivatedStockAmount() + ")",
                                                        0, partnerDailyInvestment.getUnbilledAmount(), partnerDailyInvestment.getGrnPendingAmount(),
                                                        partnerDailyInvestment.getMinInvestment(), partnerDailyInvestment.getTotalInvestment(),
                                                        partnerDailyInvestment.getShortInvestment(), partnerDailyInvestment.getUnbilledQty(),
                                                        shortDaysMap.get(fofoId)));
                        partnerRowsMap.put(fofoStore.getId(), row);
                        rows.add(row);

                }

                String fileName = "InvestmentSummary-" + FormattingUtils.formatDate(LocalDateTime.now()) + ".csv";

                if (sendTo == null) {
                        for (Map.Entry<String, Set<Integer>> storeGuyEntry : csService.getAuthUserPartnerIdMapping().entrySet()) {
                                List<List<?>> filteredRows = storeGuyEntry.getValue().stream().map(x -> partnerRowsMap.get(x))
                                                .filter(x -> x != null).collect(Collectors.toList());
                                ByteArrayOutputStream baos = FileUtil.getCSVByteStream(headers, filteredRows);
                                String[] sendToArray = new String[]{storeGuyEntry.getKey()};
                                Utils.sendMailWithAttachment(googleMailSender, sendToArray, null, "Franchise Investment Summary", "PFA",
                                                fileName, new ByteArrayResource(baos.toByteArray()));
                        }
                        sendTo = Arrays.asList("tarun.verma@smartdukaan.com", "kamini.sharma@smartdukaan.com",
                                        "neeraj.gupta@smartdukaan.com", "amit.gupta@shop2020.in", "manish.gupta@smartdukaan.com",
                                        "niranjan.kala@smartdukaan.com");
                }

                ByteArrayOutputStream baos = FileUtil.getCSVByteStream(headers, rows);
                String[] sendToArray = sendTo.toArray(new String[sendTo.size()]);
                Utils.sendMailWithAttachment(googleMailSender, sendToArray, null, "Franchise Investment Summary", "PFA",
                                fileName, new ByteArrayResource(baos.toByteArray()));

        }

        private Map<Integer, FofoReportingModel> getPartnerIdSalesHeaders() {
                Map<String, SaleRoles> partnerEmailSalesMap = new HashMap<>();

                List<Position> positions = positionRepository
                                .selectPositionByCategoryId(ProfitMandiConstants.TICKET_CATEGORY_SALES);
                Map<Integer, AuthUser> authUsersMap = authRepository.selectAllActiveUser().stream()
                                .collect(Collectors.toMap(x -> x.getId(), x -> x));
                Map<Integer, List<CustomRetailer>> positionIdRetailerMap = csService.getPositionCustomRetailerMap(positions);
                for (Position position : positions) {
                        List<CustomRetailer> crList = positionIdRetailerMap.get(position.getId());
                        if (crList == null)
                                continue;
                        for (CustomRetailer cr : crList) {
                                if (!partnerEmailSalesMap.containsKey(cr.getEmail())) {
                                        partnerEmailSalesMap.put(cr.getEmail(), new SaleRoles());
                                }
                                SaleRoles saleRoles = partnerEmailSalesMap.get(cr.getEmail());
                                AuthUser authUser = authUsersMap.get(position.getAuthUserId());
                                if (authUser == null) {
                                        continue;
                                }
                                String name = authUser.getFirstName() + " " + authUser.getLastName();
                                if (position.getEscalationType().equals(EscalationType.L1)) {
                                        saleRoles.getL1().add(name);
                                } else if (position.getEscalationType().equals(EscalationType.L2)) {
                                        saleRoles.getL2().add(name);
                                }
                        }
                }

                Set<CustomRetailer> allCrList = new HashSet<>();
                for (List<CustomRetailer> cr : positionIdRetailerMap.values()) {
                        allCrList.addAll(cr);
                }

                Map<Integer, FofoStore> fofoStoresMap = fofoStoreRepository.selectActiveStores().stream()
                                .collect(Collectors.toMap(x -> x.getId(), x -> x));

                Map<Integer, FofoReportingModel> partnerIdSalesHeadersMap = new HashMap<>();

                for (CustomRetailer cr : allCrList) {
                        FofoStore fofoStore = fofoStoresMap.get(cr.getPartnerId());
                        if (fofoStore == null) {
                                LOGGER.info("Could not find Store {} in active Store", cr.getBusinessName());
                                continue;
                        }
                        String code = fofoStore.getCode();
                        // String storeName = "SmartDukaan-" +
                        // fofoStore.getCode().replaceAll("[a-zA-Z]", "");
                        String businessName = cr.getBusinessName();
                        try {
                                String stateManager = StringUtils.join(partnerEmailSalesMap.get(cr.getEmail()).getL2(), ", ");
                                String territoryManager = StringUtils.join(partnerEmailSalesMap.get(cr.getEmail()).getL1(), ", ");
                                FofoReportingModel reportingModel = new FofoReportingModel();
                                reportingModel.setBusinessName(businessName);
                                reportingModel.setCode(code);
                                reportingModel.setFofoId(fofoStore.getId());
                                reportingModel.setRegionalManager(stateManager);
                                reportingModel.setTerritoryManager(territoryManager);
                                partnerIdSalesHeadersMap.put(fofoStore.getId(), reportingModel);
                        } catch (Exception e) {
                                LOGGER.warn("Could not find partner with email - {}", cr.getEmail());
                        }
                }
                return partnerIdSalesHeadersMap;

        }

        public void sendPartnerInvestmentDetails() throws Exception {
                this.sendPartnerInvestmentDetails(null);
        }

        public void sendAgeingReport(String... sendTo) throws Exception {

                InputStreamSource isr = reporticoService.getReportInputStreamSource(ReporticoProject.WAREHOUSENEW,
                                "itemstockageing.xml");
                InputStreamSource isr1 = reporticoService.getReportInputStreamSource(ReporticoProject.FOCO,
                                "ItemwiseOverallPendingIndent.xml");
                Attachment attachment = new Attachment(
                                "ageing-report-" + FormattingUtils.formatDate(LocalDateTime.now().minusDays(1)) + ".csv", isr);
                Attachment attachment1 = new Attachment(
                                "pending-indent-" + FormattingUtils.formatDate(LocalDateTime.now().minusDays(1)) + ".csv", isr1);

                Utils.sendMailWithAttachments(googleMailSender, STOCK_AGEING_MAIL_LIST, null, "Stock Ageing Report", "PFA",
                                attachment);
                Utils.sendMailWithAttachments(googleMailSender, ITEMWISE_PENDING_INDENT_MAIL_LIST, null,
                                "Itemwise Pending indent", "PFA", attachment1);

                // Reports to be sent to mapped partners
                Map<String, Set<String>> storeGuysMap = csService.getAuthUserPartnerEmailMapping();

                for (Map.Entry<String, Set<String>> storeGuyEntry : storeGuysMap.entrySet()) {
                        Map<String, String> params = new HashMap<>();
                        if (storeGuyEntry.getValue().size() == 0)
                                continue;
                        params.put("MANUAL_email", String.join(",", storeGuyEntry.getValue()));
                        InputStreamSource isr3 = reporticoService.getReportInputStreamSource(ReporticoProject.FOCO,
                                        "focostockreport.xml", params);
                        Attachment attache = new Attachment(
                                        "Franchise-stock-report" + FormattingUtils.formatDate(LocalDateTime.now()) + ".csv", isr3);
                        System.out.println(storeGuyEntry.getValue());
                        Utils.sendMailWithAttachments(googleMailSender, new String[] { storeGuyEntry.getKey() }, null,
                                        "Franchise Stock Report", "PFA", attache);
                }

        }

        public void sendIndentTertiary() throws Exception {

                InputStreamSource isr = reporticoService.getReportInputStreamSource(ReporticoProject.FOCO,
                                "indentandtertiary.xml");
                Attachment attachment = new Attachment(
                                "indentandtertiary-report-" + FormattingUtils.formatDate(LocalDateTime.now()) + ".csv", isr);
                Utils.sendMailWithAttachments(googleMailSender, INDENT_TERTIARY_MAIL_LIST, null, "Indent Tertiary Report",
                                "PFA", attachment);

        }

        public void sendAttendanceMorningAlert() throws Exception {
                LocalDateTime moriningTime = LocalDate.now().atTime(10, 31);
                List<AuthUser> authUsers = authRepository.selectAllActiveUser();
                Map<String, AuthUser> authUserEmailMap = authUsers.stream().filter(x -> x.isActive())
                                .collect(Collectors.toMap(x -> x.getEmailId(), x -> x));

                List<User> users = dtrUserRepository.selectAllByEmailIds(new ArrayList<>(authUserEmailMap.keySet()));
                Map<String, User> userMap = users.stream().collect(Collectors.toMap(x -> x.getEmailId(), x -> x));

                List<EmployeeAttendance> employeeAttendances = employeeAttendanceRepository
                                .selectAllByDatesBetween(LocalDate.now().atStartOfDay(), LocalDateTime.now());

                Map<Integer, Optional<EmployeeAttendance>> employeeMorningAttendance = employeeAttendances.stream()
                                .collect(Collectors.groupingBy(EmployeeAttendance::getUserId,
                                                Collectors.minBy(Comparator.comparing(EmployeeAttendance::getCreateTimestamp))));
                for (AuthUser authUser : authUsers) {
                        User user = userMap.get(authUser.getEmailId());
                        Optional<EmployeeAttendance> employeeAttendanceOptional = employeeMorningAttendance.get(user.getId());
                        LOGGER.info("AuthUser - {}, employeeAttendanceOptional {}", authUser.getName(), employeeAttendanceOptional);
                        if (employeeAttendanceOptional != null) {
                                LOGGER.info("employeeAttendanceOptional.orElse {}", employeeAttendanceOptional.orElse(null));
                                if (employeeAttendanceOptional.orElse(null) != null) {
                                        LOGGER.info("employeeAttendanceOptional.get().getCreateTimestamp() {}",
                                                        employeeAttendanceOptional.get().getCreateTimestamp());
                                }
                        }
                        if (employeeAttendanceOptional == null || employeeAttendanceOptional.orElse(null) == null
                                        || employeeAttendanceOptional.get().getCreateTimestamp().isAfter(moriningTime)) {
                                LOGGER.info("Will Send Email to {}", authUser.getFullName());
                                String body = String.format(
                                                "Dear %s,\n Pls note that you haven't punched your attendance by 10:30am%s. You have been marked absent for half the day.\n\nRegards\nHR Team",
                                                authUser.getFullName(),
                                                (employeeAttendanceOptional == null || employeeAttendanceOptional.orElse(null) == null) ? ""
                                                                : "(Punched at "
                                                                                + FormattingUtils.format(employeeAttendanceOptional.get().getCreateTimestamp())
                                                                                + ")");

                                Utils.sendMailWithAttachments(googleMailSender, new String[] { authUser.getEmailId() },
                                                new String[] { "jyoti.rawat@smartdukaan.com" }, "Attendance Alert", body);

                        }
                }

        }

        public void sendAttendanceEveningAlert() throws Exception {
                List<AuthUser> authUsers = authRepository.selectAllActiveUser();
                Map<String, AuthUser> authUserEmailMap = authUsers.stream().filter(x -> x.isActive())
                                .collect(Collectors.toMap(x -> x.getEmailId(), x -> x));

                List<User> users = dtrUserRepository.selectAllByEmailIds(new ArrayList<>(authUserEmailMap.keySet()));
                Map<String, User> userMap = users.stream().collect(Collectors.toMap(x -> x.getEmailId(), x -> x));

                Map<Integer, List<EmployeeAttendance>> employeeAttendancesMap = employeeAttendanceRepository
                                .selectAllByDatesBetween(LocalDate.now().atStartOfDay(), LocalDateTime.now()).stream()
                                .collect(Collectors.groupingBy(x -> x.getUserId()));

                for (AuthUser authUser : authUsers) {
                        User user = userMap.get(authUser.getEmailId());
                        String body = null;
                        List<EmployeeAttendance> employeeAttendances = employeeAttendancesMap.get(user.getId());
                        if (employeeAttendances == null) {
                                body = String.format(
                                                "Dear %s,\n No attendance has been registered by you today. You have been marked absent for the day.\n\nRegards\nHR Team",
                                                authUser.getFullName());
                        } else {
                                List<LocalDateTime> punchTimes = employeeAttendances.stream()
                                                .sorted(Comparator.comparing(EmployeeAttendance::getCreateTimestamp))
                                                .map(x -> x.getCreateTimestamp()).collect(Collectors.toList());
                                if (punchTimes.size() == 1) {
                                        // body = String.format("Dear %s,\n Pls note that you haven't punched out yet.
                                        // You have been marked absent for half the day. You may contact your manager
                                        // and get it regularise.\n\nRegards\nHR Team", authUser.getFullName());
                                } else {
                                        LocalDateTime firstPunch = punchTimes.get(0);
                                        LocalDateTime lastPunch = punchTimes.get(punchTimes.size() - 1);
                                        Duration duration = Duration.between(firstPunch, lastPunch);
                                        boolean hoursCompleted = lastPunch.isAfter(firstPunch.plusHours(8).plusMinutes(30));
                                        if (!hoursCompleted) {
                                                body = String.format(
                                                                "Dear %s,\n Pls note that you haven't completed 8.30 Hrs (%d.%d Hrs). You have been marked absent for half the day.\n\nRegards\nHR Team",
                                                                authUser.getFullName(), duration.toHours(),
                                                                duration.toMinutes() - duration.toHours() * 60);
                                        }
                                }

                        }
                        if (body != null) {
                                Utils.sendMailWithAttachments(googleMailSender, new String[] { authUser.getEmailId() },
                                                new String[] { "jyoti.rawat@smartdukaan.com" }, "Attendance Alert", body);
                        }
                }

                this.sendMailToHR();

        }

        private void sendMailToHR() throws Exception {
                Map<String, String> map = new HashMap<>();
                String reporticoDate = FormattingUtils.formatReporitcoDate(LocalDateTime.now());
                map.put("MANUAL_datesBetween_FROMDATE", reporticoDate);
                map.put("MANUAL_datesBetween_FROMDATE", reporticoDate);
                InputStreamSource isr = reporticoService.getReportInputStreamSource(ReporticoProject.FOCO,
                                "employeeattendance.xml");
                Attachment attachment = new Attachment("attendance-" + FormattingUtils.formatDate(LocalDateTime.now()) + ".csv",
                                isr);
                Utils.sendMailWithAttachments(googleMailSender, EMPLOYEE_ATTENDANCE_MAIL_LIST, null,
                                "Attendance - " + FormattingUtils.formatDate(LocalDateTime.now()), "PFA Attendance", attachment);
        }

        public void checkPartnerActiveStore() throws Exception {

                List<FofoStore> fofoStores = fofoStoreRepository.selectByStatus(true);

                LocalDateTime currentDate = LocalDate.now().atStartOfDay();
                if (!fofoStores.isEmpty()) {
                        for (FofoStore fofoStore : fofoStores) {

                                if (currentDate.isBefore(fofoStore.getActiveTimeStamp())) {

                                        fofoStore.setActive(true);
                                        fofoStoreRepository.persist(fofoStore);
                                        LOGGER.info("inserted into InActiveFofoStore successfully");

                                }

                                else {
                                        fofoStore.setActive(false);
                                        fofoStore.setActiveTimeStamp(null);
                                        fofoStoreRepository.persist(fofoStore);
                                        LOGGER.info("inserted into InActiveFofoStore successfully");
                                }

                        }
                }

        }

        public void sendAgeingReport() throws Exception {
                sendAgeingReport("kamini.sharma@smartdukaan.com", "amit.babu@smartdukaan.com", "tarun.verma@smartdukaan.com",
                                "niranjan.kala@smartdukaan.com", "manish.gupta@smartdukaan.com", "kuldeep.kumar@smartdukaan.com");
        }

        public void moveImeisToPriceDropImeis() throws Exception {
                List<PriceDrop> priceDrops = priceDropRepository.selectAll();
                for (PriceDrop priceDrop : priceDrops) {
                        priceDropService.priceDropStatus(priceDrop.getId());
                }
        }

        public void walletmismatch() throws Exception {
                LocalDate curDate = LocalDate.now();
                List<PartnerDailyInvestment> pdis = partnerDailyInvestmentRepository.selectAll(curDate.minusDays(2));
                System.out.println(pdis.size());
                for (PartnerDailyInvestment pdi : pdis) {
                        int fofoId = pdi.getFofoId();
                        for (PartnerDailyInvestment investment : Lists
                                        .reverse(partnerDailyInvestmentRepository.selectAll(fofoId, null, null))) {
                                float statementAmount = walletService.getOpeningTill(fofoId,
                                                investment.getDate().plusDays(1).atTime(LocalTime.of(4, 0)));
                                CustomRetailer retailer = retailerService.getFofoRetailer(fofoId);
                                LOGGER.info("{}\t{}\t{}\t{}\t{}", fofoId, retailer.getBusinessName(), retailer.getMobileNumber(),
                                                investment.getDate().toString(), investment.getWalletAmount(), statementAmount);

                        }
                }

        }

        @Autowired
        StateRepository stateRepository;

        public void gst() throws Exception {
                List<FofoOrder> fofoOrders = fofoOrderRepository.selectBetweenSaleDate(LocalDate.of(2021, 8, 16).atStartOfDay(),
                                LocalDateTime.now());
                for (FofoOrder fofoOrder : fofoOrders) {
                        int retailerAddressId = retailerRegisteredAddressRepository
                                        .selectAddressIdByRetailerId(fofoOrder.getFofoId());

                        Address retailerAddress = addressRepository.selectById(retailerAddressId);
                        CustomerAddress customerAddress = customerAddressRepository.selectById(fofoOrder.getCustomerAddressId());
                        Integer stateId = null;
                        if (customerAddress.getState().equals(retailerAddress.getState())) {
                                try {
                                        stateId = stateRepository.selectByName(customerAddress.getState()).getId();
                                } catch (Exception e) {
                                        LOGGER.error("Cannot found state named {}", customerAddress.getState());
                                        continue;
                                }
                        }
                        Map<Integer, GstRate> itemIdStateTaxRateMap = null;
                        Map<Integer, Float> itemIdIgstTaxRateMap = null;

                        List<FofoOrderItem> fofoOrderItems = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());
                        List<Integer> itemIds = fofoOrderItems.stream().map(x -> x.getItemId()).collect(Collectors.toList());
                        if (stateId != null) {
                                itemIdStateTaxRateMap = stateGstRateRepository.getStateTaxRate(itemIds, stateId);
                        } else {
                                itemIdIgstTaxRateMap = stateGstRateRepository.getIgstTaxRate(itemIds);
                        }

                        for (FofoOrderItem foi : fofoOrderItems) {
                                float sgstRate = foi.getSgstRate();
                                float cgstRate = foi.getCgstRate();
                                float igstRate = foi.getIgstRate();
                                if (stateId == null && igstRate == 0) {

                                        foi.setSgstRate(0);
                                        foi.setCgstRate(0);
                                        foi.setIgstRate(itemIdIgstTaxRateMap.get(foi.getItemId()));

                                        LOGGER.info("Invoice {}, Date {}", fofoOrder.getInvoiceNumber(), fofoOrder.getCreateTimestamp());
                                        LOGGER.info("customerAddress.getState() {}, retailerAddress.getState() {}",
                                                        customerAddress.getState(), retailerAddress.getState());
                                        LOGGER.info("Rates getIgstRate() {}", itemIdIgstTaxRateMap.get(foi.getItemId()));

                                } else if (stateId != null && sgstRate == 0 && cgstRate == 0) {

                                        foi.setIgstRate(0);
                                        foi.setCgstRate(itemIdStateTaxRateMap.get(foi.getItemId()).getCgstRate());
                                        foi.setSgstRate(itemIdStateTaxRateMap.get(foi.getItemId()).getSgstRate());

                                        LOGGER.info("Invoice {}, Date {}", fofoOrder.getInvoiceNumber(), fofoOrder.getCreateTimestamp());
                                        LOGGER.info("customerAddress.getState() {}, retailerAddress.getState() {}",
                                                        customerAddress.getState(), retailerAddress.getState());
                                        LOGGER.info("Rates getCgstRate() {}, getSgstRate() {}",
                                                        itemIdStateTaxRateMap.get(foi.getItemId()).getCgstRate(),
                                                        itemIdStateTaxRateMap.get(foi.getItemId()).getSgstRate());
                                }
                        }
                }

        }

        public void schemewalletmismatch() {
                LocalDate dateToReconcile = LocalDate.of(2018, 4, 1);
                while (dateToReconcile.isBefore(LocalDate.now())) {
                        reconcileSchemes(dateToReconcile);
                        // reconcileOrders(dateTime);
                        // reconcileRecharges(dateTime);
                        dateToReconcile = dateToReconcile.plusDays(1);
                }
        }

        private void reconcileSchemes(LocalDate date) {
                LocalDateTime startDate = date.atStartOfDay();
                LocalDateTime endDate = startDate.plusDays(1);
                List<SchemeInOut> siosCreated = schemeInOutRepository.selectAllByCreateDate(startDate, endDate);
                List<SchemeInOut> siosRefunded = schemeInOutRepository.selectAllByRefundDate(startDate, endDate);
                double totalSchemeDisbursed = siosCreated.stream().mapToDouble(x -> x.getAmount()).sum();
                double totalSchemeRolledback = siosRefunded.stream().mapToDouble(x -> x.getAmount()).sum();
                double netSchemeDisbursed = totalSchemeDisbursed - totalSchemeRolledback;
                List<WalletReferenceType> walletReferenceTypes = Arrays.asList(WalletReferenceType.SCHEME_IN,
                                WalletReferenceType.SCHEME_OUT);
                List<UserWalletHistory> history = userWalletHistoryRepository.selectAllByDateType(startDate, endDate,
                                walletReferenceTypes);
                double schemeAmountWalletTotal = history.stream().mapToDouble(x -> x.getAmount()).sum();
                if (Math.abs(netSchemeDisbursed - schemeAmountWalletTotal) > 10d) {
                        LOGGER.info("Scheme Amount mismatched for Date {}", date);

                        Map<Integer, Double> inventoryItemSchemeIO = siosCreated.stream().collect(Collectors
                                        .groupingBy(x -> x.getInventoryItemId(), Collectors.summingDouble(SchemeInOut::getAmount)));

                        Map<Integer, Double> userSchemeMap = inventoryItemRepository.selectByIds(inventoryItemSchemeIO.keySet())
                                        .stream().collect(Collectors.groupingBy(x -> x.getFofoId(),
                                                        Collectors.summingDouble(x -> inventoryItemSchemeIO.get(x.getId()))));

                        Map<Integer, Double> inventoryItemSchemeIORefunded = siosRefunded.stream().collect(Collectors
                                        .groupingBy(x -> x.getInventoryItemId(), Collectors.summingDouble(SchemeInOut::getAmount)));

                        Map<Integer, Double> userSchemeRefundedMap = inventoryItemRepository
                                        .selectByIds(inventoryItemSchemeIORefunded.keySet()).stream()
                                        .collect(Collectors.groupingBy(x -> x.getFofoId(),
                                                        Collectors.summingDouble(x -> inventoryItemSchemeIORefunded.get(x.getId()))));

                        Map<Integer, Double> finalUserSchemeAmountMap = new HashMap<>();

                        for (Map.Entry<Integer, Double> schemeAmount : userSchemeRefundedMap.entrySet()) {
                                if (!finalUserSchemeAmountMap.containsKey(schemeAmount.getKey())) {
                                        finalUserSchemeAmountMap.put(schemeAmount.getKey(), schemeAmount.getValue());
                                } else {
                                        finalUserSchemeAmountMap.put(schemeAmount.getKey(),
                                                        finalUserSchemeAmountMap.get(schemeAmount.getKey()) + schemeAmount.getValue());
                                }
                        }
                        Map<Integer, Integer> userWalletMap = userWalletRepository
                                        .selectByRetailerIds(finalUserSchemeAmountMap.keySet()).stream()
                                        .collect(Collectors.toMap(UserWallet::getUserId, UserWallet::getId));

                        Map<Integer, Double> walletAmountMap = history.stream().collect(Collectors.groupingBy(
                                        UserWalletHistory::getWalletId, Collectors.summingDouble((UserWalletHistory::getAmount))));
                        for (Map.Entry<Integer, Double> userAmount : walletAmountMap.entrySet()) {
                                double diff = Math.abs(finalUserSchemeAmountMap.get(userAmount.getKey()) - userAmount.getValue());
                                if (diff > 5) {
                                        LOGGER.info("Partner scheme mismatched for Userid {}", userWalletMap.get(userAmount.getKey()));
                                }
                        }
                }

        }

        public void dryRunSchemeReco() throws Exception {
                Map<Integer, Integer> userWalletMap = userWalletRepository.selectAll().stream()
                                .collect(Collectors.toMap(UserWallet::getUserId, UserWallet::getId));

                List<UserWalletHistory> userWalletHistory = new ArrayList<>();
                List<SchemeInOut> rolledbackSios = new ArrayList<>();
                Map<Integer, SchemeType> schemeTypeMap = schemeRepository.selectAll().stream()
                                .collect(Collectors.toMap(Scheme::getId, Scheme::getType));
                Set<String> serialNumbersConsidered = new HashSet<>();

                LocalDateTime startDate = LocalDate.of(2018, 3, 1).atStartOfDay();
                LocalDateTime endDate = LocalDate.now().atStartOfDay();
                List<Purchase> purchases = purchaseRepository.selectAllBetweenPurchaseDate(startDate, endDate);

                Map<Integer, String> storeNameMap = fofoStoreRepository.getStoresMap();
                purchases.stream().forEach(purchase -> {
                        float amountToRollback = 0;
                        String description = "Adjustment of Duplicate Scheme for Purchase Invoice "
                                        + purchase.getPurchaseReference();
                        Map<Integer, String> inventorySerialNumberMap = inventoryItemRepository.selectByPurchaseId(purchase.getId())
                                        .stream().filter(ii -> ii.getSerialNumber() != null)
                                        .collect(Collectors.toMap(InventoryItem::getId, InventoryItem::getSerialNumber));
                        if (inventorySerialNumberMap.size() > 0) {
                                for (Map.Entry<Integer, String> inventorySerialNumberEntry : inventorySerialNumberMap.entrySet()) {
                                        String serialNumber = inventorySerialNumberEntry.getValue();
                                        int inventoryItemId = inventorySerialNumberEntry.getKey();
                                        if (serialNumbersConsidered.contains(serialNumber)) {
                                                // This will rollback scheme for differenct orders for same serial
                                                List<SchemeInOut> sios = schemeInOutRepository
                                                                .selectByInventoryItemIds(new HashSet<>(Arrays.asList(inventoryItemId))).stream()
                                                                .filter(x -> x.getRolledBackTimestamp() == null
                                                                                && schemeTypeMap.get(x.getSchemeId()).equals(SchemeType.IN))
                                                                .collect(Collectors.toList());
                                                Collections.reverse(sios);
                                                for (SchemeInOut sio : sios) {
                                                        sio.setRolledBackTimestamp(LocalDateTime.now());
                                                        amountToRollback += sio.getAmount();
                                                        // sio.setSchemeType(SchemeType.OUT);
                                                        sio.setSerialNumber(serialNumber);
                                                        rolledbackSios.add(sio);
                                                }
                                                description = description.concat(" " + serialNumber + " ");
                                        } else {
                                                serialNumbersConsidered.add(serialNumber);
                                                List<Integer> schemesConsidered = new ArrayList<>();
                                                List<SchemeInOut> sios = schemeInOutRepository
                                                                .selectByInventoryItemIds(new HashSet<>(Arrays.asList(inventoryItemId))).stream()
                                                                .filter(x -> x.getRolledBackTimestamp() == null
                                                                                && schemeTypeMap.get(x.getSchemeId()).equals(SchemeType.IN))
                                                                .collect(Collectors.toList());
                                                Collections.reverse(sios);
                                                for (SchemeInOut sio : sios) {
                                                        if (!schemesConsidered.contains(sio.getSchemeId())) {
                                                                schemesConsidered.add(sio.getSchemeId());
                                                                continue;
                                                        }
                                                        sio.setRolledBackTimestamp(LocalDateTime.now());
                                                        amountToRollback += sio.getAmount();
                                                        // sio.setSchemeType(SchemeType.OUT);
                                                        sio.setSerialNumber(serialNumber);
                                                        sio.setStoreCode(storeNameMap.get(purchase.getFofoId()));
                                                        sio.setReference(purchase.getId());
                                                        rolledbackSios.add(sio);
                                                }
                                        }

                                }
                        }
                        if (amountToRollback > 0) {
                                // Address address =
                                // addressRepository.selectAllByRetailerId(purchase.getFofoId(), 0, 10).get(0);
                                UserWalletHistory uwh = new UserWalletHistory();
                                uwh.setAmount(Math.round(amountToRollback));
                                uwh.setDescription(description);
                                uwh.setTimestamp(LocalDateTime.now());
                                uwh.setReferenceType(WalletReferenceType.SCHEME_IN);
                                uwh.setReference(purchase.getId());
                                uwh.setWalletId(userWalletMap.get(purchase.getFofoId()));
                                uwh.setFofoId(purchase.getFofoId());
                                uwh.setStoreCode(storeNameMap.get(purchase.getFofoId()));
                                userWalletHistory.add(uwh);
                        }
                });
                ByteArrayOutputStream baos = FileUtil.getCSVByteStream(
                                Arrays.asList("User Id", "Store Code", "Reference Type", "Reference", "Amount", "Description",
                                                "Timestamp"),
                                userWalletHistory.stream()
                                                .map(x -> Arrays.asList(x.getWalletId(), x.getStoreCode(), x.getReferenceType(),
                                                                x.getReference(), x.getAmount(), x.getDescription(), x.getTimestamp()))
                                                .collect(Collectors.toList()));

                ByteArrayOutputStream baosOuts = FileUtil.getCSVByteStream(
                                Arrays.asList("Scheme ID", "SchemeType", "Reference", "Store Code", "Serial Number", "Amount",
                                                "Created", "Rolledback"),
                                rolledbackSios.stream()
                                                .map(x -> Arrays.asList(x.getSchemeId(), x.getSchemeType(), x.getReference(), x.getStoreCode(),
                                                                x.getSerialNumber(), x.getAmount(), x.getCreateTimestamp(), x.getRolledBackTimestamp()))
                                                .collect(Collectors.toList()));

                Utils.sendMailWithAttachments(googleMailSender, new String[] { "amit.gupta@shop2020.in" }, null,
                                "Partner Excess Amount Scheme In", "PFA",
                                new Attachment[] { new Attachment("WalletSummary.csv", new ByteArrayResource(baos.toByteArray())),
                                                new Attachment("SchemeInRolledback.csv", new ByteArrayResource(baosOuts.toByteArray())) });

                throw new Exception();

        }

        public void dryRunOutSchemeReco() throws Exception {
                List<UserWalletHistory> userWalletHistory = new ArrayList<>();
                List<SchemeInOut> rolledbackSios = new ArrayList<>();
                Map<Integer, Integer> userWalletMap = userWalletRepository.selectAll().stream()
                                .collect(Collectors.toMap(UserWallet::getUserId, UserWallet::getId));
                Map<Integer, SchemeType> schemeTypeMap = schemeRepository.selectAll().stream()
                                .collect(Collectors.toMap(Scheme::getId, Scheme::getType));
                LocalDateTime startDate = LocalDate.of(2019, 5, 1).atStartOfDay();
                LocalDateTime endDate = LocalDate.now().atStartOfDay();
                List<FofoOrder> allOrders = fofoOrderRepository.selectBetweenSaleDate(startDate, endDate);
                // Collections.reverse(allOrders);
                // List<FofoOrder> allOrders =
                // List<FofoOrder> allOrders =
                // Arrays.asList(fofoOrderRepository.selectByInvoiceNumber("UPGZ019/25"));
                Set<String> serialNumbersConsidered = new HashSet<>();
                allOrders.stream().forEach(fofoOrder -> {
                        String description = "Adjustment of Duplicate Scheme for Sale Invoice " + fofoOrder.getInvoiceNumber();
                        Map<Integer, String> inventorySerialNumberMap = new HashMap<>();
                        float amountToRollback = 0;
                        List<FofoOrderItem> orderItems = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());
                        orderItems.forEach(x -> {
                                inventorySerialNumberMap.putAll(x.getFofoLineItems().stream().filter(li -> li.getSerialNumber() != null)
                                                .collect(Collectors.toMap(FofoLineItem::getInventoryItemId, FofoLineItem::getSerialNumber)));
                        });
                        if (inventorySerialNumberMap.size() > 0) {
                                for (Map.Entry<Integer, String> inventorySerialNumberEntry : inventorySerialNumberMap.entrySet()) {
                                        String serialNumber = inventorySerialNumberEntry.getValue();
                                        int inventoryItemId = inventorySerialNumberEntry.getKey();
                                        if (serialNumbersConsidered.contains(serialNumber)) {
                                                // This will rollback scheme for differenct orders for same serial
                                                List<SchemeInOut> sios = schemeInOutRepository
                                                                .selectByInventoryItemIds(new HashSet<>(Arrays.asList(inventoryItemId))).stream()
                                                                .filter(x -> x.getRolledBackTimestamp() == null
                                                                                && schemeTypeMap.get(x.getSchemeId()).equals(SchemeType.OUT))
                                                                .collect(Collectors.toList());
                                                Collections.reverse(sios);
                                                for (SchemeInOut sio : sios) {
                                                        sio.setRolledBackTimestamp(LocalDateTime.now());
                                                        amountToRollback += sio.getAmount();
                                                        // sio.setSchemeType(SchemeType.OUT);
                                                        sio.setSerialNumber(serialNumber);
                                                        sio.setStoreCode(fofoOrder.getInvoiceNumber().split("/")[0]);
                                                        sio.setReference(fofoOrder.getId());
                                                        rolledbackSios.add(sio);
                                                }
                                                description = description.concat(" " + serialNumber + " ");
                                        } else {
                                                serialNumbersConsidered.add(serialNumber);
                                                List<Integer> schemesConsidered = new ArrayList<>();
                                                List<SchemeInOut> sios = schemeInOutRepository
                                                                .selectByInventoryItemIds(new HashSet<>(Arrays.asList(inventoryItemId))).stream()
                                                                .filter(x -> x.getRolledBackTimestamp() == null
                                                                                && schemeTypeMap.get(x.getSchemeId()).equals(SchemeType.OUT))
                                                                .collect(Collectors.toList());
                                                Collections.reverse(sios);
                                                for (SchemeInOut sio : sios) {
                                                        if (!schemesConsidered.contains(sio.getSchemeId())) {
                                                                schemesConsidered.add(sio.getSchemeId());
                                                                continue;
                                                        }
                                                        sio.setRolledBackTimestamp(LocalDateTime.now());
                                                        amountToRollback += sio.getAmount();
                                                        // sio.setSchemeType(SchemeType.OUT);
                                                        sio.setReference(fofoOrder.getId());
                                                        sio.setSerialNumber(serialNumber);
                                                        sio.setStoreCode(fofoOrder.getInvoiceNumber().split("/")[0]);
                                                        rolledbackSios.add(sio);
                                                }
                                        }

                                }
                        }
                        if (amountToRollback > 0) {
                                UserWalletHistory uwh = new UserWalletHistory();
                                uwh.setAmount(Math.round(amountToRollback));
                                uwh.setDescription(description);
                                uwh.setTimestamp(LocalDateTime.now());
                                uwh.setReferenceType(WalletReferenceType.SCHEME_OUT);
                                uwh.setReference(fofoOrder.getId());
                                uwh.setWalletId(userWalletMap.get(fofoOrder.getFofoId()));
                                uwh.setFofoId(fofoOrder.getFofoId());
                                uwh.setStoreCode(fofoOrder.getInvoiceNumber().split("/")[0]);
                                userWalletHistory.add(uwh);
                        }
                });

                ByteArrayOutputStream baos = FileUtil.getCSVByteStream(
                                Arrays.asList("Wallet Id", "Store Code", "Reference Type", "Reference", "Amount", "Description",
                                                "Timestamp"),
                                userWalletHistory.stream()
                                                .map(x -> Arrays.asList(x.getWalletId(), x.getStoreCode(), x.getReferenceType(),
                                                                x.getReference(), x.getAmount(), x.getDescription(), x.getTimestamp()))
                                                .collect(Collectors.toList()));

                ByteArrayOutputStream baosOuts = FileUtil.getCSVByteStream(
                                Arrays.asList("Scheme ID", "SchemeType", "Store Code", "Serial Number", "Amount", "Created",
                                                "Rolledback"),
                                rolledbackSios.stream()
                                                .map(x -> Arrays.asList(x.getSchemeId(), x.getSchemeType(), x.getStoreCode(),
                                                                x.getSerialNumber(), x.getAmount(), x.getCreateTimestamp(), x.getRolledBackTimestamp()))
                                                .collect(Collectors.toList()));

                Utils.sendMailWithAttachments(googleMailSender, new String[] { "amit.gupta@shop2020.in" }, null,
                                "Partner Excess Amount Scheme Out", "PFA",
                                new Attachment[] { new Attachment("WalletSummary.csv", new ByteArrayResource(baos.toByteArray())),
                                                new Attachment("SchemeOutRolledback.csv", new ByteArrayResource(baosOuts.toByteArray())) });

                throw new Exception();
        }

        public void dryRunSchemeOutReco1() throws Exception {
                List<Integer> references = Arrays.asList(6744, 7347, 8320, 8891, 9124, 9217, 9263, 9379);
                List<UserWalletHistory> userWalletHistory = new ArrayList<>();
                List<SchemeInOut> rolledbackSios = new ArrayList<>();
                Map<Integer, Integer> userWalletMap = userWalletRepository.selectAll().stream()
                                .collect(Collectors.toMap(UserWallet::getUserId, UserWallet::getId));
                Map<Integer, SchemeType> schemeTypeMap = schemeRepository.selectAll().stream()
                                .collect(Collectors.toMap(Scheme::getId, Scheme::getType));
                references.stream().forEach(reference -> {
                        FofoOrder fofoOrder = null;
                        try {
                                fofoOrder = fofoOrderRepository.selectByOrderId(reference);
                        } catch (Exception e) {

                        }
                        String description = "Adjustment of Duplicate Scheme for Sale Invoice " + fofoOrder.getInvoiceNumber();
                        Map<Integer, String> inventorySerialNumberMap = new HashMap<>();
                        float amountToRollback = 0;
                        List<FofoOrderItem> orderItems = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());
                        orderItems.forEach(x -> {
                                inventorySerialNumberMap.putAll(x.getFofoLineItems().stream().filter(li -> li.getSerialNumber() != null)
                                                .collect(Collectors.toMap(FofoLineItem::getInventoryItemId, FofoLineItem::getSerialNumber)));
                        });
                        if (inventorySerialNumberMap.size() > 0) {
                                List<SchemeInOut> sios = schemeInOutRepository
                                                .selectByInventoryItemIds(inventorySerialNumberMap.keySet()).stream()
                                                .filter(x -> schemeTypeMap.get(x.getSchemeId()).equals(SchemeType.OUT))
                                                .collect(Collectors.toList());
                                LOGGER.info("Found {} duplicate schemeouts for Orderid {}", sios.size(), fofoOrder.getId());
                                UserWalletHistory uwh = new UserWalletHistory();
                                Map<Integer, List<SchemeInOut>> inventoryIdSouts = sios.stream()
                                                .collect(Collectors.groupingBy(SchemeInOut::getInventoryItemId, Collectors.toList()));
                                for (Map.Entry<Integer, List<SchemeInOut>> inventorySioEntry : inventoryIdSouts.entrySet()) {
                                        List<SchemeInOut> outList = inventorySioEntry.getValue();
                                        if (outList.size() > 1) {

                                        }
                                }
                                uwh.setAmount(Math.round(amountToRollback));
                                uwh.setDescription(description);
                                uwh.setTimestamp(LocalDateTime.now());
                                uwh.setReferenceType(WalletReferenceType.SCHEME_OUT);
                                uwh.setReference(fofoOrder.getId());
                                uwh.setWalletId(userWalletMap.get(fofoOrder.getFofoId()));
                                uwh.setFofoId(fofoOrder.getFofoId());
                                uwh.setStoreCode(fofoOrder.getInvoiceNumber().split("/")[0]);
                                userWalletHistory.add(uwh);
                        }
                });

                ByteArrayOutputStream baos = FileUtil.getCSVByteStream(
                                Arrays.asList("User Id", "Reference Type", "Reference", "Amount", "Description", "Timestamp"),
                                userWalletHistory.stream().map(x -> Arrays.asList(x.getWalletId(), x.getReferenceType(),
                                                x.getReference(), x.getAmount(), x.getDescription(), x.getTimestamp()))
                                                .collect(Collectors.toList()));

                ByteArrayOutputStream baosOuts = FileUtil.getCSVByteStream(
                                Arrays.asList("Scheme ID", "SchemeType", "Store Code", "Serial Number", "Amount", "Created",
                                                "Rolledback"),
                                rolledbackSios.stream()
                                                .map(x -> Arrays.asList(x.getSchemeId(), x.getSchemeType(), x.getStoreCode(),
                                                                x.getSerialNumber(), x.getAmount(), x.getCreateTimestamp(), x.getRolledBackTimestamp()))
                                                .collect(Collectors.toList()));

                Utils.sendMailWithAttachments(googleMailSender,
                                new String[] { "amit.gupta@shop2020.in", "neeraj.gupta@smartdukaan.com" }, null,
                                "Partner Excess Amount", "PFA",
                                new Attachment[] { new Attachment("WalletSummary.csv", new ByteArrayResource(baos.toByteArray())),
                                                new Attachment("SchemeOutRolledback.csv", new ByteArrayResource(baosOuts.toByteArray())) });

                throw new Exception();

        }

        public void sendDailySalesNotificationToPartner(Integer fofoIdInt) throws Exception {

                LocalDateTime now = LocalDateTime.now();
                LocalDateTime from = now.with(LocalTime.MIN);
                String timeString = "Today %s";
                // Send yesterday's report
                /*
                 * if (now.getHour() < 13) { timeString = "Yesterday %s"; from =
                 * now.minusDays(1).; now = from.with(LocalTime.MAX);
                 * 
                 * }
                 */
                List<Integer> fofoIds = null;
                if (fofoIdInt == null) {
                        fofoIds = fofoStoreRepository.selectAll().stream().filter(x -> x.isActive()).map(x -> x.getId())
                                        .collect(Collectors.toList());
                } else {
                        fofoIds = Arrays.asList(fofoIdInt);
                }
                DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("h:m a");

                Map<Integer, Float> partnerPolicyAmountMap = insurancePolicyRepository.selectAmountSumGroupByRetailerId(now,
                                null);
                Map<Integer, Long> partnerPolicyQtyMap = insurancePolicyRepository.selectQtyGroupByRetailerId(now, null);

                Map<Integer, Double> spPartnerOrderValMap = fofoOrderItemRepository.selectSumAmountGroupByRetailer(from, now, 0,
                                true);

                Map<Integer, Double> spPartner3DaysOrderValMap = fofoOrderItemRepository
                                .selectSumAmountGroupByRetailer(from.minusDays(3), now, 0, true);
                Map<Integer, Long> spPartnerOrderQtyMap = fofoOrderItemRepository.selectQtyGroupByRetailer(from, now, 0, true);

                Map<Integer, Double> partnerOrderValMap = fofoOrderItemRepository.selectSumAmountGroupByRetailer(from, now, 0,
                                false);
                Map<Integer, Long> partnerOrderQtyMap = fofoOrderItemRepository.selectQtyGroupByRetailer(from, now, 0, false);

                Map<Integer, SaleTargetReportModel> saleTargetReportModelMap = new HashMap<>();
                for (int fofoId : fofoIds) {
                        SaleTargetReportModel model = new SaleTargetReportModel();
                        model.setInsuranceSale(
                                        partnerPolicyAmountMap.containsKey(fofoId) ? partnerPolicyAmountMap.get(fofoId).doubleValue() : 0);
                        model.setInsruanceQty(partnerPolicyQtyMap.containsKey(fofoId) ? partnerPolicyQtyMap.get(fofoId) : 0);
                        model.setSmartphoneSale(spPartnerOrderValMap.containsKey(fofoId) ? spPartnerOrderValMap.get(fofoId) : 0);
                        model.setSmartphoneQty(spPartnerOrderQtyMap.containsKey(fofoId) ? spPartnerOrderQtyMap.get(fofoId) : 0);
                        model.setTotalSale(partnerOrderValMap.containsKey(fofoId) ? partnerOrderValMap.get(fofoId) : 0);
                        model.setTotalQty(partnerOrderQtyMap.containsKey(fofoId) ? partnerOrderQtyMap.get(fofoId) : 0);
                        model.setPast3daysSale(
                                        spPartner3DaysOrderValMap.containsKey(fofoId) ? spPartner3DaysOrderValMap.get(fofoId) : 0);
                        model.setFofoId(fofoId);
                        saleTargetReportModelMap.put(fofoId, model);
                }

                Map<Integer, FofoReportingModel> partnerSalesHeadersMap = this.getPartnerIdSalesHeaders();
                for (Integer fofoId : fofoIds) {
                        SaleTargetReportModel model = saleTargetReportModelMap.get(fofoId);
                        SendNotificationModel sendNotificationModel = new SendNotificationModel();
                        sendNotificationModel.setCampaignName("Sales update alert");
                        sendNotificationModel.setTitle("Sale Update");
                        sendNotificationModel
                                        .setMessage(String.format("Smartphones Rs.%.0f, Insurance Rs.%.0f, Total Rs.%.0f till %s.",
                                                        model.getSmartphoneSale(), model.getInsuranceSale(), model.getTotalSale(),
                                                        String.format(timeString, now.format(timeFormatter))));
                        sendNotificationModel.setType("url");
                        sendNotificationModel.setUrl("https://app.smartdukaan.com/pages/home/notifications");
                        sendNotificationModel.setExpiresat(LocalDateTime.now().plusDays(1));
                        sendNotificationModel.setMessageType(MessageType.notification);
                        int userId = userAccountRepository.selectUserIdByRetailerId(fofoId);
                        sendNotificationModel.setUserIds(Arrays.asList(userId));
                        notificationService.sendNotification(sendNotificationModel);
                }
                // String saleReport = this.getDailySalesReportHtml(partnerSalesHeadersMap,
                // saleTargetReportModelMap);
                String statewiseSaleReport = this.getStateWiseSales(saleTargetReportModelMap, partnerSalesHeadersMap);
                String cc[] = { "tarun.verma@smartdukaan.com", "kamini.sharma@smartdukaan.com", "amit.babu@smartdukaan.com",
                                "niranjan.kala@smartdukaan.com", "up.singh@smartdukaan.com", "sm@smartdukaan.com" };

                String subject = String.format("Sale till %s", String.format(timeString, now.format(timeFormatter)));
                // this.sendMailOfHtmlFomat("amit.gupta@smartukaan.com", saleReport, cc,
                // subject);
                this.sendMailOfHtmlFormat("amit.gupta@smartdukaan.com", statewiseSaleReport, cc, "Statewise" + subject);
        }

        public void checkRazorPayPaymentStatus() throws Exception {
                List<PendingOrder> pendingOrder = pendingOrderRepository
                                .selectAllByStatus(com.spice.profitmandi.dao.enumuration.transaction.OrderStatus.PENDING);

                for (PendingOrder po : pendingOrder) {
                        RazorPay razorPay = razorPayRepository.selectByOrdeId(po.getId());
                        List<PendingOrderItem> poItems = pendingOrderItemRepository.selectByOrderId(po.getId());

                        LOGGER.info("razorPay" + razorPay);
                        if (razorPay != null) {
                                List<Payment> payments = razorPaymentService.fetchOrderForPayment(razorPay.getRazorOrderId());

                                if (!payments.isEmpty()) {
                                        List<String> statusList = new ArrayList<>();
                                        for (Payment payment : payments) {

                                                JSONObject jsonObj = new JSONObject(payment.toString());

                                                String status = jsonObj.getString("status");

                                                statusList.add(status);

                                        }
                                        LOGGER.info("statusList" + statusList);

                                        if (statusList.contains("authorized") || statusList.contains("captured")) {
                                                po.setStatus(com.spice.profitmandi.dao.enumuration.transaction.OrderStatus.PROCESSING);
                                                po.setPaidAmount(po.getTotalAmount());
                                                for (PendingOrderItem poi : poItems) {
                                                        poi.setStatus(com.spice.profitmandi.dao.enumuration.transaction.OrderStatus.PROCESSING);
                                                }
                                                Map<String, Object> emailModel = pendingOrderService.sendCreateOrderMail(po);

                                                CustomRetailer customRetailer = retailerService.getFofoRetailer(po.getFofoId());
                                                Customer customer = customerRepository.selectById(po.getCustomerId());
                                                String[] customerEmail = null;
                                                if (customer.getEmailId() != null) {
                                                        customerEmail = new String[] { customer.getEmailId() };
                                                }
                                                List<String> bccTo = Arrays.asList("kamini.sharma@smartdukaan.com",
                                                                "tarun.verma@smartdukaan.com", "niranjan.kala@smartdukaan.com", "sm@smartdukaan.com",
                                                                "tejbeer.kaur@shop2020.in", customRetailer.getEmail());
                                                List<String> authUserEmails = csService.getAuthUserByPartnerId(customRetailer.getPartnerId());
                                                if (authUserEmails != null) {
                                                        authUserEmails = new ArrayList<>();
                                                }
                                                authUserEmails.addAll(bccTo);

                                                // emailService.sendMailWithAttachments("Order Created with SmartDukaan",
                                                // "order-confirm.vm",
                                                // emailModel, customerEmail, null, authUserEmails.toArray(new String[0]));

                                        } else if (statusList.contains("refunded") || statusList.contains("failed")) {
                                                for (PendingOrderItem poi : poItems) {
                                                        poi.setStatus(com.spice.profitmandi.dao.enumuration.transaction.OrderStatus.FAILED);
                                                }

                                                po.setStatus(com.spice.profitmandi.dao.enumuration.transaction.OrderStatus.FAILED);
                                        }

                                }
                                // LOGGER.info("payment" + payments);

                        }
                }
        }

        public static class SaleTargetReportModel {
                private double totalSale;
                private long totalQty;
                private double past3daysSale;
                private int fofoId;

                public int getFofoId() {
                        return fofoId;
                }

                public void setFofoId(int fofoId) {
                        this.fofoId = fofoId;
                }

                private double smartphoneSale;
                private long smartphoneQty;
                private double insuranceSale;
                private long insruanceQty;

                public long getTotalQty() {
                        return totalQty;
                }

                public void setTotalQty(long totalQty) {
                        this.totalQty = totalQty;
                }

                public double getPast3daysSale() {
                        return past3daysSale;
                }

                public void setPast3daysSale(double past3daysSale) {
                        this.past3daysSale = past3daysSale;
                }

                @Override
                public int hashCode() {
                        final int prime = 31;
                        int result = 1;
                        result = prime * result + fofoId;
                        result = prime * result + (int) (insruanceQty ^ (insruanceQty >>> 32));
                        long temp;
                        temp = Double.doubleToLongBits(insuranceSale);
                        result = prime * result + (int) (temp ^ (temp >>> 32));
                        result = prime * result + (int) (smartphoneQty ^ (smartphoneQty >>> 32));
                        temp = Double.doubleToLongBits(smartphoneSale);
                        result = prime * result + (int) (temp ^ (temp >>> 32));
                        result = prime * result + (int) (totalQty ^ (totalQty >>> 32));
                        temp = Double.doubleToLongBits(totalSale);
                        result = prime * result + (int) (temp ^ (temp >>> 32));
                        return result;
                }

                @Override
                public boolean equals(Object obj) {
                        if (this == obj)
                                return true;
                        if (obj == null)
                                return false;
                        if (getClass() != obj.getClass())
                                return false;
                        SaleTargetReportModel other = (SaleTargetReportModel) obj;
                        if (fofoId != other.fofoId)
                                return false;
                        if (insruanceQty != other.insruanceQty)
                                return false;
                        if (Double.doubleToLongBits(insuranceSale) != Double.doubleToLongBits(other.insuranceSale))
                                return false;
                        if (smartphoneQty != other.smartphoneQty)
                                return false;
                        if (Double.doubleToLongBits(smartphoneSale) != Double.doubleToLongBits(other.smartphoneSale))
                                return false;
                        if (totalQty != other.totalQty)
                                return false;
                        if (Double.doubleToLongBits(totalSale) != Double.doubleToLongBits(other.totalSale))
                                return false;
                        return true;
                }

                public double getTotalSale() {
                        return totalSale;
                }

                public void setTotalSale(double totalSale) {
                        this.totalSale = totalSale;
                }

                public double getSmartphoneSale() {
                        return smartphoneSale;
                }

                public void setSmartphoneSale(double smartphoneSale) {
                        this.smartphoneSale = smartphoneSale;
                }

                public long getSmartphoneQty() {
                        return smartphoneQty;
                }

                public void setSmartphoneQty(long smartphoneQty) {
                        this.smartphoneQty = smartphoneQty;
                }

                public double getInsuranceSale() {
                        return insuranceSale;
                }

                public void setInsuranceSale(double insuranceSale) {
                        this.insuranceSale = insuranceSale;
                }

                public long getInsruanceQty() {
                        return insruanceQty;
                }

                public void setInsruanceQty(long insruanceQty) {
                        this.insruanceQty = insruanceQty;
                }

                @Override
                public String toString() {
                        return "SaleTargetReportModel [totalSale=" + totalSale + ", totalQty=" + totalQty + ", past3daysSale="
                                        + past3daysSale + ", fofoId=" + fofoId + ", smartphoneSale=" + smartphoneSale + ", smartphoneQty="
                                        + smartphoneQty + ", insuranceSale=" + insuranceSale + ", insruanceQty=" + insruanceQty + "]";
                }

        }

        private String getStateWiseSales(Map<Integer, SaleTargetReportModel> saleTargetReportModelMap,
                        Map<Integer, FofoReportingModel> partnerSalesHeadersMap) throws Exception {
                List<FofoStore> stores = fofoStoreRepository.selectActiveStores();
                Map<String, List<Integer>> stateMap = stores.stream().collect(Collectors
                                .groupingBy(x -> x.getCode().substring(0, 2), Collectors.mapping(x -> x.getId(), Collectors.toList())));
                List<List<Serializable>> stateWiseSales = new ArrayList<>();
                for (Map.Entry<String, List<Integer>> stateMapEntry : stateMap.entrySet()) {
                        long totalQty = stateMapEntry.getValue().stream()
                                        .collect(Collectors.summingLong(x -> saleTargetReportModelMap.get(x).getTotalQty()));
                        double totalSale = stateMapEntry.getValue().stream()
                                        .collect(Collectors.summingDouble(x -> saleTargetReportModelMap.get(x).getTotalSale()));
                        long smartPhoneQty = stateMapEntry.getValue().stream()
                                        .collect(Collectors.summingLong(x -> saleTargetReportModelMap.get(x).getSmartphoneQty()));
                        double smartPhoneSale = stateMapEntry.getValue().stream()
                                        .collect(Collectors.summingDouble(x -> saleTargetReportModelMap.get(x).getSmartphoneSale()));
                        stateWiseSales
                                        .add(Arrays.asList(stateMapEntry.getKey(), smartPhoneQty, smartPhoneSale, totalQty, totalSale));
                }
                StringBuilder sb = new StringBuilder();
                sb.append("<html><body>");
                sb.append("<p>Statewise Sale Report:</p><br/><table style='border:1px solid black';cellspacing=0>");
                sb.append("<tbody>\n" + "           <tr>"
                                + "                                             <th style='border:1px solid black;padding: 5px'>State</th>"
                                + "                                             <th style='border:1px solid black;padding: 5px'>SmartPhone Qty</th>"
                                + "                                             <th style='border:1px solid black;padding: 5px'>SmartPhone Value</th>"
                                + "                                             <th style='border:1px solid black;padding: 5px'>Total Qty</th>"
                                + "                                             <th style='border:1px solid black;padding: 5px'>Total Value</th>"
                                + "                                     </tr>");
                for (List<Serializable> stateSale : stateWiseSales) {
                        sb.append("<tr>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>" + stateSale.get(0) + "</td>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>" + stateSale.get(1) + "</td>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>" + stateSale.get(2) + "</td>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>" + stateSale.get(3) + "</td>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>" + stateSale.get(4) + "</td>");
                        sb.append("</tr>");
                }
                sb.append("</tbody></table><br><br>");

                sb.append("<p>Sale Report:</p><br/><table style='border:1px solid black';cellspacing=0>");
                sb.append("<tbody>\n" + "                                       <tr>\n"
                                + "                                             <th style='border:1px solid black;padding: 5px'>Code</th>"
                                + "                                             <th style='border:1px solid black;padding: 5px'>Business Name</th>"
                                + "                                             <th style='border:1px solid black;padding: 5px'>Regional Manager</th>"
                                + "                                             <th style='border:1px solid black;padding: 5px'>Territory Manager</th>"
                                + "                                             <th style='border:1px solid black;padding: 5px'>Sale</th>"
                                + "                                             <th style='border:1px solid black;padding: 5px'>Smartphone Sale</th>"
                                + "                                             <th style='border:1px solid black;padding: 5px'>SmartPhone Qty</th>"
                                + "                                     </tr>");

                List<Integer> sortedPartnerSalesHeaders = partnerSalesHeadersMap.values().stream()
                                .sorted(Comparator.comparing(FofoReportingModel::getCode)
                                                .thenComparing(FofoReportingModel::getRegionalManager)
                                                .thenComparing(FofoReportingModel::getTerritoryManager))
                                .map(FofoReportingModel::getFofoId).collect(Collectors.toList());
                for (Integer fofoId : sortedPartnerSalesHeaders) {
                        if (saleTargetReportModelMap.get(fofoId).getPast3daysSale() == 0) {
                                sb.append("<tr style='background-color:red'>");
                        } else {
                                sb.append("<tr>");
                        }
                        sb.append("<td style='border:1px solid black;padding: 5px'>" + partnerSalesHeadersMap.get(fofoId).getCode()
                                        + "</td>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>"
                                        + partnerSalesHeadersMap.get(fofoId).getBusinessName() + "</td>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>"
                                        + partnerSalesHeadersMap.get(fofoId).getRegionalManager() + "</td>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>"
                                        + partnerSalesHeadersMap.get(fofoId).getTerritoryManager() + "</td>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>"
                                        + saleTargetReportModelMap.get(fofoId).getTotalSale() + "</td>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>"
                                        + saleTargetReportModelMap.get(fofoId).getSmartphoneSale() + "</td>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>"
                                        + saleTargetReportModelMap.get(fofoId).getSmartphoneQty() + "</td>");
                        sb.append("</tr>");
                }

                sb.append("</tr>");

                sb.append("</body></html>");

                return sb.toString();
        }

        private void sendMailOfHtmlFormat(String email, String body, String cc[], String subject)
                        throws MessagingException, ProfitMandiBusinessException, IOException {
                MimeMessage message = mailSender.createMimeMessage();
                MimeMessageHelper helper = new MimeMessageHelper(message);
                helper.setSubject(subject);
                helper.setText(body, true);
                helper.setTo(email);
                if (cc != null) {
                        helper.setCc(cc);
                }
                InternetAddress senderAddress = new InternetAddress("noreply@smartdukaan.com", "Smart Dukaan");
                helper.setFrom(senderAddress);
                mailSender.send(message);
        }

        public void sendNotification() throws Exception {
                List<PushNotifications> pushNotifications = pushNotificationRepository.selectAllByTimestamp();
                if (!pushNotifications.isEmpty()) {
                        for (PushNotifications pushNotification : pushNotifications) {
                                Device device = deviceRepository.selectById(pushNotification.getDeviceId());
                                NotificationCampaign notificationCampaign = notificationCampaignRepository
                                                .selectById(pushNotification.getNotificationCampaignid());
                                SimpleCampaignParams scp = gson.fromJson(notificationCampaign.getImplementationParams(),
                                                SimpleCampaignParams.class);
                                Campaign campaign = new SimpleCampaign(scp);
                                String result_url = campaign.getUrl() + "&user_id=" + device.getUser_id();
                                JSONObject json = new JSONObject();
                                json.put("to", device.getFcmId());
                                JSONObject jsonObj = new JSONObject();
                                jsonObj.put("message", campaign.getMessage());
                                jsonObj.put("title", campaign.getTitle());
                                jsonObj.put("type", campaign.getType());
                                jsonObj.put("url", result_url);
                                jsonObj.put("time_to_live", campaign.getExpireTimestamp());
                                jsonObj.put("image", campaign.getImageUrl());
                                jsonObj.put("largeIcon", "large_icon");
                                jsonObj.put("smallIcon", "small_icon");
                                jsonObj.put("vibrate", 1);
                                jsonObj.put("pid", pushNotification.getId());
                                jsonObj.put("sound", 1);
                                jsonObj.put("priority", "high");
                                json.put("data", jsonObj);
                                try {
                                        CloseableHttpClient client = HttpClients.createDefault();
                                        HttpPost httpPost = new HttpPost(FCM_URL);

                                        httpPost.setHeader("Content-Type", "application/json; utf-8");
                                        httpPost.setHeader("authorization", "key=" + FCM_API_KEY);
                                        StringEntity entity = new StringEntity(json.toString());
                                        httpPost.setEntity(entity);
                                        CloseableHttpResponse response = client.execute(httpPost);

                                        if (response.getStatusLine().getStatusCode() == 200) {
                                                pushNotification.setSentTimestamp(LocalDateTime.now());
                                        } else {
                                                pushNotification.setSentTimestamp(LocalDateTime.of(1970, 1, 1, 00, 00));
                                                LOGGER.info("message" + "not sent");
                                                response.toString();
                                        }

                                } catch (Exception e) {
                                        e.printStackTrace();
                                        pushNotification.setSentTimestamp(LocalDateTime.of(1970, 1, 1, 00, 00));
                                        LOGGER.info("message " + "not sent " + e.getMessage());
                                }
                        }
                }
        }

        public void grouping() throws Exception {
                DateTimeFormatter dtf = DateTimeFormatter.ofPattern("MM-dd-yyyy hh:mm");
                List<PriceDropIMEI> priceDropImeis = priceDropIMEIRepository.selectByStatus(PriceDropImeiStatus.APPROVED);
                System.out.println(String.join("\t",
                                Arrays.asList("IMEI", "ItemId", "Brand", "Model Name", "Model Number", "Franchise Id", "Franchise Name",
                                                "Grn On", "Price Dropped On", "Approved On", "Returned On", "Price Drop Paid", "Is Doa")));
                Map<Integer, CustomRetailer> retailersMap = retailerService.getFofoRetailers(false);
                for (PriceDropIMEI priceDropIMEI : priceDropImeis) {
                        if (priceDropIMEI.getPartnerId() == 0)
                                continue;
                        HashSet<String> imeis = new HashSet<>();
                        PriceDrop priceDrop = priceDropRepository.selectById(priceDropIMEI.getPriceDropId());
                        imeis.add(priceDropIMEI.getImei());
                        List<InventoryItem> inventoryItems = inventoryItemRepository
                                        .selectByFofoIdSerialNumbers(priceDropIMEI.getPartnerId(), imeis, false);
                        if (inventoryItems.size() == 0) {
                                LOGGER.info("Need to investigate partnerId - {} imeis - {}", priceDropIMEI.getPartnerId(), imeis);
                                continue;
                        }
                        InventoryItem inventoryItem = inventoryItems.get(0);
                        CustomRetailer customRetailer = retailersMap.get(inventoryItem.getFofoId());
                        if (inventoryItem.getLastScanType().equals(ScanType.DOA_OUT)
                                        || inventoryItem.getLastScanType().equals(ScanType.PURCHASE_RET)) {
                                // check if pricedrop has been rolled out
                                List<UserWalletHistory> uwh = walletService.getAllByReference(inventoryItem.getFofoId(),
                                                priceDropIMEI.getPriceDropId(), WalletReferenceType.PRICE_DROP);
                                if (uwh.size() > 0) {
                                        Item item = itemRepository.selectById(inventoryItem.getItemId());
                                        System.out.println(String.join("\t", Arrays.asList(priceDropIMEI.getImei(),
                                                        inventoryItem.getItemId() + "", item.getBrand(), item.getModelName(), item.getModelNumber(),
                                                        inventoryItem.getFofoId() + "", customRetailer.getBusinessName(),
                                                        inventoryItem.getCreateTimestamp().format(dtf), priceDrop.getAffectedOn().format(dtf),
                                                        priceDropIMEI.getUpdateTimestamp().format(dtf),
                                                        inventoryItem.getUpdateTimestamp().format(dtf), priceDrop.getAutoPartnerPayout() + "",
                                                        inventoryItem.getLastScanType().equals(ScanType.DOA_OUT) + "")));
                                }
                        }
                }
        }

        public void toffeeRollback() throws Exception {
                toffeeService.cancelPolicyCopy("110143521986");
                toffeeService.getOrderId("110143521986");
        }

        public void attachToffeeInvoices() throws Exception {
                /*
                 * LOGGER.info("Insurance Sum Summary --- {}",
                 * insurancePolicyRepository.selectAmountSumGroupByRetailerId(LocalDateTime.MIN,
                 * LocalDateTime.MAX)); LOGGER.info("Insurance Qty Summary --- {}",
                 * insurancePolicyRepository.selectQtyGroupByRetailerId(LocalDateTime.MIN,
                 * LocalDateTime.MAX)); LOGGER.info("SmartPhone Amount Summary --- {}",
                 * fofoOrderItemRepository.selectSumAmountGroupByRetailer(LocalDateTime.MIN,
                 * LocalDateTime.MAX, 0, true)); LOGGER.info("Smartphone Qty Summary --- {}",
                 * fofoOrderItemRepository.selectQtyGroupByRetailer(LocalDateTime.MIN,
                 * LocalDateTime.MAX, 0, true));
                 */
                List<InsurancePolicy> insurancePolicies = insurancePolicyRepository.selectAllByProviderId(3,
                                Optional.of(false));
                for (InsurancePolicy insurancePolicy : insurancePolicies) {
                        String invoiceNumber = insurancePolicy.getInvoiceNumber();
                        FofoOrder fofoOrder = fofoOrderRepository.selectByInvoiceNumber(invoiceNumber);
                        PdfModel pdfModel = orderService.getInvoicePdfModel(fofoOrder.getId());
                        java.io.ByteArrayOutputStream byteArrayOutputStream = new java.io.ByteArrayOutputStream();
                        PdfUtils.generateAndWrite(Arrays.asList(pdfModel), byteArrayOutputStream);
                        String pdfInvoiceString = "data:application/pdf;base64,"
                                        + Base64.getEncoder().encodeToString(byteArrayOutputStream.toByteArray());
                        boolean attached = toffeeService.attachInvoice(insurancePolicy.getPolicyNumber().split("#")[1],
                                        pdfInvoiceString);
                        if (attached) {
                                insurancePolicy.setPosted(true);
                        }
                }
        }

        public void schemeRollback(List<String> schemeIds) throws Exception {
                List<Integer> schemeIdsInt = schemeIds.stream().map(x -> Integer.parseInt(x)).collect(Collectors.toList());
                Map<Integer, Scheme> schemesMap = schemeRepository.selectBySchemeIds(schemeIdsInt, 0, schemeIds.size()).stream()
                                .collect(Collectors.toMap(x -> x.getId(), x -> x));
                List<SchemeInOut> schemeInOuts = schemeInOutRepository.selectBySchemeIds(new HashSet<>(schemeIdsInt));
                for (SchemeInOut sio : schemeInOuts) {
                        Scheme scheme = schemesMap.get(sio.getSchemeId());
                        if (scheme.getType().equals(SchemeType.IN)) {

                        } else if (scheme.getType().equals(SchemeType.OUT)) {
                                InventoryItem inventoryItem = inventoryItemRepository.selectById(sio.getInventoryItemId());
                                List<ScanRecord> sr = scanRecordRepository.selectByInventoryItemId(sio.getInventoryItemId());
                                ScanRecord scanRecord = sr.stream().filter(x -> x.getType().equals(ScanType.SALE))
                                                .max((x1, x2) -> x1.getCreateTimestamp().compareTo(x2.getCreateTimestamp())).get();
                                if (scanRecord.getCreateTimestamp().isAfter(scheme.getEndDateTime())
                                                || scanRecord.getCreateTimestamp().isBefore(scheme.getStartDateTime())) {
                                        sio.setRolledBackTimestamp(LocalDateTime.now());
                                        FofoOrder fofoOrder = fofoOrderRepository.selectByOrderId(scanRecord.getOrderId());
                                        String rollbackReason = "Scheme reversed for "
                                                        + itemRepository.selectById(inventoryItem.getItemId()).getItemDescription() + "/Inv - "
                                                        + fofoOrder.getInvoiceNumber();
                                        walletService.rollbackAmountFromWallet(scanRecord.getFofoId(), sio.getAmount(),
                                                        scanRecord.getOrderId(), WalletReferenceType.SCHEME_OUT, rollbackReason,
                                                        LocalDateTime.now());
                                        System.out.printf("Amount %f,SchemeId %d,Reason %s\n", sio.getAmount(), sio.getSchemeId(),
                                                        rollbackReason);
                                }
                        }
                }
                // throw new Exception();
        }

        public void checkfocusedModelInPartnerStock() throws Exception {

                List<Integer> fofoIds = fofoStoreRepository.selectAll().stream().filter(x -> x.isActive()).map(x -> x.getId())
                                .collect(Collectors.toList());
                Map<Integer, Map<Integer, List<SaholicCIS>>> warehouseItemAvailabilityMap = saholicInventoryService
                                .getSaholicStock();
                Map<Integer, String> warehouseMap = ProfitMandiConstants.WAREHOUSE_MAP;
                Map<Integer, FofoReportingModel> partnerIdSalesHeadersMap = this.getPartnerIdSalesHeaders();

                Map<Integer, Map<Integer, List<SaholicPOItem>>> warehousePoItemAvailabilityMap = saholicInventoryService
                                .getSaholicPOItems();
                Map<Integer, List<FocusedModelShortageModel>> focusedModelShortageReportMap = new HashMap<>();
                for (Integer fofoId : fofoIds) {
                        List<FocusedModelShortageModel> focusedModelShortageList = new ArrayList<>();
                        focusedModelShortageReportMap.put(fofoId, focusedModelShortageList);
                        CustomRetailer customRetailer = retailerService.getFofoRetailer(fofoId);
                        Map<Integer, Integer> processingOrderMap = null;
                        Map<Integer, Integer> catalogIdAndQtyMap = null;
                        Map<Integer, Integer> grnPendingOrdersMap = null;

                        Map<Integer, Integer> currentInventorySnapshot = currentInventorySnapshotRepository.selectByFofoId(fofoId)
                                        .stream().collect(Collectors.toMap(x -> x.getItemId(), x -> x.getAvailability()));

                        if (!currentInventorySnapshot.isEmpty()) {
                                catalogIdAndQtyMap = itemRepository.selectByIds(currentInventorySnapshot.keySet()).stream()
                                                .collect(Collectors.groupingBy(x -> x.getCatalogItemId(),
                                                                Collectors.summingInt(x -> currentInventorySnapshot.get(x.getId()))));

                        }

                        Map<Integer, Integer> grnPendingOrders = orderRepository.selectPendingGrnOrders(fofoId).stream()
                                        .collect(Collectors.groupingBy(x -> x.getLineItem().getItemId(),
                                                        Collectors.summingInt(x -> x.getLineItem().getQuantity())));
                        if (!grnPendingOrders.isEmpty()) {
                                grnPendingOrdersMap = itemRepository.selectByIds(grnPendingOrders.keySet()).stream()
                                                .collect(Collectors.groupingBy(x -> x.getCatalogItemId(),
                                                                Collectors.summingInt(x -> grnPendingOrders.get(x.getId()))));

                        }

                        Map<Integer, Integer> processingOrder = orderRepository.selectOrders(fofoId, orderStatusList).stream()
                                        .collect(Collectors.groupingBy(x -> x.getLineItem().getItemId(),
                                                        Collectors.summingInt(x -> x.getLineItem().getQuantity())));
                        if (!processingOrder.isEmpty()) {
                                processingOrderMap = itemRepository.selectByIds(processingOrder.keySet()).stream()
                                                .collect(Collectors.groupingBy(x -> x.getCatalogItemId(),
                                                                Collectors.summingInt(x -> processingOrder.get(x.getId()))));

                        }

                        List<String> brands = mongoClient.getMongoBrands(fofoId, null, 3).stream().map(x -> (String) x.get("name"))
                                        .collect(Collectors.toList());

                        List<Integer> regionIds = partnerRegionRepository.selectByfofoId(fofoId).stream().map(x -> x.getRegionId())
                                        .collect(Collectors.toList());
                        LOGGER.info("regionIds" + regionIds);
                        if (regionIds.size() == 0) {
                                LOGGER.info("No region found for partner {}", fofoId);
                                continue;
                        }
                        Map<Integer, Optional<Integer>> focusedCatalogIdAndQtyMap = focusedModelRepository
                                        .selectAllByRegionIds(regionIds).stream().collect(Collectors.groupingBy(FocusedModel::getCatalogId,
                                                        Collectors.mapping(FocusedModel::getObsMinimumQty, Collectors.maxBy(Integer::compareTo))));

                        LOGGER.info("focusedCatalogIdAndQtyMap" + focusedCatalogIdAndQtyMap);

                        for (Map.Entry<Integer, Optional<Integer>> entry : focusedCatalogIdAndQtyMap.entrySet()) {
                                int minQty = entry.getValue().get();
                                int inStockQty = 0;
                                int processingQty = 0;
                                int grnPendingQty = 0;
                                int allColorNetAvailability = 0;
                                int allColorPoAvailability = 0;
                                if (processingOrderMap != null) {
                                        processingQty = (processingOrderMap.get(entry.getKey()) == null) ? 0
                                                        : processingOrderMap.get(entry.getKey());

                                }
                                if (grnPendingOrdersMap != null) {
                                        grnPendingQty = (grnPendingOrdersMap.get(entry.getKey()) == null) ? 0
                                                        : grnPendingOrdersMap.get(entry.getKey());

                                }
                                if (catalogIdAndQtyMap != null) {
                                        inStockQty = (catalogIdAndQtyMap.get(entry.getKey()) == null) ? 0
                                                        : catalogIdAndQtyMap.get(entry.getKey());

                                }

                                int grnStockQty = grnPendingQty + inStockQty;
                                int totalQty = processingQty + grnPendingQty + inStockQty;

                                int shortageQty = minQty - totalQty;
                                List<Item> item = itemRepository.selectAllByCatalogItemId(entry.getKey());
                                FofoStore fofoStore = fofoStoreRepository.selectByRetailerId(fofoId);

                                Map<Integer, List<SaholicCIS>> itemAvailabilityMap = warehouseItemAvailabilityMap
                                                .get(fofoStore.getWarehouseId());

                                Map<Integer, List<SaholicPOItem>> poItemAvailabilityMap = warehousePoItemAvailabilityMap
                                                .get(fofoStore.getWarehouseId());

                                for (Item it : item) {
                                        List<SaholicCIS> currentAvailability = null;
                                        List<SaholicPOItem> poItemAvailability = null;
                                        if (itemAvailabilityMap != null) {
                                                currentAvailability = itemAvailabilityMap.get(it.getId());
                                        }

                                        if (poItemAvailabilityMap != null) {
                                                poItemAvailability = poItemAvailabilityMap.get(it.getId());
                                        }
                                        if (currentAvailability != null) {
                                                allColorNetAvailability += currentAvailability.stream()
                                                                .collect(Collectors.summingInt(SaholicCIS::getNetavailability));
                                        }

                                        if (poItemAvailability != null) {
                                                allColorPoAvailability += poItemAvailability.stream()
                                                                .collect(Collectors.summingInt(SaholicPOItem::getUnfulfilledQty));
                                        }

                                }

                                FocusedModelShortageModel fm = new FocusedModelShortageModel();
                                fm.setFofoId(fofoId);
                                fm.setStoreCode(fofoStore.getCode());
                                fm.setStoreName(customRetailer.getBusinessName());
                                fm.setBrandName(item.get(0).getBrand());
                                fm.setModelName(item.get(0).getModelName());
                                fm.setModelNumber(item.get(0).getModelNumber());
                                fm.setGrnStockQty(grnStockQty);
                                fm.setPendingIndentQty(processingQty);
                                fm.setShortageQty(shortageQty);
                                fm.setPoAvailabitiy(allColorPoAvailability);
                                fm.setWarehouseName(warehouseMap.get(customRetailer.getWarehouseId()));
                                fm.setStateManager(partnerIdSalesHeadersMap.get(fofoId).getRegionalManager());
                                fm.setTerritoryManager(partnerIdSalesHeadersMap.get(fofoId).getTerritoryManager());
                                fm.setItemName(item.get(0).getBrand() + item.get(0).getModelNumber() + item.get(0).getModelName());
                                fm.setAvailabitiy(allColorNetAvailability);

                                focusedModelShortageList.add(fm);
                        }

                        /*
                         * if (!focusedModelShortageList.isEmpty()) { String subject = "Stock Alert";
                         * String messageText = this.getMessage(focusedModelShortageList);
                         * 
                         * this.sendMailWithAttachments(subject, messageText,
                         * customRetailer.getEmail()); String notificationMessage =
                         * this.getNotificationMessage(focusedModelShortageList);
                         * 
                         * LOGGER.info("notificationMessage" + notificationMessage);
                         * 
                         * SendNotificationModel sendNotificationModel = new SendNotificationModel();
                         * sendNotificationModel.setCampaignName("Stock Alert");
                         * sendNotificationModel.setTitle("Alert");
                         * sendNotificationModel.setMessage(notificationMessage);
                         * sendNotificationModel.setType("url"); sendNotificationModel.setUrl(
                         * "https://app.smartdukaan.com/pages/home/notifications");
                         * sendNotificationModel.setExpiresat(LocalDateTime.now().plusDays(2));
                         * sendNotificationModel.setMessageType(MessageType.notification); int userId =
                         * userAccountRepository.selectUserIdByRetailerId(fofoId);
                         * sendNotificationModel.setUserIds(Arrays.asList(userId));
                         * notificationService.sendNotification(sendNotificationModel);
                         * 
                         * }
                         */

                }
                if (!focusedModelShortageReportMap.isEmpty()) {
                        String fileName = "Stock Alert-" + FormattingUtils.formatDate(LocalDateTime.now()) + ".csv";
                        Map<String, Set<Integer>> storeGuyMap = csService.getAuthUserPartnerIdMapping();
                        Map<String, List<List<?>>> emailRowsMap = new HashMap<>();

                        focusedModelShortageReportMap.entrySet().forEach(x -> {
                                storeGuyMap.entrySet().forEach(y -> {

                                        if (y.getValue().contains(x.getKey())) {
                                                if (!emailRowsMap.containsKey(y.getKey())) {
                                                        emailRowsMap.put(y.getKey(), new ArrayList<>());
                                                }
                                                List<List<? extends Serializable>> fms = x.getValue().stream()
                                                                .map(r -> Arrays.asList(r.getStoreCode(), r.getStoreName(), r.getBrandName(),
                                                                                r.getModelName(), r.getModelNumber(), r.getWarehouseName(), r.getStateManager(),
                                                                                r.getTerritoryManager(), r.getPendingIndentQty(), r.getGrnStockQty(),
                                                                                r.getShortageQty(), r.getAvailabitiy()))
                                                                .collect(Collectors.toList());
                                                emailRowsMap.get(y.getKey()).addAll(fms);

                                        }

                                });

                        });

                        List<String> headers = Arrays.asList("Store Code", "Store Name", "Brand", "Model Name", "Model Number",
                                        "Warehouse Name", "State Manager", "Territory Manager", "Pending Indent", "InStock", "Shortage Qty",
                                        "Availability");
                        emailRowsMap.entrySet().forEach(entry -> {

                                ByteArrayOutputStream baos = null;
                                try {
                                        baos = FileUtil.getCSVByteStream(headers, entry.getValue());
                                } catch (Exception e2) {
                                        e2.printStackTrace();
                                }
                                String[] sendToArray = new String[] {

                                                entry.getKey()

                                };

                                try {
                                        Utils.sendMailWithAttachment(googleMailSender, sendToArray, null, "Stock Alert", "PFA", fileName,
                                                        new ByteArrayResource(baos.toByteArray()));
                                } catch (Exception e1) { // TODO Auto-generated catch block
                                        e1.printStackTrace();
                                }

                        });
                }
        }

        private String getNotificationMessage(List<FocusedModelShortageModel> focusedModelShortageModel) {
                StringBuilder sb = new StringBuilder();
                sb.append("Focused Model Shortage in Your Stock : \n");
                for (FocusedModelShortageModel entry : focusedModelShortageModel) {

                        sb.append(entry.getItemName() + "-" + entry.getShortageQty());
                        sb.append(String.format("%n", ""));
                }
                return sb.toString();
        }

        private void sendMailWithAttachments(String subject, String messageText, String email) throws Exception {
                MimeMessage message = mailSender.createMimeMessage();
                MimeMessageHelper helper = new MimeMessageHelper(message, true);

                helper.setSubject(subject);
                helper.setText(messageText, true);
                helper.setTo(email);
                InternetAddress senderAddress = new InternetAddress("noreply@smartdukaan.com", "Smartdukaan Alerts");
                helper.setFrom(senderAddress);
                mailSender.send(message);

        }

        private String getMessage(List<FocusedModelShortageModel> focusedModelShortageModel) {
                StringBuilder sb = new StringBuilder();
                sb.append("<html><body><p>Alert</p><p>Focused Model Shortage in Your Stock:-</p>"
                                + "<br/><table style='border:1px solid black ;padding: 5px';>");
                sb.append("<tbody>\n" + "                                       <tr>\n"
                                + "                                             <th style='border:1px solid black;padding: 5px'>Item</th>\n"
                                + "                                             <th style='border:1px solid black;padding: 5px'>Shortage Qty</th>\n"
                                + "                                     </tr>");
                for (FocusedModelShortageModel entry : focusedModelShortageModel) {

                        sb.append("<tr>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>" + entry.getItemName() + "</td>");

                        sb.append("<td style='border:1px solid black;padding: 5px'>" + entry.getShortageQty() + "</td>");

                        sb.append("</tr>");

                }

                sb.append("</tbody></table></body></html>");

                return sb.toString();
        }

        public void notifyLead() throws Exception {
                List<Lead> leadsToNotify = leadRepository.selectLeadsScheduledBetweenDate(null,
                                LocalDateTime.now().minusDays(15), LocalDateTime.now().plusHours(4));
                Map<Integer, String> authUserEmailMap = authRepository.selectAllActiveUser().stream()
                                .collect(Collectors.toMap(x -> x.getId(), x -> x.getEmailId()));
                LOGGER.info("authUserEmailMap {}", authUserEmailMap);
                Map<String, Integer> dtrEmailMap = dtrUserRepository
                                .selectAllByEmailIds(new ArrayList<>(authUserEmailMap.values())).stream()
                                .collect(Collectors.toMap(x -> x.getEmailId(), x -> x.getId()));

                LOGGER.info("dtrEmailMap {}", dtrEmailMap);

                Map<Integer, Integer> authUserKeyMap = new HashMap<>();

                for (Map.Entry<Integer, String> authUserEmail : authUserEmailMap.entrySet()) {
                        int authId = authUserEmail.getKey();
                        String email = authUserEmail.getValue();
                        authUserKeyMap.put(authId, dtrEmailMap.get(email));
                }
                LOGGER.info("authUserKeyMap", authUserKeyMap);
                LOGGER.info("leadsToNotify {}", leadsToNotify);

                String templateMessage = "Lead followup for %s %s, %s, %s is due by %s";
                for (Lead lead : leadsToNotify) {
                        if (authUserKeyMap.get(lead.getAssignTo()) == null) {
                                LOGGER.info("Assignee no longer part of system {}", lead.getAssignTo());
                                continue;
                        }
                        String notificationMessage = String.format(templateMessage, lead.getFirstName(), lead.getLastName(),
                                        lead.getAddress(), lead.getLeadMobile(), leadTimeFormatter.format(lead.getScheduledTimestamp()));
                        SendNotificationModel sendNotificationModel = new SendNotificationModel();
                        sendNotificationModel.setCampaignName("Lead Reminder");
                        sendNotificationModel.setTitle("Leads followup Reminder");
                        sendNotificationModel.setMessage(notificationMessage);
                        sendNotificationModel.setType("url");
                        sendNotificationModel.setUrl("https://app.smartdukaan.com/pages/home/leadUpdate?leadId=" + lead.getId());
                        sendNotificationModel.setExpiresat(LocalDateTime.now().plusDays(2));
                        sendNotificationModel.setMessageType(MessageType.reminder);
                        sendNotificationModel.setUserIds(Arrays.asList(authUserKeyMap.get(lead.getAssignTo())));
                        System.out.println(sendNotificationModel);
                        notificationService.sendNotification(sendNotificationModel);
                }
        }

        public void notifyVisits() throws Exception {
                List<FranchiseeVisit> franchiseeVisits = franchiseeVisitRepository
                                .selectVisitsScheduledBetweenDate(LocalDateTime.now().minusDays(15), LocalDateTime.now().plusHours(4));
                Map<Integer, String> authUserEmailMap = authRepository.selectAllActiveUser().stream()
                                .collect(Collectors.toMap(x -> x.getId(), x -> x.getEmailId()));
                Map<String, Integer> dtrEmailMap = dtrUserRepository
                                .selectAllByEmailIds(new ArrayList<>(authUserEmailMap.values())).stream()
                                .collect(Collectors.toMap(x -> x.getEmailId(), x -> x.getId()));
                Map<Integer, Integer> authUserKeyMap = new HashMap<>();

                for (Map.Entry<Integer, String> authUserEmail : authUserEmailMap.entrySet()) {
                        int authId = authUserEmail.getKey();
                        String email = authUserEmail.getValue();
                        authUserKeyMap.put(authId, dtrEmailMap.get(email));
                }
                String visitTemplate = "Planned visit to franchisee %s is due by %s";
                String followupTemplate = "Lead followup for franchisee %s is due by %s";
                DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("MMM 7, EEEE h:m a");
                for (FranchiseeVisit visit : franchiseeVisits) {
                        if (authUserKeyMap.containsKey(visit.getAuthId())) {
                                continue;
                        }
                        SendNotificationModel sendNotificationModel = new SendNotificationModel();
                        String message = null;
                        if (visit.getFranchiseActivityId() == 0) {
                                message = String.format(visitTemplate, visit.getPartnerName(),
                                                timeFormatter.format(visit.getSchelduleTimestamp()));
                                sendNotificationModel.setCampaignName("Franchisee visit Reminder");
                        } else {
                                message = String.format(followupTemplate, visit.getPartnerName(),
                                                timeFormatter.format(visit.getSchelduleTimestamp()));
                                sendNotificationModel.setCampaignName("Franchisee followup Reminder");
                        }
                        sendNotificationModel.setMessage(message);
                        sendNotificationModel.setType("url");
                        sendNotificationModel.setUrl("https://app.smartdukaan.com/pages/home/notifications");
                        sendNotificationModel.setExpiresat(LocalDateTime.now().plusDays(2));
                        sendNotificationModel.setMessageType(MessageType.reminder);
                        sendNotificationModel.setUserIds(Arrays.asList(authUserKeyMap.get(visit.getAuthId())));
                        notificationService.sendNotification(sendNotificationModel);
                }
        }

        public void ticketClosed() throws Exception {

                List<Ticket> tickets = ticketRepository.selectAllNotClosedTicketsWithStatus(ActivityType.RESOLVED);
                for (Ticket ticket : tickets) {
                        if (ticket.getUpdateTimestamp().toLocalDate().isBefore(LocalDate.now().minusDays(7))) {
                                ticket.setCloseTimestamp(LocalDateTime.now());
                                ticket.setLastActivity(ActivityType.RESOLVED_ACCEPTED);
                                ticket.setUpdateTimestamp(LocalDateTime.now());
                                ticketRepository.persist(ticket);
                        }
                }

        }

        public void checkValidateReferral() throws Exception {

                List<Refferal> referrals = refferalRepository.selectByStatus(RefferalStatus.pending);
                LOGGER.info("referrals" + referrals);
                if (!referrals.isEmpty()) {
                        String subject = "Referral Request";
                        String messageText = this.getMessageForReferral(referrals);

                        MimeMessage message = mailSender.createMimeMessage();
                        MimeMessageHelper helper = new MimeMessageHelper(message, true);
                        String[] email = { "kamini.sharma@smartdukaan.com", "tarun.verma@smartdukaan.com" };
                        helper.setSubject(subject);
                        helper.setText(messageText, true);
                        helper.setTo(email);
                        InternetAddress senderAddress = new InternetAddress("noreply@smartdukaan.com", "Smartdukaan Alerts");
                        helper.setFrom(senderAddress);
                        mailSender.send(message);

                }
        }

        private String getMessageForReferral(List<Refferal> referrals) {
                StringBuilder sb = new StringBuilder();
                sb.append("<html><body><p>Alert</p><p>Pending Referrals:-</p>"
                                + "<br/><table style='border:1px solid black ;padding: 5px';>");
                sb.append("<tbody>\n" + "                                       <tr>\n"
                                + "                                             <th style='border:1px solid black;padding: 5px'>RefereeName</th>\n"
                                + "                                             <th style='border:1px solid black;padding: 5px'>Referee Email</th>\n"
                                + "                                             <th style='border:1px solid black;padding: 5px'>Referral Name</th>\n"
                                + "                                             <th style='border:1px solid black;padding: 5px'>Refferal Mobile</th>\n"
                                + "                                             <th style='border:1px solid black;padding: 5px'>city</th>\n"
                                + "                                             <th style='border:1px solid black;padding: 5px'>state</th>\n"
                                + "                                     </tr>");
                for (Refferal entry : referrals) {

                        sb.append("<tr>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>" + entry.getRefereeName() + "</td>");

                        sb.append("<td style='border:1px solid black;padding: 5px'>" + entry.getRefereeEmail() + "</td>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>" + entry.getFirstName() + "</td>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>" + entry.getMobile() + "</td>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>" + entry.getCity() + "</td>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>" + entry.getState() + "</td>");

                        sb.append("</tr>");

                }

                sb.append("</tbody></table></body></html>");

                return sb.toString();
        }

        public void reverseWallet() throws Exception {
                LocalDate localDate = LocalDate.of(2020, 10, 28);
                List<UserWalletHistory> uwhList = userWalletHistoryRepository.selectAllByDateType(localDate.atStartOfDay(),
                                localDate.plusDays(1).atStartOfDay(),
                                Arrays.asList(WalletReferenceType.SCHEME_IN, WalletReferenceType.SCHEME_OUT));
                for (UserWalletHistory uwh : uwhList) {
                        if (uwh.getBusinessTimestamp().getMonth().equals(Month.SEPTEMBER)) {
                                UserWallet uw = userWalletRepository.selectById(uwh.getWalletId());
                                // LOGGER.info("UWH - {}", uwh);
                                // amount += uwh.getAmount();
                                // System.out.println("Amount is - " + amount);
                                // walletService.rollbackAmountFromWallet(uw.getUserId(), uwh.getAmount(),
                                // uwh.getReference(), uwh.getReferenceType(), "Margin reversal for error prone
                                // run", uwh.getBusinessTimestamp());
                                int orderId = uwh.getReference();
                                FofoOrder fofoOrder = fofoOrderRepository.selectByOrderId(orderId);
                                int inventoryItemId = 0;
                                // fofoOrderRepository.delete(fofoOrder);
                                List<FofoOrderItem> fofoOrderItems = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());
                                /*
                                 * List<PaymentOptionTransaction> paymentOptionTransactions =
                                 * paymentOptionTransactionRepository.selectByReferenceIdAndType(fofoOrder.getId
                                 * (), PaymentOptionReferenceType.ORDER); for(PaymentOptionTransaction
                                 * paymentOptionTransaction : paymentOptionTransactions) {
                                 * //paymentOptionTransactionRepository.delete(paymentOptionTransaction); }
                                 */
                                for (FofoOrderItem foi : fofoOrderItems) {
                                        // fofoOrderItemRepository.delete(foi);
                                        List<FofoLineItem> flis = fofoLineItemRepository.selectByFofoOrderItemId(foi.getId());
                                        for (FofoLineItem fli : flis) {
                                                // fofoLineItemRepository.delete(fli);
                                                inventoryItemId = fli.getInventoryItemId();
                                        }
                                }
                                List<SchemeInOut> schemeInOuts = schemeInOutRepository.selectByInventoryItemIds(
                                                java.util.stream.Stream.of(inventoryItemId).collect(Collectors.toSet()));
                                for (SchemeInOut sio : schemeInOuts) {
                                        if (sio.getCreateTimestamp().toLocalDate().equals(localDate)) {
                                                LOGGER.info("SIO - {}", sio);
                                                sio.setRolledBackTimestamp(LocalDateTime.now());
                                        }
                                }

                        }
                }

        }

        public void partnerProblemAlert() throws Exception {
                LocalDateTime curDate = LocalDate.now().atStartOfDay();
                Map<Integer, Double> lmtdSale = fofoOrderItemRepository.selectSumMopGroupByRetailer(
                                curDate.withDayOfMonth(1).minusMonths(1), curDate.with(LocalTime.MAX).minusMonths(1), 0, false);
                Map<Integer, Double> mtdSales = fofoOrderItemRepository.selectSumMopGroupByRetailer(curDate.withDayOfMonth(1),
                                curDate.with(LocalTime.MAX), 0, false);
                Map<Integer, PartnerDailyInvestment> pdi = partnerDailyInvestmentRepository.selectAll(LocalDate.now()).stream()
                                .collect(Collectors.toMap(x -> x.getFofoId(), x -> x));

                for (Entry<Integer, Double> ls : lmtdSale.entrySet()) {

                        double lmtdTwentyPercentSale = ls.getValue() * 0.2;

                        LOGGER.info("lmtdTwentyPercentSale" + lmtdTwentyPercentSale);

                        double mtdSale = mtdSales.get(ls.getKey()) == null ? 0 : mtdSales.get(ls.getKey());

                        LOGGER.info("mtdSale" + mtdSale);

                        double totalSixtyPercentInvestment = pdi.get(ls.getKey()) == null ? 0
                                        : pdi.get(ls.getKey()).getTotalInvestment() * 0.6;

                        LOGGER.info("totalSixtyPercentInvestment" + totalSixtyPercentInvestment);

                        double stockInvestment = pdi.get(ls.getKey()) == null ? 0 : pdi.get(ls.getKey()).getInStockAmount();

                        LOGGER.info("stockInvestment" + stockInvestment);

                        boolean Investmentvalue = partnerInvestmentService.isInvestmentBelow(ls.getKey(), 25);

                        PartnerProblem partnerProblem = partnerProblemRepository.selectByFofoId(ls.getKey());

                        if (partnerProblem == null) {
                                partnerProblem = new PartnerProblem();
                                partnerProblem.setFofoId(ls.getKey());
                                if (mtdSale < lmtdTwentyPercentSale) {
                                        partnerProblem.setMtd(1);
                                }
                                if (Investmentvalue) {
                                        partnerProblem.setInvestment(1);
                                }

                                if (stockInvestment < totalSixtyPercentInvestment) {
                                        partnerProblem.setInvestment(1);
                                }

                                partnerProblemRepository.persist(partnerProblem);
                        } else {
                                if (mtdSale < lmtdTwentyPercentSale) {
                                        partnerProblem.setMtd(partnerProblem.getMtd() + 1);

                                } else {
                                        partnerProblem.setMtd(0);

                                }
                                if (Investmentvalue) {
                                        partnerProblem.setInvestment(partnerProblem.getInvestment() + 1);
                                } else {
                                        partnerProblem.setInvestment(0);

                                }
                                if (stockInvestment < totalSixtyPercentInvestment) {
                                        partnerProblem.setStockInvestment(partnerProblem.getStockInvestment() + 1);
                                } else {
                                        partnerProblem.setStockInvestment(0);
                                }

                        }

                }

                List<PartnerProblem> partnerProblems = partnerProblemRepository.selectAll().stream()
                                .filter(x -> x.getMtd() + x.getInvestment() + x.getStockInvestment() > 0).collect(Collectors.toList());

                partnerProblems = partnerProblems.stream().sorted((x1, x2) -> {
                        return x1.getMtd() + x1.getInvestment() + x1.getStockInvestment() < x2.getMtd() + x2.getInvestment()
                                        + x2.getStockInvestment() ? 1 : -1;
                }).collect(Collectors.toList());

                Map<Integer, PartnerProblem> partnerProblemMap = partnerProblems.stream().sorted((x1, x2) -> {
                        return x1.getMtd() + x1.getInvestment() + x1.getStockInvestment() < x2.getMtd() + x2.getInvestment()
                                        + x2.getStockInvestment() ? 1 : -1;
                }).collect(Collectors.toMap(x -> x.getFofoId(), x -> x));

                Map<Integer, CustomRetailer> customRetailers = retailerService.getAllFofoRetailers();

                List<Integer> assignTo = Arrays.asList(15, 9, 54, 53);

                Map<Integer, AuthUser> assignAuthUserMap = authRepository.selectAllAuthUserByIds(assignTo).stream()
                                .collect(Collectors.toMap(x -> x.getId(), x -> x));

                List<String> sendTo = Arrays.asList("kamini.sharma@smartdukaan.com", "tarun.verma@smartdukaan.com",
                                "niranjan.kala@smartdukaan.com", "sm@smartdukaan.com", "tejbeer.kaur@shop2020.in");
                LOGGER.info("partnerProblem" + partnerProblems);
                StringBuilder sb = new StringBuilder();
                sb.append("<htl><body>");
                sb.append(
                                "<p>Number against MTD or Investment are the count of days the MTD is low VS LMTD OR Investment is below 75%.</p><br/><p>These partners needs immediate attention.</p><br/><table style='border:1px solid black';cellspacing=0>");
                sb.append("<tbody>\n" + "           <tr>"
                                + "                                             <th style='border:1px solid black;padding: 5px'>Partner Name</th>"
                                + "                         <th style='border:1px solid black;padding: 5px'>Assign TO</th>"
                                + "                                             <th style='border:1px solid black;padding: 5px'>Mtd</th>"
                                + "                                             <th style='border:1px solid black;padding: 5px'>Investment</th>"
                                + "                                             <th style='border:1px solid black;padding: 5px'>Stock</th>"
                                + "                                             <th style='border:1px solid black;padding: 5px'>Manager</th>"

                                + "                                     </tr>");

                for (PartnerProblem pp : partnerProblems) {
                        int value = pp.getFofoId() % 4;

                        Map<EscalationType, AuthUser> authUserMap = csService.getAuthUserAndEsclationByPartnerId(pp.getFofoId());
                        LOGGER.info("authUserMap" + authUserMap);
                        sb.append("<tr>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>"
                                        + customRetailers.get(pp.getFofoId()).getBusinessName() + "</td>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>"
                                        + assignAuthUserMap.get(assignTo.get(value)).getName() + "</td>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>" + pp.getMtd() + "</td>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>" + pp.getInvestment() + "</td>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>" + pp.getStockInvestment() + "</td>");
                        sb.append("<td style='border:1px solid black;padding: 5px'>"
                                        + (authUserMap.get(EscalationType.L1) == null ? "N/A"
                                                        : authUserMap.get(EscalationType.L1).getFirstName())
                                        + " ," + (authUserMap.get(EscalationType.L2) == null ? "N/A"
                                                        : authUserMap.get(EscalationType.L2).getFirstName())
                                        + "</td>");

                        sb.append("</tr>");
                }
                sb.append("</tbody></table><br><br>");
                String subject = "Partner Problem Alert!";
                String[] email = sendTo.toArray(new String[sendTo.size()]);

                this.sendMailHtmlFormat(email, sb.toString(), null, subject);

                Map<Integer, List<Integer>> authUserPartnerMapping = csService.getAuthUserIdPartnerIdMapping();

                for (Entry<Integer, List<Integer>> authUserPartner : authUserPartnerMapping.entrySet()) {
                        AuthUser authUser = authRepository.selectById(authUserPartner.getKey());
                        for (Integer patnerId : authUserPartner.getValue()) {
                                if (partnerProblemMap.get(patnerId) != null) {

                                        StringBuilder sbbuilder = new StringBuilder();
                                        sbbuilder.append("<hml><body>");
                                        sb.append(
                                                        "<p>Number against MTD or Investment are the count of days the MTD is low VS LMTD OR Investment is below 75%.</p><br/><p>These partners needs immediate attention.</p><br/><table style='border:1px solid black';cellspacing=0>");
                                        sbbuilder.append("<tbody>\n" + "            <tr>"
                                                        + "                                             <th style='border:1px solid black;padding: 5px'>Partner Name</th>"
                                                        + "                                             <th style='border:1px solid black;padding: 5px'>Mtd</th>"
                                                        + "                                             <th style='border:1px solid black;padding: 5px'>Investment</th>"
                                                        + "                                             <th style='border:1px solid black;padding: 5px'>Stock</th>"

                                                        + "                                     </tr>");

                                        for (Integer partnerId : authUserPartner.getValue()) {
                                                if (partnerProblemMap.get(partnerId) != null) {
                                                        PartnerProblem pp = partnerProblemMap.get(partnerId);
                                                        sbbuilder.append("<tr>");
                                                        sbbuilder.append("<td style='border:1px solid black;padding: 5px'>"
                                                                        + customRetailers.get(pp.getFofoId()).getBusinessName() + "</td>");
                                                        sbbuilder
                                                                        .append("<td style='border:1px solid black;padding: 5px'>" + pp.getMtd() + "</td>");
                                                        sbbuilder.append(
                                                                        "<td style='border:1px solid black;padding: 5px'>" + pp.getInvestment() + "</td>");
                                                        sbbuilder.append("<td style='border:1px solid black;padding: 5px'>"
                                                                        + pp.getStockInvestment() + "</td>");

                                                        sbbuilder.append("</tr>");
                                                }

                                        }
                                        sbbuilder.append("</tbody></table><br><br>");

                                        this.sendMailOfHtmlFormat(authUser.getEmailId(), sbbuilder.toString(), null, subject);
                                        break;
                                }

                        }
                }
        }

        private void sendMailHtmlFormat(String email[], String body, String cc[], String subject)
                        throws MessagingException, ProfitMandiBusinessException, IOException {
                MimeMessage message = mailSender.createMimeMessage();
                MimeMessageHelper helper = new MimeMessageHelper(message);
                helper.setSubject(subject);
                helper.setText(body, true);
                helper.setTo(email);
                if (cc != null) {
                        helper.setCc(cc);
                }
                InternetAddress senderAddress = new InternetAddress("noreply@smartdukaan.com", "Smart Dukaan");
                helper.setFrom(senderAddress);
                mailSender.send(message);
        }

        @Autowired
        WarehouseRepository warehouseRepository;

        public void getVendorWarehouses(int warehouseId) {
                LOGGER.info("Warehouses - {}", warehouseRepository.getVendorWarehouses().get(warehouseId));

        }

        public void checkImeiActivation() {

                try {
                        vivoImeiActivationService.checkImeiActivation();
                } catch (ProfitMandiBusinessException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }

        }

        public void checkItelImeiActivation(LocalDate date, Integer day) {
                LOGGER.info("Hello - {}", "hhh");

                try {
                        itelImeiActivationService.checkItelImeiActivation(date, day);
                } catch (ProfitMandiBusinessException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }

        }

        public void selectFinServiceFollowUpDateByCurrDate(LocalDate currentDate)
                        throws MessagingException, ProfitMandiBusinessException, IOException {
                LOGGER.info("selectfinServiceFollow - {}", "selectfinServiceFollowUpDateByCurrDate");

                serviceConfigService.selectFinServicePartnerfollowUpDateByCurrentDate(currentDate);

        }

        public void checkTecnoImeiActivation(LocalDate date, Integer day) {
                LOGGER.info("Hello - {}", "hhh");

                try {
                        tecnoImeiActivation.checkTecnoImeiActivation(date, day);
                } catch (ProfitMandiBusinessException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                } catch (IOException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                } catch (Exception e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                }

        }

        public void checkCancellationMargin() throws Exception {
                LocalDateTime startDate = LocalDate.of(2021, 4, 1).atStartOfDay();
                List<FofoOrder> fofoOrders = fofoOrderRepository.selectCancelledBetweenSaleDate(startDate, LocalDateTime.now());
                LOGGER.info("Total Orders =  {}", fofoOrders.size());
                for (FofoOrder fofoOrder : fofoOrders) {
                        List<UserWalletHistory> history = userWalletHistoryRepository
                                        .selectAllByreferenceIdandreferenceType(fofoOrder.getId(), WalletReferenceType.SCHEME_OUT);
                        history.addAll(userWalletHistoryRepository.selectAllByreferenceIdandreferenceType(fofoOrder.getId(),
                                        WalletReferenceType.ACTIVATION_SCHEME));
                        int walletSum = history.stream().mapToInt(x -> x.getAmount()).sum();
                        if (Math.abs(walletSum) > 1) {
                                // LOGGER.info("Cancelled invoice {}, Order Id = {}, = havent rolledback, Value
                                // = {}", fofoOrder.getInvoiceNumber(), fofoOrder.getId(), walletSum);
                                List<FofoOrderItem> fofoOrderItems = fofoOrderItemRepository.selectByOrderId(fofoOrder.getId());
                                List<FofoLineItem> flis = fofoLineItemRepository.selectByFofoOrderItemId(fofoOrderItems.get(0).getId());
                                FofoLineItem fli = flis.get(0);
                                if (StringUtils.isEmpty(fli.getSerialNumber()))
                                        continue;
                                List<SchemeInOut> schemeInOuts = schemeInOutRepository
                                                .selectByInventoryItemIds(new HashSet<>(Arrays.asList(fli.getInventoryItemId())));
                                InventoryItem inventoryItem = inventoryItemRepository.selectById(fli.getInventoryItemId());
                                double schemeSum = schemeInOuts.stream().filter(x -> x.getRolledBackTimestamp() == null)
                                                .mapToDouble(x -> x.getAmount()).sum();
                                /*
                                 * if(inventoryItem.getGoodQuantity()==1) {
                                 * LOGGER.info("GoodQty, Serial Number {}, InventoryItem = {}, Billed on {}",
                                 * inventoryItem.getSerialNumber(), inventoryItem.getId(),
                                 * inventoryItem.getUpdateTimestamp()); } else
                                 * if(inventoryItem.getBadQuantity()==1){
                                 * LOGGER.info("Bad Qty, Serial Number {}, InventoryItem = {}, Billed on {}",
                                 * inventoryItem.getSerialNumber(), inventoryItem.getId(),
                                 * inventoryItem.getUpdateTimestamp()); } else if
                                 * (inventoryItem.getLastScanType().equals(ScanType.SALE)) { LOGGER.
                                 * info("Problem Sold, Serial Number {}, InventoryItem = {}, Billed on {}",
                                 * inventoryItem.getSerialNumber(), inventoryItem.getId(),
                                 * inventoryItem.getUpdateTimestamp()); }
                                 */
                                if (inventoryItem.getLastScanType().equals(ScanType.SALE)
                                                || inventoryItem.getLastScanType().equals(ScanType.SALE_RET)) {
                                        Map<String, Double> map = schemeInOuts.stream()
                                                        .collect(
                                                                        Collectors.groupingBy(
                                                                                        x -> DateTimeFormatter.ofPattern("yyyyMMddHH")
                                                                                                        .format(x.getCreateTimestamp()) + "- " + x.getSchemeId(),
                                                                                        Collectors.summingDouble(x -> x.getAmount())));
                                        for (Map.Entry<String, Double> entry : map.entrySet()) {
                                                LOGGER.info("{} = {}", entry.getKey(), entry.getValue());
                                        }
                                        LOGGER.info("id- {}, imei- {}, lastScan = {}, Scheme sum - {}", inventoryItem.getId(),
                                                        inventoryItem.getSerialNumber(), inventoryItem.getLastScanType(), schemeSum);
                                }
                        }
                }

        }

        public static String readFileAsString(String file) throws Exception {
                String data = "";
                data = new String(Files.readAllBytes(Paths.get(file)));
                return data;
        }

        public void markDelhiveryOrderDelivered() throws ProfitMandiBusinessException, IOException {
                List<Order> orders = orderRepository.selectOrderByProviderIdAndStatus(ProfitMandiConstants.DELHIVERY_PROVIDERID,
                                OrderStatus.SHIPPED_FROM_WH);

                if (!orders.isEmpty()) {
                        Set<String> airwayBill = orders.stream().map(x -> x.getAirwayBillNumber()).collect(Collectors.toSet());

                        int arraylength = airwayBill.size();

                        if (arraylength >= 75) {

                                airwayBill = airwayBill.stream().limit(74).collect(Collectors.toSet());
                        }
                        LOGGER.info("airwayBill" + airwayBill);
                        String url = "https://track.delhivery.com/api/v1/packages/json/";

                        OkHttpClient client = new OkHttpClient();

                        Request request1 = new Request.Builder()
                                        .url(url + "?waybill=" + String.join(",", airwayBill) + "&token=" + token).get().build();

                        LOGGER.info("request1" + request1);

                        Response response = client.newCall(request1).execute();

                        LOGGER.info("jsonbj" + response.body());

                        JSONObject jsonObj = new JSONObject(response.body().string());

                        LOGGER.info("jsonObj" + jsonObj);

                        JSONArray shipmentData = jsonObj.getJSONArray("ShipmentData");
                        Set<String> airwaybillStatus = new HashSet<>();
                        for (int i = 0; i < shipmentData.length(); i++) {
                                JSONObject jsonObject = shipmentData.getJSONObject(i);
                                JSONObject shipment = jsonObject.getJSONObject("Shipment");

                                LOGGER.info("shipment" + shipment);
                                JSONObject statusDescription = shipment.getJSONObject("Status");
                                String awb = shipment.getString("AWB");

                                String status = statusDescription.getString("Status");
                                LOGGER.info("status" + status);

                                LOGGER.info("awb" + awb);
                                if (status.equals("Delivered")) {
                                        airwaybillStatus.add(awb);
                                }

                        }
                        if (!airwaybillStatus.isEmpty()) {
                                for (String aws : airwaybillStatus) {

                                        List<Order> deliverdOrders = orderRepository.selectByAirwayBillNumber(aws);
                                        for (Order dlo : deliverdOrders) {
                                                dlo.setStatus(OrderStatus.DELIVERY_SUCCESS);
                                                dlo.setStatusDescription("Order Delivered");
                                                dlo.setDeliveryTimestamp(LocalDateTime.now());
                                        }

                                        SendNotificationModel sendNotificationModel = new SendNotificationModel();
                                        sendNotificationModel.setCampaignName("Order Delivered");
                                        sendNotificationModel.setTitle("Order Delivered");
                                        sendNotificationModel.setMessage(String.format("Dear partner, your SmartDukaan ORDER " + aws
                                                        + "has been delivered to you in a safe sealed bag" + "."));
                                        sendNotificationModel.setType("url");
                                        sendNotificationModel.setUrl("https://app.smartdukaan.com/pages/home/notifications");
                                        sendNotificationModel.setExpiresat(LocalDateTime.now().plusDays(1));
                                        sendNotificationModel.setMessageType(MessageType.notification);
                                        int userId = userAccountRepository.selectUserIdByRetailerId(orders.get(0).getRetailerId());
                                        sendNotificationModel.setUserIds(Arrays.asList(userId));
                                        notificationService.sendNotification(sendNotificationModel);

                                }
                        }

                }
        }

        public void partnerWiseCreditAccount() throws Exception {

                List<FofoStore> fofoStores = fofoStoreRepository.selectActiveStores();

                for (FofoStore fs : fofoStores) {

                        if (fs.getPan() != null) {
                                AccountStatusResponseOut accountStatusResponseOut = mandiiService.getStatus(fs.getPan());

                                LOGGER.info("accountStatusResponseOut" + accountStatusResponseOut);
                                CreditAccount creditAccount = creditAccountRepository.selectByFofoIdAndGateway(fs.getId(),
                                                Gateway.MANDII);

                                if (creditAccount == null) {

                                        creditAccount = new CreditAccount();

                                        creditAccount.setFofoId(fs.getId());
                                        creditAccount.setGateway(Gateway.MANDII);

                                }

                                if (accountStatusResponseOut == null) {
                                        creditAccount.setCreditStatus(CreditStatus.UNKNOWN);
                                        creditAccount.setDescription("User company not found");

                                } else {
                                        if (accountStatusResponseOut.getSanctionLimit() != null) {
                                                creditAccount.setSanctionedAmount(accountStatusResponseOut.getSanctionLimit().floatValue());
                                        } else {
                                                creditAccount.setSanctionedAmount(0);
                                        }

                                        creditAccount.setInterestRate(accountStatusResponseOut.getRateOfInterest());
                                        if (accountStatusResponseOut.getBalanceAmount() != null) {
                                                creditAccount.setAvailableAmount(accountStatusResponseOut.getBalanceAmount().floatValue());
                                        } else {
                                                creditAccount.setAvailableAmount(0);
                                        }

                                        if (accountStatusResponseOut.getCurrentStage() != null) {
                                                creditAccount.setDescription(accountStatusResponseOut.getCurrentStage().toString());
                                        }
                                        if (accountStatusResponseOut.getStatus().equals(EligibilityStatusEnum.SANCTION_AVAILABLE)) {
                                                creditAccount.setCreditStatus(CreditStatus.SANCTIONED);
                                        } else if (accountStatusResponseOut.getStatus().equals(EligibilityStatusEnum.IN_ELIGIBLE)) {
                                                creditAccount.setCreditStatus(CreditStatus.INELIGIBLE);
                                        } else {

                                                creditAccount.setCreditStatus(CreditStatus.TO_BE_EVALUATED);
                                        }
                                }

                                creditAccount.setUpdatedOn(LocalDateTime.now());
                                creditAccountRepository.persist(creditAccount);
                        }
                }
        }

}

//2284