feat: /api/v2/analiza/* endpoints - sport analytics backend
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
RNO Import — sve PGZ sport organizacije u DB
|
||||
Filter: Županija=Primorsko-goranska, šifra djelatnosti sport (85,90,93)
|
||||
"""
|
||||
import psycopg2, psycopg2.extras, os, sys
|
||||
from datetime import datetime
|
||||
|
||||
DSN = f"host=10.10.0.2 port=6432 dbname=rinet_v3 user=rinet password={os.environ['DB_PASSWORD']}"
|
||||
DIR = "/opt/pgz-sport/_downloads/CSV"
|
||||
LOG = "/opt/pgz-sport/logs/rno_import.log"
|
||||
|
||||
os.makedirs("/opt/pgz-sport/logs", exist_ok=True)
|
||||
|
||||
def log(msg):
|
||||
ts = datetime.now().strftime("%H:%M:%S")
|
||||
line = f"[{ts}] {msg}"
|
||||
print(line, flush=True)
|
||||
with open(LOG, "a") as f: f.write(line+"\n")
|
||||
|
||||
conn = psycopg2.connect(DSN)
|
||||
conn.autocommit = True
|
||||
cur = conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor)
|
||||
|
||||
# Create table
|
||||
cur.execute("""
|
||||
CREATE TABLE IF NOT EXISTS pgz_sport.rno_organizacije (
|
||||
rno_broj TEXT PRIMARY KEY,
|
||||
datum_upisa DATE,
|
||||
datum_brisanja DATE,
|
||||
datum_izmjene DATE,
|
||||
naziv TEXT NOT NULL,
|
||||
naziv_kratki TEXT,
|
||||
oib TEXT,
|
||||
maticni_broj TEXT,
|
||||
pravni_oblik TEXT,
|
||||
adresa TEXT,
|
||||
postanski_broj TEXT,
|
||||
mjesto TEXT,
|
||||
sifra_djelatnosti TEXT,
|
||||
racun TEXT,
|
||||
stat_oznaka TEXT,
|
||||
osoba_kontakt TEXT,
|
||||
zupanija TEXT,
|
||||
telefon TEXT,
|
||||
email TEXT,
|
||||
web TEXT,
|
||||
obveza_dvojnog BOOLEAN,
|
||||
aktivna BOOLEAN DEFAULT true,
|
||||
created_at TIMESTAMPTZ DEFAULT now()
|
||||
)
|
||||
""")
|
||||
log("Table created/exists")
|
||||
|
||||
# Parse Organizacija.txt
|
||||
log("Parsing Organizacija.txt...")
|
||||
pgz_sport = []
|
||||
total = 0
|
||||
skipped = 0
|
||||
|
||||
SPORT_CODES = {"9311","9312","9313","9319","9321","9329","931","932","93","8551","8552","9004","9001","8553"}
|
||||
|
||||
with open(f"{DIR}/Organizacija.txt", encoding="utf-16-le", errors="replace") as f:
|
||||
headers = f.readline().strip("\ufeff").strip().split("$")
|
||||
h = {v: i for i, v in enumerate(headers)}
|
||||
|
||||
for line in f:
|
||||
cols = line.strip().split("$")
|
||||
if len(cols) < 20:
|
||||
continue
|
||||
total += 1
|
||||
|
||||
def g(key):
|
||||
idx = h.get(key)
|
||||
return cols[idx].strip() if idx is not None and idx < len(cols) else ""
|
||||
|
||||
zupanija = g("20. Županija")
|
||||
sifra = g("16. Šifra djelatnosti")
|
||||
naziv = g("05. Naziv neprofitne organizacije")
|
||||
|
||||
# Filter: PGZ county + sport/physical activity djelatnost codes
|
||||
is_pgz = "primorsko" in zupanija.lower() or "pgž" in zupanija.lower() or "goranska" in zupanija.lower()
|
||||
is_sport = any(sifra.startswith(s) for s in ["93","855","930","855"])
|
||||
# Also catch by name keywords
|
||||
sport_keywords = ["sport","klup","klub","savez","planinar","ronilac","jedrilic","plivac","atletik","košark","rukom","odbojk","nogom","tenis","boksac","boksa","karate","judo","strijelj","bicikl","vater","plivali","strelichar","ribolov","lov","šah","šahovsk"]
|
||||
is_sport_name = any(k in naziv.lower() for k in sport_keywords)
|
||||
|
||||
if is_pgz and (is_sport or is_sport_name):
|
||||
def parse_date(s):
|
||||
if not s or not s.strip(): return None
|
||||
try:
|
||||
parts = s.strip().rstrip(".").split(".")
|
||||
if len(parts) == 3:
|
||||
return f"{parts[2]}-{parts[1]}-{parts[0]}"
|
||||
except: pass
|
||||
return None
|
||||
|
||||
pgz_sport.append((
|
||||
g("01. RNO broj"),
|
||||
parse_date(g("02. Datum upisa u registar")),
|
||||
parse_date(g("03. Datum brisanja iz registra")),
|
||||
parse_date(g("04. Datum zadnje izmjene")),
|
||||
naziv,
|
||||
g("06. Skraćeni naziv neprofitne organizacije"),
|
||||
g("07. OIB"),
|
||||
g("08. Matični broj"),
|
||||
g("09. Pravno ustrojbeni oblik"),
|
||||
g("13. Adresa sjedišta"),
|
||||
g("14. Poštanski broj"),
|
||||
g("15. Mjesto"),
|
||||
sifra,
|
||||
g("17. Račun"),
|
||||
g("18. Statistička oznaka grada/općine"),
|
||||
g("19. Osoba za kontakt"),
|
||||
zupanija,
|
||||
g("21. Telefon"),
|
||||
g("23. Email"),
|
||||
g("24. Web stranica"),
|
||||
g("03. Datum brisanja iz registra") == "", # aktivna
|
||||
))
|
||||
|
||||
log(f"Parsed {total} rows, found {len(pgz_sport)} PGZ sport orgs")
|
||||
|
||||
# Insert
|
||||
psycopg2.extras.execute_batch(cur, """
|
||||
INSERT INTO pgz_sport.rno_organizacije
|
||||
(rno_broj, datum_upisa, datum_brisanja, datum_izmjene, naziv, naziv_kratki,
|
||||
oib, maticni_broj, pravni_oblik, adresa, postanski_broj, mjesto,
|
||||
sifra_djelatnosti, racun, stat_oznaka, osoba_kontakt, zupanija,
|
||||
telefon, email, web, aktivna)
|
||||
VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)
|
||||
ON CONFLICT (rno_broj) DO UPDATE SET
|
||||
datum_izmjene=EXCLUDED.datum_izmjene, naziv=EXCLUDED.naziv,
|
||||
email=EXCLUDED.email, web=EXCLUDED.web, aktivna=EXCLUDED.aktivna
|
||||
""", pgz_sport, page_size=500)
|
||||
|
||||
cur.execute("SELECT COUNT(*) as n FROM pgz_sport.rno_organizacije")
|
||||
n = cur.fetchone()["n"]
|
||||
log(f"✅ RNO done: {n} PGZ sport org u DB")
|
||||
|
||||
# Sample
|
||||
cur.execute("""
|
||||
SELECT naziv, oib, mjesto, sifra_djelatnosti
|
||||
FROM pgz_sport.rno_organizacije
|
||||
WHERE aktivna=true
|
||||
ORDER BY naziv
|
||||
LIMIT 10
|
||||
""")
|
||||
for row in cur.fetchall():
|
||||
log(f" {row['naziv'][:40]} | {row['mjesto']} | {row['oib']}")
|
||||
|
||||
conn.close()
|
||||
Reference in New Issue
Block a user