104 lines
3.3 KiB
Python
104 lines
3.3 KiB
Python
import json
|
|
import os
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
from typing import Any
|
|
|
|
from sqlalchemy import text, Table, insert
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from models import User, Role, WorkShift, PayrollScheme, PayRate, user_pay_rate
|
|
from models.work_shifts import WorkShiftPause
|
|
|
|
|
|
class FixtureLoader:
|
|
def __init__(self, fixture_path: str = "fixtures"):
|
|
project_root = Path(__file__).parent
|
|
self.fixture_path = project_root / fixture_path
|
|
|
|
@staticmethod
|
|
def _fixtures_to_load() -> list[tuple[str, Any]]:
|
|
return [
|
|
("roles", Role),
|
|
("payroll_schemas", PayrollScheme),
|
|
("pay_rates", PayRate),
|
|
("users", User),
|
|
("work_shifts", WorkShift),
|
|
("work_shift_pauses", WorkShiftPause),
|
|
]
|
|
|
|
@staticmethod
|
|
def _many_to_many_fixtures() -> list[tuple[str, Table]]:
|
|
return [
|
|
("user_pay_rates", user_pay_rate),
|
|
]
|
|
|
|
async def load_fixtures(self, db: AsyncSession):
|
|
file_postfix = ".json"
|
|
for fixture_file, model in self._fixtures_to_load():
|
|
await self._load_model_fixtures(db, fixture_file + file_postfix, model)
|
|
|
|
for fixture_file, table in self._many_to_many_fixtures():
|
|
await self._load_m2m_fixtures(db, fixture_file + file_postfix, table)
|
|
|
|
async def _load_model_fixtures(
|
|
self,
|
|
db: AsyncSession,
|
|
fixture_file: str,
|
|
model: Any,
|
|
):
|
|
"""Load fixtures for a specific model"""
|
|
fixture_path = os.path.join(self.fixture_path, fixture_file)
|
|
|
|
if not os.path.exists(fixture_path):
|
|
print(f"Fixture file {fixture_path} not found")
|
|
return 0
|
|
|
|
with open(fixture_path, "r") as f:
|
|
data = json.load(f)
|
|
|
|
for item_data in data:
|
|
converted_data = {}
|
|
for key, value in item_data.items():
|
|
if isinstance(value, str) and len(value) == 19:
|
|
try:
|
|
# Try to parse as datetime
|
|
converted_data[key] = datetime.strptime(value, "%Y-%m-%d %H:%M:%S")
|
|
except ValueError:
|
|
# If it fails, keep the original value
|
|
converted_data[key] = value
|
|
else:
|
|
converted_data[key] = value
|
|
|
|
db_item = model(**converted_data)
|
|
db.add(db_item)
|
|
|
|
await db.commit()
|
|
|
|
async def _load_m2m_fixtures(
|
|
self,
|
|
db: AsyncSession,
|
|
fixture_file: str,
|
|
table: Table,
|
|
):
|
|
"""Load fixtures for many-to-many association tables"""
|
|
fixture_path = os.path.join(self.fixture_path, fixture_file)
|
|
|
|
if not os.path.exists(fixture_path):
|
|
print(f"Fixture file {fixture_path} not found")
|
|
return 0
|
|
|
|
with open(fixture_path, "r") as f:
|
|
data = json.load(f)
|
|
|
|
# Use SQLAlchemy insert for association tables
|
|
if data:
|
|
await db.execute(insert(table), data)
|
|
await db.commit()
|
|
|
|
async def clear_fixtures(self, db: AsyncSession):
|
|
"""Clear all fixture data (useful for testing)"""
|
|
for fixture_file, _ in self._fixtures_to_load()[::-1]:
|
|
await db.execute(text("DELETE FROM " + fixture_file))
|
|
await db.commit()
|