backend phase 15 & frontend phase 8

This commit is contained in:
hamid
2026-07-10 03:22:29 +03:30
parent 93cc5ecb98
commit cd6c2591a6
154 changed files with 15335 additions and 37 deletions
@@ -0,0 +1,31 @@
#nullable enable
using Baya.Application.Contracts.Common;
using Microsoft.Extensions.Options;
namespace Baya.Infrastructure.CrossCutting.Seams;
/// <summary>
/// Default <see cref="ILicenseVerificationService"/> — and the mock. The MoH establishment-permit registry and
/// eNamad have <b>no public B2B API</b>, so at MVP licensing is a manual admin approval: every call returns
/// <see cref="LicenseVerificationStatus.NeedsManualReview"/>, and <c>VerifyPartnerCenter</c> records the human
/// decision. Set <see cref="LicenseVerificationOptions.AutoApprove"/> to have the mock return
/// <see cref="LicenseVerificationStatus.Valid"/> (test the auto-approve path). When a real registry/API becomes
/// available, a real implementation replaces this registration and starts returning real verdicts — callers are
/// unchanged.
/// </summary>
public sealed class MockLicenseVerificationService(IOptions<SeamOptions> options) : ILicenseVerificationService
{
private LicenseVerificationOptions Options => options.Value.LicenseVerification;
public Task<LicenseVerdict> VerifyEstablishmentPermitAsync(string permitNo, CancellationToken cancellationToken = default)
=> Task.FromResult(Verdict($"establishment permit '{permitNo}'"));
public Task<LicenseVerdict> VerifyENamadAsync(string enamadCode, CancellationToken cancellationToken = default)
=> Task.FromResult(Verdict($"eNamad '{enamadCode}'"));
private LicenseVerdict Verdict(string subject)
=> Options.AutoApprove
? new LicenseVerdict(LicenseVerificationStatus.Valid, $"Auto-approved (mock) for {subject}.")
: new LicenseVerdict(LicenseVerificationStatus.NeedsManualReview,
$"No automated registry for {subject}; requires a manual admin decision.");
}
@@ -21,6 +21,19 @@ public sealed class SeamOptions
public CurrencyOptions Currency { get; set; } = new();
public BankTransferOptions BankTransfer { get; set; } = new();
public ReviewModerationOptions ReviewModeration { get; set; } = new();
public LicenseVerificationOptions LicenseVerification { get; set; } = new();
}
/// <summary>
/// Tunes the mock <c>ILicenseVerificationService</c> (b15 partner-center eNamad / MoH establishment-permit
/// check). By default every check returns <c>NeedsManualReview</c> so <c>VerifyPartnerCenter</c> records the
/// human admin decision. Set <see cref="AutoApprove"/> to have the mock return <c>Valid</c> (test the
/// auto-approve path). The real eNamad / MoH registry adapter ignores these knobs.
/// </summary>
public sealed class LicenseVerificationOptions
{
/// <summary>When true, permit/eNamad checks auto-approve (return <c>Valid</c>) instead of requiring a manual decision.</summary>
public bool AutoApprove { get; set; }
}
/// <summary>
@@ -87,6 +87,12 @@ public static class ServiceCollectionExtension
// keeps decision authority + the human override, so the real impl never touches the handler.
services.AddSingleton<IReviewModerationService, MockReviewModerationService>();
// Partner-center licensing (backend-phase-15). eNamad / MoH establishment-permit registries have no
// public B2B API, so the mock returns NeedsManualReview (manual admin approval at MVP; config can force
// auto-approve for tests). A real registry/API client swaps in by a registration change only —
// VerifyPartnerCenter records the decision and is never touched.
services.AddSingleton<ILicenseVerificationService, MockLicenseVerificationService>();
return services;
}
}