From 10fe38b4e017cfeb4b2cb4628624b9eaa4549b16 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Mon, 6 Jul 2026 14:19:12 +0800 Subject: [PATCH] feat: add get_min_product_discount and llm_id_to_product_id - get_min_product_discount: find minimum discount for a product across all active discount records (customer-specific + NULL + '*' fallback) - llm_id_to_product_id: convert llmage.llm.id to sage.product.id - Both registered in load_discount() for use in pricing display --- discount/init.py | 87 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/discount/init.py b/discount/init.py index 4ce3f1f..7c1d82a 100644 --- a/discount/init.py +++ b/discount/init.py @@ -276,6 +276,90 @@ where discountid = ${discountid}$ return 1.0 +async def sor_get_min_product_discount(sor, product_id, resellerid, customerid): + """Find the minimum discount for a specific product from active discount records. + + Searches all active discount records for the given (resellerid, customerid), + including fallback to customerid=NULL and customerid='*' defaults. + Returns the minimum discount value across all matching discount_detail rows. + + Args: + sor: sqlor context + product_id: product.id + resellerid: LLM owner's org id (discount.resellerid) + customerid: user's org id (discount.customerid) + + Returns: minimum discount value (float), 1.0 if no discount found. + """ + env = ServerEnv() + biz_date = await env.get_business_date(sor) + + sql = """SELECT dd.discount +FROM discount_detail dd +JOIN discount d ON dd.discountid = d.id +WHERE d.resellerid = ${resellerid}$ + AND (d.customerid = ${customerid}$ OR d.customerid IS NULL OR d.customerid = '*') + AND d.enabled_date <= ${biz_date}$ + AND d.expired_date > ${biz_date}$ + AND dd.productid = ${product_id}$""" + ns = { + 'resellerid': resellerid, + 'customerid': customerid, + 'biz_date': biz_date, + 'product_id': product_id, + } + recs = await sor.sqlExe(sql, ns) + + if recs: + discounts = [r.discount for r in recs if r.discount is not None] + if discounts: + return min(discounts) + + return 1.0 + + +async def get_min_product_discount(product_id, resellerid, customerid): + """Get the minimum discount for a specific product (convenience wrapper). + + Args: + product_id: product.id + resellerid: LLM owner's org id + customerid: user's org id + + Returns: minimum discount value (float), 1.0 if no discount found. + """ + env = ServerEnv() + dbname = env.get_module_dbname('discount') + config = getConfig() + db = DBPools() + db.databases = config.databases + async with db.sqlorContext(dbname) as sor: + return await sor_get_min_product_discount(sor, product_id, resellerid, customerid) + return 1.0 + + +async def llm_id_to_product_id(llm_id): + """Convert an LLM model ID (llmage.llm.id) to a product ID (sage.product.id). + + Args: + llm_id: llmage.llm.id + + Returns: product.id or None if not found. + """ + env = ServerEnv() + dbname = env.get_module_dbname('discount') + config = getConfig() + db = DBPools() + db.databases = config.databases + async with db.sqlorContext(dbname) as sor: + sql = """SELECT id FROM product +WHERE resource_ref_id = ${llm_id}$ AND product_type = 'llm_model' LIMIT 1""" + recs = await sor.sqlExe(sql, {'llm_id': llm_id}) + if recs: + return recs[0].id + return None + + async def get_customer_discount(resellerid, customerid): """Legacy: get default discount for a customer (all products).""" env = ServerEnv() @@ -770,6 +854,9 @@ def load_discount(): env.sor_get_customer_discount = sor_get_customer_discount env.get_product_discount = get_product_discount env.sor_get_product_discount = sor_get_product_discount + env.sor_get_min_product_discount = sor_get_min_product_discount + env.get_min_product_discount = get_min_product_discount + env.llm_id_to_product_id = llm_id_to_product_id env.discount_qrcode = discount_qrcode env.set_promote_discount = set_promote_discount env.get_discount_details = get_discount_details