Merge remote-tracking branch 'origin/dev' into uate
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-1) (push) Canceled after 0s
Fineract Docker Builds / build (true, docker-compose.yml, mariadb) (push) Canceled after 0s
Fineract Liquibase Only mode - PostgreSQL / test (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-5) (push) Canceled after 0s
Fineract Docker Builds / build (false, docker-compose-postgresql.yml, postgresql) (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with ActiveMQ (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with Kafka (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, build-core) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, cucumber) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (progressive-loan, build-progressive-loan) (push) Canceled after 0s
Fineract Documentation build / build (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 1 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 10 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 3 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 4 of 10) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-1) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 2 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 5 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 6 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 7 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 8 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 9 of 10) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-1) (push) Canceled after 0s
Fineract Docker Builds / build (true, docker-compose.yml, mariadb) (push) Canceled after 0s
Fineract Liquibase Only mode - PostgreSQL / test (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-5) (push) Canceled after 0s
Fineract Docker Builds / build (false, docker-compose-postgresql.yml, postgresql) (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with ActiveMQ (push) Canceled after 0s
Fineract Messaging Smoke Tests / Smoke Test with Kafka (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, build-core) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (main, cucumber) (push) Canceled after 0s
Fineract Build & Cucumber tests (without E2E tests) / verify (progressive-loan, build-progressive-loan) (push) Canceled after 0s
Fineract Documentation build / build (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 1 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 10 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 3 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 4 of 10) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-1) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 2 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 5 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 6 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 7 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 8 of 10) (push) Canceled after 0s
Fineract E2E Tests / E2E Tests (Shard 9 of 10) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MariaDB / test (test-core-5) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-2) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-3) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - MySQL / test (test-core-5) (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
const https = require('https');
|
||||
const agent = new https.Agent({ rejectUnauthorized: false });
|
||||
|
||||
fetch('https://localhost:8443/fineract-provider/api/v1/authentication?username=mifos&password=password&tenantIdentifier=default', {
|
||||
method: 'POST',
|
||||
agent: agent
|
||||
}).then(res => res.json()).then(data => {
|
||||
const token = data.base64EncodedAuthenticationKey;
|
||||
return fetch('https://localhost:8443/fineract-provider/api/v1/clients/9/accounts?tenantIdentifier=default', {
|
||||
headers: {
|
||||
'Authorization': 'Basic ' + token,
|
||||
'Fineract-Platform-TenantId': 'default'
|
||||
},
|
||||
agent: agent
|
||||
});
|
||||
}).then(res => res.json()).then(data => {
|
||||
console.log(JSON.stringify(data, null, 2));
|
||||
}).catch(console.error);
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
package org.apache.fineract.portfolio.shareaccounts.api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.QueryParam;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import java.util.Collection;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountClientSummaryData;
|
||||
import org.apache.fineract.portfolio.shareaccounts.service.ShareAccountReadPlatformService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Path("/v1/shareaccounts/summary")
|
||||
@Component
|
||||
@Tag(name = "Share Account Summary", description = "Provides a highly optimized summary of all share accounts linked with their respective clients.")
|
||||
@RequiredArgsConstructor
|
||||
public class ShareAccountSummaryApiResource {
|
||||
|
||||
private final PlatformSecurityContext platformSecurityContext;
|
||||
private final ShareAccountReadPlatformService shareAccountReadPlatformService;
|
||||
|
||||
@GET
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "List all share accounts with client details", description = "Retrieves all share accounts along with their associated client details in a single optimized query.\n\n"
|
||||
+ "Example Requests:\n\n" + "shareaccounts/summary")
|
||||
@ApiResponse(responseCode = "200", description = "OK")
|
||||
public Collection<ShareAccountClientSummaryData> retrieveAllSummaries(@QueryParam("searchTerm") final String searchTerm) {
|
||||
long start = System.currentTimeMillis();
|
||||
System.out.println("[TIMING] Start of retrieveAllSummaries (before auth)");
|
||||
this.platformSecurityContext.authenticatedUser();
|
||||
long afterAuth = System.currentTimeMillis();
|
||||
System.out.println("[TIMING] Auth check: " + (afterAuth - start) + "ms");
|
||||
Collection<ShareAccountClientSummaryData> result = this.shareAccountReadPlatformService.retrieveAllShareAccountClientSummaries(searchTerm);
|
||||
long afterService = System.currentTimeMillis();
|
||||
System.out.println("[TIMING] Service call total (including query): " + (afterService - afterAuth) + "ms");
|
||||
System.out.println("[TIMING] Right before response returned: " + (System.currentTimeMillis() - start) + "ms total so far");
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
package org.apache.fineract.portfolio.shareaccounts.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import lombok.Getter;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountStatusEnumData;
|
||||
|
||||
@Getter
|
||||
public class ShareAccountClientSummaryData implements Serializable {
|
||||
|
||||
private final Long id;
|
||||
private final Long clientId;
|
||||
private final String clientName;
|
||||
private final Long officeId;
|
||||
private final String officeName;
|
||||
private final String accountNo;
|
||||
private final Long productId;
|
||||
private final String productName;
|
||||
private final Long totalApprovedShares;
|
||||
private final Long totalPendingForApprovalShares;
|
||||
private final CurrencyData currency;
|
||||
private final LocalDate activatedDate;
|
||||
private final ShareAccountStatusEnumData status;
|
||||
|
||||
public ShareAccountClientSummaryData(final Long id, final Long clientId, final String clientName, final Long officeId, final String officeName, final String accountNo,
|
||||
final Long productId, final String productName, final Long totalApprovedShares, final Long totalPendingForApprovalShares,
|
||||
final CurrencyData currency, final LocalDate activatedDate, final ShareAccountStatusEnumData status) {
|
||||
this.id = id;
|
||||
this.clientId = clientId;
|
||||
this.clientName = clientName;
|
||||
this.officeId = officeId;
|
||||
this.officeName = officeName;
|
||||
this.accountNo = accountNo;
|
||||
this.productId = productId;
|
||||
this.productName = productName;
|
||||
|
||||
if (totalApprovedShares == null) {
|
||||
this.totalApprovedShares = Long.valueOf(0);
|
||||
} else {
|
||||
this.totalApprovedShares = totalApprovedShares;
|
||||
}
|
||||
|
||||
if (totalPendingForApprovalShares == null) {
|
||||
this.totalPendingForApprovalShares = Long.valueOf(0);
|
||||
} else {
|
||||
this.totalPendingForApprovalShares = totalPendingForApprovalShares;
|
||||
}
|
||||
|
||||
this.currency = currency;
|
||||
this.activatedDate = activatedDate;
|
||||
this.status = status;
|
||||
}
|
||||
}
|
||||
+3
@@ -23,6 +23,7 @@ import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import org.apache.fineract.portfolio.accounts.service.AccountReadPlatformService;
|
||||
import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountData;
|
||||
import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountClientSummaryData;
|
||||
|
||||
public interface ShareAccountReadPlatformService extends AccountReadPlatformService {
|
||||
|
||||
@@ -38,5 +39,7 @@ public interface ShareAccountReadPlatformService extends AccountReadPlatformServ
|
||||
Collection<ShareAccountData> retrieveAllShareAccountDataForDividends(Long productId, boolean fetchInActiveAccounts,
|
||||
LocalDate startDate);
|
||||
|
||||
Collection<ShareAccountClientSummaryData> retrieveAllShareAccountClientSummaries(String searchTerm);
|
||||
|
||||
String retrieveAccountNumberByAccountId(Long accountId);
|
||||
}
|
||||
|
||||
+81
@@ -62,6 +62,7 @@ import org.apache.fineract.portfolio.shareaccounts.domain.ShareAccountStatusType
|
||||
import org.apache.fineract.portfolio.shareproducts.data.ShareProductData;
|
||||
import org.apache.fineract.portfolio.shareproducts.data.ShareProductMarketPriceData;
|
||||
import org.apache.fineract.portfolio.shareproducts.service.ShareProductDropdownReadPlatformService;
|
||||
import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountClientSummaryData;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
@@ -221,6 +222,29 @@ public class ShareAccountReadPlatformServiceImpl implements ShareAccountReadPlat
|
||||
}, mapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ShareAccountClientSummaryData> retrieveAllShareAccountClientSummaries(String searchTerm) {
|
||||
long start = System.currentTimeMillis();
|
||||
System.out.println("[TIMING] Inside retrieveAllShareAccountClientSummaries, before query builder setup");
|
||||
ShareAccountClientSummaryMapper mapper = new ShareAccountClientSummaryMapper();
|
||||
StringBuilder queryBuilder = new StringBuilder("select ").append(mapper.schema());
|
||||
List<Object> paramList = new ArrayList<>();
|
||||
|
||||
if (searchTerm != null && !searchTerm.trim().isEmpty()) {
|
||||
queryBuilder.append(" where (c.display_name ILIKE ? OR sa.account_no ILIKE ?)");
|
||||
String searchPattern = "%" + searchTerm + "%";
|
||||
paramList.add(searchPattern);
|
||||
paramList.add(searchPattern);
|
||||
}
|
||||
|
||||
long beforeQuery = System.currentTimeMillis();
|
||||
System.out.println("[TIMING] Before actual SQL query call. Time since service start: " + (beforeQuery - start) + "ms");
|
||||
Collection<ShareAccountClientSummaryData> result = this.jdbcTemplate.query(queryBuilder.toString(), mapper, paramList.toArray());
|
||||
long afterQuery = System.currentTimeMillis();
|
||||
System.out.println("[TIMING] Query execution (JdbcTemplate): " + (afterQuery - beforeQuery) + "ms");
|
||||
return result;
|
||||
}
|
||||
|
||||
public Collection<ShareAccountChargeData> convertChargesToShareAccountCharges(Collection<ChargeData> productCharges) {
|
||||
final Collection<ShareAccountChargeData> savingsCharges = new ArrayList<>();
|
||||
for (final ChargeData chargeData : productCharges) {
|
||||
@@ -495,6 +519,63 @@ public class ShareAccountReadPlatformServiceImpl implements ShareAccountReadPlat
|
||||
}
|
||||
}
|
||||
|
||||
private static final class ShareAccountClientSummaryMapper implements RowMapper<ShareAccountClientSummaryData> {
|
||||
|
||||
private final String schema;
|
||||
|
||||
ShareAccountClientSummaryMapper() {
|
||||
StringBuilder buff = new StringBuilder().append("sa.id as id, c.id as clientId, c.display_name as clientName, ")
|
||||
.append("sa.account_no as accountNo, p.id as productId, p.name as productName, ")
|
||||
.append("sa.total_approved_shares as approvedShares, sa.total_pending_shares as pendingShares, ")
|
||||
.append("sa.currency_code as currencyCode, sa.currency_digits as currencyDigits, sa.currency_multiplesof as inMultiplesOf, ")
|
||||
.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ")
|
||||
.append("curr.display_symbol as currencyDisplaySymbol, sa.activated_date as activatedDate, ")
|
||||
.append("sa.status_enum as statusEnum, o.id as officeId, o.name as officeName ")
|
||||
.append("from m_share_account sa ")
|
||||
.append("inner join m_client c ON c.id = sa.client_id ")
|
||||
.append("inner join m_office o ON o.id = c.office_id ")
|
||||
.append("inner join m_share_product p on p.id = sa.product_id ")
|
||||
.append("inner join m_currency curr on curr.code = sa.currency_code");
|
||||
this.schema = buff.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ShareAccountClientSummaryData mapRow(ResultSet rs, @SuppressWarnings("unused") int rowNum) throws SQLException {
|
||||
final Long id = rs.getLong("id");
|
||||
final Long clientId = rs.getLong("clientId");
|
||||
final String clientName = rs.getString("clientName");
|
||||
final String accountNo = rs.getString("accountNo");
|
||||
final Long productId = rs.getLong("productId");
|
||||
final String productName = rs.getString("productName");
|
||||
final Long totalApprovedShares = JdbcSupport.getLong(rs, "approvedShares");
|
||||
final Long totalPendingForApprovalShares = JdbcSupport.getLong(rs, "pendingShares");
|
||||
|
||||
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 LocalDate activatedDate = JdbcSupport.getLocalDate(rs, "activatedDate");
|
||||
|
||||
final Integer statusEnum = rs.getInt("statusEnum");
|
||||
final ShareAccountStatusEnumData status = SharesEnumerations.status(statusEnum);
|
||||
|
||||
final Long officeId = rs.getLong("officeId");
|
||||
final String officeName = rs.getString("officeName");
|
||||
|
||||
return new ShareAccountClientSummaryData(id, clientId, clientName, officeId, officeName, accountNo, productId, productName,
|
||||
totalApprovedShares, totalPendingForApprovalShares, currency, activatedDate, status);
|
||||
}
|
||||
|
||||
public String schema() {
|
||||
return this.schema;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String retrieveAccountNumberByAccountId(Long accountId) {
|
||||
try {
|
||||
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* 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.welcomekit.api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.welcomekit.data.ClientWelcomeKitData;
|
||||
import org.apache.fineract.portfolio.welcomekit.service.WelcomeKitReadPlatformService;
|
||||
import org.apache.fineract.portfolio.welcomekit.service.WelcomeKitWritePlatformService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Path("/v1/clients/{clientId}/welcomekit")
|
||||
@Component
|
||||
@Tag(name = "Welcome Kit Dispatch", description = "Manages the dispatching and tracking of welcome kits for clients.")
|
||||
@RequiredArgsConstructor
|
||||
public class ClientWelcomeKitApiResource {
|
||||
|
||||
private static final String RESOURCE_NAME_FOR_PERMISSIONS = "WELCOMEKIT";
|
||||
private final PlatformSecurityContext context;
|
||||
private final WelcomeKitReadPlatformService readPlatformService;
|
||||
private final WelcomeKitWritePlatformService writePlatformService;
|
||||
private final FromJsonHelper fromJsonHelper;
|
||||
|
||||
@GET
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "List all welcome kits for a Client")
|
||||
public ClientWelcomeKitData getClientWelcomeKits(@PathParam("clientId") @Parameter(description = "clientId") final Long clientId) {
|
||||
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
||||
return this.readPlatformService.retrieveWelcomeKitsByClientId(clientId);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Create a new welcome kit dispatch")
|
||||
public CommandProcessingResult dispatchWelcomeKit(@PathParam("clientId") @Parameter(description = "clientId") final Long clientId,
|
||||
@Parameter(hidden = true) final String apiRequestBodyAsJson) {
|
||||
this.context.authenticatedUser().validateHasPermissionTo("CREATE_" + RESOURCE_NAME_FOR_PERMISSIONS);
|
||||
|
||||
final JsonCommand command = JsonCommand.fromJsonElement(clientId, this.fromJsonHelper.parse(apiRequestBodyAsJson), this.fromJsonHelper);
|
||||
|
||||
return this.writePlatformService.dispatchWelcomeKit(clientId, command);
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/**
|
||||
* 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.welcomekit.api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.welcomekit.data.ClientWelcomeKitData;
|
||||
import org.apache.fineract.portfolio.welcomekit.service.WelcomeKitReadPlatformService;
|
||||
import org.apache.fineract.portfolio.welcomekit.service.WelcomeKitWritePlatformService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Path("/v1/welcomekit")
|
||||
@Component
|
||||
@Tag(name = "Welcome Kit Dispatch", description = "Manages the dispatching and tracking of welcome kits for clients.")
|
||||
@RequiredArgsConstructor
|
||||
public class WelcomeKitApiResource {
|
||||
|
||||
private static final String RESOURCE_NAME_FOR_PERMISSIONS = "WELCOMEKIT";
|
||||
private final PlatformSecurityContext context;
|
||||
private final WelcomeKitWritePlatformService writePlatformService;
|
||||
private final FromJsonHelper fromJsonHelper;
|
||||
|
||||
@PUT
|
||||
@Path("{welcomeKitId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Update the status of an existing dispatch")
|
||||
public CommandProcessingResult updateWelcomeKitStatus(
|
||||
@PathParam("welcomeKitId") @Parameter(description = "welcomeKitId") final Long welcomeKitId,
|
||||
@Parameter(hidden = true) final String apiRequestBodyAsJson) {
|
||||
this.context.authenticatedUser().validateHasPermissionTo("UPDATE_" + RESOURCE_NAME_FOR_PERMISSIONS);
|
||||
|
||||
final JsonCommand command = JsonCommand.fromJsonElement(welcomeKitId, this.fromJsonHelper.parse(apiRequestBodyAsJson), this.fromJsonHelper);
|
||||
|
||||
return this.writePlatformService.updateWelcomeKitStatus(welcomeKitId, command);
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 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.welcomekit.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class ClientWelcomeKitData implements Serializable {
|
||||
|
||||
private final String clientName;
|
||||
private final boolean canDispatchNew;
|
||||
private final List<WelcomeKitDispatchData> dispatches;
|
||||
}
|
||||
+40
@@ -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.portfolio.welcomekit.data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
public class WelcomeKitDispatchData implements Serializable {
|
||||
|
||||
private final Long id;
|
||||
private final Long clientId;
|
||||
private final String clientName;
|
||||
private final String deliveryAddress;
|
||||
private final String deliveryMode;
|
||||
private final String deliveryModeOtherText;
|
||||
private final String trackingId;
|
||||
private final String status;
|
||||
private final LocalDate dispatchedOnDate;
|
||||
private final LocalDate deliveredOnDate;
|
||||
}
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* 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.welcomekit.domain;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.EntityListeners;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.portfolio.client.domain.Client;
|
||||
import org.springframework.data.annotation.CreatedBy;
|
||||
import org.springframework.data.annotation.CreatedDate;
|
||||
import org.springframework.data.annotation.LastModifiedBy;
|
||||
import org.springframework.data.annotation.LastModifiedDate;
|
||||
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_welcome_kit_dispatch")
|
||||
@EntityListeners(AuditingEntityListener.class)
|
||||
public class WelcomeKitDispatch extends AbstractPersistableCustom<Long> {
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "client_id", nullable = false)
|
||||
private Client client;
|
||||
|
||||
@Column(name = "delivery_address", length = 500, nullable = false)
|
||||
private String deliveryAddress;
|
||||
|
||||
@Column(name = "delivery_mode", length = 50, nullable = false)
|
||||
private String deliveryMode;
|
||||
|
||||
@Column(name = "delivery_mode_other_text", length = 255)
|
||||
private String deliveryModeOtherText;
|
||||
|
||||
@Column(name = "tracking_id", length = 100, nullable = false, unique = true)
|
||||
private String trackingId;
|
||||
|
||||
@Column(name = "status", length = 30, nullable = false)
|
||||
private String status;
|
||||
|
||||
@Column(name = "dispatched_on_date", nullable = false)
|
||||
private LocalDate dispatchedOnDate;
|
||||
|
||||
@Column(name = "delivered_on_date")
|
||||
private LocalDate deliveredOnDate;
|
||||
|
||||
@CreatedBy
|
||||
@Column(name = "created_by", updatable = false)
|
||||
private Long createdBy;
|
||||
|
||||
@CreatedDate
|
||||
@Column(name = "created_date", updatable = false)
|
||||
private LocalDateTime createdDate;
|
||||
|
||||
@LastModifiedBy
|
||||
@Column(name = "last_modified_by")
|
||||
private Long lastModifiedBy;
|
||||
|
||||
@LastModifiedDate
|
||||
@Column(name = "last_modified_date")
|
||||
private LocalDateTime lastModifiedDate;
|
||||
|
||||
protected WelcomeKitDispatch() {
|
||||
// Default constructor for JPA
|
||||
}
|
||||
|
||||
private WelcomeKitDispatch(final Client client, final String deliveryAddress, final String deliveryMode,
|
||||
final String deliveryModeOtherText, final String trackingId, final String status,
|
||||
final LocalDate dispatchedOnDate) {
|
||||
this.client = client;
|
||||
this.deliveryAddress = deliveryAddress;
|
||||
this.deliveryMode = deliveryMode;
|
||||
this.deliveryModeOtherText = deliveryModeOtherText;
|
||||
this.trackingId = trackingId;
|
||||
this.status = status;
|
||||
this.dispatchedOnDate = dispatchedOnDate;
|
||||
}
|
||||
|
||||
public static WelcomeKitDispatch createNew(final Client client, final String deliveryAddress, final String deliveryMode,
|
||||
final String deliveryModeOtherText, final String trackingId, final LocalDate dispatchedOnDate) {
|
||||
return new WelcomeKitDispatch(client, deliveryAddress, deliveryMode, deliveryModeOtherText, trackingId, "DISPATCHED", dispatchedOnDate);
|
||||
}
|
||||
|
||||
public Client getClient() {
|
||||
return this.client;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
public void updateStatus(final String newStatus, final LocalDate deliveredOnDate) {
|
||||
this.status = newStatus;
|
||||
if ("DELIVERED".equals(newStatus)) {
|
||||
this.deliveredOnDate = deliveredOnDate;
|
||||
}
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* 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.welcomekit.domain;
|
||||
|
||||
import java.util.List;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface WelcomeKitDispatchRepository extends JpaRepository<WelcomeKitDispatch, Long>, JpaSpecificationExecutor<WelcomeKitDispatch> {
|
||||
|
||||
List<WelcomeKitDispatch> findByClientIdOrderByCreatedDateDesc(Long clientId);
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* 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.welcomekit.service;
|
||||
|
||||
import org.apache.fineract.portfolio.welcomekit.data.ClientWelcomeKitData;
|
||||
|
||||
public interface WelcomeKitReadPlatformService {
|
||||
|
||||
ClientWelcomeKitData retrieveWelcomeKitsByClientId(Long clientId);
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
/**
|
||||
* 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.welcomekit.service;
|
||||
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
|
||||
import org.apache.fineract.portfolio.welcomekit.data.ClientWelcomeKitData;
|
||||
import org.apache.fineract.portfolio.welcomekit.data.WelcomeKitDispatchData;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.core.RowMapper;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class WelcomeKitReadPlatformServiceImpl implements WelcomeKitReadPlatformService {
|
||||
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Override
|
||||
public ClientWelcomeKitData retrieveWelcomeKitsByClientId(Long clientId) {
|
||||
final WelcomeKitDispatchMapper rm = new WelcomeKitDispatchMapper();
|
||||
final String sql = "SELECT " + rm.schema() + " WHERE w.client_id = ? ORDER BY w.created_date DESC";
|
||||
|
||||
List<WelcomeKitDispatchData> dispatches = this.jdbcTemplate.query(sql, rm, clientId);
|
||||
|
||||
String clientName = this.jdbcTemplate.queryForObject("SELECT display_name FROM m_client WHERE id = ?", String.class, clientId);
|
||||
|
||||
boolean canDispatchNew = true;
|
||||
if (!dispatches.isEmpty()) {
|
||||
WelcomeKitDispatchData latest = dispatches.get(0);
|
||||
if ("RETURNED".equals(latest.getStatus())) {
|
||||
canDispatchNew = true;
|
||||
} else {
|
||||
canDispatchNew = false;
|
||||
}
|
||||
}
|
||||
|
||||
return ClientWelcomeKitData.builder()
|
||||
.clientName(clientName)
|
||||
.canDispatchNew(canDispatchNew)
|
||||
.dispatches(dispatches)
|
||||
.build();
|
||||
}
|
||||
|
||||
private static final class WelcomeKitDispatchMapper implements RowMapper<WelcomeKitDispatchData> {
|
||||
|
||||
public String schema() {
|
||||
return " w.id as id, w.client_id as clientId, c.display_name as clientName, "
|
||||
+ " w.delivery_address as deliveryAddress, w.delivery_mode as deliveryMode, "
|
||||
+ " w.delivery_mode_other_text as deliveryModeOtherText, w.tracking_id as trackingId, "
|
||||
+ " w.status as status, w.dispatched_on_date as dispatchedOnDate, w.delivered_on_date as deliveredOnDate "
|
||||
+ " FROM m_welcome_kit_dispatch w "
|
||||
+ " JOIN m_client c ON c.id = w.client_id ";
|
||||
}
|
||||
|
||||
@Override
|
||||
public WelcomeKitDispatchData mapRow(final ResultSet rs, @SuppressWarnings("unused") final int rowNum) throws SQLException {
|
||||
final Long id = rs.getLong("id");
|
||||
final Long clientId = rs.getLong("clientId");
|
||||
final String clientName = rs.getString("clientName");
|
||||
final String deliveryAddress = rs.getString("deliveryAddress");
|
||||
final String deliveryMode = rs.getString("deliveryMode");
|
||||
final String deliveryModeOtherText = rs.getString("deliveryModeOtherText");
|
||||
final String trackingId = rs.getString("trackingId");
|
||||
final String status = rs.getString("status");
|
||||
final LocalDate dispatchedOnDate = JdbcSupport.getLocalDate(rs, "dispatchedOnDate");
|
||||
final LocalDate deliveredOnDate = JdbcSupport.getLocalDate(rs, "deliveredOnDate");
|
||||
|
||||
return WelcomeKitDispatchData.builder()
|
||||
.id(id)
|
||||
.clientId(clientId)
|
||||
.clientName(clientName)
|
||||
.deliveryAddress(deliveryAddress)
|
||||
.deliveryMode(deliveryMode)
|
||||
.deliveryModeOtherText(deliveryModeOtherText)
|
||||
.trackingId(trackingId)
|
||||
.status(status)
|
||||
.dispatchedOnDate(dispatchedOnDate)
|
||||
.deliveredOnDate(deliveredOnDate)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* 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.welcomekit.service;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
|
||||
public interface WelcomeKitWritePlatformService {
|
||||
|
||||
CommandProcessingResult dispatchWelcomeKit(Long clientId, JsonCommand command);
|
||||
|
||||
CommandProcessingResult updateWelcomeKitStatus(Long welcomeKitId, JsonCommand command);
|
||||
}
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* 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.welcomekit.service;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.UUID;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.client.domain.Client;
|
||||
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
|
||||
import org.apache.fineract.portfolio.welcomekit.domain.WelcomeKitDispatch;
|
||||
import org.apache.fineract.portfolio.welcomekit.domain.WelcomeKitDispatchRepository;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class WelcomeKitWritePlatformServiceImpl implements WelcomeKitWritePlatformService {
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final ClientRepositoryWrapper clientRepository;
|
||||
private final WelcomeKitDispatchRepository welcomeKitDispatchRepository;
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult dispatchWelcomeKit(final Long clientId, final JsonCommand command) {
|
||||
this.context.authenticatedUser();
|
||||
|
||||
final Client client = this.clientRepository.findOneWithNotFoundDetection(clientId);
|
||||
|
||||
final String deliveryAddress = command.stringValueOfParameterNamed("deliveryAddress");
|
||||
final String deliveryMode = command.stringValueOfParameterNamed("deliveryMode");
|
||||
final String deliveryModeOtherText = command.stringValueOfParameterNamed("deliveryModeOtherText");
|
||||
final LocalDate dispatchedOnDate = command.localDateValueOfParameterNamed("dispatchedOnDate");
|
||||
|
||||
if (deliveryAddress == null || deliveryAddress.trim().isEmpty()) {
|
||||
throw new PlatformDataIntegrityException("error.msg.welcomekit.deliveryAddress.cannot.be.blank",
|
||||
"Delivery address cannot be blank.");
|
||||
}
|
||||
if (deliveryMode == null || deliveryMode.trim().isEmpty()) {
|
||||
throw new PlatformDataIntegrityException("error.msg.welcomekit.deliveryMode.cannot.be.blank",
|
||||
"Delivery mode cannot be blank.");
|
||||
}
|
||||
if (dispatchedOnDate == null) {
|
||||
throw new PlatformDataIntegrityException("error.msg.welcomekit.dispatchedOnDate.cannot.be.blank",
|
||||
"Dispatched on date cannot be blank.");
|
||||
}
|
||||
|
||||
final String trackingId = "WK-" + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
|
||||
|
||||
final WelcomeKitDispatch newDispatch = WelcomeKitDispatch.createNew(client, deliveryAddress, deliveryMode, deliveryModeOtherText,
|
||||
trackingId, dispatchedOnDate);
|
||||
|
||||
this.welcomeKitDispatchRepository.saveAndFlush(newDispatch);
|
||||
|
||||
return new CommandProcessingResultBuilder()
|
||||
.withCommandId(command.commandId())
|
||||
.withClientId(clientId)
|
||||
.withEntityId(newDispatch.getId())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult updateWelcomeKitStatus(final Long welcomeKitId, final JsonCommand command) {
|
||||
this.context.authenticatedUser();
|
||||
|
||||
final WelcomeKitDispatch dispatch = this.welcomeKitDispatchRepository.findById(welcomeKitId).orElseThrow(
|
||||
() -> new PlatformDataIntegrityException("error.msg.welcomekit.not.found", "Welcome kit not found."));
|
||||
|
||||
final String status = command.stringValueOfParameterNamed("status");
|
||||
|
||||
if (status == null || status.trim().isEmpty()) {
|
||||
throw new PlatformDataIntegrityException("error.msg.welcomekit.status.cannot.be.blank", "Status cannot be blank.");
|
||||
}
|
||||
|
||||
LocalDate deliveredOnDate = null;
|
||||
if ("DELIVERED".equals(status)) {
|
||||
deliveredOnDate = LocalDate.now();
|
||||
}
|
||||
|
||||
dispatch.updateStatus(status, deliveredOnDate);
|
||||
|
||||
this.welcomeKitDispatchRepository.saveAndFlush(dispatch);
|
||||
|
||||
return new CommandProcessingResultBuilder()
|
||||
.withCommandId(command.commandId())
|
||||
.withClientId(dispatch.getClient().getId())
|
||||
.withEntityId(dispatch.getId())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
@@ -435,6 +435,7 @@
|
||||
<include file="parts/0412_activate_outward_clearing_batch_job.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0413_inward_item_verify_signature_permission.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0414_inward_item_full_source_details.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0415_welcome_kit_dispatch.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0415_add_otp_delivery_method_and_first_login_gate_to_appuser.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0416_create_user_agreement_tables.xml" relativeToChangelogFile="true"/>
|
||||
<include file="parts/0417_add_first_login_gate_config.xml" relativeToChangelogFile="true"/>
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
|
||||
<changeSet id="0415_welcome_kit_dispatch" author="CBS" runOnChange="false">
|
||||
<sql>
|
||||
CREATE TABLE m_welcome_kit_dispatch (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
client_id BIGINT NOT NULL REFERENCES m_client(id),
|
||||
delivery_address VARCHAR(500) NOT NULL,
|
||||
delivery_mode VARCHAR(50) NOT NULL,
|
||||
delivery_mode_other_text VARCHAR(255),
|
||||
tracking_id VARCHAR(100) NOT NULL UNIQUE,
|
||||
status VARCHAR(30) NOT NULL DEFAULT 'DISPATCHED',
|
||||
dispatched_on_date DATE NOT NULL,
|
||||
delivered_on_date DATE,
|
||||
created_by BIGINT,
|
||||
created_date TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||
last_modified_by BIGINT,
|
||||
last_modified_date TIMESTAMP
|
||||
);
|
||||
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'READ_WELCOMEKIT', 'WELCOMEKIT', 'READ', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'READ_WELCOMEKIT');
|
||||
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'CREATE_WELCOMEKIT', 'WELCOMEKIT', 'CREATE', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'CREATE_WELCOMEKIT');
|
||||
|
||||
INSERT INTO m_permission (grouping, code, entity_name, action_name, can_maker_checker)
|
||||
SELECT 'portfolio', 'UPDATE_WELCOMEKIT', 'WELCOMEKIT', 'UPDATE', false
|
||||
WHERE NOT EXISTS (SELECT 1 FROM m_permission WHERE code = 'UPDATE_WELCOMEKIT');
|
||||
</sql>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
||||
+2
-1
@@ -16,10 +16,11 @@
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
org.gradle.jvmargs=-Xmx6g --add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.management/javax.management=ALL-UNNAMED --add-opens=java.naming/javax.naming=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=null
|
||||
org.gradle.jvmargs=-Xmx8g -XX:MaxMetaspaceSize=1g --add-exports jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED --add-exports jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED --add-exports=java.naming/com.sun.jndi.ldap=ALL-UNNAMED --add-opens=java.base/java.lang=ALL-UNNAMED --add-opens=java.base/java.lang.invoke=ALL-UNNAMED --add-opens=java.base/java.io=ALL-UNNAMED --add-opens=java.base/java.security=ALL-UNNAMED --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.management/javax.management=ALL-UNNAMED --add-opens=java.naming/javax.naming=ALL-UNNAMED --add-opens=java.rmi/sun.rmi.transport=null
|
||||
buildType=BUILD
|
||||
org.gradle.caching=true
|
||||
org.gradle.parallel=true
|
||||
org.gradle.workers.max=2
|
||||
org.gradle.daemon.idletimeout=10800000
|
||||
# Temporarily disabled until we fix configuration cache compatibility
|
||||
#org.gradle.configuration-cache=true
|
||||
|
||||
+2097
File diff suppressed because it is too large
Load Diff
+2115
File diff suppressed because it is too large
Load Diff
+2577
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
||||
[33m17e0dab43[m Merge branch 'dev' of https://git.lincpay.tech/CBSNexora/cbsnexora-backend into dev
|
||||
[33m67810bfae[m Add Welcome Kit Dispatch feature and Share Account summary API
|
||||
[33m7c15fbb0c[m fix(documentmanagement): close leaked file handles causing Windows re-upload failures; add entity KYC document CodeValues
|
||||
[33m6e3f195de[m Merge remote-tracking branch 'origin/uate' into uate
|
||||
[33ma65d80125[m feat(clients): maker-checker for client creation and edits (backend)
|
||||
[33mf45d5890e[m CTR/STR report and Risk Category auto mark on bases of person occupation and anual salary enter
|
||||
[33m3c58bb231[m fix(clients): pwdCategoryOptions on edit template, minor-age threshold to 18, minor KYC identity-proof bypass
|
||||
[33maabda18b6[m feat(clients): enforce Mother + Father/Caretaker family members on client activation
|
||||
[33m0e5671b70[m Merge remote-tracking branch 'origin/uate' into uate
|
||||
[33m67214ec0f[m fix(clients): stale signature bug, CKYC fixes, monthly turnover/annual income, senior citizen/PWD classification
|
||||
@@ -0,0 +1,46 @@
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
|
||||
|
||||
$headers = @{
|
||||
"fineract-platform-tenantid" = "default"
|
||||
"Content-Type" = "application/json"
|
||||
}
|
||||
$body = '{"username":"mifos", "password":"password"}'
|
||||
|
||||
Write-Host "--- AUTHENTICATION ---"
|
||||
$authResponse = Invoke-RestMethod -Method Post -Uri "https://localhost:8443/fineract-provider/api/v1/authentication?username=mifos&password=password" -Headers $headers
|
||||
$authKey = $authResponse.base64EncodedAuthenticationKey
|
||||
$headers.Add("Authorization", "Basic $authKey")
|
||||
|
||||
Write-Host "`n--- 1. GET /v1/clients/95/welcomekit ---"
|
||||
$res1 = Invoke-RestMethod -Method Get -Uri "https://localhost:8443/fineract-provider/api/v1/clients/95/welcomekit" -Headers $headers
|
||||
$res1 | ConvertTo-Json -Depth 10
|
||||
|
||||
Write-Host "`n--- 2. POST /v1/clients/95/welcomekit ---"
|
||||
$postBody = @{
|
||||
deliveryAddress = "123 Main St, Springfield"
|
||||
deliveryMode = "POSTMAN"
|
||||
dispatchedOnDate = "30 July 2026"
|
||||
dateFormat = "dd MMMM yyyy"
|
||||
locale = "en"
|
||||
} | ConvertTo-Json
|
||||
Write-Host "Request Body: $postBody"
|
||||
$res2 = Invoke-RestMethod -Method Post -Uri "https://localhost:8443/fineract-provider/api/v1/clients/95/welcomekit" -Headers $headers -Body $postBody
|
||||
$res2 | ConvertTo-Json -Depth 10
|
||||
$welcomeKitId = $res2.resourceId
|
||||
|
||||
Write-Host "`n--- 3. GET /v1/clients/95/welcomekit (after POST) ---"
|
||||
$res3 = Invoke-RestMethod -Method Get -Uri "https://localhost:8443/fineract-provider/api/v1/clients/95/welcomekit" -Headers $headers
|
||||
$res3 | ConvertTo-Json -Depth 10
|
||||
|
||||
Write-Host "`n--- 4. PUT /v1/welcomekit/$welcomeKitId ---"
|
||||
$putBody = @{
|
||||
status = "DELIVERED"
|
||||
} | ConvertTo-Json
|
||||
Write-Host "Request Body: $putBody"
|
||||
$res4 = Invoke-RestMethod -Method Put -Uri "https://localhost:8443/fineract-provider/api/v1/welcomekit/$welcomeKitId" -Headers $headers -Body $putBody
|
||||
$res4 | ConvertTo-Json -Depth 10
|
||||
|
||||
Write-Host "`n--- 5. GET /v1/clients/95/welcomekit (after PUT) ---"
|
||||
$res5 = Invoke-RestMethod -Method Get -Uri "https://localhost:8443/fineract-provider/api/v1/clients/95/welcomekit" -Headers $headers
|
||||
$res5 | ConvertTo-Json -Depth 10
|
||||
Reference in New Issue
Block a user