/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package beans.contract;
import beans.contract.entity.ServicePriceDetails;
import beans.contract.entity.ContractDetails;
import framework.beans.EntityDetails;
import framework.beans.FindEntity;
import framework.beans.FacadeBean;
import framework.beans.collaborator.CollaboratorAbstract;
import framework.beans.security.BeanRights;
import beans.contract.entity.ContractPacket;
import beans.contract.entity.Contract;
import beans.contract.entity.Polis;
import beans.contract.entity.ContractPacketPK;
import beans.contract.entity.ServicePrice;
import beans.directory.packet.entity.PacketTemplate;
import beans.directory.service.entity.Service;
import beans.service.ServiceRender;
import framework.generic.EDataIntegrity;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import framework.generic.ClipsServerException;
import java.util.HashSet;
import java.util.Set;
import javax.ejb.EJBException;
import javax.ejb.Stateful;
import javax.persistence.Query;
import beans.UserRightsSet;
import beans.contract.entity.PolisDetails;
import beans.contract.search.ContractPolisChunk;
import beans.directory.enterprise.Enterprise;
import beans.directory.lpu.entity.Lpu;
import beans.profcheckup.entity.ProfcheckupItem;
import beans.directory.service.entity.ServiceGroup;
import beans.directory.simple.entities.Insurer;
import beans.directory.simple.entities.ReceptionType;
import beans.directory.simple.entities.RegionIdCode;
import beans.user.client.entity.Client;
import beans.user.collaborator.entities.Collaborator;
import framework.audit.AuditDetails;
import framework.audit.AuditDoc;
import framework.beans.ModificationInfo;
import framework.beans.address.entities.Address;
import framework.beans.address.entities.AddressDetails;
import framework.beans.address.entities.AddressObject;
import framework.security.RightChecker;
import java.util.Collections;
import java.util.Comparator;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map.Entry;
/**Схема работы договоров
* Договора бывают 3 видов.
1. Внутренний договор (с поликлиникой) Contract.TYPE_INNER
2. Договор обязательного мед. страхования Contract.TYPE_OMI
3. Договор добровольного мед. страхования Contract.TYPE_VMI
* Договоров каждого типа может быть неограниченое количество, ответственность
* за существование ошибочных договоров ложится на бухгалтерию - они не должны
* создавать такие договора.
* Договор считается действующим, если его начальная дата существует, и уже
* наступила, а также конечная дата либо не существует либо не наступила
* Существует единственный шаблонный договор, ID = Contract.TEMPLATE_CONTRACT_ID,
* он должен быть обязательно просрочен, не должен иметь договормемберов, в нем
* можно редактировать цены.
* Все договора создаются копированием. При копировании договора начальная
* и конечная даты не существуют, копируются все цены, шаблоны и договормемберы,
* у которых не истек срок действия
* Удаление договора можно только если по нему не было оказано ни одной
* услуги, и если он не содержит ни одного договормембера.
* Модификация деталей договора: изменять нельзя, если по нему уже были
* назначены услуги за исключением выставления даты окончания договора.
* Договормемберы можно добавлять и модифицировать, а также удалять, если
* не было назначено ни одной услуги. Цены можно добавлять, а также изменять и
* удалять, если не было назначено ни одной услуги.
*/
/**
* Security - Ok.
* Integrity - Доделать! Есть ещё куча вопросов.
* @author axe
*/
@Stateful(mappedName="clips-beans/ContractBean")
public class ContractBean extends FacadeBean<Contract>
implements ContractBeanRemote {
public static int COMMAND_WRITE_MEMBER = 5;
public static int COMMAND_MODIFY_CLINIC = 6;
public static int COMMAND_MODIFY_OMI = 7;
public ContractBean() {
super(Contract.class);
}
@Override
protected void initBeanRights() {
int[] r = new int[8];
r[COMMAND_READ] = RightPresence(UserRightsSet.READ_CONTRACT.id);
int rightWriteClinic = RightPresence(UserRightsSet.WRITE_CONTRACT_WITH_CLINIC.id);
int rightWriteOmi = RightPresence(UserRightsSet.WRITE_CONTRACT_OMI.id);
int rightWrite = Math.max(rightWriteClinic, rightWriteOmi);
r[COMMAND_CREATE] = rightWrite;
r[COMMAND_MODIFY] = rightWrite;
r[COMMAND_REMOVE] = rightWrite;
r[COMMAND_WRITE_MEMBER] = RightPresence(UserRightsSet.WRITE_CONTRACT_POLIS.id);
r[COMMAND_MODIFY_CLINIC] = rightWriteClinic;
r[COMMAND_MODIFY_OMI] = rightWriteOmi;
rights = new BeanRights(r);
}
/**
* Обновляет данные сущности.
* @param details новые детали
* @throws EJBException в случае если обновление отвергнуто системой
* безопастности либо произошла ошибка
*/
@Override
protected void onUpdate(Contract entity, EntityDetails details,
AuditDoc auditDoc, List<AuditDoc> auditDocList) throws ClipsServerException {
initBeanRights(); // права могут поменяться в после сохранения договора
ContractDetails d = (ContractDetails) details;
if (d.type == Contract.TYPE_OMI) {
checkCommandAccessibility(COMMAND_MODIFY_OMI);
} else {
checkCommandAccessibility(COMMAND_MODIFY_CLINIC);
}
boolean onlySetEnd = true; //Только установить дату окончания действия договора
ContractDetails dOld = entity.getDetails((RightChecker) this);
if (dOld.id != d.id || dOld.type != d.type) {
onlySetEnd = false;
}
if(dOld.index != d.index && (dOld.index == null || !dOld.index.equals(d.index))) {
onlySetEnd = false;
}
if(dOld.begin != d.begin && (dOld.begin == null || !dOld.begin.equals(d.begin))) {
onlySetEnd = false;
}
if (onlySetEnd) {
if (dOld.end != null || d.end == null) {
onlySetEnd = false;
}
}
if (!onlySetEnd) {
checkEntityNotRef(entity, ServiceRender.class, "polis.contract", "Нельзя изменить или удалить данный договор, так как по нему уже были назначены услуги (%3$d штук) ");
}
/* проверка убрата - договора могут пересекаться хоть как
if ((d.type == Contract.TYPE_INNER || d.type == Contract.TYPE_OMI) && d.begin != null) {
Query q;
if (d.end == null) {
q = manager.createQuery("SELECT count(a) FROM Contract a WHERE " +
"(a.type = :ctype) AND (a.begin IS NOT NULL) AND (a.id <> :myId) AND " +
"((a.end IS NULL) OR (a.end > :cbegin))");
q.setParameter("ctype", d.type);
q.setParameter("myId", entity.getId());
q.setParameter("cbegin", d.begin);
} else {
q = manager.createQuery("SELECT count(a) FROM Contract a WHERE " +
"(a.type = :ctype) AND (a.begin IS NOT NULL) AND (a.id <> :myId) AND " +
"(a.begin < :cend) AND ((a.end IS NULL) OR (a.end > :cbegin))");
q.setParameter("ctype", d.type);
q.setParameter("myId", entity.getId());
q.setParameter("cend", d.end);
q.setParameter("cbegin", d.begin);
}
long c = (Long) q.getSingleResult();
if (c != 0) {
throw new EDataIntegrity("Не допустимо, чтобы внутренний договор (ВК) или ОМС, пересекался " +
"по времени действия с другим, кроме текущего. И должен начинаться позже текущего.");
}
}
*/
if (d.begin != null && d.end != null && d.begin.after(d.end)) {
throw new EDataIntegrity("Недопустимо, чтобы начало действия договора было позже его конца");
}
if (d.type == Contract.TYPE_OMI && d.lpuID != 0) {
throw new EDataIntegrity("Договор ОМС нельзя заключать с клиникой");
}
if (d.type != Contract.TYPE_OMI && d.lpuID == 0) {
throw new EDataIntegrity("В договоре не указана клиника");
}
if (d.type == Contract.TYPE_OMI) {
throwNeedAdminSecurityException("Вы не имеете права на создание или изменение договора ОМС");
}
entity.setBegin(d.begin);
entity.setEnd(d.end);
entity.setIndex(d.index);
entity.setType(d.type);
entity.setOpenForAll(d.openForAll);
entity.setEnterprise(d.enterpriseID == 0 ? null : findEntity(Enterprise.class, d.enterpriseID));
entity.setLpu(d.lpuID == 0 ? null : findEntity(Lpu.class, d.lpuID));
}
@Override
protected void onRemove(Contract entity, List<AuditDoc> auditDocList) throws ClipsServerException {
checkEntityNotRef(entity, ServiceRender.class, "polis.contract", "Нельзя удалить данный договор, так как по нему уже были назначены услуги (%3$d штук)");
checkEntityNotRef(entity, Polis.class, "contract", "Нельзя удалить данный договор, в котором есть клиенты (%3$d)");
deleteEntityList2(ServicePrice.class, new Field[]{new Field("contract", entity)},
auditDocList);
deleteEntityList2(ContractPacket.class, new Field[]{new Field("contract", entity)},
auditDocList);
}
/**
* Возвращает список услуг договора.
* В системе безопасности это комманда COMMAND_READ_SERVICE.
* @return список услуг договора
*/
@Override
public List<ServicePriceDetails> getServices() throws ClipsServerException {
checkCommandAccessibility(COMMAND_READ);
Contract entity = getExistentEntity();
List list = findEntityList(ServicePrice.class, "contract", entity);
List<ServicePriceDetails> res = new ArrayList<ServicePriceDetails>();
Iterator i = list.iterator();
while (i.hasNext()) {
ServicePrice j = (ServicePrice) i.next();
res.add(j.getDetails((RightChecker) this));
}
return res;
}
protected void checkModifyServicePrice(ServicePrice servicePrice, ServicePriceDetails details) throws ClipsServerException {
if (servicePrice.getId()!= 0 && servicePrice.getDetails(this).equals(details)) {
//Ничего не изменяется зачем проверять
return;
}
if (getExistentEntity().getType() == Contract.TYPE_OMI) {
checkCommandAccessibility(COMMAND_MODIFY_OMI);
} else {
checkCommandAccessibility(COMMAND_MODIFY_CLINIC);
}
if (getId() != 0 && servicePrice.getId() != 0) {
Contract entity = getExistentEntity();
Service service = servicePrice.getService();
Field[] fields = new FindEntity.Field[]{
new Field("polis.contract", entity),
new Field("service", service)
};
int count = getEntityCount(ServiceRender.class,fields);
if (count != 0) {
List<ServiceRender> serrenList = findEntityListWithResCount(ServiceRender.class, fields, "", 1);
throw new EDataIntegrity("Цены на данную услугу не могут быть изменены или удалены, так как она уже кому-то назначалась "
+ "\nПри необходимости создайте копию договора, а старый заблокируйте"
+ "\n[" + serrenList.get(0).getInfo() + "]");
}
}
}
/**
* Добавляет или обновляет услугу в договоре. Если details.id = 0 сущность создается,
* иначе обновляется существующая с заданным идентификатором.
* В системе безопасности это комманда COMMAND_WRITE_SERIVCE.
* @param details данные
* @return идентификатор сущности
* @throws ClipsServerException
* @throws EJBException в случае если обновление отвергнуто системой
* безопастности либо произошла ошибка *
*/
@Override
public ModificationInfo setService(ServicePriceDetails details) throws ClipsServerException {
Contract entity = getExistentEntity();
AuditDoc<ServicePrice> auditDoc;
ServicePrice servicePrice = null;
if (details.id != 0) {
servicePrice = findEntity(ServicePrice.class, details.id);
checkTheSame(servicePrice.getContract());
if (servicePrice.getService().getId() != details.serviceID) {
throw new EDataIntegrity("Зафиксирована попытка подмены данных");
}
int rtID = servicePrice.getReceptionType() == null ? 0 : servicePrice.getReceptionType().getId();
if (rtID != details.receptionTypeID) {
throw new EDataIntegrity("Зафиксирована попытка подмены данных");
}
checkModifyServicePrice(servicePrice, details);
auditDoc = new AuditDoc<ServicePrice>(servicePrice, getCollaborator());
} else {
auditDoc = new AuditDoc<ServicePrice>(null, getCollaborator());
servicePrice = new ServicePrice();
checkModifyServicePrice(servicePrice, details);
//Проверка - для посещений нельзя указывать тип приема нулл, а также типы приемов, не имеющие кодов
// для остальных услуг тип приема должна быть нулл
Service service = findEntity(Service.class, details.serviceID);
if (service.getServiceGroup().getId() == ServiceGroup.SERVICE_GROUP_VISIT) {
if (details.receptionTypeID == 0) {
throw new EDataIntegrity("При установке цены на посещение не указан тип приема");
}
ReceptionType rt = findEntity(ReceptionType.class, details.receptionTypeID);
if (rt.getExtKey().trim().isEmpty()) {
throw new EDataIntegrity("При установке цены на посещение не указан тип приема");
}
} else {
if (details.receptionTypeID != 0) {
throw new EDataIntegrity("При установке цены на услугу тип приема не должен быть указан");
}
}
servicePrice.setService(findEntity(Service.class, details.serviceID));
servicePrice.setContract(entity);
servicePrice.setReceptionType(details.receptionTypeID == 0 ? null : findEntity(ReceptionType.class, details.receptionTypeID));
}
if (details.money > details.price) {
throw new EDataIntegrity("Нельзя указывать оплату по договору больше общей стоимости услуги");
}
servicePrice.setMoney(details.money);
servicePrice.setPrice(details.price);
int id = saveEntity(servicePrice);
auditDoc.check(servicePrice);
return new ModificationInfo(id, persistAudit(auditDoc));
}
/**
* Удаляет услугу из договора.
* В системе безопасности это комманда COMMAND_WRITE_SERIVCE.
* @param anId
* @throws ClipsServerException
* @throws EJBException в случае если обновление отвергнуто системой
* безопастности либо произошла ошибка *
*/
@Override
public ModificationInfo removeService(int anID) throws ClipsServerException {
checkEntityExist();
ServicePrice servicePrice = findEntity(ServicePrice.class, anID);
checkTheSame(servicePrice.getContract());
checkModifyServicePrice(servicePrice, null);
/*Проверка - если данная услуга содержится хоть в одном из шаблонов
*пакетов услуг, входящих в данный договор, то удаление невозможно*/
String sql = "SELECT a.packetServiceTemplate FROM PacketTemplateItem a WHERE a.service = :service " +
"AND (a.packetServiceTemplate.id IN (SELECT b.packetServiceTemplate.id FROM ContractPacket b WHERE b.contract = :contract))";
Query q = manager.createQuery(sql);
q.setParameter("service", servicePrice.getService());
q.setParameter("contract", getExistentEntity());
List foundedPST = q.getResultList();
if (foundedPST.size() > 0) {
String packets = "";
for (int i = 0; i < foundedPST.size(); i++) {
PacketTemplate packetTemplate = (PacketTemplate) foundedPST.get(i);
packets += packetTemplate.getTitle() + "\n";
}
throw new EDataIntegrity("В договоре присутствуют следующие пакеты, содержащие эту услугу :\n" + packets);
}
AuditDoc<ServicePrice> auditDoc = new AuditDoc<ServicePrice>(servicePrice, getCollaborator());
manager.remove(servicePrice);
auditDoc.check(null);
return new ModificationInfo(anID, persistAudit(auditDoc));
}
/**
* Возвращает список темплейтов пакетов для данного договора.
* В системе безопасности это комманда COMMAND_READ_SERIVCE.
* @return набор идентификаторов пактных темплейтов
* @throws generic.ClipsServerException
*/
@Override
public Set<Integer> getPacketTemplates() throws ClipsServerException {
checkCommandAccessibility(COMMAND_READ);
Contract entity = getExistentEntity();
Iterator<ContractPacket> list = findEntityList(ContractPacket.class, "key.contract", entity.getId()).iterator();
Set<Integer> res = new HashSet<Integer>();
while (list.hasNext()) {
ContractPacket templates = list.next();
res.add(templates.getKey().getPacketTemplate());
}
return res;
}
/**
* В системе безопасности это комманда COMMAND_WRITE_SERIVCE.
* @param packets
* @throws generic.ClipsServerException
*/
@Override
public ModificationInfo setPacketTemplates(Set<Integer> packets) throws ClipsServerException {
Contract entity = getExistentEntity();
if (entity.getType() == Contract.TYPE_OMI) {
checkCommandAccessibility(COMMAND_MODIFY_OMI);
} else {
checkCommandAccessibility(COMMAND_MODIFY_CLINIC);
}
Set<Integer> backup = new HashSet<Integer>(packets);
Set<Integer> old = getPacketTemplates();
packets.removeAll(old);
old.removeAll(backup);
int eid = entity.getId();
Iterator<Integer> addNew = packets.iterator();
ArrayList<AuditDoc> auditDocList = new ArrayList<AuditDoc>();
while (addNew.hasNext()) {
//Проверка содержатся ли все услуги добавляемого пакета в договоре
Integer packetTemplateID = addNew.next();
String sql = "SELECT a.service FROM PacketTemplateItem a where a.packetServiceTemplate.id = :packetTemplateID " +
"AND (a.service.id NOT IN (SELECT b.service.id FROM ServicePrice b where b.contract = :contract))";
Query q = manager.createQuery(sql);
q.setParameter("packetTemplateID", packetTemplateID);
q.setParameter("contract", entity);
List notFoundedServices = q.getResultList();
if (notFoundedServices.size() != 0) {
String serviceTitles = "";
for (int i = 0; i < notFoundedServices.size(); i++) {
Service service = (Service)notFoundedServices.get(i);
serviceTitles += service.getCodeAndTitle() + "\n";
}
throw new EDataIntegrity("В договоре отсутствуют необходимые услуги : \n" + serviceTitles);
}
AuditDoc<ContractPacket> auditCP = new AuditDoc<ContractPacket>(null, getCollaborator());
auditDocList.add(auditCP);
ContractPacket cp = new ContractPacket();
cp.setKey(new ContractPacketPK(eid, packetTemplateID));
cp.setContract(entity);
cp.setPacketServiceTemplate(findEntity(PacketTemplate.class, packetTemplateID));
manager.persist(cp);
auditCP.check(cp);
}
if (old.size() > 0) {
Field f[] = {
new Field("key.contract", eid),
new Field("key.packetTemplate", old, Field.OPERATOR_IN)
};
deleteEntityList2(ContractPacket.class, f, auditDocList);
}
return new ModificationInfo(0, persistAudit(auditDocList));
}
/**
* Вовзвращает список членов договора.
* В системе безопасности это комманда COMMAND_READ_MEMBER.
* @return список членов договора
* @throws ClipsServerException
*/
@Override
public ContractPolisChunk getPolisList(ContractPolisFilter filter) throws ClipsServerException {
checkCommandAccessibility(COMMAND_READ);
Contract entity = getExistentEntity();
ArrayList<Field> fields = new ArrayList<Field>();
Field f = new Field("contract", entity);
fields.add(f);
if(filter.name != null) {
f = new Field("client.name.title", filter.name.replace("%", "") + "%", Field.OPERATOR_LIKE);
fields.add(f);
}
if(filter.surname != null) {
f = new Field("client.surname.title", filter.surname.replace("%", "") + "%", Field.OPERATOR_LIKE);
fields.add(f);
}
if(filter.pathron != null) {
f = new Field("client.pathronymic.title", filter.pathron.replace("%", "") + "%", Field.OPERATOR_LIKE);
fields.add(f);
}
if(filter.polisSeries != null) {
f = new Field("series", filter.polisSeries.replace("%", "") + "%", Field.OPERATOR_LIKE);
fields.add(f);
}
if(filter.polisNumber != null) {
f = new Field("number", filter.polisNumber.replace("%", "") + "%", Field.OPERATOR_LIKE);
fields.add(f);
}
f = new Field("trash", false);
fields.add(f);
Field[] fs = new Field[fields.size()];
fs = fields.toArray(fs);
int size = getEntityCount(Polis.class, fs);
List<Polis> res = findEntityListWithResCount(Polis.class, fs, "", 50);
Collections.sort(res, new Comparator<Polis>() {
@Override
public int compare(Polis p1, Polis p2) {
int c;
Client o1 = p1.getClient();
Client o2 = p2.getClient();
if (o1.getSurname()==null) {
return -1;
}
if (o2.getSurname()==null) {
return 1;
}
c = o1.getSurname().getTitle().compareTo(o2.getSurname().getTitle());
if (c != 0) {
return c;
} else {
if (o1.getName()==null) {
return -1;
}
if (o2.getName()==null) {
return 1;
}
c = o1.getName().getTitle().compareTo(o2.getName().getTitle());
if (c != 0) {
return c;
} else {
if (o1.getPathronymic()==null) {
return -1;
}
if (o2.getPathronymic()==null) {
return 1;
}
c = o1.getPathronymic().getTitle().compareTo(o2.getPathronymic().getTitle());
}
return c;
}
}
});
List<PolisDetails> det = getEntytyDetailsList(res);
ContractPolisChunk chunk = new ContractPolisChunk();
chunk.polisList = det;
chunk.listSize = size;
return chunk;
}
@Override
public boolean isClientNotYetInContract(int clientID) throws ClipsServerException {
Contract entity = getExistentEntity();
Field f[] = {
new Field("contract", entity),
new Field("client.id", clientID),
new Field("trash", false)
};
List polises = findEntityList(Polis.class, f);
return polises.isEmpty();
}
/**
* Добавляет или обновляет член договора. Если details.id = 0 сущность создается,
* иначе обновляется существующая с заданным идентификатором.
* В системе безопасности это комманда COMMAND_WRITE_MEMBER.
* @param details данные
* @return идентификатор сущности
* @throws ClipsServerException
* @throws EJBException в случае если обновление отвергнуто системой
* безопастности либо произошла ошибка *
*/
@Override
public ModificationInfo setPolis(PolisDetails details) throws ClipsServerException {
checkCommandAccessibility(COMMAND_WRITE_MEMBER);
Contract entity = getExistentEntity();
ArrayList<AuditDoc> auditDocList = new ArrayList<AuditDoc>();
Polis polis = null;
AuditDoc<Polis> auditDoc;
Address a = new Address();
if (details.id != 0) {
polis = findEntity(Polis.class, details.id);
checkTheSame(polis.getContract());
int count = getEntityCount(ServiceRender.class, new Field[]{new Field("polis", polis)});
count += getEntityCount(ProfcheckupItem.class, new Field[]{new Field("polis", polis)});
if (count > 0) {
//помещение старого в корзину
auditDoc = new AuditDoc<Polis>(polis, getCollaborator());
auditDocList.add(auditDoc);
polis.setTrash(true);
saveEntity(polis);
auditDoc.check(polis);
//создание нового
auditDoc = new AuditDoc<Polis>(null, getCollaborator());
auditDocList.add(auditDoc);
polis = new Polis();
}
else {
auditDoc = new AuditDoc<Polis>(polis, getCollaborator());
auditDocList.add(auditDoc);
a = polis.getAddress();
if (a == null) {
a = new Address();
}
}
}
else {
auditDoc = new AuditDoc<Polis>(null, getCollaborator());
auditDocList.add(auditDoc);
polis = new Polis();
}
polis.setClient(findEntity(Client.class, details.clientID));
polis.setContract(entity);
polis.setCollaborator(findEntity(Collaborator.class, getCollaboratorId()));
polis.setMember(details.member);
polis.setSeries(details.series);
polis.setNumber(details.number);
polis.setTillDate(details.tillDate);
polis.setFromDate(details.fromDate);
polis.setInsurer(details.insurerID != 0 ? findEntity(Insurer.class, details.insurerID) : null);
polis.setRegionCode(findEntity(RegionIdCode.class, details.regionCodeId));
AddressDetails ad = details.addressDetail;
if (ad != null) {
a.setAddressObject(ad.objectId != 0 ? findEntity(AddressObject.class, ad.objectId) : null);
a.setBuilding(ad.building);
a.setFlat(ad.flat);
saveEntity(a);
polis.setAddress(a);
}
int id = saveEntity(polis);
auditDoc.check(polis);
return new ModificationInfo(id, persistAudit(auditDocList));
}
/**
* Удаляет члена договора.
* В системе безопасности это комманда COMMAND_WRITE_MEMBER.
* @param id идентификатор члена
* @throws ClipsServerException
*/
@Override
public ModificationInfo removePolis(int id) throws ClipsServerException {
checkCommandAccessibility(COMMAND_WRITE_MEMBER);
checkEntityExist();
Polis polis = findEntity(Polis.class, id);
checkTheSame(polis.getContract());
if (getEntityCount(ServiceRender.class,
new Field[]{new Field("polis", polis)}, "") > 0) {
throw new EDataIntegrity("Нельзя удалить данного участника договора так как у него уже есть услуги");
}
if (getEntityCount(ProfcheckupItem.class,
new Field[]{new Field("polis", polis)}, "") > 0) {
throw new EDataIntegrity("Нельзя удалить данного участника договора так как у него уже есть услуги");
}
Address address = polis.getAddress();
if (address != null) {
removeEntity(address);
}
AuditDoc<Polis> auditDoc = new AuditDoc<Polis>(polis, getCollaborator());
removeEntity(polis);
auditDoc.check(null);
return new ModificationInfo(persistAudit(auditDoc));
}
@Override
public ModificationInfo copy() throws ClipsServerException {
Contract contract = getExistentEntity();
if (contract.getType() == Contract.TYPE_OMI) {
checkCommandAccessibility(COMMAND_MODIFY_OMI);
} else {
checkCommandAccessibility(COMMAND_MODIFY_CLINIC);
}
try {
ArrayList<AuditDoc> auditDocList = new ArrayList<AuditDoc>();
AuditDoc<Contract> auditDoc = new AuditDoc<Contract>(null, getCollaborator());
auditDocList.add(auditDoc);
Contract newContract = (Contract) contract.clone();
newContract.setBegin(null);
newContract.setIndex(newContract.getIndex() + "(копия)");
int id = saveEntity(newContract);
auditDoc.check(newContract);
copyServices(contract, newContract, auditDocList);
copyPackets(contract, newContract, auditDocList);
copyMembers(contract, newContract, auditDocList);
return new ModificationInfo(id, persistAudit(auditDocList));
} catch (CloneNotSupportedException ex) {
throw new ClipsServerException("Внутренняя ошибка: не удалось скопировать договор", ex);
}
}
/**
* Использовать только для толькочто соданного договора
* @param src
* @param dst
* @throws framework.generic.ClipsServerException
*/
private void copyServices(Contract src, Contract dst, List<AuditDoc> auditDocList) throws ClipsServerException, CloneNotSupportedException {
List<ServicePrice> svs = findEntityList(ServicePrice.class, "contract", src);
CollaboratorAbstract collab = getCollaborator();
for (ServicePrice b : svs) {
AuditDoc<ServicePrice> auditDoc = new AuditDoc<ServicePrice>(null, collab);
auditDocList.add(auditDoc);
ServicePrice sv = ((ServicePrice) (b).clone());
sv.setContract(dst);
saveEntity(sv);
//manager.persist(sv);
auditDoc.check(sv);
}
}
/**
* Использовать только для толькочто соданного договора
* @param src
* @param dst
* @throws framework.generic.ClipsServerException
*/
private void copyPackets(Contract src, Contract dst, List<AuditDoc> auditDocList) throws ClipsServerException, CloneNotSupportedException {
List<ContractPacket> cps = findEntityList(ContractPacket.class, "key.contract", src.getId());
CollaboratorAbstract collab = getCollaborator();
for (ContractPacket b : cps) {
AuditDoc<ContractPacket> auditDoc = new AuditDoc<ContractPacket>(null, collab);
auditDocList.add(auditDoc);
ContractPacket cp = ((ContractPacket) (b).clone());
cp.setKey(new ContractPacketPK(dst.getId(), cp.getKey().getPacketTemplate()));
manager.persist(cp);
manager.flush();
manager.refresh(cp);
auditDoc.check(cp);
}
}
/**
* Использовать только для толькочто соданного договора
* @param src
* @param dst
* @throws framework.generic.ClipsServerException
*/
private void copyMembers(Contract src, Contract dst, List<AuditDoc> auditDocList ) throws ClipsServerException {
/*Копируются договормемберы из первого договора исключая просроченные и удаленные*/
Query q = manager.createQuery("SELECT a FROM Polis a WHERE a.contract.id = :srcContractId " +
"AND (a.tillDate > :currentDate OR a.tillDate IS NULL) " +
"AND a.trash = false");
q.setParameter("srcContractId", src.getId());
q.setParameter("currentDate", GregorianCalendar.getInstance().getTime());
List<Polis> polisList = q.getResultList();
CollaboratorAbstract collab = getCollaborator();
for (int i = 0; i < polisList.size(); i++) {
Polis pOld = polisList.get(i);
if ((i % 100) == 0) {
System.out.println("Скопировано полисов - " + i + " (" + i*100.0/polisList.size() + "%)");
}
AuditDoc<Polis> auditDoc = new AuditDoc<Polis>(null, collab);
auditDocList.add(auditDoc);
Polis p = new Polis();
p.setMember(pOld.getMember());
p.setSeries(pOld.getSeries());
p.setNumber(pOld.getNumber());
p.setClient(pOld.getClient());
p.setInsurer(pOld.getInsurer());
p.setRegionCode(pOld.getRegionCode());
p.setTillDate(pOld.getTillDate());
p.setFromDate(pOld.getFromDate());
p.setTrash(pOld.isTrash());
p.setCollaborator(pOld.getCollaborator());
p.setContract(dst);
if (pOld.getAddress() != null) {
AddressDetails ad = pOld.getAddress().getDetails(this).clone();
Address a = new Address();
a.setBuilding(ad.building);
a.setFlat(ad.flat);
a.setAddressObject(ad.objectId != 0 ? findEntity(AddressObject.class, ad.objectId) : null);
manager.persist(a);
p.setAddress(a);
}
saveEntity(p);
auditDoc.check(p);
}
}
@Override
public ModificationInfo updateOMIPrice(HashSet<VisitPrice> visitPriceList) throws ClipsServerException {
//TODO Проверка не было ли оказано услуг по данному контракту
if (getExistentEntity().getType() == Contract.TYPE_OMI) {
checkCommandAccessibility(COMMAND_MODIFY_OMI);
} else {
throw new UnsupportedOperationException("Данный метод применим только к договору ОМС");
}
int serrenCount = getEntityCount(ServiceRender.class, new Field[]{new Field("polis.contract", getExistentEntity())});
if (serrenCount > 0) {
throw new EDataIntegrity("Невозможно обновить цены в контракте по которому уже были назначены услуги (" +
+ serrenCount + " услуг).");
}
/*Сначала выбираются все контрактсервайсы относящиеся к посещениям
* создается 3 мапа
* 1) код услуги - услуга
* 2) код типа приема - тип приема
* 3) код(услуги+типа приема) - контрактсервайс
*/
Field[] f = new Field[]{
new Field("serviceGroup.id", ServiceGroup.SERVICE_GROUP_VISIT)
};
List<Service> services = findEntityList(Service.class, f);
HashMap<String, Service> serviceMap = new HashMap<String, Service>();
for (Service service : services) {
serviceMap.put(service.getCode(), service);
}
List<ReceptionType> rtList = findEntityList(ReceptionType.class);
HashMap<String, ReceptionType> rtMap = new HashMap<String, ReceptionType>();
for (ReceptionType rt : rtList) {
rtMap.put(rt.getExtKey(), rt);
}
Field[] f2 = new Field[]{
new Field("contract", getExistentEntity()),
new Field("service.serviceGroup.id", ServiceGroup.SERVICE_GROUP_VISIT)
};
List<ServicePrice> prices = findEntityList(ServicePrice.class, f2);
HashMap<String, ServicePrice> priceMap = new HashMap<String, ServicePrice>();
for (ServicePrice servicePrice : prices) {
priceMap.put(servicePrice.getReceptionType().getExtKey() + servicePrice.getService().getCode(), servicePrice);
}
ArrayList<AuditDetails> auditDetList = new ArrayList<AuditDetails>();
CollaboratorAbstract collab = getCollaborator();
for (VisitPrice visitPrice : visitPriceList) {
if (Float.parseFloat(visitPrice.getPrice()) == 0) {
continue;
}
String rt;
String visit;
int price;
if (visitPrice.getId().length() != 6) {
throw new EDataIntegrity("В таблице стоимости посещений неверный ID : " + visitPrice.getId());
}
rt = visitPrice.getId().substring(0, 3);
visit = visitPrice.getId().substring(3, 6);
price = (int) (Float.parseFloat(visitPrice.getPrice())*100);
Service service = serviceMap.get(visit);
if (service == null) {
throw new EDataIntegrity("В базе отсутствует посещение с кодом " + visit +
". Обновите справочник посещений");
}
ReceptionType receptionType = rtMap.get(rt);
if (receptionType == null) {
throw new EDataIntegrity("В базе отсутствует тип приема с кодом " + visit +
". Обновите справочник типов приемов");
}
ServicePrice servicePrice = priceMap.get(visitPrice.getId());
if (servicePrice == null) {
ServicePriceDetails d = new ServicePriceDetails();
d.serviceID = service.getId();
d.receptionTypeID = receptionType.getId();
d.price = price; //договорная стоимость услгуи
d.money = price; //сумма денег оплачиваемая за услугу страховой команией
ModificationInfo mi = setService(d);
auditDetList.addAll(mi.getAudit());
} else {
ServicePriceDetails d = servicePrice.getDetails(this);
d.price = price; //договорная стоимость услгуи
d.money = price; //сумма денег оплачиваемая за услугу страховой команией
ModificationInfo mi = setService(d);
auditDetList.addAll(mi.getAudit());
priceMap.remove(visitPrice.getId());
}
}
for (Iterator<Entry<String, ServicePrice>> it = priceMap.entrySet().iterator(); it.hasNext();) {
Entry<String, ServicePrice> entry = it.next();
ServicePrice servicePrice = entry.getValue();
AuditDoc<ServicePrice> auditSP = new AuditDoc<ServicePrice>(servicePrice, collab);
removeEntity(servicePrice);
auditSP.check(null);
auditDetList.add(persistAudit(auditSP));
}
return new ModificationInfo(0, auditDetList);
}
/**
* Объединение полисов в контракте
* Отключено т.к. предназначена только для разработчиков (и отсутствует аудит)
* Объединяет 2 и более полисов для одного человека по одному контракту при совпадении номера полис
* @throws framework.generic.ClipsServerException
*/
@Override
public void unionPolises() throws ClipsServerException {
if (true) {
throw new UnsupportedOperationException("Отключено т.к. предназначена только для разработчиков (и отсутствует аудит)");
}
System.out.println("Поиск полисов - контракт " + getExistentEntity().getId());
List<Polis> polisList = findEntityList(Polis.class, "contract.id", getExistentEntity().getId());
System.out.println("Маппирование групп - количество полисов " + polisList.size());
HashMap<PolisUniq, ArrayList<Polis>> polisMap = new HashMap<PolisUniq, ArrayList<Polis>>();
for (int i = 0; i < polisList.size(); i++) {
Polis polis = polisList.get(i);
PolisUniq pu = new PolisUniq(polis);
ArrayList<Polis> array = polisMap.get(pu);
if (array == null) {
array = new ArrayList<Polis>();
polisMap.put(pu, array);
}
array.add(polis);
}
ArrayList<ArrayList<Integer>> groupList = new ArrayList<ArrayList<Integer>>();
Set<PolisUniq> keySet = polisMap.keySet();
for (Iterator<PolisUniq> it = keySet.iterator(); it.hasNext();) {
PolisUniq polisUniq = it.next();
ArrayList<Polis> pList = polisMap.get(polisUniq);
if (pList.size() < 2) {
it.remove();
} else {
ArrayList<Integer> array = new ArrayList<Integer>();
for (Polis polis : pList) {
array.add(polis.getId());
}
groupList.add(array);
}
}
System.out.println("Объединение полисов - количество групп " + polisMap.size());
polisMap = null;
keySet = null;
polisList = null;
System.gc();
int counter = 0;
float size = groupList.size();
for (ArrayList<Integer> array : groupList) {
counter ++;
System.out.println("Выполнено " + counter/size*100 + "%");
if (array.size() > 1) {
//Объединение полисов
Integer mainID = null;
for (Integer polisID : array) {
if (mainID == null || polisID > mainID) {
mainID = polisID;
}
}
Polis main = findEntity(Polis.class, mainID);
boolean inTrash = main.isTrash();
for (Integer polisID : array) {
if (polisID != mainID) {
//Перевязка ссылок
Polis polis = findEntity(Polis.class, polisID);
if (!polis.isTrash()) {
inTrash = false;
}
List<ServiceRender> serrenList = findEntityList(ServiceRender.class, "polis.id", polisID);
for (int i = 0; i < serrenList.size(); i++) {
ServiceRender serviceRender = serrenList.get(i);
serviceRender.setPolis(main);
saveEntity(serviceRender);
}
List<ProfcheckupItem> profCheckupList = findEntityList(ProfcheckupItem.class, "polis.id", polisID);
for (int i = 0; i < profCheckupList.size(); i++) {
ProfcheckupItem profcheckupItem = profCheckupList.get(i);
profcheckupItem.setPolis(main);
saveEntity(profcheckupItem);
}
Address address = polis.getAddress();
if (address != null) {
removeEntity(address);
}
removeEntity(polis);
}
}
if (!inTrash) {
main.setTrash(false);
saveEntity(main);
}
}
}
}
private class PolisUniq {
int clientID;
int contractID;
String polisNum;
public PolisUniq(Polis polis) {
clientID = polis.getClient().getId();
contractID = polis.getContract().getId();
polisNum = polis.getNumber();
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final PolisUniq other = (PolisUniq) obj;
if (this.clientID != other.clientID) {
return false;
}
if (this.contractID != other.contractID) {
return false;
}
if ((this.polisNum == null) ? (other.polisNum != null) : !this.polisNum.equals(other.polisNum)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 5;
hash = 89 * hash + this.clientID;
hash = 89 * hash + this.contractID;
hash = 89 * hash + (this.polisNum != null ? this.polisNum.hashCode() : 0);
return hash;
}
}
}