"""FDK reģistra pārbaude: XSD, ID unikalitāte, avotu esamība un pilnums, reģistrs = iestāžu failu apvienojums. python3 tools/validate.py --nolikumi ../Nolikumi-as-Code """ import argparse import glob import os import sys from lxml import etree NS = "{urn:pppa:vpk:nolikums:0.1}" FNS = "{urn:pppa:vpk:fdk:0.1}" FILES = ("funkcijas.xml", "darbi.xml", "kompetence.xml") def main(): ap = argparse.ArgumentParser() ap.add_argument("--nolikumi", required=True) a = ap.parse_args() schema = etree.XMLSchema(etree.parse("schemas/registrs-0.1.xsd")) errors, ids, by_file = [], {}, {} points, must = set(), set() for f in glob.glob(os.path.join(a.nolikumi, "data", "*.xml")): for p in etree.parse(f).getroot().iter(NS + "Point"): points.add(p.get("id")) t = (p.findtext(NS + "Text") or "").strip().lower() if p.get("kind") in ("function", "task", "right") and not t.startswith("(svītrots"): must.add(p.get("id")) used = {} for path in sorted(glob.glob("iestades/*/*.xml")) + sorted(glob.glob("registrs/*.xml")): doc = etree.parse(path) if not schema.validate(doc): errors += [f"{path}: {e.message}" for e in schema.error_log][:5] recs = [e for e in doc.getroot() if isinstance(e.tag, str)] by_file[path] = {e.get("id") for e in recs} if path.startswith("iestades/"): org = path.split("/")[1] for e in recs: i, av = e.get("id"), e.get("avots") if i in ids: errors.append(f"{i}: divreiz ({ids[i]}, {path})") ids[i] = path if e.get("iestāde") != org or i[2:9] != org: errors.append(f"{i}: iestāde nesakrīt ar mapi {org}") if av not in points: errors.append(f"{i}: avots {av} nav Nolikumi-as-Code") if av in used: errors.append(f"{av}: izmantots divreiz ({used[av]}, {i})") used[av] = i if not (e.findtext(FNS + "Formulējums") or "").strip(): errors.append(f"{i}: tukšs formulējums") built = {os.path.basename(d) for d in glob.glob("iestades/*")} must = {m for m in must if m[7:14] in built} # tikai iestādes, kas ir uzbūvētas missing = sorted(must - set(used)) errors += [f"{m}: funkcijas/uzdevuma/tiesību punkts nav reģistrā" for m in missing[:20]] for fn in FILES: inst = set().union(*[v for k, v in by_file.items() if k.startswith("iestades/") and k.endswith("/" + fn)] or [set()]) if f"registrs/{fn}" in by_file and by_file[f"registrs/{fn}"] != inst: errors.append(f"registrs/{fn}: nesakrīt ar iestāžu failu apvienojumu") n = {fn: sum(len(v) for k, v in by_file.items() if k.startswith("iestades/") and k.endswith("/" + fn)) for fn in FILES} print(f"{len(by_file)} faili, {len(ids)} ieraksti {n}; obligātie punkti {len(must)}, iztrūkst {len(missing)}") if errors: print("\n".join(errors[:60])) sys.exit(1) print("OK") if __name__ == "__main__": main()