Files
satellite-provider/SatelliteProvider.DataAccess/Repositories/RegionRepository.cs
T
Oleksandr Bezdieniezhnykh 23ab05766d [AZ-370] Refactor C17: status / point-type enums + AC RT2 update
Replaces bare strings with two enums in Common/Enums/:
  RegionStatus { Queued, Processing, Completed, Failed }
  RoutePointType { Start, End, Action, Intermediate }

Adds a Dapper EnumStringTypeHandler<T> (DataAccess/TypeHandlers/)
that round-trips enums to/from lowercase strings, registered once
at startup via DapperEnumTypeHandlers.RegisterAll(). DataAccess now
references Common (project ref) so entities can carry the enum types.

Sites converted: RegionService (5), RouteProcessingService (3),
RoutePointGraphBuilder (4), entity Status/PointType columns. Log
message and summary file format preserved via .ToLowerInvariant().

API JSON contract preserved by adding JsonStringEnumConverter with
JsonNamingPolicy.CamelCase to the http JSON options — single-word
enum members serialize to the same lowercase strings as before.

DTO renamed: Common.DTO.RegionStatus -> RegionStatusResponse to
free the RegionStatus name for the new enum (forced by the task's
explicit enum name); the renamed DTO has no public-API impact at
the JSON wire level. Stale doc references updated.

AC RT2 in _docs/00_problem/acceptance_criteria.md now lists all 4
point types (start/end/action/intermediate).

Tests: 171 / 171 unit + 5 / 5 smoke green (was 141 + 5; +30 new tests
covering type handler round-trip, set/parse, unknown-value rejection,
idempotent registration, and the AC RT2 doc check).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 03:55:22 +03:00

100 lines
3.9 KiB
C#

using Dapper;
using Microsoft.Extensions.Logging;
using Npgsql;
using SatelliteProvider.Common.Enums;
using SatelliteProvider.DataAccess.Models;
namespace SatelliteProvider.DataAccess.Repositories;
public class RegionRepository : IRegionRepository
{
private readonly string _connectionString;
private readonly ILogger<RegionRepository> _logger;
public RegionRepository(string connectionString, ILogger<RegionRepository> logger)
{
_connectionString = connectionString;
_logger = logger;
}
public async Task<RegionEntity?> GetByIdAsync(Guid id)
{
using var connection = new NpgsqlConnection(_connectionString);
const string sql = @"
SELECT id, latitude, longitude, size_meters as SizeMeters,
zoom_level as ZoomLevel, status,
csv_file_path as CsvFilePath, summary_file_path as SummaryFilePath,
tiles_downloaded as TilesDownloaded, tiles_reused as TilesReused,
stitch_tiles as StitchTiles,
created_at as CreatedAt, updated_at as UpdatedAt
FROM regions
WHERE id = @Id";
var region = await connection.QuerySingleOrDefaultAsync<RegionEntity>(sql, new { Id = id });
return region;
}
public async Task<IEnumerable<RegionEntity>> GetByStatusAsync(RegionStatus status)
{
using var connection = new NpgsqlConnection(_connectionString);
const string sql = @"
SELECT id, latitude, longitude, size_meters as SizeMeters,
zoom_level as ZoomLevel, status,
csv_file_path as CsvFilePath, summary_file_path as SummaryFilePath,
tiles_downloaded as TilesDownloaded, tiles_reused as TilesReused,
stitch_tiles as StitchTiles,
created_at as CreatedAt, updated_at as UpdatedAt
FROM regions
WHERE status = @Status
ORDER BY created_at ASC";
return await connection.QueryAsync<RegionEntity>(sql, new { Status = status });
}
public async Task<Guid> InsertAsync(RegionEntity region)
{
using var connection = new NpgsqlConnection(_connectionString);
const string sql = @"
INSERT INTO regions (id, latitude, longitude, size_meters, zoom_level,
status, csv_file_path, summary_file_path,
tiles_downloaded, tiles_reused, stitch_tiles,
created_at, updated_at)
VALUES (@Id, @Latitude, @Longitude, @SizeMeters, @ZoomLevel,
@Status, @CsvFilePath, @SummaryFilePath,
@TilesDownloaded, @TilesReused, @StitchTiles,
@CreatedAt, @UpdatedAt)
RETURNING id";
return await connection.ExecuteScalarAsync<Guid>(sql, region);
}
public async Task<int> UpdateAsync(RegionEntity region)
{
using var connection = new NpgsqlConnection(_connectionString);
const string sql = @"
UPDATE regions
SET latitude = @Latitude,
longitude = @Longitude,
size_meters = @SizeMeters,
zoom_level = @ZoomLevel,
status = @Status,
csv_file_path = @CsvFilePath,
summary_file_path = @SummaryFilePath,
tiles_downloaded = @TilesDownloaded,
tiles_reused = @TilesReused,
stitch_tiles = @StitchTiles,
updated_at = @UpdatedAt
WHERE id = @Id";
return await connection.ExecuteAsync(sql, region);
}
public async Task<int> DeleteAsync(Guid id)
{
using var connection = new NpgsqlConnection(_connectionString);
const string sql = "DELETE FROM regions WHERE id = @Id";
return await connection.ExecuteAsync(sql, new { Id = id });
}
}