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/warehouse/warehouse_dto.dart'; abstract class WarehouseRemoteDataSource { Future getWarehouseLocations({ int page = 1, int perPage = 20, bool? isActive, String? search, bool includeInactive = false, }); Future getWarehouseLocationById(int id); Future createWarehouseLocation(CreateWarehouseLocationRequest request); Future updateWarehouseLocation(int id, UpdateWarehouseLocationRequest request); Future deleteWarehouseLocation(int id); Future getWarehouseEquipment( int warehouseId, { int page = 1, int perPage = 20, }); Future getWarehouseCapacity(int id); Future> getInUseWarehouseLocations(); } @LazySingleton(as: WarehouseRemoteDataSource) class WarehouseRemoteDataSourceImpl implements WarehouseRemoteDataSource { final ApiClient _apiClient; WarehouseRemoteDataSourceImpl({ required ApiClient apiClient, }) : _apiClient = apiClient; @override Future getWarehouseLocations({ int page = 1, int perPage = 20, bool? isActive, String? search, bool includeInactive = false, }) async { try { final queryParams = { 'page': page, 'per_page': perPage, }; if (isActive != null) queryParams['is_active'] = isActive; if (search != null && search.isNotEmpty) queryParams['search'] = search; queryParams['include_inactive'] = includeInactive; final response = await _apiClient.get( ApiEndpoints.warehouseLocations, queryParameters: queryParams, ); if (response.data != null && response.data['success'] == true && response.data['data'] != null) { // API 응답 구조를 DTO에 맞게 변환 final List dataList = response.data['data']; final pagination = response.data['pagination'] ?? {}; final listData = { 'items': dataList, 'total': pagination['total'] ?? 0, 'page': pagination['page'] ?? 1, 'per_page': pagination['per_page'] ?? 20, 'total_pages': pagination['total_pages'] ?? 1, }; return WarehouseLocationListDto.fromJson(listData); } else { throw ApiException( message: response.data?['error']?['message'] ?? 'Failed to fetch warehouse locations', ); } } catch (e) { throw _handleError(e); } } @override Future getWarehouseLocationById(int id) async { try { final response = await _apiClient.get( '${ApiEndpoints.warehouseLocations}/$id', ); if (response.data != null && response.data['success'] == true && response.data['data'] != null) { return WarehouseLocationDto.fromJson(response.data['data']); } else { throw ApiException( message: response.data?['error']?['message'] ?? 'Failed to fetch warehouse location', ); } } catch (e) { throw _handleError(e); } } @override Future createWarehouseLocation(CreateWarehouseLocationRequest request) async { try { final response = await _apiClient.post( ApiEndpoints.warehouseLocations, data: request.toJson(), ); if (response.data != null && response.data['success'] == true && response.data['data'] != null) { return WarehouseLocationDto.fromJson(response.data['data']); } else { throw ApiException( message: response.data?['error']?['message'] ?? 'Failed to fetch warehouse location', ); } } catch (e) { throw _handleError(e); } } @override Future updateWarehouseLocation(int id, UpdateWarehouseLocationRequest request) async { try { final response = await _apiClient.put( '${ApiEndpoints.warehouseLocations}/$id', data: request.toJson(), ); if (response.data != null && response.data['success'] == true && response.data['data'] != null) { return WarehouseLocationDto.fromJson(response.data['data']); } else { throw ApiException( message: response.data?['error']?['message'] ?? 'Failed to fetch warehouse location', ); } } catch (e) { throw _handleError(e); } } @override Future deleteWarehouseLocation(int id) async { try { await _apiClient.delete( '${ApiEndpoints.warehouseLocations}/$id', ); } catch (e) { throw _handleError(e); } } @override Future getWarehouseEquipment( int warehouseId, { int page = 1, int perPage = 20, }) async { try { final queryParams = { 'page': page, 'per_page': perPage, }; final response = await _apiClient.get( '${ApiEndpoints.warehouseLocations}/$warehouseId/equipment', queryParameters: queryParams, ); if (response.data != null && response.data['success'] == true && response.data['data'] != null) { return WarehouseEquipmentListDto.fromJson(response.data['data']); } else { throw ApiException( message: response.data?['error']?['message'] ?? 'Failed to fetch warehouse equipment', ); } } catch (e) { throw _handleError(e); } } @override Future getWarehouseCapacity(int id) async { try { final response = await _apiClient.get( '${ApiEndpoints.warehouseLocations}/$id/capacity', ); if (response.data != null && response.data['success'] == true && response.data['data'] != null) { return WarehouseCapacityInfo.fromJson(response.data['data']); } else { throw ApiException( message: response.data?['error']?['message'] ?? 'Failed to fetch warehouse capacity', ); } } catch (e) { throw _handleError(e); } } @override Future> getInUseWarehouseLocations() async { try { final response = await _apiClient.get( '${ApiEndpoints.warehouseLocations}/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)) .toList(); } else { throw ApiException(message: 'Invalid response format'); } } catch (e) { throw _handleError(e); } } Exception _handleError(dynamic error) { if (error is ApiException) { return error; } return ApiException( message: error.toString(), ); } }