demo seed change 2
This commit is contained in:
@@ -18,6 +18,11 @@ from app.core.database import get_db
|
||||
from app.models.suppliers import Supplier
|
||||
from app.core.config import settings
|
||||
|
||||
# Import demo_dates utilities at the top level
|
||||
import sys
|
||||
sys.path.insert(0, str(Path(__file__).parent.parent.parent.parent))
|
||||
from shared.utils.demo_dates import adjust_date_for_demo, resolve_time_marker
|
||||
|
||||
logger = structlog.get_logger()
|
||||
router = APIRouter()
|
||||
|
||||
@@ -25,6 +30,62 @@ router = APIRouter()
|
||||
DEMO_TENANT_PROFESSIONAL = "a1b2c3d4-e5f6-47a8-b9c0-d1e2f3a4b5c6"
|
||||
|
||||
|
||||
def parse_date_field(
|
||||
field_value: any,
|
||||
session_time: datetime,
|
||||
field_name: str = "date"
|
||||
) -> Optional[datetime]:
|
||||
"""
|
||||
Parse a date field from JSON, supporting BASE_TS markers and ISO timestamps.
|
||||
|
||||
Args:
|
||||
field_value: The date field value (can be BASE_TS marker, ISO string, or None)
|
||||
session_time: Session creation time (timezone-aware UTC)
|
||||
field_name: Name of the field (for logging)
|
||||
|
||||
Returns:
|
||||
Timezone-aware UTC datetime or None
|
||||
"""
|
||||
if field_value is None:
|
||||
return None
|
||||
|
||||
# Handle BASE_TS markers
|
||||
if isinstance(field_value, str) and field_value.startswith("BASE_TS"):
|
||||
try:
|
||||
return resolve_time_marker(field_value, session_time)
|
||||
except (ValueError, AttributeError) as e:
|
||||
logger.warning(
|
||||
"Failed to resolve BASE_TS marker",
|
||||
field_name=field_name,
|
||||
marker=field_value,
|
||||
error=str(e)
|
||||
)
|
||||
return None
|
||||
|
||||
# Handle ISO timestamps (legacy format - convert to absolute datetime)
|
||||
if isinstance(field_value, str) and ('T' in field_value or 'Z' in field_value):
|
||||
try:
|
||||
parsed_date = datetime.fromisoformat(field_value.replace('Z', '+00:00'))
|
||||
# Adjust relative to session time
|
||||
return adjust_date_for_demo(parsed_date, session_time)
|
||||
except (ValueError, AttributeError) as e:
|
||||
logger.warning(
|
||||
"Failed to parse ISO timestamp",
|
||||
field_name=field_name,
|
||||
value=field_value,
|
||||
error=str(e)
|
||||
)
|
||||
return None
|
||||
|
||||
logger.warning(
|
||||
"Unknown date format",
|
||||
field_name=field_name,
|
||||
value=field_value,
|
||||
value_type=type(field_value).__name__
|
||||
)
|
||||
return None
|
||||
|
||||
|
||||
def verify_internal_api_key(x_internal_api_key: Optional[str] = Header(None)):
|
||||
"""Verify internal API key for service-to-service communication"""
|
||||
if x_internal_api_key != settings.INTERNAL_API_KEY:
|
||||
@@ -138,22 +199,17 @@ async def clone_demo_data(
|
||||
detail=f"Invalid UUID format in supplier data: {str(e)}"
|
||||
)
|
||||
|
||||
# Adjust dates relative to session creation time
|
||||
from shared.utils.demo_dates import adjust_date_for_demo, BASE_REFERENCE_DATE
|
||||
adjusted_created_at = adjust_date_for_demo(
|
||||
datetime.fromisoformat(supplier_data['created_at'].replace('Z', '+00:00')),
|
||||
# Parse date fields (supports BASE_TS markers and ISO timestamps)
|
||||
adjusted_created_at = parse_date_field(
|
||||
supplier_data.get('created_at'),
|
||||
session_time,
|
||||
BASE_REFERENCE_DATE
|
||||
"created_at"
|
||||
)
|
||||
# Handle optional updated_at field
|
||||
if 'updated_at' in supplier_data:
|
||||
adjusted_updated_at = adjust_date_for_demo(
|
||||
datetime.fromisoformat(supplier_data['updated_at'].replace('Z', '+00:00')),
|
||||
session_time,
|
||||
BASE_REFERENCE_DATE
|
||||
)
|
||||
else:
|
||||
adjusted_updated_at = adjusted_created_at
|
||||
adjusted_updated_at = parse_date_field(
|
||||
supplier_data.get('updated_at'),
|
||||
session_time,
|
||||
"updated_at"
|
||||
) or adjusted_created_at # Fallback to created_at if not provided
|
||||
|
||||
# Map supplier_type to enum if it's a string
|
||||
from app.models.suppliers import SupplierType, SupplierStatus, PaymentTerms
|
||||
@@ -226,17 +282,17 @@ async def clone_demo_data(
|
||||
approved_pos_count=supplier_data.get('approved_pos_count', 0),
|
||||
on_time_delivery_rate=supplier_data.get('on_time_delivery_rate', 0.0),
|
||||
fulfillment_rate=supplier_data.get('fulfillment_rate', 0.0),
|
||||
last_performance_update=adjust_date_for_demo(
|
||||
datetime.fromisoformat(supplier_data['last_performance_update'].replace('Z', '+00:00')),
|
||||
last_performance_update=parse_date_field(
|
||||
supplier_data.get('last_performance_update'),
|
||||
session_time,
|
||||
BASE_REFERENCE_DATE
|
||||
) if supplier_data.get('last_performance_update') else None,
|
||||
"last_performance_update"
|
||||
),
|
||||
approved_by=supplier_data.get('approved_by'),
|
||||
approved_at=adjust_date_for_demo(
|
||||
datetime.fromisoformat(supplier_data['approved_at'].replace('Z', '+00:00')),
|
||||
approved_at=parse_date_field(
|
||||
supplier_data.get('approved_at'),
|
||||
session_time,
|
||||
BASE_REFERENCE_DATE
|
||||
) if supplier_data.get('approved_at') else None,
|
||||
"approved_at"
|
||||
),
|
||||
rejection_reason=supplier_data.get('rejection_reason'),
|
||||
notes=supplier_data.get('notes'),
|
||||
certifications=supplier_data.get('certifications'),
|
||||
@@ -320,7 +376,7 @@ async def delete_demo_tenant_data(
|
||||
Delete all demo data for a virtual tenant.
|
||||
This endpoint is idempotent - safe to call multiple times.
|
||||
"""
|
||||
start_time = datetime.now()
|
||||
start_time = datetime.now(timezone.utc)
|
||||
|
||||
records_deleted = {
|
||||
"suppliers": 0,
|
||||
@@ -351,7 +407,7 @@ async def delete_demo_tenant_data(
|
||||
"status": "deleted",
|
||||
"virtual_tenant_id": str(virtual_tenant_id),
|
||||
"records_deleted": records_deleted,
|
||||
"duration_ms": int((datetime.now() - start_time).total_seconds() * 1000)
|
||||
"duration_ms": int((datetime.now(timezone.utc) - start_time).total_seconds() * 1000)
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
|
||||
Reference in New Issue
Block a user