Headless podatkovni servis koji svakodnevno objavljene cijene namirnica u Hrvatskoj agregira u jedinstveni API dostupan za upite. Laravel cjevovod za unos normalizira sirove datoteke cijena trgovaca u kanonski katalog proizvoda, prati svaku promjenu cijene kroz vrijeme i odgovara na upite o košarici, povijesti cijena i trgovinama u blizini — podatkovna okosnica iza usporedbe cijena u aplikaciji Household.
Prices je podatkovna okosnica iza usporedbe cijena u aplikaciji Household, i izgrađen je poput infrastrukture, a ne proizvoda: Laravel 13 API bez korisničkog sučelja, oslonjen na PostgreSQL i PostGIS. Prema hrvatskom zakonu o objavi cijena iz 2025., veliki trgovci dnevno objavljuju strojno čitljive datoteke cijena; ovaj ih servis unosi, usklađuje u jedan katalog i poslužuje rezultat preko malog autenticiranog API-ja.
Zanimljiv rad je u cjevovodu i podatkovnom modelu. Adapter po lancu pretvara format svakog trgovca u zajednički DTO, a importer neovisan o adapteru skupno upisuje u kanonski katalog — 23,6k proizvoda razriješeno barkodom kroz 21 lanac, uz klasifikacijski prolaz koji neuredna imena lanaca mapira na normalizirane kategorije. Svaka promjena cijene dodaje se u tablicu povijesti particioniranu po mjesecu, a 294 geokodirane trgovine čine “najjeftinije u mojim trgovinama” stvarnim PostGIS upitom po radijusu, a ne nagađanjem.
Admin je namjerno utilitaran — prikaz crawl pokretanja i klasifikacije za vlastiti nadzor, a ne proizvod. To je i smisao: Prices postoji da jedan posao odradi dobro i da Householdu preda čiste podatke preko poštene API granice. Brojke i tvrdnje iznad pročitane su izravno iz izvora i produkcijske baze, a ne procijenjene.
Svaki lanac objavljuje drukčiji format datoteke cijena prema hrvatskom zakonu o objavi cijena iz 2025. Adapter po lancu parsira njegov format u zajednički PriceRowDTO; importer neovisan o adapteru zatim te retke skupno upisuje u products, chain_products, prices i price_history u dijeljenim transakcijama.
Svaki lanac imenuje i kodira proizvode na svoj način. Kanonski proizvodi ključuju se barkodom, pri čemu se sirovi unos svakog lanca povezuje kao chain_product, a klasifikacijski prolaz mapira neuredna imena lanaca na normalizirane kategorije — tako da košarica može usporediti istovrsno kroz trgovce.
Trenutne cijene žive u vrućoj tablici prices; svaka zabilježena promjena dodaje se u particioniranu price_history. Mjesečne Postgres particije održavaju tablicu povijesti brzom kako raste, a rotacijska naredba osigurava nadolazeće mjesece i ispušta istekle prema rasporedu.
Trgovine nose koordinate kao PostGIS točku, pa upit stores/near vraća trgovine unutar radijusa poredane po stvarnoj udaljenosti — ne po graničnom okviru. To je ono što omogućuje da korisnik pita 'najjeftinije u mojim trgovinama', a ne 'najjeftinije u državi'.
Cijeli je servis API-first: devet autenticiranih krajnjih točaka koje pokrivaju lance, trgovine, košaricu, pretragu proizvoda, trenutne cijene, povijest cijena i status feed. Household je primarni konzument, pozivajući ga preko autenticirane HTTP granice bez dijeljene baze.
Svaki trgovac objavljuje vlastita imena proizvoda, kodove i oznake kategorija. Bez zajedničkog identiteta, usporedba 'najjeftinije košarice' bila bi besmislena — isto mlijeko izgleda kao 21 različit proizvod.
Proizvodi se kanonski ključuju barkodom, pri čemu se sirovi redak svakog lanca povezuje kao chain_product. Klasifikacijski prolaz (serijski SQL + Artisan naredba) mapira imena lanaca na normalizirane kategorije s ocjenom pouzdanosti i oznakom za ručno nadjačavanje, pa se usporedbe poklapaju kroz lance dok uparivanja niske pouzdanosti ostaju provjerljiva.
Praćenje svake promjene cijene kroz tisuće proizvoda i stotine trgovina znači tablicu povijesti koja raste bez granice — i usporava svaki upit kako raste.
price_history je particioniran po rasponu po mjesecu u Postgresu. Zakazani RotatePartitionsCommand osigurava nadolazeće particije i ispušta one izvan prozora zadržavanja, pa čitanja ostaju brza, a stari podaci uredno zastarijevaju bez ručne migracije.
Zakon iz 2025. pokriva samo trgovine velikog formata. Na Korčuli su fizički Konzumi svi malog formata i ne objavljuju ništa — pa bi naivni odgovori 'nema podataka' bili i netočni i beskorisni.
Trgovine su geokodirane i upitivane po stvarnoj PostGIS udaljenosti, a model jaz u formatima drži eksplicitnim: servis može odgovoriti 'najbliža trgovina koja objavljuje' umjesto da glumi pokrivenost koju nema. Poštenje je ugrađeno u podatke, ne nakalemljeno na sučelje.
Householdu trebaju cijene namirnica, ali velik, dnevno ažuriran skup podataka o cijenama nema mjesta unutar sheme aplikacije za vođenje kućanstva.
Prices je samostalan Laravel + Postgres servis s vlastitim unosom i životnim ciklusom. Household ga doseže samo preko autenticiranog HTTP API-ja (basket, search, history, stores-near), pa oba ostaju neovisno deployabilna i nijedan ne posjeduje podatke onog drugog.