84 lines
3.6 KiB
C#
84 lines
3.6 KiB
C#
using System.Text.Json;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Tiku.Application.Jobs;
|
|
using Tiku.Domain.Commerce;
|
|
using Tiku.Domain.Tenancy;
|
|
using Tiku.Infrastructure.Jobs;
|
|
using Tiku.Infrastructure.Persistence;
|
|
|
|
namespace Tiku.Infrastructure.Commerce.Reconciliation;
|
|
|
|
internal sealed class CommerceReconciliationJobHandler(ICommercePersistence commercePersistence,
|
|
ITenancyPersistence tenancyPersistence) : IBackgroundJobHandler
|
|
{
|
|
public string JobType => "commerce_reconciliation";
|
|
|
|
public async Task<BackgroundJobHandlerResult> HandleAsync(
|
|
BackgroundJobExecutionContext context,
|
|
CancellationToken cancellationToken = default)
|
|
{
|
|
var provider = NormalizeProvider(BackgroundJobPayload.GetString(context.Payload, "provider"));
|
|
var hasProviderConfig = await tenancyPersistence.TenantExternalProviders.AnyAsync(
|
|
item =>
|
|
item.TenantId == context.TenantId &&
|
|
item.Capability == TenantExternalProviderCapability.Payment &&
|
|
item.Provider == provider &&
|
|
item.Status == TenantExternalProviderStatus.Active,
|
|
cancellationToken);
|
|
if (!hasProviderConfig)
|
|
throw new InvalidOperationException(
|
|
$"Active payment provider '{provider}' is required for commerce reconciliation job.");
|
|
|
|
var billDate = BackgroundJobPayload.GetDateOnly(context.Payload, "billDate") ??
|
|
DateOnly.FromDateTime(DateTime.UtcNow.Date);
|
|
var billType = BackgroundJobPayload.GetEnum(context.Payload, "billType", ReconciliationBillType.Combined);
|
|
var sourceHash = $"background-job:{context.JobId:N}";
|
|
var batch = await commercePersistence.CommerceReconciliationBatches.SingleOrDefaultAsync(
|
|
item =>
|
|
item.TenantId == context.TenantId &&
|
|
item.Provider == provider &&
|
|
item.Source == ReconciliationSource.ProviderDownload &&
|
|
item.SourceHash == sourceHash,
|
|
cancellationToken);
|
|
if (batch is null)
|
|
{
|
|
batch = new CommerceReconciliationBatch
|
|
{
|
|
TenantId = context.TenantId,
|
|
Provider = provider,
|
|
BillDate = billDate,
|
|
BillType = billType,
|
|
Source = ReconciliationSource.ProviderDownload,
|
|
SourceName = $"provider-bill:{provider}:{billDate:yyyyMMdd}",
|
|
SourceHash = sourceHash,
|
|
Status = ReconciliationBatchStatus.Pending,
|
|
Metadata = JsonSerializer.SerializeToElement(new
|
|
{
|
|
jobId = context.JobId,
|
|
note =
|
|
"Provider bill job created the reconciliation batch; provider download/parser is handled by a dedicated provider processor."
|
|
})
|
|
};
|
|
commercePersistence.CommerceReconciliationBatches.Add(batch);
|
|
await commercePersistence.SaveChangesAsync(cancellationToken);
|
|
}
|
|
|
|
return new BackgroundJobHandlerResult(JsonSerializer.SerializeToElement(new
|
|
{
|
|
batchId = batch.Id,
|
|
provider,
|
|
billDate,
|
|
billType = billType.ToString(),
|
|
status = batch.Status.ToString()
|
|
}));
|
|
}
|
|
|
|
private static string NormalizeProvider(string? provider)
|
|
{
|
|
var normalized = (provider ?? string.Empty).Trim().ToLowerInvariant();
|
|
return string.IsNullOrWhiteSpace(normalized)
|
|
? throw new InvalidOperationException("Background job provider is required.")
|
|
: normalized;
|
|
}
|
|
}
|