구현: W2 도메인·인프라·서비스 레이어
Domain 레이어: - Enums: InquiryStatus (New/Contacted/Contracted/Closed) - Enums: ServiceType (기장/종소세/부가세/양도세/증여상속/기타) - Entities: Category, BlogPost, Inquiry, AdminUser (DB 매핑) - Interfaces: IBlogPostRepository, ICategoryRepository, IInquiryRepository, IDbConnectionFactory Infrastructure 레이어: - DbConnectionFactory: PostgreSQL 연결 팩토리 (Npgsql) - BlogPostRepository: GetBySlug, GetPublishedPaged, Create, Update, Delete, IncrementViewCount - CategoryRepository: GetAll, GetBySlug - InquiryRepository: Create, GetPaged, UpdateStatus - NuGet 의존성: Dapper 2.1.15, Npgsql 8.0.1, Configuration, DependencyInjection - DependencyInjection: AddInfrastructure() 확장 메서드 기술 결정: - Dapper로 SQL 완전 제어 - PostgreSQL 다중 쿼리 (QueryMultiple) 페이징 최적화 - 한국어 파라미터 처리 (::int, ::text 타입 명시) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
namespace TaxBaik.Infrastructure.Repositories;
|
||||
|
||||
using Dapper;
|
||||
using TaxBaik.Domain.Entities;
|
||||
using TaxBaik.Domain.Interfaces;
|
||||
|
||||
public class InquiryRepository(IDbConnectionFactory connectionFactory) : BaseRepository(connectionFactory), IInquiryRepository
|
||||
{
|
||||
public async Task<int> CreateAsync(Inquiry inquiry, CancellationToken cancellationToken = default)
|
||||
{
|
||||
using var conn = Conn();
|
||||
return await conn.QueryFirstAsync<int>(
|
||||
@"INSERT INTO inquiries (name, phone, email, service_type, message, status, ip_address, created_at)
|
||||
VALUES (@Name, @Phone, @Email, @ServiceType, @Message, @Status, @IpAddress, NOW())
|
||||
RETURNING id",
|
||||
inquiry);
|
||||
}
|
||||
|
||||
public async Task<Inquiry?> GetByIdAsync(int id, CancellationToken cancellationToken = default)
|
||||
{
|
||||
using var conn = Conn();
|
||||
return await conn.QueryFirstOrDefaultAsync<Inquiry>(
|
||||
"SELECT id, name, phone, email, service_type, message, status, ip_address, created_at FROM inquiries WHERE id = @Id",
|
||||
new { Id = id });
|
||||
}
|
||||
|
||||
public async Task<(IEnumerable<Inquiry> Items, int Total)> GetPagedAsync(
|
||||
int page, int pageSize, string? status = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
using var conn = Conn();
|
||||
var offset = (page - 1) * pageSize;
|
||||
|
||||
using var reader = await conn.QueryMultipleAsync(
|
||||
@"SELECT id, name, phone, email, service_type, message, status, ip_address, created_at
|
||||
FROM inquiries
|
||||
WHERE @Status::text IS NULL OR status = @Status
|
||||
ORDER BY created_at DESC
|
||||
LIMIT @PageSize OFFSET @Offset;
|
||||
|
||||
SELECT COUNT(*) FROM inquiries
|
||||
WHERE @Status::text IS NULL OR status = @Status;",
|
||||
new { Status = status, PageSize = pageSize, Offset = offset });
|
||||
|
||||
var items = (await reader.ReadAsync<Inquiry>()).ToList();
|
||||
var total = await reader.ReadFirstAsync<int>();
|
||||
|
||||
return (items, total);
|
||||
}
|
||||
|
||||
public async Task UpdateStatusAsync(int id, string status, CancellationToken cancellationToken = default)
|
||||
{
|
||||
using var conn = Conn();
|
||||
await conn.ExecuteAsync("UPDATE inquiries SET status = @Status WHERE id = @Id", new { Id = id, Status = status });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user