Spaces:
Running
Trade Relationships Module - Implementation Guide
π― Overview
The Trade Relationship module defines who can transact with whom in the supply chain. It serves as the single source of truth for:
- β Supplier eligibility for buying
- π° Commercial rules (pricing level, payment terms, credit)
- π Regional & category constraints
- π Transaction authorization (PO, Invoice, Returns, CN/DN)
Critical Rule: No Purchase Order, Invoice, Return, or Credit/Debit Note can be created unless an active trade relationship exists.
π Module Structure
app/trade_relationships/
βββ __init__.py # Module initialization
βββ constants.py # Enums, validation patterns, business rules
βββ controllers/
β βββ __init__.py
β βββ router.py # FastAPI endpoints
βββ services/
β βββ __init__.py
β βββ service.py # Business logic & CRUD operations
βββ models/
β βββ __init__.py
β βββ model.py # SQLAlchemy PostgreSQL model
βββ schemas/
βββ __init__.py
βββ schema.py # Pydantic request/response schemas
ποΈ Database Schema
Table: trans.scm_trade_relationship
The relationship is directional and explicit:
Buyer Merchant β Supplier Merchant
Key Fields:
- Parties:
from_merchant_id(buyer) βto_merchant_id(supplier) - Status:
draft|active|suspended|expired|terminated - Commercial:
pricing_level,payment_terms,credit_allowed,credit_limit - Constraints:
allowed_regions[],allowed_categories[] - Validity:
valid_from,valid_to(NULL = indefinite)
Business Constraints:
- β Unique Relationship: One relationship per merchant pair
- β Different Merchants: Buyer β Supplier
- β Credit Logic: If credit allowed, limit must be > 0
- β
Date Logic:
valid_toβ₯valid_from
ποΈ Setup Instructions
1. Run Database Migration
# From the project root directory
python migrate_trade_relationships.py
This will:
- β
Create the
scm_trade_relationshiptable intransschema - π Add 6 performance indexes
- β Apply 4 business rule constraints
- π Add column documentation
- π§ͺ Insert sample test data
2. Verify Installation
After running migration, restart your application and check:
# Check if endpoints are available
curl http://localhost:9101/docs
# Look for "trade-relationships" section in Swagger UI
3. Test Basic Functionality
# Health check
curl http://localhost:9101/trade-relationships/health
# List relationships (requires auth)
curl -H "Authorization: Bearer YOUR_TOKEN" \
-X POST http://localhost:9101/trade-relationships/list \
-H "Content-Type: application/json" \
-d '{"skip": 0, "limit": 10}'
π§ API Endpoints
Core CRUD Operations
| Method | Endpoint | Description |
|---|---|---|
POST |
/trade-relationships |
Create new relationship |
GET |
/trade-relationships/{id} |
Get relationship details |
PUT |
/trade-relationships/{id} |
Update relationship |
DELETE |
/trade-relationships/{id} |
Delete relationship |
Status Management
| Method | Endpoint | Description |
|---|---|---|
PUT |
/trade-relationships/{id}/status |
Change status (draftβactiveβsuspended, etc.) |
Supplier Discovery (Key Feature)
| Method | Endpoint | Description |
|---|---|---|
POST |
/trade-relationships/suppliers/discover |
Find suppliers for buyer (POST body) |
GET |
/trade-relationships/suppliers?buyer_merchant_id=X |
Find suppliers (query params) |
Relationship Validation
| Method | Endpoint | Description |
|---|---|---|
POST |
/trade-relationships/validate |
Validate buyerβsupplier relationship |
POST |
/trade-relationships/list |
List with filters and pagination |
π Usage Examples
1. Create a Trade Relationship
POST /trade-relationships
{
"from_merchant_id": "mch_ncnf_mumbai_001",
"to_merchant_id": "mch_company_hq_001",
"pricing_level": "NCNF",
"credit": {
"allowed": true,
"limit": 10000000,
"payment_terms": "NET_30"
},
"allowed_regions": ["IN-MH-MUM", "IN-GJ-AHM"],
"allowed_categories": ["Haircare", "Skincare"],
"remarks": "Primary procurement relationship"
}
2. Discover Suppliers for Purchase Order
POST /trade-relationships/suppliers/discover
{
"buyer_merchant_id": "mch_ncnf_mumbai_001",
"region": "IN-MH-MUM",
"category": "Haircare",
"active_only": true
}
Response:
{
"buyer_merchant_id": "mch_ncnf_mumbai_001",
"suppliers": [
{
"merchant_id": "mch_company_hq_001",
"relationship_id": "550e8400-e29b-41d4-a716-446655440000",
"pricing_level": "NCNF",
"payment_terms": "NET_30",
"credit_allowed": true,
"credit_limit": 10000000
}
],
"total_count": 1
}
3. Validate Relationship Before Transaction
POST /trade-relationships/validate
{
"buyer_id": "mch_ncnf_mumbai_001",
"supplier_id": "mch_company_hq_001",
"region": "IN-MH-MUM",
"category": "Haircare"
}
4. Change Relationship Status
PUT /trade-relationships/{id}/status
{
"status": "suspended",
"remarks": "Temporary suspension for compliance review"
}
π Authorization Logic
The Authoritative Rule
Every transaction (PO, Invoice, Return, CN/DN) must validate:
-- This query MUST return a relationship for transaction to proceed
SELECT * FROM trans.scm_trade_relationship
WHERE from_merchant_id = :buyer_id
AND to_merchant_id = :supplier_id
AND status = 'active'
AND valid_from <= CURRENT_DATE
AND (valid_to IS NULL OR valid_to >= CURRENT_DATE)
AND (allowed_regions IS NULL OR allowed_regions = ARRAY[] OR :region = ANY(allowed_regions))
AND (allowed_categories IS NULL OR allowed_categories = ARRAY[] OR :category = ANY(allowed_categories));
Integration with Other Modules
Purchase Orders: Must validate relationship before PO creation
# In PO creation service
relationship = await TradeRelationshipService.validate_relationship(
buyer_id=po_data.buyer_id,
supplier_id=po_data.supplier_id,
region=po_data.delivery_region,
category=item.category
)
if not relationship:
raise HTTPException(400, "No valid trade relationship")
Credit Validation: Check credit limits during invoice processing
if relationship.credit_allowed:
if outstanding_amount + invoice_total > relationship.credit_limit:
raise HTTPException(400, "Credit limit exceeded")
else:
# Must be prepaid
if payment_terms != "PREPAID":
raise HTTPException(400, "Prepaid payment required")
π Business Rules
Status Lifecycle
Draft β Active β Suspended β Expired β Terminated
β β β β
Active Terminated Active Terminated
β β β
Terminated Terminated
Commercial Rules
- Credit Allowed = True: Credit limit required, allows NET_X payment terms
- Credit Allowed = False: Only PREPAID allowed, no credit limit
- Empty Regions/Categories: Unrestricted (can trade anywhere/anything)
- Populated Regions/Categories: Restricted to specified values
Operational Constraints
- Regions: Format
IN-MH-MUM(Country-State-City) - Categories: Format
Haircare,Skincare(PascalCase) - Validity:
valid_toNULL means indefinite
π Performance Features
Optimized Indexes
- Buyer Lookup: Fast supplier discovery
- Supplier Lookup: Sales-side queries
- Status Filtering: Active relationship queries
- Date Filtering: Validity checks
- Array Lookups: Region/category constraints (GIN indexes)
Caching Strategy
# Future enhancement: Redis caching for frequently accessed relationships
@cached(ttl=300) # 5 minutes
async def get_cached_relationship(buyer_id: str, supplier_id: str):
# Implementation for high-frequency validation
π§ͺ Testing
Sample Data Included
The migration creates 3 test relationships:
- NCNF Mumbai β Company HQ (NET_30, βΉ1Cr credit)
- CNF Pune β NCNF Mumbai (NET_15, βΉ50L credit)
- Distributor Nashik β CNF Pune (PREPAID, no credit)
Test Scenarios
# Test supplier discovery
curl -X POST http://localhost:9101/trade-relationships/suppliers/discover \
-H "Content-Type: application/json" \
-d '{"buyer_merchant_id": "mch_ncnf_mumbai_001"}'
# Test relationship validation
curl -X POST http://localhost:9101/trade-relationships/validate \
-H "Content-Type: application/json" \
-d '{"buyer_id": "mch_ncnf_mumbai_001", "supplier_id": "mch_company_hq_001"}'
π¨ Important Notes
Hard Guards (Non-Negotiable)
- β No PO without relationship: All PO creation must validate first
- β No Invoice without relationship: All invoicing must check
- β No Returns without relationship: Return processing must verify
- β No CN/DN without relationship: Credit/Debit notes must validate
Status Check Pattern
# Use this pattern in ALL transaction modules
if not relationship or not relationship.is_valid:
raise HTTPException(
status_code=400,
detail="No valid trade relationship exists"
)
Regional/Category Enforcement
# Validate constraints when specified
if relationship.allowed_regions and region not in relationship.allowed_regions:
raise HTTPException(400, f"Region {region} not allowed")
if relationship.allowed_categories and category not in relationship.allowed_categories:
raise HTTPException(400, f"Category {category} not allowed")
π Future Enhancements
Planned Features
- Automatic Expiry: Background job to expire relationships
- Credit Monitoring: Real-time outstanding balance tracking
- Approval Workflows: Multi-step relationship approval
- Bulk Operations: CSV import/export for relationship management
- Integration Hooks: Webhooks for relationship status changes
- Analytics Dashboard: Relationship performance metrics
Integration Roadmap
- Phase 1: PO module integration (validate before PO creation)
- Phase 2: Invoice module integration (credit limit enforcement)
- Phase 3: Returns module integration (return authorization)
- Phase 4: CN/DN module integration (credit/debit authorization)
- Phase 5: Real-time credit monitoring and alerts
π Troubleshooting
Common Issues
Issue: "Trade relationship not found" error
# Check if relationship exists and is active
SELECT * FROM trans.scm_trade_relationship
WHERE from_merchant_id = 'buyer_id'
AND to_merchant_id = 'supplier_id';
Issue: "Credit limit exceeded" error
# Check current credit configuration
SELECT credit_allowed, credit_limit
FROM trans.scm_trade_relationship
WHERE relationship_id = 'relationship_id';
Issue: Foreign key errors during startup
# Ensure model is imported in sql.py
# Check that Base.metadata.create_all() includes the model
Support Contacts
- Database Issues: Check migration logs and database connectivity
- API Issues: Verify authentication and request format
- Business Logic: Review relationship status and validity dates
π Summary
The Trade Relationships module is now fully implemented and ready for integration:
β
Complete CRUD API with validation and error handling
β
PostgreSQL model with constraints and performance indexes
β
Supplier discovery for PO creation workflows
β
Relationship validation for transaction authorization
β
Status management with proper lifecycle controls
β
Migration script with sample data for testing
β
Comprehensive documentation and usage examples
Next Step: Integrate relationship validation into PO, Invoice, Returns, and CN/DN modules to enforce the business rules.
The module follows all existing patterns and is ready for production use! π