feat: add commerce persistence

This commit is contained in:
xiong
2026-07-26 05:36:03 +08:00
parent aa000c63aa
commit fc8e04ebd6
7 changed files with 12766 additions and 1 deletions

View File

@@ -1,6 +1,7 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Tiku.Domain.Commerce;
using Tiku.Domain.Content;
using Tiku.Domain.Learning;
using Tiku.Domain.QuestionBanks;
@@ -25,7 +26,7 @@ public sealed class PersistenceModelTests
.Select(entity => entity.GetTableName())
.ToHashSet(StringComparer.Ordinal);
Assert.Equal(65, tableNames.Count);
Assert.Equal(79, tableNames.Count);
Assert.Contains("tenants", tableNames);
Assert.Contains("tenant_settings", tableNames);
Assert.Contains("content_entries", tableNames);
@@ -69,6 +70,20 @@ public sealed class PersistenceModelTests
Assert.Contains("tenant_class_members", tableNames);
Assert.Contains("tenant_student_notes", tableNames);
Assert.Contains("tenant_student_followups", tableNames);
Assert.Contains("products", tableNames);
Assert.Contains("svip_plans", tableNames);
Assert.Contains("orders", tableNames);
Assert.Contains("order_items", tableNames);
Assert.Contains("payments", tableNames);
Assert.Contains("payment_events", tableNames);
Assert.Contains("entitlements", tableNames);
Assert.Contains("code_batches", tableNames);
Assert.Contains("activation_codes", tableNames);
Assert.Contains("coupons", tableNames);
Assert.Contains("coupon_redemptions", tableNames);
Assert.Contains("tenant_payment_accounts", tableNames);
Assert.Contains("tenant_subscriptions", tableNames);
Assert.Contains("tenant_usage_records", tableNames);
Assert.Contains("questions", tableNames);
Assert.Contains("question_versions", tableNames);
Assert.Contains("answer_records", tableNames);
@@ -434,4 +449,58 @@ public sealed class PersistenceModelTests
.SequenceEqual(propertyNames));
}
}
[Theory]
[InlineData(typeof(Product), nameof(Product.Tags), "'[]'::jsonb")]
[InlineData(typeof(Product), nameof(Product.DetailImages), "'[]'::jsonb")]
[InlineData(typeof(Order), nameof(Order.RawPayload), "'{}'::jsonb")]
[InlineData(typeof(OrderItem), nameof(OrderItem.Metadata), "'{}'::jsonb")]
[InlineData(typeof(Payment), nameof(Payment.RawPayload), "'{}'::jsonb")]
[InlineData(typeof(PaymentEvent), nameof(PaymentEvent.Payload), "'{}'::jsonb")]
[InlineData(typeof(Entitlement), nameof(Entitlement.Metadata), "'{}'::jsonb")]
[InlineData(typeof(TenantPaymentAccount), nameof(TenantPaymentAccount.ConfigPublic), "'{}'::jsonb")]
[InlineData(typeof(TenantSubscription), nameof(TenantSubscription.Metadata), "'{}'::jsonb")]
[InlineData(typeof(TenantUsageRecord), nameof(TenantUsageRecord.Metadata), "'{}'::jsonb")]
public void Commerce_json_properties_are_mapped_to_jsonb(
Type entityType,
string propertyName,
string expectedDefaultValueSql)
{
using var context = new TikuDbContext(Options);
var property = context.Model.FindEntityType(entityType)!
.FindProperty(propertyName)!;
Assert.Equal("jsonb", property.GetColumnType());
Assert.Equal(expectedDefaultValueSql, property.GetDefaultValueSql());
Assert.Equal(typeof(System.Text.Json.JsonElement), property.ClrType);
}
[Fact]
public void Commerce_tables_have_expected_unique_indexes_and_money_types()
{
using var context = new TikuDbContext(Options);
AssertHasUniqueIndex<Order>(nameof(Order.TenantId), nameof(Order.OrderNo));
AssertHasUniqueIndex<ActivationCode>(nameof(ActivationCode.TenantId), nameof(ActivationCode.Code));
AssertHasUniqueIndex<TenantPaymentAccount>(
nameof(TenantPaymentAccount.TenantId),
nameof(TenantPaymentAccount.Provider));
var amount = context.Model.FindEntityType(typeof(Order))!
.FindProperty(nameof(Order.AmountCents))!;
Assert.Equal(typeof(int), amount.ClrType);
void AssertHasUniqueIndex<TEntity>(params string[] propertyNames)
{
var indexes = context.Model.FindEntityType(typeof(TEntity))!.GetIndexes();
Assert.Contains(
indexes,
index => index.IsUnique
&& index.Properties
.Select(property => property.Name)
.SequenceEqual(propertyNames));
}
}
}