import 'package:injectable/injectable.dart'; import 'package:superport/data/models/equipment_history_dto.dart'; import 'package:superport/data/repositories/equipment_history_repository.dart'; @lazySingleton class EquipmentHistoryUseCase { final EquipmentHistoryRepository _repository; EquipmentHistoryUseCase(this._repository); // 재고 이력 조회 Future getEquipmentHistories({ int? page, int? pageSize, int? equipmentsId, int? warehousesId, int? companiesId, String? transactionType, String? startDate, String? endDate, }) async { return await _repository.getEquipmentHistories( page: page, pageSize: pageSize, equipmentsId: equipmentsId, warehousesId: warehousesId, companiesId: companiesId, transactionType: transactionType, startDate: startDate, endDate: endDate, ); } // 특정 이력 상세 조회 Future getEquipmentHistoryById(int id) async { return await _repository.getEquipmentHistoryById(id); } // 장비별 이력 조회 Future> getEquipmentHistoriesByEquipmentId( int equipmentId, ) async { return await _repository.getEquipmentHistoriesByEquipmentId(equipmentId); } // 창고별 이력 조회 Future> getEquipmentHistoriesByWarehouseId( int warehouseId, ) async { return await _repository.getEquipmentHistoriesByWarehouseId(warehouseId); } // 장비별 재고 현황 계산 (백엔드 기반) Future getCurrentStock(int equipmentId, {int? warehouseId}) async { final histories = await getEquipmentHistoriesByEquipmentId(equipmentId); int totalStock = 0; for (final history in histories) { if (warehouseId != null && history.warehousesId != warehouseId) continue; if (history.transactionType == TransactionType.input) { totalStock += history.quantity; } else if (history.transactionType == TransactionType.output) { totalStock -= history.quantity; } } return totalStock; } // 입고 처리 (백엔드 스키마 기반) Future createStockIn({ required int equipmentsId, required int warehousesId, required int quantity, DateTime? transactedAt, String? remark, }) async { // 비즈니스 규칙 검증 if (quantity <= 0) { throw Exception('입고 수량은 0보다 커야 합니다.'); } final request = EquipmentHistoryRequestDto( equipmentsId: equipmentsId, warehousesId: warehousesId, transactionType: TransactionType.input, quantity: quantity, transactedAt: transactedAt ?? DateTime.now(), remark: remark, ); return await _repository.createEquipmentHistory(request); } // 출고 처리 (백엔드 스키마 기반) Future createStockOut({ required int equipmentsId, required int warehousesId, required int quantity, DateTime? transactedAt, String? remark, }) async { // 비즈니스 규칙 검증 if (quantity <= 0) { throw Exception('출고 수량은 0보다 커야 합니다.'); } // 재고 확인 final currentStock = await getCurrentStock(equipmentsId, warehouseId: warehousesId); if (currentStock < quantity) { throw Exception('재고가 부족합니다. (현재 재고: $currentStock개)'); } final request = EquipmentHistoryRequestDto( equipmentsId: equipmentsId, warehousesId: warehousesId, transactionType: TransactionType.output, quantity: quantity, transactedAt: transactedAt ?? DateTime.now(), remark: remark, ); return await _repository.createEquipmentHistory(request); } // 이력 수정 Future updateEquipmentHistory( int id, EquipmentHistoryUpdateRequestDto request, ) async { // 수정 권한 검증 (필요시 추가) // 이미 완료된 트랜잭션은 수정 불가 등의 규칙 return await _repository.updateEquipmentHistory(id, request); } // 이력 삭제 Future deleteEquipmentHistory(int id) async { // 삭제 권한 검증 (필요시 추가) // 감사 추적을 위해 실제로는 soft delete 고려 await _repository.deleteEquipmentHistory(id); } // 재고 이동 (창고 간 이동) Future transferStock({ required int equipmentsId, required int quantity, required int fromWarehouseId, required int toWarehouseId, String? remark, }) async { // 1. 출고 처리 (from warehouse) await createStockOut( equipmentsId: equipmentsId, warehousesId: fromWarehouseId, quantity: quantity, remark: remark ?? '창고 이동: $fromWarehouseId → $toWarehouseId', ); // 2. 입고 처리 (to warehouse) await createStockIn( equipmentsId: equipmentsId, warehousesId: toWarehouseId, quantity: quantity, remark: remark ?? '창고 이동: $fromWarehouseId → $toWarehouseId', ); } // 재고 조정 (실사 후 조정) Future adjustInventory({ required int equipmentsId, required int actualQuantity, required int warehousesId, String? remark, }) async { // 현재 재고 확인 final currentStock = await getCurrentStock(equipmentsId, warehouseId: warehousesId); final difference = actualQuantity - currentStock; if (difference == 0) { throw Exception('재고 조정이 필요하지 않습니다.'); } if (difference > 0) { // 재고 증가 - 입고 처리 return await createStockIn( equipmentsId: equipmentsId, warehousesId: warehousesId, quantity: difference, remark: remark ?? '재고 조정: +$difference개', ); } else { // 재고 감소 - 출고 처리 return await createStockOut( equipmentsId: equipmentsId, warehousesId: warehousesId, quantity: -difference, remark: remark ?? '재고 조정: $difference개', ); } } // 재고 부족 장비 확인 (단순화) Future> checkLowStockEquipments({ int minimumStock = 10, int? warehouseId, List? equipmentIds, }) async { final lowStockEquipments = []; // 특정 장비 ID 목록이 제공된 경우, 해당 장비들만 확인 if (equipmentIds != null) { for (final equipmentId in equipmentIds) { final currentStock = await getCurrentStock(equipmentId, warehouseId: warehouseId); if (currentStock < minimumStock) { lowStockEquipments.add(equipmentId); } } } return lowStockEquipments; } // 이력 생성 (범용) Future createEquipmentHistory( EquipmentHistoryRequestDto request, ) async { // 비즈니스 규칙 검증 if (request.quantity <= 0) { throw Exception('수량은 0보다 커야 합니다.'); } // 출고인 경우 재고 확인 if (request.transactionType == TransactionType.output) { final currentStock = await getCurrentStock( request.equipmentsId, warehouseId: request.warehousesId, ); if (currentStock < request.quantity) { throw Exception('재고가 부족합니다. (현재 재고: $currentStock개)'); } } return await _repository.createEquipmentHistory(request); } }