feat(sms): 新增节点短信提醒(审核未通过/被租用需辅助/上架未成交)

This commit is contained in:
yml2213
2026-10-14 14:57:52 +08:00
parent efa0aa4ffd
commit 93e102b7c0
38 changed files with 3228 additions and 70 deletions
@@ -9,6 +9,7 @@ import (
"hfb_sys/backend/internal/listingstatus"
"hfb_sys/backend/internal/model"
"hfb_sys/backend/internal/modules/notification"
smsnode "hfb_sys/backend/internal/modules/sms"
"gorm.io/datatypes"
"gorm.io/gorm"
@@ -389,6 +390,16 @@ func (r *Repository) Reject(ctx context.Context, listingID uint64, req ReviewReq
}); err != nil {
return err
}
// 节点短信:审核未通过提醒号主修改后重新上架。只入队,由后台任务异步发送。
if _, err := smsnode.Enqueue(tx, smsnode.Entry{
UserID: listing.OwnerID,
Node: smsnode.NodeListingReviewRejected,
BizType: "listing",
BizID: listingID,
DistributionSiteID: listing.DistributionSiteID,
}); err != nil {
return err
}
dto = toDTO(*account, *listing)
return nil
})
@@ -0,0 +1,79 @@
package listing
import (
"context"
"testing"
"hfb_sys/backend/internal/database"
"hfb_sys/backend/internal/model"
smsnode "hfb_sys/backend/internal/modules/sms"
)
// 审核未通过时必须给号主入队一条短信(只落库,发送交给后台任务)。
func TestRejectEnqueuesOwnerSms(t *testing.T) {
db := database.NewTestDB()
if err := database.AutoMigrateIfMissing(db, &model.SmsMessage{}); err != nil {
t.Fatalf("AutoMigrate() error = %v", err)
}
repo := NewRepository(db, nil)
owner := model.User{Phone: "13700009001", Nickname: "号主"}
if err := db.Create(&owner).Error; err != nil {
t.Fatalf("创建号主失败: %v", err)
}
siteID := uint64(31)
account := model.GameAccount{
OwnerID: owner.ID,
Status: "draft",
ServerRegion: "国服",
LoginPlatform: "steam",
Title: "审核未通过账号",
}
if err := db.Create(&account).Error; err != nil {
t.Fatalf("创建账号失败: %v", err)
}
listing := model.RentalListing{
ListingNo: "LST-REJECT-SMS-001",
AccountID: account.ID,
OwnerID: owner.ID,
Status: "pending_review",
ReviewStatus: "pending",
DistributionSiteID: &siteID,
}
if err := db.Create(&listing).Error; err != nil {
t.Fatalf("创建商品失败: %v", err)
}
if _, err := repo.Reject(context.Background(), listing.ID, ReviewRequest{Reason: "截图不清晰"}); err != nil {
t.Fatalf("Reject() error = %v", err)
}
var row model.SmsMessage
if err := db.Where("node = ? AND biz_type = ? AND biz_id = ?",
smsnode.NodeListingReviewRejected, "listing", listing.ID).First(&row).Error; err != nil {
t.Fatalf("应给号主入队审核未通过短信, 查询失败: %v", err)
}
if row.UserID != owner.ID || row.Phone != owner.Phone {
t.Fatalf("收件人 = %d/%s, want %d/%s", row.UserID, row.Phone, owner.ID, owner.Phone)
}
if row.Status != model.SmsStatusPending {
t.Fatalf("status = %q, want %q", row.Status, model.SmsStatusPending)
}
if row.DistributionSiteID == nil || *row.DistributionSiteID != siteID {
t.Fatalf("distribution_site_id = %v, want %d", row.DistributionSiteID, siteID)
}
// 后台重复点「拒绝」不应重复入队。
if _, err := repo.Reject(context.Background(), listing.ID, ReviewRequest{Reason: "截图不清晰"}); err != nil {
t.Fatalf("重复 Reject() error = %v", err)
}
var count int64
if err := db.Model(&model.SmsMessage{}).
Where("node = ? AND biz_id = ?", smsnode.NodeListingReviewRejected, listing.ID).
Count(&count).Error; err != nil {
t.Fatalf("统计失败: %v", err)
}
if count != 1 {
t.Fatalf("短信记录数 = %d, want 1(同一账号只发一次)", count)
}
}