feat(backend): license_purchases 增 amount_minor/currency/pay_url/renewed_to 列 + 存量回填(pay v2 金额口径)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-07-10 20:26:59 +08:00
parent ceabc7977b
commit bc183ab7df
6 changed files with 60 additions and 2 deletions
+15
View File
@@ -368,6 +368,21 @@ func entitle(tx *gorm.DB, shopID uint64, plan payPlan) error {
}).Error
}
// BackfillPurchaseAmountMinor 启动回填:v1 存量购买单 amount("2999.00") → amount_minor(299900)+CNY。
// 幂等:只处理 amount_minor=0 且 amount 非空的行(参照 backfillPinyin 先例)。
func BackfillPurchaseAmountMinor(db *gorm.DB) {
var rows []model.LicensePurchase
if err := db.Where("amount_minor = 0 AND amount <> ''").Find(&rows).Error; err != nil {
return
}
for _, p := range rows {
if c, err := toCents(p.Amount); err == nil && c > 0 {
db.Model(&model.LicensePurchase{}).Where("id = ?", p.ID).
Updates(map[string]any{"amount_minor": c, "currency": "CNY"})
}
}
}
// amountEqual 金额按分归一比较("2999.00" == "2999" == "2999.0")。
func amountEqual(a, b string) bool {
ca, ea := toCents(a)
+27
View File
@@ -370,3 +370,30 @@ func TestStatus_ScopedToShop(t *testing.T) {
_, err = svc.Status(other.ID, "yanmei-otn-7")
assert.ErrorIs(t, err, ErrPurchaseNotFound, "跨店不可见")
}
// ---------- v2 金额回填 ----------
func TestBackfillPurchaseAmountMinor(t *testing.T) {
db := testutil.SetupTestDB()
shop := testutil.CreateTestShop(db, "PAY012")
p1 := createPendingPurchase(t, db, shop.ID, "annual_standard", "2999.00", "yanmei-backfill-1")
p2 := createPendingPurchase(t, db, shop.ID, PromoBizCode, "1.00", "yanmei-backfill-2")
// 已有 amount_minor>0 的行不应被覆盖
p3 := createPendingPurchase(t, db, shop.ID, "monthly_pro", "599.00", "yanmei-backfill-3")
require.NoError(t, db.Model(p3).Updates(map[string]any{"amount_minor": 123, "currency": "USD"}).Error)
BackfillPurchaseAmountMinor(db)
var got1, got2, got3 model.LicensePurchase
require.NoError(t, db.First(&got1, p1.ID).Error)
require.NoError(t, db.First(&got2, p2.ID).Error)
require.NoError(t, db.First(&got3, p3.ID).Error)
assert.Equal(t, int64(299900), got1.AmountMinor)
assert.Equal(t, "CNY", got1.Currency)
assert.Equal(t, int64(100), got2.AmountMinor)
assert.Equal(t, "CNY", got2.Currency)
assert.Equal(t, int64(123), got3.AmountMinor, "已有 amount_minor>0 的行不被覆盖")
assert.Equal(t, "USD", got3.Currency, "已有 amount_minor>0 的行不被覆盖")
}