-
Notifications
You must be signed in to change notification settings - Fork 11
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
rtc: Update AEC XML document validations #199
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,6 +47,25 @@ def validate_cesion_seq(value: int) -> None: | |
raise ValueError("Value is out of the valid range.", value) | ||
|
||
|
||
def validate_cesion_fecha(value: datetime, tz: tz_utils.PytzTimezone) -> None: | ||
""" | ||
Validate value of date and time when the "cesión" happened. | ||
|
||
:raises ValueError: | ||
""" | ||
|
||
tz_utils.validate_dt_tz(value, tz) | ||
|
||
current_date_in_tz = tz_utils.get_now_tz_aware().astimezone(tz) | ||
|
||
if not (value.date() <= current_date_in_tz.date()): | ||
raise ValueError( | ||
'Value of "fecha_cesion_dt" must be before or equal to the current day.', | ||
value, | ||
current_date_in_tz | ||
) | ||
|
||
|
||
def validate_cesion_monto(value: int) -> None: | ||
""" | ||
Validate amount of the "cesión". | ||
|
@@ -80,6 +99,25 @@ def validate_cesion_and_dte_montos(cesion_value: int, dte_value: int) -> None: | |
raise ValueError('Value of "cesión" must be <= value of DTE.', cesion_value, dte_value) | ||
|
||
|
||
def validate_cesion_fecha_ultimo_vencimiento_is_consistent_with_dte( | ||
cesion_value: date, dte_value: date | ||
) -> None: | ||
""" | ||
Validate 'fecha_ultimo_vencimiento' of the "cesión" is after or equal | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there any documentation for this rule? |
||
to 'fecha_emision' of the DTE. | ||
|
||
> Que la fecha del último vencimiento sea mayor o igual a la fecha | ||
> consignada en el documento. | ||
Source: https://github.com/cl-sii-extraoficial/archivos-oficiales/blob/master/src/docs/rtc/2013-02-11-instructivo-tecnico.pdf | ||
|
||
|
||
|
||
:raises ValueError: | ||
""" # noqa: E501 | ||
if not (cesion_value >= dte_value): | ||
raise ValueError('Value of "cesión" must be >= value of DTE.', cesion_value, dte_value) | ||
|
||
|
||
@pydantic.dataclasses.dataclass( | ||
frozen=True, | ||
config=type('Config', (), dict( | ||
|
@@ -245,9 +283,9 @@ def validate_dte_tipo_dte(cls, v: object) -> object: | |
return v | ||
|
||
@pydantic.validator('fecha_cesion_dt') | ||
def validate_datetime_tz(cls, v: object) -> object: | ||
def validate_fecha_cesion_dt(cls, v: object) -> object: | ||
if isinstance(v, datetime): | ||
tz_utils.validate_dt_tz(v, cls.DATETIME_FIELDS_TZ) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does it make sense to nesting |
||
validate_cesion_fecha(v, cls.DATETIME_FIELDS_TZ) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. inconsistent naming There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @glarrain that is the naming convention adopted for the validators of the cesion's fields e.g: |
||
return v | ||
|
||
@pydantic.validator('fecha_cesion_dt') | ||
|
@@ -321,13 +359,20 @@ class CesionL0: | |
- Same timestamp as the "Registro AoR DTE" event ``DTE Cedido``. | ||
- The above statements were empirically verified for | ||
``CesionNaturalKey(dte_key=DteNaturalKey(Rut('99***140-4'), 33, 3105), seq=2)``. | ||
- When receiving an XML AEC document, the SII validates this date is before or | ||
equal to the current day. | ||
From the section "Modelo de Operación", where the validations to the annotation | ||
requests in the "Registro Público de Transferencia de Créditos" are listed: | ||
> La validez de la fecha de transferencia, debiendo ser anterior o igual al día | ||
> actual | ||
Source: https://github.com/cl-sii-extraoficial/archivos-oficiales/blob/master/src/docs/rtc/2013-02-11-instructivo-tecnico.pdf | ||
|
||
.. warning:: The timestamp is generated by the signer of the AEC so it | ||
cannot be fully trusted. It is not clear how much validation is | ||
performed by the SII. A more trustworthy value is the RPETC email's | ||
``Fecha de Recepcion``, which is generated by the SII, but most of the | ||
time only the "fecha cesión" will be available. | ||
""" | ||
""" # noqa: E501 | ||
|
||
@property | ||
def natural_key(self) -> Optional[CesionNaturalKey]: | ||
|
@@ -392,9 +437,9 @@ def validate_seq(cls, v: object) -> object: | |
return v | ||
|
||
@pydantic.validator('fecha_cesion_dt') | ||
def validate_datetime_tz(cls, v: object) -> object: | ||
def validate_fecha_cesion_dt(cls, v: object) -> object: | ||
if isinstance(v, datetime): | ||
tz_utils.validate_dt_tz(v, cls.DATETIME_FIELDS_TZ) | ||
validate_cesion_fecha(v, cls.DATETIME_FIELDS_TZ) | ||
return v | ||
|
||
|
||
|
@@ -511,6 +556,20 @@ def validate_monto_cedido_does_not_exceed_dte_monto_total( | |
|
||
return values | ||
|
||
@pydantic.root_validator(skip_on_failure=True) | ||
def validate_fecha_ultimo_vencimiento_is_consistent_with_dte( | ||
cls, values: Mapping[str, object], | ||
) -> Mapping[str, object]: | ||
fecha_ultimo_vencimiento = values['fecha_ultimo_vencimiento'] | ||
dte_fecha_emision = values['dte_fecha_emision'] | ||
|
||
if isinstance(fecha_ultimo_vencimiento, date) and isinstance(dte_fecha_emision, date): | ||
validate_cesion_fecha_ultimo_vencimiento_is_consistent_with_dte( | ||
cesion_value=fecha_ultimo_vencimiento, dte_value=dte_fecha_emision | ||
) | ||
|
||
return values | ||
|
||
|
||
@pydantic.dataclasses.dataclass( | ||
frozen=True, | ||
|
@@ -674,12 +733,13 @@ def as_dte_data_l2(self) -> dte_data_models.DteDataL2: | |
|
||
# TODO: Validate value of 'fecha_firma_dt' in relation to the DTE data. | ||
|
||
# TODO: Validate value of 'fecha_ultimo_vencimiento' in relation to the DTE data. | ||
@pydantic.validator('fecha_cesion_dt') | ||
def validate_fecha_cesion_dt(cls, v: object) -> object: | ||
if isinstance(v, datetime): | ||
validate_cesion_fecha(v, cls.DATETIME_FIELDS_TZ) | ||
return v | ||
|
||
@pydantic.validator( | ||
'fecha_cesion_dt', | ||
'fecha_firma_dt', | ||
) | ||
@pydantic.validator('fecha_firma_dt') | ||
def validate_datetime_tz(cls, v: object) -> object: | ||
if isinstance(v, datetime): | ||
tz_utils.validate_dt_tz(v, cls.DATETIME_FIELDS_TZ) | ||
|
@@ -716,3 +776,17 @@ def validate_dte_data_l2(cls, values: Mapping[str, Any]) -> Mapping[str, object] | |
raise | ||
|
||
return values | ||
|
||
@pydantic.root_validator(skip_on_failure=True) | ||
def validate_fecha_ultimo_vencimiento_is_consistent_with_dte( | ||
cls, values: Mapping[str, object], | ||
) -> Mapping[str, object]: | ||
fecha_ultimo_vencimiento = values['fecha_ultimo_vencimiento'] | ||
dte_fecha_emision = values['dte_fecha_emision'] | ||
|
||
if isinstance(fecha_ultimo_vencimiento, date) and isinstance(dte_fecha_emision, date): | ||
validate_cesion_fecha_ultimo_vencimiento_is_consistent_with_dte( | ||
cesion_value=fecha_ultimo_vencimiento, dte_value=dte_fecha_emision | ||
) | ||
|
||
return values |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
AFAIK it is not necessary to
.astimezone(tz)
when comparing TZ-aware datetime values, because the "real" underlying datetime is not affected by the TZ used for representation. Am I right @jtrh ?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I was wrong (see my latest review)