backup: 사용하지 않는 파일 삭제 전 복구 지점

- 전체 371개 파일 중 82개 미사용 파일 식별
- Phase 1: 33개 파일 삭제 예정 (100% 안전)
- Phase 2: 30개 파일 삭제 검토 예정
- Phase 3: 19개 파일 수동 검토 예정

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
JiWoong Sul
2025-09-02 19:51:40 +09:00
parent 650cd4be55
commit c419f8f458
149 changed files with 12934 additions and 3644 deletions

View File

@@ -3,13 +3,13 @@ import 'package:injectable/injectable.dart';
import 'package:superport/core/errors/failures.dart';
import 'package:superport/data/models/administrator_dto.dart';
import 'package:superport/domain/repositories/administrator_repository.dart';
import 'package:superport/utils/constants.dart';
import 'package:superport/core/constants/app_constants.dart';
/// 관리자 UseCase 인터페이스 (비즈니스 로직)
abstract class AdministratorUseCase {
Future<Either<Failure, AdministratorListResponse>> getAdministrators({
int page = 1,
int pageSize = PaginationConstants.defaultPageSize,
int pageSize = AppConstants.adminPageSize,
String? search,
});
@@ -51,12 +51,12 @@ class AdministratorUseCaseImpl implements AdministratorUseCase {
@override
Future<Either<Failure, AdministratorListResponse>> getAdministrators({
int page = 1,
int pageSize = PaginationConstants.defaultPageSize,
int pageSize = AppConstants.adminPageSize,
String? search,
}) async {
// 비즈니스 로직: 페이지네이션 유효성 검사
if (page < 1) page = 1;
if (pageSize < 1 || pageSize > 100) pageSize = 20;
if (pageSize < 1 || pageSize > 100) pageSize = AppConstants.adminPageSize;
return await _repository.getAdministrators(
page: page,

View File

@@ -1,5 +1,6 @@
import 'package:dartz/dartz.dart';
import '../../repositories/company_repository.dart';
import '../../../core/constants/app_constants.dart';
import '../../../models/company_model.dart';
import '../../../data/models/common/paginated_response.dart';
import '../../../core/errors/failures.dart';
@@ -14,7 +15,7 @@ class GetCompaniesParams {
const GetCompaniesParams({
this.page = 1,
this.perPage = 20,
this.perPage = AppConstants.companyPageSize,
this.search,
this.isActive,
});

View File

@@ -0,0 +1,21 @@
import 'package:dartz/dartz.dart';
import '../../repositories/company_repository.dart';
import '../../../models/company_model.dart';
import '../../../core/errors/failures.dart';
import '../base_usecase.dart';
/// 회사 복구 UseCase
class RestoreCompanyUseCase extends UseCase<Company, int> {
final CompanyRepository _companyRepository;
RestoreCompanyUseCase(this._companyRepository);
@override
Future<Either<Failure, Company>> call(int companyId) async {
if (companyId <= 0) {
return Left(ValidationFailure(message: '유효하지 않은 회사 ID입니다.'));
}
return await _companyRepository.restoreCompany(companyId);
}
}

View File

@@ -12,20 +12,8 @@ class CreateEquipmentUseCase extends UseCase<EquipmentDto, EquipmentRequestDto>
@override
Future<Either<Failure, EquipmentDto>> call(EquipmentRequestDto params) async {
// 입력 검증
if (params.companiesId <= 0) {
return Left(ValidationFailure(
message: '회사를 선택해주세요.',
errors: {'companiesId': '회사는 필수 선택 항목입니다.'},
));
}
if (params.modelsId <= 0) {
return Left(ValidationFailure(
message: '모델을 선택해주세요.',
errors: {'modelsId': '모델은 필수 선택 항목입니다.'},
));
}
// 입력 검증 (백엔드에서 companies_id, models_id는 Optional이므로 null 허용)
// 존재 여부 검증은 백엔드에서 수행
if (params.serialNumber.trim().isEmpty) {
return Left(ValidationFailure(

View File

@@ -1,5 +1,6 @@
import 'package:dartz/dartz.dart';
import '../../repositories/equipment_repository.dart';
import '../../../core/constants/app_constants.dart';
import '../../../data/models/equipment/equipment_dto.dart';
import '../../../core/errors/failures.dart';
import '../../../data/models/common/paginated_response.dart';
@@ -13,7 +14,7 @@ class GetEquipmentsParams {
const GetEquipmentsParams({
this.page = 1,
this.perPage = 20,
this.perPage = AppConstants.equipmentPageSize,
this.search,
});
}

View File

@@ -0,0 +1,21 @@
import 'package:dartz/dartz.dart';
import '../../repositories/equipment_repository.dart';
import '../../../data/models/equipment/equipment_dto.dart';
import '../../../core/errors/failures.dart';
import '../base_usecase.dart';
/// 장비 복구 UseCase
class RestoreEquipmentUseCase extends UseCase<EquipmentDto, int> {
final EquipmentRepository _equipmentRepository;
RestoreEquipmentUseCase(this._equipmentRepository);
@override
Future<Either<Failure, EquipmentDto>> call(int equipmentId) async {
if (equipmentId <= 0) {
return Left(ValidationFailure(message: '유효하지 않은 장비 ID입니다.'));
}
return await _equipmentRepository.restoreEquipment(equipmentId);
}
}

View File

@@ -0,0 +1,53 @@
import 'package:dartz/dartz.dart';
import '../../repositories/equipment_repository.dart';
import '../../../data/models/equipment/equipment_dto.dart';
import '../../../core/errors/failures.dart';
import '../base_usecase.dart';
/// 장비 시리얼 검색 UseCase
class GetEquipmentBySerialUseCase extends UseCase<EquipmentDto, String> {
final EquipmentRepository _equipmentRepository;
GetEquipmentBySerialUseCase(this._equipmentRepository);
@override
Future<Either<Failure, EquipmentDto>> call(String serial) async {
if (serial.trim().isEmpty) {
return Left(ValidationFailure(message: '시리얼 번호를 입력해주세요.'));
}
return await _equipmentRepository.getEquipmentBySerial(serial);
}
}
/// 장비 바코드 검색 UseCase
class GetEquipmentByBarcodeUseCase extends UseCase<EquipmentDto, String> {
final EquipmentRepository _equipmentRepository;
GetEquipmentByBarcodeUseCase(this._equipmentRepository);
@override
Future<Either<Failure, EquipmentDto>> call(String barcode) async {
if (barcode.trim().isEmpty) {
return Left(ValidationFailure(message: '바코드를 입력해주세요.'));
}
return await _equipmentRepository.getEquipmentByBarcode(barcode);
}
}
/// 회사별 장비 조회 UseCase
class GetEquipmentsByCompanyUseCase extends UseCase<List<EquipmentDto>, int> {
final EquipmentRepository _equipmentRepository;
GetEquipmentsByCompanyUseCase(this._equipmentRepository);
@override
Future<Either<Failure, List<EquipmentDto>>> call(int companyId) async {
if (companyId <= 0) {
return Left(ValidationFailure(message: '올바른 회사 ID를 입력해주세요.'));
}
return await _equipmentRepository.getEquipmentsByCompany(companyId);
}
}

View File

@@ -1,59 +1,52 @@
import '../../data/models/maintenance_dto.dart';
import '../../data/repositories/maintenance_repository.dart';
import '../../utils/constants.dart';
import 'package:injectable/injectable.dart';
import 'package:superport/data/models/maintenance_dto.dart';
import 'package:superport/data/repositories/maintenance_repository.dart';
/// 유지보수 UseCase (백엔드 스키마 기반)
/// 백엔드 API와 100% 호환되는 단순한 CRUD 작업만 제공
@lazySingleton
class MaintenanceUseCase {
final MaintenanceRepository _repository;
MaintenanceUseCase({required MaintenanceRepository repository})
: _repository = repository;
// 유지보수 목록 조회 (백엔드 스키마 기반)
// 유지보수 목록 조회
Future<MaintenanceListResponse> getMaintenances({
int page = 1,
int pageSize = PaginationConstants.defaultPageSize,
String? sortBy,
String? sortOrder,
String? search,
int? equipmentHistoryId,
int perPage = 20,
int? equipmentId,
String? maintenanceType,
bool? isExpired,
int? expiringDays,
bool includeDeleted = false,
}) async {
return await _repository.getMaintenances(
page: page,
pageSize: pageSize,
sortBy: sortBy,
sortOrder: sortOrder,
search: search,
equipmentHistoryId: equipmentHistoryId,
perPage: perPage,
equipmentId: equipmentId,
maintenanceType: maintenanceType,
isExpired: isExpired,
expiringDays: expiringDays,
includeDeleted: includeDeleted,
);
}
// 특정 유지보수 조회
Future<MaintenanceDto> getMaintenance(int id) async {
return await _repository.getMaintenance(id);
// 특정 유지보수 상세 조회
Future<MaintenanceDto> getMaintenanceDetail(int id) async {
return await _repository.getMaintenanceDetail(id);
}
// 장비 이력별 유지보수 조회
Future<List<MaintenanceDto>> getMaintenancesByEquipmentHistory(
int equipmentHistoryId) async {
return await _repository.getMaintenancesByEquipmentHistory(equipmentHistoryId);
}
// 유지보수 생성 (백엔드 스키마 기반)
// 유지보수 생성
Future<MaintenanceDto> createMaintenance(MaintenanceRequestDto request) async {
// 기본 검증
// 기본 검증
_validateMaintenanceRequest(request);
return await _repository.createMaintenance(request);
}
// 유지보수 수정 (백엔드 스키마 기반)
// 유지보수 수정
Future<MaintenanceDto> updateMaintenance(
int id, MaintenanceUpdateRequestDto request) async {
// 기본 검증
// 기본 검증
if (request.periodMonth != null && request.periodMonth! <= 0) {
throw Exception('유지보수 주기는 1개월 이상이어야 합니다.');
}
@@ -65,62 +58,74 @@ class MaintenanceUseCase {
}
}
// 유지보수 타입 검증
if (request.maintenanceType != null &&
!MaintenanceType.allTypes.contains(request.maintenanceType!)) {
throw Exception('올바른 유지보수 타입을 선택해주세요.');
}
return await _repository.updateMaintenance(id, request);
}
// 유지보수 삭제 (백엔드 soft delete)
// 유지보수 삭제 (소프트 삭제)
Future<void> deleteMaintenance(int id) async {
// 기본 검증만
final maintenance = await _repository.getMaintenance(id);
// 진행 중인 유지보수는 삭제 불가 (선택적)
final now = DateTime.now();
if (now.isAfter(maintenance.startedAt) && now.isBefore(maintenance.endedAt)) {
throw Exception('진행 중인 유지보수는 삭제할 수 없습니다.');
}
await _repository.deleteMaintenance(id);
return await _repository.deleteMaintenance(id);
}
// 활성 유지보수 조회 (백엔드 is_deleted = false)
Future<List<MaintenanceDto>> getActiveMaintenances({
int? equipmentHistoryId,
// 만료 예정 유지보수 조회
Future<List<MaintenanceDto>> getExpiringMaintenances({int days = 30}) async {
return await _repository.getExpiringMaintenances(days: days);
}
// 활성 유지보수만 조회 (is_deleted = false)
Future<MaintenanceListResponse> getActiveMaintenances({
int page = 1,
int perPage = 20,
int? equipmentId,
String? maintenanceType,
}) async {
final response = await getMaintenances(
pageSize: 1000, // 큰 사이즈로 모든 데이터 조회
equipmentHistoryId: equipmentHistoryId,
return await getMaintenances(
page: page,
perPage: perPage,
equipmentId: equipmentId,
maintenanceType: maintenanceType,
includeDeleted: false, // 삭제된 항목 제외
);
// is_deleted = false인 것만 필터링
return response.items.where((m) => m.isActive).toList();
}
// 특정 기간 내 유지보수 조회 (백엔드 날짜 필터링)
Future<List<MaintenanceDto>> getMaintenancesByDateRange({
required DateTime startDate,
required DateTime endDate,
int? equipmentHistoryId,
// 만료된 유지보수 조회
Future<MaintenanceListResponse> getExpiredMaintenances({
int page = 1,
int perPage = 20,
}) async {
final response = await getMaintenances(
pageSize: 1000,
equipmentHistoryId: equipmentHistoryId,
return await getMaintenances(
page: page,
perPage: perPage,
isExpired: true,
includeDeleted: false,
);
// 날짜 범위 필터링 (클라이언트 사이드)
return response.items.where((maintenance) {
return maintenance.startedAt.isAfter(startDate) &&
maintenance.endedAt.isBefore(endDate);
}).toList();
}
// Private 헬퍼 메서드
// 특정 장비의 유지보수 내역 조회
Future<MaintenanceListResponse> getMaintenancesByEquipment({
required int equipmentId,
int page = 1,
int perPage = 20,
bool includeDeleted = false,
}) async {
return await getMaintenances(
page: page,
perPage: perPage,
equipmentId: equipmentId,
includeDeleted: includeDeleted,
);
}
// Private 검증 메서드
void _validateMaintenanceRequest(MaintenanceRequestDto request) {
// 필수 필드 검증 (백엔드 스키마 기반)
if (request.periodMonth <= 0) {
throw Exception('유지보수 주기는 1개월 이상이어야 합니다.');
// 유지보수 주기 검증
if (request.periodMonth <= 0 || request.periodMonth > 120) {
throw Exception('유지보수 주기는 1-120개월 사이여야 합니다.');
}
// 날짜 검증
@@ -128,43 +133,58 @@ class MaintenanceUseCase {
throw Exception('종료일은 시작일 이후여야 합니다.');
}
// 유지보수 타입 검증 (백엔드)
if (request.maintenanceType != MaintenanceType.onsite &&
request.maintenanceType != MaintenanceType.remote) {
throw Exception('유지보수 타입은 방문(O) 또는 원격(R)이어야 합니다.');
// 유지보수 타입 검증 (백엔드와 일치)
if (!MaintenanceType.allTypes.contains(request.maintenanceType)) {
throw Exception('유지보수 타입은 ${MaintenanceType.allTypes.join(', ')} 중 하나여야 합니다.');
}
}
// 통계 조회 (단순화)
// 유지보수 통계 조회
Future<MaintenanceStatistics> getMaintenanceStatistics() async {
final response = await getMaintenances(pageSize: 1000);
final maintenances = response.items;
// 첫 번째 페이지로 전체 개수 확인
final response = await getMaintenances(perPage: 1);
final totalCount = response.totalCount;
// 전체 데이터 조회 (페이지 크기를 총 개수로 설정)
final allDataResponse = await getMaintenances(
perPage: totalCount > 0 ? totalCount : 1000,
includeDeleted: false,
);
final maintenances = allDataResponse.items;
int totalCount = maintenances.length;
int activeCount = maintenances.where((m) => m.isActive).length;
int onsiteCount = maintenances.where((m) => m.maintenanceType == MaintenanceType.onsite).length;
int remoteCount = maintenances.where((m) => m.maintenanceType == MaintenanceType.remote).length;
int warrantyCount = maintenances.where((m) => m.maintenanceType == MaintenanceType.warranty).length;
int contractCount = maintenances.where((m) => m.maintenanceType == MaintenanceType.contract).length;
int inspectionCount = maintenances.where((m) => m.maintenanceType == MaintenanceType.inspection).length;
int expiredCount = maintenances.where((m) => m.isExpired).length;
return MaintenanceStatistics(
totalCount: totalCount,
activeCount: activeCount,
onsiteCount: onsiteCount,
remoteCount: remoteCount,
warrantyCount: warrantyCount,
contractCount: contractCount,
inspectionCount: inspectionCount,
expiredCount: expiredCount,
);
}
}
/// 유지보수 통계 모델 (단순화)
/// 유지보수 통계 모델
class MaintenanceStatistics {
final int totalCount;
final int activeCount;
final int onsiteCount;
final int remoteCount;
final int warrantyCount; // 무상 보증
final int contractCount; // 유상 계약
final int inspectionCount; // 점검
final int expiredCount; // 만료된 것
MaintenanceStatistics({
required this.totalCount,
required this.activeCount,
required this.onsiteCount,
required this.remoteCount,
required this.warrantyCount,
required this.contractCount,
required this.inspectionCount,
required this.expiredCount,
});
}

View File

@@ -0,0 +1,17 @@
import 'package:dartz/dartz.dart';
import '../../repositories/model_repository.dart';
import '../../../data/models/model/model_dto.dart';
import '../../../core/errors/failures.dart';
import '../base_usecase.dart';
/// 모델 생성 UseCase
class CreateModelUseCase extends UseCase<ModelDto, CreateModelRequest> {
final ModelRepository _modelRepository;
CreateModelUseCase(this._modelRepository);
@override
Future<Either<Failure, ModelDto>> call(CreateModelRequest request) async {
return await _modelRepository.createModel(request);
}
}

View File

@@ -0,0 +1,16 @@
import 'package:dartz/dartz.dart';
import '../../repositories/model_repository.dart';
import '../../../core/errors/failures.dart';
import '../base_usecase.dart';
/// 모델 삭제 UseCase
class DeleteModelUseCase extends UseCase<void, int> {
final ModelRepository _modelRepository;
DeleteModelUseCase(this._modelRepository);
@override
Future<Either<Failure, void>> call(int id) async {
return await _modelRepository.deleteModel(id);
}
}

View File

@@ -0,0 +1,17 @@
import 'package:dartz/dartz.dart';
import '../../repositories/model_repository.dart';
import '../../../data/models/model/model_dto.dart';
import '../../../core/errors/failures.dart';
import '../base_usecase.dart';
/// 모델 상세 조회 UseCase
class GetModelDetailUseCase extends UseCase<ModelDto, int> {
final ModelRepository _modelRepository;
GetModelDetailUseCase(this._modelRepository);
@override
Future<Either<Failure, ModelDto>> call(int id) async {
return await _modelRepository.getModelDetail(id);
}
}

View File

@@ -0,0 +1,17 @@
import 'package:dartz/dartz.dart';
import '../../repositories/model_repository.dart';
import '../../../data/models/model/model_dto.dart';
import '../../../core/errors/failures.dart';
import '../base_usecase.dart';
/// 제조사별 모델 조회 UseCase
class GetModelsByVendorUseCase extends UseCase<List<ModelDto>, int> {
final ModelRepository _modelRepository;
GetModelsByVendorUseCase(this._modelRepository);
@override
Future<Either<Failure, List<ModelDto>>> call(int vendorId) async {
return await _modelRepository.getModelsByVendor(vendorId);
}
}

View File

@@ -0,0 +1,40 @@
import 'package:dartz/dartz.dart';
import '../../repositories/model_repository.dart';
import '../../../data/models/model/model_dto.dart';
import '../../../core/errors/failures.dart';
import '../base_usecase.dart';
/// 모델 목록 조회 파라미터
class GetModelsParams {
final int page;
final int perPage;
final String? search;
final int? vendorId;
final bool? includeDeleted;
const GetModelsParams({
this.page = 1,
this.perPage = 10,
this.search,
this.vendorId,
this.includeDeleted,
});
}
/// 모델 목록 조회 UseCase
class GetModelsUseCase extends UseCase<ModelListDto, GetModelsParams> {
final ModelRepository _modelRepository;
GetModelsUseCase(this._modelRepository);
@override
Future<Either<Failure, ModelListDto>> call(GetModelsParams params) async {
return await _modelRepository.getModels(
page: params.page,
perPage: params.perPage,
search: params.search,
vendorId: params.vendorId,
includeDeleted: params.includeDeleted,
);
}
}

View File

@@ -0,0 +1,17 @@
import 'package:dartz/dartz.dart';
import '../../repositories/model_repository.dart';
import '../../../data/models/model/model_dto.dart';
import '../../../core/errors/failures.dart';
import '../base_usecase.dart';
/// 모델 복구 UseCase
class RestoreModelUseCase extends UseCase<ModelDto, int> {
final ModelRepository _modelRepository;
RestoreModelUseCase(this._modelRepository);
@override
Future<Either<Failure, ModelDto>> call(int id) async {
return await _modelRepository.restoreModel(id);
}
}

View File

@@ -0,0 +1,28 @@
import 'package:dartz/dartz.dart';
import '../../repositories/model_repository.dart';
import '../../../data/models/model/model_dto.dart';
import '../../../core/errors/failures.dart';
import '../base_usecase.dart';
/// 모델 수정 파라미터
class UpdateModelParams {
final int id;
final UpdateModelRequest request;
const UpdateModelParams({
required this.id,
required this.request,
});
}
/// 모델 수정 UseCase
class UpdateModelUseCase extends UseCase<ModelDto, UpdateModelParams> {
final ModelRepository _modelRepository;
UpdateModelUseCase(this._modelRepository);
@override
Future<Either<Failure, ModelDto>> call(UpdateModelParams params) async {
return await _modelRepository.updateModel(params.id, params.request);
}
}

View File

@@ -1,4 +1,5 @@
import 'package:injectable/injectable.dart';
import '../../core/constants/app_constants.dart';
import '../../data/models/rent_dto.dart';
import '../repositories/rent_repository.dart';
@@ -10,18 +11,24 @@ class RentUseCase {
RentUseCase(this._repository);
/// 임대 목록 조회 (백엔드 스키마 기반)
/// 임대 목록 조회 (백엔드 실제 파라미터)
Future<RentListResponse> getRents({
int page = 1,
int pageSize = 10,
String? search,
int? equipmentHistoryId,
int perPage = AppConstants.rentPageSize,
int? equipmentId,
int? companyId,
bool? isActive,
DateTime? dateFrom,
DateTime? dateTo,
}) async {
return await _repository.getRents(
page: page,
pageSize: pageSize,
search: search,
equipmentHistoryId: equipmentHistoryId,
perPage: perPage,
equipmentId: equipmentId,
companyId: companyId,
isActive: isActive,
dateFrom: dateFrom,
dateTo: dateTo,
);
}
@@ -57,70 +64,84 @@ class RentUseCase {
return await _repository.deleteRent(id);
}
/// 장비 이력별 임대 조회
Future<List<RentDto>> getRentsByEquipmentHistory(int equipmentHistoryId) async {
/// 진행중인 임대 조회 (백엔드 실존 API)
Future<List<RentDto>> getActiveRents() async {
return await _repository.getActiveRents();
}
/// 장비별 임대 조회 (백엔드 필터링)
Future<List<RentDto>> getRentsByEquipment(int equipmentId) async {
final response = await getRents(
pageSize: 1000,
equipmentHistoryId: equipmentHistoryId,
perPage: 1000,
equipmentId: equipmentId,
);
return response.items;
}
/// 회사별 임대 조회 (백엔드 필터링)
Future<List<RentDto>> getRentsByCompany(int companyId) async {
final response = await getRents(
perPage: 1000,
companyId: companyId,
);
return response.items;
}
/// 특정 기간 내 임대 조회 (백엔드 날짜 필터링)
Future<List<RentDto>> getRentsByDateRange({
required DateTime startDate,
required DateTime endDate,
int? equipmentHistoryId,
required DateTime dateFrom,
required DateTime dateTo,
int? equipmentId,
int? companyId,
}) async {
final response = await getRents(
pageSize: 1000,
equipmentHistoryId: equipmentHistoryId,
perPage: 1000,
equipmentId: equipmentId,
companyId: companyId,
dateFrom: dateFrom,
dateTo: dateTo,
);
// 날짜 범위 필터링 (클라이언트 사이드)
return response.items.where((rent) {
return rent.startedAt.isAfter(startDate) &&
rent.endedAt.isBefore(endDate);
}).toList();
return response.items;
}
/// 현재 진행 중인 임대 조회
Future<List<RentDto>> getCurrentRents({int? equipmentHistoryId}) async {
/// 현재 진행 중인 임대 조회 (백엔드 계산값 활용)
Future<List<RentDto>> getCurrentRents({int? equipmentId, int? companyId}) async {
final response = await getRents(
pageSize: 1000,
equipmentHistoryId: equipmentHistoryId,
perPage: 1000,
equipmentId: equipmentId,
companyId: companyId,
isActive: true, // 백엔드 필터링
);
final now = DateTime.now();
return response.items.where((rent) {
return rent.startedAt.isBefore(now) && rent.endedAt.isAfter(now);
}).toList();
return response.items;
}
/// 종료된 임대 조회
Future<List<RentDto>> getCompletedRents({int? equipmentHistoryId}) async {
/// 종료된 임대 조회 (백엔드 필터링)
Future<List<RentDto>> getCompletedRents({int? equipmentId, int? companyId}) async {
final response = await getRents(
pageSize: 1000,
equipmentHistoryId: equipmentHistoryId,
perPage: 1000,
equipmentId: equipmentId,
companyId: companyId,
isActive: false, // 백엔드 필터링
);
final now = DateTime.now();
return response.items.where((rent) {
return rent.endedAt.isBefore(now);
}).toList();
return response.items;
}
/// 예정된 임대 조회
Future<List<RentDto>> getUpcomingRents({int? equipmentHistoryId}) async {
/// 예정된 임대 조회 (백엔드 필터링)
Future<List<RentDto>> getUpcomingRents({int? equipmentId, int? companyId}) async {
final now = DateTime.now();
final tomorrow = now.add(Duration(days: 1));
final response = await getRents(
pageSize: 1000,
equipmentHistoryId: equipmentHistoryId,
perPage: 1000,
equipmentId: equipmentId,
companyId: companyId,
dateFrom: tomorrow, // 내일부터 시작하는 임대
);
final now = DateTime.now();
return response.items.where((rent) {
return rent.startedAt.isAfter(now);
}).toList();
return response.items;
}
/// 임대 기간 계산 (일수)
@@ -137,22 +158,16 @@ class RentUseCase {
return rent.endedAt.difference(now).inDays;
}
/// 임대 통계 조회 (단순화)
/// 임대 통계 조회 (백엔드 계산값 활용)
Future<RentStatistics> getRentStatistics() async {
final response = await getRents(pageSize: 1000);
final response = await getRents(perPage: 1000);
final rents = response.items;
final now = DateTime.now();
// 백엔드 계산 필드 활용
int totalCount = rents.length;
int currentCount = rents.where((rent) =>
rent.startedAt.isBefore(now) && rent.endedAt.isAfter(now)
).length;
int completedCount = rents.where((rent) =>
rent.endedAt.isBefore(now)
).length;
int upcomingCount = rents.where((rent) =>
rent.startedAt.isAfter(now)
).length;
int currentCount = rents.where((rent) => rent.isActive == true).length;
int completedCount = rents.where((rent) => rent.isActive == false && rent.endedAt.isBefore(DateTime.now())).length;
int upcomingCount = rents.where((rent) => rent.startedAt.isAfter(DateTime.now())).length;
return RentStatistics(
totalCount: totalCount,

View File

@@ -1,5 +1,6 @@
import 'package:dartz/dartz.dart';
import 'package:injectable/injectable.dart';
import '../../../core/constants/app_constants.dart';
import '../../../models/user_model.dart';
import '../../../core/errors/failures.dart';
import '../../repositories/user_repository.dart';
@@ -15,7 +16,7 @@ class GetUsersParams {
const GetUsersParams({
this.page = 1,
this.perPage = 20,
this.perPage = AppConstants.userPageSize,
this.role,
this.isActive,
});

View File

@@ -1,12 +1,12 @@
import 'package:injectable/injectable.dart';
import 'package:superport/data/models/vendor_dto.dart';
import 'package:superport/data/repositories/vendor_repository.dart';
import 'package:superport/utils/constants.dart';
import 'package:superport/core/constants/app_constants.dart';
abstract class VendorUseCase {
Future<VendorListResponse> getVendors({
int page = 1,
int limit = PaginationConstants.defaultPageSize,
int limit = AppConstants.vendorPageSize,
String? search,
bool? isActive,
});
@@ -28,13 +28,13 @@ class VendorUseCaseImpl implements VendorUseCase {
@override
Future<VendorListResponse> getVendors({
int page = 1,
int limit = PaginationConstants.defaultPageSize,
int limit = AppConstants.vendorPageSize,
String? search,
bool? isActive,
}) async {
// 비즈니스 로직: 페이지네이션 유효성 검사
if (page < 1) page = 1;
if (limit < 1 || limit > 100) limit = 20;
if (limit < 1 || limit > 100) limit = AppConstants.vendorPageSize;
return await _repository.getAll(
page: page,

View File

@@ -1,5 +1,6 @@
import 'package:dartz/dartz.dart';
import 'package:injectable/injectable.dart';
import '../../../core/constants/app_constants.dart';
import '../../../data/models/common/pagination_params.dart';
import '../../../data/models/warehouse/warehouse_location_dto.dart';
import '../../repositories/warehouse_location_repository.dart';
@@ -54,7 +55,7 @@ class GetWarehouseLocationsParams {
GetWarehouseLocationsParams({
this.page = 1,
this.perPage = 20,
this.perPage = AppConstants.warehousePageSize,
this.search,
this.filters,
});

View File

@@ -1,4 +1,5 @@
import 'package:injectable/injectable.dart';
import 'package:superport/core/constants/app_constants.dart';
import 'package:superport/data/models/zipcode_dto.dart';
import 'package:superport/data/repositories/zipcode_repository.dart';
@@ -6,29 +7,20 @@ abstract class ZipcodeUseCase {
/// 우편번호 검색 (페이지네이션 지원)
Future<ZipcodeListResponse> searchZipcodes({
int page = 1,
int limit = 20,
int limit = AppConstants.defaultPageSize,
String? search,
String? sido,
String? gu,
});
/// 우편번호로 정확한 주소 조회
Future<ZipcodeDto?> getZipcodeByNumber(int zipcode);
/// 시도별 구 목록 조회
Future<List<String>> getGuListBySido(String sido);
/// 전체 시도 목록 조회
Future<List<String>> getAllSidoList();
/// 주소 문자열로 우편번호 검색 (최적화된 검색)
Future<List<ZipcodeDto>> searchByAddress(String address);
/// 우편번호 유효성 검사
bool validateZipcode(int zipcode);
/// 검색어 유효성 검사 및 정규화
String normalizeSearchQuery(String query);
/// Hierarchy API - 시도 목록 조회
Future<HierarchyResponse> getHierarchySidos();
/// Hierarchy API - 구/군 목록 조회
Future<HierarchyResponse> getHierarchyGusBySido(String sido);
}
@Injectable(as: ZipcodeUseCase)
@@ -40,14 +32,14 @@ class ZipcodeUseCaseImpl implements ZipcodeUseCase {
@override
Future<ZipcodeListResponse> searchZipcodes({
int page = 1,
int limit = 20,
int limit = AppConstants.defaultPageSize,
String? search,
String? sido,
String? gu,
}) async {
// 비즈니스 로직: 페이지네이션 유효성 검사
if (page < 1) page = 1;
if (limit < 1 || limit > 100) limit = 20;
if (limit < 1 || limit > 100) limit = AppConstants.defaultPageSize;
// 검색어 정규화
final normalizedSearch = search != null && search.isNotEmpty
@@ -63,58 +55,6 @@ class ZipcodeUseCaseImpl implements ZipcodeUseCase {
);
}
@override
Future<ZipcodeDto?> getZipcodeByNumber(int zipcode) async {
// 우편번호 유효성 검사
if (!validateZipcode(zipcode)) {
throw ArgumentError('유효하지 않은 우편번호입니다. (5자리 숫자)');
}
return await _repository.getByZipcode(zipcode);
}
@override
Future<List<String>> getGuListBySido(String sido) async {
if (sido.trim().isEmpty) {
throw ArgumentError('시도명을 입력해주세요.');
}
final normalizedSido = sido.trim();
return await _repository.getGuBySido(normalizedSido);
}
@override
Future<List<String>> getAllSidoList() async {
return await _repository.getAllSido();
}
@override
Future<List<ZipcodeDto>> searchByAddress(String address) async {
if (address.trim().isEmpty) {
return [];
}
final normalizedAddress = normalizeSearchQuery(address);
try {
// 먼저 전체 검색으로 시도
final response = await _repository.search(
search: normalizedAddress,
limit: 10, // 상위 10개만 가져오기
);
return response.items;
} catch (e) {
// 검색 실패 시 빈 목록 반환
return [];
}
}
@override
bool validateZipcode(int zipcode) {
// 한국 우편번호는 5자리 숫자 (00000 ~ 99999)
return zipcode >= 0 && zipcode <= 99999;
}
@override
String normalizeSearchQuery(String query) {
@@ -131,5 +71,18 @@ class ZipcodeUseCaseImpl implements ZipcodeUseCase {
return normalized;
}
@override
Future<HierarchyResponse> getHierarchySidos() async {
return await _repository.getHierarchySidos();
}
@override
Future<HierarchyResponse> getHierarchyGusBySido(String sido) async {
if (sido.trim().isEmpty) {
throw ArgumentError('시도명을 입력해주세요.');
}
return await _repository.getHierarchyGusBySido(sido.trim());
}
}