#!/usr/bin/env python3 """voucher 种子:注册送 400 元欢迎券模板(WELCOME400)+ 规则。 幂等:模板按 code 判重存在即跳过(管理员后续在界面调整不受影响)。 活动参数(2026-09-06 用户定夺): - 面值 400 元,前 100 名(total_count=100 原子占额控制),30 天有效 - 规则:仅限产线订阅类产品(product_type ∈ [pipeline]) - 状态直接 active(注册挂钩只认 active 模板) 结束活动:管理界面把模板置 inactive 即可,无需改代码。 从应用根执行:py3/bin/python pkgs/voucher/scripts/seed_welcome_voucher.py """ import sys import os import asyncio APP_ROOT = os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../..")) sys.path.insert(0, os.path.join(APP_ROOT, "py3", "lib", "python3.10", "site-packages")) sys.path.insert(0, APP_ROOT) from sqlor.dbpools import DBPools from appPublic.jsonConfig import getConfig from appPublic.uniqueID import getID WELCOME_CODE = "WELCOME400" async def main(): config = getConfig(APP_ROOT, NS={"workdir": APP_ROOT}) DBPools(config.databases) async with DBPools().sqlorContext("pipeline") as sor: recs = await sor.R("voucher_template", {"code": WELCOME_CODE}) if recs: print(f"seed: {WELCOME_CODE} already exists (id={recs[0].id}), skip") return tid = getID() await sor.C("voucher_template", { "id": tid, "name": "新客户欢迎券", "code": WELCOME_CODE, "face_value": 400.0, "total_count": 100, "issued_count": 0, "valid_days": 30, "status": "active", "remark": "注册自动赠送,前100名,仅限产线订阅类产品,30天有效", "org_id": "0", "created_by": "system", }) rid = getID() await sor.C("voucher_rule", { "id": rid, "template_id": tid, "rule_type": "product_type", "rule_config": '{"product_types": ["pipeline"]}', "enabled": "1", "sort_order": 1, "remark": "仅限产线订阅类产品(400券只能买产线)", }) await sor.sqlExe("COMMIT", {}) print(f"seed: {WELCOME_CODE} created (template_id={tid}, rule_id={rid})") if __name__ == "__main__": asyncio.run(main())