org.projectforge.web.fibu.MonthlyEmployeeReportPage.java Source code

Java tutorial

Introduction

Here is the source code for org.projectforge.web.fibu.MonthlyEmployeeReportPage.java

Source

/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
//         www.projectforge.org
//
// Copyright (C) 2001-2013 Kai Reinhard (k.reinhard@micromata.de)
//
// ProjectForge is dual-licensed.
//
// This community edition is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as published
// by the Free Software Foundation; version 3 of the License.
//
// This community edition 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 General
// Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, see http://www.gnu.org/licenses/.
//
/////////////////////////////////////////////////////////////////////////////

package org.projectforge.web.fibu;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.wicket.AttributeModifier;
import org.apache.wicket.Component;
import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.SubmitLink;
import org.apache.wicket.markup.html.link.Link;
import org.apache.wicket.markup.repeater.RepeatingView;
import org.apache.wicket.model.Model;
import org.apache.wicket.model.ResourceModel;
import org.apache.wicket.request.mapper.parameter.PageParameters;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.projectforge.common.NumberHelper;
import org.projectforge.core.Configuration;
import org.projectforge.fibu.KostFormatter;
import org.projectforge.fibu.KundeDO;
import org.projectforge.fibu.MonthlyEmployeeReport;
import org.projectforge.fibu.MonthlyEmployeeReport.Kost2Row;
import org.projectforge.fibu.MonthlyEmployeeReportDao;
import org.projectforge.fibu.MonthlyEmployeeReportEntry;
import org.projectforge.fibu.MonthlyEmployeeReportWeek;
import org.projectforge.fibu.ProjektDO;
import org.projectforge.fibu.kost.Kost1DO;
import org.projectforge.fibu.kost.Kost1Dao;
import org.projectforge.fibu.kost.Kost2ArtDO;
import org.projectforge.fibu.kost.Kost2DO;
import org.projectforge.renderer.PdfRenderer;
import org.projectforge.task.TaskDO;
import org.projectforge.user.PFUserDO;
import org.projectforge.user.UserDao;
import org.projectforge.user.UserGroupCache;
import org.projectforge.web.calendar.DateTimeFormatter;
import org.projectforge.web.common.OutputType;
import org.projectforge.web.task.TaskFormatter;
import org.projectforge.web.timesheet.TimesheetListPage;
import org.projectforge.web.wicket.AbstractStandardFormPage;
import org.projectforge.web.wicket.DownloadUtils;
import org.projectforge.web.wicket.WicketUtils;
import org.projectforge.web.wicket.bootstrap.GridBuilder;
import org.projectforge.web.wicket.bootstrap.GridSize;
import org.projectforge.web.wicket.components.ContentMenuEntryPanel;
import org.projectforge.web.wicket.flowlayout.DivTextPanel;
import org.projectforge.web.wicket.flowlayout.FieldsetPanel;
import org.projectforge.web.wicket.flowlayout.TextStyle;

public class MonthlyEmployeeReportPage extends AbstractStandardFormPage implements ISelectCallerPage {
    private static final long serialVersionUID = -136398850032685654L;

    private static final org.apache.log4j.Logger log = org.apache.log4j.Logger
            .getLogger(MonthlyEmployeeReportPage.class);

    private static final String USER_PREF_KEY_FILTER = "monthlyEmployeeReportFilter";

    @SpringBean(name = "userDao")
    private UserDao userDao;

    private final MonthlyEmployeeReportForm form;

    private MonthlyEmployeeReport report;

    private WebMarkupContainer table;

    @SpringBean(name = "monthlyEmployeeReportDao")
    private MonthlyEmployeeReportDao monthlyEmployeeReportDao;

    @SpringBean(name = "pdfRenderer")
    private PdfRenderer pdfRenderer;

    @SpringBean(name = "kost1Dao")
    private Kost1Dao kost1Dao;

    @SpringBean(name = "dateTimeFormatter")
    private DateTimeFormatter dateTimeFormatter;

    @SpringBean(name = "taskFormatter")
    private TaskFormatter taskFormatter;

    @SpringBean(name = "userGroupCache")
    private UserGroupCache userGroupCache;

    private final GridBuilder gridBuilder;

    @SuppressWarnings("serial")
    public MonthlyEmployeeReportPage(final PageParameters parameters) {
        super(parameters);
        final boolean costConfigured = Configuration.getInstance().isCostConfigured();
        form = new MonthlyEmployeeReportForm(this);
        if (form.filter == null) {
            form.filter = (MonthlyEmployeeReportFilter) getUserPrefEntry(MonthlyEmployeeReportFilter.class,
                    USER_PREF_KEY_FILTER);
        }
        if (form.filter == null) {
            form.filter = new MonthlyEmployeeReportFilter();
            putUserPrefEntry(USER_PREF_KEY_FILTER, form.filter, true);
        }
        if (form.filter.getUser() == null) {
            form.filter.setUser(getUser());
        }
        body.add(form);
        form.init();
        {
            final ContentMenuEntryPanel exportAsPdf = new ContentMenuEntryPanel(getNewContentMenuChildId(),
                    new SubmitLink("link", form) {
                        @Override
                        public void onSubmit() {
                            exportAsPdf();
                        };
                    }, getString("exportAsPdf"));
            addContentMenuEntry(exportAsPdf);
        }
        gridBuilder = form.newGridBuilder(body, "fields");
        final GridSize gridSize = costConfigured == true ? GridSize.COL33 : GridSize.COL50;
        gridBuilder.newSplitPanel(gridSize);
        {
            final FieldsetPanel fs = gridBuilder.newFieldset(getString("timesheet.user")).supressLabelForWarning();
            fs.add(new DivTextPanel(fs.newChildId(), new Model<String>() {
                /**
                 * @see org.apache.wicket.model.Model#getObject()
                 */
                @Override
                public String getObject() {
                    final PFUserDO user = form.filter.getUser();
                    return user != null ? user.getFullname() : "";
                }
            }));
        }
        if (costConfigured == true) {
            gridBuilder.newSplitPanel(gridSize);
            final FieldsetPanel fs = gridBuilder.newFieldset(getString("fibu.kost1")).supressLabelForWarning();
            fs.add(new DivTextPanel(fs.newChildId(), new Model<String>() {
                /**
                 * @see org.apache.wicket.model.Model#getObject()
                 */
                @Override
                public String getObject() {
                    if (report == null) {
                        return "";
                    }
                    final Kost1DO kost1 = kost1Dao.internalGetById(report.getKost1Id());
                    return kost1 != null ? KostFormatter.format(kost1) : "";
                }
            }));
        }
        gridBuilder.newSplitPanel(gridSize);
        {
            final FieldsetPanel fs = gridBuilder.newFieldset(getString("fibu.common.workingDays"))
                    .supressLabelForWarning();
            fs.add(new DivTextPanel(fs.newChildId(), new Model<String>() {
                @Override
                public String getObject() {
                    return report != null ? String.valueOf(report.getNumberOfWorkingDays()) : "";
                };
            }));
        }
        gridBuilder.newGridPanel();
        {
            final FieldsetPanel fs = new FieldsetPanel(gridBuilder.getPanel(), getString("fibu.common.workingDays"),
                    getString("fibu.monthlyEmployeeReport.withoutTimesheets")) {
                /**
                 * @see org.apache.wicket.Component#isVisible()
                 */
                @Override
                public boolean isVisible() {
                    return report != null && StringUtils.isNotBlank(report.getFormattedUnbookedDays());
                }
            }.supressLabelForWarning();
            fs.add(new DivTextPanel(fs.newChildId(), new Model<String>() {
                /**
                 * @see org.apache.wicket.model.Model#getObject()
                 */
                @Override
                public String getObject() {
                    return report.getFormattedUnbookedDays();
                }
            }, TextStyle.RED));
        }
    }

    @Override
    public void onBeforeRender() {
        if (table != null) {
            body.remove(table);
        }
        body.add(table = new WebMarkupContainer("table"));
        report = monthlyEmployeeReportDao.getReport(form.filter.getYear(), form.filter.getMonth(),
                form.filter.getUser());
        if (report == null) {
            table.setVisible(false);
        } else {
            addReport();
        }
        super.onBeforeRender();
    }

    private void addReport() {
        final RepeatingView headcolRepeater = new RepeatingView("headcolRepeater");
        table.add(headcolRepeater);
        if (MapUtils.isEmpty(report.getKost2Rows()) == false) {
            headcolRepeater.add(new Label(headcolRepeater.newChildId(), getString("fibu.kost2")));
            headcolRepeater.add(new Label(headcolRepeater.newChildId(), getString("fibu.kunde")));
            headcolRepeater.add(new Label(headcolRepeater.newChildId(), getString("fibu.projekt")));
            headcolRepeater.add(new Label(headcolRepeater.newChildId(), getString("fibu.kost2.art")));
        } else {
            // No kost 2 entries, so only task as head is useful.
            headcolRepeater.add(new Label(headcolRepeater.newChildId(), getString("task"))
                    .add(AttributeModifier.replace("colspan", "4")));
        }
        final RepeatingView headcolWeekRepeater = new RepeatingView("headcolWeekRepeater");
        table.add(headcolWeekRepeater);
        for (final MonthlyEmployeeReportWeek week : report.getWeeks()) {
            headcolWeekRepeater.add(new Label(headcolWeekRepeater.newChildId(),
                    week.getFormattedFromDayOfMonth() + ".-" + week.getFormattedToDayOfMonth() + "."));
        }
        final RepeatingView rowRepeater = new RepeatingView("rowRepeater");
        table.add(rowRepeater);
        int rowCounter = 0;
        for (final Map.Entry<String, Kost2Row> rowEntry : report.getKost2Rows().entrySet()) {
            final WebMarkupContainer row = new WebMarkupContainer(rowRepeater.newChildId());
            rowRepeater.add(row);
            if (rowCounter++ % 2 == 0) {
                row.add(AttributeModifier.replace("class", "even"));
            } else {
                row.add(AttributeModifier.replace("class", "odd"));
            }
            final Kost2Row kost2Row = rowEntry.getValue();
            final Kost2DO cost2 = kost2Row.getKost2();
            addLabelCols(row, cost2, null, "kost2.nummer:" + cost2.getFormattedNumber(), report.getUser(),
                    report.getFromDate().getTime(), report.getToDate().getTime());
            final RepeatingView colWeekRepeater = new RepeatingView("colWeekRepeater");
            row.add(colWeekRepeater);
            for (final MonthlyEmployeeReportWeek week : report.getWeeks()) {
                final MonthlyEmployeeReportEntry entry = week.getKost2Entries().get(kost2Row.getKost2().getId());
                colWeekRepeater.add(
                        new Label(colWeekRepeater.newChildId(), entry != null ? entry.getFormattedDuration() : ""));
            }
            row.add(new Label("sum", report.getKost2Durations().get(cost2.getId()).getFormattedDuration()));
        }

        for (final Map.Entry<String, TaskDO> rowEntry : report.getTaskEntries().entrySet()) {
            final WebMarkupContainer row = new WebMarkupContainer(rowRepeater.newChildId());
            rowRepeater.add(row);
            if (rowCounter++ % 2 == 0) {
                row.add(AttributeModifier.replace("class", "even"));
            } else {
                row.add(AttributeModifier.replace("class", "odd"));
            }
            final TaskDO task = rowEntry.getValue();
            addLabelCols(row, null, task, null, report.getUser(), report.getFromDate().getTime(),
                    report.getToDate().getTime());
            final RepeatingView colWeekRepeater = new RepeatingView("colWeekRepeater");
            row.add(colWeekRepeater);
            for (final MonthlyEmployeeReportWeek week : report.getWeeks()) {
                final MonthlyEmployeeReportEntry entry = week.getTaskEntries().get(task.getId());
                colWeekRepeater.add(
                        new Label(colWeekRepeater.newChildId(), entry != null ? entry.getFormattedDuration() : ""));
            }
            row.add(new Label("sum", report.getTaskDurations().get(task.getId()).getFormattedDuration()));
        }
        {
            // Sum row.
            final WebMarkupContainer row = new WebMarkupContainer(rowRepeater.newChildId());
            rowRepeater.add(row);
            if (rowCounter++ % 2 == 0) {
                row.add(AttributeModifier.replace("class", "even"));
            } else {
                row.add(AttributeModifier.replace("class", "odd"));
            }
            addLabelCols(row, null, null, null, report.getUser(), report.getFromDate().getTime(),
                    report.getToDate().getTime()).add(AttributeModifier.replace("style", "text-align: right;"));
            final RepeatingView colWeekRepeater = new RepeatingView("colWeekRepeater");
            row.add(colWeekRepeater);
            for (final MonthlyEmployeeReportWeek week : report.getWeeks()) {
                colWeekRepeater.add(new Label(colWeekRepeater.newChildId(), week.getFormattedTotalDuration()));
            }
            row.add(new Label("sum", report.getFormattedTotalNetDuration())
                    .add(AttributeModifier.replace("style", "font-weight: bold; color:red; text-align: right;")));
        }
        if (report.getTotalGrossDuration() != report.getTotalNetDuration()) {
            // Net sum row.
            final WebMarkupContainer row = new WebMarkupContainer(rowRepeater.newChildId());
            rowRepeater.add(row);
            if (rowCounter++ % 2 == 0) {
                row.add(AttributeModifier.replace("class", "even"));
            } else {
                row.add(AttributeModifier.replace("class", "odd"));
            }
            final Component comp = new WebMarkupContainer("cost2").setVisible(false);
            row.add(comp);
            row.add(new Label("customer", "").setVisible(false));
            row.add(new Label("project", "").setVisible(false));
            final Label title = addCostType(row, getString("fibu.monthlyEmployeeReport.totalSum"));
            WicketUtils.addTooltip(title, new ResourceModel("fibu.monthlyEmployeeReport.totalSum.tooltip"));
            final WebMarkupContainer tdContainer = title.findParent(WebMarkupContainer.class);
            tdContainer.add(AttributeModifier.replace("colspan", "4"));
            tdContainer.add(AttributeModifier.replace("style", "font-weight: bold; text-align: right;"));
            final RepeatingView colWeekRepeater = new RepeatingView("colWeekRepeater");
            row.add(colWeekRepeater);
            for (@SuppressWarnings("unused")
            final MonthlyEmployeeReportWeek week : report.getWeeks()) {
                colWeekRepeater.add(new Label(colWeekRepeater.newChildId(), ""));
            }
            row.add(new Label("sum", report.getFormattedTotalGrossDuration())
                    .add(AttributeModifier.replace("style", "font-weight: bold; text-align: right;")));
        }
    }

    @SuppressWarnings("serial")
    private WebMarkupContainer addLabelCols(final WebMarkupContainer row, final Kost2DO cost2, final TaskDO task,
            final String searchString, final PFUserDO user, final long startTime, final long stopTime) {
        final WebMarkupContainer result = new WebMarkupContainer("cost2");
        row.add(result);
        final Link<String> link = new Link<String>("link") {
            @Override
            public void onClick() {
                final PageParameters params = new PageParameters();
                params.add("userId", user.getId());
                if (task != null) {
                    params.add("taskId", task.getId());
                }
                params.add("startTime", startTime);
                params.add("stopTime", stopTime);
                params.add("storeFilter", false);
                if (searchString != null) {
                    params.add("searchString", searchString);
                }
                setResponsePage(new TimesheetListPage(params));
            }
        };
        result.add(link);
        WicketUtils.addRowClick(row);
        if (cost2 != null) {
            final ProjektDO project = cost2.getProjekt();
            final KundeDO customer = project != null ? project.getKunde() : null;
            final Kost2ArtDO costType = cost2.getKost2Art();
            link.add(new Label("label", KostFormatter.format(cost2)));
            if (project != null) {
                row.add(new Label("customer", customer != null ? customer.getName() : ""));
                row.add(new Label("project", project.getName()));
            } else {
                row.add(new Label("customer", cost2.getDescription())
                        .add(AttributeModifier.replace("colspan", "2")));
                row.add(new Label("project", "").setVisible(false));
            }
            addCostType(row, costType.getName());
        } else {
            if (task != null) {
                // Entries for one task (not cost2).
                link.add(new Label("label", taskFormatter.getTaskPath(task.getId(), true, OutputType.PLAIN)));
            } else {
                link.add(new Label("label", getString("sum")));
            }
            result.add(AttributeModifier.replace("colspan", "4"));
            row.add(new Label("customer", "").setVisible(false));
            row.add(new Label("project", "").setVisible(false));
            addCostType(row, null);
        }
        return result;
    }

    private Label addCostType(final WebMarkupContainer row, final String content) {
        final WebMarkupContainer costTypeContainer = new WebMarkupContainer("costType");
        row.add(costTypeContainer);
        if (content == null) {
            costTypeContainer.setVisible(false);
            return null;
        } else {
            final Label label = new Label("content", content);
            costTypeContainer.add(label);
            return label;
        }
    }

    protected void exportAsPdf() {
        log.info("Monthly employee report for " + form.filter.getUser().getFullname() + ": "
                + form.filter.getFormattedMonth());
        final StringBuffer buf = new StringBuffer();
        buf.append(getString("menu.monthlyEmployeeReport.fileprefix")).append("_");
        final PFUserDO employee = userDao.getById(form.filter.getUserId());
        buf.append(employee.getLastname()).append("_").append(form.filter.getYear()).append("-")
                .append(form.filter.getFormattedMonth()).append(".pdf");
        final String filename = buf.toString();

        // get the sheets of the given format
        final String styleSheet = "fo-styles/monthlyEmployeeReport-template-fo.xsl";
        final String xmlData = "fo-styles/monthlyEmployeeReport2pdf.xml";

        report = monthlyEmployeeReportDao.getReport(form.filter.getYear(), form.filter.getMonth(), employee);
        final Map<String, Object> data = new HashMap<String, Object>();
        data.put("systemDate", dateTimeFormatter.getFormattedDateTime(new Date()));
        data.put("title", getString("menu.monthlyEmployeeReport"));
        data.put("employeeLabel", getString("timesheet.user"));
        data.put("employee", employee.getFullname());
        data.put("monthLabel", getString("calendar.month"));
        data.put("year", form.filter.getYear());
        data.put("month", form.filter.getFormattedMonth());
        data.put("workingDaysLabel", getString("fibu.common.workingDays"));
        data.put("workingDays", report.getNumberOfWorkingDays());
        data.put("kost1Label", getString("fibu.kost1"));
        final Kost1DO kost1 = kost1Dao.internalGetById(report.getKost1Id());
        data.put("kost1", kost1 != null ? kost1.getFormattedNumber() : "--");
        data.put("kost2Label", getString("fibu.kost2"));
        data.put("kundeLabel", getString("fibu.kunde"));
        data.put("projektLabel", getString("fibu.projekt"));
        data.put("kost2ArtLabel", getString("fibu.kost2.art"));
        data.put("sumLabel", getString("sum"));
        data.put("netSumLabel", getString("sum"));
        data.put("totalSumLabel", getString("fibu.monthlyEmployeeReport.totalSum"));
        data.put("report", report);
        data.put("signatureEmployeeLabel",
                getString("timesheet.signatureEmployee") + ": " + employee.getFullname());
        data.put("signatureProjectLeaderLabel", getString("timesheet.signatureProjectLeader"));
        data.put("unbookedWorkingDaysLabel", getString("fibu.monthlyEmployeeReport.withoutTimesheets"));
        // render the PDF with fop
        final byte[] ba = pdfRenderer.render(styleSheet, xmlData, data);
        DownloadUtils.setDownloadTarget(ba, filename);
    }

    @Override
    protected String getTitle() {
        return getString("menu.monthlyEmployeeReport");
    }

    @Override
    public void cancelSelection(final String property) {
        log.error("cancelSelection not supported. Property was '" + property + "'.");
    }

    @Override
    public void select(final String property, final Object selectedValue) {
        if ("user".equals(property) == true) {
            final Integer id;
            if (selectedValue instanceof String) {
                id = NumberHelper.parseInteger((String) selectedValue);
            } else {
                id = (Integer) selectedValue;
            }
            form.filter.setUser(userGroupCache.getUser(id));
        } else if ("quickSelect".equals(property) == true) {
            final Date date = (Date) selectedValue;
            form.setDate(date);
        } else {
            log.error("Property '" + property + "' not supported for selection.");
        }
    }

    @Override
    public void unselect(final String property) {
        log.error("unselect not supported. Property was '" + property + "'.");
    }
}