백엔드 계약 문서 동기화하고 DTO 파서 정합성 확장

This commit is contained in:
JiWoong Sul
2025-10-17 00:52:30 +09:00
parent efed3c1a6f
commit 7522f46693
10 changed files with 660 additions and 194 deletions

View File

@@ -52,10 +52,10 @@ class StockTransactionDto {
id: json['id'] as int?,
transactionNo: json['transaction_no'] as String? ?? '',
transactionDate: _parseDate(json['transaction_date']) ?? DateTime.now(),
type: _parseType(typeJson),
status: _parseStatus(statusJson),
warehouse: _parseWarehouse(warehouseJson),
createdBy: _parseEmployee(createdByJson),
type: _parseType(typeJson, json),
status: _parseStatus(statusJson, json),
warehouse: _parseWarehouse(warehouseJson, json),
createdBy: _parseEmployee(createdByJson, json),
note: json['note'] as String?,
isActive: (json['is_active'] as bool?) ?? true,
createdAt: _parseDateTime(json['created_at']),
@@ -117,36 +117,86 @@ class StockTransactionDto {
}
}
StockTransactionType _parseType(Map<String, dynamic>? json) {
return StockTransactionType(
id: json?['id'] as int? ?? 0,
name: json?['type_name'] as String? ?? '',
);
StockTransactionType _parseType(
Map<String, dynamic>? json,
Map<String, dynamic> fallback,
) {
final map = json ?? const <String, dynamic>{};
final id = map['id'] as int? ?? fallback['transaction_type_id'] as int? ?? 0;
final name =
map['name'] as String? ??
map['type_name'] as String? ??
fallback['transaction_type_name'] as String? ??
fallback['transaction_type'] as String? ??
'';
return StockTransactionType(id: id, name: name);
}
StockTransactionStatus _parseStatus(Map<String, dynamic>? json) {
return StockTransactionStatus(
id: json?['id'] as int? ?? 0,
name: json?['status_name'] as String? ?? '',
);
StockTransactionStatus _parseStatus(
Map<String, dynamic>? json,
Map<String, dynamic> fallback,
) {
final map = json ?? const <String, dynamic>{};
final id =
map['id'] as int? ?? fallback['transaction_status_id'] as int? ?? 0;
final name =
map['name'] as String? ??
map['status_name'] as String? ??
fallback['transaction_status_name'] as String? ??
fallback['transaction_status'] as String? ??
'';
return StockTransactionStatus(id: id, name: name);
}
StockTransactionWarehouse _parseWarehouse(Map<String, dynamic>? json) {
final zipcode = json?['zipcode'] as Map<String, dynamic>?;
StockTransactionWarehouse _parseWarehouse(
Map<String, dynamic>? json,
Map<String, dynamic> fallback,
) {
final map = json ?? const <String, dynamic>{};
final zipcodeMap = _mapOrEmpty(map['zipcode']);
final fallbackZipcode = _mapOrEmpty(fallback['zipcode']);
final mergedZipcode = zipcodeMap.isNotEmpty ? zipcodeMap : fallbackZipcode;
return StockTransactionWarehouse(
id: json?['id'] as int? ?? 0,
code: json?['warehouse_code'] as String? ?? '',
name: json?['warehouse_name'] as String? ?? '',
zipcode: zipcode?['zipcode'] as String?,
addressLine: zipcode?['road_name'] as String?,
id: map['id'] as int? ?? fallback['warehouse_id'] as int? ?? 0,
code:
map['warehouse_code'] as String? ??
fallback['warehouse_code'] as String? ??
fallback['warehouseCode'] as String? ??
'',
name:
map['warehouse_name'] as String? ??
fallback['warehouse_name'] as String? ??
fallback['warehouseName'] as String? ??
'',
zipcode:
mergedZipcode['zipcode'] as String? ?? fallback['zipcode'] as String?,
addressLine:
mergedZipcode['road_name'] as String? ??
mergedZipcode['roadName'] as String? ??
fallback['address_line'] as String? ??
fallback['addressLine'] as String?,
);
}
StockTransactionEmployee _parseEmployee(Map<String, dynamic>? json) {
StockTransactionEmployee _parseEmployee(
Map<String, dynamic>? json,
Map<String, dynamic> fallback,
) {
final map = json ?? const <String, dynamic>{};
return StockTransactionEmployee(
id: json?['id'] as int? ?? 0,
employeeNo: json?['employee_no'] as String? ?? '',
name: json?['employee_name'] as String? ?? '',
id:
map['id'] as int? ??
fallback['created_by_id'] as int? ??
fallback['created_by'] as int? ??
0,
employeeNo:
map['employee_no'] as String? ??
fallback['created_by_employee_no'] as String? ??
'',
name:
map['employee_name'] as String? ??
fallback['created_by_name'] as String? ??
'',
);
}
@@ -157,83 +207,184 @@ List<StockTransactionLine> _parseLines(Map<String, dynamic> json) {
StockTransactionLine(
id: item['id'] as int?,
lineNo: JsonUtils.readInt(item, 'line_no', fallback: 1),
product: _parseProduct(item['product'] as Map<String, dynamic>?),
quantity: JsonUtils.readInt(item, 'quantity', fallback: 0),
product: _parseProduct(item['product'] as Map<String, dynamic>?, item),
quantity: _readQuantity(item['quantity']),
unitPrice: _readDouble(item['unit_price']),
note: item['note'] as String?,
),
];
}
StockTransactionProduct _parseProduct(Map<String, dynamic>? json) {
final vendorJson = json?['vendor'] as Map<String, dynamic>?;
final uomJson = json?['uom'] as Map<String, dynamic>?;
StockTransactionProduct _parseProduct(
Map<String, dynamic>? json,
Map<String, dynamic> fallback,
) {
final map = json ?? const <String, dynamic>{};
return StockTransactionProduct(
id: json?['id'] as int? ?? 0,
code: json?['product_code'] as String? ?? json?['code'] as String? ?? '',
name: json?['product_name'] as String? ?? json?['name'] as String? ?? '',
vendor: vendorJson == null
? null
: StockTransactionVendorSummary(
id: vendorJson['id'] as int? ?? 0,
name:
vendorJson['vendor_name'] as String? ??
vendorJson['name'] as String? ??
'',
),
uom: uomJson == null
? null
: StockTransactionUomSummary(
id: uomJson['id'] as int? ?? 0,
name:
uomJson['uom_name'] as String? ??
uomJson['name'] as String? ??
'',
),
id:
map['id'] as int? ??
map['product_id'] as int? ??
fallback['product_id'] as int? ??
0,
code:
map['product_code'] as String? ??
map['code'] as String? ??
fallback['product_code'] as String? ??
fallback['code'] as String? ??
'',
name:
map['product_name'] as String? ??
map['name'] as String? ??
fallback['product_name'] as String? ??
fallback['name'] as String? ??
'',
vendor: _parseVendor(map['vendor'], fallback),
uom: _parseUom(map['uom'], fallback),
);
}
StockTransactionVendorSummary? _parseVendor(
dynamic source,
Map<String, dynamic> fallback,
) {
final map = _mapOrEmpty(source);
final name =
map['vendor_name'] as String? ??
map['name'] as String? ??
fallback['vendor_name'] as String? ??
fallback['vendorName'] as String? ??
fallback['manufacturer'] as String?;
if (name == null || name.trim().isEmpty) {
return null;
}
final id =
map['id'] as int? ??
map['vendor_id'] as int? ??
fallback['vendor_id'] as int? ??
0;
return StockTransactionVendorSummary(id: id, name: name);
}
StockTransactionUomSummary? _parseUom(
dynamic source,
Map<String, dynamic> fallback,
) {
final map = _mapOrEmpty(source);
final name =
map['uom_name'] as String? ??
map['name'] as String? ??
fallback['uom_name'] as String? ??
fallback['uomName'] as String? ??
fallback['unit'] as String?;
if (name == null || name.trim().isEmpty) {
return null;
}
final id =
map['id'] as int? ??
map['uom_id'] as int? ??
fallback['uom_id'] as int? ??
0;
return StockTransactionUomSummary(id: id, name: name);
}
List<StockTransactionCustomer> _parseCustomers(Map<String, dynamic> json) {
final raw = JsonUtils.extractList(json, keys: const ['customers']);
return [
for (final item in raw)
StockTransactionCustomer(
id: item['id'] as int?,
customer: _parseCustomer(item['customer'] as Map<String, dynamic>?),
customer: _parseCustomer(
item['customer'] as Map<String, dynamic>?,
item,
),
note: item['note'] as String?,
),
];
}
StockTransactionCustomerSummary _parseCustomer(Map<String, dynamic>? json) {
StockTransactionCustomerSummary _parseCustomer(
Map<String, dynamic>? json,
Map<String, dynamic> fallback,
) {
final map = json ?? const <String, dynamic>{};
return StockTransactionCustomerSummary(
id: json?['id'] as int? ?? 0,
code: json?['customer_code'] as String? ?? json?['code'] as String? ?? '',
name: json?['customer_name'] as String? ?? json?['name'] as String? ?? '',
id:
map['id'] as int? ??
map['customer_id'] as int? ??
fallback['customer_id'] as int? ??
0,
code:
map['customer_code'] as String? ??
map['code'] as String? ??
fallback['customer_code'] as String? ??
fallback['code'] as String? ??
'',
name:
map['customer_name'] as String? ??
map['name'] as String? ??
fallback['customer_name'] as String? ??
fallback['name'] as String? ??
'',
);
}
StockTransactionApprovalSummary? _parseApproval(dynamic raw) {
if (raw is! Map<String, dynamic>) {
final map = _mapOrEmpty(raw);
if (map.isEmpty) {
return null;
}
final status = raw['approval_status'] as Map<String, dynamic>?;
final statusMap = _firstNonEmptyMap([map['approval_status'], map['status']]);
return StockTransactionApprovalSummary(
id: raw['id'] as int? ?? 0,
approvalNo: raw['approval_no'] as String? ?? '',
status: status == null
id: map['id'] as int? ?? 0,
approvalNo:
map['approval_no'] as String? ?? map['approvalNo'] as String? ?? '',
status: statusMap.isEmpty
? null
: StockTransactionApprovalStatusSummary(
id: status['id'] as int? ?? 0,
id: statusMap['id'] as int? ?? statusMap['status_id'] as int? ?? 0,
name:
status['status_name'] as String? ??
status['name'] as String? ??
'',
isBlocking: status['is_blocking_next'] as bool?,
statusMap['name'] as String? ??
statusMap['status_name'] as String? ??
'-',
isBlocking:
statusMap['is_blocking_next'] as bool? ??
statusMap['isBlocking'] as bool?,
),
);
}
Map<String, dynamic> _mapOrEmpty(dynamic value) =>
value is Map<String, dynamic> ? value : const <String, dynamic>{};
Map<String, dynamic> _firstNonEmptyMap(List<dynamic> candidates) {
for (final candidate in candidates) {
if (candidate is Map<String, dynamic> && candidate.isNotEmpty) {
return candidate;
}
}
return const <String, dynamic>{};
}
int _readQuantity(Object? value) {
if (value is int) {
return value;
}
if (value is double) {
return value.round();
}
if (value is String) {
final parsedInt = int.tryParse(value);
if (parsedInt != null) {
return parsedInt;
}
final parsedDouble = double.tryParse(value);
if (parsedDouble != null) {
return parsedDouble.round();
}
}
return 0;
}
DateTime? _parseDate(Object? value) {
if (value == null) {
return null;