Commit Graph

10 Commits

Author SHA1 Message Date
kjh2064 80a16d8b20 refactor: Phase 7-3 Complete - All API Controllers + Browser Clients
TaxBaik CI/CD / build-and-deploy (push) Successful in 1m5s
**API Controllers Complete:**
- ClientController (GET /api/client paged, POST/PUT/DELETE)
- TaxFilingController (GET upcoming, GET by client, POST/PUT/DELETE)
- FaqController (GET active/all, GET by id, POST/PUT/DELETE)
- AnnouncementController (GET active/all, GET by id, POST/PUT/DELETE)

**Browser Clients Complete:**
- IClientBrowserClient + ClientBrowserClient
- ITaxFilingBrowserClient + TaxFilingBrowserClient
- IFaqBrowserClient + FaqBrowserClient
- IAnnouncementBrowserClient + AnnouncementBrowserClient

**All Registered in Program.cs:**
- BaseAddress: http://localhost:5001/taxbaik/api/
- TokenRefreshHandler attached to all clients
- DI container: AddHttpClient<IXxxClient, XxxClient>

**Blazor Refactored (Partial):**
- ClientList.razor:  IClientBrowserClient (service → API)
- ClientEdit.razor:  IClientBrowserClient (service → API)
- TaxFilings Blazor:  Pending refactor
- Faqs Blazor:  Pending refactor
- Announcements Blazor:  Pending refactor

**Phase 7 Status:**
- API-First Foundation:  100% (all controllers + clients ready)
- Blazor Refactoring: 🟡 30% (Clients done, others pending)
- Phase 6 SignalR:  Deferred (ready for real-time on API-first pages)

**SOLID Applied Throughout:**
✓ Single Responsibility: Each client handles one domain
✓ Open/Closed: Extend via interface, not modification
✓ Dependency Inversion: Blazor → Interfaces, not services
✓ Interface Segregation: Specialized clients per operation
✓ Liskov Substitution: All clients follow same contract

**Build:**  Success (0 errors, 2 warnings in Dashboard)
**Pattern:** Established & repeatable for remaining Blazor pages

Next: Blazor page migrations (TaxFilings, Faqs, Announcements)
Then: Phase 6 SignalR for real-time notifications

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 11:10:27 +09:00
kjh2064 fbdbbc7a1f refactor: Phase 7-3 - Clients + TaxFilings API-First (WIP)
TaxBaik CI/CD / build-and-deploy (push) Successful in 54s
**Clients Migration Complete:**
- ClientController: GET /api/client (paged), POST/PUT/DELETE
- ClientBrowserClient: IClientBrowserClient interface + implementation
- ClientList.razor: Service → API client
- ClientEdit.razor: Service → API client (Create/Update)

**TaxFilings API Framework Ready:**
- TaxFilingController: GET upcoming, GET by client, POST/PUT/DELETE
- TaxFilingBrowserClient: ITaxFilingBrowserClient interface + impl
- Registered in Program.cs with TokenRefreshHandler

**SOLID Applied:**
✓ Separation of concerns (Controller → Service → Repository)
✓ Dependency inversion (Blazor → Browser clients, not services)
✓ Interface segregation (Specialized clients per domain)

**Status:**
- Clients Blazor:  ClientList + ClientEdit refactored
- TaxFilings Blazor:  Pending refactor (pages exist)
- Faqs:  API + Blazor pending
- Announcements:  API + Blazor pending
- Phase 6 SignalR:  Deferred

Next: Refactor TaxFilings Blazor pages, then Faqs & Announcements
Build:  Success (0 errors, 2 warnings in Dashboard)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 11:08:43 +09:00
kjh2064 160afb7c7e refactor: Phase 7-2 Complete - Full Inquiry page API-First migration
TaxBaik CI/CD / build-and-deploy (push) Successful in 49s
**Blockers Fixed:**

1. InquiryBrowserClient URL hardcoding
   - Removed: \"http://localhost:5001\" hardcoded in each method
   - Added: Configured BaseAddress in Program.cs
   - Now uses: Relative paths (\"inquiry\", \"inquiry/{id}\", etc)
   - HttpClientFactory pipeline includes TokenRefreshHandler

2. Missing API endpoints in InquiryController
   - Added: PUT /api/inquiry/{id}/memo
   - Added: POST /api/inquiry/{id}/convert-to-client
   - Request DTOs: UpdateAdminMemoRequest, ConvertToClientRequest
   - ClientService injected (for client creation)

**Implementation:**

- InquiryBrowserClient: Extended interface
   * UpdateAdminMemoAsync(id, memo)
   * ConvertToClientAsync(id, name, phone, serviceType)
   * All methods use relative paths

- InquiryBrowserClient.ConvertToClientResponse
   * Deserialize API response to extract clientId

- InquiryDetail.razor: Full refactor
   * Before: @inject InquiryService, ClientService (direct service calls)
   * After: @inject IInquiryBrowserClient (API-only)
   * OnInitializedAsync: InquiryClient.GetByIdAsync
   * OnStatusChanged: InquiryClient.UpdateStatusAsync
   * SaveMemo: InquiryClient.UpdateAdminMemoAsync
   * ConvertToClient: InquiryClient.ConvertToClientAsync

**InquiryList.razor status:**
   * Also still injects IInquiryRepository (line 4)
   * Consider refactoring to use IInquiryBrowserClient for consistency

**Phase 7 Status:**
-  Blog page: Already API-First (ApiClient)
-  Inquiry page: Fully API-First (IInquiryBrowserClient)
  * InquiryTable:  Migrated
  * InquiryDetail:  Migrated
  * InquiryList:  Still uses IInquiryRepository (minor - reads only)

**SOLID Applied:**
✓ S: InquiryBrowserClient single responsibility
✓ D: Blazor → IInquiryBrowserClient (not ServiceLayer)
✓ O: Client can change without Blazor impact

Next: Check FAQ, Client, TaxFiling pages for same pattern.
If all still injecting services directly, migrate sequentially.
Then: Phase 6 (SignalR) will have all pages ready.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 10:59:02 +09:00
kjh2064 58edbd9c8f refactor: Phase 5 - JWT token lifecycle (Access + Refresh + Auto-refresh)
TaxBaik CI/CD / build-and-deploy (push) Successful in 48s
**Implementation:**
- AuthService: Split token generation
  * AccessToken: 15 minutes
  * RefreshToken: 7 days (10080 minutes)
  * New: GenerateTokenPair() method
  * New: RefreshAccessTokenAsync() method

- AuthTokenPair: New record (accessToken, refreshToken, expiresIn)

- AuthController: New /api/auth/refresh endpoint
  * POST /api/auth/refresh?refreshToken=...
  * Response: { accessToken, refreshToken, expiresIn }
  * RefreshTokenRequest DTO

- TokenRefreshHandler: New DelegatingHandler
  * Automatic Bearer token injection
  * 401 response handling
  * Auto-refresh with retry
  * localStorage sync (accessToken, refreshToken, tokenExpiry)

- CustomAuthenticationStateProvider: Token storage split
  * Before: auth_token (single)
  * After: accessToken, refreshToken, tokenExpiry
  * LoginAsync signature updated

- Login.razor: Handle token pair
  * LoginResponse: { accessToken, refreshToken, expiresIn }
  * Call new LoginAsync(accessToken, refreshToken, expiresIn)

- Program.cs: TokenRefreshHandler registration
  * AddScoped<TokenRefreshHandler>()
  * AdminDashboardClient pipeline: .AddHttpMessageHandler<TokenRefreshHandler>()

**SOLID Principles:**
✓ S (Single Responsibility): TokenRefreshHandler handles only token refresh
✓ D (Dependency Inversion): DelegatingHandler abstracts HTTP concerns
✓ O (Open/Closed): Token lifetime extension without code changes

**Security Pattern:**
- Short-lived access tokens (15min) reduce theft window
- Refresh tokens (7d) enable persistence without storing secrets
- Automatic refresh is transparent to components

**Flow:**
Blazor → AdminDashboardClient → TokenRefreshHandler (auto-add Bearer)
  → 401 → RefreshTokenAsync() → POST /api/auth/refresh
  → Store new pair → Retry original request

Status: Token lifecycle complete, ready for SignalR integration (Phase 6)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 10:51:24 +09:00
kjh2064 5053245575 feat: implement API-first architecture Phase 1 - Dashboard API
**Architecture Refactor (SOLID Principles):**
- Implement AdminDashboardController (REST API)
- Add dashboard summary endpoint
- Add upcoming filings endpoint
- Add recent inquiries endpoint
- Add monthly statistics endpoint

**Database Layer (Repository Pattern):**
- Extend IInquiryRepository with date range queries
- Implement CountByDateRangeAsync
- Implement CountByStatusAndDateAsync
- Extend InquiryRepository with new methods

**Service Layer (Single Responsibility):**
- Extend AdminDashboardService with API methods
- Add GetRecentInquiriesAsync
- Add GetMonthlyStatsAsync with caching

**Test Coverage:**
- Update FakeInquiryRepository mock with new methods

**SOLID Application:**
✓ Single Responsibility: Each class has one reason to change
✓ Open/Closed: Dashboard API can be extended without modifying existing code
✓ Dependency Inversion: Service depends on Repository abstraction
✓ Interface Segregation: API endpoints are focused and specific

Status: ✓ Compiles successfully (0 errors, 0 warnings)

Next phases:
- Add remaining API controllers (Announcement, Client, FAQ, TaxFiling)
- Refactor Blazor components to use API instead of services
- Implement JWT token refresh mechanism
- Add SignalR for change notifications

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 10:41:33 +09:00
kjh2064 bfad47c2af 수정: 블로그 상세 라우트 충돌 제거
TaxBaik CI/CD / build-and-deploy (push) Successful in 1m8s
TaxBaik Browser E2E / browser-e2e (push) Failing after 1m28s
2026-06-27 21:01:52 +09:00
kjh2064 f29f2c3cff 개선: 배포 검증과 관리자 UX 안정화
TaxBaik Browser E2E / browser-e2e (push) Failing after 1m3s
TaxBaik CI/CD / build-and-deploy (push) Failing after 2m46s
2026-06-27 20:57:09 +09:00
kjh2064 e3f548f163 feat: include inquiry status changer in alerts
TaxBaik Browser E2E / browser-e2e (push) Failing after 1m6s
TaxBaik CI/CD / build-and-deploy (push) Successful in 1m26s
2026-06-27 16:36:31 +09:00
kjh2064 28060b71be feat: harden auth ops and deployment baseline 2026-06-27 10:53:53 +09:00
kjh2064 e22cfb1ac5 feat: REST API 계층 추가 - 완벽한 MVC/API 분리
TaxBaik CI/CD / build-and-deploy (push) Failing after 43s
4개 API 컨트롤러 구현:
 AuthController: POST /api/auth/login
 BlogController: GET/POST/PUT/DELETE /api/blog
 CategoryController: GET/POST/PUT/DELETE /api/category
 InquiryController: POST/GET/PUT /api/inquiry

아키텍처 개선:
- Application 서비스 레이어 확장 (CategoryService 추가)
- Repository 인터페이스 CRUD 지원 추가
- Program.cs에 MapControllers() 추가
- 비즈니스 로직과 UI 완전 분리

장점:
- 향후 UI 리뉴얼 시 API 변경 불필요
- 모바일 앱, 데스크톱 클라이언트 추가 가능
- 테스트 가능한 API 엔드포인트

테스트 결과:
 블로그 API: 5개 포스트 조회
 카테고리 API: 5개 카테고리 조회
 문의 API: 문의 제출 성공
⚠️ 인증 API: 예정된 수정 대기

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-06-26 22:52:48 +09:00