220 lines
5.9 KiB
Go
220 lines
5.9 KiB
Go
package listing
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"hfb_sys/backend/internal/model"
|
|
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/clause"
|
|
)
|
|
|
|
func (r *Repository) ListAdmin(ctx context.Context, query AdminListQuery) (*AdminListResult, error) {
|
|
page := query.Page
|
|
if page <= 0 {
|
|
page = 1
|
|
}
|
|
pageSize := query.PageSize
|
|
if pageSize <= 0 {
|
|
pageSize = query.Limit
|
|
}
|
|
if pageSize <= 0 {
|
|
pageSize = 20
|
|
}
|
|
if pageSize > 100 {
|
|
pageSize = 100
|
|
}
|
|
|
|
if hasAdminAssetFilters(query) {
|
|
var rows []listingRow
|
|
err := r.applyAdminListFilters(r.baseQuery(ctx), query).
|
|
Order("l.id DESC").
|
|
Scan(&rows).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
items := filterAdminListings(rowsToDTO(rows), query)
|
|
total := int64(len(items))
|
|
start := (page - 1) * pageSize
|
|
if start < 0 {
|
|
start = 0
|
|
}
|
|
if start >= len(items) {
|
|
items = []ListingDTO{}
|
|
} else {
|
|
end := start + pageSize
|
|
if end > len(items) {
|
|
end = len(items)
|
|
}
|
|
items = items[start:end]
|
|
}
|
|
return &AdminListResult{
|
|
Items: items,
|
|
Total: total,
|
|
Page: page,
|
|
PageSize: pageSize,
|
|
}, nil
|
|
}
|
|
|
|
countDB := r.applyAdminListFilters(r.db.WithContext(ctx).Table("rental_listings AS l"), query)
|
|
var total int64
|
|
if err := countDB.Count(&total).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
db := r.applyAdminListFilters(r.baseQuery(ctx), query)
|
|
offset := (page - 1) * pageSize
|
|
if offset < 0 {
|
|
offset = 0
|
|
}
|
|
var rows []listingRow
|
|
err := db.Order("l.id DESC").Limit(pageSize).Offset(offset).Scan(&rows).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &AdminListResult{
|
|
Items: rowsToDTO(rows),
|
|
Total: total,
|
|
Page: page,
|
|
PageSize: pageSize,
|
|
}, nil
|
|
}
|
|
|
|
func (r *Repository) applyAdminListFilters(db *gorm.DB, query AdminListQuery) *gorm.DB {
|
|
if query.OwnerID > 0 {
|
|
db = db.Where("l.owner_id = ?", query.OwnerID)
|
|
}
|
|
if keyword := strings.TrimSpace(query.Keyword); keyword != "" {
|
|
like := "%" + keyword + "%"
|
|
if id, err := strconv.ParseUint(keyword, 10, 64); err == nil {
|
|
db = db.Where(
|
|
`(l.listing_no LIKE ? OR EXISTS (SELECT 1 FROM rental_orders AS o WHERE o.listing_id = l.id AND o.order_no LIKE ?) OR l.id = ? OR l.account_id = ? OR l.owner_id = ?)`,
|
|
like,
|
|
like,
|
|
id,
|
|
id,
|
|
id,
|
|
)
|
|
} else {
|
|
db = db.Where(
|
|
`(l.listing_no LIKE ? OR EXISTS (SELECT 1 FROM rental_orders AS o WHERE o.listing_id = l.id AND o.order_no LIKE ?))`,
|
|
like,
|
|
like,
|
|
)
|
|
}
|
|
}
|
|
if query.Status != "" {
|
|
db = db.Where("l.status = ?", query.Status)
|
|
}
|
|
if query.ReviewStatus != "" {
|
|
db = db.Where("l.review_status = ?", query.ReviewStatus)
|
|
}
|
|
return db
|
|
}
|
|
|
|
func (r *Repository) FindAdmin(ctx context.Context, listingID uint64) (*ListingDTO, error) {
|
|
return r.findDTO(ctx, "l.id = ?", listingID)
|
|
}
|
|
|
|
func (r *Repository) ListMine(ctx context.Context, ownerID uint64) ([]ListingDTO, error) {
|
|
var rows []listingRow
|
|
err := r.baseQuery(ctx).
|
|
Where("l.owner_id = ?", ownerID).
|
|
Order("l.id DESC").
|
|
Scan(&rows).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return sellerListings(rowsToDTO(rows)), nil
|
|
}
|
|
|
|
func (r *Repository) FindMine(ctx context.Context, ownerID uint64, id uint64) (*ListingDTO, error) {
|
|
dto, err := r.findDTO(ctx, "l.id = ? AND l.owner_id = ?", id, ownerID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
applySellerListingPrice(dto)
|
|
return dto, nil
|
|
}
|
|
|
|
func (r *Repository) findOwnedForUpdate(tx *gorm.DB, ownerID uint64, listingID uint64) (*model.RentalListing, *model.GameAccount, error) {
|
|
var listing model.RentalListing
|
|
if err := tx.Where("id = ? AND owner_id = ?", listingID, ownerID).First(&listing).Error; err != nil {
|
|
return nil, nil, err
|
|
}
|
|
var account model.GameAccount
|
|
if err := tx.Where("id = ? AND owner_id = ?", listing.AccountID, ownerID).First(&account).Error; err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return &listing, &account, nil
|
|
}
|
|
|
|
func (r *Repository) findDTO(ctx context.Context, where string, args ...any) (*ListingDTO, error) {
|
|
var row listingRow
|
|
err := r.baseQuery(ctx).
|
|
Where(where, args...).
|
|
First(&row).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
dto := row.toDTO()
|
|
return &dto, nil
|
|
}
|
|
|
|
func (r *Repository) baseQuery(ctx context.Context) *gorm.DB {
|
|
return r.db.WithContext(ctx).Table("rental_listings AS l").
|
|
Select(`l.*, a.title, a.description, a.game_name, a.server_region, a.login_platform, a.rank_level,
|
|
a.haf_coin_amount, a.asset_summary, a.screenshot_urls, COALESCE(u.phone, '') AS owner_phone, COALESCE(u.nickname, '') AS owner_nickname`).
|
|
Joins("JOIN game_accounts AS a ON a.id = l.account_id").
|
|
Joins("LEFT JOIN users AS u ON u.id = l.owner_id")
|
|
}
|
|
|
|
func (r *Repository) findForReviewUpdate(tx *gorm.DB, listingID uint64) (*model.RentalListing, *model.GameAccount, error) {
|
|
var listing model.RentalListing
|
|
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&listing, listingID).Error; err != nil {
|
|
return nil, nil, err
|
|
}
|
|
var account model.GameAccount
|
|
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&account, listing.AccountID).Error; err != nil {
|
|
return nil, nil, err
|
|
}
|
|
return &listing, &account, nil
|
|
}
|
|
|
|
func (r *Repository) nextListingNo(tx *gorm.DB, now time.Time) (string, error) {
|
|
bizDate := now.Format("20060102")
|
|
if tx.Dialector.Name() == "mysql" {
|
|
if err := tx.Exec(`
|
|
INSERT INTO listing_no_sequences (biz_date, next_seq)
|
|
VALUES (?, LAST_INSERT_ID(1))
|
|
ON DUPLICATE KEY UPDATE next_seq = LAST_INSERT_ID(next_seq + 1)
|
|
`, bizDate).Error; err != nil {
|
|
return "", err
|
|
}
|
|
var seq int
|
|
if err := tx.Raw("SELECT LAST_INSERT_ID()").Scan(&seq).Error; err != nil {
|
|
return "", err
|
|
}
|
|
return fmt.Sprintf("%s%04d", bizDate, seq), nil
|
|
}
|
|
|
|
var maxNo string
|
|
if err := tx.Table("rental_listings").
|
|
Select("COALESCE(MAX(listing_no), '')").
|
|
Where("listing_no LIKE ?", bizDate+"%").
|
|
Scan(&maxNo).Error; err != nil {
|
|
return "", err
|
|
}
|
|
seq := 1
|
|
if len(maxNo) > len(bizDate) {
|
|
if parsed, err := strconv.Atoi(maxNo[len(bizDate):]); err == nil {
|
|
seq = parsed + 1
|
|
}
|
|
}
|
|
return fmt.Sprintf("%s%04d", bizDate, seq), nil
|
|
}
|