org.libreplan.importers.ExportTimesheetsToTim.java Source code

Java tutorial

Introduction

Here is the source code for org.libreplan.importers.ExportTimesheetsToTim.java

Source

/*
 * 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 static org.libreplan.web.I18nHelper._;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.logging.Log;
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.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.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.entities.WorkReportLine;
import org.libreplan.importers.tim.DurationDTO;
import org.libreplan.importers.tim.PersonDTO;
import org.libreplan.importers.tim.ProductDTO;
import org.libreplan.importers.tim.RegistrationDateDTO;
import org.libreplan.importers.tim.TimOptions;
import org.libreplan.importers.tim.TimeRegistrationDTO;
import org.libreplan.importers.tim.TimeRegistrationRequestDTO;
import org.libreplan.importers.tim.TimeRegistrationResponseDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * Implementation of export timesheets to tim
 *
 * @author Miciele Ghiorghis <m.ghiorghis@antoniusziekenhuis.nl>
 */
@Component
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
public class ExportTimesheetsToTim implements IExportTimesheetsToTim {

    private static final Log LOG = LogFactory.getLog(ExportTimesheetsToTim.class);

    @Autowired
    private IWorkerDAO workerDAO;

    @Autowired
    IOrderSyncInfoDAO orderSyncInfoDAO;

    @Autowired
    private IAdHocTransactionService adHocTransactionService;

    @Autowired
    private IConnectorDAO connectorDAO;

    private SynchronizationInfo synchronizationInfo;

    @Override
    @Transactional(readOnly = true)
    public List<SynchronizationInfo> exportTimesheets() throws ConnectorException {
        Connector connector = getTimConnector();
        if (connector == null) {
            throw new ConnectorException(_("Tim connector not found"));
        }
        if (!connector.areConnectionValuesValid()) {
            throw new ConnectorException(_("Connection values of Tim connector are invalid"));
        }

        synchronizationInfo = new SynchronizationInfo(_("Export"));

        List<SynchronizationInfo> syncInfos = new ArrayList<SynchronizationInfo>();

        List<OrderSyncInfo> orderSyncInfos = orderSyncInfoDAO
                .findByConnectorName(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"));
            syncInfos.add(synchronizationInfo);
            return syncInfos;
        }

        for (OrderSyncInfo orderSyncInfo : orderSyncInfos) {
            LOG.info("Exporting '" + orderSyncInfo.getOrder().getName() + "'");
            exportTimesheets(orderSyncInfo.getKey(), orderSyncInfo.getOrder(), connector);
            if (!synchronizationInfo.isSuccessful()) {
                syncInfos.add(synchronizationInfo);
            }
        }
        return syncInfos;
    }

    @Override
    @Transactional(readOnly = true)
    public void exportTimesheets(String productCode, Order order) throws ConnectorException {
        if (productCode == null || productCode.isEmpty()) {
            throw new ConnectorException(_("Product code should not be empty"));
        }
        if (order == null) {
            throw new ConnectorException(_("Order should not be empty"));
        }

        Connector connector = getTimConnector();
        if (connector == null) {
            throw new ConnectorException(_("Tim connector not found"));
        }

        if (!connector.areConnectionValuesValid()) {
            throw new ConnectorException(_("Connection values of Tim connector are invalid"));
        }

        exportTimesheets(productCode, order, connector);
    }

    /**
     * exports time sheets to Tim
     *
     * @param productCode
     *            the product code
     * @param order
     *            the order
     * @param connector
     *            the connector
     *
     * @return true if export is succeeded, false otherwise
     */
    private void exportTimesheets(String productCode, Order order, Connector connector) {

        synchronizationInfo = new SynchronizationInfo(
                _("Export product code {0}, project {1}", productCode, order.getName()));

        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);
        int nrDaysTimesheetToTim = Integer
                .parseInt(properties.get(PredefinedConnectorProperties.TIM_NR_DAYS_TIMESHEET));

        LocalDate dateNrOfDaysBack = new LocalDate().minusDays(nrDaysTimesheetToTim);

        List<WorkReportLine> workReportLines = order
                .getWorkReportLines(dateNrOfDaysBack.toDateTimeAtStartOfDay().toDate(), new Date(), true);
        if (workReportLines == null || workReportLines.isEmpty()) {
            LOG.warn("No work reportlines are found for order: '" + order.getName() + "'");
            synchronizationInfo
                    .addFailedReason(_("No work reportlines are found for order: \"{0}\"", order.getName()));
            return;
        }

        List<TimeRegistrationDTO> timeRegistrationDTOs = new ArrayList<TimeRegistrationDTO>();

        for (WorkReportLine workReportLine : workReportLines) {
            TimeRegistrationDTO timeRegistrationDTO = createExportTimeRegistration(productCode, workReportLine);
            if (timeRegistrationDTO != null) {
                timeRegistrationDTOs.add(timeRegistrationDTO);
            }
        }

        if (timeRegistrationDTOs.isEmpty()) {
            LOG.warn("Unable to crate timeregistration for request");
            synchronizationInfo.addFailedReason(_("Unable to crate time registration for request"));
            return;
        }

        TimeRegistrationRequestDTO timeRegistrationRequestDTO = new TimeRegistrationRequestDTO();
        timeRegistrationRequestDTO.setTimeRegistrations(timeRegistrationDTOs);

        TimeRegistrationResponseDTO timeRegistrationResponseDTO = TimSoapClient.sendRequestReceiveResponse(url,
                userName, password, timeRegistrationRequestDTO, TimeRegistrationResponseDTO.class);

        if (timeRegistrationResponseDTO == null) {
            LOG.error("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");
            synchronizationInfo.addFailedReason(_("Registration response with empty refs"));
            return;
        }
        saveSyncInfoOnAnotherTransaction(productCode, order);
    }

    /**
     * checks if list of refs is empty
     *
     * @param refs
     *            the list of refs
     * @return true if list is empty otherwise false
     */
    private boolean isRefsListEmpty(List<Integer> refs) {
        if (refs == null) {
            return true;
        }
        refs.removeAll(Collections.singleton(0));
        return refs.isEmpty();
    }

    /**
     * Saves synchronization info
     *
     * @param productCode
     *            the productcode
     * @param order
     *            the order
     */
    private void saveSyncInfoOnAnotherTransaction(final String productCode, final Order order) {
        adHocTransactionService.runOnAnotherTransaction(new IOnTransaction<Void>() {
            @Override
            public Void execute() {
                OrderSyncInfo orderSyncInfo = orderSyncInfoDAO.findByKeyOrderAndConnectorName(productCode, order,
                        PredefinedConnectors.TIM.getName());
                if (orderSyncInfo == null) {
                    orderSyncInfo = OrderSyncInfo.create(productCode, order, PredefinedConnectors.TIM.getName());
                }
                orderSyncInfo.setLastSyncDate(new Date());
                orderSyncInfoDAO.save(orderSyncInfo);
                return null;
            }
        });
    }

    /**
     * Creates export time registration
     *
     * @param productCode
     *            the product code
     * @param workReportLine
     *            the workreportLine
     * @return timeRegistration DTO
     */
    private TimeRegistrationDTO createExportTimeRegistration(String productCode, WorkReportLine workReportLine) {
        Worker worker;
        String workerCode = workReportLine.getResource().getCode();
        try {
            worker = workerDAO.findByCode(workerCode);
        } catch (InstanceNotFoundException e) {
            LOG.warn("Worker '" + workerCode + "' not found");
            synchronizationInfo.addFailedReason(_("Worker \"{0}\" not found", workerCode));
            return null;
        }

        PersonDTO personDTO = new PersonDTO();
        personDTO.setName(worker.getName());
        personDTO.setOptions(TimOptions.UPDATE_OR_INSERT);

        ProductDTO productDTO = new ProductDTO();
        productDTO.setOptions(TimOptions.UPDATE_OR_INSERT);
        productDTO.setCode(productCode);

        RegistrationDateDTO registrationDTO = new RegistrationDateDTO();
        registrationDTO.setOptions(TimOptions.UPDATE_OR_INSERT);
        registrationDTO.setDate(workReportLine.getLocalDate());

        DurationDTO durationDTO = new DurationDTO();
        durationDTO.setOptions(TimOptions.DECIMAL);
        durationDTO.setDuration(workReportLine.getEffort().toHoursAsDecimalWithScale(2).doubleValue());

        TimeRegistrationDTO timeRegistrationDTO = new TimeRegistrationDTO();
        timeRegistrationDTO.setPerson(personDTO);
        timeRegistrationDTO.setProduct(productDTO);
        timeRegistrationDTO.setRegistrationDate(registrationDTO);
        timeRegistrationDTO.setDuration(durationDTO);
        return timeRegistrationDTO;
    }

    @Override
    @Transactional(readOnly = true)
    public OrderSyncInfo getOrderLastSyncInfo(Order order) {
        return orderSyncInfoDAO.findLastSynchronizedInfoByOrderAndConnectorName(order,
                PredefinedConnectors.TIM.getName());
    }

    /**
     * finds and returns a Tim connector
     */
    private Connector getTimConnector() {
        return connectorDAO.findUniqueByName(PredefinedConnectors.TIM.getName());
    }

    @Override
    public SynchronizationInfo getSynchronizationInfo() {
        return synchronizationInfo;
    }

}