/** * Regions Repository * Handles CRUD operations for provider regions */ import { BaseRepository } from './base'; import { Region, RegionInput, RepositoryError, ErrorCodes } from '../types'; export class RegionsRepository extends BaseRepository { protected tableName = 'regions'; protected allowedColumns = [ 'provider_id', 'region_code', 'region_name', 'country_code', 'latitude', 'longitude', 'available', ]; /** * Find all regions for a specific provider */ async findByProvider(providerId: number): Promise { try { const result = await this.db .prepare('SELECT * FROM regions WHERE provider_id = ?') .bind(providerId) .all(); return result.results; } catch (error) { this.logger.error('findByProvider failed', { providerId, error: error instanceof Error ? error.message : 'Unknown error' }); throw new RepositoryError( `Failed to find regions for provider: ${providerId}`, ErrorCodes.DATABASE_ERROR, error ); } } /** * Find a region by provider ID and region code */ async findByCode(providerId: number, code: string): Promise { try { const result = await this.db .prepare('SELECT * FROM regions WHERE provider_id = ? AND region_code = ?') .bind(providerId, code) .first(); return result || null; } catch (error) { this.logger.error('findByCode failed', { providerId, code, error: error instanceof Error ? error.message : 'Unknown error' }); throw new RepositoryError( `Failed to find region by code: ${code}`, ErrorCodes.DATABASE_ERROR, error ); } } /** * Bulk upsert regions for a provider * Uses batch operations for efficiency */ async upsertMany(providerId: number, regions: RegionInput[]): Promise { if (regions.length === 0) { return 0; } try { // Build upsert statements for each region const statements = regions.map((region) => { return this.db.prepare( `INSERT INTO regions ( provider_id, region_code, region_name, country_code, latitude, longitude, available ) VALUES (?, ?, ?, ?, ?, ?, ?) ON CONFLICT(provider_id, region_code) DO UPDATE SET region_name = excluded.region_name, country_code = excluded.country_code, latitude = excluded.latitude, longitude = excluded.longitude, available = excluded.available` ).bind( providerId, region.region_code, region.region_name, region.country_code || null, region.latitude || null, region.longitude || null, region.available ); }); // Count successful operations const successCount = await this.executeBatchCount(statements); this.logger.info('Upserted regions', { providerId, count: successCount }); return successCount; } catch (error) { this.logger.error('upsertMany failed', { providerId, count: regions.length, error: error instanceof Error ? error.message : 'Unknown error' }); throw new RepositoryError( `Failed to upsert regions for provider: ${providerId}`, ErrorCodes.TRANSACTION_FAILED, error ); } } /** * Get available regions only */ async findAvailable(providerId?: number): Promise { try { let query = 'SELECT * FROM regions WHERE available = 1'; const params: (string | number | boolean | null)[] = []; if (providerId !== undefined) { query += ' AND provider_id = ?'; params.push(providerId); } const result = await this.db .prepare(query) .bind(...params) .all(); return result.results; } catch (error) { this.logger.error('findAvailable failed', { providerId, error: error instanceof Error ? error.message : 'Unknown error' }); throw new RepositoryError( 'Failed to find available regions', ErrorCodes.DATABASE_ERROR, error ); } } /** * Update region availability status */ async updateAvailability(id: number, available: boolean): Promise { try { const result = await this.db .prepare('UPDATE regions SET available = ? WHERE id = ? RETURNING *') .bind(available ? 1 : 0, id) .first(); if (!result) { throw new RepositoryError( `Region not found: ${id}`, ErrorCodes.NOT_FOUND ); } return result; } catch (error) { this.logger.error('updateAvailability failed', { id, available, error: error instanceof Error ? error.message : 'Unknown error' }); if (error instanceof RepositoryError) { throw error; } throw new RepositoryError( `Failed to update region availability: ${id}`, ErrorCodes.DATABASE_ERROR, error ); } } }