feat: establish dotnet engineering foundation

This commit is contained in:
2026-07-27 15:00:14 +08:00
parent 60a376ea0b
commit 28e9a9fa41
36 changed files with 17301 additions and 89 deletions

View File

@@ -4,11 +4,14 @@ using Tiku.Application.Growth;
using Tiku.Domain.Common;
using Tiku.Domain.Growth;
using Tiku.Domain.Tenancy;
using Tiku.Infrastructure.Commerce;
using Tiku.Infrastructure.Persistence;
namespace Tiku.Infrastructure.Growth;
public sealed class CrmService(TikuDbContext dbContext) : ICrmService
internal sealed class CrmService(
TikuDbContext dbContext,
ITenantSecretProtector tenantSecretProtector) : ICrmService
{
private static readonly HashSet<string> SensitiveKeys = new(StringComparer.OrdinalIgnoreCase)
{
@@ -254,8 +257,15 @@ public sealed class CrmService(TikuDbContext dbContext) : ICrmService
item.RotatedAt = DateTimeOffset.UtcNow;
}
var protectedPayload = tenantSecretProtector.Protect(
tenantId,
secretRef,
JsonSerializer.SerializeToElement(new { webhookSecret = secret }));
item.Status = TenantSecretStatus.Active;
item.SecretPayload = JsonSerializer.SerializeToElement(new { webhookSecret = secret });
item.EncryptionKeyId = protectedPayload.KeyId;
item.EncryptedPayload = protectedPayload.Ciphertext;
item.EncryptionNonce = protectedPayload.Nonce;
item.EncryptionTag = protectedPayload.Tag;
}
private async Task AssertAdminAsync(CrmAdminActor actor, CancellationToken cancellationToken)

View File

@@ -136,6 +136,7 @@ public sealed class ReferralService(
var eventType = NormalizeChoice(command.EventType, AllowedEventTypes, "enter", "invalid_referral_event_type");
var source = NormalizeChoice(command.Source, AllowedSources, "unknown", "invalid_referral_source");
var resolution = await ResolveCodeCoreAsync(actor.TenantId, code, cancellationToken);
await using var transaction = await dbContext.Database.BeginTransactionAsync(cancellationToken);
var track = new ReferralTrack
{
TenantId = actor.TenantId,
@@ -148,7 +149,6 @@ public sealed class ReferralService(
UserAgent = Truncate(NormalizeOptional(userAgent), 1024),
Metadata = command.Metadata ?? JsonDefaults.Object()
};
dbContext.ReferralTracks.Add(track);
ReferralLead? lead = null;
CrmWebhookQueueItem? crmQueue = null;
@@ -164,16 +164,29 @@ public sealed class ReferralService(
false,
command.Metadata,
cancellationToken);
if (lead.FirstTrackId is null)
var setFirstTrack = lead.FirstTrackId is null;
if (setFirstTrack)
{
await dbContext.SaveChangesAsync(cancellationToken);
}
dbContext.ReferralTracks.Add(track);
track.LeadId = lead.Id;
await dbContext.SaveChangesAsync(cancellationToken);
if (setFirstTrack)
{
lead.FirstTrackId = track.Id;
}
track.LeadId = lead.Id;
crmQueue = await EnqueueCrmIfEnabledAsync(actor.TenantId, lead, "referral.track_event", cancellationToken);
}
else
{
dbContext.ReferralTracks.Add(track);
}
await dbContext.SaveChangesAsync(cancellationToken);
await transaction.CommitAsync(cancellationToken);
return new ReferralTrackResult(ToTrackItem(track), lead is null ? null : ToLeadItem(lead, true), ToQueuePreview(crmQueue));
}