30 lines
1.5 KiB
Python
30 lines
1.5 KiB
Python
"""Fail-closed text parser for the official RICMS/BA Anexo 1 PDF."""
|
|
import re
|
|
|
|
_ITEM = re.compile(r"^\s*(\d{1,2}(?:\.\d+)+)\s+(?:(\d{2}\.\d{3}\.\d{2})\s+)?(.*)$")
|
|
_NCM = re.compile(r"\b(?:\d{4}(?:\.\d{1,4}){0,3}|\d{2}(?:\.\d{1,4}){1,3})\b")
|
|
_MVA = re.compile(r"\d+(?:,\d+)?%")
|
|
|
|
def parse_page(text, page):
|
|
records, rejected = [], []
|
|
lines = [" ".join(line.split()) for line in text.splitlines()]
|
|
index = 0
|
|
while index < len(lines):
|
|
match = _ITEM.match(lines[index])
|
|
if not match:
|
|
index += 1; continue
|
|
item, cest, content = match.groups(); block = [content]; index += 1
|
|
while index < len(lines) and not _ITEM.match(lines[index]) and not lines[index].startswith("ITEM CEST"):
|
|
block.append(lines[index]); index += 1
|
|
joined = " ".join(block)
|
|
ncm = _NCM.findall(joined)
|
|
if not cest and not ncm:
|
|
rejected.append({"item": item, "source_page": page, "reason": "NO_CEST_OR_NCM"}); continue
|
|
mvas = _MVA.findall(joined)
|
|
description = joined
|
|
if cest: description = description.replace(cest, "")
|
|
for code in ncm: description = description.replace(code, "")
|
|
for mva in mvas: description = description.replace(mva, "")
|
|
records.append({"item": item, "cest": cest, "ncm_sh": ncm or None, "description": " ".join(description.split()) or None, "mva_original": mvas[-1] if mvas else None, "mva_adjusted": mvas[0] if mvas else None, "agreement_info": None, "source_page": page})
|
|
return records, rejected
|