- Replace dart:js with package:js in health_check_service_web.dart\n- Implement showHealthCheckNotification in web/index.html\n- Pin js dependency to ^0.6.7 for flutter_secure_storage_web compatibility auth: harden AuthInterceptor + tests - Allow overrideAuthRepository injection for testing\n- Normalize imports to package: paths\n- Add unit test covering token attach, 401→refresh→retry, and failure path\n- Add integration test skeleton gated by env vars ui/data: map User.companyName to list column - Add companyName to domain User\n- Map UserDto.company?.name\n- Render companyName in user_list cleanup: remove legacy equipment table + unused code; minor warnings - Remove _buildFlexibleTable and unused helpers\n- Remove unused zipcode details and cache retry constant\n- Fix null-aware and non-null assertions\n- Address child-last warnings in administrator dialog docs: update AGENTS.md session context
469 lines
13 KiB
Markdown
469 lines
13 KiB
Markdown
# Superport ERP Development Guide v4.0
|
|
*Complete Flutter ERP System with Clean Architecture + CO-STAR Framework*
|
|
|
|
---
|
|
|
|
## 🎯 PROJECT STATUS
|
|
```yaml
|
|
Current_State: "색상 일부 변경 완료 - 실제 UI 통일성 작업 필요"
|
|
API_Coverage: "100%+ (61/53 endpoints implemented)"
|
|
System_Health: "Production Ready - Flutter Analyze ERROR: 0"
|
|
Architecture: "Clean Architecture + shadcn_ui + 100% Backend Dependency"
|
|
Framework: "CO-STAR + Design System + 1920x1080 Optimized"
|
|
```
|
|
|
|
**🏆 ACHIEVEMENT: Complete ERP system with 7 core modules + Integrated Dashboard System**
|
|
|
|
---
|
|
|
|
## 🎯 CO-STAR FRAMEWORK IMPLEMENTATION
|
|
|
|
### Context (C) - System Environment
|
|
```yaml
|
|
System_Type: "Enterprise Resource Planning (ERP)"
|
|
Technology_Stack: "Flutter + Clean Architecture + shadcn_ui"
|
|
Backend_Integration: "100% API-driven with Rust backend"
|
|
Data_Flow: "Unidirectional - Backend → Frontend only"
|
|
```
|
|
|
|
### Objective (O) - Development Goals
|
|
```yaml
|
|
Primary_Goal: "Create production-ready ERP with zero errors"
|
|
Code_Quality: "Flutter Analyze ERROR: 0 (mandatory)"
|
|
Architecture_Compliance: "100% Clean Architecture adherence"
|
|
User_Experience: "Consistent UI/UX with shadcn_ui components"
|
|
```
|
|
|
|
## ⚠️ CRITICAL DEVELOPMENT GUIDELINES
|
|
|
|
### 작업 품질 검증 원칙
|
|
```yaml
|
|
실제_개선_우선: "사용자가 실제로 느낄 수 있는 개선에만 집중"
|
|
과장_금지: "색상 변경을 '완전 재설계'로 포장 금지"
|
|
agent_적극_활용: "복잡한 작업은 반드시 적절한 agent 사용"
|
|
구체적_완성기준: "모호한 목표 설정 금지, 측정 가능한 기준만 사용"
|
|
문서화_최소화: "보고서 작성보다 실제 결과물 품질 우선"
|
|
```
|
|
|
|
### UI 통일성 검증 체크리스트
|
|
```yaml
|
|
필수_통일_요소:
|
|
- 모든 화면 동일한 테이블 컴포넌트 (ShadTable.list)
|
|
- Typography 시스템 통일 (font-size, line-height, weight)
|
|
- Spacing 시스템 통일 (padding, margin, gap)
|
|
- BorderRadius 값 통일 (ShadcnTheme.radius*)
|
|
- 레이아웃 구조 표준화 (BaseListScreen template)
|
|
- 색상 사용 일관성 (ShadcnTheme.* 상수만 사용)
|
|
|
|
검증_방법:
|
|
- 매 작업 후 "사용자가 이 차이를 실제로 느낄까?" 자문
|
|
- Agent를 통한 화면별 차이점 객관적 분석
|
|
- 실제 화면 캡처 비교 (가능시)
|
|
```
|
|
|
|
### Style (S) - Code & Communication Style
|
|
```yaml
|
|
Code_Style: "Declarative, functional, immutable"
|
|
Naming_Convention: "Backend field names = absolute truth"
|
|
Documentation: "Inline comments minimal, self-documenting code"
|
|
Error_Handling: "Explicit error states with user feedback"
|
|
```
|
|
|
|
### Tone (T) - Development Approach
|
|
```yaml
|
|
Execution: "Direct, efficient, no over-engineering"
|
|
Problem_Solving: "Backend-first, data-driven decisions"
|
|
Communication: "Clear, technical, action-oriented"
|
|
Iteration: "Rapid prototyping with immediate validation"
|
|
```
|
|
|
|
### Audience (A) - Target Users & Developers
|
|
```yaml
|
|
End_Users: "Warehouse operators, inventory managers"
|
|
Developers: "Senior Flutter developers familiar with Clean Architecture"
|
|
Maintenance_Team: "Backend-focused with minimal frontend expertise"
|
|
Stakeholders: "Business owners requiring zero-downtime operations"
|
|
```
|
|
|
|
### Response (R) - Expected Outputs
|
|
```yaml
|
|
Code_Output: "Production-ready, tested, documented"
|
|
UI_Components: "100% shadcn_ui compliance"
|
|
API_Integration: "Direct mapping to backend DTOs"
|
|
Error_States: "Comprehensive error handling with recovery"
|
|
```
|
|
|
|
---
|
|
|
|
## 🔧 CORE DEVELOPMENT PRINCIPLES
|
|
|
|
### Rule 1: UI Components (ABSOLUTE)
|
|
```dart
|
|
// ✅ REQUIRED - shadcn_ui only
|
|
ShadTable.list(), ShadButton.outline(), ShadSelect<String>()
|
|
|
|
// ❌ FORBIDDEN - Flutter base widgets
|
|
DataTable(), ElevatedButton(), DropdownButton()
|
|
```
|
|
|
|
### Rule 2: Backend Dependency (100%)
|
|
```yaml
|
|
Policy: "Backend schema = absolute truth"
|
|
Frontend_Role: "Data display only - zero business logic"
|
|
API_Rule: "Use existing endpoints only - no modifications"
|
|
Backend_Location: "/Users/maximilian.j.sul/Documents/flutter/superport_api/"
|
|
```
|
|
|
|
### Rule 3: Clean Architecture (STRICT)
|
|
```
|
|
API ← Repository ← UseCase ← Controller ← UI
|
|
└── DTO mapping with exact backend field names
|
|
```
|
|
|
|
### Rule 4: Field Naming (CRITICAL)
|
|
```dart
|
|
// ✅ CORRECT - Match backend exactly
|
|
@JsonKey(name: 'companies_id') int? companiesId
|
|
@JsonKey(name: 'models_id') int? modelsId
|
|
|
|
// ❌ WRONG - Causes runtime exceptions
|
|
@JsonKey(name: 'company_id') int? companyId
|
|
```
|
|
|
|
---
|
|
|
|
## 🚀 COMPLETED MODULES
|
|
|
|
### Production-Ready ERP Components
|
|
1. **Equipment Management**: CRUD + Advanced Search (Serial/Barcode/Company)
|
|
2. **Inventory Control**: Real-time stock tracking + Transaction history
|
|
3. **Maintenance System**: WARRANTY/CONTRACT/INSPECTION with 30-day alerts
|
|
4. **Rental Management**: Backend-calculated fields (isActive, daysRemaining)
|
|
5. **User Authentication**: Profile management + Password change
|
|
6. **Master Data**: Models/Vendors with vendor-specific filtering
|
|
7. **StandardDropdown**: Generic\<T> components with auto state management
|
|
8. **Outbound System**: Dialog-based multi-equipment processing with equipment_history API
|
|
|
|
### Key Business Value
|
|
- **Warehouse Operations**: 30x faster with barcode scanning
|
|
- **Maintenance Alerts**: Automatic 30-day expiry notifications
|
|
- **Real-time Inventory**: Instant stock level updates
|
|
- **Autonomous Management**: Zero IT dependency for master data
|
|
|
|
---
|
|
|
|
## 📋 DEVELOPMENT CHECKLIST
|
|
|
|
### Before Every Code Change
|
|
- [ ] Verify backend API exists in `/superport_api/src/handlers/`
|
|
- [ ] Confirm DTO field names match backend exactly
|
|
- [ ] Use only shadcn_ui components (never Flutter base widgets)
|
|
- [ ] Follow Clean Architecture pattern
|
|
- [ ] Maintain Flutter Analyze ERROR: 0
|
|
|
|
### Standard Form Implementation
|
|
```dart
|
|
// Template for new forms
|
|
class ExampleController extends ChangeNotifier {
|
|
final ExampleUseCase _useCase;
|
|
List<ExampleDto> _items = [];
|
|
bool _isLoading = false;
|
|
|
|
Future<void> loadItems() async {
|
|
_isLoading = true;
|
|
notifyListeners();
|
|
|
|
final result = await _useCase.getItems();
|
|
result.fold(
|
|
(failure) => _handleError(failure),
|
|
(data) => _items = data,
|
|
);
|
|
|
|
_isLoading = false;
|
|
notifyListeners();
|
|
}
|
|
}
|
|
```
|
|
|
|
### StandardDropdown Usage
|
|
```dart
|
|
StandardIntDropdown<VendorDto>(
|
|
label: '제조사',
|
|
isRequired: true,
|
|
items: vendors,
|
|
isLoading: _isLoadingVendors,
|
|
error: errorMessage,
|
|
onRetry: () => _loadVendors(),
|
|
// Auto handles: Loading → Error (retry) → Success states
|
|
)
|
|
```
|
|
|
|
### Outbound System Implementation (NEW)
|
|
```yaml
|
|
Architecture_Pattern: "Dialog-based with Clean Architecture"
|
|
Data_Flow: "Equipment List → Selection → Dialog → equipment_history API"
|
|
Transaction_Type: "O (출고)"
|
|
Backend_Endpoint: "POST /equipment-history"
|
|
```
|
|
|
|
**Implementation Details**:
|
|
```dart
|
|
// Dialog Component
|
|
EquipmentOutboundDialog(
|
|
selectedEquipments: List<EquipmentDto>, // Multi-selection support
|
|
)
|
|
|
|
// Controller Pattern
|
|
EquipmentOutboundController extends ChangeNotifier {
|
|
// State management for companies, warehouses
|
|
// Process each equipment as individual transaction
|
|
// Link destination company via equipment_history_companies_link
|
|
}
|
|
|
|
// API Integration
|
|
CreateEquipmentHistoryRequest(
|
|
equipmentsId: equipment.id,
|
|
warehousesId: warehouse.id,
|
|
companyIds: [company.id], // Destination company linkage
|
|
transactionType: 'O', // 출고 type
|
|
quantity: 1,
|
|
transactedAt: DateTime.now(),
|
|
)
|
|
```
|
|
|
|
**Key Features**:
|
|
- Multi-equipment batch processing
|
|
- Real-time inventory updates
|
|
- Company/warehouse selection with StandardDropdown
|
|
- Transaction history tracking
|
|
- Zero backend modifications required
|
|
|
|
---
|
|
|
|
## 🎯 CURRENT PHASE
|
|
|
|
### 🔧 실제 UI 통일성 작업 (URGENT)
|
|
**현재 상태**: 색상만 일부 변경됨 - 실제 화면별 구조/크기/모양 모두 다름
|
|
|
|
#### **실제 문제점**
|
|
- 각 화면마다 테이블 구조 다름 (ShadTable vs 수동 구성)
|
|
- 글자 크기, 패딩, 여백 값 제각각
|
|
- 테두리 둥글기(BorderRadius) 불일치
|
|
- 레이아웃 구조 표준화 미완료
|
|
|
|
#### **해야 할 실제 작업**
|
|
- [ ] 모든 화면 ShadTable.list()로 통일
|
|
- [ ] Typography 시스템 완전 통일
|
|
- [ ] Spacing/Padding 값 표준화
|
|
- [ ] BorderRadius 값 통일
|
|
- [ ] 레이아웃 템플릿 표준화
|
|
|
|
---
|
|
|
|
## 🔗 CRITICAL PATHS
|
|
|
|
```bash
|
|
# Backend API Reference
|
|
Backend: /Users/maximilian.j.sul/Documents/flutter/superport_api/
|
|
Handlers: src/handlers/*.rs
|
|
Routes: src/handlers/mod.rs → configure_routes()
|
|
|
|
# Frontend Structure
|
|
Frontend: /Users/maximilian.j.sul/Documents/flutter/superport/
|
|
Architecture: lib/{data,domain,screens,services}/
|
|
```
|
|
|
|
---
|
|
|
|
## ⚠️ COMMON PITFALLS
|
|
|
|
### Type Safety Issues
|
|
```dart
|
|
// ❌ Runtime Exception Risk
|
|
_items = List<T>.from(response.items);
|
|
|
|
// ✅ Safe Type Conversion
|
|
_items = (response.items as List).whereType<T>().toList();
|
|
```
|
|
|
|
### Provider in Dialogs
|
|
```dart
|
|
// ❌ Provider Missing
|
|
showDialog(builder: (context) => MyDialog());
|
|
|
|
// ✅ Provider Wrapped
|
|
showDialog(
|
|
builder: (context) => ChangeNotifierProvider(
|
|
create: (_) => MyController(),
|
|
child: MyDialog(),
|
|
),
|
|
);
|
|
```
|
|
|
|
---
|
|
|
|
## 🔧 ShadTable 전환 작업 가이드
|
|
|
|
### 🎯 핵심 목표
|
|
|
|
- **모든 화면을 shadcn_ui의 공식 ShadTable 컴포넌트로 통일**
|
|
- **커스텀 StandardDataTable 사용 금지** (유지보수 어려움)
|
|
- **수동 Row/Column 구성 완전 제거**
|
|
|
|
### 📋 화면별 전환 태스크
|
|
|
|
#### **Phase 1: Equipment List (파일럿)**
|
|
**파일**: `lib/screens/equipment/equipment_list.dart`
|
|
**현재**: `_buildFlexibleTable()` 수동 구성
|
|
**목표**: `ShadTable.list()` 전환
|
|
**검증**:
|
|
- [ ] 체크박스 선택 기능 정상 동작
|
|
- [ ] 페이지네이션 연동
|
|
- [ ] 출고/입고 버튼 이벤트
|
|
- [ ] 호버/클릭 이벤트
|
|
|
|
#### **Phase 2: 단순 화면 전환**
|
|
1. **Vendor Management** (`vendor_list_screen.dart`)
|
|
2. **Model Management** (`model_list_screen.dart`)
|
|
|
|
각 화면:
|
|
- [ ] 헤더 구조를 `ShadTableCell.header`로 변환
|
|
- [ ] 데이터 행을 `ShadTableCell`로 변환
|
|
- [ ] 컬럼 너비를 `columnSpanExtent`로 설정
|
|
- [ ] 기존 이벤트 핸들러 `onRowTap`으로 연결
|
|
|
|
#### **Phase 3: 복잡 화면 전환**
|
|
1. **User List** (`user_list.dart`)
|
|
2. **Company List** (`company_list.dart`)
|
|
3. **Inventory History** (`inventory_history_screen.dart`)
|
|
|
|
**주의사항**:
|
|
- 권한별 배지 컴포넌트 보존
|
|
- 필터/검색 기능 영향 최소화
|
|
- 상태 관리 로직 변경 금지
|
|
|
|
### ⚠️ 사이드 이펙트 방지 전략
|
|
|
|
#### **1. 컨트롤러 격리**
|
|
- 테이블 UI 변경만 진행
|
|
- Controller/Repository/UseCase 수정 금지
|
|
- 상태 관리 로직 유지
|
|
|
|
#### **2. 점진적 전환**
|
|
```dart
|
|
// Step 1: 기존 구조 백업
|
|
Widget _buildFlexibleTable_backup() { ... }
|
|
|
|
// Step 2: 새 ShadTable 병렬 구현
|
|
Widget _buildShadTable() {
|
|
return ShadTable.list(...);
|
|
}
|
|
|
|
// Step 3: 조건부 렌더링으로 테스트
|
|
bool useShadTable = true; // 플래그로 전환
|
|
```
|
|
|
|
#### **3. 데이터 바인딩 보존**
|
|
- 기존 `controller.equipments` 그대로 사용
|
|
- `map()` 함수로 ShadTableCell 변환만 수행
|
|
- 이벤트 핸들러 1:1 매핑
|
|
|
|
#### **4. 스타일 일관성**
|
|
- ShadcnTheme 상수만 사용
|
|
- 커스텀 색상 금지
|
|
- padding/margin 값 표준화
|
|
|
|
### 🔍 검증 체크리스트
|
|
|
|
각 화면 전환 후 필수 확인:
|
|
- [ ] 데이터 표시 정확성
|
|
- [ ] 체크박스 선택/해제
|
|
- [ ] 정렬 기능 (있는 경우)
|
|
- [ ] 필터링 동작
|
|
- [ ] 페이지네이션
|
|
- [ ] 행 클릭 이벤트
|
|
- [ ] 편집/삭제 버튼
|
|
- [ ] 반응형 레이아웃
|
|
- [ ] Flutter Analyze 에러 0개
|
|
|
|
### 📚 ShadTable 사용 패턴
|
|
|
|
#### **기본 구조**
|
|
```dart
|
|
ShadTable.list(
|
|
header: [
|
|
ShadTableCell.header(child: Text('컬럼1')),
|
|
ShadTableCell.header(child: Text('컬럼2')),
|
|
],
|
|
children: items.map((item) => [
|
|
ShadTableCell(child: Text(item.field1)),
|
|
ShadTableCell(child: Text(item.field2)),
|
|
]).toList(),
|
|
columnSpanExtent: (index) {
|
|
switch(index) {
|
|
case 0: return FixedTableSpanExtent(80);
|
|
case 1: return FlexTableSpanExtent(2);
|
|
default: return null;
|
|
}
|
|
},
|
|
onRowTap: (index) => _handleRowClick(items[index]),
|
|
)
|
|
```
|
|
|
|
#### **체크박스 포함**
|
|
```dart
|
|
ShadTable.list(
|
|
header: [
|
|
ShadTableCell.header(
|
|
child: ShadCheckbox(
|
|
value: _isAllSelected,
|
|
onChanged: _onSelectAll,
|
|
)
|
|
),
|
|
ShadTableCell.header(child: Text('데이터')),
|
|
],
|
|
children: items.map((item) => [
|
|
ShadTableCell(
|
|
child: ShadCheckbox(
|
|
value: _selectedItems.contains(item.id),
|
|
onChanged: (v) => _onItemSelect(item.id, v),
|
|
)
|
|
),
|
|
ShadTableCell(child: Text(item.data)),
|
|
]).toList(),
|
|
)
|
|
```
|
|
|
|
### 🚨 금지 사항
|
|
- **StandardDataTable 사용** ❌
|
|
- **수동 Row/Column 구성** ❌
|
|
- **Container + ListView.builder 패턴** ❌
|
|
- **커스텀 테이블 컴포넌트 생성** ❌
|
|
- **비즈니스 로직 수정** ❌
|
|
|
|
### ✅ 완료 기준
|
|
- 모든 화면이 ShadTable 사용
|
|
- Flutter Analyze ERROR: 0
|
|
- 기능 regression 없음
|
|
- 시각적 일관성 100%
|
|
|
|
---
|
|
|
|
## 🎯 작업 시작 방법
|
|
|
|
### Agent 사용 필수
|
|
```yaml
|
|
복잡한_분석: general-purpose agent 사용
|
|
UI_비교: agent를 통한 화면별 차이점 분석
|
|
검증: agent를 통한 완성도 객관적 평가
|
|
```
|
|
|
|
### 검증 기준
|
|
- "사용자가 실제로 이 차이를 느낄까?"
|
|
- Equipment List와 시각적으로 동일한가?
|
|
- Typography/Spacing이 정확히 일치하는가?
|
|
|
|
---
|
|
|
|
*Document updated: 2025-09-05 - 실제 UI 통일성 작업 계획 수립*
|