146 lines
4.8 KiB
Dart
146 lines
4.8 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,
|
|
positionTitle: row.positionTitle,
|
|
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: Value(record.name),
|
|
positionTitle: Value(record.positionTitle),
|
|
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();
|
|
}
|
|
}
|