API v4 계약 반영하고 보고서·입출고 화면 실연동 강화
This commit is contained in:
@@ -214,7 +214,9 @@ class ApprovalStepDto {
|
||||
(json['approver'] as Map<String, dynamic>? ?? const {}),
|
||||
),
|
||||
status: ApprovalStatusDto.fromJson(
|
||||
(json['status'] as Map<String, dynamic>? ?? const {}),
|
||||
(json['status'] as Map<String, dynamic>? ??
|
||||
json['step_status'] as Map<String, dynamic>? ??
|
||||
const {}),
|
||||
),
|
||||
assignedAt: _parseDate(json['assigned_at']) ?? DateTime.now(),
|
||||
decidedAt: _parseDate(json['decided_at']),
|
||||
@@ -263,7 +265,12 @@ class ApprovalHistoryDto {
|
||||
return ApprovalHistoryDto(
|
||||
id: json['id'] as int?,
|
||||
action: ApprovalActionDto.fromJson(
|
||||
(json['action'] as Map<String, dynamic>? ?? const {}),
|
||||
json['action'] is Map<String, dynamic>
|
||||
? json['action'] as Map<String, dynamic>
|
||||
: {
|
||||
'id': json['approval_action_id'],
|
||||
'name': json['approval_action_name'],
|
||||
},
|
||||
),
|
||||
fromStatus: json['from_status'] is Map<String, dynamic>
|
||||
? ApprovalStatusDto.fromJson(
|
||||
|
||||
@@ -175,22 +175,199 @@ class ApprovalRepositoryRemote implements ApprovalRepository {
|
||||
Map<String, dynamic> body,
|
||||
) {
|
||||
final data = body['data'];
|
||||
if (data is Map<String, dynamic>) {
|
||||
if (data['approval'] is Map<String, dynamic>) {
|
||||
return data['approval'] as Map<String, dynamic>;
|
||||
final dataMap = data is Map<String, dynamic> ? data : null;
|
||||
Map<String, dynamic>? approval = _selectApprovalPayload(dataMap);
|
||||
approval ??= _selectApprovalPayload(body);
|
||||
if (approval == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final merged = Map<String, dynamic>.from(approval);
|
||||
if (dataMap != null) {
|
||||
final steps = _mergeStepsPayload(
|
||||
existing: merged['steps'],
|
||||
data: dataMap,
|
||||
);
|
||||
if (steps != null) {
|
||||
merged['steps'] = steps;
|
||||
}
|
||||
if (data['approval_data'] is Map<String, dynamic>) {
|
||||
return data['approval_data'] as Map<String, dynamic>;
|
||||
}
|
||||
final hasStatus =
|
||||
data.containsKey('status') || data.containsKey('approval_status');
|
||||
if (data.containsKey('approval_no') && hasStatus) {
|
||||
return data;
|
||||
|
||||
final histories = _mergeHistoriesPayload(
|
||||
existing: merged['histories'],
|
||||
data: dataMap,
|
||||
);
|
||||
if (histories != null) {
|
||||
merged['histories'] = histories;
|
||||
}
|
||||
}
|
||||
if (body['approval'] is Map<String, dynamic>) {
|
||||
return body['approval'] as Map<String, dynamic>;
|
||||
return merged;
|
||||
}
|
||||
|
||||
Map<String, dynamic>? _selectApprovalPayload(Map<String, dynamic>? source) {
|
||||
if (source == null) {
|
||||
return null;
|
||||
}
|
||||
if (source['approval'] is Map<String, dynamic>) {
|
||||
return Map<String, dynamic>.from(
|
||||
source['approval'] as Map<String, dynamic>,
|
||||
);
|
||||
}
|
||||
if (source['approval_data'] is Map<String, dynamic>) {
|
||||
return Map<String, dynamic>.from(
|
||||
source['approval_data'] as Map<String, dynamic>,
|
||||
);
|
||||
}
|
||||
final hasStatus =
|
||||
source.containsKey('status') || source.containsKey('approval_status');
|
||||
if (source.containsKey('approval_no') && hasStatus) {
|
||||
return Map<String, dynamic>.from(source);
|
||||
}
|
||||
if (source['approval'] == null && source['data'] is Map<String, dynamic>) {
|
||||
return _selectApprovalPayload(source['data'] as Map<String, dynamic>);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Map<String, dynamic>>? _mergeStepsPayload({
|
||||
required dynamic existing,
|
||||
required Map<String, dynamic> data,
|
||||
}) {
|
||||
final steps = <Map<String, dynamic>>[];
|
||||
|
||||
void upsert(Map<String, dynamic> step) {
|
||||
final id = step['id'] as int?;
|
||||
final order = step['step_order'] as int?;
|
||||
final index = steps.indexWhere((element) {
|
||||
final elementId = element['id'] as int?;
|
||||
if (elementId != null && id != null) {
|
||||
return elementId == id;
|
||||
}
|
||||
if (order != null) {
|
||||
return element['step_order'] == order;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
final copy = Map<String, dynamic>.from(step);
|
||||
if (index >= 0) {
|
||||
steps[index] = copy;
|
||||
} else {
|
||||
steps.add(copy);
|
||||
}
|
||||
}
|
||||
|
||||
if (existing is List) {
|
||||
for (final item in existing) {
|
||||
if (item is Map<String, dynamic>) {
|
||||
upsert(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final responseSteps = data['steps'];
|
||||
if (responseSteps is List) {
|
||||
for (final item in responseSteps) {
|
||||
if (item is Map<String, dynamic>) {
|
||||
upsert(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (data['step'] is Map<String, dynamic>) {
|
||||
upsert(data['step'] as Map<String, dynamic>);
|
||||
}
|
||||
if (data['next_step'] is Map<String, dynamic>) {
|
||||
upsert(data['next_step'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
if (steps.isEmpty) {
|
||||
return existing is List
|
||||
? existing
|
||||
.whereType<Map<String, dynamic>>()
|
||||
.map((step) => Map<String, dynamic>.from(step))
|
||||
.toList()
|
||||
: null;
|
||||
}
|
||||
|
||||
steps.sort((a, b) {
|
||||
final orderA = a['step_order'] as int? ?? 0;
|
||||
final orderB = b['step_order'] as int? ?? 0;
|
||||
return orderA.compareTo(orderB);
|
||||
});
|
||||
return steps;
|
||||
}
|
||||
|
||||
List<Map<String, dynamic>>? _mergeHistoriesPayload({
|
||||
required dynamic existing,
|
||||
required Map<String, dynamic> data,
|
||||
}) {
|
||||
final histories = <Map<String, dynamic>>[];
|
||||
|
||||
void append(Map<String, dynamic> history) {
|
||||
histories.add(Map<String, dynamic>.from(history));
|
||||
}
|
||||
|
||||
if (existing is List) {
|
||||
for (final item in existing) {
|
||||
if (item is Map<String, dynamic>) {
|
||||
append(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final responseHistories = data['histories'];
|
||||
if (responseHistories is List) {
|
||||
for (final item in responseHistories) {
|
||||
if (item is Map<String, dynamic>) {
|
||||
append(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (data['history'] is Map<String, dynamic>) {
|
||||
append(data['history'] as Map<String, dynamic>);
|
||||
}
|
||||
|
||||
if (histories.isEmpty) {
|
||||
return existing is List
|
||||
? existing
|
||||
.whereType<Map<String, dynamic>>()
|
||||
.map((history) => Map<String, dynamic>.from(history))
|
||||
.toList()
|
||||
: null;
|
||||
}
|
||||
|
||||
DateTime? parseTime(Map<String, dynamic> json) {
|
||||
String? read(dynamic value) {
|
||||
if (value is String && value.trim().isNotEmpty) {
|
||||
return value.trim();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
final raw =
|
||||
read(json['action_at']) ??
|
||||
read(json['created_at']) ??
|
||||
read(json['updated_at']);
|
||||
if (raw == null) {
|
||||
return null;
|
||||
}
|
||||
return DateTime.tryParse(raw);
|
||||
}
|
||||
|
||||
histories.sort((a, b) {
|
||||
final timeA = parseTime(a);
|
||||
final timeB = parseTime(b);
|
||||
if (timeA == null && timeB == null) {
|
||||
return 0;
|
||||
}
|
||||
if (timeA == null) {
|
||||
return 1;
|
||||
}
|
||||
if (timeB == null) {
|
||||
return -1;
|
||||
}
|
||||
return timeA.compareTo(timeB);
|
||||
});
|
||||
return histories;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,10 +31,8 @@ class ApprovalHistoryRepositoryRemote implements ApprovalHistoryRepository {
|
||||
query: {
|
||||
'page': page,
|
||||
'page_size': pageSize,
|
||||
if (query != null && query.isNotEmpty) 'q': query,
|
||||
if (action != null && action.isNotEmpty) 'action': action,
|
||||
if (from != null) 'from': from.toIso8601String(),
|
||||
if (to != null) 'to': to.toIso8601String(),
|
||||
if (from != null) 'action_from': from.toIso8601String(),
|
||||
if (to != null) 'action_to': to.toIso8601String(),
|
||||
},
|
||||
options: Options(responseType: ResponseType.json),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user