import { Pool } from 'pg'; import pool from '../../../core/config/database'; import type { OwnershipCost, OwnershipCostType } from '../domain/ownership-costs.types'; export class OwnershipCostsRepository { constructor(private readonly db: Pool = pool) {} // ======================== // Row Mappers // ======================== private mapRow(row: any): OwnershipCost { return { id: row.id, userId: row.user_id, vehicleId: row.vehicle_id, documentId: row.document_id, costType: row.cost_type, // node-postgres returns numeric/decimal columns as strings; coerce to honor the number type. amount: Number(row.amount), description: row.description, periodStart: row.period_start, periodEnd: row.period_end, notes: row.notes, createdAt: row.created_at, updatedAt: row.updated_at }; } // ======================== // CRUD Operations // ======================== async insert(cost: { id: string; userId: string; vehicleId: string; documentId?: string | null; costType: OwnershipCostType; amount: number; description?: string | null; periodStart?: string | null; periodEnd?: string | null; notes?: string | null; }): Promise { const res = await this.db.query( `INSERT INTO ownership_costs ( id, user_id, vehicle_id, document_id, cost_type, amount, description, period_start, period_end, notes ) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING *`, [ cost.id, cost.userId, cost.vehicleId, cost.documentId ?? null, cost.costType, cost.amount, cost.description ?? null, cost.periodStart ?? null, cost.periodEnd ?? null, cost.notes ?? null, ] ); return this.mapRow(res.rows[0]); } async findById(id: string, userId: string): Promise { const res = await this.db.query( `SELECT * FROM ownership_costs WHERE id = $1 AND user_id = $2`, [id, userId] ); return res.rows[0] ? this.mapRow(res.rows[0]) : null; } async findByUserId( userId: string, filters?: { vehicleId?: string; costType?: OwnershipCostType; documentId?: string } ): Promise { const conds: string[] = ['user_id = $1']; const params: any[] = [userId]; let i = 2; if (filters?.vehicleId) { conds.push(`vehicle_id = $${i++}`); params.push(filters.vehicleId); } if (filters?.costType) { conds.push(`cost_type = $${i++}`); params.push(filters.costType); } if (filters?.documentId) { conds.push(`document_id = $${i++}`); params.push(filters.documentId); } const sql = `SELECT * FROM ownership_costs WHERE ${conds.join(' AND ')} ORDER BY period_start DESC, created_at DESC`; const res = await this.db.query(sql, params); return res.rows.map(row => this.mapRow(row)); } async findByVehicleId(vehicleId: string, userId: string): Promise { const res = await this.db.query( `SELECT * FROM ownership_costs WHERE vehicle_id = $1 AND user_id = $2 ORDER BY period_start DESC, created_at DESC`, [vehicleId, userId] ); return res.rows.map(row => this.mapRow(row)); } async update( id: string, userId: string, patch: Partial> ): Promise { const fields: string[] = []; const params: any[] = []; let i = 1; if (patch.documentId !== undefined) { fields.push(`document_id = $${i++}`); params.push(patch.documentId); } if (patch.costType !== undefined) { fields.push(`cost_type = $${i++}`); params.push(patch.costType); } if (patch.amount !== undefined) { fields.push(`amount = $${i++}`); params.push(patch.amount); } if (patch.description !== undefined) { fields.push(`description = $${i++}`); params.push(patch.description); } if (patch.periodStart !== undefined) { fields.push(`period_start = $${i++}`); params.push(patch.periodStart); } if (patch.periodEnd !== undefined) { fields.push(`period_end = $${i++}`); params.push(patch.periodEnd); } if (patch.notes !== undefined) { fields.push(`notes = $${i++}`); params.push(patch.notes); } if (!fields.length) return this.findById(id, userId); params.push(id, userId); const sql = `UPDATE ownership_costs SET ${fields.join(', ')} WHERE id = $${i++} AND user_id = $${i++} RETURNING *`; const res = await this.db.query(sql, params); return res.rows[0] ? this.mapRow(res.rows[0]) : null; } async delete(id: string, userId: string): Promise { await this.db.query( `DELETE FROM ownership_costs WHERE id = $1 AND user_id = $2`, [id, userId] ); } }