Subversion Repositories SmartDukaan

Rev

Rev 36269 | Rev 36303 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 36269 Rev 36289
Line 165... Line 165...
165
 
165
 
166
@Component
166
@Component
167
@Transactional(rollbackFor = {Throwable.class, ProfitMandiBusinessException.class})
167
@Transactional(rollbackFor = {Throwable.class, ProfitMandiBusinessException.class})
168
public class ScheduledTasks {
168
public class ScheduledTasks {
169
 
169
 
-
 
170
    // Lock to serialize all methods that write to sd_credit_requirement table.
-
 
171
    // Prevents deadlocks and stale-data overwrites from concurrent cron threads.
-
 
172
    public static final Object SD_CREDIT_LOCK = new Object();
-
 
173
 
170
    @Value("${oxigen.recharge.enquiry.url}")
174
    @Value("${oxigen.recharge.enquiry.url}")
171
    private String oxigenRechargeEnquiryUrl;
175
    private String oxigenRechargeEnquiryUrl;
172
 
176
 
173
    @Autowired
177
    @Autowired
174
    PurchaseMigration purchaseMigration;
178
    PurchaseMigration purchaseMigration;
Line 3799... Line 3803...
3799
 
3803
 
3800
    @Autowired
3804
    @Autowired
3801
    private SanctionRequestRepository sanctionRequestRepository;
3805
    private SanctionRequestRepository sanctionRequestRepository;
3802
 
3806
 
3803
    public void calculateInterestAccured() throws ProfitMandiBusinessException {
3807
    public void calculateInterestAccured() throws ProfitMandiBusinessException {
-
 
3808
        synchronized (SD_CREDIT_LOCK) {
3804
        List<Loan> loans = loanRepository.selectAllActiveLoan();
3809
            List<Loan> loans = loanRepository.selectAllActiveLoan();
3805
 
3810
 
3806
        for (Loan loan : loans) {
3811
            for (Loan loan : loans) {
3807
            List<LoanStatement> loanStatements = loanStatementRepository.selectByLoanId(loan.getId());
3812
                List<LoanStatement> loanStatements = loanStatementRepository.selectByLoanId(loan.getId());
3808
            Map<LoanReferenceType, Double> loanStatusAmount = loanStatements.stream().collect(groupingBy(
3813
                Map<LoanReferenceType, Double> loanStatusAmount = loanStatements.stream().collect(groupingBy(
3809
                    x -> x.getLoanReferenceType(), Collectors.summingDouble(x -> x.getAmount().doubleValue())));
3814
                        x -> x.getLoanReferenceType(), Collectors.summingDouble(x -> x.getAmount().doubleValue())));
3810
 
3815
 
3811
            // Interest starts from this date (inclusive). Under current policy (MIN_FREE_DAYS=1),
3816
                // Interest starts from this date (inclusive). Under current policy (MIN_FREE_DAYS=1),
3812
            // this is at minimum createdOn + 1 — billing day is always free.
3817
                // this is at minimum createdOn + 1 — billing day is always free.
3813
            LocalDate interestStartDate = com.spice.profitmandi.service.transaction.SDCreditServiceImpl.computeInterestStartDate(loan);
3818
                LocalDate interestStartDate = com.spice.profitmandi.service.transaction.SDCreditServiceImpl.computeInterestStartDate(loan);
3814
 
3819
 
3815
            LOGGER.info("Loan id - {}, interestStartDate {}", loan.getId(), interestStartDate);
3820
                LOGGER.info("Loan id - {}, interestStartDate {}", loan.getId(), interestStartDate);
3816
            if (!LocalDate.now().isBefore(interestStartDate)) {
3821
                if (!LocalDate.now().isBefore(interestStartDate)) {
3817
                int loanStatementId = loanStatementRepository.selectLatestLoanSatement(loan.getFofoId(), loan.getId());
3822
                    int loanStatementId = loanStatementRepository.selectLatestLoanSatement(loan.getFofoId(), loan.getId());
3818
                LOGGER.info("loanStatementId {}", loanStatementId);
3823
                    LOGGER.info("loanStatementId {}", loanStatementId);
3819
                if (loanStatementId != 0) {
3824
                    if (loanStatementId != 0) {
3820
                    this.calculateInterest(loan, loanStatusAmount, loanStatementId);
3825
                        this.calculateInterest(loan, loanStatusAmount, loanStatementId);
3821
                } else {
3826
                    } else {
3822
                    sdCreditService.addInterest(interestStartDate, LocalDate.now(), loan, loanStatusAmount);
3827
                        sdCreditService.addInterest(interestStartDate, LocalDate.now(), loan, loanStatusAmount);
-
 
3828
                    }
3823
                }
3829
                }
3824
            }
3830
            }
3825
        }
3831
        }
3826
    }
3832
    }
3827
 
3833
 
Line 3854... Line 3860...
3854
            throw new ProfitMandiBusinessException("loanstament", loanStatement.getLoanId(), "Invalid LoanId");
3860
            throw new ProfitMandiBusinessException("loanstament", loanStatement.getLoanId(), "Invalid LoanId");
3855
        }
3861
        }
3856
    }
3862
    }
3857
 
3863
 
3858
    public void loanSettlement() throws Exception {
3864
    public void loanSettlement() throws Exception {
-
 
3865
        synchronized (SD_CREDIT_LOCK) {
3859
        List<Loan> loans = loanRepository.selectAllActiveLoanForSettlement().stream().filter(x -> x.canBeSettled()).collect(toList());
3866
            List<Loan> loans = loanRepository.selectAllActiveLoanForSettlement().stream().filter(x -> x.canBeSettled()).collect(toList());
3860
        //TODO:Upto here
3867
            //TODO:Upto here
3861
        if (!loans.isEmpty()) {
3868
            if (!loans.isEmpty()) {
3862
 
3869
 
3863
            for (Loan loan : loans) {
3870
                for (Loan loan : loans) {
3864
                LOGGER.info("Loan - {},  {}", loan.getId(), loan.canBeSettled());
3871
                    LOGGER.info("Loan - {},  {}", loan.getId(), loan.canBeSettled());
3865
                double settledAmount = sdCreditService.settleLoan(loan);
3872
                    double settledAmount = sdCreditService.settleLoan(loan);
3866
 
3873
 
3867
                List<SanctionRequest> sanctionRequests = sanctionRequestRepository.selectHoldSanctionByFofoId(loan.getFofoId());
3874
                    List<SanctionRequest> sanctionRequests = sanctionRequestRepository.selectHoldSanctionByFofoId(loan.getFofoId());
3868
                for (SanctionRequest sanctionRequest : sanctionRequests) {
3875
                    for (SanctionRequest sanctionRequest : sanctionRequests) {
-
 
3876
 
-
 
3877
                        List<Order> orders = orderRepository.selectAllByTransactionId(sanctionRequest.getTransactionId());
-
 
3878
                        if (orders.size() == 0) {
-
 
3879
                            LOGGER.info("Could not find orders - for Sanction Request {}", sanctionRequest);
-
 
3880
                            continue;
-
 
3881
                        }
3869
 
3882
 
3870
                    List<Order> orders = orderRepository.selectAllByTransactionId(sanctionRequest.getTransactionId());
3883
                        if (settledAmount >= sanctionRequest.getPendingAmount().doubleValue()) {
3871
                    if (orders.size() == 0) {
3884
                            settledAmount -= sanctionRequest.getPendingAmount().doubleValue();
3872
                        LOGGER.info("Could not find orders - for Sanction Request {}", sanctionRequest);
3885
                            sanctionRequest.setPendingAmount(BigDecimal.valueOf(0));
-
 
3886
                            this.sendUnholdEmail(orders);
3873
                        continue;
3887
                        } else {
-
 
3888
                            double pendinAmount = sanctionRequest.getPendingAmount().doubleValue() - settledAmount;
-
 
3889
                            System.out.println("Pending Amount - " + pendinAmount);
-
 
3890
                            sanctionRequest.setPendingAmount(BigDecimal.valueOf(pendinAmount));
3874
                    }
3891
                            break;
3875
 
3892
 
3876
                    if (settledAmount >= sanctionRequest.getPendingAmount().doubleValue()) {
-
 
3877
                        settledAmount -= sanctionRequest.getPendingAmount().doubleValue();
-
 
3878
                        sanctionRequest.setPendingAmount(BigDecimal.valueOf(0));
-
 
3879
                        this.sendUnholdEmail(orders);
-
 
3880
                    } else {
-
 
3881
                        double pendinAmount = sanctionRequest.getPendingAmount().doubleValue() - settledAmount;
-
 
3882
                        System.out.println("Pending Amount - " + pendinAmount);
-
 
3883
                        sanctionRequest.setPendingAmount(BigDecimal.valueOf(pendinAmount));
-
 
3884
                        break;
3893
                        }
3885
 
3894
 
3886
                    }
3895
                    }
3887
 
-
 
3888
                }
3896
                }
3889
            }
-
 
3890
 
3897
 
-
 
3898
            }
3891
        }
3899
        }
3892
 
3900
 
3893
 
-
 
3894
    }
3901
    }
3895
 
3902
 
3896
 
3903
 
3897
    private void sendUnholdEmail(List<Order> orders) throws Exception {
3904
    private void sendUnholdEmail(List<Order> orders) throws Exception {
3898
 
3905
 
Line 4016... Line 4023...
4016
        }
4023
        }
4017
 
4024
 
4018
    }
4025
    }
4019
 
4026
 
4020
    public void updatePartnerLimit() throws ProfitMandiBusinessException {
4027
    public void updatePartnerLimit() throws ProfitMandiBusinessException {
-
 
4028
        synchronized (SD_CREDIT_LOCK) {
4021
        Map<Integer, CustomRetailer> customRetailerMap = retailerService.getFofoRetailers(true);
4029
            Map<Integer, CustomRetailer> customRetailerMap = retailerService.getFofoRetailers(true);
4022
        Map<Integer, BigDecimal> fofoSidbiLimitMap = sidbiService.getSuggestedLimitMap();
4030
            Map<Integer, BigDecimal> fofoSidbiLimitMap = sidbiService.getSuggestedLimitMap();
4023
        Map<Integer, SDCreditRequirement> sdCreditRequirementMap = sdCreditRequirementRepository.selectAll().stream().collect(Collectors.toMap(x -> x.getFofoId(), x -> x));
4031
            Map<Integer, SDCreditRequirement> sdCreditRequirementMap = sdCreditRequirementRepository.selectAll().stream().collect(Collectors.toMap(x -> x.getFofoId(), x -> x));
4024
        Map<Integer, CreditAccount> creditAccountMap = creditAccountRepository.selectAllByGateways(Arrays.asList(Gateway.SIDBI, Gateway.SDDIRECT))
4032
            Map<Integer, CreditAccount> creditAccountMap = creditAccountRepository.selectAllByGateways(Arrays.asList(Gateway.SIDBI, Gateway.SDDIRECT))
4025
                .stream().filter(x -> x.isActive()).collect(Collectors.toMap(x -> x.getFofoId(), x -> x));
4033
                    .stream().filter(x -> x.isActive()).collect(Collectors.toMap(x -> x.getFofoId(), x -> x));
4026
        Map<Integer, BulkCreditSummary> bulkSummaryMap = sdCreditService.getCreditSummaryBulk();
4034
            Map<Integer, BulkCreditSummary> bulkSummaryMap = sdCreditService.getCreditSummaryBulk();
4027
        for (Entry<Integer, CustomRetailer> customRetailerEntry : customRetailerMap.entrySet()) {
-
 
4028
            int fofoId = customRetailerEntry.getKey();
-
 
4029
            LocalDateTime firstBillingDate = transactionRepository.getFirstBillingDate(fofoId);
-
 
4030
 
-
 
4031
            CreditAccount creditAccount = creditAccountMap.get(fofoId);
-
 
4032
            BulkCreditSummary bulkSummary = bulkSummaryMap.get(fofoId);
-
 
4033
            BigDecimal utilizationAmount = bulkSummary != null ? bulkSummary.getUtilization() : BigDecimal.ZERO;
-
 
4034
            PartnerDailyInvestment partnerDailyInvestment = partnerInvestmentService.getInvestment(fofoId, 0);
-
 
4035
            BigDecimal suggestedAmount = this.getSuggestedAmount(creditAccount, partnerDailyInvestment, utilizationAmount, fofoSidbiLimitMap.get(fofoId));
-
 
4036
            SDCreditRequirement sdCreditRequirement = sdCreditRequirementMap.get(fofoId);
-
 
4037
 
-
 
4038
            LOGGER.info("suggestedAmount {} ", suggestedAmount);
-
 
4039
 
-
 
4040
            if (sdCreditRequirement == null) {
-
 
4041
                sdCreditRequirement = new SDCreditRequirement();
-
 
4042
                sdCreditRequirement.setFofoId(fofoId);
-
 
4043
                sdCreditRequirement.setCreditDays(15);
-
 
4044
                sdCreditRequirement.setInterestRate(ProfitMandiConstants.NEW_INTEREST_RATE);
-
 
4045
                sdCreditRequirement.setRisk(CreditRisk.HIGH_RISK);
-
 
4046
                sdCreditRequirement.setUtilizedAmount(BigDecimal.ZERO);
-
 
4047
                sdCreditRequirement.setCreateTimestamp(LocalDateTime.now());
-
 
4048
                sdCreditRequirement.setUpdateTimestamp(LocalDateTime.now());
-
 
4049
                sdCreditRequirementRepository.persist(sdCreditRequirement);
-
 
4050
            }
-
 
4051
 
4035
 
-
 
4036
            // Sort by fofoId to ensure deterministic row-locking order and prevent deadlocks
4052
            CreditRisk creditRisk = sdCreditService.getCurrentRisk(sdCreditRequirement, firstBillingDate);
4037
            List<Integer> sortedFofoIds = customRetailerMap.keySet().stream().sorted().collect(Collectors.toList());
4053
 
4038
 
4054
            sdCreditRequirement.setRisk(creditRisk);
4039
            for (int fofoId : sortedFofoIds) {
-
 
4040
                CustomRetailer customRetailer = customRetailerMap.get(fofoId);
-
 
4041
                LocalDateTime firstBillingDate = transactionRepository.getFirstBillingDate(fofoId);
4055
 
4042
 
4056
            sdCreditRequirement.setSuggestedLimit(suggestedAmount);
4043
                CreditAccount creditAccount = creditAccountMap.get(fofoId);
4057
            if (!sdCreditRequirement.isHardLimit()) {
4044
                BulkCreditSummary bulkSummary = bulkSummaryMap.get(fofoId);
-
 
4045
                BigDecimal utilizationAmount = bulkSummary != null ? bulkSummary.getUtilization() : BigDecimal.ZERO;
-
 
4046
                PartnerDailyInvestment partnerDailyInvestment = partnerInvestmentService.getInvestment(fofoId, 0);
-
 
4047
                BigDecimal suggestedAmount = this.getSuggestedAmount(creditAccount, partnerDailyInvestment, utilizationAmount, fofoSidbiLimitMap.get(fofoId));
4058
                sdCreditRequirement.setLimit(suggestedAmount);
4048
                SDCreditRequirement sdCreditRequirement = sdCreditRequirementMap.get(fofoId);
4059
            }
-
 
4060
 
4049
 
4061
            BigDecimal availableLimit = sdCreditRequirement.getLimit().subtract(utilizationAmount);
4050
                LOGGER.info("suggestedAmount {} ", suggestedAmount);
4062
 
4051
 
-
 
4052
                if (sdCreditRequirement == null) {
4063
            LOGGER.info("utilizedLimit {} ", utilizationAmount);
4053
                    sdCreditRequirement = new SDCreditRequirement();
-
 
4054
                    sdCreditRequirement.setFofoId(fofoId);
-
 
4055
                    sdCreditRequirement.setCreditDays(15);
-
 
4056
                    sdCreditRequirement.setInterestRate(ProfitMandiConstants.NEW_INTEREST_RATE);
-
 
4057
                    sdCreditRequirement.setRisk(CreditRisk.HIGH_RISK);
-
 
4058
                    sdCreditRequirement.setUtilizedAmount(BigDecimal.ZERO);
-
 
4059
                    sdCreditRequirement.setCreateTimestamp(LocalDateTime.now());
-
 
4060
                    sdCreditRequirement.setUpdateTimestamp(LocalDateTime.now());
-
 
4061
                    sdCreditRequirementRepository.persist(sdCreditRequirement);
-
 
4062
                }
4064
 
4063
 
4065
            LOGGER.info("availableLimit {} ", availableLimit);
4064
                CreditRisk creditRisk = sdCreditService.getCurrentRisk(sdCreditRequirement, firstBillingDate);
4066
 
4065
 
4067
            sdCreditRequirement.setUtilizedAmount(utilizationAmount);
4066
                sdCreditRequirement.setRisk(creditRisk);
4068
 
4067
 
4069
            sdCreditRequirement.setUpdateTimestamp(LocalDateTime.now());
4068
                sdCreditRequirement.setSuggestedLimit(suggestedAmount);
-
 
4069
                if (!sdCreditRequirement.isHardLimit()) {
-
 
4070
                    sdCreditRequirement.setLimit(suggestedAmount);
-
 
4071
                }
4070
 
4072
 
4071
            if (creditAccount != null) {
4073
                BigDecimal availableLimit = sdCreditRequirement.getLimit().subtract(utilizationAmount);
4072
 
4074
 
4073
                creditAccount.setInterestRate(sdCreditRequirement.getInterestRate().floatValue());
-
 
4074
                creditAccount.setSanctionedAmount(sdCreditRequirement.getLimit().floatValue());
4075
                LOGGER.info("utilizedLimit {} ", utilizationAmount);
-
 
4076
 
4075
                creditAccount.setAvailableAmount(availableLimit.floatValue());
4077
                LOGGER.info("availableLimit {} ", availableLimit);
-
 
4078
 
4076
                creditAccount.setFreeDays(sdCreditRequirement.getFreeDays());
4079
                sdCreditRequirement.setUtilizedAmount(utilizationAmount);
-
 
4080
 
4077
                creditAccount.setUpdatedOn(LocalDateTime.now());
4081
                sdCreditRequirement.setUpdateTimestamp(LocalDateTime.now());
4078
            }
-
 
4079
 
4082
 
-
 
4083
                if (creditAccount != null) {
-
 
4084
 
-
 
4085
                    creditAccount.setInterestRate(sdCreditRequirement.getInterestRate().floatValue());
-
 
4086
                    creditAccount.setSanctionedAmount(sdCreditRequirement.getLimit().floatValue());
-
 
4087
                    creditAccount.setAvailableAmount(availableLimit.floatValue());
-
 
4088
                    creditAccount.setFreeDays(sdCreditRequirement.getFreeDays());
-
 
4089
                    creditAccount.setUpdatedOn(LocalDateTime.now());
-
 
4090
                }
-
 
4091
 
-
 
4092
            }
4080
        }
4093
        }
4081
 
4094
 
4082
    }
4095
    }
4083
 
4096
 
4084
    private static final NavigableMap<Double, Double> discountMap = new TreeMap<>();
4097
    private static final NavigableMap<Double, Double> discountMap = new TreeMap<>();
Line 4134... Line 4147...
4134
        }
4147
        }
4135
        return suggestedAmount;
4148
        return suggestedAmount;
4136
    }
4149
    }
4137
 
4150
 
4138
    public void notifyDefaultLoans() throws ProfitMandiBusinessException, MessagingException, IOException {
4151
    public void notifyDefaultLoans() throws ProfitMandiBusinessException, MessagingException, IOException {
4139
 
-
 
-
 
4152
        synchronized (SD_CREDIT_LOCK) {
4140
        sdCreditService.updateRisk();
4153
            sdCreditService.updateRisk();
4141
        List<Loan> defaultLoans = sdCreditService.getDefaultLoans();
4154
            List<Loan> defaultLoans = sdCreditService.getDefaultLoans();
4142
        if (!defaultLoans.isEmpty()) {
4155
            if (!defaultLoans.isEmpty()) {
4143
            this.sendDefaultLoanAlert(defaultLoans);
4156
                this.sendDefaultLoanAlert(defaultLoans);
-
 
4157
            }
4144
        }
4158
        }
4145
 
-
 
4146
    }
4159
    }
4147
 
4160
 
4148
    public void sendDefaultLoanAlert(List<Loan> defaultLoans) throws
4161
    public void sendDefaultLoanAlert(List<Loan> defaultLoans) throws
4149
            ProfitMandiBusinessException, MessagingException, IOException {
4162
            ProfitMandiBusinessException, MessagingException, IOException {
4150
        String subject = "Default Partners";
4163
        String subject = "Default Partners";
Line 5107... Line 5120...
5107
        }
5120
        }
5108
 
5121
 
5109
    }
5122
    }
5110
 
5123
 
5111
    public void sendMailWhatsAppAfterLoanDueDate() throws Exception {
5124
    public void sendMailWhatsAppAfterLoanDueDate() throws Exception {
-
 
5125
        synchronized (SD_CREDIT_LOCK) {
5112
        sdCreditService.updateRisk();
5126
            sdCreditService.updateRisk();
5113
        List<Loan> defaultLoans = sdCreditService.getDefaultLoans();
5127
            List<Loan> defaultLoans = sdCreditService.getDefaultLoans();
5114
        if (!defaultLoans.isEmpty()) {
5128
            if (!defaultLoans.isEmpty()) {
5115
            this.sendLoanAlert(defaultLoans);
5129
                this.sendLoanAlert(defaultLoans);
-
 
5130
            }
5116
        }
5131
        }
5117
 
-
 
5118
 
-
 
5119
    }
5132
    }
5120
 
5133
 
5121
    public void sendLoanAlert(List<Loan> defaultLoans) throws
5134
    public void sendLoanAlert(List<Loan> defaultLoans) throws
5122
            Exception {
5135
            Exception {
5123
 
5136