Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
0d997a20
Commit
0d997a20
authored
Apr 28, 2026
by
陈曦
Browse files
trafficapi商用migration upgrade
parent
a7386882
Pipeline
#82306
passed with stage
in 3 minutes and 1 second
Changes
49
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
backend/migration_release/092_payment_orders.sql
0 → 100644
View file @
0d997a20
CREATE
TABLE
IF
NOT
EXISTS
payment_orders
(
id
BIGSERIAL
PRIMARY
KEY
,
user_id
BIGINT
NOT
NULL
,
user_email
VARCHAR
(
255
)
NOT
NULL
DEFAULT
''
,
user_name
VARCHAR
(
100
)
NOT
NULL
DEFAULT
''
,
user_notes
TEXT
,
amount
DECIMAL
(
20
,
2
)
NOT
NULL
,
pay_amount
DECIMAL
(
20
,
2
)
NOT
NULL
,
fee_rate
DECIMAL
(
10
,
4
)
NOT
NULL
DEFAULT
0
,
recharge_code
VARCHAR
(
64
)
NOT
NULL
DEFAULT
''
,
payment_type
VARCHAR
(
30
)
NOT
NULL
DEFAULT
''
,
payment_trade_no
VARCHAR
(
128
)
NOT
NULL
DEFAULT
''
,
pay_url
TEXT
,
qr_code
TEXT
,
qr_code_img
TEXT
,
order_type
VARCHAR
(
20
)
NOT
NULL
DEFAULT
'balance'
,
plan_id
BIGINT
,
subscription_group_id
BIGINT
,
subscription_days
INT
,
provider_instance_id
VARCHAR
(
64
),
status
VARCHAR
(
30
)
NOT
NULL
DEFAULT
'PENDING'
,
refund_amount
DECIMAL
(
20
,
2
)
NOT
NULL
DEFAULT
0
,
refund_reason
TEXT
,
refund_at
TIMESTAMPTZ
,
force_refund
BOOLEAN
NOT
NULL
DEFAULT
FALSE
,
refund_requested_at
TIMESTAMPTZ
,
refund_request_reason
TEXT
,
refund_requested_by
VARCHAR
(
20
),
expires_at
TIMESTAMPTZ
NOT
NULL
,
paid_at
TIMESTAMPTZ
,
completed_at
TIMESTAMPTZ
,
failed_at
TIMESTAMPTZ
,
failed_reason
TEXT
,
client_ip
VARCHAR
(
50
)
NOT
NULL
DEFAULT
''
,
src_host
VARCHAR
(
255
)
NOT
NULL
DEFAULT
''
,
src_url
TEXT
,
created_at
TIMESTAMPTZ
NOT
NULL
DEFAULT
NOW
(),
updated_at
TIMESTAMPTZ
NOT
NULL
DEFAULT
NOW
()
);
-- Indexes
CREATE
INDEX
IF
NOT
EXISTS
idx_payment_orders_user_id
ON
payment_orders
(
user_id
);
CREATE
INDEX
IF
NOT
EXISTS
idx_payment_orders_status
ON
payment_orders
(
status
);
CREATE
INDEX
IF
NOT
EXISTS
idx_payment_orders_expires_at
ON
payment_orders
(
expires_at
);
CREATE
INDEX
IF
NOT
EXISTS
idx_payment_orders_created_at
ON
payment_orders
(
created_at
);
CREATE
INDEX
IF
NOT
EXISTS
idx_payment_orders_paid_at
ON
payment_orders
(
paid_at
);
CREATE
INDEX
IF
NOT
EXISTS
idx_payment_orders_type_paid
ON
payment_orders
(
payment_type
,
paid_at
);
CREATE
INDEX
IF
NOT
EXISTS
idx_payment_orders_order_type
ON
payment_orders
(
order_type
);
backend/migration_release/093_payment_audit_logs.sql
0 → 100644
View file @
0d997a20
CREATE
TABLE
IF
NOT
EXISTS
payment_audit_logs
(
id
BIGSERIAL
PRIMARY
KEY
,
order_id
VARCHAR
(
64
)
NOT
NULL
,
action
VARCHAR
(
50
)
NOT
NULL
,
detail
TEXT
NOT
NULL
DEFAULT
''
,
operator
VARCHAR
(
100
)
NOT
NULL
DEFAULT
'system'
,
created_at
TIMESTAMPTZ
NOT
NULL
DEFAULT
NOW
()
);
CREATE
INDEX
IF
NOT
EXISTS
idx_payment_audit_logs_order_id
ON
payment_audit_logs
(
order_id
);
backend/migration_release/094_removed_payment_channels.sql
0 → 100644
View file @
0d997a20
-- Migration 092: payment_channels table was removed before release.
-- This file is a no-op placeholder to maintain migration numbering continuity.
-- The payment system now uses the existing channels table (migration 081).
SELECT
1
;
backend/migration_release/095_channel_features.sql
0 → 100644
View file @
0d997a20
ALTER
TABLE
channels
ADD
COLUMN
IF
NOT
EXISTS
features
TEXT
NOT
NULL
DEFAULT
''
;
COMMENT
ON
COLUMN
channels
.
features
IS
'渠道特性描述,JSON 数组格式,用于支付页面展示'
;
backend/migration_release/095_subscription_plans.sql
0 → 100644
View file @
0d997a20
CREATE
TABLE
IF
NOT
EXISTS
subscription_plans
(
id
BIGSERIAL
PRIMARY
KEY
,
group_id
BIGINT
NOT
NULL
,
name
VARCHAR
(
100
)
NOT
NULL
,
description
TEXT
NOT
NULL
DEFAULT
''
,
price
DECIMAL
(
20
,
2
)
NOT
NULL
,
original_price
DECIMAL
(
20
,
2
),
validity_days
INT
NOT
NULL
DEFAULT
30
,
validity_unit
VARCHAR
(
10
)
NOT
NULL
DEFAULT
'day'
,
features
TEXT
NOT
NULL
DEFAULT
''
,
product_name
VARCHAR
(
100
)
NOT
NULL
DEFAULT
''
,
for_sale
BOOLEAN
NOT
NULL
DEFAULT
TRUE
,
sort_order
INT
NOT
NULL
DEFAULT
0
,
created_at
TIMESTAMPTZ
NOT
NULL
DEFAULT
NOW
(),
updated_at
TIMESTAMPTZ
NOT
NULL
DEFAULT
NOW
()
);
CREATE
INDEX
IF
NOT
EXISTS
idx_subscription_plans_group_id
ON
subscription_plans
(
group_id
);
CREATE
INDEX
IF
NOT
EXISTS
idx_subscription_plans_for_sale
ON
subscription_plans
(
for_sale
);
backend/migration_release/096_payment_provider_instances.sql
0 → 100644
View file @
0d997a20
CREATE
TABLE
IF
NOT
EXISTS
payment_provider_instances
(
id
BIGSERIAL
PRIMARY
KEY
,
provider_key
VARCHAR
(
30
)
NOT
NULL
,
name
VARCHAR
(
100
)
NOT
NULL
DEFAULT
''
,
config
TEXT
NOT
NULL
,
supported_types
VARCHAR
(
200
)
NOT
NULL
DEFAULT
''
,
enabled
BOOLEAN
NOT
NULL
DEFAULT
TRUE
,
sort_order
INT
NOT
NULL
DEFAULT
0
,
limits
TEXT
NOT
NULL
DEFAULT
''
,
refund_enabled
BOOLEAN
NOT
NULL
DEFAULT
FALSE
,
created_at
TIMESTAMPTZ
NOT
NULL
DEFAULT
NOW
(),
updated_at
TIMESTAMPTZ
NOT
NULL
DEFAULT
NOW
()
);
CREATE
INDEX
IF
NOT
EXISTS
idx_payment_provider_instances_provider_key
ON
payment_provider_instances
(
provider_key
);
CREATE
INDEX
IF
NOT
EXISTS
idx_payment_provider_instances_enabled
ON
payment_provider_instances
(
enabled
);
backend/migration_release/097_fix_settings_updated_at_default.sql
0 → 100644
View file @
0d997a20
-- 097_fix_settings_updated_at_default.sql
--
-- 修复 settings.updated_at 列在历史实例上可能缺失 SQL DEFAULT 的问题。
--
-- 背景:
-- 早期版本曾依赖 ent 自动迁移建表(ent 的 Default(time.Now) 仅是 Go 层默认值,
-- 不会在 SQL 层落地为 DEFAULT),随后引入的 005_schema_parity.sql 使用了
-- CREATE TABLE IF NOT EXISTS,对已存在的 settings 表不会重建,导致这部分实例
-- 的 updated_at 列虽然是 NOT NULL,但缺少 SQL DEFAULT。
--
-- 后续 098_migrate_purchase_subscription_to_custom_menu.sql 是项目中唯一使用
-- 原生 SQL INSERT INTO settings 的迁移(其余 settings 写入都走 ent / Go 层),
-- 因此该 schema 缺陷直到 098 才会触发:
-- "null value in column \"updated_at\" of relation \"settings\" violates not-null constraint"
--
-- 幂等性:
-- - ALTER COLUMN ... SET DEFAULT NOW() 在已经具备相同默认值的实例上是无操作,
-- 不会报错(PostgreSQL 允许重复设置相同的默认值)。
-- - UPDATE 子句的 WHERE updated_at IS NULL 在健康实例上匹配 0 行,不影响数据。
--
-- 这样可以同时兼容:
-- 1. 从未运行过旧版迁移的全新部署(005 已经把列建对,本迁移变成 no-op)。
-- 2. 历史损坏实例(本迁移修复缺失的默认值,使后续 098 能够正常 INSERT)。
ALTER
TABLE
settings
ALTER
COLUMN
updated_at
SET
DEFAULT
NOW
();
UPDATE
settings
SET
updated_at
=
NOW
()
WHERE
updated_at
IS
NULL
;
backend/migration_release/098_migrate_purchase_subscription_to_custom_menu.sql
0 → 100644
View file @
0d997a20
-- 096_migrate_purchase_subscription_to_custom_menu.sql
--
-- Migrates the legacy purchase_subscription_url setting into custom_menu_items.
-- After migration, purchase_subscription_enabled is set to "false" and
-- purchase_subscription_url is cleared.
--
-- Idempotent: skips if custom_menu_items already contains
-- "migrated_purchase_subscription".
DO
$$
DECLARE
v_enabled
text
;
v_url
text
;
v_raw
text
;
v_items
jsonb
;
v_new_item
jsonb
;
BEGIN
-- Read legacy settings
SELECT
value
INTO
v_enabled
FROM
settings
WHERE
key
=
'purchase_subscription_enabled'
;
SELECT
value
INTO
v_url
FROM
settings
WHERE
key
=
'purchase_subscription_url'
;
-- Skip if not enabled or URL is empty
IF
COALESCE
(
v_enabled
,
''
)
<>
'true'
OR
COALESCE
(
TRIM
(
v_url
),
''
)
=
''
THEN
RETURN
;
END
IF
;
-- Read current custom_menu_items
SELECT
value
INTO
v_raw
FROM
settings
WHERE
key
=
'custom_menu_items'
;
IF
COALESCE
(
v_raw
,
''
)
=
''
OR
v_raw
=
'null'
THEN
v_items
:
=
'[]'
::
jsonb
;
ELSE
v_items
:
=
v_raw
::
jsonb
;
END
IF
;
-- Skip if already migrated (item with id "migrated_purchase_subscription" exists)
IF
EXISTS
(
SELECT
1
FROM
jsonb_array_elements
(
v_items
)
elem
WHERE
elem
->>
'id'
=
'migrated_purchase_subscription'
)
THEN
RETURN
;
END
IF
;
-- Build the new menu item
v_new_item
:
=
jsonb_build_object
(
'id'
,
'migrated_purchase_subscription'
,
'label'
,
'Purchase'
,
'icon_svg'
,
''
,
'url'
,
TRIM
(
v_url
),
'visibility'
,
'user'
,
'sort_order'
,
100
);
-- Append to array
v_items
:
=
v_items
||
jsonb_build_array
(
v_new_item
);
-- Upsert custom_menu_items
INSERT
INTO
settings
(
key
,
value
)
VALUES
(
'custom_menu_items'
,
v_items
::
text
)
ON
CONFLICT
(
key
)
DO
UPDATE
SET
value
=
EXCLUDED
.
value
;
-- Clear legacy settings
UPDATE
settings
SET
value
=
'false'
WHERE
key
=
'purchase_subscription_enabled'
;
UPDATE
settings
SET
value
=
''
WHERE
key
=
'purchase_subscription_url'
;
RAISE
NOTICE
'[migration-096] Migrated purchase_subscription_url (%) to custom_menu_items'
,
v_url
;
END
$$
;
backend/migration_release/099_fix_migrated_purchase_menu_label_icon.sql
0 → 100644
View file @
0d997a20
-- 097_fix_migrated_purchase_menu_label_icon.sql
--
-- Fixes the custom menu item created by migration 096: updates the label
-- from hardcoded English "Purchase" to "充值/订阅", and sets the icon_svg
-- to a credit-card SVG matching the sidebar CreditCardIcon.
--
-- Idempotent: only modifies items where id = 'migrated_purchase_subscription'.
DO
$$
DECLARE
v_raw
text
;
v_items
jsonb
;
v_idx
int
;
v_icon
text
;
v_elem
jsonb
;
v_i
int
:
=
0
;
BEGIN
SELECT
value
INTO
v_raw
FROM
settings
WHERE
key
=
'custom_menu_items'
;
IF
COALESCE
(
v_raw
,
''
)
=
''
OR
v_raw
=
'null'
THEN
RETURN
;
END
IF
;
v_items
:
=
v_raw
::
jsonb
;
-- Find the index of the migrated item by iterating the array
v_idx
:
=
NULL
;
FOR
v_elem
IN
SELECT
jsonb_array_elements
(
v_items
)
LOOP
IF
v_elem
->>
'id'
=
'migrated_purchase_subscription'
THEN
v_idx
:
=
v_i
;
EXIT
;
END
IF
;
v_i
:
=
v_i
+
1
;
END
LOOP
;
IF
v_idx
IS
NULL
THEN
RETURN
;
-- item not found, nothing to fix
END
IF
;
-- Credit card SVG (Heroicons outline, matches CreditCardIcon in AppSidebar)
v_icon
:
=
'<svg fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="1.5"><path stroke-linecap="round" stroke-linejoin="round" d="M2.25 8.25h19.5M2.25 9h19.5m-16.5 5.25h6m-6 2.25h3m-3.75 3h15a2.25 2.25 0 002.25-2.25V6.75A2.25 2.25 0 0019.5 4.5h-15a2.25 2.25 0 00-2.25 2.25v10.5A2.25 2.25 0 004.5 19.5z"/></svg>'
;
-- Update label and icon_svg
v_items
:
=
jsonb_set
(
v_items
,
ARRAY
[
v_idx
::
text
,
'label'
],
'"充值/订阅"'
::
jsonb
);
v_items
:
=
jsonb_set
(
v_items
,
ARRAY
[
v_idx
::
text
,
'icon_svg'
],
to_jsonb
(
v_icon
));
UPDATE
settings
SET
value
=
v_items
::
text
WHERE
key
=
'custom_menu_items'
;
RAISE
NOTICE
'[migration-097] Fixed migrated_purchase_subscription: label=充值/订阅, icon=CreditCard SVG'
;
END
$$
;
backend/migration_release/100_remove_easypay_from_enabled_payment_types.sql
0 → 100644
View file @
0d997a20
-- 098_remove_easypay_from_enabled_payment_types.sql
--
-- Removes "easypay" from ENABLED_PAYMENT_TYPES setting.
-- "easypay" is a provider key, not a payment type. Valid payment types
-- are: alipay, wxpay, alipay_direct, wxpay_direct, stripe.
--
-- Idempotent: safe to run multiple times.
UPDATE
settings
SET
value
=
array_to_string
(
array_remove
(
string_to_array
(
value
,
','
),
'easypay'
),
','
)
WHERE
key
=
'ENABLED_PAYMENT_TYPES'
AND
value
LIKE
'%easypay%'
;
backend/migration_release/101_add_account_stats_pricing.sql
0 → 100644
View file @
0d997a20
-- Account statistics pricing: allow channels to configure custom pricing for account cost tracking.
-- 1. Channel-level toggle
ALTER
TABLE
channels
ADD
COLUMN
IF
NOT
EXISTS
apply_pricing_to_account_stats
BOOLEAN
NOT
NULL
DEFAULT
FALSE
;
-- 2. Account stats pricing rules (ordered list per channel)
CREATE
TABLE
IF
NOT
EXISTS
channel_account_stats_pricing_rules
(
id
BIGSERIAL
PRIMARY
KEY
,
channel_id
BIGINT
NOT
NULL
REFERENCES
channels
(
id
)
ON
DELETE
CASCADE
,
name
VARCHAR
(
100
)
NOT
NULL
DEFAULT
''
,
group_ids
BIGINT
[]
NOT
NULL
DEFAULT
'{}'
,
account_ids
BIGINT
[]
NOT
NULL
DEFAULT
'{}'
,
sort_order
INT
NOT
NULL
DEFAULT
0
,
created_at
TIMESTAMPTZ
NOT
NULL
DEFAULT
NOW
(),
updated_at
TIMESTAMPTZ
NOT
NULL
DEFAULT
NOW
()
);
CREATE
INDEX
IF
NOT
EXISTS
idx_cas_pricing_rules_channel_id
ON
channel_account_stats_pricing_rules
(
channel_id
);
-- 3. Model pricing for each rule (same structure as channel_model_pricing)
CREATE
TABLE
IF
NOT
EXISTS
channel_account_stats_model_pricing
(
id
BIGSERIAL
PRIMARY
KEY
,
rule_id
BIGINT
NOT
NULL
REFERENCES
channel_account_stats_pricing_rules
(
id
)
ON
DELETE
CASCADE
,
platform
VARCHAR
(
50
)
NOT
NULL
DEFAULT
''
,
models
JSONB
NOT
NULL
DEFAULT
'[]'
,
billing_mode
VARCHAR
(
20
)
NOT
NULL
DEFAULT
'token'
,
input_price
NUMERIC
(
20
,
10
),
output_price
NUMERIC
(
20
,
10
),
cache_write_price
NUMERIC
(
20
,
10
),
cache_read_price
NUMERIC
(
20
,
10
),
image_output_price
NUMERIC
(
20
,
10
),
per_request_price
NUMERIC
(
20
,
10
),
created_at
TIMESTAMPTZ
NOT
NULL
DEFAULT
NOW
(),
updated_at
TIMESTAMPTZ
NOT
NULL
DEFAULT
NOW
()
);
CREATE
INDEX
IF
NOT
EXISTS
idx_cas_model_pricing_rule_id
ON
channel_account_stats_model_pricing
(
rule_id
);
-- 4. Usage logs: pre-computed account stats cost (NULL = use default formula)
ALTER
TABLE
usage_logs
ADD
COLUMN
IF
NOT
EXISTS
account_stats_cost
NUMERIC
(
20
,
10
);
backend/migration_release/101_add_balance_notify_fields.sql
0 → 100644
View file @
0d997a20
-- Balance notification user preferences
ALTER
TABLE
users
ADD
COLUMN
IF
NOT
EXISTS
balance_notify_enabled
BOOLEAN
NOT
NULL
DEFAULT
true
;
ALTER
TABLE
users
ADD
COLUMN
IF
NOT
EXISTS
balance_notify_threshold
DECIMAL
(
20
,
8
)
DEFAULT
NULL
;
ALTER
TABLE
users
ADD
COLUMN
IF
NOT
EXISTS
balance_notify_extra_emails
TEXT
NOT
NULL
DEFAULT
'[]'
;
backend/migration_release/101_add_channel_features_config.sql
0 → 100644
View file @
0d997a20
ALTER
TABLE
channels
ADD
COLUMN
IF
NOT
EXISTS
features_config
JSONB
NOT
NULL
DEFAULT
'{}'
;
COMMENT
ON
COLUMN
channels
.
features_config
IS
'渠道特性配置(如 web_search_emulation),JSON 对象格式'
;
backend/migration_release/101_add_payment_mode.sql
0 → 100644
View file @
0d997a20
-- Add payment_mode field to payment_provider_instances
-- Values: 'redirect' (hosted page redirect), 'api' (API call for QR/payurl), '' (default/N/A)
ALTER
TABLE
payment_provider_instances
ADD
COLUMN
IF
NOT
EXISTS
payment_mode
VARCHAR
(
20
)
NOT
NULL
DEFAULT
''
;
-- Migrate existing data: easypay instances with 'easypay' in supported_types → redirect mode
-- Remove 'easypay' from supported_types and set payment_mode = 'redirect'
UPDATE
payment_provider_instances
SET
payment_mode
=
'redirect'
,
supported_types
=
TRIM
(
BOTH
','
FROM
REPLACE
(
REPLACE
(
REPLACE
(
supported_types
,
'easypay,'
,
''
),
',easypay'
,
''
),
'easypay'
,
''
))
WHERE
provider_key
=
'easypay'
AND
supported_types
LIKE
'%easypay%'
;
-- EasyPay instances without 'easypay' in supported_types → api mode
UPDATE
payment_provider_instances
SET
payment_mode
=
'api'
WHERE
provider_key
=
'easypay'
AND
payment_mode
=
''
;
backend/migration_release/102_add_balance_notify_threshold_type.sql
0 → 100644
View file @
0d997a20
-- Add threshold type support (fixed / percentage) to balance notification
ALTER
TABLE
users
ADD
COLUMN
IF
NOT
EXISTS
balance_notify_threshold_type
VARCHAR
(
10
)
NOT
NULL
DEFAULT
'fixed'
;
-- Track cumulative recharge amount for percentage threshold calculation
ALTER
TABLE
users
ADD
COLUMN
IF
NOT
EXISTS
total_recharged
DECIMAL
(
20
,
8
)
NOT
NULL
DEFAULT
0
;
backend/migration_release/102_add_out_trade_no_to_payment_orders.sql
0 → 100644
View file @
0d997a20
-- 100_add_out_trade_no_to_payment_orders.sql
-- Adds out_trade_no column for external order ID used with payment providers.
-- Allows webhook handlers to look up orders by external ID instead of embedding DB ID.
ALTER
TABLE
payment_orders
ADD
COLUMN
IF
NOT
EXISTS
out_trade_no
VARCHAR
(
64
)
NOT
NULL
DEFAULT
''
;
CREATE
INDEX
IF
NOT
EXISTS
paymentorder_out_trade_no
ON
payment_orders
(
out_trade_no
);
backend/migration_release/103_add_allow_user_refund.sql
0 → 100644
View file @
0d997a20
ALTER
TABLE
payment_provider_instances
ADD
COLUMN
IF
NOT
EXISTS
allow_user_refund
BOOLEAN
NOT
NULL
DEFAULT
false
;
backend/migration_release/104_migrate_notify_emails_to_struct.sql
0 → 100644
View file @
0d997a20
-- Migrate notification email lists from old []string format to new []NotifyEmailEntry format
-- Old: ["a@x.com", "b@x.com"]
-- New: [{"email":"a@x.com","disabled":false,"verified":true}, ...]
-- Existing emails are marked as verified=false (unverified), disabled=false (enabled)
-- 1. User balance notification emails
UPDATE
users
SET
balance_notify_extra_emails
=
(
SELECT
COALESCE
(
jsonb_agg
(
jsonb_build_object
(
'email'
,
elem
::
text
,
'disabled'
,
false
,
'verified'
,
false
)),
'[]'
::
jsonb
)::
text
FROM
jsonb_array_elements_text
(
balance_notify_extra_emails
::
jsonb
)
AS
elem
)
WHERE
balance_notify_extra_emails
IS
NOT
NULL
AND
balance_notify_extra_emails
<>
'[]'
AND
balance_notify_extra_emails
<>
''
AND
(
balance_notify_extra_emails
::
jsonb
->
0
)
IS
NOT
NULL
AND
jsonb_typeof
(
balance_notify_extra_emails
::
jsonb
->
0
)
=
'string'
;
-- 2. Admin account quota notification emails
UPDATE
settings
SET
value
=
(
SELECT
COALESCE
(
jsonb_agg
(
jsonb_build_object
(
'email'
,
elem
::
text
,
'disabled'
,
false
,
'verified'
,
false
)),
'[]'
::
jsonb
)::
text
FROM
jsonb_array_elements_text
(
value
::
jsonb
)
AS
elem
)
WHERE
key
=
'account_quota_notify_emails'
AND
value
IS
NOT
NULL
AND
value
<>
'[]'
AND
value
<>
''
AND
(
value
::
jsonb
->
0
)
IS
NOT
NULL
AND
jsonb_typeof
(
value
::
jsonb
->
0
)
=
'string'
;
backend/migration_release/105_migrate_websearch_emulation_to_tristate.sql
0 → 100644
View file @
0d997a20
-- Convert old boolean web_search_emulation to tri-state string
-- true → "enabled", false → remove key (becomes "default")
UPDATE
accounts
SET
extra
=
(
extra
-
'web_search_emulation'
)
||
jsonb_build_object
(
'web_search_emulation'
,
'enabled'
)
WHERE
extra
?
'web_search_emulation'
AND
extra
->>
'web_search_emulation'
=
'true'
;
UPDATE
accounts
SET
extra
=
extra
-
'web_search_emulation'
WHERE
extra
?
'web_search_emulation'
AND
extra
->>
'web_search_emulation'
=
'false'
;
backend/migration_release/106_add_account_stats_pricing_intervals.sql
0 → 100644
View file @
0d997a20
-- Add intervals table for account stats pricing rules (mirrors channel_pricing_intervals).
CREATE
TABLE
IF
NOT
EXISTS
channel_account_stats_pricing_intervals
(
id
BIGSERIAL
PRIMARY
KEY
,
pricing_id
BIGINT
NOT
NULL
REFERENCES
channel_account_stats_model_pricing
(
id
)
ON
DELETE
CASCADE
,
min_tokens
INT
NOT
NULL
DEFAULT
0
,
max_tokens
INT
,
tier_label
VARCHAR
(
50
),
input_price
NUMERIC
(
20
,
12
),
output_price
NUMERIC
(
20
,
12
),
cache_write_price
NUMERIC
(
20
,
12
),
cache_read_price
NUMERIC
(
20
,
12
),
per_request_price
NUMERIC
(
20
,
12
),
sort_order
INT
NOT
NULL
DEFAULT
0
,
created_at
TIMESTAMPTZ
NOT
NULL
DEFAULT
NOW
(),
updated_at
TIMESTAMPTZ
NOT
NULL
DEFAULT
NOW
()
);
CREATE
INDEX
IF
NOT
EXISTS
idx_account_stats_pricing_intervals_pricing_id
ON
channel_account_stats_pricing_intervals
(
pricing_id
);
Prev
1
2
3
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment