Package beans.contract

Source Code of beans.contract.ContractBean

/*
* 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;
        }


    }
}
TOP

Related Classes of beans.contract.ContractBean

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.