删掉租期相关错误东西

This commit is contained in:
yml2213
2026-05-23 14:44:32 +08:00
parent e6cc9f1255
commit a6a1afb879
41 changed files with 127 additions and 312 deletions
+2 -2
View File
@@ -254,7 +254,7 @@ func (j *Job) handleReturnOverdue(ctx context.Context, now time.Time, cfg thresh
UserID: order.RenterID,
Type: "timeout",
Title: "订单已逾期未归还",
Content: "租期已超时,请尽快提交归还说明,避免进入申诉处理。",
Content: "订单已超过预计截止时间,请尽快提交归还说明,避免进入申诉处理。",
BizType: "order",
BizID: &orderID,
},
@@ -262,7 +262,7 @@ func (j *Job) handleReturnOverdue(ctx context.Context, now time.Time, cfg thresh
UserID: order.OwnerID,
Type: "timeout",
Title: "租客逾期未归还",
Content: "租客未在租期结束后及时归还,你可以发起申诉或等待客服处理。",
Content: "租客未在预计截止后及时归还,你可以发起申诉或等待客服处理。",
BizType: "order",
BizID: &orderID,
},
-2
View File
@@ -36,8 +36,6 @@ type RentalListing struct {
PriceDaily float64 `gorm:"type:decimal(12,2);not null;default:0" json:"price_daily"`
PriceWeekly float64 `gorm:"type:decimal(12,2);not null;default:0" json:"price_weekly"`
DepositAmount float64 `gorm:"type:decimal(12,2);not null;default:0" json:"deposit_amount"`
MinRentHours int `gorm:"not null;default:1" json:"min_rent_hours"`
MaxRentHours int `gorm:"not null;default:168" json:"max_rent_hours"`
Status string `gorm:"size:32;not null;default:'draft'" json:"status"`
ReviewStatus string `gorm:"size:32;not null;default:'none'" json:"review_status"`
ReviewReason string `gorm:"size:255;not null;default:''" json:"review_reason"`
@@ -320,7 +320,7 @@ func buildArbitrationSettlement(order model.RentalOrder, req ArbitrateRequest) (
addRenterRefund(req.Amount, "仲裁部分退款")
addOwnerIncome(total-req.Amount, "仲裁剩余金额结算给号主")
case "release_deposit":
addOwnerIncome(order.RentAmount, "仲裁确认租金结算给号主")
addOwnerIncome(order.RentAmount, "仲裁确认订单金额结算给号主")
addRenterRefund(order.DepositAmount, "仲裁释放押金给租客")
case "deduct_deposit", "compensate_owner":
deductAmount := req.Amount
@@ -331,7 +331,7 @@ func buildArbitrationSettlement(order model.RentalOrder, req ArbitrateRequest) (
return settlement, ErrInvalidDispute
}
settlement.DepositDeductAmount = deductAmount
addOwnerIncome(order.RentAmount+deductAmount, "仲裁租金及押金赔付结算给号主")
addOwnerIncome(order.RentAmount+deductAmount, "仲裁订单金额及押金赔付结算给号主")
addRenterRefund(order.DepositAmount-deductAmount, "仲裁退回剩余押金给租客")
case "order_close":
// Only release frozen funds. No available-balance settlement happens in development mode.
-4
View File
@@ -22,8 +22,6 @@ type ListingDTO struct {
PriceDaily float64 `json:"price_daily"`
PriceWeekly float64 `json:"price_weekly"`
DepositAmount float64 `json:"deposit_amount"`
MinRentHours int `json:"min_rent_hours"`
MaxRentHours int `json:"max_rent_hours"`
Status string `json:"status"`
ReviewStatus string `json:"review_status"`
ReviewReason string `json:"review_reason"`
@@ -45,8 +43,6 @@ type CreateRequest struct {
PriceDaily float64 `json:"price_daily"`
PriceWeekly float64 `json:"price_weekly"`
DepositAmount float64 `json:"deposit_amount" binding:"required"`
MinRentHours int `json:"min_rent_hours" binding:"required"`
MaxRentHours int `json:"max_rent_hours" binding:"required"`
}
type UpdateRequest = CreateRequest
@@ -56,8 +56,6 @@ func (r *Repository) Create(ownerID uint64, req CreateRequest) (*ListingDTO, err
PriceDaily: req.PriceDaily,
PriceWeekly: req.PriceWeekly,
DepositAmount: req.DepositAmount,
MinRentHours: req.MinRentHours,
MaxRentHours: req.MaxRentHours,
Status: "draft",
ReviewStatus: "none",
}
@@ -105,8 +103,6 @@ func (r *Repository) Update(ownerID uint64, listingID uint64, req UpdateRequest)
listing.PriceDaily = req.PriceDaily
listing.PriceWeekly = req.PriceWeekly
listing.DepositAmount = req.DepositAmount
listing.MinRentHours = req.MinRentHours
listing.MaxRentHours = req.MaxRentHours
listing.Status = "draft"
listing.ReviewStatus = "none"
listing.ReviewReason = ""
@@ -470,8 +466,6 @@ func (row listingRow) toDTO() ListingDTO {
PriceDaily: row.PriceDaily,
PriceWeekly: row.PriceWeekly,
DepositAmount: row.DepositAmount,
MinRentHours: row.MinRentHours,
MaxRentHours: row.MaxRentHours,
Status: row.Status,
ReviewStatus: row.ReviewStatus,
ReviewReason: row.ReviewReason,
@@ -502,8 +496,6 @@ func toDTO(account model.GameAccount, listing model.RentalListing) *ListingDTO {
PriceDaily: listing.PriceDaily,
PriceWeekly: listing.PriceWeekly,
DepositAmount: listing.DepositAmount,
MinRentHours: listing.MinRentHours,
MaxRentHours: listing.MaxRentHours,
Status: listing.Status,
ReviewStatus: listing.ReviewStatus,
ReviewReason: listing.ReviewReason,
@@ -146,9 +146,6 @@ func validateRequest(req CreateRequest) error {
if req.PriceHourly <= 0 || req.DepositAmount < 0 {
return ErrInvalidInput
}
if req.MinRentHours <= 0 || req.MaxRentHours < req.MinRentHours {
return ErrInvalidInput
}
if req.HafCoinAmount < 0 {
return ErrInvalidInput
}
+1 -1
View File
@@ -1,3 +1,3 @@
# Order Module
订单状态机、账号交接、租期归还、超时处理。
订单状态机、账号交接、归还、超时处理。
-2
View File
@@ -20,7 +20,6 @@ type OrderDTO struct {
LoginPlatform string `json:"login_platform"`
RentStartAt *time.Time `json:"rent_start_at"`
RentEndAt *time.Time `json:"rent_end_at"`
RentHours int `json:"rent_hours"`
RentAmount float64 `json:"rent_amount"`
DepositAmount float64 `json:"deposit_amount"`
PlatformFee float64 `json:"platform_fee"`
@@ -34,7 +33,6 @@ type OrderDTO struct {
type CreateRequest struct {
ListingID uint64 `json:"listing_id" binding:"required"`
RentHours int `json:"rent_hours" binding:"required"`
}
type SubmitHandoffRequest struct {
+1 -1
View File
@@ -282,7 +282,7 @@ func writeOrderError(c *gin.Context, err error) {
case errors.Is(err, ErrDependencyUnavailable):
response.ServiceUnavailable(c, "数据库未连接")
case errors.Is(err, ErrInvalidRentHours):
response.BadRequest(c, "租期不符合规则")
response.BadRequest(c, "订单信息不符合规则")
case errors.Is(err, ErrListingUnavailable):
response.Error(c, http.StatusConflict, "listing_unavailable", "该账号暂不可租")
case errors.Is(err, ErrCannotRentOwnListing):
+8 -11
View File
@@ -38,9 +38,6 @@ func (r *Repository) Create(renterID uint64, req CreateRequest) (*OrderDTO, erro
if listing.OwnerID == renterID {
return ErrCannotRentOwnListing
}
if req.RentHours < listing.MinRentHours || req.RentHours > listing.MaxRentHours {
return ErrInvalidRentHours
}
var account model.GameAccount
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&account, listing.AccountID).Error; err != nil {
@@ -55,7 +52,8 @@ func (r *Repository) Create(renterID uint64, req CreateRequest) (*OrderDTO, erro
return err
}
now := time.Now()
rentEnd := now.Add(time.Duration(req.RentHours) * time.Hour)
rentHours := internalOrderHours
rentEnd := now.Add(time.Duration(rentHours) * time.Hour)
order := model.RentalOrder{
OrderNo: orderNo,
ListingID: listing.ID,
@@ -64,8 +62,8 @@ func (r *Repository) Create(renterID uint64, req CreateRequest) (*OrderDTO, erro
RenterID: renterID,
RentStartAt: &now,
RentEndAt: &rentEnd,
RentHours: req.RentHours,
RentAmount: listing.PriceHourly * float64(req.RentHours),
RentHours: rentHours,
RentAmount: listing.PriceHourly * float64(rentHours),
DepositAmount: listing.DepositAmount,
PlatformFee: 0,
AccountSnapshot: snapshot,
@@ -86,7 +84,7 @@ func (r *Repository) Create(renterID uint64, req CreateRequest) (*OrderDTO, erro
BalanceType: "frozen",
BizType: "order_lock",
BizNo: order.OrderNo,
Remark: "开发态模拟冻结租金和押金",
Remark: "开发态模拟冻结订单金额和押金",
},
); err != nil {
return err
@@ -272,7 +270,7 @@ func (r *Repository) ConfirmReceive(userID uint64, orderID uint64) error {
UserID: order.OwnerID,
Type: "handoff",
Title: "租客已确认收号",
Content: "订单已进入租赁中。",
Content: "订单已进入使用中。",
BizType: "order",
BizID: &orderID,
}); err != nil {
@@ -399,7 +397,7 @@ func (r *Repository) ConfirmReturn(userID uint64, orderID uint64) error {
BalanceType: "available",
BizType: "owner_income",
BizNo: order.OrderNo,
Remark: "订单完成模拟结算租金",
Remark: "订单完成模拟结算订单金额",
},
wallet.Entry{
UserID: order.RenterID,
@@ -427,7 +425,7 @@ func (r *Repository) ConfirmReturn(userID uint64, orderID uint64) error {
UserID: order.OwnerID,
Type: "settlement",
Title: "订单已完成",
Content: "订单已完成,模拟租金已入账。",
Content: "订单已完成,模拟订单金额已入账。",
BizType: "order",
BizID: &orderID,
},
@@ -727,7 +725,6 @@ func (row orderRow) toDTO() OrderDTO {
LoginPlatform: row.LoginPlatform,
RentStartAt: row.RentStartAt,
RentEndAt: row.RentEndAt,
RentHours: row.RentHours,
RentAmount: row.RentAmount,
DepositAmount: row.DepositAmount,
PlatformFee: row.PlatformFee,
+3 -1
View File
@@ -15,6 +15,8 @@ var (
ErrPermissionDenied = errors.New("permission denied")
)
const internalOrderHours = 24
type Service struct {
repo *Repository
}
@@ -27,7 +29,7 @@ func (s *Service) Create(userID uint64, req CreateRequest) (*OrderDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
if req.ListingID == 0 || req.RentHours <= 0 {
if req.ListingID == 0 {
return nil, ErrInvalidRentHours
}
return s.repo.Create(userID, req)
@@ -83,7 +83,6 @@ type PublishRatioConfig struct {
InsuranceBaseRatios []PublishInsuranceBaseRatio `json:"insurance_base_ratios"`
ConfigItems []PublishRatioConfigItem `json:"config_items"`
CoinCorrections []PublishCoinCorrection `json:"coin_corrections"`
RentRules []PublishRentRule `json:"rent_rules"`
}
type PublishInsuranceBaseRatio struct {
@@ -103,8 +102,3 @@ type PublishCoinCorrection struct {
ThresholdM float64 `json:"threshold_m"`
Correction float64 `json:"correction"`
}
type PublishRentRule struct {
ThresholdM float64 `json:"threshold_m"`
Days int `json:"days"`
}
@@ -106,11 +106,6 @@ func DefaultPublishOptions() PublishOptionsDTO {
{ThresholdM: 380, Correction: 4},
{ThresholdM: 530, Correction: 5},
},
RentRules: []PublishRentRule{
{ThresholdM: 300, Days: 7},
{ThresholdM: 100, Days: 3},
{ThresholdM: 0, Days: 1},
},
},
}
}
@@ -31,7 +31,7 @@ var defaultConfigs = []defaultConfig{
{Key: "handoff.owner_submit_timeout_minutes", Value: "30", Description: "号主待交接超时分钟数"},
{Key: "handoff.renter_confirm_timeout_minutes", Value: "30", Description: "租客待确认收号超时分钟数"},
{Key: "handoff.owner_return_confirm_timeout_minutes", Value: "120", Description: "号主待确认归还超时分钟数"},
{Key: "order.return_overdue_grace_minutes", Value: "10", Description: "租期到期后归还宽限分钟数"},
{Key: "order.return_overdue_grace_minutes", Value: "10", Description: "预计截止后归还宽限分钟数"},
{Key: "deposit.min_amount", Value: "50", Description: "发布租号最低押金"},
{Key: "risk.sms_limit_per_phone_hour", Value: "5", Description: "单手机号每小时短信验证码次数"},
{Key: "risk.sms_limit_per_ip_hour", Value: "20", Description: "单 IP 每小时短信验证码次数"},
@@ -211,7 +211,4 @@ func normalizePublishOptions(options *PublishOptionsDTO) {
if len(options.RatioConfig.CoinCorrections) == 0 {
options.RatioConfig.CoinCorrections = defaults.RatioConfig.CoinCorrections
}
if len(options.RatioConfig.RentRules) == 0 {
options.RatioConfig.RentRules = defaults.RatioConfig.RentRules
}
}
+1 -1
View File
@@ -1,3 +1,3 @@
# Wallet Module
押金冻结、租金结算、不可变资金流水。
押金冻结、订单金额结算、不可变资金流水。
-2
View File
@@ -57,8 +57,6 @@ CREATE TABLE rental_listings (
price_daily DECIMAL(12,2) NOT NULL DEFAULT 0.00,
price_weekly DECIMAL(12,2) NOT NULL DEFAULT 0.00,
deposit_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00,
min_rent_hours INT NOT NULL DEFAULT 1,
max_rent_hours INT NOT NULL DEFAULT 168,
status VARCHAR(32) NOT NULL DEFAULT 'draft',
review_status VARCHAR(32) NOT NULL DEFAULT 'none',
review_reason VARCHAR(255) NOT NULL DEFAULT '',
+10 -10
View File
@@ -214,7 +214,7 @@ VALUES
(
@owner_c, '三角洲行动', '微信', '扫码',
'纯币180M/6格/6体/5负/80发AWM',
'扫码交接,资源适中,适合三日租',
'扫码交接,资源适中,适合短期使用',
'黑鹰', 180000000,
JSON_OBJECT(
'face_owner', '',
@@ -361,29 +361,29 @@ VALUES
);
INSERT INTO rental_listings
(account_id, owner_id, price_hourly, price_daily, price_weekly, deposit_amount, min_rent_hours, max_rent_hours, status, review_status, published_at, created_at, updated_at)
SELECT id, owner_id, 29.76, 714.29, 5000.00, 120.00, 24, 168, 'published', 'approved', NOW() - INTERVAL 80 MINUTE, created_at, updated_at
(account_id, owner_id, price_hourly, price_daily, price_weekly, deposit_amount, status, review_status, published_at, created_at, updated_at)
SELECT id, owner_id, 29.76, 714.29, 5000.00, 120.00, 'published', 'approved', NOW() - INTERVAL 80 MINUTE, created_at, updated_at
FROM game_accounts WHERE title = '纯币300M/6格/6体/6负/4六甲/6六头'
UNION ALL
SELECT id, owner_id, 33.33, 800.00, 2400.00, 60.00, 24, 72, 'published', 'approved', NOW() - INTERVAL 70 MINUTE, created_at, updated_at
SELECT id, owner_id, 33.33, 800.00, 2400.00, 60.00, 'published', 'approved', NOW() - INTERVAL 70 MINUTE, created_at, updated_at
FROM game_accounts WHERE title = '纯币120M/4格/5体/5负/2六头'
UNION ALL
SELECT id, owner_id, 62.50, 1500.00, 1500.00, 80.00, 8, 24, 'published', 'approved', NOW() - INTERVAL 60 MINUTE, created_at, updated_at
SELECT id, owner_id, 62.50, 1500.00, 1500.00, 80.00, 'published', 'approved', NOW() - INTERVAL 60 MINUTE, created_at, updated_at
FROM game_accounts WHERE title = '纯币60M/2格/4体/4负/1体验卡'
UNION ALL
SELECT id, owner_id, 42.52, 1020.41, 7142.86, 180.00, 24, 168, 'published', 'approved', NOW() - INTERVAL 50 MINUTE, created_at, updated_at
SELECT id, owner_id, 42.52, 1020.41, 7142.86, 180.00, 'published', 'approved', NOW() - INTERVAL 50 MINUTE, created_at, updated_at
FROM game_accounts WHERE title = '纯币500M/9格/7体/7负/10六头'
UNION ALL
SELECT id, owner_id, 50.00, 1200.00, 3600.00, 100.00, 24, 72, 'published', 'approved', NOW() - INTERVAL 40 MINUTE, created_at, updated_at
SELECT id, owner_id, 50.00, 1200.00, 3600.00, 100.00, 'published', 'approved', NOW() - INTERVAL 40 MINUTE, created_at, updated_at
FROM game_accounts WHERE title = '纯币180M/6格/6体/5负/80发AWM'
UNION ALL
SELECT id, owner_id, 31.25, 750.00, 750.00, 50.00, 8, 24, 'published', 'approved', NOW() - INTERVAL 30 MINUTE, created_at, updated_at
SELECT id, owner_id, 31.25, 750.00, 750.00, 50.00, 'published', 'approved', NOW() - INTERVAL 30 MINUTE, created_at, updated_at
FROM game_accounts WHERE title = '纯币90M/4格/5体/4负/3五级套'
UNION ALL
SELECT id, owner_id, 25.79, 619.05, 4333.33, 120.00, 24, 168, 'published', 'approved', NOW() - INTERVAL 20 MINUTE, created_at, updated_at
SELECT id, owner_id, 25.79, 619.05, 4333.33, 120.00, 'published', 'approved', NOW() - INTERVAL 20 MINUTE, created_at, updated_at
FROM game_accounts WHERE title = '纯币260M/6格/6体/6负/皮肤多'
UNION ALL
SELECT id, owner_id, 35.71, 857.14, 6000.00, 160.00, 24, 168, 'published', 'approved', NOW() - INTERVAL 10 MINUTE, created_at, updated_at
SELECT id, owner_id, 35.71, 857.14, 6000.00, 160.00, 'published', 'approved', NOW() - INTERVAL 10 MINUTE, created_at, updated_at
FROM game_accounts WHERE title = '纯币360M/9格/7体/6负/赠送六级弹';
INSERT INTO notifications (user_id, type, title, content, biz_type, biz_id, created_at)