From 669e54f6cb3f7c4c0f265b4cff221e8d40dd45e9 Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 20 Aug 2026 23:24:24 +0300 Subject: [PATCH] test: cover transaction ordering --- CHANGELOG.md | 6 ++++++ backend/package.json | 3 ++- backend/src/services/transactions.test.ts | 13 +++++++++++++ backend/src/services/transactions.ts | 12 +++++++----- 4 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 backend/src/services/transactions.test.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 2eecf93..8ab6fd5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## [Backend 0.9.1] - 2026-08-20 + +### Added + +- Added runnable coverage for date and amount sorting tie-breakers. + ## [Backend 0.9.0] - 2026-08-20 ### Added diff --git a/backend/package.json b/backend/package.json index e18aaec..22b01bc 100644 --- a/backend/package.json +++ b/backend/package.json @@ -1,6 +1,6 @@ { "name": "@family-budget/backend", - "version": "0.9.0", + "version": "0.9.1", "private": true, "scripts": { "dev": "tsx watch src/app.ts", @@ -11,6 +11,7 @@ "test:analytics": "tsx src/services/analyticsSemantics.test.ts", "test:portfolio": "tsx src/services/portfolio.test.ts", "test:portfolio:db": "NODE_ENV=test tsx src/services/portfolio.integration.test.ts", + "test:transactions": "tsx src/services/transactions.test.ts", "test:analytics:db": "NODE_ENV=test tsx src/services/analytics.integration.test.ts", "test:import:db": "NODE_ENV=test tsx src/services/import.integration.test.ts", "test:llm": "tsx src/scripts/testLlm.ts" diff --git a/backend/src/services/transactions.test.ts b/backend/src/services/transactions.test.ts new file mode 100644 index 0000000..0fbffb5 --- /dev/null +++ b/backend/src/services/transactions.test.ts @@ -0,0 +1,13 @@ +import assert from 'node:assert/strict'; +import { transactionOrderBy } from './transactions'; + +assert.equal( + transactionOrderBy('date', 'desc'), + 't.operation_at DESC, t.source_position ASC, t.id ASC', +); +assert.equal( + transactionOrderBy('date', 'asc'), + 't.operation_at ASC, t.source_position DESC, t.id DESC', +); +assert.match(transactionOrderBy('amount', 'desc'), /t\.amount_signed DESC.*t\.operation_at DESC.*t\.source_position ASC.*t\.id DESC/); +console.log('transaction ordering: OK'); diff --git a/backend/src/services/transactions.ts b/backend/src/services/transactions.ts index 2d32a91..77f68f7 100644 --- a/backend/src/services/transactions.ts +++ b/backend/src/services/transactions.ts @@ -7,16 +7,18 @@ import type { UpdateTransactionRequest, } from '@family-budget/shared'; +export function transactionOrderBy(sortBy: 'date' | 'amount', sortOrder: 'asc' | 'desc'): string { + const direction = sortOrder === 'asc' ? 'ASC' : 'DESC'; + if (sortBy === 'amount') return `t.amount_signed ${direction}, t.operation_at DESC, t.source_position ASC, t.id DESC`; + return `t.operation_at ${direction}, t.source_position ${direction === 'ASC' ? 'DESC' : 'ASC'}, t.id ${direction === 'ASC' ? 'DESC' : 'ASC'}`; +} + export async function getTransactions( params: GetTransactionsParams, ): Promise> { const page = params.page ?? 1; const pageSize = [10, 50, 100].includes(params.pageSize ?? 50) ? (params.pageSize ?? 50) : 50; - const sortBy = params.sortBy === 'amount' ? 't.amount_signed' : 't.operation_at'; - const sortOrder = params.sortOrder === 'asc' ? 'ASC' : 'DESC'; - const orderBy = params.sortBy === 'amount' - ? `${sortBy} ${sortOrder}, t.operation_at DESC, t.source_position ASC, t.id DESC` - : `t.operation_at ${sortOrder}, t.source_position ${sortOrder === 'ASC' ? 'DESC' : 'ASC'}, t.id ${sortOrder === 'ASC' ? 'DESC' : 'ASC'}`; + const orderBy = transactionOrderBy(params.sortBy === 'amount' ? 'amount' : 'date', params.sortOrder === 'asc' ? 'asc' : 'desc'); const conditions: string[] = []; const values: unknown[] = [];