Пример проекта на Python/Django: CRM для учета обращений клиентов по купленным лицензиям на программные продукты
Мы создадим пример модели CRM для учета обращений клиентов по лицензиям на ПО. Основные сущности:
- Клиент (Client)
- Договор/заказ (Contract)
- Программный продукт (SoftwareProduct)
- Лицензия (License) - связывает клиента, договор и продукт, также содержит ключ лицензии и срок действия.
- Обращение (Ticket) - обращение клиента по проблеме или предложению, связанное с лицензией.
Дополнительно:
- Пользователь (User) - сотрудники, которые работают с обращениями.
Схема:
Client:
name: CharField
contact_info: TextField (контакты, адрес и т.д.)
created_at: DateTimeField (авто-добавление)
Contract:
client: ForeignKey(Client)
contract_number: CharField (номер договора)
signed_date: DateField
amount: DecimalField (сумма договора)
created_at: DateTimeField
SoftwareProduct:
name: CharField
version: CharField
description: TextField (описание продукта)
License:
contract: ForeignKey(Contract) # договор, по которому приобретена лицензия
software_product: ForeignKey(SoftwareProduct)
license_key: CharField (уникальный ключ лицензии)
start_date: DateField
end_date: DateField
is_active: BooleanField (действующая ли лицензия)
Ticket:
license: ForeignKey(License) # лицензия, по которой возникло обращение
created_by: ForeignKey(User) # кто создал обращение (сотрудник)
created_at: DateTimeField
updated_at: DateTimeField
subject: CharField
description: TextField
STATUS_CHOICES = [
('open', 'Открыто'),
('in_progress', 'В работе'),
('resolved', 'Решено'),
('closed', 'Закрыто'),
]
status: CharField(choices=STATUS_CHOICES, default='open')
resolution: TextField (что сделано для решения)
Также можно добавить модель для комментариев к обращению, но для простоты ограничимся.
Примечание: Одно обращение (Ticket) привязано к одной лицензии. Если у клиента несколько лицензий, то обращение относится к конкретной лицензии.
Давайте создадим модели в коде:
Вот пример структуры CRM для учета обращений клиентов по лицензиям ПО на Django/PostgreSQL. Основные модели и их взаимосвязи:
1. Модели данных (models.py)
from django.db import models
from django.contrib.auth.models import User
class Client(models.Model):
name = models.CharField("Название", max_length=255)
contact_email = models.EmailField("Email")
phone = models.CharField("Телефон", max_length=20)
address = models.TextField("Адрес", blank=True)
created_at = models.DateTimeField("Дата создания", auto_now_add=True)
def __str__(self):
return self.name
class SoftwareProduct(models.Model):
name = models.CharField("Название продукта", max_length=100)
version = models.CharField("Версия", max_length=50)
description = models.TextField("Описание", blank=True)
def __str__(self):
return f"{self.name} v.{self.version}"
class Contract(models.Model):
client = models.ForeignKey(Client, on_delete=models.CASCADE, verbose_name="Клиент")
contract_number = models.CharField("Номер договора", max_length=50, unique=True)
signed_date = models.DateField("Дата подписания")
end_date = models.DateField("Дата окончания")
file = models.FileField("Документ", upload_to="contracts/", blank=True)
def __str__(self):
return f"Договор {self.contract_number} ({self.client})"
class License(models.Model):
contract = models.ForeignKey(Contract, on_delete=models.CASCADE, verbose_name="Договор")
product = models.ForeignKey(SoftwareProduct, on_delete=models.CASCADE, verbose_name="Продукт")
license_key = models.CharField("Ключ лицензии", max_length=255, unique=True)
activation_date = models.DateField("Дата активации")
is_active = models.BooleanField("Активна", default=True)
def __str__(self):
return f"Лицензия {self.license_key[:8]}... ({self.product})"
class Ticket(models.Model):
TICKET_TYPES = (
('problem', 'Проблема'),
('suggestion', 'Предложение'),
('question', 'Вопрос'),
)
STATUSES = (
('open', 'Открыт'),
('in_progress', 'В работе'),
('resolved', 'Решен'),
('closed', 'Закрыт'),
)
license = models.ForeignKey(License, on_delete=models.CASCADE, verbose_name="Лицензия")
title = models.CharField("Заголовок", max_length=200)
description = models.TextField("Описание")
created_at = models.DateTimeField("Создано", auto_now_add=True)
updated_at = models.DateTimeField("Обновлено", auto_now=True)
ticket_type = models.CharField("Тип обращения", max_length=20, choices=TICKET_TYPES)
status = models.CharField("Статус", max_length=20, choices=STATUSES, default='open')
assigned_to = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True, verbose_name="Исполнитель")
def __str__(self):
return f"{self.get_ticket_type_display()} #{self.id} - {self.license}"
2. Схема базы данных
erDiagram
CLIENT ||--o{ CONTRACT : has
CLIENT {
string name
string contact_email
string phone
text address
datetime created_at
}
CONTRACT ||--o{ LICENSE : includes
CONTRACT {
string contract_number
date signed_date
date end_date
string file_path
}
SOFTWARE_PRODUCT ||--o{ LICENSE : belongs_to
SOFTWARE_PRODUCT {
string name
string version
text description
}
LICENSE ||--o{ TICKET : references
LICENSE {
string license_key
date activation_date
bool is_active
}
TICKET {
string title
text description
datetime created_at
datetime updated_at
enum ticket_type
enum status
}
USER ||--o{ TICKET : assigned_to
3. Основные функции системы
-
Управление клиентами
- Регистрация новых клиентов
- История договоров и лицензий
-
Учет договоров
- Хранение сканов договоров
- Отслеживание сроков действия
-
Управление лицензиями
- Активация/деактивация ключей
- Привязка к продуктам и договорам
-
Обработка обращений
- Классификация по типу (проблема/предложение)
- Назначение исполнителей
- Контроль сроков решения
- История коммуникаций
4. Пример API-запросов (DRF)
# serializers.py
from rest_framework import serializers
from .models import Ticket, License
class TicketSerializer(serializers.ModelSerializer):
class Meta:
model = Ticket
fields = '__all__'
# views.py
class TicketViewSet(viewsets.ModelViewSet):
queryset = Ticket.objects.all()
serializer_class = TicketSerializer
filterset_fields = ['status', 'ticket_type', 'license__product']
5. Особенности реализации
-
Аутентификация
- JWT-авторизация для мобильных клиентов
- Ролевая модель доступа (менеджер/техподдержка)
-
Уведомления
- Автоматические оповещения при:
- Истечении срока лицензии
- Изменении статуса обращения
- Просроченных задачах
- Автоматические оповещения при:
-
Отчетность
- Статистика по типам обращений
- Время решения проблем
- Рейтинг продуктов по количеству проблем
6. Миграции
python manage.py makemigrations python manage.py migrate
7. Рекомендуемые улучшения
- Добавить комментарии к обращениям
- Реализовать SLA-контроль сроков
- Интеграция с почтой (входящие письма → тикеты)
- Дашборды аналитики
- История изменений статусов
Для запуска минимальной версии:
- Установите Django, DRF, psycopg2
- Настройте подключение к PostgreSQL в settings.py
- Создайте суперпользователя python manage.py createsuperuser
Это базовая структура, которую можно расширять под конкретные бизнес-процессы.