FINERACT-2169: Refactor api to concrete types and add validation;

This commit is contained in:
viktorpavlenko
2025-02-19 23:10:12 +01:00
committed by Arnold Gálovics
parent 1b0cc27eec
commit 81ed0260b1
8 changed files with 231 additions and 135 deletions
@@ -49,14 +49,16 @@ import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSer
import org.apache.fineract.infrastructure.core.service.DateUtils; import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.core.service.Page; import org.apache.fineract.infrastructure.core.service.Page;
import org.apache.fineract.infrastructure.core.service.SearchParameters; import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.organisation.teller.data.CashierData; import org.apache.fineract.organisation.teller.data.CashierData;
import org.apache.fineract.organisation.teller.data.CashierTransactionData; import org.apache.fineract.organisation.teller.data.CashierTransactionData;
import org.apache.fineract.organisation.teller.data.CashierTransactionsWithSummaryData; import org.apache.fineract.organisation.teller.data.CashierTransactionsWithSummaryData;
import org.apache.fineract.organisation.teller.data.TellerData; import org.apache.fineract.organisation.teller.data.TellerData;
import org.apache.fineract.organisation.teller.data.TellerJournalData; import org.apache.fineract.organisation.teller.data.TellerJournalData;
import org.apache.fineract.organisation.teller.data.TellerTransactionData; import org.apache.fineract.organisation.teller.data.TellerTransactionData;
import org.apache.fineract.organisation.teller.domain.model.CashiersForTeller;
import org.apache.fineract.organisation.teller.domain.model.request.CashierRequest;
import org.apache.fineract.organisation.teller.domain.model.request.CashierTransactionRequest;
import org.apache.fineract.organisation.teller.domain.model.request.TellerRequest;
import org.apache.fineract.organisation.teller.service.TellerManagementReadPlatformService; import org.apache.fineract.organisation.teller.service.TellerManagementReadPlatformService;
import org.apache.fineract.organisation.teller.util.DateRange; import org.apache.fineract.organisation.teller.util.DateRange;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -67,11 +69,9 @@ import org.springframework.stereotype.Component;
@RequiredArgsConstructor @RequiredArgsConstructor
public class TellerApiResource { public class TellerApiResource {
private final PlatformSecurityContext securityContext;
private final DefaultToApiJsonSerializer<TellerData> jsonSerializer;
private final TellerManagementReadPlatformService readPlatformService; private final TellerManagementReadPlatformService readPlatformService;
private final PortfolioCommandSourceWritePlatformService commandWritePlatformService; private final PortfolioCommandSourceWritePlatformService commandWritePlatformService;
private final SqlValidator sqlValidator; private final DefaultToApiJsonSerializer<String> apiJsonSerializer;
@GET @GET
@Consumes({ MediaType.TEXT_HTML, MediaType.APPLICATION_JSON }) @Consumes({ MediaType.TEXT_HTML, MediaType.APPLICATION_JSON })
@@ -79,10 +79,8 @@ public class TellerApiResource {
@Operation(summary = "List all tellers", description = "Retrieves list tellers") @Operation(summary = "List all tellers", description = "Retrieves list tellers")
@ApiResponses({ @ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = TellerApiResourceSwagger.GetTellersResponse.class)))) }) @ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = TellerApiResourceSwagger.GetTellersResponse.class)))) })
public String getTellerData(@QueryParam("officeId") @Parameter(description = "officeId") final Long officeId) { public Collection<TellerData> getTellerData(@QueryParam("officeId") @Parameter(description = "officeId") final Long officeId) {
final Collection<TellerData> foundTellers = this.readPlatformService.getTellers(officeId); return readPlatformService.getTellers(officeId);
return this.jsonSerializer.serialize(foundTellers);
} }
@GET @GET
@@ -92,10 +90,8 @@ public class TellerApiResource {
@Operation(summary = "Retrieve tellers", description = "") @Operation(summary = "Retrieve tellers", description = "")
@ApiResponses({ @ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.GetTellersResponse.class))) }) @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.GetTellersResponse.class))) })
public String findTeller(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId) { public TellerData findTeller(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId) {
final TellerData teller = this.readPlatformService.findTeller(tellerId); return readPlatformService.findTeller(tellerId);
return this.jsonSerializer.serialize(teller);
} }
@POST @POST
@@ -106,12 +102,10 @@ public class TellerApiResource {
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PostTellersRequest.class))) @RequestBody(required = true, content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PostTellersRequest.class)))
@ApiResponses({ @ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PostTellersResponse.class))) }) @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PostTellersResponse.class))) })
public String createTeller(@Parameter(hidden = true) final String tellerData) { public CommandProcessingResult createTeller(@Parameter(hidden = true) TellerRequest tellerData) {
final CommandWrapper request = new CommandWrapperBuilder().createTeller().withJson(tellerData).build(); final CommandWrapper request = new CommandWrapperBuilder().createTeller().withJson(apiJsonSerializer.serialize(tellerData)).build();
final CommandProcessingResult result = this.commandWritePlatformService.logCommandSource(request); return this.commandWritePlatformService.logCommandSource(request);
return this.jsonSerializer.serialize(result);
} }
@PUT @PUT
@@ -122,25 +116,21 @@ public class TellerApiResource {
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PutTellersRequest.class))) @RequestBody(required = true, content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PutTellersRequest.class)))
@ApiResponses({ @ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PutTellersResponse.class))) }) @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PutTellersResponse.class))) })
public String updateTeller(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId, public CommandProcessingResult updateTeller(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId,
@Parameter(hidden = true) final String tellerData) { @Parameter(hidden = true) TellerRequest tellerData) {
final CommandWrapper request = new CommandWrapperBuilder().updateTeller(tellerId).withJson(tellerData).build(); final CommandWrapper request = new CommandWrapperBuilder().updateTeller(tellerId).withJson(apiJsonSerializer.serialize(tellerData))
.build();
final CommandProcessingResult result = this.commandWritePlatformService.logCommandSource(request); return this.commandWritePlatformService.logCommandSource(request);
return this.jsonSerializer.serialize(result);
} }
@DELETE @DELETE
@Path("{tellerId}") @Path("{tellerId}")
@Consumes({ MediaType.TEXT_HTML, MediaType.APPLICATION_JSON }) @Consumes({ MediaType.TEXT_HTML, MediaType.APPLICATION_JSON })
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public String deleteTeller(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId) { public CommandProcessingResult deleteTeller(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId) {
final CommandWrapper request = new CommandWrapperBuilder().deleteTeller(tellerId).build(); final CommandWrapper request = new CommandWrapperBuilder().deleteTeller(tellerId).build();
return this.commandWritePlatformService.logCommandSource(request);
final CommandProcessingResult result = this.commandWritePlatformService.logCommandSource(request);
return this.jsonSerializer.serialize(result);
} }
@GET @GET
@@ -150,7 +140,7 @@ public class TellerApiResource {
@Operation(summary = "List Cashiers", description = "") @Operation(summary = "List Cashiers", description = "")
@ApiResponses({ @ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.GetTellersTellerIdCashiersResponse.class))) }) @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.GetTellersTellerIdCashiersResponse.class))) })
public String getCashierData(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId, public CashiersForTeller getCashierData(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId,
@QueryParam("fromdate") @Parameter(description = "fromdate") final String fromDateStr, @QueryParam("fromdate") @Parameter(description = "fromdate") final String fromDateStr,
@QueryParam("todate") @Parameter(description = "todate") final String toDateStr) { @QueryParam("todate") @Parameter(description = "todate") final String toDateStr) {
final DateTimeFormatter dateFormatter = DateTimeFormatter.BASIC_ISO_DATE; final DateTimeFormatter dateFormatter = DateTimeFormatter.BASIC_ISO_DATE;
@@ -161,14 +151,7 @@ public class TellerApiResource {
final TellerData teller = this.readPlatformService.findTeller(tellerId); final TellerData teller = this.readPlatformService.findTeller(tellerId);
final Collection<CashierData> cashiers = this.readPlatformService.getCashiersForTeller(tellerId, fromDate, toDate); final Collection<CashierData> cashiers = this.readPlatformService.getCashiersForTeller(tellerId, fromDate, toDate);
CashiersForTeller cashiersForTeller = new CashiersForTeller(); return new CashiersForTeller(tellerId, teller.getName(), teller.getOfficeId(), teller.getOfficeName(), cashiers);
cashiersForTeller.cashiers = cashiers;
cashiersForTeller.tellerId = tellerId;
cashiersForTeller.tellerName = teller.getName();
cashiersForTeller.officeId = teller.getOfficeId();
cashiersForTeller.officeName = teller.getOfficeName();
return this.jsonSerializer.serialize(cashiersForTeller);
} }
@GET @GET
@@ -178,11 +161,9 @@ public class TellerApiResource {
@Operation(summary = "Retrieve a cashier", description = "") @Operation(summary = "Retrieve a cashier", description = "")
@ApiResponses({ @ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.GetTellersTellerIdCashiersCashierIdResponse.class))) }) @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.GetTellersTellerIdCashiersCashierIdResponse.class))) })
public String findCashierData(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId, public CashierData findCashierData(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId,
@PathParam("cashierId") @Parameter(description = "cashierId") final Long cashierId) { @PathParam("cashierId") @Parameter(description = "cashierId") final Long cashierId) {
final CashierData cashier = this.readPlatformService.findCashier(cashierId); return readPlatformService.findCashier(cashierId);
return this.jsonSerializer.serialize(cashier);
} }
@GET @GET
@@ -192,14 +173,12 @@ public class TellerApiResource {
@Operation(summary = "Find Cashiers", description = "") @Operation(summary = "Find Cashiers", description = "")
@ApiResponses({ @ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.GetTellersTellerIdCashiersTemplateResponse.class))) }) @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.GetTellersTellerIdCashiersTemplateResponse.class))) })
public String getCashierTemplate(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId) { public CashierData getCashierTemplate(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId) {
final TellerData teller = this.readPlatformService.findTeller(tellerId); final TellerData teller = this.readPlatformService.findTeller(tellerId);
Long officeId = teller.getOfficeId(); Long officeId = teller.getOfficeId();
final CashierData cashier = this.readPlatformService.retrieveCashierTemplate(officeId, tellerId, true); return this.readPlatformService.retrieveCashierTemplate(officeId, tellerId, true);
return this.jsonSerializer.serialize(cashier);
} }
@POST @POST
@@ -212,13 +191,12 @@ public class TellerApiResource {
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PostTellersTellerIdCashiersRequest.class))) @RequestBody(required = true, content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PostTellersTellerIdCashiersRequest.class)))
@ApiResponses({ @ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PostTellersTellerIdCashiersResponse.class))) }) @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PostTellersTellerIdCashiersResponse.class))) })
public String createCashier(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId, public CommandProcessingResult createCashier(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId,
@Parameter(hidden = true) final String cashierData) { @Parameter(hidden = true) final CashierRequest cashierData) {
final CommandWrapper request = new CommandWrapperBuilder().allocateTeller(tellerId).withJson(cashierData).build(); final CommandWrapper request = new CommandWrapperBuilder().allocateTeller(tellerId)
.withJson(apiJsonSerializer.serialize(cashierData)).build();
final CommandProcessingResult result = this.commandWritePlatformService.logCommandSource(request); return this.commandWritePlatformService.logCommandSource(request);
return this.jsonSerializer.serialize(result);
} }
@PUT @PUT
@@ -229,15 +207,14 @@ public class TellerApiResource {
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PutTellersTellerIdCashiersCashierIdRequest.class))) @RequestBody(required = true, content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PutTellersTellerIdCashiersCashierIdRequest.class)))
@ApiResponses({ @ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PutTellersTellerIdCashiersCashierIdResponse.class))) }) @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PutTellersTellerIdCashiersCashierIdResponse.class))) })
public String updateCashier(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId, public CommandProcessingResult updateCashier(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId,
@PathParam("cashierId") @Parameter(description = "cashierId") final Long cashierId, @PathParam("cashierId") @Parameter(description = "cashierId") final Long cashierId,
@Parameter(hidden = true) final String cashierDate) { @Parameter(hidden = true) final CashierRequest cashierDate) {
final CommandWrapper request = new CommandWrapperBuilder().updateAllocationTeller(tellerId, cashierId).withJson(cashierDate) final CommandWrapper request = new CommandWrapperBuilder().updateAllocationTeller(tellerId, cashierId)
.build(); .withJson(apiJsonSerializer.serialize(cashierDate)).build();
final CommandProcessingResult result = this.commandWritePlatformService.logCommandSource(request); return this.commandWritePlatformService.logCommandSource(request);
return this.jsonSerializer.serialize(result);
} }
@DELETE @DELETE
@@ -247,13 +224,12 @@ public class TellerApiResource {
@Operation(summary = "Delete Cashier", description = "") @Operation(summary = "Delete Cashier", description = "")
@ApiResponses({ @ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.DeleteTellersTellerIdCashiersCashierIdResponse.class))) }) @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.DeleteTellersTellerIdCashiersCashierIdResponse.class))) })
public String deleteCashier(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId, public CommandProcessingResult deleteCashier(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId,
@PathParam("cashierId") @Parameter(description = "cashierId") final Long cashierId) { @PathParam("cashierId") @Parameter(description = "cashierId") final Long cashierId) {
final CommandWrapper request = new CommandWrapperBuilder().deleteAllocationTeller(tellerId, cashierId).build(); final CommandWrapper request = new CommandWrapperBuilder().deleteAllocationTeller(tellerId, cashierId).build();
final CommandProcessingResult result = this.commandWritePlatformService.logCommandSource(request); return this.commandWritePlatformService.logCommandSource(request);
return this.jsonSerializer.serialize(result);
} }
@POST @POST
@@ -264,15 +240,13 @@ public class TellerApiResource {
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PostTellersTellerIdCashiersCashierIdAllocateRequest.class))) @RequestBody(required = true, content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PostTellersTellerIdCashiersCashierIdAllocateRequest.class)))
@ApiResponses({ @ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PostTellersTellerIdCashiersCashierIdAllocateResponse.class))) }) @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PostTellersTellerIdCashiersCashierIdAllocateResponse.class))) })
public String allocateCashToCashier(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId, public CommandProcessingResult allocateCashToCashier(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId,
@PathParam("cashierId") @Parameter(description = "cashierId") final Long cashierId, @PathParam("cashierId") @Parameter(description = "cashierId") final Long cashierId,
@Parameter(hidden = true) final String cashierTxnData) { @Parameter(hidden = true) CashierTransactionRequest cashierTxnData) {
final CommandWrapper request = new CommandWrapperBuilder().allocateCashToCashier(tellerId, cashierId).withJson(cashierTxnData) final CommandWrapper request = new CommandWrapperBuilder().allocateCashToCashier(tellerId, cashierId)
.build(); .withJson(apiJsonSerializer.serialize(cashierTxnData)).build();
final CommandProcessingResult result = this.commandWritePlatformService.logCommandSource(request); return this.commandWritePlatformService.logCommandSource(request);
return this.jsonSerializer.serialize(result);
} }
@@ -284,16 +258,13 @@ public class TellerApiResource {
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PostTellersTellerIdCashiersCashierIdSettleRequest.class))) @RequestBody(required = true, content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PostTellersTellerIdCashiersCashierIdSettleRequest.class)))
@ApiResponses({ @ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PostTellersTellerIdCashiersCashierIdSettleResponse.class))) }) @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.PostTellersTellerIdCashiersCashierIdSettleResponse.class))) })
public String settleCashFromCashier(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId, public CommandProcessingResult settleCashFromCashier(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId,
@PathParam("cashierId") @Parameter(description = "cashierId") final Long cashierId, @PathParam("cashierId") @Parameter(description = "cashierId") final Long cashierId,
@Parameter(hidden = true) final String cashierTxnData) { @Parameter(hidden = true) CashierTransactionRequest cashierTxnData) {
final CommandWrapper request = new CommandWrapperBuilder().settleCashFromCashier(tellerId, cashierId).withJson(cashierTxnData) final CommandWrapper request = new CommandWrapperBuilder().settleCashFromCashier(tellerId, cashierId)
.build(); .withJson(apiJsonSerializer.serialize(cashierTxnData)).build();
final CommandProcessingResult result = this.commandWritePlatformService.logCommandSource(request);
return this.jsonSerializer.serialize(result);
return this.commandWritePlatformService.logCommandSource(request);
} }
@GET @GET
@@ -303,28 +274,18 @@ public class TellerApiResource {
@Operation(summary = "Retrieve Cashier Transactions", description = "") @Operation(summary = "Retrieve Cashier Transactions", description = "")
@ApiResponses({ @ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.GetTellersTellerIdCashiersCashiersIdTransactionsResponse.class))) }) @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.GetTellersTellerIdCashiersCashiersIdTransactionsResponse.class))) })
public String getTransactionsForCashier(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId, public Page<CashierTransactionData> getTransactionsForCashier(
@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId,
@PathParam("cashierId") @Parameter(description = "cashierId") final Long cashierId, @PathParam("cashierId") @Parameter(description = "cashierId") final Long cashierId,
@QueryParam("currencyCode") @Parameter(description = "currencyCode") final String currencyCode, @QueryParam("currencyCode") @Parameter(description = "currencyCode") final String currencyCode,
@QueryParam("offset") @Parameter(description = "offset") final Integer offset, @QueryParam("offset") @Parameter(description = "offset") final Integer offset,
@QueryParam("limit") @Parameter(description = "limit") final Integer limit, @QueryParam("limit") @Parameter(description = "limit") final Integer limit,
@QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy, @QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy,
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) { @QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) {
// TODO: can we remove these 2 calls? we don't use the results, but left it here in case something is done in
// the functions
this.readPlatformService.findTeller(tellerId);
this.readPlatformService.findCashier(cashierId);
final LocalDate fromDate = null;
final LocalDate toDate = null;
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy) final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy)
.sortOrder(sortOrder).build(); .sortOrder(sortOrder).build();
final Page<CashierTransactionData> cashierTxns = this.readPlatformService.retrieveCashierTransactions(cashierId, false, fromDate, return this.readPlatformService.retrieveCashierTransactions(cashierId, false, null, null, currencyCode, searchParameters);
toDate, currencyCode, searchParameters);
return this.jsonSerializer.serialize(cashierTxns);
} }
@GET @GET
@@ -334,30 +295,20 @@ public class TellerApiResource {
@Operation(summary = "Retrieve Transactions With Summary For Cashier", description = "") @Operation(summary = "Retrieve Transactions With Summary For Cashier", description = "")
@ApiResponses({ @ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.GetTellersTellerIdCashiersCashiersIdSummaryAndTransactionsResponse.class))) }) @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.GetTellersTellerIdCashiersCashiersIdSummaryAndTransactionsResponse.class))) })
public String getTransactionsWithSummaryForCashier(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId, public CashierTransactionsWithSummaryData getTransactionsWithSummaryForCashier(
@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId,
@PathParam("cashierId") @Parameter(description = "cashierId") final Long cashierId, @PathParam("cashierId") @Parameter(description = "cashierId") final Long cashierId,
@QueryParam("currencyCode") @Parameter(description = "currencyCode") final String currencyCode, @QueryParam("currencyCode") @Parameter(description = "currencyCode") final String currencyCode,
@QueryParam("offset") @Parameter(description = "offset") final Integer offset, @QueryParam("offset") @Parameter(description = "offset") final Integer offset,
@QueryParam("limit") @Parameter(description = "limit") final Integer limit, @QueryParam("limit") @Parameter(description = "limit") final Integer limit,
@QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy, @QueryParam("orderBy") @Parameter(description = "orderBy") final String orderBy,
@QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) { @QueryParam("sortOrder") @Parameter(description = "sortOrder") final String sortOrder) {
// TODO: can we remove these 2 calls? we don't use the results, but left it here in case something is done in
// the functions
this.readPlatformService.findTeller(tellerId);
this.readPlatformService.findCashier(cashierId);
final LocalDate fromDate = null;
final LocalDate toDate = null;
sqlValidator.validate(orderBy);
sqlValidator.validate(sortOrder);
final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy) final SearchParameters searchParameters = SearchParameters.builder().limit(limit).offset(offset).orderBy(orderBy)
.sortOrder(sortOrder).build(); .sortOrder(sortOrder).build();
final CashierTransactionsWithSummaryData cashierTxnWithSummary = this.readPlatformService return this.readPlatformService.retrieveCashierTransactionsWithSummary(cashierId, false, null, null, currencyCode,
.retrieveCashierTransactionsWithSummary(cashierId, false, fromDate, toDate, currencyCode, searchParameters); searchParameters);
return this.jsonSerializer.serialize(cashierTxnWithSummary);
} }
@GET @GET
@@ -367,61 +318,44 @@ public class TellerApiResource {
@Operation(summary = "Retrieve Cashier Transaction Template", description = "") @Operation(summary = "Retrieve Cashier Transaction Template", description = "")
@ApiResponses({ @ApiResponses({
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.GetTellersTellerIdCashiersCashiersIdTransactionsTemplateResponse.class))) }) @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = TellerApiResourceSwagger.GetTellersTellerIdCashiersCashiersIdTransactionsTemplateResponse.class))) })
public String getCashierTxnTemplate(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId, public CashierTransactionData getCashierTxnTemplate(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId,
@PathParam("cashierId") @Parameter(description = "cashierId") final Long cashierId) { @PathParam("cashierId") @Parameter(description = "cashierId") final Long cashierId) {
final CashierTransactionData cashierTxnTemplate = this.readPlatformService.retrieveCashierTxnTemplate(cashierId); return this.readPlatformService.retrieveCashierTxnTemplate(cashierId);
return this.jsonSerializer.serialize(cashierTxnTemplate);
} }
@GET @GET
@Path("{tellerId}/transactions") @Path("{tellerId}/transactions")
@Consumes({ MediaType.TEXT_HTML, MediaType.APPLICATION_JSON }) @Consumes({ MediaType.TEXT_HTML, MediaType.APPLICATION_JSON })
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public String getTransactionData(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId, public Collection<TellerTransactionData> getTransactionData(
@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId,
@QueryParam("dateRange") @Parameter(description = "dateRange") final String dateRange) { @QueryParam("dateRange") @Parameter(description = "dateRange") final String dateRange) {
final DateRange dateRangeHolder = DateRange.fromString(dateRange); final DateRange dateRangeHolder = DateRange.fromString(dateRange);
final Collection<TellerTransactionData> transactions = this.readPlatformService.fetchTellerTransactionsByTellerId(tellerId, return this.readPlatformService.fetchTellerTransactionsByTellerId(tellerId, dateRangeHolder.getStartDate(),
dateRangeHolder.getStartDate(), dateRangeHolder.getEndDate()); dateRangeHolder.getEndDate());
return this.jsonSerializer.serialize(transactions);
} }
@GET @GET
@Path("{tellerId}/transactions/{transactionId}") @Path("{tellerId}/transactions/{transactionId}")
@Consumes({ MediaType.TEXT_HTML, MediaType.APPLICATION_JSON }) @Consumes({ MediaType.TEXT_HTML, MediaType.APPLICATION_JSON })
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public String findTransactionData(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerid, public TellerTransactionData findTransactionData(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerid,
@PathParam("transactionId") @Parameter(description = "transactionId") final Long transactionId) { @PathParam("transactionId") @Parameter(description = "transactionId") final Long transactionId) {
final TellerTransactionData transaction = this.readPlatformService.findTellerTransaction(transactionId); return this.readPlatformService.findTellerTransaction(transactionId);
return this.jsonSerializer.serialize(transaction);
} }
@GET @GET
@Path("{tellerId}/journals") @Path("{tellerId}/journals")
@Consumes({ MediaType.TEXT_HTML, MediaType.APPLICATION_JSON }) @Consumes({ MediaType.TEXT_HTML, MediaType.APPLICATION_JSON })
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
public String getJournalData(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId, public Collection<TellerJournalData> getJournalData(@PathParam("tellerId") @Parameter(description = "tellerId") final Long tellerId,
@QueryParam("cashierId") @Parameter(description = "cashierId") final Long cashierDate, @QueryParam("cashierId") @Parameter(description = "cashierId") final Long cashierDate,
@QueryParam("dateRange") @Parameter(description = "dateRange") final String dateRange) { @QueryParam("dateRange") @Parameter(description = "dateRange") final String dateRange) {
final DateRange dateRangeHolder = DateRange.fromString(dateRange); final DateRange dateRangeHolder = DateRange.fromString(dateRange);
final Collection<TellerJournalData> journals = this.readPlatformService.fetchTellerJournals(tellerId, cashierDate, return this.readPlatformService.fetchTellerJournals(tellerId, cashierDate, dateRangeHolder.getStartDate(),
dateRangeHolder.getStartDate(), dateRangeHolder.getEndDate()); dateRangeHolder.getEndDate());
return this.jsonSerializer.serialize(journals);
}
private static final class CashiersForTeller {
public Long tellerId;
public String tellerName;
public Long officeId;
public String officeName;
public Collection<CashierData> cashiers;
} }
} }
@@ -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.organisation.teller.domain.model;
import java.io.Serializable;
import java.util.Collection;
import org.apache.fineract.organisation.teller.data.CashierData;
public record CashiersForTeller(Long tellerId, String tellerName, Long officeId, String officeName,
Collection<CashierData> cashiers) implements Serializable {
}
@@ -0,0 +1,44 @@
/**
* 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.organisation.teller.domain.model.request;
import java.io.Serial;
import java.io.Serializable;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class CashierRequest implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private String description;
private Boolean isFullDay;
private Long staffId;
private String dateFormat;
private String startDate;
private String endDate;
private String locale;
private String hourStartTime;
private String minStartTime;
private String hourEndTime;
private String minEndTime;
}
@@ -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.organisation.teller.domain.model.request;
import java.io.Serial;
import java.io.Serializable;
import java.math.BigDecimal;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class CashierTransactionRequest implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
public String currencyCode;
public BigDecimal txnAmount;
public String txnNote;
public String locale;
public String dateFormat;
public String txnDate;
}
@@ -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.organisation.teller.domain.model.request;
import java.io.Serial;
import java.io.Serializable;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
public class TellerRequest implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private Integer officeId;
private String name;
private String description;
private String startDate;
private String endDate;
private Integer status;
private String dateFormat;
private String locale;
}
@@ -68,6 +68,7 @@ public final class TellerCommandFromApiJsonDeserializer {
public static final String TXN_DATE = "txnDate"; public static final String TXN_DATE = "txnDate";
public static final String TXN_NOTE = "txnNote"; public static final String TXN_NOTE = "txnNote";
public static final String TELLER = "teller"; public static final String TELLER = "teller";
private static final String START_TIME = "startTime";
/** /**
* The parameters supported for this command. * The parameters supported for this command.
*/ */
@@ -159,9 +160,9 @@ public final class TellerCommandFromApiJsonDeserializer {
if (!isFullDay) { if (!isFullDay) {
final String hourStartTime = this.fromApiJsonHelper.extractStringNamed(HOUR_START_TIME, element); final String hourStartTime = this.fromApiJsonHelper.extractStringNamed(HOUR_START_TIME, element);
baseDataValidator.reset().parameter("startTime").value(hourStartTime).notBlank(); baseDataValidator.reset().parameter(START_TIME).value(hourStartTime).notBlank();
final String minStartTime = this.fromApiJsonHelper.extractStringNamed(MIN_START_TIME, element); final String minStartTime = this.fromApiJsonHelper.extractStringNamed(MIN_START_TIME, element);
baseDataValidator.reset().parameter("startTime").value(minStartTime).notBlank(); baseDataValidator.reset().parameter(START_TIME).value(minStartTime).notBlank();
final String hourEndTime = this.fromApiJsonHelper.extractStringNamed(HOUR_END_TIME, element); final String hourEndTime = this.fromApiJsonHelper.extractStringNamed(HOUR_END_TIME, element);
baseDataValidator.reset().parameter(HOUR_END_TIME).value(hourEndTime).notBlank(); baseDataValidator.reset().parameter(HOUR_END_TIME).value(hourEndTime).notBlank();
final String minEndTime = this.fromApiJsonHelper.extractStringNamed(MIN_END_TIME, element); final String minEndTime = this.fromApiJsonHelper.extractStringNamed(MIN_END_TIME, element);
@@ -34,6 +34,7 @@ import org.apache.fineract.infrastructure.core.service.PaginationHelper;
import org.apache.fineract.infrastructure.core.service.SearchParameters; import org.apache.fineract.infrastructure.core.service.SearchParameters;
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator; import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.infrastructure.security.utils.ColumnValidator; import org.apache.fineract.infrastructure.security.utils.ColumnValidator;
import org.apache.fineract.organisation.monetary.data.CurrencyData; import org.apache.fineract.organisation.monetary.data.CurrencyData;
import org.apache.fineract.organisation.monetary.service.CurrencyReadPlatformService; import org.apache.fineract.organisation.monetary.service.CurrencyReadPlatformService;
@@ -70,6 +71,7 @@ public class TellerManagementReadPlatformServiceImpl implements TellerManagement
private final DatabaseSpecificSQLGenerator sqlGenerator; private final DatabaseSpecificSQLGenerator sqlGenerator;
private final PaginationHelper paginationHelper; private final PaginationHelper paginationHelper;
private final ColumnValidator columnValidator; private final ColumnValidator columnValidator;
private final SqlValidator sqlValidator;
private static final class TellerMapper implements RowMapper<TellerData> { private static final class TellerMapper implements RowMapper<TellerData> {
@@ -399,6 +401,8 @@ public class TellerManagementReadPlatformServiceImpl implements TellerManagement
public CashierTransactionsWithSummaryData retrieveCashierTransactionsWithSummary(final Long cashierId, final boolean includeAllTellers, public CashierTransactionsWithSummaryData retrieveCashierTransactionsWithSummary(final Long cashierId, final boolean includeAllTellers,
final LocalDate fromDate, final LocalDate toDate, final String currencyCode, final SearchParameters searchParameters) { final LocalDate fromDate, final LocalDate toDate, final String currencyCode, final SearchParameters searchParameters) {
sqlValidator.validate(searchParameters.getOrderBy());
sqlValidator.validate(searchParameters.getSortOrder());
final String nextDay = sqlGenerator.incrementDateByOneDay("c.end_date"); final String nextDay = sqlGenerator.incrementDateByOneDay("c.end_date");
final CashierTransactionSummaryMapper ctsm = new CashierTransactionSummaryMapper(); final CashierTransactionSummaryMapper ctsm = new CashierTransactionSummaryMapper();
@@ -442,6 +446,8 @@ public class TellerManagementReadPlatformServiceImpl implements TellerManagement
public Page<CashierTransactionData> retrieveCashierTransactions(final Long cashierId, final boolean includeAllTellers, public Page<CashierTransactionData> retrieveCashierTransactions(final Long cashierId, final boolean includeAllTellers,
final LocalDate fromDate, final LocalDate toDate, final String currencyCode, final SearchParameters searchParameters) { final LocalDate fromDate, final LocalDate toDate, final String currencyCode, final SearchParameters searchParameters) {
sqlValidator.validate(searchParameters.getOrderBy());
sqlValidator.validate(searchParameters.getSortOrder());
final String nextDay = sqlGenerator.incrementDateByOneDay("c.end_date"); final String nextDay = sqlGenerator.incrementDateByOneDay("c.end_date");
final CashierTransactionMapper ctm = new CashierTransactionMapper(); final CashierTransactionMapper ctm = new CashierTransactionMapper();
@@ -23,6 +23,7 @@ import org.apache.fineract.accounting.journalentry.domain.JournalEntryRepository
import org.apache.fineract.infrastructure.core.service.PaginationHelper; import org.apache.fineract.infrastructure.core.service.PaginationHelper;
import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator; import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator;
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.infrastructure.security.service.SqlValidator;
import org.apache.fineract.infrastructure.security.utils.ColumnValidator; import org.apache.fineract.infrastructure.security.utils.ColumnValidator;
import org.apache.fineract.organisation.monetary.service.CurrencyReadPlatformService; import org.apache.fineract.organisation.monetary.service.CurrencyReadPlatformService;
import org.apache.fineract.organisation.office.domain.OfficeRepositoryWrapper; import org.apache.fineract.organisation.office.domain.OfficeRepositoryWrapper;
@@ -51,9 +52,10 @@ public class OrganisationTellerConfiguration {
public TellerManagementReadPlatformService tellerManagementReadPlatformService(JdbcTemplate jdbcTemplate, public TellerManagementReadPlatformService tellerManagementReadPlatformService(JdbcTemplate jdbcTemplate,
PlatformSecurityContext context, OfficeReadPlatformService officeReadPlatformService, PlatformSecurityContext context, OfficeReadPlatformService officeReadPlatformService,
StaffReadPlatformService staffReadPlatformService, CurrencyReadPlatformService currencyReadPlatformService, StaffReadPlatformService staffReadPlatformService, CurrencyReadPlatformService currencyReadPlatformService,
DatabaseSpecificSQLGenerator sqlGenerator, PaginationHelper paginationHelper, ColumnValidator columnValidator) { DatabaseSpecificSQLGenerator sqlGenerator, PaginationHelper paginationHelper, ColumnValidator columnValidator,
SqlValidator sqlValidator) {
return new TellerManagementReadPlatformServiceImpl(jdbcTemplate, context, officeReadPlatformService, staffReadPlatformService, return new TellerManagementReadPlatformServiceImpl(jdbcTemplate, context, officeReadPlatformService, staffReadPlatformService,
currencyReadPlatformService, sqlGenerator, paginationHelper, columnValidator); currencyReadPlatformService, sqlGenerator, paginationHelper, columnValidator, sqlValidator);
} }
@Bean @Bean