refactor(order): 结算优先读取整数分快照
This commit is contained in:
@@ -161,19 +161,19 @@ func estimateOrderDurationHours(snapshot datatypes.JSON) int {
|
||||
|
||||
func buildOrderPricing(listing model.RentalListing, account model.GameAccount) orderPricing {
|
||||
rentAmountCent := listing.PriceCent
|
||||
ownerRentAmountCent := int64(math.Round(readSnapshotPrice(account.AssetSummary, "seller_total_price") * 100))
|
||||
ownerRentAmountCent := readSnapshotCent(account.AssetSummary, "seller_total_price")
|
||||
if ownerRentAmountCent <= 0 || ownerRentAmountCent > rentAmountCent {
|
||||
ownerRentAmountCent = rentAmountCent
|
||||
}
|
||||
platformFeeCent := int64(math.Round(readSnapshotPrice(account.AssetSummary, "platform_markup_amount") * 100))
|
||||
platformFeeCent := readSnapshotCent(account.AssetSummary, "platform_markup_amount")
|
||||
if platformFeeCent <= 0 || ownerRentAmountCent+platformFeeCent != rentAmountCent {
|
||||
platformFeeCent = rentAmountCent - ownerRentAmountCent
|
||||
}
|
||||
if platformFeeCent < 0 {
|
||||
platformFeeCent = 0
|
||||
}
|
||||
pureCoinAmountCent := int64(math.Round(readSnapshotPrice(account.AssetSummary, "buyer_coin_base_price") * 100))
|
||||
extraItemSnapshotCent := int64(math.Round(readSnapshotPrice(account.AssetSummary, "consumable_price") * 100))
|
||||
pureCoinAmountCent := readSnapshotCent(account.AssetSummary, "buyer_coin_base_price")
|
||||
extraItemSnapshotCent := readSnapshotCent(account.AssetSummary, "consumable_price")
|
||||
if pureCoinAmountCent <= 0 {
|
||||
if extraItemSnapshotCent > 0 && extraItemSnapshotCent <= rentAmountCent {
|
||||
pureCoinAmountCent = rentAmountCent - extraItemSnapshotCent
|
||||
@@ -185,7 +185,7 @@ func buildOrderPricing(listing model.RentalListing, account model.GameAccount) o
|
||||
pureCoinAmountCent = rentAmountCent
|
||||
}
|
||||
extraItemAmountCent := maxCent(rentAmountCent-pureCoinAmountCent, 0)
|
||||
ownerPureCoinAmountCent := int64(math.Round(readSnapshotPrice(account.AssetSummary, "seller_coin_base_price") * 100))
|
||||
ownerPureCoinAmountCent := readSnapshotCent(account.AssetSummary, "seller_coin_base_price")
|
||||
if ownerPureCoinAmountCent <= 0 || ownerPureCoinAmountCent > ownerRentAmountCent {
|
||||
ownerPureCoinAmountCent = maxCent(ownerRentAmountCent-minCent(extraItemAmountCent, ownerRentAmountCent), 0)
|
||||
}
|
||||
@@ -207,18 +207,72 @@ func readSnapshotPrice(raw datatypes.JSON, key string) float64 {
|
||||
return readOrderSnapshotPrice(raw, key)
|
||||
}
|
||||
|
||||
func readOrderSnapshotPrice(raw datatypes.JSON, key string) float64 {
|
||||
if len(raw) == 0 {
|
||||
// readSnapshotCent 优先读取 price_breakdown 的整数分字段,缺失时兼容旧元字段。
|
||||
func readSnapshotCent(raw datatypes.JSON, key string) int64 {
|
||||
return readOrderSnapshotCent(raw, key)
|
||||
}
|
||||
|
||||
func readOrderSnapshotCent(raw datatypes.JSON, key string) int64 {
|
||||
breakdown, ok := readOrderSnapshotBreakdown(raw)
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
if cent := readJSONInt64(breakdown[key+"_cent"]); cent > 0 {
|
||||
return cent
|
||||
}
|
||||
legacy := readJSONNumber(breakdown[key])
|
||||
if legacy <= 0 {
|
||||
return 0
|
||||
}
|
||||
return int64(math.Round(legacy * 100))
|
||||
}
|
||||
|
||||
func readOrderSnapshotBreakdown(raw datatypes.JSON) (map[string]any, bool) {
|
||||
if len(raw) == 0 {
|
||||
return nil, false
|
||||
}
|
||||
var snapshot map[string]any
|
||||
if err := json.Unmarshal(raw, &snapshot); err != nil {
|
||||
return 0
|
||||
return nil, false
|
||||
}
|
||||
if assetSummary, ok := snapshot["asset_summary"].(map[string]any); ok {
|
||||
snapshot = assetSummary
|
||||
}
|
||||
breakdown, ok := snapshot["price_breakdown"].(map[string]any)
|
||||
return breakdown, ok
|
||||
}
|
||||
|
||||
func readJSONInt64(value any) int64 {
|
||||
switch typed := value.(type) {
|
||||
case float64:
|
||||
return int64(typed)
|
||||
case float32:
|
||||
return int64(typed)
|
||||
case int:
|
||||
return int64(typed)
|
||||
case int64:
|
||||
return typed
|
||||
case int32:
|
||||
return int64(typed)
|
||||
case json.Number:
|
||||
number, err := typed.Int64()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return number
|
||||
case string:
|
||||
number, err := strconv.ParseInt(typed, 10, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return number
|
||||
default:
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func readOrderSnapshotPrice(raw datatypes.JSON, key string) float64 {
|
||||
breakdown, ok := readOrderSnapshotBreakdown(raw)
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
@@ -313,7 +367,7 @@ func calculateCheckoutSettlement(order model.RentalOrder, consumableAmountCent i
|
||||
orderDepositAmountCent := order.DepositAmountCent
|
||||
|
||||
buyerCoinBasePriceCent := orderPureCoinOriginalAmountCent(order)
|
||||
sellerCoinBasePriceCent := int64(math.Round(readOrderSnapshotPrice(order.AccountSnapshot, "seller_coin_base_price") * 100))
|
||||
sellerCoinBasePriceCent := readOrderSnapshotCent(order.AccountSnapshot, "seller_coin_base_price")
|
||||
if sellerCoinBasePriceCent <= 0 || sellerCoinBasePriceCent > orderOwnerRentAmountCent {
|
||||
ownerExtraItemCent := minCent(orderExtraItemOriginalAmountCent(order), orderOwnerRentAmountCent)
|
||||
sellerCoinBasePriceCent = maxCent(orderOwnerRentAmountCent-ownerExtraItemCent, 0)
|
||||
@@ -427,11 +481,11 @@ func orderPureCoinOriginalAmountCent(order model.RentalOrder) int64 {
|
||||
if order.ExtraItemOriginalAmountCent > 0 {
|
||||
return maxCent(originalRentCent-minCent(order.ExtraItemOriginalAmountCent, originalRentCent), 0)
|
||||
}
|
||||
pureCoinCent := int64(math.Round(readOrderSnapshotPrice(order.AccountSnapshot, "buyer_coin_base_price") * 100))
|
||||
pureCoinCent := readOrderSnapshotCent(order.AccountSnapshot, "buyer_coin_base_price")
|
||||
if pureCoinCent > 0 && pureCoinCent <= originalRentCent {
|
||||
return pureCoinCent
|
||||
}
|
||||
extraItemCent := int64(math.Round(readOrderSnapshotPrice(order.AccountSnapshot, "consumable_price") * 100))
|
||||
extraItemCent := readOrderSnapshotCent(order.AccountSnapshot, "consumable_price")
|
||||
if extraItemCent > 0 && extraItemCent <= originalRentCent {
|
||||
return originalRentCent - extraItemCent
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package order
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"hfb_sys/backend/internal/model"
|
||||
|
||||
"gorm.io/datatypes"
|
||||
)
|
||||
|
||||
func TestReadOrderSnapshotCentPrefersCentField(t *testing.T) {
|
||||
raw := datatypes.JSON([]byte(`{
|
||||
"asset_summary": {
|
||||
"price_breakdown": {
|
||||
"seller_total_price": 353.00,
|
||||
"seller_total_price_cent": 35301
|
||||
}
|
||||
}
|
||||
}`))
|
||||
if got := readSnapshotCent(raw, "seller_total_price"); got != 35301 {
|
||||
t.Fatalf("优先读取分字段失败: got %d, want 35301", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReadOrderSnapshotCentFallsBackToLegacyYuan(t *testing.T) {
|
||||
raw := datatypes.JSON([]byte(`{
|
||||
"asset_summary": {
|
||||
"price_breakdown": {
|
||||
"consumable_price": 120.00
|
||||
}
|
||||
}
|
||||
}`))
|
||||
if got := readSnapshotCent(raw, "consumable_price"); got != 12000 {
|
||||
t.Fatalf("旧元字段回退失败: got %d, want 12000", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBuildOrderPricingUsesCentBreakdown(t *testing.T) {
|
||||
account := model.GameAccount{
|
||||
AssetSummary: datatypes.JSON([]byte(`{
|
||||
"asset_summary": {
|
||||
"price_breakdown": {
|
||||
"seller_total_price_cent": 35301,
|
||||
"platform_markup_amount_cent": 2999,
|
||||
"buyer_coin_base_price_cent": 26315,
|
||||
"consumable_price_cent": 12000,
|
||||
"seller_coin_base_price_cent": 23315
|
||||
}
|
||||
}
|
||||
}`)),
|
||||
}
|
||||
pricing := buildOrderPricing(model.RentalListing{PriceCent: 38300}, account)
|
||||
if pricing.OwnerRentAmountCent != 35301 {
|
||||
t.Fatalf("OwnerRentAmountCent = %d, want 35301", pricing.OwnerRentAmountCent)
|
||||
}
|
||||
if pricing.PlatformFeeCent != 2999 {
|
||||
t.Fatalf("PlatformFeeCent = %d, want 2999", pricing.PlatformFeeCent)
|
||||
}
|
||||
if pricing.PureCoinAmountCent != 26315 {
|
||||
t.Fatalf("PureCoinAmountCent = %d, want 26315", pricing.PureCoinAmountCent)
|
||||
}
|
||||
if pricing.ExtraItemAmountCent != 11985 {
|
||||
t.Fatalf("ExtraItemAmountCent = %d, want 11985", pricing.ExtraItemAmountCent)
|
||||
}
|
||||
if pricing.OwnerPureCoinAmountCent != 23315 {
|
||||
t.Fatalf("OwnerPureCoinAmountCent = %d, want 23315", pricing.OwnerPureCoinAmountCent)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user