Система управления Дебиторкой Задолженностью - Описание проекта

Краткое резюме

Комплексная B2B платформа для управления кредитными лимитами, разработанная для российских производственных и дистрибьюторских компаний. Система автоматизирует весь жизненный цикл кредитной заявки — от первоначальной подачи через многоэтапные согласования отделов, оценку рисков, рассмотрение кредитным комитетом и текущий мониторинг кредитных линий. Построенная на Django с использованием мобильных API для выездной работы, платформа интегрирует внешние источники данных для оценки кредитоспособности и предоставляет уведомления в реальном времени через Firebase Cloud Messaging.


Бизнес-функциональность

1. Основное бизнес-назначение

Система служит централизованной платформой управления кредитными рисками для компаний, которые продают продукцию в кредит бизнес-клиентам. Она заменяет ручные, основанные на таблицах процессы утверждения кредитов структурированным рабочим процессом, который обеспечивает соблюдение корпоративных политик, предоставляет оценку рисков на основе данных и поддерживает полный аудит.

Целевые пользователи:

2. Ключевые бизнес-процессы

Рабочий процесс кредитной заявки

Система обеспечивает многоуровневую цепочку утверждения с автоматической маршрутизацией и уведомлениями:

  1. Менеджер - Менеджер по продажам создает заявку, вводит основные данные клиента
  2. Финансы - Финансовая служба проверяет финансовую отчетность, историю платежей
  3. Юрист - Юридический отдел проверяет условия договоров, гарантии, корпоративную структуру
  4. Директор филиала (КД Филиала) - Региональный орган утверждения (лимиты до порогового значения)
  5. Кредитный комитет - Рассмотрение комитетом для крупных кредитных лимитов (>порогового значения)
  6. Генеральный директор - Утверждение генеральным директором для исключительных/крупных сделок
  7. Исполнение отлагательных условий - Клиент выполняет требуемые условия (гарантии, документы)
  8. Проверка отлагательных условий - Юридический отдел проверяет выполнение условий
  9. Изменение лимита в ERP - Утверждено, ожидается интеграция с ERP
  10. Снятие лимита в ERP - Удаление аннулированного лимита из ERP
  11. Открытый лимит - Активная кредитная линия, клиент может совершать покупки в кредит
  12. Отозванный лимит - Кредит приостановлен из-за проблем с оплатой
  13. Отказано - Заявка отклонена
  14. Судебный - Клиент находится в процессе взыскания/судебного разбирательства

Каждый переход статуса создает запись аудита с отметкой времени, пользователем и комментарием.

Оценка кредитного риска

Специалист по рискам использует интегрированные внешние источники данных:

Интеграция с API Контур: Автоматически извлекает данные о российских компаниях:

Финансовый анализ: Система хранит и отображает:

Панель индикаторов риска:

Процесс запроса на превышение лимита

Когда менеджеру по продажам необходимо обработать заказ, превышающий утвержденный кредитный лимит клиента:

  1. Менеджер подает запрос на превышение лимита с обоснованием, суммой заказа, данными счета
  2. Система рассчитывает сумму превышения лимита (общая сумма счета - доступный кредит)
  3. Запрос автоматически направляется:
    • Кредитному директору филиала (для меньших сумм)
    • Кредитному комитету (для больших сумм)
  4. Утверждающий рассматривает историю клиента, текущую задолженность, платежную дисциплину
  5. Утверждение/отклонение создает запись аудита (OverLimitResponsibility) с именем утверждающего
  6. Менеджер получает push-уведомление о решении

Управление просроченной задолженностью

Система отслеживает просроченную дебиторскую задолженность на уровне транзакций:

Управление договорами и документацией

Для каждой утвержденной кредитной заявки:

Операции кредитного комитета

Операции в нескольких филиалах/отделах

Система позволяет настроить разные филиалы, например:

Каждый филиал имеет:

3. Мобильные выездные операции (приложение SWIFT)

Бизнес-ценность: Менеджерам по продажам на выезде необходим мгновенный доступ к кредитному статусу клиента во время посещения клиентов.

Мобильные возможности:

4. Управление подписками и платежами (приложение Users)

Модель SaaS-бизнеса:

5. Система уведомлений и связи

Комплексная маршрутизация уведомлений:

Каналы уведомлений:

Предпочтения пользователя: Пользователи контролируют частоту, типы и каналы доставки уведомлений.


Архитектура кода

1. Стек технологий

Фреймворк бэкенда

База данных

Кэширование и обмен сообщениями

Внешние интеграции

Фронтенд

Развертывание

Мониторинг и аналитика

2. Структура проекта

Credit_Public/
├── clients/                  # Управление основными кредитными заявками
│   ├── models.py            # Более 39 моделей 
│   ├── views.py             # Бизнес-логика 
│   ├── helpers.py           # Интеграция с Kontur API
│   ├── urls.py              # Маршрутизация URL
│   ├── serializers.py       # DRF сериализаторы
│   ├── tables.py            # Определения Django Tables2
│   ├── filters.py           # Django Filters
│   ├── forms.py             # Определения форм
│   └── admin.py             # Кастомизация админки Django
│
├── swift/                    # Мобильный API и push-уведомления
│   ├── models.py            # Регистрация устройств, настройки уведомлений
│   ├── views.py             # Конечные точки мобильного API
│   ├── urls.py              # Маршрутизация API
│   ├── serializers.py       # Сериализаторы мобильных данных
│   └── consumers.py         # Консьюмеры WebSocket (Django Channels)
│
├── users/                    # Аутентификация и управление подписками
│   ├── models.py            # Модели пользователя, компании, тарифа, платежей
│   ├── views.py             # Потоки аутентификации, обработка платежей
│   ├── helpers.py           # Интеграция с YooKassa
│   ├── forms.py             # Формы регистрации, входа
│   └── urls.py              # Маршрутизация URL аутентификации
│
├── django_project/           # Конфигурация Django
│   ├── settings.py          # Основные настройки (безопасность, база данных, промежуточное ПО)
│   ├── urls.py              # Конфигурация корневого URL
│   ├── asgi.py              # Конфигурация ASGI (маршрутизация WebSocket)
│   └── wsgi.py              # Конфигурация WSGI
│
├── static/                   # Статические ресурсы
│   ├── css/                 # Пользовательские таблицы стилей
│   ├── js/                  # Файлы JavaScript
│   └── images/              # Ресурсы изображений
│
├── Documents/                # Загруженные пользователем файлы
│   ├── client_files/        # Документы договоров, финансовая отчетность
│   └── logs/                # Логи приложения
│
├── conf/                     # Конфигурация Nginx
│   └── conf.d/              # Конфигурации виртуальных хостов, SSL
│
├── requirements.txt          # Зависимости Python
├── docker-compose.yml        # Оркестрация контейнеров (5 сервисов)
├── Dockerfile                # Определение контейнера приложения Django
├── manage.py                 # CLI для управления Django
├── robots.txt                # Конфигурация SEO
└── README.md                 # Документация проекта

3. Архитектура модели данных

Приложение Clients - Основные модели (clients/models.py)

Основная сущность:

ClientsModel
├── id (PK)
├── client_name (CharField, max_length=500)
├── client_inn (CharField, 12 chars, российский ИНН)
├── client_kpp (CharField, 9 chars, налоговый код филиала)
├── client_debt (DecimalField, текущая сумма долга)
├── client_late_debt (DecimalField, сумма просроченной задолженности)
├── current_limit (DecimalField, утвержденный кредитный лимит)
├── asking_limit (DecimalField, запрашиваемый кредитный лимит)
├── status (ForeignKey → StatusModel, текущий этап рабочего процесса)
├── department (ForeignKey → Department, ответственный филиал)
├── manager (ForeignKey → Employees, менеджер по работе с клиентами)
├── director (ForeignKey → Employees, директор филиала)
└── created_date (DateTimeField, auto_now_add)

Модели рабочего процесса:

Модели финансовых данных:

Модели внешних данных (Kontur API):

Модели договоров и документов:

Модели рабочего процесса превышения лимита:

Модели просроченной задолженности:

Модели кредитного комитета:

Организационные модели:

Модели приложения SWIFT (swift/models.py)

DevicesDB
├── id (PK)
├── user_id (CharField, ссылается на пользователя Django)
├── company (CharField, идентификатор компании: "inoxtrade.ru", "ariel.ru")
├── device_token (TextField, токен регистрации FCM)
├── device_type (CharField, "iOS"/"Android")
└── created_date (DateTimeField)

SwiftNotificationSettings
├── id (PK)
├── device (ForeignKey → DevicesDB)
├── status_filters (JSONField, массив идентификаторов статусов для уведомления)
├── comment_notifications (BooleanField)
└── updated_date (DateTimeField)

Модели приложения Users (users/models.py)

CompanyUsers  # Поддержка нескольких арендаторов
├── id (PK)
├── user (ForeignKey → User)
├── company (CharField, идентификатор арендатора)
└── role (CharField, роль пользователя в компании)

TariffModel  # Планы подписки
├── id (PK)
├── name (CharField, например, "500 юридических лиц")
├── legal_entities_count (IntegerField, 250/500/1000/1500/2000/3000)
├── monthly_price (DecimalField)
├── annual_price (DecimalField)
└── features (JSONField, возможности плана)

PaymentHistory
├── id (PK)
├── user (ForeignKey → User)
├── tariff (ForeignKey → TariffModel)
├── amount (DecimalField)
├── payment_date (DateTimeField)
├── yookassa_payment_id (CharField, внешний идентификатор транзакции)
└── status (CharField, "pending"/"completed"/"failed")

Demo  # Генерация лидов
├── id (PK)
├── company_name (CharField)
├── contact_person (CharField)
├── email (EmailField)
├── phone (CharField)
├── message (TextField)
└── created_date (DateTimeField)

4. Архитектура API

RESTful Mobile API (swift/views.py)

Все конечные точки возвращают JSON, требуют аутентификации через сессию или токен.

Конечные точки веб-приложения (clients/urls.py)

Панель управления и представления списков:

Операции CRUD:

Действия рабочего процесса (асинхронные представления с уведомлениями):

Интеграция данных:

Рабочий процесс превышения лимита:

Управление уведомлениями:

Отчетность:

5. Архитектура безопасности

Аутентификация и авторизация

Защита данных

Инфраструктурная безопасность

Безопасность API

6. Ключевые паттерны проектирования

Разделение ответственности

Асинхронный/Уведомляющий паттерн

Каждое действие рабочего процесса следует этому паттерну:

def workflow_action(request, pk):
    client = ClientsModel.objects.get(pk=pk)
    # 1. Проверка разрешений
    if not user_has_permission(request.user, client):
        return HttpResponseForbidden()

    # 2. Валидация бизнес-логики
    if client.status != expected_status:
        return error_response()

    # 3. Обновление состояния
    old_status = client.status
    client.status = new_status
    client.save()

    # 4. Создание записи аудита
    StatusHistory.objects.create(
        client=client,
        old_status=old_status,
        new_status=new_status,
        user=request.user
    )

    # 5. Запуск уведомлений
    notify_users(client, new_status)
    send_push_notification(client, new_status)

    # 6. Возврат ответа
    return JsonResponse({'success': True})

Архитектура с несколькими компаниями

Оптимизация запросов с предварительной выборкой

clients = ClientsModel.objects.select_related(
    'status', 'department', 'manager', 'director'
).prefetch_related(
    'clientcreditcomments_set',
    'statushistory_set',
    'clientfinances',
    'clientkonturdata'
)

Уменьшает проблему N+1 запросов в представлениях списков.

Автоматизация на основе сигналов

@receiver(post_save, sender=Demo)
def notify_sales_team(sender, instance, created, **kwargs):
    if created:
        send_email_to_sales(instance)

Запросы запускают автоматические уведомления по электронной почте.

Шаблон WebSocket Django Channels

# swift/consumers.py
class NotificationConsumer(WebsocketConsumer):
    def connect(self):
        self.user_id = self.scope['url_route']['kwargs']['user_id']
        async_to_sync(self.channel_layer.group_add)(
            f'user_{self.user_id}',
            self.channel_name
        )

    def notification(self, event):
        self.send(text_data=json.dumps(event['message']))

Доставка уведомлений в реальном времени подключенным клиентам.

7. Детали внешней интеграции

Интеграция с Kontur API (clients/helpers.py)

Ключевые функции:

def get_kontur_basics(inn, pk):
    """Получение регистрационных данных компании, информации о руководстве"""
    endpoint = f'{BASE_URL}/req?inn={inn}&key={KONTUR_API_KEY}'
    # Заполняет: модель ClientKonturData

def get_kontur_trials(inn, pk):
    """Получение судебных дел, налоговых задолженностей, исполнительных производств"""
    endpoint = f'{BASE_URL}/casesCount?inn={inn}&key={KONTUR_API_KEY}'
    # Заполняет: модели ClientTrials, Monitoring

def get_kontur_financials(inn, pk):
    """Получение финансовой отчетности за 3+ года"""
    endpoint = f'{BASE_URL}/buh?inn={inn}&key={KONTUR_API_KEY}'
    # Заполняет: модели ClientFinances, ClientIncomeSt, ClientBalanceSt

def get_shareholders(inn, pk):
    """Получение структуры собственности"""
    # Заполняет: модель ShareHolders

Обработка данных:

Firebase Cloud Messaging (swift/views.py)

Инициализация:

import firebase_admin
from firebase_admin import messaging

firebase_admin.initialize_app(credentials.Certificate('firebase-key.json'))

Функция push-уведомлений:

def send_fcm_notification(user_id, title, body, data):
    devices = DevicesDB.objects.filter(user_id=user_id)
    for device in devices:
        message = messaging.Message(
            notification=messaging.Notification(title=title, body=body),
            data=data,
            token=device.device_token
        )
        messaging.send(message)

Триггеры уведомлений:

Платежный шлюз YooKassa (users/helpers.py)

Конфигурация:

from yookassa import Configuration, Payment

Configuration.account_id = 'your_shop_id'
Configuration.secret_key = 'your_secret_key'

Поток платежей:

def payment_helper(user, tariff, billing_cycle):
    amount = tariff.monthly_price if billing_cycle == 'monthly' else tariff.annual_price

    payment = Payment.create({
        "amount": {"value": str(amount), "currency": "RUB"},
        "confirmation": {
            "type": "redirect",
            "return_url": "https://yoursite.com/payment-return/"
        },
        "capture": True,
        "description": f"Subscription: {tariff.name}"
    })

    PaymentHistory.objects.create(
        user=user,
        tariff=tariff,
        amount=amount,
        yookassa_payment_id=payment.id,
        status='pending'
    )

    return payment.confirmation.confirmation_url  # Перенаправляем пользователя сюда

def check_payment(payment_id):
    payment = Payment.find_one(payment_id)
    if payment.status == 'succeeded':
        PaymentHistory.objects.filter(yookassa_payment_id=payment_id).update(status='completed')
        # Логика активации подписки

8. Оптимизация производительности

9. Тестирование и обеспечение качества

Инфраструктура тестирования:

Инструменты качества:


Вопросы масштабируемости

Текущие ограничения:

Улучшения масштабируемости (на будущее):


Уникальные технические особенности