chore(init): 初始化解忧商行项目并完成 Phase 0 基座
This commit is contained in:
@@ -0,0 +1,626 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"hfb_sys/backend/internal/model"
|
||||
|
||||
"gorm.io/datatypes"
|
||||
)
|
||||
|
||||
func adminActionsForOrder(order model.RentalOrder) *AdminActionsDTO {
|
||||
actions := &AdminActionsDTO{}
|
||||
target, ok := resetTargetForOrder(order)
|
||||
if ok {
|
||||
actions.ResetHandoff = &AdminActionDTO{
|
||||
Enabled: true,
|
||||
Label: target.Label,
|
||||
}
|
||||
}
|
||||
if canAdminPlatformHandoff(order) {
|
||||
actions.PlatformHandoff = &AdminActionDTO{
|
||||
Enabled: true,
|
||||
Label: "客服代交接",
|
||||
}
|
||||
}
|
||||
if canAdminForceHandoff(order) {
|
||||
actions.ForceHandoff = &AdminActionDTO{
|
||||
Enabled: true,
|
||||
Label: "客服一键交接",
|
||||
}
|
||||
}
|
||||
if canAdminPlatformCheckoutConfirm(order) {
|
||||
actions.PlatformCheckoutConfirm = &AdminActionDTO{
|
||||
Enabled: true,
|
||||
Label: "客服确认结账",
|
||||
}
|
||||
actions.PlatformCheckoutCounter = &AdminActionDTO{
|
||||
Enabled: true,
|
||||
Label: "客服修改结账方案",
|
||||
}
|
||||
actions.PlatformCheckoutDispute = &AdminActionDTO{
|
||||
Enabled: true,
|
||||
Label: "发起结账争议",
|
||||
}
|
||||
}
|
||||
if canAdminMarkOfflineSettlement(order) {
|
||||
actions.PlatformOfflineSettlement = &AdminActionDTO{
|
||||
Enabled: true,
|
||||
Label: "确认线下结算",
|
||||
}
|
||||
}
|
||||
if actions.ResetHandoff == nil && actions.PlatformHandoff == nil && actions.ForceHandoff == nil &&
|
||||
actions.PlatformCheckoutConfirm == nil && actions.PlatformCheckoutCounter == nil &&
|
||||
actions.PlatformCheckoutDispute == nil && actions.PlatformOfflineSettlement == nil {
|
||||
return nil
|
||||
}
|
||||
return actions
|
||||
}
|
||||
|
||||
func (row orderRow) toAdminDTO() OrderDTO {
|
||||
rentedAt := row.RentedAt
|
||||
durationHours := orderDurationHours(row.RentalOrder)
|
||||
estimatedEndAt := orderEstimatedEndAt(row.RentalOrder)
|
||||
rentAmountCent := row.RentAmountCent
|
||||
ownerRentAmountCent := row.OwnerRentAmountCent
|
||||
platformFeeCent := row.PlatformFeeCent
|
||||
return OrderDTO{
|
||||
ID: row.ID,
|
||||
OrderNo: row.OrderNo,
|
||||
ListingID: row.ListingID,
|
||||
ListingNo: row.ListingNo,
|
||||
AccountID: row.AccountID,
|
||||
OwnerID: row.OwnerID,
|
||||
RenterID: row.RenterID,
|
||||
OwnerPhone: row.OwnerPhone,
|
||||
RenterPhone: row.RenterPhone,
|
||||
Title: row.Title,
|
||||
ServerRegion: row.ServerRegion,
|
||||
LoginPlatform: row.LoginPlatform,
|
||||
RentedAt: rentedAt,
|
||||
EstimatedDurationHours: durationHours,
|
||||
EstimatedEndAt: estimatedEndAt,
|
||||
PriceRole: "admin",
|
||||
DisplayAmountCent: row.RentAmountCent,
|
||||
RentAmountCent: &rentAmountCent,
|
||||
OwnerRentAmountCent: &ownerRentAmountCent,
|
||||
DepositAmountCent: row.DepositAmountCent,
|
||||
DepositOriginalAmountCent: effectiveDepositOriginalAmountCent(row.RentalOrder),
|
||||
DepositWaivedAmountCent: row.DepositWaivedAmountCent,
|
||||
DepositFreeLevelQuotaCent: row.DepositFreeLevelQuotaCent,
|
||||
DepositFreeManualQuotaCent: row.DepositFreeManualQuotaCent,
|
||||
DepositFreeUsedBeforeCent: row.DepositFreeUsedBeforeCent,
|
||||
PlatformFeeCent: &platformFeeCent,
|
||||
BasePriceCent: row.BasePriceCent,
|
||||
ShelfMarkupCent: row.ShelfMarkupCent,
|
||||
MarkupSiteID: row.MarkupSiteID,
|
||||
ShelfRatio: row.ShelfRatio,
|
||||
ShelfRatioDelta: row.ShelfRatioDelta,
|
||||
RentOriginalAmountCent: effectiveRentOriginalAmountCent(row.RentalOrder),
|
||||
RentDiscountAmountCent: row.RentDiscountAmountCent,
|
||||
PureCoinOriginalAmountCent: orderPureCoinOriginalAmountCent(row.RentalOrder),
|
||||
ExtraItemOriginalAmountCent: orderExtraItemOriginalAmountCent(row.RentalOrder),
|
||||
ActualCoinConsumedM: row.ActualCoinConsumedM,
|
||||
ActualPureCoinAmountCent: row.ActualPureCoinAmountCent,
|
||||
ActualPureCoinDiscountCent: row.ActualPureCoinDiscountCent,
|
||||
ActualExtraItemAmountCent: row.ActualExtraItemAmountCent,
|
||||
RenterGrowthLevel: effectiveRenterGrowthLevel(row.RentalOrder),
|
||||
RenterGrowthLevelName: effectiveRenterGrowthLevelName(row.RentalOrder),
|
||||
RenterDiscountBps: effectiveRenterDiscountBps(row.RentalOrder),
|
||||
GrowthPointsBasisCent: row.GrowthPointsBasisCent,
|
||||
GrowthPointsPerYuan: row.GrowthPointsPerYuan,
|
||||
GrowthPointsAwarded: row.GrowthPointsAwarded,
|
||||
GrowthPointsAwardedAt: row.GrowthPointsAwardedAt,
|
||||
AccountSnapshot: row.AccountSnapshot,
|
||||
AccountSource: effectiveAccountSource(row.RentalOrder),
|
||||
SourceChannel: row.SourceChannel,
|
||||
Status: row.Status,
|
||||
HandoffStatus: row.HandoffStatus,
|
||||
HandoffMode: effectiveHandoffMode(row.RentalOrder),
|
||||
SettlementMode: effectiveSettlementMode(row.RentalOrder),
|
||||
ManagedAdminID: row.ManagedAdminID,
|
||||
SettlementStatus: row.SettlementStatus,
|
||||
OfflineSettlementStatus: effectiveOfflineSettlementStatus(row.RentalOrder),
|
||||
OfflineSettlementAmountCent: row.OfflineSettlementAmountCent,
|
||||
OfflineSettlementRemark: row.OfflineSettlementRemark,
|
||||
OfflineSettledBy: row.OfflineSettledBy,
|
||||
OfflineSettledAt: row.OfflineSettledAt,
|
||||
RefundStatus: row.RefundStatus,
|
||||
RefundAmountCent: row.RefundAmountCent,
|
||||
DepositHoldStatus: row.DepositHoldStatus,
|
||||
DepositHoldAmountCent: row.DepositHoldAmountCent,
|
||||
DepositHoldReason: row.DepositHoldReason,
|
||||
DepositHeldAt: row.DepositHeldAt,
|
||||
DepositHoldReleasedAt: row.DepositHoldReleasedAt,
|
||||
AdminActions: adminActionsForOrder(row.RentalOrder),
|
||||
DistributionSiteID: row.DistributionSiteID,
|
||||
SourceTrackCode: row.SourceTrackCode,
|
||||
CreatedAt: row.CreatedAt,
|
||||
UpdatedAt: row.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
func effectiveAccountSource(order model.RentalOrder) string {
|
||||
if order.AccountSource != "" {
|
||||
return order.AccountSource
|
||||
}
|
||||
return "internal"
|
||||
}
|
||||
|
||||
func (row orderRow) toDTOForUser(userID uint64) OrderDTO {
|
||||
dto := row.toAdminDTO()
|
||||
dto.AdminActions = nil
|
||||
// 押金暂扣属于客服内部处置,不向租客/号主暴露。
|
||||
dto.DepositHoldStatus = ""
|
||||
dto.DepositHoldAmountCent = 0
|
||||
dto.DepositHoldReason = ""
|
||||
dto.DepositHeldAt = nil
|
||||
dto.DepositHoldReleasedAt = nil
|
||||
dto.ManagedAdminID = nil
|
||||
dto.OfflineSettlementStatus = ""
|
||||
dto.OfflineSettlementAmountCent = 0
|
||||
dto.OfflineSettlementRemark = ""
|
||||
dto.OfflineSettledBy = nil
|
||||
dto.OfflineSettledAt = nil
|
||||
// 外部来源渠道属于后台经营信息,仅在管理员订单详情展示。
|
||||
dto.AccountSource = ""
|
||||
dto.SourceChannel = ""
|
||||
applyOrderPriceView(&dto, row.RentalOrder, userID)
|
||||
return dto
|
||||
}
|
||||
|
||||
func (row orderRow) toUserListItem(userID uint64, paymentDeadlineAt *time.Time) UserOrderListItemDTO {
|
||||
role := "renter"
|
||||
if userID == row.OwnerID {
|
||||
role = "owner"
|
||||
}
|
||||
displayAmountCent := row.RentAmountCent
|
||||
if role == "owner" && row.OwnerRentAmountCent > 0 {
|
||||
displayAmountCent = row.OwnerRentAmountCent
|
||||
}
|
||||
rentalDays, dailyLossM := orderListingTerms(row.AccountSnapshot)
|
||||
return UserOrderListItemDTO{
|
||||
ID: row.ID,
|
||||
OrderNo: row.OrderNo,
|
||||
ListingID: row.ListingID,
|
||||
ListingNo: row.ListingNo,
|
||||
Role: role,
|
||||
Title: row.Title,
|
||||
ServerRegion: row.ServerRegion,
|
||||
LoginPlatform: row.LoginPlatform,
|
||||
RentalDays: rentalDays,
|
||||
DailyLossM: dailyLossM,
|
||||
DisplayAmountCent: displayAmountCent,
|
||||
DepositAmountCent: row.DepositAmountCent,
|
||||
DepositWaivedAmountCent: row.DepositWaivedAmountCent,
|
||||
Status: row.Status,
|
||||
HandoffStatus: row.HandoffStatus,
|
||||
PaymentDeadlineAt: paymentDeadlineAt,
|
||||
DistributionSiteID: row.DistributionSiteID,
|
||||
CreatedAt: row.CreatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
func (row orderRow) toAdminListItem() AdminOrderListItemDTO {
|
||||
return AdminOrderListItemDTO{
|
||||
ID: row.ID,
|
||||
OrderNo: row.OrderNo,
|
||||
ListingID: row.ListingID,
|
||||
ListingNo: row.ListingNo,
|
||||
OwnerPhone: row.OwnerPhone,
|
||||
RenterPhone: row.RenterPhone,
|
||||
Title: row.Title,
|
||||
ServerRegion: row.ServerRegion,
|
||||
LoginPlatform: row.LoginPlatform,
|
||||
RentAmountCent: row.RentAmountCent,
|
||||
DepositAmountCent: row.DepositAmountCent,
|
||||
Status: row.Status,
|
||||
HandoffStatus: row.HandoffStatus,
|
||||
HandoffMode: effectiveHandoffMode(row.RentalOrder),
|
||||
SettlementMode: effectiveSettlementMode(row.RentalOrder),
|
||||
SettlementStatus: row.SettlementStatus,
|
||||
CreatedAt: row.CreatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
func effectiveHandoffMode(order model.RentalOrder) string {
|
||||
if order.HandoffMode != "" {
|
||||
return order.HandoffMode
|
||||
}
|
||||
return handoffModeOwner
|
||||
}
|
||||
|
||||
func effectiveSettlementMode(order model.RentalOrder) string {
|
||||
if order.SettlementMode != "" {
|
||||
return order.SettlementMode
|
||||
}
|
||||
return settlementModeOwnerWallet
|
||||
}
|
||||
|
||||
func effectiveOfflineSettlementStatus(order model.RentalOrder) string {
|
||||
if order.OfflineSettlementStatus != "" {
|
||||
return order.OfflineSettlementStatus
|
||||
}
|
||||
return offlineSettlementStatusNone
|
||||
}
|
||||
|
||||
func effectiveDepositOriginalAmountCent(order model.RentalOrder) int64 {
|
||||
if order.DepositOriginalAmountCent > 0 {
|
||||
return order.DepositOriginalAmountCent
|
||||
}
|
||||
return order.DepositAmountCent
|
||||
}
|
||||
|
||||
func effectiveRentOriginalAmountCent(order model.RentalOrder) int64 {
|
||||
if order.RentOriginalAmountCent > 0 {
|
||||
return order.RentOriginalAmountCent
|
||||
}
|
||||
return order.RentAmountCent + order.RentDiscountAmountCent
|
||||
}
|
||||
|
||||
func effectiveRenterGrowthLevel(order model.RentalOrder) string {
|
||||
if order.RenterGrowthLevel != "" {
|
||||
return order.RenterGrowthLevel
|
||||
}
|
||||
return "normal"
|
||||
}
|
||||
|
||||
func effectiveRenterGrowthLevelName(order model.RentalOrder) string {
|
||||
if order.RenterGrowthLevelName != "" {
|
||||
return order.RenterGrowthLevelName
|
||||
}
|
||||
return "普通"
|
||||
}
|
||||
|
||||
func effectiveRenterDiscountBps(order model.RentalOrder) int {
|
||||
if order.RenterDiscountBps > 0 {
|
||||
return order.RenterDiscountBps
|
||||
}
|
||||
return 10000
|
||||
}
|
||||
|
||||
func toCheckoutAdminDTO(checkout model.OrderCheckout) CheckoutDTO {
|
||||
rentAmountCent := checkout.RentAmountCent
|
||||
ownerRentAmountCent := checkout.OwnerRentAmountCent
|
||||
platformFeeCent := checkout.PlatformFeeCent
|
||||
renterRefundAmountCent := checkout.RenterRefundAmountCent
|
||||
ownerIncomeAmountCent := checkout.OwnerIncomeAmountCent
|
||||
roundCount := checkout.RoundCount
|
||||
if roundCount <= 0 {
|
||||
roundCount = 1
|
||||
}
|
||||
turn := checkout.Turn
|
||||
if turn != checkoutTurnOwner && turn != checkoutTurnRenter {
|
||||
if checkout.Status == checkoutStatusCountered {
|
||||
turn = checkoutTurnRenter
|
||||
} else {
|
||||
turn = checkoutTurnOwner
|
||||
}
|
||||
}
|
||||
return CheckoutDTO{
|
||||
ID: checkout.ID,
|
||||
OrderID: checkout.OrderID,
|
||||
InitiatedBy: checkout.InitiatedBy,
|
||||
Status: checkout.Status,
|
||||
RoundCount: roundCount,
|
||||
Turn: turn,
|
||||
ProposedBy: checkout.ProposedBy,
|
||||
MaxRounds: checkoutMaxRounds,
|
||||
PriceRole: "admin",
|
||||
DisplayAmountCent: rentAmountCent,
|
||||
RentAmountCent: &rentAmountCent,
|
||||
OwnerRentAmountCent: &ownerRentAmountCent,
|
||||
PlatformFeeCent: &platformFeeCent,
|
||||
DepositAmountCent: checkout.DepositAmountCent,
|
||||
PureCoinAmountCent: checkout.PureCoinAmountCent,
|
||||
PureCoinDiscountCent: checkout.PureCoinDiscountCent,
|
||||
PureCoinPayableCent: checkout.PureCoinPayableCent,
|
||||
ConsumableAmountCent: checkout.ConsumableAmountCent,
|
||||
CoinConsumedM: checkout.CoinConsumedM,
|
||||
OtherAmountCent: checkout.OtherAmountCent,
|
||||
DepositDeductAmountCent: checkout.DepositDeductAmountCent,
|
||||
RenterRefundAmountCent: &renterRefundAmountCent,
|
||||
OwnerIncomeAmountCent: &ownerIncomeAmountCent,
|
||||
ShortfallCent: checkout.ShortfallCent,
|
||||
OvershootAmountCent: checkout.OvershootAmountCent,
|
||||
Content: checkout.Content,
|
||||
EvidenceURLS: decodeStringList(checkout.EvidenceURLS),
|
||||
OwnerAdjustmentReason: checkout.OwnerAdjustmentReason,
|
||||
OwnerAdjustedAt: checkout.OwnerAdjustedAt,
|
||||
RenterConfirmedAt: checkout.RenterConfirmedAt,
|
||||
RenterRejectedAt: checkout.RenterRejectedAt,
|
||||
CreatedAt: checkout.CreatedAt,
|
||||
UpdatedAt: checkout.UpdatedAt,
|
||||
}
|
||||
}
|
||||
|
||||
func toCheckoutDTOForUser(checkout model.OrderCheckout, userID uint64, order model.RentalOrder) CheckoutDTO {
|
||||
dto := toCheckoutAdminDTO(checkout)
|
||||
refreshCheckoutSettlementDTO(&dto, order, checkout)
|
||||
applyCheckoutPriceView(&dto, order, userID)
|
||||
applyCheckoutActionFlags(&dto, checkout, order, userID)
|
||||
return dto
|
||||
}
|
||||
|
||||
// refreshCheckoutSettlementDTO 用当前公式重算展示字段(兼容旧单 shortfall/overshoot 为空)
|
||||
func refreshCheckoutSettlementDTO(dto *CheckoutDTO, order model.RentalOrder, checkout model.OrderCheckout) {
|
||||
if dto == nil {
|
||||
return
|
||||
}
|
||||
if checkout.Status != checkoutStatusSubmitted && checkout.Status != checkoutStatusCountered {
|
||||
return
|
||||
}
|
||||
settlement := calculateCheckoutSettlement(order, checkout.ConsumableAmountCent, checkout.CoinConsumedM, effectiveCheckoutDepositDeductCent(checkout))
|
||||
rent := settlement.ActualRentAmountCent
|
||||
ownerRent := settlement.OwnerRentIncomeCent
|
||||
platform := settlement.PlatformFeeCent
|
||||
renterRefund := settlement.RenterRefundCent
|
||||
ownerIncome := settlement.OwnerIncomeCent
|
||||
dto.RentAmountCent = &rent
|
||||
dto.OwnerRentAmountCent = &ownerRent
|
||||
dto.PlatformFeeCent = &platform
|
||||
dto.RenterRefundAmountCent = &renterRefund
|
||||
dto.OwnerIncomeAmountCent = &ownerIncome
|
||||
dto.DisplayAmountCent = rent
|
||||
dto.ShortfallCent = settlement.ShortfallCent
|
||||
dto.OvershootAmountCent = settlement.OvershootAmountCent
|
||||
}
|
||||
|
||||
func applyCheckoutActionFlags(dto *CheckoutDTO, checkout model.OrderCheckout, order model.RentalOrder, userID uint64) {
|
||||
if dto == nil {
|
||||
return
|
||||
}
|
||||
isOwnerPending := order.Status == orderStatusPendingCheckoutConfirm ||
|
||||
(order.Status == orderStatusAbnormal &&
|
||||
(order.HandoffStatus == handoffStatusOwnerCheckoutConfirmTimeout ||
|
||||
order.HandoffStatus == handoffStatusOwnerReturnConfirmTimeout ||
|
||||
order.HandoffStatus == handoffStatusPendingOwnerCheckout))
|
||||
isRenterPending := order.Status == orderStatusPendingCheckoutAccept
|
||||
negotiating := isOwnerPending || isRenterPending
|
||||
if !negotiating || (checkout.Status != checkoutStatusSubmitted && checkout.Status != checkoutStatusCountered) {
|
||||
return
|
||||
}
|
||||
turn := dto.Turn
|
||||
round := dto.RoundCount
|
||||
isOwner := userID == order.OwnerID
|
||||
isRenter := userID == order.RenterID
|
||||
if isOwner && turn == checkoutTurnOwner && isOwnerPending {
|
||||
dto.CanAccept = dto.ShortfallCent <= 0
|
||||
dto.CanCounter = round < checkoutMaxRounds
|
||||
}
|
||||
if isRenter && turn == checkoutTurnRenter && isRenterPending {
|
||||
dto.CanAccept = dto.ShortfallCent <= 0
|
||||
dto.CanCounter = round < checkoutMaxRounds
|
||||
}
|
||||
}
|
||||
|
||||
func applyOrderPriceView(dto *OrderDTO, order model.RentalOrder, userID uint64) {
|
||||
if dto == nil {
|
||||
return
|
||||
}
|
||||
dto.PlatformFeeCent = nil
|
||||
switch {
|
||||
case userID == order.OwnerID:
|
||||
ownerAmountCent := order.OwnerRentAmountCent
|
||||
if ownerAmountCent <= 0 {
|
||||
ownerAmountCent = order.RentAmountCent
|
||||
}
|
||||
dto.PriceRole = "owner"
|
||||
dto.DisplayAmountCent = ownerAmountCent
|
||||
dto.RentAmountCent = nil
|
||||
dto.OwnerRentAmountCent = &ownerAmountCent
|
||||
dto.RentOriginalAmountCent = 0
|
||||
dto.RentDiscountAmountCent = 0
|
||||
dto.PureCoinOriginalAmountCent = 0
|
||||
dto.ExtraItemOriginalAmountCent = 0
|
||||
dto.ActualCoinConsumedM = 0
|
||||
dto.ActualPureCoinAmountCent = 0
|
||||
dto.ActualPureCoinDiscountCent = 0
|
||||
dto.ActualExtraItemAmountCent = 0
|
||||
dto.RenterGrowthLevel = ""
|
||||
dto.RenterGrowthLevelName = ""
|
||||
dto.RenterDiscountBps = 0
|
||||
dto.GrowthPointsAwarded = 0
|
||||
dto.GrowthPointsAwardedAt = nil
|
||||
dto.GrowthPointsBasisCent = 0
|
||||
dto.GrowthPointsPerYuan = 0
|
||||
sanitizeOrderSnapshot(&dto.AccountSnapshot, "owner")
|
||||
case userID == order.RenterID:
|
||||
rentAmountCent := order.RentAmountCent
|
||||
dto.PriceRole = "renter"
|
||||
dto.DisplayAmountCent = rentAmountCent
|
||||
dto.RentAmountCent = &rentAmountCent
|
||||
dto.OwnerRentAmountCent = nil
|
||||
dto.RentOriginalAmountCent = effectiveRentOriginalAmountCent(order)
|
||||
dto.RentDiscountAmountCent = order.RentDiscountAmountCent
|
||||
dto.RenterGrowthLevel = effectiveRenterGrowthLevel(order)
|
||||
dto.RenterGrowthLevelName = effectiveRenterGrowthLevelName(order)
|
||||
dto.RenterDiscountBps = effectiveRenterDiscountBps(order)
|
||||
sanitizeOrderSnapshot(&dto.AccountSnapshot, "renter")
|
||||
default:
|
||||
dto.PriceRole = ""
|
||||
dto.DisplayAmountCent = 0
|
||||
dto.RentAmountCent = nil
|
||||
dto.OwnerRentAmountCent = nil
|
||||
dto.RentOriginalAmountCent = 0
|
||||
dto.RentDiscountAmountCent = 0
|
||||
dto.PureCoinOriginalAmountCent = 0
|
||||
dto.ExtraItemOriginalAmountCent = 0
|
||||
dto.ActualCoinConsumedM = 0
|
||||
dto.ActualPureCoinAmountCent = 0
|
||||
dto.ActualPureCoinDiscountCent = 0
|
||||
dto.ActualExtraItemAmountCent = 0
|
||||
dto.RenterGrowthLevel = ""
|
||||
dto.RenterGrowthLevelName = ""
|
||||
dto.RenterDiscountBps = 0
|
||||
dto.GrowthPointsAwarded = 0
|
||||
dto.GrowthPointsAwardedAt = nil
|
||||
dto.GrowthPointsBasisCent = 0
|
||||
dto.GrowthPointsPerYuan = 0
|
||||
sanitizeOrderSnapshot(&dto.AccountSnapshot, "")
|
||||
}
|
||||
}
|
||||
|
||||
func applyCheckoutPriceView(dto *CheckoutDTO, order model.RentalOrder, userID uint64) {
|
||||
if dto == nil {
|
||||
return
|
||||
}
|
||||
ownerAmountCent := int64(0)
|
||||
if dto.OwnerRentAmountCent != nil {
|
||||
ownerAmountCent = *dto.OwnerRentAmountCent
|
||||
}
|
||||
ownerIncomeAmountCent := int64(0)
|
||||
if dto.OwnerIncomeAmountCent != nil {
|
||||
ownerIncomeAmountCent = *dto.OwnerIncomeAmountCent
|
||||
}
|
||||
rentAmountCent := int64(0)
|
||||
if dto.RentAmountCent != nil {
|
||||
rentAmountCent = *dto.RentAmountCent
|
||||
}
|
||||
renterRefundAmountCent := int64(0)
|
||||
if dto.RenterRefundAmountCent != nil {
|
||||
renterRefundAmountCent = *dto.RenterRefundAmountCent
|
||||
}
|
||||
dto.PlatformFeeCent = nil
|
||||
dto.RenterRefundAmountCent = nil
|
||||
dto.OwnerIncomeAmountCent = nil
|
||||
switch {
|
||||
case userID == order.OwnerID:
|
||||
dto.PriceRole = "owner"
|
||||
dto.DisplayAmountCent = ownerAmountCent
|
||||
dto.RentAmountCent = nil
|
||||
dto.OwnerRentAmountCent = &ownerAmountCent
|
||||
dto.OwnerIncomeAmountCent = &ownerIncomeAmountCent
|
||||
dto.PureCoinAmountCent = 0
|
||||
dto.PureCoinDiscountCent = 0
|
||||
dto.PureCoinPayableCent = 0
|
||||
case userID == order.RenterID:
|
||||
dto.PriceRole = "renter"
|
||||
dto.DisplayAmountCent = rentAmountCent
|
||||
dto.RentAmountCent = &rentAmountCent
|
||||
dto.OwnerRentAmountCent = nil
|
||||
dto.RenterRefundAmountCent = &renterRefundAmountCent
|
||||
default:
|
||||
dto.PriceRole = ""
|
||||
dto.DisplayAmountCent = 0
|
||||
dto.RentAmountCent = nil
|
||||
dto.OwnerRentAmountCent = nil
|
||||
dto.PureCoinAmountCent = 0
|
||||
dto.PureCoinDiscountCent = 0
|
||||
dto.PureCoinPayableCent = 0
|
||||
}
|
||||
}
|
||||
|
||||
func sanitizeOrderSnapshot(snapshot *datatypes.JSON, role string) {
|
||||
if snapshot == nil || len(*snapshot) == 0 {
|
||||
return
|
||||
}
|
||||
var payload map[string]any
|
||||
if err := json.Unmarshal(*snapshot, &payload); err != nil {
|
||||
return
|
||||
}
|
||||
rawSummary, ok := payload["asset_summary"]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
var summary map[string]any
|
||||
switch typed := rawSummary.(type) {
|
||||
case map[string]any:
|
||||
summary = typed
|
||||
case string:
|
||||
if err := json.Unmarshal([]byte(typed), &summary); err != nil {
|
||||
return
|
||||
}
|
||||
default:
|
||||
raw, err := json.Marshal(typed)
|
||||
if err != nil || json.Unmarshal(raw, &summary) != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
// price_breakdown 含双方比例与加价明细,仅把当前角色可见的价格字段摊平到 summary,再删除原对象。
|
||||
if breakdown, ok := summary["price_breakdown"].(map[string]any); ok && breakdown != nil {
|
||||
switch role {
|
||||
case "owner":
|
||||
if v := readJSONNumber(breakdown["seller_ratio"]); v > 0 {
|
||||
summary["publish_ratio"] = v
|
||||
summary["display_ratio"] = v
|
||||
}
|
||||
if v := readJSONNumber(breakdown["seller_reference_ratio"]); v > 0 {
|
||||
summary["reference_ratio"] = v
|
||||
}
|
||||
if v := readJSONNumber(breakdown["seller_total_price"]); v > 0 {
|
||||
summary["display_total_price"] = v
|
||||
}
|
||||
if v := readJSONNumber(breakdown["seller_coin_base_price"]); v > 0 {
|
||||
summary["display_coin_base_price"] = v
|
||||
}
|
||||
if v := readJSONNumber(breakdown["accelerated_sale_ratio"]); v > 0 {
|
||||
summary["accelerated_sale_ratio"] = v
|
||||
}
|
||||
case "renter":
|
||||
if v := readJSONNumber(breakdown["buyer_ratio"]); v > 0 {
|
||||
summary["publish_ratio"] = v
|
||||
summary["display_ratio"] = v
|
||||
}
|
||||
if v := readJSONNumber(breakdown["buyer_total_price"]); v > 0 {
|
||||
summary["display_total_price"] = v
|
||||
}
|
||||
if v := readJSONNumber(breakdown["buyer_coin_base_price"]); v > 0 {
|
||||
summary["display_coin_base_price"] = v
|
||||
}
|
||||
}
|
||||
if v := readJSONNumber(breakdown["consumable_price"]); v > 0 {
|
||||
summary["consumable_price"] = v
|
||||
}
|
||||
if v := readJSONNumber(breakdown["daily_loss_ratio_adjustment"]); v != 0 {
|
||||
summary["daily_loss_ratio_adjustment"] = v
|
||||
}
|
||||
}
|
||||
delete(summary, "price_breakdown")
|
||||
payload["asset_summary"] = summary
|
||||
raw, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
*snapshot = datatypes.JSON(raw)
|
||||
}
|
||||
|
||||
func marshalStringList(items []string) (datatypes.JSON, error) {
|
||||
if items == nil {
|
||||
items = []string{}
|
||||
}
|
||||
raw, err := json.Marshal(items)
|
||||
return datatypes.JSON(raw), err
|
||||
}
|
||||
|
||||
func decodeStringList(raw datatypes.JSON) []string {
|
||||
if len(raw) == 0 {
|
||||
return []string{}
|
||||
}
|
||||
var items []string
|
||||
if err := json.Unmarshal(raw, &items); err != nil {
|
||||
return []string{}
|
||||
}
|
||||
return items
|
||||
}
|
||||
|
||||
func makeAccountSnapshot(account model.GameAccount, listing model.RentalListing) (datatypes.JSON, error) {
|
||||
payload := map[string]any{
|
||||
"listing_id": listing.ID,
|
||||
"listing_no": listing.ListingNo,
|
||||
"account_id": account.ID,
|
||||
"title": account.Title,
|
||||
"game_name": account.GameName,
|
||||
"server_region": account.ServerRegion,
|
||||
"login_platform": account.LoginPlatform,
|
||||
"rank_level": account.RankLevel,
|
||||
"haf_coin_amount": account.HafCoinAmount,
|
||||
"asset_summary": account.AssetSummary,
|
||||
"season_tags": account.SeasonTags,
|
||||
"screenshot_urls": account.ScreenshotURLS,
|
||||
"snapshot_version": 1,
|
||||
}
|
||||
raw, err := json.Marshal(payload)
|
||||
return datatypes.JSON(raw), err
|
||||
}
|
||||
Reference in New Issue
Block a user