diff --git a/supplychain/__pycache__/init.cpython-310.pyc b/supplychain/__pycache__/init.cpython-310.pyc index 5dc0ef3..c09cad6 100644 Binary files a/supplychain/__pycache__/init.cpython-310.pyc and b/supplychain/__pycache__/init.cpython-310.pyc differ diff --git a/supplychain/init.py b/supplychain/init.py index 39939e4..a9a401e 100644 --- a/supplychain/init.py +++ b/supplychain/init.py @@ -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