Files
taxbaik/TaxBaik.Web/Services/AdminClients/ITaxFilingScheduleBrowserClient.cs
T
kjh2064 a16438dcc6
TaxBaik CI/CD / build-and-deploy (push) Failing after 27s
feat: Phase 5 Browser Clients and deployment notification strategy
Phase 5: Tax & CRM Browser Clients
- 5 API client interfaces (TaxProfile, Filing, Activity, Contract, Revenue)
- Automatic token refresh for all clients
- Error logging with fallback empty lists
- Program.cs DI registration

Telegram Deployment Notifications:
- System chat (-5585148480): deployment success/failure
- Inquiry chat (-5434691215): customer inquiries
- Login alerts disabled (spam prevention)

Architecture:
Blazor -> BrowserClient (HttpClient+TokenRefresh) -> API -> Services -> DB

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

120 lines
4.2 KiB
C#

namespace TaxBaik.Web.Services.AdminClients;
using System.Text.Json;
using TaxBaik.Domain.Entities;
public interface ITaxFilingScheduleBrowserClient
{
Task<List<TaxFilingSchedule>> GetAllAsync(CancellationToken ct = default);
Task<TaxFilingSchedule?> GetByIdAsync(int id, CancellationToken ct = default);
Task<List<TaxFilingSchedule>> GetByClientIdAsync(int clientId, CancellationToken ct = default);
Task<List<TaxFilingSchedule>> GetUpcomingDuesAsync(int daysAhead = 30, CancellationToken ct = default);
Task<int> CreateAsync(int clientId, string filingType, DateTime dueDate, int filingYear,
int? assignedTo = null, CancellationToken ct = default);
Task MarkCompletedAsync(int id, CancellationToken ct = default);
Task DeleteAsync(int id, CancellationToken ct = default);
}
public class TaxFilingScheduleBrowserClient(HttpClient httpClient, ILogger<TaxFilingScheduleBrowserClient> logger)
: ITaxFilingScheduleBrowserClient
{
private const string BaseUrl = "/api/taxfilingschedule";
public async Task<List<TaxFilingSchedule>> GetAllAsync(CancellationToken ct = default)
{
try
{
return await httpClient.GetFromJsonAsync<List<TaxFilingSchedule>>($"{BaseUrl}", ct) ?? [];
}
catch (Exception ex)
{
logger.LogError(ex, "Failed to get tax filing schedules");
return [];
}
}
public async Task<TaxFilingSchedule?> GetByIdAsync(int id, CancellationToken ct = default)
{
try
{
return await httpClient.GetFromJsonAsync<TaxFilingSchedule>($"{BaseUrl}/{id}", ct);
}
catch (Exception ex)
{
logger.LogError(ex, "Failed to get tax filing schedule {Id}", id);
return null;
}
}
public async Task<List<TaxFilingSchedule>> GetByClientIdAsync(int clientId, CancellationToken ct = default)
{
try
{
return await httpClient.GetFromJsonAsync<List<TaxFilingSchedule>>($"{BaseUrl}/client/{clientId}", ct) ?? [];
}
catch (Exception ex)
{
logger.LogError(ex, "Failed to get filing schedules for client {ClientId}", clientId);
return [];
}
}
public async Task<List<TaxFilingSchedule>> GetUpcomingDuesAsync(int daysAhead = 30, CancellationToken ct = default)
{
try
{
var response = await httpClient.GetFromJsonAsync<JsonElement>($"{BaseUrl}/upcoming?daysAhead={daysAhead}", ct);
return response.TryGetProperty("data", out var data) ? System.Text.Json.JsonSerializer.Deserialize<List<TaxFilingSchedule>>() ?? [];
}
catch (Exception ex)
{
logger.LogError(ex, "Failed to get upcoming filings");
return [];
}
}
public async Task<int> CreateAsync(int clientId, string filingType, DateTime dueDate, int filingYear,
int? assignedTo = null, CancellationToken ct = default)
{
try
{
var request = new { clientId, filingType, dueDate, filingYear, assignedTo };
var response = await httpClient.PostAsJsonAsync(BaseUrl, request, ct);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadFromJsonAsync<dynamic>(cancellationToken: ct);
return result?["id"]?.ToObject<int>() ?? 0;
}
catch (Exception ex)
{
logger.LogError(ex, "Failed to create tax filing schedule");
return 0;
}
}
public async Task MarkCompletedAsync(int id, CancellationToken ct = default)
{
try
{
var response = await httpClient.PutAsJsonAsync($"{BaseUrl}/{id}/complete", new { }, ct);
response.EnsureSuccessStatusCode();
}
catch (Exception ex)
{
logger.LogError(ex, "Failed to mark filing as completed {Id}", id);
}
}
public async Task DeleteAsync(int id, CancellationToken ct = default)
{
try
{
var response = await httpClient.DeleteAsync($"{BaseUrl}/{id}", ct);
response.EnsureSuccessStatusCode();
}
catch (Exception ex)
{
logger.LogError(ex, "Failed to delete tax filing schedule {Id}", id);
}
}
}