docs: reorganize documentation structure

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
sam 2026-02-15 10:32:23 +08:00
parent c3ae2b618c
commit 087948a8e1
4 changed files with 279 additions and 25 deletions

View File

@ -1,25 +0,0 @@
using FastEndpoints;
using FastEndpoints.Swagger;
using Microsoft.AspNetCore.Authorization;
using NetCorePal.Extensions.Dto;
namespace Fengling.Member.Web.Endpoints;
/// <summary>
/// Hello
/// </summary>
public class HelloEndpoint : EndpointWithoutRequest<ResponseData<string>>
{
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);
}
}

View File

@ -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<ArgumentException>()
.WithMessage("*会员ID必须大于0*");
}
[Fact]
public void Create_WithInvalidTenantId_ShouldThrowException()
{
var action = () => PointsAccount.Create(1, 0);
action.Should().Throw<ArgumentException>()
.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<ArgumentException>()
.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);
}
}

View File

@ -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();
}
}

View File

@ -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();
}
}