eu.ggnet.dwoss.report.entity.Report.java Source code

Java tutorial

Introduction

Here is the source code for eu.ggnet.dwoss.report.entity.Report.java

Source

/* 
 * Copyright (C) 2014 GG-Net GmbH - Oliver Gnther
 *
 * This program 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, 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 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 eu.ggnet.dwoss.report.entity;

import java.io.Serializable;
import java.util.*;

import javax.persistence.*;
import javax.validation.constraints.NotNull;

import org.apache.commons.lang3.time.DateUtils;
import org.metawidget.inspector.annotation.UiLarge;

import eu.ggnet.dwoss.rules.DocumentType;
import eu.ggnet.dwoss.rules.TradeName;
import eu.ggnet.dwoss.util.DateFormats;
import eu.ggnet.dwoss.util.persistence.EagerAble;
import eu.ggnet.dwoss.util.persistence.entity.IdentifiableEntity;

import lombok.*;

import static eu.ggnet.dwoss.report.entity.Report.ViewMode.DEFAULT;

//TODO: Name: Zusammenfassung, Comulation. Gruppierung.
/**
 *
 * @author bastian.venz
 * @has 1 - n ReportLine
 */
@Entity
@NoArgsConstructor
public class Report extends IdentifiableEntity implements Serializable, EagerAble {

    /**
     * The ViewModw of a Report.
     * A Viewmode allowed different looks and filterings for the ui.
     * <p>
     */
    public enum ViewMode {

        /**
         * Default.
         */
        DEFAULT,
        /**
         * Splitt the Invoiced Lines by the mfgDate of each unit and creates an extra view for warranties.
         */
        YEARSPLITT_AND_WARRANTIES
    }

    @Value
    public static class YearSplit implements Serializable {

        private final Date splitter;

        /**
         * Contains lines from splitter till today.
         */
        private final NavigableSet<ReportLine> before;

        /**
         * Contains lines from 1970 till splitter.
         */
        private final NavigableSet<ReportLine> after;

    }

    @Id
    @GeneratedValue
    @Getter
    private long id;

    @Version
    private int optLock;

    @NotNull
    @Getter
    @Setter
    private String name;

    /**
     * This is the type of report.
     * This value should never be changed afterwards.
     */
    @Getter
    @NotNull
    private TradeName type;

    /**
     * This String is a representation the contractor for who the report was generated.
     * If this is null its represent the AllReport.
     */
    @Getter
    private String typeName;

    /**
     * This date represent a point where the span of the report start.
     */
    @NotNull
    @Temporal(javax.persistence.TemporalType.DATE)
    @Getter
    @Setter
    private Date startingDate;

    /**
     * This date represent a point where the span of the report ends.
     */
    @NotNull
    @Temporal(javax.persistence.TemporalType.DATE)
    @Getter
    @Setter
    private Date endingDate;

    @Lob
    @Getter
    @Setter
    @UiLarge
    @Column(length = 65536)
    private String comment;

    @Getter
    @NotNull
    private ViewMode viewMode = DEFAULT;

    /**
     * This set contains the ReportsLines of the Reports, where is the mapping unidirectional.
     */
    @ManyToMany
    private Set<ReportLine> lines = new HashSet<>();

    public Report(String name, TradeName type, Date startingDate, Date endingDate, ViewMode viewMode) {
        this(name, type, startingDate, endingDate);
        this.viewMode = viewMode;
    }

    public Report(String name, TradeName type, Date startingDate, Date endingDate) {
        this.name = name;
        this.type = Objects.requireNonNull(type, "The type must not be null");
        this.typeName = type.name();
        this.startingDate = startingDate;
        this.endingDate = endingDate;
    }

    /**
     * Add a ReportLine to the Set of ReportLines.
     * <p/>
     * @param reportLine the ReportLine that will be added.
     */
    public void add(ReportLine reportLine) {
        if (reportLine == null)
            return;
        lines.add(reportLine);
        reportLine.reports.add(this);
    }

    /**
     * Remove a ReportLine from the Set of ReportLines
     * <p/>
     * @param reportLine the ReportLine that will be removed.
     */
    public void remove(ReportLine reportLine) {
        if (reportLine == null)
            return;
        lines.remove(reportLine);
        reportLine.reports.remove(this);
    }

    public void addAll(Collection<? extends ReportLine> reportLines) {
        for (ReportLine reportLine : reportLines) {
            add(reportLine);
        }
    }

    public NavigableSet<ReportLine> getLines() {
        return new TreeSet<>(lines);
    }

    /**
     * Returns all Lines of the Report for Category Invoiced, split by mfgDate - startOfReport &lt; 1 year and the rest.
     * This consists of:
     * <ul>
     * <li>Position of Type Invoice, with no References</li>
     * <li>Position of Type UNIT_ANNEX in DocumentType CREDIT_MEMO/ANNULATIION_INVOICE and a Referencing Invoice in the same report.</li>
     * </ul>
     * <p>
     * @return all Lines of the Report for Category Invoiced.
     */
    public YearSplit filterInvoicedSplit() {
        NavigableSet<ReportLine> pastSplit = filterInvoiced();
        NavigableSet<ReportLine> preSplit = new TreeSet<>();
        Date splitter = DateUtils.addYears(startingDate, -1);
        for (ReportLine line : pastSplit) {
            if (splitter.before(line.getMfgDate()))
                preSplit.add(line);
        }
        pastSplit.removeAll(preSplit);
        return new YearSplit(startingDate, preSplit, pastSplit);
    }

    /**
     * Returns all Lines of the Report for Category Invoiced.
     * This consists of:
     * <ul>
     * <li>Position of Type Capital Asset</li>
     * <li>Position of Type Invoice, with no References</li>
     * <li>Position of Type UNIT_ANNEX in DocumentType CREDIT_MEMO/ANNULATIION_INVOICE and a Referencing Invoice in the same report.</li>
     * </ul>
     * <p>
     * @return all Lines of the Report for Category Invoiced.
     */
    //TODO: We could also substract the value of a unitannex from the invoice and not return the unit annex at all.
    //But consider the impact in the ui, especially if we allow selection of such a "combined" line.
    public NavigableSet<ReportLine> filterInvoiced() {
        NavigableSet<ReportLine> result = new TreeSet<>();
        for (ReportLine line : lines) {
            if (line.getDocumentType() == DocumentType.CAPITAL_ASSET)
                result.add(line); // There is no way a capital Asset can be returned.
            // Only if we are fully repayed in this report, we are not in the invoiced result.
            if (line.getDocumentType() == DocumentType.INVOICE && !line.isFullRepayedIn(lines))
                result.add(line);
            if (line.isPartialRepayment() && !line.isFullRepayedIn(lines)
                    && lines.contains(line.getSingleReference(DocumentType.INVOICE)))
                result.add(line);
        }
        return result;
    }

    /**
     * Returns all Lines of the Report which represent Positions of CreditMemos and Annulation Invoices but the associated Invoices have been reported before.
     * This consists of:
     * <ul>
     * <li>Position of Type UNIT in DocumentType CREDIT_MEMO/ANNULATIION_INVOICE and a Referencing Invoice is not in same report.</li>
     * <li>Position of Type UNIT_ANNEX in DocumentType CREDIT_MEMO/ANNULATIION_INVOICE and a Referencing Invoice is not in same report and no UNIT also in this
     * report</li>
     * </ul>
     * <p>
     * @return all Lines of the Report which represent Positions of CreditMemos and Annulation Invoices but the associated Invoices have been reported before.
     */
    public NavigableSet<ReportLine> filterRepayed() {
        NavigableSet<ReportLine> result = new TreeSet<>();
        for (ReportLine line : lines) {
            if (line.isFullRepayment() && !lines.contains(line.getSingleReference(DocumentType.INVOICE)))
                result.add(line);
            // Implies ( !lines.contaions(null) ) == true
            if (line.isPartialRepayment() && !line.isFullRepayedIn(lines)
                    && !lines.contains(line.getSingleReference(DocumentType.INVOICE)))
                result.add(line);
        }
        return result;
    }

    /**
     * Returns all Reportlines, that don't have an impact on the result, but have only informational character.
     * <p>
     * @return all Reportlines, that don't have an impact on the result, but have only informational character.
     */
    public NavigableSet<ReportLine> filterInfos() {
        NavigableSet<ReportLine> result = new TreeSet<>(lines);
        result.removeAll(filterInvoiced());
        result.removeAll(filterRepayed());
        return result;
    }

    @Override
    public void fetchEager() {
        ReportLine.EagerHelper eagerHelper = new ReportLine.EagerHelper();
        eagerHelper.fetch(this);
    }

    /**
     * Returns a String representation of the report, seperated by all filteroperations.
     * <p>
     * @param showSplit if true the invoiced part is also splitt by mfgDate and one year before the start
     * @return a String representation of the report, seperated by all filteroperations.
     */
    public String toMultiLine(boolean showSplit) {
        String result = this.name + "\n";
        if (showSplit) {
            YearSplit splitresult = filterInvoicedSplit();

            result += buildFilter("Invoiced Before " + DateFormats.ISO.format(splitresult.splitter),
                    splitresult.before);
            result += buildFilter("Invoiced After " + DateFormats.ISO.format(splitresult.splitter),
                    splitresult.after);
        } else {
            result += buildFilter("Invoiced", filterInvoiced());

        }
        result += buildFilter("Repayed", filterRepayed());
        result += buildFilter("Infos", filterInfos());
        return result;
    }

    private String buildFilter(String head, Collection<ReportLine> lines) {
        StringBuilder sb = new StringBuilder(" " + head);
        if (lines.isEmpty())
            return "";
        sb.append("\n");
        for (ReportLine line : lines) {
            sb.append("   - ").append(line.getRefurbishId()).append("|").append(line.getDocumentTypeName())
                    .append("|").append(line.getPositionTypeName()).append("|").append(line.getPrice()).append("|")
                    .append(line.getMfgDate() == null ? "no mfgDate" : DateFormats.ISO.format(line.getMfgDate()))
                    .append("\n");
        }
        sb.append("-----\n");
        return sb.toString();
    }

    @Override
    public String toString() {
        return "Report{" + "id=" + id + ", name=" + name + ", type=" + type + ", typeName=" + typeName
                + ", startingDate=" + startingDate + ", endingDate=" + endingDate + ", comment=" + comment + '}';
    }

}