mifosx-172: wip - support adjust transaction for accounting.

This commit is contained in:
Keith Woodlock
2013-02-19 00:45:33 +00:00
parent bb63d2cb2d
commit 87eb0a6fe8
6 changed files with 163 additions and 105 deletions
@@ -1087,10 +1087,6 @@ CREATE TABLE `m_loan_transaction` (
`transaction_type_enum` smallint(5) NOT NULL,
`transaction_date` date NOT NULL,
`amount` decimal(19,6) NOT NULL,
`createdby_id` bigint(20) DEFAULT NULL,
`created_date` datetime DEFAULT NULL,
`lastmodified_date` datetime DEFAULT NULL,
`lastmodifiedby_id` bigint(20) DEFAULT NULL,
`principal_portion_derived` decimal(19,6) DEFAULT NULL,
`interest_portion_derived` decimal(19,6) DEFAULT NULL,
`fee_charges_portion_derived` decimal(19,6) DEFAULT NULL,
@@ -1937,4 +1933,4 @@ UNLOCK TABLES;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
-- Dump completed on 2013-02-18 13:20:24
-- Dump completed on 2013-02-19 0:44:13
@@ -8,4 +8,11 @@ UPDATE `m_loan_transaction` SET `is_reversed` = 1 WHERE contra_id is not null;
ALTER TABLE `m_loan_transaction` DROP FOREIGN KEY `FKCFCEA426FC69F3F1`;
ALTER TABLE `m_loan_transaction`
DROP COLUMN `contra_id` ,
DROP INDEX `FKCFCEA426FC69F3F1`;
DROP INDEX `FKCFCEA426FC69F3F1`;
ALTER TABLE `m_loan_transaction`
DROP COLUMN `lastmodifiedby_id`,
DROP COLUMN `lastmodified_date`,
DROP COLUMN `created_date`,
DROP COLUMN `createdby_id`;
@@ -165,11 +165,11 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
@Temporal(TemporalType.DATE)
@Column(name = "expected_disbursedon_date")
private Date expectedDisbursedOnDate;
private Date expectedDisbursementDate;
@Temporal(TemporalType.DATE)
@Column(name = "disbursedon_date")
private Date disbursedOnDate;
private Date actualDisbursementDate;
@SuppressWarnings("unused")
@ManyToOne(optional = true)
@@ -199,7 +199,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
@Temporal(TemporalType.DATE)
@Column(name = "maturedon_date")
private Date maturedOnDate;
private Date actualMaturityDate;
@Temporal(TemporalType.DATE)
@Column(name = "expected_firstrepaymenton_date")
@@ -387,12 +387,9 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
final LoanRepaymentScheduleTransactionProcessor loanRepaymentScheduleTransactionProcessor = this.transactionProcessor
.determineProcessor(this.transactionProcessingStrategy);
if (!loanCharge.isDueAtDisbursement()) { // TODO - only need to
// reprocess transactions
// against loan schedule if
// loan charge is added with
// due date before latest
// transaction.
// TODO - only need to reprocess transactions against loan schedule
// if loan charge is added with due date before latest transaction.
if (!loanCharge.isDueAtDisbursement()) {
final List<LoanTransaction> allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement();
loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement,
getCurrency(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges());
@@ -640,6 +637,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
public void updateLoanScheduleDependentDerivedFields() {
this.expectedMaturityDate = determineExpectedMaturityDate().toDate();
this.actualMaturityDate = determineExpectedMaturityDate().toDate();
}
public Map<String, Object> loanApplicationModification(final JsonCommand command, final Set<LoanCharge> possiblyModifedLoanCharges,
@@ -737,7 +735,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
actualChanges.put("recalculateLoanSchedule", true);
final LocalDate newValue = command.localDateValueOfParameterNamed(expectedDisbursementDateParamName);
this.expectedDisbursedOnDate = newValue.toDate();
this.expectedDisbursementDate = newValue.toDate();
removeFirstDisbursementTransaction();
disburse(getExpectedDisbursedOnLocalDate());
}
@@ -894,7 +892,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
// Have to set expectedDisbursementDate to avoid nullPointer so should
// be passed down to updateLoanSchedule method
if (loanSchedule.getDisbursementDate() != null) {
this.expectedDisbursedOnDate = loanSchedule.getDisbursementDate().toDate();
this.expectedDisbursementDate = loanSchedule.getDisbursementDate().toDate();
}
updateLoanSchedule(loanScheduleData);
@@ -914,7 +912,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
this.submittedOnDate = submittedOn.toDate();
this.submittedBy = currentUser;
this.expectedMaturityDate = determineExpectedMaturityDate().toDate();
updateLoanScheduleDependentDerivedFields();
if (loanSchedule.getRepaymentStartFromDate() != null) {
this.expectedFirstRepaymentOnDate = loanSchedule.getRepaymentStartFromDate().toDate();
@@ -1101,8 +1099,8 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
}
private void disburse(final LocalDate expectedDisbursedOnLocalDate) {
this.disbursedOnDate = expectedDisbursedOnLocalDate.toDate();
this.expectedMaturityDate = determineExpectedMaturityDate().toDate();
this.actualDisbursementDate = expectedDisbursedOnLocalDate.toDate();
updateLoanScheduleDependentDerivedFields();
handleDisbursementTransaction(expectedDisbursedOnLocalDate);
}
@@ -1147,26 +1145,19 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
this.loanStatus = statusEnum.getValue();
actualChanges.put("status", LoanEnumerations.status(this.loanStatus));
LocalDate disbursedOn = command.localDateValueOfParameterNamed("disbursedOnDate");
if (disbursedOn == null) {
disbursedOn = command.localDateValueOfParameterNamed("eventDate");
}
final LocalDate actualDisbursementDate = command.localDateValueOfParameterNamed("actualDisbursementDate");
final Locale locale = new Locale(command.locale());
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
this.disbursedOnDate = disbursedOn.toDate();
this.actualDisbursementDate = actualDisbursementDate.toDate();
this.disbursedBy = currentUser;
this.expectedMaturityDate = determineExpectedMaturityDate().toDate();
updateLoanScheduleDependentDerivedFields();
actualChanges.put("locale", command.locale());
actualChanges.put("dateFormat", command.dateFormat());
actualChanges.put("disbursedOnDate", disbursedOn.toString(fmt));
actualChanges.put("expectedMaturityDate", LocalDate.fromDateFields(this.expectedDisbursedOnDate).toString(fmt));
actualChanges.put("actualDisbursementDate", command.stringValueOfParameterNamed("actualDisbursementDate"));
handleDisbursementTransaction(disbursedOn);
handleDisbursementTransaction(actualDisbursementDate);
if (isRepaymentScheduleRegenerationRequiredForDisbursement(disbursedOn)) {
if (isRepaymentScheduleRegenerationRequiredForDisbursement(actualDisbursementDate)) {
regenerateRepaymentSchedule(currency);
}
}
@@ -1267,9 +1258,9 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
this.loanStatus = statusEnum.getValue();
actualChanges.put("status", LoanEnumerations.status(this.loanStatus));
this.disbursedOnDate = null;
this.actualDisbursementDate = null;
this.disbursedBy = null;
actualChanges.put("disbursedOnDate", "");
actualChanges.put("actualDisbursementDate", "");
existingTransactionIds.addAll(findExistingTransactionIds());
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
@@ -1290,7 +1281,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
}
private void updateLoanToPreDisbursalState() {
this.disbursedOnDate = null;
this.actualDisbursementDate = null;
for (LoanCharge charge : getNullPointerSafeLoanCharges()) {
charge.resetToOriginal(loanCurrency());
@@ -1318,11 +1309,15 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
}
public LoanTransaction makeRepayment(final LocalDate transactionDate, final BigDecimal transactionAmount,
final LoanLifecycleStateMachine loanLifecycleStateMachine) {
final LoanLifecycleStateMachine loanLifecycleStateMachine, final List<Long> existingTransactionIds,
final List<Long> existingReversedTransactionIds) {
final Money repayment = Money.of(loanCurrency(), transactionAmount);
final LoanTransaction loanTransaction = LoanTransaction.repayment(repayment, transactionDate);
existingTransactionIds.addAll(findExistingTransactionIds());
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
handleRepaymentOrWaiverTransaction(loanTransaction, loanLifecycleStateMachine, null);
return loanTransaction;
@@ -1418,7 +1413,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
this.loanStatus = statusEnum.getValue();
this.closedOnDate = transactionDate.toDate();
this.maturedOnDate = transactionDate.toDate();
this.actualMaturityDate = transactionDate.toDate();
}
private void handleLoanOverpayment(final LoanLifecycleStateMachine loanLifecycleStateMachine) {
@@ -1427,7 +1422,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
this.loanStatus = statusEnum.getValue();
this.closedOnDate = null;
this.maturedOnDate = null;
this.actualMaturityDate = null;
}
private boolean isChronologicallyLatestRepaymentOrWaiver(final LoanTransaction loanTransaction,
@@ -1530,7 +1525,11 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
}
public LoanTransaction adjustExistingTransaction(final LocalDate transactionDate, final BigDecimal transactionAmountValue,
final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanTransaction transactionForAdjustment) {
final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanTransaction transactionForAdjustment,
final List<Long> existingTransactionIds, final List<Long> existingReversedTransactionIds) {
existingTransactionIds.addAll(findExistingTransactionIds());
existingReversedTransactionIds.addAll(findExistingReversedTransactionIds());
final Money transactionAmount = Money.of(loanCurrency(), transactionAmountValue);
LoanTransaction newTransactionDetail = LoanTransaction.repayment(transactionAmount, transactionDate);
@@ -1914,8 +1913,8 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
public LocalDate getDisbursedOnDate() {
LocalDate date = null;
if (this.disbursedOnDate != null) {
date = new LocalDate(this.disbursedOnDate);
if (this.actualDisbursementDate != null) {
date = new LocalDate(this.actualDisbursementDate);
}
return date;
}
@@ -1937,13 +1936,13 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
}
public Date getExpectedDisbursedOnDate() {
return this.expectedDisbursedOnDate;
return this.expectedDisbursementDate;
}
public LocalDate getExpectedDisbursedOnLocalDate() {
LocalDate expectedDisbursementDate = null;
if (this.expectedDisbursedOnDate != null) {
expectedDisbursementDate = new LocalDate(this.expectedDisbursedOnDate);
if (this.expectedDisbursementDate != null) {
expectedDisbursementDate = new LocalDate(this.expectedDisbursementDate);
}
return expectedDisbursementDate;
}
@@ -1958,8 +1957,8 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
public LocalDate getDisbursementDate() {
LocalDate disbursementDate = getExpectedDisbursedOnLocalDate();
if (this.disbursedOnDate != null) {
disbursementDate = new LocalDate(this.disbursedOnDate);
if (this.actualDisbursementDate != null) {
disbursementDate = new LocalDate(this.actualDisbursementDate);
}
return disbursementDate;
}
@@ -1974,8 +1973,8 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
public LocalDate getActualMaturityDate() {
LocalDate possibleMaturityDate = null;
if (this.maturedOnDate != null) {
possibleMaturityDate = new LocalDate(this.maturedOnDate);
if (this.actualMaturityDate != null) {
possibleMaturityDate = new LocalDate(this.actualMaturityDate);
}
return possibleMaturityDate;
}
@@ -1986,8 +1985,8 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
if (this.expectedMaturityDate != null) {
possibleMaturityDate = new LocalDate(this.expectedMaturityDate);
}
if (this.maturedOnDate != null) {
possibleMaturityDate = new LocalDate(this.maturedOnDate);
if (this.actualMaturityDate != null) {
possibleMaturityDate = new LocalDate(this.actualMaturityDate);
}
return possibleMaturityDate;
}
@@ -2006,7 +2005,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
}
public boolean isActualDisbursedOnDateEarlierOrLaterThanExpected(final LocalDate actualDisbursedOnDate) {
return !new LocalDate(this.expectedDisbursedOnDate).isEqual(actualDisbursedOnDate);
return !new LocalDate(this.expectedDisbursementDate).isEqual(actualDisbursedOnDate);
}
public boolean isRepaymentScheduleRegenerationRequiredForDisbursement(final LocalDate actualDisbursementDate) {
@@ -2090,7 +2089,7 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
}
if (isDisbursed()) {
statusSinceDate = new LocalDate(this.disbursedOnDate);
statusSinceDate = new LocalDate(this.actualDisbursementDate);
}
if (isClosed()) {
@@ -19,14 +19,13 @@ import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.domain.AbstractAuditableCustom;
import org.mifosplatform.organisation.monetary.data.CurrencyData;
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.portfolio.loanaccount.data.LoanTransactionData;
import org.mifosplatform.portfolio.loanaccount.data.LoanTransactionEnumData;
import org.mifosplatform.portfolio.loanproduct.service.LoanEnumerations;
import org.mifosplatform.useradministration.domain.AppUser;
import org.springframework.data.jpa.domain.AbstractPersistable;
/**
* All monetary transactions against a loan are modelled through this entity.
@@ -34,12 +33,19 @@ import org.mifosplatform.useradministration.domain.AppUser;
*/
@Entity
@Table(name = "m_loan_transaction")
public final class LoanTransaction extends AbstractAuditableCustom<AppUser, Long> {
public final class LoanTransaction extends AbstractPersistable<Long> {
@ManyToOne(optional = false)
@JoinColumn(name = "loan_id", nullable = false)
private Loan loan;
@Column(name = "transaction_type_enum", nullable = false)
private final Integer typeOf;
@Temporal(TemporalType.DATE)
@Column(name = "transaction_date", nullable = false)
private final Date dateOf;
@Column(name = "amount", scale = 6, precision = 19, nullable = false)
private BigDecimal amount;
@@ -55,13 +61,6 @@ public final class LoanTransaction extends AbstractAuditableCustom<AppUser, Long
@Column(name = "penalty_charges_portion_derived", scale = 6, precision = 19, nullable = true)
private BigDecimal penaltyChargesPortion = BigDecimal.ZERO;
@Temporal(TemporalType.DATE)
@Column(name = "transaction_date", nullable = false)
private final Date dateOf;
@Column(name = "transaction_type_enum", nullable = false)
private final Integer typeOf;
@Column(name = "is_reversed", nullable = false)
private boolean reversed;
@@ -152,7 +151,7 @@ public final class LoanTransaction extends AbstractAuditableCustom<AppUser, Long
public Money getPrincipalPortion(final MonetaryCurrency currency) {
return Money.of(currency, this.principalPortion);
}
public BigDecimal getPrincipalPortion() {
return this.principalPortion;
}
@@ -160,7 +159,7 @@ public final class LoanTransaction extends AbstractAuditableCustom<AppUser, Long
public Money getInterestPortion(final MonetaryCurrency currency) {
return Money.of(currency, this.interestPortion);
}
public BigDecimal getInterestPortion() {
return this.interestPortion;
}
@@ -168,11 +167,11 @@ public final class LoanTransaction extends AbstractAuditableCustom<AppUser, Long
public Money getFeeChargesPortion(final MonetaryCurrency currency) {
return Money.of(currency, this.feeChargesPortion);
}
public BigDecimal getFeePortion() {
return this.feeChargesPortion;
}
public Money getPenaltyChargesPortion(final MonetaryCurrency currency) {
return Money.of(currency, this.penaltyChargesPortion);
}
@@ -0,0 +1,66 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.loanaccount.serialization;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.core.data.ApiParameterError;
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.InvalidJsonException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
@Component
public final class LoanEventApiJsonValidator {
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public LoanEventApiJsonValidator(final FromJsonHelper fromApiJsonHelper) {
this.fromApiJsonHelper = fromApiJsonHelper;
}
public void validateDisbursement(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Set<String> disbursementParameters = new HashSet<String>(Arrays.asList("actualDisbursementDate", "note", "locale",
"dateFormat"));
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, disbursementParameters);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan.disbursement");
final JsonElement element = fromApiJsonHelper.parse(json);
final LocalDate actualDisbursementDate = fromApiJsonHelper.extractLocalDateNamed("actualDisbursementDate", element);
baseDataValidator.reset().parameter("actualDisbursementDate").value(actualDisbursementDate).notNull();
final String note = fromApiJsonHelper.extractStringNamed("note", element);
baseDataValidator.reset().parameter("note").value(note).notExceedingLengthOf(1000);
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
}
@@ -34,7 +34,6 @@ import org.mifosplatform.portfolio.charge.exception.LoanChargeNotFoundException;
import org.mifosplatform.portfolio.client.domain.Note;
import org.mifosplatform.portfolio.client.domain.NoteRepository;
import org.mifosplatform.portfolio.loanaccount.command.LoanChargeCommand;
import org.mifosplatform.portfolio.loanaccount.command.LoanStateTransitionCommand;
import org.mifosplatform.portfolio.loanaccount.command.LoanTransactionCommand;
import org.mifosplatform.portfolio.loanaccount.command.LoanUpdateCommand;
import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine;
@@ -51,7 +50,7 @@ import org.mifosplatform.portfolio.loanaccount.exception.LoanOfficerAssignmentEx
import org.mifosplatform.portfolio.loanaccount.exception.LoanOfficerUnassignmentException;
import org.mifosplatform.portfolio.loanaccount.exception.LoanTransactionNotFoundException;
import org.mifosplatform.portfolio.loanaccount.serialization.LoanChargeCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.loanaccount.serialization.LoanStateTransitionCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.loanaccount.serialization.LoanEventApiJsonValidator;
import org.mifosplatform.portfolio.loanaccount.serialization.LoanTransactionCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.loanaccount.serialization.LoanUpdateCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.loanproduct.exception.InvalidCurrencyException;
@@ -64,7 +63,7 @@ import org.springframework.transaction.annotation.Transactional;
public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatformService {
private final PlatformSecurityContext context;
private final LoanStateTransitionCommandFromApiJsonDeserializer loanStateTransitionCommandFromApiJsonDeserializer;
private final LoanEventApiJsonValidator loanEventApiJsonValidator;
private final LoanTransactionCommandFromApiJsonDeserializer loanTransactionCommandFromApiJsonDeserializer;
private final LoanChargeCommandFromApiJsonDeserializer loanChargeCommandFromApiJsonDeserializer;
private final LoanUpdateCommandFromApiJsonDeserializer loanUpdateCommandFromApiJsonDeserializer;
@@ -79,7 +78,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
@Autowired
public LoanWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
final LoanStateTransitionCommandFromApiJsonDeserializer loanStateTransitionCommandFromApiJsonDeserializer,
final LoanEventApiJsonValidator loanEventApiJsonValidator,
final LoanTransactionCommandFromApiJsonDeserializer loanTransactionCommandFromApiJsonDeserializer,
final LoanChargeCommandFromApiJsonDeserializer loanChargeCommandFromApiJsonDeserializer,
final LoanUpdateCommandFromApiJsonDeserializer loanUpdateCommandFromApiJsonDeserializer, final LoanAssembler loanAssembler,
@@ -88,7 +87,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final ApplicationCurrencyRepository applicationCurrencyRepository,
final JournalEntryWritePlatformService journalEntryWritePlatformService) {
this.context = context;
this.loanStateTransitionCommandFromApiJsonDeserializer = loanStateTransitionCommandFromApiJsonDeserializer;
this.loanEventApiJsonValidator = loanEventApiJsonValidator;
this.loanTransactionCommandFromApiJsonDeserializer = loanTransactionCommandFromApiJsonDeserializer;
this.loanChargeCommandFromApiJsonDeserializer = loanChargeCommandFromApiJsonDeserializer;
this.loanAssembler = loanAssembler;
@@ -117,18 +116,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final AppUser currentUser = context.authenticatedUser();
final LoanStateTransitionCommand disburseLoan = this.loanStateTransitionCommandFromApiJsonDeserializer.commandFromApiJson(command
.json());
disburseLoan.validate();
this.loanEventApiJsonValidator.validateDisbursement(command.json());
final Loan loan = retrieveLoanBy(loanId);
final String noteText = command.stringValueOfParameterNamed("note");
final LocalDate actualDisbursementDate = disburseLoan.getDisbursedOnDate();
if (this.isBeforeToday(actualDisbursementDate) && currentUser.canNotDisburseLoanInPast()) { throw new NoAuthorizationException(
"User has no authority to disburse loan with a date in the past."); }
final ApplicationCurrency currency = this.applicationCurrencyRepository.findOneByCode(loan.getPrincpal().getCurrencyCode());
final ApplicationCurrency currency = this.applicationCurrencyRepository.findOneByCode(loan.getCurrencyCode());
final List<Long> existingTransactionIds = new ArrayList<Long>();
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
@@ -137,6 +129,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
if (!changes.isEmpty()) {
this.loanRepository.save(loan);
final String noteText = command.stringValueOfParameterNamed("note");
if (StringUtils.isNotBlank(noteText)) {
Note note = Note.loanNote(loan, noteText);
this.noteRepository.save(note);
@@ -171,7 +164,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final Map<String, Object> changes = loan.undoDisbursal(defaultLoanLifecycleStateMachine(), existingTransactionIds,
existingReversedTransactionIds);
if (!changes.isEmpty()) {
this.loanRepository.saveAndFlush(loan);
this.loanRepository.save(loan);
final String noteText = command.stringValueOfParameterNamed("note");
if (StringUtils.isNotBlank(noteText)) {
@@ -218,7 +211,11 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
if (this.isBeforeToday(transactionDate) && currentUser.canNotMakeRepaymentOnLoanInPast()) { throw new NoAuthorizationException(
"error.msg.no.permission.to.make.repayment.on.loan.in.past"); }
final LoanTransaction loanRepayment = loan.makeRepayment(transactionDate, transactionAmount, defaultLoanLifecycleStateMachine());
final List<Long> existingTransactionIds = new ArrayList<Long>();
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
final LoanTransaction loanRepayment = loan.makeRepayment(transactionDate, transactionAmount, defaultLoanLifecycleStateMachine(),
existingTransactionIds, existingReversedTransactionIds);
this.loanTransactionRepository.save(loanRepayment);
this.loanRepository.save(loan);
@@ -232,11 +229,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
changes.put("locale", command.locale());
changes.put("dateFormat", command.dateFormat());
// make a call to accounting
if (loan.isAccountingEnabledOnLoanProduct()) {
LoanDTO loanDTO = populateLoanData(loan, loanRepayment);
journalEntryWritePlatformService.createJournalEntriesForLoan(loanDTO);
}
final ApplicationCurrency currency = this.applicationCurrencyRepository.findOneByCode(loan.getCurrencyCode());
final Map<String, Object> accountingBridgeData = loan.deriveAccountingBridgeData(currency.toData(), existingTransactionIds,
existingReversedTransactionIds);
journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
@@ -271,15 +267,17 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
changes.put("transactionDate", command.stringValueOfParameterNamed("transactionDate"));
changes.put("transactionAmount", command.stringValueOfParameterNamed("transactionAmount"));
boolean transactionIsRepayment = transactionToAdjust.isRepayment();
final List<Long> existingTransactionIds = new ArrayList<Long>();
final List<Long> existingReversedTransactionIds = new ArrayList<Long>();
final LoanTransaction newTransactionDetail = loan.adjustExistingTransaction(transactionDate, transactionAmount,
defaultLoanLifecycleStateMachine(), transactionToAdjust);
defaultLoanLifecycleStateMachine(), transactionToAdjust, existingTransactionIds, existingReversedTransactionIds);
if (newTransactionDetail.isGreaterThanZero(loan.getPrincpal().getCurrency())) {
this.loanTransactionRepository.saveAndFlush(newTransactionDetail);
this.loanTransactionRepository.save(newTransactionDetail);
}
this.loanRepository.saveAndFlush(loan);
this.loanRepository.save(loan);
final String noteText = command.stringValueOfParameterNamed("note");
if (StringUtils.isNotBlank(noteText)) {
@@ -291,17 +289,10 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
changes.put("locale", command.locale());
changes.put("dateFormat", command.dateFormat());
// make a call to accounting only if transaction being adjusted is a
// repayment (not waiver)
if (loan.isAccountingEnabledOnLoanProduct() && transactionIsRepayment) {
List<LoanTransaction> newLoanTransactions = new ArrayList<LoanTransaction>();
if (newTransactionDetail.getId() != null) {
newLoanTransactions.add(newTransactionDetail);
}
newLoanTransactions.add(transactionToAdjust);
LoanDTO loanDTO = populateLoanDTO(loan, newLoanTransactions);
journalEntryWritePlatformService.createJournalEntriesForLoan(loanDTO);
}
final ApplicationCurrency currency = this.applicationCurrencyRepository.findOneByCode(loan.getCurrencyCode());
final Map<String, Object> accountingBridgeData = loan.deriveAccountingBridgeData(currency.toData(), existingTransactionIds,
existingReversedTransactionIds);
journalEntryWritePlatformService.createJournalEntriesForLoan(accountingBridgeData);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
@@ -655,7 +646,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
loan.reassignLoanOfficer(toLoanOfficer, dateOfLoanOfficerAssignment);
this.loanRepository.saveAndFlush(loan);
this.loanRepository.save(loan);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
@@ -717,7 +708,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
loan.removeLoanOfficer(dateOfLoanOfficerunAssigned);
this.loanRepository.saveAndFlush(loan);
this.loanRepository.save(loan);
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //