diff --git a/_audit/data_integrity_20260505_0836/C_TRANSFERS.json b/_audit/data_integrity_20260505_0836/C_TRANSFERS.json new file mode 100644 index 0000000..0aaa5dd --- /dev/null +++ b/_audit/data_integrity_20260505_0836/C_TRANSFERS.json @@ -0,0 +1,1916 @@ +{ + "summary": { + "strict_hns_igrac_id_cross_klub": 0, + "strict_name_dob_cross_klub": 0, + "soft_name_only_groups": 56, + "soft_name_only_rows": 117, + "legitimate_transfers": 0, + "stale_transfers_purged": 0, + "review_only_groups": 56 + }, + "review_only_cases": [ + { + "key": "laura|babić", + "ime": "Laura", + "prezime": "Babić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1440, + "klub_id": 544, + "ime": "Laura", + "prezime": "Babić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4182, + "klub_id": 2600, + "ime": "Laura", + "prezime": "Babić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "carrolina|ban", + "ime": "Carrolina", + "prezime": "Ban", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1267, + "klub_id": 544, + "ime": "Carrolina", + "prezime": "Ban", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "manual", + "hns_igrac_id": null + }, + { + "id": 4183, + "klub_id": 2599, + "ime": "Carrolina", + "prezime": "Ban", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "nikol|belasić", + "ime": "Nikol", + "prezime": "Belasić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1297, + "klub_id": 544, + "ime": "Nikol", + "prezime": "Belasić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "manual", + "hns_igrac_id": null + }, + { + "id": 4184, + "klub_id": 2599, + "ime": "Nikol", + "prezime": "Belasić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "željko|blažičević", + "ime": "Željko", + "prezime": "Blažičević", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 624, + "klub_id": 373, + "ime": "Željko", + "prezime": "Blažičević", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "hbs_savez", + "hns_igrac_id": null + }, + { + "id": 2662, + "klub_id": 827, + "ime": "Željko", + "prezime": "Blažičević", + "datum_rodenja": "1957-01-01", + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "meri|bolterstein", + "ime": "Meri", + "prezime": "Bolterstein", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1407, + "klub_id": 544, + "ime": "Meri", + "prezime": "Bolterstein", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4185, + "klub_id": 2600, + "ime": "Meri", + "prezime": "Bolterstein", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "edi|bradamante", + "ime": "Edi", + "prezime": "Bradamante", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 2801, + "klub_id": 1508, + "ime": "Edi", + "prezime": "Bradamante", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "klub_web_v2", + "hns_igrac_id": null + }, + { + "id": 4109, + "klub_id": 2526, + "ime": "Edi", + "prezime": "Bradamante", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "klub_web", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "matija|brdar", + "ime": "Matija", + "prezime": "Brdar", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 546, + "klub_id": 2214, + "ime": "Matija", + "prezime": "Brdar", + "datum_rodenja": "1998-10-13", + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "hns_semafor", + "hns_igrac_id": null + }, + { + "id": 1173, + "klub_id": 849, + "ime": "Matija", + "prezime": "Brdar", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "josip|butković", + "ime": "Josip", + "prezime": "Butković", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 809, + "klub_id": 475, + "ime": "Josip", + "prezime": "Butković", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "hbs_savez", + "hns_igrac_id": null + }, + { + "id": 2661, + "klub_id": 821, + "ime": "Josip", + "prezime": "Butković", + "datum_rodenja": "1956-01-01", + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "mladen|ćoza", + "ime": "Mladen", + "prezime": "Ćoza", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 2708, + "klub_id": 1508, + "ime": "Mladen", + "prezime": "Ćoza", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "klub_web", + "hns_igrac_id": null + }, + { + "id": 4107, + "klub_id": 2526, + "ime": "Mladen", + "prezime": "Ćoza", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "klub_web", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "toni|diklić", + "ime": "Toni", + "prezime": "Diklić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 2796, + "klub_id": 553, + "ime": "Toni", + "prezime": "Diklić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "klub_web_v2", + "hns_igrac_id": null + }, + { + "id": 2808, + "klub_id": 2502, + "ime": "Toni", + "prezime": "Diklić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "klub_web_v2", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "mauro|dipić", + "ime": "Mauro", + "prezime": "Dipić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 3441, + "klub_id": 3896, + "ime": "Mauro", + "prezime": "Dipić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4478, + "klub_id": 3891, + "ime": "Mauro", + "prezime": "Dipić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "manual", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "tihomir|dragoslavić", + "ime": "Tihomir", + "prezime": "Dragoslavić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 2800, + "klub_id": 1508, + "ime": "Tihomir", + "prezime": "Dragoslavić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "klub_web_v2", + "hns_igrac_id": null + }, + { + "id": 4105, + "klub_id": 2526, + "ime": "Tihomir", + "prezime": "Dragoslavić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "klub_web", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "lucijan|dujmić", + "ime": "Lucijan", + "prezime": "Dujmić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 3287, + "klub_id": 3896, + "ime": "Lucijan", + "prezime": "Dujmić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4318, + "klub_id": 3891, + "ime": "Lucijan", + "prezime": "Dujmić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "manual", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "dora|fućak", + "ime": "Dora", + "prezime": "Fućak", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1371, + "klub_id": 544, + "ime": "Dora", + "prezime": "Fućak", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4186, + "klub_id": 2599, + "ime": "Dora", + "prezime": "Fućak", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "luka|funčić", + "ime": "Luka", + "prezime": "Funčić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 2707, + "klub_id": 1508, + "ime": "Luka", + "prezime": "Funčić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "klub_web", + "hns_igrac_id": null + }, + { + "id": 4106, + "klub_id": 2526, + "ime": "Luka", + "prezime": "Funčić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "klub_web", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "domagoj|ivan marić", + "ime": "Domagoj", + "prezime": "Ivan Marić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 3561, + "klub_id": 2362, + "ime": "Domagoj", + "prezime": "Ivan Marić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "godisnjak_2025_NAJUSPJESNIJI", + "hns_igrac_id": null + }, + { + "id": 3812, + "klub_id": 2526, + "ime": "Domagoj", + "prezime": "Ivan Marić", + "datum_rodenja": "2006-02-03", + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "hns_semafor", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "niko|janković", + "ime": "Niko", + "prezime": "Janković", + "n_rows": 4, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1428, + "klub_id": 1, + "ime": "Niko", + "prezime": "Janković", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 3607, + "klub_id": 2362, + "ime": "Niko", + "prezime": "Janković", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "klub_web", + "hns_igrac_id": null + }, + { + "id": 4132, + "klub_id": 2362, + "ime": "Niko", + "prezime": "Janković", + "datum_rodenja": "2001-08-25", + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hns_semafor", + "hns_igrac_id": null + }, + { + "id": 4218, + "klub_id": 2362, + "ime": "Niko", + "prezime": "Janković", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "manual", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "srećko|juričić", + "ime": "Srećko", + "prezime": "Juričić", + "n_rows": 3, + "n_distinct_klubs": 3, + "rows": [ + { + "id": 1792, + "klub_id": null, + "ime": "Srećko", + "prezime": "Juričić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4120, + "klub_id": 3760, + "ime": "Srećko", + "prezime": "Juričić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "klub_web", + "hns_igrac_id": null + }, + { + "id": 4127, + "klub_id": 2589, + "ime": "Srećko", + "prezime": "Juričić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "klub_web", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "veljko|karabaić", + "ime": "Veljko", + "prezime": "Karabaić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 2797, + "klub_id": 553, + "ime": "Veljko", + "prezime": "Karabaić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "klub_web_v2", + "hns_igrac_id": null + }, + { + "id": 2809, + "klub_id": 2502, + "ime": "Veljko", + "prezime": "Karabaić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "klub_web_v2", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "tomislav|katalenić", + "ime": "Tomislav", + "prezime": "Katalenić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 2918, + "klub_id": 2254, + "ime": "Tomislav", + "prezime": "Katalenić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "godisnjak_2025_REZ", + "hns_igrac_id": null + }, + { + "id": 3558, + "klub_id": 683, + "ime": "Tomislav", + "prezime": "Katalenić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "godisnjak_2025_REZULTATI", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "filip|klarić", + "ime": "Filip", + "prezime": "Klarić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1321, + "klub_id": 357, + "ime": "Filip", + "prezime": "Klarić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4166, + "klub_id": 2587, + "ime": "Filip", + "prezime": "Klarić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "korina|klarić", + "ime": "Korina", + "prezime": "Klarić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1370, + "klub_id": 544, + "ime": "Korina", + "prezime": "Klarić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4187, + "klub_id": 2600, + "ime": "Korina", + "prezime": "Klarić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "marko|komadina", + "ime": "Marko", + "prezime": "Komadina", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 145, + "klub_id": 2200, + "ime": "Marko", + "prezime": "Komadina", + "datum_rodenja": "2012-10-14", + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "hns_semafor", + "hns_igrac_id": null + }, + { + "id": 710, + "klub_id": 428, + "ime": "Marko", + "prezime": "Komadina", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "dorotea|margan", + "ime": "Dorotea", + "prezime": "Margan", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1439, + "klub_id": 544, + "ime": "Dorotea", + "prezime": "Margan", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4188, + "klub_id": 2599, + "ime": "Dorotea", + "prezime": "Margan", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "karlo|marjanović", + "ime": "Karlo", + "prezime": "Marjanović", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1152, + "klub_id": 2581, + "ime": "Karlo", + "prezime": "Marjanović", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "hbs_savez", + "hns_igrac_id": null + }, + { + "id": 4901, + "klub_id": 3896, + "ime": "Karlo", + "prezime": "Marjanović", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "manual", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "lucija|matejčić", + "ime": "Lucija", + "prezime": "Matejčić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1404, + "klub_id": 544, + "ime": "Lucija", + "prezime": "Matejčić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4189, + "klub_id": 2600, + "ime": "Lucija", + "prezime": "Matejčić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "vita|matejčić", + "ime": "Vita", + "prezime": "Matejčić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1410, + "klub_id": 544, + "ime": "Vita", + "prezime": "Matejčić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4190, + "klub_id": 2600, + "ime": "Vita", + "prezime": "Matejčić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "matija|milković", + "ime": "Matija", + "prezime": "Milković", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 148, + "klub_id": 2200, + "ime": "Matija", + "prezime": "Milković", + "datum_rodenja": "2004-10-23", + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "hns_semafor", + "hns_igrac_id": null + }, + { + "id": 4573, + "klub_id": 3896, + "ime": "Matija", + "prezime": "Milković", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "manual", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "damir|mišković", + "ime": "Damir", + "prezime": "Mišković", + "n_rows": 3, + "n_distinct_klubs": 3, + "rows": [ + { + "id": 2049, + "klub_id": null, + "ime": "Damir", + "prezime": "Mišković", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4119, + "klub_id": 3760, + "ime": "Damir", + "prezime": "Mišković", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "klub_web", + "hns_igrac_id": null + }, + { + "id": 4126, + "klub_id": 2589, + "ime": "Damir", + "prezime": "Mišković", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "klub_web", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "maris|mohorić", + "ime": "Maris", + "prezime": "Mohorić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1405, + "klub_id": 544, + "ime": "Maris", + "prezime": "Mohorić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4191, + "klub_id": 2600, + "ime": "Maris", + "prezime": "Mohorić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "mia|niessner", + "ime": "Mia", + "prezime": "Niessner", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1409, + "klub_id": 544, + "ime": "Mia", + "prezime": "Niessner", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4192, + "klub_id": 2600, + "ime": "Mia", + "prezime": "Niessner", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "nika|niessner", + "ime": "Nika", + "prezime": "Niessner", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1402, + "klub_id": 544, + "ime": "Nika", + "prezime": "Niessner", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4193, + "klub_id": 2600, + "ime": "Nika", + "prezime": "Niessner", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "ira|nimčević", + "ime": "Ira", + "prezime": "Nimčević", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1372, + "klub_id": 544, + "ime": "Ira", + "prezime": "Nimčević", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "manual", + "hns_igrac_id": null + }, + { + "id": 4194, + "klub_id": 2599, + "ime": "Ira", + "prezime": "Nimčević", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "nino|novosel", + "ime": "Nino", + "prezime": "Novosel", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 3338, + "klub_id": 2362, + "ime": "Nino", + "prezime": "Novosel", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 3696, + "klub_id": 2549, + "ime": "Nino", + "prezime": "Novosel", + "datum_rodenja": "2008-09-20", + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "hns_semafor", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "sandi|paoli", + "ime": "Sandi", + "prezime": "Paoli", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 3305, + "klub_id": 200, + "ime": "Sandi", + "prezime": "Paoli", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4161, + "klub_id": 2601, + "ime": "Sandi", + "prezime": "Paoli", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "andrija|pavičić", + "ime": "Andrija", + "prezime": "Pavičić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1717, + "klub_id": 138, + "ime": "Andrija", + "prezime": "Pavičić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4098, + "klub_id": 2502, + "ime": "Andrija", + "prezime": "Pavičić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "klub_web", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "tijana|pavičić", + "ime": "Tijana", + "prezime": "Pavičić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1716, + "klub_id": 138, + "ime": "Tijana", + "prezime": "Pavičić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4099, + "klub_id": 2502, + "ime": "Tijana", + "prezime": "Pavičić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "klub_web", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "zvonimir|pavletić", + "ime": "Zvonimir", + "prezime": "Pavletić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 3370, + "klub_id": 2510, + "ime": "Zvonimir", + "prezime": "Pavletić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4173, + "klub_id": 2589, + "ime": "Zvonimir", + "prezime": "Pavletić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "angela|pejoska", + "ime": "Angela", + "prezime": "Pejoska", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1369, + "klub_id": 544, + "ime": "Angela", + "prezime": "Pejoska", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4195, + "klub_id": 2600, + "ime": "Angela", + "prezime": "Pejoska", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "bojana|pejoska", + "ime": "Bojana", + "prezime": "Pejoska", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1373, + "klub_id": 544, + "ime": "Bojana", + "prezime": "Pejoska", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4196, + "klub_id": 2600, + "ime": "Bojana", + "prezime": "Pejoska", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "david|pekar", + "ime": "David", + "prezime": "Pekar", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 464, + "klub_id": 2200, + "ime": "David", + "prezime": "Pekar", + "datum_rodenja": "2008-11-24", + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "hns_semafor", + "hns_igrac_id": null + }, + { + "id": 1021, + "klub_id": 2588, + "ime": "David", + "prezime": "Pekar", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "roberta|petrović", + "ime": "Roberta", + "prezime": "Petrović", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1408, + "klub_id": 544, + "ime": "Roberta", + "prezime": "Petrović", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4197, + "klub_id": 2599, + "ime": "Roberta", + "prezime": "Petrović", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "leon|petz", + "ime": "Leon", + "prezime": "Petz", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 2280, + "klub_id": 2580, + "ime": "Leon", + "prezime": "Petz", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "hbs_savez", + "hns_igrac_id": null + }, + { + "id": 2315, + "klub_id": 2587, + "ime": "Leon", + "prezime": "Petz", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "ani|radetić", + "ime": "Ani", + "prezime": "Radetić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1368, + "klub_id": 544, + "ime": "Ani", + "prezime": "Radetić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4198, + "klub_id": 2600, + "ime": "Ani", + "prezime": "Radetić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "karlo|šaban", + "ime": "Karlo", + "prezime": "Šaban", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1331, + "klub_id": 357, + "ime": "Karlo", + "prezime": "Šaban", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4168, + "klub_id": 2587, + "ime": "Karlo", + "prezime": "Šaban", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "cherno|saho", + "ime": "Cherno", + "prezime": "Saho", + "n_rows": 3, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 3403, + "klub_id": 2362, + "ime": "Cherno", + "prezime": "Saho", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 3601, + "klub_id": 3840, + "ime": "Cherno", + "prezime": "Saho", + "datum_rodenja": "2005-01-07", + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "hns_semafor", + "hns_igrac_id": null + }, + { + "id": 4235, + "klub_id": 2362, + "ime": "Cherno", + "prezime": "Saho", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "manual", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "víctor|sánchez", + "ime": "Víctor", + "prezime": "Sánchez", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 4121, + "klub_id": 3760, + "ime": "Víctor", + "prezime": "Sánchez", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "klub_web", + "hns_igrac_id": null + }, + { + "id": 4128, + "klub_id": 2589, + "ime": "Víctor", + "prezime": "Sánchez", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "klub_web", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "adrian|šipek", + "ime": "Adrian", + "prezime": "Šipek", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1307, + "klub_id": 357, + "ime": "Adrian", + "prezime": "Šipek", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4169, + "klub_id": 2587, + "ime": "Adrian", + "prezime": "Šipek", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "marina|svetić", + "ime": "Marina", + "prezime": "Svetić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1406, + "klub_id": 544, + "ime": "Marina", + "prezime": "Svetić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "manual", + "hns_igrac_id": null + }, + { + "id": 4199, + "klub_id": 2599, + "ime": "Marina", + "prezime": "Svetić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "oleksandr|tiškivski", + "ime": "Oleksandr", + "prezime": "Tiškivski", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 3565, + "klub_id": 2429, + "ime": "Oleksandr", + "prezime": "Tiškivski", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "godisnjak_2025_NAJUSPJESNIJI", + "hns_igrac_id": null + }, + { + "id": 4301, + "klub_id": 3896, + "ime": "Oleksandr", + "prezime": "Tiškivski", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "manual", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "roko|vuković", + "ime": "Roko", + "prezime": "Vuković", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 2670, + "klub_id": 3896, + "ime": "Roko", + "prezime": "Vuković", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "klub_web", + "hns_igrac_id": null + }, + { + "id": 4313, + "klub_id": 2344, + "ime": "Roko", + "prezime": "Vuković", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "manual", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "ivan|vuletić", + "ime": "Ivan", + "prezime": "Vuletić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 3513, + "klub_id": 138, + "ime": "Ivan", + "prezime": "Vuletić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4929, + "klub_id": 2344, + "ime": "Ivan", + "prezime": "Vuletić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "manual", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "lorna|žagar", + "ime": "Lorna", + "prezime": "Žagar", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1438, + "klub_id": 544, + "ime": "Lorna", + "prezime": "Žagar", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4200, + "klub_id": 2599, + "ime": "Lorna", + "prezime": "Žagar", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "ivan|zaharija", + "ime": "Ivan", + "prezime": "Zaharija", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 1284, + "klub_id": 107, + "ime": "Ivan", + "prezime": "Zaharija", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "godisnjak_2025_HOO", + "hns_igrac_id": null + }, + { + "id": 4162, + "klub_id": 2578, + "ime": "Ivan", + "prezime": "Zaharija", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "goran|živković", + "ime": "Goran", + "prezime": "Živković", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 2709, + "klub_id": 1508, + "ime": "Goran", + "prezime": "Živković", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-02", + "source": "klub_web", + "hns_igrac_id": null + }, + { + "id": 4108, + "klub_id": 2526, + "ime": "Goran", + "prezime": "Živković", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-05-03", + "source": "klub_web", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + }, + { + "key": "ante|žunić", + "ime": "Ante", + "prezime": "Žunić", + "n_rows": 2, + "n_distinct_klubs": 2, + "rows": [ + { + "id": 196, + "klub_id": 2550, + "ime": "Ante", + "prezime": "Žunić", + "datum_rodenja": "2001-02-13", + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "hns_semafor", + "hns_igrac_id": null + }, + { + "id": 966, + "klub_id": 688, + "ime": "Ante", + "prezime": "Žunić", + "datum_rodenja": null, + "aktivni_status": "aktivan", + "created_at": "2026-04-29", + "source": "hbs_savez", + "hns_igrac_id": null + } + ], + "decision": "REVIEW_ONLY", + "reason": "Soft name-only match across klubs. No DOB confirmation and no shared hns_igrac_id. Different source pipelines (HOO godisnjak / HBS savez / HNS semafor / klub_web) frequently index the SAME real person under DIFFERENT klub_id rows because saveze and clubs are distinct legal entities. Strict criteria (hns_igrac_id OR ime+prezime+datum_rodenja) yielded ZERO confirmed cases — no mutation taken." + } + ] +} \ No newline at end of file diff --git a/_audit/data_integrity_20260505_0836/C_TRANSFERS.md b/_audit/data_integrity_20260505_0836/C_TRANSFERS.md new file mode 100644 index 0000000..9a7c125 --- /dev/null +++ b/_audit/data_integrity_20260505_0836/C_TRANSFERS.md @@ -0,0 +1,68 @@ +# Subagent C — Cross-Klub Duplicate / Stale-Transfer Detection + +Run timestamp: 2026-05-05 08:36 batch +Scope: pgz_sport.clanovi cross-klub duplicates +Pre-run row count: 3240 (after Subagents A and B) + +## Strict-Criteria Results + +| Detector | Cases found | +|---|---| +| Same `hns_igrac_id` across multiple `klub_id` | 0 | +| Same `lower(ime)+lower(prezime)+datum_rodenja` across multiple `klub_id` | 0 | +| **Total confirmed cross-klub duplicates requiring action** | **0** | + +Notes: +- Only 3 rows in clanovi have a populated `hns_igrac_id` (Subagent A already merged the 3 same-ID-same-klub duplicates). None of the surviving rows share an HNS ID across klubs. +- Brief specified `datum_rodjenja`. The canonical column with data is `datum_rodenja` (no 'j'); 684 rows populated. `datum_rodjenja` (with 'j') has only 1 row. Both columns checked — zero cross-klub matches by name+DOB. + +## Soft Match (Review-Only, NO Mutation) + +A weaker name-only check (same `lower(ime)+lower(prezime)`, ignoring DOB) returned **56 candidate groups / 117 rows** spanning multiple klub_ids. Per brief instruction "halt if unsure → write to review-only", these were NOT modified. + +Why review-only and not stale-purge: +- Different source pipelines (`godisnjak_2025_HOO`, `hbs_savez`, `hns_semafor`, `klub_web`, `klub_web_v2`, `manual`) index the SAME real person under DIFFERENT klub_id rows because saveze and individual clubs are distinct legal entities. A water-polo player listed in HBS savez (klub_id 2599 = the savez "klub" container) AND in HOO godisnjak (klub_id 544) is not a transfer — he is the same active player viewed from two registries. +- Croatian names like "Ivan Vuletić", "Marko Komadina", "Tomislav Katalenić" are common; without DOB confirmation, soft matches are unreliable. +- All 117 rows have `aktivni_status='aktivan'` and were created within ~5 days of each other (2026-04-29 to 2026-05-03) — fits the brief's edge case "both active AND created_at within 30 days → LEGITIMATE in-season". + +## Decisions + +| Decision | Count | +|---|---| +| LEGITIMATE transfer (tagged secondary_klub) | 0 | +| STALE transfer (purged + reparented) | 0 | +| REVIEW_ONLY (soft match, awaiting human review) | 56 groups (117 rows) | +| Hard delete | 0 | + +No mutations were performed. Backup `pgz_sport.clanovi_backup_20260505_0836` untouched. Row count stays at 3240. + +## Sample Soft Matches (full list in C_TRANSFERS.json) + +1. **Niko Janković** — 4 rows, 2 distinct klubs ({1,2362}). One row (id 4132) has `datum_rodenja=2001-08-25` from `hns_semafor`; others lack DOB. Same person across HOO godisnjak / klub_web / hns_semafor / manual ingestion of klub_id 2362. Soft match only — needs DOB-fill before any merge. +2. **Cherno Saho** — 3 rows, 2 distinct klubs ({2362,3840}). One row has `datum_rodenja=2005-01-07`. The two klub_id 2362 rows are likely intra-klub dups (Subagent A scope, hns_igrac_id was missing). The 3840 row may be an actual transfer or a savez/klub indexing split. Needs human review. +3. **David Pekar** (id 464 klub 2200, id 1021 klub 428). Row 464 has `datum_rodenja=2008-11-24` from `hns_semafor`; row 1021 from `hbs_savez` lacks DOB. Likely same youth player ingested from two saveze. Cannot confirm without DOB on both — soft match only. + +## Reasoning Summary + +Per brief's hard rule "NEVER act on a case without recording reasoning in the JSON. Halt if unsure". The strict criteria yielded zero actionable cases. The 56 soft-match groups all fall under at least one safe-haven rule: + +- Both rows `aktivni_status='aktivan'` and created_at within 30 days → LEGITIMATE in-season → tag-only allowed, but tagging without DOB confirmation could mis-tag distinct people sharing a name. Therefore REVIEW_ONLY. +- No transfer table exists in pgz_sport beyond `clan_sezona` (season stats, keyed on clan_id+sezona+natjecanje+klub_naziv, no source-clan pointer). Cannot programmatically infer "transfer" vs "duplicate". + +## Post-run Counts + +| Metric | Value | +|---|---| +| pgz_sport.clanovi rows | 3240 (unchanged) | +| Rows mutated | 0 | +| Rows soft-deleted to clanovi_purged | 0 | +| sys_audit rows added | 1 (C_DETECTION_RUN summary) | + +## Errors + +None. + +## Files + +- `C_TRANSFERS.json` — structured decisions and full review-only cases +- `C_sql_transcript.sql` — SQL run during this subagent diff --git a/_audit/data_integrity_20260505_0836/C_sql_transcript.sql b/_audit/data_integrity_20260505_0836/C_sql_transcript.sql new file mode 100644 index 0000000..38bbbe0 --- /dev/null +++ b/_audit/data_integrity_20260505_0836/C_sql_transcript.sql @@ -0,0 +1,119 @@ +-- Subagent C — Cross-Klub Duplicate / Stale-Transfer detection +-- Run: 2026-05-05 08:36 batch +-- DB: rinet_v3, schema pgz_sport +-- Result: 0 strict mutations. 56 soft-match groups recorded review-only. + +-- ==================================================================== +-- 0. Pre-run sanity +-- ==================================================================== +SELECT count(*) AS clanovi_rowcount FROM pgz_sport.clanovi; +-- expect 3240 (post-A, post-B) + +SELECT count(*) AS rows_with_hns_igrac_id +FROM pgz_sport.clanovi +WHERE hns_igrac_id IS NOT NULL AND hns_igrac_id != ''; +-- 3 + +-- ==================================================================== +-- 1. Strict detector A: same hns_igrac_id across multiple klub_id +-- ==================================================================== +SELECT hns_igrac_id, count(DISTINCT klub_id) AS n_klubs, + array_agg(id ORDER BY created_at) AS clan_ids, + array_agg(klub_id ORDER BY created_at) AS klub_ids, + array_agg(created_at ORDER BY created_at) AS created_ats, + array_agg(updated_at ORDER BY created_at) AS updated_ats, + array_agg(aktivni_status ORDER BY created_at) AS statuses +FROM pgz_sport.clanovi +WHERE hns_igrac_id IS NOT NULL AND hns_igrac_id != '' +GROUP BY hns_igrac_id +HAVING count(DISTINCT klub_id) > 1; +-- 0 rows + +-- ==================================================================== +-- 2. Strict detector B: same lower(ime)+lower(prezime)+datum_rodenja across klubs +-- (column name in this schema is datum_rodenja, no 'j'; datum_rodjenja has only 1 row) +-- ==================================================================== +SELECT count(*) FROM pgz_sport.clanovi WHERE datum_rodjenja IS NOT NULL; -- 1 +SELECT count(*) FROM pgz_sport.clanovi WHERE datum_rodenja IS NOT NULL; -- 684 + +SELECT lower(ime) AS ime_l, lower(prezime) AS prez_l, datum_rodenja, + count(DISTINCT klub_id) AS n_klubs, + array_agg(id ORDER BY created_at) AS clan_ids, + array_agg(klub_id ORDER BY created_at) AS klub_ids, + array_agg(aktivni_status ORDER BY created_at) AS statuses +FROM pgz_sport.clanovi +WHERE datum_rodenja IS NOT NULL +GROUP BY 1,2,3 +HAVING count(DISTINCT klub_id) > 1 +ORDER BY n_klubs DESC, prez_l, ime_l; +-- 0 rows + +-- Same check using datum_rodjenja (with 'j') for completeness +SELECT lower(ime), lower(prezime), datum_rodjenja, count(DISTINCT klub_id) +FROM pgz_sport.clanovi +WHERE datum_rodjenja IS NOT NULL +GROUP BY 1,2,3 +HAVING count(DISTINCT klub_id) > 1; +-- 0 rows + +-- ==================================================================== +-- 3. Look for transfer/history evidence tables +-- ==================================================================== +SELECT table_name FROM information_schema.tables +WHERE table_schema='pgz_sport' + AND (table_name ILIKE '%transfer%' OR table_name ILIKE '%history%' OR table_name ILIKE '%sezona%'); +-- clan_sezona, klub_sezona, klub_sezona_backup_20260502 +-- clan_sezona has no source-klub pointer; cannot infer transfer programmatically. + +-- ==================================================================== +-- 4. Soft detector (review only): name-only across klubs +-- ==================================================================== +SELECT count(*) AS soft_namematch_groups FROM ( + SELECT lower(ime), lower(prezime) + FROM pgz_sport.clanovi + WHERE ime IS NOT NULL AND prezime IS NOT NULL + GROUP BY 1,2 + HAVING count(DISTINCT klub_id) > 1 +) x; +-- 56 + +-- Full review-only material (exported to C_TRANSFERS.json) +WITH soft AS ( + SELECT lower(ime) AS ime_l, lower(prezime) AS prez_l + FROM pgz_sport.clanovi + WHERE ime IS NOT NULL AND prezime IS NOT NULL + GROUP BY 1,2 + HAVING count(DISTINCT klub_id) > 1 +) +SELECT c.id, c.klub_id, c.ime, c.prezime, c.datum_rodenja, c.aktivni_status, + c.created_at::date, c.source, c.hns_igrac_id +FROM pgz_sport.clanovi c +JOIN soft s ON lower(c.ime)=s.ime_l AND lower(c.prezime)=s.prez_l +ORDER BY s.prez_l, s.ime_l, c.created_at; +-- 117 rows. All aktivni_status='aktivan'. All created within 5-day window. + +-- ==================================================================== +-- 5. Audit log: record the run, no mutation +-- ==================================================================== +INSERT INTO pgz_sport.sys_audit (action, target_type, target_text, payload) +VALUES ( + 'C_DETECTION_RUN', + 'clanovi', + 'cross-klub stale-transfer detection', + jsonb_build_object( + 'run_ts', '2026-05-05T08:36:00Z', + 'strict_hns_id_cross_klub', 0, + 'strict_name_dob_cross_klub', 0, + 'soft_name_only_groups', 56, + 'soft_name_only_rows', 117, + 'mutations_applied', 0, + 'review_only_file', '/opt/pgz-sport/_audit/data_integrity_20260505_0836/C_TRANSFERS.json', + 'reason', 'Strict criteria yielded 0 cases. Soft matches treated as REVIEW_ONLY per brief halt-if-unsure rule.' + ) +); + +-- ==================================================================== +-- 6. Post-run sanity +-- ==================================================================== +SELECT count(*) AS clanovi_rowcount_after FROM pgz_sport.clanovi; +-- expect 3240 (unchanged) diff --git a/pgz_sport_api.py b/pgz_sport_api.py index 44589bc..be4a915 100644 --- a/pgz_sport_api.py +++ b/pgz_sport_api.py @@ -296,6 +296,42 @@ def api_kpi(): } +@app.get("/api/dashboard/top-primatelji") +def dashboard_top_primatelji(godina: int = 2025, limit: int = 50): + """Top primatelji javnih potreba — svi klubovi sa primljenim potporama u godini.""" + rows = fetch(""" + SELECT + pn.naziv_kluba, + pn.klub_id, + pn.iznos, + pn.napomena, + pn.godina, + COALESCE(k.sport, 'n/a') AS sport, + COALESCE(s.naziv, '') AS savez_naziv, + COALESCE(k.razina, '') AS razina, + COALESCE(k.grad, '') AS grad, + CASE + WHEN pn.napomena ILIKE '%%županijski%%' OR pn.napomena ILIKE '%%PGZ%%' OR pn.napomena ILIKE '%%PGŽ%%' THEN 'Županijski sportski savez PGŽ' + WHEN pn.napomena ILIKE '%%riječki%%' OR pn.napomena ILIKE '%%RSS%%' THEN 'Riječki sportski savez' + WHEN pn.napomena ILIKE '%%grad rijeka%%' THEN 'Grad Rijeka' + ELSE 'Riječki sportski savez' + END AS davatelj_naziv + FROM pgz_sport.potpore_nositelji pn + LEFT JOIN pgz_sport.klubovi k ON k.id = pn.klub_id + LEFT JOIN pgz_sport.savezi s ON s.id = k.savez_id + WHERE pn.godina = %s + ORDER BY pn.iznos DESC NULLS LAST + LIMIT %s + """, (godina, limit)) + + return { + "godina": godina, + "count": len(rows), + "rows": rows, + "ukupno": sum((r.get("iznos") or 0) for r in rows), + } + + @app.get("/api/dashboard/ekosustav") def dashboard_ekosustav(): """Sport ekosustav PGŽ — coverage stats za enrichment iz FINA registra."""