Compare commits
13 Commits
feature/cu
...
feature/st
| Author | SHA1 | Date | |
|---|---|---|---|
| 1b81448bff | |||
| 983572a126 | |||
| 9681d26d79 | |||
| 87d8d8b913 | |||
| 5161d0300b | |||
| b7f2416e50 | |||
| ef4ebcef7c | |||
| bdf9461e17 | |||
| 90a83f4f08 | |||
| 08632be39f | |||
| bde320efb5 | |||
| 349f76fa88 | |||
| 0dbbe1afa9 |
@@ -235,3 +235,4 @@ jobs:
|
||||
EOF
|
||||
scp -i ~/.ssh/ecos_deploy_key "${tmp_current}.new" "${DEPLOY_USER}@${DEPLOY_HOST}:/tmp/current.env"
|
||||
ssh -i ~/.ssh/ecos_deploy_key "${DEPLOY_USER}@${DEPLOY_HOST}" 'cat /tmp/current.env > /opt/ecos-dev/releases/current.env && rm -f /tmp/current.env && /opt/ecos-dev/deploy.sh state-corp-backend'
|
||||
ssh -i ~/.ssh/ecos_deploy_key "${DEPLOY_USER}@${DEPLOY_HOST}" 'cd /opt/ecos-dev && docker compose --env-file runtime.env --env-file releases/current.env -f compose.yml run --rm --no-deps state-corp-web python src/manage.py migrate --noinput'
|
||||
|
||||
@@ -363,6 +363,8 @@ class BaseExcelParser(ABC, Generic[T]):
|
||||
|
||||
self._workbook = openpyxl.load_workbook(content, read_only=True, data_only=True)
|
||||
self._sheet = self._workbook.active
|
||||
if self._sheet.max_row is None or self._sheet.max_column is None:
|
||||
self._sheet.calculate_dimension(force=True)
|
||||
|
||||
def _parse_row(self, row_num: int) -> RowData | None:
|
||||
"""Парсит одну строку Excel."""
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("external_data", "0005_public_procurement_purchase_name_text"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name="bankruptcyprocedure",
|
||||
name="status",
|
||||
field=models.CharField(
|
||||
blank=True,
|
||||
db_index=True,
|
||||
default="",
|
||||
max_length=255,
|
||||
verbose_name="статус",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -179,7 +179,7 @@ class BankruptcyProcedure(UUIDPrimaryKeyMixin, TimestampMixin, models.Model):
|
||||
_("номер дела"), max_length=128, blank=True, default="", db_index=True
|
||||
)
|
||||
status = models.CharField(
|
||||
_("статус"), max_length=64, blank=True, default="", db_index=True
|
||||
_("статус"), max_length=255, blank=True, default="", db_index=True
|
||||
)
|
||||
source_url = models.TextField(_("ссылка на источник"), blank=True, default="")
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
"""Tests for core excel parser."""
|
||||
|
||||
import re
|
||||
from io import BytesIO
|
||||
from unittest.mock import MagicMock
|
||||
from zipfile import ZIP_DEFLATED, ZipFile
|
||||
|
||||
from apps.core.excel import (
|
||||
BaseExcelParser,
|
||||
@@ -15,6 +18,7 @@ from apps.core.excel import (
|
||||
validate_okpo,
|
||||
)
|
||||
from django.test import TestCase
|
||||
from openpyxl import Workbook
|
||||
|
||||
|
||||
class ValidatorsTest(TestCase):
|
||||
@@ -168,3 +172,48 @@ class BaseExcelParserTest(TestCase):
|
||||
|
||||
self.assertEqual(len(mappings), 2)
|
||||
self.assertEqual(mappings[0].field_name, "inn")
|
||||
|
||||
def test_parse_recovers_missing_read_only_worksheet_dimension(self):
|
||||
workbook = Workbook()
|
||||
sheet = workbook.active
|
||||
sheet.append(["Организация", "ОКПО", "ОГРН", "ИНН"])
|
||||
sheet.append(
|
||||
["Тестовая организация", "12345678", "1234567890123", "1234567890"]
|
||||
)
|
||||
source = BytesIO()
|
||||
workbook.save(source)
|
||||
workbook.close()
|
||||
|
||||
source.seek(0)
|
||||
without_dimension = BytesIO()
|
||||
with ZipFile(source, "r") as input_archive, ZipFile(
|
||||
without_dimension,
|
||||
"w",
|
||||
compression=ZIP_DEFLATED,
|
||||
) as output_archive:
|
||||
for item in input_archive.infolist():
|
||||
content = input_archive.read(item.filename)
|
||||
if item.filename == "xl/worksheets/sheet1.xml":
|
||||
content = re.sub(rb"<dimension[^>]*/>", b"", content, count=1)
|
||||
output_archive.writestr(item, content)
|
||||
without_dimension.seek(0)
|
||||
|
||||
created_rows = []
|
||||
|
||||
class TestParser(BaseExcelParser):
|
||||
def get_column_mappings(self):
|
||||
return []
|
||||
|
||||
def get_next_batch_id(self) -> int:
|
||||
return 1
|
||||
|
||||
def create_record(self, row_data, batch_id):
|
||||
created_rows.append((row_data, batch_id))
|
||||
return MagicMock()
|
||||
|
||||
result = TestParser().parse(without_dimension)
|
||||
|
||||
self.assertEqual(result.loaded_count, 1)
|
||||
self.assertEqual(result.skipped_count, 0)
|
||||
self.assertEqual(created_rows[0][0].organization_name, "Тестовая организация")
|
||||
self.assertEqual(created_rows[0][1], 1)
|
||||
|
||||
@@ -325,7 +325,10 @@ def build_exchange_payload() -> dict[str, list[dict[str, object]]]:
|
||||
"message_type": "Сообщение о намерении",
|
||||
"message_date": "2026-03-26",
|
||||
"case_number": "А40-555/2026",
|
||||
"status": "published",
|
||||
"status": (
|
||||
"Сообщение о включении заявленных требований в реестр "
|
||||
"требований кредиторов"
|
||||
),
|
||||
"source_url": "https://fedresurs.ru/message/001",
|
||||
}
|
||||
],
|
||||
@@ -461,6 +464,15 @@ class ExchangePackageApiTest(APITestCase):
|
||||
self.assertEqual(FinancialReportLine.objects.count(), 1)
|
||||
self.assertEqual(ArbitrationCase.objects.count(), 1)
|
||||
self.assertEqual(BankruptcyProcedure.objects.count(), 1)
|
||||
self.assertEqual(
|
||||
BankruptcyProcedure._meta.get_field("status").max_length,
|
||||
255,
|
||||
)
|
||||
self.assertEqual(
|
||||
BankruptcyProcedure.objects.get().status,
|
||||
"Сообщение о включении заявленных требований в реестр "
|
||||
"требований кредиторов",
|
||||
)
|
||||
self.assertEqual(DefenseUnreliableSupplier.objects.count(), 1)
|
||||
self.assertEqual(InformationSecurityRegistryEntry.objects.count(), 1)
|
||||
self.assertEqual(LaborVacancy.objects.count(), 1)
|
||||
|
||||
Reference in New Issue
Block a user