fix: create organizations from form uploads
All checks were successful
All checks were successful
This commit is contained in:
82
tests/apps/form_1/test_api.py
Normal file
82
tests/apps/form_1/test_api.py
Normal file
@@ -0,0 +1,82 @@
|
||||
"""API tests for form_1 records."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from decimal import Decimal
|
||||
|
||||
from django.db import connection
|
||||
from django.test import override_settings
|
||||
from django.test.utils import CaptureQueriesContext
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
|
||||
from tests.apps.form_1.factories import FormF1RecordFactory
|
||||
from tests.apps.organization.factories import OrganizationFactory
|
||||
from tests.apps.user.factories import UserFactory
|
||||
|
||||
|
||||
@override_settings(ROOT_URLCONF="core.urls")
|
||||
class FormF1RecordApiOrderingTest(APITestCase):
|
||||
"""Ordering behavior for monthly F-1 records."""
|
||||
|
||||
def setUp(self):
|
||||
self.user = UserFactory.create_user()
|
||||
self.client.force_authenticate(self.user)
|
||||
self.organization = OrganizationFactory.create(inn="1111111111")
|
||||
|
||||
def test_ordering_appends_report_month_tiebreaker_for_monthly_records(self):
|
||||
FormF1RecordFactory.create(
|
||||
organization=self.organization,
|
||||
report_year=2025,
|
||||
report_month=9,
|
||||
report_quarter=None,
|
||||
)
|
||||
FormF1RecordFactory.create(
|
||||
organization=self.organization,
|
||||
report_year=2025,
|
||||
report_month=12,
|
||||
report_quarter=None,
|
||||
)
|
||||
|
||||
with CaptureQueriesContext(connection) as queries:
|
||||
response = self.client.get(
|
||||
"/api/v1/forms/f1/records/",
|
||||
{
|
||||
"organization_inn": self.organization.inn,
|
||||
"ordering": "-report_year,-report_quarter",
|
||||
"page_size": 100,
|
||||
},
|
||||
)
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(
|
||||
[record["report_month"] for record in response.data["data"]],
|
||||
[12, 9],
|
||||
)
|
||||
list_query = next(
|
||||
query["sql"]
|
||||
for query in queries.captured_queries
|
||||
if 'FROM "form_1_formf1record"' in query["sql"]
|
||||
and "ORDER BY" in query["sql"]
|
||||
)
|
||||
self.assertIn('"form_1_formf1record"."report_month" DESC', list_query)
|
||||
|
||||
def test_read_returns_form_f1_record_payload_without_response_envelope(self):
|
||||
record = FormF1RecordFactory.create(
|
||||
organization=self.organization,
|
||||
report_year=2025,
|
||||
report_month=12,
|
||||
report_quarter=None,
|
||||
avg_employees=Decimal("785.00"),
|
||||
avg_payroll_employees=Decimal("787.00"),
|
||||
payroll_fund=Decimal("266614.00"),
|
||||
)
|
||||
|
||||
response = self.client.get(f"/api/v1/forms/f1/records/{record.id}/")
|
||||
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(response.data["id"], str(record.id))
|
||||
self.assertEqual(response.data["avg_employees"], "785.00")
|
||||
self.assertEqual(response.data["avg_payroll_employees"], "787.00")
|
||||
self.assertEqual(response.data["payroll_fund"], "266614.00")
|
||||
self.assertNotIn("data", response.data)
|
||||
@@ -92,7 +92,7 @@ class FormF1ParserTest(TestCase):
|
||||
self.assertIn("civilian_output_actual", field_names)
|
||||
|
||||
def test_create_record_uses_existing_organization(self):
|
||||
"""Report imports must attach rows only to preloaded Mostovik organizations."""
|
||||
"""Report imports reuse existing organizations when available."""
|
||||
parser = FormF1Parser(report_year=2026, report_month=9)
|
||||
parser.load_batch = 505
|
||||
organization = OrganizationFactory.create(inn="1234567890")
|
||||
|
||||
@@ -61,7 +61,7 @@ class FormF2ParserTest(TestCase):
|
||||
self.assertIn("revenue", field_names)
|
||||
|
||||
def test_create_record_uses_existing_organization(self):
|
||||
"""Report imports must attach rows only to preloaded Mostovik organizations."""
|
||||
"""Report imports reuse existing organizations when available."""
|
||||
parser = FormF2Parser(report_year=2026, report_quarter=1)
|
||||
parser.load_batch = 502
|
||||
organization = OrganizationFactory.create(inn="2234567890")
|
||||
|
||||
@@ -61,7 +61,7 @@ class FormF3ParserTest(TestCase):
|
||||
self.assertIn("total_equipment", field_names)
|
||||
|
||||
def test_create_record_uses_existing_organization(self):
|
||||
"""Report imports must attach rows only to preloaded Mostovik organizations."""
|
||||
"""Report imports reuse existing organizations when available."""
|
||||
parser = FormF3Parser(report_year=2026, report_quarter=1)
|
||||
parser.load_batch = 503
|
||||
organization = OrganizationFactory.create(inn="3234567890")
|
||||
|
||||
@@ -61,7 +61,7 @@ class FormF4ParserTest(TestCase):
|
||||
self.assertIn("net_profit_rsbu", field_names)
|
||||
|
||||
def test_create_record_uses_existing_organization(self):
|
||||
"""Report imports must attach rows only to preloaded Mostovik organizations."""
|
||||
"""Report imports reuse existing organizations when available."""
|
||||
parser = FormF4Parser(report_year=2026, report_half_year=1)
|
||||
parser.load_batch = 504
|
||||
organization = OrganizationFactory.create(inn="4234567890")
|
||||
|
||||
@@ -87,7 +87,7 @@ class FormF5ParserTest(TestCase):
|
||||
self.assertIn("name", field_names)
|
||||
|
||||
def test_create_record_uses_existing_organization(self):
|
||||
"""Report imports must attach rows only to preloaded Mostovik organizations."""
|
||||
"""Report imports reuse existing organizations when available."""
|
||||
parser = FormF5Parser(report_year=2026, report_quarter=1)
|
||||
parser.load_batch = 505
|
||||
organization = OrganizationFactory.create(inn="5234567890")
|
||||
|
||||
@@ -61,7 +61,7 @@ class FormF6ParserTest(TestCase):
|
||||
self.assertIn("total_equipment", field_names)
|
||||
|
||||
def test_create_record_uses_existing_organization(self):
|
||||
"""Report imports must attach rows only to preloaded Mostovik organizations."""
|
||||
"""Report imports reuse existing organizations when available."""
|
||||
parser = FormF6Parser(report_year=2026, report_quarter=1)
|
||||
parser.load_batch = 506
|
||||
organization = OrganizationFactory.create(inn="6234567890")
|
||||
|
||||
127
tests/apps/forms/test_parser_organization_creation.py
Normal file
127
tests/apps/forms/test_parser_organization_creation.py
Normal file
@@ -0,0 +1,127 @@
|
||||
"""Tests for organization creation during form imports."""
|
||||
|
||||
from apps.form_1.services import FormF1Parser
|
||||
from apps.form_2.services import FormF2Parser
|
||||
from apps.form_3.services import FormF3Parser
|
||||
from apps.form_4.services import FormF4Parser
|
||||
from apps.form_5.services import FormF5Parser
|
||||
from apps.form_6.services import FormF6Parser
|
||||
from apps.organization.models import Organization
|
||||
from django.test import TestCase
|
||||
|
||||
|
||||
class FormParserOrganizationCreationTest(TestCase):
|
||||
"""Tests that report rows may create organizations without exchange preload."""
|
||||
|
||||
CASES = (
|
||||
(
|
||||
"f1",
|
||||
FormF1Parser,
|
||||
{"report_year": 2026, "report_month": 9},
|
||||
601,
|
||||
{
|
||||
"organization_name": "Тестовая организация Ф-1",
|
||||
"inn": "7100000001",
|
||||
"ogrn": "1020000000001",
|
||||
"kpp": "770100001",
|
||||
"okpo": "11110001",
|
||||
"military_output_actual": 100.0,
|
||||
"civilian_output_actual": 200.0,
|
||||
},
|
||||
),
|
||||
(
|
||||
"f2",
|
||||
FormF2Parser,
|
||||
{"report_year": 2026, "report_quarter": 1},
|
||||
602,
|
||||
{
|
||||
"organization_name": "Тестовая организация Ф-2",
|
||||
"inn": "7100000002",
|
||||
"ogrn": "1020000000002",
|
||||
"kpp": "770100002",
|
||||
"okpo": "11110002",
|
||||
"total_assets": 1000000.0,
|
||||
"revenue": 500000.0,
|
||||
},
|
||||
),
|
||||
(
|
||||
"f3",
|
||||
FormF3Parser,
|
||||
{"report_year": 2026, "report_quarter": 1},
|
||||
603,
|
||||
{
|
||||
"organization_name": "Тестовая организация Ф-3",
|
||||
"inn": "7100000003",
|
||||
"ogrn": "1020000000003",
|
||||
"kpp": "770100003",
|
||||
"okpo": "11110003",
|
||||
"avg_employees": 100,
|
||||
"total_equipment": 50,
|
||||
},
|
||||
),
|
||||
(
|
||||
"f4",
|
||||
FormF4Parser,
|
||||
{"report_year": 2026, "report_half_year": 1},
|
||||
604,
|
||||
{
|
||||
"organization_name": "Тестовая организация Ф-4",
|
||||
"inn": "7100000004",
|
||||
"ogrn": "1020000000004",
|
||||
"kpp": "770100004",
|
||||
"okpo": "11110004",
|
||||
"revenue_rsbu": 1000000.0,
|
||||
"net_profit_rsbu": 50000.0,
|
||||
},
|
||||
),
|
||||
(
|
||||
"f5",
|
||||
FormF5Parser,
|
||||
{"report_year": 2026, "report_quarter": 1},
|
||||
605,
|
||||
{
|
||||
"organization_name": "Тестовая организация Ф-5",
|
||||
"inn": "7100000005",
|
||||
"ogrn": "1020000000005",
|
||||
"kpp": "770100005",
|
||||
"okpo": "11110005",
|
||||
"equipment_id": "EQ-001",
|
||||
"equipment_name": "Токарный станок",
|
||||
},
|
||||
),
|
||||
(
|
||||
"f6",
|
||||
FormF6Parser,
|
||||
{"report_year": 2026, "report_quarter": 1},
|
||||
606,
|
||||
{
|
||||
"organization_name": "Тестовая организация Ф-6",
|
||||
"inn": "7100000006",
|
||||
"ogrn": "1020000000006",
|
||||
"kpp": "770100006",
|
||||
"okpo": "11110006",
|
||||
"row_code": "001",
|
||||
"category": "Металлорежущее",
|
||||
"total_equipment": 100,
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
def test_create_record_creates_missing_organization_from_row_identifiers(self):
|
||||
for form_name, parser_class, parser_kwargs, batch_id, row_data in self.CASES:
|
||||
with self.subTest(form=form_name):
|
||||
parser = parser_class(**parser_kwargs)
|
||||
parser.load_batch = batch_id
|
||||
|
||||
self.assertFalse(
|
||||
Organization.objects.filter(inn=row_data["inn"]).exists()
|
||||
)
|
||||
|
||||
record = parser.create_record(row_data)
|
||||
|
||||
organization = Organization.objects.get(inn=row_data["inn"])
|
||||
self.assertEqual(record.organization_id, organization.id)
|
||||
self.assertEqual(organization.name, row_data["organization_name"])
|
||||
self.assertEqual(organization.ogrn, row_data["ogrn"])
|
||||
self.assertEqual(organization.kpp, row_data["kpp"])
|
||||
self.assertEqual(organization.okpo, row_data["okpo"])
|
||||
Reference in New Issue
Block a user