Add supplier and imporve inventory frontend

This commit is contained in:
Urtzi Alfaro
2025-09-18 23:32:53 +02:00
parent ae77a0e1c5
commit d61056df33
40 changed files with 2022 additions and 629 deletions

View File

@@ -13,11 +13,10 @@ class AlertProcessorConfig(BaseServiceSettings):
APP_NAME: str = "Alert Processor Service"
DESCRIPTION: str = "Central alert and recommendation processor"
# Use the notification database for alert storage
# This makes sense since alerts and notifications are closely related
# Use dedicated database for alert storage
DATABASE_URL: str = os.getenv(
"NOTIFICATION_DATABASE_URL",
"postgresql+asyncpg://notification_user:notification_pass123@notification-db:5432/notification_db"
"ALERT_PROCESSOR_DATABASE_URL",
"postgresql+asyncpg://alert_processor_user:alert_processor_pass123@alert-processor-db:5432/alert_processor_db"
)
# Use dedicated Redis DB for alert processing

View File

@@ -206,42 +206,47 @@ class AlertProcessorService:
async def store_item(self, item: dict) -> dict:
"""Store alert or recommendation in database"""
from sqlalchemy import text
query = text("""
INSERT INTO alerts (
id, tenant_id, item_type, alert_type, severity, status,
service, title, message, actions, metadata,
created_at
) VALUES (:id, :tenant_id, :item_type, :alert_type, :severity, :status,
:service, :title, :message, :actions, :metadata, :created_at)
RETURNING *
""")
from app.models.alerts import Alert, AlertSeverity, AlertStatus
from sqlalchemy import select
async with self.db_manager.get_session() as session:
result = await session.execute(
query,
{
'id': item['id'],
'tenant_id': item['tenant_id'],
'item_type': item['item_type'], # 'alert' or 'recommendation'
'alert_type': item['type'],
'severity': item['severity'],
'status': 'active',
'service': item['service'],
'title': item['title'],
'message': item['message'],
'actions': json.dumps(item.get('actions', [])),
'metadata': json.dumps(item.get('metadata', {})),
'created_at': item['timestamp']
}
# Create alert instance
alert = Alert(
id=item['id'],
tenant_id=item['tenant_id'],
item_type=item['item_type'], # 'alert' or 'recommendation'
alert_type=item['type'],
severity=AlertSeverity(item['severity']),
status=AlertStatus.ACTIVE,
service=item['service'],
title=item['title'],
message=item['message'],
actions=item.get('actions', []),
alert_metadata=item.get('metadata', {}),
created_at=datetime.fromisoformat(item['timestamp']) if isinstance(item['timestamp'], str) else item['timestamp']
)
row = result.fetchone()
session.add(alert)
await session.commit()
await session.refresh(alert)
logger.debug("Item stored in database", item_id=item['id'])
return dict(row._mapping)
# Convert to dict for return
return {
'id': str(alert.id),
'tenant_id': str(alert.tenant_id),
'item_type': alert.item_type,
'alert_type': alert.alert_type,
'severity': alert.severity.value,
'status': alert.status.value,
'service': alert.service,
'title': alert.title,
'message': alert.message,
'actions': alert.actions,
'metadata': alert.alert_metadata,
'created_at': alert.created_at
}
async def stream_to_sse(self, tenant_id: str, item: dict):
"""Publish item to Redis for SSE streaming"""

View File

@@ -0,0 +1 @@
# services/alert_processor/app/models/__init__.py

View File

@@ -0,0 +1,56 @@
# services/alert_processor/app/models/alerts.py
"""
Alert models for the alert processor service
"""
from sqlalchemy import Column, String, Text, DateTime, JSON, Enum
from sqlalchemy.dialects.postgresql import UUID
from datetime import datetime
import uuid
import enum
from shared.database.base import Base
class AlertStatus(enum.Enum):
"""Alert status values"""
ACTIVE = "active"
RESOLVED = "resolved"
ACKNOWLEDGED = "acknowledged"
IGNORED = "ignored"
class AlertSeverity(enum.Enum):
"""Alert severity levels"""
LOW = "low"
MEDIUM = "medium"
HIGH = "high"
URGENT = "urgent"
class Alert(Base):
"""Alert records for the alert processor service"""
__tablename__ = "alerts"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
tenant_id = Column(UUID(as_uuid=True), nullable=False, index=True)
# Alert classification
item_type = Column(String(50), nullable=False) # 'alert' or 'recommendation'
alert_type = Column(String(100), nullable=False) # e.g., 'overstock_warning'
severity = Column(Enum(AlertSeverity), nullable=False, index=True)
status = Column(Enum(AlertStatus), default=AlertStatus.ACTIVE, index=True)
# Source and content
service = Column(String(100), nullable=False) # originating service
title = Column(String(255), nullable=False)
message = Column(Text, nullable=False)
# Actions and metadata
actions = Column(JSON, nullable=True) # List of available actions
alert_metadata = Column(JSON, nullable=True) # Additional alert-specific data
# Timestamps
created_at = Column(DateTime, default=datetime.utcnow, index=True)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
resolved_at = Column(DateTime, nullable=True)