База данных поликлиники (больницы)

База данных поликлиники (больницы) в формате MySQL. Версия: 8.0.28 В архиве модель для MySQL Workbench и готовый скрипт базы данных, который можно импортировать или просто выполнить в MySQL Workbench для создания физической базы данных на компьютере.

База данных поликлиники

База данных поликлиники является довольно популярным запросом в рунете. В этой статье я рассмотрю вопрос проектирования базы данных и физической разработки. То есть, первая часть статьи будет освещать разработку модели базы данных, а вторая часть статьи будет описывать создание базы данных поликлиники из нашей разработанной модели.

И в самом конце статьи вы сможете скачать готовую базу данных поликлиники, которую мы с вами получим.

Проектирование базы данных поликлиники

Проектирование базы данных — это очень большая область, включающая в себя множество схем, представленных в том числе и на языке описания UML, а также включающих в себя описание бизнес-процессов в различных нотациях, например, в нотации idef0.

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

В общем, я в этой статье ограничусь только основными схемами, которые вам покажут объекты и связи между ними в разрабатываемой базе данных.

Предметная область «Поликлиника»

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

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

Что представляет собой типичная поликлиника? Прежде всего, в каждой поликлиники есть такой отдел как регистратура, где у нас хранятся все карточки наших пациентов. В поликлинике также есть корпуса, отделения. В каждом отделении имеются кабинеты, в которых врачи осуществляют прием больных граждан. Это типичная картина поликлиники.

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

Также в поликлиниках оказываются и платные услуги. В настоящее время уже не столь важно, к какому типу принадлежит поликлиника. Это может быть как коммерческая организация, так и государственная. В коммерческой практически все оказываемые услуги являются платными, а в государственной поликлинике также есть бесплатные услуги и есть услуги, которые не входят в обязательный пакет бесплатного медицинского обслуживания.

Аптека поликлиники может выступать в роли самостоятельной организации, которая просто берет в аренду одно из помещений поликлиники, а может выступать как отдел поликлиники. Почему бы и нет? Если поликлиника коммерческая, то это вполне может быть ее вспомогательным видом деятельности.

И я считаю, что этот момент тоже стоит учесть в нашей базе данных, а не ограничиваться только лишь разработкой базы данных для регистратуры поликлиники. Так наша база данных будет намного интересней и функциональней.

Еще стоит отметить, что все эти лекарственные препараты где то должны храниться. Следовательно, у поликлиники должно быть складское помещение.

Не стоит забывать и о том, что доступ к базе данных обычно осуществляется разными специалистами, следовательно потребуется вести учет пользователей, сотрудников, должностей.

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

Поэтому, давайте с вами сейчас определим что мы хотим от нашей будущей программы, чтобы потом сделать проект базы данных.

Функциональные требования к ИС «Поликлиника»

Функциональные требования к ИС «Поликлиника» (назовем ее так):

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

Таким образом, функциональные требования к информационной системе довольно обширны, а это значит, что нам потребуется выполнить проектирование базы данных с большим числом объектов.

Мнемосхема «TO BE» (Как должно быть)

Давайте рассмотрим мнемосхему деятельности поликлиники с использованием нашей будущей информационной системы.

Опишем нашу с вами мнемосхему работы поликлиники и после этого мы сможем перейти к построению информационной модели данных поликлиники.

Начинается у нас все с пациента. Пациент обращается в регистратуру поликлиники непосредственно или через сайт (если планируется разработать веб-приложение). Работник регистратуры проверяет наличие в картотеке клиники медицинской карты пациента. Если такой карты нет, то заводит новую карту на обратившегося пациента. Следует заметить, что речь идет не об обычной бумажной карте, а об электронной карте пациента, хранящейся в базе данных информационной системы.

Далее пациент выбирает нужного ему доктора и записывается на свободное время. Записать клиента также может и работник регистратуры. Это будет удобно, если, например, в качестве пациента будет выступать пожилой человек, который не умеет пользоваться современными технологиями.

После записи, работник регистратуры выдает пациенту талон, в котором указаны кабинет, ФИО доктора, дата и время записи на прием. Карта пациента при этом «уходит» из регистратуры к этому доктору, а не отдается на руки пациенту, как при классическом подходе.

В назначенное время пациент приходит к доктору, показывает талон, доктор, используя данные талона, понимает, что к нему пришел пациент (условно Иванов) и среди своих электронных карт в программе находит карту Иванова.

Доктор выслушивает жалобу пациента, записывает ее в карточку пациента в информационную систему и, если нужно назначает ему сдачу анализов, выдавая пациенту талон с названиями необходимых для прохождения анализов. Сам же доктор создает запись в информационной системе о том, какие анализы должны быть сданы пациентом. Эту запись увидит у себя в личном кабинете лаборант. При этом доктор может записать пациента на повторный прием.

Далее пациент идет с талоном к лаборанту, где он сдает необходимые анализы. Лаборант вносит результаты этих анализов в созданную доктором запись.

На повторном приеме у доктора, последний в соответствии с анализами устанавливает заболевание (диагноз) и назначает курс лечения, фиксируя все это в электронной карте пациента. Причем доктор может установить диагноз сразу, не назначая сдачу анализов.

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

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

Здесь следует отметить, что когда доктор назначает лечение, он обычно выписывает необходимые пациенту лекарственные препараты. Так вот все это пациент может приобрести в клинике в той самой упомянутой выше аптеки. Пациент также может подойти с этим рецептом, выписанным доктором к фармацевту (кассиру аптеки) и приобрести лекарства.

Отдельно стоит сказать о том, что в эту схему можно грамотно внедрить механизм работы склада, ведь лекарственные препараты должны обязательно храниться на складе аптеки поликлиники. Собственно механизм работы такой схемы будет мало чем отличаться от работы типичной аптеки. Но внедрить это в работу поликлиники будет достаточно интересно, чтобы функционал программы был более обширным. А почему бы и нет?

Для этого нам понадобится менеджер склада, который будет взаимодействовать с поставщиками. Менеджер склада формирует заявку на товары и направляет ее поставщику. Поставщик в сопровождении товарной накладной (ТОРГ-12) поставляет товары на склад аптеки поликлиники. Стоит отметить, что товары склада могут использоваться не только в аптеке, но и в стационаре поликлиники. Поэтому, я считаю, что такое комплексное внедрение очень удобно.

После проверки товаров, менеджер подписывает второй экземпляр накладной и отдает отправляет ее поставщику. Прием товара при этом фиксируется в программе.

Если при поступлении товара выявлен брак, просроченные товары или просто товары не соответствуют накладной, то составляется акт, формируется накладная на возврат и эти сведения заносятся в информационную систему.

Бракованный же товар направляется обратно поставщику вместе с подписанным актом и накладной на возврат товара. Поставщик же обратно присылает подписанный экземпляр накладной и акта. Операции пересылки можно организовать, например с использованием систем документооборота (по согласованию с поставщиками).

Также менеджер у нас формирует из программы отчет о поступлении, об остатках товаров на складе, а также можно разработать еще ряд необходимых отчетов.

В этой схеме не отображены такие роли как главный врач, заместитель главного врача и так далее. Но их можно использовать также. Можно даже добавить экономиста, который будет определять спрос на услуги, спрос на аптечные товары и тому подобное. Тут уже все будет ограничиваться потребностями клиники. Давайте же теперь перейдем непосредственно к формированию информационно-логической модели данных.

Информационно-логическая модель данных поликлиники

Логическая модель данных не зависит ни от какой-либо СУБД и создается сама по себе. Ее можно разработать как на бумаге, так и с использованием ряда компьютерных программ, таких как MS Visio.

Таких программ очень много. По сути, здесь подойдет вообще любой из графических редакторов (предпочтительно конечно векторный). Мне нравится все свои схемы выполнять в CorelDraw. Если кто-то любит Adobe Illustrator — можете взять его.

Конечно существует еще очень много программ, предназначенных непосредственно для этой цели. Некоторые из низ позволяют затем экспортировать логическую модель в физическую уже для выбранной СУБД. На рисунке ниже изображена логическая модель данных поликлиники.

Здесь сразу стоит пояснить, что данная схема данных больницы является универсальной. То есть, ее можно использовать как в платной поликлинике, так и в бесплатной. Вы можете всем имеющимся услугам установить нулевую стоимость, если у вас бесплатная поликлиника, вы можете установить стоимость для конкретных услуг и только. Приведем описание схемы данных поликлиники.

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

Поликлиника обычно представляет собой один или несколько корпусов (может быть даже расположенных на разных улицах и кварталах), отделений внутри корпусов (иногда отделение может занимать целый корпус) и кабинетов внутри каждого из таких отделений.

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

Поскольку в каждом корпусе у нас может быть от одного до нескольких отделений, то объект «Отделения» является дочерним объектом по отношению к объекту «Корпуса».

Аналогично, в каждом отделении имеется несколько кабинетов, поэтому объект «Кабинеты» является дочерним, то есть подчиненным объектом, по отношению к объекту «Корпуса».

По сути — эти объекты являются справочниками, но с подчинением друг другу, как указано в абзаце выше.

В поликлинике, как и в любой другой организации, имеются должности, которые удобно разделить на группы. С этой целью в схеме данных имеется родительский объект «Группы должностей» и дочерний (подчиненный) — «Должности».

В информационной системе всегда имеются пользователи. Такие пользователи должны где-то учитываться. С этой целью в имеющейся схеме предусмотрен справочный объект «Пользователи».

У каждого из пользователей может быть от одного до нескольких телефонных номеров, поэтому их удобно вынести в отдельный подчиненный объект «Телефоны».

Теперь более интересная вещь. Каждый пользователь занимает определенную должность и связывая их отдельным объектом мы получаем сотрудника. Для хранения этой связки используется объект «Сотрудники». Можно было бы должность хранить и непосредственно, просо сделав поле «Должность» у объекта «Пользователи». Но это будет не грамотно. В базе данных должны использоваться справочники, а данные не должны дублироваться.

Если же использовать поле, то, например, должность «Терапевт» может быть использована по отношению ко многим пользователем. А это, во-первых, не правильно, так как возникает упомянутое дублирование данных, а во-вторых — это просто не удобно.

Дублирование было критично лет 20 назад, когда жесткие диски были малых размеров. Сейчас же при огромных объемах жестких дисков — это не является проблемой, но все же база данных должна быть построена грамотно. Ну и как я уже написал — это не удобно, у должностей как бы отсутствует стандартизация в программе. И еще, допустим Иванов работал детским терапевтом (педиатром), а теперь он перешел работать глазным терапевтом. Что будете делать в этом случае?

Менять должность ему в справочнике «Пользователи» нельзя, потому что с этой записью связано очень много других записей в базе данных. И если вы измените ему должность, то все записи об этом сотруднике в базе данных за эти два года уже будут не как о педиатре, а как о глазном терапевте. Понимаете? Нужно только создавать точно такого нового пользователя, но с должностью глазного терапевта.

Но как вы понимаете это тоже не правильно, Представляется, сколько со временем будет таких Ивановых. У них у всех будут одинаковые ФИО, даты рождения, паспортные данных и прочая информация. Поэтому такой подход является в корне не верным, несмотря на то, что многие преподаватели учебных заведений все же учат своих студентов проектировать именно так.

Поэтому все эти вещи в приведенной схеме данных выделены в отдельные объекты. То есть, в нашей схеме данных каждому человеку (пользователю) может соответствовать от одной до нескольких должностей. Даже возможно одновременно, если на второй должности человек работает по совместительству.

Точно также одной должности могут соответствовать несколько человек (пользователей). На должности хирурга может работать от одного до нескольких человек, на должности педиатра тоже самое и на должности офтальмолога, пульмонолога и т.д. — тоже самое.

Такая связь между объектами «Должности» и «Пользователи» называется много-ко-многим. И чтобы ее физически организовать, добавляют промежуточный объект в схему данных, где объединяют данные из вышеупомянутых объектов «Должности» и «Пользователи». Таким объектом в нашей схеме и является объект «Сотрудники».

Эту концепцию развиваем далее. Должности или, по другому можно сказать, врачебные специализации обычно также закрепляются за определенными кабинетами. То есть, в клинике имеется кабинет терапевта, кабинет окулиста, рентген, приемные покои, лаборатория и так далее.

Поэтому в схеме данных должна присутствовать сущность, которая будет объединять кабинеты и специализации (должности). Эта сущность называется в схеме данных «Приемный кабинет».

В каждом приемном кабинете могут располагаться от одного до нескольких врачей. Кончено это не удобно и редко практикуется в поликлиниках. Но все же, например на время ремонта или по каким то другим причинам такая ситуация встречается. Поэтому нужно сделать так, чтобы расписание приема составлялось не на кабинет в целом, а на конкретного доктора, который будет вести прием в конкретном кабинете.

Более того, следует спроектировать схему данных таким образом, чтобы в любой момент можно было в расписании изменить одного доктора на другого без ущерба предыдущим записям. это достаточно важно. Что я имею сейчас ввиду?

Давайте начнем сразу с того, что сущностью, где у нас формируется расписание будет являться одноименная сущность «Расписание». В ней объединяются сведения из сущности «Приемный кабинет» и сущности «Сотрудники».

Каждый сотрудник в своем личном кабинете сам составляет себе расписание (так же его может составлять определенное должностное лицо, которому поручено данное действие. Это все зависит от конкретной клиники).

Допустим терапевт-офтальмолог Иванов составил расписание на 01.03.2024 года и, соответственно, пациенты уже записались к нему на прием еще в конце февраля. И вдруг обнаруживается, что 01.03.2024 Иванов заболел и не может выйти на работу. Но ведь пациенты уже пришли и ждут своего приема.

С точки зрения приема граждан — это не беда, если в поликлинике есть еще один профильный врач. Он примет данных пациентов. Но вот записать в карту данные и прочие манипуляции он наверно не сможет, поскольку ему потребуется войти в личный кабинет заболевшего Иванова и от его имени вести прием. Ну а это не правильно, ведь прием пациентов — это большая ответственность. В базе будет зафиксировано, что прием вел Иванов, а на самом деле Петров.

Поэтому в своей схеме я предусмотрел такой исход событий. В этом случае в сущности «Расписание» потребуется поменять только код сотрудника. При этом никакие другие записи в базе данных затронуты не будут.

Вот если сущность «Сотрудники» была бы соединена с сущностью «Приемный кабинет», тогда смена кода сотрудника в сущности «Приемный кабинет» привела бы к искажению всех записей, которые будут в истории болезни карты пациента, ведь после смены кода сотрудника во всех прошлых записях, которые делал Иванов, будет отображен другой врач, код которого мы поставили.

Но в нашем случае этого не произойдет, поскольку мы сменим код только у конкретных записей в сущности «Расписание». Более того, мы можем сменить код сотрудника не за весь приемный день, а например, до обеда останется принимать Иванов, а после обеда — Петров. Это удобно, когда, например, Иванов, отпросился по семейным обстоятельствам или просто плохо себя почувствовал и ушел с работы с обеда. В общем, в нашей схеме можно «баловаться» временем в расписании как угодно.

Это также позволит каждому доктору (даже если оба они сидят в одном кабинете) составлять собственное расписание приема, а также «привязывать» доктора к определенному кабинету.

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

Для этой цели в схеме данных имеется сущность «Расписание». То есть, для каждой связки из сущности «Приемный кабинет» и «Сотрудники» приходится множество записей из сущности «Расписание». Образно говоря, для каждого специалиста в определенном кабинете есть множество записей в сущности «Расписание».

Идем дальше. В поликлинике у нас есть регистратура, где у нас хранятся карточки пациентов поликлиники. Этакая база данных регистратуры поликлиники.

Для хранения медицинских карт предусмотрена сущность «Карты». Это справочник. Далее следует важная деталь.

Пациент (то есть карта) осуществляет обращение в поликлинику и программа осуществляет его запись в сущность «Обращения» на определенную время, дату, кабинет и специалиста, представленных в сущности «Расписание».

Каждое обращение может содержать в себе несколько записей на прием. То есть, пациент Сидоров может обратиться один раз к доктору с жалобой, а после этого может быть несколько последующих приемов.

И вот каждый из таких приемов — есть запись на прием в рамках одного обращения. Поэтому сущность «Запись на прием» является подчиненной по отношению к «Обращения» и «Расписание».

По сути от «Карты» к «Обращения» идет связь один-ко-многим, так как одна и та же карта может множество раз «обращаться» за помощью в клинику. А вот от «Расписание» к «Запись на прием» может идти связь один-к-одному, так как одно и то же время на определенную дату может использоваться только один раз в сущности «Запись на прием».

Но поскольку у нас есть связка «Расписание-Обращения», то в любом случае время записи будет использовано всего один раз и связь между сущностями «Расписание» и «Запись на прием» можно оставить как один-ко-многим и это не будет являться ошибкой.

Каждое обращение пациента (не обязательно) может сопровождаться сдачей одного или нескольких анализов, поэтому сущность «Анализы пациентов» является дочерней по отношению к сущности «Обращения».

Чтобы стандартизировать названия анализов удобно использовать для этого справочник. В нем же удобно хранить и нормативные значения для каждого анализа. Ну а для того, чтобы было удобно ориентироваться большом количестве разных анализов, из удобно хранить в разрезе групп анализов. Поэтому сущность «Группы анализов» является родительской, а сущность «Анализы» — дочерней.

Сущность «Анализы пациентов» содержит в себе связку конкретной карты (через обращение) и записи на прием. Причем отметим, что от сущности «Запись на прием» к сущности «Анализы пациентов» идет две связи один-ко-многим.

То есть, поле «Код записи» сущности «Запись на прием» связано с полями «Код записи врача, назначившего анализ» и «Код записи лаборанта, добавившего результат анализа».

Так сделано по одной простой причине. В нашей системе, каждый доктор может создать записи в сущности «Анализы пациентов». То есть, указать лаборанту, какие анализы пациенту необходимо сдать.

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

В нашей системе вся данная информация прописывается в сущности «Анализы пациентов».

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

Ну и наконец, получив результаты анализов (если эти анализы были необходимы) доктор устанавливает диагноз. Кстати сказать, у пациента может оказаться не один, а два и более диагнозов при комплексном заболевании, поэтому сущность «Диагнозы» является дочерней для сущности «Обращения» и «Запись на прием». Это значит, что конкретный диагноз может быть установлен для определенного обращения и был установлен в определенную дату/время, определенным специалистом.

Не всегда при каждом обращении доктор может назначить лечение, которое способно помочь пациенту. Иногда назначают повторный курс лечения или вовсе прописывают другие лекарственные препараты. Например, когда на какой то лекарственный препарат у пациента выявляется аллергическая реакция. Для этого нам потребуется сущность «Лечение».

Итак с регистрацией пациентов, болезней, диагнозами и так далее мы разобрались. Теперь давайте перейдем к регистрации оказанных услуг и продажи лекарственных препаратов в аптеке поликлиники.

Давайте начнем с оформления услуг, как с более простой компоновкой объектов будущей базы данных.

Для удобства учета услуг мы также будем хранить услуги в в составе групп, поэтому в схеме будут присутствовать такие сущности, как «Группы услуг» и «Услуги».

Стоимость услуг не является фиксированной величиной. Она время от времени меняется, поэтому для учета стоимости каждой услуги следует выделить отдельную сущность и назвать ее, например, «Стоимость услуг».

Доктор после оказания определенной услуги или комплекса медицинских услуг может выписывать квитанцию пациенту. Для хранения квитанций будет выделена отдельная сущность «Квитанции» и связана она будет с сущностью «Сотрудники», поскольку будет необходимо вести отмечать сотрудника, который сформировал квитанцию (то есть, доктора).

Ну и, соответственно, каждая квитанция будет включать в себя одну или несколько оказанных услуг. Поэтому сделаем сущность «Чек-лист услуги» и по внешним ключевым полям она будет связана с сущностью «Квитанции» и «Стоимость услуг». Ну то есть, мы должны в чек-листе отображать стоимость наших услуг.

Теперь перейдем к продаже товаров. Здесь тоже ничего сложного нет, просто будет представлено дополнительно несколько сущностей.

Начнем мы с того, что товары так же как и услуги будут учитываться в составе групп. Так будет удобно. У каждого товара есть единица измерения (шт., граммы, флаконы и так далее.).

Чтобы красиво унифицировать единицы измерения, следует для них создать отдельную сущность и связать ее с сущностью «Товары». При торговле товарами полезно иметь информацию о его производителе. Поэтому в схему базу данных включим такую сущность, как производители.

Производителя свяжем также с товарами как один-ко-многим. То есть, каждому производителю соответствует один или несколько видов товара.

Если будет желание хранить изображения для товаров, то можно в сущности товары добавить поле «Изображение», но мне кажется для изображений лучше будет выделить отдельную сущность. Это позволит для каждого товара хранить несколько изображений. Вместе с тем, если желание хранить изображения (фото товара) отсутствует — данную сущность можно не заполнять.

Идем дальше. Все товары у нас поступают от поставщиков. Поставщиками могут быть не обязательно производитель товаров. Это могут быть другие фирмы-посредники, поэтому поставщиков я выделил в отдельную сущность. Поскольку у каждого поставщика есть одно или несколько контактных лиц, с которыми можно взаимодействовать, то я выделил для их учета отдельную сущность «Контакты».

Стоит отметить, что обычно поставщики предоставляют каталог, в котором прописаны продаваемые ими товары. Поэтому мы обязательно создадим такую сущность для более полноценного учета и свяжем ее с сущностями «Поставщики» и «Товары».

Почему мы связали сущность «Каталог» с «Поставщики» я только что уже сказал, а вот почему мы связали ее с сущностью «Товары» сейчас расскажу.

Дело в том, что одинаковый товар может быть поставлен разными поставщиками. Например, «Парацетамол». Его может поставлять один поставщик, может другой и третий. Поэтому в каталоге обязательно указывается товар и поставщик. Сущностью «Каталог» создается связь много-ко-многим между сущностями «Поставщики» и «Товары».

То есть, один и тот же поставщик может поставлять разные товары, равно как и один и тот же товар может быть поставлен разными поставщиками.

Ну и, соответственно, каталожные цены также меняются время от времени, поэтому каждой позиции каталога соответствует множество цен. Учитываться программой конечно будет последняя.

Изучив каталог, ответственный сотрудник начнет составлять заявку поставщику. Для хранения заявок следует выделить сущность «Заявки», которая будет связана, соответственно с сотрудниками и поставщиками.

В заявку должны быть включены товары из каталога. Эти товары будут учитываться сущностью «Перечень товаров по заявке».

Когда товары поставщиком будут поставлены, они будут сопровождаться документацией (чаще всего накладной). И такая поставка будет учитываться сущностью «Приходная накладная». Естественно, что она связана с заявками, так как поставляют нам товар в соответствии с заявкой и с сотрудниками, поскольку нам потребуется вести учет сотрудников, которые будут принимать товар от поставщика.

При приеме товаров от поставщика может возникнуть три ситуации:

  • товар полностью соответствует заявке и накладной и он полностью принят;
  • товар полностью соответствует заявке и накладной, но есть брак или порча в результате транспортировки или несоответствие по количеству;
  • поступили товары, которые отсутствуют в заявке.

Рассмотрим каждый из этих случаев. Когда у нас все товары соответствуют и нет порчи, то мы такие товары будем учитывать в сущности «Перечень принятого товара». Естественно, что эта сущность связана с сущностью «Приходная накладная», поскольку перечень является ее расшифровкой, а так же с сущностью — перечень товаров по заявке, поскольку товар этого перечня мы берем из заявки (у нас же разногласий по поступлению нет).

Каждый принятый товар имеет свой маркировочный номер «Код маркировки». Поэтому в данном случае мы не будем вести общий количественный учет товаров, а будем вести прием товара по штучно. То есть, мы будем будем прописывать его характеристики и указывать их в сущности «Единицы принятого товара». Обычно эти характеристики в настоящее время не вписываются вручную, а вносятся в базу данных программы с помощью сканера штрих-кода.

Все эти характеристики зашифрованы в коде маркировки аптечного препарата. Этот код маркировки присваивается. Такие коды наносит производитель, а получает он их от СБИС «Маркировка». Закон об обязательной маркировке лекарственных препаратов был принят в 2020 году.

Более подробно об этом вы можете прочитать в статье «Маркировка лекарственных средств».

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

Эти цены будут учитываться в сущности «Цены реализации». Продажи у нас будет создавать отдельный сотрудник (аптекарь). Эти продажи будут вестись в сущности «Продажи». По сути здесь будут храниться кассовые чеки.

Ну и в самом чеке у нас отображаются товары, поэтому мы эти товары учтем в сущности «Чек-лист товары».

Теперь рассмотрим случай, когда товар соответствует, но есть разногласия, например брак, разорванная упаковка или что то другое.

Будем учитывать такой товар в сущности «Перечень не принятого товара». Естественно, что он связан с накладной и с перечнем товаров по заявке.

Совершенно аналогично, что в перечне не принятого товара по заявке будут единицы не принятого товара (то есть, мы же не принимаем конкретные единицы). Например, они разбиты или у них истек срок годности…

Такие расхождения мы будем учитывать в сущности «Расхождения при поступлении», а названия таких расхождений будут храниться в справочнике «Расхождения».

На эти товары программно будет формироваться акт возврата.

Теперь посмотрим на ситуацию, когда в накладной присутствуют товары, которые мы не заказывали.

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

Ну и в общем то, все товары, которые нам нужно вернуть мы должны объединить в накладную на возврат. Для учета этой накладной у нас есть сущность «Накладная на возврат». Естественно, что в нее попадают товары из наших двух последних случаев.

Описательная характеристика нашей информационно-логической модели данных окончена. Давайте теперь перейдем к построению физической модели данных.

Далее на основе логической модели данных создается физическая модель.

Физическая модель базы данных отличается от логической тем, что она выполнена по правилам той СУБД, для которой эта база данных создается. Но физическая модель — это все же еще модель, а не сама база данных. А вот уже из физической модели мы создадим саму базу данных. Но это будет чуть дальше, а пока разберем нашу физическую модель данных.

Выберем для построения физической модели данных СУБД MySQL. Я буду делать на версии 8.0.28, но для всех остальных версий никакой принципиальной разницы не будет.

Я выбрал серверную СУБД, так как считаю выбор настольных СУБД (таких как MS Access) не совсем подходящих под эту задачу. Скорее всего, пользователей будет много и настольная СУБД здесь не подойдет. Название таблиц и поля физической модели данных я давал русскими именами, так как MySQL прекрасно работает с кириллицей. Исключением только является имя базы данных. Имя самой базы данных лучше задать латинскими буквами, так как имя, заданное кириллицей может вызвать проблемы при импорте базы данных с помощью Workbench. Больше никаких ограничений нет.

Физическая модель данных поликлиники

Структура таблицы «Корпуса»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_корпусаКод корпусаINTEGER11СчетчикУникальное, Not NullPK
НомерНомер корпусаINTEGER2Not Null
АдресАдрес корпусаVARCHAR255Not Null

Структура таблицы «Отделения»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_отделенияКод отделенияINTEGER11СчетчикУникальное, Not NullPK
Код_корпусаКод корпусаINTEGER11Not NullFK
ОтделениеНазвание отделенияVARCHAR100Not Null

Структура таблицы «Кабинеты»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_кабинетаКод кабинетаINTEGER11СчетчикУникальное, Not NullPK
Код_отделенияКод отделенияINTEGER11Not NullFK
КабинетНомер кабинетаVARCHAR3Not Null
НазваниеНазвание кабинетаVARCHAR100

Структура таблицы «Группы_анализов»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_группыКод группыINTEGER11СчетчикУникальное, Not NullPK
ГруппаНазвание группы анализовVARCHAR100Not Null

Структура таблицы «Анализы»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_анализаКод анализаINTEGER11СчетчикУникальное, Not NullPK
Код_группыКод группыINTEGER11Not NullFK
АнализНазвание анализаVARCHAR255Not Null
Минимальное_значение_ММинимальное значение анализа для мужчинDECIMAL10,2Not Null
Максимальное_значение_ММаксимальное значение анализа для мужчинDECIMAL10,2Not Null
Минимальное_значение_ЖМинимальное значение анализа для женщинDECIMAL10,2Not Null
Максимальное_значение_ЖМаксимальное значение анализа для женщинDECIMAL10,2Not Null

Структура таблицы «Карты»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_картыКод картыINTEGER11СчетчикУникальное, Not NullPK
ФИОФИО пациентаVARCHAR45Not Null
Дата_рожденияДата рожденияDATENot Null
ПолПол (М/Ж)VARCHAR1Not Null
СНИЛССНИЛСVARCHAR14Not Null
ПаспортПаспортные данныеVARCHAR255Not Null
АдресАдрес по пропискеVARCHAR255Not Null
ТелефонНомер телефона в формате +7 (999) 999-99-99VARCHAR18

Структура таблицы «Обращения»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_обращенияКод обращенияINTEGER11СчетчикУникальное, Not NullPK
Код_картыКод картыVARCHAR11Not NullFK
ЖалобаЖалоба пациента при обращенииDATENot Null
СтатусСтатус (открыто/закрыто)VARCHAR7Not Null

Структура таблицы «Группы_должностей»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_группыКод группыINTEGER11СчетчикУникальное, Not NullPK
ГруппаГруппаVARCHAR100Not Null

Структура таблицы «Должности»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_должностиКод должностиINTEGER11СчетчикУникальное, Not NullPK
Код_группыКод группыINTEGER11Not NullFK
ДолжностьНазвание должностиVARCHAR100Not Null
СтатусСтатус (действующая/не действующая)VARCHAR14Not Null

Структура таблицы «Пользователи»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_пользователяКод пользователяINTEGER11СчетчикУникальное, Not NullPK
ФИОФИО пользователя программыVARCHAR45Not Null
Дата_рожденияДата рождения пользователяDATE100Not Null
ПаспортПаспортные данные пользователяVARCHAR255Not Null
СтатусСтатус (действующая/не действующая)VARCHAR14Not Null
ЛогинЛогин учетной записиVARCHAR45Not Null
ПарольПароль от учетной записиVARCHAR45

Структура таблицы «Телефоны»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_телефонаКод должностиINTEGER11СчетчикУникальное, Not NullPK
Код_группыКод группыINTEGER11Not NullFK
ДолжностьНазвание должностиVARCHAR100Not Null
СтатусСтатус (действующая/не действующая)VARCHAR14Not Null

Структура таблицы «Сотрудники»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_сотрудникаКод сотрудникаINTEGER11СчетчикУникальное, Not NullPK
Код_должностиКод должностиINTEGER11Not NullFK
Код_пользователяКод пользователяINTEGER11Not NullFK
Дата_назначенияДата назначения пользователя на должностьDATENot Null
Дата_увольненияДата увольненияDATE
СтатусСтатус (работает/уволен)VARCHAR8Not Null

Структура таблицы «Роли»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_ролиКод ролиINTEGER11СчетчикУникальное, Not NullPK
РольНазвание роли (администратор, главный врач, заместитель главного врача, работник регистратуры, доктор, менеджер склада, кассир)VARCHAR100Not Null

Структура таблицы «Открытые_роли»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_открытой_ролиКод открытой ролиINTEGER11СчетчикУникальное, Not NullPK
Код_ролиКод ролиINTEGER11Not NullFK
Код_сотрудникаКод сотрудникаINTEGER11Not NullFK
СтатусСтатус (действующая/не действующая)VARCHAR14Not Null

Структура таблицы «Приемный_кабинет»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_приемного_кабинетаКод открытой ролиINTEGER11СчетчикУникальное, Not NullPK
Код_кабинетаКод ролиINTEGER11Not NullFK
Код_должностиКод сотрудникаINTEGER11Not NullFK
СтатусСтатус (действует/не действует)VARCHAR12Not Null

Структура таблицы «Расписание»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_расписанияКод расписанияINTEGER11СчетчикУникальное, Not NullPK
Код_приемного_кабинетаКод приемного кабинетаINTEGER11Not NullFK
Код_сотрудникаКод сотрудника, для которого составляется расписаниеINTEGER11Not NullFK
ДатаДата приемаDATENot Null
ВремяВремя приемаTIMENot Null
СтатусСтатус (занято/свободно)VARCHAR8Not Null

Структура таблицы «Запись_на_прием»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_записиКод записиINTEGER11СчетчикУникальное, Not NullPK
Код_обращенияКод обращенияINTEGER11Not NullFK
Код_расписанияКод расписанияINTEGER11Not NullFK

Структура таблицы «Диагнозы»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_диагнозаКод диагнозаINTEGER11СчетчикУникальное, Not NullPK
Код_обращенияКод обращенияINTEGER11Not NullFK
Код_записиКод записиINTEGER11Not NullFK
ДиагнозНазвание диагнозаVARCHAR255Not Null
ПримечаниеПримечаниеVARCHAR255

Структура таблицы «Лечение»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_леченияКод леченияINTEGER11СчетчикУникальное, Not NullPK
Код_диагнозаКод диагнозаINTEGER11Not NullFK
Код_записиКод записиINTEGER11Not NullFK
ЛечениеНазначенное лечениеLONGTEXTNot Null
РезультатРезультат леченияVARCHAR255

Структура таблицы «Анализы_пациентов»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_анализа_пациентаКод анализа пациентаINTEGER11СчетчикУникальное, Not NullPK
Код_анализаКод анализаINTEGER11Not NullFK
Код_обращенияКод обращенияINTEGER11Not NullFK
Код_записи_врача_назначившего_анализКод записи врача, назначившего анализINTEGER11Not NullFK
Код_записи_лаборанта_добавившего_результат_анализаКод записи лаборанта, добавившего результат анализаINTEGER11Not NullFK
ДатаДата записи лаборантом показателя анализаDATE
ПоказательПоказатель анализаDECIMAL10,2
СтатусСтатус (норма/отклонение)VARCHAR10

Структура таблицы «Поставщики»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_поставщикаКод поставщикаINTEGER11СчетчикУникальное, Not NullPK
Полное_наименованиеПолное название организации поставщикаVARCHAR100Not Null
Краткое_наименованиеКраткое название организации поставщикаVARCHAR40Not Null
ФИО_руководителяФИО руководителяVARCHAR45Not Null
АдресАдресVARCHAR255Not Null
ИННИННVARCHAR10
КППКППVARCHAR9
ОГРНОГРНVARCHAR13
ПримечаниеПримечаниеVARCHAR255
СайтСайт организацииVARCHAR70

Структура таблицы «Контакты»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_контактаКод контактаINTEGER11СчетчикУникальное, Not NullPK
Код_поставщикаКод поставщикаINTEGER11Not NullFK
ФИОФИО контактного лицаVARCHAR45Not Null
ДолжностьДолжностьVARCHAR100
ТелефонТелефонVARCHAR18
E_mailадрес электронной почты контактного лицаVARCHAR70

Структура таблицы «Заявки»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_заявкиКод заявкиINTEGER11СчетчикУникальное, Not NullPK
Код_поставщикаКод поставщика, которому составляется заявкаINTEGER11Not NullFK
Код_сотрудникаКод сотрудника, составлявшего заявкуINTEGER11Not NullFK
НомерНомер заявкиINTEGER11Not Null
ДатаДата заявкиDATENot Null

Структура таблицы «Поставщики»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_поставщикаКод поставщикаINTEGER11СчетчикУникальное, Not NullPK
Полное_наименованиеПолное название организации поставщикаVARCHAR100Not Null

Структура таблицы «Приходная_накладная»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_накладнойКод накладнойINTEGER11СчетчикУникальное, Not NullPK
Код_заявкиКод заявки, по которой поступила накладнаяINTEGER11Not NullFK
Код_сотрудникаКод сотрудника, которые принимает товары по накладнойINTEGER11Not NullFK
НомерНомер накладнойVARCHAR20Not Null
ДатаДата накладнойDATENot Null
СтатусСтатус (полная/частичная/не соответствует)VARCHAR9Not Null

Поле «Статус» может иметь одно из трех значений (Полная/Частичная/Не соответствует):

  • Полноная — это когда все товары привезли, которые заказывали;
  • Частичная — когда часть товаров. То есть, одну заявку можно разбить на несоклько накладных с разным привозом;
  • Не соответствует — когда в накладной присутствует любое несоответствие товара/порча/явный визуальный брак и т.п.

Структура таблицы «Накладная_на_возврат»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_накладнойКод накладной на возвратINTEGER11СчетчикУникальное, Not NullPK
Код_сотрудникаКод сотрудника, оформляющего возвратINTEGER11Not NullFK
НомерНомер накладной на возвратVARCHAR20Not Null
ДатаДата накладной на возвратDATENot Null

Структура таблицы «Перечень_товаров_отсутствующих_в_заявке»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_товара_отсутствующего_в_заявкеКод товара, отсутствующего в заявкеINTEGER11СчетчикУникальное, Not NullPK
Код_накладной_на_возвратКод накладной на возвратINTEGER11Not NullFK
Код_приходной_накладнойКод приходной накладнойINTEGER11Not NullFK
ТоварНазвание возвращаемого товара (как в приходной накладной)VARCHAR100Not Null
КоличествоКоличество возвращаемого товараINTEGER11Not Null

Структура таблицы «Перечень_не_принятого_товара»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_не_принятого_товараКод не принятого товараINTEGER11СчетчикУникальное, Not NullPK
Код_накладнойКод приходной накладнойINTEGER11Not NullPK
Код_позиции_в_перечне_по_заявкеКод позиции в перечне по заявкеINTEGER11Not NullPK

Структура таблицы «Единицы_не_принятого_товара_по_заявке»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_единицы_товараКод единицы товараINTEGER11СчетчикУникальное, Not NullPK
Код_не_принятого_товараКод не принятого товараINTEGER11Not NullFK
Код_маркировкиКод маркировки товара (наносится производителем)VARCHAR83
Дата_изготовленияДата п роизводства товараDATENot Null
Дата_окончания_годностиДата окончания срока годности товараDATENot Null
Серийный_номерСерийный номер товараVARCHAR45
Номер_партииНомер партии выпуска товараVARCHAR45

Структура таблицы «Расхождения»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_расхожденияКод расходенияINTEGER11СчетчикУникальное, Not NullPK
РасхождениеНазвание расхожденияVARCHAR100Not Null

Структура таблицы «Расхождения_при_поступлении»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_расхождения_при_поступленииКод расхождения при поступленииINTEGER11СчетчикУникальное, Not NullPK
Код_расхожденияКод расхожденияINTEGER11Not NullFK
Код_единицы_товараКод единицы товара, у которого выявлено расхождениеINTEGER11Not NullFK

Структура таблицы «Перечень_накладной_на_возврат_товаров_по_заявке»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_позицииКод позицииINTEGER11СчетчикУникальное, Not NullPK
Код_накладнойКод накладной на возвратINTEGER11Not NullFK
Код_единицы_товараКод единицы не принятого товара по заявкеINTEGER11Not NullFK

Структура таблицы «Производители»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_производителяКод производителяINTEGER11СчетчикУникальное, Not NullPK
ПроизводительНазвание производителяVARCHAR100Not Null
АдресАдресVARCHAR255
ИННИННINTEGER10
КППКППINTEGER9
ОГРНОГРНINTEGER13

Структура таблицы «Единицы_измерения»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_единицы_измеренияКод единицы измеренияINTEGER11СчетчикУникальное, Not NullPK
Единица_измеренияНазвание единицы измеренияVARCHAR100Not Null

Структура таблицы «Группы_товаров»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_группыКод поставщикаINTEGER11СчетчикУникальное, Not NullPK
ГруппаПолное название организации поставщикаVARCHAR100Not Null

Структура таблицы «Товары»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_товараКод товараINTEGER11СчетчикУникальное, Not NullPK
Код_группыКод группыINTEGER11Not NullFK
Код_единицы_измеренияКод единицы измеренияINTEGER11Not NullFK
Код_производителяКод производителяINTEGER11Not NullFK
Номенклатурный_номерНоменклатурный номер (внутриорганизационный номенклатурный номер товара)INTEGER11Not Null
ТоварНазвание товараVARCHAR100Not Null
НазначениеНазначение товараLONGTEXT
Способ_применения_и_дозыСпособ применения и дозы (справедливо для лекарственных препаратов)LONGTEXT
ОписаниеОписание товараLONGTEXT

Структура таблицы «Изображения»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_изображенияКод изображенияINTEGER11СчетчикУникальное, Not NullPK
Код_товараКод товараINTEGER11Not NullFK
ИзображениеИзображение товараLONGBLOBNot Null

Структура таблицы «Каталог»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_артикулаКод артикулаINTEGER11СчетчикУникальное, Not NullPK
Код_поставщикаКод поставщикаINTEGER11Not NullFK
Код_товараКод товараINTEGER11Not NullFK
АртикулКаталожный артикул товараVARCHAR20Not Null

Структура таблицы «Цены»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_ценыКод ценыINTEGER11СчетчикУникальное, Not NullPK
Код_артикулаКод артикулаINTEGER11Not NullFK
ЦенаКаталожная цена товараDECIMAL10,2Not Null
Дата_установленияДата установления ценыDATENot Null

У каждого товара в разных каталогах одного и того же поставщика цена на товар может меняться, поэтому целесообразно иметь таблицу «Цены», где будет вестись учет текущих каталожных цен.

Структура таблицы «Перечень_товаров_по_заявке»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_позиции_в_перечне_по_заявкеКод позиции в перечне по заявкеINTEGER11СчетчикУникальное, Not NullPK
Код_заявкиКод заявкиINTEGER11Not NullFK
Код_ценыКод ценыINTEGER11Not NullFK
КоличествоКоличествоINTEGER11

В данной таблице поле «Количество» можно не заполнять, так как количество можно узнать по числу записей дочерней таблицы с соответствующим кодом позиции в перечне по заявке. Но я добавил это поле для того, чтобы все-таки было проще составлять запрос на выборку там, где фигурирует данная таблица.

Структура таблицы «Перечень_принятого_товара»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_принятого_товараКод принятого товараINTEGER11СчетчикУникальное, Not NullPK
Код_накладнойКод накладнойINTEGER11Not NullFK
Код_позиции_в_перечне_по_заявкеКод позиции в перечне по заявкеINTEGER11Not NullFK

Структура таблицы «Единицы_принятого_товара»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_единицы_товараКод единицы товараINTEGER11СчетчикУникальное, Not NullPK
Код_принятого_товараКод принятого товараINTEGER11Not NullFK
Код_маркировкиКод маркировкиVARCHAR83FK
Дата_изготовленияДата производства товараDATENot Null
Дата_окончания_годностиДата окончания срока годности товараDATENot Null
Серийный_номерСерийный номерVARCHAR45
Номер_партииНомер партииVARCHAR45
СтатусСтатус (продан/не продан)VARCHAR9

Поле «Статус» может содержать одно из двух значений — продан/не продан
Это поле удобно использовать для того, чтобы считать остаток по товару. То есть, можно выводить запросом все товары с нужным названием, у которых статус «Не продано». Причем здесь можно будет выводить остаток как по отдельным поступлениям конкретного товара, так и по всем поступлениям одного вида товара.

Структура таблицы «Продажи»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Номер_чекаНомер кассового чекаINTEGER11СчетчикУникальное, Not NullPK
Код_сотрудникаКод сотрудника, который продает товарINTEGER11Not NullFK
ДатаДата продажиDATENot Null

Структура таблицы «Цены_реализации»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_ценыКод ценыINTEGER11СчетчикУникальное, Not NullPK
Код_единицы_товараКод отдельной единицы товараINTEGER11Not NullFK
ЦенаЦена реализацииDECIMAL10,2Not Null
Дата_установленияДата установления ценыDATENot Null

Структура таблицы «Чек_лист_товары»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_позицииКод позиции в чекеINTEGER11СчетчикУникальное, Not NullPK
Код_ценыКод ценыINTEGER11Not NullFK
Номер_чекаНомер чекаINTEGER11Not NullFK

Структура таблицы «Группы_услуг»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_группыКод группы услугINTEGER11СчетчикУникальное, Not NullPK
ГруппаНазвание группы услугVARCHAR100Not Null

Структура таблицы «Услуги»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_услугиКод услугиINTEGER11СчетчикУникальное, Not NullPK
Код_группыКод группы услугINTEGER11Not NullFK
УслугаНазвание услугиVARCHAR100Not Null
ОписаниеОписание услугиLONGTEXT

Структура таблицы «Стоимость_услуг»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_стоимостиКод стоимостиINTEGER11СчетчикУникальное, Not NullPK
Код_услугиКод услугиINTEGER11Not NullFK
СтоимостьСтоимость услугиDECIMAL10,2Not Null
Дата_установленияДата установленияDATENot Null

Структура таблицы «Квитанции»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_квитанцииКод квитанцииINTEGER11СчетчикУникальное, Not NullPK
Код_сотрудникаКод сотрудника, сформировавшего квитанцию (код доктора)INTEGER11Not NullFK
Дата_формированияДата формирования квитанцииDATENot Null
Дата_оплатыДата оплаты квитанцииDATE
СтатусСтатус (оплачено/не оплачено)VARCHAR11Not Null

Структура таблицы «Чек_лист_услуги»

Идентификатор поляНаименование поляТип поляРазмерЗначение по умолчаниюУсловие на значениеКлюч
Код_поцизииКод позицииINTEGER11СчетчикУникальное, Not NullPK
Код_квитанцииКод квитанцииINTEGER11Not NullFK
Код_стоимостиКод стоимостиINTEGER11Not NullFK

Итак, мы разработали физическую модель базы данных. Этап проектирования мы закончили. Теперь давайте на примере пары таблиц рассмотрим, как создать базу данных нашей поликлиники с использованием нашей физической модели.

Создание базы данных поликлиники

Итак, открываем с вами Workbench и выбираем команду File/New Model. Далее мы меняем имя нашей схемы данных (в MySQL база данных называется схемой), например, на clinic. Регистр значения не имеет.

Далее создаем все перечисленные 50 таблиц, опираясь на нашу вышеописанную физическую модель данных. Создадим, например, таблицу «Анализы». Заполните все поля, как указано ниже на рисунке, используя при этом данные физической модели данных. Для этого закрываем эту вкладку и нажимаем Add Table, чтобы создать первую таблицу.

Аббревиатуры:
— PK — признак первичного ключа для поля;
— NN — поле не может быть пустым;
— AI — поле будет автоинкрементным. Используется совместно с первичным ключом.

Теперь перейдем на вкладку Foreign Keys для того, чтобы задать внешний ключ для нашей таблицы. Внешний ключ — это поле, которое будет соединять нашу таблицу с родительской. Из логической схемы данных мы помним, что таблица «Анализы» является дочерней по отношению к таблице «Группы анализов». Из этого следует, что наш внешний ключ должен указывать на первичный ключ таблицы «Группы анализов».

В столбце Foreign Key Name мы укажем имя нашего внешнего ключа. Мне нравится называть внешние ключи с использованием названий двух таблиц. Например, здесь я объединяю две таблицы «Группы анализов» и «Анализы» и поэтому свой ключ я называю «Группы_Анализы». Можно было бы назвать как «ГруппыАнализов_Анализы». Ну просто MySQL покажет вам ошибку при создании самой базы данных, если название ключа окажется слишком длинным.

В столбце Reference Table указываем таблицу, на которую ссылается наш внешний ключ. Это у нас таблица «Группы анализов». Выбираем ее из списка. А справа у нас появляются два столбца. В левом из них представлены поля таблицы «Анализы», а в правом лишь одно поле первичного ключа из таблицы «Группы анализов». Это поле нужно выбрать из списка.

Стоит еще установить триггеры для этой таблицы, которые будут срабатывать при обновлении у удалении данных из родительской таблицы. Установим значение Cascade. Это значит, что при удалении данных из родительской таблицы, будут удалены соответствующие данные и из дочерней таблицы. То есть, если мы удалим группу из таблицы «Группы анализов», то из дочерней таблицы «Анализы» будут удалены все анализы, которые входили в удаленную группу. Тоже самое и с обновлением данных.

Все остальные таблицы создаем по данному примеру, используя логическую и физическую модели данных. Затем будет удобно создать EER-диаграмму для наших таблиц. Это тоже самое, что мы делали в логической модели данных, так сказать, на бумаге, только теперь это будет в системе Workbench. Для этого нажмите на EER Diagram.

В новом появившемся окне сразу нужно выбрать команду Model / Diagram Properties And Size для того, чтобы задать высоту и ширину поля диаграммы в листах. Сделайте сразу 3 на 3 листа, потому что диаграмма будет большой.

После этого все созданные таблицы следует перетащить на пустой лист диаграммы и на этом листе таблицы отобразятся уже со связями.

Последним шагом в создании базы данных будет являться генерирование скрипта база данных. Скрипт представляет из себя команды языка SQL, которые создают нашу базу данных на основе только что созданных таблиц в Workbench.

Ну то есть, Workbench — это визуальный редактор базы данных. Чтобы нам руками в текстовом файле не писать большое количество команд, за нас это сделает Workbench. Мы лишь создали в нем в визуальном режиме таблицы, а скрипт сгенерируем командой: File/Export/Forward Engineer SQL Create Script.

Укажите папку, куда вы хотите сохранить скрипт и жмите до конца Next, пока не сгенерируется скрипт в указанной папке.

Теперь в Workbench откройте соединение и запустите этот скрипт и вы получите базе данных у себя на компьютере.

Кстати говоря, наша схема данных может быть значительно сокращена. Например, если вам не нужен учет оказанных услуг или учет продаж товаров, то вы легко можете удалить эти таблицы из схемы данных, ну либо просто не использовать эти таблицы в программе.

Создание базы данных поликлиники — это трудоемкий процесс и, если вы не хотите тратить время на это, то вы можете скачать уже готовый скрипт по ссылке ниже.

Скачать готовую базу данных поликлиники (больницы)

Скрипт модели базы данных поликлиники в формате MySQL

Данный скрипт получен на основе модели базы данных поликлиники, спроектированный в MySQL Workbench и экспортированный в формат файла .sql. Вы можете запустить этот скрипт на выполнение, например, в той же среде MySQL Workbench для того, чтобы из этого скрипта сгенерировалась база данных на вашем жестком диске или просто импортировать его на свой компьютер.

Скачать скрипт базы данных поликлиники в формате MySQL

База данных поликлиники (больницы) в формате MS Access

Скачать базу данных поликлиники в формате MS Access (формат будет доступен чуть позже).

Читайте также:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *