release 1.3
This commit is contained in:
@@ -86,8 +86,10 @@ async def update(reqData: dict = Depends(requestDict)):
|
||||
).replace(hour=12, minute=0, second=0)
|
||||
if "attorney" in updatePractitioner and updatePractitioner["attorney"] != "":
|
||||
logger.info("🔐 МЧД получена")
|
||||
updatePractitioner["esiaAuth"] = False
|
||||
if "signature" in updatePractitioner:
|
||||
logger.info("🔐 УКЭП получен")
|
||||
updatePractitioner["esiaAuth"] = True
|
||||
fileData = updatePractitioner.pop("signature")
|
||||
fileInfo = p7s_save(fileData, updatePractitioner["userIdLpu"])
|
||||
if fileInfo.success:
|
||||
|
||||
@@ -353,6 +353,7 @@ function updateStaffTable() {
|
||||
}
|
||||
|
||||
let rows = '';
|
||||
const showDisabled = document.getElementById('showDisabled').checked;
|
||||
|
||||
filteredPractitioners.forEach(practitioner => {
|
||||
// Проверяем, что practitioner - объект
|
||||
@@ -361,6 +362,10 @@ function updateStaffTable() {
|
||||
return;
|
||||
}
|
||||
|
||||
const isDisabled = practitioner.expired_at === null;
|
||||
|
||||
if (!showDisabled && isDisabled) return;
|
||||
|
||||
// Определяем тип подписи
|
||||
let signatureTypeHtml;
|
||||
if (practitioner.esiaAuth) {
|
||||
@@ -382,8 +387,9 @@ function updateStaffTable() {
|
||||
onclick="showAttorneyPopup('${snils}', this)">
|
||||
<i class="bi bi-eye"></i>
|
||||
</button>`;
|
||||
signatureTypeHtml = `<span class="badge bg-warning text-dark">МЧД</span>${eyeIcon}
|
||||
<span class="badge bg-info">СНИЛС</span>${snilsIcon}`;
|
||||
mchdBadge = `<span class="badge bg-warning text-dark">МЧД</span>${eyeIcon}`;
|
||||
slilsBadge = `<span class="badge bg-info">СНИЛС</span>${snilsIcon}`;
|
||||
signatureTypeHtml = isDisabled ? slilsBadge : `${mchdBadge} ${slilsBadge}`;
|
||||
}
|
||||
|
||||
// Форматируем дату и проверяем срок
|
||||
@@ -417,25 +423,40 @@ function updateStaffTable() {
|
||||
} else {
|
||||
expiryHtml = `
|
||||
<div class="d-flex align-items-center justify-content-between">
|
||||
<span class="text-muted">Не установлен</span>
|
||||
<span class="badge bg-secondary ms-2">-</span>
|
||||
<span class="text-muted">Без права подписи</span>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
// Кнопки действий
|
||||
const actionsHtml = `
|
||||
let actionsHtml = '';
|
||||
if (isDisabled) {
|
||||
actionsHtml = `
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
<button type="button" class="btn btn-outline-success"
|
||||
onclick="editPractitioner('${practitioner.userIdLpu}', true)" title="Добавить УКЭП">
|
||||
<i class="bi bi-filetype-key"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-secondary"
|
||||
onclick="editPractitioner('${practitioner.userIdLpu}', false)" title="Добавить МЧД">
|
||||
<i class="bi bi-file-earmark-binary"></i>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
actionsHtml = `
|
||||
<div class="btn-group btn-group-sm" role="group">
|
||||
<button type="button" class="btn btn-outline-primary"
|
||||
onclick="editPractitioner('${practitioner.userIdLpu}', ${practitioner.esiaAuth})" title="Изменить">
|
||||
<i class="bi bi-pencil"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-outline-danger"
|
||||
onclick="confirmDelete('${practitioner.userIdLpu}')" title="Удалить">
|
||||
<i class="bi bi-trash"></i>
|
||||
onclick="confirmDelete('${practitioner.userIdLpu}')" title="Отключить">
|
||||
<i class="bi bi-person-fill-slash"></i>
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
rows += `
|
||||
<tr>
|
||||
@@ -642,6 +663,7 @@ function editPractitioner(userIdLpu, isEsiaAuth) {
|
||||
document.getElementById('ukepPractitionerId').value = userIdLpu;
|
||||
document.getElementById('ukepFile').required = false;
|
||||
document.getElementById('ukepSnilsNumber').value = practitioner.snils;
|
||||
document.getElementById('ukepExpiryDate').value = practitioner.expired_at || '';
|
||||
|
||||
// Очищаем data-атрибуты модального окна
|
||||
const modal = document.getElementById('editUKEPModal');
|
||||
@@ -663,6 +685,7 @@ function editPractitioner(userIdLpu, isEsiaAuth) {
|
||||
document.getElementById('mchdPractitionerId').value = userIdLpu;
|
||||
document.getElementById('mchdNumber').value = practitioner.attorney || '';
|
||||
document.getElementById('mchdSnilsNumber').value = practitioner.snils;
|
||||
document.getElementById('mchdExpiryDate').value = practitioner.expired_at || '';
|
||||
|
||||
// Очищаем data-атрибуты модального окна
|
||||
const modal = document.getElementById('editMCHDModal');
|
||||
@@ -1093,6 +1116,7 @@ document.addEventListener('DOMContentLoaded', function () {
|
||||
// Обработчики попапа с номером МЧД
|
||||
document.getElementById('closeAttorneyPopupBtn').addEventListener('click', hideAttorneyPopup);
|
||||
document.getElementById('closeAttorneyBtn').addEventListener('click', hideAttorneyPopup);
|
||||
document.getElementById('showDisabled').addEventListener('click', updateStaffTable);
|
||||
|
||||
document.getElementById('copyAttorneyBtn').addEventListener('click', function () {
|
||||
const attorneyNumber = document.getElementById('attorneyNumber').textContent;
|
||||
|
||||
@@ -88,9 +88,15 @@
|
||||
|
||||
<!-- Кнопка добавления -->
|
||||
<div class="text-end mt-3">
|
||||
<button type="button" id="addStaffBtn" class="btn btn-primary">
|
||||
<i class="bi bi-plus-circle"></i> Добавить сотрудника
|
||||
</button>
|
||||
<div class="d-flex align-items-center justify-content-end">
|
||||
<div class="form-check d-flex align-items-center me-2">
|
||||
<input type="checkbox" class="form-check-input" id="showDisabled">
|
||||
<label class="form-check-label ms-1" for="showDisabled">Отображать сотрудников без права подписи</label>
|
||||
</div>
|
||||
<button type="button" id="addStaffBtn" class="btn btn-primary">
|
||||
<i class="bi bi-plus-circle"></i> Добавить сотрудника
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -211,22 +217,22 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Модальное окно подтверждения удаления -->
|
||||
<!-- Модальное окно подтверждения отключения -->
|
||||
<div class="modal fade" id="confirmDeleteModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">Подтверждение удаления</h5>
|
||||
<h5 class="modal-title">Подтверждение отключения</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Вы уверены, что хотите удалить данные сотрудника?</p>
|
||||
<p class="text-danger fw-bold">Это действие нельзя отменить.</p>
|
||||
<p>Вы уверены, что хотите отключить данного сотрудника?</p>
|
||||
<p class="text-danger fw-bold">Этот сотрудник не сможет отправлять запросы</p>
|
||||
<input type="hidden" id="deletePractitionerId">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Отмена</button>
|
||||
<button type="button" class="btn btn-danger" id="confirmDeleteBtn">Удалить</button>
|
||||
<button type="button" class="btn btn-danger" id="confirmDeleteBtn">Отключить</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -14,10 +14,10 @@ class Practitioner(Base):
|
||||
userIdLpu = Column(String, unique=True)
|
||||
name = Column(String)
|
||||
fullName = Column(String)
|
||||
esiaAuth = Column(Boolean)
|
||||
esiaAuth = Column(Boolean, nullable=True)
|
||||
attorney = Column(String, nullable=True)
|
||||
snils = Column(String)
|
||||
expired_at = Column(DateTime)
|
||||
expired_at = Column(DateTime, nullable=True)
|
||||
created_at = Column(DateTime, default=datetime.now)
|
||||
updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now)
|
||||
|
||||
@@ -35,7 +35,8 @@ class Practitioner(Base):
|
||||
return await CRUD.update(Practitioner, self.id, **kwargs)
|
||||
|
||||
async def delete(self) -> bool:
|
||||
return await CRUD.delete(self)
|
||||
clear = {"esiaAuth": None, "attorney": None, "expired_at": None}
|
||||
return await CRUD.update(Practitioner, self.id, **clear)
|
||||
|
||||
@staticmethod
|
||||
async def addPractitioner(**kwargs):
|
||||
@@ -79,13 +80,22 @@ class Practitioner(Base):
|
||||
|
||||
@staticmethod
|
||||
async def getPractitionerByIdLpu(
|
||||
idLpu: str, toDict: bool = True, isCheck: bool = False
|
||||
idLpu: str,
|
||||
toDict: bool = True,
|
||||
isCheck: bool = False,
|
||||
include_disabled: bool = False,
|
||||
):
|
||||
if type(idLpu) != str:
|
||||
idLpu = str(idLpu)
|
||||
practitioner = await CRUD.read(
|
||||
select(Practitioner).where(Practitioner.userIdLpu == idLpu)
|
||||
query = (
|
||||
select(Practitioner).where(
|
||||
Practitioner.userIdLpu == idLpu, Practitioner.expired_at != None
|
||||
)
|
||||
if not include_disabled
|
||||
else select(Practitioner).where(Practitioner.userIdLpu == idLpu)
|
||||
)
|
||||
|
||||
practitioner = await CRUD.read(query)
|
||||
if practitioner:
|
||||
data = practitioner.toDict() if toDict else practitioner
|
||||
return utils.answer(data=data)
|
||||
@@ -96,7 +106,9 @@ class Practitioner(Base):
|
||||
|
||||
@staticmethod
|
||||
async def editPractitionerByIdLpu(idLpu: str, **kwargs):
|
||||
practitioner = await Practitioner.getPractitionerByIdLpu(idLpu, False)
|
||||
practitioner = await Practitioner.getPractitionerByIdLpu(
|
||||
idLpu, False, include_disabled=True
|
||||
)
|
||||
if not practitioner.success:
|
||||
utils.logger.error(f"Сотрудник не найден, idLpu: {idLpu}")
|
||||
return utils.answer(success=False, message="Сотрудник не найден")
|
||||
|
||||
@@ -4,7 +4,6 @@ from .async_request import *
|
||||
from .logger import *
|
||||
from .attachment import *
|
||||
from .request_parser import RequestParser
|
||||
from .pdf_saver import *
|
||||
from .to_dict import *
|
||||
from .web import *
|
||||
|
||||
|
||||
Reference in New Issue
Block a user