区分线下提号账号来源

This commit is contained in:
yml2213
2026-07-27 11:13:31 +08:00
parent 8af7333969
commit 66af387b4e
11 changed files with 483 additions and 36 deletions
+64 -9
View File
@@ -67,6 +67,10 @@ func (r *Repository) Create(ctx context.Context, req CreateRequest, adminID uint
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&account, listing.AccountID).Error; err != nil {
return err
}
accountSource, sourceChannel, err := resolvePickupAccountSource(tx, listing.ID)
if err != nil {
return err
}
priceSnapshot := buildPickupPriceSnapshot(listing, account)
accountSnapshot, err := makePickupAccountSnapshot(account, listing)
if err != nil {
@@ -85,6 +89,8 @@ func (r *Repository) Create(ctx context.Context, req CreateRequest, adminID uint
AdminID: adminID,
Platform: strings.TrimSpace(req.Platform),
ShopName: strings.TrimSpace(req.ShopName),
AccountSource: accountSource,
SourceChannel: sourceChannel,
ListingPriceCent: priceSnapshot.ListingPriceCent,
OwnerPriceCent: priceSnapshot.OwnerPriceCent,
WebsiteProfitCent: priceSnapshot.WebsiteProfitCent,
@@ -143,11 +149,13 @@ func (r *Repository) Create(ctx context.Context, req CreateRequest, adminID uint
BizID: &bid,
Meta: meta,
Detail: map[string]any{
"pickup_no": pickupNo,
"listing_id": listing.ID,
"platform": pickup.Platform,
"shop_name": pickup.ShopName,
"profit_cent": pickup.ProfitAmountCent,
"pickup_no": pickupNo,
"listing_id": listing.ID,
"platform": pickup.Platform,
"shop_name": pickup.ShopName,
"account_source": pickup.AccountSource,
"source_channel": pickup.SourceChannel,
"profit_cent": pickup.ProfitAmountCent,
},
}); err != nil {
return err
@@ -422,6 +430,9 @@ func (r *Repository) ListAdmin(ctx context.Context, query AdminPickupQuery) (*Pa
if shopName := strings.TrimSpace(query.ShopName); shopName != "" {
db = db.Where("p.shop_name = ?", shopName)
}
if accountSource := strings.TrimSpace(query.AccountSource); accountSource != "" {
db = db.Where("p.account_source = ?", accountSource)
}
if kw := strings.TrimSpace(query.Keyword); kw != "" {
like := "%" + kw + "%"
db = db.Where("p.pickup_no LIKE ? OR l.listing_no LIKE ? OR a.title LIKE ?", like, like, like)
@@ -476,6 +487,7 @@ func (r *Repository) paginatePickups(db *gorm.DB, page, pageSize int, sellerView
item.ProfitAmountCent = 0
item.BuyerRatio = 0
item.ShopName = ""
item.SourceChannel = ""
}
items = append(items, item)
}
@@ -483,25 +495,41 @@ func (r *Repository) paginatePickups(db *gorm.DB, page, pageSize int, sellerView
}
// ListAvailableListings 可提号的 listing:已发布、已审核、未在交易中。
func (r *Repository) ListAvailableListings(ctx context.Context, keyword string, page, pageSize int) (*AvailableListingsResult, error) {
func (r *Repository) ListAvailableListings(ctx context.Context, query AvailableListingQuery) (*AvailableListingsResult, error) {
if r == nil || r.db == nil {
return nil, ErrDependencyUnavailable
}
latestUploads := r.db.WithContext(ctx).Table("listing_uploads").
Select("listing_id, MAX(id) AS upload_id").
Where("listing_id IS NOT NULL").
Group("listing_id")
db := r.db.WithContext(ctx).Table("rental_listings AS l").
Select("l.id, l.listing_no, l.account_id, l.owner_id, l.price_cent AS listing_price_cent, a.title AS account_title, a.server_region, a.login_platform, a.haf_coin_amount, a.asset_summary, owner.phone AS owner_phone").
Select(`l.id, l.listing_no, l.account_id, l.owner_id, l.price_cent AS listing_price_cent,
a.title AS account_title, a.server_region, a.login_platform, a.haf_coin_amount, a.asset_summary,
owner.phone AS owner_phone, l.handoff_mode, l.settlement_mode,
CASE WHEN lu.id IS NULL THEN 0 ELSE 1 END AS is_external_upload,
COALESCE(lu.source_channel, '') AS source_channel`).
Joins("JOIN game_accounts AS a ON a.id = l.account_id").
Joins("JOIN users AS owner ON owner.id = l.owner_id").
Joins("LEFT JOIN (?) AS latest_upload ON latest_upload.listing_id = l.id", latestUploads).
Joins("LEFT JOIN listing_uploads AS lu ON lu.id = latest_upload.upload_id").
Where("l.status = ? AND l.review_status = ? AND l.in_transaction = ?", "published", "approved", false)
if kw := strings.TrimSpace(keyword); kw != "" {
if kw := strings.TrimSpace(query.Keyword); kw != "" {
like := "%" + kw + "%"
db = db.Where("l.listing_no LIKE ? OR a.title LIKE ?", like, like)
}
switch strings.TrimSpace(query.SourceType) {
case ListingSourceExternal:
db = db.Where("lu.id IS NOT NULL")
case ListingSourceInternal:
db = db.Where("lu.id IS NULL")
}
var total int64
if err := db.Count(&total).Error; err != nil {
return nil, err
}
page, pageSize = normalizePaging(page, pageSize)
page, pageSize := normalizePaging(query.Page, query.PageSize)
var rows []availableListingRow
if err := db.Order("l.id DESC").Offset((page - 1) * pageSize).Limit(pageSize).Scan(&rows).Error; err != nil {
return nil, err
@@ -545,6 +573,8 @@ func (row pickupRow) toDTO() PickupDTO {
AdminID: row.AdminID,
Platform: row.Platform,
ShopName: row.ShopName,
AccountSource: row.AccountSource,
SourceChannel: row.SourceChannel,
ListingPriceCent: row.ListingPriceCent,
OwnerPriceCent: row.OwnerPriceCent,
WebsiteProfitCent: row.WebsiteProfitCent,
@@ -574,6 +604,10 @@ type availableListingRow struct {
ListingPriceCent int64
HafCoinAmount int64
AssetSummary datatypes.JSON
IsExternalUpload bool
SourceChannel string
HandoffMode string
SettlementMode string
}
func (row availableListingRow) toDTO() AvailableListingDTO {
@@ -581,6 +615,10 @@ func (row availableListingRow) toDTO() AvailableListingDTO {
model.RentalListing{PriceCent: row.ListingPriceCent},
model.GameAccount{HafCoinAmount: row.HafCoinAmount, AssetSummary: row.AssetSummary},
)
accountSource := AccountSourceInternal
if row.IsExternalUpload {
accountSource = AccountSourceExternalPlatformManaged
}
return AvailableListingDTO{
ID: row.ID,
ListingNo: row.ListingNo,
@@ -598,9 +636,26 @@ func (row availableListingRow) toDTO() AvailableListingDTO {
WebsiteProfitCent: snapshot.WebsiteProfitCent,
SellerRatio: snapshot.SellerRatio,
BuyerRatio: snapshot.BuyerRatio,
AccountSource: accountSource,
IsExternalUpload: row.IsExternalUpload,
SourceChannel: row.SourceChannel,
HandoffMode: row.HandoffMode,
SettlementMode: row.SettlementMode,
}
}
func resolvePickupAccountSource(tx *gorm.DB, listingID uint64) (string, string, error) {
var upload model.ListingUpload
err := tx.Where("listing_id = ?", listingID).Order("id DESC").First(&upload).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return AccountSourceInternal, "", nil
}
if err != nil {
return "", "", err
}
return AccountSourceExternalPlatformManaged, strings.TrimSpace(upload.SourceChannel), nil
}
func makePickupAccountSnapshot(account model.GameAccount, listing model.RentalListing) (datatypes.JSON, error) {
payload := map[string]any{
"listing_id": listing.ID,