fix: batch fix dspy violations — remove imports/print/ServerEnv, use return json.dumps, proper widgettype format

This commit is contained in:
yumoqing 2026-07-03 13:57:26 +08:00
parent e79627c55f
commit e766111aa1
11 changed files with 448 additions and 461 deletions

View File

@ -1,31 +1,4 @@
import json
from appPublic.uniqueID import getID
from datetime import datetime
async def main(request, params_kw):
"""
产品销售时调用此API计算供销记账金额。
输入参数:
productid: 产品ID
prodtypeid: 产品分类ID (可选)
quantity: 销售数量
unit_price: 销售单价
sub_distributor_id: 二级分销商ID (可选, 如果是直接销售则为空)
sale_date: 销售日期 (可选, 默认今天)
source_type: 来源类型 (1=手动, 2=API调用)
source_id: 来源记录ID (可选)
计算逻辑:
1. 查找有效的供销合同及对应产品折扣
2. 查找有效的分销协议及对应产品折扣 (如果有二级分销商)
3. 计算: 进货金额 = 单价 * 数量 * 进货折扣
4. 计算: 分销金额 = 单价 * 数量 * 分销折扣
5. 计算: 利润金额 = 分销金额 - 进货金额
6. 创建记账记录
返回: 记账记录数据
"""
user_id = await get_user() user_id = await get_user()
user_orgid = await get_userorgid() user_orgid = await get_userorgid()
dbname = get_module_dbname('supplychain') dbname = get_module_dbname('supplychain')
@ -40,7 +13,7 @@ async def main(request, params_kw):
quantity = float(data.get("quantity", 0)) quantity = float(data.get("quantity", 0))
unit_price = float(data.get("unit_price", 0)) unit_price = float(data.get("unit_price", 0))
sub_distributor_id = data.get("sub_distributor_id") sub_distributor_id = data.get("sub_distributor_id")
sale_date = data.get("sale_date", datetime.now().strftime("%Y-%m-%d")) sale_date = data.get("sale_date", curDateString())
source_type = data.get("source_type", "2") source_type = data.get("source_type", "2")
source_id = data.get("source_id") source_id = data.get("source_id")
remark = data.get("remark", "") remark = data.get("remark", "")
@ -48,20 +21,17 @@ async def main(request, params_kw):
if not productid or quantity <= 0 or unit_price <= 0: if not productid or quantity <= 0 or unit_price <= 0:
return json.dumps({"status": "error", "message": "缺少必要参数: productid, quantity, unit_price"}) return json.dumps({"status": "error", "message": "缺少必要参数: productid, quantity, unit_price"})
config = getConfig(".") db = DBPools()
DBPools(config.databases)
total_amount = quantity * unit_price total_amount = quantity * unit_price
async with db.sqlorContext(dbname) as sor: async with db.sqlorContext(dbname) as sor:
# Step 1: Find active supply contract with product discount # Step 1: Find active supply contract with product discount
# Priority: exact product > product type > default contract discount
supply_contract_id = None supply_contract_id = None
supply_contract_item_id = None supply_contract_item_id = None
supplier_id = None supplier_id = None
supply_discount = 1.0 supply_discount = 1.0
supply_amount = total_amount supply_amount = total_amount
# Find supply contract items matching this product
if prodtypeid: if prodtypeid:
sql_sci = """SELECT sci.id, sci.contract_id, sci.discount, sci.settlement_price, sc.supplier_id sql_sci = """SELECT sci.id, sci.contract_id, sci.discount, sci.settlement_price, sc.supplier_id
FROM supply_contract_items sci FROM supply_contract_items sci
@ -98,7 +68,6 @@ async def main(request, params_kw):
else: else:
supply_amount = total_amount * supply_discount supply_amount = total_amount * supply_discount
else: else:
# Fallback: find any active supply contract with default discount
sql_sc = """SELECT id, supplier_id, default_discount FROM supply_contracts sql_sc = """SELECT id, supplier_id, default_discount FROM supply_contracts
WHERE resellerid = ${resellerid}$ WHERE resellerid = ${resellerid}$
AND status = '1' AND status = '1'
@ -112,14 +81,13 @@ async def main(request, params_kw):
supply_discount = float(sc_recs[0].default_discount) if sc_recs[0].default_discount else 1.0 supply_discount = float(sc_recs[0].default_discount) if sc_recs[0].default_discount else 1.0
supply_amount = total_amount * supply_discount supply_amount = total_amount * supply_discount
# Step 2: Find active distribution agreement with product discount (if sub_distributor) # Step 2: Find active distribution agreement with product discount
distribution_agreement_id = None distribution_agreement_id = None
distribution_agreement_item_id = None distribution_agreement_item_id = None
dist_discount = 1.0 dist_discount = 1.0
dist_amount = total_amount dist_amount = total_amount
if sub_distributor_id: if sub_distributor_id:
# Find distribution agreement items matching this product
sql_dai = """SELECT dai.id, dai.agreement_id, dai.discount, dai.settlement_price sql_dai = """SELECT dai.id, dai.agreement_id, dai.discount, dai.settlement_price
FROM distribution_agreement_items dai FROM distribution_agreement_items dai
JOIN distribution_agreements da ON dai.agreement_id = da.id JOIN distribution_agreements da ON dai.agreement_id = da.id
@ -145,8 +113,10 @@ async def main(request, params_kw):
AND (da.end_date IS NULL OR da.end_date >= ${sale_date}$) AND (da.end_date IS NULL OR da.end_date >= ${sale_date}$)
AND dai.prodtypeid = ${prodtypeid}$ AND dai.prodtypeid = ${prodtypeid}$
ORDER BY dai.created_at DESC LIMIT 1""" ORDER BY dai.created_at DESC LIMIT 1"""
ns_dai["productid"] = None dai_recs = await sor.sqlExe(sql_dai, {"resellerid": user_orgid,
dai_recs = await sor.sqlExe(sql_dai, ns_dai) "sub_distributor_id": sub_distributor_id,
"sale_date": sale_date,
"prodtypeid": prodtypeid})
if dai_recs: if dai_recs:
distribution_agreement_item_id = dai_recs[0].id distribution_agreement_item_id = dai_recs[0].id
@ -157,7 +127,6 @@ async def main(request, params_kw):
else: else:
dist_amount = total_amount * dist_discount dist_amount = total_amount * dist_discount
else: else:
# Fallback: find active distribution agreement with default discount
sql_da = """SELECT id, default_discount FROM distribution_agreements sql_da = """SELECT id, default_discount FROM distribution_agreements
WHERE resellerid = ${resellerid}$ WHERE resellerid = ${resellerid}$
AND sub_distributor_id = ${sub_distributor_id}$ AND sub_distributor_id = ${sub_distributor_id}$
@ -201,7 +170,7 @@ async def main(request, params_kw):
"source_id": source_id, "source_id": source_id,
"remark": remark, "remark": remark,
"created_by": user_id, "created_by": user_id,
"created_at": datetime.now().strftime("%Y-%m-%d %H:%M:%S") "created_at": timestampstr()
} }
await sor.C("supplychain_accounting", record) await sor.C("supplychain_accounting", record)

View File

@ -1,16 +1,4 @@
import json
async def main(request, params_kw):
"""
查询某二级分销商在某产品上的分销协议折扣。
参数: sub_distributor_id, productid, prodtypeid(可选)
折扣查找优先级:
1. 精确匹配 productid
2. 匹配 prodtypeid
3. 使用协议默认折扣
"""
user_orgid = await get_userorgid() user_orgid = await get_userorgid()
dbname = get_module_dbname('supplychain') dbname = get_module_dbname('supplychain')
@ -21,11 +9,8 @@ async def main(request, params_kw):
if not sub_distributor_id or not productid: if not sub_distributor_id or not productid:
return json.dumps({"status": "error", "message": "缺少sub_distributor_id或productid参数"}) return json.dumps({"status": "error", "message": "缺少sub_distributor_id或productid参数"})
config = getConfig(".") db = DBPools()
DBPools(config.databases)
async with db.sqlorContext(dbname) as sor: async with db.sqlorContext(dbname) as sor:
# Try exact product match
sql = """SELECT dai.id, dai.agreement_id, dai.discount, dai.settlement_price, sql = """SELECT dai.id, dai.agreement_id, dai.discount, dai.settlement_price,
da.agreement_code, da.agreement_name da.agreement_code, da.agreement_name
FROM distribution_agreement_items dai FROM distribution_agreement_items dai

View File

@ -1,16 +1,4 @@
import json
async def main(request, params_kw):
"""
查询某产品在有效供销合同下的折扣信息。
参数: productid, prodtypeid(可选)
折扣查找优先级:
1. 精确匹配 productid
2. 匹配 prodtypeid
3. 使用合同默认折扣
"""
user_orgid = await get_userorgid() user_orgid = await get_userorgid()
dbname = get_module_dbname('supplychain') dbname = get_module_dbname('supplychain')
@ -20,11 +8,8 @@ async def main(request, params_kw):
if not productid: if not productid:
return json.dumps({"status": "error", "message": "缺少productid参数"}) return json.dumps({"status": "error", "message": "缺少productid参数"})
config = getConfig(".") db = DBPools()
DBPools(config.databases)
async with db.sqlorContext(dbname) as sor: async with db.sqlorContext(dbname) as sor:
# Try exact product match
sql = """SELECT sci.id, sci.contract_id, sci.discount, sci.settlement_price, sql = """SELECT sci.id, sci.contract_id, sci.discount, sci.settlement_price,
sc.contract_code, sc.contract_name, sc.supplier_id, sc.contract_code, sc.contract_name, sc.supplier_id,
s.supplier_name s.supplier_name
@ -55,7 +40,6 @@ async def main(request, params_kw):
recs = await sor.sqlExe(sql, {"resellerid": user_orgid, "prodtypeid": prodtypeid}) recs = await sor.sqlExe(sql, {"resellerid": user_orgid, "prodtypeid": prodtypeid})
if not recs: if not recs:
# Fallback to contract default
sql = """SELECT id as contract_id, contract_code, contract_name, sql = """SELECT id as contract_id, contract_code, contract_name,
supplier_id, default_discount as discount, NULL as settlement_price supplier_id, default_discount as discount, NULL as settlement_price
FROM supply_contracts FROM supply_contracts

View File

@ -1,9 +1,19 @@
import json
from ahserver.serverenv import ServerEnv ns = params_kw.copy()
env = ServerEnv()
delete_func = getattr(env, 'delete_sales_ledger', None) data = ns.copy()
if delete_func is None: data.pop('page', None)
print(json.dumps({"status": "error", "message": "delete_sales_ledger function not found"})) data.pop('rows', None)
else: data.pop('data_filter', None)
result = await delete_func(request, params_kw)
print(result) if not data.get('id'):
return json.dumps({'widgettype':'Error','options':{'title':'Delete Error','message':'缺少id'}}, ensure_ascii=False)
try:
db = DBPools()
dbname = get_module_dbname('supplychain')
async with db.sqlorContext(dbname) as sor:
await sor.D('sales_ledger', data)
return json.dumps({'widgettype':'Message','options':{'title':'Delete Success','message':'ok'}}, ensure_ascii=False)
except Exception as e:
return json.dumps({'widgettype':'Error','options':{'title':'Delete Error','message':str(e)}}, ensure_ascii=False)

View File

@ -1,9 +1,19 @@
import json
from ahserver.serverenv import ServerEnv ns = params_kw.copy()
env = ServerEnv()
update_func = getattr(env, 'update_sales_ledger', None) data = ns.copy()
if update_func is None: data.pop('page', None)
print(json.dumps({"status": "error", "message": "update_sales_ledger function not found"})) data.pop('rows', None)
else: data.pop('data_filter', None)
result = await update_func(request, params_kw)
print(result) if not data.get('id'):
return json.dumps({'widgettype':'Error','options':{'title':'Update Error','message':'缺少id'}}, ensure_ascii=False)
try:
db = DBPools()
dbname = get_module_dbname('supplychain')
async with db.sqlorContext(dbname) as sor:
await sor.U('sales_ledger', data)
return json.dumps({'widgettype':'Message','options':{'title':'Update Success','message':'ok'}}, ensure_ascii=False)
except Exception as e:
return json.dumps({'widgettype':'Error','options':{'title':'Update Error','message':str(e)}}, ensure_ascii=False)

View File

@ -1,9 +1,19 @@
import json
from ahserver.serverenv import ServerEnv ns = params_kw.copy()
env = ServerEnv()
delete_func = getattr(env, 'delete_sub_resellers', None) data = ns.copy()
if delete_func is None: data.pop('page', None)
print(json.dumps({"status": "error", "message": "delete_sub_resellers function not found"})) data.pop('rows', None)
else: data.pop('data_filter', None)
result = await delete_func(request, params_kw)
print(result) if not data.get('id'):
return json.dumps({'widgettype':'Error','options':{'title':'Delete Error','message':'缺少id'}}, ensure_ascii=False)
try:
db = DBPools()
dbname = get_module_dbname('supplychain')
async with db.sqlorContext(dbname) as sor:
await sor.D('sub_resellers', data)
return json.dumps({'widgettype':'Message','options':{'title':'Delete Success','message':'ok'}}, ensure_ascii=False)
except Exception as e:
return json.dumps({'widgettype':'Error','options':{'title':'Delete Error','message':str(e)}}, ensure_ascii=False)

View File

@ -1,9 +1,19 @@
import json
from ahserver.serverenv import ServerEnv ns = params_kw.copy()
env = ServerEnv()
update_func = getattr(env, 'update_sub_resellers', None) data = ns.copy()
if update_func is None: data.pop('page', None)
print(json.dumps({"status": "error", "message": "update_sub_resellers function not found"})) data.pop('rows', None)
else: data.pop('data_filter', None)
result = await update_func(request, params_kw)
print(result) if not data.get('id'):
return json.dumps({'widgettype':'Error','options':{'title':'Update Error','message':'缺少id'}}, ensure_ascii=False)
try:
db = DBPools()
dbname = get_module_dbname('supplychain')
async with db.sqlorContext(dbname) as sor:
await sor.U('sub_resellers', data)
return json.dumps({'widgettype':'Message','options':{'title':'Update Success','message':'ok'}}, ensure_ascii=False)
except Exception as e:
return json.dumps({'widgettype':'Error','options':{'title':'Update Error','message':str(e)}}, ensure_ascii=False)

View File

@ -1,9 +1,18 @@
import json ns = params_kw.copy()
from ahserver.serverenv import ServerEnv
env = ServerEnv() data = ns.copy()
delete_func = getattr(env, 'delete_suppliers', None) data.pop('page', None)
if delete_func is None: data.pop('rows', None)
print(json.dumps({"status": "error", "message": "delete_suppliers function not found"})) data.pop('data_filter', None)
else:
result = await delete_func(request, params_kw) if not data.get('id'):
print(result) return json.dumps({'widgettype':'Error','options':{'title':'Delete Error','message':'缺少id'}}, ensure_ascii=False)
try:
db = DBPools()
dbname = get_module_dbname('supplychain')
async with db.sqlorContext(dbname) as sor:
await sor.D('suppliers', data)
return json.dumps({'widgettype':'Message','options':{'title':'Delete Success','message':'ok'}}, ensure_ascii=False)
except Exception as e:
return json.dumps({'widgettype':'Error','options':{'title':'Delete Error','message':str(e)}}, ensure_ascii=False)

View File

@ -1,9 +1,19 @@
import json
from ahserver.serverenv import ServerEnv ns = params_kw.copy()
env = ServerEnv()
update_func = getattr(env, 'update_suppliers', None) data = ns.copy()
if update_func is None: data.pop('page', None)
print(json.dumps({"status": "error", "message": "update_suppliers function not found"})) data.pop('rows', None)
else: data.pop('data_filter', None)
result = await update_func(request, params_kw)
print(result) if not data.get('id'):
return json.dumps({'widgettype':'Error','options':{'title':'Update Error','message':'缺少id'}}, ensure_ascii=False)
try:
db = DBPools()
dbname = get_module_dbname('supplychain')
async with db.sqlorContext(dbname) as sor:
await sor.U('suppliers', data)
return json.dumps({'widgettype':'Message','options':{'title':'Update Success','message':'ok'}}, ensure_ascii=False)
except Exception as e:
return json.dumps({'widgettype':'Error','options':{'title':'Update Error','message':str(e)}}, ensure_ascii=False)

View File

@ -1,7 +1,4 @@
import json
async def main(request, params_kw):
"""Delete a supplychain_accounting record."""
dbname = get_module_dbname('supplychain') dbname = get_module_dbname('supplychain')
data = params_kw.get("data", "{}") data = params_kw.get("data", "{}")
@ -12,8 +9,7 @@ async def main(request, params_kw):
if not record_id: if not record_id:
return json.dumps({"status": "error", "message": "Missing record id"}) return json.dumps({"status": "error", "message": "Missing record id"})
config = getConfig(".") db = DBPools()
DBPools(config.databases)
async with db.sqlorContext(dbname) as sor: async with db.sqlorContext(dbname) as sor:
await sor.D("supplychain_accounting", {"id": record_id}) await sor.D("supplychain_accounting", {"id": record_id})
return json.dumps({"status": "ok", "message": "Deleted successfully"}) return json.dumps({"status": "ok", "message": "Deleted successfully"})

View File

@ -1,8 +1,4 @@
import json
from datetime import datetime
async def main(request, params_kw):
"""Update a supplychain_accounting record."""
user_id = await get_user() user_id = await get_user()
dbname = get_module_dbname('supplychain') dbname = get_module_dbname('supplychain')
@ -14,14 +10,12 @@ async def main(request, params_kw):
if not record_id: if not record_id:
return json.dumps({"status": "error", "message": "Missing record id"}) return json.dumps({"status": "error", "message": "Missing record id"})
data["updated_at"] = datetime.now().strftime("%Y-%m-%d %H:%M:%S") data["updated_at"] = timestampstr()
# Remove fields that should not be updated
for key in ["id", "resellerid", "created_by", "created_at"]: for key in ["id", "resellerid", "created_by", "created_at"]:
data.pop(key, None) data.pop(key, None)
config = getConfig(".") db = DBPools()
DBPools(config.databases)
async with db.sqlorContext(dbname) as sor: async with db.sqlorContext(dbname) as sor:
await sor.U("supplychain_accounting", data) await sor.U("supplychain_accounting", data)
return json.dumps({"status": "ok", "data": data}) return json.dumps({"status": "ok", "data": data})