org.libreplan.web.works.WorkModel.java Source code

Java tutorial

Introduction

Here is the source code for org.libreplan.web.works.WorkModel.java

Source

/*
 * This file is part of LibrePlan
 *
 * Copyright (C) 2009-2010 Fundacin para o Fomento da Calidade Industrial e
 *                         Desenvolvemento Tecnolxico de Galicia
 * Copyright (C) 2010-2011 Igalia, S.L.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package org.libreplan.web.works;

import static org.libreplan.business.common.exceptions.ValidationException.invalidValue;
import static org.libreplan.web.I18nHelper._;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.Validate;
import org.hibernate.NonUniqueResultException;
import org.joda.time.LocalDate;
import org.libreplan.business.common.IOnTransaction;
import org.libreplan.business.common.Registry;
import org.libreplan.business.common.daos.IConfigurationDAO;
import org.libreplan.business.common.daos.IEntitySequenceDAO;
import org.libreplan.business.common.entities.EntityNameEnum;
import org.libreplan.business.common.exceptions.InstanceNotFoundException;
import org.libreplan.business.common.exceptions.ValidationException;
import org.libreplan.business.documents.daos.IDocumentDAO;
import org.libreplan.business.orders.daos.ISumChargedEffortDAO;
import org.libreplan.business.orders.entities.OrderElement;
import org.libreplan.business.users.daos.IUserCoachDAO;
import org.libreplan.business.users.daos.IUserDAO;
import org.libreplan.business.users.daos.IUserDepartmentDAO;
import org.libreplan.business.users.daos.IUserSuperiorDAO;
import org.libreplan.business.users.entities.User;
import org.libreplan.business.users.entities.UserCoach;
import org.libreplan.business.users.entities.UserSuperior;
import org.libreplan.business.workingday.EffortDuration;
import org.libreplan.business.workingday.EffortDuration.Granularity;
import org.libreplan.business.workreports.daos.IWorkReportDAO;
import org.libreplan.business.workreports.daos.IWorkReportTypeDAO;
import org.libreplan.business.workreports.entities.PredefinedWorkReportTypes;
import org.libreplan.business.workreports.entities.WorkReport;
import org.libreplan.business.workreports.entities.WorkReportLine;
import org.libreplan.business.workreports.entities.WorkReportType;
import org.libreplan.business.works.daos.IWorkDAO;
import org.libreplan.business.works.entities.Work;
import org.libreplan.business.works.entities.WorkStateEnum;
import org.libreplan.business.works.entities.WorkStatusEnum;
import org.libreplan.business.works.entities.WorkTypeEnum;
import org.libreplan.web.UserUtil;
import org.libreplan.web.common.Util;
import org.libreplan.web.common.concurrentdetection.OnConcurrentModification;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.zkoss.zul.Textbox;

@Service
@Scope(BeanDefinition.SCOPE_PROTOTYPE)
@OnConcurrentModification(goToPage = "/works/work.zul")
public class WorkModel implements IWorkModel {

    @Autowired
    private IWorkDAO workDAO;

    @Autowired
    private IDocumentDAO documentDAO;

    @Autowired
    private IUserDAO userDAO;

    @Autowired
    private IUserSuperiorDAO userSuperiorDAO;

    @Autowired
    private IUserCoachDAO userCoachDAO;

    @Autowired
    private IWorkReportDAO workReportDAO;

    @Autowired
    private IConfigurationDAO configurationDAO;

    @Autowired
    private IEntitySequenceDAO entitySequenceDAO;

    @Autowired
    private IWorkReportTypeDAO workReportTypeDAO;

    @Autowired
    private ISumChargedEffortDAO sumChargedEffortDAO;

    private Work work;

    private BigDecimal previousUsedHours = BigDecimal.ZERO;

    public WorkModel() {
    }

    @Override
    @Transactional(readOnly = true)
    public List<Work> getWorks() {
        User user = UserUtil.getUserFromSession();
        return workDAO.getWorksOfUser(user);
    }

    @Override
    @Transactional
    public void confirmDelete(Work work) throws InstanceNotFoundException {
        if (work.getType() == WorkTypeEnum.TASK) {
            updateWorkReport(work, true);
        }
        workDAO.remove(work);
        workDAO.flush();
    }

    @Override
    @Transactional
    public void confirmSave() throws ValidationException {
        Validate.notEmpty(work.getTitle());
        if (!Util.isSameDate(work.getFromTime(), work.getToTime())) {
            throw new ValidationException(invalidValue(_("From time and end time should be in same date."), "title",
                    work.getTitle(), work));
        }
        if (work.getFromTime().compareTo(work.getToTime()) > 0) {
            throw new ValidationException(
                    invalidValue(_("From time should not be after end time ."), "title", work.getTitle(), work));
        }
        if (work.getType() == WorkTypeEnum.TASK && work.getTask() == null) {
            throw new ValidationException(
                    invalidValue(_("Work of task must has a task related to it."), "title", work.getTitle(), work));
        }
        if (work.getType() == WorkTypeEnum.PROJECT && work.getProject() == null) {
            throw new ValidationException(invalidValue(_("Work of project must has a project related to it."),
                    "title", work.getTitle(), work));
        }
        if (work.isNewObject()) {
            work.setRegisterTime(new Date());
        }

        workDAO.saveWithoutValidating(work);
        workDAO.flush();
    }

    @Override
    @Transactional
    public void acceptOrRejectWork(boolean accept, String comment) throws ValidationException {
        User user = UserUtil.getUserFromSession();
        String ocomment = work.getReviewComment();
        if (comment == null)
            comment = "";
        comment = ocomment + "\n\n" + _((accept ? " reviewed" : " rejected") + " by {0} at {1}.",
                user.getFullName(), Util.formatDateTime(new Date(), "")) + "\n\t" + _("Comment: ") + comment;
        work.setReviewComment(comment);
        if (accept) {
            work.setReviewTime(new Date());
            work.setReviewUser(user);

            if (work.getType() == WorkTypeEnum.TASK) {
                updateWorkReport(work, false);
            }
        }
        work.setStatus(accept ? WorkStatusEnum.REVIEWED : WorkStatusEnum.REJECTED);

        confirmSave();
    }

    private void updateWorkReport(Work work, boolean delete) {
        LocalDate date = LocalDate.fromDateFields(work.getFromTime());
        WorkReport wr = workReportDAO.getPersonalTimesheetWorkReport(work.getUser().getWorker(), date,
                configurationDAO.getConfiguration().getPersonalTimesheetsPeriodicity());

        if (wr == null) {
            wr = WorkReport.create(getPersonalTimesheetsWorkReportType());
            wr.setCode(entitySequenceDAO.getNextEntityCodeWithoutTransaction(EntityNameEnum.WORK_REPORT));
            wr.setCodeAutogenerated(true);
            wr.setResource(work.getUser().getWorker());
        } else {
            forceLoad(wr.getWorkReportLines());
        }
        WorkReportLine wrl = null;
        OrderElement orderElement = work.getTask();
        for (WorkReportLine line : wr.getWorkReportLines()) {
            if (line.getOrderElement().getId().equals(orderElement.getId())
                    && LocalDate.fromDateFields(line.getDate()).equals(date)) {
                wrl = line;
                break;
            }
        }
        if (wrl == null) {
            wrl = createWorkReportLine(wr, orderElement, date);
            wr.addWorkReportLine(wrl);
        }
        BigDecimal diff = (delete) ? work.getUsedHours().negate() : work.getUsedHours().subtract(previousUsedHours);

        EffortDuration de = EffortDuration.seconds((int) (diff.doubleValue() * 3600));
        EffortDuration effort = wrl.getEffort().plus(de);
        if (effort.compareTo(EffortDuration.zero()) < 0)
            effort = EffortDuration.zero();
        wrl.setEffort(effort);
        sumChargedEffortDAO.updateRelatedSumChargedEffortWithWorkReportLineSet(wr.getWorkReportLines());
        wr.generateWorkReportLineCodes(entitySequenceDAO.getNumberOfDigitsCode(EntityNameEnum.WORK_REPORT));
        workReportDAO.save(wr);
        workReportDAO.flush();
    }

    private void forceLoad(Set<WorkReportLine> workReportLines) {
        for (WorkReportLine line : workReportLines) {
            line.getOrderElement().getName();
        }
    }

    private WorkReportLine createWorkReportLine(WorkReport workReport, OrderElement orderElement, LocalDate date) {
        WorkReportLine workReportLine = WorkReportLine.create(workReport);
        workReportLine.setCodeAutogenerated(true);
        workReportLine.setOrderElement(orderElement);
        workReportLine.setDate(date.toDateTimeAtStartOfDay().toDate());
        workReportLine
                .setTypeOfWorkHours(configurationDAO.getConfiguration().getPersonalTimesheetsTypeOfWorkHours());
        workReportLine.setEffort(EffortDuration.zero());
        return workReportLine;
    }

    private WorkReportType getPersonalTimesheetsWorkReportType() {
        try {
            WorkReportType workReportType = workReportTypeDAO
                    .findUniqueByName(PredefinedWorkReportTypes.PERSONAL_TIMESHEETS.getName());
            return workReportType;
        } catch (NonUniqueResultException e) {
            throw new RuntimeException(e);
        } catch (InstanceNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Work getWork() {
        return work;
    }

    @Override
    public void initCreate() {
        User user = UserUtil.getUserFromSession();
        work = Work.create(user, "", "");
        work.setFromTime(Util.getRoundedDate(new Date(), 8));
        work.setToTime(Util.getRoundedDate(new Date(), 18));
        work.setUsedHours(new BigDecimal("1"));
        work.setType(WorkTypeEnum.DAILY);
        work.setState(WorkStateEnum.FINISHED);
        work.setStatus(WorkStatusEnum.RECORDED);
        previousUsedHours = BigDecimal.ZERO;
    }

    @Override
    @Transactional(readOnly = true)
    public void initEdit(Work wrk) {
        Validate.notNull(wrk);
        this.work = getFromDB(wrk);
        previousUsedHours = this.work.getUsedHours();
    }

    private Work getFromDB(Work wrk) {
        try {
            return workDAO.find(wrk.getId());
        } catch (InstanceNotFoundException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void initCreate(Object data, Object parent) {

        initCreate();

        if (data instanceof WorkTypeEnum) {
            WorkTypeEnum type = (WorkTypeEnum) data;
            if ((parent instanceof String) && ((String) parent).equals(_("My Own Works"))) {
                work.setType(type);
            }
        }
    }

    @Override
    public void initCreate(Work preceding) {
        initCreate();
        work.setType(preceding.getType());
        work.setPreceding(preceding);
        work.setTask(preceding.getTask());
        work.setProject(preceding.getProject());
    }

    @Override
    @Transactional(readOnly = true)
    public List<Work> search(User user, boolean onlyTitle, String searchString) {
        String[] keyWords = searchString.split("[\\,\\;\\s]");
        List<Work> works = workDAO.search(user, onlyTitle, keyWords);
        List<Work> result = new ArrayList<Work>();
        for (Work wrk : works) {
            if (canViewWork(wrk)) {
                result.add(wrk);
            }
        }
        return result;
    }

    /**
     * 
     * @param work
     * @return boolean:if current user can read work 
     *       user can view works: 
     *          >>his own work
     *          >>his subordinate's work which work type is daily,interim,schudled;
     *          >>his apprentice's work which work type is apprenticeship work 
     *          >>work of tasks which which the user can access
     *          >>work of project which the user can access
     */
    @Override
    @Transactional(readOnly = true)
    public boolean canViewWork(final Work work) {
        if (work != null) {

            LocalDate date = LocalDate.fromDateFields(work.getFromTime());
            User user = UserUtil.getUserFromSession();
            User wuser = work.getUser();
            if (wuser != null) {
                if (wuser.getId().equals(user.getId()))
                    return true;
                if (work.getType() == WorkTypeEnum.DAILY || work.getType() == WorkTypeEnum.INTERIM
                        || work.getType() == WorkTypeEnum.SCHEDULED) {

                    return userSuperiorDAO.isSuperior(user, wuser, date);
                } else if (work.getType() == WorkTypeEnum.APPRENTICESHIP) {
                    return userCoachDAO.isCoach(user, wuser, date);
                }
            } else if (work.getType() == WorkTypeEnum.PROJECT) {
            } else if (work.getType() == WorkTypeEnum.TASK) {

            }
            return false;

        }
        return false;
    }

    /**
     * 
     * @param work
     * @return boolean:if current user can edit work 
     *       user can edit works: 
     *          >>his own work that hasn't been reviewed
     */
    @Override
    @Transactional(readOnly = true)
    public boolean canEditWork(Work work) {
        if (work != null) {
            User user = UserUtil.getUserFromSession();
            User wuser = work.getUser();
            return (wuser != null && wuser.getId().equals(user.getId())
                    && work.getStatus() != WorkStatusEnum.REVIEWED);
        }
        return false;
    }

    /**
     * 
     * @param work
     * @return boolean:if current user can delete work 
     *       user can delete works: 
     *          >>his own work that hasn't been reviewed and rejected
     */
    @Override
    @Transactional(readOnly = true)
    public boolean canDeleteWork(Work work) {
        if (work != null) {
            User user = UserUtil.getUserFromSession();
            User wuser = work.getUser();
            return (wuser != null && wuser.getId().equals(user.getId())
                    && work.getStatus() != WorkStatusEnum.REVIEWED && work.getStatus() != WorkStatusEnum.REJECTED);
        }
        return false;
    }

    /**
     * 
     * @param work
     * @return boolean:if current user can continue work 
     *       user can continue works: 
     *          >>his own work
     *          >>work of tasks which which the user can access
     *          >>work of project which the user can access   
     */
    @Override
    @Transactional(readOnly = true)
    public boolean canContinueWork(final Work work) {
        if (work != null) {

            User user = UserUtil.getUserFromSession();
            User wuser = work.getUser();
            if (wuser != null) {
                if (wuser.getId().equals(user.getId()))
                    return true;
            } else if (work.getType() == WorkTypeEnum.PROJECT) {
            } else if (work.getType() == WorkTypeEnum.TASK) {

            }
            return false;

        }
        return false;
    }

    /**
     * 
     * @param work
     * @return boolean:if current user can continue work 
     *       user can review works: 
     *          >>his directive apprentice's apprenticeship work
     *          >>his directive subordinate' daily,scheduled,interim work
     *          >>work of task which the user is manager 
     *          >>work of project which the user is manager   
     */
    @Override
    @Transactional(readOnly = true)
    public boolean canReviewWork(final Work work) {
        if (work != null) {
            if (work.getStatus() == WorkStatusEnum.REVIEWED || work.getStatus() == WorkStatusEnum.DRAFT)
                return false;
        }

        User user = UserUtil.getUserFromSession();
        User wuser = work.getUser();
        LocalDate date = LocalDate.fromDateFields(work.getFromTime());
        if (work.getType() == WorkTypeEnum.DAILY || work.getType() == WorkTypeEnum.INTERIM
                || work.getType() == WorkTypeEnum.SCHEDULED) {
            UserSuperior us = userSuperiorDAO.findByUser(wuser, date);
            return us != null && us.getSuperior() != null && us.getSuperior().getId().equals(user.getId());
        } else if (work.getType() == WorkTypeEnum.APPRENTICESHIP) {
            UserCoach uc = userCoachDAO.findByUser(wuser, date);
            return uc != null && uc.getCoach() != null && uc.getCoach().getId().equals(user.getId());
        } else if (work.getType() == WorkTypeEnum.PROJECT) {
        } else if (work.getType() == WorkTypeEnum.TASK) {

        }
        return false;

    }

}