diff --git a/CLAUDE.md b/CLAUDE.md index d199a6d..fb37970 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,376 +1,198 @@ -# Superport ERP System - Project Rules v2.0 +# Superport ERP System -> πŸ’‘ **Note**: Global Claude Code rules from `~/.claude/CLAUDE.md` are automatically applied. This document contains **project-specific** configurations only. +> πŸ’‘ **Note**: Global Claude Code rules are in `~/.claude/CLAUDE.md`. This document contains project-specific context. -## 🎯 Project Identity +## 🎯 Project Overview -**Superport**λŠ” Rust λ°±μ—”λ“œ + Flutter μ›Ή/λͺ¨λ°”일 기반의 **μ—”ν„°ν”„λΌμ΄μ¦ˆ ERP μ‹œμŠ€ν…œ**μž…λ‹ˆλ‹€. +**Superport**λŠ” κΈ°μ—…μš© μž₯λΉ„ 관리 및 μœ μ§€λ³΄μˆ˜λ₯Ό μœ„ν•œ ν΄λΌμš°λ“œ 기반 ERP μ‹œμŠ€ν…œμž…λ‹ˆλ‹€. -### Core Domains -- **Equipment Management**: μž₯λΉ„ μž…κ³ /좜고, μ‹œλ¦¬μ–Ό 번호 좔적, 재고 관리 -- **Company Management**: 고객사 정보, 닀쀑 지점 관리 -- **User Management**: μ—­ν•  기반 μ ‘κ·Ό μ œμ–΄ (S: κ΄€λ¦¬μž, M: 멀버) -- **License Management**: μœ μ§€λ³΄μˆ˜ λΌμ΄μ„ μŠ€, 만료일 좔적 -- **Warehouse Management**: μ°½κ³  μœ„μΉ˜ 체계적 관리 +### Business Purpose +- μž₯λΉ„ μž…μΆœκ³  및 재고 관리 μžλ™ν™” +- μœ μ§€λ³΄μˆ˜ λΌμ΄μ„ μŠ€ 만료일 좔적 +- 고객사별 μž₯λΉ„ 배치 ν˜„ν™© 관리 +- μ‹€μ‹œκ°„ λŒ€μ‹œλ³΄λ“œλ₯Ό ν†΅ν•œ 경영 μΈμ‚¬μ΄νŠΈ 제곡 -## πŸ—οΈ Architecture Rules +### Target Users +- **κ΄€λ¦¬μž (Admin)**: 전체 μ‹œμŠ€ν…œ 관리, μ‚¬μš©μž κΆŒν•œ μ„€μ • +- **λ§€λ‹ˆμ € (Manager)**: μž₯λΉ„ μž…μΆœκ³  승인, λΌμ΄μ„ μŠ€ 관리 +- **일반 μ‚¬μš©μž (Member)**: μž₯λΉ„ 쑰회, κΈ°λ³Έ μž‘μ—… μˆ˜ν–‰ -### Clean Architecture Structure -``` -lib/ -β”œβ”€β”€ core/ # ⚠️ 핡심 μ„€μ • - μ‹ μ€‘νžˆ μˆ˜μ • -β”‚ β”œβ”€β”€ api_client.dart # Dio/Retrofit μ„€μ • -β”‚ β”œβ”€β”€ exceptions.dart # μ „μ—­ μ˜ˆμ™Έ 처리 -β”‚ └── navigation.dart # λΌμš°νŒ… 관리 -β”œβ”€β”€ data/ # 데이터 λ ˆμ΄μ–΄ -β”‚ β”œβ”€β”€ dto/ # API 응닡 λͺ¨λΈ (Freezed) -β”‚ β”œβ”€β”€ repositories/ # 데이터 μ†ŒμŠ€ 좔상화 -β”‚ └── services/ # API μ„œλΉ„μŠ€ (Retrofit) -β”œβ”€β”€ domain/ # λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 -β”‚ β”œβ”€β”€ entities/ # 도메인 λͺ¨λΈ -β”‚ β”œβ”€β”€ repositories/ # Repository μΈν„°νŽ˜μ΄μŠ€ -β”‚ └── usecases/ # λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 -β”œβ”€β”€ services/ # μ• ν”Œλ¦¬μΌ€μ΄μ…˜ μ„œλΉ„μŠ€ -β”‚ β”œβ”€β”€ auth_service.dart # JWT 인증 관리 -β”‚ β”œβ”€β”€ api_service.dart # API 호좜 관리 -β”‚ └── storage_service.dart # 둜컬 μ €μž₯μ†Œ -β”œβ”€β”€ screens/ # Feature-First UI -β”‚ └── [feature]/ -β”‚ β”œβ”€β”€ controllers/ # Provider 기반 μƒνƒœ 관리 -β”‚ β”œβ”€β”€ widgets/ # μž¬μ‚¬μš© μ»΄ν¬λ„ŒνŠΈ -β”‚ └── [feature]_form.dart -└── di/ # GetIt μ˜μ‘΄μ„± μ£Όμž… -``` +## πŸ—οΈ Technical Architecture -### Architecture Constraints +### Tech Stack ```yaml -constraints: - - "ControllerλŠ” λ°˜λ“œμ‹œ ChangeNotifier 상속" - - "λͺ¨λ“  API ν˜ΈμΆœμ€ ApiService 경유" - - "DTOλŠ” Freezed + JsonSerializable ν•„μˆ˜" - - "화면별 Controller 뢄리 원칙" - - "Mockκ³Ό Real μ„œλΉ„μŠ€ μ™„μ „ 뢄리" +Frontend: + platform: Flutter Web (Mobile ready) + state_management: Provider + ChangeNotifier + ui_framework: ShadCN Flutter Port + api_client: Dio + Retrofit + code_generation: Freezed + JsonSerializable + +Backend: + language: Rust + framework: Actix-Web + database: PostgreSQL + auth: JWT (24μ‹œκ°„ 만료) + api_url: https://api-dev.beavercompany.co.kr + source_path: /Users/maximilian.j.sul/Documents/flutter/superport_api + +Infrastructure: + hosting: AWS (μ˜ˆμ •) + storage: S3 (μ˜ˆμ •) + ci_cd: GitHub Actions (μ˜ˆμ •) ``` -## πŸ’» Development Environment +### Project Structure +``` +/Users/maximilian.j.sul/Documents/flutter/ +β”œβ”€β”€ superport/ # Flutter Frontend +β”‚ β”œβ”€β”€ lib/ +β”‚ β”‚ β”œβ”€β”€ core/ # 핡심 μ„€μ • 및 μœ ν‹Έλ¦¬ν‹° +β”‚ β”‚ β”œβ”€β”€ data/ # API 톡신 λ ˆμ΄μ–΄ +β”‚ β”‚ β”‚ β”œβ”€β”€ models/ # Freezed DTO +β”‚ β”‚ β”‚ └── datasources/ # API ν΄λΌμ΄μ–ΈνŠΈ +β”‚ β”‚ β”œβ”€β”€ screens/ # UI ν™”λ©΄ +β”‚ β”‚ β”‚ └── [feature]/ +β”‚ β”‚ β”‚ β”œβ”€β”€ controllers/ # μƒνƒœ 관리 +β”‚ β”‚ β”‚ └── widgets/ # UI μ»΄ν¬λ„ŒνŠΈ +β”‚ β”‚ └── services/ # λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 +β”‚ +└── superport_api/ # Rust Backend + β”œβ”€β”€ src/ + β”‚ β”œβ”€β”€ handlers/ # API μ—”λ“œν¬μΈνŠΈ + β”‚ β”œβ”€β”€ services/ # λΉ„μ¦ˆλ‹ˆμŠ€ 둜직 + β”‚ └── entities/ # DB λͺ¨λΈ + └── migrations/ # DB λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ +``` -### API Endpoints +## βœ… Implementation Status + +### Completed Features (100%) +- βœ… **인증 μ‹œμŠ€ν…œ**: JWT 기반 둜그인/λ‘œκ·Έμ•„μ›ƒ +- βœ… **νšŒμ‚¬ 관리**: CRUD, 지점 관리, μ—°λ½μ²˜ 정보 +- βœ… **μ‚¬μš©μž 관리**: 계정 생성, κΆŒν•œ μ„€μ • (Admin/Manager/Member) +- βœ… **μ°½κ³  μœ„μΉ˜ 관리**: μž…κ³ μ§€ 등둝 및 관리 +- βœ… **μž₯λΉ„ μž…κ³ **: μ‹œλ¦¬μ–Ό 번호 좔적, μˆ˜λŸ‰ 관리 +- βœ… **λΌμ΄μ„ μŠ€ 관리**: μœ μ§€λ³΄μˆ˜ κΈ°κ°„, 만료일 μ•Œλ¦Ό + +### In Progress (70%) +- πŸ”„ **μž₯λΉ„ 좜고**: API 연동 μ™„λ£Œ, UI κ°œμ„  ν•„μš” +- πŸ”„ **λŒ€μ‹œλ³΄λ“œ**: κΈ°λ³Έ 톡계 ν‘œμ‹œ, 차트 κ΅¬ν˜„ 쀑 +- πŸ”„ **검색 및 ν•„ν„°**: κΈ°λ³Έ 검색 κ΅¬ν˜„, κ³ κΈ‰ ν•„ν„° 개발 쀑 + +### Not Started (0%) +- ⏳ **μž₯λΉ„ λŒ€μ—¬**: λŒ€μ—¬/λ°˜λ‚© ν”„λ‘œμ„ΈμŠ€ +- ⏳ **μž₯λΉ„ 폐기**: 폐기 μ‚¬μœ  및 이λ ₯ 관리 +- ⏳ **λ³΄κ³ μ„œ 생성**: Excel/PDF 내보내기 +- ⏳ **λͺ¨λ°”일 μ•±**: λ°˜μ‘ν˜• λ ˆμ΄μ•„μ›ƒ μ΅œμ ν™” +- ⏳ **μ•Œλ¦Ό μ‹œμŠ€ν…œ**: 이메일/ν‘Έμ‹œ μ•Œλ¦Ό + +## πŸ› Known Issues + +### Critical ```yaml -development: - base_url: "https://api-dev.beavercompany.co.kr" - test_account: "admin@test.com / Test123!@#" - jwt_expiry: 24h +μ‹œλ¦¬μ–Ό_번호_쀑볡: + location: "μž₯λΉ„ μž…κ³  ν”„λ‘œμ„ΈμŠ€" + issue: "λ°±μ—”λ“œμ—μ„œ 쀑볡 체크 λ―Έκ΅¬ν˜„" + workaround: "ν”„λ‘ νŠΈμ—”λ“œ μž„μ‹œ 검증" + priority: HIGH -production: - base_url: "TBD" - security: "JWT + Secure Storage" +κΆŒν•œ_체크_λˆ„λ½: + location: ["warehouse_location", "overview"] + issue: "일뢀 ν™”λ©΄μ—μ„œ μ—­ν•  기반 μ ‘κ·Ό μ œμ–΄ 미적용" + impact: "λͺ¨λ“  μ‚¬μš©μžκ°€ μ ‘κ·Ό κ°€λŠ₯" + priority: HIGH ``` -### Environment Switching -```dart -// ν™˜κ²½ λ³€μˆ˜ μ„€μ • (.env) -API_MODE=mock # mock | real -BASE_URL=https://api-dev.beavercompany.co.kr - -// μ½”λ“œμ—μ„œ ν™˜κ²½ μ „ν™˜ -final isMockMode = dotenv.env['API_MODE'] == 'mock'; -if (isMockMode) { - GetIt.I.registerSingleton(MockApiService()); -} else { - GetIt.I.registerSingleton(RealApiService()); -} -``` - -## πŸ§ͺ Test Automation System - -### Test Infrastructure -```dart -// λͺ¨λ“  ν™”λ©΄ ν…ŒμŠ€νŠΈλŠ” BaseScreenTest 상속 -abstract class BaseScreenTest { - // μžλ™ μ—λŸ¬ 진단 및 μˆ˜μ • - ApiErrorDiagnostics diagnostics; - - // ν•œκ΅­μ‹ ν˜„μ‹€μ  ν…ŒμŠ€νŠΈ 데이터 - TestDataGenerator generator; - - // 병렬 μ‹€ν–‰ μ œμ–΄ (μ΅œλŒ€ 3개) - SemaphoreManager semaphore; -} -``` - -### Test Execution Priority +### Minor ```yaml -test_order: - 1: "Company Management" # νšŒμ‚¬ λ¨Όμ € 생성 - 2: "User Management" # νšŒμ‚¬μ— μ‚¬μš©μž μ—°κ²° - 3: "Warehouse Location" # μ°½κ³  μœ„μΉ˜ μ„€μ • - 4: "Equipment In" # μž₯λΉ„ μž…κ³  - 5: "License Management" # λΌμ΄μ„ μŠ€ 등둝 - 6: "Equipment Out" # μž₯λΉ„ 좜고 - 7: "Overview Dashboard" # 톡계 확인 +μƒνƒœ_κ°±μ‹ _μ§€μ—°: + location: "CRUD μž‘μ—… ν›„ 리슀트 ν™”λ©΄" + issue: "일뢀 ν™”λ©΄μ—μ„œ μžλ™ μƒˆλ‘œκ³ μΉ¨ λ―Έμž‘λ™" + workaround: "μˆ˜λ™ μƒˆλ‘œκ³ μΉ¨" + priority: MEDIUM + +λ‚ μ§œ_포맷: + location: "λΌμ΄μ„ μŠ€ 만료일" + issue: "ν•œκ΅­ μ‹œκ°„λŒ€ ν‘œμ‹œ 뢈일치" + priority: LOW ``` -### Test Commands +## πŸ“‹ TODO List + +### Immediate (This Week) +- [ ] μž₯λΉ„ 좜고 ν”„λ‘œμ„ΈμŠ€ μ™„μ„± +- [ ] λŒ€μ‹œλ³΄λ“œ 차트 κ΅¬ν˜„ (Chart.js 톡합) +- [ ] μ‹œλ¦¬μ–Ό 번호 쀑볡 체크 λ°±μ—”λ“œ κ΅¬ν˜„ +- [ ] κΆŒν•œ 체크 λˆ„λ½ ν™”λ©΄ μˆ˜μ • + +### Short Term (This Month) +- [ ] μž₯λΉ„ λŒ€μ—¬/λ°˜λ‚© κΈ°λŠ₯ κ΅¬ν˜„ +- [ ] κ³ κΈ‰ 검색 ν•„ν„° κ΅¬ν˜„ +- [ ] Excel 내보내기 κΈ°λŠ₯ +- [ ] μ„±λŠ₯ μ΅œμ ν™” (가상 슀크둀링) + +### Long Term +- [ ] λͺ¨λ°”일 μ•± μ΅œμ ν™” +- [ ] ν‘Έμ‹œ μ•Œλ¦Ό μ‹œμŠ€ν…œ +- [ ] λ‹€κ΅­μ–΄ 지원 (μ˜μ–΄) +- [ ] λŒ€μ‹œλ³΄λ“œ μ»€μŠ€ν„°λ§ˆμ΄μ§• + +## πŸ”‘ Key Decisions + +### 2025-01-07 +- **Decision**: Mock μ„œλΉ„μŠ€ 제거, Real API μ „μš©μœΌλ‘œ μ „ν™˜ +- **Reason**: 개발 ν™˜κ²½ λ‹¨μˆœν™” 및 μ‹€μ œ ν™˜κ²½ ν…ŒμŠ€νŠΈ κ°•ν™” + +### 2025-01-06 +- **Decision**: Provider νŒ¨ν„΄ μœ μ§€ (Riverpod λ§ˆμ΄κ·Έλ ˆμ΄μ…˜ 보λ₯˜) +- **Reason**: ν˜„μž¬ ꡬ쑰가 μ•ˆμ •μ , νŒ€ ν•™μŠ΅ 곑선 κ³ λ € + +### 2024-12-20 +- **Decision**: Flutter Web μš°μ„  개발 +- **Reason**: λΉ λ₯Έ 배포와 크둜슀 ν”Œλž«νΌ 지원 + +## πŸš€ Quick Commands + +### Development ```bash -# 전체 ν…ŒμŠ€νŠΈ μ‹€ν–‰ (병렬) -flutter test test/master_test_suite.dart +# Start development (Real API) +flutter run -d chrome -# νŠΉμ • ν™”λ©΄ ν…ŒμŠ€νŠΈ -flutter test test/screens/company/company_test.dart +# Run tests +flutter test -# Mock λͺ¨λ“œ ν…ŒμŠ€νŠΈ -API_MODE=mock flutter test - -# μ—λŸ¬ 진단 λͺ¨λ“œ -flutter test --dart-define=DIAGNOSTIC_MODE=true -``` - -## 🎨 UI/UX Standards - -### Design System -```yaml -base_template: "Metronic Admin Template" -component_library: "ShadCN Flutter Port" - -colors: - primary: "#5867dd" # Metronic 기본색 - secondary: "#34bfa3" - background: "#f7f8fa" - error: "#fd397a" - success: "#0abb87" - -typography: - font_family: "NotoSansKR" - korean_support: true - -layout: - style: "Microsoft Dynamics 365" - structure: "Header + Sidebar + Content" - responsive: "Web First β†’ Mobile Adaptive" -``` - -### Component Patterns -```dart -// λͺ¨λ“  폼은 이 νŒ¨ν„΄ λ”°λ₯΄κΈ° -class EntityForm extends StatefulWidget { - final EntityController controller; - final FormMode mode; // create | edit | view - - // ν•„μˆ˜ μ„Ήμ…˜ - Widget buildBasicInfo() {} - Widget buildDetailInfo() {} - Widget buildActionButtons() {} -} - -// 리슀트 ν™”λ©΄ νŒ¨ν„΄ -class EntityList extends StatelessWidget { - // ν•„μˆ˜ μš”μ†Œ - Widget buildSearchBar() {} - Widget buildFilterOptions() {} - Widget buildDataTable() {} - Widget buildPagination() {} -} -``` - -## πŸ”Œ API Integration Rules - -### Error Handling Strategy -```dart -// λͺ¨λ“  API ν˜ΈμΆœμ€ 이 νŒ¨ν„΄ μ‚¬μš© -try { - final response = await apiService.call(); - return Right(response); -} on DioException catch (e) { - // 422개 μ—λŸ¬ νŒ¨ν„΄ μžλ™ 뢄석 - final diagnosis = ApiErrorDiagnostics.analyze(e); - return Left(ApiFailure( - code: diagnosis.code, - message: diagnosis.userMessage, // ν•œκ΅­μ–΄ - technicalDetails: diagnosis.details, - )); -} -``` - -### Response Parsing Rules -```dart -// JSON νŒŒμ‹± μ£Όμ˜μ‚¬ν•­ -rules: - - "null κ°’ μ•ˆμ „ 처리 ν•„μˆ˜" - - "λ‚ μ§œλŠ” ISO 8601 ν˜•μ‹" - - "IDλŠ” 항상 String νƒ€μž…" - - "빈 배열은 [] λ°˜ν™˜" - - "쀑첩 κ°μ²΄λŠ” 별도 DTO 생성" -``` - -## 🚨 Critical Areas & Known Issues - -### ⚠️ Current Gotchas -```yaml -equipment_in: - issue: "μ‹œλ¦¬μ–Ό 번호 쀑볡 체크 λ―Έκ΅¬ν˜„" - workaround: "ν”„λ‘ νŠΈμ—”λ“œμ—μ„œ μž„μ‹œ 검증" - -license_management: - issue: "만료일 계산 둜직 뢈일치" - note: "λ°±μ—”λ“œμ™€ ν”„λ‘ νŠΈμ—”λ“œ 둜직 톡일 ν•„μš”" - -user_permission: - issue: "κΆŒν•œ 체크 일뢀 ν™”λ©΄ λˆ„λ½" - affected: ["warehouse_location", "overview"] -``` - -### πŸ”₯ Hot Paths (μ„±λŠ₯ 주의) -```yaml -critical_operations: - - path: "Equipment List with 10000+ items" - solution: "Virtual scrolling κ΅¬ν˜„λ¨" - - - path: "Dashboard statistics calculation" - solution: "5λΆ„ 캐싱 적용" - - - path: "Company branch tree loading" - solution: "Lazy loading ν•„μˆ˜" -``` - -## πŸ“Š Current Sprint Focus - -### Active Development (2025-01-06) -```yaml -priority_1: - task: "Overview Dashboard μ™„μ„±" - acceptance_criteria: - - "μ‹€μ‹œκ°„ 톡계 데이터 μ •ν™•μ„±" - - "차트 λ Œλ”λ§ μ„±λŠ₯ μ΅œμ ν™”" - - "필터링 κΈ°λŠ₯ κ΅¬ν˜„" - -priority_2: - task: "Equipment Out ν”„λ‘œμ„ΈμŠ€" - blockers: - - "좜고 승인 μ›Œν¬ν”Œλ‘œμš° λ―Έμ •" - - "재고 차감 둜직 검증 ν•„μš”" - -priority_3: - task: "Mobile App λ³€ν™˜ μ€€λΉ„" - requirements: - - "λ°˜μ‘ν˜• λ ˆμ΄μ•„μ›ƒ 점검" - - "ν„°μΉ˜ 제슀처 μ΅œμ ν™”" -``` - -## 🧬 Code Generation Commands - -### Freezed & JsonSerializable -```bash -# 단일 파일 생성 +# Generate code (Freezed, JsonSerializable) flutter pub run build_runner build --delete-conflicting-outputs -# 전체 μž¬μƒμ„± (주의: μ‹œκ°„ μ†Œμš”) -flutter pub run build_runner build --delete-conflicting-outputs +# API integration test +./test_api_integration.sh -# Watch mode (개발 쀑) -flutter pub run build_runner watch +# Start backend API (별도 터미널) +cd /Users/maximilian.j.sul/Documents/flutter/superport_api +cargo run + +# View API logs +cd /Users/maximilian.j.sul/Documents/flutter/superport_api +tail -f logs/api.log ``` -### Injectable (DI) -```bash -# DI μ„€μ • μž¬μƒμ„± -flutter pub run build_runner build --delete-conflicting-outputs +### API Configuration +``` +Base URL: https://api-dev.beavercompany.co.kr +Test Account: admin@superport.kr / admin123! +API Source Code: /Users/maximilian.j.sul/Documents/flutter/superport_api ``` -## πŸ” Debugging Helpers +## πŸ“ž Team Contacts -### Quick Debug Commands -```dart -// API 응닡 λ‘œκΉ… -ApiService.enableLogging = true; - -// Mock 데이터 확인 -MockDataViewer.show(context); - -// ν˜„μž¬ 인증 μƒνƒœ -AuthService.debugPrintToken(); - -// Controller μƒνƒœ 좔적 -controller.addListener(() => print(controller.debugState)); -``` - -### Performance Monitoring -```dart -// ν™”λ©΄ λ Œλ”λ§ μ‹œκ°„ μΈ‘μ • -Timeline.startSync('ScreenRender'); -// ... rendering code -Timeline.finishSync(); - -// API 호좜 μ‹œκ°„ 좔적 -final stopwatch = Stopwatch()..start(); -await apiCall(); -print('API took: ${stopwatch.elapsed}'); -``` - -## πŸ“ Commit Message Convention - -### Project-Specific Prefixes -``` -equipment: μž₯λΉ„ 관리 κ΄€λ ¨ -company: νšŒμ‚¬ 관리 κ΄€λ ¨ -user: μ‚¬μš©μž 관리 κ΄€λ ¨ -license: μœ μ§€λ³΄μˆ˜ λΌμ΄μ„ μŠ€ κ΄€λ ¨ -warehouse: μ°½κ³  κ΄€λ ¨ -dashboard: λŒ€μ‹œλ³΄λ“œ κ΄€λ ¨ -auth: 인증/κΆŒν•œ κ΄€λ ¨ -api: API 연동 κ΄€λ ¨ -``` - -### Examples -``` -equipment: μ‹œλ¦¬μ–Ό 번호 쀑볡 검증 둜직 μΆ”κ°€ -company: 지점 트리 ꡬ쑰 lazy loading κ΅¬ν˜„ -test: Equipment In μžλ™ν™” ν…ŒμŠ€νŠΈ μ™„μ„± -api: 422 μ—λŸ¬ μžλ™ 볡ꡬ λ©”μ»€λ‹ˆμ¦˜ κ΅¬ν˜„ -``` - -## 🎯 Success Metrics - -### Code Quality Standards -```yaml -flutter_analyze: - errors: 0 - warnings: < 10 - info: < 50 - -test_coverage: - minimum: 80% - critical_paths: 100% - -performance: - initial_load: < 3s - api_response: < 500ms - list_render: < 100ms -``` - -## πŸš€ Quick Start Guide - -### For New Developers -```bash -# 1. ν™˜κ²½ μ„€μ • -cp .env.example .env -flutter pub get - -# 2. μ½”λ“œ 생성 -flutter pub run build_runner build --delete-conflicting-outputs - -# 3. Mock λͺ¨λ“œλ‘œ μ‹œμž‘ -API_MODE=mock flutter run -d chrome - -# 4. ν…ŒμŠ€νŠΈ μ‹€ν–‰ -flutter test test/master_test_suite.dart - -# 5. μ‹€μ œ API 연동 -API_MODE=real flutter run -d chrome -``` +- **Backend API Issues**: Rust λ°±μ—”λ“œ νŒ€ +- **UI/UX Questions**: λ””μžμΈ νŒ€ +- **Business Logic**: ν”„λ‘œλ•νŠΈ λ§€λ‹ˆμ € --- -**Version**: 2.0 -**Last Updated**: 2025-01-06 -**Project Stage**: Production Ready -**Next Milestone**: Mobile App Release \ No newline at end of file +**Project Stage**: Development (70% Complete) +**Next Milestone**: Beta Release (2025-02-01) +**Last Updated**: 2025-01-08 +**Version**: 3.0 \ No newline at end of file diff --git a/lib/screens/equipment/controllers/equipment_out_form_controller.dart b/lib/screens/equipment/controllers/equipment_out_form_controller.dart index f706d65..2ae2010 100644 --- a/lib/screens/equipment/controllers/equipment_out_form_controller.dart +++ b/lib/screens/equipment/controllers/equipment_out_form_controller.dart @@ -1,10 +1,13 @@ import 'package:flutter/material.dart'; +import 'package:get_it/get_it.dart'; import 'package:intl/intl.dart'; import 'package:superport/models/equipment_unified_model.dart'; import 'package:superport/models/company_model.dart'; import 'package:superport/models/company_branch_info.dart'; import 'package:superport/models/address_model.dart'; import 'package:superport/services/mock_data_service.dart'; +import 'package:superport/services/equipment_service.dart'; +import 'package:superport/services/company_service.dart'; import 'package:superport/utils/constants.dart'; /// μž₯λΉ„ 좜고 폼 컨트둀러 @@ -195,22 +198,55 @@ class EquipmentOutFormController extends ChangeNotifier { } try { - // TODO: μ‹€μ œ μ €μž₯ 둜직 κ΅¬ν˜„ - // ν˜„μž¬λŠ” Mock 데이터 μ„œλΉ„μŠ€μ— μ €μž₯ + // APIλ₯Ό ν†΅ν•œ 좜고 처리 + final equipmentService = GetIt.instance(); + final companyService = GetIt.instance(); + + // νšŒμ‚¬ ID κ°€μ Έμ˜€κΈ° + int? companyId; + int? branchId; + + // μ„ νƒλœ νšŒμ‚¬ μ •λ³΄μ—μ„œ ID μΆ”μΆœ + if (selectedCompanies[0] != null) { + final companies = await companyService.getCompanies(search: selectedCompanies[0]); + if (companies.isNotEmpty) { + companyId = companies.first.id; + // TODO: 지점 ID 처리 둜직 μΆ”κ°€ + } + } + + if (companyId == null) { + throw Exception('좜고처 정보λ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.'); + } if (isEditMode) { - // μˆ˜μ • λͺ¨λ“œ - // dataService.updateEquipmentOut(...) + // μˆ˜μ • λͺ¨λ“œ - ν˜„μž¬ λ―Έκ΅¬ν˜„ + throw UnimplementedError('좜고 μˆ˜μ • κΈ°λŠ₯은 아직 κ΅¬ν˜„λ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.'); } else { // 생성 λͺ¨λ“œ if (selectedEquipments != null && selectedEquipments!.isNotEmpty) { // 닀쀑 μž₯λΉ„ 좜고 for (var equipmentData in selectedEquipments!) { - // dataService.addEquipmentOut(...) + final equipment = equipmentData['equipment'] as Equipment; + if (equipment.id != null) { + await equipmentService.equipmentOut( + equipmentId: equipment.id!, + quantity: equipment.quantity, + companyId: companyId, + branchId: branchId, + notes: note ?? remarkController.text, + ); + } } - } else if (selectedEquipment != null) { + } else if (selectedEquipment != null && selectedEquipment!.id != null) { // 단일 μž₯λΉ„ 좜고 - // dataService.addEquipmentOut(...) + await equipmentService.equipmentOut( + equipmentId: selectedEquipment!.id!, + quantity: selectedEquipment!.quantity, + companyId: companyId, + branchId: branchId, + notes: note ?? remarkController.text, + ); } } diff --git a/test_api_integration.sh b/test_api_integration.sh new file mode 100755 index 0000000..6e55182 --- /dev/null +++ b/test_api_integration.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +# Superport API 톡합 ν…ŒμŠ€νŠΈ 슀크립트 +# μž‘μ„±μΌ: 2025-01-07 + +echo "======================================" +echo "Superport API 톡합 ν…ŒμŠ€νŠΈ μ‹œμž‘" +echo "======================================" + +# 색상 μ •μ˜ +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +# API κΈ°λ³Έ URL +API_URL="https://api-dev.beavercompany.co.kr" + +# ν…ŒμŠ€νŠΈ 계정 +TEST_EMAIL="admin@superport.kr" +TEST_PASSWORD="admin123!" + +echo -e "\n${YELLOW}1. ν—¬μŠ€ 체크${NC}" +curl -s -X GET "$API_URL/health" | jq '.' || echo -e "${RED}ν—¬μŠ€ 체크 μ‹€νŒ¨${NC}" + +echo -e "\n${YELLOW}2. 둜그인 ν…ŒμŠ€νŠΈ${NC}" +TOKEN=$(curl -s -X POST "$API_URL/auth/login" \ + -H "Content-Type: application/json" \ + -d "{\"email\":\"$TEST_EMAIL\",\"password\":\"$TEST_PASSWORD\"}" | jq -r '.data.token') + +if [ -z "$TOKEN" ] || [ "$TOKEN" = "null" ]; then + echo -e "${RED}둜그인 μ‹€νŒ¨! 토큰을 λ°›μ§€ λͺ»ν–ˆμŠ΅λ‹ˆλ‹€.${NC}" + exit 1 +else + echo -e "${GREEN}둜그인 성곡! 토큰 νšλ“${NC}" +fi + +echo -e "\n${YELLOW}3. μž₯λΉ„ λͺ©λ‘ 쑰회${NC}" +curl -s -X GET "$API_URL/equipment" \ + -H "Authorization: Bearer $TOKEN" | jq '.data[0] | {id, equipmentNumber, status}' || echo -e "${RED}μž₯λΉ„ 쑰회 μ‹€νŒ¨${NC}" + +echo -e "\n${YELLOW}4. νšŒμ‚¬ λͺ©λ‘ 쑰회${NC}" +curl -s -X GET "$API_URL/companies" \ + -H "Authorization: Bearer $TOKEN" | jq '.data[0] | {id, name, isActive}' || echo -e "${RED}νšŒμ‚¬ 쑰회 μ‹€νŒ¨${NC}" + +echo -e "\n${YELLOW}5. μ°½κ³  μœ„μΉ˜ λͺ©λ‘ 쑰회${NC}" +curl -s -X GET "$API_URL/warehouse-locations" \ + -H "Authorization: Bearer $TOKEN" | jq '.data[0] | {id, name, isActive}' || echo -e "${RED}μ°½κ³  쑰회 μ‹€νŒ¨${NC}" + +echo -e "\n${YELLOW}6. λΌμ΄μ„ μŠ€ λͺ©λ‘ 쑰회${NC}" +curl -s -X GET "$API_URL/licenses" \ + -H "Authorization: Bearer $TOKEN" | jq '.data[0] | {id, licenseKey, isActive}' || echo -e "${RED}λΌμ΄μ„ μŠ€ 쑰회 μ‹€νŒ¨${NC}" + +echo -e "\n======================================" +echo -e "${GREEN}API 톡합 ν…ŒμŠ€νŠΈ μ™„λ£Œ${NC}" +echo "======================================" \ No newline at end of file diff --git a/test_crud_operations.md b/test_crud_operations.md new file mode 100644 index 0000000..683822d --- /dev/null +++ b/test_crud_operations.md @@ -0,0 +1,53 @@ +# CRUD μž‘μ—… ν›„ ν™”λ©΄ κ°±μ‹  ν…ŒμŠ€νŠΈ 체크리슀트 + +## ν…ŒμŠ€νŠΈ μΌμ‹œ +- μž‘μ„±μΌ: 2025-01-07 +- ν…ŒμŠ€νŠΈ ν™˜κ²½: API λͺ¨λ“œ (Mock λΉ„ν™œμ„±ν™”) + +## 1. μž₯λΉ„ 관리 (Equipment) + +### μž…κ³  (Equipment In) +- [ ] μƒˆ μž₯λΉ„ μž…κ³  β†’ 리슀트 화면에 μ¦‰μ‹œ 반영 +- [ ] μž…κ³  정보 μˆ˜μ • β†’ 리슀트 화면에 변경사항 반영 +- [ ] μž…κ³  μ‚­μ œ β†’ λ¦¬μŠ€νŠΈμ—μ„œ 제거 + +### 좜고 (Equipment Out) +- [ ] μž₯λΉ„ 좜고 처리 β†’ μƒνƒœ λ³€κ²½ 확인 +- [ ] 좜고 정보 μˆ˜μ • β†’ 변경사항 반영 +- [ ] 좜고 μ·¨μ†Œ β†’ μƒνƒœ 볡ꡬ + +## 2. νšŒμ‚¬ 관리 (Company) +- [ ] μƒˆ νšŒμ‚¬ μΆ”κ°€ β†’ λ¦¬μŠ€νŠΈμ— μ¦‰μ‹œ ν‘œμ‹œ +- [ ] νšŒμ‚¬ 정보 μˆ˜μ • β†’ 변경사항 반영 +- [ ] νšŒμ‚¬ μ‚­μ œ β†’ λ¦¬μŠ€νŠΈμ—μ„œ 제거 +- [ ] 지점 μΆ”κ°€/μˆ˜μ •/μ‚­μ œ β†’ 변경사항 반영 + +## 3. μ°½κ³  μœ„μΉ˜ 관리 (Warehouse Location) +- [ ] μƒˆ μ°½κ³  μΆ”κ°€ β†’ λ¦¬μŠ€νŠΈμ— ν‘œμ‹œ +- [ ] μ°½κ³  정보 μˆ˜μ • β†’ 변경사항 반영 +- [ ] μ°½κ³  μ‚­μ œ β†’ λ¦¬μŠ€νŠΈμ—μ„œ 제거 + +## 4. μœ μ§€λ³΄μˆ˜ λΌμ΄μ„ μŠ€ (License) +- [ ] μƒˆ λΌμ΄μ„ μŠ€ μΆ”κ°€ β†’ λ¦¬μŠ€νŠΈμ— ν‘œμ‹œ +- [ ] λΌμ΄μ„ μŠ€ 정보 μˆ˜μ • β†’ 변경사항 반영 +- [ ] λΌμ΄μ„ μŠ€ μ‚­μ œ β†’ λ¦¬μŠ€νŠΈμ—μ„œ 제거 +- [ ] λΌμ΄μ„ μŠ€ ν• λ‹Ή/ν•΄μ œ β†’ μƒνƒœ λ³€κ²½ 반영 + +## 5. μ‚¬μš©μž 관리 (User) +- [ ] μƒˆ μ‚¬μš©μž μΆ”κ°€ β†’ λ¦¬μŠ€νŠΈμ— ν‘œμ‹œ +- [ ] μ‚¬μš©μž 정보 μˆ˜μ • β†’ 변경사항 반영 +- [ ] μ‚¬μš©μž μ‚­μ œ β†’ λ¦¬μŠ€νŠΈμ—μ„œ 제거 +- [ ] κΆŒν•œ λ³€κ²½ β†’ μ¦‰μ‹œ 반영 + +## ν…ŒμŠ€νŠΈ κ²°κ³Ό 기둝 + +### 문제 발견 μ‹œ: +1. ν™”λ©΄λͺ…: +2. μž‘μ—… μœ ν˜•: (생성/μˆ˜μ •/μ‚­μ œ) +3. 증상: +4. μ˜ˆμƒ 원인: + +### ν•΄κ²° 방법: +1. μˆ˜μ •ν•œ 파일: +2. μˆ˜μ • λ‚΄μš©: +3. ν…ŒμŠ€νŠΈ κ²°κ³Ό: \ No newline at end of file