fix: make broker XLSX import atomic
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import crypto from 'crypto';
|
||||
import type { PoolClient } from 'pg';
|
||||
import { pool } from '../db/pool';
|
||||
import type { ImportPortfolioResponse, PortfolioFile, PortfolioTrade } from '@family-budget/shared';
|
||||
|
||||
@@ -45,13 +46,14 @@ export function validatePortfolio(body: unknown): asserts body is PortfolioFile
|
||||
}
|
||||
}
|
||||
|
||||
export async function importPortfolio(body: unknown, db: Pick<typeof pool, 'connect'> = pool): Promise<ImportPortfolioResponse> {
|
||||
export async function importPortfolio(body: unknown, db: Pick<typeof pool, 'connect'> = pool, transactionClient?: PoolClient): Promise<ImportPortfolioResponse> {
|
||||
validatePortfolio(body);
|
||||
const data = body;
|
||||
const sourceHash = crypto.createHash('sha256').update(JSON.stringify(data)).digest('hex');
|
||||
const client = await db.connect();
|
||||
const client = transactionClient ?? await db.connect();
|
||||
const ownsTransaction = transactionClient == null;
|
||||
try {
|
||||
await client.query('BEGIN');
|
||||
if (ownsTransaction) await client.query('BEGIN');
|
||||
const accountResult = await client.query(
|
||||
`INSERT INTO accounts (bank, account_number, currency, account_type)
|
||||
VALUES ($1, $2, 'RUB', 'brokerage')
|
||||
@@ -69,7 +71,7 @@ export async function importPortfolio(body: unknown, db: Pick<typeof pool, 'conn
|
||||
);
|
||||
if (reportResult.rows.length === 0) {
|
||||
const existing = await client.query('SELECT id FROM portfolio_reports WHERE account_id = $1 AND source_hash = $2', [accountId, sourceHash]);
|
||||
await client.query('COMMIT');
|
||||
if (ownsTransaction) await client.query('COMMIT');
|
||||
return { accountId, reportId: Number(existing.rows[0].id), importedTrades: 0, duplicateTrades: data.trades.length, positions: 0 };
|
||||
}
|
||||
const reportId = Number(reportResult.rows[0].id);
|
||||
@@ -92,12 +94,12 @@ export async function importPortfolio(body: unknown, db: Pick<typeof pool, 'conn
|
||||
);
|
||||
importedTrades += result.rowCount ?? 0;
|
||||
}
|
||||
await client.query('COMMIT');
|
||||
if (ownsTransaction) await client.query('COMMIT');
|
||||
return { accountId, reportId, importedTrades, duplicateTrades: data.trades.length - importedTrades, positions: data.positions.length };
|
||||
} catch (error) {
|
||||
await client.query('ROLLBACK');
|
||||
if (ownsTransaction) await client.query('ROLLBACK');
|
||||
throw error;
|
||||
} finally {
|
||||
client.release();
|
||||
if (ownsTransaction) client.release();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user