@fattan
программист

Doctrine — структура БД для хранения документов, и участников документооборота?

Есть информационная система (документооборот).
В ней список документов, которые могут менять статус (на согласовании, на доработке, закрыт и т.д.).
Статус меняется, когда пользователь с определенной ролью выполняет соответствующую операцию.
Например, нажимает автор документа "опубликовать" и документ меняет статус с "на доработке" на "на согласовании".

Есть нюансы:
1. есть согласующие в документе (например, инициатор, куратор) со связью manyToOne (у документа лишь один инициатор, автор, куратор...)
2. есть согласующие со связью manyToMany (любой юзер с ролью юрист может согласовать документ). Если хотя бы один юрист согласовал, документ переходит на следующую стадию
3. есть согласующие со связью manyToMany (в одном документе много исполнителей). Только если все исполнители согласовали, документ переходит на следующую стадию.

Как было раньше у нас реализовано:
одиночные роли хранились прямо в таблице document (initiator_id, curator_id, author_id):
d8ab7931f54c46b28b7c531a23584ed3.png
согласующие manyToMany (см. пункт 2), которые по ролям, хранились в отдельной таблице agreements:
22aac9c683304aa8b38e1bdbcc80ca6b.png
при этом изначально поле user_id=null, как только кто-то с ролью role_id согласовывал документ, в user_id проставлялся его айдишник, state проставлялся в 1 и документ уходил дальше

согласующие manyToMany (см. пункт 3) хранились в отдельных таблицах, соответствующих отдельной роли, например, executors:
6f705a140d8c46e1bafa401ce040d323.png
при этом, у всех узеров из списка исполнителя state=0 по умолчанию. Как только у всех state становилось 1, документ переводился на следующую стадию

Потом, потребовалось всё переписать на Symfony. И стал я думать, как правильно организовать хранение согласующих, с точки зрения Doctrine. Старый подход тут был уже неуместен. По-началу создал такую схему:

01e9bce124e243dbb68344c2ac9d063f.png

Тут одиночных согласующих храню также в документе, Согласующих из пункта 3 в таблице doc_signers
С согласующими по ролям (пункт 2 ) пока не знаю что делать.

Помогите грамотно организовать сущности. Если есть уже какая-то методология решения таких задач (я лично не нашел), киньте ссылку.

Спасибо!

UPD в разрезе Symfony+Doctrine более корректно будет говорить о структуре сущностей и связях между Entities
  • Вопрос задан
  • 868 просмотров
Пригласить эксперта
Ответы на вопрос 3
Задача не сложная. Но вы сами себя запутали. Методик вы не найдёте. Вам надо научиться анализировать происходящий у вас бизнес-процесс и разделять его на алгоритм и контекст. Решать эту задачу за вас было бы неправильно, поэтому вот вам советы:
1. Выкиньте из документа все признаки, отвечающие за согласование.
2. Введите новую сущность Согласование.
3. Свяжите Документ с сущностью Согласование единственной ссылкой. Так вы очистите документ от ненужной ему информации. Ссылка должна храниться на стороне Согласования (Owning Side Relation), но на стороне Документа должна быть возможность получить сущность Согласования (Inverse Side Relation).
4. Если я правильно понял, то ваш документ может быть согласован по трём разным алгоритмам. Если это так, то воспользуйтесь возможностью доктрины Class Table Inheritance. Вы получите одну связь со стороны документа, но разные алгоритмы аппрува со стороны Согласования.
5. В каждом из Согласований реализуйте метод isApproved со своей логикой.
6. После такого разделения вы сможете строить алгоритмы, привязываясь к каждому типу Согласований по отдельности, не обращая внимание на другие.
Ответ написан
myrkoxx
@myrkoxx
developer
чисто мое ИМХО в разрезе Symfony я никогда не стал бы проектировать сначала схему базы. Всегда начинаю с создания мапинга Doctrine. Вот как пример (очень простой)

BlogBundle\Entity\Blog:
  type: entity
  table: bb_blog
  repositoryClass: BlogBundle\Entity\Repository\BlogRepository
  fields:
      name:
          type: string
          length: 100
          nullable: false
      status:
          type: string
          length: 10
          nullable: false
  manyToOne:
      user:
          targetEntity: BlogBundle\Entity\User
          joinColumn:
              name: user_id
              referencedColumnName: id
  oneToMany:
      posts:
          targetEntity: BlogBundle\Entity\Post
          mappedBy: blog
          orderBy: { 'createdAt': 'ASC' }
          cascade:
              - remove


А потом уже с помощью DoctrineMigrationsBundle генерю миграции которые приведут базу в необходимое состояние.
Ответ написан
@u_elnur
Веб разработчик, Начинающий предприниматель
Приветствую! Мне в течение последнего года доводилось делать три похожих проекта документооборота. Хотелось бы поделиться со своим решением, как я организовал структуру таблиц (они же и сущности в доктрин).

Первое:
У моих проектов было несколько маршрутов согласования. Поэтому я хранил их отдельно. И называл их workflow (бизнес процесс)
Workflow: (Маршрут согласования)
    id
    name (Название маршрута согласования)
WorkflowPoint: (Точка согласования)
    id
    title (Название точки. Например "Согласование фин директора")
    workflow_id (Связанный маршрут)
    user_id (Пользователь, который рассматривает документ в этой точке согласования)
    order_id (Порядковый номер точки в маршруте)
    roles (Права пользователя, в данной точке согласования)


Второе:
В моих проектов в одном документе согласования могли храниться несколько файловых вложении. Поэтому Файл и Документ согласования хранились отдельно.

Approval: (Документ согласования)
    id
    title (Название документа)
    author_id (Инициатор)
    state = 0 (Состояние документа. 0 - черновик. 1 - в процессе согласования. 2 - одобрено. 3 - отказано. 4 - архивировано)
    workflow_id (Маршрут, по которому движется данный документ. По умолчанию null, кроме того, когда состояние документа в процессе согласования)
    workflow_point_id (Текущая точка согласования в маршруте. При одобрении, указывается следующая точка)
    approval_user_id (Пользователь, который должен рассмотреть документ в текущий момент. Это поле чисто для удобства в поиске)
Attachment: (Файл-вложение)
    id
    approval_id (Связанный документ)
    file_path (Путь к файлу)
    author_id (Пользователь, который вложил файл)


Я значительно упростил структуру, чтобы просто дать Вам идею для размышления. В реальных проектах было гораздо сложнее
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы