50 lines
2.5 KiB
C#
50 lines
2.5 KiB
C#
using Dapper;
|
|
using FastEndpoints;
|
|
using Npgsql;
|
|
using Shared.Operations;
|
|
using System.Text.Json;
|
|
|
|
namespace Modules.Common.Reconcile.CreateExceptions;
|
|
|
|
public sealed record CreateReconcileExceptionsRequest(IReadOnlyList<Guid> Ids);
|
|
public sealed record CreateReconcileExceptionsResponse(int CreatedOrUpdatedCount, int SkippedCount);
|
|
|
|
public sealed class Endpoint(NpgsqlDataSource dataSource, OperationsProjectionWriter projection)
|
|
: Endpoint<CreateReconcileExceptionsRequest, CreateReconcileExceptionsResponse>
|
|
{
|
|
public override void Configure() { Post("/api/reconcile/items/create-exceptions"); Permissions("common.operations.create"); }
|
|
|
|
public override async Task HandleAsync(CreateReconcileExceptionsRequest req, CancellationToken ct)
|
|
{
|
|
var tenant = OperationsIdentity.TenantId(User);
|
|
var ids = req.Ids.Distinct().Take(500).ToArray();
|
|
if (ids.Length == 0) { await Send.OkAsync(new(0, 0), ct); return; }
|
|
await using var connection = await dataSource.OpenConnectionAsync(ct);
|
|
var rows = (await connection.QueryAsync<Row>(new CommandDefinition("""
|
|
select id, reconcile_type as ReconcileType, reference_no as ReferenceNo,
|
|
expected_value as ExpectedValue, actual_value as ActualValue,
|
|
difference_value as DifferenceValue, reason_code as ReasonCode, reason_text as ReasonText,
|
|
occurred_at as OccurredAt, version
|
|
from kbx.reconcile_items
|
|
where tenant_id=@Tenant and id=any(@Ids) and status in ('mismatch','pending');
|
|
""", new { Tenant = tenant, Ids = ids }, cancellationToken: ct))).AsList();
|
|
|
|
foreach (var row in rows)
|
|
{
|
|
await projection.UpsertAsync(new UpsertWorkItem(
|
|
tenant, "COMMON", "reconcile", row.Id.ToString(), row.ReferenceNo, "COMMON-REC-001", row.Version,
|
|
"RECONCILE_MISMATCH", $"대사 불일치 · {row.ReferenceNo}", row.ReasonText,
|
|
"warning", row.OccurredAt, Context: new {
|
|
row.ReconcileType, row.ReferenceNo, row.ExpectedValue, row.ActualValue,
|
|
row.DifferenceValue, row.ReasonCode
|
|
}), ct);
|
|
}
|
|
|
|
await Send.OkAsync(new(rows.Count, ids.Length - rows.Count), ct);
|
|
}
|
|
|
|
private sealed record Row(Guid Id, string ReconcileType, string ReferenceNo, string ExpectedValue,
|
|
string ActualValue, string? DifferenceValue, string? ReasonCode, string? ReasonText,
|
|
DateTimeOffset OccurredAt, long Version);
|
|
}
|