test: cover transaction ordering
This commit is contained in:
@@ -1,5 +1,11 @@
|
|||||||
# Changelog
|
# 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
|
## [Backend 0.9.0] - 2026-08-20
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@family-budget/backend",
|
"name": "@family-budget/backend",
|
||||||
"version": "0.9.0",
|
"version": "0.9.1",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "tsx watch src/app.ts",
|
"dev": "tsx watch src/app.ts",
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
"test:analytics": "tsx src/services/analyticsSemantics.test.ts",
|
"test:analytics": "tsx src/services/analyticsSemantics.test.ts",
|
||||||
"test:portfolio": "tsx src/services/portfolio.test.ts",
|
"test:portfolio": "tsx src/services/portfolio.test.ts",
|
||||||
"test:portfolio:db": "NODE_ENV=test tsx src/services/portfolio.integration.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: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:import:db": "NODE_ENV=test tsx src/services/import.integration.test.ts",
|
||||||
"test:llm": "tsx src/scripts/testLlm.ts"
|
"test:llm": "tsx src/scripts/testLlm.ts"
|
||||||
|
|||||||
13
backend/src/services/transactions.test.ts
Normal file
13
backend/src/services/transactions.test.ts
Normal file
@@ -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');
|
||||||
@@ -7,16 +7,18 @@ import type {
|
|||||||
UpdateTransactionRequest,
|
UpdateTransactionRequest,
|
||||||
} from '@family-budget/shared';
|
} 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(
|
export async function getTransactions(
|
||||||
params: GetTransactionsParams,
|
params: GetTransactionsParams,
|
||||||
): Promise<PaginatedResponse<Transaction>> {
|
): Promise<PaginatedResponse<Transaction>> {
|
||||||
const page = params.page ?? 1;
|
const page = params.page ?? 1;
|
||||||
const pageSize = [10, 50, 100].includes(params.pageSize ?? 50) ? (params.pageSize ?? 50) : 50;
|
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 orderBy = transactionOrderBy(params.sortBy === 'amount' ? 'amount' : 'date', params.sortOrder === 'asc' ? 'asc' : 'desc');
|
||||||
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 conditions: string[] = [];
|
const conditions: string[] = [];
|
||||||
const values: unknown[] = [];
|
const values: unknown[] = [];
|
||||||
|
|||||||
Reference in New Issue
Block a user