Spaces:
Runtime error
Runtime error
Commit ·
5ea6287
1
Parent(s): ddfe596
clean up
Browse files- docs/implementation-summaries/CATALOGUE_DUAL_IDENTIFIERS.md +0 -358
- docs/implementation-summaries/CATALOGUE_SYNC_IMPLEMENTATION.md +0 -327
- docs/implementation-summaries/CATALOGUE_VALIDATION_SUMMARY.md +0 -125
- docs/implementation-summaries/CRITICAL_FIX_TRAILING_NEWLINE.md +0 -119
- docs/implementation-summaries/EMPLOYEE_ENDPOINTS_IMPLEMENTATION_SUMMARY.md +0 -341
- docs/implementation-summaries/EMPLOYEE_SYNC_INTEGRATION_SUMMARY.md +0 -204
- docs/implementation-summaries/FINAL_CONFIG_SUMMARY.md +0 -137
- docs/implementation-summaries/IMPLEMENTATION_SUMMARY.md +0 -235
- docs/implementation-summaries/INVENTORY_CONTROL_API_IMPLEMENTATION.md +0 -174
- docs/implementation-summaries/INVENTORY_CONTROL_IMPLEMENTATION.md +0 -259
- docs/implementation-summaries/INVENTORY_MIGRATION_SUMMARY.md +0 -190
- docs/implementation-summaries/MERCHANT_API_SUMMARY.md +0 -135
- docs/implementation-summaries/MERCHANT_CATALOGUE_LIST_IMPLEMENTATION.md +0 -316
- docs/implementation-summaries/PRICING_LEVELS_COMPLETE_SOLUTION.md +0 -295
- docs/implementation-summaries/PRICING_LEVELS_CORRECTED_STRUCTURE.md +0 -232
- docs/implementation-summaries/PRICING_LEVELS_SYNC_IMPLEMENTATION.md +0 -187
- docs/implementation-summaries/PROJECTION_LIST_IMPLEMENTATION.md +0 -231
- docs/implementation-summaries/PURCHASES_MODULE_IMPLEMENTATION.md +0 -272
- docs/implementation-summaries/SCM_POSTGRESQL_PO_GRN_IMPLEMENTATION.md +0 -169
- docs/implementation-summaries/SOLUTION_SUMMARY.md +0 -199
- docs/implementation-summaries/SWAGGER_FIX_SUMMARY.md +0 -93
- docs/implementation-summaries/TRADE_SALES_IMPLEMENTATION.md +0 -415
- docs/implementation-summaries/catalogue_api_examples.md +0 -166
docs/implementation-summaries/CATALOGUE_DUAL_IDENTIFIERS.md
DELETED
|
@@ -1,358 +0,0 @@
|
|
| 1 |
-
# Catalogue Dual Identifier System
|
| 2 |
-
|
| 3 |
-
## Overview
|
| 4 |
-
The catalogue system uses a dual identifier approach to provide both technical uniqueness and business readability:
|
| 5 |
-
|
| 6 |
-
- **`catalogue_id`**: Technical UUID for system operations
|
| 7 |
-
- **`catalogue_code`**: Business-readable code for human use
|
| 8 |
-
|
| 9 |
-
## Identifier Types
|
| 10 |
-
|
| 11 |
-
### 1. Catalogue ID (Technical)
|
| 12 |
-
- **Format**: UUID4 (e.g., `550e8400-e29b-41d4-a716-446655440000`)
|
| 13 |
-
- **Purpose**: Primary key for database operations
|
| 14 |
-
- **Generation**: Auto-generated if not provided
|
| 15 |
-
- **Usage**: API operations, database joins, system references
|
| 16 |
-
|
| 17 |
-
### 2. Catalogue Code (Business)
|
| 18 |
-
- **Format**: `BBB-CCC-NNNNNN` (e.g., `LOR-SHA-000001`)
|
| 19 |
-
- **Purpose**: Human-readable identifier for business operations
|
| 20 |
-
- **Generation**: Auto-generated based on brand + category + sequence
|
| 21 |
-
- **Usage**: Reports, labels, business communications
|
| 22 |
-
|
| 23 |
-
## Generation Rules
|
| 24 |
-
|
| 25 |
-
### Catalogue ID Generation
|
| 26 |
-
```python
|
| 27 |
-
# Auto-generated UUID4
|
| 28 |
-
catalogue_id = str(uuid4())
|
| 29 |
-
# Result: "550e8400-e29b-41d4-a716-446655440000"
|
| 30 |
-
```
|
| 31 |
-
|
| 32 |
-
### Catalogue Code Generation
|
| 33 |
-
```python
|
| 34 |
-
# Format: BRAND(3)-CATEGORY(3)-SEQUENCE(6)
|
| 35 |
-
brand_code = normalize_text_for_code("LOREAL", 3) # "LOR"
|
| 36 |
-
category_code = normalize_text_for_code("SHAMPOO", 3) # "SHA"
|
| 37 |
-
sequence = get_next_sequence("catalogue_code_seq") # 1
|
| 38 |
-
catalogue_code = f"{brand_code}-{category_code}-{sequence:06d}"
|
| 39 |
-
# Result: "LOR-SHA-000001"
|
| 40 |
-
```
|
| 41 |
-
|
| 42 |
-
## Brand & Category Code Mapping
|
| 43 |
-
|
| 44 |
-
### Brand Codes (Examples)
|
| 45 |
-
| Brand Name | Code | Example |
|
| 46 |
-
|------------|------|---------|
|
| 47 |
-
| LOREAL | LOR | LOR-SHA-000001 |
|
| 48 |
-
| MATRIX | MAT | MAT-CON-000001 |
|
| 49 |
-
| SCHWARZKOPF | SCH | SCH-COL-000001 |
|
| 50 |
-
| WELLA | WEL | WEL-MAS-000001 |
|
| 51 |
-
| REDKEN | RED | RED-GEL-000001 |
|
| 52 |
-
| TIGI | TIG | TIG-SPR-000001 |
|
| 53 |
-
| PAUL_MITCHELL | PAU | PAU-OIL-000001 |
|
| 54 |
-
| KERASTASE | KER | KER-SER-000001 |
|
| 55 |
-
| OLAPLEX | OLA | OLA-TRE-000001 |
|
| 56 |
-
| MOROCCANOIL | MOR | MOR-OIL-000001 |
|
| 57 |
-
|
| 58 |
-
### Category Codes (Examples)
|
| 59 |
-
| Category Name | Code | Example |
|
| 60 |
-
|---------------|------|---------|
|
| 61 |
-
| SHAMPOO | SHA | LOR-SHA-000001 |
|
| 62 |
-
| CONDITIONER | CON | MAT-CON-000001 |
|
| 63 |
-
| HAIR_MASK | HAI | WEL-HAI-000001 |
|
| 64 |
-
| HAIR_COLOR | COL | SCH-COL-000001 |
|
| 65 |
-
| STYLING_GEL | STY | RED-STY-000001 |
|
| 66 |
-
| HAIR_SPRAY | SPR | TIG-SPR-000001 |
|
| 67 |
-
| HAIR_OIL | OIL | PAU-OIL-000001 |
|
| 68 |
-
| HAIR_SERUM | SER | KER-SER-000001 |
|
| 69 |
-
|
| 70 |
-
## API Usage Examples
|
| 71 |
-
|
| 72 |
-
### 1. Full Auto-Generation (Both IDs)
|
| 73 |
-
```bash
|
| 74 |
-
curl -X 'POST' \
|
| 75 |
-
'http://127.0.0.1:8000/catalogue/catalogues' \
|
| 76 |
-
-H 'Content-Type: application/json' \
|
| 77 |
-
-d '{
|
| 78 |
-
"catalogue_name": "L'\''Oreal Professional Shampoo",
|
| 79 |
-
"catalogue_type": "Product",
|
| 80 |
-
"brand": "LOREAL",
|
| 81 |
-
"category": "SHAMPOO",
|
| 82 |
-
"description": "Professional grade shampoo"
|
| 83 |
-
}'
|
| 84 |
-
```
|
| 85 |
-
|
| 86 |
-
**Response:**
|
| 87 |
-
```json
|
| 88 |
-
{
|
| 89 |
-
"data": {
|
| 90 |
-
"catalogue_id": "550e8400-e29b-41d4-a716-446655440000",
|
| 91 |
-
"catalogue_code": "LOR-SHA-000001",
|
| 92 |
-
"catalogue_name": "L'Oreal Professional Shampoo",
|
| 93 |
-
"catalogue_type": "Product",
|
| 94 |
-
"brand": "LOREAL",
|
| 95 |
-
"category": "SHAMPOO"
|
| 96 |
-
}
|
| 97 |
-
}
|
| 98 |
-
```
|
| 99 |
-
|
| 100 |
-
### 2. Manual ID, Auto Code
|
| 101 |
-
```bash
|
| 102 |
-
curl -X 'POST' \
|
| 103 |
-
'http://127.0.0.1:8000/catalogue/catalogues' \
|
| 104 |
-
-H 'Content-Type: application/json' \
|
| 105 |
-
-d '{
|
| 106 |
-
"catalogue_id": "custom-loreal-shampoo-001",
|
| 107 |
-
"catalogue_name": "L'\''Oreal Serie Expert",
|
| 108 |
-
"catalogue_type": "Product",
|
| 109 |
-
"brand": "LOREAL",
|
| 110 |
-
"category": "SHAMPOO"
|
| 111 |
-
}'
|
| 112 |
-
```
|
| 113 |
-
|
| 114 |
-
**Response:**
|
| 115 |
-
```json
|
| 116 |
-
{
|
| 117 |
-
"data": {
|
| 118 |
-
"catalogue_id": "custom-loreal-shampoo-001",
|
| 119 |
-
"catalogue_code": "LOR-SHA-000002",
|
| 120 |
-
"catalogue_name": "L'Oreal Serie Expert",
|
| 121 |
-
"catalogue_type": "Product"
|
| 122 |
-
}
|
| 123 |
-
}
|
| 124 |
-
```
|
| 125 |
-
|
| 126 |
-
### 3. Both Manual (Override)
|
| 127 |
-
```bash
|
| 128 |
-
curl -X 'POST' \
|
| 129 |
-
'http://127.0.0.1:8000/catalogue/catalogues' \
|
| 130 |
-
-H 'Content-Type: application/json' \
|
| 131 |
-
-d '{
|
| 132 |
-
"catalogue_id": "manual-id-123",
|
| 133 |
-
"catalogue_code": "CUSTOM-CODE-001",
|
| 134 |
-
"catalogue_name": "Custom Product",
|
| 135 |
-
"catalogue_type": "Product",
|
| 136 |
-
"brand": "OTHER",
|
| 137 |
-
"category": "OTHER"
|
| 138 |
-
}'
|
| 139 |
-
```
|
| 140 |
-
|
| 141 |
-
**Response:**
|
| 142 |
-
```json
|
| 143 |
-
{
|
| 144 |
-
"data": {
|
| 145 |
-
"catalogue_id": "manual-id-123",
|
| 146 |
-
"catalogue_code": "CUSTOM-CODE-001",
|
| 147 |
-
"catalogue_name": "Custom Product",
|
| 148 |
-
"catalogue_type": "Product"
|
| 149 |
-
}
|
| 150 |
-
}
|
| 151 |
-
```
|
| 152 |
-
|
| 153 |
-
## Database Storage
|
| 154 |
-
|
| 155 |
-
### MongoDB Document
|
| 156 |
-
```json
|
| 157 |
-
{
|
| 158 |
-
"_id": ObjectId("..."),
|
| 159 |
-
"catalogue_id": "550e8400-e29b-41d4-a716-446655440000",
|
| 160 |
-
"catalogue_code": "LOR-SHA-000001",
|
| 161 |
-
"catalogue_name": "L'Oreal Professional Shampoo",
|
| 162 |
-
"catalogue_type": "Product",
|
| 163 |
-
"brand": "LOREAL",
|
| 164 |
-
"category": "SHAMPOO",
|
| 165 |
-
"identifiers": {
|
| 166 |
-
"sku": "LOR-SHA-500ML",
|
| 167 |
-
"ean_code": "1234567890123"
|
| 168 |
-
},
|
| 169 |
-
"pricing": {
|
| 170 |
-
"mrp": 1000.00,
|
| 171 |
-
"retail_price": 850.00
|
| 172 |
-
}
|
| 173 |
-
}
|
| 174 |
-
```
|
| 175 |
-
|
| 176 |
-
### PostgreSQL Record
|
| 177 |
-
```sql
|
| 178 |
-
INSERT INTO catalogue_ref (
|
| 179 |
-
catalogue_id,
|
| 180 |
-
catalogue_code,
|
| 181 |
-
catalogue_type,
|
| 182 |
-
catalogue_name,
|
| 183 |
-
sku,
|
| 184 |
-
mrp,
|
| 185 |
-
base_price,
|
| 186 |
-
status,
|
| 187 |
-
created_at
|
| 188 |
-
) VALUES (
|
| 189 |
-
'550e8400-e29b-41d4-a716-446655440000',
|
| 190 |
-
'LOR-SHA-000001',
|
| 191 |
-
'Product',
|
| 192 |
-
'L''Oreal Professional Shampoo',
|
| 193 |
-
'LOR-SHA-500ML',
|
| 194 |
-
1000.00,
|
| 195 |
-
850.00,
|
| 196 |
-
'Active',
|
| 197 |
-
NOW()
|
| 198 |
-
);
|
| 199 |
-
```
|
| 200 |
-
|
| 201 |
-
## Query Examples
|
| 202 |
-
|
| 203 |
-
### By Catalogue ID (Technical)
|
| 204 |
-
```bash
|
| 205 |
-
# Get catalogue by UUID
|
| 206 |
-
GET /catalogue/550e8400-e29b-41d4-a716-446655440000
|
| 207 |
-
|
| 208 |
-
# Update catalogue by UUID
|
| 209 |
-
PUT /catalogue/550e8400-e29b-41d4-a716-446655440000
|
| 210 |
-
```
|
| 211 |
-
|
| 212 |
-
### By Catalogue Code (Business)
|
| 213 |
-
```bash
|
| 214 |
-
# List catalogues by code pattern
|
| 215 |
-
POST /catalogue/list
|
| 216 |
-
{
|
| 217 |
-
"filters": {
|
| 218 |
-
"catalogue_code": {"$regex": "^LOR-SHA-"}
|
| 219 |
-
}
|
| 220 |
-
}
|
| 221 |
-
|
| 222 |
-
# Search by code prefix
|
| 223 |
-
POST /catalogue/list
|
| 224 |
-
{
|
| 225 |
-
"filters": {
|
| 226 |
-
"catalogue_code": {"$regex": "^LOR-"}
|
| 227 |
-
}
|
| 228 |
-
}
|
| 229 |
-
```
|
| 230 |
-
|
| 231 |
-
### PostgreSQL Queries
|
| 232 |
-
```sql
|
| 233 |
-
-- Find by catalogue code
|
| 234 |
-
SELECT * FROM catalogue_ref
|
| 235 |
-
WHERE catalogue_code = 'LOR-SHA-000001';
|
| 236 |
-
|
| 237 |
-
-- Find all L'Oreal shampoos
|
| 238 |
-
SELECT * FROM catalogue_ref
|
| 239 |
-
WHERE catalogue_code LIKE 'LOR-SHA-%';
|
| 240 |
-
|
| 241 |
-
-- Join with purchase orders using catalogue_id
|
| 242 |
-
SELECT cr.catalogue_code, cr.catalogue_name, po.po_no
|
| 243 |
-
FROM catalogue_ref cr
|
| 244 |
-
JOIN scm_po_item poi ON cr.catalogue_id = poi.catalogue_id
|
| 245 |
-
JOIN scm_po po ON poi.po_id = po.po_id;
|
| 246 |
-
```
|
| 247 |
-
|
| 248 |
-
## Use Cases
|
| 249 |
-
|
| 250 |
-
### Technical Operations (catalogue_id)
|
| 251 |
-
- **API Endpoints**: Primary identifier for REST operations
|
| 252 |
-
- **Database Joins**: Foreign key relationships
|
| 253 |
-
- **System Integration**: Microservice communication
|
| 254 |
-
- **Caching**: Cache keys and lookups
|
| 255 |
-
|
| 256 |
-
### Business Operations (catalogue_code)
|
| 257 |
-
- **Reports**: Human-readable product codes
|
| 258 |
-
- **Labels**: Product labeling and packaging
|
| 259 |
-
- **Communication**: Business discussions and documentation
|
| 260 |
-
- **Search**: User-friendly search and filtering
|
| 261 |
-
|
| 262 |
-
## Benefits of Dual System
|
| 263 |
-
|
| 264 |
-
### Technical Benefits
|
| 265 |
-
1. **UUID Uniqueness**: Guaranteed global uniqueness
|
| 266 |
-
2. **Performance**: Efficient database operations
|
| 267 |
-
3. **Security**: Non-guessable identifiers
|
| 268 |
-
4. **Scalability**: No collision concerns
|
| 269 |
-
|
| 270 |
-
### Business Benefits
|
| 271 |
-
1. **Readability**: Easy to understand and communicate
|
| 272 |
-
2. **Organization**: Logical grouping by brand/category
|
| 273 |
-
3. **Sorting**: Natural alphabetical sorting
|
| 274 |
-
4. **Recognition**: Quick visual identification
|
| 275 |
-
|
| 276 |
-
### Combined Benefits
|
| 277 |
-
1. **Flexibility**: Choose appropriate ID for context
|
| 278 |
-
2. **Migration**: Easy data migration between systems
|
| 279 |
-
3. **Integration**: Support both technical and business needs
|
| 280 |
-
4. **Reporting**: Technical accuracy with business clarity
|
| 281 |
-
|
| 282 |
-
## Sequence Management
|
| 283 |
-
|
| 284 |
-
### MongoDB Sequences
|
| 285 |
-
```javascript
|
| 286 |
-
// Sequence document in MongoDB
|
| 287 |
-
{
|
| 288 |
-
"_id": "catalogue_code_seq",
|
| 289 |
-
"value": 1234
|
| 290 |
-
}
|
| 291 |
-
|
| 292 |
-
// Atomic increment
|
| 293 |
-
db.sequences.findOneAndUpdate(
|
| 294 |
-
{"_id": "catalogue_code_seq"},
|
| 295 |
-
{"$inc": {"value": 1}},
|
| 296 |
-
{"upsert": true, "returnNewDocument": true}
|
| 297 |
-
)
|
| 298 |
-
```
|
| 299 |
-
|
| 300 |
-
### Year-Based Sequences (Future Enhancement)
|
| 301 |
-
```python
|
| 302 |
-
# Potential enhancement: Year-based sequences
|
| 303 |
-
def generate_yearly_code(brand, category, year=None):
|
| 304 |
-
year = year or datetime.now().year
|
| 305 |
-
seq = get_next_sequence(f"catalogue_code_seq_{year}")
|
| 306 |
-
return f"{brand_code}-{category_code}-{year}-{seq:06d}"
|
| 307 |
-
# Result: "LOR-SHA-2024-000001"
|
| 308 |
-
```
|
| 309 |
-
|
| 310 |
-
## Validation Rules
|
| 311 |
-
|
| 312 |
-
### Catalogue ID Validation
|
| 313 |
-
- Must be valid UUID format if provided
|
| 314 |
-
- Auto-generated if not provided
|
| 315 |
-
- Must be unique across all catalogues
|
| 316 |
-
|
| 317 |
-
### Catalogue Code Validation
|
| 318 |
-
- Must follow BBB-CCC-NNNNNN format if provided
|
| 319 |
-
- Auto-generated if brand and category provided
|
| 320 |
-
- Must be unique across all catalogues
|
| 321 |
-
- Brand must be from valid brand list
|
| 322 |
-
- Category must be from valid category list
|
| 323 |
-
|
| 324 |
-
## Error Handling
|
| 325 |
-
|
| 326 |
-
### Duplicate ID Errors
|
| 327 |
-
```json
|
| 328 |
-
{
|
| 329 |
-
"detail": "Catalogue ID already exists: 550e8400-e29b-41d4-a716-446655440000"
|
| 330 |
-
}
|
| 331 |
-
```
|
| 332 |
-
|
| 333 |
-
### Duplicate Code Errors
|
| 334 |
-
```json
|
| 335 |
-
{
|
| 336 |
-
"detail": "Catalogue code already exists: LOR-SHA-000001"
|
| 337 |
-
}
|
| 338 |
-
```
|
| 339 |
-
|
| 340 |
-
### Invalid Brand/Category
|
| 341 |
-
```json
|
| 342 |
-
{
|
| 343 |
-
"detail": "Invalid brand: FAKE_BRAND. Valid brands: LOREAL, MATRIX, ..."
|
| 344 |
-
}
|
| 345 |
-
```
|
| 346 |
-
|
| 347 |
-
## Summary
|
| 348 |
-
|
| 349 |
-
The dual identifier system provides:
|
| 350 |
-
|
| 351 |
-
✅ **Technical Efficiency**: UUID for system operations
|
| 352 |
-
✅ **Business Clarity**: Readable codes for human use
|
| 353 |
-
✅ **Auto-Generation**: Both IDs generated automatically
|
| 354 |
-
✅ **Manual Override**: Custom IDs when needed
|
| 355 |
-
✅ **Validation**: Ensures uniqueness and format compliance
|
| 356 |
-
✅ **Flexibility**: Choose appropriate ID for each use case
|
| 357 |
-
|
| 358 |
-
This approach satisfies both technical requirements (unique, efficient identifiers) and business needs (readable, meaningful codes) in a single, cohesive system.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/CATALOGUE_SYNC_IMPLEMENTATION.md
DELETED
|
@@ -1,327 +0,0 @@
|
|
| 1 |
-
# Catalogue MongoDB-PostgreSQL Synchronization
|
| 2 |
-
|
| 3 |
-
## Overview
|
| 4 |
-
Complete implementation of dual-database synchronization for catalogue data. Maintains MongoDB as the primary source of truth while keeping a PostgreSQL reference table in sync for relational queries and reporting.
|
| 5 |
-
|
| 6 |
-
## Architecture
|
| 7 |
-
|
| 8 |
-
### Dual Database Strategy
|
| 9 |
-
- **MongoDB**: Primary storage with full catalogue documents
|
| 10 |
-
- **PostgreSQL**: Reference table (`catalogue_ref`) with essential fields for joins and reporting
|
| 11 |
-
|
| 12 |
-
### Sync Flow
|
| 13 |
-
```
|
| 14 |
-
MongoDB CRUD Operation → PostgreSQL Sync → Response
|
| 15 |
-
↓ ↓
|
| 16 |
-
Primary Data Reference Data
|
| 17 |
-
(Complete) (Essential Fields)
|
| 18 |
-
```
|
| 19 |
-
|
| 20 |
-
## Database Schema
|
| 21 |
-
|
| 22 |
-
### MongoDB Collection: `scm_catalogue`
|
| 23 |
-
Complete catalogue documents with nested structures:
|
| 24 |
-
- Full product information
|
| 25 |
-
- Pricing levels and commission rules
|
| 26 |
-
- Media and attributes
|
| 27 |
-
- Metadata and audit trails
|
| 28 |
-
|
| 29 |
-
### PostgreSQL Table: `catalogue_ref`
|
| 30 |
-
```sql
|
| 31 |
-
CREATE TABLE IF NOT EXISTS public.catalogue_ref (
|
| 32 |
-
catalogue_id text NOT NULL,
|
| 33 |
-
catalogue_code text,
|
| 34 |
-
catalogue_type text NOT NULL,
|
| 35 |
-
catalogue_name text NOT NULL,
|
| 36 |
-
sku text,
|
| 37 |
-
barcode_number text,
|
| 38 |
-
hsn_code text,
|
| 39 |
-
gst_rate numeric(5,2),
|
| 40 |
-
mrp numeric(12,2),
|
| 41 |
-
base_price numeric(12,2),
|
| 42 |
-
track_inventory boolean DEFAULT false,
|
| 43 |
-
batch_managed boolean DEFAULT false,
|
| 44 |
-
status text NOT NULL,
|
| 45 |
-
created_at timestamp without time zone NOT NULL,
|
| 46 |
-
merchant_id text[] DEFAULT '{}',
|
| 47 |
-
CONSTRAINT catalogue_ref_pkey PRIMARY KEY (catalogue_id)
|
| 48 |
-
);
|
| 49 |
-
```
|
| 50 |
-
|
| 51 |
-
## Implementation Components
|
| 52 |
-
|
| 53 |
-
### 1. PostgreSQL Model (`catalogue_ref_model.py`)
|
| 54 |
-
```python
|
| 55 |
-
class CatalogueRef(Base):
|
| 56 |
-
__tablename__ = 'catalogue_ref'
|
| 57 |
-
|
| 58 |
-
catalogue_id = Column(Text, primary_key=True)
|
| 59 |
-
catalogue_code = Column(Text)
|
| 60 |
-
catalogue_type = Column(Text, nullable=False)
|
| 61 |
-
catalogue_name = Column(Text, nullable=False)
|
| 62 |
-
sku = Column(Text)
|
| 63 |
-
barcode_number = Column(Text)
|
| 64 |
-
hsn_code = Column(Text)
|
| 65 |
-
gst_rate = Column(Numeric(5, 2))
|
| 66 |
-
mrp = Column(Numeric(12, 2))
|
| 67 |
-
base_price = Column(Numeric(12, 2))
|
| 68 |
-
track_inventory = Column(Boolean, default=False)
|
| 69 |
-
batch_managed = Column(Boolean, default=False)
|
| 70 |
-
status = Column(Text, nullable=False)
|
| 71 |
-
created_at = Column(TIMESTAMP, nullable=False)
|
| 72 |
-
merchant_id = Column(ARRAY(Text))
|
| 73 |
-
```
|
| 74 |
-
|
| 75 |
-
### 2. Sync Service (`sync_service.py`)
|
| 76 |
-
Handles all PostgreSQL operations:
|
| 77 |
-
- **Data Extraction**: Converts MongoDB documents to PostgreSQL format
|
| 78 |
-
- **CRUD Operations**: Create, update, delete reference records
|
| 79 |
-
- **Status Management**: Sync activation/deactivation
|
| 80 |
-
- **Merchant Management**: Add/remove merchants from catalogue access
|
| 81 |
-
|
| 82 |
-
### 3. Enhanced Catalogue Service
|
| 83 |
-
Updated to include PostgreSQL sync:
|
| 84 |
-
- **Dual Operations**: MongoDB + PostgreSQL in single transaction
|
| 85 |
-
- **Error Handling**: Continues on sync failures (logs errors)
|
| 86 |
-
- **Optional Sync**: Works with or without PostgreSQL connection
|
| 87 |
-
|
| 88 |
-
## Sync Operations
|
| 89 |
-
|
| 90 |
-
### Create Catalogue
|
| 91 |
-
```python
|
| 92 |
-
# MongoDB Operation
|
| 93 |
-
catalogue = await mongo_collection.insert_one(catalogue_data)
|
| 94 |
-
|
| 95 |
-
# PostgreSQL Sync
|
| 96 |
-
if sync_service:
|
| 97 |
-
await sync_service.create_catalogue_ref(catalogue_model)
|
| 98 |
-
```
|
| 99 |
-
|
| 100 |
-
### Update Catalogue
|
| 101 |
-
```python
|
| 102 |
-
# MongoDB Operation
|
| 103 |
-
await mongo_collection.update_one(filter, update_data)
|
| 104 |
-
|
| 105 |
-
# PostgreSQL Sync
|
| 106 |
-
updated_doc = await mongo_collection.find_one(filter)
|
| 107 |
-
await sync_service.update_catalogue_ref(catalogue_id, updated_doc)
|
| 108 |
-
```
|
| 109 |
-
|
| 110 |
-
### Delete Catalogue
|
| 111 |
-
```python
|
| 112 |
-
# MongoDB Operation
|
| 113 |
-
await mongo_collection.delete_one(filter)
|
| 114 |
-
|
| 115 |
-
# PostgreSQL Sync
|
| 116 |
-
await sync_service.delete_catalogue_ref(catalogue_id)
|
| 117 |
-
```
|
| 118 |
-
|
| 119 |
-
### Status Changes
|
| 120 |
-
```python
|
| 121 |
-
# MongoDB Operation
|
| 122 |
-
await mongo_collection.update_one(filter, {"$set": {"meta.status": status}})
|
| 123 |
-
|
| 124 |
-
# PostgreSQL Sync
|
| 125 |
-
await sync_service.sync_catalogue_status(catalogue_id, status)
|
| 126 |
-
```
|
| 127 |
-
|
| 128 |
-
## Data Mapping
|
| 129 |
-
|
| 130 |
-
### Field Extraction Rules
|
| 131 |
-
| MongoDB Field | PostgreSQL Field | Extraction Logic |
|
| 132 |
-
|---------------|------------------|------------------|
|
| 133 |
-
| `catalogue_id` | `catalogue_id` | Direct copy |
|
| 134 |
-
| `catalogue_code` | `catalogue_code` | Direct copy |
|
| 135 |
-
| `identifiers.sku` | `sku` | Nested field extraction |
|
| 136 |
-
| `identifiers.barcode_number` | `barcode_number` | Nested field extraction |
|
| 137 |
-
| `pricing.mrp` | `mrp` | Nested field, convert to Decimal |
|
| 138 |
-
| `pricing.retail_price` | `base_price` | Nested field, fallback to sale_price |
|
| 139 |
-
| `tax.gst_rate` | `gst_rate` | Nested field, convert to Decimal |
|
| 140 |
-
| `tax.hsn_code` | `hsn_code` | Nested field extraction |
|
| 141 |
-
| `inventory.track_inventory` | `track_inventory` | Nested field, default False |
|
| 142 |
-
| `procurement.batch_managed` | `batch_managed` | Derived from batch_managed presence |
|
| 143 |
-
| `meta.status` | `status` | Nested field, default "Active" |
|
| 144 |
-
| `meta.created_at` | `created_at` | Nested field extraction |
|
| 145 |
-
|
| 146 |
-
## Error Handling
|
| 147 |
-
|
| 148 |
-
### Sync Failure Strategy
|
| 149 |
-
- **Primary Operation**: Always completes (MongoDB)
|
| 150 |
-
- **Sync Failure**: Logged but doesn't fail main operation
|
| 151 |
-
- **Monitoring**: Structured logging for sync errors
|
| 152 |
-
- **Recovery**: Manual sync tools for fixing inconsistencies
|
| 153 |
-
|
| 154 |
-
### Example Error Handling
|
| 155 |
-
```python
|
| 156 |
-
try:
|
| 157 |
-
# MongoDB operation (primary)
|
| 158 |
-
await mongo_collection.insert_one(data)
|
| 159 |
-
|
| 160 |
-
# PostgreSQL sync (secondary)
|
| 161 |
-
if sync_service:
|
| 162 |
-
await sync_service.create_catalogue_ref(catalogue)
|
| 163 |
-
|
| 164 |
-
except Exception as sync_error:
|
| 165 |
-
logger.error(f"PostgreSQL sync failed: {sync_error}")
|
| 166 |
-
# Continue - don't fail the main operation
|
| 167 |
-
```
|
| 168 |
-
|
| 169 |
-
## API Integration
|
| 170 |
-
|
| 171 |
-
### Controller Updates
|
| 172 |
-
All catalogue modification endpoints now include PostgreSQL session:
|
| 173 |
-
|
| 174 |
-
```python
|
| 175 |
-
@router.post("/catalogues")
|
| 176 |
-
async def create_catalogue(
|
| 177 |
-
data: Catalogue,
|
| 178 |
-
db: AsyncIOMotorDatabase = Depends(get_database),
|
| 179 |
-
pg_session: AsyncSession = Depends(get_pg_session),
|
| 180 |
-
):
|
| 181 |
-
service = CatalogueService(db, pg_session)
|
| 182 |
-
return await service.create_catalogue_item(data, user_id)
|
| 183 |
-
```
|
| 184 |
-
|
| 185 |
-
### Affected Endpoints
|
| 186 |
-
- `POST /catalogue/catalogues` - Create catalogue
|
| 187 |
-
- `PUT /catalogue/{catalogue_id}` - Update catalogue
|
| 188 |
-
- `DELETE /catalogue/` - Delete catalogue
|
| 189 |
-
- `POST /catalogue/{catalogue_id}/activate` - Activate catalogue
|
| 190 |
-
- `POST /catalogue/{catalogue_id}/deactivate` - Deactivate catalogue
|
| 191 |
-
|
| 192 |
-
## Benefits
|
| 193 |
-
|
| 194 |
-
### Performance Benefits
|
| 195 |
-
- **Fast Joins**: PostgreSQL reference table enables efficient joins with PO/GRN tables
|
| 196 |
-
- **Reporting**: SQL queries for analytics and reporting
|
| 197 |
-
- **Filtering**: Efficient filtering on indexed PostgreSQL fields
|
| 198 |
-
- **Aggregations**: SQL aggregations for business intelligence
|
| 199 |
-
|
| 200 |
-
### Data Consistency
|
| 201 |
-
- **Single Source**: MongoDB remains authoritative
|
| 202 |
-
- **Eventual Consistency**: PostgreSQL syncs asynchronously
|
| 203 |
-
- **Error Recovery**: Sync failures don't affect primary operations
|
| 204 |
-
- **Monitoring**: Comprehensive logging for sync status
|
| 205 |
-
|
| 206 |
-
### Integration Benefits
|
| 207 |
-
- **Purchase Orders**: Can join with `catalogue_ref` for SKU validation
|
| 208 |
-
- **Inventory**: Track inventory flags in PostgreSQL
|
| 209 |
-
- **Reporting**: SQL-based reports with catalogue data
|
| 210 |
-
- **Analytics**: Business intelligence queries
|
| 211 |
-
|
| 212 |
-
## Usage Examples
|
| 213 |
-
|
| 214 |
-
### Create Catalogue with Auto-Sync
|
| 215 |
-
```bash
|
| 216 |
-
curl -X 'POST' \
|
| 217 |
-
'http://127.0.0.1:8000/catalogue/catalogues' \
|
| 218 |
-
-H 'Content-Type: application/json' \
|
| 219 |
-
-d '{
|
| 220 |
-
"catalogue_name": "L'\''Oreal Professional Shampoo",
|
| 221 |
-
"catalogue_type": "Product",
|
| 222 |
-
"brand": "LOREAL",
|
| 223 |
-
"category": "SHAMPOO",
|
| 224 |
-
"identifiers": {
|
| 225 |
-
"sku": "LOR-SHA-500ML",
|
| 226 |
-
"barcode_number": "1234567890"
|
| 227 |
-
},
|
| 228 |
-
"pricing": {
|
| 229 |
-
"mrp": 1000.00,
|
| 230 |
-
"retail_price": 850.00
|
| 231 |
-
},
|
| 232 |
-
"tax": {
|
| 233 |
-
"gst_rate": 18.0,
|
| 234 |
-
"hsn_code": "33051000"
|
| 235 |
-
}
|
| 236 |
-
}'
|
| 237 |
-
```
|
| 238 |
-
|
| 239 |
-
**Result**:
|
| 240 |
-
- MongoDB: Complete catalogue document
|
| 241 |
-
- PostgreSQL: Reference record with essential fields
|
| 242 |
-
|
| 243 |
-
### Query PostgreSQL Reference
|
| 244 |
-
```sql
|
| 245 |
-
-- Find catalogues by brand and status
|
| 246 |
-
SELECT catalogue_id, catalogue_name, sku, mrp, status
|
| 247 |
-
FROM catalogue_ref
|
| 248 |
-
WHERE catalogue_code LIKE 'LOR-%'
|
| 249 |
-
AND status = 'Active'
|
| 250 |
-
AND track_inventory = true;
|
| 251 |
-
|
| 252 |
-
-- Join with purchase orders
|
| 253 |
-
SELECT cr.catalogue_name, cr.sku, po.po_no, poi.ord_qty
|
| 254 |
-
FROM catalogue_ref cr
|
| 255 |
-
JOIN scm_po_item poi ON cr.catalogue_id = poi.catalogue_id
|
| 256 |
-
JOIN scm_po po ON poi.po_id = po.po_id
|
| 257 |
-
WHERE cr.status = 'Active';
|
| 258 |
-
```
|
| 259 |
-
|
| 260 |
-
## Monitoring and Maintenance
|
| 261 |
-
|
| 262 |
-
### Sync Status Monitoring
|
| 263 |
-
- **Success Logs**: Successful sync operations
|
| 264 |
-
- **Error Logs**: Failed sync attempts with details
|
| 265 |
-
- **Metrics**: Sync success/failure rates
|
| 266 |
-
- **Alerts**: Critical sync failures
|
| 267 |
-
|
| 268 |
-
### Data Consistency Checks
|
| 269 |
-
```sql
|
| 270 |
-
-- Find catalogues in MongoDB but not PostgreSQL
|
| 271 |
-
-- (Requires application-level query)
|
| 272 |
-
|
| 273 |
-
-- Find orphaned PostgreSQL records
|
| 274 |
-
SELECT catalogue_id, catalogue_name
|
| 275 |
-
FROM catalogue_ref
|
| 276 |
-
WHERE catalogue_id NOT IN (
|
| 277 |
-
-- MongoDB catalogue IDs would need to be provided
|
| 278 |
-
);
|
| 279 |
-
```
|
| 280 |
-
|
| 281 |
-
### Recovery Procedures
|
| 282 |
-
1. **Identify Inconsistencies**: Compare MongoDB vs PostgreSQL
|
| 283 |
-
2. **Bulk Sync**: Re-sync missing or outdated records
|
| 284 |
-
3. **Cleanup**: Remove orphaned PostgreSQL records
|
| 285 |
-
4. **Validation**: Verify data consistency post-recovery
|
| 286 |
-
|
| 287 |
-
## Testing
|
| 288 |
-
|
| 289 |
-
### Test Coverage
|
| 290 |
-
- **Unit Tests**: Sync service methods
|
| 291 |
-
- **Integration Tests**: End-to-end CRUD with sync
|
| 292 |
-
- **Error Tests**: Sync failure scenarios
|
| 293 |
-
- **Performance Tests**: Sync operation timing
|
| 294 |
-
|
| 295 |
-
### Test Script
|
| 296 |
-
Run `test_catalogue_sync.py` to verify:
|
| 297 |
-
- Data extraction logic
|
| 298 |
-
- PostgreSQL schema compatibility
|
| 299 |
-
- Sync operation flow
|
| 300 |
-
- Error handling
|
| 301 |
-
|
| 302 |
-
## Future Enhancements
|
| 303 |
-
|
| 304 |
-
### Potential Improvements
|
| 305 |
-
1. **Batch Sync**: Bulk sync operations for performance
|
| 306 |
-
2. **Conflict Resolution**: Handle concurrent updates
|
| 307 |
-
3. **Sync Queue**: Asynchronous sync with retry logic
|
| 308 |
-
4. **Data Validation**: Cross-database consistency checks
|
| 309 |
-
5. **Sync Metrics**: Detailed performance monitoring
|
| 310 |
-
|
| 311 |
-
### Scalability Considerations
|
| 312 |
-
- **Connection Pooling**: Efficient PostgreSQL connections
|
| 313 |
-
- **Async Operations**: Non-blocking sync operations
|
| 314 |
-
- **Error Recovery**: Automatic retry mechanisms
|
| 315 |
-
- **Monitoring**: Real-time sync health monitoring
|
| 316 |
-
|
| 317 |
-
## Summary
|
| 318 |
-
|
| 319 |
-
The catalogue synchronization system provides:
|
| 320 |
-
- ✅ **Dual Database Support**: MongoDB + PostgreSQL
|
| 321 |
-
- ✅ **Automatic Sync**: Transparent sync on all CRUD operations
|
| 322 |
-
- ✅ **Error Resilience**: Continues on sync failures
|
| 323 |
-
- ✅ **Performance**: Efficient PostgreSQL queries for reporting
|
| 324 |
-
- ✅ **Consistency**: MongoDB as single source of truth
|
| 325 |
-
- ✅ **Monitoring**: Comprehensive logging and error tracking
|
| 326 |
-
|
| 327 |
-
This implementation enables the best of both worlds: MongoDB's flexibility for complex catalogue data and PostgreSQL's power for relational queries and reporting.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/CATALOGUE_VALIDATION_SUMMARY.md
DELETED
|
@@ -1,125 +0,0 @@
|
|
| 1 |
-
# Catalogue Schema Validation Updates - Industry Standards
|
| 2 |
-
|
| 3 |
-
## Overview
|
| 4 |
-
Updated the catalogue schema (`app/catalogues/schemas/schema.py`) to follow industry-standard validation practices with comprehensive field validation, cross-field validation, and proper error handling.
|
| 5 |
-
|
| 6 |
-
## Key Improvements
|
| 7 |
-
|
| 8 |
-
### 1. **Enum-Based Validation**
|
| 9 |
-
- `CatalogueType`: Product, Service, Package
|
| 10 |
-
- `CatalogueStatus`: Active, Inactive, Draft, Discontinued
|
| 11 |
-
- `Currency`: INR, USD, EUR
|
| 12 |
-
- `CommissionType`: Percent, Flat
|
| 13 |
-
- `UnitOfMeasure`: PCS, KG, GRAM, LITER, ML, etc.
|
| 14 |
-
|
| 15 |
-
### 2. **Regex Pattern Validation**
|
| 16 |
-
- **SKU**: `^[A-Z0-9\-_]{3,50}$` (3-50 alphanumeric, hyphens, underscores)
|
| 17 |
-
- **EAN Code**: `^\d{8}|\d{13}$` (EAN-8 or EAN-13 format)
|
| 18 |
-
- **Barcode**: `^[A-Z0-9\-_]{3,50}$` (alphanumeric with hyphens/underscores)
|
| 19 |
-
- **HSN Code**: `^\d{4,8}$` (4-8 digit HSN codes)
|
| 20 |
-
- **Catalogue Code**: `^[A-Z]{3}-[A-Z]{3}-\d{6}$` (BBB-CCC-NNNNNN format)
|
| 21 |
-
- **HTTPS URLs**: `^https://.+` (secure URLs only)
|
| 22 |
-
|
| 23 |
-
### 3. **Field Constraints**
|
| 24 |
-
- **String Length**: Min/max length validation with whitespace stripping
|
| 25 |
-
- **Numeric Ranges**: Proper bounds for prices (0-999999.99), percentages (0-100%), quantities
|
| 26 |
-
- **Required Fields**: Contextual requirements based on catalogue type
|
| 27 |
-
|
| 28 |
-
### 4. **Cross-Field Validation**
|
| 29 |
-
- **Product Requirements**: Products must have identifiers with SKU
|
| 30 |
-
- **Service Requirements**: Services should have descriptions
|
| 31 |
-
- **Pricing Consistency**: MRP validation, margin limits
|
| 32 |
-
- **Inventory Logic**: Reorder level vs safety stock vs max stock validation
|
| 33 |
-
- **Commission Logic**: Type and value required when enabled
|
| 34 |
-
- **Timestamp Logic**: Updated timestamp must be after created timestamp
|
| 35 |
-
- **Optional Sections**: Attributes and Media are completely optional for all catalogue types
|
| 36 |
-
|
| 37 |
-
### 5. **Industry-Standard GST Rates**
|
| 38 |
-
- Validates against standard Indian GST rates: [0, 0.25, 3, 5, 12, 18, 28]
|
| 39 |
-
- Prevents invalid GST rate entries
|
| 40 |
-
|
| 41 |
-
### 6. **Enhanced Security**
|
| 42 |
-
- **HTTPS-Only URLs**: All image and document URLs must use HTTPS
|
| 43 |
-
- **Input Sanitization**: Automatic whitespace stripping and case normalization
|
| 44 |
-
- **Field Length Limits**: Prevents oversized inputs
|
| 45 |
-
|
| 46 |
-
### 7. **API Standards Compliance**
|
| 47 |
-
- **Projection List Support**: All list endpoints support field projection for performance
|
| 48 |
-
- **Filter Validation**: Validates allowed filter fields for each endpoint type
|
| 49 |
-
- **Pagination Limits**: Proper bounds on skip/limit parameters
|
| 50 |
-
- **Error Messages**: Descriptive validation error messages
|
| 51 |
-
|
| 52 |
-
## Updated Models
|
| 53 |
-
|
| 54 |
-
### Core Models
|
| 55 |
-
1. **Identifier** - SKU, EAN, barcode validation
|
| 56 |
-
2. **Attributes** - Product attribute constraints
|
| 57 |
-
3. **PricingLevel** - Price and margin validation
|
| 58 |
-
4. **Pricing** - Currency and pricing level validation
|
| 59 |
-
5. **Commission** - Commission type and value validation
|
| 60 |
-
6. **Loyalty** - Points and redemption validation
|
| 61 |
-
7. **Procurement** - Batch management and lead time validation
|
| 62 |
-
8. **InventoryLevel** - Stock level relationship validation
|
| 63 |
-
9. **Inventory** - Unit of measure and level validation
|
| 64 |
-
10. **Tax** - HSN code and GST rate validation
|
| 65 |
-
11. **Media** - HTTPS URL validation for images
|
| 66 |
-
12. **Meta** - Status and timestamp validation
|
| 67 |
-
13. **Catalogue** - Main model with comprehensive cross-field validation
|
| 68 |
-
|
| 69 |
-
### Request Schemas
|
| 70 |
-
1. **CatalogueListFilter** - Standard list endpoint with projection support
|
| 71 |
-
2. **CatalogueDetailsRequest** - Details endpoint with projection
|
| 72 |
-
3. **CatalogueLazyFetchFilter** - Performance-optimized lazy loading
|
| 73 |
-
4. **MerchantCatalogueListFilter** - Hybrid MongoDB + PostgreSQL queries
|
| 74 |
-
|
| 75 |
-
## Benefits
|
| 76 |
-
|
| 77 |
-
### Performance
|
| 78 |
-
- **50-90% payload reduction** with projection lists
|
| 79 |
-
- **Optimized queries** with proper filtering validation
|
| 80 |
-
- **Reduced bandwidth** usage
|
| 81 |
-
|
| 82 |
-
### Data Quality
|
| 83 |
-
- **Consistent data formats** across all catalogue items
|
| 84 |
-
- **Validated business rules** prevent invalid data entry
|
| 85 |
-
- **Standardized codes** (SKU, HSN, catalogue codes)
|
| 86 |
-
- **Flexible structure** with optional attributes and media sections
|
| 87 |
-
|
| 88 |
-
### Security
|
| 89 |
-
- **HTTPS-only URLs** for all media and documents
|
| 90 |
-
- **Input validation** prevents injection attacks
|
| 91 |
-
- **Field length limits** prevent buffer overflow
|
| 92 |
-
|
| 93 |
-
### Developer Experience
|
| 94 |
-
- **Clear error messages** for validation failures
|
| 95 |
-
- **Comprehensive examples** in schema documentation
|
| 96 |
-
- **Type safety** with Pydantic models
|
| 97 |
-
|
| 98 |
-
## API Endpoint Compliance
|
| 99 |
-
|
| 100 |
-
All catalogue list endpoints now follow the mandatory API standards:
|
| 101 |
-
|
| 102 |
-
```python
|
| 103 |
-
# POST /catalogue/list
|
| 104 |
-
{
|
| 105 |
-
"filters": {"catalogue_type": "Product", "brand": "L'Oréal"},
|
| 106 |
-
"skip": 0,
|
| 107 |
-
"limit": 50,
|
| 108 |
-
"projection_list": ["catalogue_id", "catalogue_name", "pricing.mrp"]
|
| 109 |
-
}
|
| 110 |
-
```
|
| 111 |
-
|
| 112 |
-
## Migration Notes
|
| 113 |
-
|
| 114 |
-
- **Backward Compatibility**: Legacy fields maintained for smooth migration
|
| 115 |
-
- **Gradual Adoption**: New validation can be enabled incrementally
|
| 116 |
-
- **Data Cleanup**: Existing data should be validated against new rules
|
| 117 |
-
|
| 118 |
-
## Testing Recommendations
|
| 119 |
-
|
| 120 |
-
1. **Unit Tests**: Validate each field constraint and cross-field validation
|
| 121 |
-
2. **Integration Tests**: Test projection list functionality
|
| 122 |
-
3. **Performance Tests**: Measure query performance with projections
|
| 123 |
-
4. **Data Migration Tests**: Validate existing data against new schema
|
| 124 |
-
|
| 125 |
-
This update brings the catalogue schema in line with industry best practices for API design, data validation, and performance optimization.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/CRITICAL_FIX_TRAILING_NEWLINE.md
DELETED
|
@@ -1,119 +0,0 @@
|
|
| 1 |
-
# 🎯 CRITICAL FIX: Trailing Newline in Database Name
|
| 2 |
-
|
| 3 |
-
## Issue Identified
|
| 4 |
-
|
| 5 |
-
Your deployment environment variable `DB_NAME` (or `POSTGRES_DB`) has a **trailing newline character**:
|
| 6 |
-
|
| 7 |
-
```
|
| 8 |
-
database "cuatrolabs\n" does not exist
|
| 9 |
-
^^
|
| 10 |
-
```
|
| 11 |
-
|
| 12 |
-
This is why the connection was failing!
|
| 13 |
-
|
| 14 |
-
## Root Cause
|
| 15 |
-
|
| 16 |
-
Environment variables in your deployment platform likely have trailing whitespace or newlines. This commonly happens when:
|
| 17 |
-
- Copy-pasting values with extra whitespace
|
| 18 |
-
- Using multi-line input fields
|
| 19 |
-
- Programmatically setting variables with `\n` included
|
| 20 |
-
|
| 21 |
-
## Fix Applied
|
| 22 |
-
|
| 23 |
-
Added `.strip()` to all PostgreSQL environment variables in `app/core/config.py`:
|
| 24 |
-
|
| 25 |
-
```python
|
| 26 |
-
# Before (BROKEN)
|
| 27 |
-
POSTGRES_DB: str = os.getenv("POSTGRES_DB") or os.getenv("DB_NAME") or "cuatrolabs"
|
| 28 |
-
|
| 29 |
-
# After (FIXED)
|
| 30 |
-
POSTGRES_DB: str = (os.getenv("POSTGRES_DB") or os.getenv("DB_NAME") or "cuatrolabs").strip()
|
| 31 |
-
```
|
| 32 |
-
|
| 33 |
-
This removes:
|
| 34 |
-
- Leading/trailing spaces
|
| 35 |
-
- Newline characters (`\n`)
|
| 36 |
-
- Carriage returns (`\r`)
|
| 37 |
-
- Tabs (`\t`)
|
| 38 |
-
|
| 39 |
-
## All Variables Cleaned
|
| 40 |
-
|
| 41 |
-
✅ `POSTGRES_HOST` / `DB_HOST`
|
| 42 |
-
✅ `POSTGRES_PORT` / `DB_PORT`
|
| 43 |
-
✅ `POSTGRES_DB` / `DB_NAME` ← **This was the problem!**
|
| 44 |
-
✅ `POSTGRES_USER` / `DB_USER`
|
| 45 |
-
✅ `POSTGRES_PASSWORD` / `DB_PASSWORD`
|
| 46 |
-
✅ `POSTGRES_SSL_MODE` / `DB_SSLMODE`
|
| 47 |
-
✅ `POSTGRES_URI`
|
| 48 |
-
|
| 49 |
-
## What Will Happen Now
|
| 50 |
-
|
| 51 |
-
### Before (Failed)
|
| 52 |
-
```
|
| 53 |
-
database "cuatrolabs\n" does not exist
|
| 54 |
-
```
|
| 55 |
-
|
| 56 |
-
### After (Success)
|
| 57 |
-
```
|
| 58 |
-
[POSTGRES] ✅ Connection successful after 1 attempt(s)
|
| 59 |
-
```
|
| 60 |
-
|
| 61 |
-
## Action Required
|
| 62 |
-
|
| 63 |
-
1. **Redeploy** your application with the updated code
|
| 64 |
-
2. The `.strip()` will automatically clean the variables
|
| 65 |
-
3. Connection should succeed immediately
|
| 66 |
-
|
| 67 |
-
## Optional: Clean Your Environment Variables
|
| 68 |
-
|
| 69 |
-
While `.strip()` fixes the issue, you should also clean your deployment environment variables:
|
| 70 |
-
|
| 71 |
-
### Check These Variables
|
| 72 |
-
|
| 73 |
-
In your deployment platform, verify these don't have trailing spaces/newlines:
|
| 74 |
-
- `DB_NAME` → Should be exactly: `cuatrolabs` (no extra characters)
|
| 75 |
-
- `DB_HOST` → Should be exactly: `ep-sweet-surf-a1qeduoy.ap-southeast-1.aws.neon.tech`
|
| 76 |
-
- `DB_USER` → Should be exactly: `trans_owner`
|
| 77 |
-
- `DB_PORT` → Should be exactly: `5432`
|
| 78 |
-
|
| 79 |
-
### How to Check
|
| 80 |
-
|
| 81 |
-
In your deployment platform's environment variable editor:
|
| 82 |
-
1. Click on each variable
|
| 83 |
-
2. Look for any trailing spaces or newlines
|
| 84 |
-
3. Delete them if present
|
| 85 |
-
4. Save
|
| 86 |
-
|
| 87 |
-
## Testing
|
| 88 |
-
|
| 89 |
-
The fix is already applied. When you redeploy, you should see:
|
| 90 |
-
|
| 91 |
-
```
|
| 92 |
-
[CONFIG] Built POSTGRES_URI from components
|
| 93 |
-
[CONFIG] Protocol: postgresql+asyncpg
|
| 94 |
-
[CONFIG] User: trans_owner
|
| 95 |
-
[CONFIG] Host: ep-sweet-surf-a1qeduoy.ap-southeast-1.aws.neon.tech
|
| 96 |
-
[CONFIG] Port: 5432
|
| 97 |
-
[CONFIG] Database: cuatrolabs ← No more \n!
|
| 98 |
-
[CONFIG] Password: SET
|
| 99 |
-
[CONFIG] SSL Mode: require
|
| 100 |
-
|
| 101 |
-
[POSTGRES] Attempting to connect (max retries: 30)...
|
| 102 |
-
[POSTGRES] ✅ Connection successful after 1 attempt(s)
|
| 103 |
-
```
|
| 104 |
-
|
| 105 |
-
## Why This Wasn't Caught Earlier
|
| 106 |
-
|
| 107 |
-
- Local `.env` file doesn't have trailing newlines
|
| 108 |
-
- Tests passed locally
|
| 109 |
-
- Only appeared in deployment environment
|
| 110 |
-
- Error message showed the invisible `\n` character
|
| 111 |
-
|
| 112 |
-
## Summary
|
| 113 |
-
|
| 114 |
-
✅ **Problem**: `DB_NAME` had trailing newline (`"cuatrolabs\n"`)
|
| 115 |
-
✅ **Solution**: Added `.strip()` to all environment variables
|
| 116 |
-
✅ **Status**: Fixed and ready to deploy
|
| 117 |
-
✅ **Next Step**: Redeploy and verify connection success
|
| 118 |
-
|
| 119 |
-
The connection will now work correctly! 🎉
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/EMPLOYEE_ENDPOINTS_IMPLEMENTATION_SUMMARY.md
DELETED
|
@@ -1,341 +0,0 @@
|
|
| 1 |
-
# Employee API Endpoints - Implementation Summary
|
| 2 |
-
|
| 3 |
-
## Overview
|
| 4 |
-
|
| 5 |
-
Successfully implemented **33 comprehensive employee management endpoints** covering the complete employee lifecycle from onboarding to offboarding.
|
| 6 |
-
|
| 7 |
-
## Implementation Status: ✅ COMPLETE
|
| 8 |
-
|
| 9 |
-
All requested endpoints have been implemented and verified.
|
| 10 |
-
|
| 11 |
-
---
|
| 12 |
-
|
| 13 |
-
## Endpoints by Category
|
| 14 |
-
|
| 15 |
-
### ✅ Core CRUD (6 endpoints)
|
| 16 |
-
- `POST /employees` - Create employee
|
| 17 |
-
- `POST /employees/list` - List employees with projection support
|
| 18 |
-
- `GET /employees/{user_id}` - Get employee by ID
|
| 19 |
-
- `GET /employees/code/{employee_code}` - Get employee by code
|
| 20 |
-
- `PUT /employees/{user_id}` - Update employee
|
| 21 |
-
- `DELETE /employees/{user_id}` - Soft delete employee
|
| 22 |
-
|
| 23 |
-
### ✅ Onboarding (1 endpoint)
|
| 24 |
-
- `POST /employees/{user_id}/onboarding/start` - Start onboarding process
|
| 25 |
-
|
| 26 |
-
### ✅ Roles & Hierarchy (4 endpoints)
|
| 27 |
-
- `PUT /employees/{user_id}/roles` - Update employee roles
|
| 28 |
-
- `PUT /employees/{user_id}/manager` - Update employee manager
|
| 29 |
-
- `GET /employees/{user_id}/reports` - Get direct reports
|
| 30 |
-
- `GET /employees/{user_id}/hierarchy` - Get management chain
|
| 31 |
-
|
| 32 |
-
### ✅ Mobile & Location (3 endpoints)
|
| 33 |
-
- `PUT /employees/{user_id}/app-access` - Update app access settings
|
| 34 |
-
- `PUT /employees/{user_id}/location` - Update location settings
|
| 35 |
-
- `PATCH /employees/{user_id}/location-consent` - Update location consent (legacy)
|
| 36 |
-
|
| 37 |
-
### ✅ System Access (3 endpoints)
|
| 38 |
-
- `PUT /employees/{user_id}/system-access/enable` - Enable system access
|
| 39 |
-
- `PUT /employees/{user_id}/system-access/disable` - Disable system access
|
| 40 |
-
- `GET /employees/{user_id}/system-access/status` - Get access status
|
| 41 |
-
|
| 42 |
-
### ✅ Documents & Compliance (4 endpoints)
|
| 43 |
-
- `POST /employees/{user_id}/documents` - Add document
|
| 44 |
-
- `GET /employees/{user_id}/documents` - Get all documents
|
| 45 |
-
- `DELETE /employees/{user_id}/documents/{doc_type}` - Delete document
|
| 46 |
-
- `POST /employees/{user_id}/documents/verify` - Verify document
|
| 47 |
-
|
| 48 |
-
### ✅ Security & Devices (3 endpoints)
|
| 49 |
-
- `GET /employees/{user_id}/devices` - List bound devices
|
| 50 |
-
- `POST /employees/{user_id}/devices/block` - Block device
|
| 51 |
-
- `POST /employees/{user_id}/sessions/logout-all` - Logout all sessions
|
| 52 |
-
|
| 53 |
-
### ✅ Status & Offboarding (4 endpoints)
|
| 54 |
-
- `PATCH /employees/{user_id}/status` - Update status
|
| 55 |
-
- `POST /employees/{user_id}/suspend` - Suspend employee
|
| 56 |
-
- `POST /employees/{user_id}/terminate` - Terminate employee
|
| 57 |
-
- `POST /employees/{user_id}/offboarding/complete` - Complete offboarding
|
| 58 |
-
|
| 59 |
-
### ✅ Self-Service (2 endpoints)
|
| 60 |
-
- `GET /employees/me` - Get my profile
|
| 61 |
-
- `GET /employees/me/team` - Get my team
|
| 62 |
-
|
| 63 |
-
### 🚧 Audit (2 endpoints - Placeholders)
|
| 64 |
-
- `GET /employees/{user_id}/audit-logs` - Get audit logs
|
| 65 |
-
- `GET /employees/{user_id}/audit-logs/export` - Export audit logs
|
| 66 |
-
|
| 67 |
-
### ✅ Dashboard (1 endpoint)
|
| 68 |
-
- `GET /employees/info/widgets` - Get dashboard widgets
|
| 69 |
-
|
| 70 |
-
---
|
| 71 |
-
|
| 72 |
-
## Key Features Implemented
|
| 73 |
-
|
| 74 |
-
### 1. Comprehensive Validation
|
| 75 |
-
- Employee code uniqueness
|
| 76 |
-
- Email/phone uniqueness among active employees
|
| 77 |
-
- Manager hierarchy rules enforcement
|
| 78 |
-
- Age requirements (minimum 18 years)
|
| 79 |
-
- 2FA enforcement for Admin/Finance/HR roles
|
| 80 |
-
- Location tracking consent requirements
|
| 81 |
-
|
| 82 |
-
### 2. Audit Trail
|
| 83 |
-
- All mutation endpoints require `x-user-id` header
|
| 84 |
-
- Tracks who made changes and when
|
| 85 |
-
- Metadata fields for suspension/termination reasons
|
| 86 |
-
|
| 87 |
-
### 3. Soft Delete Pattern
|
| 88 |
-
- Employees are never hard-deleted
|
| 89 |
-
- Status set to 'terminated' instead
|
| 90 |
-
- Prevents deletion of employees with active reports
|
| 91 |
-
|
| 92 |
-
### 4. Projection Support
|
| 93 |
-
- `/employees/list` endpoint supports field projection
|
| 94 |
-
- Reduces payload size by 50-90%
|
| 95 |
-
- Follows API standards for all microservices
|
| 96 |
-
|
| 97 |
-
### 5. Self-Service Capabilities
|
| 98 |
-
- Employees can view their own profile
|
| 99 |
-
- Managers can view their team
|
| 100 |
-
- Supports mobile app integration
|
| 101 |
-
|
| 102 |
-
### 6. Security Features
|
| 103 |
-
- Device binding and blocking
|
| 104 |
-
- Session management (logout all)
|
| 105 |
-
- 2FA enforcement for sensitive roles
|
| 106 |
-
- System access enable/disable
|
| 107 |
-
|
| 108 |
-
### 7. Document Management
|
| 109 |
-
- Support for multiple document types (PAN, Aadhaar, etc.)
|
| 110 |
-
- Document verification workflow
|
| 111 |
-
- HTTPS URL validation for document storage
|
| 112 |
-
|
| 113 |
-
### 8. Location Tracking Compliance
|
| 114 |
-
- Explicit consent tracking with timestamp
|
| 115 |
-
- IP address and device tracking for consent
|
| 116 |
-
- Background tracking opt-in
|
| 117 |
-
- Geofencing support
|
| 118 |
-
- Configurable retention periods
|
| 119 |
-
|
| 120 |
-
---
|
| 121 |
-
|
| 122 |
-
## Business Rules Enforced
|
| 123 |
-
|
| 124 |
-
### Manager Hierarchy
|
| 125 |
-
- ASM → RSM
|
| 126 |
-
- BDE → ASM or RSM
|
| 127 |
-
- Trainer → ASM, RSM, or Head_Trainer
|
| 128 |
-
- Field_Sales → ASM, RSM, or BDE
|
| 129 |
-
|
| 130 |
-
### Status Transitions
|
| 131 |
-
- onboarding → active (activation)
|
| 132 |
-
- active → inactive (temporary leave)
|
| 133 |
-
- active → suspended (disciplinary)
|
| 134 |
-
- active/inactive/suspended → terminated (termination)
|
| 135 |
-
|
| 136 |
-
### Required Fields by Role
|
| 137 |
-
- RSM/ASM: Must have region assigned
|
| 138 |
-
- ASM/BDE/Trainer/Field_Sales: Must have manager
|
| 139 |
-
- Admin/Finance/HR: Must have 2FA enabled
|
| 140 |
-
|
| 141 |
-
### Location Tracking
|
| 142 |
-
- Requires mobile app access
|
| 143 |
-
- Background tracking requires location consent
|
| 144 |
-
- Consent timestamp automatically recorded
|
| 145 |
-
|
| 146 |
-
---
|
| 147 |
-
|
| 148 |
-
## API Standards Compliance
|
| 149 |
-
|
| 150 |
-
✅ **Projection List Support**
|
| 151 |
-
- Implemented on `/employees/list` endpoint
|
| 152 |
-
- Uses MongoDB projection for performance
|
| 153 |
-
- Returns raw dict when projection used
|
| 154 |
-
|
| 155 |
-
✅ **POST Method for List Endpoints**
|
| 156 |
-
- `/employees/list` uses POST method
|
| 157 |
-
- Supports complex filter criteria in request body
|
| 158 |
-
|
| 159 |
-
✅ **Consistent Error Handling**
|
| 160 |
-
- 400 for validation errors
|
| 161 |
-
- 404 for not found
|
| 162 |
-
- 500 for server errors
|
| 163 |
-
|
| 164 |
-
✅ **Audit Trail**
|
| 165 |
-
- `x-user-id` header on all mutation endpoints
|
| 166 |
-
- Tracks created_by, updated_by, created_at, updated_at
|
| 167 |
-
|
| 168 |
-
✅ **Soft Delete Pattern**
|
| 169 |
-
- DELETE endpoint sets status to terminated
|
| 170 |
-
- Prevents data loss
|
| 171 |
-
- Maintains referential integrity
|
| 172 |
-
|
| 173 |
-
---
|
| 174 |
-
|
| 175 |
-
## File Changes
|
| 176 |
-
|
| 177 |
-
### Modified Files
|
| 178 |
-
1. `cuatrolabs-scm-ms/app/employees/controllers/router.py`
|
| 179 |
-
- Added 20 new endpoint functions
|
| 180 |
-
- Added imports for LocationSettingsSchema, IDDocumentSchema, AppAccessSchema
|
| 181 |
-
- Organized endpoints by category with clear section headers
|
| 182 |
-
|
| 183 |
-
### New Files
|
| 184 |
-
1. `cuatrolabs-scm-ms/EMPLOYEE_API_ENDPOINTS.md`
|
| 185 |
-
- Complete API reference documentation
|
| 186 |
-
- Request/response examples
|
| 187 |
-
- Business rules and validations
|
| 188 |
-
|
| 189 |
-
2. `cuatrolabs-scm-ms/EMPLOYEE_ENDPOINTS_IMPLEMENTATION_SUMMARY.md`
|
| 190 |
-
- This file - implementation summary
|
| 191 |
-
|
| 192 |
-
3. `cuatrolabs-scm-ms/test_employee_endpoints.py`
|
| 193 |
-
- Verification script to check all endpoints are registered
|
| 194 |
-
- Categorizes endpoints by function
|
| 195 |
-
- Validates expected endpoints exist
|
| 196 |
-
|
| 197 |
-
---
|
| 198 |
-
|
| 199 |
-
## Testing Results
|
| 200 |
-
|
| 201 |
-
```
|
| 202 |
-
✅ All 33 endpoints successfully registered
|
| 203 |
-
✅ No syntax errors
|
| 204 |
-
✅ No import errors
|
| 205 |
-
✅ Proper categorization
|
| 206 |
-
✅ Consistent naming conventions
|
| 207 |
-
```
|
| 208 |
-
|
| 209 |
-
---
|
| 210 |
-
|
| 211 |
-
## Next Steps & Recommendations
|
| 212 |
-
|
| 213 |
-
### Immediate
|
| 214 |
-
1. ✅ All core endpoints implemented
|
| 215 |
-
2. ✅ Validation rules enforced
|
| 216 |
-
3. ✅ Audit trail in place
|
| 217 |
-
|
| 218 |
-
### Short Term
|
| 219 |
-
1. 🚧 Implement actual audit log collection
|
| 220 |
-
- Create separate audit_logs collection
|
| 221 |
-
- Track all employee changes
|
| 222 |
-
- Support filtering and export
|
| 223 |
-
|
| 224 |
-
2. 🚧 Integrate session management with auth service
|
| 225 |
-
- Implement token invalidation
|
| 226 |
-
- Support logout-all functionality
|
| 227 |
-
|
| 228 |
-
3. 📝 Add comprehensive unit tests
|
| 229 |
-
- Test all validation rules
|
| 230 |
-
- Test manager hierarchy enforcement
|
| 231 |
-
- Test status transitions
|
| 232 |
-
|
| 233 |
-
### Medium Term
|
| 234 |
-
1. 📝 Add rate limiting for sensitive operations
|
| 235 |
-
- Suspend/terminate endpoints
|
| 236 |
-
- Document verification
|
| 237 |
-
- Device blocking
|
| 238 |
-
|
| 239 |
-
2. 📝 Implement webhook notifications
|
| 240 |
-
- Status changes
|
| 241 |
-
- Document verification
|
| 242 |
-
- Offboarding completion
|
| 243 |
-
|
| 244 |
-
3. 📝 Add bulk operations support
|
| 245 |
-
- Bulk employee creation
|
| 246 |
-
- Bulk status updates
|
| 247 |
-
- Bulk role assignments
|
| 248 |
-
|
| 249 |
-
### Long Term
|
| 250 |
-
1. 📝 Advanced analytics endpoints
|
| 251 |
-
- Employee turnover metrics
|
| 252 |
-
- Onboarding completion rates
|
| 253 |
-
- Team performance metrics
|
| 254 |
-
|
| 255 |
-
2. 📝 Integration with external systems
|
| 256 |
-
- HRMS integration
|
| 257 |
-
- Payroll integration
|
| 258 |
-
- Background verification services
|
| 259 |
-
|
| 260 |
-
---
|
| 261 |
-
|
| 262 |
-
## Usage Examples
|
| 263 |
-
|
| 264 |
-
### Create Employee
|
| 265 |
-
```bash
|
| 266 |
-
curl -X POST http://localhost:8000/employees \
|
| 267 |
-
-H "Content-Type: application/json" \
|
| 268 |
-
-H "x-user-id: admin_001" \
|
| 269 |
-
-d '{
|
| 270 |
-
"employee_code": "EMP-MUM-001",
|
| 271 |
-
"first_name": "Rajesh",
|
| 272 |
-
"last_name": "Kumar",
|
| 273 |
-
"email": "rajesh.kumar@company.com",
|
| 274 |
-
"phone": "+919876543210",
|
| 275 |
-
"designation": "ASM",
|
| 276 |
-
"manager_id": "usr_RSM_001",
|
| 277 |
-
"base_city": "Mumbai",
|
| 278 |
-
"base_state": "Maharashtra",
|
| 279 |
-
"region": "Western",
|
| 280 |
-
"doj": "2023-01-10",
|
| 281 |
-
"emergency_contact": {
|
| 282 |
-
"name": "Priya Kumar",
|
| 283 |
-
"relation": "Spouse",
|
| 284 |
-
"phone": "+919876543211"
|
| 285 |
-
},
|
| 286 |
-
"created_by": "admin_001"
|
| 287 |
-
}'
|
| 288 |
-
```
|
| 289 |
-
|
| 290 |
-
### List Employees with Projection
|
| 291 |
-
```bash
|
| 292 |
-
curl -X POST http://localhost:8000/employees/list \
|
| 293 |
-
-H "Content-Type: application/json" \
|
| 294 |
-
-d '{
|
| 295 |
-
"designation": "ASM",
|
| 296 |
-
"status": "active",
|
| 297 |
-
"region": "Western",
|
| 298 |
-
"skip": 0,
|
| 299 |
-
"limit": 100,
|
| 300 |
-
"projection_list": ["user_id", "employee_code", "first_name", "email"]
|
| 301 |
-
}'
|
| 302 |
-
```
|
| 303 |
-
|
| 304 |
-
### Update Employee Roles
|
| 305 |
-
```bash
|
| 306 |
-
curl -X PUT http://localhost:8000/employees/usr_123/roles \
|
| 307 |
-
-H "Content-Type: application/json" \
|
| 308 |
-
-H "x-user-id: admin_001" \
|
| 309 |
-
-d '{
|
| 310 |
-
"roles": ["field_sales", "order_create", "merchant_view"]
|
| 311 |
-
}'
|
| 312 |
-
```
|
| 313 |
-
|
| 314 |
-
### Suspend Employee
|
| 315 |
-
```bash
|
| 316 |
-
curl -X POST http://localhost:8000/employees/usr_123/suspend \
|
| 317 |
-
-H "x-user-id: admin_001" \
|
| 318 |
-
-d "reason=Policy violation"
|
| 319 |
-
```
|
| 320 |
-
|
| 321 |
-
### Get My Team
|
| 322 |
-
```bash
|
| 323 |
-
curl -X GET http://localhost:8000/employees/me/team \
|
| 324 |
-
-H "x-user-id: usr_manager_001"
|
| 325 |
-
```
|
| 326 |
-
|
| 327 |
-
---
|
| 328 |
-
|
| 329 |
-
## Conclusion
|
| 330 |
-
|
| 331 |
-
All requested employee API endpoints have been successfully implemented with:
|
| 332 |
-
- ✅ 33 total endpoints covering complete employee lifecycle
|
| 333 |
-
- ✅ Comprehensive validation and business rules
|
| 334 |
-
- ✅ Audit trail and compliance features
|
| 335 |
-
- ✅ API standards compliance (projection support, POST for lists)
|
| 336 |
-
- ✅ Security features (device management, session control)
|
| 337 |
-
- ✅ Self-service capabilities
|
| 338 |
-
- ✅ Document management and verification
|
| 339 |
-
- ✅ Location tracking with consent management
|
| 340 |
-
|
| 341 |
-
The implementation is production-ready with clear documentation and follows established patterns from other modules in the SCM microservice.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/EMPLOYEE_SYNC_INTEGRATION_SUMMARY.md
DELETED
|
@@ -1,204 +0,0 @@
|
|
| 1 |
-
# Employee Sync Integration Summary
|
| 2 |
-
|
| 3 |
-
## Task 11: Integrate employee sync triggers into API endpoints
|
| 4 |
-
|
| 5 |
-
### Implementation Completed ✅
|
| 6 |
-
|
| 7 |
-
This document summarizes the implementation of employee sync triggers in the SCM microservice API endpoints.
|
| 8 |
-
|
| 9 |
-
## Changes Made
|
| 10 |
-
|
| 11 |
-
### 1. Main Application (app/main.py)
|
| 12 |
-
|
| 13 |
-
#### Added Employee Sync Service Import
|
| 14 |
-
```python
|
| 15 |
-
from app.sync.employees.service import EmployeeSyncService
|
| 16 |
-
```
|
| 17 |
-
|
| 18 |
-
#### Added Global Service Instance
|
| 19 |
-
```python
|
| 20 |
-
employee_sync_service: EmployeeSyncService = None
|
| 21 |
-
```
|
| 22 |
-
|
| 23 |
-
#### Initialized Service on Startup
|
| 24 |
-
- Added employee sync service initialization in `startup_event()`
|
| 25 |
-
- Configured with same settings as merchant and catalogue sync services
|
| 26 |
-
- Started background workers for async processing
|
| 27 |
-
- Added graceful error handling if PostgreSQL is unavailable
|
| 28 |
-
|
| 29 |
-
#### Added Shutdown Handler
|
| 30 |
-
- Added employee sync worker shutdown in `shutdown_event()`
|
| 31 |
-
- Ensures graceful cleanup of background tasks
|
| 32 |
-
|
| 33 |
-
#### Added Helper Function
|
| 34 |
-
```python
|
| 35 |
-
def get_employee_sync_service() -> EmployeeSyncService:
|
| 36 |
-
"""Get the employee sync service instance."""
|
| 37 |
-
return employee_sync_service
|
| 38 |
-
```
|
| 39 |
-
|
| 40 |
-
### 2. Employee Router (app/employees/controllers/router.py)
|
| 41 |
-
|
| 42 |
-
#### Added Sync Trigger Function
|
| 43 |
-
```python
|
| 44 |
-
def _trigger_employee_sync(employee_id: str, operation: str = "update") -> None:
|
| 45 |
-
"""
|
| 46 |
-
Trigger employee sync to PostgreSQL (fire and forget).
|
| 47 |
-
|
| 48 |
-
This is a non-blocking operation that queues the employee for sync.
|
| 49 |
-
Any errors are logged but do not affect the API response.
|
| 50 |
-
"""
|
| 51 |
-
```
|
| 52 |
-
|
| 53 |
-
Features:
|
| 54 |
-
- Non-blocking (fire and forget) operation
|
| 55 |
-
- Uses asyncio.create_task for async execution
|
| 56 |
-
- Handles missing service gracefully
|
| 57 |
-
- Logs errors without affecting API response
|
| 58 |
-
- Prevents circular dependency with lazy import
|
| 59 |
-
|
| 60 |
-
#### Integrated Sync into POST /employees
|
| 61 |
-
- Added sync trigger after successful employee creation
|
| 62 |
-
- Passes `operation="create"` parameter
|
| 63 |
-
- Uses `result.user_id` as employee identifier
|
| 64 |
-
|
| 65 |
-
#### Integrated Sync into PUT /employees/{user_id}
|
| 66 |
-
- Added sync trigger after successful employee update
|
| 67 |
-
- Passes `operation="update"` parameter
|
| 68 |
-
- Uses `user_id` parameter as employee identifier
|
| 69 |
-
|
| 70 |
-
### 3. Integration Tests (tests/test_employee_sync_integration.py)
|
| 71 |
-
|
| 72 |
-
Created comprehensive test suite with 6 tests:
|
| 73 |
-
|
| 74 |
-
1. **test_employee_sync_service_initialized**
|
| 75 |
-
- Verifies service is accessible via helper function
|
| 76 |
-
- Handles case where PostgreSQL is unavailable
|
| 77 |
-
|
| 78 |
-
2. **test_create_employee_triggers_sync**
|
| 79 |
-
- Verifies POST endpoint triggers sync
|
| 80 |
-
- Confirms operation="create" is passed
|
| 81 |
-
- Validates correct employee_id is used
|
| 82 |
-
|
| 83 |
-
3. **test_update_employee_triggers_sync**
|
| 84 |
-
- Verifies PUT endpoint triggers sync
|
| 85 |
-
- Confirms operation="update" is passed
|
| 86 |
-
- Validates correct employee_id is used
|
| 87 |
-
|
| 88 |
-
4. **test_sync_is_non_blocking**
|
| 89 |
-
- Verifies sync returns immediately
|
| 90 |
-
- Confirms fire-and-forget pattern
|
| 91 |
-
- Ensures API is not blocked by slow sync
|
| 92 |
-
|
| 93 |
-
5. **test_sync_error_does_not_affect_api**
|
| 94 |
-
- Verifies sync errors are caught
|
| 95 |
-
- Confirms API continues to work
|
| 96 |
-
- Validates error isolation
|
| 97 |
-
|
| 98 |
-
6. **test_sync_when_service_not_available**
|
| 99 |
-
- Verifies graceful handling when service is None
|
| 100 |
-
- Confirms no exceptions are raised
|
| 101 |
-
- Validates fallback behavior
|
| 102 |
-
|
| 103 |
-
**All tests passed successfully! ✅**
|
| 104 |
-
|
| 105 |
-
## Requirements Validation
|
| 106 |
-
|
| 107 |
-
### Requirement 4.7: POST /employees triggers sync ✅
|
| 108 |
-
- Implemented in `create_employee()` endpoint
|
| 109 |
-
- Triggers sync after successful creation
|
| 110 |
-
- Non-blocking operation
|
| 111 |
-
- Error handling prevents API failures
|
| 112 |
-
|
| 113 |
-
### Requirement 4.8: PUT /employees/{user_id} triggers sync ✅
|
| 114 |
-
- Implemented in `update_employee()` endpoint
|
| 115 |
-
- Triggers sync after successful update
|
| 116 |
-
- Non-blocking operation
|
| 117 |
-
- Error handling prevents API failures
|
| 118 |
-
|
| 119 |
-
### Requirement 12.1: Async execution ✅
|
| 120 |
-
- Uses `asyncio.create_task()` for fire-and-forget
|
| 121 |
-
- Does not await sync completion
|
| 122 |
-
- Returns immediately to client
|
| 123 |
-
|
| 124 |
-
### Requirement 12.2: Non-blocking API response ✅
|
| 125 |
-
- Sync triggered after MongoDB operation completes
|
| 126 |
-
- API returns success without waiting for sync
|
| 127 |
-
- Verified by test_sync_is_non_blocking
|
| 128 |
-
|
| 129 |
-
### Additional Requirements Met
|
| 130 |
-
|
| 131 |
-
- **Error Isolation**: Sync errors do not affect API (try/except in trigger function)
|
| 132 |
-
- **Service Availability**: Gracefully handles missing PostgreSQL/sync service
|
| 133 |
-
- **Logging**: All sync operations and errors are logged
|
| 134 |
-
- **Consistency**: Follows same pattern as merchant and catalogue sync
|
| 135 |
-
- **Testing**: Comprehensive integration test coverage
|
| 136 |
-
|
| 137 |
-
## Architecture
|
| 138 |
-
|
| 139 |
-
```
|
| 140 |
-
API Request → Employee Service → MongoDB
|
| 141 |
-
↓
|
| 142 |
-
API Response (immediate)
|
| 143 |
-
↓
|
| 144 |
-
_trigger_employee_sync() (fire & forget)
|
| 145 |
-
↓
|
| 146 |
-
EmployeeSyncService.sync_employee()
|
| 147 |
-
↓
|
| 148 |
-
Async Queue
|
| 149 |
-
↓
|
| 150 |
-
Background Workers (5 workers)
|
| 151 |
-
↓
|
| 152 |
-
PostgreSQL
|
| 153 |
-
```
|
| 154 |
-
|
| 155 |
-
## Configuration
|
| 156 |
-
|
| 157 |
-
The employee sync service uses the same configuration as other sync services:
|
| 158 |
-
|
| 159 |
-
- `SYNC_QUEUE_MAX_SIZE`: Maximum queue size (default: 1000)
|
| 160 |
-
- `SYNC_WORKER_COUNT`: Number of background workers (default: 5)
|
| 161 |
-
- `SYNC_RETRY_MAX_ATTEMPTS`: Maximum retry attempts (default: 3)
|
| 162 |
-
- `SYNC_QUEUE_WARNING_THRESHOLD`: Warning threshold (default: 500)
|
| 163 |
-
- `SYNC_QUEUE_CRITICAL_THRESHOLD`: Critical threshold (default: 800)
|
| 164 |
-
|
| 165 |
-
## Verification
|
| 166 |
-
|
| 167 |
-
### Code Quality
|
| 168 |
-
- ✅ No diagnostic errors in main.py
|
| 169 |
-
- ✅ No diagnostic errors in router.py
|
| 170 |
-
- ✅ Follows existing patterns (merchant/catalogue sync)
|
| 171 |
-
- ✅ Proper error handling
|
| 172 |
-
- ✅ Comprehensive logging
|
| 173 |
-
|
| 174 |
-
### Testing
|
| 175 |
-
- ✅ 6/6 integration tests passing
|
| 176 |
-
- ✅ Service initialization tested
|
| 177 |
-
- ✅ Create endpoint sync tested
|
| 178 |
-
- ✅ Update endpoint sync tested
|
| 179 |
-
- ✅ Non-blocking behavior tested
|
| 180 |
-
- ✅ Error handling tested
|
| 181 |
-
- ✅ Service unavailability tested
|
| 182 |
-
|
| 183 |
-
### Requirements
|
| 184 |
-
- ✅ Requirement 4.7 (POST sync trigger)
|
| 185 |
-
- ✅ Requirement 4.8 (PUT sync trigger)
|
| 186 |
-
- ✅ Requirement 12.1 (Async execution)
|
| 187 |
-
- ✅ Requirement 12.2 (Non-blocking)
|
| 188 |
-
|
| 189 |
-
## Next Steps
|
| 190 |
-
|
| 191 |
-
The employee sync integration is complete and ready for use. The next tasks in the implementation plan are:
|
| 192 |
-
|
| 193 |
-
- Task 12: Implement error handling and retry logic (already implemented in sync service)
|
| 194 |
-
- Task 13-15: Implement bulk sync operations
|
| 195 |
-
- Task 16: Implement monitoring and alerting
|
| 196 |
-
- Task 17: Add configuration management
|
| 197 |
-
|
| 198 |
-
## Notes
|
| 199 |
-
|
| 200 |
-
- The implementation follows the exact same pattern as merchant and catalogue sync
|
| 201 |
-
- All sync operations are logged for monitoring and debugging
|
| 202 |
-
- The system gracefully handles PostgreSQL unavailability
|
| 203 |
-
- Background workers process sync queue asynchronously
|
| 204 |
-
- Retry logic with exponential backoff is already implemented in the sync service
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/FINAL_CONFIG_SUMMARY.md
DELETED
|
@@ -1,137 +0,0 @@
|
|
| 1 |
-
# PostgreSQL Connection - Final Configuration Summary
|
| 2 |
-
|
| 3 |
-
## ✅ Configuration Updated to Match Working TMS Pattern
|
| 4 |
-
|
| 5 |
-
Your `app/core/config.py` has been updated to **exactly match** the working pattern from `insightfy-bloom-ms-tms/settings.py`.
|
| 6 |
-
|
| 7 |
-
## Key Changes
|
| 8 |
-
|
| 9 |
-
### 1. Connection String Formation (Exact TMS Pattern)
|
| 10 |
-
|
| 11 |
-
```python
|
| 12 |
-
# Check if all required components are present (TMS pattern)
|
| 13 |
-
if all([POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_HOST, POSTGRES_DB]):
|
| 14 |
-
protocol = os.getenv("DB_PROTOCOL", "postgresql+asyncpg")
|
| 15 |
-
|
| 16 |
-
# Build URI with URL-encoded password
|
| 17 |
-
POSTGRES_URI = f"{protocol}://{POSTGRES_USER}:{quote_plus(POSTGRES_PASSWORD)}@{POSTGRES_HOST}:{POSTGRES_PORT}/{POSTGRES_DB}"
|
| 18 |
-
else:
|
| 19 |
-
POSTGRES_URI = None
|
| 20 |
-
# Raise error with helpful diagnostics
|
| 21 |
-
```
|
| 22 |
-
|
| 23 |
-
### 2. Dual Variable Support
|
| 24 |
-
|
| 25 |
-
Supports both naming conventions:
|
| 26 |
-
- `POSTGRES_*` variables (primary)
|
| 27 |
-
- `DB_*` variables (fallback)
|
| 28 |
-
|
| 29 |
-
```python
|
| 30 |
-
POSTGRES_HOST = os.getenv("POSTGRES_HOST") or os.getenv("DB_HOST") or "localhost"
|
| 31 |
-
POSTGRES_USER = os.getenv("POSTGRES_USER") or os.getenv("DB_USER") or "postgres"
|
| 32 |
-
# ... etc
|
| 33 |
-
```
|
| 34 |
-
|
| 35 |
-
### 3. URL Encoding
|
| 36 |
-
|
| 37 |
-
Uses `quote_plus()` for password encoding (critical for special characters):
|
| 38 |
-
```python
|
| 39 |
-
quote_plus(POSTGRES_PASSWORD)
|
| 40 |
-
```
|
| 41 |
-
|
| 42 |
-
## What Will Happen in Deployment
|
| 43 |
-
|
| 44 |
-
### Scenario 1: Using POSTGRES_URI (Local .env)
|
| 45 |
-
```
|
| 46 |
-
[CONFIG] Using provided POSTGRES_URI
|
| 47 |
-
```
|
| 48 |
-
|
| 49 |
-
### Scenario 2: Using DB_* Variables (Deployment)
|
| 50 |
-
```
|
| 51 |
-
[CONFIG] Built POSTGRES_URI from components
|
| 52 |
-
[CONFIG] Protocol: postgresql+asyncpg
|
| 53 |
-
[CONFIG] User: trans_owner
|
| 54 |
-
[CONFIG] Host: ep-sweet-surf-a1qeduoy.ap-southeast-1.aws.neon.tech
|
| 55 |
-
[CONFIG] Port: 5432
|
| 56 |
-
[CONFIG] Database: cuatrolabs
|
| 57 |
-
[CONFIG] Password: SET
|
| 58 |
-
[CONFIG] SSL Mode: require
|
| 59 |
-
```
|
| 60 |
-
|
| 61 |
-
Then connection attempt:
|
| 62 |
-
```
|
| 63 |
-
======================================================================
|
| 64 |
-
[POSTGRES] Starting Database Connection
|
| 65 |
-
======================================================================
|
| 66 |
-
[POSTGRES] Connection String: postgresql+asyncpg://trans_owner:***@ep-sweet-surf-a1qeduoy...
|
| 67 |
-
[POSTGRES] Host: ep-sweet-surf-a1qeduoy.ap-southeast-1.aws.neon.tech
|
| 68 |
-
[POSTGRES] Port: 5432
|
| 69 |
-
[POSTGRES] Database: cuatrolabs
|
| 70 |
-
[POSTGRES] SSL Mode: require
|
| 71 |
-
======================================================================
|
| 72 |
-
|
| 73 |
-
[POSTGRES] Attempting to connect (max retries: 30)...
|
| 74 |
-
[POSTGRES] ✅ Connection successful after 1 attempt(s)
|
| 75 |
-
```
|
| 76 |
-
|
| 77 |
-
## Deployment Environment Variables
|
| 78 |
-
|
| 79 |
-
Your deployment needs these variables set:
|
| 80 |
-
|
| 81 |
-
**Option 1: Single URI (Recommended)**
|
| 82 |
-
```bash
|
| 83 |
-
POSTGRES_URI=postgresql+asyncpg://trans_owner:BookMyService7@ep-sweet-surf-a1qeduoy.ap-southeast-1.aws.neon.tech:5432/cuatrolabs
|
| 84 |
-
```
|
| 85 |
-
|
| 86 |
-
**Option 2: Individual Components (Current)**
|
| 87 |
-
```bash
|
| 88 |
-
DB_PROTOCOL=postgresql+asyncpg
|
| 89 |
-
DB_USER=trans_owner
|
| 90 |
-
DB_PASSWORD=BookMyService7
|
| 91 |
-
DB_HOST=ep-sweet-surf-a1qeduoy.ap-southeast-1.aws.neon.tech
|
| 92 |
-
DB_PORT=5432
|
| 93 |
-
DB_NAME=cuatrolabs
|
| 94 |
-
DB_SSLMODE=require
|
| 95 |
-
```
|
| 96 |
-
|
| 97 |
-
Both options will now work correctly!
|
| 98 |
-
|
| 99 |
-
## Error Handling
|
| 100 |
-
|
| 101 |
-
If variables are missing, you'll see:
|
| 102 |
-
```
|
| 103 |
-
[CONFIG] ERROR: Cannot build POSTGRES_URI - missing required components
|
| 104 |
-
[CONFIG] POSTGRES_USER: MISSING
|
| 105 |
-
[CONFIG] POSTGRES_PASSWORD: SET
|
| 106 |
-
[CONFIG] POSTGRES_HOST: SET
|
| 107 |
-
[CONFIG] POSTGRES_DB: MISSING
|
| 108 |
-
|
| 109 |
-
[CONFIG] Checking alternative env vars:
|
| 110 |
-
[CONFIG] DB_USER: trans_owner
|
| 111 |
-
[CONFIG] DB_PASSWORD: SET
|
| 112 |
-
[CONFIG] DB_HOST: ep-sweet-surf-a1qeduoy.ap-southeast-1.aws.neon.tech
|
| 113 |
-
[CONFIG] DB_NAME: cuatrolabs
|
| 114 |
-
```
|
| 115 |
-
|
| 116 |
-
This makes it immediately clear which variables need to be set.
|
| 117 |
-
|
| 118 |
-
## Next Steps
|
| 119 |
-
|
| 120 |
-
1. **Commit and push** the updated code
|
| 121 |
-
2. **Redeploy** your application
|
| 122 |
-
3. **Check startup logs** for the configuration messages
|
| 123 |
-
4. **Verify connection** success message
|
| 124 |
-
|
| 125 |
-
The configuration now exactly matches your working TMS service and should connect successfully!
|
| 126 |
-
|
| 127 |
-
## Differences from Previous Implementation
|
| 128 |
-
|
| 129 |
-
| Aspect | Before | Now (TMS Pattern) |
|
| 130 |
-
|--------|--------|-------------------|
|
| 131 |
-
| Validation | After building URI | Before building URI with `all()` |
|
| 132 |
-
| Password encoding | Conditional | Always use `quote_plus()` |
|
| 133 |
-
| Error handling | Generic | Detailed with component status |
|
| 134 |
-
| Variable check | Simple if/else | `all([...])` pattern |
|
| 135 |
-
| Protocol support | Hardcoded | From `DB_PROTOCOL` env var |
|
| 136 |
-
|
| 137 |
-
All changes align with the proven working pattern from your TMS service.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/IMPLEMENTATION_SUMMARY.md
DELETED
|
@@ -1,235 +0,0 @@
|
|
| 1 |
-
# SCM Microservice - Complete Implementation Summary
|
| 2 |
-
|
| 3 |
-
## Overview
|
| 4 |
-
Complete end-to-end implementation of Purchase Orders (PO), Goods Received Notes (GRN), and Return Merchandise Authorization (RMA) modules for the Supply Chain Management system.
|
| 5 |
-
|
| 6 |
-
## Implementation Details
|
| 7 |
-
|
| 8 |
-
### 1. Purchase Orders (PO) Module
|
| 9 |
-
|
| 10 |
-
**Files Created:**
|
| 11 |
-
- `app/schemas/purchase_order_schema.py` - Pydantic schemas
|
| 12 |
-
- `app/services/purchase_order_service.py` - Business logic
|
| 13 |
-
- `app/routers/purchase_order_router.py` - API endpoints
|
| 14 |
-
|
| 15 |
-
**Features:**
|
| 16 |
-
- ✅ Complete PO lifecycle: Draft → Submitted → Confirmed → Dispatched → Closed
|
| 17 |
-
- ✅ Merchant hierarchy validation (buyer must be child of supplier)
|
| 18 |
-
- ✅ Actions: Accept, Partial Accept, Reject, Cancel
|
| 19 |
-
- ✅ Financial calculations with GST breakdown (CGST/SGST/IGST)
|
| 20 |
-
- ✅ Auto-generated PO numbers with merchant prefix
|
| 21 |
-
- ✅ Item-level tracking with quantities and pricing
|
| 22 |
-
- ✅ Payment terms and delivery dates
|
| 23 |
-
- ✅ Audit trail (created_by, timestamps, approval tracking)
|
| 24 |
-
|
| 25 |
-
**API Endpoints:**
|
| 26 |
-
- `POST /purchase-orders` - Create PO
|
| 27 |
-
- `GET /purchase-orders/{po_id}` - Get PO
|
| 28 |
-
- `PUT /purchase-orders/{po_id}` - Update PO
|
| 29 |
-
- `POST /purchase-orders/{po_id}/submit` - Submit for approval
|
| 30 |
-
- `POST /purchase-orders/{po_id}/action` - Accept/Reject/Cancel
|
| 31 |
-
- `GET /purchase-orders` - List with filters
|
| 32 |
-
- `DELETE /purchase-orders/{po_id}` - Cancel PO
|
| 33 |
-
|
| 34 |
-
**Business Rules:**
|
| 35 |
-
- Validates merchant hierarchy (to_merchant must be parent of from_merchant)
|
| 36 |
-
- Supplier must be active
|
| 37 |
-
- Only draft/submitted POs can be updated
|
| 38 |
-
- Partial acceptance allows quantity modifications
|
| 39 |
-
- Automatic totals calculation on item changes
|
| 40 |
-
|
| 41 |
-
### 2. Goods Received Note (GRN) Module
|
| 42 |
-
|
| 43 |
-
**Files Created:**
|
| 44 |
-
- `app/schemas/grn_schema.py` - Pydantic schemas
|
| 45 |
-
- `app/services/grn_service.py` - Business logic
|
| 46 |
-
- `app/routers/grn_router.py` - API endpoints
|
| 47 |
-
|
| 48 |
-
**Features:**
|
| 49 |
-
- ✅ Receipt tracking for purchase orders
|
| 50 |
-
- ✅ Automatic discrepancy detection (expected vs received)
|
| 51 |
-
- ✅ Item condition tracking (good, damaged, defective, expired)
|
| 52 |
-
- ✅ Serial/batch number scanning and validation
|
| 53 |
-
- ✅ Photo evidence attachment for discrepancies
|
| 54 |
-
- ✅ Automatic inventory ledger updates
|
| 55 |
-
- ✅ Carrier and shipment tracking
|
| 56 |
-
- ✅ Resolution workflow for discrepancies
|
| 57 |
-
|
| 58 |
-
**API Endpoints:**
|
| 59 |
-
- `POST /grn` - Create GRN
|
| 60 |
-
- `GET /grn/{grn_id}` - Get GRN
|
| 61 |
-
- `PUT /grn/{grn_id}` - Update GRN
|
| 62 |
-
- `POST /grn/{grn_id}/resolve` - Resolve discrepancies
|
| 63 |
-
- `GET /grn` - List with filters
|
| 64 |
-
|
| 65 |
-
**Business Rules:**
|
| 66 |
-
- Validates PO exists and is in correct status (confirmed/partial/dispatched)
|
| 67 |
-
- Automatically calculates discrepancies
|
| 68 |
-
- Updates inventory ledger for accepted items only
|
| 69 |
-
- Closes PO when fully received
|
| 70 |
-
- Supports partial receipts with multiple GRNs per PO
|
| 71 |
-
- Quarantines damaged/defective items
|
| 72 |
-
|
| 73 |
-
### 3. Return Merchandise Authorization (RMA) Module
|
| 74 |
-
|
| 75 |
-
**Files Created:**
|
| 76 |
-
- `app/schemas/rma_schema.py` - Pydantic schemas
|
| 77 |
-
- `app/services/rma_service.py` - Business logic
|
| 78 |
-
- `app/routers/rma_router.py` - API endpoints
|
| 79 |
-
|
| 80 |
-
**Features:**
|
| 81 |
-
- ✅ Complete return workflow: Requested → Approved → Picked → Inspected → Closed
|
| 82 |
-
- ✅ Return reasons (defective, damaged, wrong_item, quality_issue, etc.)
|
| 83 |
-
- ✅ Actions: Refund, Replace, Store Credit, Repair
|
| 84 |
-
- ✅ Pickup scheduling with carrier integration
|
| 85 |
-
- ✅ Inspection workflow with approval/rejection
|
| 86 |
-
- ✅ Credit note generation
|
| 87 |
-
- ✅ Inventory updates for returned items
|
| 88 |
-
- ✅ Serial number validation against original order
|
| 89 |
-
|
| 90 |
-
**API Endpoints:**
|
| 91 |
-
- `POST /rma` - Create RMA
|
| 92 |
-
- `GET /rma/{rma_id}` - Get RMA
|
| 93 |
-
- `PUT /rma/{rma_id}` - Update RMA
|
| 94 |
-
- `POST /rma/{rma_id}/approve` - Approve/Reject
|
| 95 |
-
- `POST /rma/{rma_id}/pickup` - Schedule pickup
|
| 96 |
-
- `POST /rma/{rma_id}/inspect` - Perform inspection
|
| 97 |
-
- `GET /rma` - List with filters
|
| 98 |
-
- `DELETE /rma/{rma_id}` - Cancel RMA
|
| 99 |
-
|
| 100 |
-
**Business Rules:**
|
| 101 |
-
- Validates items are from the original order
|
| 102 |
-
- Enforces return window policies
|
| 103 |
-
- Supports partial approvals
|
| 104 |
-
- Validates serial numbers against inventory
|
| 105 |
-
- Updates inventory ledger on inspection approval
|
| 106 |
-
- Closes RMA after refund/replacement processing
|
| 107 |
-
|
| 108 |
-
### 4. Database Collections
|
| 109 |
-
|
| 110 |
-
**New Collections Added:**
|
| 111 |
-
- `scm_purchase_orders` - Purchase orders
|
| 112 |
-
- `scm_grn` - Goods received notes
|
| 113 |
-
- `scm_rma` - Return merchandise authorizations
|
| 114 |
-
- `scm_inventory_ledger` - Inventory transactions
|
| 115 |
-
- `scm_qr_scans` - QR/serial scan logs
|
| 116 |
-
- `scm_shipments` - Shipment tracking
|
| 117 |
-
- `scm_invoices` - Invoice records
|
| 118 |
-
- `scm_credit_notes` - Credit notes
|
| 119 |
-
|
| 120 |
-
### 5. Integration Points
|
| 121 |
-
|
| 122 |
-
**Existing Integrations:**
|
| 123 |
-
- Merchant hierarchy validation
|
| 124 |
-
- Sales order linkage for RMA
|
| 125 |
-
- Employee tracking for actions
|
| 126 |
-
|
| 127 |
-
**Future Integrations:**
|
| 128 |
-
- Carrier APIs (DTDC, etc.) for AWB generation and tracking
|
| 129 |
-
- Payment gateway for refunds
|
| 130 |
-
- QR scanning service for serial validation
|
| 131 |
-
- Notification service for status updates
|
| 132 |
-
- Analytics service for reporting
|
| 133 |
-
|
| 134 |
-
### 6. Workflow Example
|
| 135 |
-
|
| 136 |
-
Complete supply chain flow:
|
| 137 |
-
|
| 138 |
-
```
|
| 139 |
-
1. retail creates PO → distributor
|
| 140 |
-
2. distributor accepts PO
|
| 141 |
-
3. distributor dispatches goods
|
| 142 |
-
4. retail receives goods (creates GRN)
|
| 143 |
-
5. GRN shows discrepancies (short-shipped/damaged)
|
| 144 |
-
6. retail resolves discrepancy (accepts with credit note)
|
| 145 |
-
7. retail sells to customer (Sales Order)
|
| 146 |
-
8. Customer requests return (creates RMA)
|
| 147 |
-
9. retail approves RMA
|
| 148 |
-
10. Pickup scheduled
|
| 149 |
-
11. Items inspected
|
| 150 |
-
12. Refund processed, RMA closed
|
| 151 |
-
```
|
| 152 |
-
|
| 153 |
-
See `examples/po_grn_rma_workflow.py` for complete working example.
|
| 154 |
-
|
| 155 |
-
### 7. Key Features Implemented
|
| 156 |
-
|
| 157 |
-
**Validation & Business Logic:**
|
| 158 |
-
- ✅ Merchant hierarchy validation
|
| 159 |
-
- ✅ Status-based workflow enforcement
|
| 160 |
-
- ✅ Quantity and pricing calculations
|
| 161 |
-
- ✅ GST calculations (CGST/SGST/IGST)
|
| 162 |
-
- ✅ Discrepancy detection and tracking
|
| 163 |
-
- ✅ Serial/batch number tracking
|
| 164 |
-
- ✅ Idempotency support
|
| 165 |
-
|
| 166 |
-
**Audit & Traceability:**
|
| 167 |
-
- ✅ Complete audit trail (created_by, updated_by, timestamps)
|
| 168 |
-
- ✅ Status history tracking
|
| 169 |
-
- ✅ Action logging (approvals, rejections, resolutions)
|
| 170 |
-
- ✅ Serial number traceability
|
| 171 |
-
- ✅ Photo evidence for discrepancies
|
| 172 |
-
|
| 173 |
-
**Inventory Management:**
|
| 174 |
-
- ✅ Automatic inventory ledger updates
|
| 175 |
-
- ✅ Batch and serial tracking
|
| 176 |
-
- ✅ Condition-based inventory (good/damaged/defective)
|
| 177 |
-
- ✅ Return inventory processing
|
| 178 |
-
|
| 179 |
-
### 8. Testing
|
| 180 |
-
|
| 181 |
-
**Test Files:**
|
| 182 |
-
- `examples/quick_start.py` - Merchant hierarchy setup
|
| 183 |
-
- `examples/po_grn_rma_workflow.py` - Complete workflow test
|
| 184 |
-
|
| 185 |
-
**To Test:**
|
| 186 |
-
```bash
|
| 187 |
-
# Start server
|
| 188 |
-
uvicorn app.main:app --reload --port 9292
|
| 189 |
-
|
| 190 |
-
# Run workflow test
|
| 191 |
-
python3 examples/po_grn_rma_workflow.py
|
| 192 |
-
```
|
| 193 |
-
|
| 194 |
-
### 9. API Documentation
|
| 195 |
-
|
| 196 |
-
Once server is running, access interactive documentation:
|
| 197 |
-
- Swagger UI: http://localhost:9292/docs
|
| 198 |
-
- ReDoc: http://localhost:9292/redoc
|
| 199 |
-
|
| 200 |
-
### 10. Production Readiness Checklist
|
| 201 |
-
|
| 202 |
-
**Completed:**
|
| 203 |
-
- ✅ Pydantic v2 schemas with validation
|
| 204 |
-
- ✅ Async database operations
|
| 205 |
-
- ✅ Error handling and logging
|
| 206 |
-
- ✅ Status-based workflow enforcement
|
| 207 |
-
- ✅ Business rule validation
|
| 208 |
-
- ✅ Audit trail tracking
|
| 209 |
-
|
| 210 |
-
**Recommended Enhancements:**
|
| 211 |
-
- [ ] Add authentication/authorization middleware
|
| 212 |
-
- [ ] Implement rate limiting
|
| 213 |
-
- [ ] Add caching for frequently accessed data
|
| 214 |
-
- [ ] Implement event bus for inter-service communication
|
| 215 |
-
- [ ] Add comprehensive unit and integration tests
|
| 216 |
-
- [ ] Implement carrier API integrations
|
| 217 |
-
- [ ] Add QR scanning service integration
|
| 218 |
-
- [ ] Implement notification service
|
| 219 |
-
- [ ] Add analytics and reporting endpoints
|
| 220 |
-
- [ ] Implement file upload for attachments
|
| 221 |
-
- [ ] Add webhook support for external systems
|
| 222 |
-
|
| 223 |
-
## Summary
|
| 224 |
-
|
| 225 |
-
Successfully implemented complete Purchase Order, GRN, and RMA modules with:
|
| 226 |
-
- **3 new modules** (PO, GRN, RMA)
|
| 227 |
-
- **9 new schemas** with comprehensive validation
|
| 228 |
-
- **3 new services** with business logic
|
| 229 |
-
- **3 new routers** with 20+ API endpoints
|
| 230 |
-
- **8 new database collections**
|
| 231 |
-
- **Complete workflow** from purchase to returns
|
| 232 |
-
- **Full audit trail** and traceability
|
| 233 |
-
- **Production-ready** code with error handling
|
| 234 |
-
|
| 235 |
-
All modules follow the specification requirements for the Company → ncnf → cnf → distributor → retail hierarchy with proper validation, tracking, and integration points.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/INVENTORY_CONTROL_API_IMPLEMENTATION.md
DELETED
|
@@ -1,174 +0,0 @@
|
|
| 1 |
-
# Inventory Control API Implementation Summary
|
| 2 |
-
|
| 3 |
-
## 📦 Overview
|
| 4 |
-
|
| 5 |
-
This document summarizes the implementation of Stock Take & Stock Adjustment APIs that fully comply with the provided API specification. The implementation follows the orchestration-only pattern, delegating actual inventory mutations to existing stored procedures.
|
| 6 |
-
|
| 7 |
-
## ✅ Implementation Status
|
| 8 |
-
|
| 9 |
-
### Stock Take APIs - **COMPLETE**
|
| 10 |
-
|
| 11 |
-
| Endpoint | Method | Status | Description |
|
| 12 |
-
|----------|--------|--------|-------------|
|
| 13 |
-
| `/inventory/stock-take` | POST | ✅ | Create stock takes (bulk entries) |
|
| 14 |
-
| `/inventory/stock-take/list` | POST | ✅ | List with projection support |
|
| 15 |
-
| `/inventory/stock-take/{id}` | GET | ✅ | Get stock take details |
|
| 16 |
-
| `/inventory/stock-take/{id}/apply` | POST | ✅ | Apply variance to inventory |
|
| 17 |
-
|
| 18 |
-
### Stock Adjustment APIs - **COMPLETE**
|
| 19 |
-
|
| 20 |
-
| Endpoint | Method | Status | Description |
|
| 21 |
-
|----------|--------|--------|-------------|
|
| 22 |
-
| `/inventory/adjustments` | POST | ✅ | Create adjustments (bulk entries) |
|
| 23 |
-
| `/inventory/adjustments/list` | POST | ✅ | List with projection support |
|
| 24 |
-
| `/inventory/adjustments/{id}` | GET | ✅ | Get adjustment details |
|
| 25 |
-
| `/inventory/adjustments/{id}/approve` | POST | ✅ | Approve adjustment |
|
| 26 |
-
| `/inventory/adjustments/{id}/reject` | POST | ✅ | Reject adjustment |
|
| 27 |
-
|
| 28 |
-
## 🔧 Key Features Implemented
|
| 29 |
-
|
| 30 |
-
### 1. Bulk Operations Support
|
| 31 |
-
- **Stock Take**: Multiple SKUs per request via `entries[]` array
|
| 32 |
-
- **Stock Adjustment**: Multiple SKUs per request via `entries[]` array
|
| 33 |
-
- Automatic system quantity lookup from stock snapshot
|
| 34 |
-
- Variance calculation (physical - system)
|
| 35 |
-
|
| 36 |
-
### 2. Projection List Support (API Standard Compliance)
|
| 37 |
-
- All list endpoints support `projection_list` parameter
|
| 38 |
-
- 50-90% payload reduction possible
|
| 39 |
-
- Raw dict return when projection used, full model otherwise
|
| 40 |
-
- Follows MongoDB-style projection pattern
|
| 41 |
-
|
| 42 |
-
### 3. Status Flow Management
|
| 43 |
-
- **Stock Take**: RECORDED → APPLIED (immutable)
|
| 44 |
-
- **Stock Adjustment**: PENDING → APPROVED/REJECTED → APPLIED (immutable)
|
| 45 |
-
- Proper validation of status transitions
|
| 46 |
-
|
| 47 |
-
### 4. Orchestration-Only Pattern
|
| 48 |
-
- ❌ No direct writes to stock tables
|
| 49 |
-
- ❌ No direct writes to ledger tables
|
| 50 |
-
- ✅ Calls existing stored procedures for inventory mutations
|
| 51 |
-
- ✅ API layer handles workflow orchestration only
|
| 52 |
-
|
| 53 |
-
## 📊 Database Tables
|
| 54 |
-
|
| 55 |
-
### Tables Written To (Orchestration)
|
| 56 |
-
- `scm_stock_take` - Stock take records
|
| 57 |
-
- `scm_stock_adjustment` - Adjustment records
|
| 58 |
-
|
| 59 |
-
### Tables Updated Via Stored Procedures
|
| 60 |
-
- `scm_stock_ledger` - Immutable transaction log
|
| 61 |
-
- `scm_stock` - Derived stock snapshot
|
| 62 |
-
|
| 63 |
-
## 🚀 Request/Response Examples
|
| 64 |
-
|
| 65 |
-
### Create Stock Take (Bulk)
|
| 66 |
-
```json
|
| 67 |
-
POST /inventory/stock-take
|
| 68 |
-
{
|
| 69 |
-
"warehouse_id": "warehouse_123",
|
| 70 |
-
"entries": [
|
| 71 |
-
{
|
| 72 |
-
"sku": "SHMP-500-ALOE",
|
| 73 |
-
"batch_no": "BATCH-20240101",
|
| 74 |
-
"physical_qty": 95,
|
| 75 |
-
"remarks": "Shelf count"
|
| 76 |
-
}
|
| 77 |
-
]
|
| 78 |
-
}
|
| 79 |
-
```
|
| 80 |
-
|
| 81 |
-
### Create Stock Adjustment (Bulk)
|
| 82 |
-
```json
|
| 83 |
-
POST /inventory/adjustments
|
| 84 |
-
{
|
| 85 |
-
"warehouse_id": "warehouse_123",
|
| 86 |
-
"entries": [
|
| 87 |
-
{
|
| 88 |
-
"sku": "SHMP-500-ALOE",
|
| 89 |
-
"batch_no": "BATCH-20240101",
|
| 90 |
-
"adjustment_type": "DAMAGE",
|
| 91 |
-
"qty": 5,
|
| 92 |
-
"reason": "Broken bottles"
|
| 93 |
-
}
|
| 94 |
-
]
|
| 95 |
-
}
|
| 96 |
-
```
|
| 97 |
-
|
| 98 |
-
### List with Projection
|
| 99 |
-
```json
|
| 100 |
-
POST /inventory/stock-take/list
|
| 101 |
-
{
|
| 102 |
-
"filters": {
|
| 103 |
-
"warehouse_id": "warehouse_123",
|
| 104 |
-
"status": "recorded"
|
| 105 |
-
},
|
| 106 |
-
"projection_list": ["stock_take_id", "sku", "variance_qty", "status"]
|
| 107 |
-
}
|
| 108 |
-
```
|
| 109 |
-
|
| 110 |
-
## 🔄 Integration Points
|
| 111 |
-
|
| 112 |
-
### Existing Stored Procedures
|
| 113 |
-
- Stock ledger procedures are called during:
|
| 114 |
-
- Stock Take: `POST /{id}/apply`
|
| 115 |
-
- Stock Adjustment: `POST /{id}/approve`
|
| 116 |
-
- Procedures handle:
|
| 117 |
-
- Ledger entry creation
|
| 118 |
-
- Stock snapshot updates
|
| 119 |
-
- Transaction atomicity
|
| 120 |
-
|
| 121 |
-
### Legacy Support
|
| 122 |
-
- Single-entry schemas maintained for backward compatibility
|
| 123 |
-
- `CreateStockTakeRequestSingle`
|
| 124 |
-
- `CreateStockAdjustmentRequestSingle`
|
| 125 |
-
|
| 126 |
-
## 📁 File Structure
|
| 127 |
-
|
| 128 |
-
```
|
| 129 |
-
app/inventory/
|
| 130 |
-
├── stock_take/
|
| 131 |
-
│ ├── controllers/router.py # API endpoints
|
| 132 |
-
│ ├── services/service.py # Business logic
|
| 133 |
-
│ ├── schemas/schema.py # Request/response models
|
| 134 |
-
│ └── models/model.py # DB model imports
|
| 135 |
-
├── adjustments/
|
| 136 |
-
│ ├── controllers/router.py # API endpoints
|
| 137 |
-
│ ├── services/service.py # Business logic
|
| 138 |
-
│ ├── schemas/schema.py # Request/response models
|
| 139 |
-
│ └── models/model.py # DB model imports & enums
|
| 140 |
-
└── models/inventory_model.py # PostgreSQL table definitions
|
| 141 |
-
```
|
| 142 |
-
|
| 143 |
-
## 🎯 Compliance Checklist
|
| 144 |
-
|
| 145 |
-
- ✅ **POST Method**: All list endpoints use POST
|
| 146 |
-
- ✅ **Projection Support**: Optional `projection_list` parameter
|
| 147 |
-
- ✅ **Bulk Operations**: Multiple entries per request
|
| 148 |
-
- ✅ **Status Flows**: Proper lifecycle management
|
| 149 |
-
- ✅ **Orchestration Only**: No direct DB mutations
|
| 150 |
-
- ✅ **Stored Procedure Integration**: Existing procedures called
|
| 151 |
-
- ✅ **Error Handling**: Comprehensive validation & error responses
|
| 152 |
-
- ✅ **Logging**: Structured logging throughout
|
| 153 |
-
- ✅ **Type Safety**: Full Pydantic model validation
|
| 154 |
-
|
| 155 |
-
## 🧪 Testing
|
| 156 |
-
|
| 157 |
-
Run the validation script:
|
| 158 |
-
```bash
|
| 159 |
-
cd cuatrolabs-scm-ms
|
| 160 |
-
python3 test_inventory_apis.py
|
| 161 |
-
```
|
| 162 |
-
|
| 163 |
-
## 🚀 Next Steps
|
| 164 |
-
|
| 165 |
-
1. **Integration Testing**: Test with actual stored procedures
|
| 166 |
-
2. **Authentication**: Add user context from auth middleware
|
| 167 |
-
3. **Performance Testing**: Validate projection performance gains
|
| 168 |
-
4. **Documentation**: Update OpenAPI specs
|
| 169 |
-
5. **Monitoring**: Add metrics for inventory operations
|
| 170 |
-
|
| 171 |
-
---
|
| 172 |
-
|
| 173 |
-
**Implementation Complete** ✨
|
| 174 |
-
All APIs match the provided specification and are ready for integration testing.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/INVENTORY_CONTROL_IMPLEMENTATION.md
DELETED
|
@@ -1,259 +0,0 @@
|
|
| 1 |
-
# Inventory Control APIs Implementation - PostgreSQL
|
| 2 |
-
|
| 3 |
-
## Overview
|
| 4 |
-
|
| 5 |
-
Successfully implemented Stock Adjustment and Stock Take APIs for the SCM system using **PostgreSQL** following the exact specifications. The implementation maintains strict adherence to ledger integrity and auditability requirements, consistent with the purchase orders and receipts pattern.
|
| 6 |
-
|
| 7 |
-
## 🏗️ Architecture
|
| 8 |
-
|
| 9 |
-
### Core Principles Implemented
|
| 10 |
-
- **Immutable Ledger**: `scm_stock_ledger` table is append-only, single source of truth
|
| 11 |
-
- **Derived Snapshots**: `scm_stock` table is calculated from ledger, never directly edited
|
| 12 |
-
- **Approval Workflow**: Adjustments above threshold require approval before application
|
| 13 |
-
- **Audit Trail**: Complete tracking of all inventory movements with PostgreSQL ACID compliance
|
| 14 |
-
|
| 15 |
-
### PostgreSQL Tables
|
| 16 |
-
- `scm_stock_adjustment` - Stock adjustment records with UUID primary keys
|
| 17 |
-
- `scm_stock_take` - Physical count records with variance calculations
|
| 18 |
-
- `scm_stock_ledger` - Immutable transaction log with foreign key relationships
|
| 19 |
-
- `scm_stock` - Derived stock snapshots with constraints and triggers
|
| 20 |
-
|
| 21 |
-
## 📦 Modules Created
|
| 22 |
-
|
| 23 |
-
### 1. Stock Adjustments (`app/inventory/adjustments/`)
|
| 24 |
-
```
|
| 25 |
-
adjustments/
|
| 26 |
-
├── models/model.py # StockAdjustmentModel, enums
|
| 27 |
-
├── schemas/schema.py # Request/response schemas with projection support
|
| 28 |
-
├── services/service.py # Business logic and database operations
|
| 29 |
-
└── controllers/router.py # FastAPI endpoints
|
| 30 |
-
```
|
| 31 |
-
|
| 32 |
-
### 2. Stock Take (`app/inventory/stock_take/`)
|
| 33 |
-
```
|
| 34 |
-
stock_take/
|
| 35 |
-
├── models/model.py # StockTakeModel, enums
|
| 36 |
-
├── services/service.py # Business logic and database operations
|
| 37 |
-
└── controllers/router.py # FastAPI endpoints
|
| 38 |
-
```
|
| 39 |
-
|
| 40 |
-
### 3. Ledger Models (`app/inventory/ledger/models/`)
|
| 41 |
-
```
|
| 42 |
-
ledger/models/
|
| 43 |
-
└── model.py # StockLedgerModel, StockSnapshotModel
|
| 44 |
-
```
|
| 45 |
-
|
| 46 |
-
## 🔌 API Endpoints
|
| 47 |
-
|
| 48 |
-
### Stock Adjustments
|
| 49 |
-
- `POST /inventory/adjustments/` - Create adjustment
|
| 50 |
-
- `POST /inventory/adjustments/{id}/approve` - Approve pending adjustment
|
| 51 |
-
- `GET /inventory/adjustments/{id}` - Get adjustment details
|
| 52 |
-
- `POST /inventory/adjustments/list` - List with projection support
|
| 53 |
-
|
| 54 |
-
### Stock Take
|
| 55 |
-
- `POST /inventory/stock-take/` - Record physical count
|
| 56 |
-
- `POST /inventory/stock-take/{id}/apply` - Apply variance
|
| 57 |
-
- `GET /inventory/stock-take/{id}` - Get stock take details
|
| 58 |
-
- `POST /inventory/stock-take/list` - List with projection support
|
| 59 |
-
|
| 60 |
-
## 🔄 Data Flow Implementation
|
| 61 |
-
|
| 62 |
-
### Stock Adjustment Flow
|
| 63 |
-
1. **Create** → Validates stock availability for OUT adjustments
|
| 64 |
-
2. **Approval** → Required if qty > threshold (10 units)
|
| 65 |
-
3. **Apply** → Creates ledger entry + updates stock snapshot
|
| 66 |
-
4. **Complete** → Marks adjustment as applied
|
| 67 |
-
|
| 68 |
-
### Stock Take Flow
|
| 69 |
-
1. **Record** → Saves physical count, calculates variance
|
| 70 |
-
2. **Apply** → Creates internal adjustment for variance
|
| 71 |
-
3. **Process** → Follows adjustment approval workflow
|
| 72 |
-
4. **Complete** → Updates inventory via ledger
|
| 73 |
-
|
| 74 |
-
## 🛡️ Business Rules Enforced
|
| 75 |
-
|
| 76 |
-
### PostgreSQL Constraints
|
| 77 |
-
- `CHECK` constraints ensure positive quantities
|
| 78 |
-
- `FOREIGN KEY` relationships maintain referential integrity
|
| 79 |
-
- `UNIQUE` constraints prevent duplicate entries
|
| 80 |
-
- `NOT NULL` constraints enforce required fields
|
| 81 |
-
|
| 82 |
-
### Validation Rules
|
| 83 |
-
- Cannot adjust more than `qty_on_hand` (validated in service layer)
|
| 84 |
-
- Expired batches cannot be adjusted IN
|
| 85 |
-
- Batch required for batch-managed SKUs
|
| 86 |
-
- Physical qty must be >= 0 (enforced by CHECK constraint)
|
| 87 |
-
- Cannot apply stock take twice (status validation)
|
| 88 |
-
|
| 89 |
-
### Approval Workflow
|
| 90 |
-
- Adjustments > 10 units require approval
|
| 91 |
-
- Auto-approval for smaller adjustments
|
| 92 |
-
- Role-based access control implemented
|
| 93 |
-
- PostgreSQL transactions ensure atomicity
|
| 94 |
-
|
| 95 |
-
### Ledger Integrity
|
| 96 |
-
- All entries are immutable (append-only table design)
|
| 97 |
-
- Every adjustment generates ledger entry with UUID references
|
| 98 |
-
- Stock snapshots derived from ledger via SQL operations
|
| 99 |
-
- Complete audit trail maintained with PostgreSQL durability
|
| 100 |
-
|
| 101 |
-
## 📊 Projection List Support
|
| 102 |
-
|
| 103 |
-
Both list endpoints implement the mandatory projection list standard with **PostgreSQL-optimized queries**:
|
| 104 |
-
|
| 105 |
-
```python
|
| 106 |
-
# Example request with projection
|
| 107 |
-
{
|
| 108 |
-
"filters": {"merchant_id": "merchant_123", "status": "pending"},
|
| 109 |
-
"skip": 0,
|
| 110 |
-
"limit": 50,
|
| 111 |
-
"projection_list": ["adjustment_id", "sku", "qty", "status", "created_at"]
|
| 112 |
-
}
|
| 113 |
-
```
|
| 114 |
-
|
| 115 |
-
**PostgreSQL Implementation:**
|
| 116 |
-
- Uses SQLAlchemy `select()` with specific column selection
|
| 117 |
-
- Leverages PostgreSQL query optimization
|
| 118 |
-
- Maintains consistent API contract (raw dict vs full model)
|
| 119 |
-
- Supports complex filtering with `WHERE` clauses
|
| 120 |
-
|
| 121 |
-
Benefits:
|
| 122 |
-
- 50-90% payload reduction possible
|
| 123 |
-
- Better performance (PostgreSQL query optimization)
|
| 124 |
-
- Reduced network bandwidth
|
| 125 |
-
- Flexible client-side field selection
|
| 126 |
-
|
| 127 |
-
## 🔐 Access Control
|
| 128 |
-
|
| 129 |
-
### Roles Implemented
|
| 130 |
-
- `role_inventory_user` - Create adjustments/stock takes
|
| 131 |
-
- `role_inventory_approver` - Approve adjustments
|
| 132 |
-
- `role_audit_user` - View-only access
|
| 133 |
-
|
| 134 |
-
### Permissions Matrix
|
| 135 |
-
| Role | Create | Approve | View |
|
| 136 |
-
|------|--------|---------|------|
|
| 137 |
-
| inventory_user | ✅ | ❌ | ✅ |
|
| 138 |
-
| inventory_approver | ✅ | ✅ | ✅ |
|
| 139 |
-
| audit_user | ❌ | ❌ | ✅ |
|
| 140 |
-
|
| 141 |
-
## 🧪 Error Handling
|
| 142 |
-
|
| 143 |
-
### Validation Errors
|
| 144 |
-
```json
|
| 145 |
-
{
|
| 146 |
-
"error": "INVALID_ADJUSTMENT",
|
| 147 |
-
"message": "Adjustment qty exceeds available stock"
|
| 148 |
-
}
|
| 149 |
-
```
|
| 150 |
-
|
| 151 |
-
### Authorization Errors
|
| 152 |
-
```json
|
| 153 |
-
{
|
| 154 |
-
"error": "ACCESS_DENIED",
|
| 155 |
-
"message": "Approval role required"
|
| 156 |
-
}
|
| 157 |
-
```
|
| 158 |
-
|
| 159 |
-
## 📈 Key Features
|
| 160 |
-
|
| 161 |
-
### ✅ Implemented
|
| 162 |
-
- Complete REST APIs with FastAPI
|
| 163 |
-
- Pydantic schemas with validation
|
| 164 |
-
- Service-layer business logic
|
| 165 |
-
- MongoDB integration
|
| 166 |
-
- Ledger posting logic
|
| 167 |
-
- Stock snapshot updates
|
| 168 |
-
- Role-based access control
|
| 169 |
-
- Projection list support
|
| 170 |
-
- Comprehensive error handling
|
| 171 |
-
- Audit trail maintenance
|
| 172 |
-
|
| 173 |
-
### ❌ Explicitly Excluded (Per Spec)
|
| 174 |
-
- Pricing impact calculations
|
| 175 |
-
- Accounting entries
|
| 176 |
-
- Inventory valuation
|
| 177 |
-
- Automatic approvals
|
| 178 |
-
- Direct stock updates
|
| 179 |
-
|
| 180 |
-
## 🚀 Integration
|
| 181 |
-
|
| 182 |
-
### Main App Integration
|
| 183 |
-
- Routers registered in `main.py`
|
| 184 |
-
- Collections added to constants
|
| 185 |
-
- Roles added to access control
|
| 186 |
-
- All imports properly configured
|
| 187 |
-
|
| 188 |
-
### Database Schema
|
| 189 |
-
- **PostgreSQL tables** following PO/GRN pattern
|
| 190 |
-
- **UUID primary keys** for distributed system compatibility
|
| 191 |
-
- **Foreign key relationships** for data integrity
|
| 192 |
-
- **SQLAlchemy ORM** for type safety and migrations
|
| 193 |
-
- **ACID transactions** for consistency
|
| 194 |
-
- **Concurrent operations** with PostgreSQL locking
|
| 195 |
-
|
| 196 |
-
## 📝 Usage Examples
|
| 197 |
-
|
| 198 |
-
### Create Stock Adjustment
|
| 199 |
-
```json
|
| 200 |
-
POST /inventory/adjustments/
|
| 201 |
-
{
|
| 202 |
-
"merchant_id": "merchant_123",
|
| 203 |
-
"location_id": "location_456",
|
| 204 |
-
"sku": "SKU001",
|
| 205 |
-
"batch_no": "BATCH001",
|
| 206 |
-
"adj_type": "damage",
|
| 207 |
-
"qty": 5,
|
| 208 |
-
"reason": "Damaged during handling",
|
| 209 |
-
"created_by": "user_123"
|
| 210 |
-
}
|
| 211 |
-
```
|
| 212 |
-
|
| 213 |
-
### Record Stock Take
|
| 214 |
-
```json
|
| 215 |
-
POST /inventory/stock-take/
|
| 216 |
-
{
|
| 217 |
-
"merchant_id": "merchant_123",
|
| 218 |
-
"location_id": "location_456",
|
| 219 |
-
"sku": "SKU001",
|
| 220 |
-
"batch_no": "BATCH001",
|
| 221 |
-
"system_qty": 100,
|
| 222 |
-
"physical_qty": 95,
|
| 223 |
-
"created_by": "user_123"
|
| 224 |
-
}
|
| 225 |
-
```
|
| 226 |
-
|
| 227 |
-
## ✅ Validation Status
|
| 228 |
-
|
| 229 |
-
All Python files compile successfully with PostgreSQL implementation:
|
| 230 |
-
- ✅ **PostgreSQL models** compile without errors
|
| 231 |
-
- ✅ **SQLAlchemy schemas** validate correctly
|
| 232 |
-
- ✅ **Services** implement PostgreSQL business logic
|
| 233 |
-
- ✅ **Controllers** expose proper endpoints
|
| 234 |
-
- ✅ **Main app integration** with table creation
|
| 235 |
-
- ✅ **Database migrations** ready for deployment
|
| 236 |
-
|
| 237 |
-
## 🎯 Deliverables Completed
|
| 238 |
-
|
| 239 |
-
- ✅ REST APIs with proper HTTP methods
|
| 240 |
-
- ✅ Pydantic schemas with validation
|
| 241 |
-
- ✅ Service-layer business logic
|
| 242 |
-
- ✅ Ledger posting mechanisms
|
| 243 |
-
- ✅ Stock snapshot updaters
|
| 244 |
-
- ✅ Unit-testable code structure
|
| 245 |
-
- ✅ Role-based access control
|
| 246 |
-
- ✅ Projection list support
|
| 247 |
-
- ✅ Comprehensive error handling
|
| 248 |
-
|
| 249 |
-
## 🔄 Migration Summary
|
| 250 |
-
|
| 251 |
-
**Successfully migrated from MongoDB to PostgreSQL:**
|
| 252 |
-
- ✅ Replaced MongoDB collections with PostgreSQL tables
|
| 253 |
-
- ✅ Updated services to use SQLAlchemy async sessions
|
| 254 |
-
- ✅ Maintained exact same API contracts
|
| 255 |
-
- ✅ Preserved all business logic and validation rules
|
| 256 |
-
- ✅ Enhanced with PostgreSQL constraints and relationships
|
| 257 |
-
- ✅ Follows established PO/GRN PostgreSQL patterns
|
| 258 |
-
|
| 259 |
-
The implementation is **production-ready** and follows all specified requirements for ledger integrity and auditability using **PostgreSQL ACID transactions** and **relational data integrity**.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/INVENTORY_MIGRATION_SUMMARY.md
DELETED
|
@@ -1,190 +0,0 @@
|
|
| 1 |
-
# Inventory Migration Summary
|
| 2 |
-
|
| 3 |
-
## Migration Completed: December 19, 2025
|
| 4 |
-
|
| 5 |
-
### Overview
|
| 6 |
-
Successfully added `inventory` JSONB column to PostgreSQL `trans.catalogue_ref` table and migrated all inventory data from MongoDB.
|
| 7 |
-
|
| 8 |
-
## Database Status
|
| 9 |
-
|
| 10 |
-
### MongoDB
|
| 11 |
-
- **Total Catalogues**: 50
|
| 12 |
-
- **With Inventory Data**: 50 (100%)
|
| 13 |
-
- **Structure**: Multi-level inventory (ncnf, cnf, distributor, retail)
|
| 14 |
-
- **Status**: ✅ Complete
|
| 15 |
-
|
| 16 |
-
### PostgreSQL
|
| 17 |
-
- **Total Catalogues**: 50
|
| 18 |
-
- **With Inventory Data**: 50 (100%)
|
| 19 |
-
- **Column Type**: JSONB
|
| 20 |
-
- **Index**: GIN index on inventory column
|
| 21 |
-
- **Status**: ✅ Complete
|
| 22 |
-
|
| 23 |
-
## Migration Details
|
| 24 |
-
|
| 25 |
-
### Schema Changes
|
| 26 |
-
```sql
|
| 27 |
-
-- Added inventory column
|
| 28 |
-
ALTER TABLE trans.catalogue_ref
|
| 29 |
-
ADD COLUMN inventory JSONB;
|
| 30 |
-
|
| 31 |
-
-- Added GIN index for fast JSON queries
|
| 32 |
-
CREATE INDEX idx_catalogue_ref_inventory
|
| 33 |
-
ON trans.catalogue_ref USING GIN (inventory);
|
| 34 |
-
|
| 35 |
-
-- Added documentation
|
| 36 |
-
COMMENT ON COLUMN trans.catalogue_ref.inventory IS
|
| 37 |
-
'Multi-level inventory configuration with ncnf, cnf, distributor, and retail levels';
|
| 38 |
-
```
|
| 39 |
-
|
| 40 |
-
### Data Structure
|
| 41 |
-
```json
|
| 42 |
-
{
|
| 43 |
-
"unit": "PCS",
|
| 44 |
-
"levels": {
|
| 45 |
-
"ncnf": {
|
| 46 |
-
"reorder_level": 500,
|
| 47 |
-
"reorder_quantity": 1000,
|
| 48 |
-
"safety_stock": 200,
|
| 49 |
-
"lead_time_days": 10,
|
| 50 |
-
"max_stock_level": 5000
|
| 51 |
-
},
|
| 52 |
-
"cnf": {
|
| 53 |
-
"reorder_level": 200,
|
| 54 |
-
"reorder_quantity": 500,
|
| 55 |
-
"safety_stock": 100,
|
| 56 |
-
"lead_time_days": 7,
|
| 57 |
-
"max_stock_level": 2000
|
| 58 |
-
},
|
| 59 |
-
"distributor": {
|
| 60 |
-
"reorder_level": 50,
|
| 61 |
-
"reorder_quantity": 100,
|
| 62 |
-
"safety_stock": 20,
|
| 63 |
-
"lead_time_days": 5,
|
| 64 |
-
"max_stock_level": 500
|
| 65 |
-
},
|
| 66 |
-
"retail": {
|
| 67 |
-
"reorder_level": 10,
|
| 68 |
-
"reorder_quantity": 20,
|
| 69 |
-
"safety_stock": 5,
|
| 70 |
-
"lead_time_days": 3,
|
| 71 |
-
"max_stock_level": 100
|
| 72 |
-
}
|
| 73 |
-
}
|
| 74 |
-
}
|
| 75 |
-
```
|
| 76 |
-
|
| 77 |
-
## JSONB Query Examples
|
| 78 |
-
|
| 79 |
-
### Basic Queries
|
| 80 |
-
```sql
|
| 81 |
-
-- Get unit type
|
| 82 |
-
SELECT catalogue_code, inventory->>'unit' as unit
|
| 83 |
-
FROM trans.catalogue_ref
|
| 84 |
-
WHERE inventory->>'unit' = 'PCS';
|
| 85 |
-
|
| 86 |
-
-- Get retail reorder level
|
| 87 |
-
SELECT catalogue_code,
|
| 88 |
-
inventory->'levels'->'retail'->>'reorder_level' as retail_reorder
|
| 89 |
-
FROM trans.catalogue_ref
|
| 90 |
-
WHERE inventory->'levels'->'retail' IS NOT NULL;
|
| 91 |
-
|
| 92 |
-
-- Filter by inventory level
|
| 93 |
-
SELECT catalogue_code, catalogue_name
|
| 94 |
-
FROM trans.catalogue_ref
|
| 95 |
-
WHERE (inventory->'levels'->'retail'->>'reorder_level')::int > 10;
|
| 96 |
-
```
|
| 97 |
-
|
| 98 |
-
### Complex Queries
|
| 99 |
-
```sql
|
| 100 |
-
-- Get all catalogues with low retail stock levels
|
| 101 |
-
SELECT catalogue_code, catalogue_name,
|
| 102 |
-
inventory->'levels'->'retail'->>'reorder_level' as reorder,
|
| 103 |
-
inventory->'levels'->'retail'->>'max_stock_level' as max_stock
|
| 104 |
-
FROM trans.catalogue_ref
|
| 105 |
-
WHERE (inventory->'levels'->'retail'->>'reorder_level')::int < 15
|
| 106 |
-
AND 'company_cuatro_beauty_ltd' = ANY(merchant_id);
|
| 107 |
-
|
| 108 |
-
-- Check inventory configuration completeness
|
| 109 |
-
SELECT catalogue_code,
|
| 110 |
-
jsonb_object_keys(inventory->'levels') as level_name
|
| 111 |
-
FROM trans.catalogue_ref
|
| 112 |
-
WHERE inventory IS NOT NULL;
|
| 113 |
-
```
|
| 114 |
-
|
| 115 |
-
## Performance Benefits
|
| 116 |
-
|
| 117 |
-
### GIN Index
|
| 118 |
-
- **Fast JSON queries**: O(log n) lookup time
|
| 119 |
-
- **Efficient filtering**: On nested JSON properties
|
| 120 |
-
- **Optimized storage**: JSONB binary format
|
| 121 |
-
|
| 122 |
-
### Query Performance
|
| 123 |
-
- Basic JSON queries: ~1-5ms
|
| 124 |
-
- Complex nested queries: ~5-15ms
|
| 125 |
-
- Full table scans avoided with GIN index
|
| 126 |
-
|
| 127 |
-
## Migration Statistics
|
| 128 |
-
|
| 129 |
-
- **Records Migrated**: 50/50 (100%)
|
| 130 |
-
- **Failed Migrations**: 0
|
| 131 |
-
- **Data Integrity**: ✅ Perfect
|
| 132 |
-
- **Sync Status**: ✅ MongoDB ↔ PostgreSQL
|
| 133 |
-
|
| 134 |
-
## Files Created
|
| 135 |
-
|
| 136 |
-
1. `migration_add_inventory_column.sql` - SQL migration script
|
| 137 |
-
2. `migration_add_inventory_column.py` - Python migration script
|
| 138 |
-
3. `simple_verification.py` - Verification script
|
| 139 |
-
4. `INVENTORY_MIGRATION_SUMMARY.md` - This document
|
| 140 |
-
|
| 141 |
-
## Next Steps
|
| 142 |
-
|
| 143 |
-
### Immediate
|
| 144 |
-
- ✅ Inventory data available in PostgreSQL
|
| 145 |
-
- ✅ Fast JSONB queries enabled
|
| 146 |
-
- ✅ Ready for inventory management features
|
| 147 |
-
|
| 148 |
-
### Future Enhancements
|
| 149 |
-
- Add inventory tracking endpoints
|
| 150 |
-
- Implement stock level alerts
|
| 151 |
-
- Create inventory reports
|
| 152 |
-
- Build reorder automation
|
| 153 |
-
|
| 154 |
-
## Verification Commands
|
| 155 |
-
|
| 156 |
-
```bash
|
| 157 |
-
# Check MongoDB count
|
| 158 |
-
python3 -c "
|
| 159 |
-
import asyncio
|
| 160 |
-
from motor.motor_asyncio import AsyncIOMotorClient
|
| 161 |
-
from dotenv import load_dotenv
|
| 162 |
-
import os
|
| 163 |
-
|
| 164 |
-
async def check():
|
| 165 |
-
load_dotenv()
|
| 166 |
-
client = AsyncIOMotorClient(os.getenv('MONGODB_URI'))
|
| 167 |
-
db = client[os.getenv('MONGODB_DB_NAME', 'cuatrolabs')]
|
| 168 |
-
count = await db.catalogues.count_documents({'merchant_id': 'company_cuatro_beauty_ltd'})
|
| 169 |
-
print(f'MongoDB: {count} catalogues')
|
| 170 |
-
client.close()
|
| 171 |
-
|
| 172 |
-
asyncio.run(check())
|
| 173 |
-
"
|
| 174 |
-
|
| 175 |
-
# Run verification script
|
| 176 |
-
python3 simple_verification.py
|
| 177 |
-
```
|
| 178 |
-
|
| 179 |
-
## Success Criteria
|
| 180 |
-
|
| 181 |
-
- [x] Inventory column added to PostgreSQL
|
| 182 |
-
- [x] GIN index created successfully
|
| 183 |
-
- [x] All 50 records migrated
|
| 184 |
-
- [x] Data integrity verified
|
| 185 |
-
- [x] JSONB queries working
|
| 186 |
-
- [x] MongoDB-PostgreSQL sync maintained
|
| 187 |
-
|
| 188 |
-
## Status: ✅ COMPLETE
|
| 189 |
-
|
| 190 |
-
Migration completed successfully with 100% data integrity and full JSONB query support.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/MERCHANT_API_SUMMARY.md
DELETED
|
@@ -1,135 +0,0 @@
|
|
| 1 |
-
# Merchant API - Complete Endpoint Summary
|
| 2 |
-
|
| 3 |
-
## Base URL: `/api/v1`
|
| 4 |
-
|
| 5 |
-
## ✅ MERCHANT CORE (CRUD + VIEW)
|
| 6 |
-
|
| 7 |
-
| Method | Endpoint | Purpose | Status |
|
| 8 |
-
|--------|----------|---------|--------|
|
| 9 |
-
| POST | `/merchants` | Create merchant (Draft) | ✅ Implemented |
|
| 10 |
-
| GET | `/merchants/{merchant_id}` | View merchant profile | ✅ Implemented |
|
| 11 |
-
| PUT | `/merchants/{merchant_id}` | Update merchant profile | ✅ Implemented |
|
| 12 |
-
| POST | `/merchants/list` | List merchants (filters + projection) | ✅ Implemented |
|
| 13 |
-
| DELETE | `/merchants/{merchant_id}` | Soft delete merchant | ✅ Implemented |
|
| 14 |
-
| GET | `/merchants/{merchant_id}/children` | Get child merchants | ✅ Implemented |
|
| 15 |
-
| GET | `/merchants/{merchant_id}/hierarchy` | Get merchant hierarchy | ✅ Implemented |
|
| 16 |
-
|
| 17 |
-
## ✅ KYC & COMPLIANCE
|
| 18 |
-
|
| 19 |
-
| Method | Endpoint | Purpose | Status |
|
| 20 |
-
|--------|----------|---------|--------|
|
| 21 |
-
| POST | `/merchants/{merchant_id}/kyc` | Upload KYC | ✅ **NEW** |
|
| 22 |
-
| PUT | `/merchants/{merchant_id}/kyc` | Update KYC | ✅ **NEW** |
|
| 23 |
-
| POST | `/merchants/{merchant_id}/submit` | Submit for verification | ✅ **NEW** |
|
| 24 |
-
| POST | `/merchants/{merchant_id}/approve` | Approve merchant | ✅ **NEW** |
|
| 25 |
-
| POST | `/merchants/{merchant_id}/reject` | Reject merchant | ✅ **NEW** |
|
| 26 |
-
|
| 27 |
-
## ✅ BULK OPERATIONS
|
| 28 |
-
|
| 29 |
-
| Method | Endpoint | Purpose | Status |
|
| 30 |
-
|--------|----------|---------|--------|
|
| 31 |
-
| POST | `/merchants/bulk-upload` | Bulk merchant creation | ✅ **NEW** |
|
| 32 |
-
|
| 33 |
-
## Sample Merchant Document
|
| 34 |
-
|
| 35 |
-
```json
|
| 36 |
-
{
|
| 37 |
-
"_id": {"$oid": "6929fd805b6e93f6f31a6ef7"},
|
| 38 |
-
"merchant_id": "mch_Tl6fTpA4Bbzv7rAFLyDwgA",
|
| 39 |
-
"merchant_type": "ncnf",
|
| 40 |
-
"parent_merchant_id": null,
|
| 41 |
-
"merchant_code": "ncnf-INDIA-001",
|
| 42 |
-
"merchant_name": "National Distribution Center India",
|
| 43 |
-
"contact": {
|
| 44 |
-
"phone": "+919876543210",
|
| 45 |
-
"email": "national@distribution.com",
|
| 46 |
-
"address_line1": "Plot 123, Industrial Area",
|
| 47 |
-
"address_line2": "Phase 1",
|
| 48 |
-
"city": "Mumbai",
|
| 49 |
-
"state": "Maharashtra",
|
| 50 |
-
"pincode": "400001",
|
| 51 |
-
"country": "India"
|
| 52 |
-
},
|
| 53 |
-
"geo_location": null,
|
| 54 |
-
"kyc": {
|
| 55 |
-
"gst_number": "27AAPFU0939F1ZV",
|
| 56 |
-
"pan_number": "AAPFU0939F",
|
| 57 |
-
"business_certificate_url": "https://storage.example.com/ncnf_cert.pdf",
|
| 58 |
-
"bank_account_number": "1234567890123",
|
| 59 |
-
"bank_ifsc": "HDFC0001234",
|
| 60 |
-
"cancelled_cheque_url": "https://storage.example.com/ncnf_cheque.jpg"
|
| 61 |
-
},
|
| 62 |
-
"settings": {
|
| 63 |
-
"pricing_inherited": false,
|
| 64 |
-
"inventory_inherited": false,
|
| 65 |
-
"auto_allocate_stock": true,
|
| 66 |
-
"allowed_payment_modes": ["PREPAID", "COD"],
|
| 67 |
-
"credit_limit": 10000000
|
| 68 |
-
},
|
| 69 |
-
"status": "active",
|
| 70 |
-
"created_by": "system_admin",
|
| 71 |
-
"created_at": "2025-11-28T19:52:32.917061",
|
| 72 |
-
"updated_at": "2025-11-28T19:52:54.820663",
|
| 73 |
-
"metadata": {
|
| 74 |
-
"approved_by": "admin_001",
|
| 75 |
-
"approved_at": "2025-11-28T20:00:00.000000",
|
| 76 |
-
"approval_reason": "All documents verified"
|
| 77 |
-
}
|
| 78 |
-
}
|
| 79 |
-
```
|
| 80 |
-
|
| 81 |
-
## Key Features
|
| 82 |
-
|
| 83 |
-
### 1. Projection List Support
|
| 84 |
-
All list endpoints support field projection for optimized responses:
|
| 85 |
-
|
| 86 |
-
```json
|
| 87 |
-
{
|
| 88 |
-
"projection_list": ["merchant_id", "merchant_name", "merchant_type", "status"]
|
| 89 |
-
}
|
| 90 |
-
```
|
| 91 |
-
|
| 92 |
-
### 2. Merchant Status Workflow
|
| 93 |
-
```
|
| 94 |
-
draft → submitted → active
|
| 95 |
-
↓ ↓
|
| 96 |
-
rejected rejected
|
| 97 |
-
```
|
| 98 |
-
|
| 99 |
-
### 3. KYC Requirements
|
| 100 |
-
|
| 101 |
-
**cnf/distributor:**
|
| 102 |
-
- GST Number ✓
|
| 103 |
-
- PAN Number ✓
|
| 104 |
-
- Bank Account ✓
|
| 105 |
-
- Bank IFSC ✓
|
| 106 |
-
|
| 107 |
-
**retail:**
|
| 108 |
-
- PAN Number ✓ (minimum)
|
| 109 |
-
- GST (optional)
|
| 110 |
-
- Bank details (optional)
|
| 111 |
-
|
| 112 |
-
### 4. Bulk Upload
|
| 113 |
-
- Process multiple merchants in one request
|
| 114 |
-
- Skip errors option for partial success
|
| 115 |
-
- Detailed results for each merchant
|
| 116 |
-
|
| 117 |
-
## Testing
|
| 118 |
-
|
| 119 |
-
```bash
|
| 120 |
-
# Test KYC & Workflow endpoints
|
| 121 |
-
./test_merchant_kyc_workflow.sh
|
| 122 |
-
```
|
| 123 |
-
|
| 124 |
-
## Documentation
|
| 125 |
-
|
| 126 |
-
- **Full API Docs:** `MERCHANT_KYC_WORKFLOW.md`
|
| 127 |
-
- **API Standards:** `API_STANDARDS.md`
|
| 128 |
-
- **Projection Guide:** `PROJECTION_LIST_IMPLEMENTATION.md`
|
| 129 |
-
|
| 130 |
-
## Implementation Files
|
| 131 |
-
|
| 132 |
-
- **Router:** `app/merchants/controllers/router.py`
|
| 133 |
-
- **Service:** `app/merchants/services/service.py`
|
| 134 |
-
- **Schemas:** `app/merchants/schemas/schema.py`
|
| 135 |
-
- **Model:** `app/merchants/models/model.py`
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/MERCHANT_CATALOGUE_LIST_IMPLEMENTATION.md
DELETED
|
@@ -1,316 +0,0 @@
|
|
| 1 |
-
# Merchant Catalogue List Implementation
|
| 2 |
-
|
| 3 |
-
## Overview
|
| 4 |
-
|
| 5 |
-
The Merchant Catalogue List feature provides a high-performance API endpoint to fetch catalogue items with real-time inventory data for a specific merchant. This implementation joins PostgreSQL `catalogue_ref` and `scm_stock` tables to provide comprehensive product and inventory information.
|
| 6 |
-
|
| 7 |
-
## API Endpoint
|
| 8 |
-
|
| 9 |
-
```
|
| 10 |
-
POST /catalogue/merchant-catalogue/list
|
| 11 |
-
```
|
| 12 |
-
|
| 13 |
-
## Features
|
| 14 |
-
|
| 15 |
-
### ✅ **API Standards Compliance**
|
| 16 |
-
- Follows mandatory projection list support pattern
|
| 17 |
-
- POST method for list operations
|
| 18 |
-
- Standardized request/response format
|
| 19 |
-
- Consistent error handling
|
| 20 |
-
|
| 21 |
-
### ✅ **Security & Data Isolation**
|
| 22 |
-
- Merchant-level data filtering using JWT `merchant_id`
|
| 23 |
-
- Prevents cross-merchant data access
|
| 24 |
-
- Secure authentication required
|
| 25 |
-
|
| 26 |
-
### ✅ **Performance Optimization**
|
| 27 |
-
- PostgreSQL native queries with JOINs
|
| 28 |
-
- Optional projection list (50-90% payload reduction)
|
| 29 |
-
- Efficient pagination with skip/limit
|
| 30 |
-
- Stock quantity aggregation across locations
|
| 31 |
-
|
| 32 |
-
### ✅ **Flexible Filtering**
|
| 33 |
-
- Status filtering (Active/Inactive)
|
| 34 |
-
- Catalogue type filtering (Product/Service)
|
| 35 |
-
- Name-based search (ILIKE pattern matching)
|
| 36 |
-
- SKU-based search
|
| 37 |
-
- Inventory tracking filter
|
| 38 |
-
|
| 39 |
-
## Request Schema
|
| 40 |
-
|
| 41 |
-
```python
|
| 42 |
-
class MerchantCatalogueListFilter(BaseModel):
|
| 43 |
-
filters: Optional[Dict[str, Any]] = Field(None, description="Filter criteria")
|
| 44 |
-
skip: Optional[int] = Field(0, ge=0, description="Number of records to skip")
|
| 45 |
-
limit: Optional[int] = Field(10, ge=1, le=100, description="Maximum records to return")
|
| 46 |
-
catalogue_type: Optional[str] = Field(None, description="Product/Service filter")
|
| 47 |
-
projection_list: Optional[List[str]] = Field(
|
| 48 |
-
None,
|
| 49 |
-
description="List of fields to include in response"
|
| 50 |
-
)
|
| 51 |
-
```
|
| 52 |
-
|
| 53 |
-
## Response Format
|
| 54 |
-
|
| 55 |
-
```json
|
| 56 |
-
{
|
| 57 |
-
"data": [
|
| 58 |
-
{
|
| 59 |
-
"catalogue_id": "cat-001",
|
| 60 |
-
"catalogue_code": "HAIR-SHAMPOO-001",
|
| 61 |
-
"catalogue_type": "Product",
|
| 62 |
-
"catalogue_name": "Premium Hair Shampoo",
|
| 63 |
-
"sku": "SKU-SHAMPOO-001",
|
| 64 |
-
"barcode_number": "1234567890123",
|
| 65 |
-
"hsn_code": "33051000",
|
| 66 |
-
"gst_rate": 18.0,
|
| 67 |
-
"mrp": 299.00,
|
| 68 |
-
"base_price": 250.00,
|
| 69 |
-
"track_inventory": true,
|
| 70 |
-
"batch_managed": false,
|
| 71 |
-
"status": "Active",
|
| 72 |
-
"created_at": "2024-01-15T10:30:00Z",
|
| 73 |
-
"qty_on_hand": 150.0,
|
| 74 |
-
"qty_reserved": 15.0,
|
| 75 |
-
"qty_available": 135.0
|
| 76 |
-
}
|
| 77 |
-
],
|
| 78 |
-
"count": 25,
|
| 79 |
-
"status": "Success",
|
| 80 |
-
"skip": 0,
|
| 81 |
-
"limit": 10
|
| 82 |
-
}
|
| 83 |
-
```
|
| 84 |
-
|
| 85 |
-
## Usage Examples
|
| 86 |
-
|
| 87 |
-
### Basic Request
|
| 88 |
-
```bash
|
| 89 |
-
curl -X POST http://localhost:8000/catalogue/merchant-catalogue/list \
|
| 90 |
-
-H "Content-Type: application/json" \
|
| 91 |
-
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
|
| 92 |
-
-d '{
|
| 93 |
-
"filters": {},
|
| 94 |
-
"skip": 0,
|
| 95 |
-
"limit": 10
|
| 96 |
-
}'
|
| 97 |
-
```
|
| 98 |
-
|
| 99 |
-
### Optimized with Projection List
|
| 100 |
-
```bash
|
| 101 |
-
curl -X POST http://localhost:8000/catalogue/merchant-catalogue/list \
|
| 102 |
-
-H "Content-Type: application/json" \
|
| 103 |
-
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
|
| 104 |
-
-d '{
|
| 105 |
-
"projection_list": ["catalogue_id", "catalogue_name", "sku", "qty_on_hand"],
|
| 106 |
-
"limit": 20
|
| 107 |
-
}'
|
| 108 |
-
```
|
| 109 |
-
|
| 110 |
-
### Filtered Request
|
| 111 |
-
```bash
|
| 112 |
-
curl -X POST http://localhost:8000/catalogue/merchant-catalogue/list \
|
| 113 |
-
-H "Content-Type: application/json" \
|
| 114 |
-
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
|
| 115 |
-
-d '{
|
| 116 |
-
"filters": {
|
| 117 |
-
"status": "Active",
|
| 118 |
-
"catalogue_name": "Hair"
|
| 119 |
-
},
|
| 120 |
-
"catalogue_type": "Product",
|
| 121 |
-
"skip": 0,
|
| 122 |
-
"limit": 10
|
| 123 |
-
}'
|
| 124 |
-
```
|
| 125 |
-
|
| 126 |
-
## Database Schema
|
| 127 |
-
|
| 128 |
-
### Tables Involved
|
| 129 |
-
|
| 130 |
-
#### `trans.catalogue_ref`
|
| 131 |
-
- Primary catalogue information
|
| 132 |
-
- Merchant associations via `merchant_id` array
|
| 133 |
-
- Product metadata (SKU, pricing, tax info)
|
| 134 |
-
|
| 135 |
-
#### `scm_stock`
|
| 136 |
-
- Real-time inventory data
|
| 137 |
-
- Location-wise stock quantities
|
| 138 |
-
- Batch and expiry information
|
| 139 |
-
|
| 140 |
-
### SQL Query Structure
|
| 141 |
-
```sql
|
| 142 |
-
SELECT
|
| 143 |
-
cr.catalogue_id, cr.catalogue_name, cr.sku,
|
| 144 |
-
COALESCE(SUM(s.qty_on_hand), 0) as qty_on_hand,
|
| 145 |
-
COALESCE(SUM(s.qty_reserved), 0) as qty_reserved,
|
| 146 |
-
COALESCE(SUM(s.qty_available), 0) as qty_available
|
| 147 |
-
FROM trans.catalogue_ref cr
|
| 148 |
-
LEFT JOIN scm_stock s ON cr.sku = s.sku AND s.merchant_id = :merchant_id
|
| 149 |
-
WHERE :merchant_id = ANY(cr.merchant_id)
|
| 150 |
-
GROUP BY cr.catalogue_id, cr.catalogue_name, cr.sku
|
| 151 |
-
ORDER BY cr.created_at DESC
|
| 152 |
-
LIMIT :limit OFFSET :skip
|
| 153 |
-
```
|
| 154 |
-
|
| 155 |
-
## Implementation Details
|
| 156 |
-
|
| 157 |
-
### Controller Layer
|
| 158 |
-
- **File**: `app/catalogues/controllers/router.py`
|
| 159 |
-
- **Method**: `merchant_catalogue_list()`
|
| 160 |
-
- **Route**: `POST /catalogue/merchant-catalogue/list`
|
| 161 |
-
|
| 162 |
-
### Service Layer
|
| 163 |
-
- **File**: `app/catalogues/services/service.py`
|
| 164 |
-
- **Method**: `list_merchant_catalogue_items()`
|
| 165 |
-
- **Features**: PostgreSQL JOIN, aggregation, projection
|
| 166 |
-
|
| 167 |
-
### Schema Layer
|
| 168 |
-
- **File**: `app/catalogues/schemas/schema.py`
|
| 169 |
-
- **Class**: `MerchantCatalogueListFilter`
|
| 170 |
-
- **Validation**: Pydantic with field constraints
|
| 171 |
-
|
| 172 |
-
## Available Filters
|
| 173 |
-
|
| 174 |
-
| Filter | Type | Description | Example |
|
| 175 |
-
|--------|------|-------------|---------|
|
| 176 |
-
| `status` | string | Active/Inactive | `{"status": "Active"}` |
|
| 177 |
-
| `catalogue_name` | string | Name search (ILIKE) | `{"catalogue_name": "Hair"}` |
|
| 178 |
-
| `sku` | string | SKU search (ILIKE) | `{"sku": "SHAMPOO"}` |
|
| 179 |
-
| `track_inventory` | boolean | Inventory tracking flag | `{"track_inventory": true}` |
|
| 180 |
-
|
| 181 |
-
## Projection Fields
|
| 182 |
-
|
| 183 |
-
Common projection combinations for performance:
|
| 184 |
-
|
| 185 |
-
### Minimal (List View)
|
| 186 |
-
```json
|
| 187 |
-
["catalogue_id", "catalogue_name", "sku", "status"]
|
| 188 |
-
```
|
| 189 |
-
|
| 190 |
-
### With Inventory
|
| 191 |
-
```json
|
| 192 |
-
["catalogue_id", "catalogue_name", "sku", "qty_on_hand", "qty_available"]
|
| 193 |
-
```
|
| 194 |
-
|
| 195 |
-
### With Pricing
|
| 196 |
-
```json
|
| 197 |
-
["catalogue_id", "catalogue_name", "sku", "mrp", "base_price", "gst_rate"]
|
| 198 |
-
```
|
| 199 |
-
|
| 200 |
-
### Full Product Info
|
| 201 |
-
```json
|
| 202 |
-
[
|
| 203 |
-
"catalogue_id", "catalogue_name", "sku", "catalogue_type",
|
| 204 |
-
"mrp", "base_price", "qty_on_hand", "qty_available", "status"
|
| 205 |
-
]
|
| 206 |
-
```
|
| 207 |
-
|
| 208 |
-
## Testing
|
| 209 |
-
|
| 210 |
-
### Test Scripts Available
|
| 211 |
-
|
| 212 |
-
1. **Database Service Tests**: `test_merchant_catalogue_list.py`
|
| 213 |
-
- Tests service layer functionality
|
| 214 |
-
- Database integration testing
|
| 215 |
-
- Projection and filtering validation
|
| 216 |
-
|
| 217 |
-
2. **HTTP API Tests**: `test_merchant_catalogue_api.py`
|
| 218 |
-
- End-to-end API testing
|
| 219 |
-
- HTTP status code validation
|
| 220 |
-
- Response format verification
|
| 221 |
-
|
| 222 |
-
3. **curl Tests**: `test_merchant_catalogue_curl.sh`
|
| 223 |
-
- Manual API testing
|
| 224 |
-
- Example request formats
|
| 225 |
-
- Error handling demonstration
|
| 226 |
-
|
| 227 |
-
### Running Tests
|
| 228 |
-
|
| 229 |
-
```bash
|
| 230 |
-
# Run all tests
|
| 231 |
-
./run_merchant_catalogue_tests.sh
|
| 232 |
-
|
| 233 |
-
# Run specific tests
|
| 234 |
-
python3 test_merchant_catalogue_list.py
|
| 235 |
-
python3 test_merchant_catalogue_api.py
|
| 236 |
-
./test_merchant_catalogue_curl.sh
|
| 237 |
-
```
|
| 238 |
-
|
| 239 |
-
## Performance Benefits
|
| 240 |
-
|
| 241 |
-
### Projection List Impact
|
| 242 |
-
- **Without projection**: Full object ~2KB per item
|
| 243 |
-
- **With projection**: Minimal fields ~200B per item
|
| 244 |
-
- **Savings**: Up to 90% payload reduction
|
| 245 |
-
|
| 246 |
-
### Database Optimization
|
| 247 |
-
- Single JOIN query vs multiple round trips
|
| 248 |
-
- PostgreSQL native aggregation
|
| 249 |
-
- Efficient pagination with LIMIT/OFFSET
|
| 250 |
-
|
| 251 |
-
## Error Handling
|
| 252 |
-
|
| 253 |
-
### Common Error Scenarios
|
| 254 |
-
|
| 255 |
-
| Status Code | Scenario | Response |
|
| 256 |
-
|-------------|----------|----------|
|
| 257 |
-
| 400 | Missing merchant_id | `{"detail": "Merchant ID is required"}` |
|
| 258 |
-
| 401 | Invalid JWT token | `{"detail": "Authentication required"}` |
|
| 259 |
-
| 422 | Invalid payload | `{"detail": "Validation error"}` |
|
| 260 |
-
| 500 | Database error | `{"detail": "Internal server error"}` |
|
| 261 |
-
|
| 262 |
-
## Security Considerations
|
| 263 |
-
|
| 264 |
-
1. **Merchant Isolation**: Data filtered by JWT `merchant_id`
|
| 265 |
-
2. **Authentication**: JWT token required for all requests
|
| 266 |
-
3. **Authorization**: Only merchant's own data accessible
|
| 267 |
-
4. **Input Validation**: All inputs validated via Pydantic schemas
|
| 268 |
-
|
| 269 |
-
## Future Enhancements
|
| 270 |
-
|
| 271 |
-
### Potential Improvements
|
| 272 |
-
- [ ] Redis caching for frequently accessed data
|
| 273 |
-
- [ ] Elasticsearch integration for advanced search
|
| 274 |
-
- [ ] Real-time inventory updates via WebSocket
|
| 275 |
-
- [ ] Bulk operations support
|
| 276 |
-
- [ ] Export functionality (CSV/Excel)
|
| 277 |
-
|
| 278 |
-
### Performance Monitoring
|
| 279 |
-
- [ ] Query execution time logging
|
| 280 |
-
- [ ] Payload size monitoring
|
| 281 |
-
- [ ] Cache hit rate tracking
|
| 282 |
-
- [ ] API usage analytics
|
| 283 |
-
|
| 284 |
-
## Troubleshooting
|
| 285 |
-
|
| 286 |
-
### Common Issues
|
| 287 |
-
|
| 288 |
-
1. **Empty Results**
|
| 289 |
-
- Check merchant_id in JWT token
|
| 290 |
-
- Verify catalogue_ref has merchant association
|
| 291 |
-
- Check filter criteria
|
| 292 |
-
|
| 293 |
-
2. **Performance Issues**
|
| 294 |
-
- Use projection_list for large datasets
|
| 295 |
-
- Implement appropriate database indexes
|
| 296 |
-
- Monitor query execution plans
|
| 297 |
-
|
| 298 |
-
3. **Authentication Errors**
|
| 299 |
-
- Verify JWT token format
|
| 300 |
-
- Check token expiration
|
| 301 |
-
- Validate merchant_id claim
|
| 302 |
-
|
| 303 |
-
## Related Documentation
|
| 304 |
-
|
| 305 |
-
- [API Standards](./API_STANDARDS.md)
|
| 306 |
-
- [Projection List Implementation](./PROJECTION_LIST_IMPLEMENTATION.md)
|
| 307 |
-
- [Authentication Guide](./AUTHENTICATION.md)
|
| 308 |
-
- [Database Schema](./DATABASE_SCHEMA.md)
|
| 309 |
-
|
| 310 |
-
---
|
| 311 |
-
|
| 312 |
-
**Implementation Status**: ✅ Complete and Ready for Production
|
| 313 |
-
|
| 314 |
-
**Last Updated**: December 2024
|
| 315 |
-
|
| 316 |
-
**Maintainer**: SCM Development Team
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/PRICING_LEVELS_COMPLETE_SOLUTION.md
DELETED
|
@@ -1,295 +0,0 @@
|
|
| 1 |
-
# Complete Pricing Levels Solution
|
| 2 |
-
|
| 3 |
-
## Overview
|
| 4 |
-
|
| 5 |
-
This document describes the complete solution for handling pricing_levels in SCM catalogues, including migration of existing records and automatic generation for catalogues without pricing_levels.
|
| 6 |
-
|
| 7 |
-
## Problem Statement
|
| 8 |
-
|
| 9 |
-
Some catalogues in the SCM system don't have `pricing_levels` data, which is needed for multi-level pricing support. The solution generates pricing_levels based on MRP with specific margins:
|
| 10 |
-
|
| 11 |
-
- **ncnf**: MRP - 12%
|
| 12 |
-
- **cnf**: MRP - 6%
|
| 13 |
-
- **distributor**: MRP - 10%
|
| 14 |
-
- **retail**: MRP - 20%
|
| 15 |
-
|
| 16 |
-
## Solution Components
|
| 17 |
-
|
| 18 |
-
### 1. Migration Scripts
|
| 19 |
-
|
| 20 |
-
#### A. Generate Missing Pricing Levels (`migration_generate_missing_pricing_levels.py`)
|
| 21 |
-
- Finds catalogues without pricing_levels but with MRP
|
| 22 |
-
- Generates pricing_levels using the specified margin structure
|
| 23 |
-
- Updates MongoDB documents with the new pricing data
|
| 24 |
-
- Includes preview mode and comprehensive logging
|
| 25 |
-
|
| 26 |
-
**Usage:**
|
| 27 |
-
```bash
|
| 28 |
-
# Preview what would be updated
|
| 29 |
-
python migration_generate_missing_pricing_levels.py --preview
|
| 30 |
-
|
| 31 |
-
# Execute the migration
|
| 32 |
-
python migration_generate_missing_pricing_levels.py
|
| 33 |
-
```
|
| 34 |
-
|
| 35 |
-
#### B. Add PostgreSQL Column (`migration_add_pricing_levels_column.py`)
|
| 36 |
-
- Adds `pricing_levels` JSON column to PostgreSQL tables
|
| 37 |
-
- Creates performance indexes for JSON queries
|
| 38 |
-
- Handles existing table structures gracefully
|
| 39 |
-
|
| 40 |
-
**Usage:**
|
| 41 |
-
```bash
|
| 42 |
-
python migration_add_pricing_levels_column.py
|
| 43 |
-
```
|
| 44 |
-
|
| 45 |
-
### 2. Enhanced Sync Handler
|
| 46 |
-
|
| 47 |
-
The sync handler (`app/sync/catalogues/handler.py`) now includes:
|
| 48 |
-
|
| 49 |
-
#### Automatic Generation
|
| 50 |
-
- Detects catalogues without pricing_levels during sync
|
| 51 |
-
- Generates pricing_levels on-the-fly based on available MRP
|
| 52 |
-
- Logs generation activities for monitoring
|
| 53 |
-
|
| 54 |
-
#### Pricing Calculation Logic
|
| 55 |
-
```python
|
| 56 |
-
# Margin structure
|
| 57 |
-
PRICING_MARGINS = {
|
| 58 |
-
"ncnf": {"discount_pct": 12, "trade_margin": 15, "retail_margin": 25, "max_discount_pct": 5},
|
| 59 |
-
"cnf": {"discount_pct": 6, "trade_margin": 18, "retail_margin": 28, "max_discount_pct": 8},
|
| 60 |
-
"distributor": {"discount_pct": 10, "trade_margin": 20, "retail_margin": 30, "max_discount_pct": 15},
|
| 61 |
-
"retail": {"discount_pct": 20, "trade_margin": 25, "retail_margin": 35, "max_discount_pct": 20}
|
| 62 |
-
}
|
| 63 |
-
```
|
| 64 |
-
|
| 65 |
-
#### Price Calculation Formula
|
| 66 |
-
```python
|
| 67 |
-
selling_price = mrp * (100 - discount_pct) / 100
|
| 68 |
-
purchase_price = selling_price * 0.70 # 70% of selling price
|
| 69 |
-
retail_price = selling_price
|
| 70 |
-
```
|
| 71 |
-
|
| 72 |
-
### 3. Validation Scripts
|
| 73 |
-
|
| 74 |
-
#### A. Migration Validation (`validate_pricing_levels_migration.py`)
|
| 75 |
-
- Validates pricing_levels structure and calculations
|
| 76 |
-
- Checks that all required levels are present
|
| 77 |
-
- Verifies price relationships and calculations
|
| 78 |
-
- Shows sample pricing_levels for review
|
| 79 |
-
|
| 80 |
-
**Usage:**
|
| 81 |
-
```bash
|
| 82 |
-
# Full validation
|
| 83 |
-
python validate_pricing_levels_migration.py
|
| 84 |
-
|
| 85 |
-
# Show samples only
|
| 86 |
-
python validate_pricing_levels_migration.py --samples
|
| 87 |
-
```
|
| 88 |
-
|
| 89 |
-
#### B. Complete Flow Test (`test_complete_pricing_levels_flow.py`)
|
| 90 |
-
- Tests the entire pricing_levels flow end-to-end
|
| 91 |
-
- Validates sync handler generation
|
| 92 |
-
- Verifies PostgreSQL storage
|
| 93 |
-
- Tests different catalogue scenarios
|
| 94 |
-
|
| 95 |
-
**Usage:**
|
| 96 |
-
```bash
|
| 97 |
-
python test_complete_pricing_levels_flow.py
|
| 98 |
-
```
|
| 99 |
-
|
| 100 |
-
### 4. Database Schema Updates
|
| 101 |
-
|
| 102 |
-
#### PostgreSQL Table Structure
|
| 103 |
-
```sql
|
| 104 |
-
ALTER TABLE trans.catalogue_ref
|
| 105 |
-
ADD COLUMN pricing_levels JSON;
|
| 106 |
-
|
| 107 |
-
-- Performance indexes
|
| 108 |
-
CREATE INDEX idx_catalogue_ref_pricing_levels_currency
|
| 109 |
-
ON trans.catalogue_ref USING GIN ((pricing_levels->>'currency'));
|
| 110 |
-
|
| 111 |
-
CREATE INDEX idx_catalogue_ref_pricing_levels_mrp
|
| 112 |
-
ON trans.catalogue_ref USING BTREE (CAST(pricing_levels->>'mrp' AS NUMERIC));
|
| 113 |
-
```
|
| 114 |
-
|
| 115 |
-
#### SQLAlchemy Model Update
|
| 116 |
-
```python
|
| 117 |
-
class CatalogueRef(Base):
|
| 118 |
-
# ... existing columns ...
|
| 119 |
-
pricing_levels = Column(JSON)
|
| 120 |
-
```
|
| 121 |
-
|
| 122 |
-
## Generated Pricing Levels Structure
|
| 123 |
-
|
| 124 |
-
```json
|
| 125 |
-
{
|
| 126 |
-
"currency": "INR",
|
| 127 |
-
"mrp": 500,
|
| 128 |
-
"levels": {
|
| 129 |
-
"ncnf": {
|
| 130 |
-
"purchase_price": 308.00,
|
| 131 |
-
"trade_margin": 15,
|
| 132 |
-
"selling_price": 440.00,
|
| 133 |
-
"retail_price": 440.00,
|
| 134 |
-
"retail_margin": 25,
|
| 135 |
-
"max_discount_pct": 5
|
| 136 |
-
},
|
| 137 |
-
"cnf": {
|
| 138 |
-
"purchase_price": 329.00,
|
| 139 |
-
"trade_margin": 18,
|
| 140 |
-
"selling_price": 470.00,
|
| 141 |
-
"retail_price": 470.00,
|
| 142 |
-
"retail_margin": 28,
|
| 143 |
-
"max_discount_pct": 8
|
| 144 |
-
},
|
| 145 |
-
"distributor": {
|
| 146 |
-
"purchase_price": 315.00,
|
| 147 |
-
"trade_margin": 20,
|
| 148 |
-
"selling_price": 450.00,
|
| 149 |
-
"retail_price": 450.00,
|
| 150 |
-
"retail_margin": 30,
|
| 151 |
-
"max_discount_pct": 15
|
| 152 |
-
},
|
| 153 |
-
"retail": {
|
| 154 |
-
"purchase_price": 280.00,
|
| 155 |
-
"trade_margin": 25,
|
| 156 |
-
"selling_price": 400.00,
|
| 157 |
-
"retail_price": 400.00,
|
| 158 |
-
"retail_margin": 35,
|
| 159 |
-
"max_discount_pct": 20
|
| 160 |
-
}
|
| 161 |
-
}
|
| 162 |
-
}
|
| 163 |
-
```
|
| 164 |
-
|
| 165 |
-
## Deployment Steps
|
| 166 |
-
|
| 167 |
-
### 1. Pre-Migration
|
| 168 |
-
```bash
|
| 169 |
-
# 1. Backup databases
|
| 170 |
-
mongodump --db scm_db --collection catalogues
|
| 171 |
-
pg_dump -t trans.catalogue_ref > catalogue_ref_backup.sql
|
| 172 |
-
|
| 173 |
-
# 2. Preview migration impact
|
| 174 |
-
python migration_generate_missing_pricing_levels.py --preview
|
| 175 |
-
```
|
| 176 |
-
|
| 177 |
-
### 2. Execute Migration
|
| 178 |
-
```bash
|
| 179 |
-
# 1. Add PostgreSQL column
|
| 180 |
-
python migration_add_pricing_levels_column.py
|
| 181 |
-
|
| 182 |
-
# 2. Generate missing pricing_levels in MongoDB
|
| 183 |
-
python migration_generate_missing_pricing_levels.py
|
| 184 |
-
|
| 185 |
-
# 3. Validate results
|
| 186 |
-
python validate_pricing_levels_migration.py
|
| 187 |
-
```
|
| 188 |
-
|
| 189 |
-
### 3. Deploy Code
|
| 190 |
-
```bash
|
| 191 |
-
# Deploy updated sync handler and models
|
| 192 |
-
# The sync process will now automatically handle pricing_levels
|
| 193 |
-
```
|
| 194 |
-
|
| 195 |
-
### 4. Post-Migration Validation
|
| 196 |
-
```bash
|
| 197 |
-
# Run complete flow test
|
| 198 |
-
python test_complete_pricing_levels_flow.py
|
| 199 |
-
|
| 200 |
-
# Check sync logs for automatic generation
|
| 201 |
-
tail -f /var/log/scm/sync.log | grep "pricing_levels"
|
| 202 |
-
```
|
| 203 |
-
|
| 204 |
-
## Monitoring and Maintenance
|
| 205 |
-
|
| 206 |
-
### Log Monitoring
|
| 207 |
-
The system logs pricing_levels generation activities:
|
| 208 |
-
```
|
| 209 |
-
INFO: Generated pricing_levels for catalogue ABC123 with MRP ₹500
|
| 210 |
-
DEBUG: Catalogue upserted to PostgreSQL with pricing_levels
|
| 211 |
-
```
|
| 212 |
-
|
| 213 |
-
### Performance Queries
|
| 214 |
-
```sql
|
| 215 |
-
-- Count catalogues with pricing_levels
|
| 216 |
-
SELECT COUNT(1) FROM trans.catalogue_ref WHERE pricing_levels IS NOT NULL;
|
| 217 |
-
|
| 218 |
-
-- Find catalogues by currency
|
| 219 |
-
SELECT catalogue_id, catalogue_name
|
| 220 |
-
FROM trans.catalogue_ref
|
| 221 |
-
WHERE pricing_levels->>'currency' = 'INR';
|
| 222 |
-
|
| 223 |
-
-- Query by MRP range
|
| 224 |
-
SELECT catalogue_id, catalogue_name, pricing_levels->>'mrp' as mrp
|
| 225 |
-
FROM trans.catalogue_ref
|
| 226 |
-
WHERE CAST(pricing_levels->>'mrp' AS NUMERIC) BETWEEN 100 AND 500;
|
| 227 |
-
```
|
| 228 |
-
|
| 229 |
-
### Health Checks
|
| 230 |
-
```bash
|
| 231 |
-
# Regular validation
|
| 232 |
-
python validate_pricing_levels_migration.py
|
| 233 |
-
|
| 234 |
-
# Check for catalogues without pricing_levels
|
| 235 |
-
python -c "
|
| 236 |
-
import asyncio
|
| 237 |
-
from migration_generate_missing_pricing_levels import find_catalogues_without_pricing_levels
|
| 238 |
-
asyncio.run(find_catalogues_without_pricing_levels())
|
| 239 |
-
"
|
| 240 |
-
```
|
| 241 |
-
|
| 242 |
-
## Benefits
|
| 243 |
-
|
| 244 |
-
1. **Automatic Generation**: No manual intervention needed for new catalogues
|
| 245 |
-
2. **Consistent Pricing**: Standardized margin structure across all levels
|
| 246 |
-
3. **Performance**: JSON indexes enable fast pricing queries
|
| 247 |
-
4. **Backward Compatibility**: Existing catalogues continue to work
|
| 248 |
-
5. **Monitoring**: Comprehensive logging for tracking generation activities
|
| 249 |
-
6. **Validation**: Built-in validation ensures data integrity
|
| 250 |
-
|
| 251 |
-
## Troubleshooting
|
| 252 |
-
|
| 253 |
-
### Common Issues
|
| 254 |
-
|
| 255 |
-
1. **Missing MRP**: Catalogues without MRP cannot generate pricing_levels
|
| 256 |
-
- Solution: Ensure MRP is set in either `pricing.mrp` or top-level `mrp`
|
| 257 |
-
|
| 258 |
-
2. **Invalid JSON**: Corrupted pricing_levels data
|
| 259 |
-
- Solution: Re-run migration or use validation script to identify issues
|
| 260 |
-
|
| 261 |
-
3. **Sync Failures**: PostgreSQL column missing
|
| 262 |
-
- Solution: Run `migration_add_pricing_levels_column.py`
|
| 263 |
-
|
| 264 |
-
### Recovery Procedures
|
| 265 |
-
|
| 266 |
-
1. **Regenerate Pricing Levels**:
|
| 267 |
-
```bash
|
| 268 |
-
# Remove existing pricing_levels and regenerate
|
| 269 |
-
python -c "
|
| 270 |
-
import asyncio
|
| 271 |
-
from motor.motor_asyncio import AsyncIOMotorClient
|
| 272 |
-
async def reset():
|
| 273 |
-
client = AsyncIOMotorClient('mongodb://localhost:27017')
|
| 274 |
-
db = client.scm_db
|
| 275 |
-
await db.catalogues.update_many({}, {'$unset': {'pricing_levels': 1}})
|
| 276 |
-
asyncio.run(reset())
|
| 277 |
-
"
|
| 278 |
-
python migration_generate_missing_pricing_levels.py
|
| 279 |
-
```
|
| 280 |
-
|
| 281 |
-
2. **Resync to PostgreSQL**:
|
| 282 |
-
```bash
|
| 283 |
-
# Trigger resync for specific catalogues
|
| 284 |
-
python -c "
|
| 285 |
-
# Use sync service to resync catalogues
|
| 286 |
-
"
|
| 287 |
-
```
|
| 288 |
-
|
| 289 |
-
## Future Enhancements
|
| 290 |
-
|
| 291 |
-
1. **Dynamic Margins**: Support for merchant-specific margin configurations
|
| 292 |
-
2. **Currency Support**: Multi-currency pricing levels
|
| 293 |
-
3. **Bulk Updates**: API endpoints for bulk pricing updates
|
| 294 |
-
4. **Price History**: Track pricing changes over time
|
| 295 |
-
5. **Validation Rules**: Business rule validation for pricing consistency
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/PRICING_LEVELS_CORRECTED_STRUCTURE.md
DELETED
|
@@ -1,232 +0,0 @@
|
|
| 1 |
-
# Pricing Levels - Corrected Structure
|
| 2 |
-
|
| 3 |
-
## Overview
|
| 4 |
-
|
| 5 |
-
This document describes the corrected pricing_levels structure that has been implemented across MongoDB and PostgreSQL.
|
| 6 |
-
|
| 7 |
-
## Corrected Structure
|
| 8 |
-
|
| 9 |
-
The pricing_levels now contains only three essential fields per level:
|
| 10 |
-
- `cost_price`: The cost price calculated as MRP minus the discount percentage
|
| 11 |
-
- `trade_margin`: The trade margin percentage for this level
|
| 12 |
-
- `max_discount_pct`: The maximum discount percentage allowed for this level
|
| 13 |
-
|
| 14 |
-
## JSON Structure
|
| 15 |
-
|
| 16 |
-
```json
|
| 17 |
-
{
|
| 18 |
-
"currency": "INR",
|
| 19 |
-
"mrp": 500,
|
| 20 |
-
"levels": {
|
| 21 |
-
"ncnf": {
|
| 22 |
-
"cost_price": 440.00,
|
| 23 |
-
"trade_margin": 15,
|
| 24 |
-
"max_discount_pct": 5
|
| 25 |
-
},
|
| 26 |
-
"cnf": {
|
| 27 |
-
"cost_price": 470.00,
|
| 28 |
-
"trade_margin": 18,
|
| 29 |
-
"max_discount_pct": 8
|
| 30 |
-
},
|
| 31 |
-
"distributor": {
|
| 32 |
-
"cost_price": 450.00,
|
| 33 |
-
"trade_margin": 20,
|
| 34 |
-
"max_discount_pct": 15
|
| 35 |
-
},
|
| 36 |
-
"retail": {
|
| 37 |
-
"cost_price": 400.00,
|
| 38 |
-
"trade_margin": 25,
|
| 39 |
-
"max_discount_pct": 20
|
| 40 |
-
}
|
| 41 |
-
}
|
| 42 |
-
}
|
| 43 |
-
```
|
| 44 |
-
|
| 45 |
-
## Pricing Level Margins
|
| 46 |
-
|
| 47 |
-
| Level | Discount from MRP | Trade Margin | Max Discount |
|
| 48 |
-
|-------|------------------|--------------|--------------|
|
| 49 |
-
| ncnf | 12% | 15% | 5% |
|
| 50 |
-
| cnf | 6% | 18% | 8% |
|
| 51 |
-
| distributor | 10% | 20% | 15% |
|
| 52 |
-
| retail | 20% | 25% | 20% |
|
| 53 |
-
|
| 54 |
-
## Calculation Formula
|
| 55 |
-
|
| 56 |
-
```
|
| 57 |
-
cost_price = MRP × (100 - discount_pct) / 100
|
| 58 |
-
```
|
| 59 |
-
|
| 60 |
-
### Examples
|
| 61 |
-
|
| 62 |
-
**Example 1: MRP = ₹500**
|
| 63 |
-
- ncnf: ₹500 × (100 - 12) / 100 = ₹440.00
|
| 64 |
-
- cnf: ₹500 × (100 - 6) / 100 = ₹470.00
|
| 65 |
-
- distributor: ₹500 × (100 - 10) / 100 = ₹450.00
|
| 66 |
-
- retail: ₹500 × (100 - 20) / 100 = ₹400.00
|
| 67 |
-
|
| 68 |
-
**Example 2: MRP = ₹299**
|
| 69 |
-
- ncnf: ₹299 × (100 - 12) / 100 = ₹263.12
|
| 70 |
-
- cnf: ₹299 × (100 - 6) / 100 = ₹281.06
|
| 71 |
-
- distributor: ₹299 × (100 - 10) / 100 = ₹269.10
|
| 72 |
-
- retail: ₹299 × (100 - 20) / 100 = ₹239.20
|
| 73 |
-
|
| 74 |
-
## Implementation Details
|
| 75 |
-
|
| 76 |
-
### MongoDB Collection: `catalogues`
|
| 77 |
-
|
| 78 |
-
The pricing_levels field is stored as a nested document within each catalogue:
|
| 79 |
-
|
| 80 |
-
```javascript
|
| 81 |
-
{
|
| 82 |
-
"catalogue_id": "CAT-001",
|
| 83 |
-
"catalogue_name": "Sample Product",
|
| 84 |
-
"pricing_levels": {
|
| 85 |
-
"currency": "INR",
|
| 86 |
-
"mrp": 500,
|
| 87 |
-
"levels": {
|
| 88 |
-
"ncnf": {
|
| 89 |
-
"cost_price": 440.00,
|
| 90 |
-
"trade_margin": 15,
|
| 91 |
-
"max_discount_pct": 5
|
| 92 |
-
},
|
| 93 |
-
// ... other levels
|
| 94 |
-
}
|
| 95 |
-
}
|
| 96 |
-
}
|
| 97 |
-
```
|
| 98 |
-
|
| 99 |
-
### PostgreSQL Table: `trans.catalogue_ref`
|
| 100 |
-
|
| 101 |
-
The pricing_levels field is stored as JSON:
|
| 102 |
-
|
| 103 |
-
```sql
|
| 104 |
-
CREATE TABLE trans.catalogue_ref (
|
| 105 |
-
catalogue_id TEXT PRIMARY KEY,
|
| 106 |
-
-- ... other columns ...
|
| 107 |
-
pricing_levels JSON
|
| 108 |
-
);
|
| 109 |
-
```
|
| 110 |
-
|
| 111 |
-
## Schema Definition (Pydantic)
|
| 112 |
-
|
| 113 |
-
```python
|
| 114 |
-
class PricingLevel(BaseModel):
|
| 115 |
-
cost_price: Optional[float] = Field(None, ge=0, description="Cost price for this level (MRP - discount%)")
|
| 116 |
-
trade_margin: Optional[float] = Field(None, ge=0, description="Trade margin percentage")
|
| 117 |
-
max_discount_pct: Optional[float] = Field(None, ge=0, le=100, description="Maximum discount percentage allowed")
|
| 118 |
-
|
| 119 |
-
class PricingLevels(BaseModel):
|
| 120 |
-
currency: str = Field("INR", description="Currency code")
|
| 121 |
-
mrp: Optional[float] = Field(None, ge=0, description="Maximum Retail Price")
|
| 122 |
-
levels: Optional[Dict[str, PricingLevel]] = Field(None, description="Pricing levels (ncnf, cnf, distributor, retail)")
|
| 123 |
-
```
|
| 124 |
-
|
| 125 |
-
## Migration Status
|
| 126 |
-
|
| 127 |
-
✅ **Completed:**
|
| 128 |
-
1. PostgreSQL table `trans.catalogue_ref` created with `pricing_levels` JSON column
|
| 129 |
-
2. MongoDB migration script updated to generate corrected structure
|
| 130 |
-
3. Sync handler updated to automatically generate pricing_levels with corrected structure
|
| 131 |
-
4. Schema definitions updated to reflect corrected fields
|
| 132 |
-
5. Validation scripts updated to check corrected structure
|
| 133 |
-
|
| 134 |
-
## Usage Examples
|
| 135 |
-
|
| 136 |
-
### Query by Cost Price Range (PostgreSQL)
|
| 137 |
-
|
| 138 |
-
```sql
|
| 139 |
-
-- Find catalogues where retail cost price is between 200 and 400
|
| 140 |
-
SELECT catalogue_id, catalogue_name, pricing_levels
|
| 141 |
-
FROM trans.catalogue_ref
|
| 142 |
-
WHERE CAST(pricing_levels->'levels'->'retail'->>'cost_price' AS NUMERIC) BETWEEN 200 AND 400;
|
| 143 |
-
```
|
| 144 |
-
|
| 145 |
-
### Query by Currency (PostgreSQL)
|
| 146 |
-
|
| 147 |
-
```sql
|
| 148 |
-
-- Find all catalogues with INR pricing
|
| 149 |
-
SELECT catalogue_id, catalogue_name, pricing_levels->>'mrp' as mrp
|
| 150 |
-
FROM trans.catalogue_ref
|
| 151 |
-
WHERE pricing_levels->>'currency' = 'INR';
|
| 152 |
-
```
|
| 153 |
-
|
| 154 |
-
### Query in MongoDB
|
| 155 |
-
|
| 156 |
-
```javascript
|
| 157 |
-
// Find catalogues where ncnf cost price is less than 300
|
| 158 |
-
db.catalogues.find({
|
| 159 |
-
"pricing_levels.levels.ncnf.cost_price": { $lt: 300 }
|
| 160 |
-
})
|
| 161 |
-
|
| 162 |
-
// Find catalogues with specific trade margin
|
| 163 |
-
db.catalogues.find({
|
| 164 |
-
"pricing_levels.levels.distributor.trade_margin": 20
|
| 165 |
-
})
|
| 166 |
-
```
|
| 167 |
-
|
| 168 |
-
## API Response Example
|
| 169 |
-
|
| 170 |
-
```json
|
| 171 |
-
{
|
| 172 |
-
"status": "success",
|
| 173 |
-
"data": {
|
| 174 |
-
"catalogue_id": "CAT-001",
|
| 175 |
-
"catalogue_name": "Premium Hair Shampoo",
|
| 176 |
-
"catalogue_type": "Product",
|
| 177 |
-
"pricing_levels": {
|
| 178 |
-
"currency": "INR",
|
| 179 |
-
"mrp": 399,
|
| 180 |
-
"levels": {
|
| 181 |
-
"ncnf": {
|
| 182 |
-
"cost_price": 351.12,
|
| 183 |
-
"trade_margin": 15,
|
| 184 |
-
"max_discount_pct": 5
|
| 185 |
-
},
|
| 186 |
-
"cnf": {
|
| 187 |
-
"cost_price": 375.06,
|
| 188 |
-
"trade_margin": 18,
|
| 189 |
-
"max_discount_pct": 8
|
| 190 |
-
},
|
| 191 |
-
"distributor": {
|
| 192 |
-
"cost_price": 359.10,
|
| 193 |
-
"trade_margin": 20,
|
| 194 |
-
"max_discount_pct": 15
|
| 195 |
-
},
|
| 196 |
-
"retail": {
|
| 197 |
-
"cost_price": 319.20,
|
| 198 |
-
"trade_margin": 25,
|
| 199 |
-
"max_discount_pct": 20
|
| 200 |
-
}
|
| 201 |
-
}
|
| 202 |
-
}
|
| 203 |
-
}
|
| 204 |
-
}
|
| 205 |
-
```
|
| 206 |
-
|
| 207 |
-
## Benefits of Corrected Structure
|
| 208 |
-
|
| 209 |
-
1. **Simplified**: Only essential pricing fields are stored
|
| 210 |
-
2. **Clear Semantics**: `cost_price` clearly indicates the base cost for each level
|
| 211 |
-
3. **Consistent**: Same structure across all pricing levels
|
| 212 |
-
4. **Efficient**: Smaller JSON payload, faster queries
|
| 213 |
-
5. **Maintainable**: Easier to understand and update
|
| 214 |
-
|
| 215 |
-
## Validation
|
| 216 |
-
|
| 217 |
-
To validate the pricing_levels structure:
|
| 218 |
-
|
| 219 |
-
```bash
|
| 220 |
-
# Run validation script
|
| 221 |
-
python validate_pricing_levels_migration.py
|
| 222 |
-
|
| 223 |
-
# Expected output:
|
| 224 |
-
# ✅ All pricing_levels are valid!
|
| 225 |
-
```
|
| 226 |
-
|
| 227 |
-
## Notes
|
| 228 |
-
|
| 229 |
-
- All prices are stored with 2 decimal precision
|
| 230 |
-
- Currency is currently fixed to "INR" but can be extended
|
| 231 |
-
- The sync handler automatically generates pricing_levels for catalogues without them
|
| 232 |
-
- Existing catalogues with old structure should be migrated using the migration script
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/PRICING_LEVELS_SYNC_IMPLEMENTATION.md
DELETED
|
@@ -1,187 +0,0 @@
|
|
| 1 |
-
# Pricing Levels Sync Implementation
|
| 2 |
-
|
| 3 |
-
## Overview
|
| 4 |
-
|
| 5 |
-
This implementation ensures that the `pricing_levels` data from MongoDB catalogues is properly stored as JSON in PostgreSQL's `trans.catalogue_ref` table during the sync process.
|
| 6 |
-
|
| 7 |
-
## Changes Made
|
| 8 |
-
|
| 9 |
-
### 1. Updated Sync Models (`app/sync/catalogues/models.py`)
|
| 10 |
-
|
| 11 |
-
Added `pricing_levels` field to the field mapping:
|
| 12 |
-
|
| 13 |
-
```python
|
| 14 |
-
CATALOGUE_FIELD_MAPPING = {
|
| 15 |
-
# ... existing fields ...
|
| 16 |
-
"pricing_levels": "pricing_levels" # JSON
|
| 17 |
-
}
|
| 18 |
-
```
|
| 19 |
-
|
| 20 |
-
### 2. Enhanced Sync Handler (`app/sync/catalogues/handler.py`)
|
| 21 |
-
|
| 22 |
-
#### Added JSON Import
|
| 23 |
-
```python
|
| 24 |
-
import json
|
| 25 |
-
```
|
| 26 |
-
|
| 27 |
-
#### Updated `extract_nested_fields()` Method
|
| 28 |
-
- Extracts `pricing_levels` as JSON from MongoDB document
|
| 29 |
-
- Falls back to legacy `pricing` for MRP if `pricing_levels` MRP is not available
|
| 30 |
-
- Preserves the complete pricing levels structure
|
| 31 |
-
|
| 32 |
-
#### Enhanced `transform_field_value()` Method
|
| 33 |
-
- Added special handling for `pricing_levels` field
|
| 34 |
-
- Validates JSON structure
|
| 35 |
-
- Handles string-to-JSON conversion if needed
|
| 36 |
-
- Provides error logging for invalid JSON
|
| 37 |
-
|
| 38 |
-
#### Updated `upsert_to_postgres()` Method
|
| 39 |
-
- Automatically creates `pricing_levels` JSON column if it doesn't exist
|
| 40 |
-
- Ensures backward compatibility with existing tables
|
| 41 |
-
|
| 42 |
-
### 3. Updated SQLAlchemy Model (`app/catalogues/models/model.py`)
|
| 43 |
-
|
| 44 |
-
Added `pricing_levels` column to the `CatalogueRef` model:
|
| 45 |
-
|
| 46 |
-
```python
|
| 47 |
-
from sqlalchemy import JSON # Added JSON import
|
| 48 |
-
|
| 49 |
-
class CatalogueRef(Base):
|
| 50 |
-
# ... existing columns ...
|
| 51 |
-
pricing_levels = Column(JSON)
|
| 52 |
-
```
|
| 53 |
-
|
| 54 |
-
### 4. Migration Scripts
|
| 55 |
-
|
| 56 |
-
#### Python Migration (`migration_add_pricing_levels_column.py`)
|
| 57 |
-
- Adds `pricing_levels` JSON column to existing tables
|
| 58 |
-
- Creates performance indexes on JSON fields
|
| 59 |
-
- Includes error handling and logging
|
| 60 |
-
|
| 61 |
-
#### SQL Migration (`migration_add_pricing_levels_column.sql`)
|
| 62 |
-
- Direct SQL commands for adding the column
|
| 63 |
-
- Creates GIN and BTREE indexes for optimal query performance
|
| 64 |
-
- Includes documentation comments
|
| 65 |
-
|
| 66 |
-
### 5. Test Script (`test_pricing_levels_sync.py`)
|
| 67 |
-
|
| 68 |
-
Comprehensive test that:
|
| 69 |
-
- Creates test catalogue with pricing_levels in MongoDB
|
| 70 |
-
- Tests the sync process
|
| 71 |
-
- Validates data integrity in PostgreSQL
|
| 72 |
-
- Verifies JSON structure and required fields
|
| 73 |
-
- Cleans up test data
|
| 74 |
-
|
| 75 |
-
## Pricing Levels Structure
|
| 76 |
-
|
| 77 |
-
The `pricing_levels` field stores JSON data with this structure:
|
| 78 |
-
|
| 79 |
-
```json
|
| 80 |
-
{
|
| 81 |
-
"currency": "INR",
|
| 82 |
-
"mrp": 399,
|
| 83 |
-
"levels": {
|
| 84 |
-
"retail": {
|
| 85 |
-
"purchase_price": 260,
|
| 86 |
-
"trade_margin": 20,
|
| 87 |
-
"selling_price": 299,
|
| 88 |
-
"retail_price": 349,
|
| 89 |
-
"retail_margin": 30,
|
| 90 |
-
"max_discount_pct": 15
|
| 91 |
-
},
|
| 92 |
-
"distributor": {
|
| 93 |
-
"purchase_price": 230,
|
| 94 |
-
"trade_margin": 25,
|
| 95 |
-
"selling_price": 279,
|
| 96 |
-
"retail_price": 349,
|
| 97 |
-
"retail_margin": 30,
|
| 98 |
-
"max_discount_pct": 20
|
| 99 |
-
}
|
| 100 |
-
}
|
| 101 |
-
}
|
| 102 |
-
```
|
| 103 |
-
|
| 104 |
-
## Database Indexes
|
| 105 |
-
|
| 106 |
-
The following indexes are created for optimal query performance:
|
| 107 |
-
|
| 108 |
-
1. **Currency Index**: `idx_catalogue_ref_pricing_levels_currency`
|
| 109 |
-
- GIN index on `pricing_levels->>'currency'`
|
| 110 |
-
- For filtering by currency
|
| 111 |
-
|
| 112 |
-
2. **MRP Index**: `idx_catalogue_ref_pricing_levels_mrp`
|
| 113 |
-
- BTREE index on `CAST(pricing_levels->>'mrp' AS NUMERIC)`
|
| 114 |
-
- For range queries on MRP values
|
| 115 |
-
|
| 116 |
-
3. **General JSON Index**: `idx_catalogue_ref_pricing_levels_gin`
|
| 117 |
-
- GIN index on entire `pricing_levels` JSON
|
| 118 |
-
- For complex JSON queries
|
| 119 |
-
|
| 120 |
-
## Usage Examples
|
| 121 |
-
|
| 122 |
-
### Query Catalogues with Specific Currency
|
| 123 |
-
```sql
|
| 124 |
-
SELECT catalogue_id, catalogue_name, pricing_levels
|
| 125 |
-
FROM trans.catalogue_ref
|
| 126 |
-
WHERE pricing_levels->>'currency' = 'INR';
|
| 127 |
-
```
|
| 128 |
-
|
| 129 |
-
### Query by MRP Range
|
| 130 |
-
```sql
|
| 131 |
-
SELECT catalogue_id, catalogue_name, pricing_levels
|
| 132 |
-
FROM trans.catalogue_ref
|
| 133 |
-
WHERE CAST(pricing_levels->>'mrp' AS NUMERIC) BETWEEN 100 AND 500;
|
| 134 |
-
```
|
| 135 |
-
|
| 136 |
-
### Query Specific Pricing Level
|
| 137 |
-
```sql
|
| 138 |
-
SELECT catalogue_id, catalogue_name,
|
| 139 |
-
pricing_levels->'levels'->'retail'->>'selling_price' as retail_price
|
| 140 |
-
FROM trans.catalogue_ref
|
| 141 |
-
WHERE pricing_levels->'levels' ? 'retail';
|
| 142 |
-
```
|
| 143 |
-
|
| 144 |
-
## Deployment Steps
|
| 145 |
-
|
| 146 |
-
1. **Run Migration**:
|
| 147 |
-
```bash
|
| 148 |
-
# Python migration
|
| 149 |
-
python migration_add_pricing_levels_column.py
|
| 150 |
-
|
| 151 |
-
# OR SQL migration
|
| 152 |
-
psql -d your_database -f migration_add_pricing_levels_column.sql
|
| 153 |
-
```
|
| 154 |
-
|
| 155 |
-
2. **Test Sync Process**:
|
| 156 |
-
```bash
|
| 157 |
-
python test_pricing_levels_sync.py
|
| 158 |
-
```
|
| 159 |
-
|
| 160 |
-
3. **Deploy Updated Code**:
|
| 161 |
-
- Deploy the updated sync handler and models
|
| 162 |
-
- Existing sync processes will automatically handle pricing_levels
|
| 163 |
-
|
| 164 |
-
## Backward Compatibility
|
| 165 |
-
|
| 166 |
-
- Existing catalogues without `pricing_levels` will continue to work
|
| 167 |
-
- Legacy `pricing` field is still supported for MRP extraction
|
| 168 |
-
- The sync process gracefully handles both old and new pricing structures
|
| 169 |
-
- No breaking changes to existing APIs
|
| 170 |
-
|
| 171 |
-
## Benefits
|
| 172 |
-
|
| 173 |
-
1. **Enhanced Pricing Support**: Full support for multi-level pricing structures
|
| 174 |
-
2. **Performance**: JSON indexes enable fast queries on pricing data
|
| 175 |
-
3. **Flexibility**: Easy to add new pricing levels without schema changes
|
| 176 |
-
4. **Data Integrity**: Proper validation and error handling
|
| 177 |
-
5. **Backward Compatibility**: Seamless transition from legacy pricing
|
| 178 |
-
|
| 179 |
-
## Monitoring
|
| 180 |
-
|
| 181 |
-
The sync process includes comprehensive logging:
|
| 182 |
-
- Successful pricing_levels extraction and storage
|
| 183 |
-
- JSON validation errors
|
| 184 |
-
- Database operation results
|
| 185 |
-
- Performance metrics
|
| 186 |
-
|
| 187 |
-
Check logs for entries with `entity_type: catalogue` and `pricing_levels` references.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/PROJECTION_LIST_IMPLEMENTATION.md
DELETED
|
@@ -1,231 +0,0 @@
|
|
| 1 |
-
# Projection List Implementation for SCM List Endpoints
|
| 2 |
-
|
| 3 |
-
## Overview
|
| 4 |
-
This document describes the implementation of projection list support for all list/fetch endpoints in the SCM microservice. The projection list feature allows clients to specify which fields they want to receive in the response, reducing payload size and improving performance.
|
| 5 |
-
|
| 6 |
-
## Implementation Pattern
|
| 7 |
-
|
| 8 |
-
### Request Schema
|
| 9 |
-
All list request schemas now include an optional `projection_list` field:
|
| 10 |
-
|
| 11 |
-
```python
|
| 12 |
-
projection_list: Optional[List[str]] = Field(
|
| 13 |
-
None,
|
| 14 |
-
description="List of fields to include in response (e.g., ['field1', 'field2'])"
|
| 15 |
-
)
|
| 16 |
-
```
|
| 17 |
-
|
| 18 |
-
### Service Layer
|
| 19 |
-
Services use MongoDB projection to fetch only requested fields:
|
| 20 |
-
|
| 21 |
-
```python
|
| 22 |
-
# Build projection dict for MongoDB
|
| 23 |
-
projection_dict = None
|
| 24 |
-
if projection_list:
|
| 25 |
-
projection_dict = {field: 1 for field in projection_list}
|
| 26 |
-
projection_dict["_id"] = 0 # Exclude MongoDB _id
|
| 27 |
-
|
| 28 |
-
# Query with projection
|
| 29 |
-
cursor = collection.find(query, projection_dict).skip(skip).limit(limit)
|
| 30 |
-
|
| 31 |
-
# Return raw dict if projection, otherwise return Pydantic model
|
| 32 |
-
if projection_list:
|
| 33 |
-
return documents # List[Dict]
|
| 34 |
-
else:
|
| 35 |
-
return [ResponseModel(**doc) for doc in documents] # List[ResponseModel]
|
| 36 |
-
```
|
| 37 |
-
|
| 38 |
-
### Controller Layer
|
| 39 |
-
Controllers pass projection_list to services and handle both dict and model responses:
|
| 40 |
-
|
| 41 |
-
```python
|
| 42 |
-
result = await Service.list_items(
|
| 43 |
-
filters=...,
|
| 44 |
-
projection_list=payload.projection_list
|
| 45 |
-
)
|
| 46 |
-
|
| 47 |
-
# If projection is used, return raw data
|
| 48 |
-
if payload.projection_list:
|
| 49 |
-
return result
|
| 50 |
-
else:
|
| 51 |
-
return [ResponseModel(**item) for item in result]
|
| 52 |
-
```
|
| 53 |
-
|
| 54 |
-
## Updated Endpoints
|
| 55 |
-
|
| 56 |
-
### 1. Catalogues
|
| 57 |
-
- **Endpoint**: `POST /catalogue/list`
|
| 58 |
-
- **Schema**: `CatalogueListFilter`
|
| 59 |
-
- **Service**: `CatalogueService.list_items()`
|
| 60 |
-
- **Example**:
|
| 61 |
-
```json
|
| 62 |
-
{
|
| 63 |
-
"filters": {"category": "Hair Care"},
|
| 64 |
-
"page": 1,
|
| 65 |
-
"page_size": 10,
|
| 66 |
-
"projection_list": ["catalogue_id", "catalogue_name", "pricing", "inventory"]
|
| 67 |
-
}
|
| 68 |
-
```
|
| 69 |
-
|
| 70 |
-
### 2. Employees
|
| 71 |
-
- **Endpoint**: `POST /employees/list`
|
| 72 |
-
- **Schema**: `EmployeeListRequest`
|
| 73 |
-
- **Service**: `EmployeeService.list_employees()`
|
| 74 |
-
- **Example**:
|
| 75 |
-
```json
|
| 76 |
-
{
|
| 77 |
-
"designation": "ASM",
|
| 78 |
-
"status": "active",
|
| 79 |
-
"skip": 0,
|
| 80 |
-
"limit": 100,
|
| 81 |
-
"projection_list": ["user_id", "employee_code", "first_name", "last_name", "email", "phone"]
|
| 82 |
-
}
|
| 83 |
-
```
|
| 84 |
-
|
| 85 |
-
### 3. Merchants
|
| 86 |
-
- **Endpoint**: `POST /merchants/list`
|
| 87 |
-
- **Schema**: `MerchantListRequest`
|
| 88 |
-
- **Service**: `MerchantService.list_merchants()`
|
| 89 |
-
- **Example**:
|
| 90 |
-
```json
|
| 91 |
-
{
|
| 92 |
-
"merchant_type": "distributor",
|
| 93 |
-
"status": "active",
|
| 94 |
-
"skip": 0,
|
| 95 |
-
"limit": 100,
|
| 96 |
-
"projection_list": ["merchant_id", "merchant_name", "merchant_type", "contact", "status"]
|
| 97 |
-
}
|
| 98 |
-
```
|
| 99 |
-
|
| 100 |
-
### 4. System Users
|
| 101 |
-
- **Endpoint**: `POST /system-users/list`
|
| 102 |
-
- **Schema**: `SystemUserListRequest`
|
| 103 |
-
- **Service**: `SystemUserService.list_users()`
|
| 104 |
-
- **Example**:
|
| 105 |
-
```json
|
| 106 |
-
{
|
| 107 |
-
"page": 1,
|
| 108 |
-
"page_size": 20,
|
| 109 |
-
"is_active": true,
|
| 110 |
-
"projection_list": ["user_id", "username", "email", "full_name", "role_id"]
|
| 111 |
-
}
|
| 112 |
-
```
|
| 113 |
-
|
| 114 |
-
### 5. Sales Orders
|
| 115 |
-
- **Endpoint**: `POST /sales/order/list`
|
| 116 |
-
- **Schema**: `SalesOrderListRequest`
|
| 117 |
-
- **Service**: `SalesOrderService.list_sales_orders()`
|
| 118 |
-
- **Example**:
|
| 119 |
-
```json
|
| 120 |
-
{
|
| 121 |
-
"filters": {"status": ["confirmed", "processing"]},
|
| 122 |
-
"pagination": {"page": 1, "limit": 20},
|
| 123 |
-
"sort": {"field": "order_date", "order": "desc"},
|
| 124 |
-
"projection_list": ["sales_order_id", "order_number", "customer", "summary", "status"]
|
| 125 |
-
}
|
| 126 |
-
```
|
| 127 |
-
|
| 128 |
-
### 6. RMA (Returns)
|
| 129 |
-
- **Endpoint**: `POST /rma/list`
|
| 130 |
-
- **Schema**: `RMAListRequest`
|
| 131 |
-
- **Service**: `RMAService.list_rmas()`
|
| 132 |
-
- **Example**:
|
| 133 |
-
```json
|
| 134 |
-
{
|
| 135 |
-
"status": "requested",
|
| 136 |
-
"skip": 0,
|
| 137 |
-
"limit": 100,
|
| 138 |
-
"projection_list": ["rma_id", "related_order_id", "requestor_id", "status", "requested_action"]
|
| 139 |
-
}
|
| 140 |
-
```
|
| 141 |
-
|
| 142 |
-
### 7. GRN (Goods Received Notes)
|
| 143 |
-
- **Endpoint**: `POST /grn/list`
|
| 144 |
-
- **Schema**: `GRNListRequest`
|
| 145 |
-
- **Service**: `GRNService.list_grns()`
|
| 146 |
-
- **Example**:
|
| 147 |
-
```json
|
| 148 |
-
{
|
| 149 |
-
"status": "completed",
|
| 150 |
-
"skip": 0,
|
| 151 |
-
"limit": 100,
|
| 152 |
-
"projection_list": ["grn_id", "po_id", "merchant_id", "status", "received_date"]
|
| 153 |
-
}
|
| 154 |
-
```
|
| 155 |
-
|
| 156 |
-
### 8. Merchant Settings
|
| 157 |
-
- **Endpoint**: `POST /merchant-settings/list`
|
| 158 |
-
- **Schema**: `MerchantSettingsListRequest`
|
| 159 |
-
- **Service**: `MerchantSettingsService.list_merchant_settings()`
|
| 160 |
-
- **Example**:
|
| 161 |
-
```json
|
| 162 |
-
{
|
| 163 |
-
"status_filter": "active",
|
| 164 |
-
"skip": 0,
|
| 165 |
-
"limit": 100,
|
| 166 |
-
"projection_list": ["merchant_id", "business_settings", "inventory_settings", "is_active"]
|
| 167 |
-
}
|
| 168 |
-
```
|
| 169 |
-
|
| 170 |
-
## Benefits
|
| 171 |
-
|
| 172 |
-
1. **Reduced Payload Size**: Clients can request only the fields they need, reducing network bandwidth
|
| 173 |
-
2. **Improved Performance**: MongoDB projection reduces data transfer from database
|
| 174 |
-
3. **Flexible API**: Clients can optimize their queries based on use case
|
| 175 |
-
4. **Simplified API**: Single POST endpoint per resource with optional projection support
|
| 176 |
-
|
| 177 |
-
## Usage Guidelines
|
| 178 |
-
|
| 179 |
-
### When to Use Projection
|
| 180 |
-
- **List views**: Request only fields needed for display (e.g., ID, name, status)
|
| 181 |
-
- **Mobile apps**: Minimize data transfer for bandwidth-constrained environments
|
| 182 |
-
- **Dashboard widgets**: Fetch only aggregated or summary fields
|
| 183 |
-
- **Export operations**: Select specific fields for CSV/Excel exports
|
| 184 |
-
|
| 185 |
-
### When NOT to Use Projection
|
| 186 |
-
- **Detail views**: Fetch complete records for full detail pages
|
| 187 |
-
- **Create/Update operations**: Always fetch complete records for editing
|
| 188 |
-
- **Complex nested data**: Projection may not work well with deeply nested structures
|
| 189 |
-
|
| 190 |
-
### Best Practices
|
| 191 |
-
1. Always include the primary key field (e.g., `user_id`, `merchant_id`)
|
| 192 |
-
2. Request related fields together (e.g., if requesting `first_name`, also request `last_name`)
|
| 193 |
-
3. Test projection queries to ensure all required fields are included
|
| 194 |
-
4. Document which fields are commonly used together in your API documentation
|
| 195 |
-
|
| 196 |
-
## API Design
|
| 197 |
-
|
| 198 |
-
- All list endpoints use POST method to support complex request bodies
|
| 199 |
-
- Projection is optional - omit `projection_list` to get full objects
|
| 200 |
-
- When projection is used, returns raw dictionaries for maximum flexibility
|
| 201 |
-
- When projection is omitted, returns typed Pydantic models for validation
|
| 202 |
-
|
| 203 |
-
## Testing
|
| 204 |
-
|
| 205 |
-
Test projection with various field combinations:
|
| 206 |
-
|
| 207 |
-
```bash
|
| 208 |
-
# Test with projection
|
| 209 |
-
curl -X POST http://localhost:8000/employees/list \
|
| 210 |
-
-H "Content-Type: application/json" \
|
| 211 |
-
-d '{
|
| 212 |
-
"skip": 0,
|
| 213 |
-
"limit": 10,
|
| 214 |
-
"projection_list": ["user_id", "first_name", "email"]
|
| 215 |
-
}'
|
| 216 |
-
|
| 217 |
-
# Test without projection (returns full objects)
|
| 218 |
-
curl -X POST http://localhost:8000/employees/list \
|
| 219 |
-
-H "Content-Type: application/json" \
|
| 220 |
-
-d '{
|
| 221 |
-
"skip": 0,
|
| 222 |
-
"limit": 10
|
| 223 |
-
}'
|
| 224 |
-
```
|
| 225 |
-
|
| 226 |
-
## Future Enhancements
|
| 227 |
-
|
| 228 |
-
1. **Nested Field Projection**: Support dot notation for nested fields (e.g., `"contact.email"`)
|
| 229 |
-
2. **Field Aliases**: Allow clients to rename fields in response
|
| 230 |
-
3. **Computed Fields**: Support projection of calculated/derived fields
|
| 231 |
-
4. **Projection Presets**: Define common projection patterns (e.g., "summary", "detail", "minimal")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/PURCHASES_MODULE_IMPLEMENTATION.md
DELETED
|
@@ -1,272 +0,0 @@
|
|
| 1 |
-
# SCM Purchases Module - Complete Implementation
|
| 2 |
-
|
| 3 |
-
## Overview
|
| 4 |
-
Complete implementation of the Purchases module for the SCM system, including Purchase Orders (PO) and Goods Receipt Notes (GRN) with full PostgreSQL support, async operations, and projection list compliance.
|
| 5 |
-
|
| 6 |
-
## Architecture
|
| 7 |
-
|
| 8 |
-
### Folder Structure
|
| 9 |
-
```
|
| 10 |
-
purchases/
|
| 11 |
-
├── orders/ # Purchase Orders (PO)
|
| 12 |
-
│ ├── controllers/
|
| 13 |
-
│ │ └── router.py # FastAPI routes
|
| 14 |
-
│ ├── services/
|
| 15 |
-
│ │ └── service.py # Business logic
|
| 16 |
-
│ ├── models/
|
| 17 |
-
│ │ └── model.py # Model imports
|
| 18 |
-
│ ├── schemas/
|
| 19 |
-
│ │ └── schema.py # Pydantic schemas
|
| 20 |
-
│ └── __init__.py
|
| 21 |
-
├── receipts/ # Goods Receipt Notes (GRN)
|
| 22 |
-
│ ├── controllers/
|
| 23 |
-
│ │ └── router.py # FastAPI routes
|
| 24 |
-
│ ├── services/
|
| 25 |
-
│ │ └── service.py # Business logic
|
| 26 |
-
│ ├── models/
|
| 27 |
-
│ │ └── model.py # Model imports
|
| 28 |
-
│ ├── schemas/
|
| 29 |
-
│ │ └── schema.py # Pydantic schemas
|
| 30 |
-
│ └── __init__.py
|
| 31 |
-
└── __init__.py
|
| 32 |
-
```
|
| 33 |
-
|
| 34 |
-
## Database Schema (PostgreSQL)
|
| 35 |
-
|
| 36 |
-
### Purchase Orders
|
| 37 |
-
- **scm_po**: PO header with buyer/supplier, dates, amounts, status
|
| 38 |
-
- **scm_po_item**: PO line items with quantities, pricing
|
| 39 |
-
- **scm_po_status_log**: Audit trail for status changes
|
| 40 |
-
|
| 41 |
-
### Goods Receipt Notes
|
| 42 |
-
- **scm_grn**: GRN header with receiver, supplier, location
|
| 43 |
-
- **scm_grn_item**: GRN items with batch info, QC status
|
| 44 |
-
- **scm_grn_issue**: Quality/quantity issues tracking
|
| 45 |
-
|
| 46 |
-
## API Endpoints
|
| 47 |
-
|
| 48 |
-
### Purchase Orders
|
| 49 |
-
- `POST /purchases/orders` - Create PO
|
| 50 |
-
- `GET /purchases/orders/{po_id}` - Get PO by ID
|
| 51 |
-
- `POST /purchases/orders/list` - List POs with projection support ✅
|
| 52 |
-
- `POST /purchases/orders/{po_id}/submit` - Submit for approval
|
| 53 |
-
- `POST /purchases/orders/{po_id}/approve` - Approve PO
|
| 54 |
-
- `POST /purchases/orders/{po_id}/cancel` - Cancel PO
|
| 55 |
-
- `POST /purchases/orders/{po_id}/dispatch` - Mark as dispatched
|
| 56 |
-
|
| 57 |
-
### Goods Receipt Notes
|
| 58 |
-
- `POST /purchases/receipts` - Create GRN
|
| 59 |
-
- `GET /purchases/receipts/{grn_id}` - Get GRN by ID
|
| 60 |
-
- `POST /purchases/receipts/list` - List GRNs with projection support ✅
|
| 61 |
-
- `POST /purchases/receipts/{grn_id}/accept` - Accept GRN
|
| 62 |
-
- `POST /purchases/receipts/{grn_id}/reject` - Reject GRN
|
| 63 |
-
- `POST /purchases/receipts/{grn_id}/close` - Close GRN
|
| 64 |
-
- `POST /purchases/receipts/issues` - Add quality issues
|
| 65 |
-
|
| 66 |
-
## Key Features
|
| 67 |
-
|
| 68 |
-
### ✅ Projection List Support
|
| 69 |
-
Both PO and GRN list endpoints implement the mandatory projection list standard:
|
| 70 |
-
- Optional `projection_list` parameter in request schemas
|
| 71 |
-
- PostgreSQL field selection for performance
|
| 72 |
-
- Raw dict response when projection used
|
| 73 |
-
- Full model response otherwise
|
| 74 |
-
|
| 75 |
-
### ✅ Business Rules Enforcement
|
| 76 |
-
- **PO Status Flow**: draft → submitted → approved → dispatched → partial_received → closed
|
| 77 |
-
- **GRN Status Flow**: received → accepted/rejected → closed
|
| 78 |
-
- **Quantity Validation**: acc_qty + rej_qty = recv_qty
|
| 79 |
-
- **Business Logic**: Buyer-supplier transaction validation
|
| 80 |
-
|
| 81 |
-
### ✅ Role-Based Access Control
|
| 82 |
-
- `role_procurement_user` - Create/submit POs
|
| 83 |
-
- `role_procurement_approver` - Approve POs
|
| 84 |
-
- `role_warehouse_user` - Dispatch POs, close GRNs
|
| 85 |
-
- `role_qc_user` - Accept/reject GRNs, report issues
|
| 86 |
-
|
| 87 |
-
### ✅ Async PostgreSQL Operations
|
| 88 |
-
- Full async/await support with SQLAlchemy
|
| 89 |
-
- Connection pooling and proper session management
|
| 90 |
-
- Transaction safety with rollback support
|
| 91 |
-
- Performance optimized queries with selectinload
|
| 92 |
-
|
| 93 |
-
### ✅ Comprehensive Logging
|
| 94 |
-
- Structured logging with insightfy_utils
|
| 95 |
-
- Performance metrics (duration tracking)
|
| 96 |
-
- Business event logging
|
| 97 |
-
- Error tracking with context
|
| 98 |
-
|
| 99 |
-
### ✅ Data Validation
|
| 100 |
-
- Pydantic schemas with field validation
|
| 101 |
-
- Business rule validation in services
|
| 102 |
-
- Referential integrity checks
|
| 103 |
-
- Quantity and status transition validation
|
| 104 |
-
|
| 105 |
-
## Status Lifecycles
|
| 106 |
-
|
| 107 |
-
### Purchase Order States
|
| 108 |
-
```
|
| 109 |
-
draft → submitted → approved → dispatched → partial_received → closed
|
| 110 |
-
↓ ↓ ↓ ↓ ↓
|
| 111 |
-
cancelled cancelled cancelled cancelled cancelled
|
| 112 |
-
```
|
| 113 |
-
|
| 114 |
-
### GRN States
|
| 115 |
-
```
|
| 116 |
-
received → accepted → closed
|
| 117 |
-
↓ ↓
|
| 118 |
-
rejected → closed
|
| 119 |
-
```
|
| 120 |
-
|
| 121 |
-
## Integration Points
|
| 122 |
-
|
| 123 |
-
### Current Integrations
|
| 124 |
-
- **Auth Service**: User authentication and role validation
|
| 125 |
-
- **Centralized Models**: Uses `app.models.po_grn_model`
|
| 126 |
-
- **PostgreSQL**: Async database operations
|
| 127 |
-
|
| 128 |
-
### Future Integrations
|
| 129 |
-
- **Merchant Service**: Validate can_transact_with relationships
|
| 130 |
-
- **Catalogue Service**: SKU validation and batch rules
|
| 131 |
-
- **Inventory Service**: Stock posting on GRN acceptance
|
| 132 |
-
|
| 133 |
-
## Error Handling
|
| 134 |
-
|
| 135 |
-
### Validation Errors (400)
|
| 136 |
-
- Invalid status transitions
|
| 137 |
-
- Quantity validation failures
|
| 138 |
-
- Business rule violations
|
| 139 |
-
- Duplicate PO/GRN numbers
|
| 140 |
-
|
| 141 |
-
### Authorization Errors (403)
|
| 142 |
-
- Insufficient role permissions
|
| 143 |
-
- Access denied responses
|
| 144 |
-
|
| 145 |
-
### Not Found Errors (404)
|
| 146 |
-
- PO/GRN not found
|
| 147 |
-
- Invalid references
|
| 148 |
-
|
| 149 |
-
### Server Errors (500)
|
| 150 |
-
- Database connection issues
|
| 151 |
-
- Unexpected exceptions with logging
|
| 152 |
-
|
| 153 |
-
## Performance Features
|
| 154 |
-
|
| 155 |
-
### Database Optimization
|
| 156 |
-
- Proper indexing on foreign keys
|
| 157 |
-
- Selective field loading with projection
|
| 158 |
-
- Pagination support
|
| 159 |
-
- Connection pooling
|
| 160 |
-
|
| 161 |
-
### Response Optimization
|
| 162 |
-
- Field projection reduces payload by 50-90%
|
| 163 |
-
- Async operations prevent blocking
|
| 164 |
-
- Structured logging for monitoring
|
| 165 |
-
- Efficient query patterns
|
| 166 |
-
|
| 167 |
-
## Testing Considerations
|
| 168 |
-
|
| 169 |
-
### Unit Tests Needed
|
| 170 |
-
- Service layer business logic
|
| 171 |
-
- Status transition validation
|
| 172 |
-
- Quantity calculations
|
| 173 |
-
- Error handling scenarios
|
| 174 |
-
|
| 175 |
-
### Integration Tests Needed
|
| 176 |
-
- Database operations
|
| 177 |
-
- API endpoint responses
|
| 178 |
-
- Authentication flows
|
| 179 |
-
- Cross-service integrations
|
| 180 |
-
|
| 181 |
-
## Deployment Notes
|
| 182 |
-
|
| 183 |
-
### Environment Variables
|
| 184 |
-
- PostgreSQL connection settings
|
| 185 |
-
- Authentication service URLs
|
| 186 |
-
- Logging configuration
|
| 187 |
-
- Role definitions
|
| 188 |
-
|
| 189 |
-
### Database Migration
|
| 190 |
-
- Tables created via SQLAlchemy metadata
|
| 191 |
-
- Indexes for performance
|
| 192 |
-
- Foreign key constraints
|
| 193 |
-
- Initial data seeding
|
| 194 |
-
|
| 195 |
-
## Usage Examples
|
| 196 |
-
|
| 197 |
-
### Create Purchase Order
|
| 198 |
-
```python
|
| 199 |
-
POST /purchases/orders
|
| 200 |
-
{
|
| 201 |
-
// po_no is optional - auto-generated if not provided
|
| 202 |
-
"buyer_id": "merchant_123",
|
| 203 |
-
"buyer_type": "distributor",
|
| 204 |
-
"supplier_id": "supplier_456",
|
| 205 |
-
"supplier_type": "manufacturer",
|
| 206 |
-
"items": [
|
| 207 |
-
{
|
| 208 |
-
"catalogue_id": "cat_789",
|
| 209 |
-
"sku": "SHAMPOO-500ML",
|
| 210 |
-
"ord_qty": 100,
|
| 211 |
-
"uom": "pieces",
|
| 212 |
-
"unit_price": 25.50
|
| 213 |
-
}
|
| 214 |
-
],
|
| 215 |
-
"created_by": "user_123"
|
| 216 |
-
}
|
| 217 |
-
```
|
| 218 |
-
|
| 219 |
-
### Auto-Generated Numbers
|
| 220 |
-
- **PO Numbers**: Format `PO-YYYY-NNNNNN` (e.g., `PO-2024-000001`)
|
| 221 |
-
- **GRN Numbers**: Format `GRN-YYYY-NNNNNN` (e.g., `GRN-2024-000001`)
|
| 222 |
-
- Uses PostgreSQL sequences for thread-safe generation
|
| 223 |
-
- Custom prefixes supported for special cases
|
| 224 |
-
|
| 225 |
-
### List with Projection
|
| 226 |
-
```python
|
| 227 |
-
POST /purchases/orders/list
|
| 228 |
-
{
|
| 229 |
-
"filters": {"status": ["approved", "dispatched"]},
|
| 230 |
-
"page": 1,
|
| 231 |
-
"page_size": 20,
|
| 232 |
-
"projection_list": ["po_id", "po_no", "status", "total_amt"]
|
| 233 |
-
}
|
| 234 |
-
```
|
| 235 |
-
|
| 236 |
-
### Create GRN
|
| 237 |
-
```python
|
| 238 |
-
POST /purchases/receipts
|
| 239 |
-
{
|
| 240 |
-
"grn_no": "GRN-2024-001",
|
| 241 |
-
"po_id": "po_uuid_here",
|
| 242 |
-
"receiver_id": "warehouse_123",
|
| 243 |
-
"supplier_id": "supplier_456",
|
| 244 |
-
"items": [
|
| 245 |
-
{
|
| 246 |
-
"po_item_id": "po_item_uuid",
|
| 247 |
-
"catalogue_id": "cat_789",
|
| 248 |
-
"sku": "SHAMPOO-500ML",
|
| 249 |
-
"recv_qty": 95,
|
| 250 |
-
"acc_qty": 90,
|
| 251 |
-
"rej_qty": 5,
|
| 252 |
-
"uom": "pieces",
|
| 253 |
-
"batch_no": "BATCH-2024-001"
|
| 254 |
-
}
|
| 255 |
-
],
|
| 256 |
-
"created_by": "user_123"
|
| 257 |
-
}
|
| 258 |
-
```
|
| 259 |
-
|
| 260 |
-
## Summary
|
| 261 |
-
|
| 262 |
-
The Purchases module is now fully implemented with:
|
| 263 |
-
- ✅ Complete PostgreSQL async operations
|
| 264 |
-
- ✅ Projection list standard compliance
|
| 265 |
-
- ✅ Role-based access control
|
| 266 |
-
- ✅ Comprehensive business logic
|
| 267 |
-
- ✅ Status lifecycle management
|
| 268 |
-
- ✅ Error handling and logging
|
| 269 |
-
- ✅ Performance optimization
|
| 270 |
-
- ✅ Clean layered architecture
|
| 271 |
-
|
| 272 |
-
The implementation follows all SCM standards and is ready for production use.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/SCM_POSTGRESQL_PO_GRN_IMPLEMENTATION.md
DELETED
|
@@ -1,169 +0,0 @@
|
|
| 1 |
-
# SCM PostgreSQL PO/GRN Implementation Summary
|
| 2 |
-
|
| 3 |
-
## ✅ COMPLETED IMPLEMENTATION
|
| 4 |
-
|
| 5 |
-
### 📦 Consolidated Schema Implementation
|
| 6 |
-
- **Tables Created**: Following the consolidated schema with clean snake_case naming
|
| 7 |
-
- `scm_po` - Purchase Order header
|
| 8 |
-
- `scm_po_item` - Purchase Order line items
|
| 9 |
-
- `scm_po_status_log` - PO lifecycle audit trail
|
| 10 |
-
- `scm_grn` - Goods Receipt Note header
|
| 11 |
-
- `scm_grn_item` - GRN items with merged batch tracking
|
| 12 |
-
- `scm_grn_issue` - GRN discrepancies/QC issues
|
| 13 |
-
|
| 14 |
-
### 🏗️ Architecture Components
|
| 15 |
-
|
| 16 |
-
#### 1. **Models** (`app/models/po_grn_model.py`)
|
| 17 |
-
- SQLAlchemy models with proper relationships
|
| 18 |
-
- UUID primary keys for all tables
|
| 19 |
-
- Proper foreign key constraints with CASCADE
|
| 20 |
-
- Business rule validation ready
|
| 21 |
-
- Audit fields (created_at, updated_at, created_by)
|
| 22 |
-
|
| 23 |
-
#### 2. **Repository Layer** (`app/repositories/scm_po_grn_repository.py`)
|
| 24 |
-
- `ScmPoRepository` - Purchase Order operations
|
| 25 |
-
- `ScmGrnRepository` - Goods Receipt operations
|
| 26 |
-
- **Projection List Support** - PostgreSQL column selection for performance
|
| 27 |
-
- ACID transaction support
|
| 28 |
-
- Auto-status updates based on receipt completion
|
| 29 |
-
- Business rule validation (acc_qty + rej_qty = recv_qty)
|
| 30 |
-
|
| 31 |
-
#### 3. **Service Layer** (`app/services/po_grn_service.py`)
|
| 32 |
-
- `ScmPurchaseOrderService` - PO business logic
|
| 33 |
-
- `ScmGoodsReceiptService` - GRN business logic
|
| 34 |
-
- Auto-generation of PO/GRN numbers
|
| 35 |
-
- Merchant hierarchy validation
|
| 36 |
-
- Status workflow management
|
| 37 |
-
|
| 38 |
-
#### 4. **Router Layer** (`app/routers/po_grn_router.py`)
|
| 39 |
-
- RESTful endpoints following API standards
|
| 40 |
-
- **POST method for list endpoints** (as per steering rules)
|
| 41 |
-
- Projection list support for performance optimization
|
| 42 |
-
- Comprehensive error handling and logging
|
| 43 |
-
- Dashboard widget endpoints
|
| 44 |
-
|
| 45 |
-
### 🔧 Key Features Implemented
|
| 46 |
-
|
| 47 |
-
#### ✅ **API Standards Compliance**
|
| 48 |
-
- **POST `/purchase-orders-pg/list`** - List POs with projection support
|
| 49 |
-
- **POST `/purchase-orders-pg/grn/list`** - List GRNs with projection support
|
| 50 |
-
- Optional `projection_list` parameter for 50-90% payload reduction
|
| 51 |
-
- Consistent response format across all endpoints
|
| 52 |
-
|
| 53 |
-
#### ✅ **Business Logic**
|
| 54 |
-
- Auto-generation of PO/GRN numbers with merchant prefix
|
| 55 |
-
- Status workflow: draft → submitted → approved → dispatched → partial_received → closed
|
| 56 |
-
- Automatic PO status updates based on GRN receipts
|
| 57 |
-
- Batch tracking with expiry date management
|
| 58 |
-
- QC status tracking and issue management
|
| 59 |
-
|
| 60 |
-
#### ✅ **Performance Optimizations**
|
| 61 |
-
- PostgreSQL indexes on critical fields (buyer_id, supplier_id, status, sku, batch_no)
|
| 62 |
-
- Connection pooling with proper timeout settings
|
| 63 |
-
- Projection support for reduced network bandwidth
|
| 64 |
-
- Efficient query patterns with proper joins
|
| 65 |
-
|
| 66 |
-
#### ✅ **ACID Compliance**
|
| 67 |
-
- Transactional integrity for PO creation with items
|
| 68 |
-
- Status log audit trail for all changes
|
| 69 |
-
- Proper rollback on errors
|
| 70 |
-
- Consistent data state maintenance
|
| 71 |
-
|
| 72 |
-
### 📊 Database Indexes Created
|
| 73 |
-
```sql
|
| 74 |
-
-- Purchase Order indexes
|
| 75 |
-
CREATE INDEX idx_scm_po_buyer ON scm_po (buyer_id);
|
| 76 |
-
CREATE INDEX idx_scm_po_supplier ON scm_po (supplier_id);
|
| 77 |
-
CREATE INDEX idx_scm_po_status ON scm_po (status);
|
| 78 |
-
|
| 79 |
-
-- PO Item indexes
|
| 80 |
-
CREATE INDEX idx_po_item_po ON scm_po_item (po_id);
|
| 81 |
-
|
| 82 |
-
-- GRN indexes
|
| 83 |
-
CREATE INDEX idx_grn_po ON scm_grn (po_id);
|
| 84 |
-
|
| 85 |
-
-- GRN Item indexes
|
| 86 |
-
CREATE INDEX idx_grn_item_grn ON scm_grn_item (grn_id);
|
| 87 |
-
CREATE INDEX idx_grn_item_po_item ON scm_grn_item (po_item_id);
|
| 88 |
-
CREATE INDEX idx_grn_item_sku ON scm_grn_item (sku);
|
| 89 |
-
CREATE INDEX idx_grn_item_batch ON scm_grn_item (batch_no);
|
| 90 |
-
CREATE INDEX idx_grn_item_exp ON scm_grn_item (exp_dt);
|
| 91 |
-
```
|
| 92 |
-
|
| 93 |
-
### 🚀 API Endpoints Available
|
| 94 |
-
|
| 95 |
-
#### Purchase Orders
|
| 96 |
-
- `POST /purchase-orders-pg/order` - Create PO
|
| 97 |
-
- `GET /purchase-orders-pg/order/{order_id}` - Get PO details
|
| 98 |
-
- `PUT /purchase-orders-pg/order/{order_id}` - Update PO
|
| 99 |
-
- `POST /purchase-orders-pg/order/{order_id}/submit` - Submit PO for approval
|
| 100 |
-
- `POST /purchase-orders-pg/list` - List POs with projection support ⭐
|
| 101 |
-
- `GET /purchase-orders-pg/order/{order_id}/receipts` - List GRNs for PO
|
| 102 |
-
- `GET /purchase-orders-pg/info/widgets` - Dashboard widgets
|
| 103 |
-
|
| 104 |
-
#### Goods Receipt Notes
|
| 105 |
-
- `POST /purchase-orders-pg/grn` - Create GRN
|
| 106 |
-
- `GET /purchase-orders-pg/grn/{grn_id}` - Get GRN details
|
| 107 |
-
- `POST /purchase-orders-pg/grn/list` - List GRNs with projection support ⭐
|
| 108 |
-
- `POST /purchase-orders-pg/grn/{grn_id}/items/{item_id}/batch` - Add issue to GRN item
|
| 109 |
-
- `GET /purchase-orders-pg/grn/info/widgets` - GRN dashboard widgets
|
| 110 |
-
|
| 111 |
-
### 🎯 Business Rules Implemented
|
| 112 |
-
|
| 113 |
-
1. **PO Creation**:
|
| 114 |
-
- Auto-generates PO number: `PO-{merchant_id}-{YYYYMM}-{random}`
|
| 115 |
-
- Validates merchant hierarchy (buyer/supplier relationship)
|
| 116 |
-
- Creates audit log entry on status changes
|
| 117 |
-
|
| 118 |
-
2. **GRN Processing**:
|
| 119 |
-
- Validates against existing PO
|
| 120 |
-
- Enforces: `acc_qty + rej_qty = recv_qty`
|
| 121 |
-
- Updates PO item received quantities
|
| 122 |
-
- Auto-updates PO status (partial_received/closed)
|
| 123 |
-
- Batch tracking with manufacturing/expiry dates
|
| 124 |
-
|
| 125 |
-
3. **Status Workflow**:
|
| 126 |
-
- PO: draft → submitted → approved → dispatched → partial_received → closed → cancelled
|
| 127 |
-
- GRN: draft → received → partial_accept → accepted → rejected → closed
|
| 128 |
-
|
| 129 |
-
### 📈 Performance Benefits
|
| 130 |
-
|
| 131 |
-
- **50-90% payload reduction** with projection lists
|
| 132 |
-
- **ACID transactions** for data consistency
|
| 133 |
-
- **Connection pooling** for better resource utilization
|
| 134 |
-
- **Indexed queries** for fast lookups
|
| 135 |
-
- **Batch operations** for bulk processing
|
| 136 |
-
|
| 137 |
-
### 🔄 Integration Points
|
| 138 |
-
|
| 139 |
-
- **Auth Service**: JWT token validation for user context
|
| 140 |
-
- **Catalogue Service**: SKU validation and product details
|
| 141 |
-
- **Merchant Service**: Hierarchy validation (can_transact_with)
|
| 142 |
-
- **Inventory Service**: Ready for stock ledger integration
|
| 143 |
-
|
| 144 |
-
### 🧪 Testing Ready
|
| 145 |
-
|
| 146 |
-
The implementation is ready for testing with:
|
| 147 |
-
- Unit tests for business logic
|
| 148 |
-
- Integration tests for database operations
|
| 149 |
-
- API endpoint testing
|
| 150 |
-
- Performance benchmarking
|
| 151 |
-
|
| 152 |
-
### 🎉 Migration Complete
|
| 153 |
-
|
| 154 |
-
✅ **MongoDB → PostgreSQL migration completed**
|
| 155 |
-
✅ **TMS pattern implementation**
|
| 156 |
-
✅ **API standards compliance**
|
| 157 |
-
✅ **Projection list support**
|
| 158 |
-
✅ **Business rules enforcement**
|
| 159 |
-
✅ **ACID transaction support**
|
| 160 |
-
|
| 161 |
-
The SCM microservice now has a robust, scalable PostgreSQL-based PO/GRN system that follows enterprise patterns and provides excellent performance with projection support.
|
| 162 |
-
|
| 163 |
-
## Next Steps (Optional)
|
| 164 |
-
|
| 165 |
-
1. **Inventory Integration**: Connect to stock ledger for real-time inventory updates
|
| 166 |
-
2. **RMA Module**: Returns management against GRN items
|
| 167 |
-
3. **Credit Notes**: GST-compliant credit note generation
|
| 168 |
-
4. **Advanced Analytics**: Reporting and dashboard enhancements
|
| 169 |
-
5. **Batch Expiry Alerts**: Automated notifications for expiring batches
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/SOLUTION_SUMMARY.md
DELETED
|
@@ -1,199 +0,0 @@
|
|
| 1 |
-
# ✅ Enhanced retail Catalogue Implementation - COMPLETE
|
| 2 |
-
|
| 3 |
-
## 🎯 **SOLUTION DELIVERED**
|
| 4 |
-
|
| 5 |
-
Successfully implemented enhanced retail catalogue data with the exact structure you requested, including full projection list support and dual database synchronization.
|
| 6 |
-
|
| 7 |
-
## 📊 **CURRENT STATUS**
|
| 8 |
-
|
| 9 |
-
### **MongoDB (Primary Storage)**
|
| 10 |
-
- ✅ **10 catalogues** with enhanced structure
|
| 11 |
-
- ✅ **Multi-level pricing**: ncnf, cnf, distributor, retail
|
| 12 |
-
- ✅ **Multi-level inventory**: Different configurations per merchant type
|
| 13 |
-
- ✅ **Complete product data**: L'Oréal, Matrix, Schwarzkopf products
|
| 14 |
-
|
| 15 |
-
### **PostgreSQL (Reference & Performance)**
|
| 16 |
-
- ✅ **5 catalogues** fully synced with pricing JSON
|
| 17 |
-
- ✅ **Enhanced pricing data** stored as JSON
|
| 18 |
-
- ✅ **Essential fields** extracted for fast queries
|
| 19 |
-
- ✅ **Merchant filtering** working correctly
|
| 20 |
-
|
| 21 |
-
## 🏗️ **ARCHITECTURE IMPLEMENTED**
|
| 22 |
-
|
| 23 |
-
### **1. Enhanced Data Structure**
|
| 24 |
-
```json
|
| 25 |
-
{
|
| 26 |
-
"pricing": {
|
| 27 |
-
"currency": "INR",
|
| 28 |
-
"mrp": 1850,
|
| 29 |
-
"levels": {
|
| 30 |
-
"ncnf": {"cost_price": 1628.0, "trade_margin": 12, "max_discount_pct": 0},
|
| 31 |
-
"cnf": {"cost_price": 1739.0, "trade_margin": 6, "max_discount_pct": 0},
|
| 32 |
-
"distributor": {"cost_price": 1665.0, "trade_margin": 10, "max_discount_pct": 0},
|
| 33 |
-
"retail": {"cost_price": 1480.0, "trade_margin": 20, "max_discount_pct": 0}
|
| 34 |
-
}
|
| 35 |
-
},
|
| 36 |
-
"inventory": {
|
| 37 |
-
"unit": "PCS",
|
| 38 |
-
"levels": {
|
| 39 |
-
"ncnf": {"reorder_level": 500, "reorder_quantity": 1000, "safety_stock": 200},
|
| 40 |
-
"cnf": {"reorder_level": 200, "reorder_quantity": 500, "safety_stock": 100},
|
| 41 |
-
"distributor": {"reorder_level": 50, "reorder_quantity": 100, "safety_stock": 20},
|
| 42 |
-
"retail": {"reorder_level": 10, "reorder_quantity": 20, "safety_stock": 5}
|
| 43 |
-
}
|
| 44 |
-
}
|
| 45 |
-
}
|
| 46 |
-
```
|
| 47 |
-
|
| 48 |
-
### **2. API Endpoints with Projection Support**
|
| 49 |
-
|
| 50 |
-
#### **Catalogue APIs**
|
| 51 |
-
- ✅ `POST /catalogue/list` - List with projection
|
| 52 |
-
- ✅ `POST /catalogue/lazy-fetch` - Lazy loading with projection
|
| 53 |
-
- ✅ `POST /catalogue/merchant-catalogue/list` - Merchant-specific with projection
|
| 54 |
-
- ✅ `GET /catalogue/{id}` - Single item with projection
|
| 55 |
-
- ✅ `POST /catalogue/{id}/details` - POST method with projection
|
| 56 |
-
|
| 57 |
-
#### **Inventory APIs**
|
| 58 |
-
- ✅ `POST /inventory/stock/list` - Stock list with projection
|
| 59 |
-
- ✅ `POST /inventory/stock/ledger/list` - Ledger with projection
|
| 60 |
-
- ✅ `POST /inventory/stock/summary` - Summary with projection
|
| 61 |
-
- ✅ `POST /inventory/stock/availability/check` - Availability check
|
| 62 |
-
- ✅ `POST /inventory/stock/valuation` - Valuation with projection
|
| 63 |
-
|
| 64 |
-
### **3. Performance Benefits**
|
| 65 |
-
|
| 66 |
-
| Projection Type | Payload Size | Reduction |
|
| 67 |
-
|----------------|--------------|-----------|
|
| 68 |
-
| **Full Document** | ~2000+ bytes | 0% |
|
| 69 |
-
| **Basic Info** | 132 bytes | **90%** |
|
| 70 |
-
| **Pricing Only** | 497 bytes | **75%** |
|
| 71 |
-
| **Inventory Only** | 671 bytes | **66%** |
|
| 72 |
-
|
| 73 |
-
## 🔧 **SCRIPTS CREATED**
|
| 74 |
-
|
| 75 |
-
### **Data Generation**
|
| 76 |
-
- `create_enhanced_retail_catalogues.py` - Main data generator
|
| 77 |
-
- `run_enhanced_catalogue_generation.py` - Simple runner
|
| 78 |
-
- `enhanced_retail_catalogues_data.json` - Sample JSON data
|
| 79 |
-
|
| 80 |
-
### **Database Management**
|
| 81 |
-
- `fix_missing_postgres_records.py` - Sync missing records
|
| 82 |
-
- `update_postgres_pricing.py` - Update pricing data
|
| 83 |
-
- `check_postgres_duplicates.py` - Clean duplicates
|
| 84 |
-
|
| 85 |
-
### **Testing & Verification**
|
| 86 |
-
- `verify_enhanced_data.py` - Data structure verification
|
| 87 |
-
- `test_enhanced_catalogue_apis.py` - API testing suite
|
| 88 |
-
|
| 89 |
-
## 🎯 **API TESTING EXAMPLES**
|
| 90 |
-
|
| 91 |
-
### **Catalogue List with Projection**
|
| 92 |
-
```bash
|
| 93 |
-
curl -X POST "http://localhost:8000/catalogue/list" \
|
| 94 |
-
-H "Content-Type: application/json" \
|
| 95 |
-
-d '{
|
| 96 |
-
"filters": {"merchant_id": "company_cuatro_beauty_ltd"},
|
| 97 |
-
"projection_list": ["catalogue_id", "catalogue_name", "pricing"],
|
| 98 |
-
"limit": 5
|
| 99 |
-
}'
|
| 100 |
-
```
|
| 101 |
-
|
| 102 |
-
### **Inventory Stock List**
|
| 103 |
-
```bash
|
| 104 |
-
curl -X POST "http://localhost:8000/inventory/stock/list" \
|
| 105 |
-
-H "Content-Type: application/json" \
|
| 106 |
-
-d '{
|
| 107 |
-
"filters": {},
|
| 108 |
-
"projection_list": ["sku", "qty_on_hand", "qty_available"],
|
| 109 |
-
"limit": 10
|
| 110 |
-
}'
|
| 111 |
-
```
|
| 112 |
-
|
| 113 |
-
### **Stock Availability Check**
|
| 114 |
-
```bash
|
| 115 |
-
curl -X POST "http://localhost:8000/inventory/stock/availability/check" \
|
| 116 |
-
-H "Content-Type: application/json" \
|
| 117 |
-
-d '{
|
| 118 |
-
"items": [
|
| 119 |
-
{"sku": "LOR-ABS-REP-SHMP-300ML", "qty": 10, "location_id": "main_warehouse"}
|
| 120 |
-
],
|
| 121 |
-
"projection_list": ["sku", "is_available", "total_available"]
|
| 122 |
-
}'
|
| 123 |
-
```
|
| 124 |
-
|
| 125 |
-
## 📋 **SAMPLE PRODUCTS CREATED**
|
| 126 |
-
|
| 127 |
-
1. **L'Oréal Professional Absolut Repair Shampoo 300ML**
|
| 128 |
-
- SKU: `LOR-ABS-REP-SHMP-300ML`
|
| 129 |
-
- MRP: ₹1,850 | retail Cost: ₹1,480
|
| 130 |
-
|
| 131 |
-
2. **L'Oréal Professional Serie Expert Vitamino Color Shampoo 500ML**
|
| 132 |
-
- SKU: `LOR-VIT-COL-SHMP-500ML`
|
| 133 |
-
- MRP: ₹2,450 | retail Cost: ₹1,960
|
| 134 |
-
|
| 135 |
-
3. **Matrix Biolage Hydrasource Shampoo 400ML**
|
| 136 |
-
- SKU: `MTX-HYD-SRC-SHMP-400ML`
|
| 137 |
-
- MRP: ₹1,250 | retail Cost: ₹1,000
|
| 138 |
-
|
| 139 |
-
4. **L'Oréal Professional Mythic Oil Nourishing Shampoo 250ML**
|
| 140 |
-
- SKU: `LOR-MYT-OIL-SHMP-250ML`
|
| 141 |
-
- MRP: ₹1,650 | retail Cost: ₹1,320
|
| 142 |
-
|
| 143 |
-
5. **Schwarzkopf Professional BC Bonacure Repair Rescue Shampoo 250ML**
|
| 144 |
-
- SKU: `SCH-BC-REP-RES-SHMP-250ML`
|
| 145 |
-
- MRP: ₹1,450 | retail Cost: ₹1,160
|
| 146 |
-
|
| 147 |
-
## 🔍 **DATABASE VERIFICATION**
|
| 148 |
-
|
| 149 |
-
### **MongoDB Query**
|
| 150 |
-
```javascript
|
| 151 |
-
// Check enhanced structure
|
| 152 |
-
db.scm_catalogue.findOne({
|
| 153 |
-
"merchant_id": "company_cuatro_beauty_ltd",
|
| 154 |
-
"pricing.levels": {"$exists": true}
|
| 155 |
-
})
|
| 156 |
-
```
|
| 157 |
-
|
| 158 |
-
### **PostgreSQL Query**
|
| 159 |
-
```sql
|
| 160 |
-
-- Check synced data with pricing
|
| 161 |
-
SELECT catalogue_code, catalogue_name,
|
| 162 |
-
pricing->>'currency' as currency,
|
| 163 |
-
(pricing->'levels'->>'retail')::jsonb->>'cost_price' as retail_cost_price
|
| 164 |
-
FROM trans.catalogue_ref
|
| 165 |
-
WHERE 'company_cuatro_beauty_ltd' = ANY(merchant_id);
|
| 166 |
-
```
|
| 167 |
-
|
| 168 |
-
## 🎊 **BENEFITS ACHIEVED**
|
| 169 |
-
|
| 170 |
-
### **Performance**
|
| 171 |
-
- ✅ **50-90% payload reduction** with projection lists
|
| 172 |
-
- ✅ **Faster API responses** with MongoDB projection
|
| 173 |
-
- ✅ **Reduced bandwidth** for mobile clients
|
| 174 |
-
- ✅ **Efficient PostgreSQL queries** for reporting
|
| 175 |
-
|
| 176 |
-
### **Scalability**
|
| 177 |
-
- ✅ **Multi-level pricing** supports different merchant types
|
| 178 |
-
- ✅ **Flexible inventory** configurations per level
|
| 179 |
-
- ✅ **Dual database** strategy for performance and flexibility
|
| 180 |
-
- ✅ **Consistent API pattern** across all endpoints
|
| 181 |
-
|
| 182 |
-
### **Developer Experience**
|
| 183 |
-
- ✅ **Projection list support** on all list endpoints
|
| 184 |
-
- ✅ **Comprehensive testing** scripts included
|
| 185 |
-
- ✅ **Easy data generation** for development
|
| 186 |
-
- ✅ **Complete documentation** and examples
|
| 187 |
-
|
| 188 |
-
## 🚀 **READY FOR PRODUCTION**
|
| 189 |
-
|
| 190 |
-
The enhanced retail catalogue system is now fully operational with:
|
| 191 |
-
|
| 192 |
-
1. ✅ **Complete data structure** matching your requirements
|
| 193 |
-
2. ✅ **Full projection list compliance** across all APIs
|
| 194 |
-
3. ✅ **Dual database synchronization** working perfectly
|
| 195 |
-
4. ✅ **Professional beauty products** data loaded
|
| 196 |
-
5. ✅ **Comprehensive testing** suite available
|
| 197 |
-
6. ✅ **Performance optimizations** delivering 50-90% payload reduction
|
| 198 |
-
|
| 199 |
-
**Your enhanced catalogue and inventory system is ready to serve retail businesses with maximum efficiency and flexibility!** 🎉
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/SWAGGER_FIX_SUMMARY.md
DELETED
|
@@ -1,93 +0,0 @@
|
|
| 1 |
-
# Swagger/FastAPI OpenAPI Fix Summary
|
| 2 |
-
|
| 3 |
-
## Issue Description
|
| 4 |
-
The FastAPI Swagger documentation was failing to load with a 500 error on `/openapi.json` due to a Pydantic serialization error: "Unable to serialize unknown type: <class 'function'>".
|
| 5 |
-
|
| 6 |
-
## Root Cause Analysis
|
| 7 |
-
Through systematic testing of individual routers, the issue was identified in the **warehouse schemas** (`app/warehouses/schemas/schema.py`):
|
| 8 |
-
|
| 9 |
-
1. **Problematic Code**: The schema was importing SQLAlchemy functions:
|
| 10 |
-
```python
|
| 11 |
-
from sqlalchemy import false, true
|
| 12 |
-
```
|
| 13 |
-
|
| 14 |
-
2. **Usage in Examples**: These SQLAlchemy functions were used in Pydantic schema examples:
|
| 15 |
-
```python
|
| 16 |
-
"capabilities": {
|
| 17 |
-
"can_receive": true, # SQLAlchemy function, not boolean
|
| 18 |
-
"can_fulfil": true, # SQLAlchemy function, not boolean
|
| 19 |
-
"can_sell": false, # SQLAlchemy function, not boolean
|
| 20 |
-
...
|
| 21 |
-
}
|
| 22 |
-
```
|
| 23 |
-
|
| 24 |
-
3. **Serialization Error**: When FastAPI tried to generate the OpenAPI schema, Pydantic couldn't serialize the SQLAlchemy function objects.
|
| 25 |
-
|
| 26 |
-
## Solution Applied
|
| 27 |
-
1. **Removed SQLAlchemy imports**:
|
| 28 |
-
```python
|
| 29 |
-
# Before
|
| 30 |
-
from sqlalchemy import false, true
|
| 31 |
-
|
| 32 |
-
# After
|
| 33 |
-
# Removed SQLAlchemy imports - using Python booleans instead
|
| 34 |
-
```
|
| 35 |
-
|
| 36 |
-
2. **Fixed boolean values in examples**:
|
| 37 |
-
```python
|
| 38 |
-
# Before
|
| 39 |
-
"capabilities": {
|
| 40 |
-
"can_receive": true,
|
| 41 |
-
"can_fulfil": true,
|
| 42 |
-
"can_sell": false,
|
| 43 |
-
...
|
| 44 |
-
}
|
| 45 |
-
|
| 46 |
-
# After
|
| 47 |
-
"capabilities": {
|
| 48 |
-
"can_receive": True,
|
| 49 |
-
"can_fulfil": True,
|
| 50 |
-
"can_sell": False,
|
| 51 |
-
...
|
| 52 |
-
}
|
| 53 |
-
```
|
| 54 |
-
|
| 55 |
-
## Employee System User Integration
|
| 56 |
-
As part of the same session, successfully implemented the employee system user integration:
|
| 57 |
-
|
| 58 |
-
### Added Fields
|
| 59 |
-
- `is_system_user: bool` field to employee schemas and models
|
| 60 |
-
- When `is_system_user=True`, automatically creates a system user in `SCM_SYSTEM_USERS` collection
|
| 61 |
-
|
| 62 |
-
### Implementation Details
|
| 63 |
-
- **Employee Schema**: Added `is_system_user` field to `EmployeeCreate`, `EmployeeUpdate`, and `EmployeeResponse`
|
| 64 |
-
- **Employee Model**: Added `is_system_user` field to `EmployeeModel`
|
| 65 |
-
- **Employee Service**: Added `_create_employee_system_user` method that:
|
| 66 |
-
- Generates username from employee code
|
| 67 |
-
- Creates temporary password
|
| 68 |
-
- Maps designation to role_id
|
| 69 |
-
- Stores employee metadata in system user record
|
| 70 |
-
|
| 71 |
-
## Verification Results
|
| 72 |
-
✅ **OpenAPI Schema Generation**: Successfully generates schema with 131 endpoints
|
| 73 |
-
✅ **Employee Integration**: `is_system_user` field present in both create and response schemas
|
| 74 |
-
✅ **Warehouse Fix**: Boolean values properly serialized
|
| 75 |
-
✅ **All Routers**: All 15 routers now work correctly together
|
| 76 |
-
|
| 77 |
-
## Files Modified
|
| 78 |
-
1. `cuatrolabs-scm-ms/app/employees/schemas/schema.py` - Added `is_system_user` field
|
| 79 |
-
2. `cuatrolabs-scm-ms/app/employees/models/model.py` - Added `is_system_user` field
|
| 80 |
-
3. `cuatrolabs-scm-ms/app/employees/services/service.py` - Added system user creation logic
|
| 81 |
-
4. `cuatrolabs-scm-ms/app/warehouses/schemas/schema.py` - Fixed SQLAlchemy boolean issue
|
| 82 |
-
|
| 83 |
-
## Testing
|
| 84 |
-
- Created comprehensive test script (`test_swagger_fix.py`)
|
| 85 |
-
- Verified OpenAPI schema generation works
|
| 86 |
-
- Confirmed all new fields are properly included
|
| 87 |
-
- Validated boolean serialization fix
|
| 88 |
-
|
| 89 |
-
## Impact
|
| 90 |
-
- ✅ Swagger/FastAPI documentation now loads correctly
|
| 91 |
-
- ✅ Employee system user integration fully functional
|
| 92 |
-
- ✅ All API endpoints accessible via Swagger UI
|
| 93 |
-
- ✅ No breaking changes to existing functionality
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/TRADE_SALES_IMPLEMENTATION.md
DELETED
|
@@ -1,415 +0,0 @@
|
|
| 1 |
-
# Trade Sales (B2B) Implementation Guide
|
| 2 |
-
|
| 3 |
-
## Overview
|
| 4 |
-
|
| 5 |
-
The Trade Sales module handles B2B outbound sales operations where goods are sold between merchants (cnf → distributor → retail). This module implements the complete order-to-shipment execution flow with proper inventory management and audit trails.
|
| 6 |
-
|
| 7 |
-
## Architecture
|
| 8 |
-
|
| 9 |
-
### Module Structure
|
| 10 |
-
```
|
| 11 |
-
app/trade_sales/
|
| 12 |
-
├── __init__.py
|
| 13 |
-
├── controllers/
|
| 14 |
-
│ ├── __init__.py
|
| 15 |
-
│ └── router.py # FastAPI routes
|
| 16 |
-
├── services/
|
| 17 |
-
│ ├── __init__.py
|
| 18 |
-
│ └── service.py # Business logic
|
| 19 |
-
└── schemas/
|
| 20 |
-
├── __init__.py
|
| 21 |
-
└── schema.py # Pydantic models
|
| 22 |
-
```
|
| 23 |
-
|
| 24 |
-
### Database Models
|
| 25 |
-
```
|
| 26 |
-
app/models/
|
| 27 |
-
└── trade_sales_model.py # SQLAlchemy models
|
| 28 |
-
```
|
| 29 |
-
|
| 30 |
-
## Key Features
|
| 31 |
-
|
| 32 |
-
### ✅ Implemented Features
|
| 33 |
-
|
| 34 |
-
1. **Client Orders (Read-Only Views)**
|
| 35 |
-
- List client orders with projection support
|
| 36 |
-
- View detailed order information
|
| 37 |
-
- Filter by client, status, date range
|
| 38 |
-
- Derived status calculation (pending/partial/completed)
|
| 39 |
-
|
| 40 |
-
2. **Order Execution**
|
| 41 |
-
- List orders ready for execution
|
| 42 |
-
- Execute orders with shipment creation
|
| 43 |
-
- Partial shipment support
|
| 44 |
-
- Stock validation and updates
|
| 45 |
-
- Batch tracking
|
| 46 |
-
|
| 47 |
-
3. **Trade Shipments**
|
| 48 |
-
- List all shipments with projection support
|
| 49 |
-
- View detailed shipment information
|
| 50 |
-
- Track logistics details (transporter, LR, vehicle)
|
| 51 |
-
- Shipment status management
|
| 52 |
-
|
| 53 |
-
4. **Stock Integration**
|
| 54 |
-
- Automatic stock reduction on shipment
|
| 55 |
-
- Stock ledger entries for audit
|
| 56 |
-
- Batch-wise inventory tracking
|
| 57 |
-
- Stock validation before shipment
|
| 58 |
-
|
| 59 |
-
5. **API Standards Compliance**
|
| 60 |
-
- All list endpoints support projection
|
| 61 |
-
- POST method for list operations
|
| 62 |
-
- Consistent error handling
|
| 63 |
-
- Proper pagination
|
| 64 |
-
|
| 65 |
-
### 🚧 Placeholder Features (Future Implementation)
|
| 66 |
-
|
| 67 |
-
1. **Trade Invoices**
|
| 68 |
-
- Invoice generation from shipments
|
| 69 |
-
- Invoice list and detail views
|
| 70 |
-
- Payment tracking
|
| 71 |
-
|
| 72 |
-
2. **Credit Notes**
|
| 73 |
-
- Credit note generation
|
| 74 |
-
- Return processing integration
|
| 75 |
-
|
| 76 |
-
## Database Schema
|
| 77 |
-
|
| 78 |
-
### Core Tables
|
| 79 |
-
|
| 80 |
-
#### scm_trade_shipment
|
| 81 |
-
```sql
|
| 82 |
-
CREATE TABLE scm_trade_shipment (
|
| 83 |
-
shipment_id UUID PRIMARY KEY,
|
| 84 |
-
shipment_no VARCHAR(40) UNIQUE NOT NULL,
|
| 85 |
-
order_id UUID NOT NULL REFERENCES scm_po(po_id),
|
| 86 |
-
supplier_id VARCHAR(64) NOT NULL, -- cnf merchant ID
|
| 87 |
-
client_id VARCHAR(64) NOT NULL, -- distributor merchant ID
|
| 88 |
-
warehouse_id UUID NOT NULL,
|
| 89 |
-
status VARCHAR(20) NOT NULL DEFAULT 'draft',
|
| 90 |
-
shipment_date DATE NOT NULL,
|
| 91 |
-
transporter VARCHAR(100),
|
| 92 |
-
lr_no VARCHAR(50),
|
| 93 |
-
vehicle_no VARCHAR(20),
|
| 94 |
-
created_by VARCHAR(64),
|
| 95 |
-
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
| 96 |
-
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
| 97 |
-
);
|
| 98 |
-
```
|
| 99 |
-
|
| 100 |
-
#### scm_trade_shipment_item
|
| 101 |
-
```sql
|
| 102 |
-
CREATE TABLE scm_trade_shipment_item (
|
| 103 |
-
item_id UUID PRIMARY KEY,
|
| 104 |
-
shipment_id UUID NOT NULL REFERENCES scm_trade_shipment(shipment_id),
|
| 105 |
-
po_item_id UUID NOT NULL REFERENCES scm_po_item(po_item_id),
|
| 106 |
-
sku VARCHAR(64) NOT NULL,
|
| 107 |
-
batch_no VARCHAR(50) NOT NULL,
|
| 108 |
-
ordered_qty NUMERIC(12,3) NOT NULL,
|
| 109 |
-
shipped_qty NUMERIC(12,3) NOT NULL,
|
| 110 |
-
balance_qty NUMERIC(12,3) NOT NULL
|
| 111 |
-
);
|
| 112 |
-
```
|
| 113 |
-
|
| 114 |
-
### Views and Analytics
|
| 115 |
-
|
| 116 |
-
#### v_order_execution_status
|
| 117 |
-
Provides real-time order execution status with quantities and shipment counts.
|
| 118 |
-
|
| 119 |
-
#### v_trade_sales_summary
|
| 120 |
-
Aggregated trade sales metrics by client.
|
| 121 |
-
|
| 122 |
-
#### get_trade_sales_analytics()
|
| 123 |
-
Stored procedure for comprehensive trade sales analytics.
|
| 124 |
-
|
| 125 |
-
## API Endpoints
|
| 126 |
-
|
| 127 |
-
### Client Orders
|
| 128 |
-
|
| 129 |
-
#### POST /trade-sales/client-orders/list
|
| 130 |
-
List client orders with projection support.
|
| 131 |
-
|
| 132 |
-
**Request:**
|
| 133 |
-
```json
|
| 134 |
-
{
|
| 135 |
-
"filters": {
|
| 136 |
-
"client_id": "DIST-BLR-001",
|
| 137 |
-
"status": "pending",
|
| 138 |
-
"order_date_from": "2024-01-01",
|
| 139 |
-
"order_date_to": "2024-12-31"
|
| 140 |
-
},
|
| 141 |
-
"skip": 0,
|
| 142 |
-
"limit": 100,
|
| 143 |
-
"projection_list": ["order_no", "client_id", "pending_qty", "status"]
|
| 144 |
-
}
|
| 145 |
-
```
|
| 146 |
-
|
| 147 |
-
**Response:**
|
| 148 |
-
```json
|
| 149 |
-
{
|
| 150 |
-
"items": [
|
| 151 |
-
{
|
| 152 |
-
"order_no": "PO20241217001",
|
| 153 |
-
"client_id": "DIST-BLR-001",
|
| 154 |
-
"pending_qty": 150.0,
|
| 155 |
-
"status": "pending"
|
| 156 |
-
}
|
| 157 |
-
],
|
| 158 |
-
"total": 1,
|
| 159 |
-
"skip": 0,
|
| 160 |
-
"limit": 100,
|
| 161 |
-
"has_more": false
|
| 162 |
-
}
|
| 163 |
-
```
|
| 164 |
-
|
| 165 |
-
#### GET /trade-sales/client-orders/{order_id}
|
| 166 |
-
Get detailed client order with items.
|
| 167 |
-
|
| 168 |
-
### Order Execution
|
| 169 |
-
|
| 170 |
-
#### POST /trade-sales/order-execution/list
|
| 171 |
-
List orders ready for execution.
|
| 172 |
-
|
| 173 |
-
#### GET /trade-sales/order-execution/{order_id}/detail
|
| 174 |
-
Get order execution detail with stock availability.
|
| 175 |
-
|
| 176 |
-
#### POST /trade-sales/order-execution/{order_id}/execute
|
| 177 |
-
Execute order by creating shipment.
|
| 178 |
-
|
| 179 |
-
**Request:**
|
| 180 |
-
```json
|
| 181 |
-
{
|
| 182 |
-
"warehouse_id": "uuid",
|
| 183 |
-
"items": [
|
| 184 |
-
{
|
| 185 |
-
"po_item_id": "uuid",
|
| 186 |
-
"sku": "SHMP-500",
|
| 187 |
-
"batch_no": "BATCH-001",
|
| 188 |
-
"shipped_qty": 90
|
| 189 |
-
}
|
| 190 |
-
],
|
| 191 |
-
"shipment": {
|
| 192 |
-
"transporter": "VRL Logistics",
|
| 193 |
-
"lr_no": "LR-998877",
|
| 194 |
-
"vehicle_no": "KA01AB1234",
|
| 195 |
-
"shipment_date": "2024-12-17",
|
| 196 |
-
"remarks": "Partial shipment"
|
| 197 |
-
}
|
| 198 |
-
}
|
| 199 |
-
```
|
| 200 |
-
|
| 201 |
-
### Trade Shipments
|
| 202 |
-
|
| 203 |
-
#### POST /trade-sales/shipments/list
|
| 204 |
-
List trade shipments with projection support.
|
| 205 |
-
|
| 206 |
-
#### GET /trade-sales/shipments/{shipment_id}
|
| 207 |
-
Get detailed shipment information.
|
| 208 |
-
|
| 209 |
-
## Business Logic
|
| 210 |
-
|
| 211 |
-
### Order Status Derivation
|
| 212 |
-
```python
|
| 213 |
-
if shipped_qty == 0:
|
| 214 |
-
status = "pending"
|
| 215 |
-
elif shipped_qty < ordered_qty:
|
| 216 |
-
status = "partial"
|
| 217 |
-
elif shipped_qty >= ordered_qty:
|
| 218 |
-
status = "completed"
|
| 219 |
-
```
|
| 220 |
-
|
| 221 |
-
### Stock Impact Flow
|
| 222 |
-
1. **Order Execution** → Creates shipment record
|
| 223 |
-
2. **Stock Service** → Reduces supplier inventory
|
| 224 |
-
3. **Stock Ledger** → Creates audit trail
|
| 225 |
-
4. **Buyer Inventory** → Updated via separate GRN process
|
| 226 |
-
|
| 227 |
-
### Shipment Number Generation
|
| 228 |
-
Format: `TS{YYYYMMDD}{NNNN}`
|
| 229 |
-
- TS = Trade Sales prefix
|
| 230 |
-
- YYYYMMDD = Shipment date
|
| 231 |
-
- NNNN = Sequential number for the day
|
| 232 |
-
|
| 233 |
-
## Integration Points
|
| 234 |
-
|
| 235 |
-
### Stock Service Integration
|
| 236 |
-
```python
|
| 237 |
-
# Automatic stock reduction on shipment
|
| 238 |
-
stock_transaction = StockTransaction(
|
| 239 |
-
merchant_id=supplier_id,
|
| 240 |
-
location_id=warehouse_id,
|
| 241 |
-
sku=sku,
|
| 242 |
-
batch_no=batch_no,
|
| 243 |
-
qty=-shipped_qty, # Negative for outbound
|
| 244 |
-
txn_type=TransactionType.SALE_OUT,
|
| 245 |
-
ref_type=ReferenceType.SALE,
|
| 246 |
-
ref_id=shipment_id
|
| 247 |
-
)
|
| 248 |
-
```
|
| 249 |
-
|
| 250 |
-
### PO/GRN Integration
|
| 251 |
-
- **Client Orders** are read-only views of existing POs
|
| 252 |
-
- **Shipment Items** reference PO items for traceability
|
| 253 |
-
- **GRN Process** handles buyer inventory updates
|
| 254 |
-
|
| 255 |
-
## Testing
|
| 256 |
-
|
| 257 |
-
### Migration
|
| 258 |
-
```bash
|
| 259 |
-
# Run database migration
|
| 260 |
-
python migration_trade_sales_tables.py
|
| 261 |
-
|
| 262 |
-
# Rollback if needed
|
| 263 |
-
python migration_trade_sales_tables.py rollback
|
| 264 |
-
```
|
| 265 |
-
|
| 266 |
-
### Sample Data
|
| 267 |
-
```bash
|
| 268 |
-
# Create sample data
|
| 269 |
-
python examples/trade_sales/create_sample_trade_data.py
|
| 270 |
-
|
| 271 |
-
# Clean up sample data
|
| 272 |
-
python examples/trade_sales/create_sample_trade_data.py cleanup
|
| 273 |
-
```
|
| 274 |
-
|
| 275 |
-
### API Testing
|
| 276 |
-
```bash
|
| 277 |
-
# Test all APIs
|
| 278 |
-
python examples/trade_sales/test_trade_sales_apis.py
|
| 279 |
-
```
|
| 280 |
-
|
| 281 |
-
## Performance Considerations
|
| 282 |
-
|
| 283 |
-
### Projection List Benefits
|
| 284 |
-
- **Payload Reduction**: 50-90% smaller responses
|
| 285 |
-
- **Database Performance**: Reduced I/O with SQL SELECT optimization
|
| 286 |
-
- **Network Efficiency**: Less bandwidth usage
|
| 287 |
-
- **Client Flexibility**: Request only needed fields
|
| 288 |
-
|
| 289 |
-
### Indexing Strategy
|
| 290 |
-
```sql
|
| 291 |
-
-- Order lookup
|
| 292 |
-
CREATE INDEX idx_trade_shipment_order_id ON scm_trade_shipment(order_id);
|
| 293 |
-
|
| 294 |
-
-- Client filtering
|
| 295 |
-
CREATE INDEX idx_trade_shipment_client_id ON scm_trade_shipment(client_id);
|
| 296 |
-
|
| 297 |
-
-- Date range queries
|
| 298 |
-
CREATE INDEX idx_trade_shipment_date ON scm_trade_shipment(shipment_date);
|
| 299 |
-
|
| 300 |
-
-- Status filtering
|
| 301 |
-
CREATE INDEX idx_trade_shipment_status ON scm_trade_shipment(status);
|
| 302 |
-
```
|
| 303 |
-
|
| 304 |
-
## Security & Permissions
|
| 305 |
-
|
| 306 |
-
### Role-Based Access
|
| 307 |
-
- **cnf Admin**: Full access to all operations
|
| 308 |
-
- **cnf Ops**: Execute orders, view shipments
|
| 309 |
-
- **distributor**: Read-only access to own orders
|
| 310 |
-
- **Finance**: Invoice and reporting access
|
| 311 |
-
|
| 312 |
-
### Data Validation
|
| 313 |
-
- Shipment quantities cannot exceed ordered quantities
|
| 314 |
-
- Stock availability validation before shipment
|
| 315 |
-
- Batch expiry date validation
|
| 316 |
-
- Duplicate shipment number prevention
|
| 317 |
-
|
| 318 |
-
## Monitoring & Logging
|
| 319 |
-
|
| 320 |
-
### Key Metrics
|
| 321 |
-
- Orders pending execution
|
| 322 |
-
- Average shipment processing time
|
| 323 |
-
- Stock accuracy after shipments
|
| 324 |
-
- Client-wise shipment volumes
|
| 325 |
-
|
| 326 |
-
### Audit Trail
|
| 327 |
-
- All shipments are immutable after posting
|
| 328 |
-
- Complete lineage: PO → Shipment → GRN → Invoice
|
| 329 |
-
- Stock ledger provides full transaction history
|
| 330 |
-
|
| 331 |
-
## Future Enhancements
|
| 332 |
-
|
| 333 |
-
### Phase 2 Features
|
| 334 |
-
1. **Trade Invoices**
|
| 335 |
-
- Automatic invoice generation from shipments
|
| 336 |
-
- Tax calculations and compliance
|
| 337 |
-
- Payment tracking integration
|
| 338 |
-
|
| 339 |
-
2. **Credit Notes**
|
| 340 |
-
- Return processing workflow
|
| 341 |
-
- Credit note generation
|
| 342 |
-
- Adjustment handling
|
| 343 |
-
|
| 344 |
-
3. **Advanced Analytics**
|
| 345 |
-
- Client performance dashboards
|
| 346 |
-
- Shipment efficiency metrics
|
| 347 |
-
- Inventory turnover analysis
|
| 348 |
-
|
| 349 |
-
4. **Mobile Support**
|
| 350 |
-
- Mobile-optimized APIs
|
| 351 |
-
- Offline shipment creation
|
| 352 |
-
- Barcode scanning integration
|
| 353 |
-
|
| 354 |
-
### Integration Roadmap
|
| 355 |
-
1. **ERP Integration**: SAP/Oracle connector
|
| 356 |
-
2. **Logistics Integration**: 3PL system connectivity
|
| 357 |
-
3. **Payment Gateway**: Invoice payment processing
|
| 358 |
-
4. **Notification System**: SMS/Email alerts
|
| 359 |
-
|
| 360 |
-
## Troubleshooting
|
| 361 |
-
|
| 362 |
-
### Common Issues
|
| 363 |
-
|
| 364 |
-
#### Stock Validation Errors
|
| 365 |
-
```
|
| 366 |
-
Error: Cannot ship 100 units of SKU ABC. Available: 50
|
| 367 |
-
```
|
| 368 |
-
**Solution**: Check stock availability and adjust shipment quantities.
|
| 369 |
-
|
| 370 |
-
#### Duplicate Shipment Numbers
|
| 371 |
-
```
|
| 372 |
-
Error: Shipment number TS20241217001 already exists
|
| 373 |
-
```
|
| 374 |
-
**Solution**: Shipment number generation handles this automatically.
|
| 375 |
-
|
| 376 |
-
#### Missing PO Items
|
| 377 |
-
```
|
| 378 |
-
Error: Invalid PO item ID: uuid
|
| 379 |
-
```
|
| 380 |
-
**Solution**: Ensure PO items exist and are valid for the order.
|
| 381 |
-
|
| 382 |
-
### Debug Queries
|
| 383 |
-
|
| 384 |
-
#### Check Order Status
|
| 385 |
-
```sql
|
| 386 |
-
SELECT * FROM v_order_execution_status WHERE order_id = 'uuid';
|
| 387 |
-
```
|
| 388 |
-
|
| 389 |
-
#### Verify Stock Availability
|
| 390 |
-
```sql
|
| 391 |
-
SELECT sku, batch_no, qty_available
|
| 392 |
-
FROM scm_stock
|
| 393 |
-
WHERE merchant_id = 'cnf-ID' AND sku = 'SKU';
|
| 394 |
-
```
|
| 395 |
-
|
| 396 |
-
#### Trace Shipment History
|
| 397 |
-
```sql
|
| 398 |
-
SELECT ts.shipment_no, ts.shipment_date, tsi.sku, tsi.shipped_qty
|
| 399 |
-
FROM scm_trade_shipment ts
|
| 400 |
-
JOIN scm_trade_shipment_item tsi ON ts.shipment_id = tsi.shipment_id
|
| 401 |
-
WHERE ts.order_id = 'uuid'
|
| 402 |
-
ORDER BY ts.shipment_date;
|
| 403 |
-
```
|
| 404 |
-
|
| 405 |
-
## Conclusion
|
| 406 |
-
|
| 407 |
-
The Trade Sales module provides a comprehensive B2B outbound sales solution with:
|
| 408 |
-
- ✅ Complete order-to-shipment workflow
|
| 409 |
-
- ✅ Proper inventory management
|
| 410 |
-
- ✅ API standards compliance
|
| 411 |
-
- ✅ Audit trail and traceability
|
| 412 |
-
- ✅ Performance optimization
|
| 413 |
-
- ✅ Extensible architecture
|
| 414 |
-
|
| 415 |
-
The module is production-ready for the core functionality with clear paths for future enhancements.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
docs/implementation-summaries/catalogue_api_examples.md
DELETED
|
@@ -1,166 +0,0 @@
|
|
| 1 |
-
# Catalogue API Examples with Auto-Generation
|
| 2 |
-
|
| 3 |
-
## Create Catalogue with Auto-Generation
|
| 4 |
-
|
| 5 |
-
### Example 1: Full Auto-Generation
|
| 6 |
-
```bash
|
| 7 |
-
curl -X 'POST' \
|
| 8 |
-
'http://127.0.0.1:8000/catalogue' \
|
| 9 |
-
-H 'accept: application/json' \
|
| 10 |
-
-H 'Authorization: Bearer YOUR_TOKEN' \
|
| 11 |
-
-H 'Content-Type: application/json' \
|
| 12 |
-
-d '{
|
| 13 |
-
"catalogue_name": "L'\''Oreal Professional Shampoo 500ml",
|
| 14 |
-
"catalogue_type": "Product",
|
| 15 |
-
"brand": "LOREAL",
|
| 16 |
-
"category": "SHAMPOO",
|
| 17 |
-
"description": "Professional grade shampoo for all hair types",
|
| 18 |
-
"identifiers": {
|
| 19 |
-
"sku": "LOR-SHA-500ML",
|
| 20 |
-
"ean_code": "1234567890123"
|
| 21 |
-
},
|
| 22 |
-
"attributes": {
|
| 23 |
-
"size": "500ml",
|
| 24 |
-
"hair_type": "all_types"
|
| 25 |
-
},
|
| 26 |
-
"pricing": {
|
| 27 |
-
"retail_price": 850.00,
|
| 28 |
-
"mrp": 1000.00,
|
| 29 |
-
"currency": "INR"
|
| 30 |
-
}
|
| 31 |
-
}'
|
| 32 |
-
```
|
| 33 |
-
|
| 34 |
-
**Expected Response:**
|
| 35 |
-
- `catalogue_id`: Auto-generated UUID (e.g., `550e8400-e29b-41d4-a716-446655440000`)
|
| 36 |
-
- `catalogue_code`: Auto-generated code (e.g., `LOR-SHA-000001`)
|
| 37 |
-
|
| 38 |
-
### Example 2: Manual ID, Auto Code
|
| 39 |
-
```bash
|
| 40 |
-
curl -X 'POST' \
|
| 41 |
-
'http://127.0.0.1:8000/catalogue' \
|
| 42 |
-
-H 'accept: application/json' \
|
| 43 |
-
-H 'Authorization: Bearer YOUR_TOKEN' \
|
| 44 |
-
-H 'Content-Type: application/json' \
|
| 45 |
-
-d '{
|
| 46 |
-
"catalogue_id": "custom-loreal-shampoo-001",
|
| 47 |
-
"catalogue_name": "L'\''Oreal Professionnel Serie Expert",
|
| 48 |
-
"catalogue_type": "Product",
|
| 49 |
-
"brand": "LOREAL",
|
| 50 |
-
"category": "SHAMPOO",
|
| 51 |
-
"description": "Expert series professional shampoo"
|
| 52 |
-
}'
|
| 53 |
-
```
|
| 54 |
-
|
| 55 |
-
**Expected Response:**
|
| 56 |
-
- `catalogue_id`: `custom-loreal-shampoo-001` (as provided)
|
| 57 |
-
- `catalogue_code`: Auto-generated (e.g., `LOR-SHA-000002`)
|
| 58 |
-
|
| 59 |
-
### Example 3: Complete Manual Override
|
| 60 |
-
```bash
|
| 61 |
-
curl -X 'POST' \
|
| 62 |
-
'http://127.0.0.1:8000/catalogue' \
|
| 63 |
-
-H 'accept: application/json' \
|
| 64 |
-
-H 'Authorization: Bearer YOUR_TOKEN' \
|
| 65 |
-
-H 'Content-Type: application/json' \
|
| 66 |
-
-d '{
|
| 67 |
-
"catalogue_id": "manual-id-123",
|
| 68 |
-
"catalogue_code": "CUSTOM-CODE-001",
|
| 69 |
-
"catalogue_name": "Custom Product",
|
| 70 |
-
"catalogue_type": "Product",
|
| 71 |
-
"brand": "OTHER",
|
| 72 |
-
"category": "OTHER"
|
| 73 |
-
}'
|
| 74 |
-
```
|
| 75 |
-
|
| 76 |
-
## Auto-Generation Rules
|
| 77 |
-
|
| 78 |
-
### Catalogue ID Generation
|
| 79 |
-
- **Format**: UUID4 (e.g., `550e8400-e29b-41d4-a716-446655440000`)
|
| 80 |
-
- **When**: Generated if `catalogue_id` is not provided
|
| 81 |
-
- **Uniqueness**: Guaranteed unique across all catalogues
|
| 82 |
-
|
| 83 |
-
### Catalogue Code Generation
|
| 84 |
-
- **Format**: `BBB-CCC-NNNNNN` (e.g., `LOR-SHA-000001`)
|
| 85 |
-
- **When**: Generated if `catalogue_code` is not provided AND both `brand` and `category` are provided
|
| 86 |
-
- **Components**:
|
| 87 |
-
- `BBB`: 3-letter brand code (normalized)
|
| 88 |
-
- `CCC`: 3-letter category code (normalized)
|
| 89 |
-
- `NNNNNN`: 6-digit sequence number (zero-padded)
|
| 90 |
-
|
| 91 |
-
### Brand Codes (Examples)
|
| 92 |
-
- `LOREAL` → `LOR`
|
| 93 |
-
- `MATRIX` → `MAT`
|
| 94 |
-
- `SCHWARZKOPF` → `SCH`
|
| 95 |
-
- `WELLA` → `WEL`
|
| 96 |
-
- `REDKEN` → `RED`
|
| 97 |
-
- `TIGI` → `TIG`
|
| 98 |
-
- `PAUL_MITCHELL` → `PAU`
|
| 99 |
-
- `KERASTASE` → `KER`
|
| 100 |
-
- `OLAPLEX` → `OLA`
|
| 101 |
-
- `MOROCCANOIL` → `MOR`
|
| 102 |
-
|
| 103 |
-
### Category Codes (Examples)
|
| 104 |
-
- `SHAMPOO` → `SHA`
|
| 105 |
-
- `CONDITIONER` → `CON`
|
| 106 |
-
- `HAIR_MASK` → `HAI`
|
| 107 |
-
- `HAIR_OIL` → `HAI`
|
| 108 |
-
- `HAIR_SERUM` → `HAI`
|
| 109 |
-
- `HAIR_COLOR` → `HAI`
|
| 110 |
-
- `STYLING_GEL` → `STY`
|
| 111 |
-
- `STYLING_CREAM` → `STY`
|
| 112 |
-
- `HAIR_SPRAY` → `HAI`
|
| 113 |
-
|
| 114 |
-
## Validation Rules
|
| 115 |
-
|
| 116 |
-
### Valid Brands
|
| 117 |
-
```
|
| 118 |
-
LOREAL, MATRIX, SCHWARZKOPF, WELLA, REDKEN, TIGI,
|
| 119 |
-
PAUL_MITCHELL, KERASTASE, OLAPLEX, MOROCCANOIL, OTHER
|
| 120 |
-
```
|
| 121 |
-
|
| 122 |
-
### Valid Categories
|
| 123 |
-
```
|
| 124 |
-
SHAMPOO, CONDITIONER, HAIR_MASK, HAIR_OIL, HAIR_SERUM,
|
| 125 |
-
HAIR_COLOR, HAIR_BLEACH, DEVELOPER, STYLING_GEL, STYLING_CREAM,
|
| 126 |
-
HAIR_SPRAY, MOUSSE, TOOLS, ACCESSORIES, OTHER
|
| 127 |
-
```
|
| 128 |
-
|
| 129 |
-
## Error Responses
|
| 130 |
-
|
| 131 |
-
### Invalid Brand
|
| 132 |
-
```json
|
| 133 |
-
{
|
| 134 |
-
"detail": "Invalid brand: FAKE_BRAND"
|
| 135 |
-
}
|
| 136 |
-
```
|
| 137 |
-
|
| 138 |
-
### Invalid Category
|
| 139 |
-
```json
|
| 140 |
-
{
|
| 141 |
-
"detail": "Invalid category: FAKE_CATEGORY"
|
| 142 |
-
}
|
| 143 |
-
```
|
| 144 |
-
|
| 145 |
-
### Duplicate Name
|
| 146 |
-
```json
|
| 147 |
-
{
|
| 148 |
-
"detail": "Catalogue item already exists"
|
| 149 |
-
}
|
| 150 |
-
```
|
| 151 |
-
|
| 152 |
-
## Sequence Management
|
| 153 |
-
|
| 154 |
-
- **Storage**: MongoDB `sequences` collection
|
| 155 |
-
- **Thread-Safe**: Uses MongoDB's atomic `findOneAndUpdate` with `$inc`
|
| 156 |
-
- **Auto-Initialize**: Sequences created automatically on first use
|
| 157 |
-
- **Starting Value**: 1 (generates `000001`, `000002`, etc.)
|
| 158 |
-
|
| 159 |
-
## Benefits
|
| 160 |
-
|
| 161 |
-
1. **No Manual Numbering**: Eliminates duplicate code errors
|
| 162 |
-
2. **Consistent Format**: Standardized across all catalogues
|
| 163 |
-
3. **Brand Recognition**: Codes include brand/category info
|
| 164 |
-
4. **Scalable**: MongoDB atomic operations handle concurrency
|
| 165 |
-
5. **Flexible**: Optional manual override for special cases
|
| 166 |
-
6. **Searchable**: Structured codes enable easy filtering/searching
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|