Example usage for org.joda.time.format DateTimeFormat forPattern

List of usage examples for org.joda.time.format DateTimeFormat forPattern

Introduction

In this page you can find the example usage for org.joda.time.format DateTimeFormat forPattern.

Prototype

public static DateTimeFormatter forPattern(String pattern) 

Source Link

Document

Factory to create a formatter from a pattern string.

Usage

From source file:com.gst.portfolio.client.service.ClientWritePlatformServiceJpaRepositoryImpl.java

License:Apache License

@Transactional
@Override//  ww w  . ja va 2s.c  o  m
public CommandProcessingResult activateClient(final Long clientId, final JsonCommand command) {
    try {
        this.fromApiJsonDeserializer.validateActivation(command);

        final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId, true);
        validateParentGroupRulesBeforeClientActivation(client);
        final Locale locale = command.extractLocale();
        final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
        final LocalDate activationDate = command.localDateValueOfParameterNamed("activationDate");

        runEntityDatatableCheck(clientId);

        final AppUser currentUser = this.context.authenticatedUser();
        client.activate(currentUser, fmt, activationDate);
        CommandProcessingResult result = openSavingsAccount(client, fmt);
        this.clientRepository.saveAndFlush(client);
        this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.CLIENTS_ACTIVATE,
                constructEntityMap(BUSINESS_ENTITY.CLIENT, client));
        return new CommandProcessingResultBuilder() //
                .withCommandId(command.commandId()) //
                .withOfficeId(client.officeId()) //
                .withClientId(clientId) //
                .withEntityId(clientId) //
                .withSavingsId(result.getSavingsId())//
                .setRollbackTransaction(result.isRollbackTransaction())//
                .build();
    } catch (final DataIntegrityViolationException dve) {
        handleDataIntegrityIssues(command, dve.getMostSpecificCause(), dve);
        return CommandProcessingResult.empty();
    }
}

From source file:com.gst.portfolio.loanaccount.domain.Loan.java

License:Apache License

public Map<String, Object> loanApplicationRejection(final AppUser currentUser, final JsonCommand command,
        final LoanLifecycleStateMachine loanLifecycleStateMachine) {

    validateAccountStatus(LoanEvent.LOAN_REJECTED);

    final Map<String, Object> actualChanges = new LinkedHashMap<>();

    final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_REJECTED,
            LoanStatus.fromInt(this.loanStatus));
    if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
        this.loanStatus = statusEnum.getValue();
        actualChanges.put("status", LoanEnumerations.status(this.loanStatus));

        final LocalDate rejectedOn = command.localDateValueOfParameterNamed("rejectedOnDate");

        final Locale locale = new Locale(command.locale());
        final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);

        this.rejectedOnDate = rejectedOn.toDate();
        this.rejectedBy = currentUser;
        this.closedOnDate = rejectedOn.toDate();
        this.closedBy = currentUser;

        actualChanges.put("locale", command.locale());
        actualChanges.put("dateFormat", command.dateFormat());
        actualChanges.put("rejectedOnDate", rejectedOn.toString(fmt));
        actualChanges.put("closedOnDate", rejectedOn.toString(fmt));

        if (rejectedOn.isBefore(getSubmittedOnDate())) {
            final String errorMessage = "The date on which a loan is rejected cannot be before its submittal date: "
                    + getSubmittedOnDate().toString();
            throw new InvalidLoanStateTransitionException("reject", "cannot.be.before.submittal.date",
                    errorMessage, rejectedOn, getSubmittedOnDate());
        }//from www. j  a v a2s.  c  o  m

        validateActivityNotBeforeClientOrGroupTransferDate(LoanEvent.LOAN_REJECTED, rejectedOn);

        if (rejectedOn.isAfter(DateUtils.getLocalDateOfTenant())) {
            final String errorMessage = "The date on which a loan is rejected cannot be in the future.";
            throw new InvalidLoanStateTransitionException("reject", "cannot.be.a.future.date", errorMessage,
                    rejectedOn);
        }
    } else {
        final String errorMessage = "Only the loan applications with status 'Submitted and pending approval' are allowed to be rejected.";
        throw new InvalidLoanStateTransitionException("reject", "cannot.reject", errorMessage);
    }

    return actualChanges;
}

From source file:com.gst.portfolio.loanaccount.domain.Loan.java

License:Apache License

public Map<String, Object> loanApplicationWithdrawnByApplicant(final AppUser currentUser,
        final JsonCommand command, final LoanLifecycleStateMachine loanLifecycleStateMachine) {

    final Map<String, Object> actualChanges = new LinkedHashMap<>();

    final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_WITHDRAWN,
            LoanStatus.fromInt(this.loanStatus));
    if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) {
        this.loanStatus = statusEnum.getValue();
        actualChanges.put("status", LoanEnumerations.status(this.loanStatus));

        LocalDate withdrawnOn = command.localDateValueOfParameterNamed("withdrawnOnDate");
        if (withdrawnOn == null) {
            withdrawnOn = command.localDateValueOfParameterNamed("eventDate");
        }//from w w  w  . j  a v  a  2  s  .  co m

        final Locale locale = new Locale(command.locale());
        final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);

        this.withdrawnOnDate = withdrawnOn.toDate();
        this.withdrawnBy = currentUser;
        this.closedOnDate = withdrawnOn.toDate();
        this.closedBy = currentUser;

        actualChanges.put("locale", command.locale());
        actualChanges.put("dateFormat", command.dateFormat());
        actualChanges.put("withdrawnOnDate", withdrawnOn.toString(fmt));
        actualChanges.put("closedOnDate", withdrawnOn.toString(fmt));

        if (withdrawnOn.isBefore(getSubmittedOnDate())) {
            final String errorMessage = "The date on which a loan is withdrawn cannot be before its submittal date: "
                    + getSubmittedOnDate().toString();
            throw new InvalidLoanStateTransitionException("withdraw", "cannot.be.before.submittal.date",
                    errorMessage, command, getSubmittedOnDate());
        }

        validateActivityNotBeforeClientOrGroupTransferDate(LoanEvent.LOAN_WITHDRAWN, withdrawnOn);

        if (withdrawnOn.isAfter(DateUtils.getLocalDateOfTenant())) {
            final String errorMessage = "The date on which a loan is withdrawn cannot be in the future.";
            throw new InvalidLoanStateTransitionException("withdraw", "cannot.be.a.future.date", errorMessage,
                    command);
        }
    } else {
        final String errorMessage = "Only the loan applications with status 'Submitted and pending approval' are allowed to be withdrawn by applicant.";
        throw new InvalidLoanStateTransitionException("withdraw", "cannot.withdraw", errorMessage);
    }

    return actualChanges;
}

From source file:com.gst.portfolio.loanaccount.rescheduleloan.service.LoanRescheduleRequestWritePlatformServiceImpl.java

License:Apache License

@Override
@Transactional/*from   w ww. j a va2  s  .c  o m*/
public CommandProcessingResult approve(JsonCommand jsonCommand) {

    try {
        final Long loanRescheduleRequestId = jsonCommand.entityId();

        final LoanRescheduleRequest loanRescheduleRequest = this.loanRescheduleRequestRepository
                .findOne(loanRescheduleRequestId);

        if (loanRescheduleRequest == null) {
            throw new LoanRescheduleRequestNotFoundException(loanRescheduleRequestId);
        }

        // validate the request in the JsonCommand object passed as
        // parameter
        this.loanRescheduleRequestDataValidator.validateForApproveAction(jsonCommand, loanRescheduleRequest);

        final AppUser appUser = this.platformSecurityContext.authenticatedUser();
        final Map<String, Object> changes = new LinkedHashMap<>();

        LocalDate approvedOnDate = jsonCommand.localDateValueOfParameterNamed("approvedOnDate");
        final DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(jsonCommand.dateFormat())
                .withLocale(jsonCommand.extractLocale());

        changes.put("locale", jsonCommand.locale());
        changes.put("dateFormat", jsonCommand.dateFormat());
        changes.put("approvedOnDate", approvedOnDate.toString(dateTimeFormatter));
        changes.put("approvedByUserId", appUser.getId());

        Loan loan = loanRescheduleRequest.getLoan();
        final List<Long> existingTransactionIds = new ArrayList<>(loan.findExistingTransactionIds());
        final List<Long> existingReversedTransactionIds = new ArrayList<>(
                loan.findExistingReversedTransactionIds());

        ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan,
                loanRescheduleRequest.getRescheduleFromDate());

        Collection<LoanRepaymentScheduleHistory> loanRepaymentScheduleHistoryList = this.loanScheduleHistoryWritePlatformService
                .createLoanScheduleArchive(loan.getRepaymentScheduleInstallments(), loan,
                        loanRescheduleRequest);

        final LoanApplicationTerms loanApplicationTerms = loan
                .constructLoanApplicationTerms(scheduleGeneratorDTO);

        LocalDate rescheduleFromDate = null;
        Set<LoanTermVariations> activeLoanTermVariations = loan.getActiveLoanTermVariations();
        LoanTermVariations dueDateVariationInCurrentRequest = loanRescheduleRequest
                .getDueDateTermVariationIfExists();
        if (dueDateVariationInCurrentRequest != null && activeLoanTermVariations != null) {
            LocalDate fromScheduleDate = dueDateVariationInCurrentRequest.fetchTermApplicaDate();
            LocalDate currentScheduleDate = fromScheduleDate;
            LocalDate modifiedScheduleDate = dueDateVariationInCurrentRequest.fetchDateValue();
            Map<LocalDate, LocalDate> changeMap = new HashMap<>();
            changeMap.put(currentScheduleDate, modifiedScheduleDate);
            for (LoanTermVariations activeLoanTermVariation : activeLoanTermVariations) {
                if (activeLoanTermVariation.getTermType().isDueDateVariation() && activeLoanTermVariation
                        .fetchDateValue().equals(dueDateVariationInCurrentRequest.fetchTermApplicaDate())) {
                    activeLoanTermVariation.markAsInactive();
                    rescheduleFromDate = activeLoanTermVariation.fetchTermApplicaDate();
                    dueDateVariationInCurrentRequest.setTermApplicableFrom(rescheduleFromDate.toDate());
                } else if (!activeLoanTermVariation.fetchTermApplicaDate().isBefore(fromScheduleDate)) {
                    while (currentScheduleDate.isBefore(activeLoanTermVariation.fetchTermApplicaDate())) {
                        currentScheduleDate = this.scheduledDateGenerator.generateNextRepaymentDate(
                                currentScheduleDate, loanApplicationTerms, false,
                                loanApplicationTerms.getHolidayDetailDTO());
                        modifiedScheduleDate = this.scheduledDateGenerator.generateNextRepaymentDate(
                                modifiedScheduleDate, loanApplicationTerms, false,
                                loanApplicationTerms.getHolidayDetailDTO());
                        changeMap.put(currentScheduleDate, modifiedScheduleDate);
                    }
                    if (changeMap.containsKey(activeLoanTermVariation.fetchTermApplicaDate())) {
                        activeLoanTermVariation.setTermApplicableFrom(
                                changeMap.get(activeLoanTermVariation.fetchTermApplicaDate()).toDate());
                    }
                }
            }
        }
        if (rescheduleFromDate == null) {
            rescheduleFromDate = loanRescheduleRequest.getRescheduleFromDate();
        }
        for (LoanRescheduleRequestToTermVariationMapping mapping : loanRescheduleRequest
                .getLoanRescheduleRequestToTermVariationMappings()) {
            mapping.getLoanTermVariations().updateIsActive(true);
        }
        BigDecimal annualNominalInterestRate = null;
        List<LoanTermVariationsData> loanTermVariations = new ArrayList<>();
        loan.constructLoanTermVariations(scheduleGeneratorDTO.getFloatingRateDTO(), annualNominalInterestRate,
                loanTermVariations);
        loanApplicationTerms.getLoanTermVariations().setExceptionData(loanTermVariations);

        /*for (LoanTermVariationsData loanTermVariation : loanApplicationTerms.getLoanTermVariations().getDueDateVariation()) {
        if (rescheduleFromDate.isBefore(loanTermVariation.getTermApplicableFrom())) {
            LocalDate applicableDate = this.scheduledDateGenerator.generateNextRepaymentDate(rescheduleFromDate,
                    loanApplicationTerms, false, loanApplicationTerms.getHolidayDetailDTO());
            if (loanTermVariation.getTermApplicableFrom().equals(applicableDate)) {
                LocalDate adjustedDate = this.scheduledDateGenerator.generateNextRepaymentDate(adjustedApplicableDate,
                        loanApplicationTerms, false, loanApplicationTerms.getHolidayDetailDTO());
                loanTermVariation.setApplicableFromDate(adjustedDate);
            }
        }
        }*/

        final RoundingMode roundingMode = MoneyHelper.getRoundingMode();
        final MathContext mathContext = new MathContext(8, roundingMode);
        final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.loanRepaymentScheduleTransactionProcessorFactory
                .determineProcessor(loan.transactionProcessingStrategy());
        final LoanScheduleGenerator loanScheduleGenerator = this.loanScheduleFactory
                .create(loanApplicationTerms.getInterestMethod());
        final LoanLifecycleStateMachine loanLifecycleStateMachine = null;
        loan.setHelpers(loanLifecycleStateMachine, this.loanSummaryWrapper,
                this.loanRepaymentScheduleTransactionProcessorFactory);
        final LoanScheduleDTO loanSchedule = loanScheduleGenerator.rescheduleNextInstallments(mathContext,
                loanApplicationTerms, loan, loanApplicationTerms.getHolidayDetailDTO(),
                loanRepaymentScheduleTransactionProcessor, rescheduleFromDate);

        loan.updateLoanSchedule(loanSchedule.getInstallments(), appUser);
        loan.recalculateAllCharges();
        ChangedTransactionDetail changedTransactionDetail = loan.processTransactions();

        for (LoanRepaymentScheduleHistory loanRepaymentScheduleHistory : loanRepaymentScheduleHistoryList) {
            this.loanRepaymentScheduleHistoryRepository.save(loanRepaymentScheduleHistory);
        }

        loan.updateRescheduledByUser(appUser);
        loan.updateRescheduledOnDate(new LocalDate());

        // update the status of the request
        loanRescheduleRequest.approve(appUser, approvedOnDate);

        // update the loan object
        saveAndFlushLoanWithDataIntegrityViolationChecks(loan);

        if (changedTransactionDetail != null) {
            for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail
                    .getNewTransactionMappings().entrySet()) {
                this.loanTransactionRepository.save(mapEntry.getValue());
                // update loan with references to the newly created
                // transactions
                loan.addLoanTransaction(mapEntry.getValue());
                this.accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(),
                        mapEntry.getValue());
            }
        }
        postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);

        this.loanAccountDomainService.recalculateAccruals(loan, true);

        return new CommandProcessingResultBuilder().withCommandId(jsonCommand.commandId())
                .withEntityId(loanRescheduleRequestId).withLoanId(loanRescheduleRequest.getLoan().getId())
                .with(changes).build();
    }

    catch (final DataIntegrityViolationException dve) {
        // handle the data integrity violation
        handleDataIntegrityViolation(dve);

        // return an empty command processing result object
        return CommandProcessingResult.empty();
    }
}

From source file:com.gst.portfolio.loanaccount.rescheduleloan.service.LoanRescheduleRequestWritePlatformServiceImpl.java

License:Apache License

@Override
@Transactional/*w  w w  . ja v  a2 s. c  o  m*/
public CommandProcessingResult reject(JsonCommand jsonCommand) {

    try {
        final Long loanRescheduleRequestId = jsonCommand.entityId();

        final LoanRescheduleRequest loanRescheduleRequest = loanRescheduleRequestRepository
                .findOne(loanRescheduleRequestId);

        if (loanRescheduleRequest == null) {
            throw new LoanRescheduleRequestNotFoundException(loanRescheduleRequestId);
        }

        // validate the request in the JsonCommand object passed as
        // parameter
        this.loanRescheduleRequestDataValidator.validateForRejectAction(jsonCommand, loanRescheduleRequest);

        final AppUser appUser = this.platformSecurityContext.authenticatedUser();
        final Map<String, Object> changes = new LinkedHashMap<>();

        LocalDate rejectedOnDate = jsonCommand.localDateValueOfParameterNamed("rejectedOnDate");
        final DateTimeFormatter dateTimeFormatter = DateTimeFormat.forPattern(jsonCommand.dateFormat())
                .withLocale(jsonCommand.extractLocale());

        changes.put("locale", jsonCommand.locale());
        changes.put("dateFormat", jsonCommand.dateFormat());
        changes.put("rejectedOnDate", rejectedOnDate.toString(dateTimeFormatter));
        changes.put("rejectedByUserId", appUser.getId());

        if (!changes.isEmpty()) {
            loanRescheduleRequest.reject(appUser, rejectedOnDate);
            Set<LoanRescheduleRequestToTermVariationMapping> loanRescheduleRequestToTermVariationMappings = loanRescheduleRequest
                    .getLoanRescheduleRequestToTermVariationMappings();
            for (LoanRescheduleRequestToTermVariationMapping loanRescheduleRequestToTermVariationMapping : loanRescheduleRequestToTermVariationMappings) {
                loanRescheduleRequestToTermVariationMapping.getLoanTermVariations().markAsInactive();
            }
        }

        return new CommandProcessingResultBuilder().withCommandId(jsonCommand.commandId())
                .withEntityId(loanRescheduleRequestId).withLoanId(loanRescheduleRequest.getLoan().getId())
                .with(changes).build();
    }

    catch (final DataIntegrityViolationException dve) {
        // handle the data integrity violation
        handleDataIntegrityViolation(dve);

        // return an empty command processing result object
        return CommandProcessingResult.empty();
    }
}

From source file:com.gst.portfolio.loanaccount.service.LoanWritePlatformServiceJpaRepositoryImpl.java

License:Apache License

@Transactional
@Override/*from  w ww .  j  a  v  a 2s .co m*/
public CommandProcessingResult disburseLoan(final Long loanId, final JsonCommand command,
        Boolean isAccountTransfer) {

    final AppUser currentUser = getAppUserIfPresent();

    this.loanEventApiJsonValidator.validateDisbursement(command.json(), isAccountTransfer);

    final Loan loan = this.loanAssembler.assembleFrom(loanId);

    final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
    // validate ActualDisbursement Date Against Expected Disbursement Date
    LoanProduct loanProduct = loan.loanProduct();
    if (loanProduct.syncExpectedWithDisbursementDate()) {
        syncExpectedDateWithActualDisbursementDate(loan, actualDisbursementDate);
    }
    checkClientOrGroupActive(loan);

    final LocalDate nextPossibleRepaymentDate = loan.getNextPossibleRepaymentDateForRescheduling();
    final Date rescheduledRepaymentDate = command.DateValueOfParameterNamed("adjustRepaymentDate");

    entityDatatableChecksWritePlatformService.runTheCheckForProduct(loanId, EntityTables.LOAN.getName(),
            StatusEnum.DISBURSE.getCode().longValue(), EntityTables.LOAN.getForeignKeyColumnNameOnDatatable(),
            loan.productId());

    // check for product mix validations
    checkForProductMixRestrictions(loan);

    LocalDate recalculateFrom = null;
    ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService.buildScheduleGeneratorDTO(loan,
            recalculateFrom);

    // validate actual disbursement date against meeting date
    final CalendarInstance calendarInstance = this.calendarInstanceRepository
            .findCalendarInstaneByEntityId(loan.getId(), CalendarEntityType.LOANS.getValue());
    if (loan.isSyncDisbursementWithMeeting()) {
        this.loanEventApiJsonValidator.validateDisbursementDateWithMeetingDate(actualDisbursementDate,
                calendarInstance, scheduleGeneratorDTO.isSkipRepaymentOnFirstDayofMonth(),
                scheduleGeneratorDTO.getNumberOfdays());
    }

    this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.LOAN_DISBURSAL,
            constructEntityMap(BUSINESS_ENTITY.LOAN, loan));

    final List<Long> existingTransactionIds = new ArrayList<>();
    final List<Long> existingReversedTransactionIds = new ArrayList<>();

    final Map<String, Object> changes = new LinkedHashMap<>();

    final PaymentDetail paymentDetail = this.paymentDetailWritePlatformService
            .createAndPersistPaymentDetail(command, changes);

    final Boolean isPaymnetypeApplicableforDisbursementCharge = configurationDomainService
            .isPaymnetypeApplicableforDisbursementCharge();

    // Recalculate first repayment date based in actual disbursement date.
    updateLoanCounters(loan, actualDisbursementDate);
    Money amountBeforeAdjust = loan.getPrincpal();
    loan.validateAccountStatus(LoanEvent.LOAN_DISBURSED);
    boolean canDisburse = loan.canDisburse(actualDisbursementDate);
    ChangedTransactionDetail changedTransactionDetail = null;
    if (canDisburse) {
        Money disburseAmount = loan.adjustDisburseAmount(command, actualDisbursementDate);
        Money amountToDisburse = disburseAmount.copy();
        boolean recalculateSchedule = amountBeforeAdjust.isNotEqualTo(loan.getPrincpal());
        final String txnExternalId = command.stringValueOfParameterNamedAllowingNull("externalId");

        if (loan.isTopup() && loan.getClientId() != null) {
            final Long loanIdToClose = loan.getTopupLoanDetails().getLoanIdToClose();
            final Loan loanToClose = this.loanRepositoryWrapper
                    .findNonClosedLoanThatBelongsToClient(loanIdToClose, loan.getClientId());
            if (loanToClose == null) {
                throw new GeneralPlatformDomainRuleException(
                        "error.msg.loan.to.be.closed.with.topup.is.not.active",
                        "Loan to be closed with this topup is not active.");
            }
            final LocalDate lastUserTransactionOnLoanToClose = loanToClose.getLastUserTransactionDate();
            if (!loan.getDisbursementDate().isAfter(lastUserTransactionOnLoanToClose)) {
                throw new GeneralPlatformDomainRuleException(
                        "error.msg.loan.disbursal.date.should.be.after.last.transaction.date.of.loan.to.be.closed",
                        "Disbursal date of this loan application " + loan.getDisbursementDate()
                                + " should be after last transaction date of loan to be closed "
                                + lastUserTransactionOnLoanToClose);
            }

            BigDecimal loanOutstanding = this.loanReadPlatformService
                    .retrieveLoanPrePaymentTemplate(loanIdToClose, actualDisbursementDate).getAmount();
            final BigDecimal firstDisbursalAmount = loan.getFirstDisbursalAmount();
            if (loanOutstanding.compareTo(firstDisbursalAmount) > 0) {
                throw new GeneralPlatformDomainRuleException(
                        "error.msg.loan.amount.less.than.outstanding.of.loan.to.be.closed",
                        "Topup loan amount should be greater than outstanding amount of loan to be closed.");
            }

            amountToDisburse = disburseAmount.minus(loanOutstanding);

            disburseLoanToLoan(loan, command, loanOutstanding);
        }

        if (isAccountTransfer) {
            disburseLoanToSavings(loan, command, amountToDisburse, paymentDetail);
            existingTransactionIds.addAll(loan.findExistingTransactionIds());
            existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
        } else {
            existingTransactionIds.addAll(loan.findExistingTransactionIds());
            existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
            LoanTransaction disbursementTransaction = LoanTransaction.disbursement(loan.getOffice(),
                    amountToDisburse, paymentDetail, actualDisbursementDate, txnExternalId,
                    DateUtils.getLocalDateTimeOfTenant(), currentUser);
            disbursementTransaction.updateLoan(loan);
            loan.addLoanTransaction(disbursementTransaction);
        }

        regenerateScheduleOnDisbursement(command, loan, recalculateSchedule, scheduleGeneratorDTO,
                nextPossibleRepaymentDate, rescheduledRepaymentDate);
        if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
            createAndSaveLoanScheduleArchive(loan, scheduleGeneratorDTO);
        }
        if (isPaymnetypeApplicableforDisbursementCharge) {
            changedTransactionDetail = loan.disburse(currentUser, command, changes, scheduleGeneratorDTO,
                    paymentDetail);
        } else {
            changedTransactionDetail = loan.disburse(currentUser, command, changes, scheduleGeneratorDTO, null);
        }
    }
    if (!changes.isEmpty()) {
        saveAndFlushLoanWithDataIntegrityViolationChecks(loan);

        final String noteText = command.stringValueOfParameterNamed("note");
        if (StringUtils.isNotBlank(noteText)) {
            final Note note = Note.loanNote(loan, noteText);
            this.noteRepository.save(note);
        }

        if (changedTransactionDetail != null) {
            for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail
                    .getNewTransactionMappings().entrySet()) {
                this.loanTransactionRepository.save(mapEntry.getValue());
                this.accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(),
                        mapEntry.getValue());
            }
        }

        // auto create standing instruction
        createStandingInstruction(loan);

        postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);

    }

    final Set<LoanCharge> loanCharges = loan.charges();
    final Map<Long, BigDecimal> disBuLoanCharges = new HashMap<>();
    for (final LoanCharge loanCharge : loanCharges) {
        if (loanCharge.isDueAtDisbursement() && loanCharge.getChargePaymentMode().isPaymentModeAccountTransfer()
                && loanCharge.isChargePending()) {
            disBuLoanCharges.put(loanCharge.getId(), loanCharge.amountOutstanding());
        }
    }

    final Locale locale = command.extractLocale();
    final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
    for (final Map.Entry<Long, BigDecimal> entrySet : disBuLoanCharges.entrySet()) {
        final PortfolioAccountData savingAccountData = this.accountAssociationsReadPlatformService
                .retriveLoanLinkedAssociation(loanId);
        final SavingsAccount fromSavingsAccount = null;
        final boolean isRegularTransaction = true;
        final boolean isExceptionForBalanceCheck = false;
        final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(actualDisbursementDate,
                entrySet.getValue(), PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN,
                savingAccountData.accountId(), loanId, "Loan Charge Payment", locale, fmt, null, null,
                LoanTransactionType.REPAYMENT_AT_DISBURSEMENT.getValue(), entrySet.getKey(), null,
                AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null, null, fromSavingsAccount,
                isRegularTransaction, isExceptionForBalanceCheck);
        this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
    }

    updateRecurringCalendarDatesForInterestRecalculation(loan);
    this.loanAccountDomainService.recalculateAccruals(loan);
    this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_DISBURSAL,
            constructEntityMap(BUSINESS_ENTITY.LOAN, loan));
    return new CommandProcessingResultBuilder() //
            .withCommandId(command.commandId()) //
            .withEntityId(loan.getId()) //
            .withOfficeId(loan.getOfficeId()) //
            .withClientId(loan.getClientId()) //
            .withGroupId(loan.getGroupId()) //
            .withLoanId(loanId) //
            .with(changes) //
            .build();
}

From source file:com.gst.portfolio.loanaccount.service.LoanWritePlatformServiceJpaRepositoryImpl.java

License:Apache License

/****
 * TODO Vishwas: Pair with Ashok and re-factor collection sheet code-base
 * /* w  w  w  .  ja  v a  2  s.co  m*/
 * May of the changes made to disburseLoan aren't being made here, should
 * refactor to reuse disburseLoan ASAP
 *****/
@Transactional
@Override
public Map<String, Object> bulkLoanDisbursal(final JsonCommand command,
        final CollectionSheetBulkDisbursalCommand bulkDisbursalCommand, Boolean isAccountTransfer) {
    final AppUser currentUser = getAppUserIfPresent();

    final SingleDisbursalCommand[] disbursalCommand = bulkDisbursalCommand.getDisburseTransactions();
    final Map<String, Object> changes = new LinkedHashMap<>();
    if (disbursalCommand == null) {
        return changes;
    }

    final LocalDate nextPossibleRepaymentDate = null;
    final Date rescheduledRepaymentDate = null;

    for (int i = 0; i < disbursalCommand.length; i++) {
        final SingleDisbursalCommand singleLoanDisbursalCommand = disbursalCommand[i];

        final Loan loan = this.loanAssembler.assembleFrom(singleLoanDisbursalCommand.getLoanId());
        final LocalDate actualDisbursementDate = command
                .localDateValueOfParameterNamed("actualDisbursementDate");

        // validate ActualDisbursement Date Against Expected Disbursement Date
        LoanProduct loanProduct = loan.loanProduct();
        if (loanProduct.syncExpectedWithDisbursementDate()) {
            syncExpectedDateWithActualDisbursementDate(loan, actualDisbursementDate);
        }
        checkClientOrGroupActive(loan);
        this.businessEventNotifierService.notifyBusinessEventToBeExecuted(BUSINESS_EVENTS.LOAN_DISBURSAL,
                constructEntityMap(BUSINESS_ENTITY.LOAN, loan));

        final List<Long> existingTransactionIds = new ArrayList<>();
        final List<Long> existingReversedTransactionIds = new ArrayList<>();

        final PaymentDetail paymentDetail = this.paymentDetailWritePlatformService
                .createAndPersistPaymentDetail(command, changes);

        // Bulk disbursement should happen on meeting date (mostly from
        // collection sheet).
        // FIXME: AA - this should be first meeting date based on
        // disbursement date and next available meeting dates
        // assuming repayment schedule won't regenerate because expected
        // disbursement and actual disbursement happens on same date
        loan.validateAccountStatus(LoanEvent.LOAN_DISBURSED);
        updateLoanCounters(loan, actualDisbursementDate);
        boolean canDisburse = loan.canDisburse(actualDisbursementDate);
        ChangedTransactionDetail changedTransactionDetail = null;
        if (canDisburse) {
            Money amountBeforeAdjust = loan.getPrincpal();
            Money disburseAmount = loan.adjustDisburseAmount(command, actualDisbursementDate);
            boolean recalculateSchedule = amountBeforeAdjust.isNotEqualTo(loan.getPrincpal());
            final String txnExternalId = command.stringValueOfParameterNamedAllowingNull("externalId");
            if (isAccountTransfer) {
                disburseLoanToSavings(loan, command, disburseAmount, paymentDetail);
                existingTransactionIds.addAll(loan.findExistingTransactionIds());
                existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());

            } else {
                existingTransactionIds.addAll(loan.findExistingTransactionIds());
                existingReversedTransactionIds.addAll(loan.findExistingReversedTransactionIds());
                LoanTransaction disbursementTransaction = LoanTransaction.disbursement(loan.getOffice(),
                        disburseAmount, paymentDetail, actualDisbursementDate, txnExternalId,
                        DateUtils.getLocalDateTimeOfTenant(), currentUser);
                disbursementTransaction.updateLoan(loan);
                loan.addLoanTransaction(disbursementTransaction);
            }
            LocalDate recalculateFrom = null;
            final ScheduleGeneratorDTO scheduleGeneratorDTO = this.loanUtilService
                    .buildScheduleGeneratorDTO(loan, recalculateFrom);
            regenerateScheduleOnDisbursement(command, loan, recalculateSchedule, scheduleGeneratorDTO,
                    nextPossibleRepaymentDate, rescheduledRepaymentDate);
            if (loan.repaymentScheduleDetail().isInterestRecalculationEnabled()) {
                createAndSaveLoanScheduleArchive(loan, scheduleGeneratorDTO);
            }
            if (configurationDomainService.isPaymnetypeApplicableforDisbursementCharge()) {
                changedTransactionDetail = loan.disburse(currentUser, command, changes, scheduleGeneratorDTO,
                        paymentDetail);
            } else {
                changedTransactionDetail = loan.disburse(currentUser, command, changes, scheduleGeneratorDTO,
                        null);
            }
        }
        if (!changes.isEmpty()) {

            saveAndFlushLoanWithDataIntegrityViolationChecks(loan);

            final String noteText = command.stringValueOfParameterNamed("note");
            if (StringUtils.isNotBlank(noteText)) {
                final Note note = Note.loanNote(loan, noteText);
                this.noteRepository.save(note);
            }
            if (changedTransactionDetail != null) {
                for (final Map.Entry<Long, LoanTransaction> mapEntry : changedTransactionDetail
                        .getNewTransactionMappings().entrySet()) {
                    this.loanTransactionRepository.save(mapEntry.getValue());
                    this.accountTransfersWritePlatformService.updateLoanTransaction(mapEntry.getKey(),
                            mapEntry.getValue());
                }
            }
            postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds);
        }
        final Set<LoanCharge> loanCharges = loan.charges();
        final Map<Long, BigDecimal> disBuLoanCharges = new HashMap<>();
        for (final LoanCharge loanCharge : loanCharges) {
            if (loanCharge.isDueAtDisbursement()
                    && loanCharge.getChargePaymentMode().isPaymentModeAccountTransfer()
                    && loanCharge.isChargePending()) {
                disBuLoanCharges.put(loanCharge.getId(), loanCharge.amountOutstanding());
            }
        }
        final Locale locale = command.extractLocale();
        final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
        for (final Map.Entry<Long, BigDecimal> entrySet : disBuLoanCharges.entrySet()) {
            final PortfolioAccountData savingAccountData = this.accountAssociationsReadPlatformService
                    .retriveLoanLinkedAssociation(loan.getId());
            final SavingsAccount fromSavingsAccount = null;
            final boolean isRegularTransaction = true;
            final boolean isExceptionForBalanceCheck = false;
            final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(actualDisbursementDate,
                    entrySet.getValue(), PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN,
                    savingAccountData.accountId(), loan.getId(), "Loan Charge Payment", locale, fmt, null, null,
                    LoanTransactionType.REPAYMENT_AT_DISBURSEMENT.getValue(), entrySet.getKey(), null,
                    AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null, null,
                    fromSavingsAccount, isRegularTransaction, isExceptionForBalanceCheck);
            this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
        }
        updateRecurringCalendarDatesForInterestRecalculation(loan);
        this.loanAccountDomainService.recalculateAccruals(loan);
        this.businessEventNotifierService.notifyBusinessEventWasExecuted(BUSINESS_EVENTS.LOAN_DISBURSAL,
                constructEntityMap(BUSINESS_ENTITY.LOAN, loan));
    }

    return changes;
}

From source file:com.gst.portfolio.loanaccount.service.LoanWritePlatformServiceJpaRepositoryImpl.java

License:Apache License

@Override
@Transactional/*from w  w w.  j  ava  2  s . c  om*/
public CommandProcessingResult payLoanCharge(final Long loanId, Long loanChargeId, final JsonCommand command,
        final boolean isChargeIdIncludedInJson) {

    this.loanEventApiJsonValidator.validateChargePaymentTransaction(command.json(), isChargeIdIncludedInJson);
    if (isChargeIdIncludedInJson) {
        loanChargeId = command.longValueOfParameterNamed("chargeId");
    }
    final Loan loan = this.loanAssembler.assembleFrom(loanId);
    checkClientOrGroupActive(loan);
    final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId);

    // Charges may be waived only when the loan associated with them are
    // active
    if (!loan.status().isActive()) {
        throw new LoanChargeCannotBePayedException(LOAN_CHARGE_CANNOT_BE_PAYED_REASON.LOAN_INACTIVE,
                loanCharge.getId());
    }

    // validate loan charge is not already paid or waived
    if (loanCharge.isWaived()) {
        throw new LoanChargeCannotBePayedException(LOAN_CHARGE_CANNOT_BE_PAYED_REASON.ALREADY_WAIVED,
                loanCharge.getId());
    } else if (loanCharge.isPaid()) {
        throw new LoanChargeCannotBePayedException(LOAN_CHARGE_CANNOT_BE_PAYED_REASON.ALREADY_PAID,
                loanCharge.getId());
    }

    if (!loanCharge.getChargePaymentMode().isPaymentModeAccountTransfer()) {
        throw new LoanChargeCannotBePayedException(
                LOAN_CHARGE_CANNOT_BE_PAYED_REASON.CHARGE_NOT_ACCOUNT_TRANSFER, loanCharge.getId());
    }

    final LocalDate transactionDate = command.localDateValueOfParameterNamed("transactionDate");

    final Locale locale = command.extractLocale();
    final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
    Integer loanInstallmentNumber = null;
    BigDecimal amount = loanCharge.amountOutstanding();
    if (loanCharge.isInstalmentFee()) {
        LoanInstallmentCharge chargePerInstallment = null;
        final LocalDate dueDate = command.localDateValueOfParameterNamed("dueDate");
        final Integer installmentNumber = command.integerValueOfParameterNamed("installmentNumber");
        if (dueDate != null) {
            chargePerInstallment = loanCharge.getInstallmentLoanCharge(dueDate);
        } else if (installmentNumber != null) {
            chargePerInstallment = loanCharge.getInstallmentLoanCharge(installmentNumber);
        }
        if (chargePerInstallment == null) {
            chargePerInstallment = loanCharge.getUnpaidInstallmentLoanCharge();
        }
        if (chargePerInstallment.isWaived()) {
            throw new LoanChargeCannotBePayedException(LOAN_CHARGE_CANNOT_BE_PAYED_REASON.ALREADY_WAIVED,
                    loanCharge.getId());
        } else if (chargePerInstallment.isPaid()) {
            throw new LoanChargeCannotBePayedException(LOAN_CHARGE_CANNOT_BE_PAYED_REASON.ALREADY_PAID,
                    loanCharge.getId());
        }
        loanInstallmentNumber = chargePerInstallment.getRepaymentInstallment().getInstallmentNumber();
        amount = chargePerInstallment.getAmountOutstanding();
    }

    final PortfolioAccountData portfolioAccountData = this.accountAssociationsReadPlatformService
            .retriveLoanLinkedAssociation(loanId);
    if (portfolioAccountData == null) {
        final String errorMessage = "Charge with id:" + loanChargeId
                + " requires linked savings account for payment";
        throw new LinkedAccountRequiredException("loanCharge.pay", errorMessage, loanChargeId);
    }
    final SavingsAccount fromSavingsAccount = null;
    final boolean isRegularTransaction = true;
    final boolean isExceptionForBalanceCheck = false;
    final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, amount,
            PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN, portfolioAccountData.accountId(), loanId,
            "Loan Charge Payment", locale, fmt, null, null, LoanTransactionType.CHARGE_PAYMENT.getValue(),
            loanChargeId, loanInstallmentNumber, AccountTransferType.CHARGE_PAYMENT.getValue(), null, null,
            null, null, null, fromSavingsAccount, isRegularTransaction, isExceptionForBalanceCheck);
    this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
    return new CommandProcessingResultBuilder() //
            .withCommandId(command.commandId()) //
            .withEntityId(loanChargeId) //
            .withOfficeId(loan.getOfficeId()) //
            .withClientId(loan.getClientId()) //
            .withGroupId(loan.getGroupId()) //
            .withLoanId(loanId) //
            .withSavingsId(portfolioAccountData.accountId()).build();
}

From source file:com.gst.portfolio.loanaccount.service.LoanWritePlatformServiceJpaRepositoryImpl.java

License:Apache License

public void disburseLoanToLoan(final Loan loan, final JsonCommand command, final BigDecimal amount) {

    final LocalDate transactionDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
    final String txnExternalId = command.stringValueOfParameterNamedAllowingNull("externalId");

    final Locale locale = command.extractLocale();
    final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
    final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, amount,
            PortfolioAccountType.LOAN, PortfolioAccountType.LOAN, loan.getId(),
            loan.getTopupLoanDetails().getLoanIdToClose(), "Loan Topup", locale, fmt,
            LoanTransactionType.DISBURSEMENT.getValue(), LoanTransactionType.REPAYMENT.getValue(),
            txnExternalId, loan, null);//w  w  w.  j  a v a 2 s . com
    AccountTransferDetails accountTransferDetails = this.accountTransfersWritePlatformService
            .repayLoanWithTopup(accountTransferDTO);
    loan.getTopupLoanDetails().setAccountTransferDetails(accountTransferDetails.getId());
    loan.getTopupLoanDetails().setTopupAmount(amount);
}

From source file:com.gst.portfolio.loanaccount.service.LoanWritePlatformServiceJpaRepositoryImpl.java

License:Apache License

public void disburseLoanToSavings(final Loan loan, final JsonCommand command, final Money amount,
        final PaymentDetail paymentDetail) {

    final LocalDate transactionDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
    final String txnExternalId = command.stringValueOfParameterNamedAllowingNull("externalId");

    final Locale locale = command.extractLocale();
    final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
    final PortfolioAccountData portfolioAccountData = this.accountAssociationsReadPlatformService
            .retriveLoanLinkedAssociation(loan.getId());
    if (portfolioAccountData == null) {
        final String errorMessage = "Disburse Loan with id:" + loan.getId()
                + " requires linked savings account for payment";
        throw new LinkedAccountRequiredException("loan.disburse.to.savings", errorMessage, loan.getId());
    }/*from  www . j a  v  a  2s.  c  om*/
    final SavingsAccount fromSavingsAccount = null;
    final boolean isExceptionForBalanceCheck = false;
    final boolean isRegularTransaction = true;
    final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, amount.getAmount(),
            PortfolioAccountType.LOAN, PortfolioAccountType.SAVINGS, loan.getId(),
            portfolioAccountData.accountId(), "Loan Disbursement", locale, fmt, paymentDetail,
            LoanTransactionType.DISBURSEMENT.getValue(), null, null, null,
            AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, txnExternalId, loan, null,
            fromSavingsAccount, isRegularTransaction, isExceptionForBalanceCheck);
    this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);

}