/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package beans.service;
import beans.doctor.prescriptiondlo.PrescriptionDloDetails;
import framework.beans.EntityDetails;
import beans.discount.CalcDiscount;
import framework.beans.FacadeBean;
import framework.beans.security.BeanRights;
import beans.doctor.PacketService;
import beans.contract.entity.Polis;
import beans.contract.entity.PolisDetails;
import beans.contract.entity.ServicePrice;
import beans.contract.entity.ServicePriceDetails;
import beans.discount.entity.DiscountCard;
import beans.discount.entity.DiscountCardDetails;
import beans.doctor.checkup.Checkup;
import beans.doctor.checkup.CheckupDetails;
import beans.doctor.contraindication.Contraindication;
import beans.doctor.contraindication.ContraindicationDetails;
import beans.doctor.diagnosis.Diagnosis;
import beans.doctor.diagnosis.DiagnosisDetails;
import beans.doctor.direction.Direction;
import beans.doctor.direction.DirectionDetails;
import beans.doctor.prescription.Prescription;
import beans.doctor.prescription.PrescriptionDetails;
import beans.doctor.recommendation.Recommendation;
import beans.doctor.recommendation.RecommendationDetails;
import beans.expenditure.entity.Expenditure;
import beans.expenditure.entity.ExpenditureDetails;
import beans.directory.expenditure.entity.ExpenditureType;
import beans.directory.service.entity.Service;
import beans.doctor.disease.Disease;
import beans.user.collaborator.entities.Collaborator;
import framework.generic.ClipsServerException;
import framework.generic.EDataIntegrity;
import framework.generic.ESecurity;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.ejb.Stateful;
import javax.persistence.Query;
import beans.UserRightsSet;
import beans.directory.simple.entities.ReceptionType;
import beans.followup.entity.Followup;
import beans.directory.simple.entities.ServicingPlace;
import beans.doctor.prescriptiondlo.PrescriptionDlo;
import beans.service.medexam.MedSerrenResult;
import beans.doctor.sicklist.entity.SickLong;
import beans.doctor.sicklist.entity.Sicklist;
import beans.user.collaborator.entities.CollaboratorFunctions;
import framework.audit.AuditDetails;
import framework.audit.AuditDoc;
import framework.beans.ModificationInfo;
import framework.beans.collaborator.CollaboratorAbstract;
import framework.security.RightChecker;
import framework.utils.DateTimeUtils;
import java.util.LinkedList;
import javax.ejb.EJBException;
import javax.persistence.EntityManager;
/**
* Security - Ok.
* Integriy - may be Ok.
* @author axe
*/
@Stateful(mappedName="clips-beans/ServiceRenderBean")
public class ServiceRenderBean extends FacadeBean<ServiceRender>
implements ServiceRenderBeanRemote, ServiceRenderBeanLocal {
// public static final UserRights RIGHT_CREATION = UserRights.WRITE_PUBLIC_DATA;
public static final int COMMAND_READ_CONTRACT_MEMBER = 4;
public static final int COMMAND_READ_MEDICAL_DATA = 5;
public static final int COMMAND_SERVICE_RENDER_TRANSACTION_DETAIL = 6;
public static final int COMMAND_READ_SERVICE_RENDER_TRANSACTION_SUMM = 7;
public static final String NEED_SPECIFY_RECEPTION_TYPE = "Пользователь не имеет требуемого для оказания услуги типа приема";
public static final String HAVE_NOT_RECEPTION_TYPE = "Пользователь не имеет требуемого для оказания услуги типа приема";
public static final String NOT_COMPLIANCE_SPECIALITY = "Специальность врача должна не соответствует оказываемой услуге";
public ServiceRenderBean() {
super(ServiceRender.class);
}
@Override
protected void initBeanRights() throws ClipsServerException {
ServiceRender entity = (getId() == 0) ? null : getExistentEntity();
int[] r = new int[8];
r[COMMAND_READ] = RightPresence(UserRightsSet.READ_SERVICE_RENDER_DATA.id);
if (isSuperUser()) {
r[COMMAND_READ] = UserRightsSet.READ_SERVICE_RENDER_DATA.id;
}
/* команда создания услуги всегда недоступна - создание услуги
осуществляется через CreateServiceBean
*/
r[COMMAND_CREATE] = -UserRightsSet.CREATE_SERVICE_RENDER.id;
/* команда модификации и удаления
* Если услуга не в заболевании то команда доступна по праву записи
* мед. данных либо суперпользователю
* Если в заболевании то проверка такая же как и для других мед. данных
* (см. MedicalDataBean)
*/
if (entity != null) {
if (entity.getDisease() == null) {
//не в заболевании
r[COMMAND_MODIFY] = RightPresence(UserRightsSet.WRITE_MEDICAL_DATA_DURING_DAY.id);
r[COMMAND_REMOVE] = RightPresence(UserRightsSet.WRITE_MEDICAL_DATA_DURING_DAY.id);
if (isSuperUser()) {
r[COMMAND_MODIFY] = UserRightsSet.WRITE_MEDICAL_DATA_DURING_DAY.id;
r[COMMAND_REMOVE] = UserRightsSet.WRITE_MEDICAL_DATA_DURING_DAY.id;
}
} else {
//в заболевании
int modifyRight = 0;
if (RightPresence(UserRightsSet.WRITE_MEDICAL_DATA_DURING_DAY.id) > 0){
//Начинаем проверять со слабого права
modifyRight = entity.canWriteDuringDay(
isSuperUser(),
UserRightsSet.WRITE_MEDICAL_DATA_DURING_DAY,
getCollaboratorId());
}
if (RightPresence(UserRightsSet.WRITE_MEDICAL_DATA_ANY_TIME.id) > 0){
//Если есть более сильное право, то команда перезаписывается им
modifyRight = entity.canWriteAnyTime(
isSuperUser(),
UserRightsSet.WRITE_MEDICAL_DATA_ANY_TIME,
findEntity(Collaborator.class, getCollaboratorId()));
}
if (isSuperUser() && modifyRight <= 0) {
//Если суперюзер, и прав нету или запрет то всеравно разрешаем по самому сильному праву
modifyRight = UserRightsSet.WRITE_MEDICAL_DATA_ANY_TIME.id;
}
if (modifyRight == 0) {
modifyRight = -UserRightsSet.WRITE_MEDICAL_DATA_DURING_DAY.id;
}
r[COMMAND_MODIFY] = modifyRight;
r[COMMAND_REMOVE] = modifyRight;
}
}
/* Set Discount Card is out of there
int ds = (entity.getDiscountCard() == null) ?
RightPresence(UserRights.WRITE_SERVICE_RENDER_DISCOUNT_CARD.id) : 0;
r[COMMAND_WRITE_SERVICE_RENDER_DISCOUNT_CARD] = ds;
*/
r[COMMAND_READ_MEDICAL_DATA] = RightPresence(UserRightsSet.READ_MEDICAL_DATA.id);
r[COMMAND_READ_SERVICE_RENDER_TRANSACTION_SUMM] = RightPresence(UserRightsSet.READ_SERVICE_RENDER_TRANSACTION_SUMM.id);
r[COMMAND_SERVICE_RENDER_TRANSACTION_DETAIL] = RightPresence(UserRightsSet.READ_SERVICE_RENDER_TRANSACTION_DETAIL.id);
if (isSuperUser()) {
r[COMMAND_READ_MEDICAL_DATA] = UserRightsSet.READ_MEDICAL_DATA.id;
r[COMMAND_READ_SERVICE_RENDER_TRANSACTION_SUMM] = UserRightsSet.READ_SERVICE_RENDER_TRANSACTION_SUMM.id;
r[COMMAND_SERVICE_RENDER_TRANSACTION_DETAIL] = UserRightsSet.READ_SERVICE_RENDER_TRANSACTION_DETAIL.id;
}
rights = new BeanRights(r);
}
/**
* Обновляет данные сущности.
* @param entity
* @param details новые детали сущности
* @throws ClipsServerException в случае если обновление отвергнуто системой
* безопастности либо произошла ошибка
*
* Безопасность: Создание - запрещено, создание делает бин CreateServiceBean
* Модификация - свободная.
* Когда выполнена, снять флажёк выполненности можно только по WRITE_ADMIN_SERVICE_RENDER.
* Поля date, director, polis, service - можно установить только при создании.
* TODO переписать начисто
*/
@Override
protected void onUpdate(ServiceRender entity, EntityDetails details,
AuditDoc auditDoc, List<AuditDoc> auditDocList)
throws ClipsServerException {
checkPossibilityUpdate(entity, details);
ServiceRenderDetails d = (ServiceRenderDetails) details;
entity.setDate(d.date);
CollaboratorFunctions cf = d.functionsID == 0 ? null : findEntity(CollaboratorFunctions.class, d.functionsID);
//особо заебатые случаи проверки вынесены сюды
if (!entity.isRendered()) {//услуга не оказана
//услуга не оказана
if (d.functionsID != 0
&& findEntity(CollaboratorFunctions.class, d.functionsID).getCollaborator().getId() != getCollaboratorId()
&& !hasRight(UserRightsSet.WRITE_STATISTIC_MEDICAL_DATA)) {
throwNeedAdminSecurityException("У вас недостаточно прав, чтоб оказать услугу от имени другого пользователя");
}
if (d.functionsID != 0 && d.servPlaceID == 0) {
throw new EDataIntegrity("При оказании услуги необходимо указывать место обслуживания");
}
if (d.functionsID != 0
&& !DateTimeUtils.belongsToCurrentDay(d.renderDate)
&& !hasRight(UserRightsSet.WRITE_STATISTIC_MEDICAL_DATA)) {
throwNeedAdminSecurityException("У вас недостаточно прав, чтоб оказать услугу другой датой");
}
entity.setRenderedDate(d.functionsID == 0 ? null : d.renderDate);
//Если в услуге указана специальность врача, которым должна быть оказана услуга,
//то cf должен соответствовать
if (entity.getSpeciality() != null) {
if (entity.getSpeciality().getId() != cf.getSpeciality().getId()) {
throw new EDataIntegrity();
}
}
entity.setFunctions(cf);
if (d.functionsID != 0) {
//при оказании услуги анализ убираем ее из расписания анализов
Field fields[] = {
new Field("serviceRender", entity),
};
List<Checkup> list = findEntityList(Checkup.class, fields);
for (int i = 0; i < list.size(); i++) {
Checkup checkup = list.get(i);
checkup.setCheckupShedule(null);
manager.merge(checkup);
}
}
}
else {//услуга оказана
if (d.renderDate == null && d.functionsID != 0) {//отмена оказания
throwNeedAdminSecurityException("У вас недостаточно прав, чтоб отметить услугу как неоказанную");
entity.setRenderedDate(null);
entity.setFunctions(null);
} else if (!entity.getRenderedDate().equals(d.renderDate)) {
throwNeedAdminSecurityException("У вас недостаточно прав для смены даты оказания услуги");
entity.setRenderedDate(d.renderDate);
} else if (entity.getFunctions() != null && entity.getFunctions().getId() != d.functionsID) {
throwNeedAdminSecurityException("У вас недостаточно прав для смены сотрудника, оказавшего услугу");
entity.setFunctions(d.functionsID == 0 ? null : findEntity(CollaboratorFunctions.class, d.functionsID));
}
}
if (d.uet == 0) {
throw new ClipsServerException("Не указана условная единица трудоемкости\n" +
"(УЕТ = 1 для не стоматологических приемов)");
}
if (cf != null) {
ReceptionType recType = cf.getReceptionType();
String code = recType.getExtKey();
if (!code.contains("29") && d.uet != ServiceRender.DEFAULT_UET) {
throw new ClipsServerException("Для не стоматологического приема указан УЕТ отличный от единицы");
}
}
entity.setUet(d.uet);
entity.setReceived(d.received);
entity.setDiscount(d.discount);
entity.setDiscountCard(d.cardID == 0 ? null : findEntity(DiscountCard.class, d.cardID));
entity.setCancelled(d.cancelled);
entity.setRepeat(d.repeat);
entity.setPacketService(d.packetServiceID == 0 ? null : findEntity(PacketService.class, d.packetServiceID));
entity.setDisease(d.diseaseID == 0 ? null : findEntity(Disease.class, d.diseaseID));
entity.setPolis(findEntity(Polis.class, d.polisID));
entity.setService(findEntity(Service.class, d.serviceID));
entity.setDirector(findEntity(Collaborator.class, d.directorID));
entity.setPlace(d.servPlaceID == 0 ? null : findEntity(ServicingPlace.class, d.servPlaceID));
entity.setFunctions(d.functionsID == 0 ? null : findEntity(CollaboratorFunctions.class, d.functionsID));
ServiceRender ref = d.referencedID == 0 ? null : findEntity(ServiceRender.class, d.referencedID);
if(ref != null
&&ref.getDisease().getId() != entity.getDisease().getId()) {
throw new EDataIntegrity("Связанные услуги должны быть в одном заболевании");
}
entity.setReferenced(ref);
}
private void checkPossibilityUpdate(ServiceRender entity, EntityDetails details) throws ClipsServerException {
ServiceRenderDetails d = (ServiceRenderDetails) details;
boolean isAdmin = rights.getCommandAccessReason(COMMAND_MODIFY) == UserRightsSet.WRITE_ADMIN_SERVICE_RENDER.id;
// Основные проверки
if (entity.getId() != 0 &&
(entity.getDirector().getId() != d.directorID ||
entity.getPolis().getId() != d.polisID ||
entity.getService().getId() != d.serviceID || !entity.getDate().equals(d.date)) && !isAdmin) {
throw new ESecurity("Изменить поля услуги: направивший сотрудник, " +
"полис, тип услуги и дату направления на услугу, " +
"можно только при создании новой услуги или администратору");
}
// дополнительные
if (d.getId() != entity.getId()) {
throw new EDataIntegrity("Внутренняя ошибка: Попытка присвоить сущности ServiceRender другой ID");
}
if (!(d.diseaseID == 0 ||
findEntity(Disease.class, d.diseaseID).getEmc().getClient().getId() ==
findEntity(Polis.class, d.polisID).getClient().getId())) {
throw new EDataIntegrity("Внутренняя ошибка: Заболевание и полис связаны с различными пациентами");
}
}
/**
* Если нет транзакций услуга удаляется если есть отменяется.
* Перед вызовом обязательно вызывать checkPossibilityRemove();
* @param manager
* @param entity
* @param collab
* @param auditDocList
* @throws ClipsServerException
*/
public static void remove(EntityManager manager, ServiceRender entity,
CollaboratorAbstract collab, List<AuditDoc> auditDocList) throws ClipsServerException {
Query q = manager.createQuery("SELECT COUNT(mt) FROM MoneyTransaction mt " +
"WHERE mt.serviceRender = :serren");
q.setParameter("serren", entity);
Long count = (Long) q.getSingleResult();
if (count == 0) {
AuditDoc<ServiceRender> auditDoc = new AuditDoc<ServiceRender>(entity, collab);
manager.remove(entity);
auditDoc.check(null);
auditDocList.add(auditDoc);
} else {
AuditDoc<ServiceRender> auditDoc = new AuditDoc<ServiceRender>(entity, collab);
entity.setCancelled(true);
manager.persist(entity);
manager.flush();
manager.refresh(entity);
auditDoc.check(entity);
auditDocList.add(auditDoc);
}
}
/**
* Переписан FacadeBean
* Делается попытка удалить услугу, если это невозможно, то услуга отменяется
* @throws ClipsServerException
* Особенность у СЕРРЕНА - если нет денежный транзакций, то удаляет иначе отменяет
*/
@Override
public ModificationInfo remove() throws ClipsServerException {
try {
List<AuditDoc> auditDocList = new LinkedList<AuditDoc>();
checkCommandAccessibility(COMMAND_REMOVE);
ServiceRender entity = getExistentEntity();
onRemove(entity, auditDocList);
remove(manager, entity, getCollaborator(), auditDocList);
List<AuditDetails> auditInfo = persistAudit(auditDocList);
return new ModificationInfo(entity.getId(), auditInfo);
} catch (ClipsServerException ex) {
throw ex;
} catch (Exception ex) {
throw new ClipsServerException("Ошибка удаления", ex);
}
}
public static void breakPacket(EntityManager manager, ServiceRender entity,
CollaboratorAbstract collab, List<AuditDoc> auditDocList) throws ClipsServerException {
//Удаление связанных результатов медосмотров
Query query = manager.createQuery("SELECT m FROM MedSerrenResult m WHERE m.serren=:serren");
query.setParameter("serren", entity);
List<MedSerrenResult> medserrenlist = query.getResultList();
for (int i = 0; i < medserrenlist.size(); i++) {
MedSerrenResult medSerrenResult = medserrenlist.get(i);
AuditDoc<MedSerrenResult> auditMSR = new AuditDoc<MedSerrenResult>(medSerrenResult, collab);
manager.remove(medSerrenResult);
auditMSR.check(null);
auditDocList.add(auditMSR);
}
PacketService serpac = entity.getPacketService();
if (serpac != null) {
//Убирание услуг из пакета
query = manager.createQuery("SELECT s From ServiceRender s WHERE s.packetService.id = :pacserID ");
query.setParameter("pacserID", entity.getPacketService().getId());
List serrenList = query.getResultList();
for (Object object : serrenList) {
ServiceRender sr = (ServiceRender)object;
AuditDoc<ServiceRender> auditSerren = new AuditDoc<ServiceRender>(sr, collab);
sr.setPacketService(null);
manager.merge(sr);
auditSerren.check(sr);
auditDocList.add(auditSerren);
}
AuditDoc<PacketService> auditSerpac = new AuditDoc<PacketService>(serpac, collab);
manager.remove(serpac);
auditSerpac.check(null);
auditDocList.add(auditSerpac);
}
}
/**
* Удаляет услугу и разрушает пакет, если выставлена значение true
* обычный метод remove() выкинет исключение при попытке удалить услугу в пакете
* @throws ClipsServerException
*/
@Override
public ModificationInfo removeAndBreakPacket() throws ClipsServerException{
ArrayList<AuditDetails> auditDetList = new ArrayList<AuditDetails>();
List<AuditDoc> auditDocList = new ArrayList<AuditDoc>();
ServiceRender entity = getExistentEntity();
breakPacket(manager, entity, getCollaborator(), auditDocList);
auditDetList.addAll(persistAudit(auditDocList));
ModificationInfo mi = remove();
auditDetList.addAll(mi.getAudit());
return new ModificationInfo(0, auditDetList);
}
/**
* Удаляет сущность из базы данных
* Удалить СервисРендер можно только если к нему не привязаны рецепты, рекоммендации,
* направления, диагнозы, противопоказания или чекапы-осмотры или чекапы-анализы с
* установленной датой взятия пробы.
* Особеннсть для СЕРРЕНА - производится проверка без учёта транзакций
* @param entity
* @throws ClipsServerException
*/
@Override
public void onRemove(ServiceRender entity, List<AuditDoc> auditDocList) throws ClipsServerException {
checkPossibilityRemove(entity);
//Удаление чекапов идет хитрым способом тут надо знать про метаданные
String sql = "SELECT a FROM Checkup AS a " +
"WHERE (a.serviceRender=:serren) " +
"AND (a.date is null ) " +
"AND a.checkupType.isAnalyse = true";
Query query = manager.createQuery(sql);
query.setParameter("serren", entity);
List<Checkup> toDeleteList = query.getResultList();
for (Checkup checkup : toDeleteList) {
AuditDoc<Checkup> auditDoc = new AuditDoc<Checkup>(checkup, getCollaborator());
auditDoc.addFieldFormat(checkup, "xml", checkup.getCheckupType().getMetadata());
auditDoc.check(null);
removeEntity(checkup);
auditDocList.add(auditDoc);
}
deleteEntityList2(Checkup.class, new Field[]{
new Field("serviceRender", entity),
new Field("date", null, Field.OPERATOR_IS_NULL),
new Field("checkupType.isAnalyse", true)
},
auditDocList);
deleteEntityList2(Expenditure.class,
new Field[]{new Field("serviceRender", entity)},
auditDocList);
deleteEntityList2(MedSerrenResult.class,
new Field[]{new Field("serren", entity)},
auditDocList);
}
@Override
public void checkPossibilityRemove(ServiceRender entity) throws ClipsServerException {
int myId = entity.getId();
if (!isSuperUser() && entity.isRendered()){
throwNeedAdminSecurityException("Нельзя удалить оказанную услугу");
}
if (entity.getPacketService() != null) {
throw new EDataIntegrity("Нельзя удалить услугу, состоящую в пакете услуг");
}
checkEntityNotRef(Followup.class, "serrenUp", "Нельзя удалить услугу, связанную с постановкой на диспансерный учет");
checkEntityNotRef(Followup.class, "serrenDown", "Нельзя удалить услугу, связанную со снятием с диспансерного учета");
checkEntityNotRef(SickLong.class, "serren", "Нельзя удалить услугу, связанную с открытием или продлением больничного листа");
checkEntityNotRef(Sicklist.class, "serrenClosed", "Нельзя удалить услугу, связанную с закрытием больничного листа");
String msg = "Нельзя удалить услугу, если в её рамках существует %2$s";
checkEntityNotRef(Prescription.class, "serviceRender", msg);
checkEntityNotRef(Recommendation.class, "serviceRender", msg);
checkEntityNotRef(Direction.class, "serviceRender", msg);
checkEntityNotRef(Diagnosis.class, "serviceRender", msg);
checkEntityNotRef(Contraindication.class, "serviceRender", msg);
checkEntityNotRef(Prescription.class, "serviceRender", msg);
int checkup = getEntityCount(Checkup.class, new Field[]{new Field("serviceRender.id", myId),
new Field("checkupType.isAnalyse", false)
});
if (checkup != 0){
throw new EDataIntegrity("Нельзя удалить услугу, если в её рамках записан осмотр, удалите сначала осмотр");
}
int nrAnalyse = getEntityCount(Checkup.class, new Field[]{new Field("serviceRender.id", myId),
new Field("date", null, Field.OPERATOR_NOT_NULL),
new Field("checkupType.isAnalyse", true)
}, "");
if (nrAnalyse != 0){
throw new EDataIntegrity("Нельзя удалить услугу, если в её рамках есть выполненный анализ, удалите сначала анализ");
}
checkEntityNotRef(ServiceRender.class, "referenced", "Есть услуги, привязанные к данной, удалите сначала их");
}
/**
* Возвращает информацию о договоре, по которому оказывается данная услуга
* @return договор
* @throws ClipsServerException
*/
@Override
public PolisDetails getPolis() throws ClipsServerException {
checkCommandAccessibility(COMMAND_READ_CONTRACT_MEMBER);
ServiceRender entity = getExistentEntity();
Polis polis = entity.getPolis();
return polis.getDetails((RightChecker) this);
}
/**
* Возвращает дисконтную карту услугу
* @return детали дисконтной карты или null если нет дисконтой карты
* @throws ClipsServerException
*/
@Override
public DiscountCardDetails getDiscountCard() throws ClipsServerException {
checkCommandAccessibility(COMMAND_READ);
ServiceRender entity = getExistentEntity();
DiscountCard dc = entity.getDiscountCard();
if (dc == null) {
return null;
}
return dc.getDetails((RightChecker) this);
}
/**
* Возвращает список расходных материалов
* @return список расходных материалов
* @throws ClipsServerException
*/
@Override
public List<ExpenditureDetails> getExpenditureList() throws ClipsServerException {
checkCommandAccessibility(COMMAND_READ);
ServiceRender entity = getExistentEntity();
List list = findEntityList(Expenditure.class, "serviceRender", entity);
List<ExpenditureDetails> res = new ArrayList<ExpenditureDetails>();
Iterator i = list.iterator();
while (i.hasNext()) {
Expenditure j = (Expenditure) i.next();
res.add(j.getDetails((RightChecker) this));
}
return res;
}
/**
* Добавляет или обновляет расходные материалы. Если details.id = 0 сущность создается,
* иначе обновляется существующая с заданным идентификатором.
* @param details данные
* @return идентификатор сущности
* @throws ClipsServerException
* @throws EJBException в случае если обновление отвергнуто системой
* безопастности либо произошла ошибка *
*/
@Override
public ModificationInfo setExpenditure(ExpenditureDetails details) throws ClipsServerException {
checkCommandAccessibility(COMMAND_MODIFY);
ServiceRender entity = getExistentEntity();
Expenditure exp = null;
if (details.id != 0) {
exp = findEntity(Expenditure.class, details.id);
checkTheSame(exp.getServiceRender());
} else {
exp = new Expenditure();
exp.setServiceRender(entity);
}
AuditDoc<Expenditure> auditExp = new AuditDoc<Expenditure>(exp, getCollaborator());
exp.setQuantity(details.quantity);
exp.setType(findEntity(ExpenditureType.class, details.expenTypeID));
int id = saveEntity(exp);
auditExp.check(exp);
return new ModificationInfo(id, persistAudit(auditExp));
}
/**
* Удаляет расходные материалы.
* @param id идентификатор
* @throws ClipsServerException в случае если обновление отвергнуто системой
* безопасности либо произошла ошибка *
*/
@Override
public ModificationInfo removeExpenditure(int id) throws ClipsServerException {
checkCommandAccessibility(COMMAND_MODIFY);
checkEntityExist();
Expenditure exp = findEntity(Expenditure.class, id);
checkTheSame(exp.getServiceRender());
AuditDoc<Expenditure> auditExp = new AuditDoc<Expenditure>(exp, getCollaborator());
manager.remove(exp);
auditExp.check(null);
return new ModificationInfo(persistAudit(auditExp));
}
/**
* Возвращает список транзакций, отсортированных по дате создания.
* @return список транзакций
* @throws ClipsServerException
*/
@Override
public List<MoneyTransactionDetails> getMoneyTransactionList() throws ClipsServerException {
checkCommandAccessibility(COMMAND_SERVICE_RENDER_TRANSACTION_DETAIL);
ServiceRender entity = getExistentEntity();
List list = findEntityList(MoneyTransaction.class, "serviceRender", entity,
" ORDER by a.date");
List<MoneyTransactionDetails> res = new ArrayList<MoneyTransactionDetails>();
Iterator i = list.iterator();
while (i.hasNext()) {
MoneyTransaction j = (MoneyTransaction) i.next();
res.add(j.getDetails((RightChecker) this));
}
return res;
}
/**
* Возвращает сумму транзакций по данной услуге
* @return сумма транзакций
* @throws ClipsServerException
*/
@Override
public Long getMoneyTransactionSumm() throws ClipsServerException {
checkCommandAccessibility(COMMAND_READ_SERVICE_RENDER_TRANSACTION_SUMM);
ServiceRender entity = getExistentEntity();
String sql = "SELECT SUM(mt.money) FROM MoneyTransaction mt WHERE mt.serviceRender=:serren " +
"AND mt.permitted=true";
Query query = manager.createQuery(sql);
query.setParameter("serren", entity);
Long summ = (Long) query.getSingleResult();
if (summ != null) {
return summ;
} else {
return new Long(0);
}
}
/**
* Возвращает скидку, с которой должна быть оказана услуга.
* Учитывается пакет услуг, дисконтная карта, скидка введенная вручную
* @return 1-100 !null
* @throws ClipsServerException
*/
@Override
public int getCalculatedDiscount() throws ClipsServerException {
checkCommandAccessibility(COMMAND_READ);
ServiceRender entity = getExistentEntity();
DiscountCard discountCard = entity.getDiscountCard();
PacketService packetService = entity.getPacketService();
if (discountCard != null || packetService != null) {
//по дисконтной карте или по пакету услуг
int cardID = discountCard == null ? 0 : discountCard.getId();
int packetID = packetService == null ? 0 : packetService.getPacketTemplate().getId();
return CalcDiscount.calculateDiscount(manager, cardID, entity.getService().getId(), packetID);
} else {
return entity.getDiscount();
}
}
/**
* Оплачена ли услуга полностью
* @return
* @throws ClipsServerException
*/
@Override
public boolean isSerPayed() throws ClipsServerException {
//checkCommandAccessibility(COMMAND_READ);
ServiceRender entity = getExistentEntity();
//если услуга связанная, то цена 0, соответственно она оплачена
if (entity.getReferenced() != null) {
return true;
}
/* Ищем цены
* у оказываемой услуги(посещения) берем договор, тип услуги и тип приема
* В таблице цен ищем такие записи, у которых такой же контракт, тип услуги
* и тип приема либо совпадает либо нул
*/
String sql;
if (entity.getFunctions() != null) {
sql = "SELECT a FROM ServicePrice a WHERE " +
"a.contract=:contract " +
"AND a.service=:service " +
"AND (a.receptionType=:receptionType OR a.receptionType IS NULL)";
} else {
sql = "SELECT a FROM ServicePrice a WHERE " +
"a.contract=:contract " +
"AND a.service=:service " +
"AND a.receptionType IS NULL";
}
Query q = manager.createQuery(sql);
q.setParameter("contract", entity.getPolis().getContract());
q.setParameter("service", entity.getService());
if (entity.getFunctions() != null) {
q.setParameter("receptionType", entity.getFunctions().getReceptionType());
}
List<ServicePrice> servicePriceList = q.getResultList();
if (servicePriceList.size() < 1) {
throw new ClipsServerException("Не найдены цены на услугу в договоре");
}
if (servicePriceList.size() > 1) {
throw new ClipsServerException("Найдены различные цены на услугу в договоре");
}
ServicePrice cs = servicePriceList.get(0);
ServicePriceDetails details = cs.getDetails((RightChecker) this);
int price = details.price;
int money = details.money;
//Ищем скидку
int discount = getCalculatedDiscount();
//сумма транзакций
long transactionSumm = getMoneyTransactionSumm();
//финальные вычисления
int toPay = Math.round((price - money) * (1 - (float) discount / 100));
return transactionSumm >= toPay;
}
/**
* Возвращает рекоммендации, привязанные к данной услуге
* @return список деталей рекомендаций
* @throws ClipsServerException
*/
@Override
public List<RecommendationDetails> getRecommendationList() throws ClipsServerException {
checkCommandAccessibility(COMMAND_READ_MEDICAL_DATA);
return loadChildDetailsList(Recommendation.class, "serviceRender");
}
/**
* Возвращает направления, привязанные к данной услуге
* @return список деталей направлений
* @throws ClipsServerException
*/
@Override
public List<DirectionDetails> getDirectionList() throws ClipsServerException {
checkCommandAccessibility(COMMAND_READ_MEDICAL_DATA);
return loadChildDetailsList(Direction.class, "serviceRender");
}
/**
* Возвращает противопоказания, привязанные к данной услуге
* @return список деталей противопоказаний
* @throws ClipsServerException
*/
@Override
public List<ContraindicationDetails> getContraindicationList() throws ClipsServerException {
checkCommandAccessibility(COMMAND_READ_MEDICAL_DATA);
return loadChildDetailsList(Contraindication.class, "serviceRender");
}
/**
* Возвращает диагнозы, привязанные к данной услуге
* @return список деталей направлений
* @throws ClipsServerException
*/
@Override
public List<DiagnosisDetails> getDiagnosisList() throws ClipsServerException {
checkCommandAccessibility(COMMAND_READ_MEDICAL_DATA);
ServiceRender entity = getExistentEntity();
List<Diagnosis> list = findEntityList(Diagnosis.class, "serviceRender", entity,
"AND a.referenced IS NULL");
return getEntytyDetailsList(list);
}
@Override
public List<PrescriptionDetails> getPrescriptionList() throws ClipsServerException {
checkCommandAccessibility(COMMAND_READ_MEDICAL_DATA);
return loadChildDetailsList(Prescription.class, "serviceRender");
}
@Override
public List<CheckupDetails> getCheckupList() throws ClipsServerException {
checkCommandAccessibility(COMMAND_READ_MEDICAL_DATA);
return loadChildDetailsList(Checkup.class, "serviceRender");
}
/**
* Возвращает серрены из того же пакета что и данный
* @return сет деталей серренов
* @throws ClipsServerException
*/
@Override
public List<ServiceRenderDetails> getPacketSerrenList() throws ClipsServerException {
ServiceRenderDetails d = (ServiceRenderDetails) getDetails();
List<ServiceRenderDetails> res = new ArrayList<ServiceRenderDetails>();
if (d.packetServiceID == 0) {
return res;
}
PacketService ps = findEntity(PacketService.class, d.packetServiceID);
return loadChildDetailsList(ps, ServiceRender.class, "packetService");
}
@Override
public List<ServiceRenderDetails> getAccomplichedSerrenList() throws ClipsServerException {
checkCommandAccessibility(COMMAND_READ_MEDICAL_DATA);
return loadChildDetailsList(ServiceRender.class, "referenced");
}
@Override
public String canRenderService() throws ClipsServerException{
Collaborator collaborator = findEntity(Collaborator.class, getCollaboratorId());
String sql = "SELECT COUNT(cf) FROM ServicePrice sp, CollaboratorFunctions cf " +
"WHERE sp.service =:serv " +
"AND (sp.receptionType = cf.receptionType OR sp.receptionType IS NULL) AND cf.collaborator=:collab ";
if (!isSuperUser()){
sql += "AND cf.trash = FALSE";
}
Query q = manager.createQuery(sql);
q.setParameter("collab", collaborator);
q.setParameter("serv", getExistentEntity().getService());
long count = (Long) q.getSingleResult();
if (count == 0){
return NEED_SPECIFY_RECEPTION_TYPE;
}
count = getEntityCount(CollaboratorFunctions.class, new Field[]{new Field("collaborator", collaborator)});
if (count == 0){
return HAVE_NOT_RECEPTION_TYPE;
}
//проверка соответствия специальности врача
if (getExistentEntity().getSpeciality() != null) {
String sql1 = "SELECT COUNT(cf) FROM CollaboratorFunctions cf " +
"WHERE (cf.speciality =:fixedSpeciality) AND cf.collaborator=:collab ";
if (!isSuperUser()){
sql1 += "AND cf.trash = FALSE";
}
Query q1 = manager.createQuery(sql1);
q1.setParameter("collab", collaborator);
q1.setParameter("fixedSpeciality", getExistentEntity().getSpeciality());
long count1 = (Long) q1.getSingleResult();
if (count1 == 0){
return NOT_COMPLIANCE_SPECIALITY;
}
}
return null;
}
@Override
public List<PrescriptionDloDetails> getPrescriptionDloList() throws ClipsServerException {
checkCommandAccessibility(COMMAND_READ_MEDICAL_DATA);
return loadChildDetailsList(PrescriptionDlo.class, "serviceRender");
}
}