MukeshKapoor25 commited on
Commit
5ea6287
·
1 Parent(s): ddfe596
Files changed (23) hide show
  1. docs/implementation-summaries/CATALOGUE_DUAL_IDENTIFIERS.md +0 -358
  2. docs/implementation-summaries/CATALOGUE_SYNC_IMPLEMENTATION.md +0 -327
  3. docs/implementation-summaries/CATALOGUE_VALIDATION_SUMMARY.md +0 -125
  4. docs/implementation-summaries/CRITICAL_FIX_TRAILING_NEWLINE.md +0 -119
  5. docs/implementation-summaries/EMPLOYEE_ENDPOINTS_IMPLEMENTATION_SUMMARY.md +0 -341
  6. docs/implementation-summaries/EMPLOYEE_SYNC_INTEGRATION_SUMMARY.md +0 -204
  7. docs/implementation-summaries/FINAL_CONFIG_SUMMARY.md +0 -137
  8. docs/implementation-summaries/IMPLEMENTATION_SUMMARY.md +0 -235
  9. docs/implementation-summaries/INVENTORY_CONTROL_API_IMPLEMENTATION.md +0 -174
  10. docs/implementation-summaries/INVENTORY_CONTROL_IMPLEMENTATION.md +0 -259
  11. docs/implementation-summaries/INVENTORY_MIGRATION_SUMMARY.md +0 -190
  12. docs/implementation-summaries/MERCHANT_API_SUMMARY.md +0 -135
  13. docs/implementation-summaries/MERCHANT_CATALOGUE_LIST_IMPLEMENTATION.md +0 -316
  14. docs/implementation-summaries/PRICING_LEVELS_COMPLETE_SOLUTION.md +0 -295
  15. docs/implementation-summaries/PRICING_LEVELS_CORRECTED_STRUCTURE.md +0 -232
  16. docs/implementation-summaries/PRICING_LEVELS_SYNC_IMPLEMENTATION.md +0 -187
  17. docs/implementation-summaries/PROJECTION_LIST_IMPLEMENTATION.md +0 -231
  18. docs/implementation-summaries/PURCHASES_MODULE_IMPLEMENTATION.md +0 -272
  19. docs/implementation-summaries/SCM_POSTGRESQL_PO_GRN_IMPLEMENTATION.md +0 -169
  20. docs/implementation-summaries/SOLUTION_SUMMARY.md +0 -199
  21. docs/implementation-summaries/SWAGGER_FIX_SUMMARY.md +0 -93
  22. docs/implementation-summaries/TRADE_SALES_IMPLEMENTATION.md +0 -415
  23. 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