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>
This commit is contained in:
2026-06-28 10:41:33 +09:00
parent 126643665a
commit 5053245575
20 changed files with 5307 additions and 1 deletions
@@ -74,6 +74,28 @@ public class InquiryRepository(IDbConnectionFactory connectionFactory) : BaseRep
new { Status = status });
}
public async Task<int> CountByDateRangeAsync(DateTime startDate, DateTime endDate, CancellationToken cancellationToken = default)
{
using var conn = Conn();
return await conn.ExecuteScalarAsync<int>(
@"SELECT COUNT(*)
FROM inquiries
WHERE created_at >= @StartDate AND created_at <= @EndDate",
new { StartDate = startDate, EndDate = endDate });
}
public async Task<int> CountByStatusAndDateAsync(string status, DateTime startDate, DateTime endDate, CancellationToken cancellationToken = default)
{
using var conn = Conn();
return await conn.ExecuteScalarAsync<int>(
@"SELECT COUNT(*)
FROM inquiries
WHERE status = @Status
AND created_at >= @StartDate
AND created_at <= @EndDate",
new { Status = status, StartDate = startDate, EndDate = endDate });
}
public async Task UpdateStatusAsync(int id, string status, CancellationToken cancellationToken = default)
{
using var conn = Conn();