refactor: 인벤토리 테이블 스펙과 도메인 계층 정비
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
import '../../../../../core/common/utils/json_utils.dart';
|
||||
import '../../domain/entities/lookup_item.dart';
|
||||
|
||||
/// 룩업 API 응답을 표현하는 DTO.
|
||||
class LookupItemDto {
|
||||
LookupItemDto({
|
||||
required this.id,
|
||||
required this.name,
|
||||
this.code,
|
||||
this.isDefault = false,
|
||||
this.isActive = true,
|
||||
this.note,
|
||||
});
|
||||
|
||||
final int id;
|
||||
final String? code;
|
||||
final String name;
|
||||
final bool isDefault;
|
||||
final bool isActive;
|
||||
final String? note;
|
||||
|
||||
factory LookupItemDto.fromJson(Map<String, dynamic> json) {
|
||||
return LookupItemDto(
|
||||
id: json['id'] as int? ?? 0,
|
||||
code: json['code'] as String? ?? json['status_code'] as String?,
|
||||
name:
|
||||
json['name'] as String? ??
|
||||
json['type_name'] as String? ??
|
||||
json['status_name'] as String? ??
|
||||
json['action_name'] as String? ??
|
||||
'',
|
||||
isDefault: (json['is_default'] as bool?) ?? false,
|
||||
isActive: (json['is_active'] as bool?) ?? true,
|
||||
note: json['note'] as String?,
|
||||
);
|
||||
}
|
||||
|
||||
LookupItem toEntity() => LookupItem(
|
||||
id: id,
|
||||
code: code,
|
||||
name: name,
|
||||
isDefault: isDefault,
|
||||
isActive: isActive,
|
||||
note: note,
|
||||
);
|
||||
|
||||
static List<LookupItem> parseList(Map<String, dynamic>? json) {
|
||||
final rawItems = JsonUtils.extractList(json, keys: const ['items']);
|
||||
return rawItems
|
||||
.map(LookupItemDto.fromJson)
|
||||
.map((dto) => dto.toEntity())
|
||||
.toList(growable: false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
import '../../../../../core/network/api_client.dart';
|
||||
import '../../../../../core/network/api_routes.dart';
|
||||
import '../../domain/entities/lookup_item.dart';
|
||||
import '../../domain/repositories/inventory_lookup_repository.dart';
|
||||
import '../dtos/lookup_item_dto.dart';
|
||||
|
||||
/// 인벤토리 공통 룩업 API 호출 구현체.
|
||||
class InventoryLookupRepositoryRemote implements InventoryLookupRepository {
|
||||
InventoryLookupRepositoryRemote({required ApiClient apiClient})
|
||||
: _api = apiClient;
|
||||
|
||||
final ApiClient _api;
|
||||
|
||||
static const _transactionTypesPath = '${ApiRoutes.apiV1}/transaction-types';
|
||||
static const _transactionStatusesPath =
|
||||
'${ApiRoutes.apiV1}/transaction-statuses';
|
||||
static const _approvalStatusesPath = '${ApiRoutes.apiV1}/approval-statuses';
|
||||
static const _approvalActionsPath = '${ApiRoutes.apiV1}/approval-actions';
|
||||
|
||||
@override
|
||||
Future<List<LookupItem>> fetchTransactionTypes({bool activeOnly = true}) {
|
||||
return _fetchList(_transactionTypesPath, activeOnly: activeOnly);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<LookupItem>> fetchTransactionStatuses({bool activeOnly = true}) {
|
||||
return _fetchList(_transactionStatusesPath, activeOnly: activeOnly);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<LookupItem>> fetchApprovalStatuses({bool activeOnly = true}) {
|
||||
return _fetchList(_approvalStatusesPath, activeOnly: activeOnly);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<LookupItem>> fetchApprovalActions({bool activeOnly = true}) {
|
||||
return _fetchList(
|
||||
_approvalActionsPath,
|
||||
activeOnly: activeOnly,
|
||||
// Approval actions는 is_active 필터가 없을 수 있어 조건적으로 전달.
|
||||
includeIsActive: false,
|
||||
);
|
||||
}
|
||||
|
||||
Future<List<LookupItem>> _fetchList(
|
||||
String path, {
|
||||
required bool activeOnly,
|
||||
bool includeIsActive = true,
|
||||
}) async {
|
||||
final response = await _api.get<Map<String, dynamic>>(
|
||||
path,
|
||||
query: {
|
||||
'page': 1,
|
||||
'page_size': 200,
|
||||
if (includeIsActive && activeOnly) 'is_active': true,
|
||||
},
|
||||
options: Options(responseType: ResponseType.json),
|
||||
);
|
||||
return LookupItemDto.parseList(response.data ?? const {});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user