jira and tim -connector: Refactoring OrderCRUDController and other improvements
- OrderCRUDController refactored - Save or update for OrderSyncInfo instead of creating new instance for each sync - Name change for TimImpExpInfo to SynchronizationInfo - JiraSyncInfo is removed instead SynchronizationInfo is used - All files which are affected by name changes are modified - Translations added where applicable - clean up unused variables etc
This commit is contained in:
parent
cc712d4055
commit
2fc452d1b7
27 changed files with 688 additions and 508 deletions
|
|
@ -59,4 +59,24 @@ public interface IOrderSyncInfoDAO extends IGenericDAO<OrderSyncInfo, Long> {
|
|||
List<OrderSyncInfo> findLastSynchronizedInfosByOrderAndConnectorId(
|
||||
Order order, String connectorId);
|
||||
|
||||
/**
|
||||
* Searches and returns <code>{@link OrderSyncInfo}</code> for the specified
|
||||
* <code>key</code> and <code>connectorId</code>
|
||||
*
|
||||
* @param key
|
||||
* the unique key with in connector id
|
||||
* @param connectorId
|
||||
* the connector id
|
||||
*/
|
||||
OrderSyncInfo findByKeyAndConnectorId(String key, String connectorId);
|
||||
|
||||
/**
|
||||
* Finds the {@link OrderSyncInfo}s for the specified
|
||||
* <code>connectorId</code>
|
||||
*
|
||||
* @param connectorId
|
||||
* the connectorId
|
||||
* @return a list of OrderSyncInfo if found and null if not
|
||||
*/
|
||||
List<OrderSyncInfo> findByConnectorId(String connectorId);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,4 +62,19 @@ public class OrderSyncInfoDAO extends GenericDAOHibernate<OrderSyncInfo, Long>
|
|||
return criteria.list();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OrderSyncInfo findByKeyAndConnectorId(String key, String connectorId) {
|
||||
Criteria criteria = getSession().createCriteria(OrderSyncInfo.class);
|
||||
criteria.add(Restrictions.eq("key", key));
|
||||
criteria.add(Restrictions.eq("connectorId", connectorId));
|
||||
return (OrderSyncInfo) criteria.uniqueResult();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<OrderSyncInfo> findByConnectorId(String connectorId) {
|
||||
Criteria criteria = getSession().createCriteria(OrderSyncInfo.class);
|
||||
criteria.add(Restrictions.eq("connectorId", connectorId));
|
||||
return criteria.list();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ import org.libreplan.business.common.BaseEntity;
|
|||
/**
|
||||
* OrderSyncInfo entity. This entity holds order synchronization info. Each time
|
||||
* that order synchronization is successfully completed, an instance of this
|
||||
* entity is created and saved to DB to hold the synchronized info. This info is
|
||||
* then displayed in UI.
|
||||
* entity is created or updated and saved to DB to hold the synchronized info.
|
||||
* This info is then displayed in UI.
|
||||
*
|
||||
* This entity contains the following fields:
|
||||
* <ul>
|
||||
|
|
@ -49,10 +49,12 @@ public class OrderSyncInfo extends BaseEntity {
|
|||
private String connectorId;
|
||||
private Order order;
|
||||
|
||||
public static OrderSyncInfo create(Order order, String connectorId) {
|
||||
public static OrderSyncInfo create(String key, Order order,
|
||||
String connectorId) {
|
||||
Validate.notEmpty(key);
|
||||
Validate.notNull(order);
|
||||
Validate.notEmpty(connectorId);
|
||||
return create(new OrderSyncInfo(order, connectorId));
|
||||
return create(new OrderSyncInfo(key, order, connectorId));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -61,8 +63,9 @@ public class OrderSyncInfo extends BaseEntity {
|
|||
protected OrderSyncInfo() {
|
||||
}
|
||||
|
||||
private OrderSyncInfo(Order order, String connectorId) {
|
||||
private OrderSyncInfo(String key, Order order, String connectorId) {
|
||||
this.lastSyncDate = new Date();
|
||||
this.key = key;
|
||||
this.order = order;
|
||||
this.connectorId = connectorId;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -213,7 +213,7 @@
|
|||
<comment>Create new table order_sync_info</comment>
|
||||
<createTable tableName="order_sync_info">
|
||||
<column name="id" type="BIGINT">
|
||||
<constraints nullable="false" primaryKey="true" primaryKeyName="order_sync_info_pkey"/>
|
||||
<constraints nullable="false" primaryKey="true"/>
|
||||
</column>
|
||||
<column name="version" type="BIGINT">
|
||||
<constraints nullable="false"/>
|
||||
|
|
@ -288,10 +288,10 @@
|
|||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="job_group" type="VARCHAR(255)" >
|
||||
<constraints nullable="false" primaryKey="true" />
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="job_name" type="VARCHAR(255)" >
|
||||
<constraints nullable="false" primaryKey="true" />
|
||||
<constraints nullable="false" />
|
||||
</column>
|
||||
<column name="cron_expression" type="VARCHAR(255)" >
|
||||
<constraints nullable="false" />
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ public class ExportTimesheetToTimJob extends QuartzJobBean {
|
|||
try {
|
||||
exportTimesheetsToTim.exportTimesheets();
|
||||
LOG.info("Export scuccessful: "
|
||||
+ exportTimesheetsToTim.getExportProcessInfo()
|
||||
+ exportTimesheetsToTim.getSynchronizationInfo()
|
||||
.isSuccessful());
|
||||
} catch (ConnectorException e) {
|
||||
LOG.error("Export timesheet to Tim failed", e);
|
||||
|
|
|
|||
|
|
@ -32,20 +32,17 @@ import org.apache.commons.logging.LogFactory;
|
|||
import org.joda.time.LocalDate;
|
||||
import org.libreplan.business.common.IAdHocTransactionService;
|
||||
import org.libreplan.business.common.IOnTransaction;
|
||||
import org.libreplan.business.common.daos.IConfigurationDAO;
|
||||
import org.libreplan.business.common.daos.IConnectorDAO;
|
||||
import org.libreplan.business.common.entities.Connector;
|
||||
import org.libreplan.business.common.entities.ConnectorException;
|
||||
import org.libreplan.business.common.entities.PredefinedConnectorProperties;
|
||||
import org.libreplan.business.common.entities.PredefinedConnectors;
|
||||
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.libreplan.business.orders.daos.IOrderDAO;
|
||||
import org.libreplan.business.orders.daos.IOrderSyncInfoDAO;
|
||||
import org.libreplan.business.orders.entities.Order;
|
||||
import org.libreplan.business.orders.entities.OrderSyncInfo;
|
||||
import org.libreplan.business.resources.daos.IWorkerDAO;
|
||||
import org.libreplan.business.resources.entities.Worker;
|
||||
import org.libreplan.business.workreports.daos.IWorkReportLineDAO;
|
||||
import org.libreplan.business.workreports.entities.WorkReportLine;
|
||||
import org.libreplan.importers.tim.DurationDTO;
|
||||
import org.libreplan.importers.tim.PersonDTO;
|
||||
|
|
@ -76,12 +73,6 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
|
|||
@Autowired
|
||||
private IWorkerDAO workerDAO;
|
||||
|
||||
@Autowired
|
||||
private IWorkReportLineDAO workReportLineDAO;
|
||||
|
||||
@Autowired
|
||||
private IConfigurationDAO configurationDAO;
|
||||
|
||||
@Autowired
|
||||
IOrderSyncInfoDAO orderSyncInfoDAO;
|
||||
|
||||
|
|
@ -91,10 +82,7 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
|
|||
@Autowired
|
||||
private IConnectorDAO connectorDAO;
|
||||
|
||||
@Autowired
|
||||
private IOrderDAO orderDAO;
|
||||
|
||||
private TimImpExpInfo timImpExpInfo;
|
||||
private SynchronizationInfo synchronizationInfo;
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
|
|
@ -108,23 +96,19 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
|
|||
_("Connection values of Tim connector are invalid"));
|
||||
}
|
||||
|
||||
timImpExpInfo = new TimImpExpInfo(_("Export"));
|
||||
synchronizationInfo = new SynchronizationInfo(_("Export"));
|
||||
|
||||
List<Order> orders = orderDAO.getOrders();
|
||||
for (Order order : orders) {
|
||||
OrderSyncInfo orderSyncInfo = getOrderLastSyncInfo(order);
|
||||
if (orderSyncInfo == null) {
|
||||
LOG.warn("Order '" + order.getName()
|
||||
+ "' is not yet synchronized");
|
||||
timImpExpInfo
|
||||
.addFailedReason(_(
|
||||
"Order '{0}' is not yet synchronized",
|
||||
order.getName()));
|
||||
} else {
|
||||
LOG.info("Exporting '" + order.getName() + "'");
|
||||
exportTimesheets(orderSyncInfo.getKey(),
|
||||
orderSyncInfo.getOrder(), connector);
|
||||
}
|
||||
List<OrderSyncInfo> orderSyncInfos = orderSyncInfoDAO.findByConnectorId(PredefinedConnectors.TIM.getName());
|
||||
if (orderSyncInfos == null || orderSyncInfos.isEmpty()) {
|
||||
LOG.warn("No items found in 'OrderSyncInfo' to export to Tim");
|
||||
synchronizationInfo.addFailedReason(_("No items found in 'OrderSyncInfo' to export to Tim"));
|
||||
return;
|
||||
}
|
||||
|
||||
for (OrderSyncInfo orderSyncInfo : orderSyncInfos) {
|
||||
LOG.info("Exporting '" + orderSyncInfo.getOrder().getName() + "'");
|
||||
exportTimesheets(orderSyncInfo.getKey(), orderSyncInfo.getOrder(),
|
||||
connector);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -133,10 +117,10 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
|
|||
public void exportTimesheets(String productCode, Order order)
|
||||
throws ConnectorException {
|
||||
if (productCode == null || productCode.isEmpty()) {
|
||||
throw new RuntimeException("Product code should not be empty");
|
||||
throw new ConnectorException(_("Product code should not be empty"));
|
||||
}
|
||||
if (order == null) {
|
||||
throw new RuntimeException("Order should not be empty");
|
||||
throw new ConnectorException(_("Order should not be empty"));
|
||||
}
|
||||
|
||||
Connector connector = getTimConnector();
|
||||
|
|
@ -149,7 +133,7 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
|
|||
_("Connection values of Tim connector are invalid"));
|
||||
}
|
||||
|
||||
timImpExpInfo = new TimImpExpInfo(_("Export"));
|
||||
synchronizationInfo = new SynchronizationInfo(_("Export"));
|
||||
|
||||
exportTimesheets(productCode, order, connector);
|
||||
}
|
||||
|
|
@ -187,8 +171,8 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
|
|||
if (workReportLines == null || workReportLines.isEmpty()) {
|
||||
LOG.warn("No work reportlines are found for order: '"
|
||||
+ order.getName() + "'");
|
||||
timImpExpInfo.addFailedReason(_(
|
||||
"No work reportlines are found for order: '{0}'",
|
||||
synchronizationInfo.addFailedReason(_(
|
||||
"No work reportlines are found for order: \"{0}\"",
|
||||
order.getName()));
|
||||
return;
|
||||
}
|
||||
|
|
@ -205,7 +189,7 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
|
|||
|
||||
if (timeRegistrationDTOs.isEmpty()) {
|
||||
LOG.warn("Unable to crate timeregistration for request");
|
||||
timImpExpInfo
|
||||
synchronizationInfo
|
||||
.addFailedReason(_("Unable to crate time registration for request"));
|
||||
return;
|
||||
}
|
||||
|
|
@ -219,15 +203,15 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
|
|||
|
||||
if (timeRegistrationResponseDTO == null) {
|
||||
LOG.error("No response or exception in response");
|
||||
timImpExpInfo
|
||||
.addFailedReason("No response or exception in response");
|
||||
synchronizationInfo
|
||||
.addFailedReason(_("No response or exception in response"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (isRefsListEmpty(timeRegistrationResponseDTO.getRefs())) {
|
||||
LOG.warn("Registration response with empty refs");
|
||||
timImpExpInfo
|
||||
.addFailedReason("Registration response with empty refs");
|
||||
synchronizationInfo
|
||||
.addFailedReason(_("Registration response with empty refs"));
|
||||
return;
|
||||
}
|
||||
saveSyncInfoOnAnotherTransaction(productCode, order);
|
||||
|
|
@ -262,9 +246,14 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
|
|||
.runOnAnotherTransaction(new IOnTransaction<Void>() {
|
||||
@Override
|
||||
public Void execute() {
|
||||
OrderSyncInfo orderSyncInfo = OrderSyncInfo.create(
|
||||
order, PredefinedConnectors.TIM.getName());
|
||||
orderSyncInfo.setKey(productCode);
|
||||
OrderSyncInfo orderSyncInfo = orderSyncInfoDAO
|
||||
.findByKeyAndConnectorId(productCode,
|
||||
PredefinedConnectors.TIM.getName());
|
||||
if (orderSyncInfo == null) {
|
||||
orderSyncInfo = OrderSyncInfo.create(productCode,
|
||||
order, PredefinedConnectors.TIM.getName());
|
||||
}
|
||||
orderSyncInfo.setLastSyncDate(new Date());
|
||||
orderSyncInfoDAO.save(orderSyncInfo);
|
||||
return null;
|
||||
}
|
||||
|
|
@ -288,7 +277,7 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
|
|||
worker = workerDAO.findByCode(workerCode);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
LOG.warn("Worker '" + workerCode + "' not found");
|
||||
timImpExpInfo.addFailedReason(_("Worker '{0}' not found",
|
||||
synchronizationInfo.addFailedReason(_("Worker \"{0}\" not found",
|
||||
workerCode));
|
||||
return null;
|
||||
}
|
||||
|
|
@ -334,8 +323,8 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TimImpExpInfo getExportProcessInfo() {
|
||||
return timImpExpInfo;
|
||||
public SynchronizationInfo getSynchronizationInfo() {
|
||||
return synchronizationInfo;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -69,8 +69,8 @@ public interface IExportTimesheetsToTim {
|
|||
OrderSyncInfo getOrderLastSyncInfo(Order order);
|
||||
|
||||
/**
|
||||
* Returns export process info, success of fail info
|
||||
* Returns synchronization info, success of fail info
|
||||
*/
|
||||
TimImpExpInfo getExportProcessInfo();
|
||||
SynchronizationInfo getSynchronizationInfo();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ public interface IImportRosterFromTim {
|
|||
void importRosters() throws ConnectorException;
|
||||
|
||||
/**
|
||||
* Returns import process info, success of fail info
|
||||
* Returns synchronization info, success of fail info
|
||||
*/
|
||||
TimImpExpInfo getImportProcessInfo();
|
||||
SynchronizationInfo getSynchronizationInfo();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -50,8 +50,10 @@ public interface IJiraOrderElementSynchronizer {
|
|||
* https://jira.atlassian.com/browse/JRA-29409
|
||||
*
|
||||
* @return A list of labels
|
||||
* @throws ConnectorException
|
||||
* if connector not found
|
||||
*/
|
||||
List<String> getAllJiraLabels();
|
||||
List<String> getAllJiraLabels() throws ConnectorException;
|
||||
|
||||
/**
|
||||
* Get all jira issues based on the specified <code>label</code> parameter
|
||||
|
|
@ -108,6 +110,6 @@ public interface IJiraOrderElementSynchronizer {
|
|||
/**
|
||||
* returns synchronization info, success or fail info
|
||||
*/
|
||||
JiraSyncInfo getJiraSyncInfo();
|
||||
SynchronizationInfo getSynchronizationInfo();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,6 +59,6 @@ public interface IJiraTimesheetSynchronizer {
|
|||
/**
|
||||
* returns synchronization info, success or fail info
|
||||
*/
|
||||
JiraSyncInfo getJiraSyncInfo();
|
||||
SynchronizationInfo getSynchronizationInfo();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,14 +40,12 @@ import org.libreplan.business.calendars.entities.PredefinedCalendarExceptionType
|
|||
import org.libreplan.business.calendars.entities.ResourceCalendar;
|
||||
import org.libreplan.business.common.IAdHocTransactionService;
|
||||
import org.libreplan.business.common.IOnTransaction;
|
||||
import org.libreplan.business.common.daos.IConfigurationDAO;
|
||||
import org.libreplan.business.common.daos.IConnectorDAO;
|
||||
import org.libreplan.business.common.entities.Connector;
|
||||
import org.libreplan.business.common.entities.ConnectorException;
|
||||
import org.libreplan.business.common.entities.PredefinedConnectorProperties;
|
||||
import org.libreplan.business.common.entities.PredefinedConnectors;
|
||||
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.libreplan.business.resources.daos.IResourceDAO;
|
||||
import org.libreplan.business.resources.daos.IWorkerDAO;
|
||||
import org.libreplan.business.resources.entities.Worker;
|
||||
import org.libreplan.business.workingday.EffortDuration;
|
||||
|
|
@ -62,7 +60,6 @@ import org.libreplan.importers.tim.RosterDTO;
|
|||
import org.libreplan.importers.tim.RosterRequestDTO;
|
||||
import org.libreplan.importers.tim.RosterResponseDTO;
|
||||
import org.libreplan.web.calendars.IBaseCalendarModel;
|
||||
import org.libreplan.web.resources.worker.IWorkerModel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
|
|
@ -81,18 +78,9 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
|
|||
|
||||
private static final Log LOG = LogFactory.getLog(ImportRosterFromTim.class);
|
||||
|
||||
@Autowired
|
||||
private IConfigurationDAO configurationDAO;
|
||||
|
||||
@Autowired
|
||||
private IWorkerDAO workerDAO;
|
||||
|
||||
@Autowired
|
||||
private IResourceDAO resourceDAO;
|
||||
|
||||
@Autowired
|
||||
private IWorkerModel workerModel;
|
||||
|
||||
@Autowired
|
||||
private IConnectorDAO connectorDAO;
|
||||
|
||||
|
|
@ -106,7 +94,7 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
|
|||
@Qualifier("subclass")
|
||||
private IBaseCalendarModel baseCalendarModel;
|
||||
|
||||
private TimImpExpInfo timImpExpInfo;
|
||||
private SynchronizationInfo synchronizationInfo;
|
||||
|
||||
/**
|
||||
* Search criteria for roster exception days in RESPONSE message
|
||||
|
|
@ -168,7 +156,7 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
|
|||
String[] departmentIdsArray = StringUtils.stripAll(StringUtils.split(
|
||||
departmentIds, ","));
|
||||
|
||||
timImpExpInfo = new TimImpExpInfo(_("Import"));
|
||||
synchronizationInfo = new SynchronizationInfo(_("Import"));
|
||||
|
||||
for (String department : departmentIdsArray) {
|
||||
LOG.info("Department: " + department);
|
||||
|
|
@ -183,8 +171,9 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
|
|||
productivityFactor);
|
||||
} else {
|
||||
LOG.error("No valid response for department " + department);
|
||||
timImpExpInfo.addFailedReason(_(
|
||||
"No valid response for department '{0}'", department));
|
||||
synchronizationInfo.addFailedReason(_(
|
||||
"No valid response for department \"{0}\"",
|
||||
department));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -208,7 +197,7 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
|
|||
updateCalendarException(rosterExceptions);
|
||||
} else {
|
||||
LOG.info("No roster-exceptions found in the response");
|
||||
timImpExpInfo
|
||||
synchronizationInfo
|
||||
.addFailedReason(_("No roster-exceptions found in the response"));
|
||||
}
|
||||
return null;
|
||||
|
|
@ -237,7 +226,8 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
|
|||
worker = workerDAO.findUniqueByNif(workerCode);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
LOG.warn("Worker '" + workerCode + "' not found");
|
||||
timImpExpInfo.addFailedReason(_("Worker '{0}' not found",
|
||||
synchronizationInfo.addFailedReason(_(
|
||||
"Worker \"{0}\" not found",
|
||||
workerCode));
|
||||
}
|
||||
if (worker != null) {
|
||||
|
|
@ -353,7 +343,7 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
|
|||
private CalendarExceptionType getCalendarExceptionType(String name) {
|
||||
if (name == null || name.isEmpty()) {
|
||||
LOG.error("Exception name should not be empty");
|
||||
timImpExpInfo
|
||||
synchronizationInfo
|
||||
.addFailedReason(_("Exception name should not be empty"));
|
||||
return null;
|
||||
}
|
||||
|
|
@ -369,7 +359,7 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
|
|||
return calendarExceptionTypeDAO.findUniqueByName(nameToSearch);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
LOG.error("Calendar exceptionType not found", e);
|
||||
timImpExpInfo
|
||||
synchronizationInfo
|
||||
.addFailedReason(_("Calendar exception day not found"));
|
||||
}
|
||||
return null;
|
||||
|
|
@ -465,7 +455,7 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TimImpExpInfo getImportProcessInfo() {
|
||||
return timImpExpInfo;
|
||||
public SynchronizationInfo getSynchronizationInfo() {
|
||||
return synchronizationInfo;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ public class ImportRosterFromTimJob extends QuartzJobBean {
|
|||
try {
|
||||
importRosterFromTim.importRosters();
|
||||
LOG.info("Import scuccessful: "
|
||||
+ importRosterFromTim.getImportProcessInfo().isSuccessful());
|
||||
+ importRosterFromTim.getSynchronizationInfo().isSuccessful());
|
||||
} catch (ConnectorException e) {
|
||||
LOG.error("Import roster from Tim failed", e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
|
||||
public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchronizer {
|
||||
|
||||
private JiraSyncInfo jiraSyncInfo;
|
||||
private SynchronizationInfo synchronizationInfo;
|
||||
|
||||
@Autowired
|
||||
private IConnectorDAO connectorDAO;
|
||||
|
|
@ -82,10 +82,10 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz
|
|||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public List<String> getAllJiraLabels() {
|
||||
public List<String> getAllJiraLabels() throws ConnectorException {
|
||||
Connector connector = getJiraConnector();
|
||||
if (connector == null) {
|
||||
return null;
|
||||
throw new ConnectorException(_("JIRA connector not found"));
|
||||
}
|
||||
|
||||
String jiraLabels = connector.getPropertiesAsMap().get(
|
||||
|
|
@ -137,7 +137,7 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz
|
|||
@Transactional(readOnly = true)
|
||||
public void syncOrderElementsWithJiraIssues(List<IssueDTO> issues, Order order) {
|
||||
|
||||
jiraSyncInfo = new JiraSyncInfo();
|
||||
synchronizationInfo = new SynchronizationInfo(_("Synchronization"));
|
||||
|
||||
for (IssueDTO issue : issues) {
|
||||
String code = PredefinedConnectorProperties.JIRA_CODE_PREFIX
|
||||
|
|
@ -147,8 +147,9 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz
|
|||
|
||||
OrderLine orderLine = syncOrderLine(order, code, name);
|
||||
if (orderLine == null) {
|
||||
jiraSyncInfo.addSyncFailedReason("Order-element for '"
|
||||
+ issue.getKey() + "' issue not found");
|
||||
synchronizationInfo.addFailedReason(_(
|
||||
"Order-element for \"{0}\" issue not found",
|
||||
issue.getKey()));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -158,8 +159,9 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz
|
|||
.getTimetracking(), loggedHours);
|
||||
|
||||
if (estimatedHours.isZero()) {
|
||||
jiraSyncInfo.addSyncFailedReason("Estimated time for '"
|
||||
+ issue.getKey() + "' issue is 0");
|
||||
synchronizationInfo.addFailedReason(_(
|
||||
"Estimated time for \"{0}\" issue is 0",
|
||||
issue.getKey()));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -246,15 +248,16 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz
|
|||
WorkLogDTO workLog = issue.getFields().getWorklog();
|
||||
|
||||
if (workLog == null) {
|
||||
jiraSyncInfo.addSyncFailedReason("No worklogs found for '"
|
||||
+ issue.getKey() + "' issue");
|
||||
synchronizationInfo.addFailedReason(_(
|
||||
"No worklogs found for \"{0}\" issue", issue.getKey()));
|
||||
return;
|
||||
}
|
||||
|
||||
List<WorkLogItemDTO> workLogItems = workLog.getWorklogs();
|
||||
if (workLogItems.isEmpty()) {
|
||||
jiraSyncInfo.addSyncFailedReason("No worklog items found for '"
|
||||
+ issue.getKey() + "' issue");
|
||||
synchronizationInfo.addFailedReason(_(
|
||||
"No worklog items found for \"{0}\" issue",
|
||||
issue.getKey()));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -363,9 +366,10 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz
|
|||
} catch (DuplicateAdvanceAssignmentForOrderElementException e) {
|
||||
// This could happen if a parent or child of the current
|
||||
// OrderElement has an advance of type PERCENTAGE
|
||||
jiraSyncInfo
|
||||
.addSyncFailedReason("Duplicate value AdvanceAssignment for order element of '"
|
||||
+ orderElement.getCode() + "'");
|
||||
synchronizationInfo
|
||||
.addFailedReason(_(
|
||||
"Duplicate value AdvanceAssignment for order element of \"{0}\"",
|
||||
orderElement.getCode()));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -422,8 +426,8 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz
|
|||
}
|
||||
|
||||
@Override
|
||||
public JiraSyncInfo getJiraSyncInfo() {
|
||||
return jiraSyncInfo;
|
||||
public SynchronizationInfo getSynchronizationInfo() {
|
||||
return synchronizationInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -437,9 +441,13 @@ public class JiraOrderElementSynchronizer implements IJiraOrderElementSynchroniz
|
|||
@Override
|
||||
@Transactional
|
||||
public void saveSyncInfo(String key, Order order) {
|
||||
OrderSyncInfo orderSyncInfo = OrderSyncInfo.create(order,
|
||||
PredefinedConnectors.JIRA.getName());
|
||||
orderSyncInfo.setKey(key);
|
||||
OrderSyncInfo orderSyncInfo = orderSyncInfoDAO.findByKeyAndConnectorId(
|
||||
key, PredefinedConnectors.JIRA.getName());
|
||||
if (orderSyncInfo == null) {
|
||||
orderSyncInfo = OrderSyncInfo.create(key, order,
|
||||
PredefinedConnectors.JIRA.getName());
|
||||
}
|
||||
orderSyncInfo.setLastSyncDate(new Date());
|
||||
orderSyncInfoDAO.save(orderSyncInfo);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* This file is part of LibrePlan
|
||||
*
|
||||
* Copyright (C) 2013 St. Antoniusziekenhuis
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.libreplan.importers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Keeps track the synchronization info.
|
||||
*
|
||||
* @author Miciele Ghiorghis <m.ghiorghis@antoniusziekenhuis.nl>
|
||||
*/
|
||||
public class JiraSyncInfo {
|
||||
|
||||
private List<String> syncFailedReasons = new ArrayList<String>();
|
||||
|
||||
/**
|
||||
* Add the specified <code>reason</code> to syncFailedReasons list
|
||||
*
|
||||
* @param reason
|
||||
* reason why synchronizition failed
|
||||
*/
|
||||
public void addSyncFailedReason(String reason) {
|
||||
syncFailedReasons.add(reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is synchronization successful
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public boolean isSyncSuccessful() {
|
||||
return syncFailedReasons.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* returns reasons why synchronization is failed
|
||||
*/
|
||||
public List<String> getSyncFailedReasons() {
|
||||
return Collections.unmodifiableList(syncFailedReasons);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -44,7 +44,6 @@ import org.libreplan.business.resources.entities.Resource;
|
|||
import org.libreplan.business.resources.entities.Worker;
|
||||
import org.libreplan.business.workingday.EffortDuration;
|
||||
import org.libreplan.business.workreports.daos.IWorkReportDAO;
|
||||
import org.libreplan.business.workreports.daos.IWorkReportLineDAO;
|
||||
import org.libreplan.business.workreports.daos.IWorkReportTypeDAO;
|
||||
import org.libreplan.business.workreports.entities.PredefinedWorkReportTypes;
|
||||
import org.libreplan.business.workreports.entities.WorkReport;
|
||||
|
|
@ -71,7 +70,7 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
|
||||
public class JiraTimesheetSynchronizer implements IJiraTimesheetSynchronizer {
|
||||
|
||||
private JiraSyncInfo jiraSyncInfo;
|
||||
private SynchronizationInfo synchronizationInfo;
|
||||
|
||||
private List<Worker> workers;
|
||||
|
||||
|
|
@ -88,9 +87,6 @@ public class JiraTimesheetSynchronizer implements IJiraTimesheetSynchronizer {
|
|||
@Autowired
|
||||
private IWorkReportDAO workReportDAO;
|
||||
|
||||
@Autowired
|
||||
private IWorkReportLineDAO workReportLineDAO;
|
||||
|
||||
@Autowired
|
||||
private IWorkReportModel workReportModel;
|
||||
|
||||
|
|
@ -109,14 +105,14 @@ public class JiraTimesheetSynchronizer implements IJiraTimesheetSynchronizer {
|
|||
@Override
|
||||
@Transactional
|
||||
public void syncJiraTimesheetWithJiraIssues(List<IssueDTO> issues, Order order) throws ConnectorException {
|
||||
jiraSyncInfo = new JiraSyncInfo();
|
||||
synchronizationInfo = new SynchronizationInfo(_("Synchronization"));
|
||||
|
||||
workReportType = getJiraTimesheetsWorkReportType();
|
||||
typeOfWorkHours = getTypeOfWorkHours();
|
||||
|
||||
workers = getWorkers();
|
||||
if (workers == null && workers.isEmpty()) {
|
||||
jiraSyncInfo.addSyncFailedReason("No workers found");
|
||||
synchronizationInfo.addFailedReason(_("No workers found"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -124,13 +120,15 @@ public class JiraTimesheetSynchronizer implements IJiraTimesheetSynchronizer {
|
|||
.findLastSynchronizedInfoByOrderAndConnectorId(order,
|
||||
PredefinedConnectors.JIRA.getName());
|
||||
if (orderSyncInfo == null) {
|
||||
jiraSyncInfo.addSyncFailedReason("Order '" + order.getName()
|
||||
+ "' not found. Order probalbly not synchronized");
|
||||
synchronizationInfo.addFailedReason(_(
|
||||
"Order \"{0}\" not found. Order probalbly not synchronized",
|
||||
order.getName()));
|
||||
return;
|
||||
}
|
||||
if (StringUtils.isBlank(orderSyncInfo.getKey())) {
|
||||
jiraSyncInfo.addSyncFailedReason("Key for Order '"
|
||||
+ order.getName() + "' is empty");
|
||||
synchronizationInfo.addFailedReason(_(
|
||||
"Key for Order \"{0}\" is empty",
|
||||
order.getName()));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -141,14 +139,14 @@ public class JiraTimesheetSynchronizer implements IJiraTimesheetSynchronizer {
|
|||
for (IssueDTO issue : issues) {
|
||||
WorkLogDTO worklog = issue.getFields().getWorklog();
|
||||
if (worklog == null) {
|
||||
jiraSyncInfo.addSyncFailedReason("No worklogs found for '"
|
||||
+ issue.getKey() + "'");
|
||||
synchronizationInfo.addFailedReason(_(
|
||||
"No worklogs found for \"{0}\" key", issue.getKey()));
|
||||
} else {
|
||||
List<WorkLogItemDTO> workLogItems = worklog.getWorklogs();
|
||||
if (workLogItems == null || workLogItems.isEmpty()) {
|
||||
jiraSyncInfo
|
||||
.addSyncFailedReason("No worklog items found for '"
|
||||
+ issue.getKey() + "' issue");
|
||||
synchronizationInfo.addFailedReason(_(
|
||||
"No worklog items found for \"{0}\" issue",
|
||||
issue.getKey()));
|
||||
} else {
|
||||
|
||||
String codeOrderElement = PredefinedConnectorProperties.JIRA_CODE_PREFIX
|
||||
|
|
@ -157,8 +155,8 @@ public class JiraTimesheetSynchronizer implements IJiraTimesheetSynchronizer {
|
|||
OrderElement orderElement = order.getOrderElement(codeOrderElement);
|
||||
|
||||
if (orderElement == null) {
|
||||
jiraSyncInfo.addSyncFailedReason("Order element("
|
||||
+ code + ") not found");
|
||||
synchronizationInfo.addFailedReason(_(
|
||||
"Order element \"{0}\" not found", code));
|
||||
} else {
|
||||
updateOrCreateWorkReportLineAndAddToWorkReport(workReport, orderElement,
|
||||
workLogItems);
|
||||
|
|
@ -382,13 +380,13 @@ public class JiraTimesheetSynchronizer implements IJiraTimesheetSynchronizer {
|
|||
return worker;
|
||||
}
|
||||
}
|
||||
jiraSyncInfo.addSyncFailedReason("Worker('" + nif + "') not found");
|
||||
synchronizationInfo.addFailedReason(_("Worker \"{0}\" not found", nif));
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public JiraSyncInfo getJiraSyncInfo() {
|
||||
return jiraSyncInfo;
|
||||
public SynchronizationInfo getSynchronizationInfo() {
|
||||
return synchronizationInfo;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,14 +24,15 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Keeps track the success/failure of Tim's import and/or export process
|
||||
* Keeps track the success/failure of synchronization process
|
||||
*
|
||||
* @author Miciele Ghiorghis <m.ghiorghis@antoniusziekenhuis.nl>
|
||||
*/
|
||||
public class TimImpExpInfo {
|
||||
public class SynchronizationInfo {
|
||||
|
||||
/**
|
||||
* action, import or export process
|
||||
* The action, a unique key for example synchronization, import or export
|
||||
* etc action
|
||||
*/
|
||||
private String action;
|
||||
|
||||
|
|
@ -40,7 +41,7 @@ public class TimImpExpInfo {
|
|||
*/
|
||||
private List<String> failedReasons = new ArrayList<String>();
|
||||
|
||||
public TimImpExpInfo(String action) {
|
||||
public SynchronizationInfo(String action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
|
|
@ -55,14 +56,14 @@ public class TimImpExpInfo {
|
|||
* Adds the specified <code>reason</code> to <code>failedReasons<code> list
|
||||
*
|
||||
* @param reason
|
||||
* reason why import/export failed
|
||||
* reason why synchronization is failed
|
||||
*/
|
||||
public void addFailedReason(String reason) {
|
||||
failedReasons.add(reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is import or export succeeded
|
||||
* Is synchronization succeeded
|
||||
*
|
||||
* @return true if <code>failedReasons</code> is empty
|
||||
*/
|
||||
|
|
@ -71,7 +72,7 @@ public class TimImpExpInfo {
|
|||
}
|
||||
|
||||
/**
|
||||
* returns reasons why import or export failed
|
||||
* returns reasons why synchronization is failed
|
||||
*/
|
||||
public List<String> getFailedReasons() {
|
||||
return Collections.unmodifiableList(failedReasons);
|
||||
|
|
@ -26,7 +26,7 @@ import org.libreplan.business.common.entities.ConnectorException;
|
|||
import org.libreplan.business.common.entities.JobSchedulerConfiguration;
|
||||
import org.libreplan.business.common.entities.PredefinedConnectorProperties;
|
||||
import org.libreplan.business.common.exceptions.ValidationException;
|
||||
import org.libreplan.importers.TimImpExpInfo;
|
||||
import org.libreplan.importers.SynchronizationInfo;
|
||||
|
||||
/**
|
||||
* Contract for {@link JobSchedulerModel}.
|
||||
|
|
@ -64,9 +64,9 @@ public interface IJobSchedulerModel {
|
|||
throws ConnectorException;
|
||||
|
||||
/**
|
||||
* Returns import/export info. Failure or success info
|
||||
* Returns synchronization info. Failure or success info
|
||||
*/
|
||||
TimImpExpInfo getImportExportInfo();
|
||||
SynchronizationInfo getSynchronizationInfo();
|
||||
|
||||
/**
|
||||
* Prepares for create a new {@link JobSchedulerConfiguration}.
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ import org.libreplan.business.common.entities.JobClassNameEnum;
|
|||
import org.libreplan.business.common.entities.JobSchedulerConfiguration;
|
||||
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.libreplan.business.common.exceptions.ValidationException;
|
||||
import org.libreplan.importers.TimImpExpInfo;
|
||||
import org.libreplan.importers.SynchronizationInfo;
|
||||
import org.quartz.CronExpression;
|
||||
import org.zkoss.zk.ui.Component;
|
||||
import org.zkoss.zk.ui.Executions;
|
||||
|
|
@ -212,11 +212,11 @@ public class JobSchedulerController extends
|
|||
private void shwoImpExpInfo() {
|
||||
Map<String, Object> args = new HashMap<String, Object>();
|
||||
|
||||
TimImpExpInfo timImpExpInfo = jobSchedulerModel.getImportExportInfo();
|
||||
args.put("action", timImpExpInfo.getAction());
|
||||
args.put("showSuccess", timImpExpInfo.isSuccessful());
|
||||
SynchronizationInfo synchronizationInfo = jobSchedulerModel.getSynchronizationInfo();
|
||||
args.put("action", synchronizationInfo.getAction());
|
||||
args.put("showSuccess", synchronizationInfo.isSuccessful());
|
||||
args.put("failedReasons",
|
||||
new SimpleListModel(timImpExpInfo.getFailedReasons()));
|
||||
new SimpleListModel(synchronizationInfo.getFailedReasons()));
|
||||
|
||||
Window timImpExpInfoWindow = (Window) Executions.createComponents(
|
||||
"/orders/_timImpExpInfo.zul", null, args);
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ import org.libreplan.business.common.exceptions.ValidationException;
|
|||
import org.libreplan.importers.IExportTimesheetsToTim;
|
||||
import org.libreplan.importers.IImportRosterFromTim;
|
||||
import org.libreplan.importers.ISchedulerManager;
|
||||
import org.libreplan.importers.TimImpExpInfo;
|
||||
import org.libreplan.importers.SynchronizationInfo;
|
||||
import org.libreplan.web.common.concurrentdetection.OnConcurrentModification;
|
||||
import org.quartz.SchedulerException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
|
@ -69,7 +69,7 @@ public class JobSchedulerModel implements IJobSchedulerModel {
|
|||
@Autowired
|
||||
private IExportTimesheetsToTim exportTimesheetsToTim;
|
||||
|
||||
private TimImpExpInfo timImpExpInfo;
|
||||
private SynchronizationInfo synchronizationInfo;
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
|
|
@ -89,19 +89,19 @@ public class JobSchedulerModel implements IJobSchedulerModel {
|
|||
String name = jobSchedulerConfiguration.getJobClassName().getName();
|
||||
if (name.equals(JobClassNameEnum.IMPORT_ROSTER_FROM_TIM_JOB.getName())) {
|
||||
importRosterFromTim.importRosters();
|
||||
timImpExpInfo = importRosterFromTim.getImportProcessInfo();
|
||||
synchronizationInfo = importRosterFromTim.getSynchronizationInfo();
|
||||
return;
|
||||
}
|
||||
if (name.equals(JobClassNameEnum.EXPORT_TIMESHEET_TO_TIM_JOB.getName())) {
|
||||
exportTimesheetsToTim.exportTimesheets();
|
||||
timImpExpInfo = exportTimesheetsToTim.getExportProcessInfo();
|
||||
synchronizationInfo = exportTimesheetsToTim.getSynchronizationInfo();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimImpExpInfo getImportExportInfo() {
|
||||
return timImpExpInfo;
|
||||
public SynchronizationInfo getSynchronizationInfo() {
|
||||
return synchronizationInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -0,0 +1,359 @@
|
|||
/*
|
||||
* This file is part of LibrePlan
|
||||
*
|
||||
* Copyright (C) 2013 St. Antoniusziekenhuis
|
||||
*
|
||||
* 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.orders;
|
||||
|
||||
import static org.libreplan.web.I18nHelper._;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.libreplan.business.common.daos.IConnectorDAO;
|
||||
import org.libreplan.business.common.entities.Connector;
|
||||
import org.libreplan.business.common.entities.ConnectorException;
|
||||
import org.libreplan.business.common.entities.PredefinedConnectors;
|
||||
import org.libreplan.business.orders.entities.Order;
|
||||
import org.libreplan.business.orders.entities.OrderSyncInfo;
|
||||
import org.libreplan.importers.IJiraOrderElementSynchronizer;
|
||||
import org.libreplan.importers.IJiraTimesheetSynchronizer;
|
||||
import org.libreplan.importers.SynchronizationInfo;
|
||||
import org.libreplan.importers.jira.IssueDTO;
|
||||
import org.libreplan.web.common.IMessagesForUser;
|
||||
import org.libreplan.web.common.Level;
|
||||
import org.libreplan.web.common.MessagesForUser;
|
||||
import org.libreplan.web.common.Util;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.zkoss.zk.ui.Component;
|
||||
import org.zkoss.zk.ui.Executions;
|
||||
import org.zkoss.zk.ui.SuspendNotAllowedException;
|
||||
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.util.GenericForwardComposer;
|
||||
import org.zkoss.zul.Button;
|
||||
import org.zkoss.zul.Combobox;
|
||||
import org.zkoss.zul.ListModel;
|
||||
import org.zkoss.zul.Popup;
|
||||
import org.zkoss.zul.SimpleListModel;
|
||||
import org.zkoss.zul.Tab;
|
||||
import org.zkoss.zul.Textbox;
|
||||
import org.zkoss.zul.api.Groupbox;
|
||||
import org.zkoss.zul.api.Window;
|
||||
|
||||
/**
|
||||
* Controller for JIRA synchronization
|
||||
*
|
||||
* @author Miciele Ghiorghis <m.ghiorghis@antoniusziekenhuis.nl>
|
||||
*/
|
||||
public class JiraSynchronizationController extends GenericForwardComposer {
|
||||
|
||||
private static final org.apache.commons.logging.Log LOG = LogFactory
|
||||
.getLog(JiraSynchronizationController.class);
|
||||
|
||||
private OrderCRUDController orderController;
|
||||
|
||||
private Window editWindow;
|
||||
|
||||
private Groupbox jiraGroupBox;
|
||||
|
||||
private Popup jirasyncPopup;
|
||||
|
||||
private Button startJiraSyncButton, cancelJiraSyncButton,
|
||||
syncWithJiraButton;
|
||||
|
||||
private Textbox txtImportedLabel, txtLastSyncDate;
|
||||
|
||||
private Combobox comboJiraLabel;
|
||||
|
||||
private IMessagesForUser messagesForUser;
|
||||
|
||||
private Component messagesContainer;
|
||||
|
||||
@Autowired
|
||||
private IJiraOrderElementSynchronizer jiraOrderElementSynchronizer;
|
||||
|
||||
@Autowired
|
||||
private IJiraTimesheetSynchronizer jiraTimesheetSynchronizer;
|
||||
|
||||
@Autowired
|
||||
private IConnectorDAO connectorDAO;
|
||||
|
||||
@Override
|
||||
public void doAfterCompose(Component comp) throws Exception {
|
||||
super.doAfterCompose(comp);
|
||||
comp.setVariable("jiraSynchroniaztionController", this, true);
|
||||
loadComponentsEditWindow();
|
||||
showOrHideJiraEditWindow();
|
||||
updateOrderLastSyncInfoScreen();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current {@link Order}
|
||||
*/
|
||||
private Order getOrder() {
|
||||
return orderController.getOrder();
|
||||
}
|
||||
|
||||
private void loadComponentsEditWindow() {
|
||||
txtLastSyncDate = (Textbox) editWindow
|
||||
.getFellowIfAny("txtLastSyncDate");
|
||||
txtImportedLabel = (Textbox) editWindow
|
||||
.getFellowIfAny("txtImportedLabel");
|
||||
jiraGroupBox = (Groupbox) editWindow.getFellowIfAny("jiraGroupBox");
|
||||
syncWithJiraButton = (Button) editWindow
|
||||
.getFellow("syncWithJiraButton");
|
||||
messagesForUser = new MessagesForUser(messagesContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show or hide <code>JiraEditWindow</code> based on JIRA
|
||||
* {@link Connector#isActivated()}
|
||||
*/
|
||||
private void showOrHideJiraEditWindow() {
|
||||
jiraGroupBox.setVisible(isJiraActivated());
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the UI text last synchronized date and the text imported label
|
||||
*/
|
||||
private void updateOrderLastSyncInfoScreen() {
|
||||
OrderSyncInfo orderSyncInfo = jiraOrderElementSynchronizer
|
||||
.getOrderLastSyncInfo(getOrder());
|
||||
|
||||
if (orderSyncInfo != null) {
|
||||
txtLastSyncDate.setValue(Util.formatDateTime(orderSyncInfo
|
||||
.getLastSyncDate()));
|
||||
txtImportedLabel.setValue(orderSyncInfo.getKey());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if jira is Activated. Used to show/hide Jira edit window
|
||||
*/
|
||||
public boolean isJiraActivated() {
|
||||
Connector connector = connectorDAO
|
||||
.findUniqueByName(PredefinedConnectors.JIRA.getName());
|
||||
if (connector == null) {
|
||||
return false;
|
||||
}
|
||||
return connector.isActivated();
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronize with Jira
|
||||
*/
|
||||
public void syncWithJira() {
|
||||
try {
|
||||
List<String> items = jiraOrderElementSynchronizer
|
||||
.getAllJiraLabels();
|
||||
|
||||
if (!(txtImportedLabel.getText()).isEmpty()) {
|
||||
startSyncWithJira(txtImportedLabel.getText());
|
||||
return;
|
||||
}
|
||||
|
||||
setupJiraSyncPopup(editWindow, new SimpleListModelExt(items));
|
||||
|
||||
jirasyncPopup.open(syncWithJiraButton, "before_start");
|
||||
|
||||
} catch (ConnectorException e) {
|
||||
messagesForUser.showMessage(Level.ERROR,
|
||||
_("Failed: {0}", e.getMessage()));
|
||||
} catch (WebApplicationException e) {
|
||||
LOG.info(e);
|
||||
messagesForUser.showMessage(Level.ERROR,
|
||||
_("Cannot connect to JIRA server"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start synchronize with jira for the specified <code>label</code>
|
||||
*
|
||||
* @param label
|
||||
* the jira label
|
||||
*/
|
||||
public void startSyncWithJira(String label) {
|
||||
try {
|
||||
Order order = getOrder();
|
||||
|
||||
List<IssueDTO> issues = jiraOrderElementSynchronizer
|
||||
.getJiraIssues(label);
|
||||
|
||||
if (issues == null || issues.isEmpty()) {
|
||||
messagesForUser.showMessage(Level.ERROR,
|
||||
_("No JIRA issues to import"));
|
||||
return;
|
||||
}
|
||||
|
||||
order.setCodeAutogenerated(false);
|
||||
|
||||
jiraOrderElementSynchronizer.syncOrderElementsWithJiraIssues(
|
||||
issues, order);
|
||||
|
||||
orderController.saveAndContinue(false);
|
||||
|
||||
jiraOrderElementSynchronizer.saveSyncInfo(label, order);
|
||||
|
||||
if (jirasyncPopup != null) {
|
||||
jirasyncPopup.close();
|
||||
}
|
||||
|
||||
jiraTimesheetSynchronizer.syncJiraTimesheetWithJiraIssues(issues,
|
||||
order);
|
||||
|
||||
showSyncInfo();
|
||||
|
||||
// Reload order info in all tabs
|
||||
Tab previousTab = orderController.getCurrentTab();
|
||||
orderController.initEdit(order);
|
||||
orderController.selectTab(previousTab.getId());
|
||||
} catch (ConnectorException e) {
|
||||
messagesForUser.showMessage(Level.ERROR,
|
||||
_("Failed: {0}", e.getMessage()));
|
||||
} catch (WebApplicationException e) {
|
||||
LOG.info(e);
|
||||
messagesForUser.showMessage(Level.ERROR,
|
||||
_("Cannot connect to JIRA server"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows the success or failure info of synchronization
|
||||
*/
|
||||
private void showSyncInfo() {
|
||||
Map<String, Object> args = new HashMap<String, Object>();
|
||||
|
||||
SynchronizationInfo syncOrderElementInfo = jiraOrderElementSynchronizer
|
||||
.getSynchronizationInfo();
|
||||
|
||||
boolean succeeded = isSyncSucceeded(syncOrderElementInfo);
|
||||
|
||||
args.put("syncOrderElementSuccess", succeeded);
|
||||
if (syncOrderElementInfo != null) {
|
||||
args.put("syncOrderElementFailedReasons", new SimpleListModel(
|
||||
syncOrderElementInfo.getFailedReasons()));
|
||||
}
|
||||
|
||||
SynchronizationInfo jiraSyncInfoTimesheet = jiraTimesheetSynchronizer
|
||||
.getSynchronizationInfo();
|
||||
|
||||
succeeded = isSyncSucceeded(jiraSyncInfoTimesheet);
|
||||
|
||||
args.put("syncTimesheetSuccess", succeeded);
|
||||
if (jiraSyncInfoTimesheet != null) {
|
||||
args.put("syncTimesheetFailedReasons", new SimpleListModel(
|
||||
jiraSyncInfoTimesheet.getFailedReasons()));
|
||||
}
|
||||
|
||||
Window jiraSyncInfoWindow = (Window) Executions.createComponents(
|
||||
"/orders/_jiraSyncInfo.zul", null, args);
|
||||
|
||||
try {
|
||||
jiraSyncInfoWindow.doModal();
|
||||
} catch (SuspendNotAllowedException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSyncSucceeded(SynchronizationInfo syncInfo) {
|
||||
if (syncInfo == null) {
|
||||
return false;
|
||||
}
|
||||
return syncInfo.isSuccessful();
|
||||
}
|
||||
|
||||
/**
|
||||
* Setups the pop-up components
|
||||
*
|
||||
* @param comp
|
||||
* the compenent(editWidnow)
|
||||
* @param model
|
||||
* labels list model to render the combobox
|
||||
* <code>comboJiraLabel</code>
|
||||
*/
|
||||
private void setupJiraSyncPopup(Component comp, ListModel model) {
|
||||
|
||||
startJiraSyncButton = (Button) comp.getFellow("startJiraSyncButton");
|
||||
startJiraSyncButton.setLabel(_("Start sync"));
|
||||
|
||||
startJiraSyncButton.addEventListener(Events.ON_CLICK,
|
||||
new EventListener() {
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) {
|
||||
startSyncWithJira(comboJiraLabel.getValue());
|
||||
}
|
||||
});
|
||||
cancelJiraSyncButton = (Button) comp.getFellow("cancelJiraSyncButton");
|
||||
cancelJiraSyncButton.setLabel(_("Cancel"));
|
||||
cancelJiraSyncButton.addEventListener(Events.ON_CLICK,
|
||||
new EventListener() {
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) {
|
||||
jirasyncPopup.close();
|
||||
}
|
||||
});
|
||||
comboJiraLabel = (Combobox) comp.getFellowIfAny("comboJiraLabel");
|
||||
comboJiraLabel.setModel(model);
|
||||
|
||||
jirasyncPopup = (Popup) comp.getFellow("jirasyncPopup");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This class provides case insensitive search for the {@link Combobox}.
|
||||
*/
|
||||
private class SimpleListModelExt extends SimpleListModel {
|
||||
|
||||
public SimpleListModelExt(List data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
public ListModel getSubModel(Object value, int nRows) {
|
||||
final String idx = value == null ? "" : objectToString(value);
|
||||
if (nRows < 0) {
|
||||
nRows = 10;
|
||||
}
|
||||
final LinkedList data = new LinkedList();
|
||||
for (int i = 0; i < getSize(); i++) {
|
||||
if (idx.equals("")
|
||||
|| entryMatchesText(getElementAt(i).toString(), idx)) {
|
||||
data.add(getElementAt(i));
|
||||
if (--nRows <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new SimpleListModelExt(data);
|
||||
}
|
||||
|
||||
public boolean entryMatchesText(String entry, String text) {
|
||||
return entry.toLowerCase().contains(text.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -27,22 +27,16 @@ import java.util.ConcurrentModificationException;
|
|||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.ws.rs.WebApplicationException;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.libreplan.business.calendars.entities.BaseCalendar;
|
||||
import org.libreplan.business.common.daos.IConnectorDAO;
|
||||
import org.libreplan.business.common.entities.Connector;
|
||||
import org.libreplan.business.common.entities.ConnectorException;
|
||||
import org.libreplan.business.common.entities.PredefinedConnectors;
|
||||
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.libreplan.business.externalcompanies.entities.DeadlineCommunication;
|
||||
import org.libreplan.business.externalcompanies.entities.DeliverDateComparator;
|
||||
|
|
@ -53,14 +47,9 @@ import org.libreplan.business.orders.entities.Order;
|
|||
import org.libreplan.business.orders.entities.Order.SchedulingMode;
|
||||
import org.libreplan.business.orders.entities.OrderElement;
|
||||
import org.libreplan.business.orders.entities.OrderStatusEnum;
|
||||
import org.libreplan.business.orders.entities.OrderSyncInfo;
|
||||
import org.libreplan.business.planner.entities.PositionConstraintType;
|
||||
import org.libreplan.business.templates.entities.OrderTemplate;
|
||||
import org.libreplan.business.users.entities.UserRole;
|
||||
import org.libreplan.importers.IJiraOrderElementSynchronizer;
|
||||
import org.libreplan.importers.IJiraTimesheetSynchronizer;
|
||||
import org.libreplan.importers.JiraSyncInfo;
|
||||
import org.libreplan.importers.jira.IssueDTO;
|
||||
import org.libreplan.web.common.ConfirmCloseUtil;
|
||||
import org.libreplan.web.common.IMessagesForUser;
|
||||
import org.libreplan.web.common.Level;
|
||||
|
|
@ -88,7 +77,6 @@ import org.zkoss.ganttz.util.LongOperationFeedback;
|
|||
import org.zkoss.zk.ui.Component;
|
||||
import org.zkoss.zk.ui.Desktop;
|
||||
import org.zkoss.zk.ui.Executions;
|
||||
import org.zkoss.zk.ui.SuspendNotAllowedException;
|
||||
import org.zkoss.zk.ui.WrongValueException;
|
||||
import org.zkoss.zk.ui.event.Event;
|
||||
import org.zkoss.zk.ui.event.EventListener;
|
||||
|
|
@ -106,9 +94,7 @@ import org.zkoss.zul.Datebox;
|
|||
import org.zkoss.zul.Grid;
|
||||
import org.zkoss.zul.Hbox;
|
||||
import org.zkoss.zul.Label;
|
||||
import org.zkoss.zul.ListModel;
|
||||
import org.zkoss.zul.Messagebox;
|
||||
import org.zkoss.zul.Popup;
|
||||
import org.zkoss.zul.Row;
|
||||
import org.zkoss.zul.RowRenderer;
|
||||
import org.zkoss.zul.Rows;
|
||||
|
|
@ -198,6 +184,8 @@ public class OrderCRUDController extends GenericForwardComposer {
|
|||
|
||||
private ProjectDetailsController projectDetailsController;
|
||||
|
||||
private JiraSynchronizationController jiraSynchronizationController;
|
||||
|
||||
private TimSynchronizationController timSynchronizationController;
|
||||
|
||||
@Autowired
|
||||
|
|
@ -207,16 +195,6 @@ public class OrderCRUDController extends GenericForwardComposer {
|
|||
|
||||
private EndDatesRenderer endDatesRenderer = new EndDatesRenderer();
|
||||
|
||||
@Autowired
|
||||
private IJiraOrderElementSynchronizer jiraOrderElementSynchronizer;
|
||||
|
||||
@Autowired
|
||||
private IJiraTimesheetSynchronizer jiraTimesheetSynchronizer;
|
||||
|
||||
@Autowired
|
||||
private IConnectorDAO connectorDAO;
|
||||
|
||||
|
||||
@Override
|
||||
public void doAfterCompose(Component comp) throws Exception {
|
||||
super.doAfterCompose(comp);
|
||||
|
|
@ -693,7 +671,7 @@ public class OrderCRUDController extends GenericForwardComposer {
|
|||
saveAndContinue(true);
|
||||
}
|
||||
|
||||
private void saveAndContinue(boolean showSaveMessage) {
|
||||
protected void saveAndContinue(boolean showSaveMessage) {
|
||||
|
||||
Order order = orderModel.getOrder();
|
||||
final boolean isNewObject = order.isNewObject();
|
||||
|
|
@ -802,11 +780,11 @@ public class OrderCRUDController extends GenericForwardComposer {
|
|||
}
|
||||
}
|
||||
|
||||
private Tab getCurrentTab() {
|
||||
protected Tab getCurrentTab() {
|
||||
return selectedTab;
|
||||
}
|
||||
|
||||
private void selectTab(String str) {
|
||||
protected void selectTab(String str) {
|
||||
Tab tab = (Tab) editWindow.getFellowIfAny(str);
|
||||
if (tab != null) {
|
||||
tab.setSelected(true);
|
||||
|
|
@ -1042,6 +1020,7 @@ public class OrderCRUDController extends GenericForwardComposer {
|
|||
initializeCustomerComponent();
|
||||
reloadOrderDetailsTab();
|
||||
orderDatesHandler.chooseCurrentSchedulingMode();
|
||||
setupJiraSynchronizationController();
|
||||
setupTimSynchronizationController();
|
||||
}
|
||||
|
||||
|
|
@ -1706,196 +1685,29 @@ public class OrderCRUDController extends GenericForwardComposer {
|
|||
return Util.getCurrencySymbol();
|
||||
}
|
||||
|
||||
private Popup jirasyncPopup;
|
||||
private Button startJiraSyncButton, cancelJiraSyncButton, syncWithJiraButton;
|
||||
private Combobox comboJiraLabel;
|
||||
|
||||
public boolean isJiraActivated() {
|
||||
Connector connector = connectorDAO
|
||||
.findUniqueByName(PredefinedConnectors.JIRA.getName());
|
||||
if (connector == null) {
|
||||
return false;
|
||||
/**
|
||||
* Setup the connector, JiraSynchronization controller
|
||||
*/
|
||||
public void setupJiraSynchronizationController() {
|
||||
if (jiraSynchronizationController == null) {
|
||||
jiraSynchronizationController = new JiraSynchronizationController();
|
||||
}
|
||||
return connector.isActivated();
|
||||
}
|
||||
|
||||
public boolean isJiraDeactivated() {
|
||||
return !isJiraActivated();
|
||||
|
||||
}
|
||||
|
||||
public void syncWithJira() {
|
||||
try {
|
||||
List<String> items = jiraOrderElementSynchronizer.getAllJiraLabels();
|
||||
|
||||
Textbox txtImportedLabel = (Textbox) editWindow
|
||||
.getFellowIfAny("txtImportedLabel");
|
||||
|
||||
if (!(txtImportedLabel.getText()).isEmpty()) {
|
||||
startSyncWithJira(txtImportedLabel.getText());
|
||||
return;
|
||||
}
|
||||
|
||||
setupJiraSyncPopup(editWindow, new SimpleListModelExt(items));
|
||||
|
||||
syncWithJiraButton = (Button) getCurrentTab().getFellow(
|
||||
"syncWithJiraButton");
|
||||
|
||||
jirasyncPopup.open(syncWithJiraButton, "before_start");
|
||||
|
||||
} catch (WebApplicationException e) {
|
||||
LOG.info(e);
|
||||
messagesForUser.showMessage(Level.ERROR,
|
||||
_("Cannot connect to JIRA server"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void startSyncWithJira(String label) {
|
||||
try {
|
||||
Order order = getOrder();
|
||||
|
||||
List<IssueDTO> issues = jiraOrderElementSynchronizer
|
||||
.getJiraIssues(label);
|
||||
|
||||
if (issues == null || issues.isEmpty()) {
|
||||
messagesForUser.showMessage(Level.ERROR,
|
||||
_("No JIRA issues to import"));
|
||||
return;
|
||||
}
|
||||
|
||||
order.setCodeAutogenerated(false);
|
||||
|
||||
jiraOrderElementSynchronizer.syncOrderElementsWithJiraIssues(
|
||||
issues, order);
|
||||
|
||||
saveAndContinue(false);
|
||||
|
||||
jiraOrderElementSynchronizer.saveSyncInfo(label, order);
|
||||
|
||||
if (jirasyncPopup != null) {
|
||||
jirasyncPopup.close();
|
||||
}
|
||||
|
||||
jiraTimesheetSynchronizer.syncJiraTimesheetWithJiraIssues(issues,
|
||||
order);
|
||||
|
||||
showSyncInfo();
|
||||
|
||||
// Reload order info in all tabs
|
||||
Tab previousTab = getCurrentTab();
|
||||
initEdit(order);
|
||||
selectTab(previousTab.getId());
|
||||
} catch (WebApplicationException e) {
|
||||
LOG.info(e);
|
||||
messagesForUser.showMessage(Level.ERROR,
|
||||
_("Cannot connect to JIRA server"));
|
||||
} catch (ConnectorException e) {
|
||||
messagesForUser.showMessage(Level.ERROR,
|
||||
_("Failed: {0}", e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
public OrderSyncInfo getOrderLastSyncInfo() {
|
||||
return jiraOrderElementSynchronizer.getOrderLastSyncInfo(getOrder());
|
||||
}
|
||||
|
||||
private void showSyncInfo() {
|
||||
Map<String, Object> args = new HashMap<String, Object>();
|
||||
|
||||
JiraSyncInfo jiraSyncInfoProgress = jiraOrderElementSynchronizer
|
||||
.getJiraSyncInfo();
|
||||
args.put("showSyncProgressSuccess",
|
||||
jiraSyncInfoProgress.isSyncSuccessful());
|
||||
args.put("jiraSyncProgressFailedReasons", new SimpleListModel(
|
||||
jiraSyncInfoProgress.getSyncFailedReasons()));
|
||||
|
||||
JiraSyncInfo jiraSyncInfoTimesheet = jiraTimesheetSynchronizer
|
||||
.getJiraSyncInfo();
|
||||
args.put("showSyncTimesheetSuccess",
|
||||
jiraSyncInfoTimesheet.isSyncSuccessful());
|
||||
args.put("jiraSyncTimesheetFailedReasons", new SimpleListModel(
|
||||
jiraSyncInfoTimesheet.getSyncFailedReasons()));
|
||||
|
||||
Window jiraSyncInfoWindow = (Window) Executions.createComponents(
|
||||
"/orders/_jiraSyncInfo.zul", null, args);
|
||||
|
||||
try {
|
||||
jiraSyncInfoWindow.doModal();
|
||||
} catch (SuspendNotAllowedException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InterruptedException e) {
|
||||
jiraSynchronizationController.doAfterCompose(editWindow);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupJiraSyncPopup(Component comp, ListModel model) {
|
||||
|
||||
startJiraSyncButton = (Button) comp.getFellow("startJiraSyncButton");
|
||||
startJiraSyncButton.setLabel(_("Start sync"));
|
||||
|
||||
startJiraSyncButton.addEventListener(Events.ON_CLICK, new EventListener() {
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) {
|
||||
startSyncWithJira(comboJiraLabel.getValue());
|
||||
}
|
||||
});
|
||||
cancelJiraSyncButton = (Button) comp.getFellow("cancelJiraSyncButton");
|
||||
cancelJiraSyncButton.setLabel(_("Cancel"));
|
||||
cancelJiraSyncButton.addEventListener(Events.ON_CLICK, new EventListener() {
|
||||
|
||||
@Override
|
||||
public void onEvent(Event event) {
|
||||
jirasyncPopup.close();
|
||||
}
|
||||
});
|
||||
comboJiraLabel = (Combobox) comp.getFellowIfAny("comboJiraLabel");
|
||||
comboJiraLabel.setModel(model);
|
||||
|
||||
jirasyncPopup = (Popup) comp.getFellow("jirasyncPopup");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This class provides case insensitive search for the {@link Combobox}.
|
||||
* Setup the connector, TimSynchronization controller
|
||||
*/
|
||||
private class SimpleListModelExt extends SimpleListModel {
|
||||
|
||||
public SimpleListModelExt(List data) {
|
||||
super(data);
|
||||
}
|
||||
|
||||
public ListModel getSubModel(Object value, int nRows) {
|
||||
final String idx = value == null ? "" : objectToString(value);
|
||||
if (nRows < 0) {
|
||||
nRows = 10;
|
||||
}
|
||||
final LinkedList data = new LinkedList();
|
||||
for (int i = 0; i < getSize(); i++) {
|
||||
if (idx.equals("")
|
||||
|| entryMatchesText(getElementAt(i).toString(), idx)) {
|
||||
data.add(getElementAt(i));
|
||||
if (--nRows <= 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return new SimpleListModelExt(data);
|
||||
}
|
||||
|
||||
public boolean entryMatchesText(String entry, String text) {
|
||||
return entry.toLowerCase().contains(text.toLowerCase());
|
||||
}
|
||||
}
|
||||
|
||||
public void setupTimSynchronizationController() {
|
||||
if (timSynchronizationController == null) {
|
||||
timSynchronizationController = new TimSynchronizationController();
|
||||
}
|
||||
try {
|
||||
timSynchronizationController.doAfterCompose(self
|
||||
.getFellow("editOrderElement"));
|
||||
timSynchronizationController.doAfterCompose(editWindow);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,9 +29,10 @@ import org.libreplan.business.common.daos.IConnectorDAO;
|
|||
import org.libreplan.business.common.entities.Connector;
|
||||
import org.libreplan.business.common.entities.ConnectorException;
|
||||
import org.libreplan.business.common.entities.PredefinedConnectors;
|
||||
import org.libreplan.business.orders.entities.Order;
|
||||
import org.libreplan.business.orders.entities.OrderSyncInfo;
|
||||
import org.libreplan.importers.IExportTimesheetsToTim;
|
||||
import org.libreplan.importers.TimImpExpInfo;
|
||||
import org.libreplan.importers.SynchronizationInfo;
|
||||
import org.libreplan.web.common.IMessagesForUser;
|
||||
import org.libreplan.web.common.Level;
|
||||
import org.libreplan.web.common.MessagesForUser;
|
||||
|
|
@ -44,6 +45,7 @@ import org.zkoss.zk.ui.util.GenericForwardComposer;
|
|||
import org.zkoss.zul.Label;
|
||||
import org.zkoss.zul.SimpleListModel;
|
||||
import org.zkoss.zul.Textbox;
|
||||
import org.zkoss.zul.api.Groupbox;
|
||||
import org.zkoss.zul.api.Window;
|
||||
|
||||
/**
|
||||
|
|
@ -58,7 +60,12 @@ public class TimSynchronizationController extends GenericForwardComposer {
|
|||
|
||||
private OrderCRUDController orderController;
|
||||
|
||||
private Window editWindow;
|
||||
|
||||
private Groupbox timGroupBox;
|
||||
|
||||
private Textbox txtProductCode;
|
||||
|
||||
private Label labelProductCode, labelLastSyncDate;
|
||||
|
||||
@Autowired
|
||||
|
|
@ -75,19 +82,67 @@ public class TimSynchronizationController extends GenericForwardComposer {
|
|||
public void doAfterCompose(Component comp) throws Exception {
|
||||
super.doAfterCompose(comp);
|
||||
comp.setVariable("timSynchronizationController", this, true);
|
||||
txtProductCode = (Textbox) comp.getFellowIfAny("txtProductCode");
|
||||
labelLastSyncDate = (Label) comp.getFellowIfAny("labelLastSyncDate");
|
||||
labelProductCode = (Label) comp.getFellowIfAny("labelProductCode");
|
||||
messagesForUser = new MessagesForUser(messagesContainer);
|
||||
loadComponentsEditWindow(comp);
|
||||
showOrHideTimEditWindow();
|
||||
updateOrderLastSyncInfoScreen();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current {@link Order}
|
||||
*/
|
||||
private Order getOrder() {
|
||||
return orderController.getOrder();
|
||||
}
|
||||
|
||||
private void loadComponentsEditWindow(Component comp) {
|
||||
txtProductCode = (Textbox) comp.getFellowIfAny("txtProductCode");
|
||||
labelLastSyncDate = (Label) comp
|
||||
.getFellowIfAny("labelLastSyncDate");
|
||||
labelProductCode = (Label) comp
|
||||
.getFellowIfAny("labelProductCode");
|
||||
timGroupBox = (Groupbox) comp.getFellowIfAny("timGroupBox");
|
||||
|
||||
messagesForUser = new MessagesForUser(messagesContainer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show or hide <code>TimEditWindow</code> based on Tim
|
||||
* {@link Connector#isActivated()}
|
||||
*/
|
||||
private void showOrHideTimEditWindow() {
|
||||
timGroupBox.setVisible(isTimActivated());
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the UI text last synchronized date and the text product code
|
||||
*/
|
||||
private void updateOrderLastSyncInfoScreen() {
|
||||
OrderSyncInfo orderSyncInfo = exportTimesheetsToTim
|
||||
.getOrderLastSyncInfo(getOrder());
|
||||
if (orderSyncInfo != null) {
|
||||
labelLastSyncDate.setValue(Util.formatDateTime(orderSyncInfo
|
||||
.getLastSyncDate()));
|
||||
labelProductCode.setValue("(" + orderSyncInfo.getKey() + ")");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if Tim is Activated. Used to show/hide Tim edit window
|
||||
*/
|
||||
public boolean isTimActivated() {
|
||||
Connector connector = connectorDAO
|
||||
.findUniqueByName(PredefinedConnectors.TIM.getName());
|
||||
if (connector == null) {
|
||||
return false;
|
||||
}
|
||||
return connector.isActivated();
|
||||
}
|
||||
|
||||
public void startExportToTim() {
|
||||
LOG.info("startExportToTim(): " + orderController.getOrder().getName());
|
||||
txtProductCode.setConstraint("no empty:" + _("cannot be empty"));
|
||||
try {
|
||||
exportTimesheetsToTim.exportTimesheets(txtProductCode.getValue(),
|
||||
orderController.getOrder());
|
||||
getOrder());
|
||||
|
||||
updateOrderLastSyncInfoScreen();
|
||||
|
||||
|
|
@ -99,37 +154,15 @@ public class TimSynchronizationController extends GenericForwardComposer {
|
|||
}
|
||||
}
|
||||
|
||||
private void updateOrderLastSyncInfoScreen() {
|
||||
OrderSyncInfo orderSyncInfo = exportTimesheetsToTim
|
||||
.getOrderLastSyncInfo(orderController.getOrder());
|
||||
if (orderSyncInfo != null) {
|
||||
if (labelLastSyncDate != null) {
|
||||
labelLastSyncDate.setValue(Util.formatDateTime(orderSyncInfo
|
||||
.getLastSyncDate()));
|
||||
}
|
||||
if (labelProductCode != null) {
|
||||
labelProductCode.setValue("(" + orderSyncInfo.getKey() + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isTimActivated() {
|
||||
Connector connector = connectorDAO
|
||||
.findUniqueByName(PredefinedConnectors.TIM.getName());
|
||||
if (connector == null) {
|
||||
return false;
|
||||
}
|
||||
return connector.isActivated();
|
||||
}
|
||||
|
||||
private void shwoImpExpInfo() {
|
||||
Map<String, Object> args = new HashMap<String, Object>();
|
||||
|
||||
TimImpExpInfo timImpExpInfo = exportTimesheetsToTim.getExportProcessInfo();
|
||||
args.put("action", timImpExpInfo.getAction());
|
||||
args.put("showSuccess", timImpExpInfo.isSuccessful());
|
||||
SynchronizationInfo synchronizationInfo = exportTimesheetsToTim.getSynchronizationInfo();
|
||||
args.put("action", synchronizationInfo.getAction());
|
||||
args.put("showSuccess", synchronizationInfo.isSuccessful());
|
||||
args.put("failedReasons",
|
||||
new SimpleListModel(timImpExpInfo.getFailedReasons()));
|
||||
new SimpleListModel(synchronizationInfo.getFailedReasons()));
|
||||
|
||||
Window timImpExpInfoWindow = (Window) Executions.createComponents(
|
||||
"/orders/_timImpExpInfo.zul", null, args);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
macroURI="/orders/components/_listOrderElementMaterials.zul"?>
|
||||
<?component name="listOrderElementTaskQualityForms" inline="true" macroURI="_listOrderElementTaskQualityForms.zul"?>
|
||||
<?component name="listOrderElementAuthorizations" inline="true" macroURI="_listOrderElementAuthorizations.zul"?>
|
||||
<?component name="jiraOrderElementSynchronizer" inline="true" macroURI="components/_jiraOrderElementSync.zul"?>
|
||||
<?component name="timOrderTimesheetSynchronizer" inline="true" macroURI="components/_timOrderTimesheetSync.zul"?>
|
||||
|
||||
<window id="${arg.top_id}">
|
||||
|
|
@ -282,34 +283,8 @@
|
|||
</grid>
|
||||
</groupbox>
|
||||
</groupbox>
|
||||
<groupbox style="margin-top: 5px" closable="false"
|
||||
visible="@{controller.jiraActivated}">
|
||||
<caption label="${i18n:_('JIRA import information')}" />
|
||||
<separator spacing="10px"/>
|
||||
<hbox width="100%">
|
||||
<separator spacing="10px" width="100%"/>
|
||||
|
||||
<grid fixedLayout="true" hflex="1">
|
||||
<columns>
|
||||
<column width="200px" />
|
||||
<column />
|
||||
</columns>
|
||||
<rows>
|
||||
<row>
|
||||
<label value="${i18n:_('JIRA label')}" width="50px"/>
|
||||
<hbox>
|
||||
<textbox value="@{controller.orderLastSyncInfo.lastSyncDate}" width="130px" disabled="true"/>
|
||||
<textbox id="txtImportedLabel" value="@{controller.orderLastSyncInfo.key}"
|
||||
width="220px" disabled="true"/>
|
||||
<button label="${i18n:_('Sync with JIRA')}" id="syncWithJiraButton" disabled="@{controller.jiraDeactivated}"
|
||||
onClick="controller.syncWithJira()" />
|
||||
</hbox>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</hbox>
|
||||
</groupbox>
|
||||
<timOrderTimesheetSynchronizer id="timOrderTimesheetSynchronizer" />
|
||||
<jiraOrderElementSynchronizer id="jiraOrderElementSynchronizer" fulfill="tabGeneralData.onSelect"/>
|
||||
<timOrderTimesheetSynchronizer id="timOrderTimesheetSynchronizer" fulfill="tabGeneralData.onSelect" />
|
||||
</tabpanel>
|
||||
<tabpanel>
|
||||
<listOrderElementHours id="orderElementHours" fulfill="tabAssignedHours.onSelect"/>
|
||||
|
|
@ -335,15 +310,4 @@
|
|||
</tabpanel>
|
||||
</tabpanels>
|
||||
</tabbox>
|
||||
<popup id="jirasyncPopup" sclass="finder-popup">
|
||||
<groupbox mold="3d" closable="false" width="420px">
|
||||
<caption id="jiraSyncCaption" label="Select a label" />
|
||||
<combobox id="comboJiraLabel" autodrop="true" width="400px" constraint="no empty:${i18n:_('cannot be empty')}"/>
|
||||
<separator/>
|
||||
<hbox>
|
||||
<button id="startJiraSyncButton" />
|
||||
<button id="cancelJiraSyncButton" />
|
||||
</hbox>
|
||||
</groupbox>
|
||||
</popup>
|
||||
</window>
|
||||
|
|
|
|||
|
|
@ -19,32 +19,22 @@
|
|||
|
||||
<window id="winJiraSyncInfo" title="${i18n:_('LibrePlan: Jira synchronization info')}"
|
||||
width="500px" border="normal" mode="modal">
|
||||
<div>
|
||||
|
||||
<div height="250px" style="overflow:auto">
|
||||
<vbox>
|
||||
<label value="${i18n:_('Synchronization of order elements with JIRA issues was successful and project has been updated accordingly')}" sclass="remarked" />
|
||||
</vbox>
|
||||
|
||||
<separator spacing="20px"/>
|
||||
|
||||
<vbox>
|
||||
<label value="${i18n:_('Synchronization of progress assignment was successful')}" sclass="remarked" if="${arg.showSyncProgressSuccess}"/>
|
||||
<vbox if="${not arg.showSyncProgressSuccess}">
|
||||
<label value="${i18n:_('Synchronization of progress assignment is not completed for the following reasons:')}" />
|
||||
<listbox model="${arg.jiraSyncProgressFailedReasons}"/>
|
||||
<label value="${i18n:_('Synchronization order elements with JIRA issues was successful')}" sclass="remarked" if="${arg.syncOrderElementSuccess}"/>
|
||||
<vbox if="${not arg.syncOrderElementSuccess}">
|
||||
<label value="${i18n:_('Synchronization order elements with JIRA issues was not completed for the following reasons:')}" />
|
||||
<listbox model="${arg.syncOrderElementFailedReasons}"/>
|
||||
</vbox>
|
||||
</vbox>
|
||||
|
||||
<separator spacing="20px"/>
|
||||
|
||||
<vbox>
|
||||
<label value="${i18n:_('Synchronization of timesheets was successful')}" sclass="remarked" if="${arg.showSyncTimesheetSuccess}"/>
|
||||
<vbox if="${not arg.showSyncTimesheetSuccess}">
|
||||
<separator spacing="10px"/>
|
||||
<vbox if="${arg.syncOrderElementSuccess}">
|
||||
<label value="${i18n:_('Synchronization of timesheets was successful')}" sclass="remarked" if="${arg.syncTimesheetSuccess}"/>
|
||||
<vbox if="${not arg.syncTimesheetSuccess}">
|
||||
<label value="${i18n:_('Synchronization of timesheets is not completed for the following reasons:')}" />
|
||||
<listbox model="${arg.jiraSyncTimesheetFailedReasons}"/>
|
||||
<listbox model="${arg.syncTimesheetFailedReasons}"/>
|
||||
</vbox>
|
||||
</vbox>
|
||||
|
||||
</div>
|
||||
<button id="closeBtn" label="${i18n:_('Close')}" onClick="winJiraSyncInfo.detach()"
|
||||
sclass="cancel-button global-action"/>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,58 @@
|
|||
<!--
|
||||
This file is part of LibrePlan
|
||||
|
||||
Copyright (C) 2013 St. Antoniusziekenhuis
|
||||
|
||||
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/>.
|
||||
-->
|
||||
|
||||
<groupbox id="jiraGroupBox"
|
||||
style="margin-top: 5px" closable="false"
|
||||
visible="@{jiraSynchroniaztionController.jiraActivated}">
|
||||
<caption label="${i18n:_('Jira sync information')}" />
|
||||
<separator spacing="10px"/>
|
||||
<hbox width="100%">
|
||||
<separator spacing="10px" width="100%"/>
|
||||
|
||||
<grid fixedLayout="true" hflex="1">
|
||||
<columns>
|
||||
<column width="200px" />
|
||||
<column />
|
||||
</columns>
|
||||
<rows>
|
||||
<row>
|
||||
<label value="${i18n:_('JIRA label')}" width="50px"/>
|
||||
<hbox>
|
||||
<textbox id="txtLastSyncDate" value="" width="130px" disabled="true"/>
|
||||
<textbox id="txtImportedLabel" value=""
|
||||
width="220px" disabled="true"/>
|
||||
<button label="${i18n:_('Sync with JIRA')}" id="syncWithJiraButton"
|
||||
onClick="jiraSynchroniaztionController.syncWithJira()" />
|
||||
</hbox>
|
||||
</row>
|
||||
</rows>
|
||||
</grid>
|
||||
</hbox>
|
||||
<popup id="jirasyncPopup" sclass="finder-popup">
|
||||
<groupbox mold="3d" closable="false" width="420px">
|
||||
<caption id="jiraSyncCaption" label="Select a label" />
|
||||
<combobox id="comboJiraLabel" autodrop="true" width="400px" constraint="no empty:${i18n:_('cannot be empty')}"/>
|
||||
<separator/>
|
||||
<hbox>
|
||||
<button id="startJiraSyncButton" />
|
||||
<button id="cancelJiraSyncButton" />
|
||||
</hbox>
|
||||
</groupbox>
|
||||
</popup>
|
||||
</groupbox>
|
||||
|
|
@ -17,8 +17,7 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
-->
|
||||
|
||||
<groupbox id="${arg.id}"
|
||||
apply="org.libreplan.web.orders.TimSynchronizationController"
|
||||
<groupbox id="timGroupBox"
|
||||
style="margin-top: 5px" closable="false"
|
||||
visible="@{timSynchronizationController.timActivated}">
|
||||
<caption label="${i18n:_('Tim sync information')}" />
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ public class ExportTimesheetsToTimTest {
|
|||
throws ConnectorException {
|
||||
Order order = givenOrder();
|
||||
exportTimesheetsToTim.exportTimesheets("5160", order);
|
||||
boolean result = exportTimesheetsToTim.getExportProcessInfo()
|
||||
boolean result = exportTimesheetsToTim.getSynchronizationInfo()
|
||||
.isSuccessful();
|
||||
if (!result) {
|
||||
fail("Export timesheets to tim failed");
|
||||
|
|
@ -171,14 +171,14 @@ public class ExportTimesheetsToTimTest {
|
|||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException.class)
|
||||
@Test(expected = ConnectorException.class)
|
||||
public void testExportTimesheetsToTimWithInvalidCode()
|
||||
throws ConnectorException {
|
||||
Order order = givenOrder();
|
||||
exportTimesheetsToTim.exportTimesheets("", order);
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException.class)
|
||||
@Test(expected = ConnectorException.class)
|
||||
public void testExportTimesheetsToTimWithOrderNull()
|
||||
throws ConnectorException {
|
||||
exportTimesheetsToTim.exportTimesheets("5160", null);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue