const Country = require('../../models/Country'); const { VatRate, VatRateHistory, VAT_FIELDS } = require('../../models/Tax'); class TaxRepository { constructor(uow) { this.uow = uow; this.conn = uow.getConnection(); } async upsertCountries(countries, actorUserId) { let created = 0; let updated = 0; for (const c of countries) { const [res] = await this.conn.query( `INSERT INTO countries (country_code, country_name, created_by, updated_by) VALUES (?, ?, ?, ?) ON DUPLICATE KEY UPDATE country_name=VALUES(country_name), updated_by=VALUES(updated_by), updated_at=CURRENT_TIMESTAMP`, [c.code, c.name, actorUserId || null, actorUserId || null] ); if (res.affectedRows === 1) created += 1; if (res.affectedRows === 2) updated += 1; } return { created, updated }; } async getCountriesByCodes(codes) { if (!codes.length) return {}; const [rows] = await this.conn.query( `SELECT * FROM countries WHERE country_code IN (${codes.map(() => '?').join(',')})`, codes ); const map = {}; rows.forEach((r) => { map[r.country_code] = new Country(r); }); return map; } async getCountryByCode(code) { const [rows] = await this.conn.query(`SELECT * FROM countries WHERE country_code = ? LIMIT 1`, [code]); return rows[0] ? new Country(rows[0]) : null; } async getAllCurrentVatRates() { const [rows] = await this.conn.query( `SELECT c.*, vr.id AS vat_id, vr.standard_rate, vr.reduced_rate, vr.super_reduced_rate, vr.parking_rate, vr.effective_from FROM countries c LEFT JOIN vat_rates vr ON vr.country_id = c.id AND vr.effective_to IS NULL ORDER BY c.country_name ASC` ); return rows; } async getVatHistory(countryId) { const [rows] = await this.conn.query( `SELECT * FROM vat_rate_history WHERE country_id = ? ORDER BY effective_from DESC`, [countryId] ); return rows.map((r) => new VatRateHistory(r)); } async setCurrentVatRate(countryId, rates, actorUserId) { const [currentRows] = await this.conn.query( `SELECT * FROM vat_rates WHERE country_id = ? AND effective_to IS NULL LIMIT 1`, [countryId] ); const now = new Date(); const current = currentRows[0] ? new VatRate(currentRows[0]) : null; const areEqual = current && VAT_FIELDS.every((k) => { const a = current[k] == null ? null : Number(current[k]); const b = rates[k] == null ? null : Number(rates[k]); return (a === null && b === null) || a === b; }); if (areEqual) return { changed: false, skipped: true }; if (current) { await this.conn.query( `INSERT INTO vat_rate_history (country_id, standard_rate, reduced_rate, super_reduced_rate, parking_rate, effective_from, effective_to, created_by, updated_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [ countryId, current.standard_rate, current.reduced_rate, current.super_reduced_rate, current.parking_rate, current.effective_from, now, actorUserId || current.created_by || null, actorUserId || current.updated_by || null ] ); await this.conn.query( `UPDATE vat_rates SET effective_to = ?, updated_by = ? WHERE id = ?`, [now, actorUserId || null, current.id] ); } await this.conn.query( `INSERT INTO vat_rates (country_id, standard_rate, reduced_rate, super_reduced_rate, parking_rate, effective_from, effective_to, created_by, updated_by) VALUES (?, ?, ?, ?, ?, ?, NULL, ?, ?)`, [ countryId, rates.standard_rate, rates.reduced_rate, rates.super_reduced_rate, rates.parking_rate, now, actorUserId || null, actorUserId || null ] ); return { changed: true, skipped: false }; } async bulkImportVatRates(entries, actorUserId) { let ratesUpdated = 0; let ratesSkipped = 0; for (const entry of entries) { const res = await this.setCurrentVatRate(entry.country_id, entry.rates, actorUserId); if (res.changed) ratesUpdated += 1; if (res.skipped) ratesSkipped += 1; } return { ratesUpdated, ratesSkipped }; } } module.exports = TaxRepository;