feat: Denomination Master backend - master, audit, soft delete, txn breakdown
- m_denomination_master CRUD API with duplicate (denomination+kind) validation, soft delete + restore, and a full audit trail (m_denomination_master_audit logs CREATE/UPDATE/ACTIVATE/DEACTIVATE/ DELETE/RESTORE with snapshot, changes, user and timestamp) - m_savings_txn_denomination: persist per-transaction cash denomination breakdown on savings deposit; allow denominationBreakdown request param - Liquibase 0012_denomination_master registered in tenant changelog Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
7d4f409202
commit
ee915e395a
+232
@@ -0,0 +1,232 @@
|
||||
package org.apache.fineract.portfolio.denominationmaster.api;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.time.LocalDate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.denominationmaster.domain.DenominationMaster;
|
||||
import org.apache.fineract.portfolio.denominationmaster.domain.DenominationMasterAudit;
|
||||
import org.apache.fineract.portfolio.denominationmaster.domain.DenominationMasterAuditRepository;
|
||||
import org.apache.fineract.portfolio.denominationmaster.domain.DenominationMasterRepository;
|
||||
import org.apache.fineract.useradministration.domain.AppUser;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Path("/v1/denominationmaster")
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public class DenominationMasterApiResource {
|
||||
|
||||
private final DenominationMasterRepository repository;
|
||||
private final DenominationMasterAuditRepository auditRepository;
|
||||
private final PlatformSecurityContext context;
|
||||
private final Gson gson = new Gson();
|
||||
|
||||
@GET
|
||||
public String getAll() {
|
||||
List<DenominationMaster> list = repository.findByDeletedFalseOrderByKindDescDenominationDesc();
|
||||
return gson.toJson(list.stream().map(this::toMap).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("active")
|
||||
public String getActive() {
|
||||
List<DenominationMaster> list = repository.findByIsActiveTrueAndDeletedFalseOrderByKindDescDenominationDesc();
|
||||
return gson.toJson(list.stream().map(this::toMap).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("deleted")
|
||||
public String getDeleted() {
|
||||
List<DenominationMaster> list = repository.findByDeletedTrueOrderByKindDescDenominationDesc();
|
||||
return gson.toJson(list.stream().map(this::toMap).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("audit")
|
||||
public String getAllAudit() {
|
||||
List<DenominationMasterAudit> list = auditRepository.findAllByOrderByPerformedOnDesc();
|
||||
return gson.toJson(list.stream().map(this::auditToMap).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{id}/audit")
|
||||
public String getAuditForDenomination(@PathParam("id") Long id) {
|
||||
List<DenominationMasterAudit> list = auditRepository.findByDenominationIdOrderByPerformedOnDesc(id);
|
||||
return gson.toJson(list.stream().map(this::auditToMap).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
@POST
|
||||
public String create(String body) {
|
||||
JsonObject json = JsonParser.parseString(body).getAsJsonObject();
|
||||
final int denomination = json.get("denomination").getAsInt();
|
||||
final String kind = json.get("kind").getAsString();
|
||||
if (repository.existsByDenominationAndKindAndDeletedFalse(denomination, kind)) {
|
||||
throw new PlatformDataIntegrityException("error.msg.denomination.duplicate",
|
||||
"A " + kind + " of denomination " + denomination + " already exists.", "denomination", denomination);
|
||||
}
|
||||
DenominationMaster dm = DenominationMaster.create(denomination, kind,
|
||||
json.has("description") ? json.get("description").getAsString() : null,
|
||||
json.has("isActive") ? json.get("isActive").getAsBoolean() : true,
|
||||
json.has("introducedOn") ? LocalDate.parse(json.get("introducedOn").getAsString()) : null, null);
|
||||
DenominationMaster saved = repository.save(dm);
|
||||
writeAudit("CREATE", saved, null);
|
||||
JsonObject result = new JsonObject();
|
||||
result.addProperty("resourceId", saved.getId());
|
||||
return gson.toJson(result);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("{id}")
|
||||
public String update(@PathParam("id") Long id, @QueryParam("command") String command, String body) {
|
||||
DenominationMaster dm = repository.findById(id).orElseThrow(() -> new RuntimeException("Denomination not found: " + id));
|
||||
|
||||
if ("activate".equals(command)) {
|
||||
dm.setIsActive(true);
|
||||
dm.setDiscontinuedOn(null);
|
||||
repository.save(dm);
|
||||
writeAudit("ACTIVATE", dm, null);
|
||||
} else if ("deactivate".equals(command)) {
|
||||
dm.setIsActive(false);
|
||||
dm.setDiscontinuedOn(LocalDate.now());
|
||||
repository.save(dm);
|
||||
writeAudit("DEACTIVATE", dm, null);
|
||||
} else if ("restore".equals(command)) {
|
||||
if (repository.existsByDenominationAndKindAndDeletedFalseAndIdNot(dm.getDenomination(), dm.getKind(), id)) {
|
||||
throw new PlatformDataIntegrityException("error.msg.denomination.duplicate.restore",
|
||||
"Cannot restore: a " + dm.getKind() + " of denomination " + dm.getDenomination() + " already exists.",
|
||||
"denomination", dm.getDenomination());
|
||||
}
|
||||
dm.setDeleted(false);
|
||||
repository.save(dm);
|
||||
writeAudit("RESTORE", dm, null);
|
||||
} else {
|
||||
JsonObject json = JsonParser.parseString(body).getAsJsonObject();
|
||||
final int effectiveDenomination = json.has("denomination") ? json.get("denomination").getAsInt() : dm.getDenomination();
|
||||
final String effectiveKind = json.has("kind") ? json.get("kind").getAsString() : dm.getKind();
|
||||
if (repository.existsByDenominationAndKindAndDeletedFalseAndIdNot(effectiveDenomination, effectiveKind, id)) {
|
||||
throw new PlatformDataIntegrityException("error.msg.denomination.duplicate",
|
||||
"A " + effectiveKind + " of denomination " + effectiveDenomination + " already exists.", "denomination",
|
||||
effectiveDenomination);
|
||||
}
|
||||
List<String> changes = new ArrayList<>();
|
||||
if (json.has("denomination")) {
|
||||
int newVal = json.get("denomination").getAsInt();
|
||||
if (!java.util.Objects.equals(dm.getDenomination(), newVal)) {
|
||||
changes.add("denomination: " + dm.getDenomination() + " -> " + newVal);
|
||||
}
|
||||
dm.setDenomination(newVal);
|
||||
}
|
||||
if (json.has("kind")) {
|
||||
String newVal = json.get("kind").getAsString();
|
||||
if (!java.util.Objects.equals(dm.getKind(), newVal)) {
|
||||
changes.add("kind: " + dm.getKind() + " -> " + newVal);
|
||||
}
|
||||
dm.setKind(newVal);
|
||||
}
|
||||
if (json.has("description")) {
|
||||
String newVal = json.get("description").getAsString();
|
||||
if (!java.util.Objects.equals(dm.getDescription(), newVal)) {
|
||||
changes.add("description: " + dm.getDescription() + " -> " + newVal);
|
||||
}
|
||||
dm.setDescription(newVal);
|
||||
}
|
||||
if (json.has("isActive")) {
|
||||
boolean newVal = json.get("isActive").getAsBoolean();
|
||||
if (!java.util.Objects.equals(dm.getIsActive(), newVal)) {
|
||||
changes.add("isActive: " + dm.getIsActive() + " -> " + newVal);
|
||||
}
|
||||
dm.setIsActive(newVal);
|
||||
}
|
||||
if (json.has("introducedOn")) {
|
||||
LocalDate newVal = LocalDate.parse(json.get("introducedOn").getAsString());
|
||||
if (!java.util.Objects.equals(dm.getIntroducedOn(), newVal)) {
|
||||
changes.add("introducedOn: " + dm.getIntroducedOn() + " -> " + newVal);
|
||||
}
|
||||
dm.setIntroducedOn(newVal);
|
||||
}
|
||||
repository.save(dm);
|
||||
writeAudit("UPDATE", dm, changes.isEmpty() ? null : String.join("; ", changes));
|
||||
}
|
||||
JsonObject result = new JsonObject();
|
||||
result.addProperty("resourceId", id);
|
||||
return gson.toJson(result);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("{id}")
|
||||
public String delete(@PathParam("id") Long id) {
|
||||
DenominationMaster dm = repository.findById(id).orElseThrow(() -> new RuntimeException("Denomination not found: " + id));
|
||||
// soft delete: flag the row instead of removing it, so it can be restored and history is preserved
|
||||
dm.setDeleted(true);
|
||||
dm.setIsActive(false);
|
||||
repository.save(dm);
|
||||
writeAudit("DELETE", dm, null);
|
||||
JsonObject result = new JsonObject();
|
||||
result.addProperty("resourceId", id);
|
||||
return gson.toJson(result);
|
||||
}
|
||||
|
||||
private void writeAudit(final String action, final DenominationMaster dm, final String changes) {
|
||||
Long userId = null;
|
||||
String username = null;
|
||||
try {
|
||||
AppUser user = this.context.authenticatedUser();
|
||||
if (user != null) {
|
||||
userId = user.getId();
|
||||
username = user.getUsername();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// audit should never block the main operation if the user cannot be resolved
|
||||
}
|
||||
auditRepository.save(DenominationMasterAudit.of(action, dm, changes, userId, username));
|
||||
}
|
||||
|
||||
private java.util.Map<String, Object> toMap(DenominationMaster dm) {
|
||||
java.util.Map<String, Object> map = new java.util.LinkedHashMap<>();
|
||||
map.put("id", dm.getId());
|
||||
map.put("denomination", dm.getDenomination());
|
||||
map.put("kind", dm.getKind());
|
||||
map.put("description", dm.getDescription());
|
||||
map.put("isActive", dm.getIsActive());
|
||||
map.put("introducedOn", dm.getIntroducedOn() != null ? dm.getIntroducedOn().toString() : null);
|
||||
map.put("discontinuedOn", dm.getDiscontinuedOn() != null ? dm.getDiscontinuedOn().toString() : null);
|
||||
map.put("deleted", dm.getDeleted());
|
||||
return map;
|
||||
}
|
||||
|
||||
private java.util.Map<String, Object> auditToMap(DenominationMasterAudit a) {
|
||||
java.util.Map<String, Object> map = new java.util.LinkedHashMap<>();
|
||||
map.put("id", a.getId());
|
||||
map.put("denominationId", a.getDenominationId());
|
||||
map.put("action", a.getAction());
|
||||
map.put("denomination", a.getDenomination());
|
||||
map.put("kind", a.getKind());
|
||||
map.put("description", a.getDescription());
|
||||
map.put("isActive", a.getIsActive());
|
||||
map.put("introducedOn", a.getIntroducedOn() != null ? a.getIntroducedOn().toString() : null);
|
||||
map.put("discontinuedOn", a.getDiscontinuedOn() != null ? a.getDiscontinuedOn().toString() : null);
|
||||
map.put("changes", a.getChanges());
|
||||
map.put("performedBy", a.getPerformedBy());
|
||||
map.put("performedByUsername", a.getPerformedByUsername());
|
||||
map.put("performedOn", a.getPerformedOn() != null ? a.getPerformedOn().toString() : null);
|
||||
return map;
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.denominationmaster.domain;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import java.time.LocalDate;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_denomination_master")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class DenominationMaster {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "denomination", nullable = false)
|
||||
private Integer denomination;
|
||||
|
||||
@Column(name = "kind", nullable = false, length = 10)
|
||||
private String kind;
|
||||
|
||||
@Column(name = "description", length = 100)
|
||||
private String description;
|
||||
|
||||
@Column(name = "is_active", nullable = false)
|
||||
private Boolean isActive = true;
|
||||
|
||||
@Column(name = "introduced_on")
|
||||
private LocalDate introducedOn;
|
||||
|
||||
@Column(name = "discontinued_on")
|
||||
private LocalDate discontinuedOn;
|
||||
|
||||
@Column(name = "deleted", nullable = false)
|
||||
private Boolean deleted = false;
|
||||
|
||||
public static DenominationMaster create(Integer denomination, String kind, String description,
|
||||
Boolean isActive, LocalDate introducedOn, LocalDate discontinuedOn) {
|
||||
DenominationMaster dm = new DenominationMaster();
|
||||
dm.denomination = denomination;
|
||||
dm.kind = kind;
|
||||
dm.description = description;
|
||||
dm.isActive = isActive != null ? isActive : true;
|
||||
dm.introducedOn = introducedOn;
|
||||
dm.discontinuedOn = discontinuedOn;
|
||||
dm.deleted = false;
|
||||
return dm;
|
||||
}
|
||||
}
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.denominationmaster.domain;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_denomination_master_audit")
|
||||
@Getter
|
||||
@Setter
|
||||
@NoArgsConstructor
|
||||
public class DenominationMasterAudit {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "denomination_id")
|
||||
private Long denominationId;
|
||||
|
||||
@Column(name = "action", nullable = false, length = 20)
|
||||
private String action;
|
||||
|
||||
@Column(name = "denomination")
|
||||
private Integer denomination;
|
||||
|
||||
@Column(name = "kind", length = 10)
|
||||
private String kind;
|
||||
|
||||
@Column(name = "description", length = 100)
|
||||
private String description;
|
||||
|
||||
@Column(name = "is_active")
|
||||
private Boolean isActive;
|
||||
|
||||
@Column(name = "introduced_on")
|
||||
private LocalDate introducedOn;
|
||||
|
||||
@Column(name = "discontinued_on")
|
||||
private LocalDate discontinuedOn;
|
||||
|
||||
@Column(name = "changes", length = 1000)
|
||||
private String changes;
|
||||
|
||||
@Column(name = "performed_by")
|
||||
private Long performedBy;
|
||||
|
||||
@Column(name = "performed_by_username", length = 100)
|
||||
private String performedByUsername;
|
||||
|
||||
@Column(name = "performed_on", nullable = false)
|
||||
private LocalDateTime performedOn;
|
||||
|
||||
public static DenominationMasterAudit of(final String action, final DenominationMaster dm, final String changes,
|
||||
final Long performedBy, final String performedByUsername) {
|
||||
final DenominationMasterAudit a = new DenominationMasterAudit();
|
||||
a.action = action;
|
||||
a.denominationId = dm.getId();
|
||||
a.denomination = dm.getDenomination();
|
||||
a.kind = dm.getKind();
|
||||
a.description = dm.getDescription();
|
||||
a.isActive = dm.getIsActive();
|
||||
a.introducedOn = dm.getIntroducedOn();
|
||||
a.discontinuedOn = dm.getDiscontinuedOn();
|
||||
a.changes = changes;
|
||||
a.performedBy = performedBy;
|
||||
a.performedByUsername = performedByUsername;
|
||||
a.performedOn = LocalDateTime.now();
|
||||
return a;
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.denominationmaster.domain;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface DenominationMasterAuditRepository extends JpaRepository<DenominationMasterAudit, Long> {
|
||||
|
||||
List<DenominationMasterAudit> findByDenominationIdOrderByPerformedOnDesc(Long denominationId);
|
||||
|
||||
List<DenominationMasterAudit> findAllByOrderByPerformedOnDesc();
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package org.apache.fineract.portfolio.denominationmaster.domain;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface DenominationMasterRepository extends JpaRepository<DenominationMaster, Long> {
|
||||
List<DenominationMaster> findByDeletedFalseOrderByKindDescDenominationDesc();
|
||||
List<DenominationMaster> findByIsActiveTrueAndDeletedFalseOrderByKindDescDenominationDesc();
|
||||
List<DenominationMaster> findByDeletedTrueOrderByKindDescDenominationDesc();
|
||||
|
||||
boolean existsByDenominationAndKindAndDeletedFalse(Integer denomination, String kind);
|
||||
boolean existsByDenominationAndKindAndDeletedFalseAndIdNot(Integer denomination, String kind, Long id);
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* 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.denominationmaster.domain;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.GeneratedValue;
|
||||
import jakarta.persistence.GenerationType;
|
||||
import jakarta.persistence.Id;
|
||||
import jakarta.persistence.Table;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_savings_txn_denomination")
|
||||
@Getter
|
||||
@Setter
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SavingsTxnDenomination {
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.IDENTITY)
|
||||
private Long id;
|
||||
|
||||
@Column(name = "txn_id", nullable = false)
|
||||
private Long txnId;
|
||||
|
||||
@Column(name = "savings_account_id", nullable = false)
|
||||
private Long savingsAccountId;
|
||||
|
||||
@Column(name = "account_no", length = 50)
|
||||
private String accountNo;
|
||||
|
||||
@Column(name = "client_id")
|
||||
private Long clientId;
|
||||
|
||||
@Column(name = "cif_no", length = 50)
|
||||
private String cifNo;
|
||||
|
||||
@Column(name = "denomination_id", nullable = false)
|
||||
private Long denominationId;
|
||||
|
||||
@Column(name = "denomination_value", nullable = false)
|
||||
private Integer denominationValue;
|
||||
|
||||
@Column(name = "count", nullable = false)
|
||||
private Integer count;
|
||||
|
||||
@Column(name = "total_amount", nullable = false, precision = 19, scale = 6)
|
||||
private BigDecimal totalAmount;
|
||||
|
||||
@Column(name = "txn_date")
|
||||
private LocalDate txnDate;
|
||||
|
||||
@Column(name = "created_at")
|
||||
private LocalDateTime createdAt;
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.denominationmaster.domain;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
@Repository
|
||||
public interface SavingsTxnDenominationRepository extends JpaRepository<SavingsTxnDenomination, Long> {
|
||||
List<SavingsTxnDenomination> findByTxnId(Long txnId);
|
||||
List<SavingsTxnDenomination> findBySavingsAccountId(Long savingsAccountId);
|
||||
}
|
||||
+1992
-1955
File diff suppressed because it is too large
Load Diff
+4
-2
@@ -98,6 +98,7 @@ import org.apache.fineract.portfolio.savings.domain.SavingsProductFacilityConfig
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsProductFacilityLimit;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsProductFacilityLimitRepository;
|
||||
import org.apache.fineract.portfolio.savings.domain.SavingsProductRepository;
|
||||
import org.apache.fineract.portfolio.denominationmaster.domain.SavingsTxnDenominationRepository;
|
||||
import org.apache.fineract.portfolio.savings.service.FacilityChargeAutoApplyService;
|
||||
import org.apache.fineract.portfolio.savings.service.DepositAccountInterestRateChartReadPlatformService;
|
||||
import org.apache.fineract.portfolio.savings.service.DepositAccountInterestRateChartReadPlatformServiceImpl;
|
||||
@@ -424,7 +425,8 @@ public class SavingsConfiguration {
|
||||
EntityDatatableChecksWritePlatformService entityDatatableChecksWritePlatformService, AppUserRepositoryWrapper appuserRepository,
|
||||
StandingInstructionRepository standingInstructionRepository, BusinessEventNotifierService businessEventNotifierService,
|
||||
GSIMRepositoy gsimRepository, SavingsAccountInterestPostingService savingsAccountInterestPostingService,
|
||||
ErrorHandler errorHandler, FacilityChargeAutoApplyService facilityChargeAutoApplyService) {
|
||||
ErrorHandler errorHandler, FacilityChargeAutoApplyService facilityChargeAutoApplyService,
|
||||
SavingsTxnDenominationRepository savingsTxnDenominationRepository) {
|
||||
return new SavingsAccountWritePlatformServiceJpaRepositoryImpl(context, fromApiJsonDeserializer, savingAccountRepositoryWrapper,
|
||||
staffRepository, savingsAccountTransactionRepository, savingAccountAssembler, savingsAccountTransactionDataValidator,
|
||||
savingsAccountChargeDataValidator, paymentDetailWritePlatformService, journalEntryWritePlatformService,
|
||||
@@ -432,7 +434,7 @@ public class SavingsConfiguration {
|
||||
chargeRepository, savingsAccountChargeRepository, holidayRepository, workingDaysRepository, configurationDomainService,
|
||||
depositAccountOnHoldTransactionRepository, entityDatatableChecksWritePlatformService, appuserRepository,
|
||||
standingInstructionRepository, businessEventNotifierService, gsimRepository, savingsAccountInterestPostingService,
|
||||
errorHandler, facilityChargeAutoApplyService);
|
||||
errorHandler, facilityChargeAutoApplyService, savingsTxnDenominationRepository);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
@@ -318,4 +318,5 @@
|
||||
<include file="parts/0299_seed_indian_states.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0300_rename_fd_base_interest_rate_tables_to_cbs.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0301_add_current_account_to_transfer_details.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0012_denomination_master.xml" relativeToChangelogFile="true"/>
|
||||
</databaseChangeLog>
|
||||
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
|
||||
<changeSet id="denomination_master_table_001" author="CBS">
|
||||
<createTable tableName="m_denomination_master">
|
||||
<column name="id" type="BIGINT" autoIncrement="true">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="denomination" type="INT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="kind" type="VARCHAR(10)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="description" type="VARCHAR(100)"/>
|
||||
<column name="is_active" type="BOOLEAN" defaultValueBoolean="true">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="introduced_on" type="DATE"/>
|
||||
<column name="discontinued_on" type="DATE"/>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="denomination_master_initial_data_001" author="CBS">
|
||||
<insert tableName="m_denomination_master">
|
||||
<column name="denomination" value="2000"/>
|
||||
<column name="kind" value="note"/>
|
||||
<column name="description" value="2000 Rupee Note"/>
|
||||
<column name="is_active" valueBoolean="false"/>
|
||||
<column name="introduced_on" value="2016-11-08"/>
|
||||
<column name="discontinued_on" value="2023-09-30"/>
|
||||
</insert>
|
||||
<insert tableName="m_denomination_master">
|
||||
<column name="denomination" value="500"/>
|
||||
<column name="kind" value="note"/>
|
||||
<column name="description" value="500 Rupee Note"/>
|
||||
<column name="is_active" valueBoolean="true"/>
|
||||
<column name="introduced_on" value="2016-11-08"/>
|
||||
</insert>
|
||||
<insert tableName="m_denomination_master">
|
||||
<column name="denomination" value="200"/>
|
||||
<column name="kind" value="note"/>
|
||||
<column name="description" value="200 Rupee Note"/>
|
||||
<column name="is_active" valueBoolean="true"/>
|
||||
<column name="introduced_on" value="2017-08-25"/>
|
||||
</insert>
|
||||
<insert tableName="m_denomination_master">
|
||||
<column name="denomination" value="100"/>
|
||||
<column name="kind" value="note"/>
|
||||
<column name="description" value="100 Rupee Note"/>
|
||||
<column name="is_active" valueBoolean="true"/>
|
||||
<column name="introduced_on" value="2018-07-19"/>
|
||||
</insert>
|
||||
<insert tableName="m_denomination_master">
|
||||
<column name="denomination" value="50"/>
|
||||
<column name="kind" value="note"/>
|
||||
<column name="description" value="50 Rupee Note"/>
|
||||
<column name="is_active" valueBoolean="true"/>
|
||||
<column name="introduced_on" value="2017-08-25"/>
|
||||
</insert>
|
||||
<insert tableName="m_denomination_master">
|
||||
<column name="denomination" value="20"/>
|
||||
<column name="kind" value="note"/>
|
||||
<column name="description" value="20 Rupee Note"/>
|
||||
<column name="is_active" valueBoolean="true"/>
|
||||
<column name="introduced_on" value="2019-08-26"/>
|
||||
</insert>
|
||||
<insert tableName="m_denomination_master">
|
||||
<column name="denomination" value="10"/>
|
||||
<column name="kind" value="note"/>
|
||||
<column name="description" value="10 Rupee Note"/>
|
||||
<column name="is_active" valueBoolean="true"/>
|
||||
<column name="introduced_on" value="2018-01-01"/>
|
||||
</insert>
|
||||
<insert tableName="m_denomination_master">
|
||||
<column name="denomination" value="20"/>
|
||||
<column name="kind" value="coin"/>
|
||||
<column name="description" value="20 Rupee Coin"/>
|
||||
<column name="is_active" valueBoolean="true"/>
|
||||
<column name="introduced_on" value="2019-01-01"/>
|
||||
</insert>
|
||||
<insert tableName="m_denomination_master">
|
||||
<column name="denomination" value="10"/>
|
||||
<column name="kind" value="coin"/>
|
||||
<column name="description" value="10 Rupee Coin"/>
|
||||
<column name="is_active" valueBoolean="true"/>
|
||||
<column name="introduced_on" value="2009-01-01"/>
|
||||
</insert>
|
||||
<insert tableName="m_denomination_master">
|
||||
<column name="denomination" value="5"/>
|
||||
<column name="kind" value="coin"/>
|
||||
<column name="description" value="5 Rupee Coin"/>
|
||||
<column name="is_active" valueBoolean="true"/>
|
||||
<column name="introduced_on" value="2009-01-01"/>
|
||||
</insert>
|
||||
<insert tableName="m_denomination_master">
|
||||
<column name="denomination" value="2"/>
|
||||
<column name="kind" value="coin"/>
|
||||
<column name="description" value="2 Rupee Coin"/>
|
||||
<column name="is_active" valueBoolean="true"/>
|
||||
<column name="introduced_on" value="2009-01-01"/>
|
||||
</insert>
|
||||
<insert tableName="m_denomination_master">
|
||||
<column name="denomination" value="1"/>
|
||||
<column name="kind" value="coin"/>
|
||||
<column name="description" value="1 Rupee Coin"/>
|
||||
<column name="is_active" valueBoolean="true"/>
|
||||
<column name="introduced_on" value="2009-01-01"/>
|
||||
</insert>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="savings_txn_denomination_table_001" author="CBS">
|
||||
<createTable tableName="m_savings_txn_denomination">
|
||||
<column name="id" type="BIGINT" autoIncrement="true">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="txn_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="savings_account_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="account_no" type="VARCHAR(50)"/>
|
||||
<column name="client_id" type="BIGINT"/>
|
||||
<column name="cif_no" type="VARCHAR(50)"/>
|
||||
<column name="denomination_id" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="denomination_value" type="INT">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="count" type="INT" defaultValueNumeric="0">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="total_amount" type="DECIMAL(19,6)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="txn_date" type="DATE"/>
|
||||
<column name="created_at" type="TIMESTAMP" defaultValueComputed="CURRENT_TIMESTAMP"/>
|
||||
</createTable>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="denomination_master_audit_table_001" author="CBS">
|
||||
<createTable tableName="m_denomination_master_audit">
|
||||
<column name="id" type="BIGINT" autoIncrement="true">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="denomination_id" type="BIGINT"/>
|
||||
<column name="action" type="VARCHAR(20)">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="denomination" type="INT"/>
|
||||
<column name="kind" type="VARCHAR(10)"/>
|
||||
<column name="description" type="VARCHAR(100)"/>
|
||||
<column name="is_active" type="BOOLEAN"/>
|
||||
<column name="introduced_on" type="DATE"/>
|
||||
<column name="discontinued_on" type="DATE"/>
|
||||
<column name="changes" type="VARCHAR(1000)"/>
|
||||
<column name="performed_by" type="BIGINT"/>
|
||||
<column name="performed_by_username" type="VARCHAR(100)"/>
|
||||
<column name="performed_on" type="TIMESTAMP" defaultValueComputed="CURRENT_TIMESTAMP">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</createTable>
|
||||
<createIndex tableName="m_denomination_master_audit" indexName="idx_denom_audit_denom_id">
|
||||
<column name="denomination_id"/>
|
||||
</createIndex>
|
||||
</changeSet>
|
||||
|
||||
<changeSet id="denomination_master_soft_delete_001" author="CBS">
|
||||
<addColumn tableName="m_denomination_master">
|
||||
<column name="deleted" type="BOOLEAN" defaultValueBoolean="false">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
</addColumn>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+83
-82
@@ -1,82 +1,83 @@
|
||||
/**
|
||||
* 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.savings.data;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.apache.fineract.portfolio.savings.SavingsApiConstants;
|
||||
|
||||
public class SavingsAccountConstant extends SavingsApiConstants {
|
||||
|
||||
/**
|
||||
* These parameters will match the class level parameters of {@link SavingsProductData}. Where possible, we try to
|
||||
* get response parameters to match those of request parameters.
|
||||
*/
|
||||
protected static final Set<String> SAVINGS_ACCOUNT_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName,
|
||||
dateFormatParamName, monthDayFormatParamName, staffIdParamName, isGSIM, isParentAccount, accountNoParamName,
|
||||
externalIdParamName, clientIdParamName, groupIdParamName, productIdParamName, fieldOfficerIdParamName, submittedOnDateParamName,
|
||||
nominalAnnualInterestRateParamName, interestCompoundingPeriodTypeParamName, interestPostingPeriodTypeParamName,
|
||||
interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName,
|
||||
lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName,
|
||||
// withdrawalFeeAmountParamName, withdrawalFeeTypeParamName,
|
||||
withdrawalFeeForTransfersParamName, feeAmountParamName, feeOnMonthDayParamName, chargesParamName, allowOverdraftParamName,
|
||||
overdraftLimitParamName, minRequiredBalanceParamName, enforceMinRequiredBalanceParamName, lienAllowedParamName,
|
||||
maxAllowedLienLimitParamName, nominalAnnualInterestRateOverdraftParamName, minOverdraftForInterestCalculationParamName,
|
||||
withHoldTaxParamName, datatables, gsimApplicationId, gsimLastApplication,
|
||||
// CBS Account fields
|
||||
"accountType", "customerSegment", accountStatusParamName, modeOfOperationParamName,
|
||||
specialCategoryParamName, weakerSectionParamName,
|
||||
guardianNameParamName, guardianCifNumberParamName, guardianRelationshipParamName,
|
||||
guardianClientIdParamName, minorDateOfBirthParamName,
|
||||
introducerIdParamName, introducerNameParamName, introducerCifNumberParamName,
|
||||
nomineeParamName, "nominees", linkedAccountIdParamName, linkedAccountTypeParamName, linkedAccountNoParamName,
|
||||
accountFacilityConfigParamName, jointHoldersParamName,
|
||||
balanceSwapOptionParamName, msmeParamName, autoDebitFacilityParamName));
|
||||
|
||||
/**
|
||||
* These parameters will match the class level parameters of {@link SavingsAccountData}. Where possible, we try to
|
||||
* get response parameters to match those of request parameters.
|
||||
*/
|
||||
|
||||
protected static final Set<String> SAVINGS_ACCOUNT_TRANSACTION_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName,
|
||||
dateFormatParamName, transactionDateParamName, transactionAmountParamName, paymentTypeIdParamName,
|
||||
transactionAccountNumberParamName, checkNumberParamName, routingCodeParamName, receiptNumberParamName, bankNumberParamName,
|
||||
retailEntriesParamName, childAccountIdParamName, noteParamName, amountParamName, dateParamName, isManualTransaction,
|
||||
lienTransaction, chargesPaidByData, submittedOnDateParamName, accountIdParamName, accountNoParamName));
|
||||
|
||||
protected static final Set<String> SAVINGS_ACCOUNT_TRANSACTION_RESPONSE_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList(idParamName, accountNoParamName));
|
||||
|
||||
protected static final Set<String> SAVINGS_ACCOUNT_ACTIVATION_REQUEST_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList(localeParamName, dateFormatParamName, activatedOnDateParamName, "openingBalance"));
|
||||
|
||||
protected static final Set<String> SAVINGS_ACCOUNT_CLOSE_REQUEST_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList(localeParamName, dateFormatParamName, closedOnDateParamName, noteParamName, paymentTypeIdParamName,
|
||||
withdrawBalanceParamName, transactionAccountNumberParamName, checkNumberParamName, routingCodeParamName,
|
||||
receiptNumberParamName, bankNumberParamName, postInterestValidationOnClosure));
|
||||
|
||||
protected static final Set<String> SAVINGS_ACCOUNT_CHARGES_ADD_REQUEST_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList(chargeIdParamName, amountParamName, dueAsOfDateParamName, dateFormatParamName, localeParamName,
|
||||
feeOnMonthDayParamName, monthDayFormatParamName, feeIntervalParamName));
|
||||
|
||||
protected static final Set<String> SAVINGS_ACCOUNT_CHARGES_PAY_CHARGE_REQUEST_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList(amountParamName, dueAsOfDateParamName, dateFormatParamName, localeParamName, noteParamName));
|
||||
|
||||
}
|
||||
/**
|
||||
* 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.savings.data;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import org.apache.fineract.portfolio.savings.SavingsApiConstants;
|
||||
|
||||
public class SavingsAccountConstant extends SavingsApiConstants {
|
||||
|
||||
/**
|
||||
* These parameters will match the class level parameters of {@link SavingsProductData}. Where possible, we try to
|
||||
* get response parameters to match those of request parameters.
|
||||
*/
|
||||
protected static final Set<String> SAVINGS_ACCOUNT_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName,
|
||||
dateFormatParamName, monthDayFormatParamName, staffIdParamName, isGSIM, isParentAccount, accountNoParamName,
|
||||
externalIdParamName, clientIdParamName, groupIdParamName, productIdParamName, fieldOfficerIdParamName, submittedOnDateParamName,
|
||||
nominalAnnualInterestRateParamName, interestCompoundingPeriodTypeParamName, interestPostingPeriodTypeParamName,
|
||||
interestCalculationTypeParamName, interestCalculationDaysInYearTypeParamName, minRequiredOpeningBalanceParamName,
|
||||
lockinPeriodFrequencyParamName, lockinPeriodFrequencyTypeParamName,
|
||||
// withdrawalFeeAmountParamName, withdrawalFeeTypeParamName,
|
||||
withdrawalFeeForTransfersParamName, feeAmountParamName, feeOnMonthDayParamName, chargesParamName, allowOverdraftParamName,
|
||||
overdraftLimitParamName, minRequiredBalanceParamName, enforceMinRequiredBalanceParamName, lienAllowedParamName,
|
||||
maxAllowedLienLimitParamName, nominalAnnualInterestRateOverdraftParamName, minOverdraftForInterestCalculationParamName,
|
||||
withHoldTaxParamName, datatables, gsimApplicationId, gsimLastApplication,
|
||||
// CBS Account fields
|
||||
"accountType", "customerSegment", accountStatusParamName, modeOfOperationParamName,
|
||||
specialCategoryParamName, weakerSectionParamName,
|
||||
guardianNameParamName, guardianCifNumberParamName, guardianRelationshipParamName,
|
||||
guardianClientIdParamName, minorDateOfBirthParamName,
|
||||
introducerIdParamName, introducerNameParamName, introducerCifNumberParamName,
|
||||
nomineeParamName, "nominees", linkedAccountIdParamName, linkedAccountTypeParamName, linkedAccountNoParamName,
|
||||
accountFacilityConfigParamName, jointHoldersParamName,
|
||||
balanceSwapOptionParamName, msmeParamName, autoDebitFacilityParamName));
|
||||
|
||||
/**
|
||||
* These parameters will match the class level parameters of {@link SavingsAccountData}. Where possible, we try to
|
||||
* get response parameters to match those of request parameters.
|
||||
*/
|
||||
|
||||
protected static final Set<String> SAVINGS_ACCOUNT_TRANSACTION_REQUEST_DATA_PARAMETERS = new HashSet<>(Arrays.asList(localeParamName,
|
||||
dateFormatParamName, transactionDateParamName, transactionAmountParamName, paymentTypeIdParamName,
|
||||
transactionAccountNumberParamName, checkNumberParamName, routingCodeParamName, receiptNumberParamName, bankNumberParamName,
|
||||
retailEntriesParamName, childAccountIdParamName, noteParamName, amountParamName, dateParamName, isManualTransaction,
|
||||
lienTransaction, chargesPaidByData, submittedOnDateParamName, accountIdParamName, accountNoParamName,
|
||||
"denominationBreakdown"));
|
||||
|
||||
protected static final Set<String> SAVINGS_ACCOUNT_TRANSACTION_RESPONSE_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList(idParamName, accountNoParamName));
|
||||
|
||||
protected static final Set<String> SAVINGS_ACCOUNT_ACTIVATION_REQUEST_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList(localeParamName, dateFormatParamName, activatedOnDateParamName, "openingBalance"));
|
||||
|
||||
protected static final Set<String> SAVINGS_ACCOUNT_CLOSE_REQUEST_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList(localeParamName, dateFormatParamName, closedOnDateParamName, noteParamName, paymentTypeIdParamName,
|
||||
withdrawBalanceParamName, transactionAccountNumberParamName, checkNumberParamName, routingCodeParamName,
|
||||
receiptNumberParamName, bankNumberParamName, postInterestValidationOnClosure));
|
||||
|
||||
protected static final Set<String> SAVINGS_ACCOUNT_CHARGES_ADD_REQUEST_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList(chargeIdParamName, amountParamName, dueAsOfDateParamName, dateFormatParamName, localeParamName,
|
||||
feeOnMonthDayParamName, monthDayFormatParamName, feeIntervalParamName));
|
||||
|
||||
protected static final Set<String> SAVINGS_ACCOUNT_CHARGES_PAY_CHARGE_REQUEST_DATA_PARAMETERS = new HashSet<>(
|
||||
Arrays.asList(amountParamName, dueAsOfDateParamName, dateFormatParamName, localeParamName, noteParamName));
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user