diff --git a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillingDetailQueryHandler.cs b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillingDetailQueryHandler.cs index 50a90d4..23d7e21 100644 --- a/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillingDetailQueryHandler.cs +++ b/src/Application/TakeoutSaaS.Application/App/Billings/Handlers/GetBillingDetailQueryHandler.cs @@ -46,14 +46,35 @@ public sealed class GetBillingDetailQueryHandler( throw new BusinessException(ErrorCodes.NotFound, "账单不存在"); } + // 1.2 (空行后) 读取账单行数据到内存(释放 Reader,避免同连接并发执行命令) + var billingId = billReader.GetInt64(0); + var tenantId = billReader.GetInt64(1); + var tenantName = billReader.IsDBNull(2) ? string.Empty : billReader.GetString(2); + long? subscriptionId = billReader.IsDBNull(3) ? null : billReader.GetInt64(3); + var statementNo = billReader.GetString(4); + var billingType = (BillingType)billReader.GetInt32(5); + var status = (TenantBillingStatus)billReader.GetInt32(6); + var periodStart = billReader.GetDateTime(7); + var periodEnd = billReader.GetDateTime(8); + var amountDue = billReader.GetDecimal(9); + var discountAmount = billReader.GetDecimal(10); + var taxAmount = billReader.GetDecimal(11); + var amountPaid = billReader.GetDecimal(12); + var currency = billReader.IsDBNull(13) ? "CNY" : billReader.GetString(13); + var dueDate = billReader.GetDateTime(14); DateTime? reminderSentAt = billReader.IsDBNull(15) ? null : billReader.GetDateTime(15); DateTime? overdueNotifiedAt = billReader.IsDBNull(16) ? null : billReader.GetDateTime(16); var notes = billReader.IsDBNull(17) ? null : billReader.GetString(17); var lineItemsJson = billReader.IsDBNull(18) ? null : billReader.GetString(18); + var createdAt = billReader.GetDateTime(19); long? createdBy = billReader.IsDBNull(20) ? null : billReader.GetInt64(20); + DateTime? updatedAt = billReader.IsDBNull(21) ? null : billReader.GetDateTime(21); long? updatedBy = billReader.IsDBNull(22) ? null : billReader.GetInt64(22); - // 1.2 (空行后) 反序列化账单明细 + // 1.3 (空行后) 主动释放账单 Reader,确保后续查询不会触发 Npgsql 并发命令异常 + await billReader.DisposeAsync(); + + // 1.4 (空行后) 反序列化账单明细 var lineItems = new List(); if (!string.IsNullOrWhiteSpace(lineItemsJson)) { @@ -67,7 +88,7 @@ public sealed class GetBillingDetailQueryHandler( } } - // 1.3 (空行后) 查询支付记录 + // 1.5 (空行后) 查询支付记录 var payments = new List(); await using var paymentCommand = CreateCommand( connection, @@ -100,39 +121,36 @@ public sealed class GetBillingDetailQueryHandler( }); } - // 1.4 (空行后) 组装详情 DTO - var amountDue = billReader.GetDecimal(9); - var discountAmount = billReader.GetDecimal(10); - var taxAmount = billReader.GetDecimal(11); + // 1.6 (空行后) 组装详情 DTO var totalAmount = amountDue - discountAmount + taxAmount; return new BillingDetailDto { - Id = billReader.GetInt64(0), - TenantId = billReader.GetInt64(1), - TenantName = billReader.IsDBNull(2) ? string.Empty : billReader.GetString(2), - SubscriptionId = billReader.IsDBNull(3) ? null : billReader.GetInt64(3), - StatementNo = billReader.GetString(4), - BillingType = (BillingType)billReader.GetInt32(5), - Status = (TenantBillingStatus)billReader.GetInt32(6), - PeriodStart = billReader.GetDateTime(7), - PeriodEnd = billReader.GetDateTime(8), - AmountDue = billReader.GetDecimal(9), - DiscountAmount = billReader.GetDecimal(10), - TaxAmount = billReader.GetDecimal(11), + Id = billingId, + TenantId = tenantId, + TenantName = tenantName, + SubscriptionId = subscriptionId, + StatementNo = statementNo, + BillingType = billingType, + Status = status, + PeriodStart = periodStart, + PeriodEnd = periodEnd, + AmountDue = amountDue, + DiscountAmount = discountAmount, + TaxAmount = taxAmount, TotalAmount = totalAmount, - AmountPaid = billReader.GetDecimal(12), - Currency = billReader.IsDBNull(13) ? "CNY" : billReader.GetString(13), - DueDate = billReader.GetDateTime(14), + AmountPaid = amountPaid, + Currency = currency, + DueDate = dueDate, ReminderSentAt = reminderSentAt, OverdueNotifiedAt = overdueNotifiedAt, LineItemsJson = lineItemsJson, LineItems = lineItems, Payments = payments, Notes = notes, - CreatedAt = billReader.GetDateTime(19), + CreatedAt = createdAt, CreatedBy = createdBy, - UpdatedAt = billReader.IsDBNull(21) ? null : billReader.GetDateTime(21), + UpdatedAt = updatedAt, UpdatedBy = updatedBy }; },