med-cms 1.0.0-beta.1 → 1.0.0-beta.5
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.
- package/database/config/db-init.js +85 -25
- package/database/models/appointments.js +44 -39
- package/database/models/clinics.js +34 -18
- package/database/models/diseases.js +27 -37
- package/database/models/districts.js +55 -0
- package/database/models/news.js +25 -0
- package/database/models/user-addresses.js +29 -34
- package/database/models/users.js +79 -31
- package/database/services/admin/create-clinic.js +18 -6
- package/database/services/admin/db-analytics.js +42 -16
- package/database/services/admin/index.js +6 -6
- package/database/services/admin/manage-staff.js +47 -17
- package/database/services/doctor/conduct-exam.js +26 -20
- package/database/services/doctor/get-schedule.js +26 -18
- package/database/services/doctor/index.js +6 -6
- package/database/services/doctor/patient-access.js +34 -25
- package/database/services/patient/book-appointment.js +37 -17
- package/database/services/patient/calc-district.js +70 -21
- package/database/services/patient/get-profile.js +49 -21
- package/database/services/patient/index.js +5 -5
- package/index.js +60 -25
- package/migrate-diseases.js +192 -120
- package/package.json +1 -1
- package/public/css/admin.css +80 -80
- package/public/css/auth.css +52 -44
- package/public/css/doctor.css +131 -125
- package/public/css/home.css +155 -0
- package/public/html/dashboard-admin.html +423 -101
- package/public/html/dashboard-doctor.html +155 -66
- package/public/html/dashboard-patient.html +199 -94
- package/public/html/home/about.html +0 -0
- package/public/html/home/contact.html +0 -0
- package/public/html/home/info.html +0 -0
- package/public/html/home.html +159 -0
- package/public/html/login.html +73 -43
- package/public/js/admin.js +329 -165
- package/public/js/auth.js +45 -41
- package/public/js/doctor.js +117 -103
- package/public/js/home.js +113 -0
- package/public/js/patient.js +130 -108
- package/server/midleware.js +33 -13
- package/server/permissions.js +105 -43
- package/server/server.js +504 -178
- package/test.js +12 -23
|
@@ -1,44 +1,104 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
const UserAddress = require(path.join(__dirname, '..', 'models', 'user-addresses'));
|
|
6
|
-
const Disease = require(path.join(__dirname, '..', 'models', 'diseases'));
|
|
7
|
-
const Appointment = require(path.join(__dirname, '..', 'models', 'appointments'));
|
|
1
|
+
// Полностью рабочий database/config/db-init.js с динамическим расширением модели
|
|
2
|
+
|
|
3
|
+
const { Sequelize, DataTypes } = require("sequelize");
|
|
4
|
+
const path = require("path");
|
|
8
5
|
const logger = require("custom-color-logs").print;
|
|
6
|
+
|
|
9
7
|
let sequelize;
|
|
8
|
+
|
|
10
9
|
function getSequelizeInstance(dbPath) {
|
|
11
10
|
if (!sequelize) {
|
|
12
|
-
const storagePath = dbPath || path.join(process.cwd(),
|
|
11
|
+
const storagePath = dbPath || path.join(process.cwd(), "med-cms.sqlite");
|
|
13
12
|
sequelize = new Sequelize({
|
|
14
|
-
dialect:
|
|
13
|
+
dialect: "sqlite",
|
|
15
14
|
storage: storagePath,
|
|
16
|
-
logging: false
|
|
15
|
+
logging: false,
|
|
17
16
|
});
|
|
18
17
|
}
|
|
19
18
|
return sequelize;
|
|
20
19
|
}
|
|
20
|
+
|
|
21
|
+
const db = {
|
|
22
|
+
getSequelizeInstance,
|
|
23
|
+
initDatabase,
|
|
24
|
+
get sequelize() {
|
|
25
|
+
return sequelize;
|
|
26
|
+
},
|
|
27
|
+
models: {},
|
|
28
|
+
};
|
|
29
|
+
|
|
21
30
|
async function initDatabase(dbPath) {
|
|
22
31
|
const instance = getSequelizeInstance(dbPath);
|
|
32
|
+
|
|
23
33
|
try {
|
|
24
34
|
await instance.authenticate();
|
|
25
|
-
console.log(
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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(); // Синхронизируем изменения атрибутов
|
|
79
|
+
|
|
80
|
+
// =========================================================================
|
|
81
|
+
|
|
82
|
+
// 2. Безопасно запускаем связи (Associations) между всеми таблицами
|
|
83
|
+
Object.keys(db.models).forEach((modelName) => {
|
|
84
|
+
if (db.models[modelName].associate) {
|
|
85
|
+
db.models[modelName].associate(db.models);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// 3. Синхронизируем базу данных с учётом динамически добавленных полей
|
|
33
90
|
await instance.sync({ alter: true });
|
|
34
|
-
console.log(
|
|
91
|
+
console.log(
|
|
92
|
+
logger.DatabaseMedInfo(
|
|
93
|
+
"Все таблицы базы данных успешно синхронизированы.",
|
|
94
|
+
),
|
|
95
|
+
);
|
|
35
96
|
} catch (error) {
|
|
36
|
-
console.log(
|
|
97
|
+
console.log(
|
|
98
|
+
logger.DatabaseMedError("Ошибка инициализации базы данных:", error),
|
|
99
|
+
);
|
|
37
100
|
throw error;
|
|
38
101
|
}
|
|
39
102
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
getSequelizeInstance,
|
|
43
|
-
initDatabase
|
|
44
|
-
};
|
|
103
|
+
|
|
104
|
+
module.exports = db;
|
|
@@ -1,39 +1,44 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
1
|
+
module.exports = (sequelize, DataTypes) => {
|
|
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 },
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
timestamps: true,
|
|
23
|
+
},
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
Appointment.associate = (models) => {
|
|
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
|
+
});
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
return Appointment;
|
|
44
|
+
};
|
|
@@ -1,18 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
1
|
+
module.exports = (sequelize, DataTypes) => {
|
|
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 },
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
timestamps: true,
|
|
25
|
+
},
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
// Настройка связи прямо в таблице клиник
|
|
29
|
+
Clinic.associate = (models) => {
|
|
30
|
+
Clinic.hasMany(models.User, { foreignKey: "ClinicId" });
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return Clinic;
|
|
34
|
+
};
|
|
@@ -1,37 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
},
|
|
29
|
-
casesCount: {
|
|
30
|
-
type: DataTypes.INTEGER,
|
|
31
|
-
defaultValue: 0,
|
|
32
|
-
allowNull: false
|
|
33
|
-
}
|
|
34
|
-
}, {
|
|
35
|
-
timestamps: true
|
|
36
|
-
});
|
|
37
|
-
module.exports = Disease;
|
|
1
|
+
module.exports = (sequelize, DataTypes) => {
|
|
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
|
+
},
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
timestamps: true,
|
|
22
|
+
},
|
|
23
|
+
);
|
|
24
|
+
|
|
25
|
+
// У этой модели нет прямых исходящих связей (зависит от Appointment, но связь прописана там)
|
|
26
|
+
return Disease;
|
|
27
|
+
};
|
|
@@ -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,34 +1,29 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
}, {
|
|
32
|
-
timestamps: true
|
|
33
|
-
});
|
|
34
|
-
module.exports = UserAddress;
|
|
1
|
+
module.exports = (sequelize, DataTypes) => {
|
|
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 },
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
timestamps: true,
|
|
18
|
+
},
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
UserAddress.associate = (models) => {
|
|
22
|
+
UserAddress.belongsTo(models.User, {
|
|
23
|
+
foreignKey: "UserId",
|
|
24
|
+
onDelete: "CASCADE",
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
return UserAddress;
|
|
29
|
+
};
|
package/database/models/users.js
CHANGED
|
@@ -1,31 +1,79 @@
|
|
|
1
|
-
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
1
|
+
module.exports = (sequelize, DataTypes) => {
|
|
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 },
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
timestamps: true,
|
|
66
|
+
},
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
// Настройка связей пользователя
|
|
70
|
+
User.associate = (models) => {
|
|
71
|
+
User.belongsTo(models.Clinic, {
|
|
72
|
+
foreignKey: "ClinicId",
|
|
73
|
+
onDelete: "SET NULL",
|
|
74
|
+
});
|
|
75
|
+
User.hasOne(models.UserAddress, { foreignKey: "UserId" });
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
return User;
|
|
79
|
+
};
|
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
const path = require("path");
|
|
2
|
-
const
|
|
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(
|
|
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
|
-
|
|
17
|
-
|
|
26
|
+
const Clinic = dbConfig.models.Clinic || dbConfig.Clinic;
|
|
27
|
+
return await Clinic.findAll({ order: [["name", "ASC"]] });
|
|
28
|
+
},
|
|
18
29
|
};
|
|
19
|
-
|
|
30
|
+
|
|
31
|
+
module.exports = createClinic;
|