[docs]defparse_m111_no_retenciones_periods(raw:str|None)->frozenset[tuple[int,str]]:"""Parse profile ``YYYY:PERIOD`` tokens into validated period keys. Invalid tokens are ignored fail-closed: they never suppress a dependency, so verification still asks for the missing filing/evidence instead of silently treating an unclear declaration as no-obligation evidence. """ifrawisNone:returnfrozenset()periods:set[tuple[int,str]]=set()fortokeninre.split(r"[,;\s]+",raw.strip().upper()):ifnottoken:continuematch=_TOKEN_RE.fullmatch(token)ifmatchisNone:continueyear=int(match.group("year"))period_token=match.group("period")try:period=Period.from_year_and_code(year,period_token)except(PeriodError,ValueError):continueperiods.add((period.filing_year,period.registry_token))returnfrozenset(periods)
[docs]defm111_no_retenciones_periods_from_profile_values(values:Mapping[str,str]|None)->frozenset[tuple[int,str]]:"""Return attested M111 no-retenciones periods from a profile projection."""ifvaluesisNone:returnfrozenset()returnparse_m111_no_retenciones_periods(values.get(M111_NO_RETENCIONES_PROFILE_PATH))
[docs]defm111_no_retenciones_periods_for_bucket(bucket_id:str)->frozenset[tuple[int,str]]:"""Load attested M111 no-retenciones periods for ``bucket_id``. Missing profiles fail closed to an empty set. """from...domain.user_profileimportProfileNotFoundErrorfrom..user_profileimportProfileRepository,record_to_path_valuestry:aggregate=ProfileRepository().load(bucket_id)exceptProfileNotFoundError:returnfrozenset()returnm111_no_retenciones_periods_from_profile_values(record_to_path_values(aggregate.record))
[docs]defis_m111_no_retenciones_period(*,source_modelo:str,filing_year:int,period_token:str,attested_periods:frozenset[tuple[int,str]],)->bool:"""Return whether a source requirement is attested as no-obligation M111."""returnsource_modelo==Modelo.M111.valueand(filing_year,period_token)inattested_periods