113 lines
4.3 KiB
C#
113 lines
4.3 KiB
C#
using System.ComponentModel.DataAnnotations;
|
|
using MAX.Framework.Commons;
|
|
using Store.Users.Entities;
|
|
|
|
namespace Store.Users.Tests;
|
|
|
|
public sealed class UserRecordTests
|
|
{
|
|
private static readonly DateTime Time = new(2025, 1, 15, 12, 0, 0);
|
|
|
|
[Fact]
|
|
public async Task PointsQuery_AppliesAccountOperationShopAndInclusiveTimeRange()
|
|
{
|
|
using var context = new UserTestContext();
|
|
await context.Db.Insert(new[]
|
|
{
|
|
Points("main", "充值", "shop-1", Time),
|
|
Points("main", "充值", "shop-2", Time),
|
|
Points("main", "消费", "shop-1", Time),
|
|
Points("main", "充值", "shop-1", Time.AddSeconds(-1)),
|
|
Points("other", "充值", "shop-1", Time)
|
|
}).ExecuteAffrowsAsync();
|
|
var page = await context.Users.Points("main", new()
|
|
{
|
|
Operation = "充值", ShopId = "shop-1", StartTime = Time, EndTime = Time
|
|
}, default);
|
|
var record = Assert.Single(page.Items);
|
|
Assert.Equal(1, page.Total);
|
|
Assert.Equal("main", record.UserName);
|
|
Assert.Equal(Time, record.AddTime);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task PointsQuery_PaginatesWithStableDescendingIdOrder()
|
|
{
|
|
using var context = new UserTestContext();
|
|
await context.Db.Insert(new[]
|
|
{
|
|
Points("main", "充值", "shop-1", Time),
|
|
Points("main", "充值", "shop-2", Time),
|
|
Points("main", "充值", "shop-3", Time)
|
|
}).ExecuteAffrowsAsync();
|
|
var page = await context.Users.Points("main", new() { Page = 2, PageSize = 1 }, default);
|
|
Assert.Equal(3, page.Total);
|
|
Assert.Equal("shop-2", Assert.Single(page.Items).ShopId);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task BalanceQuery_FiltersTypeOrderAndTime_AndExcludesDeletedRecords()
|
|
{
|
|
using var context = new UserTestContext();
|
|
await context.Db.Insert(new[]
|
|
{
|
|
Payment("main", 1, "order", Time),
|
|
Payment("main", 0, "order", Time),
|
|
Payment("main", 1, "different", Time),
|
|
Payment("main", 1, "order", Time.AddSeconds(1)),
|
|
Payment("other", 1, "order", Time),
|
|
Payment("main", 1, "order", Time, deleted: true)
|
|
}).ExecuteAffrowsAsync();
|
|
var page = await context.Users.Balance("main", new()
|
|
{
|
|
PaymentType = 1, OrderId = "order", StartTime = Time, EndTime = Time
|
|
}, default);
|
|
var record = Assert.Single(page.Items);
|
|
Assert.Equal(1, page.Total);
|
|
Assert.Equal("main", record.UserName);
|
|
Assert.Equal(0, record.IsDeleted);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(true)]
|
|
[InlineData(false)]
|
|
public async Task OrdinaryUser_CannotQuerySomeoneElsesFundsHistory(bool points)
|
|
{
|
|
using var context = new UserTestContext();
|
|
context.CurrentUser.UserName = "main";
|
|
var error = await Assert.ThrowsAsync<AppException>(async () =>
|
|
{
|
|
if (points) await context.Users.Points("other", new(), default);
|
|
else await context.Users.Balance("other", new(), default);
|
|
});
|
|
Assert.Equal(403, error.Code);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(true)]
|
|
[InlineData(false)]
|
|
public async Task ReversedDateRange_IsRejected(bool points)
|
|
{
|
|
using var context = new UserTestContext();
|
|
await Assert.ThrowsAsync<ValidationException>(async () =>
|
|
{
|
|
var request = new Store.Users.Contracts.Dtos.UserRecordSearchRequest { StartTime = Time, EndTime = Time.AddSeconds(-1) };
|
|
if (points) await context.Users.Points("main", request, default);
|
|
else await context.Users.Balance("main", request, default);
|
|
});
|
|
}
|
|
|
|
private static UserPointsRecordEntity Points(string user, string operation, string shop, DateTime time) => new()
|
|
{
|
|
UserName = user, UserNick = user, OptionType = operation, OperatorType = "管理员", OperatorName = "admin",
|
|
DeltaPoints = 10m, NewPoints = 10m, ShopId = shop, AddTime = time
|
|
};
|
|
|
|
private static UserPaymentRecordEntity Payment(string user, int type, string order, DateTime time, bool deleted = false) => new()
|
|
{
|
|
UserName = user, Type = type, Amount = 10m, Balance = 10m, OrderId = order, CreateTime = time,
|
|
CreateBy = "admin", UpdateBy = "", PlatformCode = "", Remark = "", CounterpartyAccountName = "",
|
|
RefundFlowNo = "", IsDeleted = deleted ? 1 : 0
|
|
};
|
|
}
|