feat: add orgid to sub_resellers + get_distribution_chain

- create_sub_reseller auto-creates organization record with orgid
- get_distribution_chain walks from product_owner down to seller via sub_resellers
This commit is contained in:
yumoqing 2026-07-07 12:20:39 +08:00
parent 7c0acb5245
commit 5705e674b5
2 changed files with 67 additions and 1 deletions

View File

@ -312,7 +312,7 @@ async def delete_supply_contract_item(request, params_kw):
# ============================================================
async def create_sub_reseller(request, params_kw):
"""Create a new sub-reseller."""
"""Create a new sub-reseller with orgid for discount/accounting."""
env = ServerEnv()
user_id = await env.get_user()
resellerid = await env.get_userorgid()
@ -321,9 +321,25 @@ async def create_sub_reseller(request, params_kw):
async with db.sqlorContext(dbname) as sor:
sub_reseller_code = data.get("sub_reseller_code") or _generate_sub_reseller_code(resellerid)
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
# Create org entry for this sub_reseller
new_orgid = getID()
org_rec = {
"id": new_orgid,
"orgname": data.get("sub_reseller_name"),
"orgtype": "sub_reseller",
"status": "1",
"created_by": user_id,
"created_at": now,
"updated_at": now
}
async with db.sqlorContext("sage") as sor_sage:
await sor_sage.C("organization", org_rec)
rec = {
"id": getID(),
"resellerid": resellerid,
"orgid": new_orgid,
"sub_reseller_code": sub_reseller_code,
"sub_reseller_name": data.get("sub_reseller_name"),
"contact_person": data.get("contact_person"),
@ -553,6 +569,54 @@ async def delete_sales_ledger(request, params_kw):
return json.dumps({"status": "ok", "message": "删除成功"})
# ============================================================
# Distribution Chain Query
# ============================================================
async def get_distribution_chain(product_ownerid, seller_orgid):
"""Get the distribution chain from product owner to seller.
Chain is: product_owner ... sub_resellers recursively seller
Returns list of orgids from product_owner down to seller (inclusive).
If seller_orgid == product_ownerid, returns [product_ownerid].
"""
chain = [product_ownerid]
if seller_orgid == product_ownerid:
return chain
env = ServerEnv()
dbname = env.get_module_dbname('supplychain')
db = DBPools()
config = getConfig()
db.databases = config.databases
# Walk down the sub_reseller chain from product_owner to seller
async with db.sqlorContext(dbname) as sor:
current = product_ownerid
visited = {product_ownerid}
while current != seller_orgid:
sql = """SELECT orgid FROM sub_resellers
WHERE resellerid = ${resellerid}$ AND status = '1'
LIMIT 100"""
recs = await sor.sqlExe(sql, {'resellerid': current})
found = False
for r in (recs or []):
orgid = r.get('orgid') if hasattr(r, 'get') else getattr(r, 'orgid', None)
if orgid and orgid == seller_orgid:
chain.append(orgid)
return chain
if orgid and orgid not in visited:
visited.add(orgid)
chain.append(orgid)
current = orgid
found = True
break
if not found:
# Can't reach seller from current, chain ends here
break
return chain
# ============================================================
# Discount Calculation API (called by other modules during sales)
# ============================================================
@ -945,6 +1009,8 @@ def load_supplychain():
env.delete_product_supplier_mapping = delete_product_supplier_mapping
# Calculation API
env.calculate_sale_amounts = calculate_sale_amounts
# Distribution chain query
env.get_distribution_chain = get_distribution_chain
# Attachment folder helper
env.ensure_contract_folder = ensure_contract_folder
env.ContractAttachMgr = ContractAttachMgr