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,141 +1,163 @@
1
- document.addEventListener('DOMContentLoaded', () => {
2
- loadPatientData();
3
- loadDoctorsForBooking();
1
+ document.addEventListener("DOMContentLoaded", () => {
2
+ loadPatientData();
3
+ loadDoctorsForBooking();
4
4
  });
5
+
5
6
  async function loadPatientData() {
6
- try {
7
- const response = await fetch('/med/api/patient/me');
8
- const result = await response.json();
9
- if (!result.success) {
10
- alert('Ошибка загрузки данных: ' + result.message);
11
- window.location.href = '/med/html/login.html';
12
- return;
13
- }
14
- const data = result.data;
15
- document.getElementById('patientName').textContent = data.personalInfo.fullName;
16
- document.getElementById('patientEmail').textContent = data.personalInfo.email;
17
- const districtInfo = document.getElementById('districtInfo');
18
- if (data.personalInfo.UserAddress) {
19
- const addr = data.personalInfo.UserAddress;
20
- districtInfo.innerHTML = `
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
- document.getElementById('addrCity').value = addr.city;
26
- document.getElementById('addrStreet').value = addr.street;
27
- document.getElementById('addrHouse').value = addr.houseNumber;
28
- }
29
- const historyContainer = document.getElementById('medicalHistoryList');
30
- historyContainer.innerHTML = '';
31
- if (data.medicalHistory && data.medicalHistory.length > 0) {
32
- data.medicalHistory.forEach(record => {
33
- const card = document.createElement('div');
34
- if (record.status === 'ожидается') {
35
- card.className = 'record-card future';
36
- card.innerHTML = `
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
- } else if (record.status === 'завершен') {
44
- card.className = 'record-card';
45
- card.innerHTML = `
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 || '—'}</p>
52
- <p style="margin: 4px 0; font-size:14px;"><b>Данные осмотра:</b> ${record.objectively || '—'}</p>
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
- } catch (err) {
65
- console.error('Ошибка связи с сервером:', err);
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
- document.getElementById('addressForm').addEventListener('submit', async (e) => {
69
- e.preventDefault();
70
- const payload = {
71
- city: document.getElementById('addrCity').value,
72
- street: document.getElementById('addrStreet').value,
73
- houseNumber: document.getElementById('addrHouse').value
74
- };
75
- try {
76
- const response = await fetch('/med/api/patient/address', {
77
- method: 'POST',
78
- headers: { 'Content-Type': 'application/json' },
79
- body: JSON.stringify(payload)
80
- });
81
- const result = await response.json();
82
- if (result.success) {
83
- alert('Адрес сохранен! Система автоматически пересчитала ваш лечебный участок.');
84
- loadPatientData();
85
- } else {
86
- alert('Ошибка: ' + result.error);
87
- }
88
- } catch (err) {
89
- alert('Ошибка сети при отправке адреса');
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
- await fetch('/med-api/auth/logout', { method: 'POST' });
94
- window.location.href = '/med/html/login.html';
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
- try {
98
- const response = await fetch('/med/api/patient/doctors-list');
99
- const result = await response.json();
100
- const select = document.getElementById('bookingDoctor');
101
- select.innerHTML = '<option value="">-- Выберите врача --</option>';
102
- if (result.success && result.data.length > 0) {
103
- result.data.forEach(doc => {
104
- const opt = document.createElement('option');
105
- opt.value = doc.id;
106
- const clinicInfo = doc.Clinic ? ` (${doc.Clinic.name})` : '';
107
- opt.textContent = `${doc.specialty} — ${doc.fullName}${clinicInfo}`;
108
- select.appendChild(opt);
109
- });
110
- } else {
111
- select.innerHTML = '<option value="">Врачи пока не зарегистрированы в CMS</option>';
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
- document.getElementById('bookingForm').addEventListener('submit', async (e) => {
118
- e.preventDefault();
119
- const payload = {
120
- doctorId: document.getElementById('bookingDoctor').value,
121
- date: document.getElementById('bookingDate').value,
122
- time: document.getElementById('bookingTime').value
123
- };
124
- try {
125
- const response = await fetch('/med/api/patient/book', {
126
- method: 'POST',
127
- headers: { 'Content-Type': 'application/json' },
128
- body: JSON.stringify(payload)
129
- });
130
- const result = await response.json();
131
- if (result.success) {
132
- alert('Вы успешно записаны на прием! Талон добавлен в вашу медицинскую карту.');
133
- document.getElementById('bookingForm').reset();
134
- await loadPatientData();
135
- } else {
136
- alert('Ошибка бронирования: ' + result.error);
137
- }
138
- } catch (err) {
139
- alert('Ошибка сети при попытке записи');
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
+ });
@@ -1,16 +1,21 @@
1
- const jwt = require('jsonwebtoken');
2
- const { SPECIALTY_PERMISSIONS } = require('./permissions');
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.status(401).json({ success: false, message: 'Доступ запрещен. Пожалуйста, войдите в систему.' });
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.status(401).json({ success: false, message: 'Ваша сессия устарела. Войдите заново.' });
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.status(403).json({ success: false, message: 'Недостаточно прав для выполнения этого действия.' });
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 === 'admin') {
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.status(403).json({ success: false, message: 'Действие доступно только медицинскому персоналу.' });
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
  };
@@ -1,47 +1,109 @@
1
1
  const MED_PERMISSIONS = {
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',
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
- 'Терапевт': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
13
- 'Педиатр': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
14
- 'Врач общей практики': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
15
- 'Кардиолог': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
16
- 'Невролог': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
17
- 'Эндокринолог': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
18
- 'Гастроэнтеролог': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
19
- 'Пульмонолог': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
20
- 'Нефролог': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
21
- 'Ревматолог': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
22
- 'Гематолог': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
23
- 'Онколог': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
24
- 'Инфекционист': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
25
- 'Аллерголог-иммунолог': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
26
- 'Дерматолог': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
27
- 'Уролог': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
28
- 'Хирург': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE, MED_PERMISSIONS.SCHEDULE_SURGERY],
29
- 'Травматолог-ортопед': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE, MED_PERMISSIONS.SCHEDULE_SURGERY],
30
- 'Сосудистый хирург': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE, MED_PERMISSIONS.SCHEDULE_SURGERY],
31
- 'Нейрохирург': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE, MED_PERMISSIONS.SCHEDULE_SURGERY],
32
- 'Кардиохирург': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE, MED_PERMISSIONS.SCHEDULE_SURGERY],
33
- 'Пластический хирург': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE, MED_PERMISSIONS.SCHEDULE_SURGERY],
34
- 'Офтальмолог': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE, MED_PERMISSIONS.PRESCRIBE_GLASSES],
35
- 'Отоларинголог': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
36
- 'Стоматолог': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE],
37
- 'Гинеколог': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE, MED_PERMISSIONS.GYNECOLOGY_EXAM],
38
- 'Психиатр': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE, MED_PERMISSIONS.WRITE_PSYCH_REPORT],
39
- 'Психотерапевт': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE, MED_PERMISSIONS.WRITE_PSYCH_REPORT],
40
- 'Нарколог': [MED_PERMISSIONS.WRITE_RECIPE, MED_PERMISSIONS.WRITE_SICK_LEAVE, MED_PERMISSIONS.WRITE_PSYCH_REPORT],
41
- 'Рентгенолог': [MED_PERMISSIONS.UPLOAD_SCAN_RESULTS],
42
- 'Врач УЗД': [MED_PERMISSIONS.UPLOAD_SCAN_RESULTS],
43
- 'Эндоскопист': [MED_PERMISSIONS.UPLOAD_SCAN_RESULTS],
44
- 'Анестезиолог-реаниматолог': [MED_PERMISSIONS.WRITE_RECIPE],
45
- 'Патологоанатом': [MED_PERMISSIONS.WRITE_AUTOPSY_REPORT]
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 };