From 087948a8e186d656c4a205cca205ef832b3cd896 Mon Sep 17 00:00:00 2001 From: sam Date: Sun, 15 Feb 2026 10:32:23 +0800 Subject: [PATCH] docs: reorganize documentation structure Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus --- .../Endpoints/HelloEndpoint.cs | 25 ---- .../PointsModel/PointsAccountTests.cs | 138 ++++++++++++++++++ .../PointsRuleConditionTests.cs | 48 ++++++ .../PointsRuleModel/PointsRuleTests.cs | 93 ++++++++++++ 4 files changed, 279 insertions(+), 25 deletions(-) delete mode 100644 src/Fengling.Member.Web/Endpoints/HelloEndpoint.cs create mode 100644 test/Fengling.Member.Domain.Tests/Aggregates/PointsModel/PointsAccountTests.cs create mode 100644 test/Fengling.Member.Domain.Tests/Aggregates/PointsRuleModel/PointsRuleConditionTests.cs create mode 100644 test/Fengling.Member.Domain.Tests/Aggregates/PointsRuleModel/PointsRuleTests.cs diff --git a/src/Fengling.Member.Web/Endpoints/HelloEndpoint.cs b/src/Fengling.Member.Web/Endpoints/HelloEndpoint.cs deleted file mode 100644 index 26ec64a..0000000 --- a/src/Fengling.Member.Web/Endpoints/HelloEndpoint.cs +++ /dev/null @@ -1,25 +0,0 @@ -using FastEndpoints; -using FastEndpoints.Swagger; -using Microsoft.AspNetCore.Authorization; -using NetCorePal.Extensions.Dto; - -namespace Fengling.Member.Web.Endpoints; - -/// -/// Hello -/// -public class HelloEndpoint : EndpointWithoutRequest> -{ - public override void Configure() - { - Tags("Hello"); - Description(b => b.AutoTagOverride("Hello")); - Get("/api/hello"); - AllowAnonymous(); - } - - public override Task HandleAsync(CancellationToken ct) - { - return Send.OkAsync("hello".AsResponseData(), cancellation: ct); - } -} diff --git a/test/Fengling.Member.Domain.Tests/Aggregates/PointsModel/PointsAccountTests.cs b/test/Fengling.Member.Domain.Tests/Aggregates/PointsModel/PointsAccountTests.cs new file mode 100644 index 0000000..a400f6e --- /dev/null +++ b/test/Fengling.Member.Domain.Tests/Aggregates/PointsModel/PointsAccountTests.cs @@ -0,0 +1,138 @@ +using FluentAssertions; +using Fengling.Member.Domain.Aggregates.PointsModel; + +namespace Fengling.Member.Domain.Tests.Aggregates.PointsModel; + +public class PointsAccountTests +{ + [Fact] + public void Create_WithValidIds_ShouldCreateAccount() + { + var account = PointsAccount.Create(1, 100); + + account.MemberId.Should().Be(1); + account.TenantId.Should().Be(100); + account.TotalPoints.Should().Be(0); + account.FrozenPoints.Should().Be(0); + account.AvailablePoints.Should().Be(0); + } + + [Fact] + public void Create_WithInvalidMemberId_ShouldThrowException() + { + var action = () => PointsAccount.Create(0, 100); + + action.Should().Throw() + .WithMessage("*会员ID必须大于0*"); + } + + [Fact] + public void Create_WithInvalidTenantId_ShouldThrowException() + { + var action = () => PointsAccount.Create(1, 0); + + action.Should().Throw() + .WithMessage("*租户ID必须大于0*"); + } + + [Fact] + public void AddPoints_ShouldIncreaseTotalPoints() + { + var account = PointsAccount.Create(1, 100); + + account.AddPoints(100, "REGISTER", "source_001", "注册赠送"); + + account.TotalPoints.Should().Be(100); + account.AvailablePoints.Should().Be(100); + account.Transactions.Should().HaveCount(1); + } + + [Fact] + public void AddPoints_WithInvalidPoints_ShouldThrowException() + { + var account = PointsAccount.Create(1, 100); + + var action = () => account.AddPoints(0, "REGISTER", "source_001"); + + action.Should().Throw() + .WithMessage("*积分必须大于0*"); + } + + [Fact] + public void DeductPoints_ShouldDecreaseTotalPoints() + { + var account = PointsAccount.Create(1, 100); + account.AddPoints(100, "REGISTER", "source_001"); + + var result = account.DeductPoints(30, "EXCHANGE", "order_001"); + + result.Should().BeTrue(); + account.TotalPoints.Should().Be(70); + account.AvailablePoints.Should().Be(70); + } + + [Fact] + public void DeductPoints_WithInsufficientPoints_ShouldReturnFalse() + { + var account = PointsAccount.Create(1, 100); + account.AddPoints(50, "REGISTER", "source_001"); + + var result = account.DeductPoints(100, "EXCHANGE", "order_001"); + + result.Should().BeFalse(); + account.TotalPoints.Should().Be(50); + } + + [Fact] + public void FreezePoints_ShouldIncreaseFrozenPoints() + { + var account = PointsAccount.Create(1, 100); + account.AddPoints(100, "REGISTER", "source_001"); + + var result = account.FreezePoints(30); + + result.Should().BeTrue(); + account.FrozenPoints.Should().Be(30); + account.AvailablePoints.Should().Be(70); + } + + [Fact] + public void FreezePoints_WithInsufficientPoints_ShouldReturnFalse() + { + var account = PointsAccount.Create(1, 100); + account.AddPoints(50, "REGISTER", "source_001"); + + var result = account.FreezePoints(100); + + result.Should().BeFalse(); + account.FrozenPoints.Should().Be(0); + } + + [Fact] + public void UnfreezePoints_ShouldDecreaseFrozenPoints() + { + var account = PointsAccount.Create(1, 100); + account.AddPoints(100, "REGISTER", "source_001"); + account.FreezePoints(50); + + var result = account.UnfreezePoints(30); + + result.Should().BeTrue(); + account.FrozenPoints.Should().Be(20); + account.AvailablePoints.Should().Be(80); + } + + [Fact] + public void UseFrozenPoints_ShouldDecreaseBothFrozenAndTotalPoints() + { + var account = PointsAccount.Create(1, 100); + account.AddPoints(100, "REGISTER", "source_001"); + account.FreezePoints(50); + + var result = account.UseFrozenPoints(30); + + result.Should().BeTrue(); + account.FrozenPoints.Should().Be(20); + account.TotalPoints.Should().Be(70); + } +} diff --git a/test/Fengling.Member.Domain.Tests/Aggregates/PointsRuleModel/PointsRuleConditionTests.cs b/test/Fengling.Member.Domain.Tests/Aggregates/PointsRuleModel/PointsRuleConditionTests.cs new file mode 100644 index 0000000..8d5e395 --- /dev/null +++ b/test/Fengling.Member.Domain.Tests/Aggregates/PointsRuleModel/PointsRuleConditionTests.cs @@ -0,0 +1,48 @@ +using FluentAssertions; +using Fengling.Member.Domain.Aggregates.PointsRuleModel; +using Fengling.Member.Domain.Aggregates.PointsRuleModel.Enums; + +namespace Fengling.Member.Domain.Tests.Aggregates.PointsRuleModel; + +public class PointsRuleConditionTests +{ + [Fact] + public void Create_ShouldInitializeWithCorrectValues() + { + var rule = PointsRule.Create( + "消费送积分", + "CONSUMPTION_POINTS", + RuleType.PriceWeighted, + 50, + 30); + + var condition = PointsRuleCondition.Create( + rule.Id, + DimensionType.Product, + "100", + ">="); + + condition.RuleId.Should().Be(rule.Id); + condition.DimensionType.Should().Be(DimensionType.Product); + condition.DimensionValue.Should().Be("100"); + condition.Operator.Should().Be(">="); + } + + [Fact] + public void Create_WithNullOperator_ShouldAllowNullOperator() + { + var rule = PointsRule.Create( + "注册送积分", + "REGISTER_POINTS", + RuleType.FixedValue, + 100, + 30); + + var condition = PointsRuleCondition.Create( + rule.Id, + DimensionType.Dealer, + "1"); + + condition.Operator.Should().BeNull(); + } +} diff --git a/test/Fengling.Member.Domain.Tests/Aggregates/PointsRuleModel/PointsRuleTests.cs b/test/Fengling.Member.Domain.Tests/Aggregates/PointsRuleModel/PointsRuleTests.cs new file mode 100644 index 0000000..eb02891 --- /dev/null +++ b/test/Fengling.Member.Domain.Tests/Aggregates/PointsRuleModel/PointsRuleTests.cs @@ -0,0 +1,93 @@ +using FluentAssertions; +using Fengling.Member.Domain.Aggregates.PointsRuleModel; +using Fengling.Member.Domain.Aggregates.PointsRuleModel.Enums; + +namespace Fengling.Member.Domain.Tests.Aggregates.PointsRuleModel; + +public class PointsRuleTests +{ + [Fact] + public void Create_ShouldInitializeWithDefaultValues() + { + var rule = PointsRule.Create( + "注册送积分", + "REGISTER_POINTS", + RuleType.FixedValue, + 100, + 30); + + rule.Name.Should().Be("注册送积分"); + rule.Code.Should().Be("REGISTER_POINTS"); + rule.RuleType.Should().Be(RuleType.FixedValue); + rule.BasePoints.Should().Be(100); + rule.ValidityDays.Should().Be(30); + rule.Priority.Should().Be(0); + rule.CalculationMode.Should().Be(CalculationMode.Synchronous); + rule.WeightFactor.Should().BeNull(); + rule.IsActive.Should().BeTrue(); + rule.Conditions.Should().BeEmpty(); + } + + [Fact] + public void Create_WithAllParameters_ShouldSetAllProperties() + { + var rule = PointsRule.Create( + "消费送积分", + "CONSUMPTION_POINTS", + RuleType.PriceWeighted, + 50, + 7, + 10, + CalculationMode.Asynchronous, + 1.5m); + + rule.Name.Should().Be("消费送积分"); + rule.Code.Should().Be("CONSUMPTION_POINTS"); + rule.RuleType.Should().Be(RuleType.PriceWeighted); + rule.BasePoints.Should().Be(50); + rule.ValidityDays.Should().Be(7); + rule.Priority.Should().Be(10); + rule.CalculationMode.Should().Be(CalculationMode.Asynchronous); + rule.WeightFactor.Should().Be(1.5m); + rule.IsActive.Should().BeTrue(); + } + + [Fact] + public void AddCondition_ShouldAddConditionToList() + { + var rule = PointsRule.Create( + "消费送积分", + "CONSUMPTION_POINTS", + RuleType.PriceWeighted, + 50, + 30); + + var condition = PointsRuleCondition.Create( + rule.Id, + DimensionType.Product, + "100", + "1"); + + rule.AddCondition(condition); + + rule.Conditions.Should().HaveCount(1); + rule.Conditions.First().Should().Be(condition); + } + + [Fact] + public void Deactivate_ShouldSetIsActiveToFalse() + { + var rule = PointsRule.Create( + "注册送积分", + "REGISTER_POINTS", + RuleType.FixedValue, + 100, + 30); + + rule.IsActive.Should().BeTrue(); + + rule.Deactivate(); + + rule.IsActive.Should().BeFalse(); + } +}