增加统一倍率调整按钮

This commit is contained in:
andy committed 2026-09-23 15:46:21 +08:00
1 parent be655b6569
commit 4195525dc7
23 files changed
+750 -16

No files matched your search

+56
View File
@@ -16,6 +16,37 @@ ORDER BY provider, capability, id`
const GetBillingPriceRuleSQL = `SELECT id, provider, capability, req_key, variant_key, unit, standard_unit_price_fen, markup_multiplier, enabled, conditions, quantity_source, priority, note, source, parameter_dimensions, created_at::text, updated_at::text FROM public.billing_price_rules WHERE id = $1::text LIMIT 1`
const UpdateBillingPriceRuleSQL = `UPDATE public.billing_price_rules SET markup_multiplier = CASE WHEN $2::text = '' THEN $3::numeric ELSE markup_multiplier END, parameter_dimensions = CASE WHEN $2::text = '' THEN parameter_dimensions ELSE (SELECT jsonb_agg(CASE WHEN dimension->>'key' = $2::text THEN jsonb_set(dimension, '{tiers}', (SELECT jsonb_agg(CASE WHEN tier->>'value' = $4::text THEN jsonb_set(tier, '{markupMultiplier}', to_jsonb($3::numeric), true) ELSE tier END) FROM jsonb_array_elements(dimension->'tiers') tier), true) ELSE dimension END) FROM jsonb_array_elements(parameter_dimensions) dimension) END, updated_at = now() WHERE id = $1::text RETURNING id, provider, capability, req_key, variant_key, unit, standard_unit_price_fen, markup_multiplier, enabled, conditions, quantity_source, priority, note, source, parameter_dimensions, created_at::text, updated_at::text`
// Lock every requested row first. If even one ID is absent, eligible is false
// and this single statement updates none of them.
const UpdateBillingPriceRulesSQL = `WITH locked AS MATERIALIZED (
SELECT id FROM public.billing_price_rules WHERE id = ANY($1::text[]) FOR UPDATE
), eligible AS MATERIALIZED (
SELECT count(*) = cardinality($1::text[]) AS all_present FROM locked
), updated AS (
UPDATE public.billing_price_rules AS rule SET
markup_multiplier = $2::numeric,
parameter_dimensions = (
SELECT COALESCE(jsonb_agg(
jsonb_set(dimension.value, '{tiers}', (
SELECT COALESCE(jsonb_agg(
jsonb_set(tier.value, '{markupMultiplier}', to_jsonb($2::numeric), true)
ORDER BY tier.position
), '[]'::jsonb)
FROM jsonb_array_elements(COALESCE(dimension.value->'tiers', '[]'::jsonb))
WITH ORDINALITY AS tier(value, position)
), true) ORDER BY dimension.position
), '[]'::jsonb)
FROM jsonb_array_elements(COALESCE(rule.parameter_dimensions, '[]'::jsonb))
WITH ORDINALITY AS dimension(value, position)
),
updated_at = now()
WHERE rule.id IN (SELECT id FROM locked) AND (SELECT all_present FROM eligible)
RETURNING id, provider, capability, req_key, variant_key, unit, standard_unit_price_fen,
markup_multiplier, enabled, conditions, quantity_source, priority, note, source,
parameter_dimensions, created_at::text, updated_at::text
)
SELECT * FROM updated ORDER BY id`
const GetBillingWalletSQL = `SELECT $1::text, COALESCE(balance_fen, 0), COALESCE(total_recharged_fen, 0), COALESCE(total_charged_fen, 0), COALESCE(updated_at::text, '') FROM public.billing_wallets WHERE organization_id = $1::text UNION ALL SELECT $1::text, 0, 0, 0, '' WHERE NOT EXISTS (SELECT 1 FROM public.billing_wallets WHERE organization_id = $1::text) LIMIT 1`
const ListBillingWalletsSQL = `SELECT organization_id, balance_fen, total_recharged_fen, total_charged_fen, updated_at::text FROM public.billing_wallets ORDER BY updated_at DESC`
const ListBillingLedgerSQL = `SELECT id, organization_id, COALESCE(account_id, ''), COALESCE(job_id, ''), kind, delta_fen, balance_after_fen, currency, idempotency_key, description, metadata, created_at::text FROM public.billing_ledger WHERE ($1::text = '' OR organization_id = $1::text) AND ($2::text = '' OR account_id = $2::text) ORDER BY created_at DESC LIMIT $3::integer`
@@ -87,6 +118,31 @@ func (db *Database) UpdateBillingPriceRule(ctx context.Context, id string, patch
rule, err := scanFullPriceRule(rows)
return &rule, err
}
func (db *Database) UpdateBillingPriceRules(ctx context.Context, patch billing.BulkPricePatch) ([]billing.PriceRule, error) {
if len(patch.RuleIDs) == 0 {
return nil, billing.ErrPriceNotFound
}
rows, err := db.billingQuery(ctx, UpdateBillingPriceRulesSQL, patch.RuleIDs, patch.MarkupMultiplier)
if err != nil {
return nil, err
}
defer rows.Close()
rules := make([]billing.PriceRule, 0, len(patch.RuleIDs))
for rows.Next() {
rule, err := scanFullPriceRule(rows)
if err != nil {
return nil, err
}
rules = append(rules, rule)
}
if err := rows.Err(); err != nil {
return nil, err
}
if len(rules) != len(patch.RuleIDs) {
return nil, billing.ErrPriceNotFound
}
return rules, nil
}
func scanFullPriceRule(rows Rows) (billing.PriceRule, error) {
var rule billing.PriceRule
var req, variant, quantity, note sql.NullString