3

Я разрабатываю приложение для управления проектами в Django, для которого требуется несколько линейный процесс ответа с участием разных групп пользователей (как в Django auth Groups). Каждый шаг процесса ответа имеет несколько вариантов ответа (большинство параметров, уникальных для шага) и назначается пользователю в пределах определенной группы. Следующий шаг в процессе определяется ответом пользователя, и иногда может потребоваться дополнительная информация от одного из членов проекта.Django: Как отслеживать линейный (но гибкий) процесс управления проектами?

Проблема в том, что моя текущая реализация кажется довольно громоздкой, и я уверен, что есть лучший способ отслеживать процесс ответа. Я надеялся, что кто-то может дать некоторое представление о более надежном решении.

В качестве простого примера рассмотрим проект со следующими группами пользователей: Sales Rep, Sales Manager и Project Manager. Модели в настоящее время выглядит следующим образом:

class Project(models.Model): 
    assigned_to = models.ForeignKey(User, related_name="projects_assigned_to") #Indicates which user needs to respond next. Will be sales_rep, sales_mgr, or project_mgr. 
    sales_rep = models.ForeignKey(User, related_name="sales_rep_projects") #choices limited to "Sales Rep" Group 
    sales_mgr = models.ForeignKey(User, related_name="sales_mgr_projects") #choices limited to "Sales Manager" Group 
    project_mgr = models.ForeignKey(User, related_name="project_mgr_projects") #choices limited to "Project Manager" Group 
    current_step = models.ForeignKey(Step, related_name="projects_with_current_step") 
    previous_step = models.ForeignKey(Step, related_name="projects_with_previous_step") 
    status = models.ForeignKey(Status) #Automatically assigned according to the user's response. Includes things like "On Track", "On Hold", "Rejected", "Accepted", etc. 

class Step(models.Model): 
    name = models.CharField(max_length=50) 

class Status(models.Model): 
    name = models.CharField(max_length=50) 

Вот простой обзор того, как этот процесс может работать:

  1. Sales Rep создает новый проект и он назначен менеджером по продажам
  2. Менеджер по продажам является представлены следующие варианты:
    (a) утвердить проект или
    (b) запросить дополнительную информацию у торгового представителя
  3. Если проект утверждено, назначить руководитель проекта, который представлен со следующими параметрами:
    (а) начать проект
    (б) отклонить проект
    (с) запросить дополнительную информацию от отдела продаж или менеджер по продажам
  4. Если больше информация запрашивается у пользователя, проект назначается этому пользователю, и им просто нужно предоставить ответ текстового поля. Однако, как только их ответ был получен, проект должен вернуться к предыдущему шагу (вот почему я отслеживаю current_step и previous_step выше). В этом примере, если диспетчер проектов запрашивает дополнительную информацию у торгового представителя, после ответа отдела продаж ответ на проект должен быть возвращен диспетчеру проекта с теми же параметрами ответа, которые у него были до (начало, отклонение, запрос дополнительной информации).

Полный процесс имеет около 10 или около того таких шагов.

Чтобы усложнить ситуацию, я также должен иметь возможность отображать ответ, выбранный для каждого шага. Например, если Менеджер по продажам одобряет проект, он должен отображать «Менеджер по продажам одобренный проект» вместе с любыми комментариями, которые они могут иметь. Модель выглядит следующим образом:

class Response(models.Model): 
    comment = models.TextField() 
    response_action = models.ForeignKey(ResponseAction) 
    submitted = models.DateTimeField() 

class ResponseAction(models.Model): 
    """ I.e. 'Sales Manager approved the project', 'Project Manager commenced the project'""" 
    name = models.CharField(max_length=100) 

Сейчас логика для каждого ответного действия закодирована в представлении, и нет никаких формальных отношений между одним шагом и другим. Я чувствую, что есть лучшая структура модели или структура данных, которые я должен использовать, чтобы отслеживать этот рабочий процесс, но я работал с текущей системой так долго, что у меня возникли проблемы, думая об этом по-другому. Любое понимание или вдохновение были бы очень признательны! Дайте мне знать, если мне нужно что-то разъяснить.

ответ

1

Больше использовать модель Step. Вы можете провести следующие шаги в качестве внешних ключей. Таким образом, вы можете редактировать поток, изменяя данные (например, с помощью администратора, а не жесткого кодирования).Может быть что-то вроде:

class Step(models.Model): 
    name = models.CharField(max_length=50) 
    responsible_role = models.CharField(max_length=50) # this contains 'sales_rep', 'sales_mgr' etc 
    allowed_actions = models.ManyToManyField('AllowedAction') 

class AllowedAction(models.Model): 
    name = models.CharField(max_length=50) 
    next_step = models.ForeignKey('Step') # the next step, if this action is chosen 

отделите фактическую историю проекта на другую модель:

class ProjectHistoryStep(models.Model): 
    timestamp = models.DateTimeField() 
    step = models.ForeignKey('Step') 
    project = models.ForeignKey('Project') 

Вы можете использовать эту модель для отслеживания фактического прогресса ваших проектов (не забывайте, что модели имеют get_next_by_FOO) ,

Вам понадобится только один вид, который обрабатывает всю логику (он должен просто вызвать какой-либо метод в классе Project для выполнения фактической работы) - проверьте, в каком состоянии находится проект (последний проект ProjectHistoryStep для этого проекта), и что было действием Пользователя, и действовать соответствующим образом.

+0

Спасибо за ваш отзыв, это выглядит действительно многообещающим! Сегодня я поиграю с ним и дам вам знать, как это происходит. –

+0

Я хотел запустить еще одну вещь. Для некоторых разрешенных действий необходимо заполнить несколько полей. Должен ли я указывать эти поля на уровне формы или создавать другое поле ManyToMany для чего-то вроде AllowedActionOption? Спасибо за вашу помощь. –

+0

Если его простые (например, все текстовые поля, просто с разными именами), то вам следует создать еще одну модель с M2M из AllowedAction. Если его более сложный (некоторые поля FK - в других местах, некоторые - это тексты, некоторые - URL-адреса и т. Д.), Затем использует формы django и просто указывается в разрешенном действии, какую форму использовать. –