[Snow Team] backend-fixer: auto-commit work

This commit is contained in:
yml
2026-06-09 17:04:40 +08:00
parent f5b38ff772
commit 62b898d7cc
11 changed files with 291 additions and 214 deletions
+2 -1
View File
@@ -25,7 +25,8 @@ type FreezeRequest struct {
} }
type DepositFreeQuotaRequest struct { type DepositFreeQuotaRequest struct {
Amount float64 `json:"amount"` AmountCent int64 `json:"amount_cent"`
Amount float64 `json:"amount"`
} }
type PaginatedResult struct { type PaginatedResult struct {
@@ -2,6 +2,7 @@ package adminuser
import ( import (
"errors" "errors"
"math"
"hfb_sys/backend/internal/auditlog" "hfb_sys/backend/internal/auditlog"
"hfb_sys/backend/internal/model" "hfb_sys/backend/internal/model"
@@ -60,24 +61,29 @@ func (r *Repository) Unfreeze(adminID uint64, userID uint64, meta AuditMeta) (*U
} }
func (r *Repository) SetDepositFreeQuota(adminID uint64, userID uint64, req DepositFreeQuotaRequest, meta AuditMeta) (*UserDTO, error) { func (r *Repository) SetDepositFreeQuota(adminID uint64, userID uint64, req DepositFreeQuotaRequest, meta AuditMeta) (*UserDTO, error) {
amount := roundMoney(req.Amount) amountCent := depositFreeQuotaAmountCent(req)
if amount < 0 { if amountCent < 0 {
return nil, ErrInvalidUser return nil, ErrInvalidUser
} }
amount := float64(amountCent) / 100
err := r.db.Transaction(func(tx *gorm.DB) error { err := r.db.Transaction(func(tx *gorm.DB) error {
var user model.User var user model.User
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&user, userID).Error; err != nil { if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).First(&user, userID).Error; err != nil {
return err return err
} }
beforeAmount := user.DepositFreeQuota beforeAmount := user.DepositFreeQuota
beforeAmountCent := user.DepositFreeQuotaCent
user.DepositFreeQuota = amount user.DepositFreeQuota = amount
user.DepositFreeQuotaCent = amountCent
if err := tx.Save(&user).Error; err != nil { if err := tx.Save(&user).Error; err != nil {
return err return err
} }
return appendAuditLog(tx, adminID, "admin_user.set_deposit_free_quota", user.ID, meta, map[string]any{ return appendAuditLog(tx, adminID, "admin_user.set_deposit_free_quota", user.ID, meta, map[string]any{
"user_id": user.ID, "user_id": user.ID,
"before_amount": beforeAmount, "before_amount": beforeAmount,
"after_amount": amount, "after_amount": amount,
"before_amount_cent": beforeAmountCent,
"after_amount_cent": amountCent,
}) })
}) })
if err != nil { if err != nil {
@@ -172,6 +178,13 @@ func roundMoney(value float64) float64 {
return money.Round(value) return money.Round(value)
} }
func depositFreeQuotaAmountCent(req DepositFreeQuotaRequest) int64 {
if req.AmountCent != 0 {
return req.AmountCent
}
return int64(math.Round(req.Amount * 100))
}
func appendAuditLog(tx *gorm.DB, actorID uint64, action string, bizID uint64, meta AuditMeta, detail map[string]any) error { func appendAuditLog(tx *gorm.DB, actorID uint64, action string, bizID uint64, meta AuditMeta, detail map[string]any) error {
return auditlog.Append(tx, auditlog.Entry{ return auditlog.Append(tx, auditlog.Entry{
ActorType: "admin", ActorType: "admin",
+18 -9
View File
@@ -345,11 +345,20 @@ type arbitrationSettlement struct {
} }
func buildArbitrationSettlement(order model.RentalOrder, req ArbitrateRequest, renterFrozenBalance float64) (arbitrationSettlement, error) { func buildArbitrationSettlement(order model.RentalOrder, req ArbitrateRequest, renterFrozenBalance float64) (arbitrationSettlement, error) {
total := roundMoney(order.RentAmount + order.DepositAmount) rentAmount := float64(order.RentAmountCent) / 100
ownerRentAmount := roundMoney(order.OwnerRentAmount) if rentAmount <= 0 {
if ownerRentAmount <= 0 || ownerRentAmount > order.RentAmount { rentAmount = order.RentAmount
ownerRentAmount = roundMoney(order.RentAmount)
} }
depositAmount := float64(order.DepositAmountCent) / 100
if depositAmount <= 0 {
depositAmount = order.DepositAmount
}
ownerRentAmount := float64(order.OwnerRentAmountCent) / 100
if ownerRentAmount <= 0 || ownerRentAmount > rentAmount {
ownerRentAmount = rentAmount
}
total := roundMoney(rentAmount + depositAmount)
ownerRentAmount = roundMoney(ownerRentAmount)
settlement := arbitrationSettlement{} settlement := arbitrationSettlement{}
orderID := order.ID orderID := order.ID
releaseFrozenAmount := minMoney(total, roundMoney(renterFrozenBalance)) releaseFrozenAmount := minMoney(total, roundMoney(renterFrozenBalance))
@@ -398,21 +407,21 @@ func buildArbitrationSettlement(order model.RentalOrder, req ArbitrateRequest, r
return settlement, ErrInvalidDispute return settlement, ErrInvalidDispute
} }
addRenterRefund(req.Amount, "仲裁部分退款") addRenterRefund(req.Amount, "仲裁部分退款")
addOwnerIncome(minMoney(total-req.Amount, ownerRentAmount+order.DepositAmount), "仲裁剩余金额结算给号主") addOwnerIncome(minMoney(total-req.Amount, ownerRentAmount+depositAmount), "仲裁剩余金额结算给号主")
case "release_deposit": case "release_deposit":
addOwnerIncome(ownerRentAmount, "仲裁确认订单金额结算给号主") addOwnerIncome(ownerRentAmount, "仲裁确认订单金额结算给号主")
addRenterRefund(order.DepositAmount, "仲裁释放押金给租客") addRenterRefund(depositAmount, "仲裁释放押金给租客")
case "deduct_deposit", "compensate_owner": case "deduct_deposit", "compensate_owner":
deductAmount := roundMoney(req.Amount) deductAmount := roundMoney(req.Amount)
if deductAmount <= 0 { if deductAmount <= 0 {
deductAmount = order.DepositAmount deductAmount = depositAmount
} }
if deductAmount > order.DepositAmount { if deductAmount > depositAmount {
return settlement, ErrInvalidDispute return settlement, ErrInvalidDispute
} }
settlement.DepositDeductAmount = deductAmount settlement.DepositDeductAmount = deductAmount
addOwnerIncome(ownerRentAmount+deductAmount, "仲裁订单金额及押金赔付结算给号主") addOwnerIncome(ownerRentAmount+deductAmount, "仲裁订单金额及押金赔付结算给号主")
addRenterRefund(order.DepositAmount-deductAmount, "仲裁退回剩余押金给租客") addRenterRefund(depositAmount-deductAmount, "仲裁退回剩余押金给租客")
case "order_close": case "order_close":
// Only release frozen funds. No available-balance settlement happens in development mode. // Only release frozen funds. No available-balance settlement happens in development mode.
case "mark_abnormal": case "mark_abnormal":
@@ -9,13 +9,13 @@ import (
func TestBuildArbitrationSettlementSkipsFrozenReleaseWhenNoFrozenBalance(t *testing.T) { func TestBuildArbitrationSettlementSkipsFrozenReleaseWhenNoFrozenBalance(t *testing.T) {
order := model.RentalOrder{ order := model.RentalOrder{
ID: 11, ID: 11,
OrderNo: "RO202606080001", OrderNo: "RO202606080001",
RenterID: 101, RenterID: 101,
OwnerID: 202, OwnerID: 202,
RentAmount: 200, RentAmountCent: 20000,
OwnerRentAmount: 180, OwnerRentAmountCent: 18000,
DepositAmount: 100, DepositAmountCent: 10000,
} }
settlement, err := buildArbitrationSettlement(order, ArbitrateRequest{ settlement, err := buildArbitrationSettlement(order, ArbitrateRequest{
@@ -46,13 +46,13 @@ func TestBuildArbitrationSettlementSkipsFrozenReleaseWhenNoFrozenBalance(t *test
func TestBuildArbitrationSettlementLimitsFrozenReleaseToExistingBalance(t *testing.T) { func TestBuildArbitrationSettlementLimitsFrozenReleaseToExistingBalance(t *testing.T) {
order := model.RentalOrder{ order := model.RentalOrder{
ID: 12, ID: 12,
OrderNo: "RO202606080002", OrderNo: "RO202606080002",
RenterID: 101, RenterID: 101,
OwnerID: 202, OwnerID: 202,
RentAmount: 200, RentAmountCent: 20000,
OwnerRentAmount: 180, OwnerRentAmountCent: 18000,
DepositAmount: 100, DepositAmountCent: 10000,
} }
settlement, err := buildArbitrationSettlement(order, ArbitrateRequest{ settlement, err := buildArbitrationSettlement(order, ArbitrateRequest{
@@ -69,8 +69,8 @@ func TestBuildArbitrationSettlementLimitsFrozenReleaseToExistingBalance(t *testi
continue continue
} }
releaseEntryCount++ releaseEntryCount++
if entry.Amount != 120 { if entry.AmountCent != 12000 {
t.Fatalf("release frozen amount = %.1f, want 120.0", entry.Amount) t.Fatalf("release frozen amount cent = %d, want 12000", entry.AmountCent)
} }
} }
if releaseEntryCount != 1 { if releaseEntryCount != 1 {
+29 -23
View File
@@ -82,14 +82,16 @@ func (r *Repository) Create(ownerID uint64, req CreateRequest, reviewRequired bo
price := normalizedListingPrice(req) price := normalizedListingPrice(req)
depositAmount := roundMoney(req.DepositAmount) depositAmount := roundMoney(req.DepositAmount)
listing := model.RentalListing{ listing := model.RentalListing{
ListingNo: listingNo, ListingNo: listingNo,
AccountID: account.ID, AccountID: account.ID,
OwnerID: ownerID, OwnerID: ownerID,
Price: price, Price: price,
DepositAmount: depositAmount, PriceCent: int64(math.Round(price * 100)),
Status: listingStatus, DepositAmount: depositAmount,
ReviewStatus: reviewStatus, DepositAmountCent: int64(math.Round(depositAmount * 100)),
PublishedAt: publishedAt, Status: listingStatus,
ReviewStatus: reviewStatus,
PublishedAt: publishedAt,
} }
if err := tx.Create(&listing).Error; err != nil { if err := tx.Create(&listing).Error; err != nil {
return err return err
@@ -147,14 +149,18 @@ func (r *Repository) CreateFromExternalUpload(upload externalUploadCreate, req C
if err := tx.Create(&account).Error; err != nil { if err := tx.Create(&account).Error; err != nil {
return err return err
} }
price := normalizedListingPrice(req)
depositAmount := roundMoney(req.DepositAmount)
listing := model.RentalListing{ listing := model.RentalListing{
ListingNo: listingNo, ListingNo: listingNo,
AccountID: account.ID, AccountID: account.ID,
OwnerID: owner.ID, OwnerID: owner.ID,
Price: normalizedListingPrice(req), Price: price,
DepositAmount: roundMoney(req.DepositAmount), PriceCent: int64(math.Round(price * 100)),
Status: "draft", DepositAmount: depositAmount,
ReviewStatus: "pending", DepositAmountCent: int64(math.Round(depositAmount * 100)),
Status: "draft",
ReviewStatus: "pending",
} }
if err := tx.Create(&listing).Error; err != nil { if err := tx.Create(&listing).Error; err != nil {
return err return err
@@ -1439,14 +1445,14 @@ func (row listingRow) toDTO() ListingDTO {
screenshotURLS := cleanScreenshotURLs(decodeScreenshots(row.ScreenshotURLS)) screenshotURLS := cleanScreenshotURLs(decodeScreenshots(row.ScreenshotURLS))
reviewStatus, reviewReason := normalizedReviewState(row.Status, row.ReviewStatus, row.ReviewReason) reviewStatus, reviewReason := normalizedReviewState(row.Status, row.ReviewStatus, row.ReviewReason)
return ListingDTO{ return ListingDTO{
ID: row.ID, ID: row.ID,
ListingNo: row.ListingNo, ListingNo: row.ListingNo,
AccountID: row.AccountID, AccountID: row.AccountID,
OwnerID: row.OwnerID, OwnerID: row.OwnerID,
OwnerPhone: row.OwnerPhone, OwnerPhone: row.OwnerPhone,
OwnerNickname: row.OwnerNickname, OwnerNickname: row.OwnerNickname,
Title: row.Title, Title: row.Title,
Description: row.Description, Description: row.Description,
GameName: row.GameName, GameName: row.GameName,
ServerRegion: row.ServerRegion, ServerRegion: row.ServerRegion,
LoginPlatform: row.LoginPlatform, LoginPlatform: row.LoginPlatform,
@@ -69,7 +69,7 @@ func TestCreateRequiresPublishAgreements(t *testing.T) {
func TestApplySellerListingPriceUsesSellerTotalPrice(t *testing.T) { func TestApplySellerListingPriceUsesSellerTotalPrice(t *testing.T) {
item := &ListingDTO{ item := &ListingDTO{
Price: 238, PriceCent: 23800,
AssetSummary: map[string]any{ AssetSummary: map[string]any{
"price_breakdown": map[string]any{ "price_breakdown": map[string]any{
"seller_total_price": 200, "seller_total_price": 200,
@@ -79,14 +79,14 @@ func TestApplySellerListingPriceUsesSellerTotalPrice(t *testing.T) {
applySellerListingPrice(item) applySellerListingPrice(item)
if item.Price != 200 { if item.PriceCent != 20000 {
t.Fatalf("expected seller price 200, got %.2f", item.Price) t.Fatalf("expected seller price 20000, got %d", item.PriceCent)
} }
} }
func TestApplySellerListingPriceKeepsFallbackPrice(t *testing.T) { func TestApplySellerListingPriceKeepsFallbackPrice(t *testing.T) {
item := &ListingDTO{ item := &ListingDTO{
Price: 238, PriceCent: 23800,
AssetSummary: map[string]any{ AssetSummary: map[string]any{
"price_breakdown": map[string]any{ "price_breakdown": map[string]any{
"seller_total_price": 0, "seller_total_price": 0,
@@ -96,8 +96,8 @@ func TestApplySellerListingPriceKeepsFallbackPrice(t *testing.T) {
applySellerListingPrice(item) applySellerListingPrice(item)
if item.Price != 238 { if item.PriceCent != 23800 {
t.Fatalf("expected fallback price 238, got %.2f", item.Price) t.Fatalf("expected fallback price 23800, got %d", item.PriceCent)
} }
} }
+33 -18
View File
@@ -185,11 +185,17 @@ func (r *Repository) Create(renterID uint64, req CreateRequest) (*OrderDTO, erro
OwnerID: listing.OwnerID, OwnerID: listing.OwnerID,
RenterID: renterID, RenterID: renterID,
EstimatedDurationHours: rentHours, EstimatedDurationHours: rentHours,
RentAmount: float64(pricing.RentAmountCent) / 100,
RentAmountCent: pricing.RentAmountCent, RentAmountCent: pricing.RentAmountCent,
OwnerRentAmount: float64(pricing.OwnerRentAmountCent) / 100,
OwnerRentAmountCent: pricing.OwnerRentAmountCent, OwnerRentAmountCent: pricing.OwnerRentAmountCent,
DepositAmount: paidDepositAmount,
DepositAmountCent: int64(math.Round(paidDepositAmount * 100)), DepositAmountCent: int64(math.Round(paidDepositAmount * 100)),
DepositOriginalAmount: depositOriginalAmount,
DepositOriginalAmountCent: int64(math.Round(depositOriginalAmount * 100)), DepositOriginalAmountCent: int64(math.Round(depositOriginalAmount * 100)),
DepositWaivedAmount: waivedDepositAmount,
DepositWaivedAmountCent: int64(math.Round(waivedDepositAmount * 100)), DepositWaivedAmountCent: int64(math.Round(waivedDepositAmount * 100)),
PlatformFee: float64(pricing.PlatformFeeCent) / 100,
PlatformFeeCent: pricing.PlatformFeeCent, PlatformFeeCent: pricing.PlatformFeeCent,
AccountSnapshot: snapshot, AccountSnapshot: snapshot,
Status: "pending_payment", Status: "pending_payment",
@@ -690,10 +696,10 @@ func (r *Repository) CounterCheckout(userID uint64, orderID uint64, req CounterC
return nil, err return nil, err
} }
dto := toCheckoutDTOForUser(*checkout, userID, model.RentalOrder{ dto := toCheckoutDTOForUser(*checkout, userID, model.RentalOrder{
OwnerID: userID, OwnerID: userID,
RentAmountCent: int64(math.Round(checkout.RentAmount * 100)), RentAmountCent: int64(math.Round(checkout.RentAmount * 100)),
OwnerRentAmountCent: int64(math.Round(checkout.OwnerRentAmount * 100)), OwnerRentAmountCent: int64(math.Round(checkout.OwnerRentAmount * 100)),
DepositAmountCent: int64(math.Round(checkout.DepositAmount * 100)), DepositAmountCent: int64(math.Round(checkout.DepositAmount * 100)),
}) })
return &dto, nil return &dto, nil
} }
@@ -1244,21 +1250,30 @@ func buildCheckout(order model.RentalOrder, initiatedBy uint64, status string, c
return model.OrderCheckout{}, err return model.OrderCheckout{}, err
} }
return model.OrderCheckout{ return model.OrderCheckout{
OrderID: order.ID, OrderID: order.ID,
InitiatedBy: initiatedBy, InitiatedBy: initiatedBy,
Status: status, Status: status,
RentAmount: float64(settlement.ActualRentAmountCent) / 100, RentAmount: float64(settlement.ActualRentAmountCent) / 100,
OwnerRentAmount: float64(settlement.OwnerRentIncomeCent) / 100, RentAmountCent: settlement.ActualRentAmountCent,
PlatformFee: float64(settlement.PlatformFeeCent) / 100, OwnerRentAmount: float64(settlement.OwnerRentIncomeCent) / 100,
DepositAmount: depositAmountFromCent, OwnerRentAmountCent: settlement.OwnerRentIncomeCent,
ConsumableAmount: consumableAmount, PlatformFee: float64(settlement.PlatformFeeCent) / 100,
CoinConsumedM: roundQuantity(coinConsumedM), PlatformFeeCent: settlement.PlatformFeeCent,
OtherAmount: otherAmount, DepositAmount: depositAmountFromCent,
DepositDeductAmount: roundMoney(deductAmount), DepositAmountCent: order.DepositAmountCent,
RenterRefundAmount: float64(settlement.RenterRefundCent) / 100, ConsumableAmount: consumableAmount,
OwnerIncomeAmount: float64(settlement.OwnerIncomeCent) / 100, ConsumableAmountCent: int64(math.Round(consumableAmount * 100)),
Content: content, CoinConsumedM: roundQuantity(coinConsumedM),
EvidenceURLS: evidence, OtherAmount: otherAmount,
OtherAmountCent: int64(math.Round(otherAmount * 100)),
DepositDeductAmount: roundMoney(deductAmount),
DepositDeductAmountCent: settlement.DepositCompensationCent,
RenterRefundAmount: float64(settlement.RenterRefundCent) / 100,
RenterRefundAmountCent: settlement.RenterRefundCent,
OwnerIncomeAmount: float64(settlement.OwnerIncomeCent) / 100,
OwnerIncomeAmountCent: settlement.OwnerIncomeCent,
Content: content,
EvidenceURLS: evidence,
}, nil }, nil
} }
@@ -12,9 +12,9 @@ import (
func TestCalculateCheckoutSettlementRefundsUnusedRent(t *testing.T) { func TestCalculateCheckoutSettlementRefundsUnusedRent(t *testing.T) {
order := model.RentalOrder{ order := model.RentalOrder{
RentAmount: 383, RentAmountCent: 38300,
OwnerRentAmount: 353, OwnerRentAmountCent: 35300,
DepositAmount: 150, DepositAmountCent: 15000,
AccountSnapshot: datatypes.JSON([]byte(`{ AccountSnapshot: datatypes.JSON([]byte(`{
"haf_coin_amount": 100000000, "haf_coin_amount": 100000000,
"asset_summary": { "asset_summary": {
@@ -30,35 +30,35 @@ func TestCalculateCheckoutSettlementRefundsUnusedRent(t *testing.T) {
settlement := calculateCheckoutSettlement(order, 7, 90, 0) settlement := calculateCheckoutSettlement(order, 7, 90, 0)
// 角精度:243.7 = roundMoney(236.7 + 7) // 角精度:243.7 = roundMoney(236.7 + 7)
if settlement.ActualRentAmount != 243.7 { if float64(settlement.ActualRentAmountCent)/100 != 243.7 {
t.Fatalf("ActualRentAmount = %.1f, want 243.7", settlement.ActualRentAmount) t.Fatalf("ActualRentAmount = %.1f, want 243.7", float64(settlement.ActualRentAmountCent)/100)
} }
// 角精度:216.7 = roundMoney(209.7 + 7) 卖家币价+消耗品 // 角精度:216.7 = roundMoney(209.7 + 7) 卖家币价+消耗品
if settlement.OwnerRentIncome != 216.7 { if float64(settlement.OwnerRentIncomeCent)/100 != 216.7 {
t.Fatalf("OwnerRentIncome = %.1f, want 216.7", settlement.OwnerRentIncome) t.Fatalf("OwnerRentIncome = %.1f, want 216.7", float64(settlement.OwnerRentIncomeCent)/100)
} }
// 角精度:27.0 = roundMoney(27) 平台费 // 角精度:27.0 = roundMoney(27) 平台费
if settlement.PlatformFee != 27.0 { if float64(settlement.PlatformFeeCent)/100 != 27.0 {
t.Fatalf("PlatformFee = %.1f, want 27.0", settlement.PlatformFee) t.Fatalf("PlatformFee = %.1f, want 27.0", float64(settlement.PlatformFeeCent)/100)
} }
// 角精度:139.3 = roundMoney(383 - 243.7) // 角精度:139.3 = roundMoney(383 - 243.7)
if settlement.RentRefund != 139.3 { if float64(settlement.RentRefundCent)/100 != 139.3 {
t.Fatalf("RentRefund = %.1f, want 139.3", settlement.RentRefund) t.Fatalf("RentRefund = %.1f, want 139.3", float64(settlement.RentRefundCent)/100)
} }
if settlement.DepositRefund != 150 { if float64(settlement.DepositRefundCent)/100 != 150 {
t.Fatalf("DepositRefund = %.1f, want 150.0", settlement.DepositRefund) t.Fatalf("DepositRefund = %.1f, want 150.0", float64(settlement.DepositRefundCent)/100)
} }
// 角精度:289.3 = roundMoney(139.3 + 150) // 角精度:289.3 = roundMoney(139.3 + 150)
if settlement.RenterRefund != 289.3 { if float64(settlement.RenterRefundCent)/100 != 289.3 {
t.Fatalf("RenterRefund = %.1f, want 289.3", settlement.RenterRefund) t.Fatalf("RenterRefund = %.1f, want 289.3", float64(settlement.RenterRefundCent)/100)
} }
} }
func TestCalculateCheckoutSettlementUsesBuyerAndSellerRatiosSeparately(t *testing.T) { func TestCalculateCheckoutSettlementUsesBuyerAndSellerRatiosSeparately(t *testing.T) {
order := model.RentalOrder{ order := model.RentalOrder{
RentAmount: 383, RentAmountCent: 38300,
OwnerRentAmount: 353, OwnerRentAmountCent: 35300,
DepositAmount: 150, DepositAmountCent: 15000,
AccountSnapshot: datatypes.JSON([]byte(`{ AccountSnapshot: datatypes.JSON([]byte(`{
"haf_coin_amount": 100000000, "haf_coin_amount": 100000000,
"asset_summary": { "asset_summary": {
@@ -74,24 +74,24 @@ func TestCalculateCheckoutSettlementUsesBuyerAndSellerRatiosSeparately(t *testin
settlement := calculateCheckoutSettlement(order, 0, 50, 0) settlement := calculateCheckoutSettlement(order, 0, 50, 0)
// 角精度:131.5 = roundMoney(131.5) // 角精度:131.5 = roundMoney(131.5)
if settlement.ActualRentAmount != 131.5 { if float64(settlement.ActualRentAmountCent)/100 != 131.5 {
t.Fatalf("租客侧实际租金 = %.1f, want 131.5", settlement.ActualRentAmount) t.Fatalf("租客侧实际租金 = %.1f, want 131.5", float64(settlement.ActualRentAmountCent)/100)
} }
// 角精度:116.5 = roundMoney(116.5) // 角精度:116.5 = roundMoney(116.5)
if settlement.OwnerRentIncome != 116.5 { if float64(settlement.OwnerRentIncomeCent)/100 != 116.5 {
t.Fatalf("卖家侧租金收入 = %.1f, want 116.5", settlement.OwnerRentIncome) t.Fatalf("卖家侧租金收入 = %.1f, want 116.5", float64(settlement.OwnerRentIncomeCent)/100)
} }
// 角精度:15.0 = roundMoney(15) // 角精度:15.0 = roundMoney(15)
if settlement.PlatformFee != 15.0 { if float64(settlement.PlatformFeeCent)/100 != 15.0 {
t.Fatalf("平台差价 = %.1f, want 15.0", settlement.PlatformFee) t.Fatalf("平台差价 = %.1f, want 15.0", float64(settlement.PlatformFeeCent)/100)
} }
} }
func TestCalculateCheckoutSettlementAddsDepositCompensation(t *testing.T) { func TestCalculateCheckoutSettlementAddsDepositCompensation(t *testing.T) {
order := model.RentalOrder{ order := model.RentalOrder{
RentAmount: 383, RentAmountCent: 38300,
OwnerRentAmount: 353, OwnerRentAmountCent: 35300,
DepositAmount: 150, DepositAmountCent: 15000,
AccountSnapshot: datatypes.JSON([]byte(`{ AccountSnapshot: datatypes.JSON([]byte(`{
"haf_coin_amount": 100000000, "haf_coin_amount": 100000000,
"asset_summary": { "asset_summary": {
@@ -106,20 +106,20 @@ func TestCalculateCheckoutSettlementAddsDepositCompensation(t *testing.T) {
settlement := calculateCheckoutSettlement(order, 120, 100, 30) settlement := calculateCheckoutSettlement(order, 120, 100, 30)
if settlement.ActualRentAmount != 383 { if float64(settlement.ActualRentAmountCent)/100 != 383 {
t.Fatalf("ActualRentAmount = %.2f, want 383.00", settlement.ActualRentAmount) t.Fatalf("ActualRentAmount = %.2f, want 383.00", float64(settlement.ActualRentAmountCent)/100)
} }
if settlement.OwnerRentIncome != 353 { if float64(settlement.OwnerRentIncomeCent)/100 != 353 {
t.Fatalf("OwnerRentIncome = %.2f, want 353.00", settlement.OwnerRentIncome) t.Fatalf("OwnerRentIncome = %.2f, want 353.00", float64(settlement.OwnerRentIncomeCent)/100)
} }
if settlement.DepositCompensation != 30 { if float64(settlement.DepositCompensationCent)/100 != 30 {
t.Fatalf("DepositCompensation = %.2f, want 30.00", settlement.DepositCompensation) t.Fatalf("DepositCompensation = %.2f, want 30.00", float64(settlement.DepositCompensationCent)/100)
} }
if settlement.OwnerIncome != 383 { if float64(settlement.OwnerIncomeCent)/100 != 383 {
t.Fatalf("OwnerIncome = %.2f, want 383.00", settlement.OwnerIncome) t.Fatalf("OwnerIncome = %.2f, want 383.00", float64(settlement.OwnerIncomeCent)/100)
} }
if settlement.RenterRefund != 120 { if float64(settlement.RenterRefundCent)/100 != 120 {
t.Fatalf("RenterRefund = %.2f, want 120.00", settlement.RenterRefund) t.Fatalf("RenterRefund = %.2f, want 120.00", float64(settlement.RenterRefundCent)/100)
} }
} }
@@ -9,13 +9,13 @@ import (
func TestApplyEntryRoundsMoneyBeforeComparing(t *testing.T) { func TestApplyEntryRoundsMoneyBeforeComparing(t *testing.T) {
account := model.WalletAccount{ account := model.WalletAccount{
UserID: 7, UserID: 7,
FrozenBalance: 606.41, FrozenBalanceCent: 60641,
} }
entry := Entry{ entry := Entry{
UserID: 7, UserID: 7,
Direction: "out", Direction: "out",
Amount: 406.41 + 200.00, AmountCent: 60641,
BalanceType: "frozen", BalanceType: "frozen",
} }
@@ -26,20 +26,20 @@ func TestApplyEntryRoundsMoneyBeforeComparing(t *testing.T) {
if balanceAfter != 0 { if balanceAfter != 0 {
t.Fatalf("balanceAfter = %v, want 0", balanceAfter) t.Fatalf("balanceAfter = %v, want 0", balanceAfter)
} }
if account.FrozenBalance != 0 { if account.FrozenBalanceCent != 0 {
t.Fatalf("FrozenBalance = %v, want 0", account.FrozenBalance) t.Fatalf("FrozenBalanceCent = %d, want 0", account.FrozenBalanceCent)
} }
} }
func TestApplyEntryKeepsWalletMoneyAtJiaoPrecision(t *testing.T) { func TestApplyEntryKeepsWalletMoneyAtJiaoPrecision(t *testing.T) {
account := model.WalletAccount{ account := model.WalletAccount{
UserID: 8, UserID: 8,
AvailableBalance: 0, AvailableBalanceCent: 0,
} }
entry := Entry{ entry := Entry{
UserID: 8, UserID: 8,
Direction: "in", Direction: "in",
Amount: 2.30, AmountCent: 230,
BalanceType: "available", BalanceType: "available",
} }
@@ -47,11 +47,11 @@ func TestApplyEntryKeepsWalletMoneyAtJiaoPrecision(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("applyEntry() error = %v", err) t.Fatalf("applyEntry() error = %v", err)
} }
if balanceAfter != 2.3 { if balanceAfter != 230 {
t.Fatalf("balanceAfter = %v, want 2.3", balanceAfter) t.Fatalf("balanceAfter = %d, want 230", balanceAfter)
} }
if account.AvailableBalance != 2.3 { if account.AvailableBalanceCent != 230 {
t.Fatalf("AvailableBalance = %v, want 2.3", account.AvailableBalance) t.Fatalf("AvailableBalanceCent = %d, want 230", account.AvailableBalanceCent)
} }
if rounded := roundWalletMoney(2.36); rounded != 2.4 { if rounded := roundWalletMoney(2.36); rounded != 2.4 {
@@ -58,8 +58,11 @@ func (r *Repository) Create(userID uint64, req CreateWithdrawalRequest) (*Withdr
withdrawal := model.WithdrawalRequest{ withdrawal := model.WithdrawalRequest{
WithdrawNo: withdrawNo, WithdrawNo: withdrawNo,
UserID: userID, UserID: userID,
Amount: float64(req.AmountCent) / 100,
AmountCent: req.AmountCent, AmountCent: req.AmountCent,
Fee: float64(feeCent) / 100,
FeeCent: feeCent, FeeCent: feeCent,
ActualAmount: float64(actualAmountCent) / 100,
ActualAmountCent: actualAmountCent, ActualAmountCent: actualAmountCent,
PaymentAccountID: &req.PaymentAccountID, PaymentAccountID: &req.PaymentAccountID,
AccountType: paymentAccount.AccountType, AccountType: paymentAccount.AccountType,
@@ -8,49 +8,61 @@
-- 用户表:免押额度 -- 用户表:免押额度
ALTER TABLE users ALTER TABLE users
ADD COLUMN deposit_free_quota_cent BIGINT NOT NULL DEFAULT 0 COMMENT '免押总额度(分)' AFTER deposit_free_quota; ADD COLUMN IF NOT EXISTS deposit_free_quota_cent BIGINT NOT NULL DEFAULT 0 COMMENT '免押总额度(分)' AFTER deposit_free_quota;
-- 商品表:价格和押金 -- 商品表:价格和押金
ALTER TABLE rental_listings ALTER TABLE rental_listings
ADD COLUMN price_cent BIGINT NOT NULL DEFAULT 0 COMMENT '租金(分/小时)' AFTER price, ADD COLUMN IF NOT EXISTS price_cent BIGINT NOT NULL DEFAULT 0 COMMENT '租金(分/小时)' AFTER price,
ADD COLUMN deposit_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '押金金额(分)' AFTER deposit_amount; ADD COLUMN IF NOT EXISTS deposit_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '押金金额(分)' AFTER deposit_amount;
-- 订单表:租金、押金、平台费 -- 订单表:租金、押金、平台费
ALTER TABLE rental_orders ALTER TABLE rental_orders
ADD COLUMN rent_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '租金总额(分)' AFTER rent_amount, ADD COLUMN IF NOT EXISTS rent_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '租金总额(分)' AFTER rent_amount,
ADD COLUMN owner_rent_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '号主实得租金(分)' AFTER owner_rent_amount, ADD COLUMN IF NOT EXISTS owner_rent_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '号主实得租金(分)' AFTER owner_rent_amount,
ADD COLUMN deposit_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '实际收取押金(分)' AFTER deposit_amount, ADD COLUMN IF NOT EXISTS deposit_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '实际收取押金(分)' AFTER deposit_amount,
ADD COLUMN deposit_original_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '商品原始押金(分)' AFTER deposit_original_amount, ADD COLUMN IF NOT EXISTS deposit_original_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '商品原始押金(分)' AFTER deposit_original_amount,
ADD COLUMN deposit_waived_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '免押抵扣金额(分)' AFTER deposit_waived_amount, ADD COLUMN IF NOT EXISTS deposit_waived_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '免押抵扣金额(分)' AFTER deposit_waived_amount,
ADD COLUMN platform_fee_cent BIGINT NOT NULL DEFAULT 0 COMMENT '平台手续费(分)' AFTER platform_fee; ADD COLUMN IF NOT EXISTS platform_fee_cent BIGINT NOT NULL DEFAULT 0 COMMENT '平台手续费(分)' AFTER platform_fee;
-- 结算记录表:所有金额字段 -- 结算记录表:所有金额字段
ALTER TABLE order_checkouts ALTER TABLE order_checkouts
ADD COLUMN rent_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '租金(分)' AFTER rent_amount, ADD COLUMN IF NOT EXISTS rent_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '租金(分)' AFTER rent_amount,
ADD COLUMN owner_rent_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '号主实得租金(分)' AFTER owner_rent_amount, ADD COLUMN IF NOT EXISTS owner_rent_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '号主实得租金(分)' AFTER owner_rent_amount,
ADD COLUMN platform_fee_cent BIGINT NOT NULL DEFAULT 0 COMMENT '平台手续费(分)' AFTER platform_fee, ADD COLUMN IF NOT EXISTS platform_fee_cent BIGINT NOT NULL DEFAULT 0 COMMENT '平台手续费(分)' AFTER platform_fee,
ADD COLUMN deposit_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '押金(分)' AFTER deposit_amount, ADD COLUMN IF NOT EXISTS deposit_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '押金(分)' AFTER deposit_amount,
ADD COLUMN consumable_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '消耗品扣费(分)' AFTER consumable_amount, ADD COLUMN IF NOT EXISTS consumable_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '消耗品扣费(分)' AFTER consumable_amount,
ADD COLUMN other_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '其他费用(分)' AFTER other_amount, ADD COLUMN IF NOT EXISTS other_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '其他费用(分)' AFTER other_amount,
ADD COLUMN deposit_deduct_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '押金扣除金额(分)' AFTER deposit_deduct_amount, ADD COLUMN IF NOT EXISTS deposit_deduct_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '押金扣除金额(分)' AFTER deposit_deduct_amount,
ADD COLUMN renter_refund_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '租客退款金额(分)' AFTER renter_refund_amount, ADD COLUMN IF NOT EXISTS renter_refund_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '租客退款金额(分)' AFTER renter_refund_amount,
ADD COLUMN owner_income_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '号主收入金额(分)' AFTER owner_income_amount; ADD COLUMN IF NOT EXISTS owner_income_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '号主收入金额(分)' AFTER owner_income_amount;
-- 钱包账户表:余额 -- 钱包账户表:余额
ALTER TABLE wallet_accounts ALTER TABLE wallet_accounts
ADD COLUMN available_balance_cent BIGINT NOT NULL DEFAULT 0 COMMENT '可用余额(分)' AFTER available_balance, ADD COLUMN IF NOT EXISTS available_balance_cent BIGINT NOT NULL DEFAULT 0 COMMENT '可用余额(分)' AFTER available_balance,
ADD COLUMN frozen_balance_cent BIGINT NOT NULL DEFAULT 0 COMMENT '冻结余额(分)' AFTER frozen_balance; ADD COLUMN IF NOT EXISTS frozen_balance_cent BIGINT NOT NULL DEFAULT 0 COMMENT '冻结余额(分)' AFTER frozen_balance;
-- 钱包流水表:金额和余额 -- 钱包流水表:金额和余额
ALTER TABLE wallet_ledger ALTER TABLE wallet_ledger
ADD COLUMN amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '金额(分)' AFTER amount, ADD COLUMN IF NOT EXISTS amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '金额(分)' AFTER amount,
ADD COLUMN balance_after_cent BIGINT NOT NULL DEFAULT 0 COMMENT '变动后余额(分)' AFTER balance_after; ADD COLUMN IF NOT EXISTS balance_after_cent BIGINT NOT NULL DEFAULT 0 COMMENT '变动后余额(分)' AFTER balance_after;
-- 提现表:如果存在的话 -- 提现表是可选模块;仅在表存在时修改,避免缺表环境迁移失败。
ALTER TABLE withdrawal_requests SET @withdrawal_requests_exists := (
ADD COLUMN amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '提现金额(分)' AFTER amount, SELECT COUNT(*)
ADD COLUMN fee_cent BIGINT NOT NULL DEFAULT 0 COMMENT '手续费(分)' AFTER fee, FROM information_schema.tables
ADD COLUMN actual_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT '实际到账(分)' AFTER actual_amount; WHERE table_schema = DATABASE()
AND table_name = 'withdrawal_requests'
);
SET @sql := IF(@withdrawal_requests_exists > 0,
'ALTER TABLE withdrawal_requests
ADD COLUMN IF NOT EXISTS amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT ''提现金额(分)'' AFTER amount,
ADD COLUMN IF NOT EXISTS fee_cent BIGINT NOT NULL DEFAULT 0 COMMENT ''手续费(分)'' AFTER fee,
ADD COLUMN IF NOT EXISTS actual_amount_cent BIGINT NOT NULL DEFAULT 0 COMMENT ''实际到账(分)'' AFTER actual_amount',
'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- ============================================ -- ============================================
-- 数据迁移:从 DECIMAL 复制到 BIGINT(分) -- 数据迁移:从 DECIMAL 复制到 BIGINT(分)
@@ -58,59 +70,66 @@ ALTER TABLE withdrawal_requests
-- ============================================ -- ============================================
-- 用户免押额度 -- 用户免押额度
UPDATE users SET deposit_free_quota_cent = ROUND(deposit_free_quota * 100) WHERE deposit_free_quota > 0; UPDATE users
SET deposit_free_quota_cent = ROUND(deposit_free_quota * 100)
WHERE deposit_free_quota > 0;
-- 商品价格和押金 -- 商品价格和押金
UPDATE rental_listings SET UPDATE rental_listings
price_cent = ROUND(price * 100), SET price_cent = ROUND(price * 100),
deposit_amount_cent = ROUND(deposit_amount * 100) deposit_amount_cent = ROUND(deposit_amount * 100)
WHERE price > 0 OR deposit_amount > 0; WHERE price > 0 OR deposit_amount > 0;
-- 订单金额 -- 订单金额
UPDATE rental_orders SET UPDATE rental_orders
rent_amount_cent = ROUND(rent_amount * 100), SET rent_amount_cent = ROUND(rent_amount * 100),
owner_rent_amount_cent = ROUND(owner_rent_amount * 100), owner_rent_amount_cent = ROUND(owner_rent_amount * 100),
deposit_amount_cent = ROUND(deposit_amount * 100), deposit_amount_cent = ROUND(deposit_amount * 100),
deposit_original_amount_cent = ROUND(deposit_original_amount * 100), deposit_original_amount_cent = ROUND(deposit_original_amount * 100),
deposit_waived_amount_cent = ROUND(deposit_waived_amount * 100), deposit_waived_amount_cent = ROUND(deposit_waived_amount * 100),
platform_fee_cent = ROUND(platform_fee * 100) platform_fee_cent = ROUND(platform_fee * 100)
WHERE rent_amount > 0 OR owner_rent_amount > 0 OR deposit_amount > 0 WHERE rent_amount > 0 OR owner_rent_amount > 0 OR deposit_amount > 0
OR deposit_original_amount > 0 OR deposit_waived_amount > 0 OR platform_fee > 0; OR deposit_original_amount > 0 OR deposit_waived_amount > 0 OR platform_fee > 0;
-- 结算记录 -- 结算记录
UPDATE order_checkouts SET UPDATE order_checkouts
rent_amount_cent = ROUND(rent_amount * 100), SET rent_amount_cent = ROUND(rent_amount * 100),
owner_rent_amount_cent = ROUND(owner_rent_amount * 100), owner_rent_amount_cent = ROUND(owner_rent_amount * 100),
platform_fee_cent = ROUND(platform_fee * 100), platform_fee_cent = ROUND(platform_fee * 100),
deposit_amount_cent = ROUND(deposit_amount * 100), deposit_amount_cent = ROUND(deposit_amount * 100),
consumable_amount_cent = ROUND(consumable_amount * 100), consumable_amount_cent = ROUND(consumable_amount * 100),
other_amount_cent = ROUND(other_amount * 100), other_amount_cent = ROUND(other_amount * 100),
deposit_deduct_amount_cent = ROUND(deposit_deduct_amount * 100), deposit_deduct_amount_cent = ROUND(deposit_deduct_amount * 100),
renter_refund_amount_cent = ROUND(renter_refund_amount * 100), renter_refund_amount_cent = ROUND(renter_refund_amount * 100),
owner_income_amount_cent = ROUND(owner_income_amount * 100) owner_income_amount_cent = ROUND(owner_income_amount * 100)
WHERE rent_amount > 0 OR owner_rent_amount > 0 OR platform_fee > 0 WHERE rent_amount > 0 OR owner_rent_amount > 0 OR platform_fee > 0
OR deposit_amount > 0 OR consumable_amount > 0 OR other_amount > 0 OR deposit_amount > 0 OR consumable_amount > 0 OR other_amount > 0
OR deposit_deduct_amount > 0 OR renter_refund_amount > 0 OR owner_income_amount > 0; OR deposit_deduct_amount > 0 OR renter_refund_amount > 0 OR owner_income_amount > 0;
-- 钱包余额 -- 钱包余额
UPDATE wallet_accounts SET UPDATE wallet_accounts
available_balance_cent = ROUND(available_balance * 100), SET available_balance_cent = ROUND(available_balance * 100),
frozen_balance_cent = ROUND(frozen_balance * 100) frozen_balance_cent = ROUND(frozen_balance * 100)
WHERE available_balance > 0 OR frozen_balance > 0; WHERE available_balance > 0 OR frozen_balance > 0;
-- 钱包流水 -- 钱包流水
UPDATE wallet_ledger SET UPDATE wallet_ledger
amount_cent = ROUND(amount * 100), SET amount_cent = ROUND(amount * 100),
balance_after_cent = ROUND(balance_after * 100) balance_after_cent = ROUND(balance_after * 100)
WHERE amount != 0 OR balance_after != 0; WHERE amount != 0 OR balance_after != 0;
-- 提现记录 -- 提现记录
UPDATE withdrawal_requests SET SET @sql := IF(@withdrawal_requests_exists > 0,
amount_cent = ROUND(amount * 100), 'UPDATE withdrawal_requests
fee_cent = ROUND(fee * 100), SET amount_cent = ROUND(amount * 100),
actual_amount_cent = ROUND(actual_amount * 100) fee_cent = ROUND(fee * 100),
WHERE amount > 0 OR fee > 0 OR actual_amount > 0; actual_amount_cent = ROUND(actual_amount * 100)
WHERE amount > 0 OR fee > 0 OR actual_amount > 0',
'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- +goose StatementEnd -- +goose StatementEnd
-- +goose Down -- +goose Down
@@ -119,42 +138,53 @@ WHERE amount > 0 OR fee > 0 OR actual_amount > 0;
-- 回滚:删除所有新增的分字段 -- 回滚:删除所有新增的分字段
-- ============================================ -- ============================================
ALTER TABLE users DROP COLUMN deposit_free_quota_cent; ALTER TABLE users DROP COLUMN IF EXISTS deposit_free_quota_cent;
ALTER TABLE rental_listings ALTER TABLE rental_listings
DROP COLUMN price_cent, DROP COLUMN IF EXISTS price_cent,
DROP COLUMN deposit_amount_cent; DROP COLUMN IF EXISTS deposit_amount_cent;
ALTER TABLE rental_orders ALTER TABLE rental_orders
DROP COLUMN rent_amount_cent, DROP COLUMN IF EXISTS rent_amount_cent,
DROP COLUMN owner_rent_amount_cent, DROP COLUMN IF EXISTS owner_rent_amount_cent,
DROP COLUMN deposit_amount_cent, DROP COLUMN IF EXISTS deposit_amount_cent,
DROP COLUMN deposit_original_amount_cent, DROP COLUMN IF EXISTS deposit_original_amount_cent,
DROP COLUMN deposit_waived_amount_cent, DROP COLUMN IF EXISTS deposit_waived_amount_cent,
DROP COLUMN platform_fee_cent; DROP COLUMN IF EXISTS platform_fee_cent;
ALTER TABLE order_checkouts ALTER TABLE order_checkouts
DROP COLUMN rent_amount_cent, DROP COLUMN IF EXISTS rent_amount_cent,
DROP COLUMN owner_rent_amount_cent, DROP COLUMN IF EXISTS owner_rent_amount_cent,
DROP COLUMN platform_fee_cent, DROP COLUMN IF EXISTS platform_fee_cent,
DROP COLUMN deposit_amount_cent, DROP COLUMN IF EXISTS deposit_amount_cent,
DROP COLUMN consumable_amount_cent, DROP COLUMN IF EXISTS consumable_amount_cent,
DROP COLUMN other_amount_cent, DROP COLUMN IF EXISTS other_amount_cent,
DROP COLUMN deposit_deduct_amount_cent, DROP COLUMN IF EXISTS deposit_deduct_amount_cent,
DROP COLUMN renter_refund_amount_cent, DROP COLUMN IF EXISTS renter_refund_amount_cent,
DROP COLUMN owner_income_amount_cent; DROP COLUMN IF EXISTS owner_income_amount_cent;
ALTER TABLE wallet_accounts ALTER TABLE wallet_accounts
DROP COLUMN available_balance_cent, DROP COLUMN IF EXISTS available_balance_cent,
DROP COLUMN frozen_balance_cent; DROP COLUMN IF EXISTS frozen_balance_cent;
ALTER TABLE wallet_ledger ALTER TABLE wallet_ledger
DROP COLUMN amount_cent, DROP COLUMN IF EXISTS amount_cent,
DROP COLUMN balance_after_cent; DROP COLUMN IF EXISTS balance_after_cent;
ALTER TABLE withdrawal_requests
DROP COLUMN amount_cent,
DROP COLUMN fee_cent,
DROP COLUMN actual_amount_cent;
SET @withdrawal_requests_exists := (
SELECT COUNT(*)
FROM information_schema.tables
WHERE table_schema = DATABASE()
AND table_name = 'withdrawal_requests'
);
SET @sql := IF(@withdrawal_requests_exists > 0,
'ALTER TABLE withdrawal_requests
DROP COLUMN IF EXISTS amount_cent,
DROP COLUMN IF EXISTS fee_cent,
DROP COLUMN IF EXISTS actual_amount_cent',
'SELECT 1'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
-- +goose StatementEnd -- +goose StatementEnd