From bc8af7a4cfdc1d9299c591346dd48458d446f194 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Sat, 4 Jul 2026 19:49:02 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E4=BA=A7=E5=93=81=E6=8A=98=E6=89=A3?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E6=98=BE=E7=A4=BA=E5=9F=BA=E5=87=86=E6=8A=98?= =?UTF-8?q?=E6=89=A3(1.0)=E5=B9=B6=E6=A0=87=E8=AE=B0=E6=96=B9=E6=A1=88?= =?UTF-8?q?=E5=86=85=E4=BA=A7=E5=93=81=20-=20get=5Fdiscount=5Fsetting=5Fpr?= =?UTF-8?q?oducts:=20LEFT=20JOIN=E5=9F=BA=E5=87=86=E6=8A=98=E6=89=A3?= =?UTF-8?q?=E6=96=B9=E6=A1=88=5FHeaX,=20COALESCE=E4=BC=98=E5=85=88?= =?UTF-8?q?=E6=96=B9=E6=A1=88=E6=8A=98=E6=89=A3,=20=E6=96=B0=E5=A2=9Ein=5F?= =?UTF-8?q?plan=E5=AD=97=E6=AE=B5=20-=20get=5Fproducts=5Fwith=5Fdiscount.d?= =?UTF-8?q?spy:=20=E5=90=8C=E6=AD=A5=E5=8A=A0=E5=9F=BA=E5=87=86=E6=8A=98?= =?UTF-8?q?=E6=89=A3COALESCE=20-=20index.ui:=20=E6=8A=98=E6=89=A3=E9=BB=98?= =?UTF-8?q?=E8=AE=A41.0,=20=E6=96=B0=E5=A2=9E'=E2=9C=93=E6=96=B9=E6=A1=88?= =?UTF-8?q?=E5=86=85'=E6=A0=87=E8=AE=B0=E5=88=97=20-=20save=5Fdiscount:=20?= =?UTF-8?q?old=5Fdiscount=E9=BB=98=E8=AE=A41.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- discount/init.py | 21 +- .../get_products_with_discount.dspy | 24 ++- wwwroot/discount_setting/index.ui | 194 +++++++++--------- 3 files changed, 134 insertions(+), 105 deletions(-) diff --git a/discount/init.py b/discount/init.py index 1ad3139..3800537 100644 --- a/discount/init.py +++ b/discount/init.py @@ -754,6 +754,10 @@ async def get_discount_setting_products(request): config = getConfig() db.databases = config.databases + # 查询基准折扣方案ID (customerid='*', 全部用户适用) + base_sql = "SELECT id FROM discount WHERE customerid='*' AND resellerid=${org_id}$ LIMIT 1" + base_ns = {'org_id': user_orgid} + sql = """ SELECT p.id as productid, @@ -762,18 +766,31 @@ async def get_discount_setting_products(request): p.category_id, pc.name as category_name, dd.id as detail_id, - dd.discount, - dd.discountid + COALESCE(dd.discount, base_dd.discount) as discount, + dd.discountid, + CASE WHEN dd.id IS NOT NULL THEN 1 ELSE 0 END as in_plan FROM product p LEFT JOIN product_category pc ON p.category_id = pc.id LEFT JOIN discount_detail dd ON dd.productid = p.id AND dd.discountid = ${discountid}$ + LEFT JOIN discount_detail base_dd ON base_dd.productid = p.id + AND base_dd.discountid = ${base_discountid}$ WHERE p.org_id = ${org_id}$ AND p.status = '1' """ ns = {'discountid': discountid, 'org_id': user_orgid} async with db.sqlorContext(dbname) as sor: + # 查询基准折扣方案ID, 若不存在则降级(没有基准折扣) + base_recs = await sor.sqlExe(base_sql, base_ns) + base_discountid = base_recs[0].id if base_recs else None + if base_discountid: + ns['base_discountid'] = base_discountid + else: + # 无基准方案时, 用discountid自身代替, 保证COALESCE正常(只会取dd.discount, base_dd为NULL) + ns['base_discountid'] = discountid + recs = await sor.sqlExe(sql, ns) + # 为每个产品附加 in_plan 标记 return recs if recs else [] diff --git a/wwwroot/discount_setting/get_products_with_discount.dspy b/wwwroot/discount_setting/get_products_with_discount.dspy index bc48efd..b9e4649 100644 --- a/wwwroot/discount_setting/get_products_with_discount.dspy +++ b/wwwroot/discount_setting/get_products_with_discount.dspy @@ -16,6 +16,17 @@ if not ns.get('page'): if not ns.get('sort'): ns['sort'] = 'category_name, product_name' +ns['org_id'] = user_orgid + +db = DBPools() +dbname = get_module_dbname('discount') +# 查询基准折扣方案ID (customerid='*', 全部用户适用) +base_sql = "SELECT id FROM discount WHERE customerid='*' AND resellerid=${org_id}$ LIMIT 1" +async with db.sqlorContext(dbname) as sor: + base_recs = await sor.sqlExe(base_sql, ns.copy()) + base_discountid = base_recs[0].id if base_recs else discountid + ns['base_discountid'] = base_discountid + sql = ''' SELECT p.id as productid, @@ -24,21 +35,20 @@ SELECT p.category_id, pc.name as category_name, dd.id as detail_id, - dd.discount, - dd.discountid + COALESCE(dd.discount, base_dd.discount) as discount, + dd.discountid, + CASE WHEN dd.id IS NOT NULL THEN 1 ELSE 0 END as in_plan FROM product p LEFT JOIN product_category pc ON p.category_id = pc.id LEFT JOIN discount_detail dd ON dd.productid = p.id AND dd.discountid = ${discountid}$ +LEFT JOIN discount_detail base_dd ON base_dd.productid = p.id + AND base_dd.discountid = ${base_discountid}$ WHERE p.org_id = ${org_id}$ AND p.status = '1' ORDER BY pc.name, p.product_name ''' -ns['org_id'] = user_orgid - -db = DBPools() -dbname = get_module_dbname('discount') -debug(f'get_products_with_discount: org_id={user_orgid}, discountid={discountid}, dbname={dbname}') +debug(f'get_products_with_discount: org_id={user_orgid}, discountid={discountid}, dbname={dbname}, base_discountid={ns["base_discountid"]}') async with db.sqlorContext(dbname) as sor: r = await sor.sqlPaging(sql, ns.copy()) debug(f'{sql=}, {ns=},get_products_with_discount: returned {len(r.get("rows", []))} products') diff --git a/wwwroot/discount_setting/index.ui b/wwwroot/discount_setting/index.ui index a604a08..b0011b6 100644 --- a/wwwroot/discount_setting/index.ui +++ b/wwwroot/discount_setting/index.ui @@ -1,102 +1,104 @@ {% set products = get_discount_setting_products(request) %} {% set info = get_discount_info(request) %} { - "widgettype": "VBox", - "options": { - "width": "100%", - "height": "100%", - "css": "filler" - }, - "subwidgets": [ - { - "widgettype": "Text", - "options": { - "text": "产品折扣设置 - {{info.name or ''}}{% if info.customer %} ({{info.customer}}){% endif %}", - "fontSize": "16px", - "fontWeight": "600", - "color": "#F1F5F9", - "padding": "8px 12px" - } - }, - { - "widgettype": "HBox", - "options": { - "bgcolor": "#0F172A", - "padding": "8px 0", - "borderRadius": "6px 6px 0 0", - "alignItems": "center", - "width": "100%" - }, - "subwidgets": [ - {"widgettype": "Text", "options": {"text": "产品分类", "width": "22%", "padding": "0 12px", "fontSize": "12px", "fontWeight": "600", "color": "#94A3B8"}}, - {"widgettype": "Text", "options": {"text": "产品名称", "width": "34%", "padding": "0 12px", "fontSize": "12px", "fontWeight": "600", "color": "#94A3B8"}}, - {"widgettype": "Text", "options": {"text": "产品编码", "width": "22%", "padding": "0 12px", "fontSize": "12px", "fontWeight": "600", "color": "#94A3B8"}}, - {"widgettype": "Text", "options": {"text": "折扣", "width": "22%", "padding": "0 12px", "fontSize": "12px", "fontWeight": "600", "color": "#94A3B8"}} - ] - }, - { - "widgettype": "VScrollPanel", - "options": { - "width": "100%", - "flex": "1" - }, - "subwidgets": [ - { - "widgettype": "VBox", - "options": { - "width": "100%" - }, - "subwidgets": [ +\t"widgettype": "VBox", +\t"options": { +\t\t"width": "100%", +\t\t"height": "100%", +\t\t"css": "filler" +\t}, +\t"subwidgets": [ +\t\t{ +\t\t\t"widgettype": "Text", +\t\t\t"options": { +\t\t\t\t"text": "产品折扣设置 - {{info.name or ''}}{% if info.customer %} ({{info.customer}}){% endif %}", +\t\t\t\t"fontSize": "16px", +\t\t\t\t"fontWeight": "600", +\t\t\t\t"color": "#F1F5F9", +\t\t\t\t"padding": "8px 12px" +\t\t\t} +\t\t}, +\t\t{ +\t\t\t"widgettype": "HBox", +\t\t\t"options": { +\t\t\t\t"bgcolor": "#0F172A", +\t\t\t\t"padding": "8px 0", +\t\t\t\t"borderRadius": "6px 6px 0 0", +\t\t\t\t"alignItems": "center", +\t\t\t\t"width": "100%" +\t\t\t}, +\t\t\t"subwidgets": [ +\t\t\t\t{"widgettype": "Text", "options": {"text": "产品分类", "width": "20%", "padding": "0 8px", "fontSize": "12px", "fontWeight": "600", "color": "#94A3B8"}}, +\t\t\t\t{"widgettype": "Text", "options": {"text": "产品名称", "width": "28%", "padding": "0 8px", "fontSize": "12px", "fontWeight": "600", "color": "#94A3B8"}}, +\t\t\t\t{"widgettype": "Text", "options": {"text": "产品编码", "width": "18%", "padding": "0 8px", "fontSize": "12px", "fontWeight": "600", "color": "#94A3B8"}}, +\t\t\t\t{"widgettype": "Text", "options": {"text": "折扣", "width": "14%", "padding": "0 8px", "fontSize": "12px", "fontWeight": "600", "color": "#94A3B8"}}, +\t\t\t\t{"widgettype": "Text", "options": {"text": "状态", "width": "16%", "padding": "0 8px", "fontSize": "12px", "fontWeight": "600", "color": "#94A3B8"}} +\t\t\t] +\t\t}, +\t\t{ +\t\t\t"widgettype": "VScrollPanel", +\t\t\t"options": { +\t\t\t\t"width": "100%", +\t\t\t\t"flex": "1" +\t\t\t}, +\t\t\t"subwidgets": [ +\t\t\t\t{ +\t\t\t\t\t"widgettype": "VBox", +\t\t\t\t\t"options": { +\t\t\t\t\t\t"width": "100%" +\t\t\t\t\t}, +\t\t\t\t\t"subwidgets": [ {% for p in products %} - { - "widgettype": "HBox", - "options": { - "padding": "6px 0", - "border": "0 0 1px 0", - "borderColor": "#334155", - "alignItems": "center", - "width": "100%" - }, - "subwidgets": [ - {"widgettype": "Text", "options": {"text": "{{p.category_name or ''}}", "width": "22%", "padding": "0 12px", "fontSize": "12px", "color": "#E2E8F0"}}, - {"widgettype": "Text", "options": {"text": "{{p.product_name or ''}}", "width": "34%", "padding": "0 12px", "fontSize": "12px", "color": "#F1F5F9"}}, - {"widgettype": "Text", "options": {"text": "{{p.product_code or ''}}", "width": "22%", "padding": "0 12px", "fontSize": "12px", "color": "#E2E8F0"}}, - { - "widgettype": "UiFloat", - "options": { - "width": "22%", - "padding": "0 12px", - "name": "discount", - "value": "{{p.discount or ''}}", - "placeholder": "0~1", - "dec_len": 2, - "fontSize": "12px" - }, - "binds": [ - { - "wid": "self", - "event": "blur", - "actiontype": "urlwidget", - "datawidget": "self", - "target": "self", - "options": { - "url": "{{entire_url('./save_discount.dspy')}}", - "params": { - "discountid": "{{params_kw.discountid}}", - "old_discount": "{{p.discount or ''}}", - "productid": "{{p.productid}}", - "detail_id": "{{p.detail_id or ''}}" - } - } - } - ] - } - ] - }{% if not loop.last %},{% endif %} +\t\t\t\t\t\t{ +\t\t\t\t\t\t\t"widgettype": "HBox", +\t\t\t\t\t\t\t"options": { +\t\t\t\t\t\t\t\t"padding": "6px 0", +\t\t\t\t\t\t\t\t"border": "0 0 1px 0", +\t\t\t\t\t\t\t\t"borderColor": "#334155", +\t\t\t\t\t\t\t\t"alignItems": "center", +\t\t\t\t\t\t\t\t"width": "100%" +\t\t\t\t\t\t\t}, +\t\t\t\t\t\t\t"subwidgets": [ +\t\t\t\t\t\t\t\t{"widgettype": "Text", "options": {"text": "{{p.category_name or ''}}", "width": "20%", "padding": "0 8px", "fontSize": "12px", "color": "#E2E8F0"}}, +\t\t\t\t\t\t\t\t{"widgettype": "Text", "options": {"text": "{{p.product_name or ''}}", "width": "28%", "padding": "0 8px", "fontSize": "12px", "color": "#F1F5F9"}}, +\t\t\t\t\t\t\t\t{"widgettype": "Text", "options": {"text": "{{p.product_code or ''}}", "width": "18%", "padding": "0 8px", "fontSize": "12px", "color": "#E2E8F0"}}, +\t\t\t\t\t\t\t\t{ +\t\t\t\t\t\t\t\t\t"widgettype": "UiFloat", +\t\t\t\t\t\t\t\t\t"options": { +\t\t\t\t\t\t\t\t\t\t"width": "14%", +\t\t\t\t\t\t\t\t\t\t"padding": "0 8px", +\t\t\t\t\t\t\t\t\t\t"name": "discount", +\t\t\t\t\t\t\t\t\t\t"value": "{{p.discount or '1.0'}}", +\t\t\t\t\t\t\t\t\t\t"placeholder": "0~1", +\t\t\t\t\t\t\t\t\t\t"dec_len": 2, +\t\t\t\t\t\t\t\t\t\t"fontSize": "12px" +\t\t\t\t\t\t\t\t\t}, +\t\t\t\t\t\t\t\t\t"binds": [ +\t\t\t\t\t\t\t\t\t\t{ +\t\t\t\t\t\t\t\t\t\t\t"wid": "self", +\t\t\t\t\t\t\t\t\t\t\t"event": "blur", +\t\t\t\t\t\t\t\t\t\t\t"actiontype": "urlwidget", +\t\t\t\t\t\t\t\t\t\t\t"datawidget": "self", +\t\t\t\t\t\t\t\t\t\t\t"target": "self", +\t\t\t\t\t\t\t\t\t\t\t"options": { +\t\t\t\t\t\t\t\t\t\t\t\t"url": "{{entire_url('./save_discount.dspy')}}", +\t\t\t\t\t\t\t\t\t\t\t\t"params": { +\t\t\t\t\t\t\t\t\t\t\t\t\t"discountid": "{{params_kw.discountid}}", +\t\t\t\t\t\t\t\t\t\t\t\t\t"old_discount": "{{p.discount or '1.0'}}", +\t\t\t\t\t\t\t\t\t\t\t\t\t"productid": "{{p.productid}}", +\t\t\t\t\t\t\t\t\t\t\t\t\t"detail_id": "{{p.detail_id or ''}}" +\t\t\t\t\t\t\t\t\t\t\t\t} +\t\t\t\t\t\t\t\t\t\t\t} +\t\t\t\t\t\t\t\t\t\t} +\t\t\t\t\t\t\t\t\t] +\t\t\t\t\t\t\t\t}, +\t\t\t\t\t\t\t\t{"widgettype": "Text", "options": {"text": "{% if p.in_plan == 1 %}✓方案内{% endif %}", "width": "16%", "padding": "0 8px", "fontSize": "11px", "color": "#34D399"}} +\t\t\t\t\t\t\t] +\t\t\t\t\t\t}{% if not loop.last %},{% endif %} {% endfor %} - ] - } - ] - } - ] +\t\t\t\t\t] +\t\t\t\t} +\t\t\t] +\t\t} +\t] }