feat(admin): expand exchange admin and unify admin UX
Some checks failed
CI/CD Pipeline / Code Quality Checks (pull_request) Failing after 2m39s
CI/CD Pipeline / Run Tests (pull_request) Successful in 3m0s
CI/CD Pipeline / Run API Inventory E2E Tests (pull_request) Successful in 35s
CI/CD Pipeline / Telegram Notify Success (pull_request) Has been skipped
Some checks failed
CI/CD Pipeline / Code Quality Checks (pull_request) Failing after 2m39s
CI/CD Pipeline / Run Tests (pull_request) Successful in 3m0s
CI/CD Pipeline / Run API Inventory E2E Tests (pull_request) Successful in 35s
CI/CD Pipeline / Telegram Notify Success (pull_request) Has been skipped
This commit is contained in:
@@ -171,41 +171,52 @@ class ParserLoadLogAdmin(admin.ModelAdmin):
|
||||
|
||||
list_display = [
|
||||
"id",
|
||||
"source",
|
||||
"batch_id",
|
||||
"source_title",
|
||||
"status_badge",
|
||||
"records_count",
|
||||
"created_at",
|
||||
]
|
||||
list_filter = ["source", "status", "created_at"]
|
||||
search_fields = ["batch_id", "error_message"]
|
||||
search_fields = ["error_message"]
|
||||
readonly_fields = ["created_at", "updated_at"]
|
||||
ordering = ["-created_at"]
|
||||
list_per_page = 50
|
||||
date_hierarchy = "created_at"
|
||||
|
||||
fieldsets = (
|
||||
("Основное", {"fields": ("source", "batch_id", "status")}),
|
||||
("Основное", {"fields": ("source", "status")}),
|
||||
("Результат", {"fields": ("records_count", "error_message")}),
|
||||
("Даты", {"fields": ("created_at", "updated_at"), "classes": ("collapse",)}),
|
||||
(
|
||||
"Служебное",
|
||||
{
|
||||
"fields": ("batch_id", "created_at", "updated_at"),
|
||||
"classes": ("collapse",),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
def source_title(self, obj):
|
||||
"""Полное название источника."""
|
||||
return obj.get_source_display()
|
||||
|
||||
source_title.short_description = "Источник"
|
||||
source_title.admin_order_field = "source"
|
||||
|
||||
def status_badge(self, obj):
|
||||
"""Цветной бейдж статуса."""
|
||||
colors = {
|
||||
"success": "#28a745",
|
||||
"failed": "#dc3545",
|
||||
"in_progress": "#ffc107",
|
||||
"pending": "#6c757d",
|
||||
ParserLoadLog.Status.SUCCESS: "#28a745",
|
||||
ParserLoadLog.Status.FAILED: "#dc3545",
|
||||
ParserLoadLog.Status.IN_PROGRESS: "#ffc107",
|
||||
ParserLoadLog.Status.PENDING: "#6c757d",
|
||||
ParserLoadLog.Status.SKIPPED: "#17a2b8",
|
||||
}
|
||||
color = colors.get(obj.status, "#6c757d")
|
||||
return format_html(
|
||||
'<span style="color: white; background: {}; padding: 3px 10px; '
|
||||
'border-radius: 3px;">{}</span>',
|
||||
color,
|
||||
obj.get_status_display()
|
||||
if hasattr(obj, "get_status_display")
|
||||
else obj.status,
|
||||
obj.get_status_display(),
|
||||
)
|
||||
|
||||
status_badge.short_description = "Статус"
|
||||
@@ -917,7 +928,7 @@ class FinancialReportAdmin(admin.ModelAdmin):
|
||||
context = {
|
||||
**self.admin_site.each_context(request),
|
||||
"opts": self.model._meta,
|
||||
"title": "Загрузка Excel отчетности ФНС",
|
||||
"title": "Загрузка Excel бухгалтерской отчетности ФНС",
|
||||
"changelist_url": changelist_url,
|
||||
}
|
||||
return TemplateResponse(
|
||||
@@ -961,7 +972,7 @@ class FinancialReportAdmin(admin.ModelAdmin):
|
||||
context = {
|
||||
**self.admin_site.each_context(request),
|
||||
"opts": self.model._meta,
|
||||
"title": "Загрузка ZIP отчетности ФНС",
|
||||
"title": "Загрузка ZIP бухгалтерской отчетности ФНС",
|
||||
"changelist_url": changelist_url,
|
||||
}
|
||||
return TemplateResponse(
|
||||
|
||||
51
src/apps/parsers/migrations/0016_auto_20260324_1120.py
Normal file
51
src/apps/parsers/migrations/0016_auto_20260324_1120.py
Normal file
@@ -0,0 +1,51 @@
|
||||
# Generated by Django 3.2.25 on 2026-03-24 11:20
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('parsers', '0015_add_proxy_metadata'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterModelOptions(
|
||||
name='financialreport',
|
||||
options={'ordering': ['-created_at'], 'verbose_name': 'запись бухгалтерской отчетности ФНС', 'verbose_name_plural': 'Бухгалтерская отчетность ФНС'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='industrialcertificaterecord',
|
||||
options={'ordering': ['-created_at'], 'verbose_name': 'сертификат промышленного производства', 'verbose_name_plural': 'Сертификаты промышленного производства'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='industrialproductrecord',
|
||||
options={'ordering': ['-created_at'], 'verbose_name': 'запись реестра промышленной продукции', 'verbose_name_plural': 'Реестр промышленной продукции'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='inspectionrecord',
|
||||
options={'ordering': ['-created_at'], 'verbose_name': 'запись единого реестра проверок', 'verbose_name_plural': 'Единый реестр проверок'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='manufacturerrecord',
|
||||
options={'ordering': ['-created_at'], 'verbose_name': 'запись реестра производителей', 'verbose_name_plural': 'Реестр производителей'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='parserloadlog',
|
||||
options={'ordering': ['-created_at'], 'verbose_name': 'обновление источника', 'verbose_name_plural': 'история обновлений'},
|
||||
),
|
||||
migrations.AlterModelOptions(
|
||||
name='procurementrecord',
|
||||
options={'ordering': ['-created_at'], 'verbose_name': 'запись ЕИС закупок', 'verbose_name_plural': 'Единая информационная система закупок'},
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='parserloadlog',
|
||||
name='source',
|
||||
field=models.CharField(choices=[('industrial', 'Сертификаты промышленного производства'), ('industrial_products', 'Реестр промышленной продукции'), ('manufactures', 'Реестр производителей'), ('inspections', 'Единый реестр проверок'), ('procurements', 'Единая информационная система закупок'), ('fns_reports', 'Бухгалтерская отчетность ФНС')], db_index=True, help_text='Источник данных', max_length=50, verbose_name='источник'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='parserloadlog',
|
||||
name='status',
|
||||
field=models.CharField(choices=[('success', 'Успешно'), ('failed', 'Ошибка'), ('in_progress', 'В процессе'), ('pending', 'В очереди'), ('skipped', 'Пропущено')], default='success', help_text='Статус загрузки', max_length=20, verbose_name='статус'),
|
||||
),
|
||||
]
|
||||
@@ -17,13 +17,20 @@ class ParserLoadLog(TimestampMixin, models.Model):
|
||||
"""
|
||||
|
||||
class Source(models.TextChoices):
|
||||
INDUSTRIAL = "industrial", _("Промышленное производство")
|
||||
INDUSTRIAL = "industrial", _("Сертификаты промышленного производства")
|
||||
INDUSTRIAL_PRODUCTS = "industrial_products", _("Реестр промышленной продукции")
|
||||
MANUFACTURES = "manufactures", _("Реестр производителей")
|
||||
INSPECTIONS = "inspections", _("Единый реестр проверок")
|
||||
PROCUREMENTS = "procurements", _("Государственные закупки")
|
||||
PROCUREMENTS = "procurements", _("Единая информационная система закупок")
|
||||
FNS_REPORTS = "fns_reports", _("Бухгалтерская отчетность ФНС")
|
||||
|
||||
class Status(models.TextChoices):
|
||||
SUCCESS = "success", _("Успешно")
|
||||
FAILED = "failed", _("Ошибка")
|
||||
IN_PROGRESS = "in_progress", _("В процессе")
|
||||
PENDING = "pending", _("В очереди")
|
||||
SKIPPED = "skipped", _("Пропущено")
|
||||
|
||||
batch_id = models.PositiveIntegerField(
|
||||
_("ID пакета"),
|
||||
db_index=True,
|
||||
@@ -44,7 +51,8 @@ class ParserLoadLog(TimestampMixin, models.Model):
|
||||
status = models.CharField(
|
||||
_("статус"),
|
||||
max_length=20,
|
||||
default="success",
|
||||
choices=Status.choices,
|
||||
default=Status.SUCCESS,
|
||||
help_text=_("Статус загрузки"),
|
||||
)
|
||||
error_message = models.TextField(
|
||||
@@ -55,8 +63,8 @@ class ParserLoadLog(TimestampMixin, models.Model):
|
||||
|
||||
class Meta:
|
||||
db_table = "parsers_load_log"
|
||||
verbose_name = _("лог загрузки")
|
||||
verbose_name_plural = _("логи загрузок")
|
||||
verbose_name = _("обновление источника")
|
||||
verbose_name_plural = _("история обновлений")
|
||||
ordering = ["-created_at"]
|
||||
indexes = [
|
||||
models.Index(fields=["source", "batch_id"]),
|
||||
@@ -149,8 +157,8 @@ class IndustrialCertificateRecord(TimestampMixin, models.Model):
|
||||
|
||||
class Meta:
|
||||
db_table = "parsers_industrial_certificate"
|
||||
verbose_name = _("сертификат промпроизводства")
|
||||
verbose_name_plural = _("сертификаты промпроизводства")
|
||||
verbose_name = _("сертификат промышленного производства")
|
||||
verbose_name_plural = _("Сертификаты промышленного производства")
|
||||
ordering = ["-created_at"]
|
||||
indexes = [
|
||||
models.Index(fields=["inn", "certificate_number"]),
|
||||
@@ -212,8 +220,8 @@ class ManufacturerRecord(TimestampMixin, models.Model):
|
||||
|
||||
class Meta:
|
||||
db_table = "parsers_manufacturer"
|
||||
verbose_name = _("производитель")
|
||||
verbose_name_plural = _("производители")
|
||||
verbose_name = _("запись реестра производителей")
|
||||
verbose_name_plural = _("Реестр производителей")
|
||||
ordering = ["-created_at"]
|
||||
indexes = [
|
||||
models.Index(fields=["load_batch", "inn"]),
|
||||
@@ -303,8 +311,8 @@ class IndustrialProductRecord(TimestampMixin, models.Model):
|
||||
|
||||
class Meta:
|
||||
db_table = "parsers_industrial_product"
|
||||
verbose_name = _("промышленная продукция")
|
||||
verbose_name_plural = _("промышленная продукция")
|
||||
verbose_name = _("запись реестра промышленной продукции")
|
||||
verbose_name_plural = _("Реестр промышленной продукции")
|
||||
ordering = ["-created_at"]
|
||||
indexes = [
|
||||
models.Index(fields=["load_batch", "inn"]),
|
||||
@@ -507,8 +515,8 @@ class InspectionRecord(TimestampMixin, models.Model):
|
||||
|
||||
class Meta:
|
||||
db_table = "parsers_inspection"
|
||||
verbose_name = _("проверка")
|
||||
verbose_name_plural = _("проверки")
|
||||
verbose_name = _("запись единого реестра проверок")
|
||||
verbose_name_plural = _("Единый реестр проверок")
|
||||
ordering = ["-created_at"]
|
||||
indexes = [
|
||||
models.Index(fields=["inn", "registration_number"]),
|
||||
@@ -683,8 +691,8 @@ class ProcurementRecord(TimestampMixin, models.Model):
|
||||
|
||||
class Meta:
|
||||
db_table = "parsers_procurement"
|
||||
verbose_name = _("закупка")
|
||||
verbose_name_plural = _("закупки")
|
||||
verbose_name = _("запись ЕИС закупок")
|
||||
verbose_name_plural = _("Единая информационная система закупок")
|
||||
ordering = ["-created_at"]
|
||||
indexes = [
|
||||
models.Index(fields=["customer_inn", "purchase_number"]),
|
||||
@@ -781,8 +789,8 @@ class FinancialReport(TimestampMixin, models.Model):
|
||||
|
||||
class Meta:
|
||||
db_table = "parsers_financial_report"
|
||||
verbose_name = _("финансовый отчет")
|
||||
verbose_name_plural = _("финансовые отчеты")
|
||||
verbose_name = _("запись бухгалтерской отчетности ФНС")
|
||||
verbose_name_plural = _("Бухгалтерская отчетность ФНС")
|
||||
ordering = ["-created_at"]
|
||||
indexes = [
|
||||
models.Index(fields=["ogrn", "status"]),
|
||||
|
||||
Reference in New Issue
Block a user