PopupWindow renders dspy response directly. DataViewer doesn't work inside popup context. HTML meta refresh redirects to CRUD page.
Supplychain Module
Supplier and Reseller Management module for Sage platform.
Overview
Manages the complete supply chain workflow for reseller/distributor organizations:
- Operators manage suppliers and supply contracts with product-level discount terms
- Sales manage sub-resellers (tier-2 distributors) and distribution agreements with product-level discount terms
- Sales ledger records transactions and calculates supply/distribution amounts for accounting
Architecture
Tables
| Table | Description |
|---|---|
suppliers |
Supplier master data (contact, bank, tax info) |
supply_contracts |
Supply contracts between reseller and supplier |
supply_contract_items |
Product-level discount details per supply contract |
sub_resellers |
Sub-reseller (tier-2 distributor) master data |
distribution_agreements |
Distribution agreements between reseller and sub-reseller |
distribution_agreement_items |
Product-level discount details per distribution agreement |
sales_ledger |
Sales transaction records with calculated amounts |
platform_supply_relations |
Platform-level org-to-org supply relationships (P0) |
platform_supply_products |
Product details within platform supply relations (P0) |
product_supplier_mapping |
Unified product-to-supplier mapping across internal/external (P0) |
P0 Platform Supply Chain (2026-06)
Enables supply chain relationships between organizations on the Sage platform:
- platform_supply_relations: Links two organizations (supplier ↔ buyer) with cooperation type (distribution/agency/direct-supply), settlement mode (discount/commission/fixed), and contract period
- platform_supply_products: Product-level pricing within a supply relation — supply price, retail price, discount, commission rate, min order qty
- product_supplier_mapping: Unified view mapping any product to its supplier(s), whether internal (platform org) or external (suppliers table), with preferred supplier flag
Key business APIs:
query_platform_suppliers.dspy— List platform orgs available as suppliers (excludes current user's org)query_platform_products.dspy— List active products owned by a supplier orgimport_supplier_product.dspy— Import a supplier's product into buyer's mapping (creates product_supplier_mapping record)
Discount Calculation Logic
calculate_sale_amounts() API is called during product sales:
- Finds active supply contract for the supplier (filtered by date and status)
- Looks up product-specific discount in contract items (priority: exact product > product type > default)
- Finds active distribution agreement for the sub-reseller
- Looks up product-specific discount in agreement items (same priority)
- Calculates: supply_amount = total * supply_discount, distribution_amount = total * distribution_discount, profit = distribution - supply
Role-Based Access
reseller.operator— manage suppliers, supply contracts, and contract itemsreseller.sale— manage sub-resellers, distribution agreements, and agreement itemsreseller.accountant— view and manage sales ledger entries
Directory Structure
supplychain/
├── supplychain/
│ ├── __init__.py # Package init
│ └── init.py # Module init + ServerEnv registration
├── wwwroot/
│ ├── index.ui # Module entry point
│ ├── menu.ui # Navigation menu
│ └── api/ # CRUD API endpoints (.dspy files)
├── models/ # Table definitions (JSON)
├── json/ # CRUD definitions (JSON)
├── init/ # Initialization data
├── pyproject.toml
├── build.sh
└── README.md
Sage Integration
1. Install module
cd ~/repos/sage/pkgs
git clone https://git.opencomputing.cn/yumoqing/supplychain
cd supplychain
../../py3/bin/pip install .
2. Generate DDL and apply to database
cd ~/repos/sage/pkgs/supplychain/models
../../py3/bin/json2ddl mysql . > mysql.ddl.sql
mysql -h <db_host> -u <db_user> -p sage < mysql.ddl.sql
3. Generate CRUD UI files
cd ~/repos/sage/pkgs/supplychain/json
../../py3/bin/xls2ui -m ../models -o ../wwwroot supplychain *.json
4. Link wwwroot
cd ~/repos/sage/wwwroot
ln -sf ../pkgs/supplychain/wwwroot supplychain
5. Register module in Sage
Add to ~/repos/sage/app/sage.py:
from supplychain.init import load_supplychain
# In init():
load_supplychain()
6. Register RBAC permissions
Add to ~/repos/sage/load_path.py:
/supplychain logined
/supplychain/index.ui logined
/supplychain/menu.ui any
/supplychain/suppliers_list logined
/supplychain/suppliers_list/index.ui logined
/supplychain/supply_contracts_list logined
/supplychain/supply_contracts_list/index.ui logined
/supplychain/supply_contract_items_list logined
/supplychain/supply_contract_items_list/index.ui logined
/supplychain/sub_resellers_list logined
/supplychain/sub_resellers_list/index.ui logined
/supplychain/distribution_agreements_list logined
/supplychain/distribution_agreements_list/index.ui logined
/supplychain/distribution_agreement_items_list logined
/supplychain/distribution_agreement_items_list/index.ui logined
/supplychain/sales_ledger_list logined
/supplychain/sales_ledger_list/index.ui logined
/supplychain/api/suppliers_create.dspy logined
/supplychain/api/suppliers_update.dspy logined
/supplychain/api/suppliers_delete.dspy logined
/supplychain/api/supply_contracts_create.dspy logined
/supplychain/api/supply_contracts_update.dspy logined
/supplychain/api/supply_contracts_delete.dspy logined
/supplychain/api/supply_contract_items_create.dspy logined
/supplychain/api/supply_contract_items_update.dspy logined
/supplychain/api/supply_contract_items_delete.dspy logined
/supplychain/api/sub_resellers_create.dspy logined
/supplychain/api/sub_resellers_update.dspy logined
/supplychain/api/sub_resellers_delete.dspy logined
/supplychain/api/distribution_agreements_create.dspy logined
/supplychain/api/distribution_agreements_update.dspy logined
/supplychain/api/distribution_agreements_delete.dspy logined
/supplychain/api/distribution_agreement_items_create.dspy logined
/supplychain/api/distribution_agreement_items_update.dspy logined
/supplychain/api/distribution_agreement_items_delete.dspy logined
/supplychain/api/sales_ledger_create.dspy logined
/supplychain/api/sales_ledger_update.dspy logined
/supplychain/api/sales_ledger_delete.dspy logined
Then run:
cd ~/repos/sage && ./py3/bin/python load_path.py
7. Restart Sage
cd ~/repos/sage && ./stop.sh && ./start.sh
API for External Modules
Other modules can call calculate_sale_amounts() to compute supply/distribution amounts during sales:
env = ServerEnv()
result = await env.calculate_sale_amounts(request, {
"resellerid": org_id,
"sub_reseller_id": sub_reseller_id, # optional
"supplier_id": supplier_id, # optional
"prodtypeid": product_type_id,
"productid": product_id,
"quantity": qty,
"unit_price": price,
})
# Returns: {contract_id, agreement_id, total_amount, supply_discount, supply_amount, distribution_discount, distribution_amount, profit_amount}
Deployment Checklist
- Execute DDL:
models/mysql.ddl.sql— creates 3 new tables (platform_supply_relations, platform_supply_products, product_supplier_mapping) - Init appcodes: Run
init/data.jsoninserts for 6 appcode groups - Build CRUD UI:
bash build.sh - Register RBAC:
~/repos/sage/py3/bin/python scripts/load_path.py(or central load_path.py) - Restart Sage
Description
Languages
Python
97.4%
Shell
2.6%