"""Stammdaten-Export/Import (JSON) mit ID-Erhalt und Konfliktmodi.""" import pytest from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker from sqlalchemy.pool import StaticPool from app.database import Base from app.models import Category, FieldDefinition, Location, PackageType, Unit from app.services.master_data import ( FORMAT_KEY, export_master_data, import_master_data, ) def _fresh_db(): engine = create_engine( "sqlite://", connect_args={"check_same_thread": False}, poolclass=StaticPool ) Base.metadata.create_all(bind=engine) return sessionmaker(bind=engine, autoflush=False, autocommit=False)() def test_roundtrip_erhaelt_ids_und_baum(db): ober = Category(name="Elektronik", tracking="object") db.add(ober) db.flush() unter = Category(name="Kabel", parent_id=ober.id, tracking="object") db.add(unter) db.flush() db.add(FieldDefinition(category_id=ober.id, label="Kapazität", key="kapazitaet", field_type="number", unit="mAh")) haus = Location(name="Hedingen") db.add(haus) db.flush() keller = Location(name="Keller", parent_id=haus.id) db.add(keller) beutel = PackageType(singular="Beutel", plural="Beutel") db.add(beutel) db.commit() beutel_id = beutel.id data = export_master_data(db) ziel = _fresh_db() import_master_data(ziel, data, mode="skip") assert ziel.get(Category, ober.id).name == "Elektronik" assert ziel.get(Category, unter.id).parent_id == ober.id # Baum erhalten assert ziel.get(Location, keller.id).parent_id == haus.id assert ziel.query(FieldDefinition).filter_by(category_id=ober.id).first().label == "Kapazität" assert ziel.get(PackageType, beutel_id).singular == "Beutel" # id erhalten def test_skip_laesst_vorhandenes_unangetastet(db): a = Location(name="Alt") db.add(a) db.commit() data = {FORMAT_KEY: 1, "locations": [{"id": a.id, "name": "Neu"}]} rep = import_master_data(db, data, mode="skip") assert db.get(Location, a.id).name == "Alt" assert rep["skipped"].get("locations") == 1 def test_overwrite_aktualisiert_per_id(db): a = Location(name="Alt") db.add(a) db.commit() data = {FORMAT_KEY: 1, "locations": [{"id": a.id, "name": "Neu"}]} rep = import_master_data(db, data, mode="overwrite") assert db.get(Location, a.id).name == "Neu" assert rep["updated"].get("locations") == 1 def test_falsche_datei_wirft(): with pytest.raises(ValueError): import_master_data(_fresh_db(), {"foo": 1}) def test_namenskonflikt_wird_uebersprungen_nicht_abgebrochen(db): # Vorhandene Einheit unter id X; Import bringt gleichen Namen unter anderer id. vorhanden = Unit(name="Spezialeinheit", kind="count", factor=1) db.add(vorhanden) db.commit() data = {FORMAT_KEY: 1, "units": [{"id": vorhanden.id + 999, "name": "Spezialeinheit", "kind": "count", "factor": 1}]} rep = import_master_data(db, data, mode="skip") # Gleicher Name unter neuer id -> Eindeutigkeit verletzt -> uebersprungen. assert rep["skipped"].get("units") == 1 assert db.query(Unit).filter_by(name="Spezialeinheit").count() == 1