tim-connector: check if connector values are invalid and more
Better error handling: * check if connector connection values are valid * New ConnectorException * New .zul file to show import/export failed/success information * All files modified affected by these changes
This commit is contained in:
parent
9325470d3d
commit
3891048f00
17 changed files with 443 additions and 54 deletions
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
package org.libreplan.business.common.entities;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
|
@ -118,4 +120,29 @@ public class Connector extends BaseEntity {
|
|||
"Y");
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if connector's connections values are valid
|
||||
*
|
||||
* @return true if connection values are valid
|
||||
*/
|
||||
public boolean areConnectionValuesValid() {
|
||||
String serverUrl = getPropertiesAsMap().get(
|
||||
PredefinedConnectorProperties.SERVER_URL);
|
||||
try {
|
||||
new URL(serverUrl);
|
||||
} catch (MalformedURLException e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(getPropertiesAsMap().get(
|
||||
PredefinedConnectorProperties.USERNAME))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (StringUtils.isBlank(getPropertiesAsMap().get(
|
||||
PredefinedConnectorProperties.PASSWORD))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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.business.common.entities;
|
||||
|
||||
/**
|
||||
* Exception to ecapsulate connector(values) exceptions
|
||||
*
|
||||
* @author Miciele Ghiorghis <m.ghiorghis@antoniusziekenhuis.nl>
|
||||
*/
|
||||
public class ConnectorException extends Exception {
|
||||
|
||||
public ConnectorException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
<property name="name" column="name" not-null="true" />
|
||||
|
||||
<list name="properties" table="connector_property">
|
||||
<list name="properties" table="connector_property" lazy="false">
|
||||
<key column="connector_id" />
|
||||
<list-index column="connector_property_position" />
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@
|
|||
|
||||
package org.libreplan.importers;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.libreplan.business.common.entities.ConnectorException;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
|
@ -30,6 +33,8 @@ import org.springframework.scheduling.quartz.QuartzJobBean;
|
|||
* @author Miciele Ghiorghis <m.ghiorghis@antoniusziekenhuis.nl>
|
||||
*/
|
||||
public class ExportTimesheetToTimJob extends QuartzJobBean {
|
||||
private static final Log LOG = LogFactory
|
||||
.getLog(ExportTimesheetToTimJob.class);
|
||||
|
||||
@Override
|
||||
protected void executeInternal(JobExecutionContext context)
|
||||
|
|
@ -40,7 +45,14 @@ public class ExportTimesheetToTimJob extends QuartzJobBean {
|
|||
IExportTimesheetsToTim exportTimesheetsToTim = (IExportTimesheetsToTim) applicationContext
|
||||
.getBean("exportTimesheetsToTim");
|
||||
|
||||
exportTimesheetsToTim.exportTimesheets();
|
||||
try {
|
||||
exportTimesheetsToTim.exportTimesheets();
|
||||
LOG.info("Export scuccessful: "
|
||||
+ exportTimesheetsToTim.getExportProcessInfo()
|
||||
.isSuccessful());
|
||||
} catch (ConnectorException e) {
|
||||
LOG.error("Export timesheet to Tim failed", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ 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;
|
||||
|
|
@ -91,47 +92,67 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
|
|||
@Autowired
|
||||
private IOrderDAO orderDAO;
|
||||
|
||||
private TimImpExpInfo timImpExpInfo;
|
||||
|
||||
/**
|
||||
* Action name
|
||||
*/
|
||||
private static final String EXPORT = "Export";
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public void exportTimesheets() {
|
||||
String name = PredefinedConnectors.TIM.getName();
|
||||
Connector connector = connectorDAO.findUniqueByName(name);
|
||||
public void exportTimesheets() throws ConnectorException {
|
||||
Connector connector = getTimConnector();
|
||||
if (connector == null) {
|
||||
return;
|
||||
throw new ConnectorException("Tim connector not found");
|
||||
}
|
||||
if (!connector.areConnectionValuesValid()) {
|
||||
throw new ConnectorException(
|
||||
"Connection values of Tim connector are invalid");
|
||||
}
|
||||
|
||||
timImpExpInfo = new TimImpExpInfo(EXPORT);
|
||||
|
||||
List<Order> orders = orderDAO.getOrders();
|
||||
for (Order order : orders) {
|
||||
OrderSyncInfo orderSyncInfo = orderSyncInfoDAO
|
||||
.findLastSynchronizedInfoByOrderAndConnectorId(order,
|
||||
name);
|
||||
OrderSyncInfo orderSyncInfo = getOrderLastSyncInfo(order);
|
||||
if (orderSyncInfo == null) {
|
||||
LOG.warn("Order '" + order.getName()
|
||||
+ "' is not yet synchronized");
|
||||
timImpExpInfo.addFailedReason("Order '" + order.getName()
|
||||
+ "' is not yet synchronized");
|
||||
} else {
|
||||
boolean result = exportTimesheets(orderSyncInfo.getKey(),
|
||||
LOG.info("Exporting '" + order.getName() + "'");
|
||||
exportTimesheets(orderSyncInfo.getKey(),
|
||||
orderSyncInfo.getOrder(), connector);
|
||||
LOG.info("Export successful: " + result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public boolean exportTimesheets(String productCode, Order order) {
|
||||
public void exportTimesheets(String productCode, Order order)
|
||||
throws ConnectorException {
|
||||
if (productCode == null || productCode.isEmpty()) {
|
||||
throw new RuntimeException("Product code should not be empty");
|
||||
}
|
||||
if (order == null) {
|
||||
throw new RuntimeException("Order should not be empty");
|
||||
}
|
||||
Connector connector = connectorDAO
|
||||
.findUniqueByName(PredefinedConnectors.TIM.getName());
|
||||
|
||||
Connector connector = getTimConnector();
|
||||
if (connector == null) {
|
||||
throw new RuntimeException("Tim connector not found");
|
||||
throw new ConnectorException("Tim connector not found");
|
||||
}
|
||||
|
||||
return exportTimesheets(productCode, order, connector);
|
||||
if (!connector.areConnectionValuesValid()) {
|
||||
throw new ConnectorException(
|
||||
"Connection values of Tim connector are invalid");
|
||||
}
|
||||
|
||||
timImpExpInfo = new TimImpExpInfo(EXPORT);
|
||||
|
||||
exportTimesheets(productCode, order, connector);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -146,7 +167,7 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
|
|||
*
|
||||
* @return true if export is succeeded, false otherwise
|
||||
*/
|
||||
private boolean exportTimesheets(String productCode, Order order,
|
||||
private void exportTimesheets(String productCode, Order order,
|
||||
Connector connector) {
|
||||
Map<String, String> properties = connector.getPropertiesAsMap();
|
||||
|
||||
|
|
@ -165,8 +186,12 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
|
|||
dateNrOfDaysBack.toDateTimeAtStartOfDay().toDate(), new Date(),
|
||||
true);
|
||||
if (workReportLines == null || workReportLines.isEmpty()) {
|
||||
LOG.warn("No work reportlines are found");
|
||||
return false;
|
||||
LOG.warn("No work reportlines are found for order: '"
|
||||
+ order.getName() + "'");
|
||||
timImpExpInfo
|
||||
.addFailedReason("No work reportlines are found for order: '"
|
||||
+ order.getName() + "'");
|
||||
return;
|
||||
}
|
||||
|
||||
List<TimeRegistrationDTO> timeRegistrationDTOs = new ArrayList<TimeRegistrationDTO>();
|
||||
|
|
@ -181,7 +206,9 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
|
|||
|
||||
if (timeRegistrationDTOs.isEmpty()) {
|
||||
LOG.warn("Unable to crate timeregistration for request");
|
||||
return false;
|
||||
timImpExpInfo
|
||||
.addFailedReason("Unable to crate timeregistration for request");
|
||||
return;
|
||||
}
|
||||
|
||||
TimeRegistrationRequestDTO timeRegistrationRequestDTO = new TimeRegistrationRequestDTO();
|
||||
|
|
@ -191,12 +218,20 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
|
|||
.sendRequestReceiveResponse(url, userName, password,
|
||||
timeRegistrationRequestDTO, TimeRegistrationResponseDTO.class);
|
||||
|
||||
if (timeRegistrationResponseDTO == null) {
|
||||
LOG.error("No response or exception in response");
|
||||
timImpExpInfo
|
||||
.addFailedReason("No response or exception in response");
|
||||
return;
|
||||
}
|
||||
|
||||
if (isRefsListEmpty(timeRegistrationResponseDTO.getRefs())) {
|
||||
LOG.warn("Registration response with empty refs");
|
||||
return false;
|
||||
timImpExpInfo
|
||||
.addFailedReason("Registration response with empty refs");
|
||||
return;
|
||||
}
|
||||
saveSyncInfoOnAnotherTransaction(productCode, order);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -254,6 +289,8 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
|
|||
worker = workerDAO.findByCode(workerCode);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
LOG.warn("Worker \"" + workerCode + "\" not found!");
|
||||
timImpExpInfo.addFailedReason("Worker \"" + workerCode
|
||||
+ "\" not found!");
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
@ -289,4 +326,17 @@ public class ExportTimesheetsToTim implements IExportTimesheetsToTim {
|
|||
order, PredefinedConnectors.TIM.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* finds and returns a Tim connector
|
||||
*/
|
||||
private Connector getTimConnector() {
|
||||
return connectorDAO
|
||||
.findUniqueByName(PredefinedConnectors.TIM.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimImpExpInfo getExportProcessInfo() {
|
||||
return timImpExpInfo;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
package org.libreplan.importers;
|
||||
|
||||
import org.libreplan.business.common.entities.Connector;
|
||||
import org.libreplan.business.common.entities.ConnectorException;
|
||||
import org.libreplan.business.orders.entities.Order;
|
||||
import org.libreplan.business.orders.entities.OrderSyncInfo;
|
||||
|
||||
|
|
@ -43,15 +44,20 @@ public interface IExportTimesheetsToTim {
|
|||
* the Tim's productCode
|
||||
* @param order
|
||||
* an existing order
|
||||
* @throws ConnectorException
|
||||
* if connector is not valid
|
||||
*/
|
||||
boolean exportTimesheets(String productCode, Order order);
|
||||
void exportTimesheets(String productCode, Order order) throws ConnectorException;
|
||||
|
||||
/**
|
||||
* Loops through all existing {@link Order}s and searches for last
|
||||
* synchronized order. if found, start exporting the time sheets of that
|
||||
* order to Tim SOAP server. if not found write info to the log file.
|
||||
*
|
||||
* @throws ConnectorException
|
||||
* if connector is not valid
|
||||
*/
|
||||
void exportTimesheets();
|
||||
void exportTimesheets() throws ConnectorException;
|
||||
|
||||
/**
|
||||
* Gets the most recent synchronized time sheet info
|
||||
|
|
@ -62,4 +68,9 @@ public interface IExportTimesheetsToTim {
|
|||
*/
|
||||
OrderSyncInfo getOrderLastSyncInfo(Order order);
|
||||
|
||||
/**
|
||||
* Returns export process info, success of fail info
|
||||
*/
|
||||
TimImpExpInfo getExportProcessInfo();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ package org.libreplan.importers;
|
|||
|
||||
import org.libreplan.business.calendars.entities.CalendarException;
|
||||
import org.libreplan.business.common.entities.Connector;
|
||||
import org.libreplan.business.common.entities.ConnectorException;
|
||||
|
||||
/**
|
||||
* Import Rosters from Tim SOAP server using {@link TimSoapClient} and updates
|
||||
|
|
@ -38,6 +39,14 @@ public interface IImportRosterFromTim {
|
|||
*
|
||||
* If worker calendar exception already exists it will be removed and added
|
||||
* new one, in other cases a new calendar exception will be created
|
||||
*
|
||||
* @throws ConnectorException
|
||||
* if connector is not valid
|
||||
*/
|
||||
void importRosters();
|
||||
void importRosters() throws ConnectorException;
|
||||
|
||||
/**
|
||||
* Returns import process info, success of fail info
|
||||
*/
|
||||
TimImpExpInfo getImportProcessInfo();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ 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;
|
||||
|
|
@ -103,6 +104,13 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
|
|||
@Qualifier("subclass")
|
||||
private IBaseCalendarModel baseCalendarModel;
|
||||
|
||||
private TimImpExpInfo timImpExpInfo;
|
||||
|
||||
/**
|
||||
* Action name
|
||||
*/
|
||||
private static final String IMPORT = "Import";
|
||||
|
||||
/**
|
||||
* Search criteria for roster exception days in RESPONSE message
|
||||
* {@link RosterDTO}
|
||||
|
|
@ -124,18 +132,24 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
|
|||
|
||||
@Override
|
||||
@Transactional
|
||||
public void importRosters() {
|
||||
public void importRosters() throws ConnectorException {
|
||||
Connector connector = connectorDAO
|
||||
.findUniqueByName(
|
||||
PredefinedConnectors.TIM.getName());
|
||||
.findUniqueByName(PredefinedConnectors.TIM.getName());
|
||||
if (connector == null) {
|
||||
return;
|
||||
throw new ConnectorException("Tim Connector not found");
|
||||
}
|
||||
|
||||
if (!connector.areConnectionValuesValid()) {
|
||||
throw new ConnectorException(
|
||||
"Connection values of Tim connector are invalid");
|
||||
}
|
||||
|
||||
Map<String, String> properties = connector.getPropertiesAsMap();
|
||||
String url = properties.get(PredefinedConnectorProperties.SERVER_URL);
|
||||
|
||||
String userName = properties
|
||||
.get(PredefinedConnectorProperties.USERNAME);
|
||||
|
||||
String password = properties
|
||||
.get(PredefinedConnectorProperties.PASSWORD);
|
||||
|
||||
|
|
@ -149,14 +163,16 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
|
|||
String departmentIds = properties
|
||||
.get(PredefinedConnectorProperties.TIM_DEPARTAMENTS_IMPORT_ROSTER);
|
||||
|
||||
if (StringUtils.isEmpty(departmentIds)) {
|
||||
if (StringUtils.isBlank(departmentIds)) {
|
||||
LOG.warn("No departments configured");
|
||||
return;
|
||||
throw new ConnectorException("No departments configured");
|
||||
}
|
||||
|
||||
String[] departmentIdsArray = StringUtils.stripAll(StringUtils.split(
|
||||
departmentIds, ","));
|
||||
|
||||
timImpExpInfo = new TimImpExpInfo(IMPORT);
|
||||
|
||||
for (String department : departmentIdsArray) {
|
||||
LOG.info("Department: " + department);
|
||||
RosterRequestDTO rosterRequestDTO = createRosterRequest(department,
|
||||
|
|
@ -165,12 +181,18 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
|
|||
.sendRequestReceiveResponse(url, userName, password,
|
||||
rosterRequestDTO, RosterResponseDTO.class);
|
||||
|
||||
updateWorkersCalendarException(rosterResponseDTO,
|
||||
productivityFactor);
|
||||
if (rosterResponseDTO != null) {
|
||||
updateWorkersCalendarException(rosterResponseDTO,
|
||||
productivityFactor);
|
||||
} else {
|
||||
LOG.error("No valid response for department " + department);
|
||||
timImpExpInfo
|
||||
.addFailedReason("No valid response for department "
|
||||
+ department);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* updates workers Exception calendar
|
||||
*
|
||||
|
|
@ -190,6 +212,8 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
|
|||
updateCalendarException(rosterExceptions);
|
||||
} else {
|
||||
LOG.info("No roster-exceptions found in the response");
|
||||
timImpExpInfo
|
||||
.addFailedReason("No roster-exceptions found in the response");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -217,6 +241,8 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
|
|||
worker = workerDAO.findUniqueByNif(workerCode);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
LOG.warn("Worker \"" + workerCode + "\" not found!");
|
||||
timImpExpInfo.addFailedReason("Worker \"" + workerCode
|
||||
+ "\" not found!");
|
||||
}
|
||||
if (worker != null) {
|
||||
List<RosterDTO> list = entry.getValue();
|
||||
|
|
@ -331,6 +357,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.addFailedReason("Exception name should not be empty");
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
|
|
@ -345,6 +372,7 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
|
|||
return calendarExceptionTypeDAO.findUniqueByName(nameToSearch);
|
||||
} catch (InstanceNotFoundException e) {
|
||||
LOG.error("Calendar exceptionType not found", e);
|
||||
timImpExpInfo.addFailedReason("Calendar exceptionType not found");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
@ -437,4 +465,9 @@ public class ImportRosterFromTim implements IImportRosterFromTim {
|
|||
rosterDTO.setConcept(false);
|
||||
return rosterDTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimImpExpInfo getImportProcessInfo() {
|
||||
return timImpExpInfo;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,9 @@
|
|||
|
||||
package org.libreplan.importers;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.libreplan.business.common.entities.ConnectorException;
|
||||
import org.quartz.JobExecutionContext;
|
||||
import org.quartz.JobExecutionException;
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
|
|
@ -35,6 +38,8 @@ import org.springframework.stereotype.Component;
|
|||
@Component
|
||||
@Scope(BeanDefinition.SCOPE_SINGLETON)
|
||||
public class ImportRosterFromTimJob extends QuartzJobBean {
|
||||
private static final Log LOG = LogFactory
|
||||
.getLog(ImportRosterFromTimJob.class);
|
||||
|
||||
@Override
|
||||
protected void executeInternal(JobExecutionContext context)
|
||||
|
|
@ -45,7 +50,13 @@ public class ImportRosterFromTimJob extends QuartzJobBean {
|
|||
IImportRosterFromTim importRosterFromTim = (IImportRosterFromTim) applicationContext
|
||||
.getBean("importRosterFromTim");
|
||||
|
||||
importRosterFromTim.importRosters();
|
||||
try {
|
||||
importRosterFromTim.importRosters();
|
||||
LOG.info("Import scuccessful: "
|
||||
+ importRosterFromTim.getImportProcessInfo().isSuccessful());
|
||||
} catch (ConnectorException e) {
|
||||
LOG.error("Import roster from Tim failed", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* 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 success/failure of Tim's import and/or export process
|
||||
*
|
||||
* @author Miciele Ghiorghis <m.ghiorghis@antoniusziekenhuis.nl>
|
||||
*/
|
||||
public class TimImpExpInfo {
|
||||
|
||||
/**
|
||||
* action, import or export process
|
||||
*/
|
||||
private String action;
|
||||
|
||||
/**
|
||||
* Holds failed reasons
|
||||
*/
|
||||
private List<String> failedReasons = new ArrayList<String>();
|
||||
|
||||
public TimImpExpInfo(String action) {
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the action
|
||||
*/
|
||||
public String getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified <code>reason</code> to <code>failedReasons<code> list
|
||||
*
|
||||
* @param reason
|
||||
* reason why import/export failed
|
||||
*/
|
||||
public void addFailedReason(String reason) {
|
||||
failedReasons.add(reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is import or export succeeded
|
||||
*
|
||||
* @return true if <code>failedReasons</code> is empty
|
||||
*/
|
||||
public boolean isSuccessful() {
|
||||
return failedReasons.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* returns reasons why import or export failed
|
||||
*/
|
||||
public List<String> getFailedReasons() {
|
||||
return Collections.unmodifiableList(failedReasons);
|
||||
}
|
||||
}
|
||||
|
|
@ -22,9 +22,11 @@ package org.libreplan.web.common;
|
|||
import java.util.List;
|
||||
|
||||
import org.libreplan.business.common.entities.Connector;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Contract for {@link JobSchedulerModel}.
|
||||
|
|
@ -55,9 +57,16 @@ public interface IJobSchedulerModel {
|
|||
*
|
||||
* @param jobSchedulerConfiguration
|
||||
* the job configuration
|
||||
* @throws ConnectorException
|
||||
* if connector is not valid
|
||||
*/
|
||||
void doManual(JobSchedulerConfiguration jobSchedulerConfiguration);
|
||||
void doManual(JobSchedulerConfiguration jobSchedulerConfiguration)
|
||||
throws ConnectorException;
|
||||
|
||||
/**
|
||||
* Returns import/export info. Failure or success info
|
||||
*/
|
||||
TimImpExpInfo getImportExportInfo();
|
||||
|
||||
/**
|
||||
* Prepares for create a new {@link JobSchedulerConfiguration}.
|
||||
|
|
|
|||
|
|
@ -23,18 +23,24 @@ import static org.libreplan.web.I18nHelper._;
|
|||
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.libreplan.business.common.entities.Connector;
|
||||
import org.libreplan.business.common.entities.ConnectorException;
|
||||
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.quartz.CronExpression;
|
||||
import org.zkoss.zk.ui.Component;
|
||||
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;
|
||||
|
|
@ -46,7 +52,9 @@ import org.zkoss.zul.Label;
|
|||
import org.zkoss.zul.Popup;
|
||||
import org.zkoss.zul.Row;
|
||||
import org.zkoss.zul.RowRenderer;
|
||||
import org.zkoss.zul.SimpleListModel;
|
||||
import org.zkoss.zul.api.Textbox;
|
||||
import org.zkoss.zul.api.Window;
|
||||
|
||||
/**
|
||||
* Controller for job scheduler manager
|
||||
|
|
@ -174,7 +182,13 @@ public class JobSchedulerController extends
|
|||
|
||||
@Override
|
||||
public void onEvent(Event event) throws Exception {
|
||||
jobSchedulerModel.doManual(jobSchedulerConfiguration);
|
||||
try {
|
||||
jobSchedulerModel.doManual(jobSchedulerConfiguration);
|
||||
shwoImpExpInfo();
|
||||
} catch (ConnectorException e) {
|
||||
messagesForUser.showMessage(Level.ERROR,
|
||||
_(e.getMessage()));
|
||||
}
|
||||
}
|
||||
}));
|
||||
hbox.appendChild(Util.createEditButton(new EventListener() {
|
||||
|
|
@ -195,6 +209,27 @@ 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());
|
||||
args.put("failedReasons",
|
||||
new SimpleListModel(timImpExpInfo.getFailedReasons()));
|
||||
|
||||
Window timImpExpInfoWindow = (Window) Executions.createComponents(
|
||||
"/orders/_timImpExpInfo.zul", null, args);
|
||||
|
||||
try {
|
||||
timImpExpInfoWindow.doModal();
|
||||
} catch (SuspendNotAllowedException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the next fire time for the specified job in
|
||||
* {@link JobSchedulerConfiguration}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import java.util.List;
|
|||
import org.libreplan.business.common.daos.IConnectorDAO;
|
||||
import org.libreplan.business.common.daos.IJobSchedulerConfigurationDAO;
|
||||
import org.libreplan.business.common.entities.Connector;
|
||||
import org.libreplan.business.common.entities.ConnectorException;
|
||||
import org.libreplan.business.common.entities.JobClassNameEnum;
|
||||
import org.libreplan.business.common.entities.JobSchedulerConfiguration;
|
||||
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
|
||||
|
|
@ -31,6 +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.web.common.concurrentdetection.OnConcurrentModification;
|
||||
import org.quartz.SchedulerException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
|
@ -67,6 +69,8 @@ public class JobSchedulerModel implements IJobSchedulerModel {
|
|||
@Autowired
|
||||
private IExportTimesheetsToTim exportTimesheetsToTim;
|
||||
|
||||
private TimImpExpInfo timImpExpInfo;
|
||||
|
||||
@Override
|
||||
@Transactional(readOnly = true)
|
||||
public List<JobSchedulerConfiguration> getJobSchedulerConfigurations() {
|
||||
|
|
@ -80,18 +84,26 @@ public class JobSchedulerModel implements IJobSchedulerModel {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void doManual(JobSchedulerConfiguration jobSchedulerConfiguration) {
|
||||
public void doManual(JobSchedulerConfiguration jobSchedulerConfiguration)
|
||||
throws ConnectorException {
|
||||
String name = jobSchedulerConfiguration.getJobClassName().getName();
|
||||
if (name.equals(JobClassNameEnum.IMPORT_ROSTER_FROM_TIM_JOB.getName())) {
|
||||
importRosterFromTim.importRosters();
|
||||
timImpExpInfo = importRosterFromTim.getImportProcessInfo();
|
||||
return;
|
||||
}
|
||||
if (name.equals(JobClassNameEnum.EXPORT_TIMESHEET_TO_TIM_JOB.getName())) {
|
||||
exportTimesheetsToTim.exportTimesheets();
|
||||
timImpExpInfo = exportTimesheetsToTim.getExportProcessInfo();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TimImpExpInfo getImportExportInfo() {
|
||||
return timImpExpInfo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initCreate() {
|
||||
this.jobSchedulerConfiguration = JobSchedulerConfiguration.create();
|
||||
|
|
|
|||
|
|
@ -21,21 +21,30 @@ package org.libreplan.web.orders;
|
|||
|
||||
import static org.libreplan.web.I18nHelper._;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
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.OrderSyncInfo;
|
||||
import org.libreplan.importers.IExportTimesheetsToTim;
|
||||
import org.libreplan.importers.TimImpExpInfo;
|
||||
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.util.GenericForwardComposer;
|
||||
import org.zkoss.zul.Label;
|
||||
import org.zkoss.zul.SimpleListModel;
|
||||
import org.zkoss.zul.Textbox;
|
||||
import org.zkoss.zul.api.Window;
|
||||
|
||||
/**
|
||||
* Controller for Tim synchronization
|
||||
|
|
@ -76,15 +85,18 @@ public class TimSynchronizationController extends GenericForwardComposer {
|
|||
public void startExportToTim() {
|
||||
LOG.info("startExportToTim(): " + orderController.getOrder().getName());
|
||||
txtProductCode.setConstraint("no empty:" + _("cannot be empty"));
|
||||
if (exportTimesheetsToTim.exportTimesheets(txtProductCode.getValue(),
|
||||
orderController.getOrder())) {
|
||||
messagesForUser.showMessage(Level.INFO,
|
||||
"Exporting timesheets to Tim is completed successfully");
|
||||
} else {
|
||||
try {
|
||||
exportTimesheetsToTim.exportTimesheets(txtProductCode.getValue(),
|
||||
orderController.getOrder());
|
||||
|
||||
updateOrderLastSyncInfoScreen();
|
||||
|
||||
shwoImpExpInfo();
|
||||
|
||||
} catch (ConnectorException e) {
|
||||
messagesForUser.showMessage(Level.ERROR,
|
||||
_("Exporting timesheets to Tim failed"));
|
||||
_("Exporting timesheets to Tim failed. Check the Tim connector"));
|
||||
}
|
||||
updateOrderLastSyncInfoScreen();
|
||||
}
|
||||
|
||||
private void updateOrderLastSyncInfoScreen() {
|
||||
|
|
@ -109,4 +121,26 @@ public class TimSynchronizationController extends GenericForwardComposer {
|
|||
}
|
||||
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());
|
||||
args.put("failedReasons",
|
||||
new SimpleListModel(timImpExpInfo.getFailedReasons()));
|
||||
|
||||
Window timImpExpInfoWindow = (Window) Executions.createComponents(
|
||||
"/orders/_timImpExpInfo.zul", null, args);
|
||||
|
||||
try {
|
||||
timImpExpInfoWindow.doModal();
|
||||
} catch (SuspendNotAllowedException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
31
libreplan-webapp/src/main/webapp/orders/_timImpExpInfo.zul
Normal file
31
libreplan-webapp/src/main/webapp/orders/_timImpExpInfo.zul
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<!--
|
||||
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/>.
|
||||
-->
|
||||
|
||||
<window id="winTimImpExpInfo" title="${i18n:_('LibrePlan: Tim import export info')}"
|
||||
width="500px" border="normal" mode="modal">
|
||||
<div>
|
||||
<vbox>
|
||||
<label value="${arg.action} ${i18n:_('was successful')}" sclass="remarked" if="${arg.showSuccess}"/>
|
||||
<label value="${arg.action} ${i18n:_('is not completed for the following reasons:')}" sclass="remarked" if="${not arg.showSuccess}"/>
|
||||
<listbox model="${arg.failedReasons}"/>
|
||||
</vbox>
|
||||
</div>
|
||||
<button id="closeBtn" label="${i18n:_('Close')}" onClick="winTimImpExpInfo.detach()"
|
||||
sclass="cancel-button global-action"/>
|
||||
</window>
|
||||
|
|
@ -44,14 +44,13 @@ import org.libreplan.business.IDataBootstrap;
|
|||
import org.libreplan.business.common.IAdHocTransactionService;
|
||||
import org.libreplan.business.common.IOnTransaction;
|
||||
import org.libreplan.business.common.daos.IConfigurationDAO;
|
||||
import org.libreplan.business.common.entities.ConnectorException;
|
||||
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
|
||||
import org.libreplan.business.orders.daos.IOrderDAO;
|
||||
import org.libreplan.business.orders.entities.Order;
|
||||
import org.libreplan.business.scenarios.IScenarioManager;
|
||||
import org.libreplan.business.scenarios.entities.OrderVersion;
|
||||
import org.libreplan.business.scenarios.entities.Scenario;
|
||||
import org.libreplan.importers.ExportTimesheetsToTim;
|
||||
import org.libreplan.importers.IExportTimesheetsToTim;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
|
@ -160,9 +159,12 @@ public class ExportTimesheetsToTimTest {
|
|||
|
||||
@Test
|
||||
@Ignore("Only working if you have a Tim server configured")
|
||||
public void testExportTimesheetsToTimWithValidCodeAndOrder() {
|
||||
public void testExportTimesheetsToTimWithValidCodeAndOrder()
|
||||
throws ConnectorException {
|
||||
Order order = givenOrder();
|
||||
boolean result = exportTimesheetsToTim.exportTimesheets("5160", order);
|
||||
exportTimesheetsToTim.exportTimesheets("5160", order);
|
||||
boolean result = exportTimesheetsToTim.getExportProcessInfo()
|
||||
.isSuccessful();
|
||||
if (!result) {
|
||||
fail("Export timesheets to tim failed");
|
||||
}
|
||||
|
|
@ -170,13 +172,15 @@ public class ExportTimesheetsToTimTest {
|
|||
}
|
||||
|
||||
@Test(expected = RuntimeException.class)
|
||||
public void testExportTimesheetsToTimWithInvalidCode() {
|
||||
public void testExportTimesheetsToTimWithInvalidCode()
|
||||
throws ConnectorException {
|
||||
Order order = givenOrder();
|
||||
exportTimesheetsToTim.exportTimesheets("", order);
|
||||
}
|
||||
|
||||
@Test(expected = RuntimeException.class)
|
||||
public void testExportTimesheetsToTimWithOrderNull() {
|
||||
public void testExportTimesheetsToTimWithOrderNull()
|
||||
throws ConnectorException {
|
||||
exportTimesheetsToTim.exportTimesheets("5160", null);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,8 +35,7 @@ import org.junit.runner.RunWith;
|
|||
import org.libreplan.business.IDataBootstrap;
|
||||
import org.libreplan.business.common.IAdHocTransactionService;
|
||||
import org.libreplan.business.common.IOnTransaction;
|
||||
import org.libreplan.importers.IImportRosterFromTim;
|
||||
import org.libreplan.importers.ImportRosterFromTim;
|
||||
import org.libreplan.business.common.entities.ConnectorException;
|
||||
import org.libreplan.web.calendars.IBaseCalendarModel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
|
|
@ -93,7 +92,7 @@ public class ImportRosterFromTimTest {
|
|||
|
||||
@Test
|
||||
@Ignore("Only working if you have a Tim server configured")
|
||||
public void testImportRosters() {
|
||||
public void testImportRosters() throws ConnectorException {
|
||||
importRosterFromTim.importRosters();
|
||||
assertTrue(baseCalendarModel.getCalendarExceptionType() != null);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue