feat(fns): парсер ФНС бухгалтерской отчетности
- Модели FinancialReport и FinancialReportLine
- FNSExcelParser для файлов fin_{id}_{ogrn}.xlsx
- FNSReportService с дедупликацией по хешу файла
- Celery задачи для мониторинга папки (каждые 5 мин)
- API: POST /fns/upload/, GET /fns/reports/
- Django admin интеграция
- 25 unit-тестов
This commit is contained in:
@@ -3,6 +3,8 @@ Admin configuration for parsers app.
|
||||
"""
|
||||
|
||||
from apps.parsers.models import (
|
||||
FinancialReport,
|
||||
FinancialReportLine,
|
||||
IndustrialCertificateRecord,
|
||||
InspectionRecord,
|
||||
ManufacturerRecord,
|
||||
@@ -520,3 +522,107 @@ class ProcurementRecordAdmin(admin.ModelAdmin):
|
||||
def has_change_permission(self, request, obj=None):
|
||||
"""Запретить редактирование записей."""
|
||||
return False
|
||||
|
||||
|
||||
class FinancialReportLineInline(admin.TabularInline):
|
||||
"""Inline для строк финансового отчета."""
|
||||
|
||||
model = FinancialReportLine
|
||||
extra = 0
|
||||
readonly_fields = [
|
||||
"form_code",
|
||||
"line_code",
|
||||
"line_name",
|
||||
"year",
|
||||
"period_start",
|
||||
"period_end",
|
||||
]
|
||||
can_delete = False
|
||||
|
||||
def has_add_permission(self, request, obj=None):
|
||||
return False
|
||||
|
||||
|
||||
@admin.register(FinancialReport)
|
||||
class FinancialReportAdmin(admin.ModelAdmin):
|
||||
"""Admin для финансовых отчетов ФНС."""
|
||||
|
||||
list_display = [
|
||||
"external_id",
|
||||
"ogrn",
|
||||
"file_name",
|
||||
"status_badge",
|
||||
"source",
|
||||
"lines_count",
|
||||
"load_batch",
|
||||
"created_at",
|
||||
]
|
||||
list_filter = ["status", "source", "load_batch", "created_at"]
|
||||
search_fields = ["external_id", "ogrn", "file_name"]
|
||||
readonly_fields = [
|
||||
"external_id",
|
||||
"ogrn",
|
||||
"file_name",
|
||||
"file_hash",
|
||||
"load_batch",
|
||||
"status",
|
||||
"source",
|
||||
"error_message",
|
||||
"created_at",
|
||||
"updated_at",
|
||||
]
|
||||
ordering = ["-created_at"]
|
||||
list_per_page = 50
|
||||
date_hierarchy = "created_at"
|
||||
inlines = [FinancialReportLineInline]
|
||||
|
||||
fieldsets = (
|
||||
(
|
||||
"Основное",
|
||||
{"fields": ("external_id", "ogrn", "file_name", "file_hash")},
|
||||
),
|
||||
(
|
||||
"Статус",
|
||||
{"fields": ("status", "source", "error_message")},
|
||||
),
|
||||
(
|
||||
"Системное",
|
||||
{
|
||||
"fields": ("load_batch", "created_at", "updated_at"),
|
||||
"classes": ("collapse",),
|
||||
},
|
||||
),
|
||||
)
|
||||
|
||||
def lines_count(self, obj):
|
||||
"""Количество строк в отчете."""
|
||||
return obj.lines.count()
|
||||
|
||||
lines_count.short_description = "Строк"
|
||||
|
||||
def status_badge(self, obj):
|
||||
"""Цветной бейдж статуса."""
|
||||
colors = {
|
||||
"pending": "#6c757d",
|
||||
"processing": "#ffc107",
|
||||
"success": "#28a745",
|
||||
"failed": "#dc3545",
|
||||
}
|
||||
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(),
|
||||
)
|
||||
|
||||
status_badge.short_description = "Статус"
|
||||
status_badge.admin_order_field = "status"
|
||||
|
||||
def has_add_permission(self, request):
|
||||
"""Запретить создание записей вручную."""
|
||||
return False
|
||||
|
||||
def has_change_permission(self, request, obj=None):
|
||||
"""Запретить редактирование записей."""
|
||||
return False
|
||||
|
||||
Reference in New Issue
Block a user