Spaces:
Sleeping
Sleeping
| """ | |
| Inventory Requirements Service | |
| Helper service for working with project inventory requirements. | |
| Used when receiving inventory batches to validate against project requirements. | |
| """ | |
| from sqlalchemy.orm import Session | |
| from fastapi import HTTPException | |
| from typing import List, Dict, Any, Optional | |
| from uuid import UUID | |
| import logging | |
| from app.models.project import Project | |
| logger = logging.getLogger(__name__) | |
| class InventoryRequirementsService: | |
| """Service for managing project inventory requirements""" | |
| def get_project_inventory_requirements( | |
| project_id: UUID, | |
| db: Session, | |
| usage_type: Optional[str] = None, | |
| category: Optional[str] = None | |
| ) -> Dict[str, Dict[str, Any]]: | |
| """ | |
| Get inventory requirements for a project | |
| Args: | |
| project_id: Project ID | |
| db: Database session | |
| usage_type: Filter by usage type ('installed' or 'consumed') | |
| category: Filter by category | |
| Returns: | |
| Dictionary of inventory requirements keyed by code | |
| """ | |
| project = db.query(Project).filter(Project.id == project_id).first() | |
| if not project: | |
| raise HTTPException(status_code=404, detail="Project not found") | |
| inventory_reqs = project.inventory_requirements or {} | |
| # Apply filters if provided | |
| if usage_type or category: | |
| filtered_reqs = {} | |
| for code, req in inventory_reqs.items(): | |
| if usage_type and req.get('usage_type') != usage_type: | |
| continue | |
| if category and req.get('category') != category: | |
| continue | |
| filtered_reqs[code] = req | |
| return filtered_reqs | |
| return inventory_reqs | |
| def get_inventory_requirement_by_code( | |
| project_id: UUID, | |
| inventory_code: str, | |
| db: Session | |
| ) -> Optional[Dict[str, Any]]: | |
| """ | |
| Get a specific inventory requirement by code | |
| Args: | |
| project_id: Project ID | |
| inventory_code: Inventory code to look up | |
| db: Database session | |
| Returns: | |
| Inventory requirement dict or None if not found | |
| """ | |
| inventory_reqs = InventoryRequirementsService.get_project_inventory_requirements( | |
| project_id, db | |
| ) | |
| return inventory_reqs.get(inventory_code) | |
| def validate_inventory_code( | |
| project_id: UUID, | |
| inventory_code: str, | |
| db: Session | |
| ) -> bool: | |
| """ | |
| Validate that an inventory code exists in project requirements | |
| Args: | |
| project_id: Project ID | |
| inventory_code: Inventory code to validate | |
| db: Database session | |
| Returns: | |
| True if valid, raises HTTPException if invalid | |
| """ | |
| req = InventoryRequirementsService.get_inventory_requirement_by_code( | |
| project_id, inventory_code, db | |
| ) | |
| if not req: | |
| raise HTTPException( | |
| status_code=400, | |
| detail=f"Invalid inventory code '{inventory_code}'. Not defined in project requirements." | |
| ) | |
| return True | |
| def get_inventory_dropdown_options( | |
| project_id: UUID, | |
| db: Session, | |
| usage_type: Optional[str] = None | |
| ) -> List[Dict[str, Any]]: | |
| """ | |
| Get inventory options formatted for dropdown selection | |
| Used when receiving inventory batches | |
| Args: | |
| project_id: Project ID | |
| db: Database session | |
| usage_type: Filter by usage type | |
| Returns: | |
| List of dropdown options with code, name, description | |
| """ | |
| inventory_reqs = InventoryRequirementsService.get_project_inventory_requirements( | |
| project_id, db, usage_type=usage_type | |
| ) | |
| options = [] | |
| for code, req in inventory_reqs.items(): | |
| options.append({ | |
| 'code': code, | |
| 'name': req.get('name'), | |
| 'description': req.get('description'), | |
| 'category': req.get('category'), | |
| 'unit': req.get('unit', 'pieces'), | |
| 'requires_serial_number': req.get('requires_serial_number', False), | |
| 'usage_type': req.get('usage_type') | |
| }) | |
| # Sort by category then name | |
| options.sort(key=lambda x: (x.get('category') or '', x.get('name') or '')) | |
| return options | |
| def get_installed_inventory_for_completion( | |
| project_id: UUID, | |
| db: Session | |
| ) -> List[Dict[str, Any]]: | |
| """ | |
| Get inventory items that should appear in ticket completion forms | |
| Only returns 'installed' items with include_in_completion=True | |
| Args: | |
| project_id: Project ID | |
| db: Database session | |
| Returns: | |
| List of inventory items for completion form | |
| """ | |
| inventory_reqs = InventoryRequirementsService.get_project_inventory_requirements( | |
| project_id, db, usage_type='installed' | |
| ) | |
| completion_items = [] | |
| for code, req in inventory_reqs.items(): | |
| if req.get('include_in_completion', True): | |
| completion_items.append({ | |
| 'code': code, | |
| 'name': req.get('name'), | |
| 'description': req.get('description'), | |
| 'requires_serial_number': req.get('requires_serial_number', False), | |
| 'completion_field_label': req.get('completion_field_label') or req.get('name'), | |
| 'completion_required': req.get('completion_required', True), | |
| 'category': req.get('category') | |
| }) | |
| return completion_items | |
| def get_inventory_categories( | |
| project_id: UUID, | |
| db: Session | |
| ) -> List[str]: | |
| """ | |
| Get list of unique inventory categories in project | |
| Args: | |
| project_id: Project ID | |
| db: Database session | |
| Returns: | |
| List of category names | |
| """ | |
| inventory_reqs = InventoryRequirementsService.get_project_inventory_requirements( | |
| project_id, db | |
| ) | |
| categories = set() | |
| for req in inventory_reqs.values(): | |
| category = req.get('category') | |
| if category: | |
| categories.add(category) | |
| return sorted(list(categories)) | |