diff --git a/backend/app/routers/products.py b/backend/app/routers/products.py index 481b80b..9f0701c 100644 --- a/backend/app/routers/products.py +++ b/backend/app/routers/products.py @@ -251,19 +251,21 @@ def update_product( data.pop("date_precision", None) # Spalte ist NOT NULL else: data["date_precision"] = data["date_precision"].value - alte_bildadresse = product.image_url for field, value in data.items(): setattr(product, field, value) # Gruppe oder Barcode koennen sich geaendert haben - Code nachziehen. sync_group_code(db, product) - if "image_url" in data and data["image_url"] != alte_bildadresse: - # Neue Adresse heisst neues Bild – die alte Kopie waere sonst dauerhaft - # falsch, weil ``ensure`` nur nachlaedt, wenn gar keine Kopie da ist. + if "image_url" in data: + # Massgeblich ist, woher die vorhandene Kopie stammt - nicht, ob sich + # die Adresse am Artikel geaendert hat. Sonst passierte genau dann + # nichts, wenn die Adresse schon stimmte, der Abruf damals aber + # fehlschlug: Der Artikel bliebe dauerhaft ohne Bild. alt = db.get(ProductImage, product.id) - if alt is not None: + if alt is not None and alt.source_url != product.image_url: db.delete(alt) db.flush() - if product.image_url: + alt = None + if alt is None and product.image_url: images.store(db, product, product.image_url) db.commit() db.refresh(product) diff --git a/backend/tests/test_product_images.py b/backend/tests/test_product_images.py index 211a5b4..4f3b155 100644 --- a/backend/tests/test_product_images.py +++ b/backend/tests/test_product_images.py @@ -99,6 +99,28 @@ def test_import_ueberschreibt_kein_vorhandenes_bild(db, user): assert vorhanden.image_url == "https://eigenes.example/bild.jpg" +def test_speichern_holt_nach_wenn_die_kopie_fehlt(db, user, monkeypatch): + """Der haeufigste Fall: Adresse stimmt laengst, der Abruf schlug nur einmal fehl. + + Wuerde nur auf eine geaenderte Adresse geachtet, bliebe so ein Artikel + dauerhaft ohne Bild - "Uebernehmen" waere dann folgenlos. + """ + from app.routers.products import update_product + from app.schemas import ProductUpdate + + monkeypatch.setattr(images, "fetch", lambda url: (EIN_PIXEL, "image/png")) + artikel = _artikel(db, "https://example.org/pesto.png") + assert db.get(ProductImage, artikel.id) is None + + update_product( + artikel.id, + ProductUpdate(image_url="https://example.org/pesto.png"), + db=db, + _=user, + ) + assert db.get(ProductImage, artikel.id) is not None + + def test_fetch_geht_nur_an_http_adressen(monkeypatch): """Ohne diese Schranke waere eine 'file://'-Adresse ein Weg ins Dateisystem.""" monkeypatch.setattr( diff --git a/web/src/components/OffVergleich.jsx b/web/src/components/OffVergleich.jsx index f4f223c..8d6f9d8 100644 --- a/web/src/components/OffVergleich.jsx +++ b/web/src/components/OffVergleich.jsx @@ -11,7 +11,8 @@ import ProduktBild from "./ProduktBild"; * felder: [{ schluessel, titel, eigen, fremd, anzeigeEigen?, anzeigeFremd? }] */ export default function OffVergleich({ - felder, bildEigenId, bildFremdUrl, onUebernehmen, onAlle, onSchliessen, + felder, bildEigenId, bildFremdUrl, bildUebernommen, + onUebernehmen, onAlle, onSchliessen, }) { const leer = (wert) => wert === null || wert === undefined || wert === ""; const abweichend = felder.filter((f) => !leer(f.fremd) && String(f.fremd) !== String(f.eigen)); @@ -62,7 +63,19 @@ export default function OffVergleich({