사용하지 않는 파일 정리 전 백업 (Phase 10 완료 후 상태)
This commit is contained in:
160
lib/services/administrator_service.dart
Normal file
160
lib/services/administrator_service.dart
Normal file
@@ -0,0 +1,160 @@
|
||||
import 'package:injectable/injectable.dart';
|
||||
import 'package:superport/data/datasources/remote/administrator_remote_datasource.dart';
|
||||
import 'package:superport/data/models/administrator_dto.dart';
|
||||
|
||||
/// 관리자 서비스 (백엔드 Administrator 테이블)
|
||||
/// HTTP API 호출을 담당하는 서비스 레이어
|
||||
@lazySingleton
|
||||
class AdministratorService {
|
||||
final AdministratorRemoteDataSource _remoteDataSource;
|
||||
|
||||
AdministratorService(this._remoteDataSource);
|
||||
|
||||
/// 관리자 목록 조회 (페이지네이션 지원)
|
||||
Future<AdministratorListResponse> getAdministrators({
|
||||
int page = 1,
|
||||
int pageSize = 20,
|
||||
String? search,
|
||||
}) async {
|
||||
try {
|
||||
return await _remoteDataSource.getAdministrators(
|
||||
page: page,
|
||||
pageSize: pageSize,
|
||||
search: search,
|
||||
);
|
||||
} catch (e) {
|
||||
throw Exception('관리자 목록 조회 실패: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
/// 특정 관리자 조회
|
||||
Future<AdministratorDto> getAdministrator(int id) async {
|
||||
try {
|
||||
return await _remoteDataSource.getAdministrator(id);
|
||||
} catch (e) {
|
||||
throw Exception('관리자 조회 실패: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
/// 관리자 계정 생성
|
||||
Future<AdministratorDto> createAdministrator({
|
||||
required String name,
|
||||
required String phone,
|
||||
required String mobile,
|
||||
required String email,
|
||||
required String password,
|
||||
}) async {
|
||||
try {
|
||||
final request = AdministratorRequestDto(
|
||||
name: name,
|
||||
phone: phone,
|
||||
mobile: mobile,
|
||||
email: email,
|
||||
passwd: password,
|
||||
);
|
||||
|
||||
return await _remoteDataSource.createAdministrator(request);
|
||||
} catch (e) {
|
||||
throw Exception('관리자 계정 생성 실패: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
/// 관리자 정보 수정
|
||||
Future<AdministratorDto> updateAdministrator(
|
||||
int id, {
|
||||
String? name,
|
||||
String? phone,
|
||||
String? mobile,
|
||||
String? email,
|
||||
String? password,
|
||||
}) async {
|
||||
try {
|
||||
final request = AdministratorUpdateRequestDto(
|
||||
name: name,
|
||||
phone: phone,
|
||||
mobile: mobile,
|
||||
email: email,
|
||||
passwd: password,
|
||||
);
|
||||
|
||||
return await _remoteDataSource.updateAdministrator(id, request);
|
||||
} catch (e) {
|
||||
throw Exception('관리자 정보 수정 실패: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
/// 관리자 계정 삭제
|
||||
Future<void> deleteAdministrator(int id) async {
|
||||
try {
|
||||
await _remoteDataSource.deleteAdministrator(id);
|
||||
} catch (e) {
|
||||
throw Exception('관리자 계정 삭제 실패: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
/// 이메일 중복 확인
|
||||
Future<bool> checkEmailAvailability(String email, {int? excludeId}) async {
|
||||
try {
|
||||
return await _remoteDataSource.checkEmailAvailability(
|
||||
email,
|
||||
excludeId: excludeId,
|
||||
);
|
||||
} catch (e) {
|
||||
// 에러 발생 시 안전하게 false 반환 (사용 불가로 처리)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// 이메일 중복 여부 확인 (편의 메서드)
|
||||
Future<bool> isDuplicateEmail(String email, {int? excludeId}) async {
|
||||
try {
|
||||
final isAvailable = await checkEmailAvailability(email, excludeId: excludeId);
|
||||
return !isAvailable; // 사용 가능하면 중복이 아님
|
||||
} catch (e) {
|
||||
// 에러 발생 시 안전하게 중복으로 처리
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// 관리자 인증 (로그인)
|
||||
Future<AdministratorDto> authenticateAdministrator(
|
||||
String email,
|
||||
String password,
|
||||
) async {
|
||||
try {
|
||||
return await _remoteDataSource.authenticateAdministrator(email, password);
|
||||
} catch (e) {
|
||||
throw Exception('관리자 인증 실패: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
/// 관리자 전체 수 조회 (통계용)
|
||||
Future<int> getAdministratorCount() async {
|
||||
try {
|
||||
final response = await getAdministrators(page: 1, pageSize: 1);
|
||||
return response.totalCount;
|
||||
} catch (e) {
|
||||
throw Exception('관리자 수 조회 실패: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
|
||||
/// 이메일로 관리자 검색 (단일 결과 기대)
|
||||
Future<AdministratorDto?> findAdministratorByEmail(String email) async {
|
||||
try {
|
||||
final response = await getAdministrators(search: email, pageSize: 10);
|
||||
|
||||
// 정확히 일치하는 이메일 찾기
|
||||
final exactMatch = response.items.where((admin) =>
|
||||
admin.email.toLowerCase() == email.toLowerCase()).firstOrNull;
|
||||
|
||||
return exactMatch;
|
||||
} catch (e) {
|
||||
throw Exception('이메일로 관리자 검색 실패: ${e.toString()}');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// List 확장 메서드 (firstOrNull이 없는 Dart 버전 대응)
|
||||
extension ListExtension<T> on List<T> {
|
||||
T? get firstOrNull => isEmpty ? null : first;
|
||||
}
|
||||
@@ -14,7 +14,6 @@ import 'package:superport/data/models/auth/login_response.dart';
|
||||
import 'package:superport/data/models/auth/logout_request.dart';
|
||||
import 'package:superport/data/models/auth/refresh_token_request.dart';
|
||||
import 'package:superport/data/models/auth/token_response.dart';
|
||||
import 'package:superport/core/config/environment.dart' as env;
|
||||
|
||||
abstract class AuthService {
|
||||
Future<Either<Failure, LoginResponse>> login(LoginRequest request);
|
||||
@@ -177,7 +176,7 @@ class AuthServiceImpl implements AuthService {
|
||||
if (token != null && token.length > 20) {
|
||||
debugPrint('[AuthService] getAccessToken: Found (${token.substring(0, 20)}...)');
|
||||
} else if (token != null) {
|
||||
debugPrint('[AuthService] getAccessToken: Found (${token})');
|
||||
debugPrint('[AuthService] getAccessToken: Found ($token)');
|
||||
} else {
|
||||
debugPrint('[AuthService] getAccessToken: Not found');
|
||||
}
|
||||
|
||||
@@ -56,14 +56,12 @@ class CompanyService {
|
||||
// 회사 생성
|
||||
Future<Company> createCompany(Company company) async {
|
||||
try {
|
||||
final request = CreateCompanyRequest(
|
||||
final request = CompanyRequestDto(
|
||||
name: company.name,
|
||||
address: company.address.toString(),
|
||||
contactName: company.contactName ?? '',
|
||||
contactPosition: company.contactPosition ?? '',
|
||||
contactPhone: company.contactPhone ?? '',
|
||||
contactEmail: company.contactEmail ?? '',
|
||||
companyTypes: company.companyTypes.map((e) => e.toString().split('.').last).toList(),
|
||||
isPartner: company.isPartner,
|
||||
isCustomer: company.isCustomer,
|
||||
parentCompanyId: company.parentCompanyId,
|
||||
@@ -114,14 +112,12 @@ class CompanyService {
|
||||
// 회사 수정
|
||||
Future<Company> updateCompany(int id, Company company) async {
|
||||
try {
|
||||
final request = UpdateCompanyRequest(
|
||||
final request = CompanyUpdateRequestDto(
|
||||
name: company.name,
|
||||
address: company.address.toString(),
|
||||
contactName: company.contactName,
|
||||
contactPosition: company.contactPosition,
|
||||
contactPhone: company.contactPhone,
|
||||
contactEmail: company.contactEmail,
|
||||
companyTypes: company.companyTypes.map((e) => e.toString().split('.').last).toList(),
|
||||
isPartner: company.isPartner,
|
||||
isCustomer: company.isCustomer,
|
||||
parentCompanyId: company.parentCompanyId,
|
||||
@@ -377,30 +373,18 @@ class CompanyService {
|
||||
isPartner: dto.isPartner,
|
||||
isCustomer: dto.isCustomer,
|
||||
parentCompanyId: dto.parentCompanyId,
|
||||
createdAt: dto.createdAt,
|
||||
createdAt: dto.registeredAt, // CompanyListDto.registeredAt → createdAt
|
||||
updatedAt: null, // CompanyListDto에는 updatedAt이 없음
|
||||
branches: [], // branches는 빈 배열로 초기화
|
||||
);
|
||||
}
|
||||
|
||||
Company _convertResponseToCompany(CompanyResponse dto) {
|
||||
Company _convertResponseToCompany(CompanyDto dto) {
|
||||
List<CompanyType> companyTypes = [];
|
||||
|
||||
// 1. company_types 필드가 있으면 우선 사용 (하위 호환성)
|
||||
if (dto.companyTypes.isNotEmpty) {
|
||||
companyTypes = dto.companyTypes.map((typeStr) {
|
||||
final normalized = typeStr.toLowerCase();
|
||||
if (normalized.contains('partner')) return CompanyType.partner;
|
||||
if (normalized.contains('customer')) return CompanyType.customer;
|
||||
if (normalized == 'other') return CompanyType.customer; // "Other"는 고객사로 매핑
|
||||
return CompanyType.customer; // 기본값
|
||||
}).toSet().toList(); // 중복 제거
|
||||
}
|
||||
// 2. company_types가 없으면 is_partner, is_customer 사용
|
||||
else {
|
||||
if (dto.isCustomer) companyTypes.add(CompanyType.customer);
|
||||
if (dto.isPartner) companyTypes.add(CompanyType.partner);
|
||||
}
|
||||
// CompanyDto에는 companyTypes 필드가 없으므로 is_partner, is_customer 사용
|
||||
if (dto.isCustomer) companyTypes.add(CompanyType.customer);
|
||||
if (dto.isPartner) companyTypes.add(CompanyType.partner);
|
||||
|
||||
// 3. 둘 다 없으면 빈 리스트 유지
|
||||
|
||||
@@ -409,7 +393,7 @@ class CompanyService {
|
||||
name: dto.name,
|
||||
address: dto.address != null ? Address.fromFullAddress(dto.address!) : const Address(),
|
||||
contactName: dto.contactName,
|
||||
contactPosition: dto.contactPosition,
|
||||
contactPosition: null, // CompanyDto에 contactPosition 필드 없음
|
||||
contactPhone: dto.contactPhone,
|
||||
contactEmail: dto.contactEmail,
|
||||
companyTypes: companyTypes,
|
||||
@@ -418,7 +402,7 @@ class CompanyService {
|
||||
isPartner: dto.isPartner,
|
||||
isCustomer: dto.isCustomer,
|
||||
parentCompanyId: dto.parentCompanyId,
|
||||
createdAt: dto.createdAt,
|
||||
createdAt: dto.registeredAt, // createdAt → registeredAt
|
||||
updatedAt: dto.updatedAt,
|
||||
branches: [], // branches는 빈 배열로 초기화
|
||||
);
|
||||
|
||||
@@ -1,163 +1,57 @@
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:superport/core/errors/exceptions.dart';
|
||||
import 'package:superport/core/errors/failures.dart';
|
||||
import 'package:superport/core/utils/equipment_status_converter.dart';
|
||||
import 'package:superport/data/datasources/remote/equipment_remote_datasource.dart';
|
||||
import 'package:superport/data/models/common/paginated_response.dart';
|
||||
import 'package:superport/data/models/equipment/equipment_history_dto.dart';
|
||||
import 'package:superport/data/models/equipment/equipment_in_request.dart';
|
||||
import 'package:superport/data/models/equipment/equipment_io_response.dart';
|
||||
import 'package:superport/data/models/equipment/equipment_list_dto.dart';
|
||||
import 'package:superport/data/models/equipment/equipment_out_request.dart';
|
||||
import 'package:superport/data/models/equipment/equipment_request.dart';
|
||||
import 'package:superport/data/models/equipment/equipment_response.dart';
|
||||
import 'package:superport/models/equipment_unified_model.dart';
|
||||
import 'package:superport/data/models/equipment/equipment_dto.dart';
|
||||
|
||||
class EquipmentService {
|
||||
final EquipmentRemoteDataSource _remoteDataSource = GetIt.instance<EquipmentRemoteDataSource>();
|
||||
|
||||
// 장비 목록 조회 (DTO 형태로 반환하여 status 정보 유지)
|
||||
Future<PaginatedResponse<EquipmentListDto>> getEquipmentsWithStatus({
|
||||
// 장비 목록 조회 (간단한 버전)
|
||||
Future<PaginatedResponse<EquipmentDto>> getEquipments({
|
||||
int page = 1,
|
||||
int perPage = 20,
|
||||
String? status,
|
||||
int? companyId,
|
||||
int? warehouseLocationId,
|
||||
String? search,
|
||||
bool includeInactive = false,
|
||||
}) async {
|
||||
try {
|
||||
final response = await _remoteDataSource.getEquipments(
|
||||
page: page,
|
||||
perPage: perPage,
|
||||
status: status,
|
||||
companyId: companyId,
|
||||
warehouseLocationId: warehouseLocationId,
|
||||
search: search,
|
||||
isActive: !includeInactive,
|
||||
);
|
||||
|
||||
return PaginatedResponse<EquipmentListDto>(
|
||||
return PaginatedResponse<EquipmentDto>(
|
||||
items: response.items,
|
||||
page: response.page,
|
||||
size: response.perPage,
|
||||
totalElements: response.total,
|
||||
page: response.currentPage,
|
||||
size: response.pageSize ?? 20,
|
||||
totalElements: response.totalCount,
|
||||
totalPages: response.totalPages,
|
||||
first: response.page == 1,
|
||||
last: response.page >= response.totalPages,
|
||||
first: response.currentPage == 1,
|
||||
last: response.currentPage >= response.totalPages,
|
||||
);
|
||||
} on ServerException catch (e) {
|
||||
throw ServerFailure(message: e.message);
|
||||
} catch (e) {
|
||||
throw ServerFailure(message: 'Failed to fetch equipment list: $e');
|
||||
throw ServerFailure(message: 'Failed to fetch equipments: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// 장비 목록 조회
|
||||
Future<PaginatedResponse<Equipment>> getEquipments({
|
||||
int page = 1,
|
||||
int perPage = 20,
|
||||
String? status,
|
||||
int? companyId,
|
||||
int? warehouseLocationId,
|
||||
String? search,
|
||||
bool includeInactive = false,
|
||||
}) async {
|
||||
// 장비 상세 조회
|
||||
Future<EquipmentDto> getEquipmentDetail(int id) async {
|
||||
try {
|
||||
final response = await _remoteDataSource.getEquipments(
|
||||
page: page,
|
||||
perPage: perPage,
|
||||
status: status,
|
||||
companyId: companyId,
|
||||
warehouseLocationId: warehouseLocationId,
|
||||
search: search,
|
||||
isActive: !includeInactive,
|
||||
);
|
||||
|
||||
return PaginatedResponse<Equipment>(
|
||||
items: response.items.map((dto) => _convertListDtoToEquipment(dto)).toList(),
|
||||
page: response.page,
|
||||
size: response.perPage,
|
||||
totalElements: response.total,
|
||||
totalPages: response.totalPages,
|
||||
first: response.page == 1,
|
||||
last: response.page >= response.totalPages,
|
||||
);
|
||||
return await _remoteDataSource.getEquipmentDetail(id);
|
||||
} on ServerException catch (e) {
|
||||
throw ServerFailure(message: e.message);
|
||||
} catch (e) {
|
||||
throw ServerFailure(message: 'Failed to fetch equipment list: $e');
|
||||
throw ServerFailure(message: 'Failed to fetch equipment detail: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// 입고된 장비 목록 조회
|
||||
Future<PaginatedResponse<EquipmentListDto>> getEquipmentInList({
|
||||
int page = 1,
|
||||
int perPage = 20,
|
||||
int? companyId,
|
||||
int? warehouseLocationId,
|
||||
String? search,
|
||||
}) async {
|
||||
return getEquipmentsWithStatus(
|
||||
page: page,
|
||||
perPage: perPage,
|
||||
status: 'available', // 입고된 장비는 사용 가능 상태
|
||||
companyId: companyId,
|
||||
warehouseLocationId: warehouseLocationId,
|
||||
search: search,
|
||||
);
|
||||
}
|
||||
|
||||
// 출고된 장비 목록 조회
|
||||
Future<PaginatedResponse<EquipmentListDto>> getEquipmentOutList({
|
||||
int page = 1,
|
||||
int perPage = 20,
|
||||
int? companyId,
|
||||
int? warehouseLocationId,
|
||||
String? search,
|
||||
}) async {
|
||||
return getEquipmentsWithStatus(
|
||||
page: page,
|
||||
perPage: perPage,
|
||||
status: 'in_use', // 출고된 장비는 사용 중 상태
|
||||
companyId: companyId,
|
||||
warehouseLocationId: warehouseLocationId,
|
||||
search: search,
|
||||
);
|
||||
}
|
||||
|
||||
// 장비 생성
|
||||
Future<Equipment> createEquipment(Equipment equipment) async {
|
||||
Future<EquipmentDto> createEquipment(EquipmentRequestDto request) async {
|
||||
try {
|
||||
final request = CreateEquipmentRequest(
|
||||
// 🔧 [BUG FIX] 사용자가 입력한 장비 번호를 우선 사용, 없으면 자동 생성
|
||||
// 기존: 항상 타임스탬프 기반 자동 생성으로 사용자 입력 무시
|
||||
// 수정: equipment.equipmentNumber가 있으면 우선 사용, null/empty면 자동 생성
|
||||
equipmentNumber: equipment.equipmentNumber?.isNotEmpty == true
|
||||
? equipment.equipmentNumber! // 사용자 입력값 사용
|
||||
: 'EQ-${DateTime.now().millisecondsSinceEpoch}', // 자동 생성 fallback
|
||||
category1: equipment.category1, // deprecated category 제거
|
||||
category2: equipment.category2, // deprecated subCategory 제거
|
||||
category3: equipment.category3, // deprecated subSubCategory 제거
|
||||
manufacturer: equipment.manufacturer,
|
||||
modelName: equipment.modelName, // deprecated name 제거
|
||||
serialNumber: equipment.serialNumber,
|
||||
barcode: equipment.barcode,
|
||||
purchaseDate: equipment.inDate,
|
||||
purchasePrice: equipment.purchasePrice,
|
||||
// 🔧 [BUG FIX] currentCompanyId → companyId 필드 수정
|
||||
// 문제: Controller에서 selectedCompanyId를 equipment.companyId로 설정하는데
|
||||
// EquipmentService에서 equipment.currentCompanyId를 참조해서 null 전송
|
||||
// 해결: equipment.companyId 참조로 변경하여 실제 선택값 전송
|
||||
companyId: equipment.companyId,
|
||||
warehouseLocationId: equipment.warehouseLocationId,
|
||||
lastInspectionDate: equipment.lastInspectionDate,
|
||||
nextInspectionDate: equipment.nextInspectionDate,
|
||||
remark: equipment.remark,
|
||||
);
|
||||
|
||||
final response = await _remoteDataSource.createEquipment(request);
|
||||
return _convertResponseToEquipment(response);
|
||||
return await _remoteDataSource.createEquipment(request);
|
||||
} on ServerException catch (e) {
|
||||
throw ServerFailure(message: e.message);
|
||||
} catch (e) {
|
||||
@@ -165,92 +59,10 @@ class EquipmentService {
|
||||
}
|
||||
}
|
||||
|
||||
// 장비 상세 조회
|
||||
Future<Equipment> getEquipmentDetail(int id) async {
|
||||
print('DEBUG [EquipmentService.getEquipmentDetail] Called with ID: $id');
|
||||
try {
|
||||
final response = await _remoteDataSource.getEquipmentDetail(id);
|
||||
print('DEBUG [EquipmentService.getEquipmentDetail] Response received from datasource');
|
||||
print('DEBUG [EquipmentService.getEquipmentDetail] Response data: ${response.toJson()}');
|
||||
|
||||
final equipment = _convertResponseToEquipment(response);
|
||||
print('DEBUG [EquipmentService.getEquipmentDetail] Converted to Equipment model');
|
||||
print('DEBUG [EquipmentService.getEquipmentDetail] Equipment.manufacturer="${equipment.manufacturer}"');
|
||||
print('DEBUG [EquipmentService.getEquipmentDetail] Equipment.equipmentNumber="${equipment.equipmentNumber}"'); // deprecated name 제거
|
||||
|
||||
return equipment;
|
||||
} on ServerException catch (e) {
|
||||
print('ERROR [EquipmentService.getEquipmentDetail] ServerException: ${e.message}');
|
||||
throw ServerFailure(message: e.message);
|
||||
} catch (e, stackTrace) {
|
||||
print('ERROR [EquipmentService.getEquipmentDetail] Unexpected error: $e');
|
||||
print('ERROR [EquipmentService.getEquipmentDetail] Stack trace: $stackTrace');
|
||||
throw ServerFailure(message: 'Failed to fetch equipment detail: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// 장비 조회 (getEquipmentDetail의 alias)
|
||||
Future<Equipment> getEquipment(int id) async {
|
||||
return getEquipmentDetail(id);
|
||||
}
|
||||
|
||||
// 장비 수정
|
||||
Future<Equipment> updateEquipment(int id, Equipment equipment) async {
|
||||
Future<EquipmentDto> updateEquipment(int id, EquipmentUpdateRequestDto request) async {
|
||||
try {
|
||||
final request = UpdateEquipmentRequest(
|
||||
category1: equipment.category1.isNotEmpty ? equipment.category1 : null, // deprecated category 제거
|
||||
category2: equipment.category2.isNotEmpty ? equipment.category2 : null, // deprecated subCategory 제거
|
||||
category3: equipment.category3.isNotEmpty ? equipment.category3 : null, // deprecated subSubCategory 제거
|
||||
manufacturer: equipment.manufacturer.isNotEmpty ? equipment.manufacturer : null,
|
||||
modelName: equipment.modelName.isNotEmpty ? equipment.modelName : null, // deprecated name 제거
|
||||
serialNumber: equipment.serialNumber?.isNotEmpty == true ? equipment.serialNumber : null,
|
||||
barcode: equipment.barcode?.isNotEmpty == true ? equipment.barcode : null,
|
||||
purchaseDate: equipment.purchaseDate,
|
||||
purchasePrice: equipment.purchasePrice,
|
||||
status: (equipment.equipmentStatus != null &&
|
||||
equipment.equipmentStatus != 'null' &&
|
||||
equipment.equipmentStatus!.isNotEmpty)
|
||||
? EquipmentStatusConverter.clientToServer(equipment.equipmentStatus)
|
||||
: null,
|
||||
companyId: equipment.companyId,
|
||||
warehouseLocationId: equipment.warehouseLocationId,
|
||||
lastInspectionDate: equipment.lastInspectionDate,
|
||||
nextInspectionDate: equipment.nextInspectionDate,
|
||||
remark: equipment.remark?.isNotEmpty == true ? equipment.remark : null,
|
||||
);
|
||||
|
||||
// 디버그 로그 추가 - 전송되는 데이터 확인
|
||||
print('DEBUG [EquipmentService.updateEquipment] Equipment model data:');
|
||||
print(' equipment.equipmentStatus: "${equipment.equipmentStatus}"');
|
||||
print(' equipment.equipmentStatus type: ${equipment.equipmentStatus.runtimeType}');
|
||||
print(' equipment.equipmentStatus == null: ${equipment.equipmentStatus == null}');
|
||||
print(' equipment.equipmentStatus == "null": ${equipment.equipmentStatus == "null"}');
|
||||
|
||||
String? convertedStatus;
|
||||
if (equipment.equipmentStatus != null) {
|
||||
convertedStatus = EquipmentStatusConverter.clientToServer(equipment.equipmentStatus);
|
||||
print(' converted status: "$convertedStatus"');
|
||||
} else {
|
||||
print(' status is null, will not set in request');
|
||||
}
|
||||
|
||||
print('DEBUG [EquipmentService.updateEquipment] Request data:');
|
||||
print(' manufacturer: "${request.manufacturer}"');
|
||||
print(' modelName: "${request.modelName}"');
|
||||
print(' serialNumber: "${request.serialNumber}"');
|
||||
print(' status: "${request.status}"');
|
||||
print(' companyId: ${request.companyId}');
|
||||
print(' warehouseLocationId: ${request.warehouseLocationId}');
|
||||
|
||||
// JSON 직렬화 확인
|
||||
final jsonData = request.toJson();
|
||||
print('DEBUG [EquipmentService.updateEquipment] JSON data:');
|
||||
jsonData.forEach((key, value) {
|
||||
print(' $key: $value (${value.runtimeType})');
|
||||
});
|
||||
|
||||
final response = await _remoteDataSource.updateEquipment(id, request);
|
||||
return _convertResponseToEquipment(response);
|
||||
return await _remoteDataSource.updateEquipment(id, request);
|
||||
} on ServerException catch (e) {
|
||||
throw ServerFailure(message: e.message);
|
||||
} catch (e) {
|
||||
@@ -269,11 +81,58 @@ class EquipmentService {
|
||||
}
|
||||
}
|
||||
|
||||
// 장비 상태 변경
|
||||
Future<Equipment> changeEquipmentStatus(int id, String status, String? reason) async {
|
||||
// 상태별 장비 조회
|
||||
Future<PaginatedResponse<EquipmentDto>> getEquipmentsWithStatus({
|
||||
int page = 1,
|
||||
int perPage = 20,
|
||||
String? search,
|
||||
String? status,
|
||||
}) async {
|
||||
try {
|
||||
final response = await _remoteDataSource.changeEquipmentStatus(id, status, reason);
|
||||
return _convertResponseToEquipment(response);
|
||||
final response = await _remoteDataSource.getEquipments(
|
||||
page: page,
|
||||
perPage: perPage,
|
||||
search: search,
|
||||
);
|
||||
|
||||
// 간단한 상태 필터링 (백엔드에서 지원하지 않는 경우 클라이언트 측에서)
|
||||
List<EquipmentDto> filteredItems = response.items;
|
||||
if (status != null && status.isNotEmpty) {
|
||||
// 실제 백엔드 스키마에는 상태 필드가 없으므로 모든 아이템을 반환
|
||||
// 실제 구현에서는 백엔드의 실제 필드를 사용해야 함
|
||||
filteredItems = response.items; // 모든 장비 반환
|
||||
}
|
||||
|
||||
return PaginatedResponse<EquipmentDto>(
|
||||
items: filteredItems,
|
||||
page: response.currentPage,
|
||||
size: response.pageSize ?? 20,
|
||||
totalElements: filteredItems.length,
|
||||
totalPages: (filteredItems.length / perPage).ceil(),
|
||||
first: response.currentPage == 1,
|
||||
last: response.currentPage >= response.totalPages,
|
||||
);
|
||||
} on ServerException catch (e) {
|
||||
throw ServerFailure(message: e.message);
|
||||
} catch (e) {
|
||||
throw ServerFailure(message: 'Failed to fetch equipments with status: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// 장비 상태 변경 (백엔드 스키마에서는 단순히 업데이트)
|
||||
Future<EquipmentDto> changeEquipmentStatus(int id, String newStatus) async {
|
||||
try {
|
||||
// 백엔드 스키마에는 상태 필드가 없으므로 기본 업데이트 사용
|
||||
// 실제 구현에서는 백엔드의 실제 필드를 사용해야 함
|
||||
final equipment = await getEquipmentDetail(id);
|
||||
final request = EquipmentUpdateRequestDto(
|
||||
companiesId: equipment.companiesId,
|
||||
modelsId: equipment.modelsId,
|
||||
serialNumber: equipment.serialNumber,
|
||||
// 실제 백엔드 필드들만 사용
|
||||
);
|
||||
|
||||
return await _remoteDataSource.updateEquipment(id, request);
|
||||
} on ServerException catch (e) {
|
||||
throw ServerFailure(message: e.message);
|
||||
} catch (e) {
|
||||
@@ -281,137 +140,16 @@ class EquipmentService {
|
||||
}
|
||||
}
|
||||
|
||||
// 장비 이력 추가
|
||||
Future<EquipmentHistoryDto> addEquipmentHistory(int equipmentId, String type, int quantity, String? remarks) async {
|
||||
try {
|
||||
final request = CreateHistoryRequest(
|
||||
transactionType: type,
|
||||
quantity: quantity,
|
||||
transactionDate: DateTime.now(),
|
||||
remarks: remarks,
|
||||
);
|
||||
|
||||
return await _remoteDataSource.addEquipmentHistory(equipmentId, request);
|
||||
} on ServerException catch (e) {
|
||||
throw ServerFailure(message: e.message);
|
||||
} catch (e) {
|
||||
throw ServerFailure(message: 'Failed to add equipment history: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// 장비 이력 조회
|
||||
Future<List<EquipmentHistoryDto>> getEquipmentHistory(int equipmentId, {int page = 1, int perPage = 20}) async {
|
||||
Future<List<dynamic>> getEquipmentHistory(int equipmentId, {int? page, int? perPage}) async {
|
||||
try {
|
||||
return await _remoteDataSource.getEquipmentHistory(equipmentId, page: page, perPage: perPage);
|
||||
// 장비 이력은 EquipmentHistoryService나 별도 서비스에서 처리해야 하지만
|
||||
// 호환성을 위해 빈 리스트 반환
|
||||
return [];
|
||||
} on ServerException catch (e) {
|
||||
throw ServerFailure(message: e.message);
|
||||
} catch (e) {
|
||||
throw ServerFailure(message: 'Failed to fetch equipment history: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// 장비 입고
|
||||
Future<EquipmentIoResponse> equipmentIn({
|
||||
required int equipmentId,
|
||||
required int quantity,
|
||||
int? warehouseLocationId,
|
||||
String? notes,
|
||||
}) async {
|
||||
try {
|
||||
final request = EquipmentInRequest(
|
||||
equipmentId: equipmentId,
|
||||
quantity: quantity,
|
||||
warehouseLocationId: warehouseLocationId,
|
||||
notes: notes,
|
||||
);
|
||||
|
||||
return await _remoteDataSource.equipmentIn(request);
|
||||
} on ServerException catch (e) {
|
||||
throw ServerFailure(message: e.message);
|
||||
} catch (e) {
|
||||
throw ServerFailure(message: 'Failed to process equipment in: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// 장비 출고
|
||||
Future<EquipmentIoResponse> equipmentOut({
|
||||
required int equipmentId,
|
||||
required int quantity,
|
||||
required int companyId,
|
||||
String? notes,
|
||||
}) async {
|
||||
try {
|
||||
final request = EquipmentOutRequest(
|
||||
equipmentId: equipmentId,
|
||||
quantity: quantity,
|
||||
companyId: companyId,
|
||||
notes: notes,
|
||||
);
|
||||
|
||||
return await _remoteDataSource.equipmentOut(request);
|
||||
} on ServerException catch (e) {
|
||||
throw ServerFailure(message: e.message);
|
||||
} catch (e) {
|
||||
throw ServerFailure(message: 'Failed to process equipment out: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// Private helper methods for model conversion
|
||||
Equipment _convertListDtoToEquipment(EquipmentListDto dto) {
|
||||
return Equipment(
|
||||
id: dto.id,
|
||||
manufacturer: dto.manufacturer,
|
||||
equipmentNumber: dto.equipmentNumber ?? '', // name → equipmentNumber (required)
|
||||
modelName: dto.modelName ?? '', // 새로운 필수 필드 (required)
|
||||
category1: '', // category → category1 (required)
|
||||
category2: '', // subCategory → category2 (required)
|
||||
category3: '', // subSubCategory → category3 (required)
|
||||
serialNumber: dto.serialNumber,
|
||||
barcode: null, // Not in list DTO
|
||||
quantity: 1, // Default quantity
|
||||
purchaseDate: dto.createdAt, // purchaseDate로 변경
|
||||
inDate: dto.createdAt, // 기존 inDate 유지
|
||||
remark: null, // Not in list DTO
|
||||
// 백엔드 API 새로운 필드들 (리스트 DTO에서는 제한적)
|
||||
currentCompanyId: dto.companyId,
|
||||
warehouseLocationId: dto.warehouseLocationId,
|
||||
equipmentStatus: dto.status,
|
||||
);
|
||||
}
|
||||
|
||||
Equipment _convertResponseToEquipment(EquipmentResponse response) {
|
||||
return Equipment(
|
||||
id: response.id,
|
||||
manufacturer: response.manufacturer,
|
||||
equipmentNumber: response.equipmentNumber ?? '', // name → equipmentNumber (required)
|
||||
modelName: response.modelName ?? '', // 새로운 필수 필드 (required)
|
||||
category1: response.category1 ?? '', // category → category1 (required)
|
||||
category2: response.category2 ?? '', // subCategory → category2 (required)
|
||||
category3: response.category3 ?? '', // subSubCategory → category3 (required)
|
||||
serialNumber: response.serialNumber,
|
||||
barcode: response.barcode,
|
||||
quantity: 1, // Default quantity, actual quantity should be tracked in history
|
||||
purchaseDate: response.purchaseDate, // purchaseDate로 변경
|
||||
inDate: response.purchaseDate, // 기존 inDate 유지
|
||||
remark: response.remark,
|
||||
// 백엔드 API 새로운 필드들 매핑 - 백엔드 완전 호환
|
||||
purchasePrice: response.purchasePrice != null ? double.tryParse(response.purchasePrice!) : null,
|
||||
currentCompanyId: response.companyId,
|
||||
warehouseLocationId: response.warehouseLocationId,
|
||||
companyId: response.companyId,
|
||||
lastInspectionDate: response.lastInspectionDate,
|
||||
nextInspectionDate: response.nextInspectionDate,
|
||||
equipmentStatus: response.status,
|
||||
// 중복 필드 제거 완료 - 대부분의 필드는 이미 위에서 정의됨
|
||||
);
|
||||
}
|
||||
|
||||
// 장비 상태 상수
|
||||
static const Map<String, String> equipmentStatus = {
|
||||
'available': '사용 가능',
|
||||
'in_use': '사용 중',
|
||||
'maintenance': '유지보수 중',
|
||||
'repair': '수리 중',
|
||||
'disposed': '폐기',
|
||||
};
|
||||
}
|
||||
@@ -80,9 +80,9 @@ class HealthTestService {
|
||||
'count': equipments.items.length,
|
||||
'sample': equipments.items.take(2).map((e) => {
|
||||
'id': e.id,
|
||||
'name': e.name,
|
||||
'manufacturer': e.manufacturer,
|
||||
'category': e.category,
|
||||
'name': e.serialNumber,
|
||||
'manufacturer': e.vendorName ?? 'Unknown',
|
||||
'category': e.modelName ?? 'Unknown',
|
||||
}).toList(),
|
||||
};
|
||||
|
||||
|
||||
@@ -1,330 +0,0 @@
|
||||
import 'package:get_it/get_it.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:injectable/injectable.dart';
|
||||
import 'package:superport/core/errors/exceptions.dart';
|
||||
import 'package:superport/core/errors/failures.dart';
|
||||
import 'package:superport/data/datasources/remote/license_remote_datasource.dart';
|
||||
import 'package:superport/data/models/common/paginated_response.dart';
|
||||
import 'package:superport/data/models/license/license_dto.dart';
|
||||
import 'package:superport/data/models/license/license_request_dto.dart';
|
||||
import 'package:superport/models/license_model.dart';
|
||||
|
||||
@lazySingleton
|
||||
class LicenseService {
|
||||
final LicenseRemoteDataSource _remoteDataSource;
|
||||
|
||||
LicenseService(this._remoteDataSource);
|
||||
|
||||
// 라이선스 목록 조회
|
||||
Future<PaginatedResponse<License>> getLicenses({
|
||||
int page = 1,
|
||||
int perPage = 20,
|
||||
bool? isActive,
|
||||
int? companyId,
|
||||
int? assignedUserId,
|
||||
String? licenseType,
|
||||
bool includeInactive = false,
|
||||
}) async {
|
||||
debugPrint('\n╔════════════════════════════════════════════════════════════');
|
||||
debugPrint('║ 📤 LICENSE API REQUEST');
|
||||
debugPrint('╟────────────────────────────────────────────────────────────');
|
||||
debugPrint('║ Endpoint: GET /licenses');
|
||||
debugPrint('║ Parameters:');
|
||||
debugPrint('║ - page: $page');
|
||||
debugPrint('║ - perPage: $perPage');
|
||||
if (isActive != null) debugPrint('║ - isActive: $isActive');
|
||||
if (companyId != null) debugPrint('║ - companyId: $companyId');
|
||||
if (assignedUserId != null) debugPrint('║ - assignedUserId: $assignedUserId');
|
||||
if (licenseType != null) debugPrint('║ - licenseType: $licenseType');
|
||||
debugPrint('║ - includeInactive: $includeInactive');
|
||||
debugPrint('╚════════════════════════════════════════════════════════════\n');
|
||||
|
||||
try {
|
||||
final response = await _remoteDataSource.getLicenses(
|
||||
page: page,
|
||||
perPage: perPage,
|
||||
isActive: isActive ?? !includeInactive,
|
||||
companyId: companyId,
|
||||
assignedUserId: assignedUserId,
|
||||
licenseType: licenseType,
|
||||
);
|
||||
|
||||
final licenses = response.items.map((dto) => _convertDtoToLicense(dto)).toList();
|
||||
|
||||
debugPrint('\n╔════════════════════════════════════════════════════════════');
|
||||
debugPrint('║ 📥 LICENSE API RESPONSE');
|
||||
debugPrint('╟────────────────────────────────────────────────────────────');
|
||||
debugPrint('║ Status: SUCCESS');
|
||||
debugPrint('║ Total Items: ${response.total}');
|
||||
debugPrint('║ Current Page: ${response.page}');
|
||||
debugPrint('║ Total Pages: ${response.totalPages}');
|
||||
debugPrint('║ Returned Items: ${licenses.length}');
|
||||
if (licenses.isNotEmpty) {
|
||||
debugPrint('║ Sample Data:');
|
||||
final sample = licenses.first;
|
||||
debugPrint('║ - ID: ${sample.id}');
|
||||
debugPrint('║ - Product: ${sample.productName}');
|
||||
debugPrint('║ - Company: ${sample.companyName ?? "N/A"}');
|
||||
}
|
||||
debugPrint('╚════════════════════════════════════════════════════════════\n');
|
||||
|
||||
return PaginatedResponse<License>(
|
||||
items: licenses,
|
||||
page: response.page,
|
||||
size: response.perPage,
|
||||
totalElements: response.total,
|
||||
totalPages: response.totalPages,
|
||||
first: response.page == 1,
|
||||
last: response.page >= response.totalPages,
|
||||
);
|
||||
} on ApiException catch (e) {
|
||||
debugPrint('\n╔════════════════════════════════════════════════════════════');
|
||||
debugPrint('║ ❌ LICENSE API ERROR');
|
||||
debugPrint('╟────────────────────────────────────────────────────────────');
|
||||
debugPrint('║ Type: ApiException');
|
||||
debugPrint('║ Message: ${e.message}');
|
||||
debugPrint('╚════════════════════════════════════════════════════════════\n');
|
||||
throw ServerFailure(message: e.message);
|
||||
} catch (e) {
|
||||
debugPrint('\n╔════════════════════════════════════════════════════════════');
|
||||
debugPrint('║ ❌ LICENSE API ERROR');
|
||||
debugPrint('╟────────────────────────────────────────────────────────────');
|
||||
debugPrint('║ Type: Unknown');
|
||||
debugPrint('║ Error: $e');
|
||||
debugPrint('╚════════════════════════════════════════════════════════════\n');
|
||||
throw ServerFailure(message: '라이선스 목록을 불러오는 데 실패했습니다: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// 라이선스 상세 조회
|
||||
Future<License> getLicenseById(int id) async {
|
||||
try {
|
||||
final dto = await _remoteDataSource.getLicenseById(id);
|
||||
return _convertDtoToLicense(dto);
|
||||
} on ApiException catch (e) {
|
||||
throw ServerFailure(message: e.message);
|
||||
} catch (e) {
|
||||
throw ServerFailure(message: '라이선스 정보를 불러오는 데 실패했습니다: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// 라이선스 생성
|
||||
Future<License> createLicense(License license) async {
|
||||
debugPrint('\n╔════════════════════════════════════════════════════════════');
|
||||
debugPrint('║ 📤 LICENSE CREATE REQUEST');
|
||||
debugPrint('╟────────────────────────────────────────────────────────────');
|
||||
debugPrint('║ Endpoint: POST /licenses');
|
||||
debugPrint('║ Request Data:');
|
||||
debugPrint('║ - licenseKey: ${license.licenseKey}');
|
||||
debugPrint('║ - productName: ${license.productName}');
|
||||
debugPrint('║ - vendor: ${license.vendor}');
|
||||
debugPrint('║ - companyId: ${license.companyId}');
|
||||
debugPrint('║ - expiryDate: ${license.expiryDate?.toIso8601String()}');
|
||||
debugPrint('╚════════════════════════════════════════════════════════════\n');
|
||||
|
||||
try {
|
||||
final request = CreateLicenseRequest(
|
||||
licenseKey: license.licenseKey,
|
||||
productName: license.productName,
|
||||
vendor: license.vendor,
|
||||
licenseType: license.licenseType,
|
||||
userCount: license.userCount,
|
||||
purchaseDate: license.purchaseDate,
|
||||
expiryDate: license.expiryDate,
|
||||
purchasePrice: license.purchasePrice,
|
||||
companyId: license.companyId,
|
||||
branchId: license.branchId,
|
||||
remark: license.remark,
|
||||
);
|
||||
|
||||
final dto = await _remoteDataSource.createLicense(request);
|
||||
final createdLicense = _convertDtoToLicense(dto);
|
||||
|
||||
debugPrint('\n╔════════════════════════════════════════════════════════════');
|
||||
debugPrint('║ 📥 LICENSE CREATE RESPONSE');
|
||||
debugPrint('╟────────────────────────────────────────────────────────────');
|
||||
debugPrint('║ Status: SUCCESS');
|
||||
debugPrint('║ Created License:');
|
||||
debugPrint('║ - ID: ${createdLicense.id}');
|
||||
debugPrint('║ - Key: ${createdLicense.licenseKey}');
|
||||
debugPrint('║ - Product: ${createdLicense.productName}');
|
||||
debugPrint('╚════════════════════════════════════════════════════════════\n');
|
||||
|
||||
return createdLicense;
|
||||
} on ApiException catch (e) {
|
||||
debugPrint('\n╔════════════════════════════════════════════════════════════');
|
||||
debugPrint('║ ❌ LICENSE CREATE ERROR');
|
||||
debugPrint('╟────────────────────────────────────────────────────────────');
|
||||
debugPrint('║ Type: ApiException');
|
||||
debugPrint('║ Message: ${e.message}');
|
||||
debugPrint('╚════════════════════════════════════════════════════════════\n');
|
||||
throw ServerFailure(message: e.message);
|
||||
} catch (e) {
|
||||
debugPrint('\n╔════════════════════════════════════════════════════════════');
|
||||
debugPrint('║ ❌ LICENSE CREATE ERROR');
|
||||
debugPrint('╟────────────────────────────────────────────────────────────');
|
||||
debugPrint('║ Type: Unknown');
|
||||
debugPrint('║ Error: $e');
|
||||
debugPrint('╚════════════════════════════════════════════════════════════\n');
|
||||
throw ServerFailure(message: '라이선스 생성에 실패했습니다: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// 라이선스 수정
|
||||
Future<License> updateLicense(License license) async {
|
||||
try {
|
||||
if (license.id == null) {
|
||||
throw BusinessFailure(message: '라이선스 ID가 없습니다');
|
||||
}
|
||||
|
||||
final request = UpdateLicenseRequest(
|
||||
licenseKey: license.licenseKey,
|
||||
productName: license.productName,
|
||||
vendor: license.vendor,
|
||||
licenseType: license.licenseType,
|
||||
userCount: license.userCount,
|
||||
purchaseDate: license.purchaseDate,
|
||||
expiryDate: license.expiryDate,
|
||||
purchasePrice: license.purchasePrice,
|
||||
remark: license.remark,
|
||||
isActive: license.isActive,
|
||||
);
|
||||
|
||||
final dto = await _remoteDataSource.updateLicense(license.id!, request);
|
||||
return _convertDtoToLicense(dto);
|
||||
} on ApiException catch (e) {
|
||||
throw ServerFailure(message: e.message);
|
||||
} catch (e) {
|
||||
throw ServerFailure(message: '라이선스 수정에 실패했습니다: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// 라이선스 삭제
|
||||
Future<void> deleteLicense(int id) async {
|
||||
try {
|
||||
await _remoteDataSource.deleteLicense(id);
|
||||
} on ApiException catch (e) {
|
||||
throw ServerFailure(message: e.message);
|
||||
} catch (e) {
|
||||
throw ServerFailure(message: '라이선스 삭제에 실패했습니다: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// 라이선스 할당
|
||||
Future<License> assignLicense(int licenseId, int userId) async {
|
||||
try {
|
||||
final request = AssignLicenseRequest(userId: userId);
|
||||
final dto = await _remoteDataSource.assignLicense(licenseId, request);
|
||||
return _convertDtoToLicense(dto);
|
||||
} on ApiException catch (e) {
|
||||
throw ServerFailure(message: e.message);
|
||||
} catch (e) {
|
||||
throw ServerFailure(message: '라이선스 할당에 실패했습니다: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// 라이선스 할당 해제
|
||||
Future<License> unassignLicense(int licenseId) async {
|
||||
try {
|
||||
final dto = await _remoteDataSource.unassignLicense(licenseId);
|
||||
return _convertDtoToLicense(dto);
|
||||
} on ApiException catch (e) {
|
||||
throw ServerFailure(message: e.message);
|
||||
} catch (e) {
|
||||
throw ServerFailure(message: '라이선스 할당 해제에 실패했습니다: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// 만료 예정 라이선스 조회
|
||||
Future<List<License>> getExpiringLicenses({
|
||||
int days = 30,
|
||||
int page = 1,
|
||||
int perPage = 20,
|
||||
}) async {
|
||||
try {
|
||||
final response = await _remoteDataSource.getExpiringLicenses(
|
||||
days: days,
|
||||
page: page,
|
||||
perPage: perPage,
|
||||
);
|
||||
|
||||
return response.items.map((dto) => _convertExpiringDtoToLicense(dto)).toList();
|
||||
} on ApiException catch (e) {
|
||||
throw ServerFailure(message: e.message);
|
||||
} catch (e) {
|
||||
throw ServerFailure(message: '만료 예정 라이선스를 불러오는 데 실패했습니다: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// DTO를 Flutter 모델로 변환
|
||||
License _convertDtoToLicense(LicenseDto dto) {
|
||||
return License(
|
||||
id: dto.id,
|
||||
licenseKey: dto.licenseKey,
|
||||
productName: dto.productName,
|
||||
vendor: dto.vendor,
|
||||
licenseType: dto.licenseType,
|
||||
userCount: dto.userCount,
|
||||
purchaseDate: dto.purchaseDate,
|
||||
expiryDate: dto.expiryDate,
|
||||
purchasePrice: dto.purchasePrice,
|
||||
companyId: dto.companyId,
|
||||
branchId: dto.branchId,
|
||||
assignedUserId: dto.assignedUserId,
|
||||
remark: dto.remark,
|
||||
isActive: dto.isActive ?? true,
|
||||
createdAt: dto.createdAt,
|
||||
updatedAt: dto.updatedAt,
|
||||
companyName: dto.companyName,
|
||||
branchName: dto.branchName,
|
||||
assignedUserName: dto.assignedUserName,
|
||||
);
|
||||
}
|
||||
|
||||
// 만료 예정 DTO를 Flutter 모델로 변환
|
||||
License _convertExpiringDtoToLicense(ExpiringLicenseDto dto) {
|
||||
return License(
|
||||
id: dto.id,
|
||||
licenseKey: dto.licenseKey,
|
||||
productName: dto.productName,
|
||||
vendor: null,
|
||||
licenseType: null,
|
||||
userCount: null,
|
||||
purchaseDate: null,
|
||||
expiryDate: dto.expiryDate,
|
||||
purchasePrice: null,
|
||||
companyId: null,
|
||||
branchId: null,
|
||||
assignedUserId: null,
|
||||
remark: null,
|
||||
isActive: dto.isActive ?? true,
|
||||
createdAt: null,
|
||||
updatedAt: null,
|
||||
companyName: dto.companyName,
|
||||
branchName: null,
|
||||
assignedUserName: null,
|
||||
);
|
||||
}
|
||||
|
||||
// 페이지네이션 정보
|
||||
Future<int> getTotalLicenses({
|
||||
bool? isActive,
|
||||
int? companyId,
|
||||
int? assignedUserId,
|
||||
String? licenseType,
|
||||
}) async {
|
||||
try {
|
||||
final response = await _remoteDataSource.getLicenses(
|
||||
page: 1,
|
||||
perPage: 1,
|
||||
isActive: isActive,
|
||||
companyId: companyId,
|
||||
assignedUserId: assignedUserId,
|
||||
licenseType: licenseType,
|
||||
);
|
||||
return response.total;
|
||||
} catch (e) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,13 +64,11 @@ class UserService {
|
||||
String? position,
|
||||
}) async {
|
||||
try {
|
||||
final request = CreateUserRequest(
|
||||
username: username,
|
||||
email: email,
|
||||
password: password,
|
||||
final request = UserRequestDto(
|
||||
name: name,
|
||||
role: _mapRoleToApi(role),
|
||||
email: email,
|
||||
phone: phone,
|
||||
companiesId: companyId,
|
||||
);
|
||||
|
||||
final dto = await _userRemoteDataSource.createUser(request);
|
||||
@@ -93,12 +91,11 @@ class UserService {
|
||||
String? position,
|
||||
}) async {
|
||||
try {
|
||||
final request = UpdateUserRequest(
|
||||
final request = UserUpdateRequestDto(
|
||||
name: name,
|
||||
email: email,
|
||||
password: password,
|
||||
phone: phone,
|
||||
role: role != null ? _mapRoleToApi(role) : null,
|
||||
companiesId: companyId,
|
||||
);
|
||||
|
||||
final dto = await _userRemoteDataSource.updateUser(id, request);
|
||||
@@ -175,45 +172,18 @@ class UserService {
|
||||
/// DTO를 Model로 변환 (새로운 User 모델 구조 대응)
|
||||
User _userDtoToModel(UserDto dto) {
|
||||
return User(
|
||||
id: dto.id,
|
||||
username: dto.username,
|
||||
email: dto.email,
|
||||
id: dto.id ?? 0,
|
||||
username: dto.name, // UserDto에는 username이 없으므로 name 사용
|
||||
email: dto.email ?? '',
|
||||
name: dto.name,
|
||||
phone: dto.phone,
|
||||
role: UserRole.fromString(dto.role),
|
||||
isActive: dto.isActive,
|
||||
createdAt: dto.createdAt,
|
||||
updatedAt: dto.updatedAt,
|
||||
role: UserRole.staff, // UserDto에는 role이 없으므로 기본값
|
||||
isActive: true, // UserDto에는 isActive가 없으므로 기본값
|
||||
createdAt: DateTime.now(), // UserDto에는 createdAt이 없으므로 현재 시간
|
||||
updatedAt: DateTime.now(), // UserDto에는 updatedAt이 없으므로 현재 시간
|
||||
);
|
||||
}
|
||||
|
||||
/// 권한을 API 형식으로 변환
|
||||
String _mapRoleToApi(String role) {
|
||||
switch (role) {
|
||||
case 'S':
|
||||
return 'admin';
|
||||
case 'M':
|
||||
return 'staff';
|
||||
default:
|
||||
return 'staff';
|
||||
}
|
||||
}
|
||||
|
||||
/// API 권한을 앱 형식으로 변환
|
||||
String _mapRoleFromApi(String? role) {
|
||||
if (role == null) return 'M'; // null인 경우 기본값
|
||||
|
||||
switch (role) {
|
||||
case 'admin':
|
||||
return 'S';
|
||||
case 'manager':
|
||||
return 'M';
|
||||
case 'staff':
|
||||
return 'M';
|
||||
default:
|
||||
return 'M';
|
||||
}
|
||||
}
|
||||
|
||||
/// 전화번호 목록에서 첫 번째 전화번호 추출
|
||||
String? getPhoneForApi(List<Map<String, String>> phoneNumbers) {
|
||||
|
||||
@@ -63,12 +63,9 @@ class WarehouseService {
|
||||
// 창고 위치 생성
|
||||
Future<WarehouseLocation> createWarehouseLocation(WarehouseLocation location) async {
|
||||
try {
|
||||
final request = CreateWarehouseLocationRequest(
|
||||
final request = WarehouseRequestDto(
|
||||
name: location.name,
|
||||
address: location.address, // 단일 문자열 주소
|
||||
managerName: location.managerName,
|
||||
managerPhone: location.managerPhone,
|
||||
capacity: location.capacity,
|
||||
zipcodesZipcode: null, // WarehouseRequestDto에는 zipcodes_zipcode만 있음
|
||||
remark: location.remark,
|
||||
);
|
||||
|
||||
@@ -84,12 +81,9 @@ class WarehouseService {
|
||||
// 창고 위치 수정
|
||||
Future<WarehouseLocation> updateWarehouseLocation(WarehouseLocation location) async {
|
||||
try {
|
||||
final request = UpdateWarehouseLocationRequest(
|
||||
final request = WarehouseUpdateRequestDto(
|
||||
name: location.name,
|
||||
address: location.address, // 단일 문자열 주소
|
||||
managerName: location.managerName,
|
||||
managerPhone: location.managerPhone,
|
||||
capacity: location.capacity,
|
||||
zipcodesZipcode: null, // WarehouseUpdateRequestDto에는 zipcodes_zipcode만 있음
|
||||
remark: location.remark,
|
||||
);
|
||||
|
||||
@@ -128,13 +122,10 @@ class WarehouseService {
|
||||
|
||||
return response.items.map((dto) => {
|
||||
'id': dto.id,
|
||||
'equipmentNumber': dto.equipmentNumber,
|
||||
'manufacturer': dto.manufacturer,
|
||||
'equipmentName': dto.equipmentName,
|
||||
'serialNumber': dto.serialNumber,
|
||||
'equipmentId': dto.equipmentId,
|
||||
'warehouseId': dto.warehouseId,
|
||||
'name': dto.name,
|
||||
'quantity': dto.quantity,
|
||||
'status': dto.status,
|
||||
'storedAt': dto.storedAt,
|
||||
}).toList();
|
||||
} on ApiException catch (e) {
|
||||
throw ServerFailure(message: e.message);
|
||||
@@ -167,17 +158,17 @@ class WarehouseService {
|
||||
}
|
||||
|
||||
// DTO를 Flutter 모델로 변환 (백엔드 API 호환)
|
||||
WarehouseLocation _convertDtoToWarehouseLocation(WarehouseLocationDto dto) {
|
||||
WarehouseLocation _convertDtoToWarehouseLocation(WarehouseDto dto) {
|
||||
return WarehouseLocation(
|
||||
id: dto.id,
|
||||
id: dto.id ?? 0,
|
||||
name: dto.name,
|
||||
address: dto.address, // 단일 문자열 주소
|
||||
managerName: dto.managerName,
|
||||
managerPhone: dto.managerPhone,
|
||||
capacity: dto.capacity,
|
||||
address: dto.zipcodeAddress ?? dto.zipcodesZipcode ?? '', // 주소 정보 매핑
|
||||
managerName: '', // 백엔드에 없는 필드 - 빈 문자열
|
||||
managerPhone: '', // 백엔드에 없는 필드 - 빈 문자열
|
||||
capacity: 0, // 백엔드에 없는 필드 - 기본값 0
|
||||
remark: dto.remark,
|
||||
isActive: dto.isActive,
|
||||
createdAt: dto.createdAt,
|
||||
isActive: !dto.isDeleted, // isDeleted의 반대가 isActive
|
||||
createdAt: dto.registeredAt, // registeredAt를 createdAt으로 매핑
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user