Merge pull request #45 from dgray16/master

Rewrite notification system.
This commit is contained in:
Jeroen Baten 2016-02-24 16:36:06 +01:00
commit 327360bd08
35 changed files with 1777 additions and 372 deletions

View file

@ -25,13 +25,20 @@ package org.libreplan.business.common.entities;
* {@link JobSchedulerConfiguration}
*
* @author Miciele Ghiorghis <m.ghiorghis@antoniusziekenhuis.nl>
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
*/
public enum JobClassNameEnum {
IMPORT_ROSTER_FROM_TIM_JOB("org.libreplan.importers", "ImportRosterFromTimJob"),
EXPORT_TIMESHEET_TO_TIM_JOB("org.libreplan.importers", "ExportTimesheetToTimJob"),
SYNC_ORDERELEMENTS_WITH_JIRA_ISSUES_JOB("org.libreplan.importers", "JiraOrderElementSynchronizerJob"),
SEND_EMAIL_JOB("org.libreplan.importers", "SendEmailJob");
SEND_EMAIL_TASK_ASSIGNED_TO_RESOURCE("org.libreplan.importers.notifications.jobs", "SendEmailOnTaskAssignedToResourceJob"),
SEND_EMAIL_RESOURCE_REMOVED_FROM_TASK("org.libreplan.importers.notifications.jobs", "SendEmailOnResourceRemovedFromTaskJob"),
SEND_EMAIL_MILESTONE_REACHED("org.libreplan.importers.notifications.jobs", "SendEmailOnMilestoneReachedJob"),
SEND_EMAIL_TASK_SHOULD_START("org.libreplan.importers.notifications.jobs", "SendEmailOnTaskShouldStartJob"),
SEND_EMAIL_TASK_SHOULD_FINISH("org.libreplan.importers.notifications.jobs", "SendEmailOnTaskShouldFinishJob"),
SEND_EMAIL_TIMESHEET_DATA_MISSING("org.libreplan.importers.notifications.jobs", "SendEmailOnTimesheetDataMissingJob");
private String packageName;
private String name;

View file

@ -32,10 +32,11 @@ import java.util.List;
*
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 19.10.15.
* on 19.10.2015.
*/
@Repository
public class EmailNotificationDAO extends GenericDAOHibernate<EmailNotification, Long> implements IEmailNotificationDAO {
public class EmailNotificationDAO extends GenericDAOHibernate<EmailNotification, Long>
implements IEmailNotificationDAO {
@Override
public List<EmailNotification> getAll() {

View file

@ -26,14 +26,19 @@ import static org.libreplan.business.i18n.I18nHelper._;
*
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 28.09.15.
* on 28.09.2015.
*
* TEMPLATE_N(_("Template N")) - for i18n
* TEMPLATE_A("Template A") - for general use (no internationalizing)
*/
public enum EmailTemplateEnum {
TEMPLATE_TASK_ASSIGNED_TO_RESOURCE(_("Task assigned to resource"));
TEMPLATE_TASK_ASSIGNED_TO_RESOURCE(_("Task assigned to resource")),
TEMPLATE_RESOURCE_REMOVED_FROM_TASK(_("Resource removed from task")),
TEMPLATE_MILESTONE_REACHED(_("Milestone reached")),
TEMPLATE_TODAY_TASK_SHOULD_START(_("Task should start")),
TEMPLATE_TODAY_TASK_SHOULD_FINISH(_("Task should finish")),
TEMPLATE_ENTER_DATA_IN_TIMESHEET(_("Enter data in timesheet"));
private final String templateType;

View file

@ -37,9 +37,7 @@ import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Restrictions;
import org.libreplan.business.common.IAdHocTransactionService;
import org.libreplan.business.common.daos.IntegrationEntityDAO;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.expensesheet.daos.IExpenseSheetLineDAO;
@ -88,15 +86,6 @@ public class OrderElementDAO extends IntegrationEntityDAO<OrderElement>
@Autowired
private ITaskSourceDAO taskSourceDAO;
@Autowired
private IOrderDAO orderDAO;
@Autowired
private IAdHocTransactionService transactionService;
@Autowired
private SessionFactory sessionFactory;
@Override
public List<OrderElement> findWithoutParent() {
Criteria c = getSession().createCriteria(OrderElement.class);
@ -260,6 +249,7 @@ public class OrderElementDAO extends IntegrationEntityDAO<OrderElement>
}
@Override
@Transactional
public List<OrderElement> getAll() {
return list(OrderElement.class);
}

View file

@ -30,6 +30,7 @@ import org.libreplan.business.planner.entities.TaskGroup;
/**
* @author Óscar González Fernández <ogonzalez@igalia.com>
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
*/
public interface ITaskElementDAO extends IGenericDAO<TaskElement, Long> {
@ -39,4 +40,8 @@ public interface ITaskElementDAO extends IGenericDAO<TaskElement, Long> {
List<TaskElement> getTaskElementsNoMilestonesWithoutTaskSource();
List<TaskElement> getTaskElementsWithMilestones();
List<TaskElement> getTaskElementsWithParentsWithoutMilestones();
}

View file

@ -42,6 +42,7 @@ import org.springframework.transaction.annotation.Transactional;
/**
* @author Óscar González Fernández <ogonzalez@igalia.com>
* @author Jacobo Aragunde Pérez <jaragunde@igalia.com>
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
*/
@Repository
@Scope(BeanDefinition.SCOPE_SINGLETON)
@ -135,4 +136,23 @@ public class TaskElementDAO extends GenericDAOHibernate<TaskElement, Long>
return query.list();
}
@Override
@Transactional
public List<TaskElement> getTaskElementsWithMilestones(){
String strQuery = "FROM TaskElement "
+ "WHERE id IN (SELECT id FROM TaskMilestone)";
Query query = getSession().createQuery(strQuery);
return query.list();
}
@Override
@Transactional
public List<TaskElement> getTaskElementsWithParentsWithoutMilestones() {
String strQuery = "FROM TaskElement "
+ "WHERE parent IS NOT NULL AND "
+ "id NOT IN (SELECT id FROM TaskMilestone)";
Query query = getSession().createQuery(strQuery);
return query.list();
}
}

View file

@ -24,13 +24,13 @@
column="last_sequence_code" />
<!-- Index created in a database-object section -->
<set name="exceptions" access="field" cascade="all-delete-orphan" batch-size="10">
<set name="exceptions" access="field" cascade="all-delete-orphan" batch-size="10" lazy="false">
<key column="base_calendar_id" />
<one-to-many class="CalendarException" />
</set>
<!-- Index created in a database-object section -->
<list name="calendarDataVersions" access="field" cascade="all-delete-orphan" batch-size="10">
<list name="calendarDataVersions" access="field" cascade="all-delete-orphan" batch-size="10" lazy="false">
<key column="base_calendar_id" />
<index column="position_in_calendar" />
<one-to-many class="CalendarData" />
@ -43,7 +43,7 @@
<one-to-many class="CalendarAvailability" />
</list>
<joined-subclass name="ResourceCalendar" table="resource_calendar">
<joined-subclass name="ResourceCalendar" table="resource_calendar" lazy="false">
<key column="base_calendar_id" />
<property name="capacity" not-null="true" />
<one-to-one name="resource"

View file

@ -27,7 +27,7 @@
</class>
<class name="EmailNotification" abstract="true" table="notification_queue">
<class name="EmailNotification" abstract="true" table="notification_queue" dynamic-insert="true">
<id name="id" access="property" type="long">
<generator class="hilo">

View file

@ -32,7 +32,7 @@
<!-- Indexed -->
<many-to-one name="parent" class="TaskGroup" cascade="none" column="parent"
index="idx_task_element_on_task_group" />
index="idx_task_element_on_task_group" lazy="false" />
<one-to-one name="taskSource" cascade="delete" />
@ -89,7 +89,7 @@
cascade="all"/>
<!-- Indexed on the other side -->
<set name="resourceAllocations" cascade="all-delete-orphan">
<set name="resourceAllocations" cascade="all-delete-orphan" lazy="false">
<key column="task" />
<one-to-many class="ResourceAllocation" />
</set>

View file

@ -1,302 +0,0 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2015 LibrePlan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 org.libreplan.importers;
import org.libreplan.business.common.Configuration;
import org.libreplan.business.common.daos.IConnectorDAO;
import org.libreplan.business.common.entities.Connector;
import org.libreplan.business.common.entities.ConnectorProperty;
import org.libreplan.business.email.entities.EmailNotification;
import org.libreplan.business.email.entities.EmailTemplate;
import org.libreplan.business.email.entities.EmailTemplateEnum;
import org.libreplan.business.resources.entities.Resource;
import org.libreplan.business.resources.entities.Worker;
import org.libreplan.business.settings.entities.Language;
import org.libreplan.web.email.IEmailNotificationModel;
import org.libreplan.web.email.IEmailTemplateModel;
import org.libreplan.web.planner.tabs.MultipleTabsPlannerController;
import org.libreplan.web.resources.worker.IWorkerModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Transport;
import javax.mail.Session;
import javax.mail.PasswordAuthentication;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.NoSuchProviderException;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
/**
* Sends E-mail to users with data that storing in notification_queue table
*
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 13.10.15.
*/
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class SendEmail implements ISendEmail {
@Autowired
private IEmailNotificationModel emailNotificationModel;
@Autowired
private IConnectorDAO connectorDAO;
@Autowired
private IWorkerModel workerModel;
@Autowired
private IEmailTemplateModel emailTemplateModel;
private List<EmailNotification> notifications;
private List<EmailTemplate> emailTemplates;
@Override
public void sendEmail() {
if ( Configuration.isEmailSendingEnabled() == true ){
if (validConnection() == true){
notifications = emailNotificationModel.getAll();
for (int i = 0; i < notifications.size(); i++) composeMessageForUser(notifications.get(i));
deleteAllNotificationsAfterSending();
}
}
}
private void composeMessageForUser(EmailNotification notification){
// Gather data about EmailTemplate needs to be used
Resource resource = notification.getResource();
EmailTemplateEnum type = notification.getType();
Locale locale;
Worker currentWorker = getCurrentWorker(resource.getId());
if ( currentWorker.getUser().getApplicationLanguage().equals(Language.BROWSER_LANGUAGE) ) {
locale = new Locale(System.getProperty("user.language"));
} else {
locale = new Locale(currentWorker.getUser().getApplicationLanguage().getLocale().getLanguage());
}
EmailTemplate currentEmailTemplate = findCurrentEmailTemplate(type, locale);
// Modify text that will be composed
String text = currentEmailTemplate.getContent();
if ( type.equals(EmailTemplateEnum.TEMPLATE_TASK_ASSIGNED_TO_RESOURCE) ){
text = text.replaceAll("\\{username\\}", currentWorker.getUser().getLoginName());
text = text.replaceAll("\\{firstname\\}", currentWorker.getUser().getFirstName());
text = text.replaceAll("\\{lastname\\}", currentWorker.getUser().getLastName());
text = text.replaceAll("\\{project\\}", notification.getProject().getName());
text = text.replaceAll("\\{resource\\}", notification.getResource().getName());
text = text.replaceAll("\\{task\\}", notification.getTask().getName());
text = text.replaceAll("\\{url\\}", MultipleTabsPlannerController.WELCOME_URL);
}
// Get/Set connection properties
List<ConnectorProperty> emailConnectorProperties = getEmailConnectorProperties();
String receiver = currentWorker.getUser().getEmail();
String protocol = null;
String host = null;
String port = null;
String sender = null;
String usrnme = null;
String psswrd = null;
for (int i = 0; i < emailConnectorProperties.size(); i++){
switch (i){
case 1: {
protocol = emailConnectorProperties.get(1).getValue();
break;
}
case 2: {
host = emailConnectorProperties.get(2).getValue();
break;
}
case 3: {
port = emailConnectorProperties.get(3).getValue();
break;
}
case 4: {
sender = emailConnectorProperties.get(4).getValue();
break;
}
case 5: {
usrnme = emailConnectorProperties.get(5).getValue();
break;
}
case 6: {
psswrd = emailConnectorProperties.get(6).getValue();
break;
}
}
}
// Set properties of connection
Properties properties = new Properties();
if ( protocol.equals("STARTTLS") ) {
properties.put("mail.smtp.starttls.enable", "true");
properties.put("mail.smtp.host", host);
properties.put("mail.smtp.socketFactory.port", port);
properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.put("mail.smtp.auth", "true");
properties.put("mail.smtp.port", port);
}
else if ( protocol.equals("SMTP") ) {
properties.put("mail.smtp.host", host);
properties.put("mail.smtp.port", port);
}
final String username = usrnme;
final String password = psswrd;
/* It is very important to use Session.getInstance instead of Session.getDefaultInstance */
Session mailSession = Session.getInstance(properties,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
// Send message
try{
MimeMessage message = new MimeMessage(mailSession);
message.setFrom(new InternetAddress(sender));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(receiver));
String subject = currentEmailTemplate.getSubject();
message.setSubject(subject);
message.setText(text);
Transport.send(message);
} catch (MessagingException e){throw new RuntimeException(e);}
}
private void deleteAllNotificationsAfterSending(){
emailNotificationModel.deleteAll();
}
private List<ConnectorProperty> getEmailConnectorProperties() {
Connector connector = connectorDAO.findUniqueByName("E-mail");
List<ConnectorProperty> properties = connector.getProperties();
return properties;
}
private EmailTemplate findCurrentEmailTemplate(EmailTemplateEnum templateEnum, Locale locale){
emailTemplates = emailTemplateModel.getAll();
for (EmailTemplate item : emailTemplates)
if ( item.getType().equals(templateEnum) && item.getLanguage().getLocale().equals(locale) )
return item;
return null;
}
private Worker getCurrentWorker(Long resourceID){
List<Worker> workerList = workerModel.getWorkers();
for(int i = 0; i < workerList.size(); i++)
if ( workerList.get(i).getId().equals(resourceID) )
return workerList.get(i);
return null;
}
private boolean validConnection(){
List<ConnectorProperty> emailConnectorProperties = getEmailConnectorProperties();
String protocol = null;
String host = null;
String port = null;
String usrnme = null;
String psswrd = null;
for (int i = 0; i < emailConnectorProperties.size(); i++){
switch (i){
case 1: {
protocol = emailConnectorProperties.get(1).getValue();
break;
}
case 2: {
host = emailConnectorProperties.get(2).getValue();
break;
}
case 3: {
port = emailConnectorProperties.get(3).getValue();
break;
}
case 5: {
usrnme = emailConnectorProperties.get(5).getValue();
break;
}
case 6: {
psswrd = emailConnectorProperties.get(6).getValue();
break;
}
}
}
// Set properties of connection
Properties properties = new Properties();
Transport transport = null;
try {
if (protocol.equals("SMTP")) {
properties.setProperty("mail.smtp.port", port);
properties.setProperty("mail.smtp.host", host);
Session session = Session.getInstance(properties, null);
transport = session.getTransport("smtp");
if (usrnme.equals("") && psswrd.equals("")) transport.connect();
} else if (protocol.equals("STARTTLS")) {
properties.setProperty("mail.smtps.port", port);
properties.setProperty("mail.smtps.host", host);
Session session = Session.getInstance(properties, null);
transport = session.getTransport("smtps");
if (!usrnme.equals("") && psswrd != null) transport.connect(host, usrnme, psswrd);
}
if (transport.isConnected()) return true;
} catch (NoSuchProviderException e) {}
catch (MessagingException e) {}
return false;
}
}

View file

@ -0,0 +1,237 @@
package org.libreplan.importers.notifications;
import org.libreplan.business.common.entities.ConnectorProperty;
import org.libreplan.business.email.entities.EmailNotification;
import org.libreplan.business.email.entities.EmailTemplate;
import org.libreplan.business.email.entities.EmailTemplateEnum;
import org.libreplan.business.resources.entities.Resource;
import org.libreplan.business.resources.entities.Worker;
import org.libreplan.business.settings.entities.Language;
import org.libreplan.business.users.entities.UserRole;
import org.libreplan.web.email.IEmailTemplateModel;
import org.libreplan.web.planner.tabs.MultipleTabsPlannerController;
import org.libreplan.web.resources.worker.IWorkerModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.zkoss.zul.Messagebox;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import static org.libreplan.web.I18nHelper._;
/**
* Sends E-mail to users with data that storing in notification_queue table
* and that are treat to incoming EmailNotification
*
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 20.01.2016.
*/
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class ComposeMessage {
@Autowired
private IWorkerModel workerModel;
@Autowired
private IEmailTemplateModel emailTemplateModel;
@Autowired
private EmailConnectionValidator emailConnectionValidator;
private String protocol;
private String host;
private String port;
private String sender;
private String usrnme;
private String psswrd;
private Properties properties;
public boolean composeMessageForUser(EmailNotification notification) {
// Gather data about EmailTemplate needs to be used
Resource resource = notification.getResource();
EmailTemplateEnum type = notification.getType();
Locale locale;
Worker currentWorker = getCurrentWorker(resource.getId());
UserRole currentUserRole = getCurrentUserRole(notification.getType());
if ( currentWorker.getUser().isInRole(currentUserRole) ){
if ( currentWorker.getUser().getApplicationLanguage().equals(Language.BROWSER_LANGUAGE) ) {
locale = new Locale(System.getProperty("user.language"));
} else {
locale = new Locale(currentWorker.getUser().getApplicationLanguage().getLocale().getLanguage());
}
EmailTemplate currentEmailTemplate = findCurrentEmailTemplate(type, locale);
// Modify text that will be composed
String text = currentEmailTemplate.getContent();
text = replaceKeywords(text, currentWorker, notification);
String receiver = currentWorker.getUser().getEmail();
setupConnectionProperties();
final String username = usrnme;
final String password = psswrd;
// It is very important to use Session.getInstance instead of Session.getDefaultInstance
Session mailSession = Session.getInstance(properties,
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
});
// Send message
try{
MimeMessage message = new MimeMessage(mailSession);
message.setFrom(new InternetAddress(sender));
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(receiver));
String subject = currentEmailTemplate.getSubject();
message.setSubject(subject);
message.setText(text);
Transport.send(message);
return true;
} catch (MessagingException e) {
throw new RuntimeException(e);
} catch (NullPointerException e){
if (receiver == null) try {
Messagebox.show(_(currentWorker.getUser().getLoginName() + " - this user have not filled E-mail"), _("Error"),
Messagebox.OK, Messagebox.ERROR);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
return false;
}
private Worker getCurrentWorker(Long resourceID){
List<Worker> workerList = workerModel.getWorkers();
for(int i = 0; i < workerList.size(); i++)
if ( workerList.get(i).getId().equals(resourceID) )
return workerList.get(i);
return null;
}
private EmailTemplate findCurrentEmailTemplate(EmailTemplateEnum templateEnum, Locale locale){
List<EmailTemplate> emailTemplates;
emailTemplates = emailTemplateModel.getAll();
for (EmailTemplate item : emailTemplates)
if ( item.getType().equals(templateEnum) && item.getLanguage().getLocale().equals(locale) )
return item;
return null;
}
private String replaceKeywords(String text, Worker currentWorker, EmailNotification notification){
if ( notification.getType().equals(EmailTemplateEnum.TEMPLATE_ENTER_DATA_IN_TIMESHEET) ){
// It is because there is no other data for
// EmailNotification of TEMPLATE_ENTER_DATA_IN_TIMESHEET notification type
text = text.replaceAll("\\{resource\\}", notification.getResource().getName());
}
else {
text = text.replaceAll("\\{username\\}", currentWorker.getUser().getLoginName());
text = text.replaceAll("\\{firstname\\}", currentWorker.getUser().getFirstName());
text = text.replaceAll("\\{lastname\\}", currentWorker.getUser().getLastName());
text = text.replaceAll("\\{project\\}", notification.getProject().getName());
text = text.replaceAll("\\{resource\\}", notification.getResource().getName());
text = text.replaceAll("\\{task\\}", notification.getTask().getName());
text = text.replaceAll("\\{url\\}", MultipleTabsPlannerController.WELCOME_URL);
}
return text;
}
private void setupConnectionProperties(){
List<ConnectorProperty> emailConnectorProperties = emailConnectionValidator.getEmailConnectorProperties();
for (int i = 0; i < emailConnectorProperties.size(); i++){
switch (i){
case 1: {
protocol = emailConnectorProperties.get(1).getValue();
break;
}
case 2: {
host = emailConnectorProperties.get(2).getValue();
break;
}
case 3: {
port = emailConnectorProperties.get(3).getValue();
break;
}
case 4: {
sender = emailConnectorProperties.get(4).getValue();
break;
}
case 5: {
usrnme = emailConnectorProperties.get(5).getValue();
break;
}
case 6: {
psswrd = emailConnectorProperties.get(6).getValue();
break;
}
}
}
properties = new Properties();
if ( protocol.equals("STARTTLS") ) {
properties.put("mail.smtp.starttls.enable", "true");
properties.put("mail.smtp.host", host);
properties.put("mail.smtp.socketFactory.port", port);
properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
properties.put("mail.smtp.auth", "true");
properties.put("mail.smtp.port", port);
}
else if ( protocol.equals("SMTP") ) {
properties.put("mail.smtp.host", host);
properties.put("mail.smtp.port", port);
}
}
private UserRole getCurrentUserRole(EmailTemplateEnum type){
switch (type){
case TEMPLATE_TASK_ASSIGNED_TO_RESOURCE: return UserRole.ROLE_EMAIL_TASK_ASSIGNED_TO_RESOURCE;
case TEMPLATE_RESOURCE_REMOVED_FROM_TASK: return UserRole.ROLE_EMAIL_RESOURCE_REMOVED_FROM_TASK;
case TEMPLATE_MILESTONE_REACHED: return UserRole.ROLE_EMAIL_MILESTONE_REACHED;
case TEMPLATE_TODAY_TASK_SHOULD_START: return UserRole.ROLE_EMAIL_TASK_SHOULD_START;
case TEMPLATE_TODAY_TASK_SHOULD_FINISH: return UserRole.ROLE_EMAIL_TASK_SHOULD_FINISH;
case TEMPLATE_ENTER_DATA_IN_TIMESHEET: return UserRole.ROLE_EMAIL_TIMESHEET_DATA_MISSING;
}
return null;
}
}

View file

@ -0,0 +1,138 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2016 LibrePlan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 org.libreplan.importers.notifications;
import org.libreplan.business.common.daos.IConnectorDAO;
import org.libreplan.business.common.entities.Connector;
import org.libreplan.business.common.entities.ConnectorProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session;
import javax.mail.Transport;
import java.util.List;
import java.util.Properties;
/**
* Validate Email Connection properties
*
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 20.01.2016.
*/
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class EmailConnectionValidator {
@Autowired
private IConnectorDAO connectorDAO;
public boolean validConnection(){
List<ConnectorProperty> emailConnectorProperties = getEmailConnectorProperties();
String protocol = null;
String host = null;
String port = null;
String usrnme = null;
String psswrd = null;
for (int i = 0; i < emailConnectorProperties.size(); i++){
switch (i){
case 1: {
protocol = emailConnectorProperties.get(1).getValue();
break;
}
case 2: {
host = emailConnectorProperties.get(2).getValue();
break;
}
case 3: {
port = emailConnectorProperties.get(3).getValue();
break;
}
case 5: {
usrnme = emailConnectorProperties.get(5).getValue();
break;
}
case 6: {
psswrd = emailConnectorProperties.get(6).getValue();
break;
}
}
}
// Set properties of connection
Properties properties = new Properties();
Transport transport = null;
try {
if (protocol.equals("SMTP")) {
properties.setProperty("mail.smtp.port", port);
properties.setProperty("mail.smtp.host", host);
Session session = Session.getInstance(properties, null);
transport = session.getTransport("smtp");
if (usrnme.equals("") && psswrd.equals("")) transport.connect();
} else if (protocol.equals("STARTTLS")) {
properties.setProperty("mail.smtps.port", port);
properties.setProperty("mail.smtps.host", host);
Session session = Session.getInstance(properties, null);
transport = session.getTransport("smtps");
if (!usrnme.equals("") && psswrd != null) transport.connect(host, usrnme, psswrd);
}
if (transport != null && transport.isConnected()) return true;
} catch (NoSuchProviderException e) {
e.printStackTrace();
}
catch (MessagingException e) {
e.printStackTrace();
}
return false;
}
public List<ConnectorProperty> getEmailConnectorProperties() {
Connector connector = connectorDAO.findUniqueByName("E-mail");
return connector.getProperties();
}
public boolean isConnectionActivated(){
List<ConnectorProperty> emailConnectorProperties = getEmailConnectorProperties();
for (ConnectorProperty item : emailConnectorProperties){
if ( item.getKey().equals("Activated") )
if ( item.getValue().equals("Y") )
return true;
else break;
}
return false;
}
}

View file

@ -17,17 +17,20 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.libreplan.importers;
package org.libreplan.importers.notifications;
import org.libreplan.business.email.entities.EmailNotification;
/**
* Sends E-mail to users with data that storing in notification_queue table
*
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 13.10.15.
* on 13.10.2015.
*/
public interface ISendEmail {
public interface IEmailNotificationJob {
void sendEmail();
boolean composeMessageForUser(EmailNotification notification);
}

View file

@ -0,0 +1,51 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2016 LibrePlan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 org.libreplan.importers.notifications.jobs;
import org.libreplan.importers.notifications.IEmailNotificationJob;
import org.libreplan.importers.notifications.realization.SendEmailOnMilestoneReached;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.QuartzJobBean;
/**
* Sends E-mail to users with data that storing in notification_queue table
* and that are treat to {@link EmailTemplateEnum.TEMPLATE_MILESTONE_REACHED}
*
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 20.01.2016.
*
*/
public class SendEmailOnMilestoneReachedJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
ApplicationContext applicationContext = (ApplicationContext) context.getJobDetail().
getJobDataMap().get("applicationContext");
IEmailNotificationJob milestoneReached = (SendEmailOnMilestoneReached) applicationContext
.getBean("SendEmailOnMilestoneReached");
milestoneReached.sendEmail();
}
}

View file

@ -0,0 +1,50 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2016 LibrePlan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 org.libreplan.importers.notifications.jobs;
import org.libreplan.importers.notifications.IEmailNotificationJob;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.QuartzJobBean;
/**
* Sends E-mail to users with data that storing in notification_queue table
* and that are treat to {@link EmailTemplateEnum.TEMPLATE_RESOURCE_REMOVED_FROM_TASK}
*
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 20.01.2016.
*
*/
public class SendEmailOnResourceRemovedFromTaskJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
ApplicationContext applicationContext = (ApplicationContext) context.getJobDetail().
getJobDataMap().get("applicationContext");
IEmailNotificationJob resourceRemovedFromTask = (IEmailNotificationJob) applicationContext
.getBean("SendEmailOnResourceRemovedFromTask");
resourceRemovedFromTask.sendEmail();
}
}

View file

@ -17,8 +17,10 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.libreplan.importers;
package org.libreplan.importers.notifications.jobs;
import org.libreplan.importers.notifications.IEmailNotificationJob;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.context.ApplicationContext;
@ -26,22 +28,25 @@ import org.springframework.scheduling.quartz.QuartzJobBean;
/**
* Sends E-mail to users with data that storing in notification_queue table
* and that are treat to {@link EmailTemplateEnum.TEMPLATE_TASK_ASSIGNED_TO_RESOURCE}
*
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 13.10.15.
* on 13.10.2015.
*
*/
public class SendEmailJob extends QuartzJobBean {
public class SendEmailOnTaskAssignedToResourceJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
ApplicationContext applicationContext = (ApplicationContext) context.getJobDetail().
getJobDataMap().get("applicationContext");
ISendEmail sendEmail = (ISendEmail) applicationContext.getBean("sendEmail");
sendEmail.sendEmail();
IEmailNotificationJob taskAssignedToResource = (IEmailNotificationJob) applicationContext
.getBean("SendEmailOnTaskAssignedToResource");
taskAssignedToResource.sendEmail();
}
}

View file

@ -0,0 +1,50 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2016 LibrePlan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 org.libreplan.importers.notifications.jobs;
import org.libreplan.importers.notifications.IEmailNotificationJob;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.QuartzJobBean;
/**
* Sends E-mail to users with data that storing in notification_queue table
* and that are treat to {@link EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_FINISH}
*
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 20.01.2016.
*
*/
public class SendEmailOnTaskShouldFinishJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
ApplicationContext applicationContext = (ApplicationContext) context.getJobDetail().
getJobDataMap().get("applicationContext");
IEmailNotificationJob taskShouldFinish = (IEmailNotificationJob) applicationContext
.getBean("SendEmailOnTaskShouldFinish");
taskShouldFinish.sendEmail();
}
}

View file

@ -0,0 +1,50 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2016 LibrePlan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 org.libreplan.importers.notifications.jobs;
import org.libreplan.importers.notifications.IEmailNotificationJob;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.QuartzJobBean;
/**
* Sends E-mail to users with data that storing in notification_queue table
* and that are treat to {@link EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_START}
*
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 20.01.2016.
*
*/
public class SendEmailOnTaskShouldStartJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
ApplicationContext applicationContext = (ApplicationContext) context.getJobDetail().
getJobDataMap().get("applicationContext");
IEmailNotificationJob taskShouldStart = (IEmailNotificationJob) applicationContext
.getBean("SendEmailOnTaskShouldStart");
taskShouldStart.sendEmail();
}
}

View file

@ -0,0 +1,50 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2016 LibrePlan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 org.libreplan.importers.notifications.jobs;
import org.libreplan.importers.notifications.IEmailNotificationJob;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.quartz.QuartzJobBean;
/**
* Sends E-mail to users with data that storing in notification_queue table
* and that are treat to {@link EmailTemplateEnum.TEMPLATE_ENTER_DATA_IN_TIMESHEET}
*
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 20.01.2016.
*
*/
public class SendEmailOnTimesheetDataMissingJob extends QuartzJobBean {
@Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
ApplicationContext applicationContext = (ApplicationContext) context.getJobDetail().
getJobDataMap().get("applicationContext");
IEmailNotificationJob timesheetMissing = (IEmailNotificationJob) applicationContext
.getBean("SendEmailOnTimesheetDataMissing");
timesheetMissing.sendEmail();
}
}

View file

@ -0,0 +1,155 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2016 LibrePlan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 org.libreplan.importers.notifications.realization;
import org.joda.time.LocalDate;
import org.libreplan.business.common.Configuration;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.email.entities.EmailNotification;
import org.libreplan.business.email.entities.EmailTemplateEnum;
import org.libreplan.business.planner.daos.ITaskElementDAO;
import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.business.users.daos.IUserDAO;
import org.libreplan.business.users.entities.User;
import org.libreplan.business.users.entities.UserRole;
import org.libreplan.importers.notifications.ComposeMessage;
import org.libreplan.importers.notifications.EmailConnectionValidator;
import org.libreplan.importers.notifications.IEmailNotificationJob;
import org.libreplan.web.email.IEmailNotificationModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
/**
* Sends E-mail to manager user (it writes in responsible field in project properties)
* with data that storing in notification_queue table
* and that are treat to {@link EmailTemplateEnum.TEMPLATE_MILESTONE_REACHED}
* Date will be send on current date equals to deadline date of {@link Milestone}
* But it will be only send to Manager (you can assign him in project properties)
*
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 20.01.2016.
*/
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class SendEmailOnMilestoneReached implements IEmailNotificationJob {
@Autowired
private IEmailNotificationModel emailNotificationModel;
@Autowired
private ITaskElementDAO taskElementDAO;
@Autowired
private IUserDAO userDAO;
@Autowired
private ComposeMessage composeMessage;
@Autowired
EmailConnectionValidator emailConnectionValidator;
@Override
public void sendEmail() {
// Gathering data
checkMilestoneDate();
if ( Configuration.isEmailSendingEnabled() ){
if ( emailConnectionValidator.isConnectionActivated() )
if ( emailConnectionValidator.validConnection() ){
List<EmailNotification> notifications = emailNotificationModel
.getAllByType(EmailTemplateEnum.TEMPLATE_MILESTONE_REACHED);
for (int i = 0; i < notifications.size(); i++)
if ( composeMessageForUser(notifications.get(i)) )
deleteSingleNotification(notifications.get(i));
}
}
}
@Override
public boolean composeMessageForUser(EmailNotification notification) {
return composeMessage.composeMessageForUser(notification);
}
private void deleteSingleNotification(EmailNotification notification){
emailNotificationModel.deleteById(notification);
}
private void sendEmailNotificationToManager(TaskElement item){
emailNotificationModel.setNewObject();
emailNotificationModel.setType(EmailTemplateEnum.TEMPLATE_MILESTONE_REACHED);
emailNotificationModel.setUpdated(new Date());
String responsible = "";
if ( item.getParent().getOrderElement().getOrder().getResponsible() != null )
responsible = item.getParent().getOrderElement().getOrder().getResponsible();
User user = null;
try {
user = userDAO.findByLoginName(responsible);
} catch (InstanceNotFoundException e) {
e.printStackTrace();
}
if ( user.getWorker() != null && user.isInRole(UserRole.ROLE_EMAIL_MILESTONE_REACHED) ) {
emailNotificationModel.setResource(user.getWorker());
emailNotificationModel.setTask(item);
emailNotificationModel.setProject(item.getParent());
emailNotificationModel.confirmSave();
}
}
public void checkMilestoneDate() {
List<TaskElement> list = taskElementDAO.getTaskElementsWithMilestones();
LocalDate date = new LocalDate();
int currentYear = date.getYear();
int currentMonth = date.getMonthOfYear();
int currentDay = date.getDayOfMonth();
for (TaskElement item : list){
if ( item.getDeadline() != null ){
LocalDate deadline = item.getDeadline();
int deadlineYear = deadline.getYear();
int deadlineMonth = deadline.getMonthOfYear();
int deadlineDay = deadline.getDayOfMonth();
if (currentYear == deadlineYear &&
currentMonth == deadlineMonth &&
currentDay == deadlineDay)
sendEmailNotificationToManager(item);
}
}
}
}

View file

@ -0,0 +1,89 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2016 LibrePlan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 org.libreplan.importers.notifications.realization;
import org.libreplan.business.common.Configuration;
import org.libreplan.business.email.entities.EmailNotification;
import org.libreplan.business.email.entities.EmailTemplateEnum;
import org.libreplan.importers.notifications.ComposeMessage;
import org.libreplan.importers.notifications.EmailConnectionValidator;
import org.libreplan.importers.notifications.IEmailNotificationJob;
import org.libreplan.web.email.IEmailNotificationModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* Sends E-mail to users with data that storing in notification_queue table
* and that are treat to TEMPLATE_RESOUCE_REMOVED_FROM_TASK
* Data will be send if resource has been removed from task (in resource allocation)
*
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 20.01.2016.
*/
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class SendEmailOnResourceRemovedFromTask implements IEmailNotificationJob {
@Autowired
private IEmailNotificationModel emailNotificationModel;
@Autowired
private EmailConnectionValidator emailConnectionValidator;
@Autowired
private ComposeMessage composeMessage;
@Override
public void sendEmail() {
// At this time all data have gathered, if it exists of course
if ( Configuration.isEmailSendingEnabled() ){
if ( emailConnectionValidator.isConnectionActivated() )
if ( emailConnectionValidator.validConnection() ){
List<EmailNotification> notifications = emailNotificationModel
.getAllByType(EmailTemplateEnum.TEMPLATE_RESOURCE_REMOVED_FROM_TASK);
for (int i = 0; i < notifications.size(); i++)
if ( composeMessageForUser(notifications.get(i)) )
deleteSingleNotification(notifications.get(i));
}
}
}
@Override
public boolean composeMessageForUser(EmailNotification notification) {
return composeMessage.composeMessageForUser(notification);
}
private void deleteSingleNotification(EmailNotification notification){
emailNotificationModel.deleteById(notification);
}
}

View file

@ -0,0 +1,89 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2015 LibrePlan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 org.libreplan.importers.notifications.realization;
import org.libreplan.business.common.Configuration;
import org.libreplan.business.email.entities.EmailNotification;
import org.libreplan.business.email.entities.EmailTemplateEnum;
import org.libreplan.importers.notifications.ComposeMessage;
import org.libreplan.importers.notifications.EmailConnectionValidator;
import org.libreplan.importers.notifications.IEmailNotificationJob;
import org.libreplan.web.email.IEmailNotificationModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
/**
* Sends E-mail to users with data that storing in notification_queue table
* and that are treat to {@link EmailTemplateEnum.TEMPLATE_ENTER_DATA_IN_TIMESHEET}
* Data will be send after user will be assigned to some task.
*
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 13.10.2015.
*/
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class SendEmailOnTaskAssignedToResource implements IEmailNotificationJob {
@Autowired
private IEmailNotificationModel emailNotificationModel;
@Autowired
private EmailConnectionValidator emailConnectionValidator;
@Autowired
private ComposeMessage composeMessage;
@Override
@Transactional
public void sendEmail() {
if ( Configuration.isEmailSendingEnabled() ){
if ( emailConnectionValidator.isConnectionActivated() )
if ( emailConnectionValidator.validConnection() ){
List<EmailNotification> notifications = emailNotificationModel
.getAllByType(EmailTemplateEnum.TEMPLATE_TASK_ASSIGNED_TO_RESOURCE);
for (int i = 0; i < notifications.size(); i++)
if ( composeMessageForUser(notifications.get(i)) )
deleteSingleNotification(notifications.get(i));
}
}
}
@Override
public boolean composeMessageForUser(EmailNotification notification) {
return composeMessage.composeMessageForUser(notification);
}
private void deleteSingleNotification(EmailNotification notification){
emailNotificationModel.deleteById(notification);
}
}

View file

@ -0,0 +1,145 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2016 LibrePlan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 org.libreplan.importers.notifications.realization;
import org.libreplan.business.common.Configuration;
import org.libreplan.business.email.entities.EmailNotification;
import org.libreplan.business.email.entities.EmailTemplateEnum;
import org.libreplan.business.planner.daos.ITaskElementDAO;
import org.libreplan.business.planner.entities.ResourceAllocation;
import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.business.resources.entities.Resource;
import org.libreplan.importers.notifications.ComposeMessage;
import org.libreplan.importers.notifications.EmailConnectionValidator;
import org.libreplan.importers.notifications.IEmailNotificationJob;
import org.libreplan.web.email.IEmailNotificationModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* Sends E-mail to users with data that storing in notification_queue table
* and that are treat to {@link EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_FINISH}
* Data will be send when current day equals to finish date.
*
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 21.01.2016.
*/
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class SendEmailOnTaskShouldFinish implements IEmailNotificationJob {
@Autowired
private IEmailNotificationModel emailNotificationModel;
@Autowired
private ITaskElementDAO taskElementDAO;
@Autowired
private ComposeMessage composeMessage;
@Autowired
private EmailConnectionValidator emailConnectionValidator;
@Override
public void sendEmail() {
// Gather data for email sending
taskShouldFinish();
if ( Configuration.isEmailSendingEnabled() ){
if ( emailConnectionValidator.isConnectionActivated() )
if ( emailConnectionValidator.validConnection() ){
List<EmailNotification> notifications = emailNotificationModel
.getAllByType(EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_FINISH);
for (int i = 0; i < notifications.size(); i++)
if ( composeMessageForUser(notifications.get(i)) )
deleteSingleNotification(notifications.get(i));
}
}
}
@Override
public boolean composeMessageForUser(EmailNotification notification) {
return composeMessage.composeMessageForUser(notification);
}
private void deleteSingleNotification(EmailNotification notification){
emailNotificationModel.deleteById(notification);
}
@Transactional
public void taskShouldFinish() {
// Check if current date equals with item date
Date date = new Date();
int currentYear = date.getYear();
int currentMonth = date.getMonth();
int currentDay = date.getDay();
List<TaskElement> tasks = taskElementDAO.getTaskElementsWithParentsWithoutMilestones();
for (TaskElement item : tasks){
Date endDate = item.getEndDate();
int endYear = endDate.getYear();
int endMonth = endDate.getMonth();
int endDay = endDate.getDay();
if ( currentYear == endYear &&
currentMonth == endMonth &&
currentDay == endDay ){
// Get all resources for current task and send them email notification
sendEmailNotificationAboutTaskShouldFinish(item);
}
}
}
private void sendEmailNotificationAboutTaskShouldFinish(TaskElement item){
List<ResourceAllocation<?>> list = new ArrayList<ResourceAllocation<?>>();
list.addAll(item.getAllResourceAllocations());
List<Resource> resources = new ArrayList<Resource>();
for (ResourceAllocation<?> allocation : list)
resources.add(allocation.getAssociatedResources().get(0));
for (Resource resourceItem : resources){
emailNotificationModel.setNewObject();
emailNotificationModel.setType(EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_FINISH);
emailNotificationModel.setUpdated(new Date());
emailNotificationModel.setResource(resourceItem);
emailNotificationModel.setTask(item);
emailNotificationModel.setProject(item.getParent());
emailNotificationModel.confirmSave();
}
}
}

View file

@ -0,0 +1,144 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2016 LibrePlan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 org.libreplan.importers.notifications.realization;
import org.libreplan.business.common.Configuration;
import org.libreplan.business.email.entities.EmailNotification;
import org.libreplan.business.email.entities.EmailTemplateEnum;
import org.libreplan.business.planner.daos.ITaskElementDAO;
import org.libreplan.business.planner.entities.ResourceAllocation;
import org.libreplan.business.planner.entities.TaskElement;
import org.libreplan.business.resources.entities.Resource;
import org.libreplan.importers.notifications.ComposeMessage;
import org.libreplan.importers.notifications.EmailConnectionValidator;
import org.libreplan.importers.notifications.IEmailNotificationJob;
import org.libreplan.web.email.IEmailNotificationModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* Sends E-mail users with data that storing in notification_queue table
* and that are treat to {@link EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_START}
* Data will be send if current data equals to start date.
*
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 20.01.2016.
*/
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class SendEmailOnTaskShouldStart implements IEmailNotificationJob {
@Autowired
private IEmailNotificationModel emailNotificationModel;
@Autowired
private ITaskElementDAO taskElementDAO;
@Autowired
private ComposeMessage composeMessage;
@Autowired
private EmailConnectionValidator emailConnectionValidator;
@Override
public void sendEmail() {
// Gather data
taskShouldStart();
if ( Configuration.isEmailSendingEnabled() ){
if ( emailConnectionValidator.isConnectionActivated() )
if ( emailConnectionValidator.validConnection() ){
List<EmailNotification> notifications = emailNotificationModel
.getAllByType(EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_START);
for (int i = 0; i < notifications.size(); i++)
if ( composeMessageForUser(notifications.get(i)) )
deleteSingleNotification(notifications.get(i));
}
}
}
@Override
public boolean composeMessageForUser(EmailNotification notification) {
return composeMessage.composeMessageForUser(notification);
}
private void deleteSingleNotification(EmailNotification notification){
emailNotificationModel.deleteById(notification);
}
@Transactional
public void taskShouldStart() {
// Check if current date equals with item date
Date date = new Date();
int currentYear = date.getYear();
int currentMonth = date.getMonth();
int currentDay = date.getDay();
List<TaskElement> tasks = taskElementDAO.getTaskElementsWithParentsWithoutMilestones();
for (TaskElement item : tasks){
Date startDate = item.getStartDate();
int startYear = startDate.getYear();
int startMonth = startDate.getMonth();
int startDay = startDate.getDay();
if ( currentYear == startYear &&
currentMonth == startMonth &&
currentDay == startDay){
// Get all resources for current task and send them email notification
sendEmailNotificationAboutTaskShouldStart(item);
}
}
}
private void sendEmailNotificationAboutTaskShouldStart(TaskElement item){
List<ResourceAllocation<?>> list = new ArrayList<ResourceAllocation<?>>();
list.addAll(item.getAllResourceAllocations());
List<Resource> resources = new ArrayList<Resource>();
for (ResourceAllocation<?> allocation : list)
resources.add(allocation.getAssociatedResources().get(0));
for (Resource resourceItem : resources){
emailNotificationModel.setNewObject();
emailNotificationModel.setType(EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_START);
emailNotificationModel.setUpdated(new Date());
emailNotificationModel.setResource(resourceItem);
emailNotificationModel.setTask(item);
emailNotificationModel.setProject(item.getParent());
emailNotificationModel.confirmSave();
}
}
}

View file

@ -0,0 +1,254 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2016 LibrePlan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* 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 org.libreplan.importers.notifications.realization;
import org.joda.time.LocalDate;
import org.libreplan.business.common.Configuration;
import org.libreplan.business.common.daos.IConfigurationDAO;
import org.libreplan.business.common.entities.PersonalTimesheetsPeriodicityEnum;
import org.libreplan.business.email.entities.EmailNotification;
import org.libreplan.business.email.entities.EmailTemplateEnum;
import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.resources.entities.Resource;
import org.libreplan.business.resources.entities.Worker;
import org.libreplan.business.users.entities.User;
import org.libreplan.business.workingday.EffortDuration;
import org.libreplan.business.workingday.IntraDayDate;
import org.libreplan.business.workreports.daos.IWorkReportDAO;
import org.libreplan.business.workreports.entities.WorkReport;
import org.libreplan.business.workreports.entities.WorkReportLine;
import org.libreplan.business.workreports.entities.WorkReportType;
import org.libreplan.importers.notifications.ComposeMessage;
import org.libreplan.importers.notifications.EmailConnectionValidator;
import org.libreplan.importers.notifications.IEmailNotificationJob;
import org.libreplan.web.calendars.BaseCalendarModel;
import org.libreplan.web.common.Util;
import org.libreplan.web.email.IEmailNotificationModel;
import org.libreplan.web.users.IUserModel;
import org.libreplan.web.users.dashboard.PersonalTimesheetDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
/**
* Sends E-mail to users with data that storing in notification_queue table
* and that are treat to {@link EmailTemplateEnum.TEMPLATE_ENTER_DATA_IN_TIMESHEET}
* Data will be send for bound users with empty timesheet lines.
*
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 20.01.2016.
*/
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class SendEmailOnTimesheetDataMissing implements IEmailNotificationJob {
@Autowired
private IEmailNotificationModel emailNotificationModel;
@Autowired
private IConfigurationDAO configurationDAO;
@Autowired
private IWorkReportDAO workReportDAO;
@Autowired
private IUserModel userModel;
@Autowired
private ComposeMessage composeMessage;
@Autowired
private EmailConnectionValidator emailConnectionValidator;
@Override
@Transactional
public void sendEmail() {
checkTimesheet();
if ( Configuration.isEmailSendingEnabled() ){
if ( emailConnectionValidator.isConnectionActivated() )
if ( emailConnectionValidator.validConnection() ){
List<EmailNotification> notifications = emailNotificationModel
.getAllByType(EmailTemplateEnum.TEMPLATE_ENTER_DATA_IN_TIMESHEET);
for (int i = 0; i < notifications.size(); i++)
if ( composeMessageForUser(notifications.get(i)) )
deleteSingleNotification(notifications.get(i));
}
}
}
@Override
public boolean composeMessageForUser(EmailNotification notification) {
return composeMessage.composeMessageForUser(notification);
}
private void deleteSingleNotification(EmailNotification notification){
emailNotificationModel.deleteById(notification);
}
public void checkTimesheet() {
List<User> list = getPersonalTimesheets();
addRowsToNotificationTable(list);
}
@Transactional
private List<User> getPersonalTimesheets() {
List<PersonalTimesheetDTO> personalTimesheetDTO = new ArrayList<PersonalTimesheetDTO>();
List<User> usersWithoutTimesheets = new ArrayList<User>();
List<User> users = userModel.getUsers();
for (User user : users)
if (user.isBound()) {
Resource resource = user.getWorker();
BaseCalendarModel.forceLoadBaseCalendar(resource.getCalendar());
LocalDate activationDate = getActivationDate(user.getWorker());
LocalDate currentDate = new LocalDate();
personalTimesheetDTO.addAll(getPersonalTimesheets(user.getWorker(), activationDate,
currentDate.plusMonths(1), getPersonalTimesheetsPeriodicity()));
for(PersonalTimesheetDTO item : personalTimesheetDTO){
WorkReport workReport = item.getWorkReport();
if ( item.getTasksNumber() == 0 && workReport == null )
if ( !usersWithoutTimesheets.contains(user) )
usersWithoutTimesheets.add(user);
}
personalTimesheetDTO.clear();
}
return usersWithoutTimesheets;
}
private void addRowsToNotificationTable(List<User> users){
for (User user : users){
emailNotificationModel.setNewObject();
emailNotificationModel.setResource(user.getWorker());
emailNotificationModel.setType(EmailTemplateEnum.TEMPLATE_ENTER_DATA_IN_TIMESHEET);
emailNotificationModel.setUpdated(new Date());
emailNotificationModel.confirmSave();
}
}
private List<PersonalTimesheetDTO> getPersonalTimesheets(Resource resource,
LocalDate start, LocalDate end,
PersonalTimesheetsPeriodicityEnum periodicity) {
start = periodicity.getStart(start);
end = periodicity.getEnd(end);
int items = periodicity.getItemsBetween(start, end);
List<PersonalTimesheetDTO> result = new ArrayList<PersonalTimesheetDTO>();
// In decreasing order to provide a list sorted with the more recent
// personal timesheets at the beginning
for (int i = items; i >= 0; i--) {
LocalDate date = periodicity.getDateForItemFromDate(i, start);
WorkReport workReport = getWorkReport(resource, date, periodicity);
EffortDuration hours = EffortDuration.zero();
int tasksNumber = 0;
if (workReport != null) {
hours = workReport.getTotalEffortDuration();
tasksNumber = getNumberOfOrderElementsWithTrackedTime(workReport);
}
result.add(new PersonalTimesheetDTO(date, workReport,
getResourceCapcity(resource, date, periodicity), hours,
tasksNumber));
}
return result;
}
private LocalDate getActivationDate(Worker worker) {
return worker.getCalendar().getFistCalendarAvailability()
.getStartDate();
}
private PersonalTimesheetsPeriodicityEnum getPersonalTimesheetsPeriodicity() {
return configurationDAO.getConfiguration()
.getPersonalTimesheetsPeriodicity();
}
private WorkReport getWorkReport(Resource resource, LocalDate date,
PersonalTimesheetsPeriodicityEnum periodicity) {
WorkReport workReport = workReportDAO.getPersonalTimesheetWorkReport(
resource, date, periodicity);
forceLoad(workReport);
return workReport;
}
private void forceLoad(WorkReport workReport) {
if (workReport != null) {
WorkReportType workReportType = workReport.getWorkReportType();
workReportType.getLineFields().size();
workReportType.getWorkReportLabelTypeAssigments().size();
workReportType.getHeadingFields().size();
}
}
private int getNumberOfOrderElementsWithTrackedTime(WorkReport workReport) {
if (workReport == null) {
return 0;
}
List<OrderElement> orderElements = new ArrayList<OrderElement>();
for (WorkReportLine line : workReport.getWorkReportLines()) {
if (!line.getEffort().isZero()) {
OrderElement orderElement = line.getOrderElement();
if (!Util.contains(orderElements, orderElement)) {
orderElements.add(orderElement);
}
}
}
return orderElements.size();
}
private EffortDuration getResourceCapcity(Resource resource, LocalDate date,
PersonalTimesheetsPeriodicityEnum periodicity) {
LocalDate start = periodicity.getStart(date);
LocalDate end = periodicity.getEnd(date);
EffortDuration capacity = EffortDuration.zero();
for (LocalDate day = start; day.compareTo(end) <= 0; day = day
.plusDays(1)) {
capacity = capacity.plus(resource.getCalendar().getCapacityOn(
IntraDayDate.PartialDay.wholeDay(day)));
}
return capacity;
}
}

View file

@ -31,8 +31,6 @@ import java.util.ArrayList;
import java.util.Set;
import java.util.Map;
import java.util.Collections;
import java.util.Comparator;
import java.util.ConcurrentModificationException;
import java.util.HashSet;
import java.util.Arrays;
@ -1365,6 +1363,11 @@ public class ConfigurationController extends GenericForwardComposer {
emailPasswordTextbox.getValue().length() != 0 &&
emailSenderTextbox.getValue().matches("^\\S+@\\S+\\.\\S+$") )
return true;
if ( protocolsCombobox != null && protocolsCombobox.getSelectedItem() != null ){
if ( protocolsCombobox.getSelectedItem().getLabel().equals("SMTP") )
return true;
}
}
return false;
}

View file

@ -35,10 +35,11 @@ import org.libreplan.importers.IImportRosterFromTim;
import org.libreplan.importers.IJiraOrderElementSynchronizer;
import org.libreplan.importers.ISchedulerManager;
import org.libreplan.importers.SynchronizationInfo;
import org.libreplan.importers.ISendEmail;
import org.libreplan.importers.notifications.IEmailNotificationJob;
import org.libreplan.web.common.concurrentdetection.OnConcurrentModification;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
@ -51,6 +52,7 @@ import static org.libreplan.web.I18nHelper._;
*
* @author Manuel Rego Casasnovas <rego@igalia.com>
* @author Miciele Ghiorghis <m.ghiorghis@antoniusziekenhuis.nl>
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
*/
@Service
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@ -79,8 +81,30 @@ public class JobSchedulerModel implements IJobSchedulerModel {
private List<SynchronizationInfo> synchronizationInfos;
@Qualifier("sendEmailOnTaskAssignedToResource")
@Autowired
private ISendEmail email;
private IEmailNotificationJob taskAssignedToResource;
@Qualifier("sendEmailOnMilestoneReached")
@Autowired
private IEmailNotificationJob milestoneReached;
@Qualifier("sendEmailOnResourceRemovedFromTask")
@Autowired
private IEmailNotificationJob resourceRemovedFromTask;
@Qualifier("sendEmailOnTaskShouldStart")
@Autowired
private IEmailNotificationJob taskShouldStart;
@Qualifier("sendEmailOnTaskShouldFinish")
@Autowired
private IEmailNotificationJob taskShouldFinish;
@Qualifier("sendEmailOnTimesheetDataMissing")
@Autowired
private IEmailNotificationJob timesheetDataMissing;
@Override
@Transactional(readOnly = true)
@ -112,10 +136,40 @@ public class JobSchedulerModel implements IJobSchedulerModel {
.syncOrderElementsWithJiraIssues();
return;
}
if ( name.equals(JobClassNameEnum.SEND_EMAIL_JOB.getName()) ) {
if ( name.equals(JobClassNameEnum.SEND_EMAIL_TASK_ASSIGNED_TO_RESOURCE.getName()) ) {
synchronizationInfos = new ArrayList<SynchronizationInfo>();
synchronizationInfos.add(new SynchronizationInfo(_("Send E-mail")));
email.sendEmail();
synchronizationInfos.add(new SynchronizationInfo(_("Task assigned to resource emails")));
taskAssignedToResource.sendEmail();
return;
}
if ( name.equals(JobClassNameEnum.SEND_EMAIL_RESOURCE_REMOVED_FROM_TASK.getName()) ) {
synchronizationInfos = new ArrayList<SynchronizationInfo>();
synchronizationInfos.add(new SynchronizationInfo(_("Resource removed from task")));
resourceRemovedFromTask.sendEmail();
return;
}
if ( name.equals(JobClassNameEnum.SEND_EMAIL_MILESTONE_REACHED.getName()) ) {
synchronizationInfos = new ArrayList<SynchronizationInfo>();
synchronizationInfos.add(new SynchronizationInfo(_("Milestone reached")));
milestoneReached.sendEmail();
return;
}
if ( name.equals(JobClassNameEnum.SEND_EMAIL_TASK_SHOULD_START.getName()) ) {
synchronizationInfos = new ArrayList<SynchronizationInfo>();
synchronizationInfos.add(new SynchronizationInfo(_("Task should start")));
taskShouldStart.sendEmail();
return;
}
if ( name.equals(JobClassNameEnum.SEND_EMAIL_TASK_SHOULD_FINISH.getName()) ) {
synchronizationInfos = new ArrayList<SynchronizationInfo>();
synchronizationInfos.add(new SynchronizationInfo(_("Task should finish")));
taskShouldFinish.sendEmail();
return;
}
if ( name.equals(JobClassNameEnum.SEND_EMAIL_TIMESHEET_DATA_MISSING.getName()) ) {
synchronizationInfos = new ArrayList<SynchronizationInfo>();
synchronizationInfos.add(new SynchronizationInfo(_("Timesheet data missing")));
timesheetDataMissing.sendEmail();
return;
}

View file

@ -34,7 +34,7 @@ import java.util.List;
*
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 17.12.15.
* on 17.12.2015.
*/
@Service

View file

@ -87,6 +87,7 @@ import org.zkoss.zul.Window;
* @author Manuel Rego Casasnovas <mrego@igalia.com>
* @author Diego Pino Garcia <dpino@igalia.com>
* @author Javier Moran Rua <jmoran@igalia.com>
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
*/
@org.springframework.stereotype.Component("resourceAllocationController")
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@ -315,6 +316,12 @@ public class ResourceAllocationController extends GenericForwardComposer {
try {
allocationSelector.addChoosen();
} finally {
// For email notification feature
int rowsSize = allocationRows.getCurrentRows().size();
editTaskController.getTaskPropertiesController().listToAdd
.add(allocationRows.getCurrentRows().get(rowsSize - 1).getAssociatedResources().get(0));
editTaskController.getTaskPropertiesController().setResourcesAdded(true);
tbResourceAllocation.setSelected(true);
applyButton.setVisible(true);
allocationSelector.clearAll();
@ -618,6 +625,8 @@ public class ResourceAllocationController extends GenericForwardComposer {
@Override
public void onEvent(Event event) {
editTaskController.getTaskPropertiesController().getListToDelete()
.add(data.getAssociatedResources().get(0));
removeAllocation(data);
}
});

View file

@ -59,7 +59,6 @@ import org.libreplan.business.planner.entities.GenericResourceAllocation;
import org.libreplan.business.planner.entities.IMoneyCostCalculator;
import org.libreplan.business.planner.entities.ResourceAllocation;
import org.libreplan.business.planner.entities.ResourceAllocation.IVisitor;
import org.libreplan.business.planner.entities.HoursCostCalculator;
import org.libreplan.business.planner.entities.SpecificResourceAllocation;
import org.libreplan.business.planner.entities.StretchesFunction;
import org.libreplan.business.planner.entities.SubcontractorDeliverDate;
@ -103,6 +102,7 @@ import org.zkoss.zk.ui.Desktop;
*
* @author Óscar González Fernández <ogonzalez@igalia.com>
* @author Lorenzo Tilve Álvaro <ltilve@igalia.com>
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
*/
@Component
@Scope(BeanDefinition.SCOPE_SINGLETON)
@ -233,7 +233,8 @@ public class PlanningStateCreator {
}
}
PlanningState result = createPlanning(reload(order));
result.onRetrieval();
// It was called before, no need to do it one more
//result.onRetrieval();
if (desktop != null) {
desktop.setAttribute(ATTRIBUTE_NAME, result);
}

View file

@ -93,6 +93,7 @@ import org.libreplan.web.common.MessagesForUser;
import org.libreplan.web.common.concurrentdetection.ConcurrentModificationHandling;
import org.libreplan.web.planner.TaskElementAdapter;
import org.libreplan.web.planner.order.PlanningStateCreator.PlanningState;
import org.libreplan.web.planner.taskedition.TaskPropertiesController;
import org.libreplan.web.security.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
@ -121,6 +122,7 @@ import org.zkoss.zul.Messagebox;
* @author Óscar González Fernández <ogonzalez@igalia.com>
* @author Javier Moran Rua <jmoran@igalia.com>
* @author Manuel Rego Casasnovas <rego@igalia.com>
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
*/
@Component
@Scope(BeanDefinition.SCOPE_SINGLETON)
@ -217,6 +219,9 @@ public class SaveCommandBuilder {
@Autowired
private ISumExpensesRecalculator sumExpensesRecalculator;
public static TaskPropertiesController taskPropertiesController;
private class SaveCommand implements ISaveCommand {
private PlanningState state;
@ -263,6 +268,10 @@ public class SaveCommandBuilder {
@Override
public void doActions() {
// A little bit hack
if (taskPropertiesController != null)
taskPropertiesController.emailNotificationAddNew();
notifyUserThatSavingIsDone();
}
});

View file

@ -50,12 +50,13 @@ import org.libreplan.business.workingday.IntraDayDate;
import org.libreplan.web.I18nHelper;
import org.libreplan.web.common.Util;
import org.libreplan.web.email.IEmailNotificationModel;
import org.libreplan.web.orders.IOrderModel;
import org.libreplan.web.planner.allocation.AllocationResult;
import org.libreplan.web.planner.order.SaveCommandBuilder;
import org.libreplan.web.resources.worker.IWorkerModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.dao.DataIntegrityViolationException;
import org.zkoss.ganttz.TaskEditFormComposer;
import org.zkoss.ganttz.TaskEditFormComposer.TaskDTO;
import org.zkoss.ganttz.data.TaskContainer;
@ -82,6 +83,7 @@ import org.zkoss.zul.api.Tabpanel;
* Controller for edit {@link Task} popup.
*
* @author Manuel Rego Casasnovas <mrego@igalia.com>
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
*/
@org.springframework.stereotype.Component("taskPropertiesController")
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@ -130,10 +132,9 @@ public class TaskPropertiesController extends GenericForwardComposer {
private IEmailNotificationModel emailNotificationModel;
private IOrderModel orderModel;
private IWorkerModel workerModel;
private boolean isResourcesAdded = false;
public void init(final EditTaskController editTaskController,
@ -433,7 +434,9 @@ public class TaskPropertiesController extends GenericForwardComposer {
}
public void accept() {
EmailNotificationAddNewWithTaskAssignedToResource();
if ( !isResourcesAdded ) listToAdd.clear();
SaveCommandBuilder.taskPropertiesController = getObject();
boolean ok = true;
if (currentTaskElement instanceof ITaskPositionConstrained) {
@ -730,49 +733,88 @@ public class TaskPropertiesController extends GenericForwardComposer {
return Util.getMoneyFormat();
}
private void EmailNotificationAddNewWithTaskAssignedToResource(){
public List<Resource> listToDelete = new ArrayList<Resource>();
public List<Resource> listToAdd = new ArrayList<Resource>();
if ( allocationResult.getSpecificAllocations().size() != 0 ) {
public void emailNotificationAddNew(){
/* Check if resources in allocation are bound by user and are in role ROLE_EMAIL_TASK_ASSIGNED_TO_RESOURCE
* setUser method calling manually because, after initialization user will be null
* Then send valid data to notification_queue table */
/**
* Check if resources in allocation are bound by user and in what ROLE they are
* setUser method calling manually because, after initialization user will be null
* Then send valid data to notification_queue table
*/
proceedList(EmailTemplateEnum.TEMPLATE_TASK_ASSIGNED_TO_RESOURCE, listToAdd);
proceedList(EmailTemplateEnum.TEMPLATE_RESOURCE_REMOVED_FROM_TASK, listToDelete);
listToAdd.clear();
listToDelete.clear();
}
private void proceedList(EmailTemplateEnum enumeration, List<Resource> list){
if ( list.size() != 0 ){
List<Worker> workersList = workerModel.getWorkers();
Worker currentWorker;
Resource currentResource;
User currentUser;
for (int i = 0; i < workersList.size(); i++)
for (int j = 0; j < allocationResult.getSpecificAllocations().size(); j++){
for (int j = 0; j < list.size(); j++){
currentWorker = workersList.get(i);
currentResource = allocationResult.getSpecificAllocations().get(j).getResource();
currentResource = list.get(j);
if ( currentWorker.getId().equals(currentResource.getId()) ){
workersList.get(i).setUser(workerModel.getBoundUserFromDB(currentWorker));
currentUser = currentWorker.getUser();
User currentUser = currentWorker.getUser();
if ( currentUser != null &&
currentUser.isInRole(UserRole.ROLE_EMAIL_TASK_ASSIGNED_TO_RESOURCE) ) {
emailNotificationModel.setType(EmailTemplateEnum.TEMPLATE_TASK_ASSIGNED_TO_RESOURCE);
emailNotificationModel.setUpdated(new Date());
emailNotificationModel.setResource(allocationResult.getSpecificAllocations().get(j).getResource());
emailNotificationModel.setTask(currentTaskElement.getTaskSource().getTask());
emailNotificationModel.setProject(currentTaskElement.getParent().getTaskSource().getTask());
emailNotificationModel.confirmSave();
}
if ( currentUser != null
&& (currentUser.isInRole(UserRole.ROLE_EMAIL_TASK_ASSIGNED_TO_RESOURCE)
|| currentUser.isInRole(UserRole.ROLE_EMAIL_RESOURCE_REMOVED_FROM_TASK)) )
setEmailNotificationEntity(enumeration, currentResource);
break;
}
}
}
}
private void setEmailNotificationEntity(EmailTemplateEnum enumeration, Resource resource){
try{
emailNotificationModel.setNewObject();
if ( enumeration.equals(EmailTemplateEnum.TEMPLATE_TASK_ASSIGNED_TO_RESOURCE) )
emailNotificationModel.setType(EmailTemplateEnum.TEMPLATE_TASK_ASSIGNED_TO_RESOURCE);
else if ( enumeration.equals(EmailTemplateEnum.TEMPLATE_RESOURCE_REMOVED_FROM_TASK) )
emailNotificationModel.setType(EmailTemplateEnum.TEMPLATE_RESOURCE_REMOVED_FROM_TASK);
emailNotificationModel.setUpdated(new Date());
emailNotificationModel.setResource(resource);
emailNotificationModel.setTask(currentTaskElement.getTaskSource().getTask());
emailNotificationModel.setProject(currentTaskElement.getParent().getTaskSource().getTask());
emailNotificationModel.confirmSave();
} catch (DataIntegrityViolationException e){
try {
Messagebox.show(_("You cannot email user twice with the same info"), _("Error"),
Messagebox.OK, Messagebox.ERROR);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
public List<Resource> getListToDelete() {
return listToDelete;
}
public void setResourcesAdded(boolean resourcesAdded) {
isResourcesAdded = resourcesAdded;
}
private TaskPropertiesController getObject(){
return this;
}
}

View file

@ -61,7 +61,7 @@ public class PersonalTimesheetDTO {
* @param tasksNumber
* Number of tasks in the personal timesheet
*/
PersonalTimesheetDTO(LocalDate date, WorkReport workReport,
public PersonalTimesheetDTO(LocalDate date, WorkReport workReport,
EffortDuration resourceCapacity, EffortDuration totalHours,
int tasksNumber) {
this.date = date;

View file

@ -21,7 +21,6 @@
package org.libreplan.web.users.services;
import java.util.Collection;
import java.util.Collections;
import org.springframework.security.authentication.dao.SaltSource;

View file

@ -9363,4 +9363,56 @@ msgstr ""
#: libreplan-webapp/src/main/webapp/orders/imports/projectImport.zul:42
msgid "Your project could only partially be imported"
msgstr ""
#: libreplan-business/src/main/java/org/libreplan/business/email/entities/EmailTemplateEnum.java:37
msgid "Resource removed from task"
msgstr ""
#: libreplan-business/src/main/java/org/libreplan/business/email/entities/EmailTemplateEnum.java:38
msgid "Milestone reached"
msgstr ""
#: libreplan-business/src/main/java/org/libreplan/business/email/entities/EmailTemplateEnum.java:39
msgid "Task should start"
msgstr ""
#: libreplan-business/src/main/java/org/libreplan/business/email/entities/EmailTemplateEnum.java:40
msgid "Task should finish"
msgstr ""
#: libreplan-business/src/main/java/org/libreplan/business/email/entities/EmailTemplateEnum.java:41
msgid "Enter data in timesheet"
msgstr ""
#: libreplan-business/src/main/java/org/libreplan/business/users/entities/UserRole.java:96
msgid "Email: task assigned to resource"
msgstr ""
#: libreplan-business/src/main/java/org/libreplan/business/users/entities/UserRole.java:97
msgid "Email: resource removed from task"
msgstr ""
#: libreplan-business/src/main/java/org/libreplan/business/users/entities/UserRole.java:98
msgid "Email: milestone reached"
msgstr ""
#: libreplan-business/src/main/java/org/libreplan/business/users/entities/UserRole.java:99
msgid "Email: task should finish"
msgstr ""
#: libreplan-business/src/main/java/org/libreplan/business/users/entities/UserRole.java:100
msgid "Email: task should start"
msgstr ""
#: libreplan-business/src/main/java/org/libreplan/business/users/entities/UserRole.java:101
msgid "Email: timesheet data missing"
msgstr ""
#: libreplan-webapp/src/main/java/org/libreplan/web/planner/taskedition/TaskPropertiesController.java:804
msgid "You cannot email user twice with the same info"
msgstr ""