forked from gongxuegit/tiku-backend.net
feat: add tenant points and coupon operations
This commit is contained in:
@@ -17,6 +17,10 @@ public sealed class TenantCommerceQueryDto
|
||||
|
||||
[Range(1, 200)]
|
||||
public int? Limit { get; set; }
|
||||
|
||||
public Guid? UserId { get; set; }
|
||||
|
||||
public Guid? RegionId { get; set; }
|
||||
}
|
||||
|
||||
public sealed class UpsertPaymentAccountDto
|
||||
@@ -134,3 +138,162 @@ public sealed class RedeemActivationCodeDto
|
||||
return new RedeemActivationCodeCommand(Code, UserId, RegionId);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class UpsertPointTaskDto
|
||||
{
|
||||
public Guid? Id { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(100)]
|
||||
public string TaskKey { get; set; } = string.Empty;
|
||||
|
||||
[Required]
|
||||
[StringLength(200)]
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(1000)]
|
||||
public string? Description { get; set; }
|
||||
|
||||
public PointActivityTaskType TaskType { get; set; } = PointActivityTaskType.Manual;
|
||||
public PointActivityTaskStatus Status { get; set; } = PointActivityTaskStatus.Active;
|
||||
|
||||
[Range(1, int.MaxValue)]
|
||||
public int Points { get; set; }
|
||||
|
||||
[Range(1, 1000)]
|
||||
public int MaxClaimsPerUser { get; set; } = 1;
|
||||
|
||||
public DateTimeOffset? StartsAt { get; set; }
|
||||
public DateTimeOffset? EndsAt { get; set; }
|
||||
public int SortOrder { get; set; }
|
||||
public JsonElement Rules { get; set; } = JsonDefaults.Object();
|
||||
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
|
||||
|
||||
public UpsertPointTaskCommand ToCommand()
|
||||
{
|
||||
return new UpsertPointTaskCommand(
|
||||
Id,
|
||||
TaskKey,
|
||||
Title,
|
||||
Description,
|
||||
TaskType,
|
||||
Status,
|
||||
Points,
|
||||
MaxClaimsPerUser,
|
||||
StartsAt,
|
||||
EndsAt,
|
||||
SortOrder,
|
||||
Rules,
|
||||
Metadata);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class UpsertPointExchangeItemDto
|
||||
{
|
||||
public Guid? Id { get; set; }
|
||||
public Guid? RegionId { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(100)]
|
||||
public string ItemKey { get; set; } = string.Empty;
|
||||
|
||||
[Required]
|
||||
[StringLength(200)]
|
||||
public string Name { get; set; } = string.Empty;
|
||||
|
||||
[StringLength(1000)]
|
||||
public string? Description { get; set; }
|
||||
|
||||
public PointExchangeItemType ItemType { get; set; } = PointExchangeItemType.Entitlement;
|
||||
public PointExchangeItemStatus Status { get; set; } = PointExchangeItemStatus.Active;
|
||||
|
||||
[Range(1, int.MaxValue)]
|
||||
public int PointsCost { get; set; }
|
||||
|
||||
[Range(0, int.MaxValue)]
|
||||
public int? Stock { get; set; }
|
||||
|
||||
[Range(0, 3650)]
|
||||
public int? Days { get; set; }
|
||||
|
||||
public int SortOrder { get; set; }
|
||||
public DateTimeOffset? StartsAt { get; set; }
|
||||
public DateTimeOffset? EndsAt { get; set; }
|
||||
public JsonElement FulfillmentPayload { get; set; } = JsonDefaults.Object();
|
||||
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
|
||||
|
||||
public UpsertPointExchangeItemCommand ToCommand()
|
||||
{
|
||||
return new UpsertPointExchangeItemCommand(
|
||||
Id,
|
||||
RegionId,
|
||||
ItemKey,
|
||||
Name,
|
||||
Description,
|
||||
ItemType,
|
||||
Status,
|
||||
PointsCost,
|
||||
Stock,
|
||||
Days,
|
||||
SortOrder,
|
||||
StartsAt,
|
||||
EndsAt,
|
||||
FulfillmentPayload,
|
||||
Metadata);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class UpdatePointExchangeOrderStatusDto
|
||||
{
|
||||
[Required]
|
||||
public Guid OrderId { get; set; }
|
||||
|
||||
public PointExchangeOrderStatus Status { get; set; }
|
||||
|
||||
public UpdatePointExchangeOrderStatusCommand ToCommand()
|
||||
{
|
||||
return new UpdatePointExchangeOrderStatusCommand(OrderId, Status);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class UpsertTenantCouponDto
|
||||
{
|
||||
public Guid? Id { get; set; }
|
||||
|
||||
[Required]
|
||||
[StringLength(100)]
|
||||
public string Code { get; set; } = string.Empty;
|
||||
|
||||
public Guid? PlanId { get; set; }
|
||||
public DiscountType DiscountType { get; set; } = DiscountType.Fixed;
|
||||
|
||||
[Range(typeof(decimal), "0.01", "999999")]
|
||||
public decimal DiscountValue { get; set; }
|
||||
|
||||
public DateTimeOffset? ValidFrom { get; set; }
|
||||
public DateTimeOffset? ValidTo { get; set; }
|
||||
|
||||
[Range(1, int.MaxValue)]
|
||||
public int? MaxUses { get; set; }
|
||||
|
||||
[StringLength(50)]
|
||||
public string? Source { get; set; }
|
||||
|
||||
[StringLength(1000)]
|
||||
public string? Remark { get; set; }
|
||||
|
||||
public UpsertCouponCommand ToCommand()
|
||||
{
|
||||
return new UpsertCouponCommand(
|
||||
Id,
|
||||
Code,
|
||||
PlanId,
|
||||
DiscountType,
|
||||
DiscountValue,
|
||||
ValidFrom,
|
||||
ValidTo,
|
||||
MaxUses,
|
||||
Source,
|
||||
Remark);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,6 +119,149 @@ public sealed class TenantCommerceController(
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpGet("point-activity-tasks")]
|
||||
[EndpointSummary("查询积分活动任务")]
|
||||
[ProducesResponseType<TenantPointTaskList>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<TenantPointTaskList>> PointTasks(
|
||||
[FromQuery] TenantCommerceQueryDto query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await commerceAdminService.GetPointTasksAsync(
|
||||
ResolveActor(),
|
||||
ToPointQuery(query),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPut("point-activity-tasks")]
|
||||
[EndpointSummary("新增或更新积分活动任务")]
|
||||
[ProducesResponseType<object>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<object>> UpsertPointTask(
|
||||
UpsertPointTaskDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await commerceAdminService.UpsertPointTaskAsync(
|
||||
ResolveActor(),
|
||||
request.ToCommand(),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpGet("point-activity-claims")]
|
||||
[EndpointSummary("查询积分任务领取记录")]
|
||||
[ProducesResponseType<TenantPointClaimList>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<TenantPointClaimList>> PointClaims(
|
||||
[FromQuery] TenantCommerceQueryDto query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await commerceAdminService.GetPointClaimsAsync(
|
||||
ResolveActor(),
|
||||
ToPointQuery(query),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpGet("point-exchange-items")]
|
||||
[EndpointSummary("查询积分兑换项")]
|
||||
[ProducesResponseType<TenantPointExchangeItemList>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<TenantPointExchangeItemList>> PointExchangeItems(
|
||||
[FromQuery] TenantCommerceQueryDto query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await commerceAdminService.GetPointExchangeItemsAsync(
|
||||
ResolveActor(),
|
||||
ToPointQuery(query),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPut("point-exchange-items")]
|
||||
[EndpointSummary("新增或更新积分兑换项")]
|
||||
[ProducesResponseType<object>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<object>> UpsertPointExchangeItem(
|
||||
UpsertPointExchangeItemDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await commerceAdminService.UpsertPointExchangeItemAsync(
|
||||
ResolveActor(),
|
||||
request.ToCommand(),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpGet("point-exchange-orders")]
|
||||
[EndpointSummary("查询积分兑换订单")]
|
||||
[ProducesResponseType<TenantPointExchangeOrderList>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<TenantPointExchangeOrderList>> PointExchangeOrders(
|
||||
[FromQuery] TenantCommerceQueryDto query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await commerceAdminService.GetPointExchangeOrdersAsync(
|
||||
ResolveActor(),
|
||||
ToPointQuery(query),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPost("point-exchange-orders/status")]
|
||||
[EndpointSummary("更新积分兑换订单状态")]
|
||||
[ProducesResponseType<object>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<object>> UpdatePointExchangeOrderStatus(
|
||||
UpdatePointExchangeOrderStatusDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await commerceAdminService.UpdatePointExchangeOrderStatusAsync(
|
||||
ResolveActor(),
|
||||
request.ToCommand(),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpGet("coupons")]
|
||||
[EndpointSummary("查询租户优惠券")]
|
||||
[ProducesResponseType<TenantCouponList>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<TenantCouponList>> Coupons(
|
||||
[FromQuery] TenantCommerceQueryDto query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await commerceAdminService.GetCouponsAsync(
|
||||
ResolveActor(),
|
||||
ToQuery(query),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpPut("coupons")]
|
||||
[EndpointSummary("新增或更新租户优惠券")]
|
||||
[ProducesResponseType<object>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<object>> UpsertCoupon(
|
||||
UpsertTenantCouponDto request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await commerceAdminService.UpsertCouponAsync(
|
||||
ResolveActor(),
|
||||
request.ToCommand(),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpGet("coupons/redemptions")]
|
||||
[EndpointSummary("查询优惠券领取和核销记录")]
|
||||
[ProducesResponseType<TenantCouponRedemptionList>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<TenantCouponRedemptionList>> CouponRedemptions(
|
||||
[FromQuery] TenantCommerceQueryDto query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await commerceAdminService.GetCouponRedemptionsAsync(
|
||||
ResolveActor(),
|
||||
ToQuery(query),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
[HttpGet("coupons/report")]
|
||||
[EndpointSummary("查询优惠券基础报表")]
|
||||
[ProducesResponseType<TenantCouponReport>(StatusCodes.Status200OK)]
|
||||
public async Task<ActionResult<TenantCouponReport>> CouponReport(
|
||||
[FromQuery] TenantCommerceQueryDto query,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
return Ok(await commerceAdminService.GetCouponReportAsync(
|
||||
ResolveActor(),
|
||||
ToQuery(query),
|
||||
cancellationToken));
|
||||
}
|
||||
|
||||
private CommerceAdminActor ResolveActor()
|
||||
{
|
||||
if (currentTenant.TenantId is null || currentUser.UserId is null)
|
||||
@@ -133,4 +276,9 @@ public sealed class TenantCommerceController(
|
||||
{
|
||||
return new CommerceAdminQuery(query.Provider, query.Status, query.Limit);
|
||||
}
|
||||
|
||||
private static TenantPointQuery ToPointQuery(TenantCommerceQueryDto query)
|
||||
{
|
||||
return new TenantPointQuery(query.Status, query.Limit, query.UserId, query.RegionId);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user