med-cms 1.0.0-beta.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/LICENSE.txt +13 -0
  2. package/README.md +117 -0
  3. package/database/config/db-init.js +67 -53
  4. package/database/models/appointments.js +35 -20
  5. package/database/models/clinics.js +25 -13
  6. package/database/models/diseases.js +21 -13
  7. package/database/models/districts.js +55 -0
  8. package/database/models/news.js +25 -0
  9. package/database/models/user-addresses.js +21 -14
  10. package/database/models/users.js +69 -26
  11. package/database/services/admin/create-clinic.js +18 -6
  12. package/database/services/admin/db-analytics.js +42 -16
  13. package/database/services/admin/index.js +6 -6
  14. package/database/services/admin/manage-staff.js +47 -17
  15. package/database/services/doctor/conduct-exam.js +26 -20
  16. package/database/services/doctor/get-schedule.js +26 -18
  17. package/database/services/doctor/index.js +6 -6
  18. package/database/services/doctor/patient-access.js +34 -25
  19. package/database/services/patient/book-appointment.js +37 -17
  20. package/database/services/patient/calc-district.js +70 -21
  21. package/database/services/patient/get-profile.js +49 -21
  22. package/database/services/patient/index.js +5 -5
  23. package/env_init.js +55 -0
  24. package/index.d.ts +38 -24
  25. package/index.js +48 -25
  26. package/migrate-diseases.js +192 -120
  27. package/package.json +3 -3
  28. package/public/css/admin.css +80 -80
  29. package/public/css/auth.css +52 -44
  30. package/public/css/doctor.css +131 -125
  31. package/public/css/home.css +155 -0
  32. package/public/html/dashboard-admin.html +423 -101
  33. package/public/html/dashboard-doctor.html +155 -66
  34. package/public/html/dashboard-patient.html +199 -94
  35. package/public/html/home/about.html +0 -0
  36. package/public/html/home/contact.html +0 -0
  37. package/public/html/home/info.html +0 -0
  38. package/public/html/home.html +159 -0
  39. package/public/html/login.html +73 -43
  40. package/public/js/admin.js +329 -165
  41. package/public/js/auth.js +45 -41
  42. package/public/js/doctor.js +117 -103
  43. package/public/js/home.js +113 -0
  44. package/public/js/patient.js +130 -108
  45. package/server/midleware.js +33 -13
  46. package/server/permissions.js +105 -43
  47. package/server/server.js +517 -176
  48. package/README +0 -161
  49. package/test.js +0 -27
package/LICENSE.txt ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2026 RPM-programmer (github) / prm-programmer (npmjs)
2
+
3
+ Permission to use, copy, modify, and/or distribute this software for any purpose with or
4
+ without fee is hereby granted, provided that the above copyright notice and this permission
5
+ notice appear in all copies.
6
+
7
+ THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
13
+ IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,117 @@
1
+ # MED-CMS (v1.0.0)
2
+
3
+ > ## `med-cms` — Это автономный медецинский движок для управления сетями клиник, персоналом и расписание приймов и т.д. Написан `med-cms` на node.js с использованием **express**, **sequelize**
4
+
5
+ ### Модуль поставляется со встроенной базой данных, системой разграничения прав доступа на основе **34 медицинских специальностей** и готовым веб-интерфейсом (АРМ Врача, Личный Кабинет Пациента, Панель Суперадминистратора), а также готовой главной страницей
6
+
7
+ ---
8
+
9
+ ## Ключевые возможности
10
+
11
+ - **Автономность** База данных SQLite3 не требует установки тяжелых серверов (PostgreSQL/MySQL/MongoDB). Файл БД и таблицы создаются автоматически прямо в папке проекта.
12
+ - **Безопасность и Сессии:** Авторизация реализована через зашифрованные JWT-токены, хранящиеся в защищенных **HttpOnly Cookie**. JS на клиенте не имеет доступа к токену.
13
+ - **Матрица прав доступа (34 специальности):** Гибкое разграничение возможностей врачей. Стоматолог или Эндокринолог не смогут получить доступ к эндпоинтам назначения нейрохирургических операций — то-есть не к своим данным
14
+ - **Автоматический расчет участков:** При регистрации или изменении адреса проживания пациента система сама вычисляет номер его терапевтического участка и закрепленный кабинет врача. Участки настраиваются админом.
15
+ - **Статистика болезней и МКБ-10:** Выделенный независимый справочник заболеваний в базе данных с возможностью автономной миграции и автоматическим инкрементом счетчиков заболеваемости при закрытии приемов врачами.
16
+ - **Возможность управлять новостями** А админ панеле есть форма позволяющая выкладывать новости.
17
+ - **Автозапись в `.env`** При запуске проекта код проверяет есть ли `.env` и настройки в нём, если то записывает настройки в него.
18
+
19
+ ---
20
+
21
+ ## Установка и быстрая настройка
22
+
23
+ ### 1. Установка модуля
24
+
25
+ #### Установите пакет в ваше Node.js приложение:
26
+
27
+ ```bash
28
+ npm install med-cms
29
+ # или
30
+ yarn add med-cms
31
+ ```
32
+
33
+ > **Важно для пользователей Linux:** Пакетам `sequelize` и `sqlite3` иногда требуются компиляторы C++ для сборки бинарных файлов под вашу архитектуру ядра. Перед развертыванием убедитесь, что в системе установлены базовые утилиты сборки:
34
+ >
35
+ > ```bash
36
+ > sudo apt update && sudo apt install -y build-essential python3
37
+ > ```
38
+
39
+ ### 2. Подключение в Express
40
+
41
+ #### Для интеграции CMS в ваш Express-сервер импортируйте функцию инициализации и передайте туда ваш инстанс `app`:
42
+
43
+ ```javascript
44
+ const express = require("express");
45
+ require("dotenv").config();
46
+
47
+ const app = express();
48
+
49
+ // Импортируем инициализатор нашего npm-модуля
50
+ const MI = require("med-cms");
51
+
52
+ // здесь ваши роуты ...
53
+ app.get("/", async (req, res) => {
54
+ res.end("HELLO!");
55
+ });
56
+
57
+ (async function startServer() {
58
+ // Запускаем медицинский движок med-cms
59
+ // требуется асинхронность из-за запросов в к бд
60
+ await MI(app);
61
+
62
+ app.listen(3000, () => {
63
+ console.log(`Сервер успешно запущен!`);
64
+ });
65
+ })();
66
+ ```
67
+
68
+ ---
69
+
70
+ ## Миграция расширенного справочника болезней (РБ)
71
+
72
+ ### Справочник заболеваний полностью изолирован от кода ядра CMS. Для наполнения пустой таблицы `Diseases` актуальными и социально значимыми кодами МКБ-10 для Республики Беларусь, запустите команду миграции перед стартом основного сервера:
73
+
74
+ ```bash
75
+ node node_modules/med-cms/migrate-diseases.js
76
+ # или
77
+ node node_modules\med-cms\migrate-diseases.js
78
+ ```
79
+
80
+ ### Это наполнит отдельную таблицу базы данных 18 распространенными диагнозами (ОРВИ, Острый бронхит, Внебольничная пневмония, Артериальная гипертензия, Остеохондроз, Эндемический зоб и др.), которые автоматически начнут подтягиваться в HTML-тег `<select>` на рабочем месте врача.
81
+
82
+ ---
83
+
84
+ ## Роли и Маршрутизация (API & Web)
85
+
86
+ ### Архитектура роутера жестко разделяет отдачу интерфейсов и данных, исключая ошибки парсинга `JSON.parse` в браузере:
87
+
88
+ - **Интерфейс (Web-страницы):** `http://localhost:3000/med/...`
89
+ - **Данные (JSON API):** `http://localhost:3000/med/api/...`
90
+
91
+ ### Матрица маршрутов
92
+
93
+ | Действие | Метод | Маршрут (URL) | Доступ (Роль) |
94
+ | :--------------------------- | :---- | :---------------------------------------- | :------------ |
95
+ | Страница авторизации и входа | `GET` | `/med/html/login.html` (или `/med/login`) | Публичный |
96
+ | Главная страница | `GET` | `/med/html/home.html` (или `/med/home`) | Публичный |
97
+
98
+ ---
99
+
100
+ ### Алгоритм проведения инициялизации:
101
+
102
+ 1. Выполните миграцию справочника болезней: `node node_modules/med-cms/migrate-diseases.js` или `node node_modules\med-cms\migrate-diseases.js`.
103
+ 2. Откройте браузер на `http://localhost:3000/med/home` и нажмите на кнопку **`вход`**.
104
+ 3. Авторизируйтесь (заполните поля почты и пароля) (данные можно узнать в настройках `.env`)
105
+ 4. В левой форме добавьте поликлинику. Она запишется в SQLite под числовым `ID: 1`.
106
+ 5. Кликните на карточку «Всего клиник», чтобы развернуть интерактивную таблицу и проверить числовой ID.
107
+ 6. В правой форме зарегистрируйте аккаунт врача, выбрав созданную поликлинику №1 из выпадающего списка.
108
+ 7. Выйдите из админки, нажмите «Зарегистрироваться как пациент» и создайте профиль.
109
+ 8. В кабинете пациента выберите созданного врача, дату, время и нажмите **«Забронировать талон»**. Талон мгновенно отобразится в блоке предстоящих приемов.
110
+ 9. Авторизуйтесь под созданным врачом. Пациент появится в вашей очереди. Нажмите «Принять», заполните жалобы, выберите из подгрузившегося справочника диагноз _«Острый бронхит»_ и закройте прием. Системные счетчики зафиксируют визит, а статистика болезни обновится в SQLite.
111
+ 10. Также можете с аккаунта админа настроить участки и новости!
112
+
113
+ ---
114
+
115
+ ## Лицензия
116
+
117
+ ### Проект распространяется на условиях открытой лицензии [**ISC**](LICENSE.txt). Разработано [RPM-programmer](https://github.com/RPM-programmer/) для создания масштабируемых и отказоустойчивых медицинских информационных систем.
@@ -1,88 +1,102 @@
1
- const { Sequelize, DataTypes } = require('sequelize');
2
- const path = require('path');
1
+ // Полностью рабочий database/config/db-init.js с динамическим расширением модели
2
+
3
+ const { Sequelize, DataTypes } = require("sequelize");
4
+ const path = require("path");
3
5
  const logger = require("custom-color-logs").print;
4
6
 
5
7
  let sequelize;
6
8
 
7
9
  function getSequelizeInstance(dbPath) {
8
10
  if (!sequelize) {
9
- const storagePath = dbPath || path.join(process.cwd(), 'med-cms.sqlite');
11
+ const storagePath = dbPath || path.join(process.cwd(), "med-cms.sqlite");
10
12
  sequelize = new Sequelize({
11
- dialect: 'sqlite',
13
+ dialect: "sqlite",
12
14
  storage: storagePath,
13
- logging: false
15
+ logging: false,
14
16
  });
15
17
  }
16
18
  return sequelize;
17
19
  }
18
20
 
19
- async function initDatabase(dbPath) {
20
- const instance = getSequelizeInstance(dbPath);
21
-
22
- try {
23
- await instance.authenticate();
24
- console.log(logger.DatabaseMedInfo("Успешное подключение к SQLite через Sequelize."));
25
-
26
- // 1. Импортируем функции моделей и сразу инициализируем их инстансом sequelize
27
- const models = {
28
- Clinic: require(path.join(__dirname, '..', 'models', 'clinics'))(instance, DataTypes),
29
- User: require(path.join(__dirname, '..', 'models', 'users'))(instance, DataTypes),
30
- UserAddress: require(path.join(__dirname, '..', 'models', 'user-addresses'))(instance, DataTypes),
31
- Disease: require(path.join(__dirname, '..', 'models', 'diseases'))(instance, DataTypes),
32
- Appointment: require(path.join(__dirname, '..', 'models', 'appointments'))(instance, DataTypes)
33
- };
34
-
35
- // 2. Автоматически запускаем связи, которые мы прописали внутри файлов таблиц
36
- Object.keys(models).forEach((modelName) => {
37
- if (models[modelName].associate) {
38
- models[modelName].associate(models);
39
- }
40
- });
41
-
42
- await instance.sync({ alter: true });
43
- console.log(logger.DatabaseMedInfo("Все таблицы базы данных успешно синхронизированы."));
44
- } catch (error) {
45
- console.log(logger.DatabaseMedError('Ошибка инициализации базы данных:', error));
46
- throw error;
47
- }
48
- }
49
-
50
- // В самом конце вашего database/config/db-init.js вместо старого exports:
51
-
52
21
  const db = {
53
22
  getSequelizeInstance,
54
23
  initDatabase,
55
- get sequelize() { return sequelize; },
56
- // Динамически прокидываем модели наружу, чтобы они были доступны как db.User, db.Clinic и т.д.
57
- models: {}
24
+ get sequelize() {
25
+ return sequelize;
26
+ },
27
+ models: {},
58
28
  };
59
29
 
60
- // Перепишем функцию initDatabase, чтобы она сохраняла модели в db.models и самом объекте db
61
30
  async function initDatabase(dbPath) {
62
31
  const instance = getSequelizeInstance(dbPath);
63
-
32
+
64
33
  try {
65
34
  await instance.authenticate();
66
- console.log(logger.DatabaseMedInfo("Успешное подключение к SQLite через Sequelize."));
35
+ console.log(
36
+ logger.DatabaseMedInfo("Успешное подключение к SQLite через Sequelize."),
37
+ );
38
+
39
+ // 1. Инициализируем базовые модели из фабрик
40
+ db.models.Clinic = db.Clinic = require(
41
+ path.join(__dirname, "..", "models", "clinics"),
42
+ )(instance, DataTypes);
43
+ db.models.User = db.User = require(
44
+ path.join(__dirname, "..", "models", "users"),
45
+ )(instance, DataTypes);
46
+ db.models.UserAddress = db.UserAddress = require(
47
+ path.join(__dirname, "..", "models", "user-addresses"),
48
+ )(instance, DataTypes);
49
+ db.models.Disease = db.Disease = require(
50
+ path.join(__dirname, "..", "models", "diseases"),
51
+ )(instance, DataTypes);
52
+ db.models.Appointment = db.Appointment = require(
53
+ path.join(__dirname, "..", "models", "appointments"),
54
+ )(instance, DataTypes);
55
+ db.models.District = db.District = require(
56
+ path.join(__dirname, "..", "models", "districts"),
57
+ )(instance, DataTypes);
58
+ db.models.News = db.News = require(
59
+ path.join(__dirname, "..", "models", "news"),
60
+ )(instance, DataTypes);
61
+ // =========================================================================
62
+ // 🔥 ДИНАМИЧЕСКИЙ ХАК: Расширяем модель User прямо в памяти до синхронизации!
63
+ // =========================================================================
64
+
65
+ // А) Принудительно внедряем колонку должностей (position), которой нет в файле
66
+ db.User.rawAttributes.position = {
67
+ type: DataTypes.STRING,
68
+ allowNull: true,
69
+ defaultValue: "Пациент",
70
+ };
71
+ db.User.refreshAttributes(); // Заставляем Sequelize пересобрать схему модели
72
+
73
+ // Б) Снимаем жесткие ограничения ENUM с поля specialty, превращая его в гибкую строку
74
+ db.User.rawAttributes.specialty = {
75
+ type: DataTypes.STRING,
76
+ allowNull: true,
77
+ };
78
+ db.User.refreshAttributes(); // Синхронизируем изменения атрибутов
67
79
 
68
- // Инициализируем и сохраняем в объект
69
- db.models.Clinic = db.Clinic = require(path.join(__dirname, '..', 'models', 'clinics'))(instance, DataTypes);
70
- db.models.User = db.User = require(path.join(__dirname, '..', 'models', 'users'))(instance, DataTypes);
71
- db.models.UserAddress = db.UserAddress = require(path.join(__dirname, '..', 'models', 'user-addresses'))(instance, DataTypes);
72
- db.models.Disease = db.Disease = require(path.join(__dirname, '..', 'models', 'diseases'))(instance, DataTypes);
73
- db.models.Appointment = db.Appointment = require(path.join(__dirname, '..', 'models', 'appointments'))(instance, DataTypes);
80
+ // =========================================================================
74
81
 
75
- // Запускаем связи
82
+ // 2. Безопасно запускаем связи (Associations) между всеми таблицами
76
83
  Object.keys(db.models).forEach((modelName) => {
77
84
  if (db.models[modelName].associate) {
78
85
  db.models[modelName].associate(db.models);
79
86
  }
80
87
  });
81
88
 
89
+ // 3. Синхронизируем базу данных с учётом динамически добавленных полей
82
90
  await instance.sync({ alter: true });
83
- console.log(logger.DatabaseMedInfo("Все таблицы базы данных успешно синхронизированы."));
91
+ console.log(
92
+ logger.DatabaseMedInfo(
93
+ "Все таблицы базы данных успешно синхронизированы.",
94
+ ),
95
+ );
84
96
  } catch (error) {
85
- console.log(logger.DatabaseMedError('Ошибка инициализации базы данных:', error));
97
+ console.log(
98
+ logger.DatabaseMedError("Ошибка инициализации базы данных:", error),
99
+ );
86
100
  throw error;
87
101
  }
88
102
  }
@@ -1,28 +1,43 @@
1
1
  module.exports = (sequelize, DataTypes) => {
2
- const Appointment = sequelize.define('Appointment', {
3
- id: {
4
- type: DataTypes.UUID,
5
- defaultValue: DataTypes.UUIDV4,
6
- primaryKey: true
2
+ const Appointment = sequelize.define(
3
+ "Appointment",
4
+ {
5
+ id: {
6
+ type: DataTypes.UUID,
7
+ defaultValue: DataTypes.UUIDV4,
8
+ primaryKey: true,
9
+ },
10
+ date: { type: DataTypes.DATEONLY, allowNull: false },
11
+ time: { type: DataTypes.STRING, allowNull: false },
12
+ status: {
13
+ type: DataTypes.ENUM("ожидается", "завершен", "отменен"),
14
+ defaultValue: "ожидается",
15
+ allowNull: false,
16
+ },
17
+ complaints: { type: DataTypes.TEXT, allowNull: true },
18
+ objectively: { type: DataTypes.TEXT, allowNull: true },
19
+ doctorNotes: { type: DataTypes.TEXT, allowNull: true },
7
20
  },
8
- date: { type: DataTypes.DATEONLY, allowNull: false },
9
- time: { type: DataTypes.STRING, allowNull: false },
10
- status: {
11
- type: DataTypes.ENUM('ожидается', 'завершен', 'отменен'),
12
- defaultValue: 'ожидается',
13
- allowNull: false
21
+ {
22
+ timestamps: true,
14
23
  },
15
- complaints: { type: DataTypes.TEXT, allowNull: true },
16
- objectively: { type: DataTypes.TEXT, allowNull: true },
17
- doctorNotes: { type: DataTypes.TEXT, allowNull: true }
18
- }, {
19
- timestamps: true
20
- });
24
+ );
21
25
 
22
26
  Appointment.associate = (models) => {
23
- Appointment.belongsTo(models.User, { as: 'Patient', foreignKey: 'PatientId', onDelete: 'CASCADE' });
24
- Appointment.belongsTo(models.User, { as: 'Doctor', foreignKey: 'DoctorId', onDelete: 'CASCADE' });
25
- Appointment.belongsTo(models.Disease, { foreignKey: 'DiseaseId', onDelete: 'SET NULL' });
27
+ Appointment.belongsTo(models.User, {
28
+ as: "Patient",
29
+ foreignKey: "PatientId",
30
+ onDelete: "CASCADE",
31
+ });
32
+ Appointment.belongsTo(models.User, {
33
+ as: "Doctor",
34
+ foreignKey: "DoctorId",
35
+ onDelete: "CASCADE",
36
+ });
37
+ Appointment.belongsTo(models.Disease, {
38
+ foreignKey: "DiseaseId",
39
+ onDelete: "SET NULL",
40
+ });
26
41
  };
27
42
 
28
43
  return Appointment;
@@ -1,21 +1,33 @@
1
1
  module.exports = (sequelize, DataTypes) => {
2
- const Clinic = sequelize.define('Clinic', {
3
- id: {
4
- type: DataTypes.INTEGER,
5
- autoIncrement: true,
6
- primaryKey: true
2
+ const Clinic = sequelize.define(
3
+ "Clinic",
4
+ {
5
+ id: {
6
+ type: DataTypes.INTEGER,
7
+ autoIncrement: true,
8
+ primaryKey: true,
9
+ },
10
+ name: { type: DataTypes.STRING, allowNull: false, unique: true },
11
+ type: {
12
+ type: DataTypes.ENUM(
13
+ "больница",
14
+ "поликлиника",
15
+ "станция скорой помощи",
16
+ "частный медицинский центр",
17
+ ),
18
+ allowNull: false,
19
+ },
20
+ address: { type: DataTypes.STRING, allowNull: false },
21
+ phone: { type: DataTypes.STRING, allowNull: true },
7
22
  },
8
- name: { type: DataTypes.STRING, allowNull: false, unique: true },
9
- type: { type: DataTypes.ENUM('больница', 'поликлиника', 'станция скорой помощи', 'частный медицинский центр'), allowNull: false },
10
- address: { type: DataTypes.STRING, allowNull: false },
11
- phone: { type: DataTypes.STRING, allowNull: true }
12
- }, {
13
- timestamps: true
14
- });
23
+ {
24
+ timestamps: true,
25
+ },
26
+ );
15
27
 
16
28
  // Настройка связи прямо в таблице клиник
17
29
  Clinic.associate = (models) => {
18
- Clinic.hasMany(models.User, { foreignKey: 'ClinicId' });
30
+ Clinic.hasMany(models.User, { foreignKey: "ClinicId" });
19
31
  };
20
32
 
21
33
  return Clinic;
@@ -1,18 +1,26 @@
1
1
  module.exports = (sequelize, DataTypes) => {
2
- const Disease = sequelize.define('Disease', {
3
- id: {
4
- type: DataTypes.INTEGER,
5
- autoIncrement: true,
6
- primaryKey: true
2
+ const Disease = sequelize.define(
3
+ "Disease",
4
+ {
5
+ id: {
6
+ type: DataTypes.INTEGER,
7
+ autoIncrement: true,
8
+ primaryKey: true,
9
+ },
10
+ name: { type: DataTypes.STRING, allowNull: false, unique: true },
11
+ code: { type: DataTypes.STRING, allowNull: false, unique: true },
12
+ treatmentRecommendations: { type: DataTypes.TEXT, allowNull: true },
13
+ recommendedMedications: { type: DataTypes.TEXT, allowNull: true },
14
+ casesCount: {
15
+ type: DataTypes.INTEGER,
16
+ defaultValue: 0,
17
+ allowNull: false,
18
+ },
7
19
  },
8
- name: { type: DataTypes.STRING, allowNull: false, unique: true },
9
- code: { type: DataTypes.STRING, allowNull: false, unique: true },
10
- treatmentRecommendations: { type: DataTypes.TEXT, allowNull: true },
11
- recommendedMedications: { type: DataTypes.TEXT, allowNull: true },
12
- casesCount: { type: DataTypes.INTEGER, defaultValue: 0, allowNull: false }
13
- }, {
14
- timestamps: true
15
- });
20
+ {
21
+ timestamps: true,
22
+ },
23
+ );
16
24
 
17
25
  // У этой модели нет прямых исходящих связей (зависит от Appointment, но связь прописана там)
18
26
  return Disease;
@@ -0,0 +1,55 @@
1
+ module.exports = (sequelize, DataTypes) => {
2
+ const District = sequelize.define(
3
+ "District",
4
+ {
5
+ id: {
6
+ type: DataTypes.INTEGER,
7
+ autoIncrement: true,
8
+ primaryKey: true,
9
+ },
10
+ name: {
11
+ type: DataTypes.STRING, // Например: "Терапевтический участок №3"
12
+ allowNull: false,
13
+ },
14
+ city: {
15
+ type: DataTypes.STRING, // Например: "Минск"
16
+ allowNull: false,
17
+ },
18
+ street: {
19
+ type: DataTypes.STRING, // Например: "Машерова"
20
+ allowNull: false,
21
+ set(value) {
22
+ this.setDataValue("street", value.toLowerCase().trim());
23
+ },
24
+ },
25
+ // Диапазон обслуживаемых домов (например: "1-20" или "все")
26
+ houses: {
27
+ type: DataTypes.STRING,
28
+ allowNull: false,
29
+ defaultValue: "все",
30
+ },
31
+ cabinet: {
32
+ type: DataTypes.STRING, // Например: "Кабинет №302"
33
+ allowNull: false,
34
+ },
35
+ doctorName: {
36
+ type: DataTypes.STRING,
37
+ allowNull: true,
38
+ defaultValue: "Врач не назначен",
39
+ },
40
+ },
41
+ {
42
+ timestamps: true,
43
+ },
44
+ );
45
+
46
+ District.associate = (models) => {
47
+ // ЖЕСТКАЯ ПРИВЯЗКА: Участок и его кабинет принадлежат конкретному учреждению
48
+ District.belongsTo(models.Clinic, {
49
+ foreignKey: "ClinicId",
50
+ onDelete: "CASCADE",
51
+ });
52
+ };
53
+
54
+ return District;
55
+ };
@@ -0,0 +1,25 @@
1
+ module.exports = (sequelize, DataTypes) => {
2
+ const News = sequelize.define(
3
+ "News",
4
+ {
5
+ id: {
6
+ type: DataTypes.INTEGER,
7
+ autoIncrement: true,
8
+ primaryKey: true,
9
+ },
10
+ title: {
11
+ type: DataTypes.STRING,
12
+ allowNull: false,
13
+ },
14
+ content: {
15
+ type: DataTypes.TEXT,
16
+ allowNull: false,
17
+ },
18
+ },
19
+ {
20
+ timestamps: true,
21
+ },
22
+ );
23
+
24
+ return News;
25
+ };
@@ -1,21 +1,28 @@
1
1
  module.exports = (sequelize, DataTypes) => {
2
- const UserAddress = sequelize.define('UserAddress', {
3
- id: {
4
- type: DataTypes.UUID,
5
- defaultValue: DataTypes.UUIDV4,
6
- primaryKey: true
2
+ const UserAddress = sequelize.define(
3
+ "UserAddress",
4
+ {
5
+ id: {
6
+ type: DataTypes.UUID,
7
+ defaultValue: DataTypes.UUIDV4,
8
+ primaryKey: true,
9
+ },
10
+ city: { type: DataTypes.STRING, allowNull: false },
11
+ street: { type: DataTypes.STRING, allowNull: false },
12
+ houseNumber: { type: DataTypes.STRING, allowNull: false },
13
+ assignedDistrict: { type: DataTypes.STRING, allowNull: true },
14
+ assignedCabinet: { type: DataTypes.STRING, allowNull: true },
7
15
  },
8
- city: { type: DataTypes.STRING, allowNull: false },
9
- street: { type: DataTypes.STRING, allowNull: false },
10
- houseNumber: { type: DataTypes.STRING, allowNull: false },
11
- assignedDistrict: { type: DataTypes.STRING, allowNull: true },
12
- assignedCabinet: { type: DataTypes.STRING, allowNull: true }
13
- }, {
14
- timestamps: true
15
- });
16
+ {
17
+ timestamps: true,
18
+ },
19
+ );
16
20
 
17
21
  UserAddress.associate = (models) => {
18
- UserAddress.belongsTo(models.User, { foreignKey: 'UserId', onDelete: 'CASCADE' });
22
+ UserAddress.belongsTo(models.User, {
23
+ foreignKey: "UserId",
24
+ onDelete: "CASCADE",
25
+ });
19
26
  };
20
27
 
21
28
  return UserAddress;