fix(discount): 兼容discount_detail表不存在的情况,fallback到discount.discount字段 + 新增discount_detail表定义和迁移脚本 + 修复discount.json中float类型缺少dec字段

This commit is contained in:
yumoqing 2026-05-24 22:31:42 +08:00
parent b41c89e9dd
commit 3a57205337
5 changed files with 242 additions and 12 deletions

Binary file not shown.

View File

@ -124,9 +124,18 @@ async def disable_old_discount(sor, resellerid, customerid, biz_date):
return return
async def _discount_detail_exists(sor):
"""Check if discount_detail table exists."""
try:
await sor.sqlExe("SELECT 1 FROM discount_detail LIMIT 0", {})
return True
except Exception:
return False
async def sor_get_star_discount(sor, resellerid, biz_date): async def sor_get_star_discount(sor, resellerid, biz_date):
"""Get default discount for a reseller (no specific customer).""" """Get default discount for a reseller (no specific customer)."""
sql = """select d.id from discount d sql = """select d.id, d.discount from discount d
where d.resellerid = ${resellerid}$ where d.resellerid = ${resellerid}$
and d.customerid is NULL and d.customerid is NULL
and d.enabled_date <= ${biz_date}$ and d.enabled_date <= ${biz_date}$
@ -139,15 +148,19 @@ where d.resellerid = ${resellerid}$
if not recs: if not recs:
return 1 return 1
# Look up default discount detail (prodtypeid=None, productid=None) discountid = recs[0].id
sql2 = """select discount from discount_detail # If discount_detail table exists, look up default detail
if await _discount_detail_exists(sor):
sql2 = """select discount from discount_detail
where discountid = ${discountid}$ where discountid = ${discountid}$
and prodtypeid is NULL and prodtypeid is NULL
and productid is NULL""" and productid is NULL"""
recs2 = await sor.sqlExe(sql2, {'discountid': recs[0].id}) recs2 = await sor.sqlExe(sql2, {'discountid': discountid})
if not recs2: if not recs2:
return 1 return 1
return recs2[0].discount return recs2[0].discount
# Fallback: read discount value directly from discount table
return recs[0].discount if recs[0].discount is not None else 1
async def sor_get_customer_discount(sor, resellerid, customerid): async def sor_get_customer_discount(sor, resellerid, customerid):
@ -170,14 +183,18 @@ where resellerid = ${resellerid}$
return await sor_get_star_discount(sor, resellerid, biz_date) return await sor_get_star_discount(sor, resellerid, biz_date)
# Return default discount for this customer (prodtypeid=None, productid=None) # Return default discount for this customer (prodtypeid=None, productid=None)
sql2 = """select discount from discount_detail discountid = recs[0].id
if await _discount_detail_exists(sor):
sql2 = """select discount from discount_detail
where discountid = ${discountid}$ where discountid = ${discountid}$
and prodtypeid is NULL and prodtypeid is NULL
and productid is NULL""" and productid is NULL"""
recs2 = await sor.sqlExe(sql2, {'discountid': recs[0].id}) recs2 = await sor.sqlExe(sql2, {'discountid': discountid})
if not recs2: if not recs2:
return 1 return 1
return recs2[0].discount return recs2[0].discount
# Fallback: read discount value directly from discount table
return recs[0].discount if recs[0].discount is not None else 1
async def sor_get_product_discount(sor, resellerid, customerid, prodtypeid, productid): async def sor_get_product_discount(sor, resellerid, customerid, prodtypeid, productid):
@ -218,6 +235,10 @@ where resellerid = ${resellerid}$
discountid = recs[0].id discountid = recs[0].id
# If discount_detail table doesn't exist, fall back to discount.discount
if not await _discount_detail_exists(sor):
return recs[0].discount if recs[0].discount is not None else 1.0
# Step 2: Try exact product match # Step 2: Try exact product match
sql2 = """select discount from discount_detail sql2 = """select discount from discount_detail
where discountid = ${discountid}$ where discountid = ${discountid}$

69
models/discount.json Normal file
View File

@ -0,0 +1,69 @@
{
"summary": [
{
"name": "discount",
"title": "折扣表",
"primary": ["id"],
"catelog": "entity"
}
],
"fields": [
{
"name": "id",
"title": "id",
"type": "str",
"length": 32
},
{
"name": "name",
"title": "折扣名称",
"type": "str",
"length": 100
},
{
"name": "resellerid",
"title": "商户id",
"type": "str",
"length": 32,
"default": "*"
},
{
"name": "customerid",
"title": "客户id",
"type": "str",
"length": 32,
"default": "*"
},
{
"name": "discount",
"title": "折扣",
"type": "float",
"length": 5,
"dec": 4
},
{
"name": "enabled_date",
"title": "启用日期",
"type": "date"
},
{
"name": "expired_date",
"title": "失效日期",
"type": "date"
}
],
"codes": [
{
"field": "resellerid",
"table": "organization",
"valuefield": "id",
"textfield": "orgname"
},
{
"field": "customerid",
"table": "organization",
"valuefield": "id",
"textfield": "orgname"
}
]
}

View File

@ -0,0 +1,79 @@
{
"summary": [
{
"name": "discount_detail",
"title": "折扣明细表",
"primary": ["id"],
"catelog": "entity"
}
],
"fields": [
{
"name": "id",
"title": "id",
"type": "str",
"length": 32,
"nullable": "no"
},
{
"name": "discountid",
"title": "折扣方案id",
"type": "str",
"length": 32,
"nullable": "no"
},
{
"name": "resellerid",
"title": "商户id",
"type": "str",
"length": 32,
"nullable": "no"
},
{
"name": "prodtypeid",
"title": "产品种类id",
"type": "str",
"length": 32
},
{
"name": "productid",
"title": "产品id",
"type": "str",
"length": 32
},
{
"name": "discount",
"title": "折扣",
"type": "double",
"length": 5,
"dec": 4,
"nullable": "no"
}
],
"indexes": [
{
"name": "idx_dd_discountid",
"idxtype": "index",
"idxfields": ["discountid"]
},
{
"name": "idx_dd_product",
"idxtype": "index",
"idxfields": ["discountid", "prodtypeid", "productid"]
}
],
"codes": [
{
"field": "discountid",
"table": "discount",
"valuefield": "id",
"textfield": "name"
},
{
"field": "resellerid",
"table": "organization",
"valuefield": "id",
"textfield": "orgname"
}
]
}

View File

@ -0,0 +1,61 @@
-- ============================================================
-- discount 模块迁移脚本:新增 discount_detail 表
-- 从旧版 discount 表迁移折扣值到 discount_detail
-- 日期: 2026-05-24
-- 执行前请备份数据库!
-- ============================================================
-- 1. 创建 discount_detail 表
CREATE TABLE IF NOT EXISTS discount_detail
(
`id` VARCHAR(32) NOT NULL COMMENT 'id',
`discountid` VARCHAR(32) NOT NULL COMMENT '折扣id',
`resellerid` VARCHAR(32) DEFAULT '*' COMMENT '商户id',
`prodtypeid` VARCHAR(32) DEFAULT NULL COMMENT '产品类型id',
`productid` VARCHAR(32) DEFAULT NULL COMMENT '产品id',
`discount` double(5,4) COMMENT '折扣值',
PRIMARY KEY(id),
INDEX idx_dd_discountid (discountid),
INDEX idx_dd_product (discountid, prodtypeid, productid)
)
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci
engine=innodb
COMMENT '折扣产品明细';
-- 2. 为 discount 表添加 name 字段(如果不存在)
ALTER TABLE discount ADD COLUMN IF NOT EXISTS `name` VARCHAR(100) COMMENT '折扣名称';
-- 3. 将现有 discount 记录的 discount 值迁移到 discount_detail
-- 为每条 discount 记录创建一条默认明细prodtypeid=NULL, productid=NULL
INSERT IGNORE INTO discount_detail (id, discountid, resellerid, prodtypeid, productid, discount)
SELECT
CONCAT('mig_', id, '_default') AS id,
d.id AS discountid,
d.resellerid,
NULL AS prodtypeid,
NULL AS productid,
d.discount
FROM discount d
WHERE d.discount IS NOT NULL AND d.discount > 0
AND NOT EXISTS (
SELECT 1 FROM discount_detail dd
WHERE dd.discountid = d.id
AND dd.prodtypeid IS NULL
AND dd.productid IS NULL
);
-- ============================================================
-- 验证步骤(执行后运行):
-- 1. 确认表创建成功:
-- SHOW TABLES LIKE 'discount_detail';
-- 2. 确认明细记录已迁移:
-- SELECT COUNT(*) FROM discount_detail;
-- SELECT * FROM discount_detail ORDER BY discountid;
-- 3. 确认 discount 表 name 字段存在:
-- DESCRIBE discount;
-- ============================================================
-- 回滚步骤(如需撤销):
-- DROP TABLE IF EXISTS discount_detail;
-- ALTER TABLE discount DROP COLUMN IF EXISTS name;
-- ============================================================