com.axelor.apps.crm.service.EventService.java Source code

Java tutorial

Introduction

Here is the source code for com.axelor.apps.crm.service.EventService.java

Source

/**
 * Axelor Business Solutions
 *
 * Copyright (C) 2015 Axelor (<http://axelor.com>).
 *
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.axelor.apps.crm.service;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.mail.MessagingException;

import net.fortuna.ical4j.model.Calendar;
import net.fortuna.ical4j.model.ValidationException;
import net.fortuna.ical4j.model.property.Method;

import org.joda.time.Duration;
import org.joda.time.Interval;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;

import com.axelor.apps.base.db.Address;
import com.axelor.apps.base.db.ICalendarUser;
import com.axelor.apps.base.db.Partner;
import com.axelor.apps.base.ical.ICalendarException;
import com.axelor.apps.base.service.PartnerService;
import com.axelor.apps.crm.db.Event;
import com.axelor.apps.crm.db.Lead;
import com.axelor.apps.crm.db.repo.EventRepository;
import com.axelor.apps.crm.exception.IExceptionMessage;
import com.axelor.apps.crm.service.config.CrmConfigService;
import com.axelor.apps.message.db.EmailAddress;
import com.axelor.apps.message.db.Message;
import com.axelor.apps.message.db.Template;
import com.axelor.apps.message.db.repo.EmailAddressRepository;
import com.axelor.apps.message.db.repo.MessageRepository;
import com.axelor.apps.message.service.MailAccountService;
import com.axelor.apps.message.service.MessageService;
import com.axelor.apps.message.service.TemplateMessageService;
import com.axelor.auth.db.User;
import com.axelor.exception.AxelorException;
import com.axelor.exception.db.IException;
import com.axelor.i18n.I18n;
import com.axelor.inject.Beans;
import com.axelor.mail.db.MailAddress;
import com.axelor.mail.db.repo.MailAddressRepository;
import com.axelor.mail.db.repo.MailFollowerRepository;
import com.axelor.meta.db.MetaFile;
import com.google.common.base.Strings;
import com.google.inject.Inject;
import com.google.inject.persist.Transactional;

public class EventService {

    @Inject
    private EventAttendeeService eventAttendeeService;

    @Inject
    private PartnerService partnerService;

    @Inject
    private EventRepository eventRepo;

    @Inject
    protected MailFollowerRepository mailFollowerRepo;

    static final String REQUEST = "REQUEST";

    public Duration computeDuration(LocalDateTime startDateTime, LocalDateTime endDateTime) {

        return new Interval(startDateTime.toDateTime(), endDateTime.toDateTime()).toDuration();

    }

    public int getDuration(Duration duration) {

        return duration.toStandardSeconds().getSeconds();

    }

    public LocalDateTime computeStartDateTime(int duration, LocalDateTime endDateTime) {

        return endDateTime.minusSeconds(duration);

    }

    public LocalDateTime computeEndDateTime(LocalDateTime startDateTime, int duration) {

        return startDateTime.plusSeconds(duration);

    }

    @Transactional
    public void saveEvent(Event event) {
        eventRepo.save(event);
    }

    @Transactional
    public void addLeadAttendee(Event event, Lead lead, Partner contactPartner) {

        event.addEventAttendeeListItem(eventAttendeeService.createEventAttendee(event, lead, contactPartner));
        eventRepo.save(event);

    }

    public Event createEvent(LocalDateTime fromDateTime, LocalDateTime toDateTime, User user, String description,
            int type, String subject) {
        Event event = new Event();
        event.setSubject(subject);
        event.setStartDateTime(fromDateTime);
        event.setEndDateTime(toDateTime);
        event.setUser(user);
        event.setTypeSelect(type);
        if (!Strings.isNullOrEmpty(description)) {
            event.setDescription(description);
        }
        return event;
    }

    public String getInvoicingAddressFullName(Partner partner) {

        Address address = partnerService.getInvoicingAddress(partner);
        if (address != null) {
            return address.getFullName();
        }

        return null;
    }

    public void manageFollowers(Event event) {
        List<ICalendarUser> attendeesSet = event.getAttendees();
        if (attendeesSet != null) {
            for (ICalendarUser user : attendeesSet) {
                if (user.getUser() != null) {
                    mailFollowerRepo.follow(event, user.getUser());
                } else {
                    MailAddress mailAddress = Beans.get(MailAddressRepository.class).findOrCreate(user.getEmail(),
                            user.getName());
                    mailFollowerRepo.follow(event, mailAddress);
                }

            }
        }
    }

    public Event checkModifications(Event event, Event previousEvent)
            throws AxelorException, ClassNotFoundException, InstantiationException, IllegalAccessException,
            IOException, MessagingException {
        Set<User> previousUserSet = previousEvent.getInternalGuestSet();
        Set<User> userSet = event.getInternalGuestSet();
        Set<Partner> previousContactSet = previousEvent.getExternalGuestSet();
        Set<Partner> contactSet = previousEvent.getExternalGuestSet();

        List<User> deletedUsers = this.deletedGuests(previousUserSet, userSet);
        List<User> addedUsers = this.addedGuests(previousUserSet, userSet);

        List<Partner> deletedContacts = this.deletedGuests(previousContactSet, contactSet);
        List<Partner> addedContacts = this.addedGuests(previousContactSet, contactSet);

        Template deletedGuestsTemplate = Beans.get(CrmConfigService.class)
                .getCrmConfig(event.getUser().getActiveCompany()).getMeetingGuestDeletedTemplate();
        Template addedGuestsTemplate = Beans.get(CrmConfigService.class)
                .getCrmConfig(event.getUser().getActiveCompany()).getMeetingGuestAddedTemplate();
        Template changedDateTemplate = Beans.get(CrmConfigService.class)
                .getCrmConfig(event.getUser().getActiveCompany()).getMeetingDateChangeTemplate();

        if (deletedGuestsTemplate == null || addedGuestsTemplate == null || changedDateTemplate == null) {
            throw new AxelorException(String.format(I18n.get(IExceptionMessage.CRM_CONFIG_TEMPLATES),
                    event.getUser().getActiveCompany()), IException.CONFIGURATION_ERROR);
        }
        if (!event.getEndDateTime().isEqual(previousEvent.getEndDateTime())) {
            for (Partner partner : contactSet) {
                Message message = Beans.get(TemplateMessageService.class).generateMessage(event,
                        changedDateTemplate);
                if (message.getFromEmailAddress() == null) {
                    message.setFromEmailAddress(event.getUser().getPartner().getEmailAddress());
                }
                message.addToEmailAddressSetItem(partner.getEmailAddress());
                message = Beans.get(MessageService.class).sendByEmail(message);
            }
            for (User user : userSet) {
                Message message = Beans.get(TemplateMessageService.class).generateMessage(event,
                        changedDateTemplate);
                if (message.getFromEmailAddress() == null) {
                    message.setFromEmailAddress(event.getUser().getPartner().getEmailAddress());
                }
                message.addToEmailAddressSetItem(user.getPartner().getEmailAddress());
                message = Beans.get(MessageService.class).sendByEmail(message);
            }
            Message message = Beans.get(TemplateMessageService.class).generateMessage(event, changedDateTemplate);
            if (message.getFromEmailAddress() == null) {
                message.setFromEmailAddress(event.getUser().getPartner().getEmailAddress());
            }
            message.addToEmailAddressSetItem(event.getUser().getPartner().getEmailAddress());
            message = Beans.get(MessageService.class).sendByEmail(message);

        }
        for (Partner partner : addedContacts) {
            Message message = Beans.get(TemplateMessageService.class).generateMessage(event, addedGuestsTemplate);
            if (message.getFromEmailAddress() == null) {
                message.setFromEmailAddress(event.getUser().getPartner().getEmailAddress());
            }
            message.addToEmailAddressSetItem(partner.getEmailAddress());
            message = Beans.get(MessageService.class).sendByEmail(message);
        }
        for (Partner partner : deletedContacts) {
            Message message = Beans.get(TemplateMessageService.class).generateMessage(event, deletedGuestsTemplate);
            if (message.getFromEmailAddress() == null) {
                message.setFromEmailAddress(event.getUser().getPartner().getEmailAddress());
            }
            message.addToEmailAddressSetItem(partner.getEmailAddress());
            message = Beans.get(MessageService.class).sendByEmail(message);
        }
        for (User user : addedUsers) {
            Message message = Beans.get(TemplateMessageService.class).generateMessage(event, addedGuestsTemplate);
            if (message.getFromEmailAddress() == null) {
                message.setFromEmailAddress(event.getUser().getPartner().getEmailAddress());
            }
            message.addToEmailAddressSetItem(user.getPartner().getEmailAddress());
            message = Beans.get(MessageService.class).sendByEmail(message);
        }
        for (User user : deletedUsers) {
            Message message = Beans.get(TemplateMessageService.class).generateMessage(event, deletedGuestsTemplate);
            if (message.getFromEmailAddress() == null) {
                message.setFromEmailAddress(event.getUser().getPartner().getEmailAddress());
            }
            message.addToEmailAddressSetItem(user.getPartner().getEmailAddress());
            message = Beans.get(MessageService.class).sendByEmail(message);
        }
        return event;
    }

    public <T> List<T> deletedGuests(Set<T> previousSet, Set<T> set) {
        List<T> deletedList = new ArrayList<T>();
        if (previousSet != null) {
            for (T object : previousSet) {
                if (set == null || set.isEmpty() || !set.contains(object)) {
                    deletedList.add(object);
                }
            }
        }
        return deletedList;
    }

    public <T> List<T> addedGuests(Set<T> previousSet, Set<T> set) {
        List<T> addedList = new ArrayList<T>();
        if (set != null) {
            for (T object : set) {
                if (previousSet == null || previousSet.isEmpty() || !previousSet.contains(object)) {
                    addedList.add(object);
                }
            }
        }
        return addedList;
    }

    public void sendMails(Event event) throws AxelorException, ClassNotFoundException, InstantiationException,
            IllegalAccessException, IOException, MessagingException {
        Template guestAddedTemplate = Beans.get(CrmConfigService.class)
                .getCrmConfig(event.getUser().getActiveCompany()).getMeetingGuestAddedTemplate();
        if (guestAddedTemplate == null) {
            throw new AxelorException(String.format(I18n.get(IExceptionMessage.CRM_CONFIG_TEMPLATES),
                    event.getUser().getActiveCompany()), IException.CONFIGURATION_ERROR);
        }
        if (event.getExternalGuestSet() != null) {
            for (Partner partner : event.getExternalGuestSet()) {
                Message message = Beans.get(TemplateMessageService.class).generateMessage(event,
                        guestAddedTemplate);
                if (message.getFromEmailAddress() == null) {
                    message.setFromEmailAddress(event.getUser().getPartner().getEmailAddress());
                }
                message.addToEmailAddressSetItem(partner.getEmailAddress());
                message = Beans.get(MessageService.class).sendByEmail(message);
            }
        }
        if (event.getInternalGuestSet() != null) {
            for (User user : event.getInternalGuestSet()) {
                Message message = Beans.get(TemplateMessageService.class).generateMessage(event,
                        guestAddedTemplate);
                if (message.getFromEmailAddress() == null) {
                    message.setFromEmailAddress(event.getUser().getPartner().getEmailAddress());
                }
                message.addToEmailAddressSetItem(user.getPartner().getEmailAddress());
                message = Beans.get(MessageService.class).sendByEmail(message);
            }
        }

        Message message = Beans.get(TemplateMessageService.class).generateMessage(event, guestAddedTemplate);
        if (message.getFromEmailAddress() == null) {
            message.setFromEmailAddress(event.getUser().getPartner().getEmailAddress());
        }
        message.addToEmailAddressSetItem(event.getUser().getPartner().getEmailAddress());
        message = Beans.get(MessageService.class).sendByEmail(message);
    }

    @Transactional
    public void addUserGuest(User user, Event event)
            throws ClassNotFoundException, InstantiationException, IllegalAccessException, AxelorException,
            MessagingException, IOException, ICalendarException, ValidationException, ParseException {
        if (user.getPartner() != null && user.getPartner().getEmailAddress() != null) {
            String email = user.getPartner().getEmailAddress().getAddress();
            if (event.getAttendees() != null && !Strings.isNullOrEmpty(email)) {
                boolean exist = false;
                for (ICalendarUser attendee : event.getAttendees()) {
                    if (email.equals(attendee.getEmail())) {
                        exist = true;
                        break;
                    }
                }
                if (!exist) {
                    ICalendarUser calUser = new ICalendarUser();
                    calUser.setEmail(email);
                    calUser.setName(user.getFullName());
                    calUser.setUser(user);
                    event.addAttendee(calUser);
                    eventRepo.save(event);
                    if (event.getCalendarCrm() != null) {
                        Beans.get(CalendarService.class).sync(event.getCalendarCrm());
                    }
                    this.sendMail(event, email);
                }
            }
        }
    }

    @Transactional
    public void addPartnerGuest(Partner partner, Event event)
            throws ClassNotFoundException, InstantiationException, IllegalAccessException, AxelorException,
            MessagingException, IOException, ICalendarException, ValidationException, ParseException {
        if (partner.getEmailAddress() != null) {
            String email = partner.getEmailAddress().getAddress();
            if (event.getAttendees() != null && !Strings.isNullOrEmpty(email)) {
                boolean exist = false;
                for (ICalendarUser attendee : event.getAttendees()) {
                    if (email.equals(attendee.getEmail())) {
                        exist = true;
                        break;
                    }
                }
                if (!exist) {
                    ICalendarUser calUser = new ICalendarUser();
                    calUser.setEmail(email);
                    calUser.setName(partner.getFullName());
                    if (partner.getUser() != null) {
                        calUser.setUser(partner.getUser());
                    }
                    event.addAttendee(calUser);
                    eventRepo.save(event);
                    if (event.getCalendarCrm() != null) {
                        Beans.get(CalendarService.class).sync(event.getCalendarCrm());
                    }
                    this.sendMail(event, email);

                }
            }
        }
    }

    @Transactional
    public void addEmailGuest(EmailAddress email, Event event)
            throws ClassNotFoundException, InstantiationException, IllegalAccessException, AxelorException,
            MessagingException, IOException, ICalendarException, ValidationException, ParseException {
        if (event.getAttendees() != null && email != null) {
            boolean exist = false;
            for (ICalendarUser attendee : event.getAttendees()) {
                if (email.getAddress().equals(attendee.getEmail())) {
                    exist = true;
                    break;
                }
            }
            if (!exist) {
                ICalendarUser calUser = new ICalendarUser();
                calUser.setEmail(email.getAddress());
                calUser.setName(email.getName());
                if (email.getPartner() != null && email.getPartner().getUser() != null) {
                    calUser.setUser(email.getPartner().getUser());
                }
                event.addAttendee(calUser);
                eventRepo.save(event);
            }
        }
    }

    @Transactional
    public void sendMail(Event event, String email)
            throws AxelorException, MessagingException, IOException, ClassNotFoundException, InstantiationException,
            IllegalAccessException, ValidationException, ParseException, ICalendarException {
        EmailAddress emailAddress = null;
        emailAddress = Beans.get(EmailAddressRepository.class).all().filter("self.address = ?1", email).fetchOne();
        if (emailAddress == null) {
            emailAddress = new EmailAddress(email);
        }
        Template guestAddedTemplate = Beans.get(CrmConfigService.class)
                .getCrmConfig(event.getUser().getActiveCompany()).getMeetingGuestAddedTemplate();
        Message message = new Message();
        if (guestAddedTemplate == null) {

            if (message.getFromEmailAddress() == null) {
                message.setFromEmailAddress(event.getUser().getPartner().getEmailAddress());
            }
            message.addToEmailAddressSetItem(emailAddress);
            message.setSubject(event.getSubject());
            message.setMailAccount(Beans.get(MailAccountService.class).getDefaultMailAccount());
        } else {
            message = Beans.get(TemplateMessageService.class).generateMessage(event, guestAddedTemplate);
            if (message.getFromEmailAddress() == null) {
                message.setFromEmailAddress(event.getUser().getPartner().getEmailAddress());
            }
            message.addToEmailAddressSetItem(emailAddress);
        }
        if (event.getUid() != null) {
            CalendarService calendarService = Beans.get(CalendarService.class);
            Calendar cal = calendarService.getCalendar(event.getUid(), event.getCalendarCrm());
            cal.getProperties().add(Method.REQUEST);
            File file = calendarService.export(cal);
            Path filePath = file.toPath();
            MetaFile metaFile = new MetaFile();
            metaFile.setFileName(file.getName());
            metaFile.setFileType(Files.probeContentType(filePath));
            metaFile.setFileSize(Files.size(filePath));
            metaFile.setFilePath(file.getName());
            Set<MetaFile> fileSet = new HashSet<MetaFile>();
            fileSet.add(metaFile);
            Beans.get(MessageRepository.class).save(message);
            Beans.get(MessageService.class).attachMetaFiles(message, fileSet);
        }
        message = Beans.get(MessageService.class).sendByEmail(message);
    }

    @Transactional
    public void addRecurrentEventsByDays(Event event, int periodicity, int endType, int repetitionsNumber,
            LocalDate endDate) {
        Event lastEvent = event;
        if (endType == 1) {
            int repeated = 0;
            while (repeated != repetitionsNumber) {
                Event copy = eventRepo.copy(lastEvent, false);
                copy.setParentEvent(lastEvent);
                copy.setStartDateTime(copy.getStartDateTime().plusDays(periodicity));
                copy.setEndDateTime(copy.getEndDateTime().plusDays(periodicity));
                eventRepo.save(copy);
                repeated++;
                lastEvent = copy;
            }
        } else {
            while (!lastEvent.getStartDateTime().plusDays(periodicity).isAfter(endDate)) {
                Event copy = eventRepo.copy(lastEvent, false);
                copy.setParentEvent(lastEvent);
                copy.setStartDateTime(copy.getStartDateTime().plusDays(periodicity));
                copy.setEndDateTime(copy.getEndDateTime().plusDays(periodicity));
                eventRepo.save(copy);
                lastEvent = copy;
            }
        }
    }

    @Transactional
    public void addRecurrentEventsByWeeks(Event event, int periodicity, int endType, int repetitionsNumber,
            LocalDate endDate, Map<Integer, Boolean> daysCheckedMap) {
        Event lastEvent = event;
        List<Integer> list = new ArrayList<Integer>();
        for (int day : daysCheckedMap.keySet()) {
            list.add(day);
        }
        Collections.sort(list);
        if (endType == 1) {
            int repeated = 0;
            Event copy = eventRepo.copy(lastEvent, false);
            copy.setParentEvent(lastEvent);
            int dayOfWeek = copy.getStartDateTime().getDayOfWeek();
            LocalDateTime nextDateTime = new LocalDateTime();
            if (dayOfWeek < list.get(0)) {
                nextDateTime = new LocalDateTime(copy.getStartDateTime().plusDays(list.get(0) - dayOfWeek));
            } else if (dayOfWeek > list.get(0)) {
                nextDateTime = new LocalDateTime(copy.getStartDateTime().plusDays((7 - dayOfWeek) + list.get(0)));
            }
            Duration dur = new Duration(copy.getStartDateTime().toDateTime(), copy.getEndDateTime().toDateTime());

            for (Integer integer : list) {
                nextDateTime.plusDays(integer - nextDateTime.getDayOfWeek());
                copy.setStartDateTime(nextDateTime);
                copy.setEndDateTime(nextDateTime.plus(dur));
                eventRepo.save(copy);
                lastEvent = copy;
                repeated++;
            }

            while (repeated < repetitionsNumber) {
                copy = eventRepo.copy(lastEvent, false);
                copy.setParentEvent(lastEvent);
                copy.setStartDateTime(copy.getStartDateTime().plusWeeks(periodicity));
                copy.setEndDateTime(copy.getEndDateTime().plusWeeks(periodicity));

                dayOfWeek = copy.getStartDateTime().getDayOfWeek();
                nextDateTime = new LocalDateTime();
                if (dayOfWeek < list.get(0)) {
                    nextDateTime = new LocalDateTime(copy.getStartDateTime().plusDays(list.get(0) - dayOfWeek));
                } else if (dayOfWeek > list.get(0)) {
                    nextDateTime = new LocalDateTime(
                            copy.getStartDateTime().plusDays((7 - dayOfWeek) + list.get(0)));
                }
                dur = new Duration(copy.getStartDateTime().toDateTime(), copy.getEndDateTime().toDateTime());

                for (Integer integer : list) {
                    nextDateTime.plusDays(integer - nextDateTime.getDayOfWeek());
                    copy.setStartDateTime(nextDateTime);
                    copy.setEndDateTime(nextDateTime.plus(dur));
                    eventRepo.save(copy);
                    lastEvent = copy;
                    repeated++;
                }
            }
        } else {

            Event copy = eventRepo.copy(lastEvent, false);
            copy.setParentEvent(lastEvent);
            int dayOfWeek = copy.getStartDateTime().getDayOfWeek();
            LocalDateTime nextDateTime = new LocalDateTime();
            if (dayOfWeek < list.get(0)) {
                nextDateTime = new LocalDateTime(copy.getStartDateTime().plusDays(list.get(0) - dayOfWeek));
            } else if (dayOfWeek > list.get(0)) {
                nextDateTime = new LocalDateTime(copy.getStartDateTime().plusDays((7 - dayOfWeek) + list.get(0)));
            }
            Duration dur = new Duration(copy.getStartDateTime().toDateTime(), copy.getEndDateTime().toDateTime());

            for (Integer integer : list) {
                nextDateTime.plusDays(integer - nextDateTime.getDayOfWeek());
                copy.setStartDateTime(nextDateTime);
                copy.setEndDateTime(nextDateTime.plus(dur));
                eventRepo.save(copy);
                lastEvent = copy;
            }

            while (!copy.getStartDateTime().plusWeeks(periodicity).isAfter(endDate)) {
                copy = eventRepo.copy(lastEvent, false);
                copy.setParentEvent(lastEvent);
                copy.setStartDateTime(copy.getStartDateTime().plusWeeks(periodicity));
                copy.setEndDateTime(copy.getEndDateTime().plusWeeks(periodicity));

                dayOfWeek = copy.getStartDateTime().getDayOfWeek();
                nextDateTime = new LocalDateTime();
                if (dayOfWeek < list.get(0)) {
                    nextDateTime = new LocalDateTime(copy.getStartDateTime().plusDays(list.get(0) - dayOfWeek));
                } else if (dayOfWeek > list.get(0)) {
                    nextDateTime = new LocalDateTime(
                            copy.getStartDateTime().plusDays((7 - dayOfWeek) + list.get(0)));
                }
                dur = new Duration(copy.getStartDateTime().toDateTime(), copy.getEndDateTime().toDateTime());

                for (Integer integer : list) {
                    nextDateTime.plusDays(integer - nextDateTime.getDayOfWeek());
                    copy.setStartDateTime(nextDateTime);
                    copy.setEndDateTime(nextDateTime.plus(dur));
                    eventRepo.save(copy);
                    lastEvent = copy;
                }
            }
        }
    }

    @Transactional
    public void addRecurrentEventsByMonths(Event event, int periodicity, int endType, int repetitionsNumber,
            LocalDate endDate, int monthRepeatType) {
        Event lastEvent = event;
        if (monthRepeatType == 1) {
            int dayOfMonth = event.getStartDateTime().getDayOfMonth();
            if (endType == 1) {
                int repeated = 0;
                while (repeated != repetitionsNumber) {
                    Event copy = eventRepo.copy(lastEvent, false);
                    copy.setParentEvent(lastEvent);
                    if (copy.getStartDateTime().plusMonths(periodicity).dayOfMonth()
                            .getMaximumValue() >= dayOfMonth) {
                        copy.setStartDateTime(copy.getStartDateTime().plusMonths(periodicity));
                        copy.setEndDateTime(copy.getEndDateTime().plusMonths(periodicity));
                        eventRepo.save(copy);
                        repeated++;
                        lastEvent = copy;
                    }
                }
            } else {
                while (!lastEvent.getStartDateTime().plusMonths(periodicity).isAfter(endDate)) {
                    Event copy = eventRepo.copy(lastEvent, false);
                    copy.setParentEvent(lastEvent);
                    if (copy.getStartDateTime().plusMonths(periodicity).dayOfMonth()
                            .getMaximumValue() >= dayOfMonth) {
                        copy.setStartDateTime(copy.getStartDateTime().plusMonths(periodicity));
                        copy.setEndDateTime(copy.getEndDateTime().plusMonths(periodicity));
                        eventRepo.save(copy);
                        lastEvent = copy;
                    }
                }
            }
        }

        else {
            int dayOfWeek = event.getStartDateTime().getDayOfWeek();
            int positionInMonth = 0;
            if (event.getStartDateTime().getDayOfMonth() % 7 == 0) {
                positionInMonth = event.getStartDateTime().getDayOfMonth() / 7;
            } else {
                positionInMonth = (event.getStartDateTime().getDayOfMonth() / 7) + 1;
            }

            if (endType == 1) {
                int repeated = 0;
                while (repeated != repetitionsNumber) {
                    Event copy = eventRepo.copy(lastEvent, false);
                    copy.setParentEvent(lastEvent);
                    LocalDateTime nextDateTime = new LocalDateTime(copy.getStartDateTime());
                    nextDateTime.plusMonths(periodicity);
                    int nextDayOfWeek = nextDateTime.getDayOfWeek();
                    if (nextDayOfWeek > dayOfWeek) {
                        nextDateTime.minusDays(nextDayOfWeek - dayOfWeek);
                    } else {
                        nextDateTime.plusDays(dayOfWeek - nextDayOfWeek);
                    }
                    int nextPositionInMonth = 0;
                    if (event.getStartDateTime().getDayOfMonth() % 7 == 0) {
                        nextPositionInMonth = event.getStartDateTime().getDayOfMonth() / 7;
                    } else {
                        nextPositionInMonth = (event.getStartDateTime().getDayOfMonth() / 7) + 1;
                    }
                    if (nextPositionInMonth > positionInMonth) {
                        nextDateTime.minusWeeks(nextPositionInMonth - positionInMonth);
                    } else {
                        nextDateTime.plusWeeks(positionInMonth - nextPositionInMonth);
                    }
                    Duration dur = new Duration(copy.getStartDateTime().toDateTime(),
                            copy.getEndDateTime().toDateTime());
                    copy.setStartDateTime(nextDateTime);
                    copy.setEndDateTime(nextDateTime.plus(dur));
                    eventRepo.save(copy);
                    repeated++;
                    lastEvent = copy;
                }
            } else {
                LocalDateTime nextDateTime = new LocalDateTime(lastEvent.getStartDateTime());
                nextDateTime.plusMonths(periodicity);
                int nextDayOfWeek = nextDateTime.getDayOfWeek();
                if (nextDayOfWeek > dayOfWeek) {
                    nextDateTime.minusDays(nextDayOfWeek - dayOfWeek);
                } else {
                    nextDateTime.plusDays(dayOfWeek - nextDayOfWeek);
                }
                int nextPositionInMonth = 0;
                if (event.getStartDateTime().getDayOfMonth() % 7 == 0) {
                    nextPositionInMonth = event.getStartDateTime().getDayOfMonth() / 7;
                } else {
                    nextPositionInMonth = (event.getStartDateTime().getDayOfMonth() / 7) + 1;
                }
                if (nextPositionInMonth > positionInMonth) {
                    nextDateTime.minusWeeks(nextPositionInMonth - positionInMonth);
                } else {
                    nextDateTime.plusWeeks(positionInMonth - nextPositionInMonth);
                }
                while (!nextDateTime.isAfter(endDate)) {
                    Event copy = eventRepo.copy(lastEvent, false);
                    copy.setParentEvent(lastEvent);

                    Duration dur = new Duration(copy.getStartDateTime().toDateTime(),
                            copy.getEndDateTime().toDateTime());
                    copy.setStartDateTime(nextDateTime);
                    copy.setEndDateTime(nextDateTime.plus(dur));
                    eventRepo.save(copy);
                    lastEvent = copy;

                    nextDateTime = new LocalDateTime(lastEvent.getStartDateTime());
                    nextDateTime.plusMonths(periodicity);
                    nextDayOfWeek = nextDateTime.getDayOfWeek();
                    if (nextDayOfWeek > dayOfWeek) {
                        nextDateTime.minusDays(nextDayOfWeek - dayOfWeek);
                    } else {
                        nextDateTime.plusDays(dayOfWeek - nextDayOfWeek);
                    }
                    nextPositionInMonth = 0;
                    if (event.getStartDateTime().getDayOfMonth() % 7 == 0) {
                        nextPositionInMonth = event.getStartDateTime().getDayOfMonth() / 7;
                    } else {
                        nextPositionInMonth = (event.getStartDateTime().getDayOfMonth() / 7) + 1;
                    }
                    if (nextPositionInMonth > positionInMonth) {
                        nextDateTime.minusWeeks(nextPositionInMonth - positionInMonth);
                    } else {
                        nextDateTime.plusWeeks(positionInMonth - nextPositionInMonth);
                    }
                }
            }
        }
    }

    @Transactional
    public void addRecurrentEventsByYears(Event event, int periodicity, int endType, int repetitionsNumber,
            LocalDate endDate) {
        Event lastEvent = event;
        if (endType == 1) {
            int repeated = 0;
            while (repeated != repetitionsNumber) {
                Event copy = eventRepo.copy(lastEvent, false);
                copy.setParentEvent(lastEvent);
                copy.setStartDateTime(copy.getStartDateTime().plusYears(periodicity));
                copy.setEndDateTime(copy.getEndDateTime().plusYears(periodicity));

                eventRepo.save(copy);
                repeated++;
                lastEvent = copy;
            }
        } else {
            while (!lastEvent.getStartDateTime().plusYears(periodicity).isAfter(endDate)) {
                Event copy = eventRepo.copy(lastEvent, false);
                copy.setParentEvent(lastEvent);
                copy.setStartDateTime(copy.getStartDateTime().plusYears(periodicity));
                copy.setEndDateTime(copy.getEndDateTime().plusYears(periodicity));
                eventRepo.save(copy);
                lastEvent = copy;
            }
        }
    }

    @Transactional
    public void applyChangesToAll(Event event) {

        Event child = eventRepo.all().filter("self.parentEvent.id = ?1", event.getId()).fetchOne();
        Event parent = event.getParentEvent();
        Event copyEvent = eventRepo.copy(event, false);
        while (child != null) {
            child.setSubject(event.getSubject());
            child.setCalendar(event.getCalendar());
            child.setStartDateTime(child.getStartDateTime().withHourOfDay(event.getStartDateTime().getHourOfDay()));
            child.setStartDateTime(
                    child.getStartDateTime().withMinuteOfHour(event.getStartDateTime().getMinuteOfHour()));
            child.setEndDateTime(child.getEndDateTime().withHourOfDay(event.getEndDateTime().getHourOfDay()));
            child.setEndDateTime(child.getEndDateTime().withMinuteOfHour(event.getEndDateTime().getMinuteOfHour()));
            child.setDuration(event.getDuration());
            child.setUser(event.getUser());
            child.setTeam(event.getTeam());
            child.setDisponibilitySelect(event.getDisponibilitySelect());
            child.setVisibilitySelect(event.getVisibilitySelect());
            child.setDescription(event.getDescription());
            child.setClientPartner(event.getClientPartner());
            child.setContactPartner(event.getContactPartner());
            child.setLead(event.getLead());
            child.setTypeSelect(event.getTypeSelect());
            child.setLocation(event.getLocation());
            eventRepo.save(child);
            copyEvent = child;
            child = eventRepo.all().filter("self.parentEvent.id = ?1", copyEvent.getId()).fetchOne();
        }
        while (parent != null) {
            Event nextParent = parent.getParentEvent();
            parent.setSubject(event.getSubject());
            parent.setCalendar(event.getCalendar());
            parent.setStartDateTime(
                    parent.getStartDateTime().withHourOfDay(event.getStartDateTime().getHourOfDay()));
            parent.setStartDateTime(
                    parent.getStartDateTime().withMinuteOfHour(event.getStartDateTime().getMinuteOfHour()));
            parent.setEndDateTime(parent.getEndDateTime().withHourOfDay(event.getEndDateTime().getHourOfDay()));
            parent.setEndDateTime(
                    parent.getEndDateTime().withMinuteOfHour(event.getEndDateTime().getMinuteOfHour()));
            parent.setDuration(event.getDuration());
            parent.setUser(event.getUser());
            parent.setTeam(event.getTeam());
            parent.setDisponibilitySelect(event.getDisponibilitySelect());
            parent.setVisibilitySelect(event.getVisibilitySelect());
            parent.setDescription(event.getDescription());
            parent.setClientPartner(event.getClientPartner());
            parent.setContactPartner(event.getContactPartner());
            parent.setLead(event.getLead());
            parent.setTypeSelect(event.getTypeSelect());
            parent.setLocation(event.getLocation());
            eventRepo.save(parent);
            parent = nextParent;
        }
    }
}