diff --git a/mifosng-db/multi-tenant-demo-backups/ceda/bk_ceda_trial.sql b/mifosng-db/multi-tenant-demo-backups/ceda/bk_ceda_trial.sql index 57a96b78e..5f47c45b6 100644 --- a/mifosng-db/multi-tenant-demo-backups/ceda/bk_ceda_trial.sql +++ b/mifosng-db/multi-tenant-demo-backups/ceda/bk_ceda_trial.sql @@ -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 diff --git a/mifosng-db/patches/10-refactor-contra-reversal-transactions-for-loan-portfolio.sql b/mifosng-db/patches/10-refactor-contra-reversal-transactions-for-loan-portfolio.sql index 1a5b66983..baf000fd6 100644 --- a/mifosng-db/patches/10-refactor-contra-reversal-transactions-for-loan-portfolio.sql +++ b/mifosng-db/patches/10-refactor-contra-reversal-transactions-for-loan-portfolio.sql @@ -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`; \ No newline at end of file +DROP INDEX `FKCFCEA426FC69F3F1`; + + +ALTER TABLE `m_loan_transaction` +DROP COLUMN `lastmodifiedby_id`, +DROP COLUMN `lastmodified_date`, +DROP COLUMN `created_date`, +DROP COLUMN `createdby_id`; \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java index 5620abb8f..854b65d1e 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java @@ -165,11 +165,11 @@ public class Loan extends AbstractAuditableCustom { @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 { @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 { 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 allNonContraTransactionsPostDisbursement = retreiveListOfTransactionsPostDisbursement(); loanRepaymentScheduleTransactionProcessor.handleTransaction(getDisbursementDate(), allNonContraTransactionsPostDisbursement, getCurrency(), this.repaymentScheduleInstallments, getNullPointerSafeLoanCharges()); @@ -640,6 +637,7 @@ public class Loan extends AbstractAuditableCustom { public void updateLoanScheduleDependentDerivedFields() { this.expectedMaturityDate = determineExpectedMaturityDate().toDate(); + this.actualMaturityDate = determineExpectedMaturityDate().toDate(); } public Map loanApplicationModification(final JsonCommand command, final Set possiblyModifedLoanCharges, @@ -737,7 +735,7 @@ public class Loan extends AbstractAuditableCustom { 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 { // 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 { 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 { } 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 { 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 { 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 { } 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 { } public LoanTransaction makeRepayment(final LocalDate transactionDate, final BigDecimal transactionAmount, - final LoanLifecycleStateMachine loanLifecycleStateMachine) { + final LoanLifecycleStateMachine loanLifecycleStateMachine, final List existingTransactionIds, + final List 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 { 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 { 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 { } public LoanTransaction adjustExistingTransaction(final LocalDate transactionDate, final BigDecimal transactionAmountValue, - final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanTransaction transactionForAdjustment) { + final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanTransaction transactionForAdjustment, + final List existingTransactionIds, final List 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 { 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 { } 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 { 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 { 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 { 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 { } 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 { } if (isDisbursed()) { - statusSinceDate = new LocalDate(this.disbursedOnDate); + statusSinceDate = new LocalDate(this.actualDisbursementDate); } if (isClosed()) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanTransaction.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanTransaction.java index 87ae169f7..eb9146de0 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanTransaction.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanTransaction.java @@ -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 { +public final class LoanTransaction extends AbstractPersistable { @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 disbursementParameters = new HashSet(Arrays.asList("actualDisbursementDate", "note", "locale", + "dateFormat")); + + final Type typeOfMap = new TypeToken>() {}.getType(); + fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, disbursementParameters); + + final List dataValidationErrors = new ArrayList(); + 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 dataValidationErrors) { + if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", + "Validation errors exist.", dataValidationErrors); } + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index dce196baf..419776a75 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -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 existingTransactionIds = new ArrayList(); final List existingReversedTransactionIds = new ArrayList(); @@ -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 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 existingTransactionIds = new ArrayList(); + final List existingReversedTransactionIds = new ArrayList(); + + 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 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 existingTransactionIds = new ArrayList(); + final List existingReversedTransactionIds = new ArrayList(); 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 newLoanTransactions = new ArrayList(); - 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 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()) //