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
@@ -1,35 +1,78 @@
1
1
  module.exports = (sequelize, DataTypes) => {
2
- const User = sequelize.define('User', {
3
- id: {
4
- type: DataTypes.INTEGER,
5
- autoIncrement: true,
6
- primaryKey: true
2
+ const User = sequelize.define(
3
+ "User",
4
+ {
5
+ id: {
6
+ type: DataTypes.INTEGER,
7
+ autoIncrement: true,
8
+ primaryKey: true,
9
+ },
10
+ email: {
11
+ type: DataTypes.STRING,
12
+ allowNull: false,
13
+ unique: true,
14
+ validate: { isEmail: true },
15
+ },
16
+ password: { type: DataTypes.STRING, allowNull: false },
17
+ fullName: { type: DataTypes.STRING, allowNull: false },
18
+ role: {
19
+ type: DataTypes.ENUM("patient", "doctor", "admin"),
20
+ defaultValue: "patient",
21
+ allowNull: false,
22
+ },
23
+ specialty: {
24
+ type: DataTypes.ENUM(
25
+ "Терапевт",
26
+ "Педиатр",
27
+ "Врач общей практики",
28
+ "Кардиолог",
29
+ "Невролог",
30
+ "Эндокринолог",
31
+ "Гастроэнтеролог",
32
+ "Пульмонолог",
33
+ "Нефролог",
34
+ "Ревматолог",
35
+ "Гематолог",
36
+ "Хирург",
37
+ "Травматолог-ортопед",
38
+ "Сосудистый хирург",
39
+ "Нейрохирург",
40
+ "Кардиохирург",
41
+ "Пластический хирург",
42
+ "Офтальмолог",
43
+ "Отоларинголог",
44
+ "Дерматолог",
45
+ "Стоматолог",
46
+ "Гинеколог",
47
+ "Уролог",
48
+ "Онколог",
49
+ "Инфекционист",
50
+ "Аллерголог-иммунолог",
51
+ "Психиатр",
52
+ "Психотерапевт",
53
+ "Нарколог",
54
+ "Анестезиолог-реаниматолог",
55
+ "Рентгенолог",
56
+ "Врач УЗД",
57
+ "Эндоскопист",
58
+ "Патологоанатом",
59
+ ),
60
+ allowNull: true,
61
+ },
62
+ isTemporaryPassword: { type: DataTypes.BOOLEAN, defaultValue: false },
7
63
  },
8
- email: { type: DataTypes.STRING, allowNull: false, unique: true, validate: { isEmail: true } },
9
- password: { type: DataTypes.STRING, allowNull: false },
10
- fullName: { type: DataTypes.STRING, allowNull: false },
11
- role: { type: DataTypes.ENUM('patient', 'doctor', 'admin'), defaultValue: 'patient', allowNull: false },
12
- specialty: {
13
- type: DataTypes.ENUM(
14
- 'Терапевт', 'Педиатр', 'Врач общей практики', 'Кардиолог', 'Невролог',
15
- 'Эндокринолог', 'Гастроэнтеролог', 'Пульмонолог', 'Нефролог', 'Ревматолог',
16
- 'Гематолог', 'Хирург', 'Травматолог-ортопед', 'Сосудистый хирург', 'Нейрохирург',
17
- 'Кардиохирург', 'Пластический хирург', 'Офтальмолог', 'Отоларинголог', 'Дерматолог',
18
- 'Стоматолог', 'Гинеколог', 'Уролог', 'Онколог', 'Инфекционист', 'Аллерголог-иммунолог',
19
- 'Психиатр', 'Психотерапевт', 'Нарколог', 'Анестезиолог-реаниматолог', 'Рентгенолог',
20
- 'Врач УЗД', 'Эндоскопист', 'Патологоанатом'
21
- ),
22
- allowNull: true
64
+ {
65
+ timestamps: true,
23
66
  },
24
- isTemporaryPassword: { type: DataTypes.BOOLEAN, defaultValue: false }
25
- }, {
26
- timestamps: true
27
- });
67
+ );
28
68
 
29
69
  // Настройка связей пользователя
30
70
  User.associate = (models) => {
31
- User.belongsTo(models.Clinic, { foreignKey: 'ClinicId', onDelete: 'SET NULL' });
32
- User.hasOne(models.UserAddress, { foreignKey: 'UserId' });
71
+ User.belongsTo(models.Clinic, {
72
+ foreignKey: "ClinicId",
73
+ onDelete: "SET NULL",
74
+ });
75
+ User.hasOne(models.UserAddress, { foreignKey: "UserId" });
33
76
  };
34
77
 
35
78
  return User;
@@ -1,19 +1,31 @@
1
1
  const path = require("path");
2
- const Clinic = require(path.join(__dirname, '..', '..', 'models', 'clinics'));
2
+ const dbConfig = require(
3
+ path.join(__dirname, "..", "..", "config", "db-init.js"),
4
+ );
5
+
3
6
  const createClinic = {
4
7
  async create(clinicData) {
8
+ const Clinic = dbConfig.models.Clinic || dbConfig.Clinic;
5
9
  const { name, type, address, phone } = clinicData;
10
+
6
11
  if (!name || !type || !address) {
7
- throw new Error('Поля name, type и address обязательны для заполнения');
12
+ throw new Error("Поля name, type и address обязательны для заполнения");
8
13
  }
14
+
9
15
  const candidate = await Clinic.findOne({ where: { name } });
10
16
  if (candidate) {
11
- throw new Error('Медицинское учреждение с таким названием уже зарегистрировано');
17
+ throw new Error(
18
+ "Медицинское учреждение с таким названием уже зарегистрировано",
19
+ );
12
20
  }
21
+
13
22
  return await Clinic.create({ name, type, address, phone });
14
23
  },
24
+
15
25
  async getAll() {
16
- return await Clinic.findAll({ order: [['name', 'ASC']] });
17
- }
26
+ const Clinic = dbConfig.models.Clinic || dbConfig.Clinic;
27
+ return await Clinic.findAll({ order: [["name", "ASC"]] });
28
+ },
18
29
  };
19
- module.exports = createClinic;
30
+
31
+ module.exports = createClinic;
@@ -1,34 +1,60 @@
1
- const path = require("path")
2
- const User = require(path.join(__dirname, '..', '..', 'models', 'users'));
3
- const Clinic = require(path.join(__dirname, '..', '..', 'models', 'clinics'));
4
- const Disease = require(path.join(__dirname, '..', '..', 'models', 'diseases'));
5
- const Appointment = require(path.join(__dirname, '..', '..', 'models', 'appointments'));
1
+ const path = require("path");
2
+ // Импортируем только синглтон конфигурации базы данных
3
+ const dbConfig = require(
4
+ path.join(__dirname, "..", "..", "config", "db-init.js"),
5
+ );
6
+
6
7
  const dbAnalytics = {
8
+ /**
9
+ * Собрать общую медицинскую статистику и данные для дашборда
10
+ */
7
11
  async getStats() {
12
+ // Безопасно достаем проинициализированные фабриками модели онлайн
13
+ const Clinic = dbConfig.models.Clinic || dbConfig.Clinic;
14
+ const User = dbConfig.models.User || dbConfig.User;
15
+ const Disease = dbConfig.models.Disease || dbConfig.Disease;
16
+ const Appointment = dbConfig.models.Appointment || dbConfig.Appointment;
17
+
18
+ if (!Clinic || !User || !Disease || !Appointment) {
19
+ throw new Error(
20
+ "Критическая ошибка: Модели базы данных еще не проинициализированы!",
21
+ );
22
+ }
23
+
24
+ // Собираем агрегированные цифры для карточек админки через Sequelize
8
25
  const totalClinics = await Clinic.count();
9
- const totalPatients = await User.count({ where: { role: 'patient' } });
10
- const totalStaff = await User.count({ where: { role: 'doctor' } });
26
+ const totalPatients = await User.count({ where: { role: "patient" } });
27
+ const totalStaff = await User.count({ where: { role: "doctor" } });
11
28
  const totalAppointments = await Appointment.count();
29
+
30
+ // Топ-5 самых частых болезней по инкрементируемому счетчику
12
31
  const topDiseases = await Disease.findAll({
13
32
  limit: 5,
14
- order: [['casesCount', 'DESC']],
15
- attributes: ['name', 'code', 'casesCount']
33
+ order: [["casesCount", "DESC"]],
34
+ attributes: ["name", "code", "casesCount"],
16
35
  });
36
+
37
+ // Разбивка персонала по специальностям (для графиков или таблиц)
17
38
  const staffBySpecialty = await User.findAll({
18
- where: { role: 'doctor' },
19
- attributes: ['specialty', [User.sequelize.fn('COUNT', User.sequelize.col('id')), 'count']],
20
- group: ['specialty']
39
+ where: { role: "doctor" },
40
+ attributes: [
41
+ "specialty",
42
+ [User.sequelize.fn("COUNT", User.sequelize.col("id")), "count"],
43
+ ],
44
+ group: ["specialty"],
21
45
  });
46
+
22
47
  return {
23
48
  summary: {
24
49
  totalClinics,
25
50
  totalPatients,
26
51
  totalStaff,
27
- totalAppointments
52
+ totalAppointments,
28
53
  },
29
54
  topDiseases,
30
- staffBySpecialty
55
+ staffBySpecialty,
31
56
  };
32
- }
57
+ },
33
58
  };
34
- module.exports = dbAnalytics;
59
+
60
+ module.exports = dbAnalytics;
@@ -1,12 +1,12 @@
1
- const path = require("path")
2
- const createClinic = require(path.join(__dirname, 'create-clinic'));
3
- const manageStaff = require(path.join(__dirname, 'manage-staff'));
4
- const dbAnalytics = require(path.join(__dirname, 'db-analytics'));
1
+ const path = require("path");
2
+ const createClinic = require(path.join(__dirname, "create-clinic"));
3
+ const manageStaff = require(path.join(__dirname, "manage-staff"));
4
+ const dbAnalytics = require(path.join(__dirname, "db-analytics"));
5
5
  const AdminService = {
6
6
  createClinic: createClinic.create,
7
7
  getAllClinics: createClinic.getAll,
8
8
  createStaffAccount: manageStaff.createAccount,
9
9
  deleteAccount: manageStaff.deleteAccount,
10
- getSystemStats: dbAnalytics.getStats
10
+ getSystemStats: dbAnalytics.getStats,
11
11
  };
12
- module.exports = AdminService;
12
+ module.exports = AdminService;
@@ -1,41 +1,71 @@
1
- const path = require("path")
2
- const User = require(path.join(__dirname, '..', '..', 'models', 'users'));
3
- const Clinic = require(path.join(__dirname, '..', '..', 'models', 'clinics'));
4
- const bcrypt = require('bcrypt');
1
+ const path = require("path");
2
+ const dbConfig = require(
3
+ path.join(__dirname, "..", "..", "config", "db-init.js"),
4
+ );
5
+
6
+ // ИСПРАВЛЕНИЕ: Добавляем точный импорт вашей библиотеки bcrypt
7
+ const bcrypt = require("bcrypt");
8
+
5
9
  const manageStaff = {
6
- async createAccount(staffData) {
10
+ async createAccount(staffData) {
11
+ const User = dbConfig.models.User || dbConfig.User;
12
+ const Clinic = dbConfig.models.Clinic || dbConfig.Clinic;
13
+
7
14
  const { email, rawPassword, fullName, medicalProfile } = staffData;
8
15
  const ClinicId = staffData.ClinicId || staffData.clinicId;
16
+
9
17
  if (!email || !rawPassword || !fullName || !medicalProfile || !ClinicId) {
10
- throw new Error('Необходимо заполнить обязательные поля: email, rawPassword, fullName, medicalProfile, clinicId');
18
+ throw new Error(
19
+ "Необходимо заполнить обязательные поля: email, rawPassword, fullName, medicalProfile, clinicId",
20
+ );
11
21
  }
22
+
12
23
  const clinicExists = await Clinic.findByPk(ClinicId);
13
24
  if (!clinicExists) {
14
25
  throw new Error(`Медицинское учреждение с ID №${ClinicId} не найдено.`);
15
26
  }
27
+
16
28
  const candidate = await User.findOne({ where: { email } });
17
29
  if (candidate) {
18
- throw new Error('Сотрудник с таким email уже зарегистрирован');
30
+ throw new Error("Сотрудник с таким email уже зарегистрирован");
19
31
  }
20
- let finalPosition = 'Врач';
32
+
33
+ // Хешируем временный пароль с помощью подключенного нативного bcrypt
34
+ const hashedPassword = await bcrypt.hash(rawPassword, 10);
35
+
36
+ let finalPosition = "Врач";
21
37
  let finalSpecialty = medicalProfile;
22
- const purePositions = ['Главврач', 'Медсестра', 'Врач скорой помощи', 'Фельдшер', 'Регистратор'];
38
+ const purePositions = [
39
+ "Главврач",
40
+ "Медсестра",
41
+ "Врач скорой помощи",
42
+ "Фельдшер",
43
+ "Регистратор",
44
+ ];
45
+
23
46
  if (purePositions.includes(medicalProfile)) {
24
47
  finalPosition = medicalProfile;
25
- finalSpecialty = 'Общий медицинский профиль';
48
+ finalSpecialty = "Общий медицинский профиль";
26
49
  }
27
- const hashedPassword = await bcrypt.hash(rawPassword, 10);
28
- const newStaff = await User.create({
50
+
51
+ return await User.create({
29
52
  email,
30
53
  password: hashedPassword,
31
54
  fullName,
32
- role: 'doctor',
55
+ role: "doctor",
33
56
  position: finalPosition,
34
57
  specialty: finalSpecialty,
35
58
  ClinicId: Number(ClinicId),
36
- isTemporaryPassword: true
59
+ isTemporaryPassword: true,
37
60
  });
38
- return newStaff;
39
- }
61
+ },
62
+
63
+ async deleteAccount(userId) {
64
+ const User = dbConfig.models.User || dbConfig.User;
65
+ const deletedRows = await User.destroy({ where: { id: userId } });
66
+ if (deletedRows === 0) throw new Error("Аккаунт не найден");
67
+ return { success: true, message: "Аккаунт успешно удален" };
68
+ },
40
69
  };
41
- module.exports = manageStaff;
70
+
71
+ module.exports = manageStaff;
@@ -1,33 +1,39 @@
1
- const path = require("path")
2
- const Appointment = require(path.join(__dirname, '..', '..', 'models', 'appointments'));
3
- const Disease = require(path.join(__dirname, '..', '..', 'models', 'diseases'));
1
+ const path = require("path");
2
+ const dbConfig = require(
3
+ path.join(__dirname, "..", "..", "config", "db-init.js"),
4
+ );
5
+
4
6
  const conductExam = {
5
7
  async saveResult(examData) {
6
- const { appointmentId, complaints, objectively, doctorNotes, diseaseId } = examData;
7
- if (!appointmentId) {
8
- throw new Error('ID приема обязателен для сохранения результатов');
9
- }
8
+ const { appointmentId, complaints, objectively, doctorNotes, diseaseId } =
9
+ examData;
10
+
11
+ const Appointment = dbConfig.models.Appointment || dbConfig.Appointment;
12
+ const Disease = dbConfig.models.Disease || dbConfig.Disease;
13
+
14
+ if (!appointmentId) throw new Error("ID приема обязателен");
15
+
10
16
  const appointment = await Appointment.findByPk(appointmentId);
11
- if (!appointment) {
12
- throw new Error('Указанный прием не найден');
13
- }
14
- if (appointment.status === 'завершен') {
15
- throw new Error('Этот прием уже был успешно завершен ранее');
16
- }
17
+ if (!appointment) throw new Error("Прием не найден");
18
+ if (appointment.status === "завершен")
19
+ throw new Error("Прием уже завершен");
20
+
17
21
  appointment.complaints = complaints;
18
22
  appointment.objectively = objectively;
19
23
  appointment.doctorNotes = doctorNotes;
20
- appointment.status = 'завершен';
24
+ appointment.status = "завершен";
25
+
21
26
  if (diseaseId) {
22
27
  const disease = await Disease.findByPk(diseaseId);
23
- if (!disease) {
24
- throw new Error('Указанная болезнь не найдена в справочнике диагнозов');
25
- }
28
+ if (!disease) throw new Error("Болезнь не найдена в справочнике");
29
+
26
30
  appointment.DiseaseId = diseaseId;
27
- await disease.increment('casesCount', { by: 1 });
31
+ await disease.increment("casesCount", { by: 1 });
28
32
  }
33
+
29
34
  await appointment.save();
30
35
  return appointment;
31
- }
36
+ },
32
37
  };
33
- module.exports = conductExam;
38
+
39
+ module.exports = conductExam;
@@ -1,23 +1,31 @@
1
- const path = require("path")
2
- const Appointment = require(path.join(__dirname, '..', '..', 'models', 'appointments'));
3
- const User = require(path.join(__dirname, '..', '..', 'models', 'users'));
1
+ const path = require("path");
2
+ const dbConfig = require(
3
+ path.join(__dirname, "..", "..", "config", "db-init.js"),
4
+ );
5
+
4
6
  const getSchedule = {
5
7
  async byDoctorId(doctorId) {
6
- if (!doctorId) {
7
- throw new Error('ID врача не указан');
8
- }
8
+ if (!doctorId) throw new Error("ID врача не указан");
9
+
10
+ // Достаем проинициализированные модели из синглтона
11
+ const Appointment = dbConfig.models.Appointment || dbConfig.Appointment;
12
+ const User = dbConfig.models.User || dbConfig.User;
13
+
9
14
  return await Appointment.findAll({
10
- where: {
11
- DoctorId: doctorId,
12
- status: 'ожидается'
13
- },
14
- include: [{
15
- model: User,
16
- as: 'Patient',
17
- attributes: ['id', 'fullName', 'email']
18
- }],
19
- order: [['date', 'ASC'], ['time', 'ASC']]
15
+ where: { DoctorId: doctorId, status: "ожидается" },
16
+ include: [
17
+ {
18
+ model: User,
19
+ as: "Patient",
20
+ attributes: ["id", "fullName", "email"],
21
+ },
22
+ ],
23
+ order: [
24
+ ["date", "ASC"],
25
+ ["time", "ASC"],
26
+ ],
20
27
  });
21
- }
28
+ },
22
29
  };
23
- module.exports = getSchedule;
30
+
31
+ module.exports = getSchedule;
@@ -1,10 +1,10 @@
1
- const path = require("path")
2
- const getSchedule = require(path.join(__dirname, 'get-schedule'));
3
- const patientAccess = require(path.join(__dirname, 'patient-access'));
4
- const conductExam = require(path.join(__dirname, 'conduct-exam'));
1
+ const path = require("path");
2
+ const getSchedule = require(path.join(__dirname, "get-schedule"));
3
+ const patientAccess = require(path.join(__dirname, "patient-access"));
4
+ const conductExam = require(path.join(__dirname, "conduct-exam"));
5
5
  const DoctorService = {
6
6
  getMySchedule: getSchedule.byDoctorId,
7
7
  getPatientHistory: patientAccess.getHistory,
8
- saveExamination: conductExam.saveResult
8
+ saveExamination: conductExam.saveResult,
9
9
  };
10
- module.exports = DoctorService;
10
+ module.exports = DoctorService;
@@ -1,34 +1,43 @@
1
1
  const path = require("path");
2
- const User = require(path.join(__dirname, '..', '..', 'models', 'users'));
3
- const Appointment = require(path.join(__dirname, '..', '..', 'models', 'appointments'));
4
- const Disease = require(path.join(__dirname, '..', '..', 'models', 'diseases'));
5
- const UserAddress = require(path.join(__dirname, '..', '..', 'models', 'user-addresses'));
2
+ const dbConfig = require(
3
+ path.join(__dirname, "..", "..", "config", "db-init.js"),
4
+ );
5
+
6
6
  const patientAccess = {
7
7
  async getHistory(patientId) {
8
- if (!patientId) {
9
- throw new Error('ID пациента не указан');
10
- }
11
- const patient = await User.findByPk(patientId, {
12
- attributes: ['id', 'fullName', 'email'],
8
+ if (!patientId) throw new Error("ID пациента не указан");
9
+
10
+ const User = dbConfig.models.User || dbConfig.User;
11
+ const Appointment = dbConfig.models.Appointment || dbConfig.Appointment;
12
+ const Disease = dbConfig.models.Disease || dbConfig.Disease;
13
+ const UserAddress = dbConfig.models.UserAddress || dbConfig.UserAddress;
14
+
15
+ return await User.findByPk(patientId, {
16
+ attributes: ["id", "fullName", "email"],
13
17
  include: [
14
- {
18
+ {
15
19
  model: UserAddress,
16
- attributes: ['city', 'street', 'houseNumber', 'assignedDistrict', 'assignedCabinet']
20
+ attributes: [
21
+ "city",
22
+ "street",
23
+ "houseNumber",
24
+ "assignedDistrict",
25
+ "assignedCabinet",
26
+ ],
17
27
  },
18
- {
19
- model: Appointment,
20
- as: 'PatientAppointments',
21
- where: { status: 'завершен' },
22
- include: [{ model: Disease, attributes: ['name', 'code'] }],
23
- required: false
24
- }
28
+ {
29
+ model: Appointment,
30
+ as: "PatientAppointments",
31
+ where: { status: "завершен" },
32
+ include: [{ model: Disease, attributes: ["name", "code"] }],
33
+ required: false,
34
+ },
35
+ ],
36
+ order: [
37
+ [{ model: Appointment, as: "PatientAppointments" }, "date", "DESC"],
25
38
  ],
26
- order: [[{ model: Appointment, as: 'PatientAppointments' }, 'date', 'DESC']]
27
39
  });
28
- if (!patient) {
29
- throw new Error('Пациент не найден в базе данных');
30
- }
31
- return patient;
32
- }
40
+ },
33
41
  };
34
- module.exports = patientAccess;
42
+
43
+ module.exports = patientAccess;
@@ -1,45 +1,65 @@
1
- const path = require("path")
2
- const Appointment = require(path.join(__dirname, '..', '..', 'models', 'appointments'));
3
- const User = require(path.join(__dirname, '..', '..', 'models', 'users'));
1
+ const path = require("path");
2
+ const dbConfig = require(
3
+ path.join(__dirname, "..", "..", "config", "db-init.js"),
4
+ );
5
+
4
6
  const bookAppointment = {
7
+ /**
8
+ * Записать пациента к врачу на свободное время
9
+ */
5
10
  async create(patientId, appointmentData) {
6
11
  const { doctorId, date, time } = appointmentData;
12
+
13
+ const Appointment = dbConfig.models.Appointment || dbConfig.Appointment;
14
+ const User = dbConfig.models.User || dbConfig.User;
15
+
7
16
  if (!doctorId || !date || !time) {
8
- throw new Error('Необходимо выбрать врача, дату и время приема');
17
+ throw new Error("Необходимо выбрать врача, дату и время приема");
9
18
  }
10
- const doctor = await User.findOne({ where: { id: doctorId, role: 'doctor' } });
19
+
20
+ const doctor = await User.findOne({
21
+ where: { id: doctorId, role: "doctor" },
22
+ });
11
23
  if (!doctor) {
12
- throw new Error('Указанный врач не найден в системе или не имеет прав на прием');
24
+ throw new Error(
25
+ "Указанный сотрудник не найден или не имеет прав на прием",
26
+ );
13
27
  }
28
+
14
29
  const isSlotBusy = await Appointment.findOne({
15
30
  where: {
16
31
  DoctorId: doctorId,
17
32
  date: date,
18
33
  time: time,
19
- status: 'ожидается'
20
- }
34
+ status: "ожидается",
35
+ },
21
36
  });
37
+
22
38
  if (isSlotBusy) {
23
- throw new Error(`Время ${time} на дату ${date} к врачу ${doctor.fullName} уже занято. Выберите другой слот.`);
39
+ throw new Error(`Время ${time} на дату ${date} уже занято.`);
24
40
  }
41
+
25
42
  const isPatientDoubleBooked = await Appointment.findOne({
26
43
  where: {
27
44
  PatientId: patientId,
28
45
  DoctorId: doctorId,
29
46
  date: date,
30
- status: 'ожидается'
31
- }
47
+ status: "ожидается",
48
+ },
32
49
  });
50
+
33
51
  if (isPatientDoubleBooked) {
34
- throw new Error(`Вы уже записаны к врачу ${doctor.fullName} на дату ${date}. Нельзя бронировать несколько талонов на один день.`);
52
+ throw new Error(`Вы уже записаны к этому специалисту на выбранную дату.`);
35
53
  }
54
+
36
55
  return await Appointment.create({
37
56
  date,
38
57
  time,
39
- status: 'ожидается',
40
- PatientId: patientId,
41
- DoctorId: doctorId
58
+ status: "ожидается",
59
+ PatientId: Number(patientId),
60
+ DoctorId: Number(doctorId),
42
61
  });
43
- }
62
+ },
44
63
  };
45
- module.exports = bookAppointment;
64
+
65
+ module.exports = bookAppointment;