feat(approvals): Approval Flow v2 프런트엔드 전면 개편
- 환경/라우터 모듈에 approval_flow_v2 토글을 추가하고 FeatureFlags 초기화를 연결 (.env*, lib/core/**) - ApiClient 빌더·ApiRoutes 확장과 ApprovalRepositoryRemote 리팩터링으로 include·액션 시그니처를 정합화 - ApprovalFlow·ApprovalDraft 엔티티/레포/유즈케이스를 도입해 서버 초안과 단계 액션(승인·회수·재상신)을 지원 - Approval 컨트롤러·히스토리·템플릿 페이지와 공유 위젯을 재작성해 감사 로그·회수 UX·템플릿 CRUD를 반영 - Inbound/Outbound/Rental 컨트롤러·페이지에 결재 섹션을 삽입하고 대시보드 pending 카드 요약을 갱신 - SuperportDialog·FormField 등 공통 위젯을 보강하고 승인 위젯 가이드를 추가해 UI 가이드를 정리 - 결재/재고 테스트 픽스처와 단위·위젯·통합 테스트를 확장하고 flutter_test_config로 스테이징 호스트를 허용 - Approval Flow 레포트/플랜 문서를 업데이트하고 ApprovalFlow_System_Integration_and_ChangePlan.md를 추가 - 실행: flutter analyze, flutter test
This commit is contained in:
@@ -150,5 +150,56 @@ void main() {
|
||||
expect(client.unwrap(response), {'status': 'ok'});
|
||||
});
|
||||
});
|
||||
|
||||
group('buildPath', () {
|
||||
test('선행 슬래시를 유지하며 세그먼트를 결합한다', () {
|
||||
final path = ApiClient.buildPath('/api/v1', ['approvals', 1, 'steps']);
|
||||
expect(path, '/api/v1/approvals/1/steps');
|
||||
});
|
||||
|
||||
test('세그먼트의 중복 슬래시를 제거한다', () {
|
||||
final path = ApiClient.buildPath('/api/v1/', ['/approval/', '/submit']);
|
||||
expect(path, '/api/v1/approval/submit');
|
||||
});
|
||||
});
|
||||
|
||||
group('buildQuery', () {
|
||||
test('페이지네이션/검색 파라미터를 정규화한다', () {
|
||||
final now = DateTime.utc(2025, 1, 5, 12, 30);
|
||||
final query = ApiClient.buildQuery(
|
||||
page: 2,
|
||||
pageSize: 50,
|
||||
q: ' 품번 ',
|
||||
sort: ' transaction_date ',
|
||||
order: ' DESC ',
|
||||
include: const ['steps', 'histories', 'steps'],
|
||||
updatedSince: now,
|
||||
filters: {
|
||||
'transaction_id': 10,
|
||||
'status': ' 진행 ',
|
||||
'keyword': ' ',
|
||||
'from': DateTime.utc(2025, 1, 1, 9),
|
||||
'ids': [' 1 ', null, '2'],
|
||||
},
|
||||
);
|
||||
|
||||
expect(query['page'], 2);
|
||||
expect(query['page_size'], 50);
|
||||
expect(query['q'], '품번');
|
||||
expect(query['sort'], 'transaction_date');
|
||||
expect(query['order'], 'desc');
|
||||
expect(query['include'], 'steps,histories');
|
||||
expect(query['updated_since'], now.toUtc().toIso8601String());
|
||||
expect(query['transaction_id'], 10);
|
||||
expect(query['status'], '진행');
|
||||
expect(query.containsKey('keyword'), isFalse);
|
||||
expect(
|
||||
query['from'],
|
||||
DateTime.utc(2025, 1, 1, 9).toUtc().toIso8601String(),
|
||||
);
|
||||
expect(query['ids'], '1,2');
|
||||
expect(() => query['page'] = 1, throwsUnsupportedError);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -92,9 +92,7 @@ void main() {
|
||||
requestOptions: requestOptions,
|
||||
statusCode: 401,
|
||||
data: {
|
||||
'error': {
|
||||
'message': 'invalid credentials',
|
||||
},
|
||||
'error': {'message': 'invalid credentials'},
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user