fix(订单): 修复折扣计算问题并添加四舍五入处理
Build docker and publish / build (20.15.1) (push) Successful in 6m53s

统一处理百分比和系数两种折扣输入方式,增加边界保护
在金额计算中使用math.Round进行四舍五入处理
添加相关单元测试确保计算准确性
This commit is contained in:
2025-12-02 02:22:09 -08:00
parent fcdd6ac170
commit 9987bd43fa
15 changed files with 206 additions and 30 deletions
@@ -3,6 +3,7 @@ package portal
import (
"context"
"encoding/json"
"math"
"github.com/perfect-panel/server/pkg/tool"
@@ -43,7 +44,7 @@ func (l *PrePurchaseOrderLogic) PrePurchaseOrder(req *types.PrePurchaseOrderRequ
discount = getDiscount(dis, req.Quantity)
}
price := sub.UnitPrice * req.Quantity
amount := int64(float64(price) * discount)
amount := int64(math.Round(float64(price) * discount))
discountAmount := price - amount
var coupon int64
if req.Coupon != "" {
@@ -3,6 +3,7 @@ package portal
import (
"context"
"encoding/json"
"math"
"strconv"
"time"
@@ -184,7 +185,7 @@ func (l *PurchaseCheckoutLogic) alipayF2fPayment(pay *payment.Payment, info *ord
l.Errorw("[PurchaseCheckout] queryExchangeRate error", logger.Field("error", err.Error()))
return "", errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "queryExchangeRate error: %s", err.Error())
}
convertAmount := int64(amount * 100) // Convert to cents for API
convertAmount := int64(math.Round(amount * 100)) // Convert to cents for API
// Create pre-payment trade and generate QR code
QRCode, err := client.PreCreateTrade(l.ctx, alipay.Order{
@@ -222,7 +223,7 @@ func (l *PurchaseCheckoutLogic) stripePayment(config string, info *order.Order,
l.Errorw("[PurchaseCheckout] queryExchangeRate error", logger.Field("error", err.Error()))
return nil, errors.Wrapf(xerr.NewErrCode(xerr.ERROR), "queryExchangeRate error: %s", err.Error())
}
convertAmount := int64(amount * 100) // Convert to cents for Stripe API
convertAmount := int64(math.Round(amount * 100)) // Convert to cents for Stripe API
// Create Stripe payment sheet for client-side processing
result, err := client.CreatePaymentSheet(&stripe.Order{
@@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"fmt"
"math"
"time"
"github.com/perfect-panel/server/internal/model/order"
@@ -67,7 +68,7 @@ func (l *PurchaseLogic) Purchase(req *types.PortalPurchaseRequest) (resp *types.
}
price := sub.UnitPrice * req.Quantity
// discount amount
amount := int64(float64(price) * discount)
amount := int64(math.Round(float64(price) * discount))
discountAmount := price - amount
var couponAmount int64 = 0
+16 -8
View File
@@ -1,25 +1,33 @@
package portal
import (
"math"
"github.com/perfect-panel/server/internal/model/coupon"
"github.com/perfect-panel/server/internal/model/payment"
"github.com/perfect-panel/server/internal/types"
)
func getDiscount(discounts []types.SubscribeDiscount, inputMonths int64) float64 {
var finalDiscount int64 = 100
for _, discount := range discounts {
if inputMonths >= discount.Quantity && int64(discount.Discount*100) < finalDiscount {
finalDiscount = int64(discount.Discount * 100)
final := 1.0
for _, d := range discounts {
val := d.Discount
if val > 1 && val <= 100 {
val = val / 100.0
}
if val < 0 {
val = 0
}
if inputMonths >= d.Quantity && val < final {
final = val
}
}
return float64(finalDiscount) / float64(100)
return final
}
func calculateCoupon(amount int64, couponInfo *coupon.Coupon) int64 {
if couponInfo.Type == 1 {
return int64(float64(amount) * (float64(couponInfo.Discount) / float64(100)))
return int64(math.Round(float64(amount) * (float64(couponInfo.Discount) / float64(100))))
} else {
return min(couponInfo.Discount, amount)
}
@@ -39,5 +47,5 @@ func calculateFee(amount int64, config *payment.Payment) int64 {
case 3:
fee = float64(amount)*(float64(config.FeePercent)/float64(100)) + float64(config.FeeAmount)
}
return int64(fee)
return int64(math.Round(fee))
}
+23
View File
@@ -0,0 +1,23 @@
package portal
import (
"testing"
"github.com/perfect-panel/server/internal/types"
)
func TestGetDiscount_Coefficient(t *testing.T) {
discounts := []types.SubscribeDiscount{{Quantity: 7, Discount: 0.9}}
got := getDiscount(discounts, 7)
if got != 0.9 {
t.Fatalf("expected 0.9, got %v", got)
}
}
func TestGetDiscount_Percentage(t *testing.T) {
discounts := []types.SubscribeDiscount{{Quantity: 7, Discount: 90}}
got := getDiscount(discounts, 7)
if got != 0.9 {
t.Fatalf("expected 0.9 from 90%%, got %v", got)
}
}