c2955ad02f
TaxBaik CI/CD / build-and-deploy (push) Successful in 49s
Phase 2: Repository Implementation (Dapper) - TaxProfileRepository: tax profile CRUD + risk level analysis + filing due dates - TaxFilingScheduleRepository: schedule tracking + upcoming due dates + completion marking - ConsultingActivityRepository: CRM activity history + pending followups + consultant tracking - ContractRepository: contract lifecycle + active contracts + expiring alerts + MRR calculation - RevenueTrackingRepository: invoice tracking + payment status + revenue analysis Phase 3: Service Layer (Business Logic) - TaxProfileService: profile creation, risk assessment, upcoming filing detection - TaxFilingScheduleService: schedule management, deadline tracking, completion workflow - ConsultingActivityService: activity logging, followup management, consultant productivity - ContractService: contract management, MRR calculation, expiring contract alerts - RevenueTrackingService: invoice creation, payment tracking, revenue analytics Phase 4: API Controller (REST Endpoints) - TaxProfileController: CRUD operations + high-risk filtering + upcoming filings query Architecture Highlights: - SOLID principles: each layer has clear responsibility - Dapper-based repositories for data access - Comprehensive service layer for business logic - RESTful API design with proper error handling - Ready for Blazor UI implementation and deployment Database Migration V015 executed: - 5 new specialized tables for CRM and tax accounting - Appropriate indexes for query performance - Foreign key constraints for data integrity
71 lines
3.9 KiB
C#
71 lines
3.9 KiB
C#
namespace TaxBaik.Infrastructure.Repositories;
|
|
|
|
using Dapper;
|
|
using TaxBaik.Domain.Entities;
|
|
using TaxBaik.Domain.Interfaces;
|
|
|
|
public class TaxProfileRepository(IDbConnectionFactory connectionFactory) : BaseRepository(connectionFactory), ITaxProfileRepository
|
|
{
|
|
public async Task<int> CreateAsync(TaxProfile profile, CancellationToken cancellationToken = default)
|
|
{
|
|
using var conn = Conn();
|
|
return await conn.QueryFirstAsync<int>(
|
|
@"INSERT INTO tax_profiles (client_id, business_registration, business_type, establishment_date,
|
|
annual_revenue_range, employee_count, accounting_method, fiscal_year_end, last_filing_date,
|
|
next_filing_due_date, tax_risk_level, previous_audit_history, special_notes, created_at, updated_at)
|
|
VALUES (@ClientId, @BusinessRegistration, @BusinessType, @EstablishmentDate, @AnnualRevenueRange,
|
|
@EmployeeCount, @AccountingMethod, @FiscalYearEnd, @LastFilingDate, @NextFilingDueDate,
|
|
@TaxRiskLevel, @PreviousAuditHistory, @SpecialNotes, NOW(), NOW())
|
|
RETURNING id",
|
|
profile);
|
|
}
|
|
|
|
public async Task<TaxProfile?> GetByClientIdAsync(int clientId, CancellationToken cancellationToken = default)
|
|
{
|
|
using var conn = Conn();
|
|
return await conn.QueryFirstOrDefaultAsync<TaxProfile>(
|
|
@"SELECT id, client_id, business_registration, business_type, establishment_date,
|
|
annual_revenue_range, employee_count, accounting_method, fiscal_year_end, last_filing_date,
|
|
next_filing_due_date, tax_risk_level, previous_audit_history, special_notes, created_at, updated_at
|
|
FROM tax_profiles WHERE client_id = @ClientId",
|
|
new { ClientId = clientId });
|
|
}
|
|
|
|
public async Task UpdateAsync(TaxProfile profile, CancellationToken cancellationToken = default)
|
|
{
|
|
using var conn = Conn();
|
|
await conn.ExecuteAsync(
|
|
@"UPDATE tax_profiles SET business_registration = @BusinessRegistration, business_type = @BusinessType,
|
|
establishment_date = @EstablishmentDate, annual_revenue_range = @AnnualRevenueRange,
|
|
employee_count = @EmployeeCount, accounting_method = @AccountingMethod, fiscal_year_end = @FiscalYearEnd,
|
|
last_filing_date = @LastFilingDate, next_filing_due_date = @NextFilingDueDate,
|
|
tax_risk_level = @TaxRiskLevel, previous_audit_history = @PreviousAuditHistory,
|
|
special_notes = @SpecialNotes, updated_at = NOW()
|
|
WHERE id = @Id",
|
|
profile);
|
|
}
|
|
|
|
public async Task<IEnumerable<TaxProfile>> GetByRiskLevelAsync(string riskLevel, CancellationToken cancellationToken = default)
|
|
{
|
|
using var conn = Conn();
|
|
return await conn.QueryAsync<TaxProfile>(
|
|
@"SELECT id, client_id, business_registration, business_type, establishment_date,
|
|
annual_revenue_range, employee_count, accounting_method, fiscal_year_end, last_filing_date,
|
|
next_filing_due_date, tax_risk_level, previous_audit_history, special_notes, created_at, updated_at
|
|
FROM tax_profiles WHERE tax_risk_level = @RiskLevel ORDER BY client_id",
|
|
new { RiskLevel = riskLevel });
|
|
}
|
|
|
|
public async Task<IEnumerable<TaxProfile>> GetUpcomingFilingDuesAsync(DateTime startDate, DateTime endDate, CancellationToken cancellationToken = default)
|
|
{
|
|
using var conn = Conn();
|
|
return await conn.QueryAsync<TaxProfile>(
|
|
@"SELECT id, client_id, business_registration, business_type, establishment_date,
|
|
annual_revenue_range, employee_count, accounting_method, fiscal_year_end, last_filing_date,
|
|
next_filing_due_date, tax_risk_level, previous_audit_history, special_notes, created_at, updated_at
|
|
FROM tax_profiles WHERE next_filing_due_date BETWEEN @StartDate AND @EndDate
|
|
ORDER BY next_filing_due_date",
|
|
new { StartDate = startDate, EndDate = endDate });
|
|
}
|
|
}
|