Add POI feature and imporve the overall backend implementation
This commit is contained in:
@@ -30,6 +30,17 @@ The **Procurement Service** automates ingredient purchasing by analyzing product
|
||||
- **Performance Tracking** - Monitor on-time delivery and quality
|
||||
- **Supplier Scorecards** - Data-driven supplier evaluation
|
||||
|
||||
### Purchase Order Workflow & Tracking (🆕)
|
||||
- **Dashboard-Integrated Approval** - Approve/reject POs directly from dashboard action queue
|
||||
- **Progressive Disclosure** - View PO details inline without navigation
|
||||
- **Automatic Supplier Notifications** - Professional HTML emails sent on approval
|
||||
- **Delivery Date Tracking** - Auto-calculate estimated delivery based on supplier lead time
|
||||
- **Color-Coded Status Indicators** - Visual delivery tracking (green/yellow/red)
|
||||
- **Overdue Detection** - Hourly background job detects late deliveries
|
||||
- **Severity Levels** - Low (1d), Medium (2-3d), High (4-7d), Critical (7+ days overdue)
|
||||
- **Delivery Receipt Modal** - Comprehensive delivery recording with batch/expiry tracking
|
||||
- **Automatic Stock Updates** - Inventory updated automatically via events when deliveries recorded
|
||||
|
||||
### Stock Optimization
|
||||
- **Reorder Point Calculation** - When to order based on consumption rate
|
||||
- **Economic Order Quantity (EOQ)** - Optimal order size calculation
|
||||
@@ -103,9 +114,19 @@ The **Procurement Service** automates ingredient purchasing by analyzing product
|
||||
- `POST /api/v1/procurement/purchase-orders` - Create purchase order
|
||||
- `GET /api/v1/procurement/purchase-orders/{po_id}` - Get PO details
|
||||
- `PUT /api/v1/procurement/purchase-orders/{po_id}` - Update PO
|
||||
- `POST /api/v1/procurement/purchase-orders/{po_id}/approve` - Approve PO (triggers email)
|
||||
- `POST /api/v1/procurement/purchase-orders/{po_id}/reject` - Reject PO with reason
|
||||
- `POST /api/v1/procurement/purchase-orders/{po_id}/send` - Send PO to supplier
|
||||
- `POST /api/v1/procurement/purchase-orders/{po_id}/receive` - Mark PO received
|
||||
- `POST /api/v1/procurement/purchase-orders/{po_id}/cancel` - Cancel PO
|
||||
- `GET /api/v1/procurement/purchase-orders/overdue` - Get overdue POs (🆕)
|
||||
- `GET /api/v1/procurement/purchase-orders/{po_id}/overdue-status` - Check if PO is overdue (🆕)
|
||||
|
||||
### Deliveries (🆕)
|
||||
- `POST /api/v1/procurement/purchase-orders/{po_id}/deliveries` - Record delivery receipt
|
||||
- `GET /api/v1/procurement/purchase-orders/{po_id}/deliveries` - List deliveries for PO
|
||||
- `GET /api/v1/procurement/purchase-orders/{po_id}/deliveries/{delivery_id}` - Get delivery details
|
||||
- `PATCH /api/v1/procurement/purchase-orders/{po_id}/deliveries/{delivery_id}/status` - Update delivery status
|
||||
|
||||
### Purchase Order Items
|
||||
- `GET /api/v1/procurement/purchase-orders/{po_id}/items` - List PO items
|
||||
@@ -690,8 +711,110 @@ async def recommend_supplier(
|
||||
|
||||
### Published Events (RabbitMQ)
|
||||
|
||||
**Exchange**: `procurement.events`
|
||||
**Routing Keys**: `po.approved`, `po.rejected`, `po.sent_to_supplier`, `delivery.received`, `procurement.needs_calculated`, `procurement.po_created`, `procurement.stockout_risk`
|
||||
|
||||
### Purchase Order Lifecycle Events (🆕)
|
||||
|
||||
**PO Approved Event** - Published when a PO is approved
|
||||
- **Routing Key**: `po.approved`
|
||||
- **Consumed By**: Notification service (sends email to supplier)
|
||||
- **Trigger**: User approves PO in dashboard or via API
|
||||
|
||||
```json
|
||||
{
|
||||
"event_id": "uuid",
|
||||
"event_type": "po.approved",
|
||||
"service_name": "procurement",
|
||||
"timestamp": "2025-11-12T10:30:00Z",
|
||||
"data": {
|
||||
"tenant_id": "uuid",
|
||||
"po_id": "uuid",
|
||||
"po_number": "PO-2025-1112-001",
|
||||
"supplier_id": "uuid",
|
||||
"supplier_name": "Harinas García",
|
||||
"supplier_email": "pedidos@harinasgarcia.es",
|
||||
"supplier_phone": "+34612345678",
|
||||
"total_amount": 850.00,
|
||||
"currency": "EUR",
|
||||
"required_delivery_date": "2025-11-19",
|
||||
"items": [
|
||||
{
|
||||
"product_name": "Harina de Trigo T-55",
|
||||
"ordered_quantity": 100.0,
|
||||
"unit_of_measure": "kg",
|
||||
"unit_price": 0.85,
|
||||
"line_total": 85.00
|
||||
}
|
||||
],
|
||||
"approved_by": "uuid",
|
||||
"approved_at": "2025-11-12T10:30:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**PO Rejected Event** - Published when a PO is rejected
|
||||
- **Routing Key**: `po.rejected`
|
||||
- **Consumed By**: Notification service (notifies stakeholders)
|
||||
- **Trigger**: User rejects PO with reason
|
||||
|
||||
```json
|
||||
{
|
||||
"event_id": "uuid",
|
||||
"event_type": "po.rejected",
|
||||
"service_name": "procurement",
|
||||
"timestamp": "2025-11-12T10:30:00Z",
|
||||
"data": {
|
||||
"tenant_id": "uuid",
|
||||
"po_id": "uuid",
|
||||
"po_number": "PO-2025-1112-001",
|
||||
"supplier_id": "uuid",
|
||||
"supplier_name": "Harinas García",
|
||||
"rejection_reason": "Price too high compared to market rate",
|
||||
"rejected_by": "uuid",
|
||||
"rejected_at": "2025-11-12T10:30:00Z"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Delivery Received Event** - Published when a delivery is recorded
|
||||
- **Routing Key**: `delivery.received`
|
||||
- **Consumed By**: Inventory service (automatically updates stock)
|
||||
- **Trigger**: User records delivery receipt in `DeliveryReceiptModal`
|
||||
|
||||
```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",
|
||||
"product_name": "Harina de Trigo T-55",
|
||||
"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 bags"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Legacy/Other Events
|
||||
|
||||
**Exchange**: `procurement`
|
||||
**Routing Keys**: `procurement.needs_calculated`, `procurement.po_created`, `procurement.po_received`, `procurement.stockout_risk`
|
||||
**Routing Keys**: `procurement.needs_calculated`, `procurement.po_created`, `procurement.stockout_risk`
|
||||
|
||||
**Procurement Needs Calculated Event**
|
||||
```json
|
||||
|
||||
Reference in New Issue
Block a user