This is an automated email from the ASF dual-hosted git repository.
adamsaghy pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new e1d820756f FINERACT-2180: Trigger (internal) business event when new
datatable entry was added
e1d820756f is described below
commit e1d820756fec33ecb1174894639b20f284217c42
Author: Jose Alberto Hernandez <[email protected]>
AuthorDate: Tue Feb 25 07:18:48 2025 -0500
FINERACT-2180: Trigger (internal) business event when new datatable entry
was added
---
.../service/ReadWriteNonCoreDataServiceImpl.java | 49 ++-
.../starter/DataQueriesAutoConfiguration.java | 10 +-
.../datatable/DatatableEntryBusinessEvent.java | 47 +++
.../DatatableEntryCreatedBusinessEvent.java | 41 ++
.../DatatableEntryDeletedBusinessEvent.java | 40 ++
.../domain/datatable/DatatableEntryDetails.java | 36 ++
.../DatatableEntryUpdatedBusinessEvent.java | 40 ++
.../portfolio/client/api/ClientsApiResource.java | 7 +-
.../client/service/ClientReadPlatformService.java | 2 -
.../service/ClientReadPlatformServiceImpl.java | 89 -----
.../service/ClientTemplateReadPlatformService.java | 27 ++
.../ClientTemplateReadPlatformServiceImpl.java | 133 +++++++
.../savings/api/SavingsAccountsApiResource.java | 8 +-
.../SavingsAccountReadPlatformServiceImpl.java | 350 +----------------
...ingsAccountTemplateReadPlatformServiceImpl.java | 412 +++++++++++++++++++++
.../savings/starter/SavingsConfiguration.java | 25 +-
.../service/DatatableBusinessEventTest.java | 207 +++++++++++
.../service/SavingsAccountReadPlatformService.java | 2 -
.../SavingsAccountTemplateReadPlatformService.java | 27 ++
19 files changed, 1081 insertions(+), 471 deletions(-)
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java
index 78796b1165..91e9a47b18 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/service/ReadWriteNonCoreDataServiceImpl.java
@@ -106,8 +106,12 @@ import
org.apache.fineract.infrastructure.dataqueries.data.ResultsetRowData;
import
org.apache.fineract.infrastructure.dataqueries.exception.DatatableEntryRequiredException;
import
org.apache.fineract.infrastructure.dataqueries.exception.DatatableNotFoundException;
import
org.apache.fineract.infrastructure.dataqueries.exception.DatatableSystemErrorException;
+import
org.apache.fineract.infrastructure.event.business.domain.datatable.DatatableEntryCreatedBusinessEvent;
+import
org.apache.fineract.infrastructure.event.business.domain.datatable.DatatableEntryDeletedBusinessEvent;
+import
org.apache.fineract.infrastructure.event.business.domain.datatable.DatatableEntryDetails;
+import
org.apache.fineract.infrastructure.event.business.domain.datatable.DatatableEntryUpdatedBusinessEvent;
+import
org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
import
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
-import
org.apache.fineract.infrastructure.security.service.SqlInjectionPreventerService;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.infrastructure.security.utils.ColumnValidator;
import org.apache.fineract.portfolio.search.data.AdvancedQueryData;
@@ -156,10 +160,10 @@ public class ReadWriteNonCoreDataServiceImpl implements
ReadWriteNonCoreDataServ
private final DataTableValidator dataTableValidator;
private final ColumnValidator columnValidator;
private final NamedParameterJdbcTemplate namedParameterJdbcTemplate;
- private final SqlInjectionPreventerService preventSqlInjectionService;
private final DatatableKeywordGenerator datatableKeywordGenerator;
private final SqlValidator sqlValidator;
private final SearchUtil searchUtil;
+ private final BusinessEventNotifierService businessEventNotifierService;
@Override
public List<DatatableData> retrieveDatatableNames(final String appTable) {
@@ -1307,8 +1311,9 @@ public class ReadWriteNonCoreDataServiceImpl implements
ReadWriteNonCoreDataServ
ArrayList<String> insertColumns = new ArrayList<>(
List.of(entityTable.getForeignKeyColumnNameOnDatatable(),
CREATEDAT_FIELD_NAME, UPDATEDAT_FIELD_NAME));
- LocalDateTime auditDateTime = DateUtils.getAuditLocalDateTime();
+ final LocalDateTime auditDateTime = DateUtils.getAuditLocalDateTime();
ArrayList<Object> params = new ArrayList<>(List.of(appTableId,
auditDateTime, auditDateTime));
+ Map<String, Object> dataObjectParams = new HashMap<String, Object>();
for (Map.Entry<String, String> entry : dataParams.entrySet()) {
if (isTechnicalParam(entry.getKey())) {
continue;
@@ -1318,8 +1323,11 @@ public class ReadWriteNonCoreDataServiceImpl implements
ReadWriteNonCoreDataServ
continue;
}
insertColumns.add(columnHeader.getColumnName());
- params.add(searchUtil.parseJdbcColumnValue(columnHeader,
entry.getValue(), dateFormat, dateTimeFormat, locale, false,
- sqlGenerator));
+ Object valueParam = searchUtil.parseJdbcColumnValue(columnHeader,
entry.getValue(), dateFormat, dateTimeFormat, locale, false,
+ sqlGenerator);
+ params.add(valueParam);
+ dataObjectParams.put(entry.getKey(), valueParam);
+
}
if (addScore) {
List<Object> scoreIds = params.stream().filter(e -> e != null &&
!String.valueOf(e).isBlank()).toList();
@@ -1353,6 +1361,11 @@ public class ReadWriteNonCoreDataServiceImpl implements
ReadWriteNonCoreDataServ
if (isMultirowDatatable(columnHeaders)) {
resourceId = sqlGenerator.fetchPK(keyHolder);
}
+
+ final DatatableEntryDetails datatableEntryDetails = new
DatatableEntryDetails(dataTableName, entityTable, resourceId,
+ appTableId, dataObjectParams);
+ businessEventNotifierService.notifyPostBusinessEvent(new
DatatableEntryCreatedBusinessEvent(datatableEntryDetails));
+
return
CommandProcessingResult.fromCommandProcessingResult(commandProcessingResult,
resourceId);
} catch (final DataAccessException dve) {
handleDataIntegrityIssues(dataTableName, appTableId,
dve.getMostSpecificCause(), dve);
@@ -1422,6 +1435,7 @@ public class ReadWriteNonCoreDataServiceImpl implements
ReadWriteNonCoreDataServ
final Type typeOfMap = new TypeToken<Map<String, String>>()
{}.getType();
final Map<String, String> dataParams =
fromJsonHelper.extractDataMap(typeOfMap, command.json());
+ final Map<String, Object> dataObjectParams = new HashMap<String,
Object>();
final String dateFormat = dataParams.get(API_PARAM_DATE_FORMAT);
// fall back to dateFormat to keep backward compatibility
@@ -1445,6 +1459,7 @@ public class ReadWriteNonCoreDataServiceImpl implements
ReadWriteNonCoreDataServ
Object existingValue = valuesByHeader.get(columnHeader);
Object columnValue = searchUtil.parseColumnValue(columnHeader,
entry.getValue(), dateFormat, dateTimeFormat, locale, false,
sqlGenerator);
+ dataObjectParams.put(entry.getKey(), columnValue);
if ((columnHeader.getColumnType().isDecimalType() &&
MathUtil.isEqualTo((BigDecimal) existingValue, (BigDecimal) columnValue))
|| (existingValue == null ? columnValue == null :
existingValue.equals(columnValue))) {
log.debug("Ignore change on update {}:{}", dataTableName,
columnName);
@@ -1457,16 +1472,23 @@ public class ReadWriteNonCoreDataServiceImpl implements
ReadWriteNonCoreDataServ
Long primaryKey = datatableId == null ? appTableId : datatableId;
if (!updateColumns.isEmpty()) {
ResultsetColumnHeaderData pkColumn =
searchUtil.getFiltered(columnHeaders,
ResultsetColumnHeaderData::getIsColumnPrimaryKey);
- params.add(primaryKey);
- final String sql = sqlGenerator.buildUpdate(dataTableName,
updateColumns, headersByName) + " WHERE " + pkColumn.getColumnName()
- + " = ?";
- int updated = jdbcTemplate.update(sql,
params.toArray(Object[]::new)); // NOSONAR
- if (updated != 1) {
- throw new
PlatformDataIntegrityException("error.msg.invalid.update", "Expected one
updated row.");
+ if (pkColumn != null) {
+ params.add(primaryKey);
+ final String sql = sqlGenerator.buildUpdate(dataTableName,
updateColumns, headersByName) + " WHERE "
+ + pkColumn.getColumnName() + " = ?";
+ int updated = jdbcTemplate.update(sql,
params.toArray(Object[]::new)); // NOSONAR
+ if (updated != 1) {
+ throw new
PlatformDataIntegrityException("error.msg.invalid.update", "Expected one
updated row.");
+ }
}
} else {
log.debug("No change on update {}", dataTableName);
}
+
+ final DatatableEntryDetails datatableEntryDetails = new
DatatableEntryDetails(dataTableName, entityTable, datatableId, appTableId,
+ dataObjectParams);
+ businessEventNotifierService.notifyPostBusinessEvent(new
DatatableEntryUpdatedBusinessEvent(datatableEntryDetails));
+
return new
CommandProcessingResultBuilder().withCommandId(command.commandId()) //
.withEntityId(primaryKey) //
.withOfficeId(commandProcessingResult.getOfficeId()) //
@@ -1517,6 +1539,11 @@ public class ReadWriteNonCoreDataServiceImpl implements
ReadWriteNonCoreDataServ
+ whereValue;
this.jdbcTemplate.update(sql); // NOSONAR
+ final Map<String, Object> dataParams = null;
+ final DatatableEntryDetails datatableEntryDetails = new
DatatableEntryDetails(dataTableName, entityTable, datatableId, appTableId,
+ dataParams);
+ businessEventNotifierService.notifyPostBusinessEvent(new
DatatableEntryDeletedBusinessEvent(datatableEntryDetails));
+
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(whereValue) //
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/starter/DataQueriesAutoConfiguration.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/starter/DataQueriesAutoConfiguration.java
index 8425fa997f..4de72b69ad 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/starter/DataQueriesAutoConfiguration.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/dataqueries/starter/DataQueriesAutoConfiguration.java
@@ -29,8 +29,8 @@ import
org.apache.fineract.infrastructure.dataqueries.service.DatatableKeywordGe
import
org.apache.fineract.infrastructure.dataqueries.service.GenericDataService;
import
org.apache.fineract.infrastructure.dataqueries.service.ReadWriteNonCoreDataService;
import
org.apache.fineract.infrastructure.dataqueries.service.ReadWriteNonCoreDataServiceImpl;
+import
org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
import
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
-import
org.apache.fineract.infrastructure.security.service.SqlInjectionPreventerService;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.infrastructure.security.utils.ColumnValidator;
import org.apache.fineract.portfolio.search.service.SearchUtil;
@@ -51,11 +51,11 @@ public class DataQueriesAutoConfiguration {
final DatatableCommandFromApiJsonDeserializer
fromApiJsonDeserializer,
final ConfigurationDomainService configurationDomainService, final
CodeReadPlatformService codeReadPlatformService,
final DataTableValidator dataTableValidator, final ColumnValidator
columnValidator,
- final NamedParameterJdbcTemplate namedParameterJdbcTemplate, final
SqlInjectionPreventerService preventSqlInjectionService,
- DatatableKeywordGenerator datatableKeywordGenerator, SqlValidator
sqlValidator, SearchUtil searchUtil) {
+ final NamedParameterJdbcTemplate namedParameterJdbcTemplate,
DatatableKeywordGenerator datatableKeywordGenerator,
+ SqlValidator sqlValidator, SearchUtil searchUtil, final
BusinessEventNotifierService businessEventNotifierService) {
return new ReadWriteNonCoreDataServiceImpl(jdbcTemplate,
databaseTypeResolver, sqlGenerator, context, fromJsonHelper,
genericDataService, fromApiJsonDeserializer,
configurationDomainService, codeReadPlatformService, dataTableValidator,
- columnValidator, namedParameterJdbcTemplate,
preventSqlInjectionService, datatableKeywordGenerator, sqlValidator,
- searchUtil);
+ columnValidator, namedParameterJdbcTemplate,
datatableKeywordGenerator, sqlValidator, searchUtil,
+ businessEventNotifierService);
}
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/business/domain/datatable/DatatableEntryBusinessEvent.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/business/domain/datatable/DatatableEntryBusinessEvent.java
new file mode 100644
index 0000000000..3a51b060b3
--- /dev/null
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/business/domain/datatable/DatatableEntryBusinessEvent.java
@@ -0,0 +1,47 @@
+/**
+ * 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.infrastructure.event.business.domain.datatable;
+
+import lombok.Getter;
+import
org.apache.fineract.infrastructure.event.business.domain.AbstractBusinessEvent;
+
+@Getter
+public abstract class DatatableEntryBusinessEvent extends
AbstractBusinessEvent<DatatableEntryDetails> {
+
+ protected static final String CATEGORY = "Datatable";
+ public static final String TYPE = "DatatableEntryBusinessEvent";
+
+ protected DatatableEntryDetails datatableEntryDetails;
+
+ public DatatableEntryBusinessEvent(final DatatableEntryDetails
datatableEntryDetails) {
+ super(datatableEntryDetails);
+ this.datatableEntryDetails = datatableEntryDetails;
+ }
+
+ @Override
+ public String getType() {
+ return TYPE;
+ }
+
+ @Override
+ public String getCategory() {
+ return CATEGORY;
+ }
+
+}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/business/domain/datatable/DatatableEntryCreatedBusinessEvent.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/business/domain/datatable/DatatableEntryCreatedBusinessEvent.java
new file mode 100644
index 0000000000..a61688b42a
--- /dev/null
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/business/domain/datatable/DatatableEntryCreatedBusinessEvent.java
@@ -0,0 +1,41 @@
+/**
+ * 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.infrastructure.event.business.domain.datatable;
+
+import
org.apache.fineract.infrastructure.event.business.domain.NoExternalEvent;
+
+public class DatatableEntryCreatedBusinessEvent extends
DatatableEntryBusinessEvent implements NoExternalEvent {
+
+ public static final String TYPE = "DatatableEntryCreatedBusinessEvent";
+
+ public DatatableEntryCreatedBusinessEvent(final DatatableEntryDetails
datatableEntryDetails) {
+ super(datatableEntryDetails);
+ }
+
+ @Override
+ public String getType() {
+ return TYPE;
+ }
+
+ @Override
+ public Long getAggregateRootId() {
+ return datatableEntryDetails.getEntityId();
+ }
+
+}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/business/domain/datatable/DatatableEntryDeletedBusinessEvent.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/business/domain/datatable/DatatableEntryDeletedBusinessEvent.java
new file mode 100644
index 0000000000..e1fa56247d
--- /dev/null
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/business/domain/datatable/DatatableEntryDeletedBusinessEvent.java
@@ -0,0 +1,40 @@
+/**
+ * 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.infrastructure.event.business.domain.datatable;
+
+import
org.apache.fineract.infrastructure.event.business.domain.NoExternalEvent;
+
+public class DatatableEntryDeletedBusinessEvent extends
DatatableEntryBusinessEvent implements NoExternalEvent {
+
+ public static final String TYPE = "DatatableEntryDeletedBusinessEvent";
+
+ public DatatableEntryDeletedBusinessEvent(final DatatableEntryDetails
datatableEntryDetails) {
+ super(datatableEntryDetails);
+ }
+
+ @Override
+ public String getType() {
+ return TYPE;
+ }
+
+ @Override
+ public Long getAggregateRootId() {
+ return datatableEntryDetails.getEntityId();
+ }
+}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/business/domain/datatable/DatatableEntryDetails.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/business/domain/datatable/DatatableEntryDetails.java
new file mode 100644
index 0000000000..0aada8cc6d
--- /dev/null
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/business/domain/datatable/DatatableEntryDetails.java
@@ -0,0 +1,36 @@
+/**
+ * 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.infrastructure.event.business.domain.datatable;
+
+import java.util.Map;
+import lombok.Data;
+import lombok.RequiredArgsConstructor;
+import org.apache.fineract.infrastructure.dataqueries.data.EntityTables;
+
+@Data
+@RequiredArgsConstructor
+public class DatatableEntryDetails {
+
+ private final String datatableName;
+ private final EntityTables entityType;
+ private final Long entityId;
+ private final Long appTableId;
+ private final Map<String, Object> data;
+
+}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/business/domain/datatable/DatatableEntryUpdatedBusinessEvent.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/business/domain/datatable/DatatableEntryUpdatedBusinessEvent.java
new file mode 100644
index 0000000000..ed361fdd28
--- /dev/null
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/event/business/domain/datatable/DatatableEntryUpdatedBusinessEvent.java
@@ -0,0 +1,40 @@
+/**
+ * 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.infrastructure.event.business.domain.datatable;
+
+import
org.apache.fineract.infrastructure.event.business.domain.NoExternalEvent;
+
+public class DatatableEntryUpdatedBusinessEvent extends
DatatableEntryBusinessEvent implements NoExternalEvent {
+
+ public static final String TYPE = "DatatableEntryUpdatedBusinessEvent";
+
+ public DatatableEntryUpdatedBusinessEvent(final DatatableEntryDetails
datatableEntryDetails) {
+ super(datatableEntryDetails);
+ }
+
+ @Override
+ public String getType() {
+ return TYPE;
+ }
+
+ @Override
+ public Long getAggregateRootId() {
+ return datatableEntryDetails.getEntityId();
+ }
+}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientsApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientsApiResource.java
index dab2cffbc9..7a1140235b 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientsApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/api/ClientsApiResource.java
@@ -68,6 +68,7 @@ import
org.apache.fineract.portfolio.accountdetails.service.AccountDetailsReadPl
import org.apache.fineract.portfolio.client.data.ClientData;
import org.apache.fineract.portfolio.client.exception.ClientNotFoundException;
import org.apache.fineract.portfolio.client.service.ClientReadPlatformService;
+import
org.apache.fineract.portfolio.client.service.ClientTemplateReadPlatformService;
import org.apache.fineract.portfolio.loanaccount.guarantor.data.ObligeeData;
import
org.apache.fineract.portfolio.loanaccount.guarantor.service.GuarantorReadPlatformService;
import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
@@ -85,6 +86,7 @@ public class ClientsApiResource {
private final PlatformSecurityContext context;
private final ClientReadPlatformService clientReadPlatformService;
+ private final ClientTemplateReadPlatformService
clientTemplateReadPlatformService;
private final ToApiJsonSerializer<ClientData> toApiJsonSerializer;
private final ToApiJsonSerializer<AccountSummaryCollectionData>
clientAccountSummaryToApiJsonSerializer;
private final ApiRequestParameterHelper apiRequestParameterHelper;
@@ -122,7 +124,7 @@ public class ClientsApiResource {
} else if (CommandParameterUtil.is(commandParam, "withdraw")) {
clientData =
clientReadPlatformService.retrieveAllNarrations(ClientApiConstants.CLIENT_WITHDRAW_REASON);
} else {
- clientData = clientReadPlatformService.retrieveTemplate(officeId,
staffInSelectedOfficeOnly);
+ clientData =
clientTemplateReadPlatformService.retrieveTemplate(officeId,
staffInSelectedOfficeOnly);
}
final ApiRequestJsonSerializationSettings settings =
apiRequestParameterHelper.process(uriInfo.getQueryParameters());
@@ -458,7 +460,8 @@ public class ClientsApiResource {
private ClientData retrieveClientData(final Long clientId, final boolean
staffInSelectedOfficeOnly, final boolean isTemplate) {
ClientData clientData =
clientReadPlatformService.retrieveOne(clientId);
if (isTemplate) {
- final ClientData templateData =
clientReadPlatformService.retrieveTemplate(clientData.getOfficeId(),
staffInSelectedOfficeOnly);
+ final ClientData templateData =
clientTemplateReadPlatformService.retrieveTemplate(clientData.getOfficeId(),
+ staffInSelectedOfficeOnly);
clientData = ClientData.templateOnTop(clientData, templateData);
Collection<SavingsAccountData> savingAccountOptions =
savingsAccountReadPlatformService.retrieveForLookup(clientId, null);
if (savingAccountOptions != null && savingAccountOptions.size() >
0) {
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformService.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformService.java
index 60514e729e..5fa017e72f 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformService.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformService.java
@@ -27,8 +27,6 @@ import org.apache.fineract.portfolio.client.data.ClientData;
public interface ClientReadPlatformService {
- ClientData retrieveTemplate(Long officeId, boolean
staffInSelectedOfficeOnly);
-
Page<ClientData> retrieveAll(SearchParameters searchParameters);
ClientData retrieveOne(Long clientId);
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java
index 7f747b78e7..74d45fcb43 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientReadPlatformServiceImpl.java
@@ -32,54 +32,36 @@ import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.infrastructure.codes.data.CodeValueData;
import
org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService;
-import
org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
import org.apache.fineract.infrastructure.core.domain.ExternalId;
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
import
org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
-import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.core.service.ExternalIdFactory;
import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.PaginationHelper;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import
org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
-import org.apache.fineract.infrastructure.dataqueries.data.DatatableData;
-import org.apache.fineract.infrastructure.dataqueries.data.EntityTables;
-import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum;
-import
org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksReadService;
import
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.utils.ColumnValidator;
-import org.apache.fineract.organisation.office.data.OfficeData;
-import
org.apache.fineract.organisation.office.service.OfficeReadPlatformService;
-import org.apache.fineract.organisation.staff.data.StaffData;
-import org.apache.fineract.organisation.staff.service.StaffReadPlatformService;
-import org.apache.fineract.portfolio.address.data.AddressData;
-import
org.apache.fineract.portfolio.address.service.AddressReadPlatformService;
-import org.apache.fineract.portfolio.client.api.ClientApiConstants;
import
org.apache.fineract.portfolio.client.data.ClientCollateralManagementData;
import org.apache.fineract.portfolio.client.data.ClientData;
-import org.apache.fineract.portfolio.client.data.ClientFamilyMembersData;
import org.apache.fineract.portfolio.client.data.ClientNonPersonData;
import org.apache.fineract.portfolio.client.data.ClientTimelineData;
import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.client.domain.ClientEnumerations;
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
import org.apache.fineract.portfolio.client.domain.ClientStatus;
-import org.apache.fineract.portfolio.client.domain.LegalForm;
import org.apache.fineract.portfolio.client.exception.ClientNotFoundException;
import org.apache.fineract.portfolio.client.mapper.ClientMapper;
import
org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagement;
import
org.apache.fineract.portfolio.collateralmanagement.domain.ClientCollateralManagementRepositoryWrapper;
import org.apache.fineract.portfolio.group.data.GroupGeneralData;
-import org.apache.fineract.portfolio.savings.data.SavingsProductData;
-import
org.apache.fineract.portfolio.savings.service.SavingsProductReadPlatformService;
import org.apache.fineract.useradministration.domain.AppUser;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;
-import org.springframework.util.CollectionUtils;
@Service
@RequiredArgsConstructor
@@ -87,10 +69,7 @@ public class ClientReadPlatformServiceImpl implements
ClientReadPlatformService
private final JdbcTemplate jdbcTemplate;
private final PlatformSecurityContext context;
- private final OfficeReadPlatformService officeReadPlatformService;
- private final StaffReadPlatformService staffReadPlatformService;
private final CodeValueReadPlatformService codeValueReadPlatformService;
- private final SavingsProductReadPlatformService
savingsProductReadPlatformService;
// data mappers
private final PaginationHelper paginationHelper;
private final DatabaseSpecificSQLGenerator sqlGenerator;
@@ -99,71 +78,11 @@ public class ClientReadPlatformServiceImpl implements
ClientReadPlatformService
private final ClientMembersOfGroupMapper membersOfGroupMapper = new
ClientMembersOfGroupMapper();
private final ParentGroupsMapper clientGroupsMapper = new
ParentGroupsMapper();
- private final AddressReadPlatformService addressReadPlatformService;
- private final ClientFamilyMembersReadPlatformService
clientFamilyMembersReadPlatformService;
- private final EntityDatatableChecksReadService
entityDatatableChecksReadService;
private final ColumnValidator columnValidator;
private final ClientCollateralManagementRepositoryWrapper
clientCollateralManagementRepositoryWrapper;
- private final ConfigurationDomainService configurationDomainService;
private final ClientRepositoryWrapper clientRepositoryWrapper;
private final ClientMapper clientMapper;
- @Override
- public ClientData retrieveTemplate(final Long officeId, final boolean
staffInSelectedOfficeOnly) {
- this.context.authenticatedUser();
-
- final Long defaultOfficeId = defaultToUsersOfficeIfNull(officeId);
- AddressData address = null;
-
- final Collection<OfficeData> offices =
this.officeReadPlatformService.retrieveAllOfficesForDropdown();
-
- final Collection<SavingsProductData> savingsProductDatas =
this.savingsProductReadPlatformService.retrieveAllForLookupByType(null);
-
- final Boolean isAddressEnabled =
configurationDomainService.isAddressEnabled();
- if (isAddressEnabled) {
- address = this.addressReadPlatformService.retrieveTemplate();
- }
-
- final ClientFamilyMembersData familyMemberOptions =
this.clientFamilyMembersReadPlatformService.retrieveTemplate();
-
- Collection<StaffData> staffOptions = null;
-
- final boolean loanOfficersOnly = false;
- if (staffInSelectedOfficeOnly) {
- staffOptions =
this.staffReadPlatformService.retrieveAllStaffForDropdown(defaultOfficeId);
- } else {
- staffOptions =
this.staffReadPlatformService.retrieveAllStaffInOfficeAndItsParentOfficeHierarchy(defaultOfficeId,
- loanOfficersOnly);
- }
- if (CollectionUtils.isEmpty(staffOptions)) {
- staffOptions = null;
- }
- final List<CodeValueData> genderOptions = new ArrayList<>(
-
this.codeValueReadPlatformService.retrieveCodeValuesByCode(ClientApiConstants.GENDER));
-
- final List<CodeValueData> clientTypeOptions = new ArrayList<>(
-
this.codeValueReadPlatformService.retrieveCodeValuesByCode(ClientApiConstants.CLIENT_TYPE));
-
- final List<CodeValueData> clientClassificationOptions = new
ArrayList<>(
-
this.codeValueReadPlatformService.retrieveCodeValuesByCode(ClientApiConstants.CLIENT_CLASSIFICATION));
-
- final List<CodeValueData> clientNonPersonConstitutionOptions = new
ArrayList<>(
-
this.codeValueReadPlatformService.retrieveCodeValuesByCode(ClientApiConstants.CLIENT_NON_PERSON_CONSTITUTION));
-
- final List<CodeValueData> clientNonPersonMainBusinessLineOptions = new
ArrayList<>(
-
this.codeValueReadPlatformService.retrieveCodeValuesByCode(ClientApiConstants.CLIENT_NON_PERSON_MAIN_BUSINESS_LINE));
-
- final List<EnumOptionData> clientLegalFormOptions =
ClientEnumerations.legalForm(LegalForm.values());
-
- final List<DatatableData> datatableTemplates =
this.entityDatatableChecksReadService.retrieveTemplates(StatusEnum.CREATE.getValue(),
- EntityTables.CLIENT.getName(), null);
-
- return ClientData.template(defaultOfficeId,
LocalDate.now(DateUtils.getDateTimeZoneOfTenant()), offices, staffOptions, null,
- genderOptions, savingsProductDatas, clientTypeOptions,
clientClassificationOptions, clientNonPersonConstitutionOptions,
- clientNonPersonMainBusinessLineOptions,
clientLegalFormOptions, familyMemberOptions,
- new ArrayList<AddressData>(Arrays.asList(address)),
isAddressEnabled, datatableTemplates);
- }
-
@Override
public Page<ClientData> retrieveAll(final SearchParameters
searchParameters) {
@@ -643,14 +562,6 @@ public class ClientReadPlatformServiceImpl implements
ClientReadPlatformService
}
}
- private Long defaultToUsersOfficeIfNull(final Long officeId) {
- Long defaultOfficeId = officeId;
- if (defaultOfficeId == null) {
- defaultOfficeId =
this.context.authenticatedUser().getOffice().getId();
- }
- return defaultOfficeId;
- }
-
@Override
public ClientData retrieveAllNarrations(final String clientNarrations) {
final List<CodeValueData> narrations = new ArrayList<>(
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientTemplateReadPlatformService.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientTemplateReadPlatformService.java
new file mode 100644
index 0000000000..b4ac660da7
--- /dev/null
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientTemplateReadPlatformService.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.portfolio.client.service;
+
+import org.apache.fineract.portfolio.client.data.ClientData;
+
+public interface ClientTemplateReadPlatformService {
+
+ ClientData retrieveTemplate(Long officeId, boolean
staffInSelectedOfficeOnly);
+
+}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientTemplateReadPlatformServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientTemplateReadPlatformServiceImpl.java
new file mode 100644
index 0000000000..7bb563cee8
--- /dev/null
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/client/service/ClientTemplateReadPlatformServiceImpl.java
@@ -0,0 +1,133 @@
+/**
+ * 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.client.service;
+
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import lombok.RequiredArgsConstructor;
+import org.apache.fineract.infrastructure.codes.data.CodeValueData;
+import
org.apache.fineract.infrastructure.codes.service.CodeValueReadPlatformService;
+import
org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.infrastructure.core.service.DateUtils;
+import org.apache.fineract.infrastructure.dataqueries.data.DatatableData;
+import org.apache.fineract.infrastructure.dataqueries.data.EntityTables;
+import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum;
+import
org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksReadService;
+import
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import org.apache.fineract.organisation.office.data.OfficeData;
+import
org.apache.fineract.organisation.office.service.OfficeReadPlatformService;
+import org.apache.fineract.organisation.staff.data.StaffData;
+import org.apache.fineract.organisation.staff.service.StaffReadPlatformService;
+import org.apache.fineract.portfolio.address.data.AddressData;
+import
org.apache.fineract.portfolio.address.service.AddressReadPlatformService;
+import org.apache.fineract.portfolio.client.api.ClientApiConstants;
+import org.apache.fineract.portfolio.client.data.ClientData;
+import org.apache.fineract.portfolio.client.data.ClientFamilyMembersData;
+import org.apache.fineract.portfolio.client.domain.ClientEnumerations;
+import org.apache.fineract.portfolio.client.domain.LegalForm;
+import org.apache.fineract.portfolio.savings.data.SavingsProductData;
+import
org.apache.fineract.portfolio.savings.service.SavingsProductReadPlatformService;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+@Service
+@RequiredArgsConstructor
+public class ClientTemplateReadPlatformServiceImpl implements
ClientTemplateReadPlatformService {
+
+ private final PlatformSecurityContext context;
+ private final OfficeReadPlatformService officeReadPlatformService;
+ private final StaffReadPlatformService staffReadPlatformService;
+ private final CodeValueReadPlatformService codeValueReadPlatformService;
+ private final SavingsProductReadPlatformService
savingsProductReadPlatformService;
+ // data mappers
+ private final EntityDatatableChecksReadService
entityDatatableChecksReadService;
+
+ private final AddressReadPlatformService addressReadPlatformService;
+ private final ClientFamilyMembersReadPlatformService
clientFamilyMembersReadPlatformService;
+ private final ConfigurationDomainService configurationDomainService;
+
+ @Override
+ public ClientData retrieveTemplate(final Long officeId, final boolean
staffInSelectedOfficeOnly) {
+ this.context.authenticatedUser();
+
+ final Long defaultOfficeId = defaultToUsersOfficeIfNull(officeId);
+ AddressData address = null;
+
+ final Collection<OfficeData> offices =
this.officeReadPlatformService.retrieveAllOfficesForDropdown();
+
+ final Collection<SavingsProductData> savingsProductDatas =
this.savingsProductReadPlatformService.retrieveAllForLookupByType(null);
+
+ final Boolean isAddressEnabled =
configurationDomainService.isAddressEnabled();
+ if (isAddressEnabled) {
+ address = this.addressReadPlatformService.retrieveTemplate();
+ }
+
+ final ClientFamilyMembersData familyMemberOptions =
this.clientFamilyMembersReadPlatformService.retrieveTemplate();
+
+ Collection<StaffData> staffOptions = null;
+
+ final boolean loanOfficersOnly = false;
+ if (staffInSelectedOfficeOnly) {
+ staffOptions =
this.staffReadPlatformService.retrieveAllStaffForDropdown(defaultOfficeId);
+ } else {
+ staffOptions =
this.staffReadPlatformService.retrieveAllStaffInOfficeAndItsParentOfficeHierarchy(defaultOfficeId,
+ loanOfficersOnly);
+ }
+ if (CollectionUtils.isEmpty(staffOptions)) {
+ staffOptions = null;
+ }
+ final List<CodeValueData> genderOptions = new ArrayList<>(
+
this.codeValueReadPlatformService.retrieveCodeValuesByCode(ClientApiConstants.GENDER));
+
+ final List<CodeValueData> clientTypeOptions = new ArrayList<>(
+
this.codeValueReadPlatformService.retrieveCodeValuesByCode(ClientApiConstants.CLIENT_TYPE));
+
+ final List<CodeValueData> clientClassificationOptions = new
ArrayList<>(
+
this.codeValueReadPlatformService.retrieveCodeValuesByCode(ClientApiConstants.CLIENT_CLASSIFICATION));
+
+ final List<CodeValueData> clientNonPersonConstitutionOptions = new
ArrayList<>(
+
this.codeValueReadPlatformService.retrieveCodeValuesByCode(ClientApiConstants.CLIENT_NON_PERSON_CONSTITUTION));
+
+ final List<CodeValueData> clientNonPersonMainBusinessLineOptions = new
ArrayList<>(
+
this.codeValueReadPlatformService.retrieveCodeValuesByCode(ClientApiConstants.CLIENT_NON_PERSON_MAIN_BUSINESS_LINE));
+
+ final List<EnumOptionData> clientLegalFormOptions =
ClientEnumerations.legalForm(LegalForm.values());
+
+ final List<DatatableData> datatableTemplates =
this.entityDatatableChecksReadService.retrieveTemplates(StatusEnum.CREATE.getValue(),
+ EntityTables.CLIENT.getName(), null);
+
+ return ClientData.template(defaultOfficeId,
LocalDate.now(DateUtils.getDateTimeZoneOfTenant()), offices, staffOptions, null,
+ genderOptions, savingsProductDatas, clientTypeOptions,
clientClassificationOptions, clientNonPersonConstitutionOptions,
+ clientNonPersonMainBusinessLineOptions,
clientLegalFormOptions, familyMemberOptions,
+ new ArrayList<AddressData>(Arrays.asList(address)),
isAddressEnabled, datatableTemplates);
+ }
+
+ private Long defaultToUsersOfficeIfNull(final Long officeId) {
+ Long defaultOfficeId = officeId;
+ if (defaultOfficeId == null) {
+ defaultOfficeId =
this.context.authenticatedUser().getOffice().getId();
+ }
+ return defaultOfficeId;
+ }
+
+}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsAccountsApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsAccountsApiResource.java
index 32d6a50ae5..1aa63d0fab 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsAccountsApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/api/SavingsAccountsApiResource.java
@@ -74,6 +74,7 @@ import
org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionData;
import
org.apache.fineract.portfolio.savings.exception.SavingsAccountNotFoundException;
import
org.apache.fineract.portfolio.savings.service.SavingsAccountChargeReadPlatformService;
import
org.apache.fineract.portfolio.savings.service.SavingsAccountReadPlatformService;
+import
org.apache.fineract.portfolio.savings.service.SavingsAccountTemplateReadPlatformService;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
import org.springframework.stereotype.Component;
@@ -86,6 +87,7 @@ import org.springframework.util.CollectionUtils;
public class SavingsAccountsApiResource {
private final SavingsAccountReadPlatformService
savingsAccountReadPlatformService;
+ private final SavingsAccountTemplateReadPlatformService
savingsAccountTemplateReadPlatformService;
private final PlatformSecurityContext context;
private final DefaultToApiJsonSerializer<SavingsAccountData>
toApiJsonSerializer;
private final PortfolioCommandSourceWritePlatformService
commandsSourceWritePlatformService;
@@ -112,7 +114,7 @@ public class SavingsAccountsApiResource {
context.authenticatedUser().validateHasReadPermission(SavingsApiConstants.SAVINGS_ACCOUNT_RESOURCE_NAME);
- final SavingsAccountData savingsAccount =
savingsAccountReadPlatformService.retrieveTemplate(clientId, groupId, productId,
+ final SavingsAccountData savingsAccount =
savingsAccountTemplateReadPlatformService.retrieveTemplate(clientId, groupId,
productId,
staffInSelectedOfficeOnly);
final ApiRequestJsonSerializationSettings settings =
apiRequestParameterHelper.process(uriInfo.getQueryParameters());
@@ -662,8 +664,8 @@ public class SavingsAccountsApiResource {
SavingsAccountData templateData = null;
final ApiRequestJsonSerializationSettings settings =
apiRequestParameterHelper.process(uriInfo.getQueryParameters());
if (settings.isTemplate()) {
- templateData =
savingsAccountReadPlatformService.retrieveTemplate(savingsAccount.getClientId(),
savingsAccount.getGroupId(),
- savingsAccount.getSavingsProductId(),
staffInSelectedOfficeOnly);
+ templateData =
savingsAccountTemplateReadPlatformService.retrieveTemplate(savingsAccount.getClientId(),
+ savingsAccount.getGroupId(),
savingsAccount.getSavingsProductId(), staffInSelectedOfficeOnly);
}
return SavingsAccountData.withTemplateOptions(savingsAccount,
templateData, transactions, charges);
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java
index 46579b8a76..22a9298d19 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformServiceImpl.java
@@ -42,23 +42,12 @@ import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.PaginationHelper;
import org.apache.fineract.infrastructure.core.service.SearchParameters;
import
org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
-import org.apache.fineract.infrastructure.dataqueries.data.DatatableData;
-import org.apache.fineract.infrastructure.dataqueries.data.EntityTables;
-import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum;
-import
org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksReadService;
import
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.utils.ColumnValidator;
import org.apache.fineract.organisation.monetary.data.CurrencyData;
-import org.apache.fineract.organisation.staff.data.StaffData;
-import org.apache.fineract.organisation.staff.service.StaffReadPlatformService;
import org.apache.fineract.portfolio.account.data.AccountTransferData;
-import org.apache.fineract.portfolio.charge.data.ChargeData;
-import org.apache.fineract.portfolio.charge.service.ChargeReadPlatformService;
-import
org.apache.fineract.portfolio.charge.util.ConvertChargeDataToSpecificChargeData;
import org.apache.fineract.portfolio.client.data.ClientData;
-import org.apache.fineract.portfolio.client.service.ClientReadPlatformService;
import org.apache.fineract.portfolio.group.data.GroupGeneralData;
-import org.apache.fineract.portfolio.group.service.GroupReadPlatformService;
import org.apache.fineract.portfolio.paymentdetail.data.PaymentDetailData;
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeData;
import org.apache.fineract.portfolio.savings.DepositAccountType;
@@ -91,19 +80,12 @@ import
org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.core.RowMapper;
-import org.springframework.util.CollectionUtils;
public class SavingsAccountReadPlatformServiceImpl implements
SavingsAccountReadPlatformService {
private final PlatformSecurityContext context;
private final JdbcTemplate jdbcTemplate;
- private final ClientReadPlatformService clientReadPlatformService;
- private final GroupReadPlatformService groupReadPlatformService;
- private final SavingsProductReadPlatformService
savingsProductReadPlatformService;
- private final StaffReadPlatformService staffReadPlatformService;
- private final SavingsDropdownReadPlatformService
dropdownReadPlatformService;
private final DatabaseSpecificSQLGenerator sqlGenerator;
- private final ChargeReadPlatformService chargeReadPlatformService;
// mappers
private final SavingsAccountTransactionTemplateMapper
transactionTemplateMapper;
@@ -116,35 +98,22 @@ public class SavingsAccountReadPlatformServiceImpl
implements SavingsAccountRead
// pagination
private final PaginationHelper paginationHelper;
- private final EntityDatatableChecksReadService
entityDatatableChecksReadService;
private final ColumnValidator columnValidator;
private final SavingsAccountAssembler savingAccountAssembler;
private final SavingsAccountRepositoryWrapper
savingsAccountRepositoryWrapper;
public SavingsAccountReadPlatformServiceImpl(final PlatformSecurityContext
context, final JdbcTemplate jdbcTemplate,
- final ClientReadPlatformService clientReadPlatformService, final
GroupReadPlatformService groupReadPlatformService,
- final SavingsProductReadPlatformService
savingProductReadPlatformService,
- final StaffReadPlatformService staffReadPlatformService, final
SavingsDropdownReadPlatformService dropdownReadPlatformService,
- final ChargeReadPlatformService chargeReadPlatformService,
- final EntityDatatableChecksReadService
entityDatatableChecksReadService, final ColumnValidator columnValidator,
- final SavingsAccountAssembler savingAccountAssembler,
PaginationHelper paginationHelper,
+ final SavingsAccountAssembler savingAccountAssembler,
PaginationHelper paginationHelper, ColumnValidator columnValidator,
DatabaseSpecificSQLGenerator sqlGenerator,
SavingsAccountRepositoryWrapper savingsAccountRepositoryWrapper) {
this.context = context;
this.jdbcTemplate = jdbcTemplate;
- this.clientReadPlatformService = clientReadPlatformService;
- this.groupReadPlatformService = groupReadPlatformService;
- this.savingsProductReadPlatformService =
savingProductReadPlatformService;
- this.staffReadPlatformService = staffReadPlatformService;
- this.dropdownReadPlatformService = dropdownReadPlatformService;
this.sqlGenerator = sqlGenerator;
this.savingsAccountRepositoryWrapper = savingsAccountRepositoryWrapper;
this.transactionTemplateMapper = new
SavingsAccountTransactionTemplateMapper();
this.transactionsMapper = new SavingsAccountTransactionsMapper();
this.savingsAccountTransactionsForBatchMapper = new
SavingsAccountTransactionsForBatchMapper();
this.savingAccountMapper = new SavingAccountMapper();
- this.chargeReadPlatformService = chargeReadPlatformService;
- this.entityDatatableChecksReadService =
entityDatatableChecksReadService;
this.columnValidator = columnValidator;
this.paginationHelper = paginationHelper;
this.savingAccountMapperForInterestPosting = new
SavingAccountMapperForInterestPosting();
@@ -1033,141 +1002,6 @@ public class SavingsAccountReadPlatformServiceImpl
implements SavingsAccountRead
}
}
- @Override
- public SavingsAccountData retrieveTemplate(final Long clientId, final Long
groupId, final Long productId,
- final boolean staffInSelectedOfficeOnly) {
-
- final AppUser loggedInUser = this.context.authenticatedUser();
- Long officeId = loggedInUser.getOffice().getId();
-
- ClientData client = null;
- if (clientId != null) {
- client = this.clientReadPlatformService.retrieveOne(clientId);
- officeId = client.getOfficeId();
- }
-
- GroupGeneralData group = null;
- if (groupId != null) {
- group = this.groupReadPlatformService.retrieveOne(groupId);
- officeId = group.getOfficeId();
- }
-
- final Collection<SavingsProductData> productOptions =
this.savingsProductReadPlatformService.retrieveAllForLookup();
- SavingsAccountData template = null;
- if (productId != null) {
-
- final SavingAccountTemplateMapper mapper = new
SavingAccountTemplateMapper(client, group);
-
- final String sql = "select " + mapper.schema() + " where sp.id =
?";
- template = this.jdbcTemplate.queryForObject(sql, mapper, new
Object[] { productId }); // NOSONAR
-
- final Collection<EnumOptionData>
interestCompoundingPeriodTypeOptions = this.dropdownReadPlatformService
- .retrieveCompoundingInterestPeriodTypeOptions();
-
- final Collection<EnumOptionData> interestPostingPeriodTypeOptions
= this.dropdownReadPlatformService
- .retrieveInterestPostingPeriodTypeOptions();
-
- final Collection<EnumOptionData> interestCalculationTypeOptions =
this.dropdownReadPlatformService
- .retrieveInterestCalculationTypeOptions();
-
- final Collection<EnumOptionData>
interestCalculationDaysInYearTypeOptions = this.dropdownReadPlatformService
- .retrieveInterestCalculationDaysInYearTypeOptions();
-
- final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions
= this.dropdownReadPlatformService
- .retrieveLockinPeriodFrequencyTypeOptions();
-
- final Collection<EnumOptionData> withdrawalFeeTypeOptions =
this.dropdownReadPlatformService.retrievewithdrawalFeeTypeOptions();
-
- final Collection<SavingsAccountTransactionData> transactions =
null;
- final Collection<ChargeData> productCharges =
this.chargeReadPlatformService.retrieveSavingsProductCharges(productId);
- // update charges from Product charges
- final Collection<SavingsAccountChargeData> charges =
fromChargesToSavingsCharges(productCharges);
-
- final boolean feeChargesOnly = false;
- final Collection<ChargeData> chargeOptions =
this.chargeReadPlatformService
- .retrieveSavingsProductApplicableCharges(feeChargesOnly);
-
- Collection<StaffData> fieldOfficerOptions = null;
-
- if (officeId != null) {
-
- if (staffInSelectedOfficeOnly) {
- // only bring back loan officers in selected branch/office
- final Collection<StaffData> fieldOfficersInBranch =
this.staffReadPlatformService
- .retrieveAllLoanOfficersInOfficeById(officeId);
-
- if (!CollectionUtils.isEmpty(fieldOfficersInBranch)) {
- fieldOfficerOptions = new
ArrayList<>(fieldOfficersInBranch);
- }
- } else {
- // by default bring back all officers in selected
- // branch/office as well as officers in office above
- // this office
- final boolean restrictToLoanOfficersOnly = true;
- final Collection<StaffData> loanOfficersInHierarchy =
this.staffReadPlatformService
-
.retrieveAllStaffInOfficeAndItsParentOfficeHierarchy(officeId,
restrictToLoanOfficersOnly);
-
- if (!CollectionUtils.isEmpty(loanOfficersInHierarchy)) {
- fieldOfficerOptions = new
ArrayList<>(loanOfficersInHierarchy);
- }
- }
- }
-
- template = SavingsAccountData.withTemplateOptions(template,
productOptions, fieldOfficerOptions,
- interestCompoundingPeriodTypeOptions,
interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
- interestCalculationDaysInYearTypeOptions,
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, transactions,
- charges, chargeOptions);
- } else {
-
- String clientName = null;
- if (client != null) {
- clientName = client.getDisplayName();
- }
-
- String groupName = null;
- if (group != null) {
- groupName = group.getName();
- }
-
- template = SavingsAccountData.withClientTemplate(clientId,
clientName, groupId, groupName);
-
- final Collection<StaffData> fieldOfficerOptions = null;
- final Collection<EnumOptionData>
interestCompoundingPeriodTypeOptions = null;
- final Collection<EnumOptionData> interestPostingPeriodTypeOptions
= null;
- final Collection<EnumOptionData> interestCalculationTypeOptions =
null;
- final Collection<EnumOptionData>
interestCalculationDaysInYearTypeOptions = null;
- final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions
= null;
- final Collection<EnumOptionData> withdrawalFeeTypeOptions = null;
-
- final Collection<SavingsAccountTransactionData> transactions =
null;
- final Collection<SavingsAccountChargeData> charges = null;
-
- final boolean feeChargesOnly = false;
- final Collection<ChargeData> chargeOptions =
this.chargeReadPlatformService
- .retrieveSavingsProductApplicableCharges(feeChargesOnly);
-
- template = SavingsAccountData.withTemplateOptions(template,
productOptions, fieldOfficerOptions,
- interestCompoundingPeriodTypeOptions,
interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
- interestCalculationDaysInYearTypeOptions,
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, transactions,
- charges, chargeOptions);
- }
-
- final List<DatatableData> datatableTemplates =
this.entityDatatableChecksReadService.retrieveTemplates(StatusEnum.CREATE.getValue(),
- EntityTables.SAVINGS.getName(), productId);
- template.setDatatables(datatableTemplates);
-
- return template;
- }
-
- private Collection<SavingsAccountChargeData>
fromChargesToSavingsCharges(final Collection<ChargeData> productCharges) {
- final Collection<SavingsAccountChargeData> savingsCharges = new
ArrayList<>();
- for (final ChargeData chargeData : productCharges) {
- final SavingsAccountChargeData savingsCharge =
ConvertChargeDataToSpecificChargeData.toSavingsAccountChargeData(chargeData);
- savingsCharges.add(savingsCharge);
- }
- return savingsCharges;
- }
-
@Override
public SavingsAccountTransactionData
retrieveDepositTransactionTemplate(final Long savingsId,
final DepositAccountType depositAccountType) {
@@ -1402,188 +1236,6 @@ public class SavingsAccountReadPlatformServiceImpl
implements SavingsAccountRead
}
}
- private static final class SavingAccountTemplateMapper implements
RowMapper<SavingsAccountData> {
-
- private final ClientData client;
- private final GroupGeneralData group;
-
- private final String schemaSql;
-
- SavingAccountTemplateMapper(final ClientData client, final
GroupGeneralData group) {
- this.client = client;
- this.group = group;
-
- final StringBuilder sqlBuilder = new StringBuilder(400);
- sqlBuilder.append("sp.id as productId, sp.name as productName, ");
- sqlBuilder.append(
- "sp.currency_code as currencyCode, sp.currency_digits as
currencyDigits, sp.currency_multiplesof as inMultiplesOf, ");
- sqlBuilder.append("curr.name as currencyName,
curr.internationalized_name_code as currencyNameCode, ");
- sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol,
");
- sqlBuilder.append("sp.nominal_annual_interest_rate as
nominalAnnualIterestRate, ");
- sqlBuilder.append("sp.interest_compounding_period_enum as
interestCompoundingPeriodType, ");
- sqlBuilder.append("sp.interest_posting_period_enum as
interestPostingPeriodType, ");
- sqlBuilder.append("sp.interest_calculation_type_enum as
interestCalculationType, ");
- sqlBuilder.append("sp.interest_calculation_days_in_year_type_enum
as interestCalculationDaysInYearType, ");
- sqlBuilder.append("sp.min_required_opening_balance as
minRequiredOpeningBalance, ");
- sqlBuilder.append("sp.lockin_period_frequency as
lockinPeriodFrequency,");
- sqlBuilder.append("sp.lockin_period_frequency_enum as
lockinPeriodFrequencyType, ");
- // sqlBuilder.append("sp.withdrawal_fee_amount as
- // withdrawalFeeAmount,");
- // sqlBuilder.append("sp.withdrawal_fee_type_enum as
- // withdrawalFeeTypeEnum, ");
- sqlBuilder.append("sp.withdrawal_fee_for_transfer as
withdrawalFeeForTransfers, ");
- sqlBuilder.append("sp.min_balance_for_interest_calculation as
minBalanceForInterestCalculation, ");
- sqlBuilder.append("sp.allow_overdraft as allowOverdraft, ");
- sqlBuilder.append("sp.overdraft_limit as overdraftLimit, ");
- sqlBuilder.append("sp.nominal_annual_interest_rate_overdraft as
nominalAnnualInterestRateOverdraft, ");
- sqlBuilder.append("sp.min_overdraft_for_interest_calculation as
minOverdraftForInterestCalculation, ");
- sqlBuilder.append("sp.withhold_tax as withHoldTax,");
- sqlBuilder.append("tg.id as taxGroupId, tg.name as taxGroupName,
");
-
- // sqlBuilder.append("sp.annual_fee_amount as annualFeeAmount,");
- // sqlBuilder.append("sp.annual_fee_on_month as annualFeeOnMonth,
- // ");
- // sqlBuilder.append("sp.annual_fee_on_day as annualFeeOnDay ");
- sqlBuilder.append("sp.min_required_balance as minRequiredBalance,
");
- sqlBuilder.append("sp.enforce_min_required_balance as
enforceMinRequiredBalance, ");
- sqlBuilder.append("sp.max_allowed_lien_limit as
maxAllowedLienLimit, ");
- sqlBuilder.append("sp.is_lien_allowed as lienAllowed ");
- sqlBuilder.append("from m_savings_product sp ");
- sqlBuilder.append("join m_currency curr on curr.code =
sp.currency_code ");
- sqlBuilder.append("left join m_tax_group tg on tg.id =
sp.tax_group_id ");
-
- this.schemaSql = sqlBuilder.toString();
- }
-
- public String schema() {
- return this.schemaSql;
- }
-
- @Override
- public SavingsAccountData mapRow(final ResultSet rs,
@SuppressWarnings("unused") final int rowNum) throws SQLException {
-
- final Long productId = rs.getLong("productId");
- final String productName = rs.getString("productName");
-
- final String currencyCode = rs.getString("currencyCode");
- final String currencyName = rs.getString("currencyName");
- final String currencyNameCode = rs.getString("currencyNameCode");
- final String currencyDisplaySymbol =
rs.getString("currencyDisplaySymbol");
- final Integer currencyDigits = JdbcSupport.getInteger(rs,
"currencyDigits");
- final Integer inMultiplesOf = JdbcSupport.getInteger(rs,
"inMultiplesOf");
- final CurrencyData currency = new CurrencyData(currencyCode,
currencyName, currencyDigits, inMultiplesOf, currencyDisplaySymbol,
- currencyNameCode);
-
- final BigDecimal nominalAnnualIterestRate =
rs.getBigDecimal("nominalAnnualIterestRate");
-
- final EnumOptionData interestCompoundingPeriodType =
SavingsEnumerations.compoundingInterestPeriodType(
-
SavingsCompoundingInterestPeriodType.fromInt(JdbcSupport.getInteger(rs,
"interestCompoundingPeriodType")));
-
- final EnumOptionData interestPostingPeriodType =
SavingsEnumerations.interestPostingPeriodType(
-
SavingsPostingInterestPeriodType.fromInt(JdbcSupport.getInteger(rs,
"interestPostingPeriodType")));
-
- final EnumOptionData interestCalculationType = SavingsEnumerations
-
.interestCalculationType(SavingsInterestCalculationType.fromInt(JdbcSupport.getInteger(rs,
"interestCalculationType")));
-
- final EnumOptionData interestCalculationDaysInYearType =
SavingsEnumerations.interestCalculationDaysInYearType(
-
SavingsInterestCalculationDaysInYearType.fromInt(JdbcSupport.getInteger(rs,
"interestCalculationDaysInYearType")));
-
- final BigDecimal minRequiredOpeningBalance =
JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "minRequiredOpeningBalance");
-
- final Integer lockinPeriodFrequency = JdbcSupport.getInteger(rs,
"lockinPeriodFrequency");
- EnumOptionData lockinPeriodFrequencyType = null;
- final Integer lockinPeriodFrequencyTypeValue =
JdbcSupport.getInteger(rs, "lockinPeriodFrequencyType");
- if (lockinPeriodFrequencyTypeValue != null) {
- final SavingsPeriodFrequencyType lockinPeriodType =
SavingsPeriodFrequencyType.fromInt(lockinPeriodFrequencyTypeValue);
- lockinPeriodFrequencyType =
SavingsEnumerations.lockinPeriodFrequencyType(lockinPeriodType);
- }
-
- // final BigDecimal withdrawalFeeAmount =
- // rs.getBigDecimal("withdrawalFeeAmount");
-
- /*
- * EnumOptionData withdrawalFeeType = null; final Integer
withdrawalFeeTypeValue =
- * JdbcSupport.getInteger(rs, "withdrawalFeeTypeEnum"); if
(withdrawalFeeTypeValue != null) {
- * withdrawalFeeType =
SavingsEnumerations.withdrawalFeeType(withdrawalFeeTypeValue); }
- */
- final boolean withdrawalFeeForTransfers =
rs.getBoolean("withdrawalFeeForTransfers");
-
- final boolean allowOverdraft = rs.getBoolean("allowOverdraft");
- final BigDecimal overdraftLimit =
JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "overdraftLimit");
- final BigDecimal nominalAnnualInterestRateOverdraft =
JdbcSupport.getBigDecimalDefaultToNullIfZero(rs,
- "nominalAnnualInterestRateOverdraft");
- final BigDecimal minOverdraftForInterestCalculation =
JdbcSupport.getBigDecimalDefaultToNullIfZero(rs,
- "minOverdraftForInterestCalculation");
-
- final BigDecimal minRequiredBalance =
JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "minRequiredBalance");
- final boolean enforceMinRequiredBalance =
rs.getBoolean("enforceMinRequiredBalance");
- final BigDecimal maxAllowedLienLimit =
JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "maxAllowedLienLimit");
- final boolean lienAllowed = rs.getBoolean("lienAllowed");
- final BigDecimal minBalanceForInterestCalculation =
JdbcSupport.getBigDecimalDefaultToNullIfZero(rs,
- "minBalanceForInterestCalculation");
-
- // final BigDecimal annualFeeAmount =
- // JdbcSupport.getBigDecimalDefaultToNullIfZero(rs,
- // "annualFeeAmount");
-
- /*
- * MonthDay annualFeeOnMonthDay = null; final Integer
annualFeeOnMonth = JdbcSupport.getInteger(rs,
- * "annualFeeOnMonth"); final Integer annualFeeOnDay =
JdbcSupport.getInteger(rs, "annualFeeOnDay"); if
- * (annualFeeAmount != null && annualFeeOnDay != null) {
annualFeeOnMonthDay = new
- * MonthDay(annualFeeOnMonth, annualFeeOnDay); }
- */
-
- final boolean withHoldTax = rs.getBoolean("withHoldTax");
- final Long taxGroupId = JdbcSupport.getLong(rs, "taxGroupId");
- final String taxGroupName = rs.getString("taxGroupName");
- TaxGroupData taxGroupData = null;
- if (taxGroupId != null) {
- taxGroupData = TaxGroupData.lookup(taxGroupId, taxGroupName);
- }
-
- Long clientId = null;
- String clientName = null;
- if (this.client != null) {
- clientId = this.client.getId();
- clientName = this.client.getDisplayName();
- }
-
- Long groupId = null;
- String groupName = null;
- if (this.group != null) {
- groupId = this.group.getId();
- groupName = this.group.getName();
- }
-
- final Long fieldOfficerId = null;
- final String fieldOfficerName = null;
- final SavingsAccountStatusEnumData status = null;
- // final LocalDate annualFeeNextDueDate = null;
- final SavingsAccountSummaryData summary = null;
- final BigDecimal onHoldFunds = null;
- final BigDecimal savingsAmountOnHold = null;
-
- final SavingsAccountSubStatusEnumData subStatus = null;
- final String reasonForBlock = null;
- final LocalDate lastActiveTransactionDate = null;
- final boolean isDormancyTrackingActive = false;
- final Integer daysToInactive = null;
- final Integer daysToDormancy = null;
- final Integer daysToEscheat = null;
-
- final SavingsAccountApplicationTimelineData timeline =
SavingsAccountApplicationTimelineData.templateDefault();
- final EnumOptionData depositType = null;
- return SavingsAccountData.instance(null, null, depositType, null,
groupId, groupName, clientId, clientName, productId,
- productName, fieldOfficerId, fieldOfficerName, status,
subStatus, reasonForBlock, timeline, currency,
- nominalAnnualIterestRate, interestCompoundingPeriodType,
interestPostingPeriodType, interestCalculationType,
- interestCalculationDaysInYearType,
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
- withdrawalFeeForTransfers, summary, allowOverdraft,
overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
- maxAllowedLienLimit, lienAllowed,
minBalanceForInterestCalculation, onHoldFunds,
nominalAnnualInterestRateOverdraft,
- minOverdraftForInterestCalculation, withHoldTax,
taxGroupData, lastActiveTransactionDate, isDormancyTrackingActive,
- daysToInactive, daysToDormancy, daysToEscheat,
savingsAmountOnHold);
- }
- }
-
@Override
public Collection<SavingsAccountData> retrieveForLookup(Long clientId,
Boolean overdraft) {
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountTemplateReadPlatformServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountTemplateReadPlatformServiceImpl.java
new file mode 100644
index 0000000000..3817eb0638
--- /dev/null
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountTemplateReadPlatformServiceImpl.java
@@ -0,0 +1,412 @@
+/**
+ * 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.service;
+
+import java.math.BigDecimal;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import org.apache.fineract.infrastructure.core.data.EnumOptionData;
+import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
+import org.apache.fineract.infrastructure.dataqueries.data.DatatableData;
+import org.apache.fineract.infrastructure.dataqueries.data.EntityTables;
+import org.apache.fineract.infrastructure.dataqueries.data.StatusEnum;
+import
org.apache.fineract.infrastructure.dataqueries.service.EntityDatatableChecksReadService;
+import
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import org.apache.fineract.infrastructure.security.utils.ColumnValidator;
+import org.apache.fineract.organisation.monetary.data.CurrencyData;
+import org.apache.fineract.organisation.staff.data.StaffData;
+import org.apache.fineract.organisation.staff.service.StaffReadPlatformService;
+import org.apache.fineract.portfolio.charge.data.ChargeData;
+import org.apache.fineract.portfolio.charge.service.ChargeReadPlatformService;
+import
org.apache.fineract.portfolio.charge.util.ConvertChargeDataToSpecificChargeData;
+import org.apache.fineract.portfolio.client.data.ClientData;
+import org.apache.fineract.portfolio.client.service.ClientReadPlatformService;
+import org.apache.fineract.portfolio.group.data.GroupGeneralData;
+import org.apache.fineract.portfolio.group.service.GroupReadPlatformService;
+import
org.apache.fineract.portfolio.savings.SavingsCompoundingInterestPeriodType;
+import
org.apache.fineract.portfolio.savings.SavingsInterestCalculationDaysInYearType;
+import org.apache.fineract.portfolio.savings.SavingsInterestCalculationType;
+import org.apache.fineract.portfolio.savings.SavingsPeriodFrequencyType;
+import org.apache.fineract.portfolio.savings.SavingsPostingInterestPeriodType;
+import
org.apache.fineract.portfolio.savings.data.SavingsAccountApplicationTimelineData;
+import org.apache.fineract.portfolio.savings.data.SavingsAccountChargeData;
+import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
+import org.apache.fineract.portfolio.savings.data.SavingsAccountStatusEnumData;
+import
org.apache.fineract.portfolio.savings.data.SavingsAccountSubStatusEnumData;
+import org.apache.fineract.portfolio.savings.data.SavingsAccountSummaryData;
+import
org.apache.fineract.portfolio.savings.data.SavingsAccountTransactionData;
+import org.apache.fineract.portfolio.savings.data.SavingsProductData;
+import org.apache.fineract.portfolio.tax.data.TaxGroupData;
+import org.apache.fineract.useradministration.domain.AppUser;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.util.CollectionUtils;
+
+public class SavingsAccountTemplateReadPlatformServiceImpl implements
SavingsAccountTemplateReadPlatformService {
+
+ private final PlatformSecurityContext context;
+ private final JdbcTemplate jdbcTemplate;
+ private final ClientReadPlatformService clientReadPlatformService;
+ private final GroupReadPlatformService groupReadPlatformService;
+ private final SavingsProductReadPlatformService
savingsProductReadPlatformService;
+ private final StaffReadPlatformService staffReadPlatformService;
+ private final SavingsDropdownReadPlatformService
dropdownReadPlatformService;
+ private final ChargeReadPlatformService chargeReadPlatformService;
+
+ private final EntityDatatableChecksReadService
entityDatatableChecksReadService;
+
+ public SavingsAccountTemplateReadPlatformServiceImpl(final
PlatformSecurityContext context, final JdbcTemplate jdbcTemplate,
+ final ClientReadPlatformService clientReadPlatformService, final
GroupReadPlatformService groupReadPlatformService,
+ final SavingsProductReadPlatformService
savingProductReadPlatformService,
+ final StaffReadPlatformService staffReadPlatformService, final
SavingsDropdownReadPlatformService dropdownReadPlatformService,
+ final ChargeReadPlatformService chargeReadPlatformService,
+ final EntityDatatableChecksReadService
entityDatatableChecksReadService, final ColumnValidator columnValidator) {
+ this.context = context;
+ this.jdbcTemplate = jdbcTemplate;
+ this.clientReadPlatformService = clientReadPlatformService;
+ this.groupReadPlatformService = groupReadPlatformService;
+ this.savingsProductReadPlatformService =
savingProductReadPlatformService;
+ this.staffReadPlatformService = staffReadPlatformService;
+ this.dropdownReadPlatformService = dropdownReadPlatformService;
+ this.chargeReadPlatformService = chargeReadPlatformService;
+ this.entityDatatableChecksReadService =
entityDatatableChecksReadService;
+ }
+
+ @Override
+ public SavingsAccountData retrieveTemplate(final Long clientId, final Long
groupId, final Long productId,
+ final boolean staffInSelectedOfficeOnly) {
+
+ final AppUser loggedInUser = this.context.authenticatedUser();
+ Long officeId = loggedInUser.getOffice().getId();
+
+ ClientData client = null;
+ if (clientId != null) {
+ client = this.clientReadPlatformService.retrieveOne(clientId);
+ officeId = client.getOfficeId();
+ }
+
+ GroupGeneralData group = null;
+ if (groupId != null) {
+ group = this.groupReadPlatformService.retrieveOne(groupId);
+ officeId = group.getOfficeId();
+ }
+
+ final Collection<SavingsProductData> productOptions =
this.savingsProductReadPlatformService.retrieveAllForLookup();
+ SavingsAccountData template = null;
+ if (productId != null) {
+
+ final SavingAccountTemplateMapper mapper = new
SavingAccountTemplateMapper(client, group);
+
+ final String sql = "select " + mapper.schema() + " where sp.id =
?";
+ template = this.jdbcTemplate.queryForObject(sql, mapper, new
Object[] { productId }); // NOSONAR
+
+ final Collection<EnumOptionData>
interestCompoundingPeriodTypeOptions = this.dropdownReadPlatformService
+ .retrieveCompoundingInterestPeriodTypeOptions();
+
+ final Collection<EnumOptionData> interestPostingPeriodTypeOptions
= this.dropdownReadPlatformService
+ .retrieveInterestPostingPeriodTypeOptions();
+
+ final Collection<EnumOptionData> interestCalculationTypeOptions =
this.dropdownReadPlatformService
+ .retrieveInterestCalculationTypeOptions();
+
+ final Collection<EnumOptionData>
interestCalculationDaysInYearTypeOptions = this.dropdownReadPlatformService
+ .retrieveInterestCalculationDaysInYearTypeOptions();
+
+ final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions
= this.dropdownReadPlatformService
+ .retrieveLockinPeriodFrequencyTypeOptions();
+
+ final Collection<EnumOptionData> withdrawalFeeTypeOptions =
this.dropdownReadPlatformService.retrievewithdrawalFeeTypeOptions();
+
+ final Collection<SavingsAccountTransactionData> transactions =
null;
+ final Collection<ChargeData> productCharges =
this.chargeReadPlatformService.retrieveSavingsProductCharges(productId);
+ // update charges from Product charges
+ final Collection<SavingsAccountChargeData> charges =
fromChargesToSavingsCharges(productCharges);
+
+ final boolean feeChargesOnly = false;
+ final Collection<ChargeData> chargeOptions =
this.chargeReadPlatformService
+ .retrieveSavingsProductApplicableCharges(feeChargesOnly);
+
+ Collection<StaffData> fieldOfficerOptions = null;
+
+ if (officeId != null) {
+
+ if (staffInSelectedOfficeOnly) {
+ // only bring back loan officers in selected branch/office
+ final Collection<StaffData> fieldOfficersInBranch =
this.staffReadPlatformService
+ .retrieveAllLoanOfficersInOfficeById(officeId);
+
+ if (!CollectionUtils.isEmpty(fieldOfficersInBranch)) {
+ fieldOfficerOptions = new
ArrayList<>(fieldOfficersInBranch);
+ }
+ } else {
+ // by default bring back all officers in selected
+ // branch/office as well as officers in office above
+ // this office
+ final boolean restrictToLoanOfficersOnly = true;
+ final Collection<StaffData> loanOfficersInHierarchy =
this.staffReadPlatformService
+
.retrieveAllStaffInOfficeAndItsParentOfficeHierarchy(officeId,
restrictToLoanOfficersOnly);
+
+ if (!CollectionUtils.isEmpty(loanOfficersInHierarchy)) {
+ fieldOfficerOptions = new
ArrayList<>(loanOfficersInHierarchy);
+ }
+ }
+ }
+
+ template = SavingsAccountData.withTemplateOptions(template,
productOptions, fieldOfficerOptions,
+ interestCompoundingPeriodTypeOptions,
interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
+ interestCalculationDaysInYearTypeOptions,
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, transactions,
+ charges, chargeOptions);
+ } else {
+
+ String clientName = null;
+ if (client != null) {
+ clientName = client.getDisplayName();
+ }
+
+ String groupName = null;
+ if (group != null) {
+ groupName = group.getName();
+ }
+
+ template = SavingsAccountData.withClientTemplate(clientId,
clientName, groupId, groupName);
+
+ final Collection<StaffData> fieldOfficerOptions = null;
+ final Collection<EnumOptionData>
interestCompoundingPeriodTypeOptions = null;
+ final Collection<EnumOptionData> interestPostingPeriodTypeOptions
= null;
+ final Collection<EnumOptionData> interestCalculationTypeOptions =
null;
+ final Collection<EnumOptionData>
interestCalculationDaysInYearTypeOptions = null;
+ final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions
= null;
+ final Collection<EnumOptionData> withdrawalFeeTypeOptions = null;
+
+ final Collection<SavingsAccountTransactionData> transactions =
null;
+ final Collection<SavingsAccountChargeData> charges = null;
+
+ final boolean feeChargesOnly = false;
+ final Collection<ChargeData> chargeOptions =
this.chargeReadPlatformService
+ .retrieveSavingsProductApplicableCharges(feeChargesOnly);
+
+ template = SavingsAccountData.withTemplateOptions(template,
productOptions, fieldOfficerOptions,
+ interestCompoundingPeriodTypeOptions,
interestPostingPeriodTypeOptions, interestCalculationTypeOptions,
+ interestCalculationDaysInYearTypeOptions,
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, transactions,
+ charges, chargeOptions);
+ }
+
+ final List<DatatableData> datatableTemplates =
this.entityDatatableChecksReadService.retrieveTemplates(StatusEnum.CREATE.getValue(),
+ EntityTables.SAVINGS.getName(), productId);
+ template.setDatatables(datatableTemplates);
+
+ return template;
+ }
+
+ private static final class SavingAccountTemplateMapper implements
RowMapper<SavingsAccountData> {
+
+ private final ClientData client;
+ private final GroupGeneralData group;
+
+ private final String schemaSql;
+
+ SavingAccountTemplateMapper(final ClientData client, final
GroupGeneralData group) {
+ this.client = client;
+ this.group = group;
+
+ final StringBuilder sqlBuilder = new StringBuilder(400);
+ sqlBuilder.append("sp.id as productId, sp.name as productName, ");
+ sqlBuilder.append(
+ "sp.currency_code as currencyCode, sp.currency_digits as
currencyDigits, sp.currency_multiplesof as inMultiplesOf, ");
+ sqlBuilder.append("curr.name as currencyName,
curr.internationalized_name_code as currencyNameCode, ");
+ sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol,
");
+ sqlBuilder.append("sp.nominal_annual_interest_rate as
nominalAnnualIterestRate, ");
+ sqlBuilder.append("sp.interest_compounding_period_enum as
interestCompoundingPeriodType, ");
+ sqlBuilder.append("sp.interest_posting_period_enum as
interestPostingPeriodType, ");
+ sqlBuilder.append("sp.interest_calculation_type_enum as
interestCalculationType, ");
+ sqlBuilder.append("sp.interest_calculation_days_in_year_type_enum
as interestCalculationDaysInYearType, ");
+ sqlBuilder.append("sp.min_required_opening_balance as
minRequiredOpeningBalance, ");
+ sqlBuilder.append("sp.lockin_period_frequency as
lockinPeriodFrequency,");
+ sqlBuilder.append("sp.lockin_period_frequency_enum as
lockinPeriodFrequencyType, ");
+ // sqlBuilder.append("sp.withdrawal_fee_amount as
+ // withdrawalFeeAmount,");
+ // sqlBuilder.append("sp.withdrawal_fee_type_enum as
+ // withdrawalFeeTypeEnum, ");
+ sqlBuilder.append("sp.withdrawal_fee_for_transfer as
withdrawalFeeForTransfers, ");
+ sqlBuilder.append("sp.min_balance_for_interest_calculation as
minBalanceForInterestCalculation, ");
+ sqlBuilder.append("sp.allow_overdraft as allowOverdraft, ");
+ sqlBuilder.append("sp.overdraft_limit as overdraftLimit, ");
+ sqlBuilder.append("sp.nominal_annual_interest_rate_overdraft as
nominalAnnualInterestRateOverdraft, ");
+ sqlBuilder.append("sp.min_overdraft_for_interest_calculation as
minOverdraftForInterestCalculation, ");
+ sqlBuilder.append("sp.withhold_tax as withHoldTax,");
+ sqlBuilder.append("tg.id as taxGroupId, tg.name as taxGroupName,
");
+
+ // sqlBuilder.append("sp.annual_fee_amount as annualFeeAmount,");
+ // sqlBuilder.append("sp.annual_fee_on_month as annualFeeOnMonth,
+ // ");
+ // sqlBuilder.append("sp.annual_fee_on_day as annualFeeOnDay ");
+ sqlBuilder.append("sp.min_required_balance as minRequiredBalance,
");
+ sqlBuilder.append("sp.enforce_min_required_balance as
enforceMinRequiredBalance, ");
+ sqlBuilder.append("sp.max_allowed_lien_limit as
maxAllowedLienLimit, ");
+ sqlBuilder.append("sp.is_lien_allowed as lienAllowed ");
+ sqlBuilder.append("from m_savings_product sp ");
+ sqlBuilder.append("join m_currency curr on curr.code =
sp.currency_code ");
+ sqlBuilder.append("left join m_tax_group tg on tg.id =
sp.tax_group_id ");
+
+ this.schemaSql = sqlBuilder.toString();
+ }
+
+ public String schema() {
+ return this.schemaSql;
+ }
+
+ @Override
+ public SavingsAccountData mapRow(final ResultSet rs,
@SuppressWarnings("unused") final int rowNum) throws SQLException {
+
+ final Long productId = rs.getLong("productId");
+ final String productName = rs.getString("productName");
+
+ final String currencyCode = rs.getString("currencyCode");
+ final String currencyName = rs.getString("currencyName");
+ final String currencyNameCode = rs.getString("currencyNameCode");
+ final String currencyDisplaySymbol =
rs.getString("currencyDisplaySymbol");
+ final Integer currencyDigits = JdbcSupport.getInteger(rs,
"currencyDigits");
+ final Integer inMultiplesOf = JdbcSupport.getInteger(rs,
"inMultiplesOf");
+ final CurrencyData currency = new CurrencyData(currencyCode,
currencyName, currencyDigits, inMultiplesOf, currencyDisplaySymbol,
+ currencyNameCode);
+
+ final BigDecimal nominalAnnualIterestRate =
rs.getBigDecimal("nominalAnnualIterestRate");
+
+ final EnumOptionData interestCompoundingPeriodType =
SavingsEnumerations.compoundingInterestPeriodType(
+
SavingsCompoundingInterestPeriodType.fromInt(JdbcSupport.getInteger(rs,
"interestCompoundingPeriodType")));
+
+ final EnumOptionData interestPostingPeriodType =
SavingsEnumerations.interestPostingPeriodType(
+
SavingsPostingInterestPeriodType.fromInt(JdbcSupport.getInteger(rs,
"interestPostingPeriodType")));
+
+ final EnumOptionData interestCalculationType = SavingsEnumerations
+
.interestCalculationType(SavingsInterestCalculationType.fromInt(JdbcSupport.getInteger(rs,
"interestCalculationType")));
+
+ final EnumOptionData interestCalculationDaysInYearType =
SavingsEnumerations.interestCalculationDaysInYearType(
+
SavingsInterestCalculationDaysInYearType.fromInt(JdbcSupport.getInteger(rs,
"interestCalculationDaysInYearType")));
+
+ final BigDecimal minRequiredOpeningBalance =
JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "minRequiredOpeningBalance");
+
+ final Integer lockinPeriodFrequency = JdbcSupport.getInteger(rs,
"lockinPeriodFrequency");
+ EnumOptionData lockinPeriodFrequencyType = null;
+ final Integer lockinPeriodFrequencyTypeValue =
JdbcSupport.getInteger(rs, "lockinPeriodFrequencyType");
+ if (lockinPeriodFrequencyTypeValue != null) {
+ final SavingsPeriodFrequencyType lockinPeriodType =
SavingsPeriodFrequencyType.fromInt(lockinPeriodFrequencyTypeValue);
+ lockinPeriodFrequencyType =
SavingsEnumerations.lockinPeriodFrequencyType(lockinPeriodType);
+ }
+
+ // final BigDecimal withdrawalFeeAmount =
+ // rs.getBigDecimal("withdrawalFeeAmount");
+
+ /*
+ * EnumOptionData withdrawalFeeType = null; final Integer
withdrawalFeeTypeValue =
+ * JdbcSupport.getInteger(rs, "withdrawalFeeTypeEnum"); if
(withdrawalFeeTypeValue != null) {
+ * withdrawalFeeType =
SavingsEnumerations.withdrawalFeeType(withdrawalFeeTypeValue); }
+ */
+ final boolean withdrawalFeeForTransfers =
rs.getBoolean("withdrawalFeeForTransfers");
+
+ final boolean allowOverdraft = rs.getBoolean("allowOverdraft");
+ final BigDecimal overdraftLimit =
JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "overdraftLimit");
+ final BigDecimal nominalAnnualInterestRateOverdraft =
JdbcSupport.getBigDecimalDefaultToNullIfZero(rs,
+ "nominalAnnualInterestRateOverdraft");
+ final BigDecimal minOverdraftForInterestCalculation =
JdbcSupport.getBigDecimalDefaultToNullIfZero(rs,
+ "minOverdraftForInterestCalculation");
+
+ final BigDecimal minRequiredBalance =
JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "minRequiredBalance");
+ final boolean enforceMinRequiredBalance =
rs.getBoolean("enforceMinRequiredBalance");
+ final BigDecimal maxAllowedLienLimit =
JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "maxAllowedLienLimit");
+ final boolean lienAllowed = rs.getBoolean("lienAllowed");
+ final BigDecimal minBalanceForInterestCalculation =
JdbcSupport.getBigDecimalDefaultToNullIfZero(rs,
+ "minBalanceForInterestCalculation");
+
+ // final BigDecimal annualFeeAmount =
+ // JdbcSupport.getBigDecimalDefaultToNullIfZero(rs,
+ // "annualFeeAmount");
+
+ /*
+ * MonthDay annualFeeOnMonthDay = null; final Integer
annualFeeOnMonth = JdbcSupport.getInteger(rs,
+ * "annualFeeOnMonth"); final Integer annualFeeOnDay =
JdbcSupport.getInteger(rs, "annualFeeOnDay"); if
+ * (annualFeeAmount != null && annualFeeOnDay != null) {
annualFeeOnMonthDay = new
+ * MonthDay(annualFeeOnMonth, annualFeeOnDay); }
+ */
+
+ final boolean withHoldTax = rs.getBoolean("withHoldTax");
+ final Long taxGroupId = JdbcSupport.getLong(rs, "taxGroupId");
+ final String taxGroupName = rs.getString("taxGroupName");
+ TaxGroupData taxGroupData = null;
+ if (taxGroupId != null) {
+ taxGroupData = TaxGroupData.lookup(taxGroupId, taxGroupName);
+ }
+
+ Long clientId = null;
+ String clientName = null;
+ if (this.client != null) {
+ clientId = this.client.getId();
+ clientName = this.client.getDisplayName();
+ }
+
+ Long groupId = null;
+ String groupName = null;
+ if (this.group != null) {
+ groupId = this.group.getId();
+ groupName = this.group.getName();
+ }
+
+ final Long fieldOfficerId = null;
+ final String fieldOfficerName = null;
+ final SavingsAccountStatusEnumData status = null;
+ // final LocalDate annualFeeNextDueDate = null;
+ final SavingsAccountSummaryData summary = null;
+ final BigDecimal onHoldFunds = null;
+ final BigDecimal savingsAmountOnHold = null;
+
+ final SavingsAccountSubStatusEnumData subStatus = null;
+ final String reasonForBlock = null;
+ final LocalDate lastActiveTransactionDate = null;
+ final boolean isDormancyTrackingActive = false;
+ final Integer daysToInactive = null;
+ final Integer daysToDormancy = null;
+ final Integer daysToEscheat = null;
+
+ final SavingsAccountApplicationTimelineData timeline =
SavingsAccountApplicationTimelineData.templateDefault();
+ final EnumOptionData depositType = null;
+ return SavingsAccountData.instance(null, null, depositType, null,
groupId, groupName, clientId, clientName, productId,
+ productName, fieldOfficerId, fieldOfficerName, status,
subStatus, reasonForBlock, timeline, currency,
+ nominalAnnualIterestRate, interestCompoundingPeriodType,
interestPostingPeriodType, interestCalculationType,
+ interestCalculationDaysInYearType,
minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
+ withdrawalFeeForTransfers, summary, allowOverdraft,
overdraftLimit, minRequiredBalance, enforceMinRequiredBalance,
+ maxAllowedLienLimit, lienAllowed,
minBalanceForInterestCalculation, onHoldFunds,
nominalAnnualInterestRateOverdraft,
+ minOverdraftForInterestCalculation, withHoldTax,
taxGroupData, lastActiveTransactionDate, isDormancyTrackingActive,
+ daysToInactive, daysToDormancy, daysToEscheat,
savingsAmountOnHold);
+ }
+ }
+
+ private Collection<SavingsAccountChargeData>
fromChargesToSavingsCharges(final Collection<ChargeData> productCharges) {
+ final Collection<SavingsAccountChargeData> savingsCharges = new
ArrayList<>();
+ for (final ChargeData chargeData : productCharges) {
+ final SavingsAccountChargeData savingsCharge =
ConvertChargeDataToSpecificChargeData.toSavingsAccountChargeData(chargeData);
+ savingsCharges.add(savingsCharge);
+ }
+ return savingsCharges;
+ }
+
+}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/starter/SavingsConfiguration.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/starter/SavingsConfiguration.java
index c81ab4eefe..19578d472c 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/starter/SavingsConfiguration.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/starter/SavingsConfiguration.java
@@ -124,6 +124,8 @@ import
org.apache.fineract.portfolio.savings.service.SavingsAccountInterestPosti
import
org.apache.fineract.portfolio.savings.service.SavingsAccountInterestPostingServiceImpl;
import
org.apache.fineract.portfolio.savings.service.SavingsAccountReadPlatformService;
import
org.apache.fineract.portfolio.savings.service.SavingsAccountReadPlatformServiceImpl;
+import
org.apache.fineract.portfolio.savings.service.SavingsAccountTemplateReadPlatformService;
+import
org.apache.fineract.portfolio.savings.service.SavingsAccountTemplateReadPlatformServiceImpl;
import
org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformService;
import
org.apache.fineract.portfolio.savings.service.SavingsAccountWritePlatformServiceJpaRepositoryImpl;
import
org.apache.fineract.portfolio.savings.service.SavingsApplicationProcessWritePlatformService;
@@ -335,16 +337,23 @@ public class SavingsConfiguration {
@Bean
@ConditionalOnMissingBean(SavingsAccountReadPlatformService.class)
public SavingsAccountReadPlatformService
savingsAccountReadPlatformService(PlatformSecurityContext context, JdbcTemplate
jdbcTemplate,
- ClientReadPlatformService clientReadPlatformService,
GroupReadPlatformService groupReadPlatformService,
- SavingsProductReadPlatformService
savingProductReadPlatformService, StaffReadPlatformService
staffReadPlatformService,
- SavingsDropdownReadPlatformService dropdownReadPlatformService,
ChargeReadPlatformService chargeReadPlatformService,
- EntityDatatableChecksReadService entityDatatableChecksReadService,
ColumnValidator columnValidator,
SavingsAccountAssembler savingAccountAssembler, PaginationHelper
paginationHelper, DatabaseSpecificSQLGenerator sqlGenerator,
- SavingsAccountRepositoryWrapper savingsAccountRepositoryWrapper) {
- return new SavingsAccountReadPlatformServiceImpl(context,
jdbcTemplate, clientReadPlatformService, groupReadPlatformService,
+ SavingsAccountRepositoryWrapper savingsAccountRepositoryWrapper,
ColumnValidator columnValidator) {
+ return new SavingsAccountReadPlatformServiceImpl(context,
jdbcTemplate, savingAccountAssembler, paginationHelper, columnValidator,
+ sqlGenerator, savingsAccountRepositoryWrapper);
+ }
+
+ @Bean
+ @ConditionalOnMissingBean(SavingsAccountTemplateReadPlatformService.class)
+ public SavingsAccountTemplateReadPlatformService
savingsAccountTemplateReadPlatformService(PlatformSecurityContext context,
+ JdbcTemplate jdbcTemplate, ClientReadPlatformService
clientReadPlatformService,
+ GroupReadPlatformService groupReadPlatformService,
SavingsProductReadPlatformService savingProductReadPlatformService,
+ StaffReadPlatformService staffReadPlatformService,
SavingsDropdownReadPlatformService dropdownReadPlatformService,
+ ChargeReadPlatformService chargeReadPlatformService,
EntityDatatableChecksReadService entityDatatableChecksReadService,
+ ColumnValidator columnValidator) {
+ return new SavingsAccountTemplateReadPlatformServiceImpl(context,
jdbcTemplate, clientReadPlatformService, groupReadPlatformService,
savingProductReadPlatformService, staffReadPlatformService,
dropdownReadPlatformService, chargeReadPlatformService,
- entityDatatableChecksReadService, columnValidator,
savingAccountAssembler, paginationHelper, sqlGenerator,
- savingsAccountRepositoryWrapper);
+ entityDatatableChecksReadService, columnValidator);
}
@Bean
diff --git
a/fineract-provider/src/test/java/org/apache/fineract/infrastructure/dataqueries/service/DatatableBusinessEventTest.java
b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/dataqueries/service/DatatableBusinessEventTest.java
new file mode 100644
index 0000000000..13171e7d77
--- /dev/null
+++
b/fineract-provider/src/test/java/org/apache/fineract/infrastructure/dataqueries/service/DatatableBusinessEventTest.java
@@ -0,0 +1,207 @@
+/**
+ * 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.infrastructure.dataqueries.service;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.fineract.infrastructure.businessdate.domain.BusinessDateType;
+import
org.apache.fineract.infrastructure.codes.service.CodeReadPlatformService;
+import
org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
+import org.apache.fineract.infrastructure.core.api.JsonCommand;
+import org.apache.fineract.infrastructure.core.domain.ActionContext;
+import org.apache.fineract.infrastructure.core.domain.FineractPlatformTenant;
+import
org.apache.fineract.infrastructure.core.domain.FineractPlatformTenantConnection;
+import
org.apache.fineract.infrastructure.core.serialization.DatatableCommandFromApiJsonDeserializer;
+import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
+import org.apache.fineract.infrastructure.core.service.ThreadLocalContextUtil;
+import
org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
+import
org.apache.fineract.infrastructure.core.service.database.DatabaseTypeResolver;
+import org.apache.fineract.infrastructure.dataqueries.data.DataTableValidator;
+import org.apache.fineract.infrastructure.dataqueries.data.ResultsetRowData;
+import org.apache.fineract.infrastructure.event.business.domain.BusinessEvent;
+import
org.apache.fineract.infrastructure.event.business.domain.datatable.DatatableEntryBusinessEvent;
+import
org.apache.fineract.infrastructure.event.business.service.BusinessEventNotifierService;
+import
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import org.apache.fineract.infrastructure.security.utils.ColumnValidator;
+import org.apache.fineract.infrastructure.security.utils.DefaultSqlValidator;
+import org.apache.fineract.organisation.office.domain.Office;
+import org.apache.fineract.portfolio.search.service.SearchUtil;
+import org.apache.fineract.useradministration.domain.AppUser;
+import org.jetbrains.annotations.NotNull;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.jupiter.MockitoExtension;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.PreparedStatementCreator;
+import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
+import org.springframework.jdbc.support.KeyHolder;
+import org.springframework.jdbc.support.rowset.SqlRowSet;
+
+@ExtendWith(MockitoExtension.class)
+public class DatatableBusinessEventTest {
+
+ @Mock
+ private PlatformSecurityContext context;
+ @Mock
+ private BusinessEventNotifierService businessEventNotifierService;
+ @Mock
+ private JdbcTemplate jdbcTemplate;
+ @Mock
+ private GenericDataService genericDataService;
+ @Mock
+ private SearchUtil searchUtil;
+ @Mock
+ private DatabaseTypeResolver databaseTypeResolver;
+ @Mock
+ private DatabaseSpecificSQLGenerator sqlGenerator;
+ @Mock
+ private FineractPlatformTenantConnection tenantConnection;
+ @Mock
+ private DefaultSqlValidator sqlValidator;
+ @Mock
+ private FromJsonHelper fromJsonHelper;
+ @Mock
+ private DatatableCommandFromApiJsonDeserializer fromApiJsonDeserializer;
+ @Mock
+ private ConfigurationDomainService configurationDomainService;
+ @Mock
+ private CodeReadPlatformService codeReadPlatformService;
+ @Mock
+ private DataTableValidator dataTableValidator;
+ @Mock
+ private ColumnValidator columnValidator;
+ @Mock
+ private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
+ @Mock
+ private DatatableKeywordGenerator datatableKeywordGenerator;
+
+ @InjectMocks
+ private ReadWriteNonCoreDataServiceImpl underTest;
+
+ @Captor
+ private ArgumentCaptor<BusinessEvent<?>> businessEventArgumentCaptor;
+
+ private static String DATATABLE_NAME = "test_loan_data";
+
+ @BeforeEach
+ public void setUp() {
+ ThreadLocalContextUtil.setTenant(new FineractPlatformTenant(1L,
"default", "Default", "Asia/Kolkata", null));
+ ThreadLocalContextUtil.setActionContext(ActionContext.DEFAULT);
+ ThreadLocalContextUtil.setBusinessDates(new
HashMap<>(Map.of(BusinessDateType.BUSINESS_DATE, LocalDate.parse("2024-01-16"),
+ BusinessDateType.COB_DATE, LocalDate.parse("2024-01-15"))));
+
+ SqlRowSet sqlRS = Mockito.mock(SqlRowSet.class);
+ SqlRowSet sqlRSData = Mockito.mock(SqlRowSet.class);
+ doNothing().when(sqlValidator).validate(anyString());
+ when(jdbcTemplate.queryForRowSet(anyString(),
anyString())).thenReturn(sqlRS);
+ when(jdbcTemplate.queryForRowSet(anyString())).thenReturn(sqlRSData);
+
+ when(sqlRS.next()).thenReturn(true).thenReturn(false);
+ when(sqlRS.getString("application_table_name")).thenReturn("m_loan");
+ when(sqlRSData.next()).thenReturn(true).thenReturn(false);
+ when(sqlRSData.getObject(anyString())).thenReturn(1L);
+
+ AppUser currentUser = Mockito.mock(AppUser.class);
+ Office office = Mockito.mock(Office.class);
+ when(context.authenticatedUser()).thenReturn(currentUser);
+ when(currentUser.getOffice()).thenReturn(office);
+ when(office.getHierarchy()).thenReturn(".");
+ }
+
+ @AfterEach
+ public void tearDown() {
+ ThreadLocalContextUtil.reset();
+ }
+
+ @Test
+ public void businessEventCreateNewDatatableEntryTest() {
+ when(jdbcTemplate.update(any(PreparedStatementCreator.class),
any(KeyHolder.class))).thenReturn(1);
+
+ underTest.createNewDatatableEntry(DATATABLE_NAME, 1L,
createJsonCommand("{}", 1L));
+
+ ArgumentCaptor<BusinessEvent<?>> businessEventArgumentCaptor =
verifyBusinessEvents(1);
+ verifyDatatableBusinessEvent(businessEventArgumentCaptor, 0, 1L);
+ }
+
+ @Test
+ public void businessEventUpdateDatatableEntryTest() {
+ List<Object> values = new ArrayList<>();
+ values.add(1L);
+ List<ResultsetRowData> result = new ArrayList<>();
+ result.add(ResultsetRowData.create(values));
+ when(genericDataService.fillResultsetRowData(anyString(),
any())).thenReturn(result);
+
+ // ResultsetColumnHeaderData resultSet =
Mockito.mock(ResultsetColumnHeaderData.class);
+ // when(searchUtil.getFiltered(columnHeaders,
+ //
ResultsetColumnHeaderData::getIsColumnPrimaryKey)).thenReturn(resultSet);
+
+ underTest.updateDatatableEntryOneToMany(DATATABLE_NAME, 1L, 1L,
createJsonCommand("{}", 1L));
+
+ ArgumentCaptor<BusinessEvent<?>> businessEventArgumentCaptor =
verifyBusinessEvents(1);
+ verifyDatatableBusinessEvent(businessEventArgumentCaptor, 0, 1L);
+ }
+
+ @Test
+ public void businessEventDeleteDatatableEntryTest() {
+
+ underTest.deleteDatatableEntry(DATATABLE_NAME, 1L, 1L,
createJsonCommand("{}", 1L));
+
+ ArgumentCaptor<BusinessEvent<?>> businessEventArgumentCaptor =
verifyBusinessEvents(1);
+ verifyDatatableBusinessEvent(businessEventArgumentCaptor, 0, 1L);
+ }
+
+ @NotNull
+ private ArgumentCaptor<BusinessEvent<?>> verifyBusinessEvents(int
expectedBusinessEvents) {
+ @SuppressWarnings("unchecked")
+ ArgumentCaptor<BusinessEvent<?>> businessEventArgumentCaptor =
ArgumentCaptor.forClass(BusinessEvent.class);
+ verify(businessEventNotifierService,
times(expectedBusinessEvents)).notifyPostBusinessEvent(businessEventArgumentCaptor.capture());
+ return businessEventArgumentCaptor;
+ }
+
+ private void verifyDatatableBusinessEvent(ArgumentCaptor<BusinessEvent<?>>
businessEventArgumentCaptor, int index, Long entityId) {
+ assertTrue(businessEventArgumentCaptor.getAllValues().get(index)
instanceof DatatableEntryBusinessEvent);
+ assertEquals(DATATABLE_NAME, ((DatatableEntryBusinessEvent)
businessEventArgumentCaptor.getAllValues().get(index))
+ .getDatatableEntryDetails().getDatatableName());
+ assertEquals(entityId, ((DatatableEntryBusinessEvent)
businessEventArgumentCaptor.getAllValues().get(index)).getAggregateRootId());
+ }
+
+ private JsonCommand createJsonCommand(final String jsonCommand, final Long
resourceId) {
+ return new JsonCommand(null, jsonCommand, null, null, null,
resourceId, null, null, null, null, null, null, null, null, null, null,
+ null, null);
+ }
+}
diff --git
a/fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformService.java
b/fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformService.java
index 4a39f44540..dc36728b53 100644
---
a/fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformService.java
+++
b/fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountReadPlatformService.java
@@ -40,8 +40,6 @@ public interface SavingsAccountReadPlatformService {
SavingsAccountData retrieveOne(Long savingsId);
- SavingsAccountData retrieveTemplate(Long clientId, Long groupId, Long
productId, boolean staffInSelectedOfficeOnly);
-
SavingsAccountTransactionData retrieveDepositTransactionTemplate(Long
savingsId, DepositAccountType depositAccountType);
Collection<SavingsAccountTransactionData> retrieveAllTransactions(Long
savingsId, DepositAccountType depositAccountType);
diff --git
a/fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountTemplateReadPlatformService.java
b/fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountTemplateReadPlatformService.java
new file mode 100644
index 0000000000..d0f6233bef
--- /dev/null
+++
b/fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsAccountTemplateReadPlatformService.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.portfolio.savings.service;
+
+import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
+
+public interface SavingsAccountTemplateReadPlatformService {
+
+ SavingsAccountData retrieveTemplate(Long clientId, Long groupId, Long
productId, boolean staffInSelectedOfficeOnly);
+
+}