@page "/admin/tax-profiles" @using TaxBaik.Web.Services.AdminClients @inject ITaxProfileBrowserClient TaxProfileClient @inject IClientBrowserClient ClientClient @inject ICommonCodeBrowserClient CommonCodeClient @inject ISnackbar Snackbar @inject IDialogService DialogService @attribute [Authorize] 세무 프로필 CRM & 세무관리 세무 프로필 고객별 세무 프로필, 신고 일정, 위험도 추적 새 프로필 추가 @if (profiles == null) { } else if (profiles.Count == 0) { 세무 프로필이 없습니다. } else { @if (clientMap.TryGetValue(context.Item.ClientId, out var clientName)) { @clientName } @context.Item.TaxRiskLevel @if (context.Item.NextFilingDueDate.HasValue) { @context.Item.NextFilingDueDate.Value.ToString("yyyy-MM-dd") } } @(isEditMode ? "세무 프로필 수정" : "새 세무 프로필 추가") @foreach (var client in clients) { @GetClientDisplayName(client) } @foreach (var type in businessTypes) { @type.CodeName } @foreach (var level in riskLevels) { @level.CodeName } 취소 저장 @code { [CascadingParameter] private Task? AuthStateTask { get; set; } private List? profiles; private List clients = []; private Dictionary clientMap = new(); private List businessTypes = []; private List riskLevels = []; private MudForm? form; private bool isDialogOpen; private bool isEditMode; private TaxProfile? editingProfile; private TaxProfileForm profileForm = new(); protected override async Task OnAfterRenderAsync(bool firstRender) { if (firstRender) { if (AuthStateTask != null) { var authState = await AuthStateTask; if (authState.User.Identity?.IsAuthenticated == true) { await LoadData(); StateHasChanged(); } } } } private async Task LoadData() { try { profiles = await TaxProfileClient.GetAllAsync(); var (clientItems, _) = await ClientClient.GetPagedAsync(pageSize: 1000); clients = clientItems.ToList(); clientMap = clients.ToDictionary(c => c.Id, GetClientDisplayName); businessTypes = await CommonCodeClient.GetByGroupAsync("BUSINESS_TYPE"); if (businessTypes.Count == 0) { businessTypes = [ new() { CodeValue = "일반제조업", CodeName = "일반제조업" }, new() { CodeValue = "도소매업", CodeName = "도소매업" }, new() { CodeValue = "서비스업", CodeName = "서비스업" }, new() { CodeValue = "정보통신업", CodeName = "정보통신업" }, new() { CodeValue = "부동산업", CodeName = "부동산업" }, new() { CodeValue = "건설업", CodeName = "건설업" }, new() { CodeValue = "음식점업", CodeName = "음식점업" }, new() { CodeValue = "프리랜서", CodeName = "프리랜서" }, new() { CodeValue = "기타", CodeName = "기타" } ]; } riskLevels = await CommonCodeClient.GetByGroupAsync("TAX_RISK_LEVEL"); if (riskLevels.Count == 0) { riskLevels = [ new() { CodeValue = "low", CodeName = "낮음" }, new() { CodeValue = "normal", CodeName = "보통" }, new() { CodeValue = "high", CodeName = "높음" } ]; } } catch (Exception ex) { Snackbar.Add($"데이터 로드 실패: {ex.Message}", Severity.Error); } } private void OpenCreateDialog() { isEditMode = false; editingProfile = null; profileForm = new TaxProfileForm { ClientId = clients.FirstOrDefault()?.Id, TaxRiskLevel = "normal", NextFilingDueDate = DateTime.Today.AddMonths(1) }; isDialogOpen = true; } private async Task OpenEditDialog(TaxProfile profile) { isEditMode = true; editingProfile = profile; profileForm = new TaxProfileForm { ClientId = profile.ClientId, BusinessType = profile.BusinessType ?? "", TaxRiskLevel = profile.TaxRiskLevel, NextFilingDueDate = profile.NextFilingDueDate, SpecialNotes = profile.SpecialNotes }; isDialogOpen = true; } private async Task SaveProfile() { if (form != null) { await form.Validate(); if (!form.IsValid) { Snackbar.Add("고객을 선택하세요.", Severity.Warning); return; } } try { if (isEditMode && editingProfile != null) { await TaxProfileClient.UpdateAsync(editingProfile.Id, profileForm.BusinessType, null, profileForm.NextFilingDueDate, profileForm.TaxRiskLevel); Snackbar.Add("세무 프로필이 수정되었습니다.", Severity.Success); } else { if (!profileForm.ClientId.HasValue) { Snackbar.Add("고객을 선택하세요.", Severity.Warning); return; } var newId = await TaxProfileClient.CreateAsync( profileForm.ClientId.Value, profileForm.BusinessType); if (newId > 0) { // 생성 후 상태 업데이트 처리 await TaxProfileClient.UpdateAsync( newId, profileForm.BusinessType, null, profileForm.NextFilingDueDate, profileForm.TaxRiskLevel); Snackbar.Add("세무 프로필이 추가되었습니다.", Severity.Success); } } CloseDialog(); await LoadData(); } catch (Exception ex) { Snackbar.Add($"저장 실패: {ex.Message}", Severity.Error); } } private async Task DeleteProfile(int id) { var parameters = new DialogParameters(); parameters.Add("Title", "삭제 확인"); parameters.Add("Message", "이 세무 프로필을 삭제하시겠습니까?"); var dialog = await DialogService.ShowAsync("", parameters); var result = await dialog.Result; if (result?.Canceled ?? true) return; try { await TaxProfileClient.DeleteAsync(id); Snackbar.Add("세무 프로필이 삭제되었습니다.", Severity.Success); await LoadData(); } catch (Exception ex) { Snackbar.Add($"삭제 실패: {ex.Message}", Severity.Error); } } private void CloseDialog() { isDialogOpen = false; isEditMode = false; editingProfile = null; profileForm = new(); } private Color GetRiskColor(string riskLevel) => riskLevel switch { "high" => Color.Error, "normal" => Color.Warning, "low" => Color.Success, _ => Color.Default }; private static string GetClientDisplayName(Client client) => !string.IsNullOrWhiteSpace(client.CompanyName) ? client.CompanyName : !string.IsNullOrWhiteSpace(client.Name) ? client.Name : $"Client #{client.Id}"; private class TaxProfileForm { public int? ClientId { get; set; } public string BusinessType { get; set; } = ""; public string TaxRiskLevel { get; set; } = "normal"; public DateTime? NextFilingDueDate { get; set; } public string? SpecialNotes { get; set; } } }