namespace TaxBaik.Application.Services; using TaxBaik.Domain.Entities; using TaxBaik.Domain.Interfaces; public class RevenueTrackingService(IRevenueTrackingRepository repository) { public async Task CreateAsync(int clientId, string invoiceNumber, DateTime invoiceDate, decimal amount, string? serviceType = null, DateTime? dueDate = null, CancellationToken ct = default) { if (clientId <= 0) throw new ValidationException("유효한 고객을 선택하세요."); if (string.IsNullOrWhiteSpace(invoiceNumber)) throw new ValidationException("인보이스 번호를 입력하세요."); if (amount <= 0) throw new ValidationException("금액은 0보다 커야 합니다."); var revenue = new RevenueTracking { ClientId = clientId, InvoiceNumber = invoiceNumber.Trim(), InvoiceDate = invoiceDate, Amount = amount, ServiceType = string.IsNullOrWhiteSpace(serviceType) ? null : serviceType.Trim(), DueDate = dueDate, PaymentStatus = "pending", CreatedAt = DateTime.UtcNow, UpdatedAt = DateTime.UtcNow }; return await repository.CreateAsync(revenue, ct); } public async Task> GetByClientIdAsync(int clientId, CancellationToken ct = default) => await repository.GetByClientIdAsync(clientId, ct); public async Task> GetAllAsync(CancellationToken ct = default) => await repository.GetAllAsync(ct); public async Task> GetPendingPaymentsAsync(CancellationToken ct = default) => await repository.GetPendingPaymentsAsync(ct); public async Task> GetMonthlyRevenueAsync(DateTime month, CancellationToken ct = default) { var startDate = new DateTime(month.Year, month.Month, 1); var endDate = startDate.AddMonths(1).AddDays(-1); return await repository.GetByDateRangeAsync(startDate, endDate, ct); } public async Task MarkPaidAsync(int id, DateTime paymentDate, CancellationToken ct = default) => await repository.MarkPaidAsync(id, paymentDate, ct); public async Task GetTotalRevenueAsync(DateTime startDate, DateTime endDate, CancellationToken ct = default) => await repository.GetTotalRevenueAsync(startDate, endDate, ct); }