Add initial implementations for forms and organization apps with serializers, factories, and admin configurations
Some checks failed
CI/CD Pipeline / Run Tests (push) Failing after 45s
CI/CD Pipeline / Code Quality Checks (push) Failing after 48s
CI/CD Pipeline / Build Docker Images (push) Has been skipped
CI/CD Pipeline / Push to Gitea Registry (push) Has been skipped
CI/CD Pipeline / Deploy to Server (push) Has been skipped

This commit is contained in:
2026-03-28 18:23:06 +01:00
parent 8ed3e1175c
commit 345b1d0cc8
201 changed files with 15097 additions and 6691 deletions

View File

@@ -1,7 +1,6 @@
"""Tests for core excel parser."""
from io import BytesIO
from unittest.mock import MagicMock, patch
from unittest.mock import MagicMock
from apps.core.excel import (
BaseExcelParser,
@@ -22,80 +21,66 @@ class ValidatorsTest(TestCase):
"""Tests for validators."""
def test_validate_inn_valid_10_digits(self):
"""Test valid 10-digit INN."""
self.assertEqual(validate_inn("1234567890"), "1234567890")
self.assertEqual(validate_inn("1234567890"), (True, ""))
def test_validate_inn_valid_12_digits(self):
"""Test valid 12-digit INN."""
self.assertEqual(validate_inn("123456789012"), "123456789012")
self.assertEqual(validate_inn("123456789012"), (True, ""))
def test_validate_inn_strips_whitespace(self):
"""Test INN strips whitespace."""
self.assertEqual(validate_inn(" 1234567890 "), "1234567890")
self.assertEqual(validate_inn(" 1234567890 "), (True, ""))
def test_validate_inn_invalid_length(self):
"""Test INN with invalid length raises ValueError."""
with self.assertRaises(ValueError) as ctx:
validate_inn("12345")
self.assertIn("10 или 12", str(ctx.exception))
valid, message = validate_inn("12345")
self.assertFalse(valid)
self.assertIn("10 или 12", message)
def test_validate_inn_none_returns_none(self):
"""Test None INN returns None."""
self.assertIsNone(validate_inn(None))
def test_validate_inn_none_returns_error(self):
self.assertEqual(validate_inn(None), (False, "ИНН обязателен"))
def test_validate_ogrn_valid_13_digits(self):
"""Test valid 13-digit OGRN."""
self.assertEqual(validate_ogrn("1234567890123"), "1234567890123")
self.assertEqual(validate_ogrn("1234567890123"), (True, ""))
def test_validate_ogrn_valid_15_digits(self):
"""Test valid 15-digit OGRN."""
self.assertEqual(validate_ogrn("123456789012345"), "123456789012345")
self.assertEqual(validate_ogrn("123456789012345"), (True, ""))
def test_validate_ogrn_invalid_length(self):
"""Test OGRN with invalid length raises ValueError."""
with self.assertRaises(ValueError) as ctx:
validate_ogrn("12345")
self.assertIn("13 или 15", str(ctx.exception))
valid, message = validate_ogrn("12345")
self.assertFalse(valid)
self.assertIn("13 или 15", message)
def test_validate_kpp_valid(self):
"""Test valid 9-digit KPP."""
self.assertEqual(validate_kpp("123456789"), "123456789")
self.assertEqual(validate_kpp("123456789"), (True, ""))
def test_validate_kpp_invalid_length(self):
"""Test KPP with invalid length raises ValueError."""
with self.assertRaises(ValueError) as ctx:
validate_kpp("12345")
self.assertIn("9 цифр", str(ctx.exception))
valid, message = validate_kpp("12345")
self.assertFalse(valid)
self.assertIn("9 цифр", message)
def test_validate_okpo_valid_8_digits(self):
"""Test valid 8-digit OKPO."""
self.assertEqual(validate_okpo("12345678"), "12345678")
self.assertEqual(validate_okpo("12345678"), (True, ""))
def test_validate_okpo_valid_10_digits(self):
"""Test valid 10-digit OKPO."""
self.assertEqual(validate_okpo("1234567890"), "1234567890")
self.assertEqual(validate_okpo("1234567890"), (True, ""))
class DataclassesTest(TestCase):
"""Tests for dataclasses."""
def test_column_mapping_creation(self):
"""Test ColumnMapping creation."""
mapping = ColumnMapping(
column_index=1,
field_name="test_field",
header_pattern="Test Header",
excel_column=1,
excel_header="Test Header",
model_field="test_field",
)
self.assertEqual(mapping.column_index, 1)
self.assertEqual(mapping.excel_column, 1)
self.assertEqual(mapping.field_name, "test_field")
self.assertFalse(mapping.required)
def test_column_mapping_with_validator(self):
"""Test ColumnMapping with validator."""
mapping = ColumnMapping(
column_index=1,
field_name="inn",
header_pattern="ИНН",
excel_column=1,
excel_header="ИНН",
model_field="inn",
required=True,
validator=validate_inn,
)
@@ -103,16 +88,19 @@ class DataclassesTest(TestCase):
self.assertIsNotNone(mapping.validator)
def test_row_data_creation(self):
"""Test RowData creation."""
data = RowData(
row_number=5,
data={"field1": "value1", "field2": 123},
organization_name="Тестовая организация",
inn="1234567890",
ogrn="1234567890123",
kpp="123456789",
okpo="12345678",
fields={"field1": "value1", "field2": 123},
)
self.assertEqual(data.row_number, 5)
self.assertEqual(data.data["field1"], "value1")
self.assertEqual(data.fields["field1"], "value1")
def test_field_error_creation(self):
"""Test FieldError creation."""
error = FieldError(
field="inn",
message="Invalid INN",
@@ -120,50 +108,60 @@ class DataclassesTest(TestCase):
)
self.assertEqual(error.field, "inn")
self.assertEqual(error.message, "Invalid INN")
self.assertEqual(error.value, "12345")
def test_row_validation_error_creation(self):
"""Test RowValidationError creation."""
error = RowValidationError(
row_number=10,
row=10,
inn="1234567890",
kpp="123456789",
organization_name="Тест",
errors=[FieldError(field="inn", message="Invalid", value="x")],
)
self.assertEqual(error.row_number, 10)
self.assertEqual(error.row, 10)
self.assertEqual(len(error.errors), 1)
def test_parse_result_creation(self):
"""Test ParseResult creation."""
result = ParseResult(
success=True,
records_created=5,
records_failed=1,
batch_id=123,
loaded_count=5,
skipped_count=1,
errors=[],
load_batch="batch-123",
)
self.assertTrue(result.success)
self.assertEqual(result.records_created, 5)
self.assertEqual(result.load_batch, "batch-123")
self.assertEqual(result.batch_id, 123)
self.assertEqual(result.loaded_count, 5)
self.assertEqual(result.skipped_count, 1)
class BaseExcelParserTest(TestCase):
"""Tests for BaseExcelParser."""
def test_parser_abstract_methods(self):
"""Test parser has abstract methods."""
with self.assertRaises(TypeError):
BaseExcelParser()
def test_concrete_parser_implementation(self):
"""Test concrete parser implementation."""
class TestParser(BaseExcelParser):
def get_column_mappings(self):
return [
ColumnMapping(column_index=1, field_name="inn", header_pattern="ИНН", required=True),
ColumnMapping(column_index=2, field_name="name", header_pattern="Наименование"),
ColumnMapping(
excel_column=1,
excel_header="ИНН",
model_field="inn",
required=True,
),
ColumnMapping(
excel_column=2,
excel_header="Наименование",
model_field="name",
),
]
def create_record(self, row_data: dict):
return MagicMock(id=1)
def get_next_batch_id(self) -> int:
return 1
def create_record(self, row_data, batch_id):
return MagicMock(id=1, batch_id=batch_id, row_data=row_data)
parser = TestParser()
mappings = parser.get_column_mappings()