diff --git a/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/starter/OrganisationTellerConfiguration.java b/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/starter/OrganisationTellerConfiguration.java index 87136fa0c..e78b4a99a 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/starter/OrganisationTellerConfiguration.java +++ b/fineract-provider/src/main/java/org/apache/fineract/organisation/teller/starter/OrganisationTellerConfiguration.java @@ -1,71 +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.organisation.teller.starter; - -import org.apache.fineract.accounting.financialactivityaccount.domain.FinancialActivityAccountRepositoryWrapper; -import org.apache.fineract.accounting.journalentry.domain.JournalEntryRepository; -import org.apache.fineract.infrastructure.core.service.PaginationHelper; -import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator; -import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; -import org.apache.fineract.infrastructure.security.service.SqlValidator; -import org.apache.fineract.organisation.monetary.service.CurrencyReadPlatformService; -import org.apache.fineract.organisation.office.domain.OfficeRepositoryWrapper; -import org.apache.fineract.organisation.office.service.OfficeReadPlatformService; -import org.apache.fineract.organisation.staff.domain.StaffRepository; -import org.apache.fineract.organisation.staff.service.StaffReadPlatformService; -import org.apache.fineract.organisation.teller.data.CashierTransactionDataValidator; -import org.apache.fineract.organisation.teller.domain.CashierRepository; -import org.apache.fineract.organisation.teller.domain.CashierTransactionRepository; -import org.apache.fineract.organisation.teller.domain.TellerRepositoryWrapper; -import org.apache.fineract.organisation.teller.serialization.TellerCommandFromApiJsonDeserializer; -import org.apache.fineract.organisation.teller.service.TellerManagementReadPlatformService; -import org.apache.fineract.organisation.teller.service.TellerManagementReadPlatformServiceImpl; -import org.apache.fineract.organisation.teller.service.TellerWritePlatformService; -import org.apache.fineract.organisation.teller.service.TellerWritePlatformServiceJpaImpl; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.jdbc.core.JdbcTemplate; - -@Configuration -public class OrganisationTellerConfiguration { - - @Bean - @ConditionalOnMissingBean(TellerManagementReadPlatformService.class) - public TellerManagementReadPlatformService tellerManagementReadPlatformService(JdbcTemplate jdbcTemplate, - PlatformSecurityContext context, OfficeReadPlatformService officeReadPlatformService, - StaffReadPlatformService staffReadPlatformService, CurrencyReadPlatformService currencyReadPlatformService, - DatabaseSpecificSQLGenerator sqlGenerator, PaginationHelper paginationHelper, SqlValidator sqlValidator) { - return new TellerManagementReadPlatformServiceImpl(jdbcTemplate, context, officeReadPlatformService, staffReadPlatformService, - currencyReadPlatformService, sqlGenerator, paginationHelper, sqlValidator); - } - - @Bean - @ConditionalOnMissingBean(TellerWritePlatformService.class) - public TellerWritePlatformService tellerWritePlatformService(PlatformSecurityContext context, - TellerCommandFromApiJsonDeserializer fromApiJsonDeserializer, TellerRepositoryWrapper tellerRepositoryWrapper, - OfficeRepositoryWrapper officeRepositoryWrapper, StaffRepository staffRepository, CashierRepository cashierRepository, - CashierTransactionRepository cashierTxnRepository, JournalEntryRepository glJournalEntryRepository, - FinancialActivityAccountRepositoryWrapper financialActivityAccountRepositoryWrapper, - CashierTransactionDataValidator cashierTransactionDataValidator) { - return new TellerWritePlatformServiceJpaImpl(context, fromApiJsonDeserializer, tellerRepositoryWrapper, officeRepositoryWrapper, - staffRepository, cashierRepository, cashierTxnRepository, glJournalEntryRepository, - financialActivityAccountRepositoryWrapper, cashierTransactionDataValidator); - } -} +/** + * 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.starter; + +import org.apache.fineract.infrastructure.core.service.PaginationHelper; +import org.apache.fineract.infrastructure.core.service.database.DatabaseSpecificSQLGenerator; +import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext; +import org.apache.fineract.infrastructure.security.service.SqlValidator; +import org.apache.fineract.organisation.monetary.service.CurrencyReadPlatformService; +import org.apache.fineract.organisation.office.domain.OfficeRepositoryWrapper; +import org.apache.fineract.organisation.office.service.OfficeReadPlatformService; +import org.apache.fineract.organisation.staff.domain.StaffRepository; +import org.apache.fineract.organisation.staff.service.StaffReadPlatformService; +import org.apache.fineract.organisation.teller.data.CashierTransactionDataValidator; +import org.apache.fineract.organisation.teller.domain.CashierRepository; +import org.apache.fineract.organisation.teller.domain.CashierTransactionRepository; +import org.apache.fineract.organisation.teller.domain.TellerRepositoryWrapper; +import org.apache.fineract.organisation.teller.serialization.TellerCommandFromApiJsonDeserializer; +import org.apache.fineract.organisation.teller.service.TellerManagementReadPlatformService; +import org.apache.fineract.organisation.teller.service.TellerManagementReadPlatformServiceImpl; +import org.apache.fineract.organisation.teller.service.TellerWritePlatformService; +import org.apache.fineract.organisation.teller.service.TellerWritePlatformServiceJpaImpl; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jdbc.core.JdbcTemplate; + +@Configuration +public class OrganisationTellerConfiguration { + + @Bean + @ConditionalOnMissingBean(TellerManagementReadPlatformService.class) + public TellerManagementReadPlatformService tellerManagementReadPlatformService(JdbcTemplate jdbcTemplate, + PlatformSecurityContext context, OfficeReadPlatformService officeReadPlatformService, + StaffReadPlatformService staffReadPlatformService, CurrencyReadPlatformService currencyReadPlatformService, + DatabaseSpecificSQLGenerator sqlGenerator, PaginationHelper paginationHelper, SqlValidator sqlValidator) { + return new TellerManagementReadPlatformServiceImpl(jdbcTemplate, context, officeReadPlatformService, staffReadPlatformService, + currencyReadPlatformService, sqlGenerator, paginationHelper, sqlValidator); + } + + @Bean + @ConditionalOnMissingBean(TellerWritePlatformService.class) + public TellerWritePlatformService tellerWritePlatformService(PlatformSecurityContext context, + TellerCommandFromApiJsonDeserializer fromApiJsonDeserializer, TellerRepositoryWrapper tellerRepositoryWrapper, + OfficeRepositoryWrapper officeRepositoryWrapper, StaffRepository staffRepository, CashierRepository cashierRepository, + CashierTransactionRepository cashierTxnRepository, + CashierTransactionDataValidator cashierTransactionDataValidator) { + return new TellerWritePlatformServiceJpaImpl(context, fromApiJsonDeserializer, tellerRepositoryWrapper, officeRepositoryWrapper, + staffRepository, cashierRepository, cashierTxnRepository, cashierTransactionDataValidator); + } +} diff --git a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashreport/api/CashReportApiResource.java b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashreport/api/CashReportApiResource.java index e17bacfb8..a89eb956f 100644 --- a/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashreport/api/CashReportApiResource.java +++ b/fineract-provider/src/main/java/org/apache/fineract/portfolio/cashreport/api/CashReportApiResource.java @@ -518,4 +518,81 @@ public class CashReportApiResource { entry[2] += count * sign; } } + + /** + * GET /cashreports/gl-entries?date=yyyy-MM-dd&cashierId=X&tellerId=Y + * Returns cashier transaction summary: voucher no, account no, + * account holder name, DR (withdrawal), CR (deposit). + * - cashierId: filter by specific cashier + * - tellerId: filter by all cashiers under a teller + * - neither: all cashier transactions for the date + */ + @GET + @Path("gl-entries") + public String glEntries(@QueryParam("date") String date, + @QueryParam("cashierId") Long cashierId, + @QueryParam("tellerId") Long tellerId) { + + final String txnDate = (date != null && !date.isBlank()) ? date : LocalDate.now().toString(); + + // Build cashier officer_id filter + String officerFilter; + Object[] params; + + if (cashierId != null) { + officerFilter = "AND std.officer_id IN (" + + "SELECT au.id FROM m_appuser au " + + "JOIN m_cashiers mc ON mc.staff_id = au.staff_id WHERE mc.id = ?)"; + params = new Object[] { txnDate, cashierId }; + } else if (tellerId != null) { + officerFilter = "AND std.officer_id IN (" + + "SELECT au.id FROM m_appuser au " + + "JOIN m_cashiers mc ON mc.staff_id = au.staff_id " + + "JOIN m_tellers mt ON mt.id = mc.teller_id WHERE mt.id = ?)"; + params = new Object[] { txnDate, tellerId }; + } else { + officerFilter = "AND std.officer_id IN (" + + "SELECT au.id FROM m_appuser au " + + "JOIN m_cashiers mc ON mc.staff_id = au.staff_id)"; + params = new Object[] { txnDate }; + } + + // One row per transaction — account no, account holder name, dr/cr amount + final String sql = "SELECT " + + " std.txn_id AS voucher_no, " + + " std.account_no AS ac_no, " + + " COALESCE(mc.display_name, '') AS ac_name, " + + " SUM(CASE WHEN std.txn_type = 'WITHDRAWAL' THEN std.total_amount ELSE 0 END) AS dr_amount, " + + " SUM(CASE WHEN std.txn_type = 'DEPOSIT' THEN std.total_amount ELSE 0 END) AS cr_amount " + + "FROM m_savings_txn_denomination std " + + "LEFT JOIN m_client mc ON mc.id = std.client_id " + + "WHERE std.txn_date = CAST(? AS DATE) " + + officerFilter + + " GROUP BY std.txn_id, std.account_no, mc.display_name " + + "ORDER BY std.txn_id"; + + List> rows = jdbcTemplate.query(sql, (rs, rowNum) -> { + Map row = new LinkedHashMap<>(); + row.put("voucherNo", rs.getLong("voucher_no")); + row.put("acNo", rs.getString("ac_no")); + row.put("acName", rs.getString("ac_name")); + row.put("dr", rs.getBigDecimal("dr_amount")); + row.put("cr", rs.getBigDecimal("cr_amount")); + return row; + }, params); + + java.math.BigDecimal totalDr = rows.stream() + .map(r -> (java.math.BigDecimal) r.get("dr")) + .reduce(java.math.BigDecimal.ZERO, java.math.BigDecimal::add); + java.math.BigDecimal totalCr = rows.stream() + .map(r -> (java.math.BigDecimal) r.get("cr")) + .reduce(java.math.BigDecimal.ZERO, java.math.BigDecimal::add); + + Map result = new LinkedHashMap<>(); + result.put("date", txnDate); + result.put("rows", rows); + result.put("totalDr", totalDr); + result.put("totalCr", totalCr); + return gson.toJson(result); + } }