Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions src/cl_sii/dte/data_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import dataclasses
import logging
import random
from datetime import date, datetime
from typing import Mapping, Optional, Sequence

Expand Down Expand Up @@ -206,6 +207,34 @@ def validate_folio(cls, v: object) -> object:
validate_dte_folio(v)
return v

############################################################################
# class methods
############################################################################

@classmethod
def random(
cls,
emisor_rut: Optional[Rut] = None,
tipo_dte: TipoDte | Sequence[TipoDte] = tuple(TipoDte),
folio: Optional[int] = None,
) -> Self:
"""
Generate random DTE natural key within valid ranges.

:param emisor_rut: RUT of the "emisor" of the DTE. If `None`, a random RUT is generated.
:param tipo_dte: The kind of DTE. If a sequence is provided, a random one is chosen.
:param folio: The sequential number of the DTE. If `None`, a random folio is generated.
"""
if emisor_rut is None:
emisor_rut = Rut.random()
if isinstance(tipo_dte, Sequence):
tipo_dte = random.choice(tipo_dte)
if folio is None:
folio = random.randint(
constants.DTE_FOLIO_FIELD_MIN_VALUE, constants.DTE_FOLIO_FIELD_MAX_VALUE
)
return cls(emisor_rut, tipo_dte, folio)


@pydantic.dataclasses.dataclass(
frozen=True,
Expand Down
62 changes: 62 additions & 0 deletions src/tests/test_dte_data_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,68 @@ def test_as_dict(self) -> None:
def test_slug(self) -> None:
self.assertEqual(self.dte_nk_1.slug, '76354771-K--33--170')

def test_random(self) -> None:
# Test that random() returns a DteNaturalKey instance
random_dte_nk = DteNaturalKey.random()
self.assertIsInstance(random_dte_nk, DteNaturalKey)

# Test with default parameters -
# tipo_dte should be randomly selected from all TipoDte values
random_dte_nk_default = DteNaturalKey.random()
self.assertIsInstance(random_dte_nk_default.tipo_dte, TipoDte)
self.assertIn(random_dte_nk_default.tipo_dte, TipoDte)

# Test that each call to random() returns different values
random_dte_nk_1 = DteNaturalKey.random()
random_dte_nk_2 = DteNaturalKey.random()
self.assertNotEqual(random_dte_nk_1, random_dte_nk_2)

# Test that the generated folio values are within valid ranges
self.assertGreaterEqual(random_dte_nk.folio, DTE_FOLIO_FIELD_MIN_VALUE)
self.assertLessEqual(random_dte_nk.folio, DTE_FOLIO_FIELD_MAX_VALUE)

# Test that emisor_rut is a valid Rut instance
self.assertIsInstance(random_dte_nk.emisor_rut, Rut)

# Test that tipo_dte is a valid TipoDte enum value
self.assertIsInstance(random_dte_nk.tipo_dte, TipoDte)
self.assertIn(random_dte_nk.tipo_dte, TipoDte)

# Test with custom parameters
custom_rut = Rut('12345678-9')
custom_tipo = TipoDte.NOTA_CREDITO_ELECTRONICA
custom_folio = 12345

custom_dte_nk = DteNaturalKey.random(
emisor_rut=custom_rut, tipo_dte=custom_tipo, folio=custom_folio
)

self.assertEqual(custom_dte_nk.emisor_rut, custom_rut)
self.assertEqual(custom_dte_nk.tipo_dte, custom_tipo)
self.assertEqual(custom_dte_nk.folio, custom_folio)

# Test with specific tipo_dte (single value, not sequence)
specific_tipo = TipoDte.FACTURA_ELECTRONICA
specific_dte_nk = DteNaturalKey.random(tipo_dte=specific_tipo)
self.assertEqual(specific_dte_nk.tipo_dte, specific_tipo)

# Test with partial custom parameters
partial_custom = DteNaturalKey.random(emisor_rut=custom_rut)
self.assertEqual(partial_custom.emisor_rut, custom_rut)
self.assertIsInstance(partial_custom.tipo_dte, TipoDte)
self.assertGreaterEqual(partial_custom.folio, DTE_FOLIO_FIELD_MIN_VALUE)
self.assertLessEqual(partial_custom.folio, DTE_FOLIO_FIELD_MAX_VALUE)

# Test that multiple calls generate different combinations
generated_combinations = set()
for _ in range(10):
dte_nk = DteNaturalKey.random()
combination = (dte_nk.emisor_rut, dte_nk.tipo_dte, dte_nk.folio)
generated_combinations.add(combination)

# Should generate mostly unique combinations (allow some duplicates due to randomness)
self.assertGreater(len(generated_combinations), 1)


class DteDataL0Test(unittest.TestCase):
def setUp(self) -> None:
Expand Down