예제 #1
0
    def __post_init__(self) -> None:
        super().__post_init__()

        if self.fecha_reclamo_dt is not None:
            if not isinstance(self.fecha_reclamo_dt, datetime):
                raise TypeError("Inappropriate type of 'fecha_reclamo_dt'.")
            tz_utils.validate_dt_tz(self.fecha_reclamo_dt, SII_OFFICIAL_TZ)
예제 #2
0
    def __post_init__(self) -> None:
        """
        Run validation automatically after setting the fields values.

        :raises TypeError, ValueError:

        """
        super().__post_init__()

        if not isinstance(self.emisor_razon_social, str):
            raise TypeError("Inappropriate type of 'emisor_razon_social'.")
        validate_contribuyente_razon_social(self.emisor_razon_social)

        if not isinstance(self.receptor_razon_social, str):
            raise TypeError("Inappropriate type of 'receptor_razon_social'.")
        validate_contribuyente_razon_social(self.receptor_razon_social)

        if self.fecha_vencimiento_date is not None:
            if not isinstance(self.fecha_vencimiento_date, date):
                raise TypeError(
                    "Inappropriate type of 'fecha_vencimiento_date'.")

        if self.firma_documento_dt is not None:
            if not isinstance(self.firma_documento_dt, datetime):
                raise TypeError("Inappropriate type of 'firma_documento_dt'.")
            tz_utils.validate_dt_tz(self.firma_documento_dt,
                                    self.DATETIME_FIELDS_TZ)

        if self.signature_value is not None:
            if not isinstance(self.signature_value, bytes):
                raise TypeError("Inappropriate type of 'signature_value'.")
            # warning: do NOT strip a bytes value because "strip" implies an ASCII-encoded text,
            #   which in this case it is not.
            validate_non_empty_bytes(self.signature_value)

        if self.signature_x509_cert_der is not None:
            if not isinstance(self.signature_x509_cert_der, bytes):
                raise TypeError(
                    "Inappropriate type of 'signature_x509_cert_der'.")
            # warning: do NOT strip a bytes value because "strip" implies an ASCII-encoded text,
            #   which in this case it is not.
            validate_non_empty_bytes(self.signature_x509_cert_der)

        if self.emisor_giro is not None:
            if not isinstance(self.emisor_giro, str):
                raise TypeError("Inappropriate type of 'emisor_giro'.")
            validate_clean_str(self.emisor_giro)
            validate_non_empty_str(self.emisor_giro)

        if self.emisor_email is not None:
            if not isinstance(self.emisor_email, str):
                raise TypeError("Inappropriate type of 'emisor_email'.")
            validate_clean_str(self.emisor_email)
            validate_non_empty_str(self.emisor_email)

        if self.receptor_email is not None:
            if not isinstance(self.receptor_email, str):
                raise TypeError("Inappropriate type of 'receptor_email'.")
            validate_clean_str(self.receptor_email)
            validate_non_empty_str(self.receptor_email)
예제 #3
0
    def __post_init__(self) -> None:
        super().__post_init__()

        if not isinstance(self.emisor_razon_social, str):
            raise TypeError("Inappropriate type of 'emisor_razon_social'.")
        cl_sii.dte.data_models.validate_contribuyente_razon_social(
            self.emisor_razon_social)

        if self.fecha_reclamo_dt is not None:
            if not isinstance(self.fecha_reclamo_dt, datetime):
                raise TypeError("Inappropriate type of 'fecha_reclamo_dt'.")
            tz_utils.validate_dt_tz(self.fecha_reclamo_dt, SII_OFFICIAL_TZ)
예제 #4
0
    def __post_init__(self) -> None:
        """
        Run validation automatically after setting the fields values.

        :raises TypeError, ValueError:

        """
        if self.RCV_KIND == RcvKind.COMPRAS:
            if self.RC_ESTADO_CONTABLE is None:
                raise ValueError(
                    "'RC_ESTADO_CONTABLE' must not be None when 'RCV_KIND' is 'COMPRAS'.")
        elif self.RCV_KIND == RcvKind.VENTAS:
            if self.RC_ESTADO_CONTABLE is not None:
                raise ValueError(
                    "'RC_ESTADO_CONTABLE' must be None when 'RCV_KIND' is 'VENTAS'.")

        if not isinstance(self.emisor_rut, Rut):
            raise TypeError("Inappropriate type of 'emisor_rut'.")

        if not isinstance(self.tipo_docto, RcvTipoDocto):
            raise TypeError("Inappropriate type of 'tipo_docto'.")

        if not isinstance(self.folio, int):
            raise TypeError("Inappropriate type of 'folio'.")
        if not self.folio > 0:
            raise ValueError("Inappropriate value of 'folio'.")

        if not isinstance(self.fecha_emision_date, date):
            raise TypeError("Inappropriate type of 'fecha_emision_date'.")

        if not isinstance(self.receptor_rut, Rut):
            raise TypeError("Inappropriate type of 'receptor_rut'.")

        # TODO: figure out validation rules of 'monto_total'
        if not isinstance(self.monto_total, int):
            raise TypeError("Inappropriate type of 'monto_total'.")

        if not isinstance(self.emisor_razon_social, str):
            raise TypeError("Inappropriate type of 'emisor_razon_social'.")
        cl_sii.dte.data_models.validate_contribuyente_razon_social(self.emisor_razon_social)

        if not isinstance(self.receptor_razon_social, str):
            raise TypeError("Inappropriate type of 'receptor_razon_social'.")
        cl_sii.dte.data_models.validate_contribuyente_razon_social(self.receptor_razon_social)

        if not isinstance(self.fecha_recepcion_dt, datetime):
            raise TypeError("Inappropriate type of 'fecha_recepcion_dt'.")
        tz_utils.validate_dt_tz(self.fecha_recepcion_dt, SII_OFFICIAL_TZ)
    def test_validate_dt_tz_tzinfo_zone_attribute_check(self) -> None:
        # Time zone: UTC. Source: Pytz:
        tzinfo_utc_pytz = TZ_UTC
        dt_with_tzinfo_utc_pytz = convert_naive_dt_to_tz_aware(
            datetime.datetime(2021, 1, 6, 15, 21),
            tzinfo_utc_pytz,
        )

        # Time zone: UTC. Source: Python Standard Library:
        tzinfo_utc_stdlib = datetime.timezone.utc
        dt_with_tzinfo_utc_stdlib = datetime.datetime.fromisoformat(
            '2021-01-06T15:04+00:00')

        # Time zone: Not UTC. Source: Pytz:
        tzinfo_not_utc_pytz = _TZ_CL_SANTIAGO
        dt_with_tzinfo_not_utc_pytz = convert_naive_dt_to_tz_aware(
            datetime.datetime(2021, 1, 6, 15, 21),
            tzinfo_not_utc_pytz,
        )

        # Time zone: Not UTC. Source: Python Standard Library:
        tzinfo_not_utc_stdlib = datetime.timezone(
            datetime.timedelta(days=-1, seconds=75600))
        dt_with_tzinfo_not_utc_stdlib = datetime.datetime.fromisoformat(
            '2021-01-06T15:04-03:00')

        # Test datetimes with UTC time zone:
        expected_error_message = re.compile(
            r"^Object datetime.timezone.utc must have 'zone' attribute.$")
        with self.assertRaisesRegex(AssertionError, expected_error_message):
            validate_dt_tz(dt_with_tzinfo_utc_pytz, tzinfo_utc_stdlib)
        with self.assertRaisesRegex(AssertionError, expected_error_message):
            validate_dt_tz(dt_with_tzinfo_utc_stdlib, tzinfo_utc_pytz)

        # Test datetimes with non-UTC time zone:
        expected_error_message = re.compile(
            r"^Object"
            r" datetime.timezone\(datetime.timedelta\(days=-1, seconds=75600\)\)"
            r" must have 'zone' attribute.$")
        with self.assertRaisesRegex(AssertionError, expected_error_message):
            validate_dt_tz(dt_with_tzinfo_not_utc_pytz,
                           tzinfo_not_utc_stdlib)  # type: ignore
        with self.assertRaisesRegex(AssertionError, expected_error_message):
            validate_dt_tz(dt_with_tzinfo_not_utc_stdlib, tzinfo_not_utc_pytz)
    def __post_init__(self) -> None:
        """
        Run validation automatically after setting the fields values.

        :raises TypeError, ValueError:

        """
        #######################################################################
        # fields of DTE
        #######################################################################

        if not isinstance(self.dte_vendedor_rut, Rut):
            raise TypeError("Inappropriate type of 'dte_vendedor_rut'.")

        if not isinstance(self.dte_deudor_rut, Rut):
            raise TypeError("Inappropriate type of 'dte_deudor_rut'.")

        if not isinstance(self.dte_tipo_dte, TipoDteEnum):
            raise TypeError("Inappropriate type of 'dte_tipo_dte'.")
        if self.dte_tipo_dte not in TIPO_DTE_CEDIBLES:
            raise ValueError(
                "The \"tipo DTE\" in 'dte_tipo_dte' is not \"cedible\".",
                self.dte_tipo_dte)

        if not isinstance(self.dte_folio, int):
            raise TypeError("Inappropriate type of 'dte_folio'.")
        if not self.dte_folio > 0:
            raise ValueError("Inappropriate value of 'dte_folio'.")

        if not isinstance(self.dte_fecha_emision, date):
            raise TypeError("Inappropriate type of 'dte_fecha_emision'.")

        # TODO: figure out validation rules of 'dte_monto_total'
        if not isinstance(self.dte_monto_total, int):
            raise TypeError("Inappropriate type of 'dte_monto_total'.")

        #######################################################################
        # fields of "cesion"
        #######################################################################

        if not isinstance(self.cedente_rut, Rut):
            raise TypeError("Inappropriate type of 'cedente_rut'.")

        if not isinstance(self.cedente_razon_social, str):
            raise TypeError("Inappropriate type of 'cedente_razon_social'.")
        cl_sii.dte.data_models.validate_contribuyente_razon_social(
            self.cedente_razon_social)

        if self.cedente_email is not None:
            if not isinstance(self.cedente_email, str):
                raise TypeError("Inappropriate type of 'cedente_email'.")
            cl_sii.dte.data_models.validate_clean_str(self.cedente_email)
            cl_sii.dte.data_models.validate_non_empty_str(self.cedente_email)

        if not isinstance(self.cesionario_rut, Rut):
            raise TypeError("Inappropriate type of 'cesionario_rut'.")

        if not isinstance(self.cesionario_razon_social, str):
            raise TypeError("Inappropriate type of 'cesionario_razon_social'.")
        cl_sii.dte.data_models.validate_contribuyente_razon_social(
            self.cesionario_razon_social)

        if self.cesionario_emails is not None:
            if not isinstance(self.cesionario_emails, str):
                raise TypeError("Inappropriate type of 'cesionario_emails'.")
            cl_sii.dte.data_models.validate_clean_str(self.cesionario_emails)
            cl_sii.dte.data_models.validate_non_empty_str(
                self.cesionario_emails)

        if self.deudor_email is not None:
            if not isinstance(self.deudor_email, str):
                raise TypeError("Inappropriate type of 'deudor_email'.")
            cl_sii.dte.data_models.validate_clean_str(self.deudor_email)
            cl_sii.dte.data_models.validate_non_empty_str(self.deudor_email)

        if not isinstance(self.fecha_cesion_dt, datetime):
            raise TypeError("Inappropriate type of 'fecha_cesion_dt'.")
        tz_utils.validate_dt_tz(self.fecha_cesion_dt, SII_OFFICIAL_TZ)

        if not isinstance(self.fecha_cesion, date):
            raise TypeError("Inappropriate type of 'fecha_cesion'.")
        if self.fecha_cesion_dt.date() != self.fecha_cesion:
            raise ValueError(
                "Date of 'fecha_cesion_dt' (considering timezone) does not match 'fecha_cesion'.",
                self.fecha_cesion_dt, self.fecha_cesion)

        if not isinstance(self.monto_cedido, int):
            raise TypeError("Inappropriate type of 'monto_cedido'.")
        if not self.monto_cedido >= CESION_MONTO_CEDIDO_FIELD_MIN_VALUE:
            raise ValueError(
                f"Amount 'monto_cedido' must be >= {CESION_MONTO_CEDIDO_FIELD_MIN_VALUE}.",
                self.monto_cedido)
        data_models.validate_cesion_and_dte_montos(
            cesion_value=self.monto_cedido,
            dte_value=self.dte_monto_total,
        )

        if not isinstance(self.fecha_ultimo_vencimiento, date):
            raise TypeError(
                "Inappropriate type of 'fecha_ultimo_vencimiento'.")

        if not isinstance(self.estado, str):
            raise TypeError("Inappropriate type of 'estado'.")
        cl_sii.dte.data_models.validate_clean_str(self.estado)
        cl_sii.dte.data_models.validate_non_empty_str(self.estado)
 def validate_datetime_tz(cls, v: object) -> object:
     if isinstance(v, datetime):
         tz_utils.validate_dt_tz(v, cls.DATETIME_FIELDS_TZ)
     return v