Add POI feature and imporve the overall backend implementation

This commit is contained in:
Urtzi Alfaro
2025-11-12 15:34:10 +01:00
parent e8096cd979
commit 5783c7ed05
173 changed files with 16862 additions and 9078 deletions

View File

@@ -22,6 +22,13 @@ The **Inventory Service** is the operational backbone of Bakery-IA, managing ing
- **Historical Analysis** - Analyze consumption patterns over time
- **Waste Tracking** - Monitor and categorize waste (expired, damaged, etc.)
### Automatic Stock Updates from Deliveries (🆕)
- **Event-Driven Stock Updates** - Automatically updates stock when deliveries are received from procurement
- **Batch & Expiry Tracking** - Records batch/lot numbers and expiration dates from delivery receipts
- **Audit Trail** - Creates complete stock entry records for each delivery
- **Zero Manual Entry** - Eliminates manual stock entry after deliveries
- **Real-Time Synchronization** - Stock levels update immediately when deliveries are recorded
### Food Safety Compliance (HACCP)
- **Temperature Monitoring** - Critical control point temperature logs
- **Food Safety Alerts** - Automated safety notifications
@@ -336,7 +343,15 @@ CREATE TABLE food_safety_alerts (
```
### Consumed Events
- **From Procurement**: Stock received from suppliers
**From Procurement Service (🆕)**
- **Delivery Received** (`delivery.received`) - Automatically updates stock levels when deliveries are recorded
- Creates/updates Stock records for each inventory product
- Creates StockEntry audit records with batch/lot numbers and expiry dates
- Handles accepted quantities from delivery receipts
- Links stock movements to delivery reference IDs for full traceability
**From Other Services**
- **From Production**: Ingredient consumption in production
- **From Sales**: Finished product sales (for inventory valuation)
@@ -467,13 +482,13 @@ pytest --cov=app tests/ --cov-report=html
## Integration Points
### Dependencies
- **Procurement Service** - Receive stock from purchase orders
- **Procurement Service** - Receive stock from purchase orders via delivery events (🆕)
- **Production Service** - Consume ingredients in production
- **Forecasting Service** - Provide consumption data for forecasts
- **Suppliers Service** - Supplier information for stock items
- **PostgreSQL** - Inventory data storage
- **Redis** - Dashboard KPI cache
- **RabbitMQ** - Alert publishing
- **RabbitMQ** - Alert publishing and delivery event consumption (🆕)
### Dependents
- **Production Service** - Check ingredient availability
@@ -482,6 +497,133 @@ pytest --cov=app tests/ --cov-report=html
- **Frontend Dashboard** - Display inventory status
- **Notification Service** - Send inventory alerts
## Delivery Event Processing (🆕)
### Automatic Stock Updates from Deliveries
The inventory service automatically updates stock levels when deliveries are recorded in the procurement service through event-driven architecture.
**How It Works:**
1. User records delivery receipt in procurement service (frontend `DeliveryReceiptModal`)
2. Procurement service publishes `delivery.received` event to RabbitMQ
3. Inventory service's `DeliveryEventConsumer` listens for and processes the event
4. For each delivered item:
- Gets or creates Stock record for the inventory product
- Updates `quantity_available` by adding accepted quantity
- Creates StockEntry audit record with:
- Transaction type: `RESTOCK`
- Reference type: `DELIVERY`
- Batch/lot number from delivery
- Expiration date from delivery
- Quantity change and new balance
**Benefits:**
- **Zero Manual Entry** - Eliminates duplicate data entry in inventory after recording deliveries
- **Real-Time Updates** - Stock levels update within seconds of delivery recording
- **Complete Traceability** - Every stock change linked to source delivery
- **Batch Tracking** - Automatic batch/lot number recording for food safety compliance
- **Expiry Management** - Expiration dates automatically captured from delivery receipts
### Delivery Event Consumer Implementation
```python
async def process_delivery_stock_update(self, event_data: Dict[str, Any]) -> bool:
"""
Process delivery event and update stock levels.
Listens to: procurement.events exchange, routing key: delivery.received
Creates: Stock records and StockEntry audit records
"""
data = event_data.get('data', {})
tenant_id = uuid.UUID(data.get('tenant_id'))
delivery_id = uuid.UUID(data.get('delivery_id'))
items = data.get('items', [])
async with database_manager.get_session() as session:
stock_repo = StockRepository(session)
entry_repo = StockEntryRepository(session)
for item in items:
inventory_product_id = uuid.UUID(item.get('inventory_product_id'))
accepted_quantity = Decimal(str(item.get('accepted_quantity', 0)))
if accepted_quantity <= 0:
continue # Skip rejected items
# Get or create stock record
stock = await stock_repo.get_stock_by_product(
tenant_id=tenant_id,
inventory_product_id=inventory_product_id
)
if not stock:
# Create new stock record
stock = await stock_repo.create_stock({
'tenant_id': tenant_id,
'inventory_product_id': inventory_product_id,
'quantity_available': Decimal('0'),
# ... other fields
})
# Update stock quantity
new_quantity = stock.quantity_available + accepted_quantity
await stock_repo.update_stock(
stock_id=stock.id,
tenant_id=tenant_id,
update_data={
'quantity_available': new_quantity,
'last_restocked_at': datetime.now(timezone.utc)
}
)
# Create stock entry for audit trail
entry = await entry_repo.create_entry({
'tenant_id': tenant_id,
'stock_id': stock.id,
'transaction_type': 'RESTOCK',
'quantity_change': accepted_quantity,
'quantity_after': new_quantity,
'reference_type': 'DELIVERY',
'reference_id': delivery_id,
'batch_number': item.get('batch_lot_number'),
'expiry_date': item.get('expiry_date'),
'notes': f"Delivery received from PO. Batch: {item.get('batch_lot_number', 'N/A')}"
})
await session.commit()
return True
```
**Event Schema:**
```json
{
"event_id": "uuid",
"event_type": "delivery.received",
"service_name": "procurement",
"timestamp": "2025-11-12T10:30:00Z",
"data": {
"tenant_id": "uuid",
"delivery_id": "uuid",
"po_id": "uuid",
"received_by": "uuid",
"received_at": "2025-11-12T10:30:00Z",
"items": [
{
"inventory_product_id": "uuid",
"ordered_quantity": 100.0,
"delivered_quantity": 98.0,
"accepted_quantity": 95.0,
"rejected_quantity": 3.0,
"batch_lot_number": "LOT-2025-1112",
"expiry_date": "2025-12-12",
"rejection_reason": "3 damaged units"
}
]
}
}
```
## FIFO Implementation
### FIFO Consumption Logic