사용하지 않는 파일 정리 전 백업 (Phase 10 완료 후 상태)
This commit is contained in:
251
lib/data/datasources/remote/administrator_remote_datasource.dart
Normal file
251
lib/data/datasources/remote/administrator_remote_datasource.dart
Normal file
@@ -0,0 +1,251 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:injectable/injectable.dart';
|
||||
import 'package:superport/core/errors/exceptions.dart';
|
||||
import 'package:superport/data/datasources/remote/api_client.dart';
|
||||
import 'package:superport/data/models/administrator_dto.dart';
|
||||
|
||||
/// 관리자 원격 데이터 소스 (백엔드 Administrator 테이블)
|
||||
/// 엔드포인트: /api/v1/administrators
|
||||
abstract class AdministratorRemoteDataSource {
|
||||
/// 관리자 목록 조회 (페이지네이션 지원)
|
||||
Future<AdministratorListResponse> getAdministrators({
|
||||
int page = 1,
|
||||
int pageSize = 20,
|
||||
String? search,
|
||||
});
|
||||
|
||||
/// 단일 관리자 조회
|
||||
Future<AdministratorDto> getAdministrator(int id);
|
||||
|
||||
/// 관리자 생성
|
||||
Future<AdministratorDto> createAdministrator(AdministratorRequestDto request);
|
||||
|
||||
/// 관리자 정보 수정
|
||||
Future<AdministratorDto> updateAdministrator(int id, AdministratorUpdateRequestDto request);
|
||||
|
||||
/// 관리자 삭제
|
||||
Future<void> deleteAdministrator(int id);
|
||||
|
||||
/// 이메일 중복 확인
|
||||
Future<bool> checkEmailAvailability(String email, {int? excludeId});
|
||||
|
||||
/// 관리자 인증 (로그인)
|
||||
Future<AdministratorDto> authenticateAdministrator(String email, String password);
|
||||
}
|
||||
|
||||
@LazySingleton(as: AdministratorRemoteDataSource)
|
||||
class AdministratorRemoteDataSourceImpl implements AdministratorRemoteDataSource {
|
||||
final ApiClient _apiClient;
|
||||
|
||||
AdministratorRemoteDataSourceImpl(this._apiClient);
|
||||
|
||||
/// 관리자 목록 조회
|
||||
@override
|
||||
Future<AdministratorListResponse> getAdministrators({
|
||||
int page = 1,
|
||||
int pageSize = 20,
|
||||
String? search,
|
||||
}) async {
|
||||
try {
|
||||
final queryParams = <String, dynamic>{
|
||||
'page': page,
|
||||
'page_size': pageSize,
|
||||
};
|
||||
|
||||
if (search != null && search.isNotEmpty) {
|
||||
queryParams['search'] = search;
|
||||
}
|
||||
|
||||
final response = await _apiClient.get(
|
||||
'/administrators',
|
||||
queryParameters: queryParams,
|
||||
);
|
||||
|
||||
if (response.data != null) {
|
||||
return AdministratorListResponse.fromJson(response.data);
|
||||
} else {
|
||||
throw ApiException(
|
||||
message: '관리자 목록 조회 응답이 비어있습니다',
|
||||
statusCode: response.statusCode ?? 500,
|
||||
);
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
throw ApiException(
|
||||
message: e.message ?? '관리자 목록 조회 중 오류 발생',
|
||||
statusCode: e.response?.statusCode,
|
||||
);
|
||||
} catch (e) {
|
||||
throw ApiException(
|
||||
message: '관리자 목록 조회 중 오류 발생: ${e.toString()}',
|
||||
statusCode: 500,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 단일 관리자 조회
|
||||
@override
|
||||
Future<AdministratorDto> getAdministrator(int id) async {
|
||||
try {
|
||||
final response = await _apiClient.get('/administrators/$id');
|
||||
|
||||
if (response.data != null) {
|
||||
return AdministratorDto.fromJson(response.data);
|
||||
} else {
|
||||
throw ApiException(
|
||||
message: '관리자 정보 조회 응답이 비어있습니다',
|
||||
statusCode: response.statusCode ?? 500,
|
||||
);
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
throw ApiException(
|
||||
message: e.message ?? 'API 호출 중 오류 발생',
|
||||
statusCode: e.response?.statusCode,
|
||||
);
|
||||
} catch (e) {
|
||||
throw ApiException(
|
||||
message: '관리자 정보 조회 중 오류 발생: ${e.toString()}',
|
||||
statusCode: 500,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 관리자 생성
|
||||
@override
|
||||
Future<AdministratorDto> createAdministrator(AdministratorRequestDto request) async {
|
||||
try {
|
||||
final response = await _apiClient.post(
|
||||
'/administrators',
|
||||
data: request.toJson(),
|
||||
);
|
||||
|
||||
if (response.data != null) {
|
||||
return AdministratorDto.fromJson(response.data);
|
||||
} else {
|
||||
throw ApiException(
|
||||
message: '관리자 생성 응답이 비어있습니다',
|
||||
statusCode: response.statusCode ?? 500,
|
||||
);
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
throw ApiException(
|
||||
message: e.message ?? 'API 호출 중 오류 발생',
|
||||
statusCode: e.response?.statusCode,
|
||||
);
|
||||
} catch (e) {
|
||||
throw ApiException(
|
||||
message: '관리자 생성 중 오류 발생: ${e.toString()}',
|
||||
statusCode: 500,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 관리자 정보 수정
|
||||
@override
|
||||
Future<AdministratorDto> updateAdministrator(int id, AdministratorUpdateRequestDto request) async {
|
||||
try {
|
||||
final response = await _apiClient.put(
|
||||
'/administrators/$id',
|
||||
data: request.toJson(),
|
||||
);
|
||||
|
||||
if (response.data != null) {
|
||||
return AdministratorDto.fromJson(response.data);
|
||||
} else {
|
||||
throw ApiException(
|
||||
message: '관리자 정보 수정 응답이 비어있습니다',
|
||||
statusCode: response.statusCode ?? 500,
|
||||
);
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
throw ApiException(
|
||||
message: e.message ?? 'API 호출 중 오류 발생',
|
||||
statusCode: e.response?.statusCode,
|
||||
);
|
||||
} catch (e) {
|
||||
throw ApiException(
|
||||
message: '관리자 정보 수정 중 오류 발생: ${e.toString()}',
|
||||
statusCode: 500,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 관리자 삭제
|
||||
@override
|
||||
Future<void> deleteAdministrator(int id) async {
|
||||
try {
|
||||
await _apiClient.delete('/administrators/$id');
|
||||
} on DioException catch (e) {
|
||||
throw ApiException(
|
||||
message: e.message ?? 'API 호출 중 오류 발생',
|
||||
statusCode: e.response?.statusCode,
|
||||
);
|
||||
} catch (e) {
|
||||
throw ApiException(
|
||||
message: '관리자 삭제 중 오류 발생: ${e.toString()}',
|
||||
statusCode: 500,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 이메일 중복 확인 (미래에 백엔드에서 지원될 수 있는 기능)
|
||||
@override
|
||||
Future<bool> checkEmailAvailability(String email, {int? excludeId}) async {
|
||||
try {
|
||||
// 현재는 단순히 true 반환 (중복되지 않음으로 가정)
|
||||
// 실제 백엔드 구현 시 아래와 같이 호출
|
||||
/*
|
||||
final queryParams = <String, dynamic>{
|
||||
'email': email,
|
||||
if (excludeId != null) 'exclude_id': excludeId,
|
||||
};
|
||||
|
||||
final response = await _apiClient.get(
|
||||
'/administrators/check-email',
|
||||
queryParameters: queryParams,
|
||||
);
|
||||
|
||||
return response.data['available'] ?? false;
|
||||
*/
|
||||
|
||||
return true; // 임시로 항상 사용 가능으로 반환
|
||||
} catch (e) {
|
||||
// 에러 발생 시 안전하게 false 반환 (사용 불가로 처리)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// 관리자 인증 (로그인)
|
||||
@override
|
||||
Future<AdministratorDto> authenticateAdministrator(String email, String password) async {
|
||||
try {
|
||||
final response = await _apiClient.post(
|
||||
'/auth/login',
|
||||
data: {
|
||||
'email': email,
|
||||
'password': password,
|
||||
},
|
||||
);
|
||||
|
||||
if (response.data != null && response.data['user'] != null) {
|
||||
return AdministratorDto.fromJson(response.data['user']);
|
||||
} else if (response.data != null) {
|
||||
return AdministratorDto.fromJson(response.data);
|
||||
} else {
|
||||
throw ApiException(
|
||||
message: '로그인 응답이 비어있습니다',
|
||||
statusCode: response.statusCode ?? 500,
|
||||
);
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
throw ApiException(
|
||||
message: e.message ?? 'API 호출 중 오류 발생',
|
||||
statusCode: e.response?.statusCode,
|
||||
);
|
||||
} catch (e) {
|
||||
throw ApiException(
|
||||
message: '관리자 인증 중 오류 발생: ${e.toString()}',
|
||||
statusCode: 500,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ class AuthRemoteDataSourceImpl implements AuthRemoteDataSource {
|
||||
final dataFields = responseData['data'] as Map<String, dynamic>;
|
||||
DebugLogger.validateResponseStructure(
|
||||
dataFields,
|
||||
['access_token', 'refresh_token', 'user'],
|
||||
['access_token', 'refresh_token', 'admin'], // API returns 'admin' instead of 'user'
|
||||
responseName: 'LoginResponse.data',
|
||||
);
|
||||
|
||||
@@ -81,7 +81,7 @@ class AuthRemoteDataSourceImpl implements AuthRemoteDataSource {
|
||||
// 응답 데이터 구조 검증 (snake_case 키 확인)
|
||||
DebugLogger.validateResponseStructure(
|
||||
responseData as Map<String, dynamic>,
|
||||
['access_token', 'refresh_token', 'user'],
|
||||
['access_token', 'refresh_token', 'admin'], // API returns 'admin' instead of 'user'
|
||||
responseName: 'LoginResponse',
|
||||
);
|
||||
|
||||
|
||||
@@ -19,13 +19,13 @@ abstract class CompanyRemoteDataSource {
|
||||
bool? isActive,
|
||||
});
|
||||
|
||||
Future<CompanyResponse> createCompany(CreateCompanyRequest request);
|
||||
Future<CompanyDto> createCompany(CompanyRequestDto request);
|
||||
|
||||
Future<CompanyResponse> getCompanyDetail(int id);
|
||||
Future<CompanyDto> getCompanyDetail(int id);
|
||||
|
||||
Future<CompanyWithChildren> getCompanyWithChildren(int id);
|
||||
|
||||
Future<CompanyResponse> updateCompany(int id, UpdateCompanyRequest request);
|
||||
Future<CompanyDto> updateCompany(int id, CompanyUpdateRequestDto request);
|
||||
|
||||
Future<void> deleteCompany(int id);
|
||||
|
||||
@@ -123,7 +123,7 @@ class CompanyRemoteDataSourceImpl implements CompanyRemoteDataSource {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<CompanyResponse> createCompany(CreateCompanyRequest request) async {
|
||||
Future<CompanyDto> createCompany(CompanyRequestDto request) async {
|
||||
try {
|
||||
debugPrint('[CompanyRemoteDataSource] Sending POST request to ${ApiEndpoints.companies}');
|
||||
debugPrint('[CompanyRemoteDataSource] Request data: ${request.toJson()}');
|
||||
@@ -141,12 +141,12 @@ class CompanyRemoteDataSourceImpl implements CompanyRemoteDataSource {
|
||||
final responseData = response.data;
|
||||
if (responseData != null && responseData['success'] == true && responseData['data'] != null) {
|
||||
// 직접 파싱
|
||||
return CompanyResponse.fromJson(responseData['data'] as Map<String, dynamic>);
|
||||
return CompanyDto.fromJson(responseData['data'] as Map<String, dynamic>);
|
||||
} else {
|
||||
// ApiResponse 형식으로 파싱 시도
|
||||
final apiResponse = ApiResponse<CompanyResponse>.fromJson(
|
||||
final apiResponse = ApiResponse<CompanyDto>.fromJson(
|
||||
response.data,
|
||||
(json) => CompanyResponse.fromJson(json as Map<String, dynamic>),
|
||||
(json) => CompanyDto.fromJson(json as Map<String, dynamic>),
|
||||
);
|
||||
return apiResponse.data!;
|
||||
}
|
||||
@@ -165,13 +165,13 @@ class CompanyRemoteDataSourceImpl implements CompanyRemoteDataSource {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<CompanyResponse> getCompanyDetail(int id) async {
|
||||
Future<CompanyDto> getCompanyDetail(int id) async {
|
||||
try {
|
||||
final response = await _apiClient.dio.get(
|
||||
'${ApiEndpoints.companies}/$id',
|
||||
);
|
||||
|
||||
return CompanyResponse.fromJson(response.data['data']);
|
||||
return CompanyDto.fromJson(response.data['data']);
|
||||
} on DioException catch (e) {
|
||||
throw ServerException(
|
||||
message: e.response?.data['message'] ?? 'Failed to fetch company detail',
|
||||
@@ -197,14 +197,14 @@ class CompanyRemoteDataSourceImpl implements CompanyRemoteDataSource {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<CompanyResponse> updateCompany(int id, UpdateCompanyRequest request) async {
|
||||
Future<CompanyDto> updateCompany(int id, CompanyUpdateRequestDto request) async {
|
||||
try {
|
||||
final response = await _apiClient.dio.put(
|
||||
'${ApiEndpoints.companies}/$id',
|
||||
data: request.toJson(),
|
||||
);
|
||||
|
||||
return CompanyResponse.fromJson(response.data['data']);
|
||||
return CompanyDto.fromJson(response.data['data']);
|
||||
} on DioException catch (e) {
|
||||
throw ServerException(
|
||||
message: e.response?.data['message'] ?? 'Failed to update company',
|
||||
|
||||
@@ -3,66 +3,38 @@ import 'package:get_it/get_it.dart';
|
||||
import 'package:superport/core/constants/api_endpoints.dart';
|
||||
import 'package:superport/core/errors/exceptions.dart';
|
||||
import 'package:superport/data/datasources/remote/api_client.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/data/models/equipment/equipment_dto.dart';
|
||||
|
||||
abstract class EquipmentRemoteDataSource {
|
||||
Future<EquipmentListResponseDto> getEquipments({
|
||||
Future<EquipmentListResponse> getEquipments({
|
||||
int page = 1,
|
||||
int perPage = 20,
|
||||
String? status,
|
||||
int? companyId,
|
||||
int? warehouseLocationId,
|
||||
String? search,
|
||||
bool? isActive,
|
||||
});
|
||||
|
||||
Future<EquipmentResponse> createEquipment(CreateEquipmentRequest request);
|
||||
Future<EquipmentDto> createEquipment(EquipmentRequestDto request);
|
||||
|
||||
Future<EquipmentResponse> getEquipmentDetail(int id);
|
||||
Future<EquipmentDto> getEquipmentDetail(int id);
|
||||
|
||||
Future<EquipmentResponse> updateEquipment(int id, UpdateEquipmentRequest request);
|
||||
Future<EquipmentDto> updateEquipment(int id, EquipmentUpdateRequestDto request);
|
||||
|
||||
Future<void> deleteEquipment(int id);
|
||||
|
||||
Future<EquipmentResponse> changeEquipmentStatus(int id, String status, String? reason);
|
||||
|
||||
Future<EquipmentHistoryDto> addEquipmentHistory(int equipmentId, CreateHistoryRequest request);
|
||||
|
||||
Future<List<EquipmentHistoryDto>> getEquipmentHistory(int equipmentId, {int page = 1, int perPage = 20});
|
||||
|
||||
Future<EquipmentIoResponse> equipmentIn(EquipmentInRequest request);
|
||||
|
||||
Future<EquipmentIoResponse> equipmentOut(EquipmentOutRequest request);
|
||||
}
|
||||
|
||||
class EquipmentRemoteDataSourceImpl implements EquipmentRemoteDataSource {
|
||||
final ApiClient _apiClient = GetIt.instance<ApiClient>();
|
||||
|
||||
@override
|
||||
Future<EquipmentListResponseDto> getEquipments({
|
||||
Future<EquipmentListResponse> getEquipments({
|
||||
int page = 1,
|
||||
int perPage = 20,
|
||||
String? status,
|
||||
int? companyId,
|
||||
int? warehouseLocationId,
|
||||
String? search,
|
||||
bool? isActive,
|
||||
}) async {
|
||||
try {
|
||||
final queryParams = {
|
||||
final queryParams = <String, dynamic>{
|
||||
'page': page,
|
||||
'per_page': perPage,
|
||||
if (status != null) 'status': status,
|
||||
if (companyId != null) 'company_id': companyId,
|
||||
if (warehouseLocationId != null) 'warehouse_location_id': warehouseLocationId,
|
||||
'page_size': perPage,
|
||||
if (search != null && search.isNotEmpty) 'search': search,
|
||||
if (isActive != null) 'is_active': isActive,
|
||||
};
|
||||
|
||||
final response = await _apiClient.get(
|
||||
@@ -70,25 +42,11 @@ class EquipmentRemoteDataSourceImpl implements EquipmentRemoteDataSource {
|
||||
queryParameters: queryParams,
|
||||
);
|
||||
|
||||
if (response.data['success'] == true && response.data['data'] != null) {
|
||||
// API 응답 구조를 DTO에 맞게 변환 (백엔드 실제 응답 구조에 맞춤)
|
||||
final List<dynamic> dataList = response.data['data'];
|
||||
final pagination = response.data['pagination'] ?? {};
|
||||
|
||||
final listData = {
|
||||
'items': dataList,
|
||||
'total': pagination['total'] ?? 0,
|
||||
'page': pagination['page'] ?? 1, // 백엔드는 'page' 사용 ('current_page' 아님)
|
||||
'per_page': pagination['per_page'] ?? 20,
|
||||
'total_pages': pagination['total_pages'] ?? 1,
|
||||
};
|
||||
|
||||
return EquipmentListResponseDto.fromJson(listData);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: response.data['message'] ?? 'Failed to fetch equipment list',
|
||||
);
|
||||
}
|
||||
print('[Equipment API] Response: ${response.data}');
|
||||
|
||||
// 백엔드 응답은 직접 data 배열과 페이지네이션 정보 반환
|
||||
final Map<String, dynamic> responseData = response.data;
|
||||
return EquipmentListResponse.fromJson(responseData);
|
||||
} on DioException catch (e) {
|
||||
throw ServerException(
|
||||
message: e.response?.data['message'] ?? 'Network error occurred',
|
||||
@@ -98,20 +56,15 @@ class EquipmentRemoteDataSourceImpl implements EquipmentRemoteDataSource {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<EquipmentResponse> createEquipment(CreateEquipmentRequest request) async {
|
||||
Future<EquipmentDto> createEquipment(EquipmentRequestDto request) async {
|
||||
try {
|
||||
final response = await _apiClient.post(
|
||||
ApiEndpoints.equipment,
|
||||
data: request.toJson(),
|
||||
);
|
||||
|
||||
if (response.data['success'] == true && response.data['data'] != null) {
|
||||
return EquipmentResponse.fromJson(response.data['data']);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: response.data['message'] ?? 'Failed to create equipment',
|
||||
);
|
||||
}
|
||||
print('[Equipment API] Create Response: ${response.data}');
|
||||
return EquipmentDto.fromJson(response.data);
|
||||
} on DioException catch (e) {
|
||||
throw ServerException(
|
||||
message: e.response?.data['message'] ?? 'Network error occurred',
|
||||
@@ -121,17 +74,12 @@ class EquipmentRemoteDataSourceImpl implements EquipmentRemoteDataSource {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<EquipmentResponse> getEquipmentDetail(int id) async {
|
||||
Future<EquipmentDto> getEquipmentDetail(int id) async {
|
||||
try {
|
||||
final response = await _apiClient.get('${ApiEndpoints.equipment}/$id');
|
||||
|
||||
if (response.data['success'] == true && response.data['data'] != null) {
|
||||
return EquipmentResponse.fromJson(response.data['data']);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: response.data['message'] ?? 'Failed to fetch equipment detail',
|
||||
);
|
||||
}
|
||||
print('[Equipment API] Detail Response: ${response.data}');
|
||||
return EquipmentDto.fromJson(response.data);
|
||||
} on DioException catch (e) {
|
||||
throw ServerException(
|
||||
message: e.response?.data['message'] ?? 'Network error occurred',
|
||||
@@ -141,20 +89,15 @@ class EquipmentRemoteDataSourceImpl implements EquipmentRemoteDataSource {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<EquipmentResponse> updateEquipment(int id, UpdateEquipmentRequest request) async {
|
||||
Future<EquipmentDto> updateEquipment(int id, EquipmentUpdateRequestDto request) async {
|
||||
try {
|
||||
final response = await _apiClient.put(
|
||||
'${ApiEndpoints.equipment}/$id',
|
||||
data: request.toJson(),
|
||||
);
|
||||
|
||||
if (response.data['success'] == true && response.data['data'] != null) {
|
||||
return EquipmentResponse.fromJson(response.data['data']);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: response.data['message'] ?? 'Failed to update equipment',
|
||||
);
|
||||
}
|
||||
print('[Equipment API] Update Response: ${response.data}');
|
||||
return EquipmentDto.fromJson(response.data);
|
||||
} on DioException catch (e) {
|
||||
throw ServerException(
|
||||
message: e.response?.data['message'] ?? 'Network error occurred',
|
||||
@@ -166,192 +109,7 @@ class EquipmentRemoteDataSourceImpl implements EquipmentRemoteDataSource {
|
||||
@override
|
||||
Future<void> deleteEquipment(int id) async {
|
||||
try {
|
||||
final response = await _apiClient.delete('${ApiEndpoints.equipment}/$id');
|
||||
|
||||
if (response.data['success'] != true) {
|
||||
throw ServerException(
|
||||
message: response.data['message'] ?? 'Failed to delete equipment',
|
||||
);
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
throw ServerException(
|
||||
message: e.response?.data['message'] ?? 'Network error occurred',
|
||||
statusCode: e.response?.statusCode,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<EquipmentResponse> changeEquipmentStatus(int id, String status, String? reason) async {
|
||||
try {
|
||||
final response = await _apiClient.patch(
|
||||
'${ApiEndpoints.equipment}/$id/status',
|
||||
data: {
|
||||
'status': status,
|
||||
if (reason != null) 'reason': reason,
|
||||
},
|
||||
);
|
||||
|
||||
if (response.data['success'] == true && response.data['data'] != null) {
|
||||
return EquipmentResponse.fromJson(response.data['data']);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: response.data['message'] ?? 'Failed to change equipment status',
|
||||
);
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
throw ServerException(
|
||||
message: e.response?.data['message'] ?? 'Network error occurred',
|
||||
statusCode: e.response?.statusCode,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<EquipmentHistoryDto> addEquipmentHistory(int equipmentId, CreateHistoryRequest request) async {
|
||||
try {
|
||||
final response = await _apiClient.post(
|
||||
'${ApiEndpoints.equipment}/$equipmentId/history',
|
||||
data: request.toJson(),
|
||||
);
|
||||
|
||||
if (response.data['success'] == true && response.data['data'] != null) {
|
||||
return EquipmentHistoryDto.fromJson(response.data['data']);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: response.data['message'] ?? 'Failed to add equipment history',
|
||||
);
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
throw ServerException(
|
||||
message: e.response?.data['message'] ?? 'Network error occurred',
|
||||
statusCode: e.response?.statusCode,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<EquipmentHistoryDto>> getEquipmentHistory(int equipmentId, {int page = 1, int perPage = 20}) async {
|
||||
try {
|
||||
final queryParams = {
|
||||
'page': page,
|
||||
'per_page': perPage,
|
||||
};
|
||||
|
||||
print('[API] Requesting equipment history: ${ApiEndpoints.equipment}/$equipmentId/history');
|
||||
print('[API] Query params: $queryParams');
|
||||
|
||||
final response = await _apiClient.get(
|
||||
'${ApiEndpoints.equipment}/$equipmentId/history',
|
||||
queryParameters: queryParams,
|
||||
);
|
||||
|
||||
print('[API] Response status: ${response.statusCode}');
|
||||
print('[API] Response data type: ${response.data.runtimeType}');
|
||||
print('[API] Full response: ${response.data}');
|
||||
|
||||
// API 응답 구조 확인
|
||||
if (response.data == null) {
|
||||
print('[API ERROR] Response data is null');
|
||||
throw ServerException(message: 'Empty response from server');
|
||||
}
|
||||
|
||||
// 응답이 Map인지 확인
|
||||
if (response.data is! Map) {
|
||||
print('[API ERROR] Response is not a Map: ${response.data.runtimeType}');
|
||||
throw ServerException(message: 'Invalid response format');
|
||||
}
|
||||
|
||||
// success 필드 확인
|
||||
final success = response.data['success'];
|
||||
print('[API] Success field: $success');
|
||||
|
||||
if (success == true) {
|
||||
final responseData = response.data['data'];
|
||||
print('[API] Data field type: ${responseData?.runtimeType}');
|
||||
|
||||
if (responseData == null) {
|
||||
print('[API] No data field, returning empty list');
|
||||
return [];
|
||||
}
|
||||
|
||||
if (responseData is! List) {
|
||||
print('[API ERROR] Data is not a List: ${responseData.runtimeType}');
|
||||
throw ServerException(message: 'Invalid data format');
|
||||
}
|
||||
|
||||
final List<dynamic> data = responseData;
|
||||
print('[API] History data count: ${data.length}');
|
||||
|
||||
if (data.isEmpty) {
|
||||
print('[API] Empty history data');
|
||||
return [];
|
||||
}
|
||||
|
||||
print('[API] First history item: ${data.first}');
|
||||
|
||||
try {
|
||||
final histories = data.map((json) {
|
||||
print('[API] Parsing history item: $json');
|
||||
return EquipmentHistoryDto.fromJson(json);
|
||||
}).toList();
|
||||
print('[API] Successfully parsed ${histories.length} history items');
|
||||
return histories;
|
||||
} catch (e) {
|
||||
print('[API ERROR] Failed to parse history data: $e');
|
||||
throw ServerException(message: 'Failed to parse history data: $e');
|
||||
}
|
||||
} else {
|
||||
final errorMessage = response.data['message'] ?? response.data['error'] ?? 'Failed to fetch equipment history';
|
||||
print('[API ERROR] Request failed: $errorMessage');
|
||||
throw ServerException(message: errorMessage);
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
throw ServerException(
|
||||
message: e.response?.data['message'] ?? 'Network error occurred',
|
||||
statusCode: e.response?.statusCode,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<EquipmentIoResponse> equipmentIn(EquipmentInRequest request) async {
|
||||
try {
|
||||
final response = await _apiClient.post(
|
||||
'${ApiEndpoints.equipment}/in',
|
||||
data: request.toJson(),
|
||||
);
|
||||
|
||||
if (response.data['success'] == true && response.data['data'] != null) {
|
||||
return EquipmentIoResponse.fromJson(response.data['data']);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: response.data['message'] ?? 'Failed to process equipment in',
|
||||
);
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
throw ServerException(
|
||||
message: e.response?.data['message'] ?? 'Network error occurred',
|
||||
statusCode: e.response?.statusCode,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<EquipmentIoResponse> equipmentOut(EquipmentOutRequest request) async {
|
||||
try {
|
||||
final response = await _apiClient.post(
|
||||
'${ApiEndpoints.equipment}/out',
|
||||
data: request.toJson(),
|
||||
);
|
||||
|
||||
if (response.data['success'] == true && response.data['data'] != null) {
|
||||
return EquipmentIoResponse.fromJson(response.data['data']);
|
||||
} else {
|
||||
throw ServerException(
|
||||
message: response.data['message'] ?? 'Failed to process equipment out',
|
||||
);
|
||||
}
|
||||
await _apiClient.delete('${ApiEndpoints.equipment}/$id');
|
||||
} on DioException catch (e) {
|
||||
throw ServerException(
|
||||
message: e.response?.data['message'] ?? 'Network error occurred',
|
||||
|
||||
@@ -52,6 +52,22 @@ class ResponseInterceptor extends Interceptor {
|
||||
|
||||
/// 직접 데이터 응답인지 확인
|
||||
bool _isDirectDataResponse(Map<String, dynamic> data) {
|
||||
// 페이지네이션 응답은 변형하지 않음 (이미 올바른 구조)
|
||||
// data, total, page 등이 있으면 페이지네이션 응답으로 간주
|
||||
if (data.containsKey('data') &&
|
||||
data.containsKey('total') &&
|
||||
data.containsKey('page')) {
|
||||
return false; // 페이지네이션 응답은 변형 안함
|
||||
}
|
||||
|
||||
// 엔티티 단일 응답 패턴 (vendor, model, equipment 등)
|
||||
// id, name이 있으면서 registered_at 또는 created_at이 있으면 엔티티 응답으로 간주
|
||||
if (data.containsKey('id') &&
|
||||
data.containsKey('name') &&
|
||||
(data.containsKey('registered_at') || data.containsKey('created_at'))) {
|
||||
return false; // 엔티티 응답은 변형 안함
|
||||
}
|
||||
|
||||
// 로그인 응답 패턴
|
||||
if (data.containsKey('accessToken') ||
|
||||
data.containsKey('access_token') ||
|
||||
@@ -65,10 +81,9 @@ class ResponseInterceptor extends Interceptor {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 리스트 응답 패턴
|
||||
// 단순 배열 응답 패턴 (페이지네이션 정보 없이 배열만 반환)
|
||||
if (data.containsKey('items') ||
|
||||
data.containsKey('results') ||
|
||||
data.containsKey('data') && data['data'] is List) {
|
||||
data.containsKey('results')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,298 +0,0 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:injectable/injectable.dart';
|
||||
import 'package:superport/core/constants/api_endpoints.dart';
|
||||
import 'package:superport/core/errors/exceptions.dart';
|
||||
import 'package:superport/data/datasources/remote/api_client.dart';
|
||||
import 'package:superport/data/models/license/license_dto.dart';
|
||||
import 'package:superport/data/models/license/license_request_dto.dart';
|
||||
|
||||
abstract class LicenseRemoteDataSource {
|
||||
Future<LicenseListResponseDto> getLicenses({
|
||||
int page = 1,
|
||||
int perPage = 20,
|
||||
bool? isActive,
|
||||
int? companyId,
|
||||
int? assignedUserId,
|
||||
String? licenseType,
|
||||
});
|
||||
|
||||
Future<LicenseDto> getLicenseById(int id);
|
||||
Future<LicenseDto> createLicense(CreateLicenseRequest request);
|
||||
Future<LicenseDto> updateLicense(int id, UpdateLicenseRequest request);
|
||||
Future<void> deleteLicense(int id);
|
||||
Future<LicenseDto> assignLicense(int id, AssignLicenseRequest request);
|
||||
Future<LicenseDto> unassignLicense(int id);
|
||||
Future<ExpiringLicenseListDto> getExpiringLicenses({
|
||||
int days = 30,
|
||||
int page = 1,
|
||||
int perPage = 20,
|
||||
});
|
||||
}
|
||||
|
||||
@LazySingleton(as: LicenseRemoteDataSource)
|
||||
class LicenseRemoteDataSourceImpl implements LicenseRemoteDataSource {
|
||||
final ApiClient _apiClient;
|
||||
|
||||
LicenseRemoteDataSourceImpl({
|
||||
required ApiClient apiClient,
|
||||
}) : _apiClient = apiClient;
|
||||
|
||||
@override
|
||||
Future<LicenseListResponseDto> getLicenses({
|
||||
int page = 1,
|
||||
int perPage = 20,
|
||||
bool? isActive,
|
||||
int? companyId,
|
||||
int? assignedUserId,
|
||||
String? licenseType,
|
||||
}) async {
|
||||
try {
|
||||
final queryParams = <String, dynamic>{
|
||||
'page': page,
|
||||
'per_page': perPage,
|
||||
};
|
||||
|
||||
if (isActive != null) queryParams['is_active'] = isActive;
|
||||
if (companyId != null) queryParams['company_id'] = companyId;
|
||||
if (assignedUserId != null) queryParams['assigned_user_id'] = assignedUserId;
|
||||
if (licenseType != null) queryParams['license_type'] = licenseType;
|
||||
|
||||
final response = await _apiClient.get(
|
||||
ApiEndpoints.licenses,
|
||||
queryParameters: queryParams,
|
||||
);
|
||||
|
||||
if (response.data != null && response.data['success'] == true && response.data['data'] != null) {
|
||||
// API 응답이 배열인 경우와 객체인 경우를 모두 처리
|
||||
final data = response.data['data'];
|
||||
if (data is List) {
|
||||
// 배열 응답을 LicenseListResponseDto 형식으로 변환
|
||||
final List<LicenseDto> licenses = [];
|
||||
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
try {
|
||||
final item = data[i];
|
||||
debugPrint('📑 Parsing license item $i: ${item['license_key']}');
|
||||
|
||||
// null 검사 및 기본값 설정
|
||||
final licenseDto = LicenseDto.fromJson({
|
||||
...item,
|
||||
// 필수 필드 보장
|
||||
'license_key': item['license_key'] ?? '',
|
||||
'is_active': item['is_active'] ?? true,
|
||||
'created_at': item['created_at'] ?? DateTime.now().toIso8601String(),
|
||||
'updated_at': item['updated_at'] ?? DateTime.now().toIso8601String(),
|
||||
});
|
||||
licenses.add(licenseDto);
|
||||
} catch (e, stackTrace) {
|
||||
debugPrint('❌ Error parsing license item $i: $e');
|
||||
debugPrint('Item data: ${data[i]}');
|
||||
debugPrint('Stack trace: $stackTrace');
|
||||
// 파싱 실패한 항목은 건너뛰고 계속
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
final pagination = response.data['pagination'] ?? {};
|
||||
return LicenseListResponseDto(
|
||||
items: licenses,
|
||||
total: pagination['total'] ?? licenses.length,
|
||||
page: pagination['page'] ?? page,
|
||||
perPage: pagination['per_page'] ?? perPage,
|
||||
totalPages: pagination['total_pages'] ?? 1,
|
||||
);
|
||||
} else if (data['items'] != null) {
|
||||
// 이미 LicenseListResponseDto 형식인 경우
|
||||
return LicenseListResponseDto.fromJson(data);
|
||||
} else {
|
||||
// 예상치 못한 형식인 경우
|
||||
throw ApiException(
|
||||
message: 'Unexpected response format for license list',
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw ApiException(
|
||||
message: response.data?['error']?['message'] ?? 'Failed to fetch licenses',
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
throw _handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<LicenseDto> getLicenseById(int id) async {
|
||||
try {
|
||||
final response = await _apiClient.get(
|
||||
'${ApiEndpoints.licenses}/$id',
|
||||
);
|
||||
|
||||
if (response.data != null && response.data['success'] == true && response.data['data'] != null) {
|
||||
return LicenseDto.fromJson(response.data['data']);
|
||||
} else {
|
||||
throw ApiException(
|
||||
message: response.data?['error']?['message'] ?? 'Failed to fetch license',
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
throw _handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<LicenseDto> createLicense(CreateLicenseRequest request) async {
|
||||
try {
|
||||
final response = await _apiClient.post(
|
||||
ApiEndpoints.licenses,
|
||||
data: request.toJson(),
|
||||
);
|
||||
|
||||
if (response.data != null && response.data['success'] == true && response.data['data'] != null) {
|
||||
return LicenseDto.fromJson(response.data['data']);
|
||||
} else {
|
||||
throw ApiException(
|
||||
message: response.data?['error']?['message'] ?? 'Failed to fetch license',
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
throw _handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<LicenseDto> updateLicense(int id, UpdateLicenseRequest request) async {
|
||||
try {
|
||||
final response = await _apiClient.put(
|
||||
'${ApiEndpoints.licenses}/$id',
|
||||
data: request.toJson(),
|
||||
);
|
||||
|
||||
if (response.data != null && response.data['success'] == true && response.data['data'] != null) {
|
||||
return LicenseDto.fromJson(response.data['data']);
|
||||
} else {
|
||||
throw ApiException(
|
||||
message: response.data?['error']?['message'] ?? 'Failed to fetch license',
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
throw _handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> deleteLicense(int id) async {
|
||||
try {
|
||||
await _apiClient.delete(
|
||||
'${ApiEndpoints.licenses}/$id',
|
||||
);
|
||||
} catch (e) {
|
||||
throw _handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<LicenseDto> assignLicense(int id, AssignLicenseRequest request) async {
|
||||
try {
|
||||
final response = await _apiClient.patch(
|
||||
'${ApiEndpoints.licenses}/$id/assign',
|
||||
data: request.toJson(),
|
||||
);
|
||||
|
||||
if (response.data != null && response.data['success'] == true && response.data['data'] != null) {
|
||||
return LicenseDto.fromJson(response.data['data']);
|
||||
} else {
|
||||
throw ApiException(
|
||||
message: response.data?['error']?['message'] ?? 'Failed to fetch license',
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
throw _handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<LicenseDto> unassignLicense(int id) async {
|
||||
try {
|
||||
final response = await _apiClient.patch(
|
||||
'${ApiEndpoints.licenses}/$id/unassign',
|
||||
);
|
||||
|
||||
if (response.data != null && response.data['success'] == true && response.data['data'] != null) {
|
||||
return LicenseDto.fromJson(response.data['data']);
|
||||
} else {
|
||||
throw ApiException(
|
||||
message: response.data?['error']?['message'] ?? 'Failed to fetch license',
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
throw _handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<ExpiringLicenseListDto> getExpiringLicenses({
|
||||
int days = 30,
|
||||
int page = 1,
|
||||
int perPage = 20,
|
||||
}) async {
|
||||
try {
|
||||
final queryParams = <String, dynamic>{
|
||||
'days': days,
|
||||
'page': page,
|
||||
'per_page': perPage,
|
||||
};
|
||||
|
||||
final response = await _apiClient.get(
|
||||
'${ApiEndpoints.licenses}/expiring',
|
||||
queryParameters: queryParams,
|
||||
);
|
||||
|
||||
if (response.data != null && response.data['success'] == true && response.data['data'] != null) {
|
||||
// API 응답이 배열 형태인 경우 처리
|
||||
final data = response.data['data'];
|
||||
final pagination = response.data['pagination'] ?? {};
|
||||
|
||||
if (data is List) {
|
||||
// 배열 응답을 ExpiringLicenseListDto 형식으로 변환
|
||||
final List<ExpiringLicenseDto> licenses = [];
|
||||
|
||||
for (var item in data) {
|
||||
try {
|
||||
licenses.add(ExpiringLicenseDto.fromJson(item));
|
||||
} catch (e) {
|
||||
debugPrint('❌ Error parsing expiring license: $e');
|
||||
debugPrint('Item data: $item');
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return ExpiringLicenseListDto(
|
||||
items: licenses,
|
||||
total: pagination['total'] ?? licenses.length,
|
||||
page: pagination['page'] ?? page,
|
||||
perPage: pagination['per_page'] ?? perPage,
|
||||
totalPages: pagination['total_pages'] ?? 1,
|
||||
);
|
||||
} else {
|
||||
// 이미 올바른 형식인 경우
|
||||
return ExpiringLicenseListDto.fromJson(data);
|
||||
}
|
||||
} else {
|
||||
throw ApiException(
|
||||
message: response.data?['error']?['message'] ?? 'Failed to fetch expiring licenses',
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
throw _handleError(e);
|
||||
}
|
||||
}
|
||||
|
||||
Exception _handleError(dynamic error) {
|
||||
if (error is ApiException) {
|
||||
return error;
|
||||
}
|
||||
return ApiException(
|
||||
message: error.toString(),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -19,10 +19,10 @@ abstract class UserRemoteDataSource {
|
||||
Future<UserDto> getUser(int id);
|
||||
|
||||
/// 사용자 생성
|
||||
Future<UserDto> createUser(CreateUserRequest request);
|
||||
Future<UserDto> createUser(UserRequestDto request);
|
||||
|
||||
/// 사용자 정보 수정 (비밀번호 포함)
|
||||
Future<UserDto> updateUser(int id, UpdateUserRequest request);
|
||||
Future<UserDto> updateUser(int id, UserUpdateRequestDto request);
|
||||
|
||||
/// 사용자 소프트 삭제 (is_active = false)
|
||||
Future<void> deleteUser(int id);
|
||||
@@ -146,7 +146,7 @@ class UserRemoteDataSourceImpl implements UserRemoteDataSource {
|
||||
|
||||
/// 사용자 생성 (POST /api/v1/users)
|
||||
@override
|
||||
Future<UserDto> createUser(CreateUserRequest request) async {
|
||||
Future<UserDto> createUser(UserRequestDto request) async {
|
||||
try {
|
||||
final response = await _apiClient.post(
|
||||
'/users',
|
||||
@@ -175,7 +175,7 @@ class UserRemoteDataSourceImpl implements UserRemoteDataSource {
|
||||
|
||||
/// 사용자 수정 (PUT /api/v1/users/{id})
|
||||
@override
|
||||
Future<UserDto> updateUser(int id, UpdateUserRequest request) async {
|
||||
Future<UserDto> updateUser(int id, UserUpdateRequestDto request) async {
|
||||
try {
|
||||
// null이나 빈 값 필터링하여 실제로 변경된 필드만 전송
|
||||
final requestData = request.toJson();
|
||||
|
||||
@@ -13,9 +13,9 @@ abstract class WarehouseLocationRemoteDataSource {
|
||||
Map<String, dynamic>? filters,
|
||||
});
|
||||
|
||||
Future<WarehouseLocationDto> getWarehouseLocationDetail(int id);
|
||||
Future<WarehouseLocationDto> createWarehouseLocation(CreateWarehouseLocationRequest request);
|
||||
Future<WarehouseLocationDto> updateWarehouseLocation(int id, UpdateWarehouseLocationRequest request);
|
||||
Future<WarehouseDto> getWarehouseLocationDetail(int id);
|
||||
Future<WarehouseDto> createWarehouseLocation(WarehouseRequestDto request);
|
||||
Future<WarehouseDto> updateWarehouseLocation(int id, WarehouseUpdateRequestDto request);
|
||||
Future<void> deleteWarehouseLocation(int id);
|
||||
Future<WarehouseCapacityInfo> getWarehouseCapacity(int id);
|
||||
Future<WarehouseEquipmentListDto> getWarehouseEquipment({
|
||||
@@ -65,60 +65,46 @@ class WarehouseLocationRemoteDataSourceImpl implements WarehouseLocationRemoteDa
|
||||
}
|
||||
|
||||
final response = await _apiClient.get(
|
||||
ApiEndpoints.warehouseLocations,
|
||||
ApiEndpoints.warehouses,
|
||||
queryParameters: queryParams,
|
||||
);
|
||||
|
||||
if (response.data != null && response.data['success'] == true && response.data['data'] != null) {
|
||||
// API 응답이 배열인 경우와 객체인 경우를 모두 처리
|
||||
if (response.data != null) {
|
||||
// 백엔드는 직접 페이지네이션 구조를 반환
|
||||
final data = response.data['data'];
|
||||
if (data is List) {
|
||||
// 배열 응답을 WarehouseLocationListDto 형식으로 변환
|
||||
final List<WarehouseLocationDto> warehouses = [];
|
||||
if (data != null && data is List) {
|
||||
final List<WarehouseDto> warehouses = [];
|
||||
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
try {
|
||||
final item = data[i];
|
||||
debugPrint('📦 Parsing warehouse location item $i: ${item['name']}');
|
||||
|
||||
// null 검사 및 기본값 설정
|
||||
final warehouseDto = WarehouseLocationDto.fromJson({
|
||||
...item,
|
||||
// 필수 필드 보장
|
||||
'name': item['name'] ?? '',
|
||||
'is_active': item['is_active'] ?? true,
|
||||
'created_at': item['created_at'] ?? DateTime.now().toIso8601String(),
|
||||
});
|
||||
final warehouseDto = WarehouseDto.fromJson(item);
|
||||
warehouses.add(warehouseDto);
|
||||
} catch (e, stackTrace) {
|
||||
debugPrint('❌ Error parsing warehouse location item $i: $e');
|
||||
debugPrint('Item data: ${data[i]}');
|
||||
debugPrint('Stack trace: $stackTrace');
|
||||
// 파싱 실패한 항목은 건너뛰고 계속
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
final pagination = response.data['pagination'] ?? {};
|
||||
return WarehouseLocationListDto(
|
||||
items: warehouses,
|
||||
total: pagination['total'] ?? warehouses.length,
|
||||
page: pagination['page'] ?? page,
|
||||
perPage: pagination['per_page'] ?? perPage,
|
||||
totalPages: pagination['total_pages'] ?? 1,
|
||||
total: response.data['total'] ?? warehouses.length,
|
||||
page: response.data['page'] ?? page,
|
||||
perPage: response.data['page_size'] ?? perPage,
|
||||
totalPages: response.data['total_pages'] ?? 1,
|
||||
);
|
||||
} else if (data['items'] != null) {
|
||||
// 이미 WarehouseLocationListDto 형식인 경우
|
||||
return WarehouseLocationListDto.fromJson(data);
|
||||
} else {
|
||||
// 예상치 못한 형식인 경우
|
||||
throw ApiException(
|
||||
message: 'Unexpected response format for warehouse location list',
|
||||
message: 'Invalid response format: expected data array',
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw ApiException(
|
||||
message: response.data?['error']?['message'] ?? 'Failed to fetch warehouse locations',
|
||||
message: 'Empty response from server',
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -127,17 +113,17 @@ class WarehouseLocationRemoteDataSourceImpl implements WarehouseLocationRemoteDa
|
||||
}
|
||||
|
||||
@override
|
||||
Future<WarehouseLocationDto> getWarehouseLocationDetail(int id) async {
|
||||
Future<WarehouseDto> getWarehouseLocationDetail(int id) async {
|
||||
try {
|
||||
final response = await _apiClient.get(
|
||||
'${ApiEndpoints.warehouseLocations}/$id',
|
||||
'${ApiEndpoints.warehouses}/$id',
|
||||
);
|
||||
|
||||
if (response.data != null && response.data['success'] == true && response.data['data'] != null) {
|
||||
return WarehouseLocationDto.fromJson(response.data['data']);
|
||||
if (response.data != null) {
|
||||
return WarehouseDto.fromJson(response.data);
|
||||
} else {
|
||||
throw ApiException(
|
||||
message: response.data?['error']?['message'] ?? 'Failed to fetch warehouse location',
|
||||
message: 'Failed to fetch warehouse location',
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -146,18 +132,18 @@ class WarehouseLocationRemoteDataSourceImpl implements WarehouseLocationRemoteDa
|
||||
}
|
||||
|
||||
@override
|
||||
Future<WarehouseLocationDto> createWarehouseLocation(CreateWarehouseLocationRequest request) async {
|
||||
Future<WarehouseDto> createWarehouseLocation(WarehouseRequestDto request) async {
|
||||
try {
|
||||
final response = await _apiClient.post(
|
||||
ApiEndpoints.warehouseLocations,
|
||||
ApiEndpoints.warehouses,
|
||||
data: request.toJson(),
|
||||
);
|
||||
|
||||
if (response.data != null && response.data['success'] == true && response.data['data'] != null) {
|
||||
return WarehouseLocationDto.fromJson(response.data['data']);
|
||||
if (response.data != null) {
|
||||
return WarehouseDto.fromJson(response.data);
|
||||
} else {
|
||||
throw ApiException(
|
||||
message: response.data?['error']?['message'] ?? 'Failed to create warehouse location',
|
||||
message: 'Failed to create warehouse location',
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -166,18 +152,18 @@ class WarehouseLocationRemoteDataSourceImpl implements WarehouseLocationRemoteDa
|
||||
}
|
||||
|
||||
@override
|
||||
Future<WarehouseLocationDto> updateWarehouseLocation(int id, UpdateWarehouseLocationRequest request) async {
|
||||
Future<WarehouseDto> updateWarehouseLocation(int id, WarehouseUpdateRequestDto request) async {
|
||||
try {
|
||||
final response = await _apiClient.put(
|
||||
'${ApiEndpoints.warehouseLocations}/$id',
|
||||
'${ApiEndpoints.warehouses}/$id',
|
||||
data: request.toJson(),
|
||||
);
|
||||
|
||||
if (response.data != null && response.data['success'] == true && response.data['data'] != null) {
|
||||
return WarehouseLocationDto.fromJson(response.data['data']);
|
||||
if (response.data != null) {
|
||||
return WarehouseDto.fromJson(response.data);
|
||||
} else {
|
||||
throw ApiException(
|
||||
message: response.data?['error']?['message'] ?? 'Failed to update warehouse location',
|
||||
message: 'Failed to update warehouse location',
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -189,7 +175,7 @@ class WarehouseLocationRemoteDataSourceImpl implements WarehouseLocationRemoteDa
|
||||
Future<void> deleteWarehouseLocation(int id) async {
|
||||
try {
|
||||
await _apiClient.delete(
|
||||
'${ApiEndpoints.warehouseLocations}/$id',
|
||||
'${ApiEndpoints.warehouses}/$id',
|
||||
);
|
||||
} catch (e) {
|
||||
throw _handleError(e);
|
||||
@@ -200,7 +186,7 @@ class WarehouseLocationRemoteDataSourceImpl implements WarehouseLocationRemoteDa
|
||||
Future<WarehouseCapacityInfo> getWarehouseCapacity(int id) async {
|
||||
try {
|
||||
final response = await _apiClient.get(
|
||||
'${ApiEndpoints.warehouseLocations}/$id/capacity',
|
||||
'${ApiEndpoints.warehouses}/$id/capacity',
|
||||
);
|
||||
|
||||
if (response.data != null && response.data['success'] == true && response.data['data'] != null) {
|
||||
@@ -228,7 +214,7 @@ class WarehouseLocationRemoteDataSourceImpl implements WarehouseLocationRemoteDa
|
||||
};
|
||||
|
||||
final response = await _apiClient.get(
|
||||
'${ApiEndpoints.warehouseLocations}/$warehouseId/equipment',
|
||||
'${ApiEndpoints.warehouses}/$warehouseId/equipment',
|
||||
queryParameters: queryParams,
|
||||
);
|
||||
|
||||
@@ -253,9 +239,6 @@ class WarehouseLocationRemoteDataSourceImpl implements WarehouseLocationRemoteDa
|
||||
return WarehouseEquipmentListDto(
|
||||
items: equipment,
|
||||
total: pagination['total'] ?? equipment.length,
|
||||
page: pagination['page'] ?? page,
|
||||
perPage: pagination['per_page'] ?? perPage,
|
||||
totalPages: pagination['total_pages'] ?? 1,
|
||||
);
|
||||
} else {
|
||||
// 이미 올바른 형식인 경우
|
||||
@@ -276,7 +259,7 @@ class WarehouseLocationRemoteDataSourceImpl implements WarehouseLocationRemoteDa
|
||||
Future<void> updateWarehouseLocationStatus(int id, bool isActive) async {
|
||||
try {
|
||||
await _apiClient.patch(
|
||||
'${ApiEndpoints.warehouseLocations}/$id/status',
|
||||
'${ApiEndpoints.warehouses}/$id/status',
|
||||
data: {'is_active': isActive},
|
||||
);
|
||||
} catch (e) {
|
||||
@@ -288,7 +271,7 @@ class WarehouseLocationRemoteDataSourceImpl implements WarehouseLocationRemoteDa
|
||||
Future<bool> checkWarehouseHasEquipment(int id) async {
|
||||
try {
|
||||
final response = await _apiClient.get(
|
||||
'${ApiEndpoints.warehouseLocations}/$id/has-equipment',
|
||||
'${ApiEndpoints.warehouses}/$id/has-equipment',
|
||||
);
|
||||
|
||||
if (response.data != null && response.data['success'] == true) {
|
||||
@@ -306,7 +289,7 @@ class WarehouseLocationRemoteDataSourceImpl implements WarehouseLocationRemoteDa
|
||||
Future<bool> checkDuplicateWarehouseName(String name) async {
|
||||
try {
|
||||
final response = await _apiClient.get(
|
||||
'${ApiEndpoints.warehouseLocations}/check-duplicate',
|
||||
'${ApiEndpoints.warehouses}/check-duplicate',
|
||||
queryParameters: {'name': name},
|
||||
);
|
||||
|
||||
|
||||
@@ -13,9 +13,9 @@ abstract class WarehouseRemoteDataSource {
|
||||
bool includeInactive = false,
|
||||
});
|
||||
|
||||
Future<WarehouseLocationDto> getWarehouseLocationById(int id);
|
||||
Future<WarehouseLocationDto> createWarehouseLocation(CreateWarehouseLocationRequest request);
|
||||
Future<WarehouseLocationDto> updateWarehouseLocation(int id, UpdateWarehouseLocationRequest request);
|
||||
Future<WarehouseDto> getWarehouseLocationById(int id);
|
||||
Future<WarehouseDto> createWarehouseLocation(WarehouseRequestDto request);
|
||||
Future<WarehouseDto> updateWarehouseLocation(int id, WarehouseUpdateRequestDto request);
|
||||
Future<void> deleteWarehouseLocation(int id);
|
||||
Future<WarehouseEquipmentListDto> getWarehouseEquipment(
|
||||
int warehouseId, {
|
||||
@@ -23,7 +23,7 @@ abstract class WarehouseRemoteDataSource {
|
||||
int perPage = 20,
|
||||
});
|
||||
Future<WarehouseCapacityInfo> getWarehouseCapacity(int id);
|
||||
Future<List<WarehouseLocationDto>> getInUseWarehouseLocations();
|
||||
Future<List<WarehouseDto>> getInUseWarehouseLocations();
|
||||
}
|
||||
|
||||
@LazySingleton(as: WarehouseRemoteDataSource)
|
||||
@@ -53,7 +53,7 @@ class WarehouseRemoteDataSourceImpl implements WarehouseRemoteDataSource {
|
||||
queryParams['include_inactive'] = includeInactive;
|
||||
|
||||
final response = await _apiClient.get(
|
||||
ApiEndpoints.warehouseLocations,
|
||||
ApiEndpoints.warehouses,
|
||||
queryParameters: queryParams,
|
||||
);
|
||||
|
||||
@@ -82,14 +82,14 @@ class WarehouseRemoteDataSourceImpl implements WarehouseRemoteDataSource {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<WarehouseLocationDto> getWarehouseLocationById(int id) async {
|
||||
Future<WarehouseDto> getWarehouseLocationById(int id) async {
|
||||
try {
|
||||
final response = await _apiClient.get(
|
||||
'${ApiEndpoints.warehouseLocations}/$id',
|
||||
'${ApiEndpoints.warehouses}/$id',
|
||||
);
|
||||
|
||||
if (response.data != null && response.data['success'] == true && response.data['data'] != null) {
|
||||
return WarehouseLocationDto.fromJson(response.data['data']);
|
||||
return WarehouseDto.fromJson(response.data['data']);
|
||||
} else {
|
||||
throw ApiException(
|
||||
message: response.data?['error']?['message'] ?? 'Failed to fetch warehouse location',
|
||||
@@ -101,15 +101,15 @@ class WarehouseRemoteDataSourceImpl implements WarehouseRemoteDataSource {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<WarehouseLocationDto> createWarehouseLocation(CreateWarehouseLocationRequest request) async {
|
||||
Future<WarehouseDto> createWarehouseLocation(WarehouseRequestDto request) async {
|
||||
try {
|
||||
final response = await _apiClient.post(
|
||||
ApiEndpoints.warehouseLocations,
|
||||
ApiEndpoints.warehouses,
|
||||
data: request.toJson(),
|
||||
);
|
||||
|
||||
if (response.data != null && response.data['success'] == true && response.data['data'] != null) {
|
||||
return WarehouseLocationDto.fromJson(response.data['data']);
|
||||
return WarehouseDto.fromJson(response.data['data']);
|
||||
} else {
|
||||
throw ApiException(
|
||||
message: response.data?['error']?['message'] ?? 'Failed to fetch warehouse location',
|
||||
@@ -121,15 +121,15 @@ class WarehouseRemoteDataSourceImpl implements WarehouseRemoteDataSource {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<WarehouseLocationDto> updateWarehouseLocation(int id, UpdateWarehouseLocationRequest request) async {
|
||||
Future<WarehouseDto> updateWarehouseLocation(int id, WarehouseUpdateRequestDto request) async {
|
||||
try {
|
||||
final response = await _apiClient.put(
|
||||
'${ApiEndpoints.warehouseLocations}/$id',
|
||||
'${ApiEndpoints.warehouses}/$id',
|
||||
data: request.toJson(),
|
||||
);
|
||||
|
||||
if (response.data != null && response.data['success'] == true && response.data['data'] != null) {
|
||||
return WarehouseLocationDto.fromJson(response.data['data']);
|
||||
return WarehouseDto.fromJson(response.data['data']);
|
||||
} else {
|
||||
throw ApiException(
|
||||
message: response.data?['error']?['message'] ?? 'Failed to fetch warehouse location',
|
||||
@@ -144,7 +144,7 @@ class WarehouseRemoteDataSourceImpl implements WarehouseRemoteDataSource {
|
||||
Future<void> deleteWarehouseLocation(int id) async {
|
||||
try {
|
||||
await _apiClient.delete(
|
||||
'${ApiEndpoints.warehouseLocations}/$id',
|
||||
'${ApiEndpoints.warehouses}/$id',
|
||||
);
|
||||
} catch (e) {
|
||||
throw _handleError(e);
|
||||
@@ -200,15 +200,15 @@ class WarehouseRemoteDataSourceImpl implements WarehouseRemoteDataSource {
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<WarehouseLocationDto>> getInUseWarehouseLocations() async {
|
||||
Future<List<WarehouseDto>> getInUseWarehouseLocations() async {
|
||||
try {
|
||||
final response = await _apiClient.get(
|
||||
'${ApiEndpoints.warehouseLocations}/in-use',
|
||||
'${ApiEndpoints.warehouses}/in-use',
|
||||
);
|
||||
|
||||
if (response.data != null && response.data['success'] == true && response.data['data'] is List) {
|
||||
return (response.data['data'] as List)
|
||||
.map((item) => WarehouseLocationDto.fromJson(item))
|
||||
.map((item) => WarehouseDto.fromJson(item))
|
||||
.toList();
|
||||
} else {
|
||||
throw ApiException(message: 'Invalid response format');
|
||||
|
||||
Reference in New Issue
Block a user