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.
- package/LICENSE.txt +13 -0
- package/README.md +117 -0
- package/database/config/db-init.js +67 -53
- package/database/models/appointments.js +35 -20
- package/database/models/clinics.js +25 -13
- package/database/models/diseases.js +21 -13
- package/database/models/districts.js +55 -0
- package/database/models/news.js +25 -0
- package/database/models/user-addresses.js +21 -14
- package/database/models/users.js +69 -26
- 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/env_init.js +55 -0
- package/index.d.ts +38 -24
- package/index.js +48 -25
- package/migrate-diseases.js +192 -120
- package/package.json +3 -3
- 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 +517 -176
- package/README +0 -161
- package/test.js +0 -27
package/public/js/patient.js
CHANGED
|
@@ -1,141 +1,163 @@
|
|
|
1
|
-
document.addEventListener(
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
document.addEventListener("DOMContentLoaded", () => {
|
|
2
|
+
loadPatientData();
|
|
3
|
+
loadDoctorsForBooking();
|
|
4
4
|
});
|
|
5
|
+
|
|
5
6
|
async function loadPatientData() {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
7
|
+
try {
|
|
8
|
+
const response = await fetch("/med/api/patient/me");
|
|
9
|
+
const result = await response.json();
|
|
10
|
+
|
|
11
|
+
if (!result.success) {
|
|
12
|
+
// ИСПРАВЛЕНИЕ: Читаем result.error (как отдает бэкенд), либо result.message
|
|
13
|
+
const errorText = result.error || result.message || "Неизвестная ошибка";
|
|
14
|
+
alert("Ошибка загрузки данных: " + errorText);
|
|
15
|
+
window.location.href = "/med/med-login"; // Перенаправляем на правильный веб-роут входа
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const data = result.data;
|
|
20
|
+
document.getElementById("patientName").textContent =
|
|
21
|
+
data.personalInfo.fullName;
|
|
22
|
+
document.getElementById("patientEmail").textContent =
|
|
23
|
+
data.personalInfo.email;
|
|
24
|
+
|
|
25
|
+
const districtInfo = document.getElementById("districtInfo");
|
|
26
|
+
if (data.personalInfo.UserAddress) {
|
|
27
|
+
const addr = data.personalInfo.UserAddress;
|
|
28
|
+
districtInfo.innerHTML = `
|
|
21
29
|
<p><b>Ваш адрес:</b> г. ${addr.city}, ул. ${addr.street}, д. ${addr.houseNumber}</p>
|
|
22
30
|
<p style="margin-top: 10px;">🩺 <span class="badge">${addr.assignedDistrict}</span></p>
|
|
23
31
|
<p style="margin-top: 10px;">🚪 <span class="badge" style="background:#ecfdf5; color:#065f46;">${addr.assignedCabinet}</span></p>
|
|
24
32
|
`;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
document.getElementById("addrCity").value = addr.city;
|
|
34
|
+
document.getElementById("addrStreet").value = addr.street;
|
|
35
|
+
document.getElementById("addrHouse").value = addr.houseNumber;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const historyContainer = document.getElementById("medicalHistoryList");
|
|
39
|
+
historyContainer.innerHTML = "";
|
|
40
|
+
|
|
41
|
+
if (data.medicalHistory && data.medicalHistory.length > 0) {
|
|
42
|
+
data.medicalHistory.forEach((record) => {
|
|
43
|
+
const card = document.createElement("div");
|
|
44
|
+
if (record.status === "ожидается") {
|
|
45
|
+
card.className = "record-card future";
|
|
46
|
+
card.innerHTML = `
|
|
37
47
|
<div style="display:flex; justify-content:space-between; font-weight:bold; color:#047857;">
|
|
38
48
|
<span>📅 Предстоящий прием: ${record.date} в ${record.time}</span>
|
|
39
49
|
<span>Статус: ожидается</span>
|
|
40
50
|
</div>
|
|
41
51
|
<p style="margin: 5px 0 0 0;"><b>Врач:</b> ${record.Doctor.fullName} (${record.Doctor.specialty})</p>
|
|
42
52
|
`;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
53
|
+
} else if (record.status === "завершен") {
|
|
54
|
+
card.className = "record-card";
|
|
55
|
+
card.innerHTML = `
|
|
46
56
|
<div style="display:flex; justify-content:space-between; font-weight:bold; color:#1e3a8a; margin-bottom: 8px;">
|
|
47
57
|
<span>🩺 Осмотр от ${record.date} в ${record.time}</span>
|
|
48
58
|
<span style="color:#2563eb;">Диагноз: [${record.Disease.code}] ${record.Disease.name}</span>
|
|
49
59
|
</div>
|
|
50
60
|
<p style="margin: 4px 0;"><b>Врач:</b> ${record.Doctor.fullName} (${record.Doctor.specialty})</p>
|
|
51
|
-
<p style="margin: 4px 0; font-size:14px;"><b>Жалобы:</b> ${record.complaints ||
|
|
52
|
-
<p style="margin: 4px 0; font-size:14px;"><b>Данные осмотра:</b> ${record.objectively ||
|
|
61
|
+
<p style="margin: 4px 0; font-size:14px;"><b>Жалобы:</b> ${record.complaints || "—"}</p>
|
|
62
|
+
<p style="margin: 4px 0; font-size:14px;"><b>Данные осмотра:</b> ${record.objectively || "—"}</p>
|
|
53
63
|
<div style="margin-top:8px; padding:8px; background:#f1f5f9; border-radius:4px; font-size:13px;">
|
|
54
64
|
<p style="margin:0 0 4px 0;">💊 <b>Рекомендации и лекарства:</b> ${record.Disease.treatmentRecommendations}</p>
|
|
55
65
|
<p style="margin:0;"><b>Назначено:</b> ${record.Disease.recommendedMedications}</p>
|
|
56
66
|
</div>
|
|
57
67
|
`;
|
|
58
|
-
}
|
|
59
|
-
historyContainer.appendChild(card);
|
|
60
|
-
});
|
|
61
|
-
} else {
|
|
62
|
-
historyContainer.innerHTML = '<p style="color: #64748b;">У вас пока нет записей в медицинской карте.</p>';
|
|
63
68
|
}
|
|
64
|
-
|
|
65
|
-
|
|
69
|
+
historyContainer.appendChild(card);
|
|
70
|
+
});
|
|
71
|
+
} else {
|
|
72
|
+
historyContainer.innerHTML =
|
|
73
|
+
'<p style="color: #64748b;">У вас пока нет записей в медицинской карте.</p>';
|
|
66
74
|
}
|
|
75
|
+
} catch (err) {
|
|
76
|
+
console.error("Ошибка связи с сервером:", err);
|
|
77
|
+
alert("Критическая ошибка фронтенда при разборе JSON");
|
|
78
|
+
}
|
|
67
79
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
}
|
|
89
|
-
|
|
80
|
+
|
|
81
|
+
document.getElementById("addressForm").addEventListener("submit", async (e) => {
|
|
82
|
+
e.preventDefault();
|
|
83
|
+
const payload = {
|
|
84
|
+
city: document.getElementById("addrCity").value,
|
|
85
|
+
street: document.getElementById("addrStreet").value,
|
|
86
|
+
houseNumber: document.getElementById("addrHouse").value,
|
|
87
|
+
};
|
|
88
|
+
try {
|
|
89
|
+
const response = await fetch("/med/api/patient/address", {
|
|
90
|
+
method: "POST",
|
|
91
|
+
headers: { "Content-Type": "application/json" },
|
|
92
|
+
body: JSON.stringify(payload),
|
|
93
|
+
});
|
|
94
|
+
const result = await response.json();
|
|
95
|
+
if (result.success) {
|
|
96
|
+
alert(
|
|
97
|
+
"Адрес сохранен! Система автоматически пересчитала ваш лечебный участок.",
|
|
98
|
+
);
|
|
99
|
+
loadPatientData();
|
|
100
|
+
} else {
|
|
101
|
+
alert("Ошибка: " + result.error);
|
|
90
102
|
}
|
|
103
|
+
} catch (err) {
|
|
104
|
+
alert("Ошибка сети при отправке адреса");
|
|
105
|
+
}
|
|
91
106
|
});
|
|
107
|
+
|
|
92
108
|
async function logout() {
|
|
93
|
-
|
|
94
|
-
|
|
109
|
+
// ИСПРАВЛЕНИЕ: Исправлен путь логаута на абсолютный /med/api
|
|
110
|
+
await fetch("/med/api/auth/logout", { method: "POST" });
|
|
111
|
+
window.location.href = "/med/med-login";
|
|
95
112
|
}
|
|
113
|
+
|
|
96
114
|
async function loadDoctorsForBooking() {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
} catch (err) {
|
|
114
|
-
console.error('Ошибка загрузки врачей:', err);
|
|
115
|
+
try {
|
|
116
|
+
const response = await fetch("/med/api/patient/doctors-list");
|
|
117
|
+
const result = await response.json();
|
|
118
|
+
const select = document.getElementById("bookingDoctor");
|
|
119
|
+
select.innerHTML = '<option value="">-- Выберите врача --</option>';
|
|
120
|
+
if (result.success && result.data.length > 0) {
|
|
121
|
+
result.data.forEach((doc) => {
|
|
122
|
+
const opt = document.createElement("option");
|
|
123
|
+
opt.value = doc.id;
|
|
124
|
+
const clinicInfo = doc.Clinic ? ` (${doc.Clinic.name})` : "";
|
|
125
|
+
opt.textContent = `${doc.specialty} — ${doc.fullName}${clinicInfo}`;
|
|
126
|
+
select.appendChild(opt);
|
|
127
|
+
});
|
|
128
|
+
} else {
|
|
129
|
+
select.innerHTML =
|
|
130
|
+
'<option value="">Врачи пока не зарегистрированы в CMS</option>';
|
|
115
131
|
}
|
|
132
|
+
} catch (err) {
|
|
133
|
+
console.error("Ошибка загрузки врачей:", err);
|
|
134
|
+
}
|
|
116
135
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
139
|
-
|
|
136
|
+
|
|
137
|
+
document.getElementById("bookingForm").addEventListener("submit", async (e) => {
|
|
138
|
+
e.preventDefault();
|
|
139
|
+
const payload = {
|
|
140
|
+
doctorId: document.getElementById("bookingDoctor").value,
|
|
141
|
+
date: document.getElementById("bookingDate").value,
|
|
142
|
+
time: document.getElementById("bookingTime").value,
|
|
143
|
+
};
|
|
144
|
+
try {
|
|
145
|
+
const response = await fetch("/med/api/patient/book", {
|
|
146
|
+
method: "POST",
|
|
147
|
+
headers: { "Content-Type": "application/json" },
|
|
148
|
+
body: JSON.stringify(payload),
|
|
149
|
+
});
|
|
150
|
+
const result = await response.json();
|
|
151
|
+
if (result.success) {
|
|
152
|
+
alert(
|
|
153
|
+
"Вы успешно записаны на прием! Талон добавлен в вашу медицинскую карту.",
|
|
154
|
+
);
|
|
155
|
+
document.getElementById("bookingForm").reset();
|
|
156
|
+
await loadPatientData();
|
|
157
|
+
} else {
|
|
158
|
+
alert("Ошибка бронирования: " + result.error);
|
|
140
159
|
}
|
|
141
|
-
})
|
|
160
|
+
} catch (err) {
|
|
161
|
+
alert("Ошибка сети при попытке записи");
|
|
162
|
+
}
|
|
163
|
+
});
|
package/server/midleware.js
CHANGED
|
@@ -1,16 +1,21 @@
|
|
|
1
|
-
const jwt = require(
|
|
2
|
-
const { SPECIALTY_PERMISSIONS } = require(
|
|
1
|
+
const jwt = require("jsonwebtoken");
|
|
2
|
+
const { SPECIALTY_PERMISSIONS } = require("./permissions");
|
|
3
3
|
|
|
4
|
-
module.exports = function(jwtSecret) {
|
|
4
|
+
module.exports = function (jwtSecret) {
|
|
5
5
|
return {
|
|
6
6
|
/**
|
|
7
7
|
* Основная проверка авторизации по HttpOnly куке
|
|
8
8
|
*/
|
|
9
9
|
verifyCookie: (req, res, next) => {
|
|
10
10
|
const token = req.cookies.med_auth_token;
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
if (!token) {
|
|
13
|
-
return res
|
|
13
|
+
return res
|
|
14
|
+
.status(401)
|
|
15
|
+
.json({
|
|
16
|
+
success: false,
|
|
17
|
+
message: "Доступ запрещен. Пожалуйста, войдите в систему.",
|
|
18
|
+
});
|
|
14
19
|
}
|
|
15
20
|
|
|
16
21
|
try {
|
|
@@ -18,7 +23,12 @@ module.exports = function(jwtSecret) {
|
|
|
18
23
|
req.user = decoded; // Добавляем в req: id, role, specialty
|
|
19
24
|
next();
|
|
20
25
|
} catch (err) {
|
|
21
|
-
return res
|
|
26
|
+
return res
|
|
27
|
+
.status(401)
|
|
28
|
+
.json({
|
|
29
|
+
success: false,
|
|
30
|
+
message: "Ваша сессия устарела. Войдите заново.",
|
|
31
|
+
});
|
|
22
32
|
}
|
|
23
33
|
},
|
|
24
34
|
|
|
@@ -28,7 +38,12 @@ module.exports = function(jwtSecret) {
|
|
|
28
38
|
requireRole: (allowedRoles) => {
|
|
29
39
|
return (req, res, next) => {
|
|
30
40
|
if (!req.user || !allowedRoles.includes(req.user.role)) {
|
|
31
|
-
return res
|
|
41
|
+
return res
|
|
42
|
+
.status(403)
|
|
43
|
+
.json({
|
|
44
|
+
success: false,
|
|
45
|
+
message: "Недостаточно прав для выполнения этого действия.",
|
|
46
|
+
});
|
|
32
47
|
}
|
|
33
48
|
next();
|
|
34
49
|
};
|
|
@@ -40,26 +55,31 @@ module.exports = function(jwtSecret) {
|
|
|
40
55
|
checkPermission: (requiredPermission) => {
|
|
41
56
|
return (req, res, next) => {
|
|
42
57
|
// Администраторам разрешаем любые медицинские эндпоинты по дефолту
|
|
43
|
-
if (req.user && req.user.role ===
|
|
58
|
+
if (req.user && req.user.role === "admin") {
|
|
44
59
|
return next();
|
|
45
60
|
}
|
|
46
61
|
|
|
47
62
|
const doctorSpecialty = req.user?.specialty;
|
|
48
63
|
if (!doctorSpecialty) {
|
|
49
|
-
return res
|
|
64
|
+
return res
|
|
65
|
+
.status(403)
|
|
66
|
+
.json({
|
|
67
|
+
success: false,
|
|
68
|
+
message: "Действие доступно только медицинскому персоналу.",
|
|
69
|
+
});
|
|
50
70
|
}
|
|
51
71
|
|
|
52
72
|
const allowedPermissions = SPECIALTY_PERMISSIONS[doctorSpecialty] || [];
|
|
53
73
|
|
|
54
74
|
if (!allowedPermissions.includes(requiredPermission)) {
|
|
55
|
-
return res.status(403).json({
|
|
56
|
-
success: false,
|
|
57
|
-
message: `У специальности "${doctorSpecialty}" нет прав на действие: ${requiredPermission}
|
|
75
|
+
return res.status(403).json({
|
|
76
|
+
success: false,
|
|
77
|
+
message: `У специальности "${doctorSpecialty}" нет прав на действие: ${requiredPermission}`,
|
|
58
78
|
});
|
|
59
79
|
}
|
|
60
80
|
|
|
61
81
|
next();
|
|
62
82
|
};
|
|
63
|
-
}
|
|
83
|
+
},
|
|
64
84
|
};
|
|
65
85
|
};
|
package/server/permissions.js
CHANGED
|
@@ -1,47 +1,109 @@
|
|
|
1
1
|
const MED_PERMISSIONS = {
|
|
2
|
-
WRITE_RECIPE:
|
|
3
|
-
WRITE_SICK_LEAVE:
|
|
4
|
-
SCHEDULE_SURGERY:
|
|
5
|
-
UPLOAD_SCAN_RESULTS:
|
|
6
|
-
WRITE_PSYCH_REPORT:
|
|
7
|
-
WRITE_AUTOPSY_REPORT:
|
|
8
|
-
GYNECOLOGY_EXAM:
|
|
9
|
-
PRESCRIBE_GLASSES:
|
|
2
|
+
WRITE_RECIPE: "write_recipe",
|
|
3
|
+
WRITE_SICK_LEAVE: "write_sick_leave",
|
|
4
|
+
SCHEDULE_SURGERY: "schedule_surgery",
|
|
5
|
+
UPLOAD_SCAN_RESULTS: "upload_scan_results",
|
|
6
|
+
WRITE_PSYCH_REPORT: "write_psych_report",
|
|
7
|
+
WRITE_AUTOPSY_REPORT: "write_autopsy",
|
|
8
|
+
GYNECOLOGY_EXAM: "gynecology_exam",
|
|
9
|
+
PRESCRIBE_GLASSES: "prescribe_glasses",
|
|
10
10
|
};
|
|
11
11
|
const SPECIALTY_PERMISSIONS = {
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
12
|
+
Терапевт: [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
|
|
13
|
+
Педиатр: [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
|
|
14
|
+
"Врач общей практики": [
|
|
15
|
+
MED_PERMISSIONS.WRITE_RECIPE,
|
|
16
|
+
MED_PERMISSIONS.WRITE_SICK_LEAVE,
|
|
17
|
+
],
|
|
18
|
+
Кардиолог: [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
|
|
19
|
+
Невролог: [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
|
|
20
|
+
Эндокринолог: [
|
|
21
|
+
MED_PERMISSIONS.WRITE_RECIPE,
|
|
22
|
+
MED_PERMISSIONS.WRITE_SICK_LEAVE,
|
|
23
|
+
],
|
|
24
|
+
Гастроэнтеролог: [
|
|
25
|
+
MED_PERMISSIONS.WRITE_RECIPE,
|
|
26
|
+
MED_PERMISSIONS.WRITE_SICK_LEAVE,
|
|
27
|
+
],
|
|
28
|
+
Пульмонолог: [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
|
|
29
|
+
Нефролог: [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
|
|
30
|
+
Ревматолог: [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
|
|
31
|
+
Гематолог: [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
|
|
32
|
+
Онколог: [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
|
|
33
|
+
Инфекционист: [
|
|
34
|
+
MED_PERMISSIONS.WRITE_RECIPE,
|
|
35
|
+
MED_PERMISSIONS.WRITE_SICK_LEAVE,
|
|
36
|
+
],
|
|
37
|
+
"Аллерголог-иммунолог": [
|
|
38
|
+
MED_PERMISSIONS.WRITE_RECIPE,
|
|
39
|
+
MED_PERMISSIONS.WRITE_SICK_LEAVE,
|
|
40
|
+
],
|
|
41
|
+
Дерматолог: [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
|
|
42
|
+
Уролог: [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
|
|
43
|
+
Хирург: [
|
|
44
|
+
MED_PERMISSIONS.WRITE_RECIPE,
|
|
45
|
+
MED_PERMISSIONS.WRITE_SICK_LEAVE,
|
|
46
|
+
MED_PERMISSIONS.SCHEDULE_SURGERY,
|
|
47
|
+
],
|
|
48
|
+
"Травматолог-ортопед": [
|
|
49
|
+
MED_PERMISSIONS.WRITE_RECIPE,
|
|
50
|
+
MED_PERMISSIONS.WRITE_SICK_LEAVE,
|
|
51
|
+
MED_PERMISSIONS.SCHEDULE_SURGERY,
|
|
52
|
+
],
|
|
53
|
+
"Сосудистый хирург": [
|
|
54
|
+
MED_PERMISSIONS.WRITE_RECIPE,
|
|
55
|
+
MED_PERMISSIONS.WRITE_SICK_LEAVE,
|
|
56
|
+
MED_PERMISSIONS.SCHEDULE_SURGERY,
|
|
57
|
+
],
|
|
58
|
+
Нейрохирург: [
|
|
59
|
+
MED_PERMISSIONS.WRITE_RECIPE,
|
|
60
|
+
MED_PERMISSIONS.WRITE_SICK_LEAVE,
|
|
61
|
+
MED_PERMISSIONS.SCHEDULE_SURGERY,
|
|
62
|
+
],
|
|
63
|
+
Кардиохирург: [
|
|
64
|
+
MED_PERMISSIONS.WRITE_RECIPE,
|
|
65
|
+
MED_PERMISSIONS.WRITE_SICK_LEAVE,
|
|
66
|
+
MED_PERMISSIONS.SCHEDULE_SURGERY,
|
|
67
|
+
],
|
|
68
|
+
"Пластический хирург": [
|
|
69
|
+
MED_PERMISSIONS.WRITE_RECIPE,
|
|
70
|
+
MED_PERMISSIONS.WRITE_SICK_LEAVE,
|
|
71
|
+
MED_PERMISSIONS.SCHEDULE_SURGERY,
|
|
72
|
+
],
|
|
73
|
+
Офтальмолог: [
|
|
74
|
+
MED_PERMISSIONS.WRITE_RECIPE,
|
|
75
|
+
MED_PERMISSIONS.WRITE_SICK_LEAVE,
|
|
76
|
+
MED_PERMISSIONS.PRESCRIBE_GLASSES,
|
|
77
|
+
],
|
|
78
|
+
Отоларинголог: [
|
|
79
|
+
MED_PERMISSIONS.WRITE_RECIPE,
|
|
80
|
+
MED_PERMISSIONS.WRITE_SICK_LEAVE,
|
|
81
|
+
],
|
|
82
|
+
Стоматолог: [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
|
|
83
|
+
Гинеколог: [
|
|
84
|
+
MED_PERMISSIONS.WRITE_RECIPE,
|
|
85
|
+
MED_PERMISSIONS.WRITE_SICK_LEAVE,
|
|
86
|
+
MED_PERMISSIONS.GYNECOLOGY_EXAM,
|
|
87
|
+
],
|
|
88
|
+
Психиатр: [
|
|
89
|
+
MED_PERMISSIONS.WRITE_RECIPE,
|
|
90
|
+
MED_PERMISSIONS.WRITE_SICK_LEAVE,
|
|
91
|
+
MED_PERMISSIONS.WRITE_PSYCH_REPORT,
|
|
92
|
+
],
|
|
93
|
+
Психотерапевт: [
|
|
94
|
+
MED_PERMISSIONS.WRITE_RECIPE,
|
|
95
|
+
MED_PERMISSIONS.WRITE_SICK_LEAVE,
|
|
96
|
+
MED_PERMISSIONS.WRITE_PSYCH_REPORT,
|
|
97
|
+
],
|
|
98
|
+
Нарколог: [
|
|
99
|
+
MED_PERMISSIONS.WRITE_RECIPE,
|
|
100
|
+
MED_PERMISSIONS.WRITE_SICK_LEAVE,
|
|
101
|
+
MED_PERMISSIONS.WRITE_PSYCH_REPORT,
|
|
102
|
+
],
|
|
103
|
+
Рентгенолог: [MED_PERMISSIONS.UPLOAD_SCAN_RESULTS],
|
|
104
|
+
"Врач УЗД": [MED_PERMISSIONS.UPLOAD_SCAN_RESULTS],
|
|
105
|
+
Эндоскопист: [MED_PERMISSIONS.UPLOAD_SCAN_RESULTS],
|
|
106
|
+
"Анестезиолог-реаниматолог": [MED_PERMISSIONS.WRITE_RECIPE],
|
|
107
|
+
Патологоанатом: [MED_PERMISSIONS.WRITE_AUTOPSY_REPORT],
|
|
46
108
|
};
|
|
47
|
-
module.exports = { MED_PERMISSIONS, SPECIALTY_PERMISSIONS };
|
|
109
|
+
module.exports = { MED_PERMISSIONS, SPECIALTY_PERMISSIONS };
|