uto_manager/lib/infrastructure/repositories/drift_personnel_repository....

144 lines
4.7 KiB
Dart

import 'dart:convert';
import 'package:drift/drift.dart' show Value;
import 'package:uto_manager/domain/entities/authorized_rank.dart';
import 'package:uto_manager/domain/entities/personnel_record.dart' as domain;
import 'package:uto_manager/domain/repositories/personnel_repository.dart';
import 'package:uto_manager/domain/value_objects/duty_mos.dart';
import 'package:uto_manager/infrastructure/database/app_database.dart';
import 'package:uto_manager/infrastructure/database/daos/personnel_dao.dart';
/// Drift-backed implementation of [PersonnelRepository].
///
/// Converts between Drift [PersonnelData] rows and domain
/// [domain.PersonnelRecord] entities. All persistence is handled via
/// [PersonnelDao].
class DriftPersonnelRepository implements PersonnelRepository {
const DriftPersonnelRepository({required this.dao});
final PersonnelDao dao;
// ---------------------------------------------------------------------------
// Mapping helpers
// ---------------------------------------------------------------------------
domain.PersonnelRecord _toDomain(PersonnelData row) {
return domain.PersonnelRecord(
soldierId: row.soldierId,
name: row.name,
primaryMos: DutyMos.unvalidated(row.primaryMos),
payGrade: AuthorizedRank.values.firstWhere((r) => r.name == row.payGrade),
qualifications: (jsonDecode(row.qualifications) as List<dynamic>).cast<String>(),
readinessState: domain.ReadinessState.values.firstWhere(
(s) => s.name == row.readinessState,
),
assignedSlotId: row.assignedSlotId,
);
}
PersonnelCompanion _toCompanion(domain.PersonnelRecord record) {
return PersonnelCompanion.insert(
soldierId: record.soldierId,
name: record.name,
primaryMos: record.primaryMos.code,
payGrade: record.payGrade.name,
qualifications: jsonEncode(record.qualifications),
readinessState: record.readinessState.name,
assignedSlotId: Value(record.assignedSlotId),
);
}
// ---------------------------------------------------------------------------
// PersonnelRepository implementation
// ---------------------------------------------------------------------------
@override
Future<List<domain.PersonnelRecord>> getAll() async {
final rows = await dao.getAllPersonnel();
return rows.map(_toDomain).toList();
}
@override
Future<domain.PersonnelRecord?> getById(String soldierId) async {
final row = await dao.getPersonnelById(soldierId);
return row == null ? null : _toDomain(row);
}
@override
Future<List<domain.PersonnelRecord>> getBySlot(String slotId) async {
final rows = await dao.getBySlot(slotId);
return rows.map(_toDomain).toList();
}
@override
Future<List<domain.PersonnelRecord>> getUnassigned() async {
final rows = await dao.getUnassigned();
return rows.map(_toDomain).toList();
}
@override
Future<List<domain.PersonnelRecord>> getByMos(DutyMos primaryMos) async {
final rows = await dao.getByMos(primaryMos.code);
return rows.map(_toDomain).toList();
}
@override
Future<List<domain.PersonnelRecord>> getByPayGrade(AuthorizedRank payGrade) async {
final rows = await dao.getByPayGrade(payGrade.name);
return rows.map(_toDomain).toList();
}
@override
Future<void> insert(domain.PersonnelRecord record) async {
final existing = await dao.getPersonnelById(record.soldierId);
if (existing != null) {
throw StateError('Personnel ${record.soldierId} already exists.');
}
await dao.insertPersonnel(_toCompanion(record));
}
@override
Future<void> insertAll(List<domain.PersonnelRecord> records) async {
await dao.insertAllPersonnel(records.map(_toCompanion).toList());
}
@override
Future<void> update(domain.PersonnelRecord record) async {
final existing = await dao.getPersonnelById(record.soldierId);
if (existing == null) {
throw StateError('Personnel ${record.soldierId} not found.');
}
await dao.updatePersonnel(_toCompanion(record));
}
@override
Future<void> delete(String soldierId) async {
await dao.deletePersonnel(soldierId);
}
@override
Future<void> assignToSlot(String soldierId, String slotId) async {
await dao.assignToSlot(soldierId, slotId);
}
@override
Future<void> unassignFromSlot(String soldierId) async {
await dao.unassignFromSlot(soldierId);
}
@override
Stream<List<domain.PersonnelRecord>> watchAll() {
return dao.watchAllPersonnel().map((rows) => rows.map(_toDomain).toList());
}
@override
Stream<List<domain.PersonnelRecord>> watchUnassigned() {
return dao.watchUnassigned().map((rows) => rows.map(_toDomain).toList());
}
@override
Future<void> deleteAll() async {
await dao.deleteAllPersonnel();
}
}