File size: 5,259 Bytes
cd357c6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# Foreign Key Fixes Summary

## Issue Resolved

**Error**: `Foreign key associated with column 'scm_trade_shipment.order_id' could not find table 'scm_po' with which to generate a foreign key to target column 'po_id'`

**Root Cause**: 
1. Multiple `Base` instances across different model files
2. Foreign key references not including schema prefixes
3. Tables in different schemas causing reference issues

## Solutions Applied

### 1. Created Shared Database Base

**File**: `app/core/database.py`
```python
from sqlalchemy.orm import declarative_base

# Shared Base for all SQLAlchemy models
Base = declarative_base()
```

### 2. Updated All Models to Use Shared Base

#### Before:
```python
# Each model file had its own Base
from sqlalchemy.orm import declarative_base
Base = declarative_base()
```

#### After:
```python
# All models now use shared Base
from app.core.database import Base
```

**Files Updated**:
- `app/catalogues/models/model.py`
- `app/inventory/stock/models/model.py`
- `app/purchases/orders/models/model.py`
- `app/purchases/receipts/models/model.py`
- `app/trade_sales/models/model.py`

### 3. Fixed Foreign Key Schema References

#### Before:
```python
ForeignKey('scm_po.po_id')
ForeignKey('scm_grn.grn_id')
```

#### After:
```python
ForeignKey('trans.scm_po.po_id')
ForeignKey('trans.scm_grn.grn_id')
```

**Foreign Keys Fixed**:

**`app/trade_sales/models/model.py`**:
- `order_id`: `'scm_po.po_id'` β†’ `'trans.scm_po.po_id'`
- `shipment_id`: `'scm_trade_shipment.shipment_id'` β†’ `'trans.scm_trade_shipment.shipment_id'`
- `po_item_id`: `'scm_po_item.po_item_id'` β†’ `'trans.scm_po_item.po_item_id'`

**`app/inventory/stock/models/model.py`**:
- `ledger_id`: `'scm_stock_ledger.ledger_id'` β†’ `'trans.scm_stock_ledger.ledger_id'`
- `adjustment_id`: `'scm_stock_adjustment.adjustment_id'` β†’ `'trans.scm_stock_adjustment.adjustment_id'`

**`app/purchases/orders/models/model.py`**:
- `po_id`: `'scm_po.po_id'` β†’ `'trans.scm_po.po_id'`

**`app/purchases/receipts/models/model.py`**:
- `po_id`: `'scm_po.po_id'` β†’ `'trans.scm_po.po_id'`
- `grn_id`: `'scm_grn.grn_id'` β†’ `'trans.scm_grn.grn_id'`
- `po_item_id`: `'scm_po_item.po_item_id'` β†’ `'trans.scm_po_item.po_item_id'`
- `grn_item_id`: `'scm_grn_item.grn_item_id'` β†’ `'trans.scm_grn_item.grn_item_id'`

### 4. Updated Table Creation Logic

**File**: `app/sql.py`

#### Before:
```python
from app.purchases.orders.models.model import Base
```

#### After:
```python
from app.core.database import Base

# Import all models to ensure they're registered with Base
from app.catalogues.models.model import CatalogueRef
from app.inventory.stock.models.model import ScmStock, ScmStockLedger, ScmStockAdjustment, ScmStockTake
from app.purchases.orders.models.model import ScmPo, ScmPoItem, ScmPoStatusLog
from app.purchases.receipts.models.model import ScmGrn, ScmGrnItem, ScmGrnIssue
from app.trade_sales.models.model import ScmTradeShipment, ScmTradeShipmentItem
```

## Database Configuration

### Current Setup:
- **Database**: `cuatrolabs`
- **Schema**: `trans` (for all SCM tables)
- **Shared Base**: All models use `app.core.database.Base`

### Tables in `trans` Schema:
1. `catalogue_ref` - Catalogue reference with pricing_levels
2. `scm_stock` - Stock snapshots
3. `scm_stock_ledger` - Stock movement ledger
4. `scm_stock_adjustment` - Stock adjustments
5. `scm_stock_take` - Physical stock audits
6. `scm_po` - Purchase orders
7. `scm_po_item` - Purchase order items
8. `scm_po_status_log` - PO status changes
9. `scm_grn` - Goods receipt notes
10. `scm_grn_item` - GRN items
11. `scm_grn_issue` - GRN issues/discrepancies
12. `scm_trade_shipment` - Trade shipments
13. `scm_trade_shipment_item` - Trade shipment items

## Verification Results

### βœ… **All Tests Passed**:
1. **Model Import**: All models import successfully with shared Base
2. **Foreign Keys**: All foreign key relationships resolve correctly
3. **Table Creation**: `create_tables()` executes without errors
4. **Application Startup**: FastAPI app starts without foreign key errors
5. **Schema Consistency**: All tables use `trans` schema consistently

### βœ… **Foreign Key Relationships Working**:
- Trade shipments β†’ Purchase orders
- Trade shipment items β†’ PO items
- GRN items β†’ Purchase orders
- Stock adjustments β†’ Stock ledger
- All cross-table relationships functional

## Benefits Achieved

1. **Eliminated Foreign Key Errors**: All table relationships work correctly
2. **Schema Consistency**: All SCM tables in `trans` schema
3. **Maintainable Code**: Single shared Base for all models
4. **Database Integrity**: Proper foreign key constraints enforced
5. **Application Stability**: No startup errors related to table relationships

## Future Maintenance

### When Adding New Models:
1. Always import from `app.core.database import Base`
2. Include schema in `__table_args__ = {'schema': 'trans'}`
3. Use full schema.table format in foreign keys: `'trans.table_name.column'`
4. Add model imports to `app/sql.py` create_tables function

### Schema Migration Best Practices:
1. Use consistent schema across all related tables
2. Always specify schema explicitly in models
3. Include schema in foreign key references
4. Test foreign key relationships after schema changes