cash-only registers, day book sections and DD amendments
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-2) (push) Canceled after 0s
Fineract Docker Builds / build (false, docker-compose-postgresql.yml, postgresql) (push) Canceled after 0s
Fineract Docker Builds / build (true, docker-compose.yml, mariadb) (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 2 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 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 Cargo & Unit- & Integration tests - MariaDB / test (test-core-1) (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 - PostgreSQL / test (test-core-3) (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 - 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-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-5) (push) Canceled after 0s
Fineract Liquibase Only mode - PostgreSQL / test (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 Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-1) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-2) (push) Canceled after 0s
Fineract Docker Builds / build (false, docker-compose-postgresql.yml, postgresql) (push) Canceled after 0s
Fineract Docker Builds / build (true, docker-compose.yml, mariadb) (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 2 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 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 Cargo & Unit- & Integration tests - MariaDB / test (test-core-1) (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 - PostgreSQL / test (test-core-3) (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 - 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-4) (push) Canceled after 0s
Fineract Cargo & Unit- & Integration tests - PostgreSQL / test (test-core-5) (push) Canceled after 0s
Fineract Liquibase Only mode - PostgreSQL / test (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
Cashier reports now reconcile against the drawer: - Received/Payment exclude what cannot be cash rather than admitting only proven cash, so registers that pay out without recording a denomination breakdown are no longer silently dropped - Closing report scoped to the cashier, with opening/closing balance, reversed counter transactions excluded, and cash DD receipts counted - Day book split into Cashier and Clerk sections, filed by whose cash moved rather than who raised the request Fixed one deposit or withdrawal raising two vouchers: the cashier deposit and clerk withdrawal registers did not suppress the inner savings command's voucher, doubling the day's cash on both reports. Sponsor DD: - Amendment request flow (beneficiary, payable-at branch and city) under maker-checker; face value and funding stay unamendable - Cash DD denominations were collected but never saved, and the amount check demanded a figure notes could not add to; both fixed and the breakdown is now required Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
-- Removes the duplicate vouchers left behind by the double-count bug.
|
||||
--
|
||||
-- Until 2026-09-03 the cashier deposit and clerk withdrawal registers did not wrap their inner
|
||||
-- savings command in VoucherService.withOwnVoucher(...), so one counter transaction raised two
|
||||
-- vouchers over the same money: the register's own (CASHIER_DEPOSIT_REQUEST / CLERK_WITHDRAWAL_
|
||||
-- REQUEST) and a second one from the savings command (SAVINGS_TRANSACTION). The cashier's Received
|
||||
-- and Payment reports counted both, doubling the day's cash.
|
||||
--
|
||||
-- The code is fixed, so no new duplicates are created. This clears the ones already recorded.
|
||||
--
|
||||
-- WHICH ONE IS DELETED: the SAVINGS_TRANSACTION voucher. The register's voucher is the keeper --
|
||||
-- it is the one the register owns, attaches its DR/CR lines to, and stamps onto
|
||||
-- m_savings_account_transaction.voucher_no. Deleting the register's voucher instead would break
|
||||
-- that link and orphan the request row.
|
||||
--
|
||||
-- Run: psql -h localhost -U postgres -d fineract_default -v ON_ERROR_STOP=1 -f cleanup_duplicate_vouchers.sql
|
||||
|
||||
BEGIN;
|
||||
|
||||
-- The duplicates: a SAVINGS_TRANSACTION voucher whose transaction is already claimed by a
|
||||
-- register voucher. Matching through savings_txn_id rather than by date or amount so that two
|
||||
-- genuinely separate transactions of the same value on the same day are never confused.
|
||||
CREATE TEMP TABLE dup_vouchers ON COMMIT DROP AS
|
||||
SELECT sav.voucher_no
|
||||
FROM m_voucher sav
|
||||
JOIN m_voucher reg
|
||||
ON reg.savings_txn_id = sav.reference_id
|
||||
AND reg.reference_type IN ('CLERK_WITHDRAWAL_REQUEST', 'CASHIER_DEPOSIT_REQUEST')
|
||||
WHERE sav.reference_type = 'SAVINGS_TRANSACTION'
|
||||
AND sav.voucher_type IN ('DEPOSIT', 'WITHDRAWAL');
|
||||
|
||||
-- Refuse to run if anything else has attached itself to a voucher about to be deleted: a
|
||||
-- verification or an attachment means someone acted on that slip, and it must be looked at by hand
|
||||
-- rather than removed silently.
|
||||
DO $$
|
||||
DECLARE
|
||||
blocked INT;
|
||||
BEGIN
|
||||
SELECT COUNT(*) INTO blocked
|
||||
FROM (SELECT voucher_no FROM m_voucher_verification
|
||||
WHERE voucher_no IN (SELECT voucher_no FROM dup_vouchers)
|
||||
UNION ALL
|
||||
SELECT voucher_no FROM m_voucher_attachment
|
||||
WHERE voucher_no IN (SELECT voucher_no FROM dup_vouchers)) x;
|
||||
IF blocked > 0 THEN
|
||||
RAISE EXCEPTION 'Aborting: % duplicate voucher(s) carry a verification or attachment. Review these by hand.', blocked;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
-- Likewise refuse if a savings transaction is stamped with a voucher about to be deleted. It should
|
||||
-- carry the register's number, not the duplicate's; if it does not, the pair needs looking at.
|
||||
DO $$
|
||||
DECLARE
|
||||
stamped INT;
|
||||
BEGIN
|
||||
SELECT COUNT(*) INTO stamped FROM m_savings_account_transaction
|
||||
WHERE voucher_no IN (SELECT voucher_no FROM dup_vouchers);
|
||||
IF stamped > 0 THEN
|
||||
RAISE EXCEPTION 'Aborting: % savings transaction(s) are stamped with a duplicate voucher number.', stamped;
|
||||
END IF;
|
||||
END $$;
|
||||
|
||||
SELECT voucher_no AS "about to delete" FROM dup_vouchers ORDER BY voucher_no;
|
||||
|
||||
DELETE FROM m_voucher_line WHERE voucher_no IN (SELECT voucher_no FROM dup_vouchers);
|
||||
DELETE FROM m_voucher WHERE voucher_no IN (SELECT voucher_no FROM dup_vouchers);
|
||||
|
||||
COMMIT;
|
||||
Reference in New Issue
Block a user