fix: KoePi trinkgut bekommt eigene, praezise Koordinaten statt gemeinsamem Referenzpunkt

This commit is contained in:
2026-07-20 17:31:40 +02:00
parent 8734067dcd
commit 99ac6cf068

View File

@@ -75,7 +75,7 @@ const RETAILER_FAMILIES = {
const LOCAL_STORE_TARGETS = [
{ retailer: 'Netto Marken-Discount', uniqueName: 'netto-marken-discount', addressMatch: 'Im Bonnefeld 19' },
{ retailer: 'Netto Getränke-Discount', uniqueName: 'netto-getraenke-discount', addressMatch: 'Im Bonnefeld 21' },
{ retailer: 'trinkgut', uniqueName: 'trinkgut', addressMatch: 'Keniastraße 39' },
{ retailer: 'trinkgut', uniqueName: 'trinkgut', addressMatch: 'Keniastraße 39', lat: '51.377915761179864', lon: '6.773658722208071' },
{ retailer: 'REWE', uniqueName: 'rewe', addressMatch: 'Fischerstr. 110-112' },
{ retailer: 'Kaufland', uniqueName: 'kaufland', addressMatch: 'Auf der Höhe 20' },
{ retailer: 'Penny', uniqueName: 'penny', addressMatch: 'Sittardsberger Allee 10' },
@@ -181,13 +181,14 @@ async function fetchLeafletFlightToLeafletMap(extraSearchKeys = []) {
// closestStore (id/address/distanceInMeters — Grundlage der Filial-Whitelist),
// name (enthält oft "(KW29 Do-Sa)" o.ä.) und children (Liste aller Angebote
// mit ihrem pageIndex, für den seiten-genauen Direktlink).
async function fetchLeafletDetail(leafletId, cache) {
if (cache.has(leafletId)) return cache.get(leafletId);
async function fetchLeafletDetail(leafletId, cache, lat = MG_LAT, lon = MG_LON) {
const cacheKey = `${leafletId}:${lat}:${lon}`;
if (cache.has(cacheKey)) return cache.get(cacheKey);
const empty = { id: leafletId, name: '', closestStore: { id: null, address: '', distanceMeters: null }, children: [] };
try {
const url = `https://api.marktguru.de/api/v1/leaflets/${leafletId}?as=mobiledetailed&latitude=${MG_LAT}&longitude=${MG_LON}&zipCode=${MG_ZIP}`;
const url = `https://api.marktguru.de/api/v1/leaflets/${leafletId}?as=mobiledetailed&latitude=${lat}&longitude=${lon}&zipCode=${MG_ZIP}`;
const res = await fetch(url, { headers: mgHeaders });
if (!res.ok) { cache.set(leafletId, empty); return empty; }
if (!res.ok) { cache.set(cacheKey, empty); return empty; }
const json = await res.json();
const store = json.closestStore;
const result = {
@@ -199,11 +200,11 @@ async function fetchLeafletDetail(leafletId, cache) {
children: json.children || [],
};
console.log(`🍺 KöPi: Leaflet ${leafletId} ("${result.name}") → closestStore: ${store ? `id=${store.id} "${store.address}" (${Math.round(store.distanceInMeters||0)}m entfernt)` : 'keine'}`);
cache.set(leafletId, result);
cache.set(cacheKey, result);
return result;
} catch (e) {
console.log(`🍺 KöPi: Leaflet-Detail-Abruf für ${leafletId} fehlgeschlagen: ${e.message}`);
cache.set(leafletId, empty);
cache.set(cacheKey, empty);
return empty;
}
}
@@ -276,7 +277,7 @@ async function resolveLocalStores() {
let found = null;
for (const l of leaflets) {
if (!l.mainLeafletId) continue;
const detail = await fetchLeafletDetail(l.mainLeafletId, cache);
const detail = await fetchLeafletDetail(l.mainLeafletId, cache, target.lat || MG_LAT, target.lon || MG_LON);
const store = detail.closestStore;
if (store.id != null && addressesMatch(store.address, target.addressMatch)) {
found = store;
@@ -587,7 +588,7 @@ async function scrapeProspekte() {
const leaflets = await fetchLeafletsForRetailer(target.uniqueName);
for (const f of leaflets) {
if (!f.mainLeafletId) continue;
const detail = await fetchLeafletDetail(f.mainLeafletId, leafletCache);
const detail = await fetchLeafletDetail(f.mainLeafletId, leafletCache, target.lat || MG_LAT, target.lon || MG_LON);
const store = detail.closestStore;
const weekInfo = weekInfoWithFallback(detail.name, f.validFrom);
// Store-spezifische Bezeichnung aus der Whitelist bevorzugen (z.B. "Netto