package order import ( "time" "hfb_sys/backend/internal/model" "hfb_sys/backend/internal/modules/notification" "hfb_sys/backend/internal/modules/wallet" "gorm.io/gorm" ) func (r *Repository) finalizeCheckout(tx *gorm.DB, order *model.RentalOrder, checkout *model.OrderCheckout, renterContent string) (*refundAction, error) { listing, account, err := r.lockListingAccountForOrder(tx, order) if err != nil { return nil, err } now := time.Now() order.Status = orderStatusCompleted order.HandoffStatus = handoffStatusReturned order.SettlementStatus = settlementStatusSettled order.SettledAt = &now order.OwnerSettledAt = &now if err := completeAssets(tx, listing, account); err != nil { return nil, err } settlement := buildCheckoutSettlement(*order, checkout) if err := appendCheckoutOwnerIncome(tx, order, settlement); err != nil { return nil, err } refund, err := r.prepareCheckoutRefund(order, settlement) if err != nil { return nil, err } applyCheckoutSettlement(checkout, settlement) if err := appendCheckoutCompletedNotifications(tx, order, renterContent); err != nil { return nil, err } if err := saveFinalizedCheckout(tx, order, checkout, listing, account); err != nil { return nil, err } return refund, nil } func appendCheckoutOwnerIncome(tx *gorm.DB, order *model.RentalOrder, settlement checkoutSettlement) error { orderID := order.ID var ownerEntries []wallet.Entry if settlement.OwnerRentIncomeCent > 0 { ownerEntries = append(ownerEntries, wallet.Entry{ UserID: order.OwnerID, OrderID: &orderID, Direction: "in", AmountCent: settlement.OwnerRentIncomeCent, BalanceType: "available", BizType: walletBizOwnerIncome, BizNo: order.OrderNo, Remark: "订单结账租金收入", }) } if settlement.DepositCompensationCent > 0 { ownerEntries = append(ownerEntries, wallet.Entry{ UserID: order.OwnerID, OrderID: &orderID, Direction: "in", AmountCent: settlement.DepositCompensationCent, BalanceType: "available", BizType: walletBizDepositCompensation, BizNo: order.OrderNo, Remark: "订单结账押金赔付", }) } if len(ownerEntries) == 0 { return nil } return wallet.AppendEntries(tx, ownerEntries...) } func (r *Repository) prepareCheckoutRefund(order *model.RentalOrder, settlement checkoutSettlement) (*refundAction, error) { renterRefundTotalCent := settlement.RentRefundCent + settlement.DepositRefundCent // 押金暂扣:若订单已暂扣,拦截本次结账中应退还租客的押金部分挂起不退,其余(租金退款)照常原路退。 actualRefundCent := order.ApplyDepositHold(renterRefundTotalCent, settlement.DepositRefundCent) if actualRefundCent <= 0 { return nil, nil } return r.prepareRefund(order, actualRefundCent, refundBizCheckout, "结账退款原路退还") } func applyCheckoutSettlement(checkout *model.OrderCheckout, settlement checkoutSettlement) { checkout.RentAmountCent = settlement.ActualRentAmountCent checkout.OwnerRentAmountCent = settlement.OwnerRentIncomeCent checkout.PlatformFeeCent = settlement.PlatformFeeCent checkout.RenterRefundAmountCent = settlement.RenterRefundCent checkout.OwnerIncomeAmountCent = settlement.OwnerIncomeCent } func appendCheckoutCompletedNotifications(tx *gorm.DB, order *model.RentalOrder, renterContent string) error { orderID := order.ID return notification.Append(tx, notification.Entry{ UserID: order.RenterID, Type: "settlement", Title: "订单已完成", Content: renterContent, BizType: "order", BizID: &orderID, }, notification.Entry{ UserID: order.OwnerID, Type: "settlement", Title: "订单已完成", Content: "订单已完成,结账金额已入账。", BizType: "order", BizID: &orderID, }, ) } func saveFinalizedCheckout(tx *gorm.DB, order *model.RentalOrder, checkout *model.OrderCheckout, listing *model.RentalListing, account *model.GameAccount) error { if err := tx.Save(order).Error; err != nil { return err } if err := tx.Save(checkout).Error; err != nil { return err } if err := tx.Save(listing).Error; err != nil { return err } return tx.Save(account).Error } func hasOpenCheckout(tx *gorm.DB, orderID uint64) (bool, error) { var count int64 err := tx.Model(&model.OrderCheckout{}). Where("order_id = ? AND status IN ?", orderID, []string{checkoutStatusSubmitted, checkoutStatusCountered, checkoutStatusAccepted, checkoutStatusDisputed}). Count(&count).Error return count > 0, err }