chore: finalize amount migration fixes

This commit is contained in:
yml
2026-06-09 17:45:29 +08:00
parent 38c0ba69dc
commit 87673288ef
16 changed files with 214 additions and 2327 deletions
+6
View File
@@ -3,6 +3,7 @@
FROM golang:1.26-alpine AS build
WORKDIR /src
ARG GOOSE_VERSION=v3.27.1
ARG GOPROXY=https://goproxy.cn,direct
ARG GOSUMDB=sum.golang.google.cn
ENV GOPROXY=${GOPROXY} \
@@ -11,6 +12,9 @@ ENV GOPROXY=${GOPROXY} \
COPY go.mod go.sum* ./
RUN --mount=type=cache,target=/go/pkg/mod go mod download
COPY . .
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
go install github.com/pressly/goose/v3/cmd/goose@${GOOSE_VERSION}
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
CGO_ENABLED=0 GOOS=linux go build -o /out/hfb-api ./cmd/api
@@ -21,5 +25,7 @@ WORKDIR /app
ENV TZ=Asia/Shanghai
RUN apk add --no-cache tzdata
COPY --from=build /out/hfb-api /app/hfb-api
COPY --from=build /go/bin/goose /app/goose
COPY --from=build /src/migrations /app/migrations
EXPOSE 8080
CMD ["/app/hfb-api"]
@@ -30,27 +30,27 @@ func TestCalculateCheckoutSettlementRefundsUnusedRent(t *testing.T) {
settlement := calculateCheckoutSettlement(order, 7, 90, 0)
// 角精度:243.7 = roundMoney(236.7 + 7)
if float64(settlement.ActualRentAmountCent)/100 != 243.7 {
t.Fatalf("ActualRentAmount = %.1f, want 243.7", float64(settlement.ActualRentAmountCent)/100)
if settlement.ActualRentAmountCent != 24370 {
t.Fatalf("ActualRentAmountCent = %d, want 24370", settlement.ActualRentAmountCent)
}
// 角精度:216.7 = roundMoney(209.7 + 7) 卖家币价+消耗品
if float64(settlement.OwnerRentIncomeCent)/100 != 216.7 {
t.Fatalf("OwnerRentIncome = %.1f, want 216.7", float64(settlement.OwnerRentIncomeCent)/100)
if settlement.OwnerRentIncomeCent != 21670 {
t.Fatalf("OwnerRentIncomeCent = %d, want 21670", settlement.OwnerRentIncomeCent)
}
// 角精度:27.0 = roundMoney(27) 平台费
if float64(settlement.PlatformFeeCent)/100 != 27.0 {
t.Fatalf("PlatformFee = %.1f, want 27.0", float64(settlement.PlatformFeeCent)/100)
if settlement.PlatformFeeCent != 2700 {
t.Fatalf("PlatformFeeCent = %d, want 2700", settlement.PlatformFeeCent)
}
// 角精度:139.3 = roundMoney(383 - 243.7)
if float64(settlement.RentRefundCent)/100 != 139.3 {
t.Fatalf("RentRefund = %.1f, want 139.3", float64(settlement.RentRefundCent)/100)
if settlement.RentRefundCent != 13930 {
t.Fatalf("RentRefundCent = %d, want 13930", settlement.RentRefundCent)
}
if float64(settlement.DepositRefundCent)/100 != 150 {
t.Fatalf("DepositRefund = %.1f, want 150.0", float64(settlement.DepositRefundCent)/100)
if settlement.DepositRefundCent != 15000 {
t.Fatalf("DepositRefundCent = %d, want 15000", settlement.DepositRefundCent)
}
// 角精度:289.3 = roundMoney(139.3 + 150)
if float64(settlement.RenterRefundCent)/100 != 289.3 {
t.Fatalf("RenterRefund = %.1f, want 289.3", float64(settlement.RenterRefundCent)/100)
if settlement.RenterRefundCent != 28930 {
t.Fatalf("RenterRefundCent = %d, want 28930", settlement.RenterRefundCent)
}
}
@@ -74,16 +74,16 @@ func TestCalculateCheckoutSettlementUsesBuyerAndSellerRatiosSeparately(t *testin
settlement := calculateCheckoutSettlement(order, 0, 50, 0)
// 角精度:131.5 = roundMoney(131.5)
if float64(settlement.ActualRentAmountCent)/100 != 131.5 {
t.Fatalf("租客侧实际租金 = %.1f, want 131.5", float64(settlement.ActualRentAmountCent)/100)
if settlement.ActualRentAmountCent != 13150 {
t.Fatalf("租客侧实际租金 = %d, want 13150", settlement.ActualRentAmountCent)
}
// 角精度:116.5 = roundMoney(116.5)
if float64(settlement.OwnerRentIncomeCent)/100 != 116.5 {
t.Fatalf("卖家侧租金收入 = %.1f, want 116.5", float64(settlement.OwnerRentIncomeCent)/100)
if settlement.OwnerRentIncomeCent != 11650 {
t.Fatalf("卖家侧租金收入 = %d, want 11650", settlement.OwnerRentIncomeCent)
}
// 角精度:15.0 = roundMoney(15)
if float64(settlement.PlatformFeeCent)/100 != 15.0 {
t.Fatalf("平台差价 = %.1f, want 15.0", float64(settlement.PlatformFeeCent)/100)
if settlement.PlatformFeeCent != 1500 {
t.Fatalf("平台差价 = %d, want 1500", settlement.PlatformFeeCent)
}
}
@@ -106,20 +106,20 @@ func TestCalculateCheckoutSettlementAddsDepositCompensation(t *testing.T) {
settlement := calculateCheckoutSettlement(order, 120, 100, 30)
if float64(settlement.ActualRentAmountCent)/100 != 383 {
t.Fatalf("ActualRentAmount = %.2f, want 383.00", float64(settlement.ActualRentAmountCent)/100)
if settlement.ActualRentAmountCent != 38300 {
t.Fatalf("ActualRentAmountCent = %d, want 38300", settlement.ActualRentAmountCent)
}
if float64(settlement.OwnerRentIncomeCent)/100 != 353 {
t.Fatalf("OwnerRentIncome = %.2f, want 353.00", float64(settlement.OwnerRentIncomeCent)/100)
if settlement.OwnerRentIncomeCent != 35300 {
t.Fatalf("OwnerRentIncomeCent = %d, want 35300", settlement.OwnerRentIncomeCent)
}
if float64(settlement.DepositCompensationCent)/100 != 30 {
t.Fatalf("DepositCompensation = %.2f, want 30.00", float64(settlement.DepositCompensationCent)/100)
if settlement.DepositCompensationCent != 3000 {
t.Fatalf("DepositCompensationCent = %d, want 3000", settlement.DepositCompensationCent)
}
if float64(settlement.OwnerIncomeCent)/100 != 383 {
t.Fatalf("OwnerIncome = %.2f, want 383.00", float64(settlement.OwnerIncomeCent)/100)
if settlement.OwnerIncomeCent != 38300 {
t.Fatalf("OwnerIncomeCent = %d, want 38300", settlement.OwnerIncomeCent)
}
if float64(settlement.RenterRefundCent)/100 != 120 {
t.Fatalf("RenterRefund = %.2f, want 120.00", float64(settlement.RenterRefundCent)/100)
if settlement.RenterRefundCent != 12000 {
t.Fatalf("RenterRefundCent = %d, want 12000", settlement.RenterRefundCent)
}
}
+27
View File
@@ -4,6 +4,8 @@
-- 创建时间: 2026-06-05
-- ============================================
-- +goose Up
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
@@ -21,6 +23,7 @@ CREATE TABLE IF NOT EXISTS users (
risk_status VARCHAR(32) NOT NULL DEFAULT 'normal' COMMENT '风控状态: normal正常, warning警告, frozen冻结',
credit_score INT NOT NULL DEFAULT 100 COMMENT '信用分',
deposit_free_quota DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '免押总额度',
deposit_free_quota_cent BIGINT NOT NULL DEFAULT 0 COMMENT '免押总额度(分)',
status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT '账号状态: active活跃, inactive停用, banned封禁',
last_login_at DATETIME NULL COMMENT '最后登录时间',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
@@ -80,7 +83,9 @@ CREATE TABLE IF NOT EXISTS rental_listings (
account_id BIGINT UNSIGNED NOT NULL COMMENT '关联的游戏账号ID',
owner_id BIGINT UNSIGNED NOT NULL COMMENT '号主ID',
price DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '租金(元/小时)',
price_cent BIGINT NOT NULL DEFAULT 0 COMMENT '租金(分/小时)',
deposit_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '押金金额',
deposit_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '押金金额(分)',
in_transaction TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否正在交易中: 0否, 1是',
status VARCHAR(32) NOT NULL DEFAULT 'draft' COMMENT '商品状态: draft草稿, active上架, offline下架, deleted删除',
review_status VARCHAR(32) NOT NULL DEFAULT 'none' COMMENT '审核状态: none无需审核, pending待审核, approved通过, rejected拒绝',
@@ -118,11 +123,17 @@ CREATE TABLE IF NOT EXISTS rental_orders (
rented_at DATETIME NULL COMMENT '租用开始时间',
estimated_duration_hours INT NOT NULL DEFAULT 24 COMMENT '预计租用时长(小时)',
rent_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '租金总额',
rent_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '租金总额(分)',
owner_rent_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '号主实得租金',
owner_rent_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '号主实得租金(分)',
deposit_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '实际收取押金金额',
deposit_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '实际收取押金(分)',
deposit_original_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '商品原始押金金额',
deposit_original_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '商品原始押金(分)',
deposit_waived_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '本单免押抵扣金额',
deposit_waived_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '免押抵扣金额(分)',
platform_fee DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '平台手续费',
platform_fee_cent BIGINT NOT NULL DEFAULT 0 COMMENT '平台手续费(分)',
account_snapshot JSON NULL COMMENT '账号快照(下单时的账号状态)',
status VARCHAR(32) NOT NULL DEFAULT 'pending_payment' COMMENT '订单状态: pending_payment待支付, active进行中, completed已完成, cancelled已取消, closed已关闭',
handoff_status VARCHAR(32) NOT NULL DEFAULT 'none' COMMENT '交接状态: none未开始, owner_delivered号主已交, renter_confirmed租客已确认, renter_returned租客已还, owner_received号主已收',
@@ -151,15 +162,24 @@ CREATE TABLE IF NOT EXISTS order_checkouts (
initiated_by BIGINT UNSIGNED NOT NULL COMMENT '发起者ID',
status VARCHAR(32) NOT NULL DEFAULT 'submitted' COMMENT '结算状态: submitted已提交, renter_confirmed租客确认, renter_rejected租客拒绝, completed完成',
rent_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '租金',
rent_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '租金(分)',
owner_rent_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '号主实得租金',
owner_rent_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '号主实得租金(分)',
platform_fee DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '平台手续费',
platform_fee_cent BIGINT NOT NULL DEFAULT 0 COMMENT '平台手续费(分)',
deposit_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '押金',
deposit_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '押金(分)',
consumable_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '消耗品扣费',
consumable_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '消耗品扣费(分)',
coin_consumed_m DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '游戏币消耗(百万为单位)',
other_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '其他费用',
other_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '其他费用(分)',
deposit_deduct_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '押金扣除金额',
deposit_deduct_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '押金扣除金额(分)',
renter_refund_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '租客退款金额',
renter_refund_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '租客退款金额(分)',
owner_income_amount DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '号主收入金额',
owner_income_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '号主收入金额(分)',
content TEXT NULL COMMENT '结算说明',
evidence_urls JSON NULL COMMENT '证据截图URL列表',
owner_adjustment_reason TEXT NULL COMMENT '号主调整原因',
@@ -196,7 +216,9 @@ CREATE TABLE IF NOT EXISTS wallet_accounts (
id BIGINT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
user_id BIGINT UNSIGNED NOT NULL COMMENT '用户ID',
available_balance DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '可用余额',
available_balance_cent BIGINT NOT NULL DEFAULT 0 COMMENT '可用余额(分)',
frozen_balance DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '冻结余额',
frozen_balance_cent BIGINT NOT NULL DEFAULT 0 COMMENT '冻结余额(分)',
status VARCHAR(32) NOT NULL DEFAULT 'active' COMMENT '钱包状态: active正常, frozen冻结, closed关闭',
created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
@@ -211,7 +233,9 @@ CREATE TABLE IF NOT EXISTS wallet_ledger (
order_id BIGINT UNSIGNED NULL COMMENT '关联订单ID',
direction VARCHAR(16) NOT NULL COMMENT '方向: in收入, out支出',
amount DECIMAL(12,2) NOT NULL COMMENT '金额',
amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '金额(分)',
balance_after DECIMAL(12,2) NOT NULL COMMENT '变动后余额',
balance_after_cent BIGINT NOT NULL DEFAULT 0 COMMENT '变动后余额(分)',
balance_type VARCHAR(32) NOT NULL COMMENT '余额类型: available可用, frozen冻结',
biz_type VARCHAR(32) NOT NULL COMMENT '业务类型: rent_payment租金支付, deposit_freeze押金冻结, settlement结算, refund退款等',
biz_no VARCHAR(64) NOT NULL COMMENT '业务单号',
@@ -816,8 +840,11 @@ CREATE TABLE IF NOT EXISTS withdrawal_requests (
withdraw_no VARCHAR(64) NOT NULL COMMENT '提现单号',
user_id BIGINT UNSIGNED NOT NULL COMMENT '用户ID',
amount DECIMAL(12,2) NOT NULL COMMENT '提现金额',
amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '提现金额(分)',
fee DECIMAL(12,2) NOT NULL DEFAULT 0.00 COMMENT '手续费',
fee_cent BIGINT NOT NULL DEFAULT 0 COMMENT '手续费(分)',
actual_amount DECIMAL(12,2) NOT NULL COMMENT '实际到账金额',
actual_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '实际到账(分)',
-- 收款账号信息(快照)
payment_account_id BIGINT UNSIGNED NULL COMMENT '收款账号ID',