feat: implement full current account transaction write service
- New CurrentAccountTransactionWritePlatformService interface with deposit, withdrawal, holdAmount, releaseAmount, undoTransaction, reverseTransaction, and adjustTransaction operations - New CurrentAccountTransactionWritePlatformServiceImpl using m_current_account tables directly (not m_savings_account), with GL journal entry posting - Add holdAmount, releaseAmount, reversal factory methods to CurrentAccountTransaction - Wire all 7 current account transaction command handlers to new write service - Fix CurrentAccountTransactionsApiResource template SQL column: currency_multiplesof - Fix account number search in SearchParameters Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
b25d5a30d2
commit
ce0fb18eeb
+193
-149
@@ -1,149 +1,193 @@
|
||||
/**
|
||||
* 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.portfolio.currentaccount.domain;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.organisation.office.domain.Office;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_current_account_transaction")
|
||||
@Getter
|
||||
@Setter
|
||||
public class CurrentAccountTransaction extends AbstractPersistableCustom<Long> {
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "current_account_id", nullable = false)
|
||||
private CurrentAccount currentAccount;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "office_id", nullable = false)
|
||||
private Office office;
|
||||
|
||||
// 1=Deposit, 2=Withdrawal, 3=InterestPosting, 4=Charge, 5=ChargeWaiver, 6=Transfer, 7=Reversal
|
||||
@Column(name = "transaction_type_enum", nullable = false)
|
||||
private Integer transactionTypeEnum;
|
||||
|
||||
@Column(name = "transaction_date", nullable = false)
|
||||
private LocalDate transactionDate;
|
||||
|
||||
@Column(name = "amount", nullable = false, precision = 19, scale = 6)
|
||||
private BigDecimal amount;
|
||||
|
||||
@Column(name = "ref_no", length = 100)
|
||||
private String refNo;
|
||||
|
||||
@Column(name = "remarks", length = 500)
|
||||
private String remarks;
|
||||
|
||||
@Column(name = "is_reversed", nullable = false)
|
||||
private boolean reversed = false;
|
||||
|
||||
@Column(name = "is_reversal", nullable = false)
|
||||
private boolean reversal = false;
|
||||
|
||||
@Column(name = "original_transaction_id")
|
||||
private Long originalTransactionId;
|
||||
|
||||
@Column(name = "is_manual", nullable = false)
|
||||
private boolean manual = false;
|
||||
|
||||
@Column(name = "running_balance_derived", precision = 19, scale = 6)
|
||||
private BigDecimal runningBalanceDerived;
|
||||
|
||||
@Column(name = "cumulative_balance_derived", precision = 19, scale = 6)
|
||||
private BigDecimal cumulativeBalanceDerived;
|
||||
|
||||
@Column(name = "balance_end_date_derived")
|
||||
private LocalDate balanceEndDateDerived;
|
||||
|
||||
@Column(name = "balance_number_of_days_derived")
|
||||
private Integer balanceNumberOfDaysDerived;
|
||||
|
||||
@Column(name = "overdraft_amount_derived", precision = 19, scale = 6)
|
||||
private BigDecimal overdraftAmountDerived;
|
||||
|
||||
@Column(name = "is_lien_transaction", nullable = false)
|
||||
private boolean lienTransaction = false;
|
||||
|
||||
@Column(name = "release_id_of_hold_amount_transaction")
|
||||
private Long releaseIdOfHoldAmountTransaction;
|
||||
|
||||
@Column(name = "reason_for_block", length = 200)
|
||||
private String reasonForBlock;
|
||||
|
||||
@Column(name = "submitted_on_date")
|
||||
private LocalDate submittedOnDate;
|
||||
|
||||
@Column(name = "created_date")
|
||||
private LocalDateTime createdDate;
|
||||
|
||||
@Column(name = "created_by")
|
||||
private Long createdBy;
|
||||
|
||||
protected CurrentAccountTransaction() {}
|
||||
|
||||
public static CurrentAccountTransaction deposit(CurrentAccount account, Office office,
|
||||
BigDecimal amount, LocalDate transactionDate, String refNo) {
|
||||
CurrentAccountTransaction txn = new CurrentAccountTransaction();
|
||||
txn.currentAccount = account;
|
||||
txn.office = office;
|
||||
txn.transactionTypeEnum = 1;
|
||||
txn.amount = amount;
|
||||
txn.transactionDate = transactionDate;
|
||||
txn.refNo = refNo;
|
||||
txn.submittedOnDate = transactionDate;
|
||||
return txn;
|
||||
}
|
||||
|
||||
public static CurrentAccountTransaction chargeDeduction(CurrentAccount account, Office office,
|
||||
BigDecimal amount, LocalDate transactionDate) {
|
||||
CurrentAccountTransaction txn = new CurrentAccountTransaction();
|
||||
txn.currentAccount = account;
|
||||
txn.office = office;
|
||||
txn.transactionTypeEnum = 7; // PAY_CHARGE
|
||||
txn.amount = amount;
|
||||
txn.transactionDate = transactionDate;
|
||||
txn.submittedOnDate = transactionDate;
|
||||
return txn;
|
||||
}
|
||||
|
||||
public static CurrentAccountTransaction withdrawal(CurrentAccount account, Office office,
|
||||
BigDecimal amount, LocalDate transactionDate, String refNo) {
|
||||
CurrentAccountTransaction txn = new CurrentAccountTransaction();
|
||||
txn.currentAccount = account;
|
||||
txn.office = office;
|
||||
txn.transactionTypeEnum = 2;
|
||||
txn.amount = amount;
|
||||
txn.transactionDate = transactionDate;
|
||||
txn.refNo = refNo;
|
||||
txn.submittedOnDate = transactionDate;
|
||||
return txn;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 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.portfolio.currentaccount.domain;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.organisation.office.domain.Office;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_current_account_transaction")
|
||||
@Getter
|
||||
@Setter
|
||||
public class CurrentAccountTransaction extends AbstractPersistableCustom<Long> {
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "current_account_id", nullable = false)
|
||||
private CurrentAccount currentAccount;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "office_id", nullable = false)
|
||||
private Office office;
|
||||
|
||||
// 1=Deposit, 2=Withdrawal, 3=InterestPosting, 4=Charge, 5=ChargeWaiver, 6=Transfer, 7=Reversal
|
||||
@Column(name = "transaction_type_enum", nullable = false)
|
||||
private Integer transactionTypeEnum;
|
||||
|
||||
@Column(name = "transaction_date", nullable = false)
|
||||
private LocalDate transactionDate;
|
||||
|
||||
@Column(name = "amount", nullable = false, precision = 19, scale = 6)
|
||||
private BigDecimal amount;
|
||||
|
||||
@Column(name = "ref_no", length = 100)
|
||||
private String refNo;
|
||||
|
||||
@Column(name = "remarks", length = 500)
|
||||
private String remarks;
|
||||
|
||||
@Column(name = "is_reversed", nullable = false)
|
||||
private boolean reversed = false;
|
||||
|
||||
@Column(name = "is_reversal", nullable = false)
|
||||
private boolean reversal = false;
|
||||
|
||||
@Column(name = "original_transaction_id")
|
||||
private Long originalTransactionId;
|
||||
|
||||
@Column(name = "is_manual", nullable = false)
|
||||
private boolean manual = false;
|
||||
|
||||
@Column(name = "running_balance_derived", precision = 19, scale = 6)
|
||||
private BigDecimal runningBalanceDerived;
|
||||
|
||||
@Column(name = "cumulative_balance_derived", precision = 19, scale = 6)
|
||||
private BigDecimal cumulativeBalanceDerived;
|
||||
|
||||
@Column(name = "balance_end_date_derived")
|
||||
private LocalDate balanceEndDateDerived;
|
||||
|
||||
@Column(name = "balance_number_of_days_derived")
|
||||
private Integer balanceNumberOfDaysDerived;
|
||||
|
||||
@Column(name = "overdraft_amount_derived", precision = 19, scale = 6)
|
||||
private BigDecimal overdraftAmountDerived;
|
||||
|
||||
@Column(name = "is_lien_transaction", nullable = false)
|
||||
private boolean lienTransaction = false;
|
||||
|
||||
@Column(name = "release_id_of_hold_amount_transaction")
|
||||
private Long releaseIdOfHoldAmountTransaction;
|
||||
|
||||
@Column(name = "reason_for_block", length = 200)
|
||||
private String reasonForBlock;
|
||||
|
||||
@Column(name = "submitted_on_date")
|
||||
private LocalDate submittedOnDate;
|
||||
|
||||
@Column(name = "created_date")
|
||||
private LocalDateTime createdDate;
|
||||
|
||||
@Column(name = "created_by")
|
||||
private Long createdBy;
|
||||
|
||||
protected CurrentAccountTransaction() {}
|
||||
|
||||
public static CurrentAccountTransaction deposit(CurrentAccount account, Office office,
|
||||
BigDecimal amount, LocalDate transactionDate, String refNo) {
|
||||
CurrentAccountTransaction txn = new CurrentAccountTransaction();
|
||||
txn.currentAccount = account;
|
||||
txn.office = office;
|
||||
txn.transactionTypeEnum = 1;
|
||||
txn.amount = amount;
|
||||
txn.transactionDate = transactionDate;
|
||||
txn.refNo = refNo;
|
||||
txn.submittedOnDate = transactionDate;
|
||||
return txn;
|
||||
}
|
||||
|
||||
public static CurrentAccountTransaction chargeDeduction(CurrentAccount account, Office office,
|
||||
BigDecimal amount, LocalDate transactionDate) {
|
||||
CurrentAccountTransaction txn = new CurrentAccountTransaction();
|
||||
txn.currentAccount = account;
|
||||
txn.office = office;
|
||||
txn.transactionTypeEnum = 7; // PAY_CHARGE
|
||||
txn.amount = amount;
|
||||
txn.transactionDate = transactionDate;
|
||||
txn.submittedOnDate = transactionDate;
|
||||
return txn;
|
||||
}
|
||||
|
||||
public static CurrentAccountTransaction withdrawal(CurrentAccount account, Office office,
|
||||
BigDecimal amount, LocalDate transactionDate, String refNo) {
|
||||
CurrentAccountTransaction txn = new CurrentAccountTransaction();
|
||||
txn.currentAccount = account;
|
||||
txn.office = office;
|
||||
txn.transactionTypeEnum = 2;
|
||||
txn.amount = amount;
|
||||
txn.transactionDate = transactionDate;
|
||||
txn.refNo = refNo;
|
||||
txn.submittedOnDate = transactionDate;
|
||||
return txn;
|
||||
}
|
||||
|
||||
// transactionTypeEnum = 8 (Hold Amount)
|
||||
public static CurrentAccountTransaction holdAmount(CurrentAccount account, Office office,
|
||||
BigDecimal amount, LocalDate transactionDate, String reasonForBlock) {
|
||||
CurrentAccountTransaction txn = new CurrentAccountTransaction();
|
||||
txn.currentAccount = account;
|
||||
txn.office = office;
|
||||
txn.transactionTypeEnum = 8;
|
||||
txn.amount = amount;
|
||||
txn.transactionDate = transactionDate;
|
||||
txn.lienTransaction = true;
|
||||
txn.reasonForBlock = reasonForBlock;
|
||||
txn.submittedOnDate = transactionDate;
|
||||
return txn;
|
||||
}
|
||||
|
||||
// transactionTypeEnum = 9 (Release Amount)
|
||||
public static CurrentAccountTransaction releaseAmount(CurrentAccount account, Office office,
|
||||
BigDecimal amount, LocalDate transactionDate, Long holdTransactionId) {
|
||||
CurrentAccountTransaction txn = new CurrentAccountTransaction();
|
||||
txn.currentAccount = account;
|
||||
txn.office = office;
|
||||
txn.transactionTypeEnum = 9;
|
||||
txn.amount = amount;
|
||||
txn.transactionDate = transactionDate;
|
||||
txn.releaseIdOfHoldAmountTransaction = holdTransactionId;
|
||||
txn.submittedOnDate = transactionDate;
|
||||
return txn;
|
||||
}
|
||||
|
||||
// transactionTypeEnum = 7 (Reversal / Undo)
|
||||
public static CurrentAccountTransaction reversal(CurrentAccount account, Office office,
|
||||
BigDecimal amount, LocalDate transactionDate, Long originalTransactionId) {
|
||||
CurrentAccountTransaction txn = new CurrentAccountTransaction();
|
||||
txn.currentAccount = account;
|
||||
txn.office = office;
|
||||
txn.transactionTypeEnum = 7;
|
||||
txn.amount = amount;
|
||||
txn.transactionDate = transactionDate;
|
||||
txn.reversal = true;
|
||||
txn.originalTransactionId = originalTransactionId;
|
||||
txn.submittedOnDate = transactionDate;
|
||||
return txn;
|
||||
}
|
||||
}
|
||||
|
||||
+31
-29
@@ -1,29 +1,31 @@
|
||||
/**
|
||||
* 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.portfolio.currentaccount.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface CurrentAccountReadPlatformService {
|
||||
|
||||
Map<String, Object> retrieveOne(Long accountId);
|
||||
|
||||
List<Map<String, Object>> retrieveAll();
|
||||
}
|
||||
/**
|
||||
* 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.portfolio.currentaccount.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface CurrentAccountReadPlatformService {
|
||||
|
||||
Map<String, Object> retrieveOne(Long accountId);
|
||||
|
||||
List<Map<String, Object>> retrieveAll();
|
||||
|
||||
List<Map<String, Object>> retrieveAll(Integer offset, Integer limit, String accountNo, String clientName);
|
||||
}
|
||||
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/**
|
||||
* 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.portfolio.currentaccount.service;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
|
||||
public interface CurrentAccountTransactionWritePlatformService {
|
||||
|
||||
CommandProcessingResult deposit(Long accountId, JsonCommand command);
|
||||
|
||||
CommandProcessingResult withdrawal(Long accountId, JsonCommand command);
|
||||
|
||||
CommandProcessingResult holdAmount(Long accountId, JsonCommand command);
|
||||
|
||||
CommandProcessingResult releaseAmount(Long accountId, Long transactionId);
|
||||
|
||||
CommandProcessingResult undoTransaction(Long accountId, Long transactionId, boolean isReversal);
|
||||
|
||||
CommandProcessingResult reverseTransaction(Long accountId, Long transactionId, boolean isReversal, JsonCommand command);
|
||||
|
||||
CommandProcessingResult adjustTransaction(Long accountId, Long transactionId, JsonCommand command);
|
||||
}
|
||||
Reference in New Issue
Block a user