From 0e85f998c69206ee79cdd3f6c258167beb8dcdc4 Mon Sep 17 00:00:00 2001 From: fynmanoj Date: Thu, 2 Sep 2021 14:30:42 +0530 Subject: [PATCH] settlement-api-for-collection-and-txn-value-date --- .../domain/data/CollectionStatusEnum.java | 27 ++++ .../domain/data/SettleCollectionsRequest.java | 116 ++++++++++++++++++ .../domain/data/TransactionRequestData.java | 14 ++- .../command/SettleCollectionsCommand.java | 35 ++++++ .../handler/CollectionsCommandHandler.java | 92 +++++++++++++- .../handler/ProductInstanceAggregate.java | 3 +- .../handler/TransactionCommandHandler.java | 2 - .../repository/SelfExpiringTokenEntity.java | 1 + .../service/SelfExpiringTokenService.java | 15 +++ .../internal/service/TransactionService.java | 32 +++-- .../rest/CollectionsRestController.java | 18 +++ 11 files changed, 338 insertions(+), 17 deletions(-) create mode 100644 api/src/main/java/org/apache/fineract/cn/deposit/api/v1/collection/domain/data/CollectionStatusEnum.java create mode 100644 api/src/main/java/org/apache/fineract/cn/deposit/api/v1/collection/domain/data/SettleCollectionsRequest.java create mode 100644 service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/SettleCollectionsCommand.java diff --git a/api/src/main/java/org/apache/fineract/cn/deposit/api/v1/collection/domain/data/CollectionStatusEnum.java b/api/src/main/java/org/apache/fineract/cn/deposit/api/v1/collection/domain/data/CollectionStatusEnum.java new file mode 100644 index 0000000..81bebb1 --- /dev/null +++ b/api/src/main/java/org/apache/fineract/cn/deposit/api/v1/collection/domain/data/CollectionStatusEnum.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.fineract.cn.deposit.api.v1.collection.domain.data; + +/** + * @author manoj + */ +public enum CollectionStatusEnum { + INIT, + PROCESSING, + COLLECTED; +} diff --git a/api/src/main/java/org/apache/fineract/cn/deposit/api/v1/collection/domain/data/SettleCollectionsRequest.java b/api/src/main/java/org/apache/fineract/cn/deposit/api/v1/collection/domain/data/SettleCollectionsRequest.java new file mode 100644 index 0000000..f92a4e7 --- /dev/null +++ b/api/src/main/java/org/apache/fineract/cn/deposit/api/v1/collection/domain/data/SettleCollectionsRequest.java @@ -0,0 +1,116 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.fineract.cn.deposit.api.v1.collection.domain.data; + +import java.math.BigDecimal; + +/** + * @author manoj + */ +public class SettleCollectionsRequest { + private String token; + private BigDecimal amount; + + private String transactionCode; + private String requestCode; + private String routingCode; + private String externalId; + private String note; + private String txnDate; + + public SettleCollectionsRequest() { + } + + public SettleCollectionsRequest(String token, BigDecimal amount, String transactionCode, + String requestCode, String routingCode, String externalId, String note, + String txnDate) { + this.token = token; + this.amount = amount; + this.transactionCode = transactionCode; + this.requestCode = requestCode; + this.routingCode = routingCode; + this.externalId = externalId; + this.note = note; + this.txnDate = txnDate; + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public BigDecimal getAmount() { + return amount; + } + + public void setAmount(BigDecimal amount) { + this.amount = amount; + } + + public String getTransactionCode() { + return transactionCode; + } + + public void setTransactionCode(String transactionCode) { + this.transactionCode = transactionCode; + } + + public String getRequestCode() { + return requestCode; + } + + public void setRequestCode(String requestCode) { + this.requestCode = requestCode; + } + + public String getRoutingCode() { + return routingCode; + } + + public void setRoutingCode(String routingCode) { + this.routingCode = routingCode; + } + + public String getExternalId() { + return externalId; + } + + public void setExternalId(String externalId) { + this.externalId = externalId; + } + + public String getNote() { + return note; + } + + public void setNote(String note) { + this.note = note; + } + + public String getTxnDate() { + return txnDate; + } + + public void setTxnDate(String txnDate) { + this.txnDate = txnDate; + } + +} diff --git a/api/src/main/java/org/apache/fineract/cn/deposit/api/v1/transaction/domain/data/TransactionRequestData.java b/api/src/main/java/org/apache/fineract/cn/deposit/api/v1/transaction/domain/data/TransactionRequestData.java index f92a576..0b2846e 100644 --- a/api/src/main/java/org/apache/fineract/cn/deposit/api/v1/transaction/domain/data/TransactionRequestData.java +++ b/api/src/main/java/org/apache/fineract/cn/deposit/api/v1/transaction/domain/data/TransactionRequestData.java @@ -62,13 +62,16 @@ public class TransactionRequestData { @Length(max = 32) private String toAccountId; + private String transactionDate; + public TransactionRequestData() { } public TransactionRequestData(String transactionCode, String requestCode, String routingCode, String externalId, String accountId, String note, LocalDateTime expiration, MoneyData amount, String subTxnId, - String fromAccountId, String toAccountId) { + String fromAccountId, String toAccountId, + String transactionDate) { this.transactionCode = transactionCode; this.requestCode = requestCode; this.routingCode = routingCode; @@ -81,6 +84,7 @@ public TransactionRequestData(String transactionCode, String requestCode, String this.subTxnId = subTxnId; this.fromAccountId = fromAccountId; this.toAccountId = toAccountId; + this.transactionDate = transactionDate; } @NotNull @@ -175,4 +179,12 @@ public String getToAccountId() { public void setToAccountId(String toAccountId) { this.toAccountId = toAccountId; } + + public String getTransactionDate() { + return transactionDate; + } + + public void setTransactionDate(String transactionDate) { + this.transactionDate = transactionDate; + } } diff --git a/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/SettleCollectionsCommand.java b/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/SettleCollectionsCommand.java new file mode 100644 index 0000000..b6db482 --- /dev/null +++ b/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/SettleCollectionsCommand.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.fineract.cn.deposit.service.internal.command; + +import org.apache.fineract.cn.deposit.api.v1.collection.domain.data.SettleCollectionsRequest; + +/** + * @author manoj + */ +public class SettleCollectionsCommand { + private SettleCollectionsRequest settleCollectionsRequest; + + public SettleCollectionsCommand(SettleCollectionsRequest settleCollectionsRequest) { + this.settleCollectionsRequest = settleCollectionsRequest; + } + + public SettleCollectionsRequest getSettleCollectionsRequest() { + return settleCollectionsRequest; + } +} diff --git a/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/handler/CollectionsCommandHandler.java b/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/handler/CollectionsCommandHandler.java index 1b77e0d..0959a5a 100644 --- a/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/handler/CollectionsCommandHandler.java +++ b/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/handler/CollectionsCommandHandler.java @@ -20,19 +20,23 @@ import org.apache.fineract.cn.command.annotation.Aggregate; import org.apache.fineract.cn.command.annotation.CommandHandler; import org.apache.fineract.cn.command.annotation.CommandLogLevel; -import org.apache.fineract.cn.deposit.api.v1.collection.domain.data.CollectionsResponse; -import org.apache.fineract.cn.deposit.api.v1.collection.domain.data.IndividualPayments; -import org.apache.fineract.cn.deposit.api.v1.collection.domain.data.TokenEntities; +import org.apache.fineract.cn.deposit.api.v1.collection.domain.data.*; +import org.apache.fineract.cn.deposit.api.v1.transaction.domain.data.MoneyData; +import org.apache.fineract.cn.deposit.api.v1.transaction.domain.data.TransactionActionType; +import org.apache.fineract.cn.deposit.api.v1.transaction.domain.data.TransactionRequestData; import org.apache.fineract.cn.deposit.service.ServiceConstants; import org.apache.fineract.cn.deposit.service.internal.command.CreateCollectionsCommand; +import org.apache.fineract.cn.deposit.service.internal.command.SettleCollectionsCommand; import org.apache.fineract.cn.deposit.service.internal.command.UpdateCollectionsCommand; import org.apache.fineract.cn.deposit.service.internal.mapper.CollectionsMapper; import org.apache.fineract.cn.deposit.service.internal.repository.*; import org.apache.fineract.cn.deposit.service.internal.service.SelfExpiringTokenService; +import org.apache.fineract.cn.deposit.service.rest.TransactionRestController; import org.apache.fineract.cn.lang.ServiceException; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Lazy; import org.springframework.transaction.annotation.Transactional; import javax.validation.constraints.NotNull; @@ -47,19 +51,25 @@ public class CollectionsCommandHandler { private final ProductInstanceRepository productInstanceRepository; private final SubTransactionTypeRepository subTransactionTypeRepository; private final CollectionsRepository collectionsRepository; + private final IndividualCollectionsRepository individualCollectionsRepository; private final SelfExpiringTokenService selfExpiringTokenService; + private final TransactionRestController transactionRestController; @Autowired public CollectionsCommandHandler(@Qualifier(ServiceConstants.LOGGER_NAME) Logger logger, ProductInstanceRepository productInstanceRepository, SubTransactionTypeRepository subTransactionTypeRepository, CollectionsRepository collectionsRepository, - SelfExpiringTokenService selfExpiringTokenService) { + IndividualCollectionsRepository individualCollectionsRepository, + SelfExpiringTokenService selfExpiringTokenService, + @Lazy TransactionRestController transactionRestController) { this.logger = logger; this.productInstanceRepository = productInstanceRepository; this.subTransactionTypeRepository = subTransactionTypeRepository; this.collectionsRepository = collectionsRepository; + this.individualCollectionsRepository = individualCollectionsRepository; this.selfExpiringTokenService = selfExpiringTokenService; + this.transactionRestController = transactionRestController; } @Transactional @@ -117,5 +127,79 @@ private static LocalDateTime getNow() { return LocalDateTime.now(Clock.systemUTC()); } + @Transactional + @CommandHandler(logStart = CommandLogLevel.INFO, logFinish = CommandLogLevel.INFO) + public CollectionsResponse settleCollection(@NotNull SettleCollectionsCommand command) throws Throwable { + SettleCollectionsRequest request = command.getSettleCollectionsRequest(); + //1. find which collection it is + SelfExpiringTokenEntity token = this.selfExpiringTokenService.fetchActiveToken(request.getToken()); + CollectionsEntity collectionsEntity; + if(TokenEntities.COLLECTION.name().equals(token.getEntityType())){ + //if group collection, deposit individual, then transfer to group + + collectionsEntity = this.collectionsRepository.findByCollectionReference(token.getEntityReference()) + .orElseThrow(() -> ServiceException.notFound("Collection {0} not found", token.getEntityReference())); + //validate amount + if(collectionsEntity.getAmount().compareTo(request.getAmount()) !=0){ + throw ServiceException.internalError("Amount mismatch"); + } + if(CollectionStatusEnum.COLLECTED.name().equals(collectionsEntity.getStatus())){ + throw ServiceException.internalError("Already Collected"); + } + + + for (IndividualCollectionsEntity individualCollectionsEntity : collectionsEntity.getIndvCollections()) { + if (individualCollectionsEntity.getAttendance().equals(AttendanceEnum.PRESENT.name())) { + //deposit + TransactionRequestData depositReq = new TransactionRequestData(request.getTransactionCode(), request.getRequestCode(), + request.getRoutingCode(), request.getExternalId(), individualCollectionsEntity.getAccount().getAccountIdentifier(), + request.getNote(), null, + MoneyData.build(individualCollectionsEntity.getAmount(), individualCollectionsEntity.getCollection().getCurrency()), + collectionsEntity.getSubTxnType().getIdentifier(), null, null, request.getTxnDate()); + + transactionRestController.performTxn(TransactionActionType.DEPOSIT.name(), depositReq); + + //transfer + TransactionRequestData transferReq = new TransactionRequestData(request.getTransactionCode(), request.getRequestCode(), + request.getRoutingCode(), request.getExternalId(), null, + request.getNote(), null, + MoneyData.build(individualCollectionsEntity.getAmount(), individualCollectionsEntity.getCollection().getCurrency()), + collectionsEntity.getSubTxnType().getIdentifier(), individualCollectionsEntity.getAccount().getAccountIdentifier(), collectionsEntity.getAccount().getAccountIdentifier(), + request.getTxnDate()); + transactionRestController.performTxn(TransactionActionType.TRANSFER.name(), transferReq); + + this.selfExpiringTokenService.markTokenAsUsed(individualCollectionsEntity.getToken()); + } + } + this.selfExpiringTokenService.markTokenAsUsed(collectionsEntity.getToken()); + collectionsEntity.setStatus(CollectionStatusEnum.COLLECTED.name()); + collectionsRepository.save(collectionsEntity); + }else{ + //if individual collection, deposit to individual account + IndividualCollectionsEntity individualCollectionsEntity = this.individualCollectionsRepository.findByIndividualCollectionReference(token.getEntityReference()) + .orElseThrow(() -> ServiceException.notFound("Collection {0} not found", token.getEntityReference())); + collectionsEntity = individualCollectionsEntity.getCollection(); + //validate amount + if(individualCollectionsEntity.getAmount().compareTo(request.getAmount()) != 0){ + throw ServiceException.internalError("Amount mismatch"); + } + if(CollectionStatusEnum.COLLECTED.name().equals(collectionsEntity.getStatus())){ + throw ServiceException.internalError("Already Collected"); + } + //add txn Date and subTxnType + //deposit + TransactionRequestData depositReq = new TransactionRequestData(request.getTransactionCode(), request.getRequestCode(), + request.getRoutingCode(), request.getExternalId(), individualCollectionsEntity.getAccount().getAccountIdentifier(), + request.getNote(), null, + MoneyData.build(individualCollectionsEntity.getAmount(), individualCollectionsEntity.getCollection().getCurrency()), + collectionsEntity.getSubTxnType().getIdentifier(), null, null, request.getTxnDate()); + + transactionRestController.performTxn(TransactionActionType.DEPOSIT.name(), depositReq); + this.selfExpiringTokenService.markTokenAsUsed(individualCollectionsEntity.getToken()); + collectionsEntity.setStatus(CollectionStatusEnum.PROCESSING.name()); + collectionsRepository.save(collectionsEntity); + } + return CollectionsMapper.map(collectionsEntity); + } } diff --git a/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/handler/ProductInstanceAggregate.java b/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/handler/ProductInstanceAggregate.java index 15b7aae..2162afb 100644 --- a/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/handler/ProductInstanceAggregate.java +++ b/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/handler/ProductInstanceAggregate.java @@ -108,7 +108,8 @@ public String createProductInstance(final CreateProductInstanceCommand createPro productInstanceEntity.setCreatedBy(UserContextHolder.checkedGetUser()); productInstanceEntity.setCreatedOn(LocalDateTime.now(Clock.systemUTC())); - productInstanceEntity.setState("PENDING"); + if(StringUtils.isBlank(productInstanceEntity.getState())) + productInstanceEntity.setState("PENDING"); this.productInstanceRepository.save(productInstanceEntity); return productInstance.getCustomerIdentifier(); diff --git a/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/handler/TransactionCommandHandler.java b/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/handler/TransactionCommandHandler.java index 4851a35..77d3877 100644 --- a/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/handler/TransactionCommandHandler.java +++ b/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/command/handler/TransactionCommandHandler.java @@ -55,11 +55,9 @@ public TransactionResponseData performTransfer(@NotNull TransactionCommand comma switch (command.getAction()) { case WITHDRAWAL: { - //command = dataValidator.validatePrepareTransfer(command); return transactionService.withdraw(command); } case DEPOSIT: { - //command = dataValidator.validateCommitTransfer(command); return transactionService.deposit(command); } case TRANSFER: { diff --git a/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/repository/SelfExpiringTokenEntity.java b/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/repository/SelfExpiringTokenEntity.java index 3d9d992..a761983 100644 --- a/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/repository/SelfExpiringTokenEntity.java +++ b/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/repository/SelfExpiringTokenEntity.java @@ -41,6 +41,7 @@ public class SelfExpiringTokenEntity { @Convert(converter = LocalDateTimeConverter.class) private LocalDateTime tokenExpiresBy; + /*TokenStatus*/ @Column(name = "status", length = 10) private String status; diff --git a/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/service/SelfExpiringTokenService.java b/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/service/SelfExpiringTokenService.java index dae344e..5668ec6 100644 --- a/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/service/SelfExpiringTokenService.java +++ b/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/service/SelfExpiringTokenService.java @@ -21,11 +21,14 @@ import org.apache.fineract.cn.deposit.service.ServiceConstants; import org.apache.fineract.cn.deposit.service.internal.repository.SelfExpiringTokenEntity; import org.apache.fineract.cn.deposit.service.internal.repository.SelfExpiringTokenRepository; +import org.apache.fineract.cn.lang.ServiceException; import org.slf4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; import java.security.SecureRandom; import java.time.LocalDateTime; @@ -63,6 +66,18 @@ public SelfExpiringTokenEntity generateAndSaveToken(String entityType, String en return entity; } + public SelfExpiringTokenEntity fetchActiveToken(String token){ + return this.selfExpiringTokenRepository.findByTokenAndStatus(token, TokenStatus.ACTIVE.name()).orElseThrow( + ()-> ServiceException.notFound("Active token not found") + ); + } + + @Transactional(propagation = Propagation.REQUIRES_NEW) + public void markTokenAsUsed(SelfExpiringTokenEntity selfExpiringTokenEntity){ + selfExpiringTokenEntity.setStatus(TokenStatus.USED.name()); + this.selfExpiringTokenRepository.save(selfExpiringTokenEntity); + } + private String generateUniqueToken(){ String token = generateRandomToken(otpTokenLength); while(this.selfExpiringTokenRepository.findByTokenAndStatus(token, TokenStatus.ACTIVE.name()).isPresent()){ diff --git a/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/service/TransactionService.java b/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/service/TransactionService.java index e739159..86b8c75 100644 --- a/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/service/TransactionService.java +++ b/service/src/main/java/org/apache/fineract/cn/deposit/service/internal/service/TransactionService.java @@ -93,12 +93,18 @@ public TransactionResponseData withdraw(TransactionCommand command) { TransactionRequestData request = command.getTransactionRequest(); accountAccessValidator.validate(request.getAccountId(), ACCT_WITHDRAWAL_OPERATION); AccountWrapper accountWrapper = validateAndGetAccount(request, request.getAccountId(), TransactionTypeEnum.WITHDRAWAL); - LocalDateTime transactionDate = getNow(); + LocalDateTime transactionDate; + if(StringUtils.isNotBlank(request.getTransactionDate())){ + transactionDate = DateConverter.fromIsoString(request.getTransactionDate()); + } else { + transactionDate = getNow(); + } + //get txntype charges List charges = getCharges(accountWrapper.productDefinition, TransactionTypeEnum.WITHDRAWAL); //todo: get subTxnType charges - TransactionEntity txn = doWithdraw(request, accountWrapper, charges, getNow(), request.getAccountId()); + TransactionEntity txn = doWithdraw(request, accountWrapper, charges, transactionDate, request.getAccountId()); return TransactionResponseData.build(request.getRoutingCode(), request.getExternalId(), @@ -112,11 +118,16 @@ public TransactionResponseData deposit(TransactionCommand command) { accountAccessValidator.validate(request.getAccountId(), ACCT_DEPOSIT_OPERATION); AccountWrapper accountWrapper = validateAndGetAccount(request, request.getAccountId(), TransactionTypeEnum.DEPOSIT); - LocalDateTime transactionDate = getNow(); + LocalDateTime transactionDate; + if(StringUtils.isNotBlank(request.getTransactionDate())){ + transactionDate = DateConverter.fromIsoString(request.getTransactionDate()); + } else { + transactionDate = getNow(); + } //get txntype charges List charges = getCharges(accountWrapper.productDefinition, TransactionTypeEnum.DEPOSIT); //todo: get subTxnType charges - TransactionEntity txn = doDeposit(request, accountWrapper, charges, getNow(), request.getAccountId()); + TransactionEntity txn = doDeposit(request, accountWrapper, charges, transactionDate, request.getAccountId()); return TransactionResponseData.build(request.getRoutingCode(), request.getExternalId(), request.getRequestCode(), ActionState.ACCEPTED, @@ -127,13 +138,18 @@ public TransactionResponseData transfer(TransactionCommand command) { TransactionRequestData request = command.getTransactionRequest(); AccountWrapper fromAccountWrapper = validateAndGetAccount(request, request.getFromAccountId(), TransactionTypeEnum.WITHDRAWAL); AccountWrapper toAccountWrapper = validateAndGetAccount(request, request.getToAccountId(), TransactionTypeEnum.DEPOSIT); - LocalDateTime transactionDate = getNow(); + LocalDateTime transactionDate; + if(StringUtils.isNotBlank(request.getTransactionDate())){ + transactionDate = DateConverter.fromIsoString(request.getTransactionDate()); + } else { + transactionDate = getNow(); + } //get txntype charges List charges = getCharges(fromAccountWrapper.productDefinition, TransactionTypeEnum.ACCOUNT_TRANSFER); //todo: get subTxnType charges - TransactionEntity txn = doWithdraw(request, fromAccountWrapper, charges, getNow(), request.getFromAccountId()); - TransactionEntity txn2 = doDeposit(request, toAccountWrapper, new ArrayList<>(), getNow(), request.getToAccountId()); + TransactionEntity txn = doWithdraw(request, fromAccountWrapper, charges, transactionDate, request.getFromAccountId()); + TransactionEntity txn2 = doDeposit(request, toAccountWrapper, new ArrayList<>(), transactionDate, request.getToAccountId()); return TransactionResponseData.build(request.getRoutingCode(), request.getExternalId(), request.getRequestCode(), ActionState.ACCEPTED, @@ -461,8 +477,6 @@ public BalanceResponse fetchBalance(String identifier) { return balance; } - - public static class AccountWrapper { @NotNull private final Account account; diff --git a/service/src/main/java/org/apache/fineract/cn/deposit/service/rest/CollectionsRestController.java b/service/src/main/java/org/apache/fineract/cn/deposit/service/rest/CollectionsRestController.java index e33616b..d09739f 100644 --- a/service/src/main/java/org/apache/fineract/cn/deposit/service/rest/CollectionsRestController.java +++ b/service/src/main/java/org/apache/fineract/cn/deposit/service/rest/CollectionsRestController.java @@ -24,8 +24,10 @@ import org.apache.fineract.cn.deposit.api.v1.PermittableGroupIds; import org.apache.fineract.cn.deposit.api.v1.collection.domain.data.CollectionsRequest; import org.apache.fineract.cn.deposit.api.v1.collection.domain.data.CollectionsResponse; +import org.apache.fineract.cn.deposit.api.v1.collection.domain.data.SettleCollectionsRequest; import org.apache.fineract.cn.deposit.service.ServiceConstants; import org.apache.fineract.cn.deposit.service.internal.command.CreateCollectionsCommand; +import org.apache.fineract.cn.deposit.service.internal.command.SettleCollectionsCommand; import org.apache.fineract.cn.deposit.service.internal.command.UpdateCollectionsCommand; import org.apache.fineract.cn.deposit.service.internal.service.CollectionsService; import org.slf4j.Logger; @@ -99,4 +101,20 @@ ResponseEntity getCollection(@PathVariable("collectionsRefe CollectionsResponse result = collectionsService.fetchCollection(collectionsReference); return ResponseEntity.ok(result); } + + @Permittable(value = AcceptedTokenType.TENANT, groupId = PermittableGroupIds.COLLECTION_MANAGEMENT) + @RequestMapping( + value = "/settlement", + method = RequestMethod.POST, + consumes = MediaType.APPLICATION_JSON_VALUE, + produces = MediaType.APPLICATION_JSON_VALUE + ) + public + @ResponseBody + ResponseEntity settleCollection( @RequestBody SettleCollectionsRequest settleCollectionsRequest) + throws Throwable { + CommandCallback result = commandGateway.process(new SettleCollectionsCommand(settleCollectionsRequest), + CollectionsResponse.class); + return ResponseEntity.ok(result.get()); + } }