Merge pull request #97 from dgray16/master

Add tests for Email functionality
This commit is contained in:
Jeroen Baten 2016-08-04 13:41:46 +02:00 committed by GitHub
commit 16b8ced6c0
52 changed files with 1663 additions and 1689 deletions

View file

@ -28,28 +28,17 @@ import org.libreplan.business.common.Registry;
import org.libreplan.business.common.daos.IJobSchedulerConfigurationDAO; import org.libreplan.business.common.daos.IJobSchedulerConfigurationDAO;
/** /**
* JobSchedulerConfiguration entity, represents parameters for the jobs to be * JobSchedulerConfiguration entity, represents parameters for the jobs to be scheduled.
* scheduled. This entity is used by the <code>SchedulerManager</code> to * This entity is used by the <code>SchedulerManager</code> to
* schedule jobs and in UI to show the scheduler status. * schedule jobs and in UI to show the scheduler status.
* *
* The <code>jobGroup</code> and <code>jobName</code> together forms a job key * The <code>jobGroup</code> and <code>jobName</code> together forms a job key
* and non of the fields must be null. Moreover it should contain a valid * and non of the fields must be null. Moreover it should contain a valid <code>cronExpression</code>.
* <code>cronExpression</code>
* *
* @author Miciele Ghiorghis <m.ghiorghis@antoniusziekenhuis.nl> * @author Miciele Ghiorghis <m.ghiorghis@antoniusziekenhuis.nl>
*/ */
public class JobSchedulerConfiguration extends BaseEntity implements IHumanIdentifiable { public class JobSchedulerConfiguration extends BaseEntity implements IHumanIdentifiable {
public static JobSchedulerConfiguration create() {
return create(new JobSchedulerConfiguration());
}
/**
* Constructor for Hibernate. Do not use!
*/
protected JobSchedulerConfiguration() {
}
private String jobGroup; private String jobGroup;
private String jobName; private String jobName;
@ -62,6 +51,15 @@ public class JobSchedulerConfiguration extends BaseEntity implements IHumanIdent
private String connectorName; private String connectorName;
/**
* Constructor for Hibernate. Do not use!
*/
protected JobSchedulerConfiguration() {}
public static JobSchedulerConfiguration create() {
return create(new JobSchedulerConfiguration());
}
@NotNull(message = "job group not specified") @NotNull(message = "job group not specified")
public String getJobGroup() { public String getJobGroup() {
return jobGroup; return jobGroup;
@ -124,7 +122,9 @@ public class JobSchedulerConfiguration extends BaseEntity implements IHumanIdent
if ( StringUtils.isBlank(jobGroup) && StringUtils.isBlank(jobName) ) { if ( StringUtils.isBlank(jobGroup) && StringUtils.isBlank(jobName) ) {
return true; return true;
} }
IJobSchedulerConfigurationDAO jobSchedulerConfigurationDAO = Registry.getJobSchedulerConfigurationDAO(); IJobSchedulerConfigurationDAO jobSchedulerConfigurationDAO = Registry.getJobSchedulerConfigurationDAO();
if ( isNewObject() ) { if ( isNewObject() ) {
return !jobSchedulerConfigurationDAO.existsByJobGroupAndJobNameAnotherTransaction(this); return !jobSchedulerConfigurationDAO.existsByJobGroupAndJobNameAnotherTransaction(this);
} else { } else {

View file

@ -30,12 +30,11 @@ import java.util.List;
/** /**
* Dao for {@link EmailNotification} * Dao for {@link EmailNotification}
* *
* Created by * @author Created by Vova Perebykivskiy <vova@libreplan-enterprise.com> on 19.10.2015.
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 19.10.2015.
*/ */
@Repository @Repository
public class EmailNotificationDAO extends GenericDAOHibernate<EmailNotification, Long> public class EmailNotificationDAO
extends GenericDAOHibernate<EmailNotification, Long>
implements IEmailNotificationDAO { implements IEmailNotificationDAO {
@Override @Override
@ -45,13 +44,16 @@ public class EmailNotificationDAO extends GenericDAOHibernate<EmailNotification,
@Override @Override
public List<EmailNotification> getAllByType(EmailTemplateEnum enumeration) { public List<EmailNotification> getAllByType(EmailTemplateEnum enumeration) {
return getSession().createCriteria(EmailNotification.class) return getSession()
.add(Restrictions.eq("type", enumeration)).list(); .createCriteria(EmailNotification.class)
.add(Restrictions.eq("type", enumeration))
.list();
} }
@Override @Override
public boolean deleteAll() { public boolean deleteAll() {
List<EmailNotification> notifications = list(EmailNotification.class); List<EmailNotification> notifications = list(EmailNotification.class);
for (Object item : notifications){ for (Object item : notifications){
getSession().delete(item); getSession().delete(item);
} }
@ -61,23 +63,30 @@ public class EmailNotificationDAO extends GenericDAOHibernate<EmailNotification,
@Override @Override
public boolean deleteAllByType(EmailTemplateEnum enumeration) { public boolean deleteAllByType(EmailTemplateEnum enumeration) {
List<EmailNotification> notifications = getSession().createCriteria(EmailNotification.class) List<EmailNotification> notifications = getSession()
.add(Restrictions.eq("type", enumeration)).list(); .createCriteria(EmailNotification.class)
.add(Restrictions.eq("type", enumeration))
.list();
for (Object item : notifications){ for (Object item : notifications){
getSession().delete(item); getSession().delete(item);
} }
if ( getSession().createCriteria(EmailNotification.class) return getSession()
.add(Restrictions.eq("type", enumeration.ordinal())).list().size() == 0 ) return true; .createCriteria(EmailNotification.class)
return false; .add(Restrictions.eq("type", enumeration.ordinal()))
.list()
.size() == 0;
} }
@Override @Override
public boolean deleteById(EmailNotification notification) { public boolean deleteById(EmailNotification notification) {
getSession().delete(notification); getSession().delete(notification);
if ( getSession().createCriteria(EmailNotification.class).add(Restrictions.eq("id", notification.getId()))
.uniqueResult() != null ) return false; return getSession()
return true; .createCriteria(EmailNotification.class)
.add(Restrictions.eq("id", notification.getId()))
.uniqueResult() == null;
} }
} }

View file

@ -19,60 +19,56 @@
package org.libreplan.business.email.daos; package org.libreplan.business.email.daos;
import org.hibernate.criterion.Restrictions;
import org.libreplan.business.common.daos.GenericDAOHibernate; import org.libreplan.business.common.daos.GenericDAOHibernate;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.email.entities.EmailTemplate; import org.libreplan.business.email.entities.EmailTemplate;
import org.libreplan.business.email.entities.EmailTemplateEnum;
import org.libreplan.business.settings.entities.Language;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import java.util.List; import java.util.List;
/** /**
* DAO for {@link EmailTemplate} * DAO for {@link EmailTemplate}
* *
* Created by * @author Created by Vova Perebykivskiy <vova@libreplan-enterprise.com> on 24.09.2015.
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 24.09.2015.
*/ */
@Repository @Repository
public class EmailTemplateDAO extends GenericDAOHibernate<EmailTemplate, Long> implements IEmailTemplateDAO{ public class EmailTemplateDAO extends GenericDAOHibernate<EmailTemplate, Long> implements IEmailTemplateDAO{
@Override @Override
@Transactional(readOnly = true)
public List<EmailTemplate> getAll() { public List<EmailTemplate> getAll() {
return list(EmailTemplate.class); return list(EmailTemplate.class);
} }
@Override @Override
public String getContentBySelectedLanguage(int languageOrdinal, int emailTemplateTypeOrdinal) { @Transactional(readOnly = true)
for (int i = 0; i < list(EmailTemplate.class).size(); i++) public List<EmailTemplate> findByType(EmailTemplateEnum type) {
if ( list(EmailTemplate.class).get(i).getLanguage().ordinal() == languageOrdinal && return getSession()
list(EmailTemplate.class).get(i).getType().ordinal() == emailTemplateTypeOrdinal ) .createCriteria(EmailTemplate.class)
return list(EmailTemplate.class).get(i).getContent(); .add(Restrictions.eq("type", type))
return ""; .list();
} }
@Override @Override
public String getContentBySelectedTemplate(int emailTemplateTypeOrdinal, int languageOrdinal) { @Transactional(readOnly = true)
for (int i = 0; i < list(EmailTemplate.class).size(); i++) public EmailTemplate findByTypeAndLanguage(EmailTemplateEnum type, Language language) {
if ( list(EmailTemplate.class).get(i).getType().ordinal() == emailTemplateTypeOrdinal && return (EmailTemplate) getSession()
list(EmailTemplate.class).get(i).getLanguage().ordinal() == languageOrdinal ) .createCriteria(EmailTemplate.class)
return list(EmailTemplate.class).get(i).getContent(); .add(Restrictions.eq("type", type))
return ""; .add(Restrictions.eq("language", language))
.uniqueResult();
} }
@Override @Override
public String getSubjectBySelectedLanguage(int languageOrdinal, int emailTemplateTypeOrdinal) { @Transactional
for (int i = 0; i < list(EmailTemplate.class).size(); i++) public void delete(EmailTemplate entity) {
if ( list(EmailTemplate.class).get(i).getLanguage().ordinal() == languageOrdinal && try {
list(EmailTemplate.class).get(i).getType().ordinal() == emailTemplateTypeOrdinal ) remove(entity.getId());
return list(EmailTemplate.class).get(i).getSubject(); } catch (InstanceNotFoundException ignored) {
return ""; }
}
@Override
public String getSubjectBySelectedTemplate(int emailTemplateTypeOrdinal, int languageOrdinal) {
for (int i = 0; i < list(EmailTemplate.class).size(); i++)
if ( list(EmailTemplate.class).get(i).getType().ordinal() == emailTemplateTypeOrdinal &&
list(EmailTemplate.class).get(i).getLanguage().ordinal() == languageOrdinal )
return list(EmailTemplate.class).get(i).getSubject();
return "";
} }
} }

View file

@ -28,15 +28,17 @@ import java.util.List;
/** /**
* Contract for {@link EmailNotificationDAO} * Contract for {@link EmailNotificationDAO}
* *
* Created by * @author Created by Vova Perebykivskiy <vova@libreplan-enterprise.com> on 19.10.2015.
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 19.10.15.
*/ */
public interface IEmailNotificationDAO extends IGenericDAO<EmailNotification, Long> { public interface IEmailNotificationDAO extends IGenericDAO<EmailNotification, Long> {
List<EmailNotification> getAll(); List<EmailNotification> getAll();
List<EmailNotification> getAllByType(EmailTemplateEnum enumeration); List<EmailNotification> getAllByType(EmailTemplateEnum enumeration);
boolean deleteAll(); boolean deleteAll();
boolean deleteAllByType(EmailTemplateEnum enumeration); boolean deleteAllByType(EmailTemplateEnum enumeration);
boolean deleteById(EmailNotification notification); boolean deleteById(EmailNotification notification);
} }

View file

@ -21,6 +21,8 @@ package org.libreplan.business.email.daos;
import org.libreplan.business.common.daos.IGenericDAO; import org.libreplan.business.common.daos.IGenericDAO;
import org.libreplan.business.email.entities.EmailTemplate; import org.libreplan.business.email.entities.EmailTemplate;
import org.libreplan.business.email.entities.EmailTemplateEnum;
import org.libreplan.business.settings.entities.Language;
import java.util.List; import java.util.List;
@ -28,17 +30,15 @@ import java.util.List;
* DAO interface for the <code>EmailTemplate</code> entity. * DAO interface for the <code>EmailTemplate</code> entity.
* Contract for {@link EmailTemplateDAO} * Contract for {@link EmailTemplateDAO}
* *
* Created by * @author Created by Vova Perebykivskiy <vova@libreplan-enterprise.com> on 29.09.2015.
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 29.09.2015.
*/ */
public interface IEmailTemplateDAO extends IGenericDAO<EmailTemplate, Long>{ public interface IEmailTemplateDAO extends IGenericDAO<EmailTemplate, Long>{
List<EmailTemplate> getAll(); List<EmailTemplate> getAll();
String getContentBySelectedLanguage(int languageOrdinal, int emailTemplateTypeOrdinal); List<EmailTemplate> findByType(EmailTemplateEnum emailTemplateEnum);
String getContentBySelectedTemplate(int emailTemplateTypeOrdinal, int languageOrdinal);
String getSubjectBySelectedLanguage(int languageOrdinal, int emailTemplateTypeOrdinal); EmailTemplate findByTypeAndLanguage(EmailTemplateEnum emailTemplateEnum, Language language);
String getSubjectBySelectedTemplate(int emailTemplateTypeOrdinal, int languageOrdinal);
void delete(EmailTemplate entity);
} }

View file

@ -31,9 +31,7 @@ import java.util.Date;
* This class is intended to work as a Hibernate component. * This class is intended to work as a Hibernate component.
* It represents the Email notification to be send to user. * It represents the Email notification to be send to user.
* *
* Created by * @author Created by Vova Perebykivskyi <vova@libreplan-enterprise.com> on 19.10.2015.
* @author Vova Perebykivskyi <vova@libreplan-enterprise.com>
* on 19.10.2015.
*/ */
public class EmailNotification extends BaseEntity { public class EmailNotification extends BaseEntity {

View file

@ -27,9 +27,7 @@ import org.libreplan.business.settings.entities.Language;
* This class is intended to work as a Hibernate component. * This class is intended to work as a Hibernate component.
* It represents the E-mail template to be modified by admin and send to user. * It represents the E-mail template to be modified by admin and send to user.
* *
* Created by * @author Created by Vova Perebykivskyi <vova@libreplan-enterprise.com> on 29.09.2015.
* @author Vova Perebykivskyi <vova@libreplan-enterprise.com>
* on 29.09.2015.
*/ */
public class EmailTemplate extends BaseEntity { public class EmailTemplate extends BaseEntity {
@ -56,14 +54,14 @@ public class EmailTemplate extends BaseEntity {
} }
public String getContent() { public String getContent() {
return content; return content != null ? content : "";
} }
public void setContent(String content) { public void setContent(String content) {
this.content = content; this.content = content;
} }
public String getSubject() { public String getSubject() {
return subject; return subject != null ? subject : "";
} }
public void setSubject(String subject) { public void setSubject(String subject) {
this.subject = subject; this.subject = subject;

View file

@ -24,9 +24,7 @@ import static org.libreplan.business.i18n.I18nHelper._;
/** /**
* Available E-mail templates. * Available E-mail templates.
* *
* Created by * @author Created by Vova Perebykivskyi <vova@libreplan-enterprise.com> on 28.09.2015.
* @author Vova Perebykivskyi <vova@libreplan-enterprise.com>
* on 28.09.2015.
* *
* TEMPLATE_N(_("Template N")) - for i18n * TEMPLATE_N(_("Template N")) - for i18n
* TEMPLATE_A("Template A") - for general use (no internationalizing) * TEMPLATE_A("Template A") - for general use (no internationalizing)

View file

@ -20,8 +20,7 @@ package org.libreplan.business.planner.entities;
/** /**
* Manual allocation function, it used to represent when user has done a manual * Manual allocation function, it used to represent when user has done a manual allocation.
* allocation.
* *
* @author Manuel Rego Casasnovas <rego@igalia.com> * @author Manuel Rego Casasnovas <rego@igalia.com>
*/ */

View file

@ -45,19 +45,20 @@ import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
/** /**
* DAO for {@link QualityForm} * DAO for {@link QualityForm}.
*
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com> * @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
*/ */
@Repository @Repository
@Scope(BeanDefinition.SCOPE_SINGLETON) @Scope(BeanDefinition.SCOPE_SINGLETON)
public class QualityFormDAO extends GenericDAOHibernate<QualityForm, Long> public class QualityFormDAO extends GenericDAOHibernate<QualityForm, Long> implements IQualityFormDAO {
implements IQualityFormDAO {
@Autowired @Autowired
private IAdvanceTypeDAO advanceTypeDAO; private IAdvanceTypeDAO advanceTypeDAO;
@Override @Override
@Transactional(readOnly = true)
public List<QualityForm> getAll() { public List<QualityForm> getAll() {
return list(QualityForm.class); return list(QualityForm.class);
} }
@ -67,8 +68,7 @@ public class QualityFormDAO extends GenericDAOHibernate<QualityForm, Long>
public boolean isUnique(QualityForm qualityForm) { public boolean isUnique(QualityForm qualityForm) {
try { try {
QualityForm result = findUniqueByName(qualityForm); QualityForm result = findUniqueByName(qualityForm);
return (result == null || result.getId() return result == null || result.getId().equals(qualityForm.getId());
.equals(qualityForm.getId()));
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
return false; return false;
@ -78,32 +78,33 @@ public class QualityFormDAO extends GenericDAOHibernate<QualityForm, Long>
@Override @Override
@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true) @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)
public QualityForm findByNameAndType(String name, QualityFormType type) { public QualityForm findByNameAndType(String name, QualityFormType type) {
return (QualityForm) getSession().createCriteria(QualityForm.class) return (QualityForm) getSession()
.add(Restrictions.eq("name", name)).add( .createCriteria(QualityForm.class)
Restrictions.eq("qualityFormType", type)) .add(Restrictions.eq("name", name))
.add(Restrictions.eq("qualityFormType", type))
.uniqueResult(); .uniqueResult();
} }
@Override @Override
@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true) @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)
public List<QualityForm> getAllByType(QualityFormType type) { public List<QualityForm> getAllByType(QualityFormType type) {
Criteria c = getSession().createCriteria(QualityForm.class).add( return getSession()
Restrictions.eq("qualityFormType", type)); .createCriteria(QualityForm.class)
return ((List<QualityForm>) c.list()); .add(Restrictions.eq("qualityFormType", type))
.list();
} }
@Override @Override
@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true) @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)
public QualityForm findUniqueByName(QualityForm qualityForm) public QualityForm findUniqueByName(QualityForm qualityForm) throws InstanceNotFoundException {
throws InstanceNotFoundException {
Validate.notNull(qualityForm); Validate.notNull(qualityForm);
return findUniqueByName(qualityForm.getName()); return findUniqueByName(qualityForm.getName());
} }
@Override @Override
@Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true) @Transactional(propagation = Propagation.REQUIRES_NEW, readOnly = true)
public QualityForm findUniqueByName(String name) public QualityForm findUniqueByName(String name) throws InstanceNotFoundException, NonUniqueResultException {
throws InstanceNotFoundException, NonUniqueResultException {
Criteria c = getSession().createCriteria(QualityForm.class); Criteria c = getSession().createCriteria(QualityForm.class);
c.add(Restrictions.eq("name", name)); c.add(Restrictions.eq("name", name));
QualityForm qualityForm = (QualityForm) c.uniqueResult(); QualityForm qualityForm = (QualityForm) c.uniqueResult();
@ -119,7 +120,8 @@ public class QualityFormDAO extends GenericDAOHibernate<QualityForm, Long>
public boolean existsOtherWorkReportTypeByName(QualityForm qualityForm) { public boolean existsOtherWorkReportTypeByName(QualityForm qualityForm) {
try { try {
QualityForm t = findUniqueByName(qualityForm); QualityForm t = findUniqueByName(qualityForm);
return (t != null && t != qualityForm);
return t != null && t != qualityForm;
} catch (InstanceNotFoundException e) { } catch (InstanceNotFoundException e) {
return false; return false;
} }
@ -141,8 +143,9 @@ public class QualityFormDAO extends GenericDAOHibernate<QualityForm, Long>
advanceTypeDAO.save(advanceType); advanceTypeDAO.save(advanceType);
advanceType.setUnitName(name); advanceType.setUnitName(name);
} else { } else {
advanceType = AdvanceType.create(name, new BigDecimal(100), advanceType = AdvanceType.create(
false, new BigDecimal(0.01), true, true, true); name, new BigDecimal(100), false, BigDecimal.valueOf(0.01), true, true, true);
advanceTypeDAO.save(advanceType); advanceTypeDAO.save(advanceType);
entity.setAdvanceType(advanceType); entity.setAdvanceType(advanceType);
@ -154,14 +157,15 @@ public class QualityFormDAO extends GenericDAOHibernate<QualityForm, Long>
@Override @Override
public void checkHasTasks(QualityForm qualityForm) throws ValidationException { public void checkHasTasks(QualityForm qualityForm) throws ValidationException {
Query query = getSession().createQuery( String queryString =
"FROM TaskQualityForm taskQualityForm JOIN taskQualityForm.qualityForm tq WHERE tq IN (:qualityForms)"); "FROM TaskQualityForm taskQualityForm JOIN taskQualityForm.qualityForm tq WHERE tq IN (:qualityForms)";
Query query = getSession().createQuery(queryString);
query.setParameterList("qualityForms", Collections.singleton(qualityForm)); query.setParameterList("qualityForms", Collections.singleton(qualityForm));
if (!query.list().isEmpty()) { if (!query.list().isEmpty()) {
throw ValidationException throw ValidationException.invalidValueException(
.invalidValueException( "Cannot delete quality form. It is being used at this moment by some task.", qualityForm);
"Cannot delete quality form. It is being used at this moment by some task.",
qualityForm);
} }
} }
} }

View file

@ -32,11 +32,6 @@
</createIndex> </createIndex>
<sql> <sql>
INSERT INTO email_template VALUES(1, 0, 3, 'Task assigned to resource : Autogenerated content text', 'Autogenerated subject text'); INSERT INTO email_template VALUES(1, 0, 3, 'Task assigned to resource : Autogenerated content text', 'Autogenerated subject text');
INSERT INTO email_template VALUES(2, 1, 3, 'Resource removed from task : Autogenerated content text', 'Autogenerated subject text');
INSERT INTO email_template VALUES(3, 2, 3, 'Milestone reached : Autogenerated content text', 'Autogenerated subject text');
INSERT INTO email_template VALUES(4, 3, 3, 'Task should start : Autogenerated content text', 'Autogenerated subject text');
INSERT INTO email_template VALUES(5, 4, 3, 'Task should finish : Autogenerated content text', 'Autogenerated subject text');
INSERT INTO email_template VALUES(6, 5, 3, 'Enter data to timesheet : Autogenerated content text', 'Autogenerated subject text');
</sql> </sql>
</changeSet> </changeSet>

View file

@ -1,9 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" <beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.0.xsd

View file

@ -4,7 +4,7 @@
<hibernate-mapping package="org.libreplan.business.email.entities" default-access="field"> <hibernate-mapping package="org.libreplan.business.email.entities" default-access="field">
<class name="org.libreplan.business.email.entities.EmailTemplate" table="email_template"> <class name="EmailTemplate" table="email_template">
<id name="id" access="property" type="long"> <id name="id" access="property" type="long">
<generator class="increment" > <generator class="increment" >

View file

@ -79,9 +79,9 @@
<many-to-many class="SchedulingDataForVersion" column="scheduling_state_for_version_id" /> <many-to-many class="SchedulingDataForVersion" column="scheduling_state_for_version_id" />
</map> </map>
<one-to-one name="sumChargedEffort" class="SumChargedEffort" cascade="delete" property-ref="orderElement" /> <one-to-one name="sumChargedEffort" class="SumChargedEffort" cascade="delete-orphan" property-ref="orderElement" />
<one-to-one name="sumExpenses" class="SumExpenses" cascade="delete" property-ref="orderElement" /> <one-to-one name="sumExpenses" class="SumExpenses" cascade="delete-orphan" property-ref="orderElement" />
<joined-subclass name="OrderLineGroup" table="order_line_group"> <joined-subclass name="OrderLineGroup" table="order_line_group">
<key column="order_element_id"/> <key column="order_element_id"/>

View file

@ -97,6 +97,9 @@
<value> <value>
TestEntities.hbm.xml TestEntities.hbm.xml
</value> </value>
<value>
org/libreplan/business/common/entities/Limits.hbm.xml
</value>
</list> </list>
</property> </property>

View file

@ -394,9 +394,8 @@
<!-- Java mail --> <!-- Java mail -->
<dependency> <dependency>
<groupId>javax.mail</groupId> <groupId>com.sun.mail</groupId>
<artifactId>mail</artifactId> <artifactId>javax.mail</artifactId>
<version>1.5.0-b01</version>
</dependency> </dependency>
<!-- JAX-RS API --> <!-- JAX-RS API -->

View file

@ -34,9 +34,7 @@ import static org.libreplan.web.I18nHelper._;
* Sends E-mail to users with data that storing in notification_queue table * Sends E-mail to users with data that storing in notification_queue table
* and that are treat to incoming EmailNotification * and that are treat to incoming EmailNotification
* *
* Created by * @author Created by Vova Perebykivskiy <vova@libreplan-enterprise.com> on 20.01.2016.
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 20.01.2016.
*/ */
@Component @Component
@ -77,6 +75,7 @@ public class ComposeMessage {
UserRole currentUserRole = getCurrentUserRole(notification.getType()); UserRole currentUserRole = getCurrentUserRole(notification.getType());
if ( currentWorker.getUser().isInRole(currentUserRole) ) { if ( currentWorker.getUser().isInRole(currentUserRole) ) {
if ( currentWorker.getUser().getApplicationLanguage().equals(Language.BROWSER_LANGUAGE) ) { if ( currentWorker.getUser().getApplicationLanguage().equals(Language.BROWSER_LANGUAGE) ) {
locale = new Locale(System.getProperty("user.language")); locale = new Locale(System.getProperty("user.language"));
} else { } else {
@ -96,9 +95,8 @@ public class ComposeMessage {
final String username = usrnme; final String username = usrnme;
final String password = psswrd; final String password = psswrd;
// It is very important to use Session.getInstance instead of Session.getDefaultInstance // It is very important to use Session.getInstance() instead of Session.getDefaultInstance()
Session mailSession = Session.getInstance(properties, Session mailSession = Session.getInstance(properties, new javax.mail.Authenticator() {
new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() { protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password); return new PasswordAuthentication(username, password);
} }
@ -123,9 +121,11 @@ public class ComposeMessage {
} catch (MessagingException e) { } catch (MessagingException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} catch (NullPointerException e) { } catch (NullPointerException e) {
if (receiver == null) try { if (receiver == null)
Messagebox.show(_(currentWorker.getUser().getLoginName() + " - this user have not filled E-mail"), _("Error"), try {
Messagebox.OK, Messagebox.ERROR); Messagebox.show(
_(currentWorker.getUser().getLoginName() + " - this user have not filled E-mail"),
_("Error"), Messagebox.OK, Messagebox.ERROR);
} catch (InterruptedException e1) { } catch (InterruptedException e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
@ -136,18 +136,21 @@ public class ComposeMessage {
private Worker getCurrentWorker(Long resourceID) { private Worker getCurrentWorker(Long resourceID) {
List<Worker> workerList = workerModel.getWorkers(); List<Worker> workerList = workerModel.getWorkers();
for(int i = 0; i < workerList.size(); i++) for (Worker current : workerList)
if ( workerList.get(i).getId().equals(resourceID) ) if ( current.getId().equals(resourceID) )
return workerList.get(i); return current;
return null; return null;
} }
private EmailTemplate findCurrentEmailTemplate(EmailTemplateEnum templateEnum, Locale locale) { private EmailTemplate findCurrentEmailTemplate(EmailTemplateEnum templateEnum, Locale locale) {
List<EmailTemplate> emailTemplates; List<EmailTemplate> emailTemplates;
emailTemplates = emailTemplateModel.getAll(); emailTemplates = emailTemplateModel.getAll();
for (EmailTemplate item : emailTemplates) for (EmailTemplate item : emailTemplates)
if ( item.getType().equals(templateEnum) && item.getLanguage().getLocale().equals(locale) ) if ( item.getType().equals(templateEnum) && item.getLanguage().getLocale().equals(locale) )
return item; return item;
return null; return null;
} }
@ -174,36 +177,39 @@ public class ComposeMessage {
for (int i = 0; i < emailConnectorProperties.size(); i++) { for (int i = 0; i < emailConnectorProperties.size(); i++) {
switch (i) { switch (i) {
case 1: { case 1:
protocol = emailConnectorProperties.get(1).getValue(); protocol = emailConnectorProperties.get(1).getValue();
break; break;
}
case 2: { case 2:
host = emailConnectorProperties.get(2).getValue(); host = emailConnectorProperties.get(2).getValue();
break; break;
}
case 3: { case 3:
port = emailConnectorProperties.get(3).getValue(); port = emailConnectorProperties.get(3).getValue();
break; break;
}
case 4: { case 4:
sender = emailConnectorProperties.get(4).getValue(); sender = emailConnectorProperties.get(4).getValue();
break; break;
}
case 5: { case 5:
usrnme = emailConnectorProperties.get(5).getValue(); usrnme = emailConnectorProperties.get(5).getValue();
break; break;
}
case 6: { case 6:
psswrd = emailConnectorProperties.get(6).getValue(); psswrd = emailConnectorProperties.get(6).getValue();
break; break;
}
default:
/* Nothing */
break;
} }
} }
properties = new Properties(); properties = new Properties();
if ( protocol.equals("STARTTLS") ) { if ( "STARTTLS".equals(protocol) ) {
properties.put("mail.smtp.starttls.enable", "true"); properties.put("mail.smtp.starttls.enable", "true");
properties.put("mail.smtp.host", host); properties.put("mail.smtp.host", host);
properties.put("mail.smtp.socketFactory.port", port); properties.put("mail.smtp.socketFactory.port", port);
@ -211,7 +217,7 @@ public class ComposeMessage {
properties.put("mail.smtp.auth", "true"); properties.put("mail.smtp.auth", "true");
properties.put("mail.smtp.port", port); properties.put("mail.smtp.port", port);
} }
else if ( protocol.equals("SMTP") ) { else if ( "SMTP".equals(protocol) ) {
properties.put("mail.smtp.host", host); properties.put("mail.smtp.host", host);
properties.put("mail.smtp.port", port); properties.put("mail.smtp.port", port);
} }
@ -219,19 +225,28 @@ public class ComposeMessage {
private UserRole getCurrentUserRole(EmailTemplateEnum type) { private UserRole getCurrentUserRole(EmailTemplateEnum type) {
switch (type) { switch (type) {
case TEMPLATE_TASK_ASSIGNED_TO_RESOURCE: return UserRole.ROLE_EMAIL_TASK_ASSIGNED_TO_RESOURCE; 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_RESOURCE_REMOVED_FROM_TASK:
return UserRole.ROLE_EMAIL_RESOURCE_REMOVED_FROM_TASK;
case TEMPLATE_MILESTONE_REACHED: return UserRole.ROLE_EMAIL_MILESTONE_REACHED; 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_START:
return UserRole.ROLE_EMAIL_TASK_SHOULD_START;
case TEMPLATE_TODAY_TASK_SHOULD_FINISH: return UserRole.ROLE_EMAIL_TASK_SHOULD_FINISH; 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; case TEMPLATE_ENTER_DATA_IN_TIMESHEET:
} return UserRole.ROLE_EMAIL_TIMESHEET_DATA_MISSING;
default:
/* There is no other template */
return null; return null;
} }
}
} }

View file

@ -28,7 +28,6 @@ import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import javax.mail.MessagingException; import javax.mail.MessagingException;
import javax.mail.NoSuchProviderException;
import javax.mail.Session; import javax.mail.Session;
import javax.mail.Transport; import javax.mail.Transport;
import java.util.List; import java.util.List;
@ -37,9 +36,7 @@ import java.util.Properties;
/** /**
* Validate Email Connection properties * Validate Email Connection properties
* *
* Created by * @author Created by Vova Perebykivskyi <vova@libreplan-enterprise.com> on 20.01.2016.
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 20.01.2016.
*/ */
@Component @Component
@ -49,6 +46,9 @@ public class EmailConnectionValidator {
@Autowired @Autowired
private IConnectorDAO connectorDAO; private IConnectorDAO connectorDAO;
/* Needed for EmailTest */
public static Exception exceptionType;
public boolean validConnection() { public boolean validConnection() {
List<ConnectorProperty> emailConnectorProperties = getEmailConnectorProperties(); List<ConnectorProperty> emailConnectorProperties = getEmailConnectorProperties();
@ -60,26 +60,29 @@ public class EmailConnectionValidator {
for (int i = 0; i < emailConnectorProperties.size(); i++) { for (int i = 0; i < emailConnectorProperties.size(); i++) {
switch ( i ) { switch ( i ) {
case 1: { case 1:
protocol = emailConnectorProperties.get(1).getValue(); protocol = emailConnectorProperties.get(1).getValue();
break; break;
}
case 2: { case 2:
host = emailConnectorProperties.get(2).getValue(); host = emailConnectorProperties.get(2).getValue();
break; break;
}
case 3: { case 3:
port = emailConnectorProperties.get(3).getValue(); port = emailConnectorProperties.get(3).getValue();
break; break;
}
case 5: { case 5:
usrnme = emailConnectorProperties.get(5).getValue(); usrnme = emailConnectorProperties.get(5).getValue();
break; break;
}
case 6: { case 6:
psswrd = emailConnectorProperties.get(6).getValue(); psswrd = emailConnectorProperties.get(6).getValue();
break; break;
}
default:
/* Nothing */
break;
} }
} }
@ -92,32 +95,37 @@ public class EmailConnectionValidator {
if ( protocol.equals("SMTP") ) { if ( protocol.equals("SMTP") ) {
properties.setProperty("mail.smtp.port", port); properties.setProperty("mail.smtp.port", port);
properties.setProperty("mail.smtp.host", host); properties.setProperty("mail.smtp.host", host);
properties.setProperty("mail.smtp.connectiontimeout", Integer.toString(3000));
Session session = Session.getInstance(properties, null); Session session = Session.getInstance(properties, null);
transport = session.getTransport("smtp"); transport = session.getTransport("smtp");
if (usrnme.equals("") && psswrd.equals("")) transport.connect(); if ( "".equals(usrnme) && "".equals(psswrd) )
transport.connect();
} else if ( protocol.equals("STARTTLS") ) { } else if ( protocol.equals("STARTTLS") ) {
properties.setProperty("mail.smtps.port", port); properties.setProperty("mail.smtps.port", port);
properties.setProperty("mail.smtps.host", host); properties.setProperty("mail.smtps.host", host);
properties.setProperty("mail.smtp.connectiontimeout", Integer.toString(3000));
Session session = Session.getInstance(properties, null); Session session = Session.getInstance(properties, null);
transport = session.getTransport("smtps"); transport = session.getTransport("smtps");
if (!usrnme.equals("") && psswrd != null) transport.connect(host, usrnme, psswrd);
}
if (transport != null && transport.isConnected()) return true;
} catch (NoSuchProviderException e) { if ( !"".equals(usrnme) && psswrd != null )
e.printStackTrace(); transport.connect(host, usrnme, psswrd);
} }
catch (MessagingException e) { if ( transport != null && transport.isConnected() )
return true;
} catch (MessagingException e) {
e.printStackTrace(); e.printStackTrace();
// FIXME must be a better way to send exception type to test class
exceptionType = e;
} }
return false; return false;
} }
public List<ConnectorProperty> getEmailConnectorProperties() { public List<ConnectorProperty> getEmailConnectorProperties() {
Connector connector = connectorDAO.findUniqueByName("E-mail"); Connector connector = connectorDAO.findUniqueByName("E-mail");
return connector.getProperties(); return connector.getProperties();

View file

@ -22,15 +22,15 @@ package org.libreplan.importers.notifications;
import org.libreplan.business.email.entities.EmailNotification; import org.libreplan.business.email.entities.EmailNotification;
/** /**
* Sends E-mail to users with data that storing in notification_queue table * Sends E-mail to users with data that storing in notification_queue table.
* *
* Created by * @author Created by Vova Perebykivskyi <vova@libreplan-enterprise.com> on 13.10.2015.
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 13.10.2015.
*/ */
public interface IEmailNotificationJob { public interface IEmailNotificationJob {
void sendEmail(); void sendEmail();
boolean composeMessageForUser(EmailNotification notification); boolean composeMessageForUser(EmailNotification notification);
} }

View file

@ -27,22 +27,20 @@ import org.springframework.scheduling.quartz.QuartzJobBean;
/** /**
* Sends E-mail to users with data that storing in notification_queue table * 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} * and that are treat to
* * {@link org.libreplan.business.email.entities.EmailTemplateEnum#TEMPLATE_RESOURCE_REMOVED_FROM_TASK}
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 20.01.2016.
* *
* @author Created by Vova Perebykivskiy <vova@libreplan-enterprise.com> on 20.01.2016.
*/ */
public class SendEmailOnResourceRemovedFromTaskJob extends QuartzJobBean { public class SendEmailOnResourceRemovedFromTaskJob extends QuartzJobBean {
@Override @Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException { protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
ApplicationContext applicationContext = (ApplicationContext) context.getJobDetail(). ApplicationContext applicationContext =
getJobDataMap().get("applicationContext"); (ApplicationContext) context.getJobDetail().getJobDataMap().get("applicationContext");
IEmailNotificationJob resourceRemovedFromTask = (IEmailNotificationJob) applicationContext IEmailNotificationJob resourceRemovedFromTask =
.getBean("SendEmailOnResourceRemovedFromTask"); (IEmailNotificationJob) applicationContext.getBean("SendEmailOnResourceRemovedFromTask");
resourceRemovedFromTask.sendEmail(); resourceRemovedFromTask.sendEmail();
} }

View file

@ -28,23 +28,21 @@ import org.springframework.scheduling.quartz.QuartzJobBean;
/** /**
* Sends E-mail to users with data that storing in notification_queue table * 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} * and that are treat to
* * {@link org.libreplan.business.email.entities.EmailTemplateEnum#TEMPLATE_TASK_ASSIGNED_TO_RESOURCE}
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 13.10.2015.
* *
* @author Created by Vova Perebykivskiy <vova@libreplan-enterprise.com> on 13.10.2015.
*/ */
public class SendEmailOnTaskAssignedToResourceJob extends QuartzJobBean { public class SendEmailOnTaskAssignedToResourceJob extends QuartzJobBean {
@Override @Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException { protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
ApplicationContext applicationContext = (ApplicationContext) context.getJobDetail(). ApplicationContext applicationContext =
getJobDataMap().get("applicationContext"); (ApplicationContext) context.getJobDetail().getJobDataMap().get("applicationContext");
IEmailNotificationJob taskAssignedToResource = (IEmailNotificationJob) applicationContext IEmailNotificationJob taskAssignedToResource =
.getBean("SendEmailOnTaskAssignedToResource"); (IEmailNotificationJob) applicationContext.getBean("SendEmailOnTaskAssignedToResource");
taskAssignedToResource.sendEmail(); taskAssignedToResource.sendEmail();
} }

View file

@ -27,22 +27,21 @@ import org.springframework.scheduling.quartz.QuartzJobBean;
/** /**
* Sends E-mail to users with data that storing in notification_queue table * 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} * and that are treat to
* * {@link org.libreplan.business.email.entities.EmailTemplateEnum#TEMPLATE_TODAY_TASK_SHOULD_FINISH}
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 20.01.2016.
* *
* @author Created by Vova Perebykivskiy <vova@libreplan-enterprise.com> on 20.01.2016.
*/ */
public class SendEmailOnTaskShouldFinishJob extends QuartzJobBean { public class SendEmailOnTaskShouldFinishJob extends QuartzJobBean {
@Override @Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException { protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
ApplicationContext applicationContext = (ApplicationContext) context.getJobDetail().
getJobDataMap().get("applicationContext");
IEmailNotificationJob taskShouldFinish = (IEmailNotificationJob) applicationContext ApplicationContext applicationContext =
.getBean("SendEmailOnTaskShouldFinish"); (ApplicationContext) context.getJobDetail().getJobDataMap().get("applicationContext");
IEmailNotificationJob taskShouldFinish =
(IEmailNotificationJob) applicationContext.getBean("SendEmailOnTaskShouldFinish");
taskShouldFinish.sendEmail(); taskShouldFinish.sendEmail();
} }

View file

@ -27,22 +27,22 @@ import org.springframework.scheduling.quartz.QuartzJobBean;
/** /**
* Sends E-mail to users with data that storing in notification_queue table * 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} * and that are treat to
* {@link org.libreplan.business.email.entities.EmailTemplateEnum#TEMPLATE_TODAY_TASK_SHOULD_START}.
* *
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 20.01.2016.
* *
* @author Created by Vova Perebykivskyi <vova@libreplan-enterprise.com> on 20.01.2016
*/ */
public class SendEmailOnTaskShouldStartJob extends QuartzJobBean { public class SendEmailOnTaskShouldStartJob extends QuartzJobBean {
@Override @Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException { protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
ApplicationContext applicationContext = (ApplicationContext) context.getJobDetail().
getJobDataMap().get("applicationContext");
IEmailNotificationJob taskShouldStart = (IEmailNotificationJob) applicationContext ApplicationContext applicationContext = (ApplicationContext)
.getBean("SendEmailOnTaskShouldStart"); context.getJobDetail().getJobDataMap().get("applicationContext");
IEmailNotificationJob taskShouldStart =
(IEmailNotificationJob) applicationContext.getBean("SendEmailOnTaskShouldStart");
taskShouldStart.sendEmail(); taskShouldStart.sendEmail();
} }

View file

@ -27,22 +27,20 @@ import org.springframework.scheduling.quartz.QuartzJobBean;
/** /**
* Sends E-mail to users with data that storing in notification_queue table * 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} * and that are treat to
* * {@link org.libreplan.business.email.entities.EmailTemplateEnum#TEMPLATE_ENTER_DATA_IN_TIMESHEET}
* Created by
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 20.01.2016.
* *
* @author Created by Vova Perebykivskiy <vova@libreplan-enterprise.com> on 20.01.2016.
*/ */
public class SendEmailOnTimesheetDataMissingJob extends QuartzJobBean { public class SendEmailOnTimesheetDataMissingJob extends QuartzJobBean {
@Override @Override
protected void executeInternal(JobExecutionContext context) throws JobExecutionException { protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
ApplicationContext applicationContext = (ApplicationContext) context.getJobDetail(). ApplicationContext applicationContext =
getJobDataMap().get("applicationContext"); (ApplicationContext) context.getJobDetail().getJobDataMap().get("applicationContext");
IEmailNotificationJob timesheetMissing = (IEmailNotificationJob) applicationContext IEmailNotificationJob timesheetMissing =
.getBean("SendEmailOnTimesheetDataMissing"); (IEmailNotificationJob) applicationContext.getBean("SendEmailOnTimesheetDataMissing");
timesheetMissing.sendEmail(); timesheetMissing.sendEmail();
} }

View file

@ -39,7 +39,6 @@ import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -51,9 +50,7 @@ import java.util.List;
* Date will be send on current date equals to deadline date of {@link Milestone} * 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) * But it will be only send to Manager (you can assign him in project properties)
* *
* Created by * @author Created by Vova Perebykivskyi <vova@libreplan-enterprise.com> on 20.01.2016
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 20.01.2016.
*/ */
@Component @Component
@ -82,16 +79,14 @@ public class SendEmailOnMilestoneReached implements IEmailNotificationJob {
if ( Configuration.isEmailSendingEnabled() ) { if ( Configuration.isEmailSendingEnabled() ) {
if ( emailConnectionValidator.isConnectionActivated() ) if ( emailConnectionValidator.isConnectionActivated() && emailConnectionValidator.validConnection() ) {
if ( emailConnectionValidator.validConnection() ){ List<EmailNotification> notifications =
emailNotificationModel.getAllByType(EmailTemplateEnum.TEMPLATE_MILESTONE_REACHED);
List<EmailNotification> notifications = emailNotificationModel for (EmailNotification notification : notifications)
.getAllByType(EmailTemplateEnum.TEMPLATE_MILESTONE_REACHED); if ( composeMessageForUser(notification) )
deleteSingleNotification(notification);
for (int i = 0; i < notifications.size(); i++)
if ( composeMessageForUser(notifications.get(i)) )
deleteSingleNotification(notifications.get(i));
} }
} }
} }
@ -144,9 +139,7 @@ public class SendEmailOnMilestoneReached implements IEmailNotificationJob {
int deadlineMonth = deadline.getMonthOfYear(); int deadlineMonth = deadline.getMonthOfYear();
int deadlineDay = deadline.getDayOfMonth(); int deadlineDay = deadline.getDayOfMonth();
if (currentYear == deadlineYear && if ( currentYear == deadlineYear && currentMonth == deadlineMonth && currentDay == deadlineDay )
currentMonth == deadlineMonth &&
currentDay == deadlineDay)
sendEmailNotificationToManager(item); sendEmailNotificationToManager(item);
} }
} }

View file

@ -36,12 +36,10 @@ import java.util.List;
/** /**
* Sends E-mail to users with data that storing in notification_queue table * Sends E-mail to users with data that storing in notification_queue table
* and that are treat to TEMPLATE_RESOUCE_REMOVED_FROM_TASK * and that are treat to {@link EmailTemplateEnum#TEMPLATE_RESOURCE_REMOVED_FROM_TASK}
* Data will be send if resource has been removed from task (in resource allocation) * Data will be send if resource has been removed from task (in resource allocation)
* *
* Created by * @author Created by Vova Perebykivskiy <vova@libreplan-enterprise.com> on 20.01.2016.
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 20.01.2016.
*/ */
@Component @Component
@ -62,13 +60,10 @@ public class SendEmailOnResourceRemovedFromTask implements IEmailNotificationJob
// At this time all data have gathered, if it exists of course // At this time all data have gathered, if it exists of course
if ( Configuration.isEmailSendingEnabled() ) { if ( Configuration.isEmailSendingEnabled() ) {
if ( emailConnectionValidator.isConnectionActivated() && emailConnectionValidator.validConnection() ) {
if ( emailConnectionValidator.isConnectionActivated() ) List<EmailNotification> notifications =
emailNotificationModel.getAllByType(EmailTemplateEnum.TEMPLATE_RESOURCE_REMOVED_FROM_TASK);
if ( emailConnectionValidator.validConnection() ){
List<EmailNotification> notifications = emailNotificationModel
.getAllByType(EmailTemplateEnum.TEMPLATE_RESOURCE_REMOVED_FROM_TASK);
for (int i = 0; i < notifications.size(); i++) for (int i = 0; i < notifications.size(); i++)
if ( composeMessageForUser(notifications.get(i)) ) if ( composeMessageForUser(notifications.get(i)) )

View file

@ -38,12 +38,10 @@ import java.util.List;
/** /**
* Sends E-mail to users with data that storing in notification_queue table * 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} * and that are treat to {@link EmailTemplateEnum#TEMPLATE_ENTER_DATA_IN_TIMESHEET}
* Data will be send after user will be assigned to some task. * Data will be send after user will be assigned to some task.
* *
* Created by * @author Created by Vova Perebykivskyi <vova@libreplan-enterprise.com> on 13.10.2015.
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 13.10.2015.
*/ */
@Component @Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE) @Scope(BeanDefinition.SCOPE_PROTOTYPE)
@ -63,16 +61,14 @@ public class SendEmailOnTaskAssignedToResource implements IEmailNotificationJob
public void sendEmail() { public void sendEmail() {
if ( Configuration.isEmailSendingEnabled() ) { if ( Configuration.isEmailSendingEnabled() ) {
if ( emailConnectionValidator.isConnectionActivated() ) if ( emailConnectionValidator.isConnectionActivated() && emailConnectionValidator.validConnection() ) {
if ( emailConnectionValidator.validConnection() ){ List<EmailNotification> notifications =
emailNotificationModel.getAllByType(EmailTemplateEnum.TEMPLATE_TASK_ASSIGNED_TO_RESOURCE);
List<EmailNotification> notifications = emailNotificationModel for (EmailNotification notification : notifications)
.getAllByType(EmailTemplateEnum.TEMPLATE_TASK_ASSIGNED_TO_RESOURCE); if ( composeMessageForUser(notification) )
deleteSingleNotification(notification);
for (int i = 0; i < notifications.size(); i++)
if ( composeMessageForUser(notifications.get(i)) )
deleteSingleNotification(notifications.get(i));
} }
} }
} }

View file

@ -44,12 +44,10 @@ import java.util.List;
/** /**
* Sends E-mail to users with data that storing in notification_queue table * 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} * and that are treat to {@link EmailTemplateEnum#TEMPLATE_TODAY_TASK_SHOULD_FINISH}
* Data will be send when current day equals to finish date. * Data will be send when current day equals to finish date.
* *
* Created by * @author Created by Vova Perebykivskiy <vova@libreplan-enterprise.com> on 21.01.2016.
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 21.01.2016.
*/ */
@Component @Component
@ -74,13 +72,10 @@ public class SendEmailOnTaskShouldFinish implements IEmailNotificationJob {
taskShouldFinish(); taskShouldFinish();
if ( Configuration.isEmailSendingEnabled() ) { if ( Configuration.isEmailSendingEnabled() ) {
if ( emailConnectionValidator.isConnectionActivated() && emailConnectionValidator.validConnection() ) {
if ( emailConnectionValidator.isConnectionActivated() ) List<EmailNotification> notifications =
emailNotificationModel.getAllByType(EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_FINISH);
if ( emailConnectionValidator.validConnection() ){
List<EmailNotification> notifications = emailNotificationModel
.getAllByType(EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_FINISH);
for (int i = 0; i < notifications.size(); i++) for (int i = 0; i < notifications.size(); i++)
if ( composeMessageForUser(notifications.get(i)) ) if ( composeMessageForUser(notifications.get(i)) )
@ -100,6 +95,7 @@ public class SendEmailOnTaskShouldFinish implements IEmailNotificationJob {
@Transactional @Transactional
public void taskShouldFinish() { public void taskShouldFinish() {
// TODO resolve deprecated
// Check if current date equals with item date // Check if current date equals with item date
Date date = new Date(); Date date = new Date();
int currentYear = date.getYear(); int currentYear = date.getYear();
@ -124,10 +120,10 @@ public class SendEmailOnTaskShouldFinish implements IEmailNotificationJob {
private void sendEmailNotificationAboutTaskShouldFinish(TaskElement item){ private void sendEmailNotificationAboutTaskShouldFinish(TaskElement item){
List<ResourceAllocation<?>> list = new ArrayList<ResourceAllocation<?>>(); List<ResourceAllocation<?>> list = new ArrayList<>();
list.addAll(item.getAllResourceAllocations()); list.addAll(item.getAllResourceAllocations());
List<Resource> resources = new ArrayList<Resource>(); List<Resource> resources = new ArrayList<>();
for (ResourceAllocation<?> allocation : list) for (ResourceAllocation<?> allocation : list)
resources.add(allocation.getAssociatedResources().get(0)); resources.add(allocation.getAssociatedResources().get(0));

View file

@ -44,12 +44,10 @@ import java.util.List;
/** /**
* Sends E-mail users with data that storing in notification_queue table * Sends E-mail users with data that storing in notification_queue table
* and that are treat to {@link EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_START} * and that are treat to {@link EmailTemplateEnum#TEMPLATE_TODAY_TASK_SHOULD_START}
* Data will be send if current data equals to start date. * Data will be send if current data equals to start date.
* *
* Created by * @author Created by Vova Perebykivskyi <vova@libreplan-enterprise.com> on 20.01.2016.
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 20.01.2016.
*/ */
@Component @Component
@ -75,16 +73,14 @@ public class SendEmailOnTaskShouldStart implements IEmailNotificationJob {
if ( Configuration.isEmailSendingEnabled() ) { if ( Configuration.isEmailSendingEnabled() ) {
if ( emailConnectionValidator.isConnectionActivated() ) if ( emailConnectionValidator.isConnectionActivated() && emailConnectionValidator.validConnection() ) {
if ( emailConnectionValidator.validConnection() ){ List<EmailNotification> notifications =
emailNotificationModel.getAllByType(EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_START);
List<EmailNotification> notifications = emailNotificationModel for (EmailNotification notification : notifications)
.getAllByType(EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_START); if ( composeMessageForUser(notification) )
deleteSingleNotification(notification);
for (int i = 0; i < notifications.size(); i++)
if ( composeMessageForUser(notifications.get(i)) )
deleteSingleNotification(notifications.get(i));
} }
} }
} }
@ -102,6 +98,7 @@ public class SendEmailOnTaskShouldStart implements IEmailNotificationJob {
public void taskShouldStart() { public void taskShouldStart() {
// Check if current date equals with item date // Check if current date equals with item date
Date date = new Date(); Date date = new Date();
// TODO resolve deprecated
int currentYear = date.getYear(); int currentYear = date.getYear();
int currentMonth = date.getMonth(); int currentMonth = date.getMonth();
int currentDay = date.getDay(); int currentDay = date.getDay();
@ -113,9 +110,7 @@ public class SendEmailOnTaskShouldStart implements IEmailNotificationJob {
int startMonth = startDate.getMonth(); int startMonth = startDate.getMonth();
int startDay = startDate.getDay(); int startDay = startDate.getDay();
if ( currentYear == startYear && if ( currentYear == startYear && currentMonth == startMonth && currentDay == startDay ) {
currentMonth == startMonth &&
currentDay == startDay){
// Get all resources for current task and send them email notification // Get all resources for current task and send them email notification
sendEmailNotificationAboutTaskShouldStart(item); sendEmailNotificationAboutTaskShouldStart(item);
} }
@ -123,10 +118,10 @@ public class SendEmailOnTaskShouldStart implements IEmailNotificationJob {
} }
private void sendEmailNotificationAboutTaskShouldStart(TaskElement item) { private void sendEmailNotificationAboutTaskShouldStart(TaskElement item) {
List<ResourceAllocation<?>> list = new ArrayList<ResourceAllocation<?>>(); List<ResourceAllocation<?>> list = new ArrayList<>();
list.addAll(item.getAllResourceAllocations()); list.addAll(item.getAllResourceAllocations());
List<Resource> resources = new ArrayList<Resource>(); List<Resource> resources = new ArrayList<>();
for (ResourceAllocation<?> allocation : list) for (ResourceAllocation<?> allocation : list)
resources.add(allocation.getAssociatedResources().get(0)); resources.add(allocation.getAssociatedResources().get(0));

View file

@ -60,12 +60,10 @@ import java.util.List;
/** /**
* Sends E-mail to users with data that storing in notification_queue table * 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} * and that are treat to {@link EmailTemplateEnum#TEMPLATE_ENTER_DATA_IN_TIMESHEET}
* Data will be send for bound users with empty timesheet lines. * Data will be send for bound users with empty timesheet lines.
* *
* Created by * @author Created by Vova Perebykivskiy <vova@libreplan-enterprise.com> on 20.01.2016.
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 20.01.2016.
*/ */
@Component @Component
@ -96,13 +94,10 @@ public class SendEmailOnTimesheetDataMissing implements IEmailNotificationJob {
checkTimesheet(); checkTimesheet();
if ( Configuration.isEmailSendingEnabled() ) { if ( Configuration.isEmailSendingEnabled() ) {
if ( emailConnectionValidator.isConnectionActivated() && emailConnectionValidator.validConnection() ) {
if ( emailConnectionValidator.isConnectionActivated() ) List<EmailNotification> notifications =
emailNotificationModel.getAllByType(EmailTemplateEnum.TEMPLATE_ENTER_DATA_IN_TIMESHEET);
if ( emailConnectionValidator.validConnection() ){
List<EmailNotification> notifications = emailNotificationModel
.getAllByType(EmailTemplateEnum.TEMPLATE_ENTER_DATA_IN_TIMESHEET);
for (int i = 0; i < notifications.size(); i++) for (int i = 0; i < notifications.size(); i++)
if ( composeMessageForUser(notifications.get(i)) ) if ( composeMessageForUser(notifications.get(i)) )
@ -128,8 +123,8 @@ public class SendEmailOnTimesheetDataMissing implements IEmailNotificationJob {
@Transactional @Transactional
private List<User> getPersonalTimesheets() { private List<User> getPersonalTimesheets() {
List<PersonalTimesheetDTO> personalTimesheetDTO = new ArrayList<PersonalTimesheetDTO>(); List<PersonalTimesheetDTO> personalTimesheetDTO = new ArrayList<>();
List<User> usersWithoutTimesheets = new ArrayList<User>(); List<User> usersWithoutTimesheets = new ArrayList<>();
List<User> users = userModel.getUsers(); List<User> users = userModel.getUsers();
for (User user : users) for (User user : users)
@ -139,11 +134,15 @@ public class SendEmailOnTimesheetDataMissing implements IEmailNotificationJob {
LocalDate activationDate = getActivationDate(user.getWorker()); LocalDate activationDate = getActivationDate(user.getWorker());
LocalDate currentDate = new LocalDate(); LocalDate currentDate = new LocalDate();
personalTimesheetDTO.addAll(getPersonalTimesheets(user.getWorker(), activationDate, personalTimesheetDTO.addAll(getPersonalTimesheets(
currentDate.plusMonths(1), getPersonalTimesheetsPeriodicity())); user.getWorker(),
activationDate,
currentDate.plusMonths(1),
getPersonalTimesheetsPeriodicity()));
for(PersonalTimesheetDTO item : personalTimesheetDTO) { for(PersonalTimesheetDTO item : personalTimesheetDTO) {
WorkReport workReport = item.getWorkReport(); WorkReport workReport = item.getWorkReport();
if ( item.getTasksNumber() == 0 && workReport == null ) if ( item.getTasksNumber() == 0 && workReport == null )
if ( !usersWithoutTimesheets.contains(user) ) if ( !usersWithoutTimesheets.contains(user) )
usersWithoutTimesheets.add(user); usersWithoutTimesheets.add(user);
@ -173,10 +172,9 @@ public class SendEmailOnTimesheetDataMissing implements IEmailNotificationJob {
end = periodicity.getEnd(end); end = periodicity.getEnd(end);
int items = periodicity.getItemsBetween(start, end); int items = periodicity.getItemsBetween(start, end);
List<PersonalTimesheetDTO> result = new ArrayList<PersonalTimesheetDTO>(); List<PersonalTimesheetDTO> result = new ArrayList<>();
// In decreasing order to provide a list sorted with the more recent // In decreasing order to provide a list sorted with the more recent personal timesheets at the beginning
// personal timesheets at the beginning
for (int i = items; i >= 0; i--) { for (int i = items; i >= 0; i--) {
LocalDate date = periodicity.getDateForItemFromDate(i, start); LocalDate date = periodicity.getDateForItemFromDate(i, start);
@ -189,28 +187,31 @@ public class SendEmailOnTimesheetDataMissing implements IEmailNotificationJob {
tasksNumber = getNumberOfOrderElementsWithTrackedTime(workReport); tasksNumber = getNumberOfOrderElementsWithTrackedTime(workReport);
} }
result.add(new PersonalTimesheetDTO(date, workReport, result.add(new PersonalTimesheetDTO(
getResourceCapcity(resource, date, periodicity), hours, date,
workReport,
getResourceCapcity(resource, date, periodicity),
hours,
tasksNumber)); tasksNumber));
} }
return result; return result;
} }
private LocalDate getActivationDate(Worker worker) { private LocalDate getActivationDate(Worker worker) {
return worker.getCalendar().getFistCalendarAvailability() return worker.getCalendar().getFistCalendarAvailability().getStartDate();
.getStartDate();
} }
private PersonalTimesheetsPeriodicityEnum getPersonalTimesheetsPeriodicity() { private PersonalTimesheetsPeriodicityEnum getPersonalTimesheetsPeriodicity() {
return configurationDAO.getConfiguration() return configurationDAO.getConfiguration().getPersonalTimesheetsPeriodicity();
.getPersonalTimesheetsPeriodicity();
} }
private WorkReport getWorkReport(Resource resource, LocalDate date, private WorkReport getWorkReport(Resource resource, LocalDate date,
PersonalTimesheetsPeriodicityEnum periodicity) { PersonalTimesheetsPeriodicityEnum periodicity) {
WorkReport workReport = workReportDAO.getPersonalTimesheetWorkReport( WorkReport workReport = workReportDAO.getPersonalTimesheetWorkReport(
resource, date, periodicity); resource, date, periodicity);
forceLoad(workReport); forceLoad(workReport);
return workReport; return workReport;
} }
private void forceLoad(WorkReport workReport) { private void forceLoad(WorkReport workReport) {
@ -226,7 +227,7 @@ public class SendEmailOnTimesheetDataMissing implements IEmailNotificationJob {
return 0; return 0;
} }
List<OrderElement> orderElements = new ArrayList<OrderElement>(); List<OrderElement> orderElements = new ArrayList<>();
for (WorkReportLine line : workReport.getWorkReportLines()) { for (WorkReportLine line : workReport.getWorkReportLines()) {
if (!line.getEffort().isZero()) { if (!line.getEffort().isZero()) {
OrderElement orderElement = line.getOrderElement(); OrderElement orderElement = line.getOrderElement();
@ -239,14 +240,13 @@ public class SendEmailOnTimesheetDataMissing implements IEmailNotificationJob {
} }
private EffortDuration getResourceCapcity(Resource resource, LocalDate date, private EffortDuration getResourceCapcity(Resource resource, LocalDate date,
PersonalTimesheetsPeriodicityEnum periodicity) { PersonalTimesheetsPeriodicityEnum periodicity) {
LocalDate start = periodicity.getStart(date); LocalDate start = periodicity.getStart(date);
LocalDate end = periodicity.getEnd(date); LocalDate end = periodicity.getEnd(date);
EffortDuration capacity = EffortDuration.zero(); EffortDuration capacity = EffortDuration.zero();
for (LocalDate day = start; day.compareTo(end) <= 0; day = day for (LocalDate day = start; day.compareTo(end) <= 0; day = day.plusDays(1)) {
.plusDays(1)) { capacity = capacity.plus(resource.getCalendar().getCapacityOn(IntraDayDate.PartialDay.wholeDay(day)));
capacity = capacity.plus(resource.getCalendar().getCapacityOn(
IntraDayDate.PartialDay.wholeDay(day)));
} }
return capacity; return capacity;
} }

View file

@ -37,15 +37,14 @@ import org.libreplan.importers.SynchronizationInfo;
public interface IJobSchedulerModel { public interface IJobSchedulerModel {
/** /**
* returns all job scheduler configurations * Returns all job scheduler configurations.
* *
* @return list of <code>JobSchedulerConfiguration</code> * @return list of <code>JobSchedulerConfiguration</code>
*/ */
List<JobSchedulerConfiguration> getJobSchedulerConfigurations(); List<JobSchedulerConfiguration> getJobSchedulerConfigurations();
/** /**
* returns next fire time for the specified job from * Returns next fire time for the specified job from <code>{@link JobSchedulerConfiguration}</code>.
* <code>{@link JobSchedulerConfiguration}</code>
* *
* @param jobSchedulerConfiguration * @param jobSchedulerConfiguration
* the job scheduler configuration * the job scheduler configuration
@ -53,18 +52,17 @@ public interface IJobSchedulerModel {
String getNextFireTime(JobSchedulerConfiguration jobSchedulerConfiguration); String getNextFireTime(JobSchedulerConfiguration jobSchedulerConfiguration);
/** /**
* Do manual action(replacement of scheduling) * Do manual action(replacement of scheduling).
* *
* @param jobSchedulerConfiguration * @param jobSchedulerConfiguration
* the job configuration * the job configuration
* @throws ConnectorException * @throws ConnectorException
* if connector is not valid * if connector is not valid
*/ */
void doManual(JobSchedulerConfiguration jobSchedulerConfiguration) void doManual(JobSchedulerConfiguration jobSchedulerConfiguration) throws ConnectorException;
throws ConnectorException;
/** /**
* Returns synchronization infos. Failures or successes info * Returns synchronization infos. Failures or successes info.
*/ */
List<SynchronizationInfo> getSynchronizationInfos(); List<SynchronizationInfo> getSynchronizationInfos();
@ -74,7 +72,7 @@ public interface IJobSchedulerModel {
void initCreate(); void initCreate();
/** /**
* Prepares for edit {@link JobSchedulerConfiguration} * Prepares for edit {@link JobSchedulerConfiguration}.
* *
* @param jobSchedulerConfiguration * @param jobSchedulerConfiguration
* object to be edited * object to be edited
@ -89,7 +87,7 @@ public interface IJobSchedulerModel {
JobSchedulerConfiguration getJobSchedulerConfiguration(); JobSchedulerConfiguration getJobSchedulerConfiguration();
/** /**
* Saves the current {@link JobSchedulerConfiguration} * Saves the current {@link JobSchedulerConfiguration}.
* *
* @throws ValidationException * @throws ValidationException
* if validation fails * if validation fails
@ -97,12 +95,12 @@ public interface IJobSchedulerModel {
void confirmSave() throws ValidationException; void confirmSave() throws ValidationException;
/** /**
* Cancels the current {@link JobSchedulerConfiguration} * Cancels the current {@link JobSchedulerConfiguration}.
*/ */
void cancel(); void cancel();
/** /**
* Removes the current {@link JobSchedulerConfiguration} * Removes the current {@link JobSchedulerConfiguration}.
* *
* @param jobSchedulerConfiguration * @param jobSchedulerConfiguration
* object to be removed * object to be removed
@ -110,16 +108,15 @@ public interface IJobSchedulerModel {
void remove(JobSchedulerConfiguration jobSchedulerConfiguration); void remove(JobSchedulerConfiguration jobSchedulerConfiguration);
/** /**
* returns list of connectors * Returns list of connectors
*/ */
List<Connector> getConnectors(); List<Connector> getConnectors();
/** /**
* Schedule or unschedule jobs for the specified <code>connector</code> * Schedule or unschedule jobs for the specified <code>connector</code>.
* *
* schedule all jobs of the specified <code>connector</code>'s property * Schedule all jobs of the specified <code>connector</code>'s property
* {@link PredefinedConnectorProperties#ACTIVATED} is 'Y', otherwise * {@link PredefinedConnectorProperties#ACTIVATED} is 'Y', otherwise unschedule the jobs.
* unschedule the jobs
* *
* @param connector * @param connector
* where to check if property is changed * where to check if property is changed
@ -128,22 +125,20 @@ public interface IJobSchedulerModel {
boolean scheduleOrUnscheduleJobs(Connector connector); boolean scheduleOrUnscheduleJobs(Connector connector);
/** /**
* schedule or unschedule job for the specified job in * Schedule or unschedule job for the specified job in <code>{@link JobSchedulerConfiguration}</code>.
* <code>{@link JobSchedulerConfiguration}</code>
* *
* @return true if scheduling is succeeded, false otherwise * @return true if scheduling is succeeded, false otherwise
*/ */
boolean scheduleOrUnscheduleJob(); boolean scheduleOrUnscheduleJob();
/** /**
* Delete job specified in <code>{@link JobSchedulerConfiguration}</code> * Delete job specified in <code>{@link JobSchedulerConfiguration}</code>.
* *
* @param jobSchedulerConfiguration * @param jobSchedulerConfiguration
* configuration for the job to be deleted * configuration for the job to be deleted
* @return true if job is successfully deleted from the scheduler, false * @return true if job is successfully deleted from the scheduler, false
* otherwise * otherwise
*/ */
boolean deleteScheduledJob( boolean deleteScheduledJob(JobSchedulerConfiguration jobSchedulerConfiguration);
JobSchedulerConfiguration jobSchedulerConfiguration);
} }

View file

@ -42,7 +42,6 @@ import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.SuspendNotAllowedException; import org.zkoss.zk.ui.SuspendNotAllowedException;
import org.zkoss.zk.ui.WrongValueException; import org.zkoss.zk.ui.WrongValueException;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener; import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events; import org.zkoss.zk.ui.event.Events;
import org.zkoss.zul.Button; import org.zkoss.zul.Button;
@ -52,7 +51,6 @@ import org.zkoss.zul.Hbox;
import org.zkoss.zul.Label; import org.zkoss.zul.Label;
import org.zkoss.zul.Listbox; import org.zkoss.zul.Listbox;
import org.zkoss.zul.Popup; import org.zkoss.zul.Popup;
import org.zkoss.zul.Row;
import org.zkoss.zul.RowRenderer; import org.zkoss.zul.RowRenderer;
import org.zkoss.zul.SimpleListModel; import org.zkoss.zul.SimpleListModel;
import org.zkoss.zul.api.Caption; import org.zkoss.zul.api.Caption;
@ -64,27 +62,30 @@ import org.zkoss.zul.api.Window;
* *
* @author Miciele Ghiorghis <m.ghiorghis@antoniusziekenhuis.nl> * @author Miciele Ghiorghis <m.ghiorghis@antoniusziekenhuis.nl>
*/ */
public class JobSchedulerController extends public class JobSchedulerController extends BaseCRUDController<JobSchedulerConfiguration> {
BaseCRUDController<JobSchedulerConfiguration> {
private static final Log LOG = LogFactory private static final Log LOG = LogFactory.getLog(JobSchedulerController.class);
.getLog(JobSchedulerController.class);
private Grid listJobSchedulings;
private Grid cronExpressionGrid;
private Popup cronExpressionInputPopup; private Popup cronExpressionInputPopup;
private Label jobGroup; private Label jobGroup;
private Label jobName; private Label jobName;
private Textbox cronExpressionTextBox; private Textbox cronExpressionTextBox;
private Textbox cronExpressionSeconds; private Textbox cronExpressionSeconds;
private Textbox cronExpressionMinutes; private Textbox cronExpressionMinutes;
private Textbox cronExpressionHours; private Textbox cronExpressionHours;
private Textbox cronExpressionDayOfMonth; private Textbox cronExpressionDayOfMonth;
private Textbox cronExpressionMonth; private Textbox cronExpressionMonth;
private Textbox cronExpressionDayOfWeek; private Textbox cronExpressionDayOfWeek;
private Textbox cronExpressionYear; private Textbox cronExpressionYear;
private IJobSchedulerModel jobSchedulerModel; private IJobSchedulerModel jobSchedulerModel;
@ -92,71 +93,67 @@ public class JobSchedulerController extends
@Override @Override
public void doAfterCompose(Component comp) throws Exception { public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp); super.doAfterCompose(comp);
listJobSchedulings = (Grid) listWindow Grid listJobSchedulings = (Grid) listWindow.getFellowIfAny("listJobSchedulings");
.getFellowIfAny("listJobSchedulings");
listJobSchedulings.getModel(); listJobSchedulings.getModel();
initCronExpressionPopup(); initCronExpressionPopup();
} }
/** /**
* initializes cron expressions for popup * Initializes cron expressions for popup
*/ */
private void initCronExpressionPopup() { private void initCronExpressionPopup() {
cronExpressionTextBox = (Textbox) editWindow cronExpressionTextBox = (Textbox) editWindow.getFellow("cronExpressionTextBox");
.getFellow("cronExpressionTextBox");
cronExpressionInputPopup = (Popup) editWindow cronExpressionInputPopup = (Popup) editWindow.getFellow("cronExpressionInputPopup");
.getFellow("cronExpressionInputPopup");
jobGroup = (Label) cronExpressionInputPopup.getFellow("jobGroup"); jobGroup = (Label) cronExpressionInputPopup.getFellow("jobGroup");
jobName = (Label) cronExpressionInputPopup.getFellow("jobName"); jobName = (Label) cronExpressionInputPopup.getFellow("jobName");
cronExpressionGrid = (Grid) cronExpressionInputPopup Grid cronExpressionGrid = (Grid) cronExpressionInputPopup.getFellow("cronExpressionGrid");
.getFellow("cronExpressionGrid");
cronExpressionSeconds = (Textbox) cronExpressionGrid cronExpressionSeconds = (Textbox) cronExpressionGrid.getFellow("cronExpressionSeconds");
.getFellow("cronExpressionSeconds");
cronExpressionMinutes = (Textbox) cronExpressionGrid cronExpressionMinutes = (Textbox) cronExpressionGrid.getFellow("cronExpressionMinutes");
.getFellow("cronExpressionMinutes");
cronExpressionHours = (Textbox) cronExpressionGrid cronExpressionHours = (Textbox) cronExpressionGrid.getFellow("cronExpressionHours");
.getFellow("cronExpressionHours");
cronExpressionDayOfMonth = (Textbox) cronExpressionGrid cronExpressionDayOfMonth = (Textbox) cronExpressionGrid.getFellow("cronExpressionDayOfMonth");
.getFellow("cronExpressionDayOfMonth");
cronExpressionMonth = (Textbox) cronExpressionGrid cronExpressionMonth = (Textbox) cronExpressionGrid.getFellow("cronExpressionMonth");
.getFellow("cronExpressionMonth");
cronExpressionDayOfWeek = (Textbox) cronExpressionGrid cronExpressionDayOfWeek = (Textbox) cronExpressionGrid.getFellow("cronExpressionDayOfWeek");
.getFellow("cronExpressionDayOfWeek");
cronExpressionYear = (Textbox) cronExpressionGrid cronExpressionYear = (Textbox) cronExpressionGrid.getFellow("cronExpressionYear");
.getFellow("cronExpressionYear");
} }
/** /**
* returns a list of {@link JobSchedulerConfiguration} * Returns a list of {@link JobSchedulerConfiguration}
*/ */
public List<JobSchedulerConfiguration> getJobSchedulerConfigurations() { public List<JobSchedulerConfiguration> getJobSchedulerConfigurations() {
return jobSchedulerModel.getJobSchedulerConfigurations(); return jobSchedulerModel.getJobSchedulerConfigurations();
} }
/** /**
* returns {@link JobSchedulerConfiguration} * Returns {@link JobSchedulerConfiguration}
*/ */
public JobSchedulerConfiguration getJobSchedulerConfiguration() { public JobSchedulerConfiguration getJobSchedulerConfiguration() {
return jobSchedulerModel.getJobSchedulerConfiguration(); return jobSchedulerModel.getJobSchedulerConfiguration();
} }
/** /**
* returns all predefined jobs * Returns all predefined jobs
*/ */
public JobClassNameEnum[] getJobNames() { public JobClassNameEnum[] getJobNames() {
return JobClassNameEnum.values(); return JobClassNameEnum.values();
} }
/** /**
* return list of connectorNames * Return list of connectorNames
*/ */
public List<String> getConnectorNames() { public List<String> getConnectorNames() {
List<Connector> connectors = jobSchedulerModel.getConnectors(); List<Connector> connectors = jobSchedulerModel.getConnectors();
List<String> connectorNames = new ArrayList<String>(); List<String> connectorNames = new ArrayList<>();
for (Connector connector : connectors) { for (Connector connector : connectors) {
connectorNames.add(connector.getName()); connectorNames.add(connector.getName());
} }
@ -164,59 +161,37 @@ public class JobSchedulerController extends
} }
/** /**
* renders job scheduling and returns {@link RowRenderer} * Renders job scheduling and returns {@link RowRenderer}
*/ */
public RowRenderer getJobSchedulingRenderer() { public RowRenderer getJobSchedulingRenderer() {
return new RowRenderer() { return (row, data) -> {
@Override
public void render(Row row, Object data) {
final JobSchedulerConfiguration jobSchedulerConfiguration = (JobSchedulerConfiguration) data; final JobSchedulerConfiguration jobSchedulerConfiguration = (JobSchedulerConfiguration) data;
row.setValue(data); row.setValue(data);
Util.appendLabel(row, jobSchedulerConfiguration.getJobGroup()); Util.appendLabel(row, jobSchedulerConfiguration.getJobGroup());
Util.appendLabel(row, jobSchedulerConfiguration.getJobName()); Util.appendLabel(row, jobSchedulerConfiguration.getJobName());
Util.appendLabel(row, Util.appendLabel(row, jobSchedulerConfiguration.getCronExpression());
jobSchedulerConfiguration.getCronExpression()); Util.appendLabel(row, getNextFireTime(jobSchedulerConfiguration));
Util.appendLabel(row,
getNextFireTime(jobSchedulerConfiguration));
Hbox hbox = new Hbox(); Hbox hbox = new Hbox();
hbox.appendChild(createManualButton(new EventListener() {
@Override hbox.appendChild(createManualButton(event -> {
public void onEvent(Event event) throws Exception {
try { try {
jobSchedulerModel.doManual(jobSchedulerConfiguration); jobSchedulerModel.doManual(jobSchedulerConfiguration);
showSynchronizationInfo(); showSynchronizationInfo();
} catch (ConnectorException e) { } catch (ConnectorException e) {
messagesForUser.showMessage(Level.ERROR, messagesForUser.showMessage(Level.ERROR, e.getMessage());
e.getMessage());
}
} }
})); }));
hbox.appendChild(Util.createEditButton(new EventListener() {
@Override
public void onEvent(Event event) {
goToEditForm(jobSchedulerConfiguration);
}
}));
hbox.appendChild(Util.createRemoveButton(new EventListener() {
@Override
public void onEvent(Event event) {
confirmDelete(jobSchedulerConfiguration);
}
}));
row.appendChild(hbox);
} hbox.appendChild(Util.createEditButton(event -> goToEditForm(jobSchedulerConfiguration)));
hbox.appendChild(Util.createRemoveButton(event -> confirmDelete(jobSchedulerConfiguration)));
row.appendChild(hbox);
}; };
} }
public RowRenderer getSynchronizationInfoRenderer() { public RowRenderer getSynchronizationInfoRenderer() {
return new RowRenderer() { return (row, data) -> {
@Override
public void render(Row row, Object data) {
final SynchronizationInfo synchronizationInfo = (SynchronizationInfo) data; final SynchronizationInfo synchronizationInfo = (SynchronizationInfo) data;
row.setValue(data); row.setValue(data);
@ -233,11 +208,9 @@ public class JobSchedulerController extends
Listbox listbox = new Listbox(); Listbox listbox = new Listbox();
listbox.setModel(new SimpleListModel(synchronizationInfo listbox.setModel(new SimpleListModel(synchronizationInfo.getFailedReasons()));
.getFailedReasons()));
groupbox.appendChild(listbox); groupbox.appendChild(listbox);
} }
}
}; };
} }
@ -248,10 +221,9 @@ public class JobSchedulerController extends
private void showSynchronizationInfo() { private void showSynchronizationInfo() {
Map<String, Object> args = new HashMap<String, Object>(); Map<String, Object> args = new HashMap<>();
Window win = (Window) Executions.createComponents( Window win = (Window) Executions.createComponents("/orders/_synchronizationInfo.zul", null, args);
"/orders/_synchronizationInfo.zul", null, args);
Window syncInfoWin = (Window) win.getFellowIfAny("syncInfoWin"); Window syncInfoWin = (Window) win.getFellowIfAny("syncInfoWin");
@ -263,27 +235,23 @@ public class JobSchedulerController extends
try { try {
win.doModal(); win.doModal();
} catch (SuspendNotAllowedException e) { } catch (SuspendNotAllowedException | InterruptedException e) {
throw new RuntimeException(e);
} catch (InterruptedException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
/** /**
* returns the next fire time for the specified job in * Returns the next fire time for the specified job in {@link JobSchedulerConfiguration}
* {@link JobSchedulerConfiguration}
* *
* @param jobSchedulerConfiguration * @param jobSchedulerConfiguration
* the job scheduler configuration * the job scheduler configuration
*/ */
private String getNextFireTime( private String getNextFireTime(JobSchedulerConfiguration jobSchedulerConfiguration) {
JobSchedulerConfiguration jobSchedulerConfiguration) {
return jobSchedulerModel.getNextFireTime(jobSchedulerConfiguration); return jobSchedulerModel.getNextFireTime(jobSchedulerConfiguration);
} }
/** /**
* creates and returns a button * Creates and returns a button
* *
* @param eventListener * @param eventListener
* Event listener for this button * Event listener for this button
@ -292,6 +260,7 @@ public class JobSchedulerController extends
Button button = new Button(_("Manual")); Button button = new Button(_("Manual"));
button.setTooltiptext(_("Manual")); button.setTooltiptext(_("Manual"));
button.addEventListener(Events.ON_CLICK, eventListener); button.addEventListener(Events.ON_CLICK, eventListener);
return button; return button;
} }
@ -309,14 +278,13 @@ public class JobSchedulerController extends
* @param jobSchedulerConfiguration * @param jobSchedulerConfiguration
* where to read the values * where to read the values
*/ */
private void setupCronExpressionPopup( private void setupCronExpressionPopup(final JobSchedulerConfiguration jobSchedulerConfiguration) {
final JobSchedulerConfiguration jobSchedulerConfiguration) {
if (jobSchedulerConfiguration != null) { if (jobSchedulerConfiguration != null) {
jobGroup.setValue(jobSchedulerConfiguration.getJobGroup()); jobGroup.setValue(jobSchedulerConfiguration.getJobGroup());
jobName.setValue(jobSchedulerConfiguration.getJobName()); jobName.setValue(jobSchedulerConfiguration.getJobName());
String cronExpression = jobSchedulerConfiguration String cronExpression = jobSchedulerConfiguration.getCronExpression();
.getCronExpression();
if (cronExpression == null || cronExpression.isEmpty()) { if (cronExpression == null || cronExpression.isEmpty()) {
return; return;
} }
@ -337,8 +305,7 @@ public class JobSchedulerController extends
} }
/** /**
* sets the <code>cronExpressionTextBox</code> value from the * Sets the <code>cronExpressionTextBox</code> value from the <code>cronExpressionInputPopup</code>
* <code>cronExpressionInputPopup</code>
*/ */
public void updateCronExpression() { public void updateCronExpression() {
String cronExpression = getCronExpressionString(); String cronExpression = getCronExpressionString();
@ -347,9 +314,9 @@ public class JobSchedulerController extends
new CronExpression(cronExpression); new CronExpression(cronExpression);
} catch (ParseException e) { } catch (ParseException e) {
LOG.info("Unable to parse cron expression", e); LOG.info("Unable to parse cron expression", e);
throw new WrongValueException(cronExpressionInputPopup,
_("Unable to parse cron expression") + ":\n" throw new WrongValueException(
+ e.getMessage()); cronExpressionInputPopup, _("Unable to parse cron expression") + ":\n" + e.getMessage());
} }
cronExpressionTextBox.setValue(cronExpression); cronExpressionTextBox.setValue(cronExpression);
cronExpressionInputPopup.close(); cronExpressionInputPopup.close();
@ -371,15 +338,12 @@ public class JobSchedulerController extends
cronExpression += StringUtils.trimToEmpty(cronExpressionDayOfWeek.getValue()); cronExpression += StringUtils.trimToEmpty(cronExpressionDayOfWeek.getValue());
String year = StringUtils.trimToEmpty(cronExpressionYear.getValue()); String year = StringUtils.trimToEmpty(cronExpressionYear.getValue());
if (!year.isEmpty()) {
cronExpression += " " + year;
}
return cronExpression; return !year.isEmpty() ? cronExpression + " " + year : cronExpression;
} }
/** /**
* closes the popup * Closes the popup
*/ */
public void cancelPopup() { public void cancelPopup() {
cronExpressionInputPopup.close(); cronExpressionInputPopup.close();
@ -410,8 +374,7 @@ public class JobSchedulerController extends
protected void save() throws ValidationException { protected void save() throws ValidationException {
jobSchedulerModel.confirmSave(); jobSchedulerModel.confirmSave();
if (jobSchedulerModel.scheduleOrUnscheduleJob()) { if (jobSchedulerModel.scheduleOrUnscheduleJob()) {
messagesForUser.showMessage(Level.INFO, messagesForUser.showMessage(Level.INFO, _("Job is scheduled/unscheduled"));
_("Job is scheduled/unscheduled"));
} }
} }
@ -426,12 +389,10 @@ public class JobSchedulerController extends
} }
@Override @Override
protected void delete(JobSchedulerConfiguration entity) protected void delete(JobSchedulerConfiguration entity) throws InstanceNotFoundException {
throws InstanceNotFoundException {
jobSchedulerModel.remove(entity); jobSchedulerModel.remove(entity);
if (jobSchedulerModel.deleteScheduledJob(entity)) { if (jobSchedulerModel.deleteScheduledJob(entity)) {
messagesForUser.showMessage(Level.INFO, messagesForUser.showMessage(Level.INFO, _("Job is deleted from scheduler"));
_("Job is deleted from scheduler"));
} }
} }

View file

@ -52,7 +52,7 @@ import static org.libreplan.web.I18nHelper._;
* *
* @author Manuel Rego Casasnovas <rego@igalia.com> * @author Manuel Rego Casasnovas <rego@igalia.com>
* @author Miciele Ghiorghis <m.ghiorghis@antoniusziekenhuis.nl> * @author Miciele Ghiorghis <m.ghiorghis@antoniusziekenhuis.nl>
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com> * @author Vova Perebykivskyi <vova@libreplan-enterprise.com>
*/ */
@Service @Service
@Scope(BeanDefinition.SCOPE_PROTOTYPE) @Scope(BeanDefinition.SCOPE_PROTOTYPE)
@ -79,8 +79,6 @@ public class JobSchedulerModel implements IJobSchedulerModel {
@Autowired @Autowired
private IJiraOrderElementSynchronizer jiraOrderElementSynchronizer; private IJiraOrderElementSynchronizer jiraOrderElementSynchronizer;
private List<SynchronizationInfo> synchronizationInfos;
@Qualifier("sendEmailOnTaskAssignedToResource") @Qualifier("sendEmailOnTaskAssignedToResource")
@Autowired @Autowired
private IEmailNotificationJob taskAssignedToResource; private IEmailNotificationJob taskAssignedToResource;
@ -105,6 +103,8 @@ public class JobSchedulerModel implements IJobSchedulerModel {
@Autowired @Autowired
private IEmailNotificationJob timesheetDataMissing; private IEmailNotificationJob timesheetDataMissing;
private List<SynchronizationInfo> synchronizationInfos = new ArrayList<>();
@Override @Override
@Transactional(readOnly = true) @Transactional(readOnly = true)
@ -113,63 +113,77 @@ public class JobSchedulerModel implements IJobSchedulerModel {
} }
@Override @Override
public String getNextFireTime( public String getNextFireTime(JobSchedulerConfiguration jobSchedulerConfiguration) {
JobSchedulerConfiguration jobSchedulerConfiguration) {
return schedulerManager.getNextFireTime(jobSchedulerConfiguration); return schedulerManager.getNextFireTime(jobSchedulerConfiguration);
} }
@Override @Override
public void doManual(JobSchedulerConfiguration jobSchedulerConfiguration) public void doManual(JobSchedulerConfiguration jobSchedulerConfiguration) throws ConnectorException {
throws ConnectorException {
String name = jobSchedulerConfiguration.getJobClassName().getName(); String name = jobSchedulerConfiguration.getJobClassName().getName();
if ( name.equals(JobClassNameEnum.IMPORT_ROSTER_FROM_TIM_JOB.getName()) ) { if ( name.equals(JobClassNameEnum.IMPORT_ROSTER_FROM_TIM_JOB.getName()) ) {
synchronizationInfos = importRosterFromTim.importRosters(); synchronizationInfos = importRosterFromTim.importRosters();
return; return;
} }
if ( name.equals(JobClassNameEnum.EXPORT_TIMESHEET_TO_TIM_JOB.getName()) ) { if ( name.equals(JobClassNameEnum.EXPORT_TIMESHEET_TO_TIM_JOB.getName()) ) {
synchronizationInfos = exportTimesheetsToTim.exportTimesheets(); synchronizationInfos = exportTimesheetsToTim.exportTimesheets();
return; return;
} }
if (name.equals(JobClassNameEnum.SYNC_ORDERELEMENTS_WITH_JIRA_ISSUES_JOB
.getName())) { if ( name.equals(JobClassNameEnum.SYNC_ORDERELEMENTS_WITH_JIRA_ISSUES_JOB.getName()) ) {
synchronizationInfos = jiraOrderElementSynchronizer synchronizationInfos = jiraOrderElementSynchronizer.syncOrderElementsWithJiraIssues();
.syncOrderElementsWithJiraIssues();
return; return;
} }
if ( name.equals(JobClassNameEnum.SEND_EMAIL_TASK_ASSIGNED_TO_RESOURCE.getName()) ) { if ( name.equals(JobClassNameEnum.SEND_EMAIL_TASK_ASSIGNED_TO_RESOURCE.getName()) ) {
synchronizationInfos = new ArrayList<SynchronizationInfo>(); synchronizationInfos = new ArrayList<>();
synchronizationInfos.add(new SynchronizationInfo(_("Task assigned to resource emails"))); synchronizationInfos.add(new SynchronizationInfo(_("Task assigned to resource emails")));
taskAssignedToResource.sendEmail(); taskAssignedToResource.sendEmail();
return; return;
} }
if ( name.equals(JobClassNameEnum.SEND_EMAIL_RESOURCE_REMOVED_FROM_TASK.getName()) ) { if ( name.equals(JobClassNameEnum.SEND_EMAIL_RESOURCE_REMOVED_FROM_TASK.getName()) ) {
synchronizationInfos = new ArrayList<SynchronizationInfo>(); synchronizationInfos = new ArrayList<>();
synchronizationInfos.add(new SynchronizationInfo(_("Resource removed from task"))); synchronizationInfos.add(new SynchronizationInfo(_("Resource removed from task")));
resourceRemovedFromTask.sendEmail(); resourceRemovedFromTask.sendEmail();
return; return;
} }
if ( name.equals(JobClassNameEnum.SEND_EMAIL_MILESTONE_REACHED.getName()) ) { if ( name.equals(JobClassNameEnum.SEND_EMAIL_MILESTONE_REACHED.getName()) ) {
synchronizationInfos = new ArrayList<SynchronizationInfo>(); synchronizationInfos = new ArrayList<>();
synchronizationInfos.add(new SynchronizationInfo(_("Milestone reached"))); synchronizationInfos.add(new SynchronizationInfo(_("Milestone reached")));
milestoneReached.sendEmail(); milestoneReached.sendEmail();
return; return;
} }
if ( name.equals(JobClassNameEnum.SEND_EMAIL_TASK_SHOULD_START.getName()) ) { if ( name.equals(JobClassNameEnum.SEND_EMAIL_TASK_SHOULD_START.getName()) ) {
synchronizationInfos = new ArrayList<SynchronizationInfo>(); synchronizationInfos = new ArrayList<>();
synchronizationInfos.add(new SynchronizationInfo(_("Task should start"))); synchronizationInfos.add(new SynchronizationInfo(_("Task should start")));
taskShouldStart.sendEmail(); taskShouldStart.sendEmail();
return; return;
} }
if ( name.equals(JobClassNameEnum.SEND_EMAIL_TASK_SHOULD_FINISH.getName()) ) { if ( name.equals(JobClassNameEnum.SEND_EMAIL_TASK_SHOULD_FINISH.getName()) ) {
synchronizationInfos = new ArrayList<SynchronizationInfo>(); synchronizationInfos = new ArrayList<>();
synchronizationInfos.add(new SynchronizationInfo(_("Task should finish"))); synchronizationInfos.add(new SynchronizationInfo(_("Task should finish")));
taskShouldFinish.sendEmail(); taskShouldFinish.sendEmail();
return; return;
} }
if ( name.equals(JobClassNameEnum.SEND_EMAIL_TIMESHEET_DATA_MISSING.getName()) ) { if ( name.equals(JobClassNameEnum.SEND_EMAIL_TIMESHEET_DATA_MISSING.getName()) ) {
synchronizationInfos = new ArrayList<SynchronizationInfo>(); synchronizationInfos = new ArrayList<>();
synchronizationInfos.add(new SynchronizationInfo(_("Timesheet data missing"))); synchronizationInfos.add(new SynchronizationInfo(_("Timesheet data missing")));
timesheetDataMissing.sendEmail(); timesheetDataMissing.sendEmail();
return; return;
} }
@ -211,8 +225,7 @@ public class JobSchedulerModel implements IJobSchedulerModel {
@Transactional @Transactional
public void remove(JobSchedulerConfiguration jobSchedulerConfiguration) { public void remove(JobSchedulerConfiguration jobSchedulerConfiguration) {
try { try {
jobSchedulerConfigurationDAO.remove(jobSchedulerConfiguration jobSchedulerConfigurationDAO.remove(jobSchedulerConfiguration.getId());
.getId());
} catch (InstanceNotFoundException e) { } catch (InstanceNotFoundException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -226,8 +239,9 @@ public class JobSchedulerModel implements IJobSchedulerModel {
@Override @Override
public boolean scheduleOrUnscheduleJobs(Connector connector) { public boolean scheduleOrUnscheduleJobs(Connector connector) {
List<JobSchedulerConfiguration> jobSchedulerConfigurations = jobSchedulerConfigurationDAO
.findByConnectorName(connector.getName()); List<JobSchedulerConfiguration> jobSchedulerConfigurations =
jobSchedulerConfigurationDAO.findByConnectorName(connector.getName());
for (JobSchedulerConfiguration jobSchedulerConfiguration : jobSchedulerConfigurations) { for (JobSchedulerConfiguration jobSchedulerConfiguration : jobSchedulerConfigurations) {
try { try {
@ -250,8 +264,7 @@ public class JobSchedulerModel implements IJobSchedulerModel {
} }
@Override @Override
public boolean deleteScheduledJob( public boolean deleteScheduledJob(JobSchedulerConfiguration jobSchedulerConfiguration) {
JobSchedulerConfiguration jobSchedulerConfiguration) {
try { try {
schedulerManager.deleteJob(jobSchedulerConfiguration); schedulerManager.deleteJob(jobSchedulerConfiguration);
} catch (SchedulerException e) { } catch (SchedulerException e) {

View file

@ -40,9 +40,7 @@ import java.util.List;
/** /**
* Model for operations related to {@link EmailNotification}. * Model for operations related to {@link EmailNotification}.
* *
* Created by * @author Created by Vova Perebykivskiy <vova@libreplan-enterprise.com> on 21.10.2015.
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 21.10.15.
*/ */
@Service @Service

View file

@ -38,22 +38,20 @@ import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.Executions; import org.zkoss.zk.ui.Executions;
import org.zkoss.zk.ui.util.GenericForwardComposer; import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Listitem;
import org.zkoss.zul.ListitemRenderer; import org.zkoss.zul.ListitemRenderer;
import org.zkoss.zul.Textbox; import org.zkoss.zul.Textbox;
import java.util.List; import java.util.List;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList; import java.util.LinkedList;
import static org.libreplan.web.I18nHelper._; import static org.libreplan.web.I18nHelper._;
/** /**
* Created by * Controller for page Edit email templates.
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com> *
* on 25.09.15. * @author Created by Vova Perebykivskiy <vova@libreplan-enterprise.com> on 25.09.2015.
*/ */
public class EmailTemplateController extends GenericForwardComposer{ public class EmailTemplateController extends GenericForwardComposer{
@ -73,25 +71,25 @@ public class EmailTemplateController extends GenericForwardComposer{
private Textbox subjectTextbox; private Textbox subjectTextbox;
public static ListitemRenderer languagesRenderer = new ListitemRenderer() { public static ListitemRenderer languagesRenderer = (item, data) -> {
@Override
public void render(Listitem item, Object data) throws Exception {
Language language = (Language) data; Language language = (Language) data;
String displayName = language.getDisplayName(); String displayName = language.getDisplayName();
item.setLabel(displayName); item.setLabel(displayName);
}
}; };
@Override @Override
public void doAfterCompose(Component comp) throws Exception { public void doAfterCompose(Component comp) throws Exception {
super.doAfterCompose(comp); super.doAfterCompose(comp);
// TODO resolve deprecated
comp.setVariable("emailTemplateController", this, true); comp.setVariable("emailTemplateController", this, true);
messages = new MessagesForUser(messagesContainer); messages = new MessagesForUser(messagesContainer);
// Set default template and language for user // Set default template and language for user.
// And content and subject for that language & template // And content and subject for that language & template.
setUser(); setUser();
setSelectedLanguage(user.getApplicationLanguage()); setSelectedLanguage(Language.ENGLISH_LANGUAGE);
getContentDataBySelectedLanguage(); getContentDataBySelectedLanguage();
getSubjectDataBySelectedLanguage(); getSubjectDataBySelectedLanguage();
@ -104,11 +102,10 @@ public class EmailTemplateController extends GenericForwardComposer{
emailTemplateModel.confirmSave(); emailTemplateModel.confirmSave();
messages.clearMessages(); messages.clearMessages();
messages.showMessage(Level.INFO, _("E-mail template saved")); messages.showMessage(Level.INFO, _("E-mail template saved"));
return true; return true;
} catch (ValidationException e) { } catch (ValidationException e) {
messages.showInvalidValues(e); messages.showInvalidValues(e);
} catch (InstanceNotFoundException e) {
e.printStackTrace();
} }
return false; return false;
} }
@ -132,10 +129,8 @@ public class EmailTemplateController extends GenericForwardComposer{
return languagesRenderer; return languagesRenderer;
} }
public List<Language> getLanguages() { public List<Language> getLanguages() {
List<Language> languages = new LinkedList<Language>(Arrays.asList(Language.values())); List<Language> languages = new LinkedList<>(Arrays.asList(Language.values()));
Collections.sort(languages, new Comparator<Language>() { Collections.sort(languages, (o1, o2) -> {
@Override
public int compare(Language o1, Language o2) {
if ( o1.equals(Language.BROWSER_LANGUAGE) ) { if ( o1.equals(Language.BROWSER_LANGUAGE) ) {
return -1; return -1;
} }
@ -143,9 +138,9 @@ public class EmailTemplateController extends GenericForwardComposer{
return 1; return 1;
} }
return o1.getDisplayName().compareTo(o2.getDisplayName()); return o1.getDisplayName().compareTo(o2.getDisplayName());
}
}); });
languages.remove(0); languages.remove(0);
return languages; return languages;
} }
@ -161,13 +156,10 @@ public class EmailTemplateController extends GenericForwardComposer{
} }
public ListitemRenderer getEmailTemplateEnumRenderer() { public ListitemRenderer getEmailTemplateEnumRenderer() {
return new ListitemRenderer() { return (item, data) -> {
@Override
public void render(Listitem item, Object data) throws Exception {
EmailTemplateEnum template = (EmailTemplateEnum) data; EmailTemplateEnum template = (EmailTemplateEnum) data;
item.setLabel(_(template.getTemplateType())); item.setLabel(_(template.getTemplateType()));
item.setValue(template); item.setValue(template);
}
}; };
} }
public List<EmailTemplateEnum> getEmailTemplateEnum() { public List<EmailTemplateEnum> getEmailTemplateEnum() {
@ -184,17 +176,17 @@ public class EmailTemplateController extends GenericForwardComposer{
} }
private void getContentDataBySelectedLanguage() { private void getContentDataBySelectedLanguage() {
contentsTextbox.setValue(emailTemplateModel.getContentBySelectedLanguage(getSelectedLanguage().ordinal(), getSelectedEmailTemplateEnum().ordinal())); contentsTextbox.setValue(emailTemplateModel.getContent(getSelectedLanguage(), getSelectedEmailTemplateEnum()));
} }
private void getContentDataBySelectedTemplate() { private void getContentDataBySelectedTemplate() {
contentsTextbox.setValue( emailTemplateModel.getContentBySelectedTemplate(getSelectedEmailTemplateEnum().ordinal(), getSelectedLanguage().ordinal()) ); contentsTextbox.setValue(emailTemplateModel.getContent(getSelectedLanguage(), getSelectedEmailTemplateEnum()));
} }
private void getSubjectDataBySelectedLanguage() { private void getSubjectDataBySelectedLanguage() {
subjectTextbox.setValue(emailTemplateModel.getSubjectBySelectedLanguage(getSelectedLanguage().ordinal(), getSelectedEmailTemplateEnum().ordinal())); subjectTextbox.setValue(emailTemplateModel.getSubject(getSelectedLanguage(), getSelectedEmailTemplateEnum()));
} }
private void getSubjectDataBySelectedTemplate() { private void getSubjectDataBySelectedTemplate() {
subjectTextbox.setValue( emailTemplateModel.getSubjectBySelectedTemplate(getSelectedEmailTemplateEnum().ordinal(), getSelectedLanguage().ordinal()) ); subjectTextbox.setValue(emailTemplateModel.getSubject(getSelectedLanguage(), getSelectedEmailTemplateEnum()));
} }
@Transactional @Transactional

View file

@ -36,9 +36,7 @@ import java.util.List;
/** /**
* Model for operations related to {@link EmailTemplate}. * Model for operations related to {@link EmailTemplate}.
* *
* Created by * @author Created by Vova Perebykivskiy <vova@libreplan-enterprise.com> on 25.09.2015.
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 25.09.15.
*/ */
@Service @Service
@Scope(BeanDefinition.SCOPE_PROTOTYPE) @Scope(BeanDefinition.SCOPE_PROTOTYPE)
@ -52,18 +50,27 @@ public class EmailTemplateModel implements IEmailTemplateModel {
@Override @Override
@Transactional @Transactional
public void confirmSave() throws InstanceNotFoundException { public void confirmSave() {
/* If current EmailTemplate entity (id) is existing in DB than it needs to be updated. /*
* If current EmailTemplate entity (id) is existing in DB than it needs to be updated.
* Else current EmailTemplate entity (id) is creating and getting new values from form. * Else current EmailTemplate entity (id) is creating and getting new values from form.
*/ */
List<EmailTemplate> emailTemplates = emailTemplateDAO.getAll(); List<EmailTemplate> emailTemplates = emailTemplateDAO.getAll();
EmailTemplate emailTemplateFromDatabase = null; EmailTemplate emailTemplateFromDatabase = null;
boolean condition;
for (int i = 0; i < emailTemplates.size(); i++) { for (EmailTemplate emailTemplate1 : emailTemplates) {
if ( emailTemplate.getLanguage() == emailTemplates.get(i).getLanguage() &&
emailTemplate.getType() == emailTemplates.get(i).getType() ) { condition = emailTemplate.getLanguage() == emailTemplate1.getLanguage() &&
emailTemplateFromDatabase = emailTemplateDAO.find(emailTemplates.get(i).getId()); emailTemplate.getType() == emailTemplate1.getType();
if ( condition ) {
try {
emailTemplateFromDatabase = emailTemplateDAO.find(emailTemplate1.getId());
} catch (InstanceNotFoundException e) {
e.printStackTrace();
}
} }
} }
@ -89,13 +96,11 @@ public class EmailTemplateModel implements IEmailTemplateModel {
} }
@Override @Override
@Transactional
public List<EmailTemplate> getAll() { public List<EmailTemplate> getAll() {
return emailTemplateDAO.getAll(); return emailTemplateDAO.getAll();
} }
@Override @Override
@Transactional
public Language getLanguage() { public Language getLanguage() {
return this.emailTemplate.getLanguage(); return this.emailTemplate.getLanguage();
} }
@ -113,46 +118,37 @@ public class EmailTemplateModel implements IEmailTemplateModel {
this.emailTemplate.setType(emailTemplateEnum); this.emailTemplate.setType(emailTemplateEnum);
} }
@Override
public String getContent() {
return this.emailTemplate.getContent();
}
@Override @Override
public void setContent(String content) { public void setContent(String content) {
this.emailTemplate.setContent(content); this.emailTemplate.setContent(content);
} }
@Override
public String getSubject() {
return this.emailTemplate.getSubject();
}
@Override @Override
public void setSubject(String subject) { public void setSubject(String subject) {
this.emailTemplate.setSubject(subject); this.emailTemplate.setSubject(subject);
} }
@Override @Override
@Transactional public String getContent(Language language, EmailTemplateEnum type) {
public String getContentBySelectedLanguage(int languageOrdinal, int emailTemplateTypeOrdinal) { EmailTemplate template = getEmailTemplateByTypeAndLanguage(type, language);
return emailTemplateDAO.getContentBySelectedLanguage(languageOrdinal, emailTemplateTypeOrdinal);
return template != null ? template.getContent() : "";
} }
@Override @Override
@Transactional public String getSubject(Language language, EmailTemplateEnum type) {
public String getContentBySelectedTemplate(int emailTemplateTypeOrdinal, int languageOrdinal) { EmailTemplate template = getEmailTemplateByTypeAndLanguage(type, language);
return emailTemplateDAO.getContentBySelectedTemplate(emailTemplateTypeOrdinal, languageOrdinal);
return template != null ? template.getSubject() : "";
}
public EmailTemplate getEmailTemplateByTypeAndLanguage(EmailTemplateEnum type, Language language) {
return emailTemplateDAO.findByTypeAndLanguage(type, language);
} }
@Override @Override
@Transactional public void delete() {
public String getSubjectBySelectedLanguage(int languageOrdinal, int emailTemplateTypeOrdinal) { emailTemplateDAO.delete(this.emailTemplate);
return emailTemplateDAO.getSubjectBySelectedLanguage(languageOrdinal, emailTemplateTypeOrdinal);
}
@Override
@Transactional
public String getSubjectBySelectedTemplate(int emailTemplateTypeOrdinal, int languageOrdinal) {
return emailTemplateDAO.getSubjectBySelectedTemplate(emailTemplateTypeOrdinal, languageOrdinal);
} }
} }

View file

@ -31,25 +31,30 @@ import java.util.List;
/** /**
* Contract for {@link EmailNotification} * Contract for {@link EmailNotification}
* *
* Created by * @author Created by Vova Perebykivskiy <vova@libreplan-enterprise.com> on 21.10.2015.
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 21.10.15.
*/ */
public interface IEmailNotificationModel { public interface IEmailNotificationModel {
void confirmSave() throws ValidationException; void confirmSave() throws ValidationException;
List<EmailNotification> getAll(); List<EmailNotification> getAll();
List<EmailNotification> getAllByType(EmailTemplateEnum enumeration); List<EmailNotification> getAllByType(EmailTemplateEnum enumeration);
boolean deleteAll(); boolean deleteAll();
boolean deleteAllByType(EmailTemplateEnum enumeration); boolean deleteAllByType(EmailTemplateEnum enumeration);
boolean deleteById(EmailNotification notification); boolean deleteById(EmailNotification notification);
void setType(EmailTemplateEnum type); void setType(EmailTemplateEnum type);
void setUpdated(Date date); void setUpdated(Date date);
void setResource(Resource resource); void setResource(Resource resource);
void setTask(TaskElement task); void setTask(TaskElement task);
void setProject(TaskElement project); void setProject(TaskElement project);
EmailNotification getEmailNotification(); EmailNotification getEmailNotification();

View file

@ -19,8 +19,6 @@
package org.libreplan.web.email; package org.libreplan.web.email;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.common.exceptions.ValidationException;
import org.libreplan.business.email.entities.EmailTemplate; import org.libreplan.business.email.entities.EmailTemplate;
import org.libreplan.business.settings.entities.Language; import org.libreplan.business.settings.entities.Language;
import org.libreplan.business.email.entities.EmailTemplateEnum; import org.libreplan.business.email.entities.EmailTemplateEnum;
@ -30,31 +28,31 @@ import java.util.List;
/** /**
* Contract for {@link EmailTemplate} * Contract for {@link EmailTemplate}
* *
* Created by * @author Created by Vova Perebykivskyi <vova@libreplan-enterprise.com> on 28.09.2015.
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com>
* on 28.09.2015.
*/ */
public interface IEmailTemplateModel { public interface IEmailTemplateModel {
void confirmSave() throws ValidationException, InstanceNotFoundException; void confirmSave();
List<EmailTemplate> getAll(); List<EmailTemplate> getAll();
String getContentBySelectedLanguage(int languageOrdinal, int emailTemplateTypeOrdinal); String getContent(Language language, EmailTemplateEnum emailTemplateEnum);
String getContentBySelectedTemplate(int emailTemplateTypeOrdinal, int languageOrdinal);
String getSubjectBySelectedLanguage(int languageOrdinal, int emailTemplateTypeOrdinal); String getSubject(Language language, EmailTemplateEnum emailTemplateEnum);
String getSubjectBySelectedTemplate(int emailTemplateTypeOrdinal, int languageOrdinal);
String getContent();
void setContent(String content); void setContent(String content);
Language getLanguage(); Language getLanguage();
void setLanguage(Language language); void setLanguage(Language language);
EmailTemplateEnum getEmailTemplateEnum(); EmailTemplateEnum getEmailTemplateEnum();
void setEmailTemplateEnum(EmailTemplateEnum emailTemplateEnum); void setEmailTemplateEnum(EmailTemplateEnum emailTemplateEnum);
String getSubject();
void setSubject(String subject); void setSubject(String subject);
EmailTemplate getEmailTemplateByTypeAndLanguage(EmailTemplateEnum emailTemplateEnum, Language language);
void delete();
} }

View file

@ -52,7 +52,7 @@ import org.springframework.transaction.annotation.Transactional;
/** /**
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com> * @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com> * @author Vova Perebykivskyi <vova@libreplan-enterprise.com>
*/ */
@Service @Service
@Scope(BeanDefinition.SCOPE_PROTOTYPE) @Scope(BeanDefinition.SCOPE_PROTOTYPE)
@ -116,15 +116,11 @@ public class AssignedTaskQualityFormsToOrderElementModel implements IAssignedTas
@Override @Override
public List<QualityForm> getNotAssignedQualityForms() { public List<QualityForm> getNotAssignedQualityForms() {
List<QualityForm> result = new ArrayList<QualityForm>(); return orderElement != null ? getListNotAssignedQualityForms() : new ArrayList<>();
if ( orderElement != null ) {
return getListNotAssignedQualityForms();
}
return result;
} }
private List<QualityForm> getListNotAssignedQualityForms() { private List<QualityForm> getListNotAssignedQualityForms() {
List<QualityForm> result = new ArrayList<QualityForm>(); List<QualityForm> result = new ArrayList<>();
for (QualityForm qualityForm : orderModel.getQualityForms()) { for (QualityForm qualityForm : orderModel.getQualityForms()) {
if ( !isAssigned(qualityForm) ) { if ( !isAssigned(qualityForm) ) {
result.add(qualityForm); result.add(qualityForm);
@ -135,7 +131,7 @@ public class AssignedTaskQualityFormsToOrderElementModel implements IAssignedTas
@Override @Override
public List<QualityForm> getAssignedQualityForms() { public List<QualityForm> getAssignedQualityForms() {
List<QualityForm> result = new ArrayList<QualityForm>(); List<QualityForm> result = new ArrayList<>();
for (QualityForm qualityForm : qualityFormDAO.getAll()) { for (QualityForm qualityForm : qualityFormDAO.getAll()) {
if ( isAssigned(qualityForm) ) { if ( isAssigned(qualityForm) ) {
result.add(qualityForm); result.add(qualityForm);
@ -146,7 +142,7 @@ public class AssignedTaskQualityFormsToOrderElementModel implements IAssignedTas
@Override @Override
public List<TaskQualityForm> getTaskQualityForms() { public List<TaskQualityForm> getTaskQualityForms() {
List<TaskQualityForm> result = new ArrayList<TaskQualityForm>(); List<TaskQualityForm> result = new ArrayList<>();
if ( orderElement != null ) { if ( orderElement != null ) {
result.addAll(orderElement.getTaskQualityForms()); result.addAll(orderElement.getTaskQualityForms());
} }
@ -176,8 +172,8 @@ public class AssignedTaskQualityFormsToOrderElementModel implements IAssignedTas
@Override @Override
public boolean isAssigned(QualityForm qualityForm) { public boolean isAssigned(QualityForm qualityForm) {
// orderDAO used for gathered data to be sent to LibrePlan server // orderDAO used for gathered data to be sent to LibrePlan server.
// In general case orderElement will be not null and only that part of code will be triggered // In general case orderElement will be not null and only that part of code will be triggered.
if ( orderElement != null ) { if ( orderElement != null ) {
for (TaskQualityForm taskQualityForm : orderElement.getTaskQualityForms()) { for (TaskQualityForm taskQualityForm : orderElement.getTaskQualityForms()) {
@ -203,37 +199,27 @@ public class AssignedTaskQualityFormsToOrderElementModel implements IAssignedTas
} }
public boolean isDisabledPassedItem(TaskQualityForm taskQualityForm, TaskQualityFormItem item) { public boolean isDisabledPassedItem(TaskQualityForm taskQualityForm, TaskQualityFormItem item) {
if ( (taskQualityForm == null) || ((item == null)) ) { return (taskQualityForm == null) ||
return true; (item == null) ||
} !taskQualityForm.isByItems() && !(item.getPassed() ||
if ( !taskQualityForm.isByItems() ) { taskQualityForm.isPassedPreviousItem(item));
return (!(item.getPassed() || taskQualityForm.isPassedPreviousItem(item)));
}
return false;
} }
public boolean isDisabledDateItem(TaskQualityForm taskQualityForm, TaskQualityFormItem item) { public boolean isDisabledDateItem(TaskQualityForm taskQualityForm, TaskQualityFormItem item) {
if ( (taskQualityForm == null) || ((item == null)) ) { return (taskQualityForm == null) || (item == null) || !taskQualityForm.isByItems() && !item.getPassed();
return true;
}
return (!taskQualityForm.isByItems() && (!item.getPassed()));
} }
public boolean isCorrectConsecutiveDate(TaskQualityForm taskQualityForm, TaskQualityFormItem item) { public boolean isCorrectConsecutiveDate(TaskQualityForm taskQualityForm, TaskQualityFormItem item) {
if ( (taskQualityForm == null) || ((item == null)) ) { return (taskQualityForm == null) ||
return true; (item == null) ||
} taskQualityForm.isByItems() ||
if ( taskQualityForm.isByItems() ) { taskQualityForm.isCorrectConsecutiveDate(item);
return true;
}
return (taskQualityForm.isCorrectConsecutiveDate(item));
} }
public void updatePassedTaskQualityFormItems(TaskQualityForm taskQualityForm) { public void updatePassedTaskQualityFormItems(TaskQualityForm taskQualityForm) {
if (taskQualityForm != null) { if (taskQualityForm != null) {
Integer position = getFirstNotPassedPosition(taskQualityForm); Integer position = getFirstNotPassedPosition(taskQualityForm);
List<TaskQualityFormItem> items = taskQualityForm List<TaskQualityFormItem> items = taskQualityForm.getTaskQualityFormItems();
.getTaskQualityFormItems();
for (int i = position; i < items.size(); i++) { for (int i = position; i < items.size(); i++) {
items.get(i).setPassed(false); items.get(i).setPassed(false);
items.get(i).setDate(null); items.get(i).setDate(null);
@ -243,8 +229,7 @@ public class AssignedTaskQualityFormsToOrderElementModel implements IAssignedTas
private Integer getFirstNotPassedPosition(TaskQualityForm taskQualityForm) { private Integer getFirstNotPassedPosition(TaskQualityForm taskQualityForm) {
Integer position = 0; Integer position = 0;
for (TaskQualityFormItem item : taskQualityForm for (TaskQualityFormItem item : taskQualityForm.getTaskQualityFormItems()) {
.getTaskQualityFormItems()) {
if (!item.getPassed()) { if (!item.getPassed()) {
return position; return position;
} }
@ -254,12 +239,10 @@ public class AssignedTaskQualityFormsToOrderElementModel implements IAssignedTas
} }
// Operation to confirm and validate // Operation to confirm and validate
@Override @Override
public void validate() { public void validate() {
if (getOrderElement() != null) { if (getOrderElement() != null) {
for (TaskQualityForm taskQualityForm : orderElement for (TaskQualityForm taskQualityForm : orderElement.getTaskQualityForms()) {
.getTaskQualityForms()) {
validateTaskQualityForm(taskQualityForm); validateTaskQualityForm(taskQualityForm);
} }
} }
@ -270,19 +253,15 @@ public class AssignedTaskQualityFormsToOrderElementModel implements IAssignedTas
} }
private void validateTaskQualityFormItems(TaskQualityForm taskQualityForm) { private void validateTaskQualityFormItems(TaskQualityForm taskQualityForm) {
for (TaskQualityFormItem item : taskQualityForm for (TaskQualityFormItem item : taskQualityForm.getTaskQualityFormItems()) {
.getTaskQualityFormItems()) {
if ((!taskQualityForm.isByItems()) if ( (!taskQualityForm.isByItems()) && (!taskQualityForm.isCorrectConsecutivePassed(item)) ) {
&& (!taskQualityForm.isCorrectConsecutivePassed(item))) { throw new ValidationException(invalidValue(
throw new ValidationException(
invalidValue(
_("cannot be checked until the previous item is checked before"), _("cannot be checked until the previous item is checked before"),
"passed", item.getName(), taskQualityForm)); "passed", item.getName(), taskQualityForm));
} }
if ((!taskQualityForm.isByItems()) if ( (!taskQualityForm.isByItems()) && (!taskQualityForm.isCorrectConsecutiveDate(item)) ) {
&& (!taskQualityForm.isCorrectConsecutiveDate(item))) {
throw new ValidationException(invalidValue( throw new ValidationException(invalidValue(
_("must be after the previous date"), _("must be after the previous date"),
"date", item.getName(), taskQualityForm)); "date", item.getName(), taskQualityForm));
@ -299,8 +278,7 @@ public class AssignedTaskQualityFormsToOrderElementModel implements IAssignedTas
@Override @Override
@Transactional(readOnly = true) @Transactional(readOnly = true)
public void addAdvanceAssignmentIfNeeded(TaskQualityForm taskQualityForm) public void addAdvanceAssignmentIfNeeded(TaskQualityForm taskQualityForm)
throws DuplicateValueTrueReportGlobalAdvanceException, throws DuplicateValueTrueReportGlobalAdvanceException, DuplicateAdvanceAssignmentForOrderElementException {
DuplicateAdvanceAssignmentForOrderElementException {
AdvanceType advanceType = taskQualityForm.getQualityForm().getAdvanceType(); AdvanceType advanceType = taskQualityForm.getQualityForm().getAdvanceType();
advanceTypeDAO.reattach(advanceType); advanceTypeDAO.reattach(advanceType);
@ -340,8 +318,7 @@ public class AssignedTaskQualityFormsToOrderElementModel implements IAssignedTas
} }
private void showMessageDeleteSpread() throws ValidationException { private void showMessageDeleteSpread() throws ValidationException {
throw new ValidationException( throw new ValidationException(_("Quality form cannot be removed as it is spreading progress"));
_("Quality form cannot be removed as it is spreading progress"));
} }
@Override @Override

View file

@ -33,33 +33,31 @@ import org.libreplan.business.qualityforms.entities.TaskQualityFormItem;
/** /**
* @author Susana Montes Pedreira <smontes@wirelessgalicia.com> * @author Susana Montes Pedreira <smontes@wirelessgalicia.com>
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com> * @author Vova Perebykivskyi <vova@libreplan-enterprise.com>
*/ */
public interface IAssignedTaskQualityFormsToOrderElementModel { public interface IAssignedTaskQualityFormsToOrderElementModel {
/** /**
* Assigns {@link TaskQualityForm} to {@link OrderElement} * Assigns {@link TaskQualityForm} to {@link OrderElement}.
* @param @ QualityForm} * @param @ QualityForm}
*/ */
void assignTaskQualityForm(QualityForm qualityForm); void assignTaskQualityForm(QualityForm qualityForm);
/** /**
* Delete {@link TaskQualityForm} * Delete {@link TaskQualityForm}.
* @param taskQualityForm * @param taskQualityForm
*/ */
void deleteTaskQualityForm(TaskQualityForm taskQualityForm); void deleteTaskQualityForm(TaskQualityForm taskQualityForm);
/** /**
* Gets all {@link TaskQualityForm} assigned to the current * Gets all {@link TaskQualityForm} assigned to the current {@link OrderElement}.
* {@link OrderElement} * @return {@link List<TaskQualityForm>}
* @return
*/ */
List<TaskQualityForm> getTaskQualityForms(); List<TaskQualityForm> getTaskQualityForms();
/** /**
* Returns all the unallocated {@link QualityForm} to the current * Returns all the unallocated {@link QualityForm} to the current {@link OrderElement}.
* {@link OrderElement} * @return {@link List<QualityForm>}
* @return
*/ */
List<QualityForm> getNotAssignedQualityForms(); List<QualityForm> getNotAssignedQualityForms();
@ -69,22 +67,20 @@ public interface IAssignedTaskQualityFormsToOrderElementModel {
List<QualityForm> getAssignedQualityForms(); List<QualityForm> getAssignedQualityForms();
/** /**
* Returns {@link OrderElement} * @return {@link OrderElement}
* @return
*/ */
OrderElement getOrderElement(); OrderElement getOrderElement();
void init(OrderElement orderElement); void init(OrderElement orderElement);
/** /**
* Check whether {@link QualityForm} has been already assigned to * Check whether {@link QualityForm} has been already assigned to {@link OrderElement} or not.
* {@link OrderElement} or not
* @param qualityForm * @param qualityForm
*/ */
boolean isAssigned(QualityForm qualityForm); boolean isAssigned(QualityForm qualityForm);
/** /**
* Set {@link OrderElement} * Set {@link OrderElement}.
* @param orderElement * @param orderElement
*/ */
void setOrderElement(OrderElement orderElement); void setOrderElement(OrderElement orderElement);
@ -95,47 +91,36 @@ public interface IAssignedTaskQualityFormsToOrderElementModel {
void setOrderModel(IOrderModel orderModel); void setOrderModel(IOrderModel orderModel);
/** /**
* Update the date and the property passed of all the * Update the date and the property passed of all the {@link TaskQualityFormItem} of the {@link TaskQualityForm}.
* {@link TaskQualityFormItem} of the {@ TaskQualityForm}
* @param taskQualityForm * @param taskQualityForm
*/ */
void updatePassedTaskQualityFormItems(TaskQualityForm taskQualityForm); void updatePassedTaskQualityFormItems(TaskQualityForm taskQualityForm);
/** /**
* Check whether {@link QualityFormItem} the property passed must be * Check whether {@link QualityFormItem} the property passed must be disabled.
* disabled * @param taskQualityForm, item
* @param taskQualityForm
* ,item
*/ */
boolean isDisabledPassedItem(TaskQualityForm taskQualityForm, boolean isDisabledPassedItem(TaskQualityForm taskQualityForm, TaskQualityFormItem item);
TaskQualityFormItem item);
/** /**
* Check whether {@link QualityFormItem} date must be disabled * Check whether {@link QualityFormItem} date must be disabled.
* @param taskQualityForm * @param taskQualityForm, item
* ,item
*/ */
boolean isDisabledDateItem(TaskQualityForm taskQualityForm, boolean isDisabledDateItem(TaskQualityForm taskQualityForm, TaskQualityFormItem item);
TaskQualityFormItem item);
/** /**
* Check whether {@link QualityFormItem} date is consecutive * Check whether {@link QualityFormItem} date is consecutive.
* @param taskQualityForm * @param taskQualityForm, item
* ,item
*/ */
boolean isCorrectConsecutiveDate(TaskQualityForm taskQualityForm, boolean isCorrectConsecutiveDate(TaskQualityForm taskQualityForm, TaskQualityFormItem item);
TaskQualityFormItem item);
/** /**
* Check whether all {@link QualityForm} and its {@link QualityFormItem} are * Check whether all {@link QualityForm} and its {@link QualityFormItem} are valid.
* valid.
* @param
*/ */
void validate(); void validate();
void addAdvanceAssignmentIfNeeded(TaskQualityForm taskQualityForm) void addAdvanceAssignmentIfNeeded(TaskQualityForm taskQualityForm)
throws DuplicateValueTrueReportGlobalAdvanceException, throws DuplicateValueTrueReportGlobalAdvanceException, DuplicateAdvanceAssignmentForOrderElementException;
DuplicateAdvanceAssignmentForOrderElementException;
void removeAdvanceAssignmentIfNeeded(TaskQualityForm taskQualityForm); void removeAdvanceAssignmentIfNeeded(TaskQualityForm taskQualityForm);

View file

@ -48,7 +48,6 @@ import org.libreplan.web.common.components.AllocationSelector;
import org.libreplan.web.common.components.NewAllocationSelector; import org.libreplan.web.common.components.NewAllocationSelector;
import org.libreplan.web.common.components.NewAllocationSelectorCombo; import org.libreplan.web.common.components.NewAllocationSelectorCombo;
import org.libreplan.web.common.components.ResourceAllocationBehaviour; import org.libreplan.web.common.components.ResourceAllocationBehaviour;
import org.libreplan.web.planner.allocation.TaskInformation.ITotalHoursCalculationListener;
import org.libreplan.web.planner.order.PlanningStateCreator.PlanningState; import org.libreplan.web.planner.order.PlanningStateCreator.PlanningState;
import org.libreplan.web.planner.taskedition.EditTaskController; import org.libreplan.web.planner.taskedition.EditTaskController;
import org.libreplan.web.planner.taskedition.TaskPropertiesController; import org.libreplan.web.planner.taskedition.TaskPropertiesController;
@ -61,7 +60,6 @@ import org.zkoss.ganttz.timetracker.OnColumnsRowRenderer;
import org.zkoss.zk.ui.Component; import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.WrongValueException; import org.zkoss.zk.ui.WrongValueException;
import org.zkoss.zk.ui.event.Event; import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events; import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.util.GenericForwardComposer; import org.zkoss.zk.ui.util.GenericForwardComposer;
import org.zkoss.zul.Button; import org.zkoss.zul.Button;
@ -88,7 +86,7 @@ import org.zkoss.zul.Window;
* @author Manuel Rego Casasnovas <mrego@igalia.com> * @author Manuel Rego Casasnovas <mrego@igalia.com>
* @author Diego Pino Garcia <dpino@igalia.com> * @author Diego Pino Garcia <dpino@igalia.com>
* @author Javier Moran Rua <jmoran@igalia.com> * @author Javier Moran Rua <jmoran@igalia.com>
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com> * @author Vova Perebykivskyi <vova@libreplan-enterprise.com>
*/ */
@org.springframework.stereotype.Component("resourceAllocationController") @org.springframework.stereotype.Component("resourceAllocationController")
@Scope(BeanDefinition.SCOPE_PROTOTYPE) @Scope(BeanDefinition.SCOPE_PROTOTYPE)
@ -117,10 +115,13 @@ public class ResourceAllocationController extends GenericForwardComposer {
private Decimalbox allResourcesPerDay; private Decimalbox allResourcesPerDay;
private Label allOriginalEffort; private Label allOriginalEffort;
private Label allTotalEffort; private Label allTotalEffort;
private Label allConsolidatedEffort; private Label allConsolidatedEffort;
private Label allTotalResourcesPerDay; private Label allTotalResourcesPerDay;
private Label allConsolidatedResourcesPerDay; private Label allConsolidatedResourcesPerDay;
private Button applyButton; private Button applyButton;
@ -172,12 +173,15 @@ public class ResourceAllocationController extends GenericForwardComposer {
} }
/** /**
* Shows Resource Allocation window * Shows Resource Allocation window.
* @param context
* @param task * @param task
* @param ganttTask
* @param planningState * @param planningState
* @param messagesForUser
*/ */
public void init(IContextWithPlannerTask<TaskElement> context, Task task, PlanningState planningState, public void init(IContextWithPlannerTask<TaskElement> context,
Task task,
PlanningState planningState,
IMessagesForUser messagesForUser) { IMessagesForUser messagesForUser) {
try { try {
if ( formBinder != null ) { if ( formBinder != null ) {
@ -240,13 +244,7 @@ public class ResourceAllocationController extends GenericForwardComposer {
private void initializeTaskInformationComponent() { private void initializeTaskInformationComponent() {
taskInformation.initializeGridTaskRows(resourceAllocationModel.getHoursAggregatedByCriterions()); taskInformation.initializeGridTaskRows(resourceAllocationModel.getHoursAggregatedByCriterions());
formBinder.setRecommendedAllocation(taskInformation.getBtnRecommendedAllocation()); formBinder.setRecommendedAllocation(taskInformation.getBtnRecommendedAllocation());
taskInformation.onCalculateTotalHours(new ITotalHoursCalculationListener() { taskInformation.onCalculateTotalHours(() -> resourceAllocationModel.getOrderHours());
@Override
public Integer getTotalHours() {
return resourceAllocationModel.getOrderHours();
}
});
} }
private void initializeAllocationConfigurationComponent() { private void initializeAllocationConfigurationComponent() {
@ -261,18 +259,18 @@ public class ResourceAllocationController extends GenericForwardComposer {
return new Label(data.getCriterionsJoinedByComma()); return new Label(data.getCriterionsJoinedByComma());
} }
}, },
RESOURCE_TYPE{
RESOURCE_TYPE{
@Override @Override
public Component cell(HoursRendererColumn column, AggregatedHoursGroup data) { public Component cell(HoursRendererColumn column, AggregatedHoursGroup data) {
return new Label(asString(data.getResourceType())); return new Label(asString(data.getResourceType()));
} }
}, },
HOURS { HOURS {
@Override @Override
public Component cell(HoursRendererColumn column, AggregatedHoursGroup data) { public Component cell(HoursRendererColumn column, AggregatedHoursGroup data) {
Label result = new Label(Integer.toString(data.getHours())); return new Label(Integer.toString(data.getHours()));
return result;
} }
}; };
@ -286,6 +284,7 @@ public class ResourceAllocationController extends GenericForwardComposer {
default: default:
LOG.warn("no i18n for " + resourceType.name()); LOG.warn("no i18n for " + resourceType.name());
return resourceType.name(); return resourceType.name();
} }
} }
@ -294,8 +293,7 @@ public class ResourceAllocationController extends GenericForwardComposer {
} }
/** /**
* Pick resources selected from {@link NewAllocationSelector} and add them to * Pick resources selected from {@link NewAllocationSelector} and add them to resource allocation list.
* resource allocation list
* *
* @param e * @param e
*/ */
@ -305,8 +303,12 @@ public class ResourceAllocationController extends GenericForwardComposer {
} finally { } finally {
// For email notification feature // For email notification feature
int rowsSize = allocationRows.getCurrentRows().size(); int rowsSize = allocationRows.getCurrentRows().size();
editTaskController.getTaskPropertiesController().listToAdd
editTaskController
.getTaskPropertiesController()
.getListToAdd()
.add(allocationRows.getCurrentRows().get(rowsSize - 1).getAssociatedResources().get(0)); .add(allocationRows.getCurrentRows().get(rowsSize - 1).getAssociatedResources().get(0));
editTaskController.getTaskPropertiesController().setResourcesAdded(true); editTaskController.getTaskPropertiesController().setResourcesAdded(true);
tbResourceAllocation.setSelected(true); tbResourceAllocation.setSelected(true);
@ -320,15 +322,13 @@ public class ResourceAllocationController extends GenericForwardComposer {
applyButton.setVisible(false); applyButton.setVisible(false);
workerSearchTab.setSelected(true); workerSearchTab.setSelected(true);
LocalDate start = LocalDate LocalDate start = LocalDate.fromDateFields(resourceAllocationModel.getTaskStart());
.fromDateFields(resourceAllocationModel.getTaskStart()); LocalDate end = LocalDate.fromDateFields(resourceAllocationModel.getTaskEnd());
LocalDate end = LocalDate
.fromDateFields(resourceAllocationModel.getTaskEnd());
newAllocationSelector.open(start, end); newAllocationSelector.open(start, end);
} }
/** /**
* Shows the extended view of the resources allocations * Shows the extended view of the resources allocations.
*/ */
public void onCheckExtendedView() { public void onCheckExtendedView() {
if (isExtendedView()) { if (isExtendedView()) {
@ -345,21 +345,14 @@ public class ResourceAllocationController extends GenericForwardComposer {
} }
public int getColspanHours() { public int getColspanHours() {
if (isExtendedView()) { return isExtendedView() ? 4 : 1;
return 4;
}
return 1;
} }
public int getColspanResources() { public int getColspanResources() {
if (isExtendedView()) { return isExtendedView() ? 3 : 1;
return 3;
}
return 1;
} }
/** /**
* Close search worker in worker search tab * Close search worker in worker search tab.
* @param e
*/ */
public void onCloseSelectWorkers() { public void onCloseSelectWorkers() {
tbResourceAllocation.setSelected(true); tbResourceAllocation.setSelected(true);
@ -380,6 +373,7 @@ public class ResourceAllocationController extends GenericForwardComposer {
return resourceAllocationController.getTaskWorkableDays(); return resourceAllocationController.getTaskWorkableDays();
} }
}, },
NUMBER_OF_HOURS(CalculatedValue.NUMBER_OF_HOURS) { NUMBER_OF_HOURS(CalculatedValue.NUMBER_OF_HOURS) {
@Override @Override
public String getName() { public String getName() {
@ -392,8 +386,8 @@ public class ResourceAllocationController extends GenericForwardComposer {
return resourceAllocationController.assignedEffortComponent; return resourceAllocationController.assignedEffortComponent;
} }
}, },
RESOURCES_PER_DAY(CalculatedValue.RESOURCES_PER_DAY) {
RESOURCES_PER_DAY(CalculatedValue.RESOURCES_PER_DAY) {
@Override @Override
public String getName() { public String getName() {
return _("Calculate Resources per Day"); return _("Calculate Resources per Day");
@ -406,36 +400,34 @@ public class ResourceAllocationController extends GenericForwardComposer {
} }
}; };
private final CalculatedValue calculatedValue;
CalculationTypeRadio(CalculatedValue calculatedValue) {
this.calculatedValue = calculatedValue;
}
public static CalculationTypeRadio from(CalculatedValue calculatedValue) { public static CalculationTypeRadio from(CalculatedValue calculatedValue) {
Validate.notNull(calculatedValue); Validate.notNull(calculatedValue);
for (CalculationTypeRadio calculationTypeRadio : CalculationTypeRadio for (CalculationTypeRadio calculationTypeRadio : CalculationTypeRadio.values()) {
.values()) {
if (calculationTypeRadio.getCalculatedValue() == calculatedValue) { if (calculationTypeRadio.getCalculatedValue() == calculatedValue) {
return calculationTypeRadio; return calculationTypeRadio;
} }
} }
throw new RuntimeException("not found " throw new RuntimeException(
+ CalculationTypeRadio.class.getSimpleName() + " for " "not found " + CalculationTypeRadio.class.getSimpleName() + " for " + calculatedValue);
+ calculatedValue);
} }
public abstract Component input( public abstract Component input(ResourceAllocationController resourceAllocationController);
ResourceAllocationController resourceAllocationController);
public Radio createRadio() { public Radio createRadio() {
Radio result = new Radio(); Radio result = new Radio();
result.setLabel(getName()); result.setLabel(getName());
result.setValue(toString()); result.setValue(toString());
return result; return result;
} }
private final CalculatedValue calculatedValue;
private CalculationTypeRadio(CalculatedValue calculatedValue) {
this.calculatedValue = calculatedValue;
}
public abstract String getName(); public abstract String getName();
public CalculatedValue getCalculatedValue() { public CalculatedValue getCalculatedValue() {
@ -451,32 +443,37 @@ public class ResourceAllocationController extends GenericForwardComposer {
return new Label(data.getName()); return new Label(data.getName());
} }
}, },
ALPHA(_("Alpha")) { ALPHA(_("Alpha")) {
@Override @Override
public Component cellFor(DerivedAllocation data) { public Component cellFor(DerivedAllocation data) {
return new Label(String.format("%3.2f", data.getAlpha())); return new Label(String.format("%3.2f", data.getAlpha()));
} }
}, },
HOURS(_("Total Hours")) { HOURS(_("Total Hours")) {
@Override @Override
public Component cellFor(DerivedAllocation data) { public Component cellFor(DerivedAllocation data) {
return new Label(data.getHours() + ""); return new Label(Integer.toString(data.getHours()));
} }
}; };
private final String name;
private static final ICellForDetailItemRenderer<DerivedAllocationColumn, DerivedAllocation> cellRenderer =
(column, data) -> column.cellFor(data);
DerivedAllocationColumn(String name) {
this.name = name;
}
/** /**
* Forces to mark the string as needing translation * Forces to mark the string as needing translation.
*/ */
private static String _(String string) { private static String _(String string) {
return string; return string;
} }
private final String name;
private DerivedAllocationColumn(String name) {
this.name = name;
}
public String getName() { public String getName() {
return I18nHelper._(name); return I18nHelper._(name);
} }
@ -489,26 +486,16 @@ public class ResourceAllocationController extends GenericForwardComposer {
public static void appendColumnsTo(Grid grid) { public static void appendColumnsTo(Grid grid) {
Columns columns = new Columns(); Columns columns = new Columns();
grid.appendChild(columns); grid.appendChild(columns);
for (DerivedAllocationColumn each : values()) { for (DerivedAllocationColumn each : values()) {
columns.appendChild(each.toColumn()); columns.appendChild(each.toColumn());
} }
} }
public static RowRenderer createRenderer() { public static RowRenderer createRenderer() {
return OnColumnsRowRenderer.create(cellRenderer, Arrays return OnColumnsRowRenderer.create(cellRenderer, Arrays.asList(DerivedAllocationColumn.values()));
.asList(DerivedAllocationColumn.values()));
} }
private static final ICellForDetailItemRenderer<DerivedAllocationColumn, DerivedAllocation> cellRenderer= new ICellForDetailItemRenderer<DerivedAllocationColumn, DerivedAllocation>() {
@Override
public Component cellFor(
DerivedAllocationColumn column,
DerivedAllocation data) {
return column.cellFor(data);
}
};
abstract Component cellFor(DerivedAllocation data); abstract Component cellFor(DerivedAllocation data);
} }
@ -516,15 +503,16 @@ public class ResourceAllocationController extends GenericForwardComposer {
return Arrays.asList(CalculationTypeRadio.values()); return Arrays.asList(CalculationTypeRadio.values());
} }
public List<? extends Object> getResourceAllocations() { public List<?> getResourceAllocations() {
return formBinder != null ? plusAggregatingRow(formBinder return formBinder != null
.getCurrentRows()) : Collections ? plusAggregatingRow(formBinder.getCurrentRows())
.<AllocationRow> emptyList(); : Collections.<AllocationRow> emptyList();
} }
private List<Object> plusAggregatingRow(List<AllocationRow> currentRows) { private List<Object> plusAggregatingRow(List<AllocationRow> currentRows) {
List<Object> result = new ArrayList<Object>(currentRows); List<Object> result = new ArrayList<>(currentRows);
result.add(null); result.add(null);
return result; return result;
} }
@ -548,7 +536,6 @@ public class ResourceAllocationController extends GenericForwardComposer {
} }
/** /**
*
* @return <code>true</code> if it must exist <code>false</code> if exit * @return <code>true</code> if it must exist <code>false</code> if exit
* must be prevented * must be prevented
*/ */
@ -572,50 +559,39 @@ public class ResourceAllocationController extends GenericForwardComposer {
} }
} }
private void renderResourceAllocation(Row row, final AllocationRow data) private void renderResourceAllocation(Row row, final AllocationRow data) {
{
row.setValue(data); row.setValue(data);
append(row, data.createDetail()); append(row, data.createDetail());
append(row, new Label(data.getName())); append(row, new Label(data.getName()));
append(row, new Label(data.getOriginalEffort().toFormattedString())); append(row, new Label(data.getOriginalEffort().toFormattedString()));
append(row, new Label(data.getTotalEffort().toFormattedString())); append(row, new Label(data.getTotalEffort().toFormattedString()));
append(row, new Label(data.getConsolidatedEffort() append(row, new Label(data.getConsolidatedEffort().toFormattedString()));
.toFormattedString()));
append(row, data.getEffortInput()); append(row, data.getEffortInput());
append(row, new Label(data.getTotalResourcesPerDay().getAmount() append(row, new Label(data.getTotalResourcesPerDay().getAmount().toString()));
.toString())); append(row, new Label(data.getConsolidatedResourcesPerDay().getAmount().toString()));
append(row, new Label(data.getConsolidatedResourcesPerDay()
.getAmount().toString()));
Div resourcesPerDayContainer = append(row, new Div()); Div resourcesPerDayContainer = append(row, new Div());
append(resourcesPerDayContainer, append(resourcesPerDayContainer, data.getIntendedResourcesPerDayInput());
data.getIntendedResourcesPerDayInput()); Label realResourcesPerDay = append(resourcesPerDayContainer, data.getRealResourcesPerDay());
Label realResourcesPerDay = append(resourcesPerDayContainer,
data.getRealResourcesPerDay());
realResourcesPerDay.setStyle("float: right; padding-right: 1em;"); realResourcesPerDay.setStyle("float: right; padding-right: 1em;");
Listbox assignmentFunctionListbox = data.getAssignmentFunctionListbox(); Listbox assignmentFunctionListbox = data.getAssignmentFunctionListbox();
append(row, assignmentFunctionListbox); append(row, assignmentFunctionListbox);
assignmentFunctionListbox.addEventListener(Events.ON_SELECT, assignmentFunctionListbox.addEventListener(Events.ON_SELECT, event -> data.resetAssignmentFunction());
new EventListener() {
@Override
public void onEvent(Event arg0) throws Exception {
data.resetAssignmentFunction();
}
});
// On click delete button // On click delete button
Button deleteButton = appendDeleteButton(row); Button deleteButton = appendDeleteButton(row);
deleteButton.setDisabled(isAnyManualOrTaskUpdatedFromTimesheets()); deleteButton.setDisabled(isAnyManualOrTaskUpdatedFromTimesheets());
formBinder.setDeleteButtonFor(data, deleteButton); formBinder.setDeleteButtonFor(data, deleteButton);
deleteButton.addEventListener("onClick", new EventListener() {
@Override deleteButton.addEventListener("onClick", event -> {
public void onEvent(Event event) {
editTaskController.getTaskPropertiesController().getListToDelete() editTaskController
.getTaskPropertiesController()
.getListToDelete()
.add(data.getAssociatedResources().get(0)); .add(data.getAssociatedResources().get(0));
removeAllocation(data); removeAllocation(data);
}
}); });
if (!data.isSatisfied()) { if (!data.isSatisfied()) {
@ -632,12 +608,10 @@ public class ResourceAllocationController extends GenericForwardComposer {
append(row, allOriginalEffort); append(row, allOriginalEffort);
append(row, allTotalEffort); append(row, allTotalEffort);
append(row, allConsolidatedEffort); append(row, allConsolidatedEffort);
append(row, CalculationTypeRadio.NUMBER_OF_HOURS append(row, CalculationTypeRadio.NUMBER_OF_HOURS.input(controller));
.input(controller));
append(row, allTotalResourcesPerDay); append(row, allTotalResourcesPerDay);
append(row, allConsolidatedResourcesPerDay); append(row, allConsolidatedResourcesPerDay);
append(row, CalculationTypeRadio.RESOURCES_PER_DAY append(row, CalculationTypeRadio.RESOURCES_PER_DAY.input(controller));
.input(controller));
append(row, new Label()); append(row, new Label());
} }
@ -652,6 +626,7 @@ public class ResourceAllocationController extends GenericForwardComposer {
button.setImage("/common/img/ico_borrar1.png"); button.setImage("/common/img/ico_borrar1.png");
button.setHoverImage("/common/img/ico_borrar.png"); button.setHoverImage("/common/img/ico_borrar.png");
button.setTooltiptext(_("Delete")); button.setTooltiptext(_("Delete"));
return append(row, button); return append(row, button);
} }
@ -670,7 +645,7 @@ public class ResourceAllocationController extends GenericForwardComposer {
} }
public boolean hasResourceAllocations() { public boolean hasResourceAllocations() {
return ((getResourceAllocations().size() > 1)); return getResourceAllocations().size() > 1;
} }
public boolean isAnyNotFlat() { public boolean isAnyNotFlat() {
@ -678,11 +653,7 @@ public class ResourceAllocationController extends GenericForwardComposer {
} }
public boolean isAnyManualOrTaskUpdatedFromTimesheets() { public boolean isAnyManualOrTaskUpdatedFromTimesheets() {
if (formBinder == null) { return formBinder != null && (formBinder.isAnyManual() || formBinder.isTaskUpdatedFromTimesheets());
return false;
}
return formBinder.isAnyManual()
|| formBinder.isTaskUpdatedFromTimesheets();
} }
} }

View file

@ -157,8 +157,6 @@ public class MultipleTabsPlannerController implements Composer, IGlobalViewEntry
@Autowired @Autowired
private OrderCRUDController orderCRUDController; private OrderCRUDController orderCRUDController;
@Autowired @Autowired
private PlanningStateCreator planningStateCreator; private PlanningStateCreator planningStateCreator;

View file

@ -25,7 +25,6 @@ import static org.libreplan.web.I18nHelper._;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.Iterator;
import java.util.List; import java.util.List;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
@ -83,7 +82,7 @@ import org.zkoss.zul.api.Tabpanel;
* Controller for edit {@link Task} popup. * Controller for edit {@link Task} popup.
* *
* @author Manuel Rego Casasnovas <mrego@igalia.com> * @author Manuel Rego Casasnovas <mrego@igalia.com>
* @author Vova Perebykivskiy <vova@libreplan-enterprise.com> * @author Vova Perebykivskyi <vova@libreplan-enterprise.com>
*/ */
@org.springframework.stereotype.Component("taskPropertiesController") @org.springframework.stereotype.Component("taskPropertiesController")
@Scope(BeanDefinition.SCOPE_PROTOTYPE) @Scope(BeanDefinition.SCOPE_PROTOTYPE)
@ -136,33 +135,36 @@ public class TaskPropertiesController extends GenericForwardComposer {
private boolean isResourcesAdded = false; private boolean isResourcesAdded = false;
private List<Resource> listToDelete = new ArrayList<>();
private List<Resource> listToAdd = new ArrayList<>();
public void init(final EditTaskController editTaskController, public void init(final EditTaskController editTaskController,
IContextWithPlannerTask<TaskElement> context, IContextWithPlannerTask<TaskElement> context,
TaskElement taskElement) { TaskElement taskElement) {
this.editTaskController = editTaskController; this.editTaskController = editTaskController;
this.currentContext = context; this.currentContext = context;
this.currentTaskElement = taskElement; this.currentTaskElement = taskElement;
Order order = null; Order order;
if (context != null) { if (context != null) {
order = findOrderIn(context); order = findOrderIn(context);
} else { } else {
order = taskElement.getOrderElement().getOrder(); order = taskElement.getOrderElement().getOrder();
} }
// WebStartConstraintType.setItems(startConstraintTypes, order);
setItemsStartConstraintTypesCombo(order); setItemsStartConstraintTypesCombo(order);
originalState = getResourceAllocationType(currentTaskElement); originalState = getResourceAllocationType(currentTaskElement);
setOldState(originalState); setOldState(originalState);
disabledConstraintsAndAllocations = currentTaskElement disabledConstraintsAndAllocations = currentTaskElement.isSubcontractedAndWasAlreadySent() ||
.isSubcontractedAndWasAlreadySent() currentTaskElement.isLimitingAndHasDayAssignments() ||
|| currentTaskElement.isLimitingAndHasDayAssignments() currentTaskElement.isUpdatedFromTimesheets();
|| currentTaskElement.isUpdatedFromTimesheets();
if (!disabledConstraintsAndAllocations && (currentTaskElement.isTask())) { if (!disabledConstraintsAndAllocations && (currentTaskElement.isTask())) {
disabledConstraintsAndAllocations = ((Task) currentTaskElement) disabledConstraintsAndAllocations = ((Task) currentTaskElement).isManualAnyAllocation();
.isManualAnyAllocation();
} }
startConstraintTypes.setDisabled(disabledConstraintsAndAllocations); startConstraintTypes.setDisabled(disabledConstraintsAndAllocations);
startConstraintDate.setDisabled(disabledConstraintsAndAllocations); startConstraintDate.setDisabled(disabledConstraintsAndAllocations);
@ -177,13 +179,16 @@ public class TaskPropertiesController extends GenericForwardComposer {
private void setItemsStartConstraintTypesCombo(Order order) { private void setItemsStartConstraintTypesCombo(Order order) {
startConstraintTypes.getChildren().clear(); startConstraintTypes.getChildren().clear();
for (PositionConstraintType type : PositionConstraintType.values()) { for (PositionConstraintType type : PositionConstraintType.values()) {
if ( (type != PositionConstraintType.AS_LATE_AS_POSSIBLE && if ( (type != PositionConstraintType.AS_LATE_AS_POSSIBLE &&
type != PositionConstraintType.AS_SOON_AS_POSSIBLE) || type != PositionConstraintType.AS_SOON_AS_POSSIBLE) ||
(type == PositionConstraintType.AS_LATE_AS_POSSIBLE && (type == PositionConstraintType.AS_LATE_AS_POSSIBLE &&
order.getDeadline() != null) || order.getDeadline() != null) ||
(type == PositionConstraintType.AS_SOON_AS_POSSIBLE && (type == PositionConstraintType.AS_SOON_AS_POSSIBLE &&
order.getInitDate() != null) ) { order.getInitDate() != null) ) {
Comboitem comboitem = new Comboitem(_(type.getName())); Comboitem comboitem = new Comboitem(_(type.getName()));
comboitem.setValue(type); comboitem.setValue(type);
startConstraintTypes.appendChild(comboitem); startConstraintTypes.appendChild(comboitem);
@ -192,32 +197,31 @@ public class TaskPropertiesController extends GenericForwardComposer {
} }
private Order findOrderIn(IContextWithPlannerTask<TaskElement> context) { private Order findOrderIn(IContextWithPlannerTask<TaskElement> context) {
TaskElement topTask = context.getMapper().findAssociatedDomainObject( TaskElement topTask = context.getMapper().findAssociatedDomainObject(findTopMostTask(context));
findTopMostTask(context));
return topTask.getParent().getOrderElement().getOrder(); return topTask.getParent().getOrderElement().getOrder();
} }
private OrderElement findOrderElementIn(IContextWithPlannerTask<TaskElement> context) { private OrderElement findOrderElementIn(IContextWithPlannerTask<TaskElement> context) {
TaskElement topTask = context.getMapper().findAssociatedDomainObject( TaskElement topTask = context.getMapper().findAssociatedDomainObject(findTopMostTask(context));
findTopMostTask(context));
return topTask.getOrderElement(); return topTask.getOrderElement();
} }
private org.zkoss.ganttz.data.Task findTopMostTask( private org.zkoss.ganttz.data.Task findTopMostTask(IContextWithPlannerTask<TaskElement> context) {
IContextWithPlannerTask<TaskElement> context) { List<? extends TaskContainer> parents = context.getMapper().getParents(context.getTask());
List<? extends TaskContainer> parents = context.getMapper().getParents(
context.getTask()); return parents.isEmpty() ? context.getTask() : parents.get(parents.size() - 1);
return parents.isEmpty() ? context.getTask() : parents.get(parents
.size() - 1);
} }
private void setOldState(ResourceAllocationTypeEnum state) { private void setOldState(ResourceAllocationTypeEnum state) {
// TODO resolve deprecated
lbResourceAllocationType.setVariable("oldState", state, true); lbResourceAllocationType.setVariable("oldState", state, true);
} }
private ResourceAllocationTypeEnum getOldState() { private ResourceAllocationTypeEnum getOldState() {
return (ResourceAllocationTypeEnum) lbResourceAllocationType // TODO resolve deprecated
.getVariable("oldState", true); return (ResourceAllocationTypeEnum) lbResourceAllocationType.getVariable("oldState", true);
} }
private void setResourceAllocationType(Listbox listbox, ResourceAllocationTypeEnum value) { private void setResourceAllocationType(Listbox listbox, ResourceAllocationTypeEnum value) {
@ -225,9 +229,10 @@ public class TaskPropertiesController extends GenericForwardComposer {
} }
private void setResourceAllocationType(Listbox listbox, String label) { private void setResourceAllocationType(Listbox listbox, String label) {
for (Iterator i = listbox.getChildren().iterator(); i.hasNext(); ) { for (Object o : listbox.getChildren()) {
Listitem item = (Listitem) i.next(); Listitem item = (Listitem) o;
Listcell cell = (Listcell) item.getFirstChild(); Listcell cell = (Listcell) item.getFirstChild();
if ( cell.getLabel() != null && cell.getLabel().equals(label) ) { if ( cell.getLabel() != null && cell.getLabel().equals(label) ) {
item.setSelected(true); item.setSelected(true);
} }
@ -239,7 +244,7 @@ public class TaskPropertiesController extends GenericForwardComposer {
Task task = (Task) currentTaskElement; Task task = (Task) currentTaskElement;
showDurationRow(task); showDurationRow(task);
showStartConstraintRow(task); showStartConstraintRow(task);
showResourceAllocationTypeRow(task); showResourceAllocationTypeRow();
} else { } else {
hideDurationRow(); hideDurationRow();
if (currentTaskElement instanceof ITaskPositionConstrained) { if (currentTaskElement instanceof ITaskPositionConstrained) {
@ -258,7 +263,7 @@ public class TaskPropertiesController extends GenericForwardComposer {
resourceAllocationType.setVisible(false); resourceAllocationType.setVisible(false);
} }
private void showResourceAllocationTypeRow(Task task) { private void showResourceAllocationTypeRow() {
resourceAllocationType.setVisible(true); resourceAllocationType.setVisible(true);
} }
@ -268,8 +273,7 @@ public class TaskPropertiesController extends GenericForwardComposer {
private void showStartConstraintRow(ITaskPositionConstrained task) { private void showStartConstraintRow(ITaskPositionConstrained task) {
startConstraint.setVisible(true); startConstraint.setVisible(true);
PositionConstraintType type = task.getPositionConstraint() PositionConstraintType type = task.getPositionConstraint().getConstraintType();
.getConstraintType();
startConstraintTypes.setSelectedItemApi(findComboWithType(type)); startConstraintTypes.setSelectedItemApi(findComboWithType(type));
updateStartConstraint(type); updateStartConstraint(type);
} }
@ -278,7 +282,7 @@ public class TaskPropertiesController extends GenericForwardComposer {
for (Object component : startConstraintTypes.getChildren()) { for (Object component : startConstraintTypes.getChildren()) {
if (component instanceof Comboitem) { if (component instanceof Comboitem) {
Comboitem item = (Comboitem) component; Comboitem item = (Comboitem) component;
if (((PositionConstraintType) item.getValue()) == type) { if ( item.getValue() == type) {
return item; return item;
} }
} }
@ -292,26 +296,25 @@ public class TaskPropertiesController extends GenericForwardComposer {
} }
private void updateStartConstraint(PositionConstraintType type) { private void updateStartConstraint(PositionConstraintType type) {
TaskPositionConstraint taskStartConstraint = currentTaskElementAsTaskLeafConstraint() TaskPositionConstraint taskStartConstraint = currentTaskElementAsTaskLeafConstraint().getPositionConstraint();
.getPositionConstraint();
startConstraintDate.setVisible(type.isAssociatedDateRequired()); startConstraintDate.setVisible(type.isAssociatedDateRequired());
if (taskStartConstraint.getConstraintDateAsDate() != null) { if (taskStartConstraint.getConstraintDateAsDate() != null) {
startConstraintDate.setValue(taskStartConstraint startConstraintDate.setValue(taskStartConstraint.getConstraintDateAsDate());
.getConstraintDateAsDate());
} }
} }
private boolean saveConstraintChanges() { private boolean saveConstraintChanges() {
TaskPositionConstraint taskConstraint = currentTaskElementAsTaskLeafConstraint() TaskPositionConstraint taskConstraint = currentTaskElementAsTaskLeafConstraint().getPositionConstraint();
.getPositionConstraint(); PositionConstraintType type = (PositionConstraintType) startConstraintTypes.getSelectedItemApi().getValue();
PositionConstraintType type = (PositionConstraintType) startConstraintTypes
.getSelectedItemApi().getValue(); IntraDayDate inputDate = type.isAssociatedDateRequired()
IntraDayDate inputDate = type.isAssociatedDateRequired() ? IntraDayDate ? IntraDayDate.startOfDay(LocalDate.fromDateFields(startConstraintDate.getValue()))
.startOfDay(LocalDate.fromDateFields(startConstraintDate : null;
.getValue())) : null;
if (taskConstraint.isValid(type, inputDate)) { if (taskConstraint.isValid(type, inputDate)) {
taskConstraint.update(type, inputDate); taskConstraint.update(type, inputDate);
//at this point we could call currentContext.recalculatePosition(currentTaskElement) // At this point we could call currentContext.recalculatePosition(currentTaskElement)
// to trigger the scheduling algorithm, but we don't do it because // to trigger the scheduling algorithm, but we don't do it because
// the ResourceAllocationController, which is attached to the other // the ResourceAllocationController, which is attached to the other
// tab of the same window, will do it anyway. // tab of the same window, will do it anyway.
@ -339,15 +342,13 @@ public class TaskPropertiesController extends GenericForwardComposer {
super.doAfterCompose(comp); super.doAfterCompose(comp);
tabpanel = (Tabpanel) comp; tabpanel = (Tabpanel) comp;
taskEditFormComposer.doAfterCompose(comp); taskEditFormComposer.doAfterCompose(comp);
startConstraintTypes.addEventListener(Events.ON_SELECT,
new EventListener() {
@Override startConstraintTypes.addEventListener(Events.ON_SELECT, event -> {
public void onEvent(Event event) {
PositionConstraintType constraint = (PositionConstraintType) startConstraintTypes PositionConstraintType constraint =
.getSelectedItemApi().getValue(); (PositionConstraintType) startConstraintTypes.getSelectedItemApi().getValue();
constraintTypeChoosen(constraint); constraintTypeChoosen(constraint);
}
}); });
lbResourceAllocationType.addEventListener(Events.ON_SELECT, new EventListener() { lbResourceAllocationType.addEventListener(Events.ON_SELECT, new EventListener() {
@ -358,19 +359,22 @@ public class TaskPropertiesController extends GenericForwardComposer {
final ResourceAllocationTypeEnum oldState = getOldState(); final ResourceAllocationTypeEnum oldState = getOldState();
ResourceAllocationTypeEnum newState = getSelectedValue(new ArrayList(se.getSelectedItems())); ResourceAllocationTypeEnum newState = getSelectedValue(new ArrayList(se.getSelectedItems()));
if (thereIsTransition(newState)) { if (thereIsTransition(newState)) {
if (isConsolidatedTask()) { if (isConsolidatedTask()) {
restoreOldState(); restoreOldState();
editTaskController.showNonPermitChangeResourceAllocationType(); editTaskController.showNonPermitChangeResourceAllocationType();
} else { } else {
if(newState.equals(ResourceAllocationTypeEnum.SUBCONTRACT) if (newState.equals(ResourceAllocationTypeEnum.SUBCONTRACT) && !checkCompatibleAllocation()) {
&& !checkCompatibleAllocation()){
try { try {
restoreOldState(); restoreOldState();
Messagebox.show(_("This resource allocation type is incompatible. The task has an associated order element which has a progress that is of type subcontractor. "), Messagebox.show(
_("This resource allocation type is incompatible. " +
"The task has an associated order element which has a progress that " +
"is of type subcontractor. "),
_("Error"), Messagebox.OK , Messagebox.ERROR); _("Error"), Messagebox.OK , Messagebox.ERROR);
} catch (InterruptedException e) { } catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace(); e.printStackTrace();
} }
}else{ }else{
@ -379,13 +383,14 @@ public class TaskPropertiesController extends GenericForwardComposer {
} }
} }
} }
if (oldState == null) { if (oldState == null) {
setOldState(newState); setOldState(newState);
} }
} }
private ResourceAllocationTypeEnum getSelectedValue(List<Listitem> selectedItems) { private ResourceAllocationTypeEnum getSelectedValue(List<Listitem> selectedItems) {
final Listitem item = (Listitem) selectedItems.get(0); final Listitem item = selectedItems.get(0);
final Listcell cell = (Listcell) item.getChildren().get(0); final Listcell cell = (Listcell) item.getChildren().get(0);
return ResourceAllocationTypeEnum.asEnum(cell.getLabel()); return ResourceAllocationTypeEnum.asEnum(cell.getLabel());
} }
@ -399,7 +404,7 @@ public class TaskPropertiesController extends GenericForwardComposer {
} }
private boolean checkCompatibleAllocation(){ private boolean checkCompatibleAllocation(){
OrderElement orderElement = null; OrderElement orderElement;
AdvanceType advanceType = PredefinedAdvancedTypes.SUBCONTRACTOR.getType(); AdvanceType advanceType = PredefinedAdvancedTypes.SUBCONTRACTOR.getType();
if (this.currentContext != null) { if (this.currentContext != null) {
@ -411,11 +416,12 @@ public class TaskPropertiesController extends GenericForwardComposer {
return false; return false;
} }
try { try {
DirectAdvanceAssignment newAdvanceAssignment = DirectAdvanceAssignment DirectAdvanceAssignment newAdvanceAssignment = DirectAdvanceAssignment.create();
.create();
newAdvanceAssignment.setAdvanceType(advanceType); newAdvanceAssignment.setAdvanceType(advanceType);
orderElement.checkAncestorsNoOtherAssignmentWithSameAdvanceType( orderElement.checkAncestorsNoOtherAssignmentWithSameAdvanceType(
orderElement.getParent(), newAdvanceAssignment); orderElement.getParent(), newAdvanceAssignment);
} catch (DuplicateAdvanceAssignmentForOrderElementException e) { } catch (DuplicateAdvanceAssignmentForOrderElementException e) {
return false; return false;
} }
@ -427,10 +433,7 @@ public class TaskPropertiesController extends GenericForwardComposer {
} }
public TaskDTO getGanttTaskDTO() { public TaskDTO getGanttTaskDTO() {
if (taskEditFormComposer == null) { return taskEditFormComposer == null ? null : taskEditFormComposer.getTaskDTO();
return null;
}
return taskEditFormComposer.getTaskDTO();
} }
public void accept() { public void accept() {
@ -456,36 +459,40 @@ public class TaskPropertiesController extends GenericForwardComposer {
} }
/** /**
* Enum for showing type of resource assignation option list * Enum for showing type of resource assignation option list.
* *
* @author Diego Pino Garcia <dpino@igalia.com> * @author Diego Pino Garcia <dpino@igalia.com>
* *
*/ */
public enum ResourceAllocationTypeEnum { public enum ResourceAllocationTypeEnum {
NON_LIMITING_RESOURCES(_("Normal resource assignment")), NON_LIMITING_RESOURCES(_("Normal resource assignment")),
LIMITING_RESOURCES(_("Queue-based resource assignation")), LIMITING_RESOURCES(_("Queue-based resource assignation")),
SUBCONTRACT(_("Subcontract")); SUBCONTRACT(_("Subcontract"));
/**
* Forces to mark the string as needing translation
*/
private static String _(String string) {
return string;
}
private String option; private String option;
private static final List<ResourceAllocationTypeEnum> nonMasterOptionList = new ArrayList<ResourceAllocationTypeEnum>() { private static final List<ResourceAllocationTypeEnum> nonMasterOptionList =
new ArrayList<ResourceAllocationTypeEnum>() {
{ {
add(NON_LIMITING_RESOURCES); add(NON_LIMITING_RESOURCES);
add(SUBCONTRACT); add(SUBCONTRACT);
} }
}; };
private ResourceAllocationTypeEnum(String option) { ResourceAllocationTypeEnum(String option) {
this.option = option; this.option = option;
} }
/**
* Forces to mark the string as needing translation.
*/
private static String _(String string) {
return string;
}
@Override
public String toString() { public String toString() {
return I18nHelper._(option); return I18nHelper._(option);
} }
@ -505,8 +512,10 @@ public class TaskPropertiesController extends GenericForwardComposer {
public static ResourceAllocationTypeEnum asEnum(String label) { public static ResourceAllocationTypeEnum asEnum(String label) {
if (NON_LIMITING_RESOURCES.toString().equals(label)) { if (NON_LIMITING_RESOURCES.toString().equals(label)) {
return NON_LIMITING_RESOURCES; return NON_LIMITING_RESOURCES;
} else if (LIMITING_RESOURCES.toString().equals(label)) { } else if (LIMITING_RESOURCES.toString().equals(label)) {
return LIMITING_RESOURCES; return LIMITING_RESOURCES;
} else if (SUBCONTRACT.toString().equals(label)) { } else if (SUBCONTRACT.toString().equals(label)) {
return SUBCONTRACT; return SUBCONTRACT;
} }
@ -516,11 +525,9 @@ public class TaskPropertiesController extends GenericForwardComposer {
} }
public List<ResourceAllocationTypeEnum> getResourceAllocationTypeOptionList() { public List<ResourceAllocationTypeEnum> getResourceAllocationTypeOptionList() {
if (scenarioManager.getCurrent().isMaster()) { return scenarioManager.getCurrent().isMaster()
return ResourceAllocationTypeEnum.getOptionList(); ? ResourceAllocationTypeEnum.getOptionList()
} else { : ResourceAllocationTypeEnum.getOptionListForNonMasterBranch();
return ResourceAllocationTypeEnum.getOptionListForNonMasterBranch();
}
} }
public ResourceAllocationTypeEnum getResourceAllocationType() { public ResourceAllocationTypeEnum getResourceAllocationType() {
@ -528,13 +535,11 @@ public class TaskPropertiesController extends GenericForwardComposer {
} }
/** /**
* Does nothing, but it must exist for receiving selected value from listbox * Does nothing, but it must exist for receiving selected value from ListBox.
* *
* @param resourceAllocation * @param resourceAllocation
*/ */
public void setResourceAllocationType(ResourceAllocationTypeEnum resourceAllocation) { public void setResourceAllocationType(ResourceAllocationTypeEnum resourceAllocation) {}
}
public ResourceAllocationTypeEnum getResourceAllocationType(TaskElement taskElement) { public ResourceAllocationTypeEnum getResourceAllocationType(TaskElement taskElement) {
if ( taskElement == null || !isTask(taskElement) ) { if ( taskElement == null || !isTask(taskElement) ) {
@ -544,13 +549,13 @@ public class TaskPropertiesController extends GenericForwardComposer {
} }
/** /**
* Returns type of resource allocation depending on state of task * Returns type of resource allocation depending on state of task.
* *
* If task is subcontracted, return a SUBCONTRACT state * If task is subcontracted, return a SUBCONTRACT state.
* If task has at least one limiting resource, returns a LIMITING RESOURCE state * If task has at least one limiting resource, returns a LIMITING RESOURCE state.
* Otherwise, return default state (NON-LIMITING RESOURCE) * Otherwise, return default state (NON-LIMITING RESOURCE).
* *
* @return * @return {@link ResourceAllocationTypeEnum}
*/ */
public ResourceAllocationTypeEnum getResourceAllocationType(Task task) { public ResourceAllocationTypeEnum getResourceAllocationType(Task task) {
ResourceAllocationTypeEnum result = ResourceAllocationTypeEnum.NON_LIMITING_RESOURCES; ResourceAllocationTypeEnum result = ResourceAllocationTypeEnum.NON_LIMITING_RESOURCES;
@ -583,7 +588,7 @@ public class TaskPropertiesController extends GenericForwardComposer {
} }
/** /**
* Change state from NonLimitingResource assignation type to a new state (limiting, subcontract) * Change state from NonLimitingResource assignation type to a new state (limiting, subcontract).
* *
* @param newState * @param newState
*/ */
@ -595,17 +600,17 @@ public class TaskPropertiesController extends GenericForwardComposer {
Task task = asTask(currentTaskElement); Task task = asTask(currentTaskElement);
if (task.hasResourceAllocations()) { if (task.hasResourceAllocations()) {
try { try {
if (Messagebox.show(_("Assigned resources for this task will be deleted. Are you sure?"), if (Messagebox.show(
_("Assigned resources for this task will be deleted. Are you sure?"),
_("Warning"), Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION) == Messagebox.OK) { _("Warning"), Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION) == Messagebox.OK) {
task.removeAllResourceAllocations(); task.removeAllResourceAllocations();
setStateTo(newState); setStateTo(newState);
} else { } else {
resetStateTo(ResourceAllocationTypeEnum.NON_LIMITING_RESOURCES); resetStateTo(ResourceAllocationTypeEnum.NON_LIMITING_RESOURCES);
} }
return; return;
} catch (InterruptedException e) { } catch (InterruptedException ignored) {}
}
} }
setStateTo(newState); setStateTo(newState);
} }
@ -621,7 +626,7 @@ public class TaskPropertiesController extends GenericForwardComposer {
} }
/** /**
* Change state from LimitingResource assignation type to a new state (non-limiting, subcontract) * Change state from LimitingResource assignation type to a new state (non-limiting, subcontract).
* *
* @param newState * @param newState
*/ */
@ -633,23 +638,23 @@ public class TaskPropertiesController extends GenericForwardComposer {
Task task = asTask(currentTaskElement); Task task = asTask(currentTaskElement);
if (task.hasResourceAllocations()) { if (task.hasResourceAllocations()) {
try { try {
if (Messagebox.show(_("Assigned resources for this task will be deleted. Are you sure?"), if (Messagebox.show(
_("Assigned resources for this task will be deleted. Are you sure?"),
_("Warning"), Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION) == Messagebox.OK) { _("Warning"), Messagebox.OK | Messagebox.CANCEL, Messagebox.QUESTION) == Messagebox.OK) {
task.removeAllResourceAllocations(); task.removeAllResourceAllocations();
setStateTo(newState); setStateTo(newState);
} else { } else {
resetStateTo(ResourceAllocationTypeEnum.LIMITING_RESOURCES); resetStateTo(ResourceAllocationTypeEnum.LIMITING_RESOURCES);
} }
return; return;
} catch (InterruptedException e) { } catch (InterruptedException ignored) {}
}
} }
setStateTo(newState); setStateTo(newState);
} }
/** /**
* Change state from Subcontract assignation type to a new state (non-limiting, limiting) * Change state from Subcontract assignation type to a new state (non-limiting, limiting).
* *
* @param newState * @param newState
*/ */
@ -657,23 +662,25 @@ public class TaskPropertiesController extends GenericForwardComposer {
Task task = asTask(currentTaskElement); Task task = asTask(currentTaskElement);
if (task.isSubcontracted()) { if (task.isSubcontracted()) {
final Date communicationDate = (task.getSubcontractedTaskData() != null) ?
task.getSubcontractedTaskData().getSubcontractCommunicationDate() final Date communicationDate = (task.getSubcontractedTaskData() != null)
? task.getSubcontractedTaskData().getSubcontractCommunicationDate()
: null; : null;
// Notification has been sent // Notification has been sent
if (communicationDate != null) { if (communicationDate != null) {
try { try {
if (Messagebox.show(_("IMPORTANT: Don't forget to communicate to subcontractor that his contract has been cancelled"), if (Messagebox.show(
_("IMPORTANT: Don't forget to communicate to subcontractor " +
"that his contract has been cancelled"),
_("Warning"), Messagebox.OK, Messagebox.EXCLAMATION) == Messagebox.OK) { _("Warning"), Messagebox.OK, Messagebox.EXCLAMATION) == Messagebox.OK) {
setStateTo(newState); setStateTo(newState);
} else { } else {
resetStateTo(ResourceAllocationTypeEnum.SUBCONTRACT); resetStateTo(ResourceAllocationTypeEnum.SUBCONTRACT);
} }
return; return;
} catch (InterruptedException e) { } catch (InterruptedException ignored) {}
}
} }
} }
setStateTo(newState); setStateTo(newState);
@ -704,10 +711,8 @@ public class TaskPropertiesController extends GenericForwardComposer {
public boolean isConsolidatedTask() { public boolean isConsolidatedTask() {
Task task = asTask(currentTaskElement); Task task = asTask(currentTaskElement);
if (task != null) {
return task.hasConsolidations(); return task != null && task.hasConsolidations();
}
return false;
} }
public void updateTaskEndDate(LocalDate endDate) { public void updateTaskEndDate(LocalDate endDate) {
@ -716,8 +721,7 @@ public class TaskPropertiesController extends GenericForwardComposer {
} }
public void updateTaskStartDate(LocalDate newStart) { public void updateTaskStartDate(LocalDate newStart) {
getGanttTaskDTO().beginDate = newStart.toDateTimeAtStartOfDay() getGanttTaskDTO().beginDate = newStart.toDateTimeAtStartOfDay().toDate();
.toDate();
Util.reloadBindings(startDateBox); Util.reloadBindings(startDateBox);
} }
@ -733,14 +737,11 @@ public class TaskPropertiesController extends GenericForwardComposer {
return Util.getMoneyFormat(); return Util.getMoneyFormat();
} }
public List<Resource> listToDelete = new ArrayList<Resource>();
public List<Resource> listToAdd = new ArrayList<Resource>();
public void emailNotificationAddNew() { public void emailNotificationAddNew() {
/** /*
* Check if resources in allocation are bound by user and in what ROLE they are * 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 * setUser method calling manually because, after initialization, user will be null.
* Then send valid data to notification_queue table * Then send valid data to notification_queue table
*/ */
@ -751,7 +752,7 @@ public class TaskPropertiesController extends GenericForwardComposer {
} }
private void proceedList(EmailTemplateEnum enumeration, List<Resource> list){ private void proceedList(EmailTemplateEnum enumeration, List<Resource> list){
if ( list.size() != 0 ){ if ( !list.isEmpty() ) {
List<Worker> workersList = workerModel.getWorkers(); List<Worker> workersList = workerModel.getWorkers();
Worker currentWorker; Worker currentWorker;
Resource currentResource; Resource currentResource;
@ -783,6 +784,7 @@ public class TaskPropertiesController extends GenericForwardComposer {
if ( enumeration.equals(EmailTemplateEnum.TEMPLATE_TASK_ASSIGNED_TO_RESOURCE) ) if ( enumeration.equals(EmailTemplateEnum.TEMPLATE_TASK_ASSIGNED_TO_RESOURCE) )
emailNotificationModel.setType(EmailTemplateEnum.TEMPLATE_TASK_ASSIGNED_TO_RESOURCE); emailNotificationModel.setType(EmailTemplateEnum.TEMPLATE_TASK_ASSIGNED_TO_RESOURCE);
else if ( enumeration.equals(EmailTemplateEnum.TEMPLATE_RESOURCE_REMOVED_FROM_TASK) ) else if ( enumeration.equals(EmailTemplateEnum.TEMPLATE_RESOURCE_REMOVED_FROM_TASK) )
emailNotificationModel.setType(EmailTemplateEnum.TEMPLATE_RESOURCE_REMOVED_FROM_TASK); emailNotificationModel.setType(EmailTemplateEnum.TEMPLATE_RESOURCE_REMOVED_FROM_TASK);
@ -797,8 +799,10 @@ public class TaskPropertiesController extends GenericForwardComposer {
emailNotificationModel.confirmSave(); emailNotificationModel.confirmSave();
} catch (DataIntegrityViolationException e){ } catch (DataIntegrityViolationException e){
try { try {
Messagebox.show(_("You cannot email user twice with the same info"), _("Error"), Messagebox.show(
_("You cannot email user twice with the same info"), _("Error"),
Messagebox.OK, Messagebox.ERROR); Messagebox.OK, Messagebox.ERROR);
} catch (InterruptedException e1) { } catch (InterruptedException e1) {
e1.printStackTrace(); e1.printStackTrace();
} }
@ -809,6 +813,10 @@ public class TaskPropertiesController extends GenericForwardComposer {
return listToDelete; return listToDelete;
} }
public List<Resource> getListToAdd() {
return listToAdd;
}
public void setResourcesAdded(boolean resourcesAdded) { public void setResourcesAdded(boolean resourcesAdded) {
isResourcesAdded = resourcesAdded; isResourcesAdded = resourcesAdded;
} }

View file

@ -1,119 +0,0 @@
/*
* This file is part of LibrePlan
*
* Copyright (C) 2012 Igalia, S.L.
*
* 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.web.users.services;
import javax.servlet.http.HttpServletRequest;
import org.libreplan.business.common.IAdHocTransactionService;
import org.libreplan.business.common.IOnTransaction;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.users.daos.IOrderAuthorizationDAO;
import org.libreplan.business.users.daos.IUserDAO;
import org.libreplan.business.users.entities.User;
import org.libreplan.business.users.entities.UserRole;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.Authentication;
import org.springframework.security.ui.TargetUrlResolverImpl;
import org.springframework.security.ui.savedrequest.SavedRequest;
import org.springframework.security.userdetails.UserDetails;
*/
/**
* Determines the URL for authenticated users depending on if user is bound or
* not to any resource.<br />
*
* If the user is bound to a resource then the target URL will be the user
* dashboard.
*
* @author Manuel Rego Casasnovas <mrego@igalia.com>
*//*
public class CustomTargetUrlResolver extends TargetUrlResolverImpl {
public final static String USER_DASHBOARD_URL = "/myaccount/userDashboard.zul";
public static final String PLANNING_URL = "/planner/index.zul";
public static final String SETTINGS_URL = "/myaccount/settings.zul";
@Autowired
private IUserDAO userDAO;
@Autowired
private IOrderAuthorizationDAO orderAuthorizationDAO;
@Autowired
private IAdHocTransactionService transactionServiceDAO;
@Override
public String determineTargetUrl(SavedRequest savedRequest,
HttpServletRequest currentRequest, final Authentication auth) {
if (isUserInRole(auth, UserRole.ROLE_SUPERUSER.name())) {
return super.determineTargetUrl(savedRequest, currentRequest, auth);
}
if (isUserInRole(auth, UserRole.ROLE_BOUND_USER.name())) {
return USER_DASHBOARD_URL;
}
if (isUserInRole(auth, UserRole.ROLE_PLANNING.name())) {
return PLANNING_URL;
}
boolean userOrItsProfilesHaveAnyAuthorization = transactionServiceDAO
.runOnReadOnlyTransaction(new IOnTransaction<Boolean>() {
@Override
public Boolean execute() {
try {
UserDetails userDetails = (UserDetails) auth.getPrincipal();
User user = userDAO.findByLoginName(userDetails.getUsername());
user.getProfiles().size();
return orderAuthorizationDAO
.userOrItsProfilesHaveAnyAuthorization(user);
} catch (InstanceNotFoundException e) {
throw new RuntimeException(e);
}
}
});
if (userOrItsProfilesHaveAnyAuthorization) {
return PLANNING_URL;
}
return SETTINGS_URL;
}
private boolean isUserInRole(Authentication auth, String role) {
if ((auth == null) || (auth.getPrincipal() == null)
|| (auth.getAuthorities() == null)) {
return false;
}
for (int i = 0; i < auth.getAuthorities().length; i++) {
if (role.equals(auth.getAuthorities()[i].getAuthority())) {
return true;
}
}
return false;
}
}
*/

View file

@ -63,9 +63,9 @@ import org.springframework.transaction.annotation.Transactional;
@Path("/orderelements/") @Path("/orderelements/")
@Produces("application/xml") @Produces("application/xml")
@Service("orderElementServiceREST") @Service("orderElementServiceREST")
public class OrderElementServiceREST extends public class OrderElementServiceREST
GenericRESTService<Order, OrderDTO> implements extends GenericRESTService<Order, OrderDTO>
IOrderElementService { implements IOrderElementService {
@Autowired @Autowired
private IOrderDAO orderDAO; private IOrderDAO orderDAO;
@ -86,15 +86,13 @@ public class OrderElementServiceREST extends
@Override @Override
@POST @POST
@Consumes("application/xml") @Consumes("application/xml")
public InstanceConstraintViolationsListDTO addOrders( public InstanceConstraintViolationsListDTO addOrders(OrderListDTO orderListDTO) {
OrderListDTO orderListDTO) {
return save(orderListDTO.orderDTOs); return save(orderListDTO.orderDTOs);
} }
@Override @Override
protected OrderDTO toDTO(Order entity) { protected OrderDTO toDTO(Order entity) {
return (OrderDTO) OrderElementConverter.toDTO(entity, return (OrderDTO) OrderElementConverter.toDTO(entity, ConfigurationOrderElementConverter.all());
ConfigurationOrderElementConverter.all());
} }
@Override @Override
@ -103,17 +101,15 @@ public class OrderElementServiceREST extends
} }
@Override @Override
protected Order toEntity(OrderDTO entityDTO) throws ValidationException, protected Order toEntity(OrderDTO entityDTO) throws ValidationException, RecoverableErrorException {
RecoverableErrorException { return (Order) OrderElementConverter.toEntity(entityDTO, ConfigurationOrderElementConverter.all());
return (Order) OrderElementConverter.toEntity(entityDTO,
ConfigurationOrderElementConverter.all());
} }
@Override @Override
protected void updateEntity(Order entity, OrderDTO entityDTO) protected void updateEntity(Order entity, OrderDTO entityDTO)
throws ValidationException, RecoverableErrorException { throws ValidationException, RecoverableErrorException {
OrderElementConverter.update(entity, entityDTO,
ConfigurationOrderElementConverter.all()); OrderElementConverter.update(entity, entityDTO, ConfigurationOrderElementConverter.all());
} }
@Override @Override
@ -133,8 +129,7 @@ public class OrderElementServiceREST extends
OrderElement orderElement = orderElementDAO.findByCode(code); OrderElement orderElement = orderElementDAO.findByCode(code);
String errorMessage = checkRemovalValidation(orderElement); String errorMessage = checkRemovalValidation(orderElement);
if (errorMessage != null) { if (errorMessage != null) {
return Response.status(Status.FORBIDDEN) return Response.status(Status.FORBIDDEN).entity(new ErrorDTO(errorMessage)).build();
.entity(new ErrorDTO(errorMessage)).build();
} }
if (orderElement.isOrder()) { if (orderElement.isOrder()) {
@ -152,6 +147,7 @@ public class OrderElementServiceREST extends
if (!parent.isOrder() && parent.getChildren().isEmpty()) { if (!parent.isOrder() && parent.getChildren().isEmpty()) {
OrderElement newElement = parent.toLeaf(); OrderElement newElement = parent.toLeaf();
if (!order.isCodeAutogenerated()) { if (!order.isCodeAutogenerated()) {
newElement.setCode(UUID.randomUUID().toString()); newElement.setCode(UUID.randomUUID().toString());
} }
@ -170,12 +166,12 @@ public class OrderElementServiceREST extends
private String checkRemovalValidation(OrderElement orderElement) { private String checkRemovalValidation(OrderElement orderElement) {
try { try {
if (orderElementDAO if (orderElementDAO.isAlreadyInUseThisOrAnyOfItsChildren(orderElement)) {
.isAlreadyInUseThisOrAnyOfItsChildren(orderElement)) {
return "You cannot remove the order element '" return "You cannot remove the order element '"
+ orderElement.getName() + orderElement.getName()
+ "' because it or any of its children have tracked time in some work report"; + "' because it or any of its children have tracked time in some work report";
} }
if (orderElementDAO.hasImputedExpenseSheetThisOrAnyOfItsChildren(orderElement.getId())) { if (orderElementDAO.hasImputedExpenseSheetThisOrAnyOfItsChildren(orderElement.getId())) {
return "You cannot remove the order element '" return "You cannot remove the order element '"
+ orderElement.getName() + orderElement.getName()
@ -183,13 +179,13 @@ public class OrderElementServiceREST extends
} }
OrderLineGroup parent = orderElement.getParent(); OrderLineGroup parent = orderElement.getParent();
if (parent != null && !parent.isOrder() if (parent != null && !parent.isOrder() && parent.getChildren().size() == 1) {
&& parent.getChildren().size() == 1) {
if (orderElementDAO.isAlreadyInUse(parent)) { if (orderElementDAO.isAlreadyInUse(parent)) {
return "You cannot remove the order element '" return "You cannot remove the order element '"
+ orderElement.getName() + orderElement.getName()
+ "' because it is the only child of its parent and its parent has tracked time in some work report"; + "' because it is the only child of its parent and its parent has tracked time in some work report";
} }
if (orderElementDAO.hasImputedExpenseSheet(parent.getId())) { if (orderElementDAO.hasImputedExpenseSheet(parent.getId())) {
return "You cannot remove the order element '" return "You cannot remove the order element '"
+ orderElement.getName() + orderElement.getName()
@ -207,6 +203,7 @@ public class OrderElementServiceREST extends
if (orderElement.getId().equals(id)) { if (orderElement.getId().equals(id)) {
return orderElement; return orderElement;
} }
for (OrderElement child : orderElement.getChildren()) { for (OrderElement child : orderElement.getChildren()) {
OrderElement found = findOrderElement(child, id); OrderElement found = findOrderElement(child, id);
if (found != null) { if (found != null) {

View file

@ -38,7 +38,7 @@
<!-- Pages --> <!-- Pages -->
<intercept-url pattern="/templates/*" access="hasAnyRole('ROLE_SUPERUSER', 'ROLE_TEMPLATES')" /> <intercept-url pattern="/templates/*" access="hasAnyRole('ROLE_SUPERUSER', 'ROLE_TEMPLATES')" />
<intercept-url pattern="/email/*" access="ROLE_SUPERUSER"/> <intercept-url pattern="/email/*" access="hasAnyRole('ROLE_SUPERUSER', 'ROLE_EDIT_EMAIL_TEMPLATES')"/>
<intercept-url pattern="/resources/worker/worker.zul" access="hasAnyRole('ROLE_SUPERUSER', 'ROLE_WORKERS')" /> <intercept-url pattern="/resources/worker/worker.zul" access="hasAnyRole('ROLE_SUPERUSER', 'ROLE_WORKERS')" />
<intercept-url pattern="/resources/machine/*" access="hasAnyRole('ROLE_SUPERUSER', 'ROLE_MACHINES')" /> <intercept-url pattern="/resources/machine/*" access="hasAnyRole('ROLE_SUPERUSER', 'ROLE_MACHINES')" />

View file

@ -42,8 +42,8 @@
<caption label="${i18n:_('General user data')}" /> <caption label="${i18n:_('General user data')}" />
<grid> <grid>
<columns> <columns>
<column width="220px"></column> <column width="220px"/>
<column width="420px"></column> <column width="420px"/>
</columns> </columns>
<rows> <rows>
<row> <row>
@ -128,8 +128,11 @@
</tabpanel> </tabpanel>
</tabpanels> </tabpanels>
</tabbox> </tabbox>
<button onClick="emailTemplateController.save()" autodisable="self" label="${i18n:_('Save')}" sclass="save-button global-action"/> <button onClick="emailTemplateController.save()" autodisable="self" label="${i18n:_('Save')}"
<button onClick="emailTemplateController.cancel()" label="${i18n:_('Cancel')}" sclass="cancel-button global-action"/> sclass="save-button global-action"/>
<button onClick="emailTemplateController.cancel()" label="${i18n:_('Cancel')}"
sclass="cancel-button global-action"/>
</window> </window>
</zk> </zk>

View file

@ -0,0 +1,298 @@
package org.libreplan.web.test.ws.email;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.libreplan.business.common.Registry;
import org.libreplan.business.common.entities.Connector;
import org.libreplan.business.common.entities.ConnectorProperty;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.email.daos.IEmailNotificationDAO;
import org.libreplan.business.email.daos.IEmailTemplateDAO;
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.orders.entities.HoursGroup;
import org.libreplan.business.orders.entities.Order;
import org.libreplan.business.orders.entities.OrderLine;
import org.libreplan.business.orders.entities.SchedulingDataForVersion;
import org.libreplan.business.orders.entities.TaskSource;
import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.planner.daos.ITaskElementDAO;
import org.libreplan.business.planner.entities.Task;
import org.libreplan.business.planner.entities.TaskGroup;
import org.libreplan.business.resources.daos.IWorkerDAO;
import org.libreplan.business.resources.entities.Worker;
import org.libreplan.business.scenarios.bootstrap.IScenariosBootstrap;
import org.libreplan.business.scenarios.entities.OrderVersion;
import org.libreplan.business.settings.entities.Language;
import org.libreplan.business.users.daos.IUserDAO;
import org.libreplan.business.users.entities.User;
import org.libreplan.business.users.entities.UserRole;
import org.libreplan.business.workingday.IntraDayDate;
import org.libreplan.importers.notifications.EmailConnectionValidator;
import org.libreplan.importers.notifications.IEmailNotificationJob;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.annotation.Transactional;
import javax.mail.MessagingException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import static org.easymock.EasyMock.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.libreplan.business.BusinessGlobalNames.BUSINESS_SPRING_CONFIG_FILE;
import static org.libreplan.web.WebappGlobalNames.WEBAPP_SPRING_CONFIG_FILE;
import static org.libreplan.web.WebappGlobalNames.WEBAPP_SPRING_SECURITY_CONFIG_FILE;
import static org.libreplan.web.test.WebappGlobalNames.WEBAPP_SPRING_CONFIG_TEST_FILE;
import static org.libreplan.web.test.WebappGlobalNames.WEBAPP_SPRING_SECURITY_CONFIG_TEST_FILE;
/**
* Tests for {@link EmailTemplate}, {@link EmailNotification}.
*
* @author Created by Vova Perebykivskyi on 06.22.2016.
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
BUSINESS_SPRING_CONFIG_FILE,
WEBAPP_SPRING_CONFIG_FILE,
WEBAPP_SPRING_CONFIG_TEST_FILE,
WEBAPP_SPRING_SECURITY_CONFIG_FILE,
WEBAPP_SPRING_SECURITY_CONFIG_TEST_FILE })
public class EmailTest {
@Autowired
private IEmailTemplateDAO emailTemplateDAO;
@Autowired
private IScenariosBootstrap scenariosBootstrap;
@Autowired
private IEmailNotificationDAO emailNotificationDAO;
@Qualifier("sendEmailOnTaskShouldStart")
@Autowired
private IEmailNotificationJob taskShouldStart;
@Autowired
private IWorkerDAO workerDAO;
@Autowired
private ITaskElementDAO taskElementDAO;
@Autowired
private IUserDAO userDAO;
@Before
public void loadRequiredData() {
scenariosBootstrap.loadRequiredData();
}
@Test
@Transactional
public void testACreateEmailTemplate() {
EmailTemplate emailTemplate = createEmailTemplate();
emailTemplateDAO.save(emailTemplate);
EmailTemplate newEmailTemplate = emailTemplateDAO.findByTypeAndLanguage(
EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_START, Language.ENGLISH_LANGUAGE);
assertEquals(emailTemplate, newEmailTemplate);
}
@Test
@Transactional
public void testBCreateEmailNotification() {
emailTemplateDAO.save(createEmailTemplate());
EmailNotification emailNotification = createEmailNotification();
emailNotificationDAO.save(emailNotification);
try {
EmailNotification newEmailNotification = emailNotificationDAO.find(emailNotification.getId());
assertEquals(emailNotification, newEmailNotification);
} catch (InstanceNotFoundException e) {
e.printStackTrace();
}
}
@Test
@Transactional
public void testCSendEmail() {
EmailTemplate emailTemplate = createEmailTemplate();
emailTemplateDAO.save(emailTemplate);
EmailNotification emailNotification = createEmailNotification();
emailNotificationDAO.save(emailNotification);
// Before sending an Email I should specify email connector properties
createEmailConnector();
/*
* Now I should call taskShouldStart.sendEmail();
* But I will drop on checking email connection properties.
* So I will get exception. Test is over.
* There is no possibility to send message without real connection data.
*/
taskShouldStart.sendEmail();
emailTemplateDAO.delete(emailTemplate);
emailNotificationDAO.deleteAll();
assertTrue(EmailConnectionValidator.exceptionType instanceof MessagingException);
}
private EmailTemplate createEmailTemplate() {
EmailTemplate emailTemplate = new EmailTemplate();
emailTemplate.setType(EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_START);
emailTemplate.setLanguage(Language.ENGLISH_LANGUAGE);
emailTemplate.setSubject("Last words of Dunkan");
emailTemplate.setContent("May He watch over us all...");
return emailTemplate;
}
private EmailNotification createEmailNotification() {
EmailTemplate emailTemplate = emailTemplateDAO.findByTypeAndLanguage(
EmailTemplateEnum.TEMPLATE_TODAY_TASK_SHOULD_START, Language.ENGLISH_LANGUAGE);
EmailNotification emailNotification = new EmailNotification();
emailNotification.setType(emailTemplate.getType());
emailNotification.setUpdated(new Date());
emailNotification.setResource(createWorker());
emailNotification.setProject(createProjectWithTask());
emailNotification.setTask(emailNotification.getProject().getChildren().get(0));
return emailNotification;
}
private Worker createWorker() {
Worker warden = Worker.create();
warden.setFirstName("Alistair");
warden.setSurname("Theirin");
warden.setNif("9:10 Dragon");
warden.setUser(createUser());
workerDAO.save(warden);
return warden;
}
private User createUser() {
User user = User.create("Cole", "Spirit", "vova235@gmail.com");
user.addRole(UserRole.ROLE_EMAIL_TASK_SHOULD_START);
userDAO.save(user);
return user;
}
private TaskGroup createProjectWithTask() {
TaskGroup parent = createTaskGroup();
Task child = createTask();
parent.addTaskElement(child);
taskElementDAO.save(parent);
return parent;
}
private TaskGroup createTaskGroup() {
HoursGroup hoursGroup = new HoursGroup();
hoursGroup.setWorkingHours(6);
Order order = new Order();
order.useSchedulingDataFor(mockOrderVersion());
order.setInitDate(new Date());
OrderLine orderLine = OrderLine.create();
orderLine.setName("Project: Send Email");
order.add(orderLine);
SchedulingDataForVersion version = mockSchedulingDataForVersion(orderLine);
TaskSource taskSource = TaskSource.create(version, Collections.singletonList(hoursGroup));
TaskGroup result = TaskGroup.create(taskSource);
result.setIntraDayEndDate(IntraDayDate.startOfDay(result.getIntraDayStartDate().getDate().plusDays(10)));
return result;
}
private OrderVersion mockOrderVersion() {
OrderVersion result = createNiceMock(OrderVersion.class);
replay(result);
return result;
}
private SchedulingDataForVersion mockSchedulingDataForVersion(OrderElement orderElement) {
SchedulingDataForVersion result = createNiceMock(SchedulingDataForVersion.class);
TaskSource taskSource = createNiceMock(TaskSource.class);
expect(result.getOrderElement()).andReturn(orderElement).anyTimes();
expect(taskSource.getOrderElement()).andReturn(orderElement).anyTimes();
expect(result.getTaskSource()).andReturn(taskSource).anyTimes();
replay(result, taskSource);
return result;
}
private Task createTask() {
HoursGroup hoursGroup = new HoursGroup();
hoursGroup.setWorkingHours(5);
OrderLine orderLine = OrderLine.create();
orderLine.setName("Task: use Quartz");
Order order = new Order();
order.useSchedulingDataFor(mockOrderVersion());
order.setInitDate(new Date());
order.add(orderLine);
SchedulingDataForVersion version = mockSchedulingDataForVersion(orderLine);
TaskSource taskSource = TaskSource.create(version, Collections.singletonList(hoursGroup));
return Task.createTask(taskSource);
}
private void createEmailConnector() {
Connector connector = Connector.create("E-mail");
List<ConnectorProperty> properties = new ArrayList<>();
properties.add(ConnectorProperty.create("Activated", "Y"));
properties.add(ConnectorProperty.create("Protocol", "SMTP"));
properties.add(ConnectorProperty.create("Host", "127.0.0.2"));
properties.add(ConnectorProperty.create("Port", "25"));
properties.add(ConnectorProperty.create("Email sender", "dunkan@libreplan-enterprise.com"));
properties.add(ConnectorProperty.create("Email username", ""));
properties.add(ConnectorProperty.create("Email password", ""));
connector.setProperties(properties);
Registry.getConnectorDAO().save(connector);
}
}

View file

@ -643,6 +643,12 @@ public class OrderElementServiceTest {
assertThat(response.getStatus(), equalTo(Status.OK.getStatusCode())); assertThat(response.getStatus(), equalTo(Status.OK.getStatusCode()));
try { try {
/*
* Flush is needed because
* before there were errors that after removing object some references were still present.
*/
sessionFactory.getCurrentSession().flush();
orderElementDAO.findByCode(codeToRemove); orderElementDAO.findByCode(codeToRemove);
} catch (InstanceNotFoundException e) { } catch (InstanceNotFoundException e) {
assertTrue(true); assertTrue(true);

View file

@ -91,6 +91,12 @@
<value> <value>
org/libreplan/business/scenarios/entities/Scenarios.hbm.xml org/libreplan/business/scenarios/entities/Scenarios.hbm.xml
</value> </value>
<value>
org/libreplan/business/email/entities/Email.hbm.xml
</value>
<value>
org/libreplan/business/common/entities/Connector.hbm.xml
</value>
</list> </list>
</property> </property>

32
pom.xml
View file

@ -125,7 +125,7 @@
<dataSource.url>jdbc:postgresql://localhost/libreplan${libreplan.mode}</dataSource.url> <dataSource.url>jdbc:postgresql://localhost/libreplan${libreplan.mode}</dataSource.url>
<testDataSource.url>${dataSource.url}test</testDataSource.url> <testDataSource.url>${dataSource.url}test</testDataSource.url>
<!-- Hibernate properties --> <!-- Hibernate properties -->
<hibernate.dialect>org.hibernate.dialect.PostgreSQL9Dialect</hibernate.dialect> <hibernate.dialect>org.hibernate.dialect.PostgreSQL82Dialect</hibernate.dialect>
<databasetable.prefix>public.</databasetable.prefix> <databasetable.prefix>public.</databasetable.prefix>
</properties> </properties>
</profile> </profile>
@ -521,7 +521,7 @@
<dependency> <dependency>
<groupId>org.apache.cxf</groupId> <groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http</artifactId> <artifactId>cxf-rt-transports-http</artifactId>
<version>3.1.6</version> <version>3.1.7</version>
<exclusions> <exclusions>
<exclusion> <exclusion>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
@ -541,10 +541,11 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.cxf</groupId> <groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-frontend-jaxrs</artifactId> <artifactId>cxf-rt-frontend-jaxrs</artifactId>
<version>3.1.6</version> <version>3.1.7</version>
<exclusions> <exclusions>
<exclusion> <exclusion>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
@ -560,24 +561,11 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.apache.cxf</groupId> <groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-client</artifactId> <artifactId>cxf-rt-rs-client</artifactId>
<version>3.1.6</version> <version>3.1.7</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
</exclusion>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<!-- Jackson provider --> <!-- Jackson provider -->
@ -653,6 +641,7 @@
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId> <artifactId>slf4j-api</artifactId>
</exclusion> </exclusion>
<exclusion> <exclusion>
<groupId>org.slf4j</groupId> <groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId> <artifactId>slf4j-log4j12</artifactId>
@ -660,6 +649,13 @@
</exclusions> </exclusions>
</dependency> </dependency>
<!-- Java mail -->
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.5.5</version>
</dependency>
</dependencies> </dependencies>
</dependencyManagement> </dependencyManagement>