feat: 增加订单过滤功能,支持按内容ID、支付时间范围和支付金额范围筛选

This commit is contained in:
2025-12-18 16:46:40 +08:00
parent 3249e405ac
commit e268176af5
8 changed files with 418 additions and 37 deletions

View File

@@ -23,42 +23,74 @@ import (
"go.ipao.vip/gen/types"
)
// PurchaseOrderSnapshot 为“内容购买订单”的下单快照(用于历史展示与争议审计)。
type PurchaseOrderSnapshot struct {
ContentID int64 `json:"content_id"`
ContentTitle string `json:"content_title"`
ContentUserID int64 `json:"content_user_id"`
ContentVisibility consts.ContentVisibility `json:"content_visibility"`
PreviewSeconds int32 `json:"preview_seconds"`
PreviewDownloadable bool `json:"preview_downloadable"`
Currency consts.Currency `json:"currency"`
PriceAmount int64 `json:"price_amount"`
DiscountType consts.DiscountType `json:"discount_type"`
DiscountValue int64 `json:"discount_value"`
DiscountStartAt *time.Time `json:"discount_start_at,omitempty"`
DiscountEndAt *time.Time `json:"discount_end_at,omitempty"`
AmountOriginal int64 `json:"amount_original"`
AmountDiscount int64 `json:"amount_discount"`
AmountPaid int64 `json:"amount_paid"`
PurchaseAt time.Time `json:"purchase_at"`
PurchaseIdempotency string `json:"purchase_idempotency_key,omitempty"`
PurchasePricingNotes string `json:"purchase_pricing_notes,omitempty"`
// ContentID 内容ID。
ContentID int64 `json:"content_id"`
// ContentTitle 内容标题(下单时快照,避免事后改名影响历史订单展示)。
ContentTitle string `json:"content_title"`
// ContentUserID 内容作者用户ID用于审计与后续分成扩展
ContentUserID int64 `json:"content_user_id"`
// ContentVisibility 下单时的可见性快照。
ContentVisibility consts.ContentVisibility `json:"content_visibility"`
// PreviewSeconds 下单时的试看秒数快照。
PreviewSeconds int32 `json:"preview_seconds"`
// PreviewDownloadable 下单时的试看是否可下载快照(当前固定为 false
PreviewDownloadable bool `json:"preview_downloadable"`
// Currency 币种:当前固定 CNY金额单位为分
Currency consts.Currency `json:"currency"`
// PriceAmount 基础价格(分)。
PriceAmount int64 `json:"price_amount"`
// DiscountType 折扣类型none/percent/amount
DiscountType consts.DiscountType `json:"discount_type"`
// DiscountValue 折扣值percent=0-100amount=分)。
DiscountValue int64 `json:"discount_value"`
// DiscountStartAt 折扣开始时间(可选)。
DiscountStartAt *time.Time `json:"discount_start_at,omitempty"`
// DiscountEndAt 折扣结束时间(可选)。
DiscountEndAt *time.Time `json:"discount_end_at,omitempty"`
// AmountOriginal 原价金额(分)。
AmountOriginal int64 `json:"amount_original"`
// AmountDiscount 优惠金额(分)。
AmountDiscount int64 `json:"amount_discount"`
// AmountPaid 实付金额(分)。
AmountPaid int64 `json:"amount_paid"`
// PurchaseAt 下单时间(逻辑时间)。
PurchaseAt time.Time `json:"purchase_at"`
// PurchaseIdempotency 幂等键(可选)。
PurchaseIdempotency string `json:"purchase_idempotency_key,omitempty"`
// PurchasePricingNotes 价格计算补充说明(可选,便于排查争议)。
PurchasePricingNotes string `json:"purchase_pricing_notes,omitempty"`
}
// OrderItemSnapshot 为“订单明细”的内容快照。
type OrderItemSnapshot struct {
ContentID int64 `json:"content_id"`
ContentTitle string `json:"content_title"`
ContentUserID int64 `json:"content_user_id"`
AmountPaid int64 `json:"amount_paid"`
// ContentID 内容ID。
ContentID int64 `json:"content_id"`
// ContentTitle 内容标题快照。
ContentTitle string `json:"content_title"`
// ContentUserID 内容作者用户ID。
ContentUserID int64 `json:"content_user_id"`
// AmountPaid 该行实付金额(分)。
AmountPaid int64 `json:"amount_paid"`
}
// TopupOrderSnapshot 为“后台充值订单”的快照(用于审计与追责)。
type TopupOrderSnapshot struct {
OperatorUserID int64 `json:"operator_user_id"`
TargetUserID int64 `json:"target_user_id"`
Amount int64 `json:"amount"`
Currency consts.Currency `json:"currency"`
Reason string `json:"reason,omitempty"`
IdempotencyKey string `json:"idempotency_key,omitempty"`
TopupAt time.Time `json:"topup_at"`
// OperatorUserID 充值操作人用户ID租户管理员
OperatorUserID int64 `json:"operator_user_id"`
// TargetUserID 充值目标用户ID租户成员
TargetUserID int64 `json:"target_user_id"`
// Amount 充值金额(分)。
Amount int64 `json:"amount"`
// Currency 币种:当前固定 CNY金额单位为分
Currency consts.Currency `json:"currency"`
// Reason 充值原因(可选,强烈建议填写用于审计)。
Reason string `json:"reason,omitempty"`
// IdempotencyKey 幂等键(可选)。
IdempotencyKey string `json:"idempotency_key,omitempty"`
// TopupAt 充值时间(逻辑时间)。
TopupAt time.Time `json:"topup_at"`
}
// PurchaseContentParams 定义“租户内使用余额购买内容”的入参。
@@ -237,9 +269,10 @@ func (s *order) MyOrderPage(
}
logrus.WithFields(logrus.Fields{
"tenant_id": tenantID,
"user_id": userID,
"status": lo.FromPtr(filter.Status),
"tenant_id": tenantID,
"user_id": userID,
"status": lo.FromPtr(filter.Status),
"content_id": lo.FromPtr(filter.ContentID),
}).Info("services.order.me.page")
filter.Pagination.Format()
@@ -254,6 +287,18 @@ func (s *order) MyOrderPage(
if filter.Status != nil {
conds = append(conds, tbl.Status.Eq(*filter.Status))
}
if filter.PaidAtFrom != nil {
conds = append(conds, tbl.PaidAt.Gte(*filter.PaidAtFrom))
}
if filter.PaidAtTo != nil {
conds = append(conds, tbl.PaidAt.Lte(*filter.PaidAtTo))
}
if filter.ContentID != nil && *filter.ContentID > 0 {
oiTbl, _ := models.OrderItemQuery.QueryContext(ctx)
query = query.LeftJoin(oiTbl, oiTbl.OrderID.EqCol(tbl.ID))
conds = append(conds, oiTbl.ContentID.Eq(*filter.ContentID))
query = query.Group(tbl.ID)
}
items, total, err := query.Where(conds...).Order(tbl.ID.Desc()).FindByPage(int(filter.Offset()), int(filter.Limit))
if err != nil {
@@ -305,9 +350,10 @@ func (s *order) AdminOrderPage(
}
logrus.WithFields(logrus.Fields{
"tenant_id": tenantID,
"user_id": lo.FromPtr(filter.UserID),
"status": lo.FromPtr(filter.Status),
"tenant_id": tenantID,
"user_id": lo.FromPtr(filter.UserID),
"status": lo.FromPtr(filter.Status),
"content_id": lo.FromPtr(filter.ContentID),
}).Info("services.order.admin.page")
filter.Pagination.Format()
@@ -322,6 +368,24 @@ func (s *order) AdminOrderPage(
if filter.Status != nil {
conds = append(conds, tbl.Status.Eq(*filter.Status))
}
if filter.PaidAtFrom != nil {
conds = append(conds, tbl.PaidAt.Gte(*filter.PaidAtFrom))
}
if filter.PaidAtTo != nil {
conds = append(conds, tbl.PaidAt.Lte(*filter.PaidAtTo))
}
if filter.AmountPaidMin != nil {
conds = append(conds, tbl.AmountPaid.Gte(*filter.AmountPaidMin))
}
if filter.AmountPaidMax != nil {
conds = append(conds, tbl.AmountPaid.Lte(*filter.AmountPaidMax))
}
if filter.ContentID != nil && *filter.ContentID > 0 {
oiTbl, _ := models.OrderItemQuery.QueryContext(ctx)
query = query.LeftJoin(oiTbl, oiTbl.OrderID.EqCol(tbl.ID))
conds = append(conds, oiTbl.ContentID.Eq(*filter.ContentID))
query = query.Group(tbl.ID)
}
items, total, err := query.Where(conds...).Order(tbl.ID.Desc()).FindByPage(int(filter.Offset()), int(filter.Limit))
if err != nil {