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

Discount Calculation Logic

calculate_sale_amounts() API is called during product sales:

  1. Finds active supply contract for the supplier (filtered by date and status)
  2. Looks up product-specific discount in contract items (priority: exact product > product type > default)
  3. Finds active distribution agreement for the sub-reseller
  4. Looks up product-specific discount in agreement items (same priority)
  5. 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 items
  • reseller.sale — manage sub-resellers, distribution agreements, and agreement items
  • reseller.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
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}
Description
No description provided
Readme 431 KiB
Languages
Python 97.1%
Shell 2.9%