/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package beans.doctor.diagnosis;
import beans.UserRightsSet;
import framework.beans.EntityDetails;
import beans.doctor.MedicalDataBean;
import beans.directory.mkb10.entity.Mkb10;
import beans.directory.simple.entities.DiagnosisEncounter;
import beans.directory.simple.entities.DiagnosisType;
import beans.directory.simple.entities.TraumaType;
import beans.service.ServiceRender;
import beans.doctor.sicklist.entity.Sicklist;
import beans.followup.entity.Followup;
import framework.audit.AuditDoc;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import framework.generic.ClipsServerException;
import framework.generic.EDataIntegrity;
import framework.generic.ESecurity;
import javax.ejb.EJBException;
import javax.ejb.Stateful;
import javax.persistence.Query;
import framework.security.RightChecker;
import framework.utils.DateTimeUtils;
import java.util.Date;
/**
* @security - Ok.
* Integrity - may be Ok.
* @author axe
*/
@Stateful(mappedName="clips-beans/DiagnosisBean")
public class DiagnosisBean extends MedicalDataBean<Diagnosis>
implements DiagnosisBeanRemote {
public DiagnosisBean() {
super(Diagnosis.class);
}
/**
* Обновляет данные сущности.
* @param details новые детали сущности
* @throws ClipsServerException
* @throws EJBException в случае если обновление отвергнуто системой
* безопастности либо произошла ошибка
* Безопасность.
* Установка прав для мед. данных Рецептов, рекоммендаций, направлений, противопоказаний,
* диагнозов и осмотров. Читать можно только по READ_MEDICAL_DATA.
* Изменять и удалять по WRITE_MEDICAL_DATA_DURING_DAY и WRITE_MEDICAL_DATA_ANY_TIME.
* Для осмотров ещё два, менее мощных права WRITE_CHECKUP_DURING_DAY и WRITE_CHECKUP_ANY_TIME.
* XXX_DURING_DAY - позволяет писать данные, если услуга не выполнена или выполнена в течении
* текущего дня, изменять данные может только сотрудник, создавший запись.
* XXX_ANY_TIME - позволяет редактировать любую запись, без ограничений.
*/
@Override
protected void onUpdate(Diagnosis entity, EntityDetails details,
AuditDoc auditDoc, List<AuditDoc> auditDocList) throws ClipsServerException {
super.onUpdate(entity, details, auditDoc, auditDocList);
// после того как дигноз был назначен больничному его нельзя изменять
if (entity.getId() != 0){
if (findEntityList(Sicklist.class, "diagOpen.id", entity.getId()).size() > 0
|| findEntityList(Sicklist.class, "diagClose.id", entity.getId()).size() > 0){
if (RightPresence(UserRightsSet.WRITE_MEDICAL_DATA_ANY_TIME.id) < 0){
throw new ESecurity("По этому диагнозу был выдан больничный лист, для его изменения вы должны облодать как минимум правом \"" + UserRightsSet.WRITE_MEDICAL_DATA_ANY_TIME.getDescription() + "\"");
}
}
}
DiagnosisDetails d = (DiagnosisDetails) details;
if(entity.getId() != 0) {
if(entity.getServiceRender().getId() != d.serviceRenderID) {
throw new ESecurity("Cмена услуги недопустима");
}
} else {
if (!DateTimeUtils.belongsToCurrentDay(d.date)
&& !hasRight(UserRightsSet.WRITE_STATISTIC_MEDICAL_DATA)) {
throwNeedAdminSecurityException("Недостаточно прав для записи диагноза другой датой");
}
entity.setDate(d.date);
entity.setServiceRender(findEntity(ServiceRender.class, d.serviceRenderID));
}
Mkb10 mkb10 = findEntity(Mkb10.class, d.mkbID);
if (mustHaveStage(mkb10) && d.stage == 0) {
throw new ClipsServerException("При постановке диагноза " + mkb10.getTitle()
+ "\nнеобходимо указывать стадию заболевания");
}
entity.setMkb10(mkb10);
entity.setComplication(d.complicationID == 0 ? null : findEntity(Mkb10.class, d.complicationID));
entity.setAuthor(d.author);
entity.setEncounter(d.encounter == 0 ? null : findEntity(DiagnosisEncounter.class, d.encounter));
entity.setType(findEntity(DiagnosisType.class, d.type));
entity.setStage(d.stage == 0 ? null : d.stage);
entity.setTraumaType(d.traumaTypeID == 0 ? null : findEntity(TraumaType.class, d.traumaTypeID));
Diagnosis ref = d.referenced == 0 ? null : findEntity(Diagnosis.class, d.referenced);
if(ref != null
&&ref.getServiceRender().getId() != entity.getServiceRender().getId()) {
throw new EDataIntegrity("Связанные диагнозы должны быть в одной услуге");
}
entity.setReferenced(ref);
}
@Override
protected void onRemove(Diagnosis entity, List<AuditDoc> auditDocList) throws ClipsServerException {
super.onRemove(entity, auditDocList);
checkPossibilityRemove(entity);
deleteEntityList2(Diagnosis.class,
new Field [] { new Field("referenced", entity) },
auditDocList
);
}
/**
* Возвращает список сопуствующих диагнозов
* @return сопутствующие диагнозы
*/
@Override
public List<DiagnosisDetails> getAccomplichedDiagnosisList() throws ClipsServerException {
Diagnosis entity = getExistentEntity();
Field field[] = {
new Field("serviceRender", entity.getServiceRender()),
new Field("referenced", entity)
};
Collection<Diagnosis> list = findEntityList(Diagnosis.class, field);
List<DiagnosisDetails> res = new ArrayList<DiagnosisDetails>();
Iterator<Diagnosis> i = list.iterator();
while(i.hasNext()) {
Diagnosis j = (Diagnosis) i.next();
res.add(j.getDetails((RightChecker) this));
}
return res;
}
@Override
protected void afterUpdate(Diagnosis entity, boolean isNewEntity,
EntityDetails details, List<AuditDoc> auditDocList) throws ClipsServerException {
super.afterUpdate(entity, isNewEntity, details, auditDocList);
if (entity.getType().getId() != DiagnosisType.DIAGNOSIS_TYPE_PRELIMINARY && entity.getReferenced() == null){
String sql = "SELECT d FROM Diagnosis d "
+ "WHERE d.serviceRender.disease=:st AND d.type.id=:dt AND d<>:this";
Query q = manager.createQuery(sql);
q.setParameter("st", entity.getServiceRender().getDisease());
q.setParameter("this", entity);
q.setParameter("dt", DiagnosisType.DIAGNOSIS_TYPE_FINAL);
Iterator it = q.getResultList().iterator();
while (it.hasNext()) {
Diagnosis d = (Diagnosis)it.next();
AuditDoc<Diagnosis> auditDoc = new AuditDoc<Diagnosis>(d, getCollaborator());
d.setType(findEntity(DiagnosisType.class, DiagnosisType.DIAGNOSIS_TYPE_PRELIMINARY));
checkAudit(auditDocList, auditDoc, d);
manager.merge(d);
}
manager.flush();
}
}
private void checkPossibilityRemove(Diagnosis entity) throws ClipsServerException {
int size = findEntityList(Sicklist.class, new Field[]{new Field("diagOpen", entity)}).size();
size += findEntityList(Sicklist.class, new Field[]{new Field("diagClose", entity)}).size();
if (size > 0) {
throw new ClipsServerException("Диагноз указан в больничном, удаление невозможно");
}
size = findEntityList(Followup.class, new Field[]{new Field("diagnosisUp", entity)}).size();
if (size > 0) {
throw new ClipsServerException("Диагноз указан в диспансерном учете, удаление невозможно");
}
}
/**
* Должна присутствовать стадия заболевания
* @param mkb10
* @return
*/
private boolean mustHaveStage(final Mkb10 mkb10) {
//Алкогольная зависимость
if (mkb10.getId() == Mkb10.MKB10_ALCOHOL_DEPENDENCE) {
return true;
}
//Злокачественные новообразования
boolean isMN = false;
Mkb10 m = mkb10;
do {
if (m.getId() == Mkb10.MKB10_MALIGNANT_NEOPLASM) {
isMN = true;
}
m = m.getRef();
} while (m != null);
return isMN;
}
@Override
public boolean mustHaveStage(int mkbID) throws ClipsServerException{
Mkb10 mkb10 = findEntity(Mkb10.class, mkbID);
return mustHaveStage(mkb10);
}
}