/////////////////////////////////////////////////////////////////////////////
//
// Project ProjectForge Community Edition
// www.projectforge.org
//
// Copyright (C) 2001-2014 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.fibu.kost;
import java.io.Serializable;
import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.projectforge.common.NumberHelper;
import org.projectforge.core.CurrencyFormatter;
import org.projectforge.fibu.KontoDO;
import org.projectforge.fibu.KostFormatter;
import org.projectforge.fibu.kost.reporting.Report;
import org.projectforge.user.PFUserContext;
import org.projectforge.web.HtmlHelper;
/**
* Used in config.xml for the definition of the used business assessment schema. The business assessment is displayed in different
* accounting areas, such as for DATEV accounting records.
*
* @author Kai Reinhard (k.reinhard@micromata.de)
*
*/
public class BusinessAssessment implements Serializable
{
private static final long serialVersionUID = 1752437122374944451L;
private BusinessAssessmentConfig config;
private final List<BusinessAssessmentRow> rows = new ArrayList<BusinessAssessmentRow>();
private static final Logger log = Logger.getLogger(BusinessAssessment.class);
private String title;
private String shortname; // Ein Kurzname um z.B. labels oder Dateinamen zu generieren
private int counter = 0;
private int year;
private int month;
private Object reference;
private boolean storeAccountRecordsInRows;
/**
* Fügt alle namentlichen BwaZeilen der Bwa in die übergebene Map. Nützlich für JasperReport, einmal unter der Bezeichnung und einmal
* unter der Zeilennummer als key.
* @param map Key ist die Zeilen
*/
public static void putBusinessAssessmentRows(final Map<String, Object> map, final BusinessAssessment businessAssessment)
{
for (final BusinessAssessmentRow row : businessAssessment.rows) {
final double val = getDouble(row.getAmount());
map.put("r" + row.getNo(), val);
if (StringUtils.isNotBlank(row.getId()) == true) {
map.put(row.getId(), val);
}
}
}
private static double getDouble(final BigDecimal amount)
{
if (amount == null) {
return 0.0;
}
return amount.doubleValue();
}
public BusinessAssessment(final BusinessAssessmentConfig config)
{
this.config = config;
if (config == null || config.getRows() == null) {
return;
}
for (final BusinessAssessmentRowConfig rowConfig : config.getRows()) {
rows.add(new BusinessAssessmentRow(this, rowConfig));
}
}
public BusinessAssessment(final BusinessAssessmentConfig config, final List<BuchungssatzDO> records)
{
this(config);
setAccountRecords(records);
}
public BusinessAssessment(final BusinessAssessmentConfig config, final int year, final int month)
{
this(config);
this.year = year;
this.month = month;
}
public void setAccountRecords(final List<BuchungssatzDO> records)
{
if (CollectionUtils.isEmpty(rows) == true) {
return;
}
if (CollectionUtils.isNotEmpty(records) == true) {
for (final BuchungssatzDO record : records) {
counter++;
// Diese Berechnungen werden anhand des Wertenachweises einer Bwa geführt:
if (record.isIgnore() == true) {
continue;
}
final KontoDO account = record.getKonto();
if (account == null || account.getNummer() == null) {
continue;
}
final int accountNumber = account.getNummer();
boolean found = false;
for (final BusinessAssessmentRow row : rows) {
if (row.doesMatch(accountNumber) == true) {
row.addAccountRecord(record);
found = true;
break;
}
}
if (found == false) {
log.warn("Ignoring Satz: " + record);
record.setIgnore(true);
}
}
recalculate();
}
}
public void recalculate()
{
if (rows == null) {
return;
}
for (final BusinessAssessmentRow row : rows) {
if (row == null) {
continue;
}
row.recalculate();
}
}
/**
* @return the rows
*/
public List<BusinessAssessmentRow> getRows()
{
return rows;
}
public BusinessAssessmentRow getOverallPerformanceRow()
{
if (config == null) {
return null;
}
return getRow(config.getOverallPerformance());
}
public BigDecimal getOverallPerformanceRowAmount()
{
final BusinessAssessmentRow row = getOverallPerformanceRow();
return row != null ? row.getAmount() : null;
}
public BusinessAssessmentRow getMerchandisePurchaseRow()
{
if (config == null) {
return null;
}
return getRow(config.getMerchandisePurchase());
}
public BigDecimal getMerchandisePurchaseRowAmount()
{
final BusinessAssessmentRow row = getMerchandisePurchaseRow();
return row != null ? row.getAmount() : null;
}
public BusinessAssessmentRow getPreliminaryResultRow()
{
if (config == null) {
return null;
}
return getRow(config.getPreliminaryResult());
}
public BigDecimal getPreliminaryResultRowAmount()
{
final BusinessAssessmentRow row = getPreliminaryResultRow();
return row != null ? row.getAmount() : null;
}
public String asHtml()
{
final StringBuffer buf = new StringBuffer();
buf.append(getHeader(true));
buf.append("<table class=\"business-assessment\">\n");
if (rows != null) {
for (final BusinessAssessmentRow row : rows) {
asLine(buf, row, true);
}
}
buf.append("</table>\n");
return buf.toString();
}
public String getHeader()
{
return getHeader(false);
}
public String getHeader(final boolean html)
{
final StringBuffer buf = new StringBuffer();
if (html == true) {
buf.append("<h3>");
}
if (config != null) {
buf.append(config.getHeading());
} else {
buf.append("business assessment (not defined in config.xml, see AdministrationGuide).");
}
if (year > 0) {
buf.append(": ").append(KostFormatter.formatBuchungsmonat(year, month));
}
if (title != null) {
buf.append(" \"").append(title).append("\"");
}
if (html == true) {
buf.append("</h3>\n");
} else {
buf.append(":\n");
}
return buf.toString();
}
@Override
public String toString()
{
final StringBuffer buf = new StringBuffer();
buf.append(getHeader());
if (rows != null) {
for (final BusinessAssessmentRow row : rows) {
asLine(buf, row, false);
}
}
return buf.toString();
}
private void asLine(final StringBuffer buf, final String no, final String title, final BigDecimal amount, final int indent,
final int scale, final String unit, final boolean html)
{
if (html == true) {
buf.append(" <tr><td>").append(no).append("</td><td class=\"indent-").append(indent).append("\">");
} else {
buf.append(StringUtils.leftPad(no, 4));
}
int length = 25;
for (int i = 0; i < indent; i++) {
if (html == false) {
buf.append(" ");
}
length--; // One space lost.
}
if (html == true) {
buf.append(HtmlHelper.escapeHtml(StringUtils.defaultString(title), false)).append("</td>");
} else {
buf.append(" ").append(StringUtils.rightPad(StringUtils.defaultString(title), length)).append(" ");
}
if (html == true) {
buf.append("<td style=\"text-align: right;\">");
}
if (amount != null && amount.compareTo(BigDecimal.ZERO) != 0) {
String value;
if ("€".equals(unit) == true) {
value = CurrencyFormatter.format(amount);
} else {
final NumberFormat format = NumberHelper.getNumberFractionFormat(PFUserContext.getLocale(), scale);
value = format.format(amount) + " " + unit;
}
buf.append(StringUtils.leftPad(value, 18));
}
if (html == true) {
buf.append("</td></tr>\n");
} else {
buf.append("\n");
}
}
private void asLine(final StringBuffer buf, final BusinessAssessmentRow row, final boolean html)
{
asLine(buf, row.getNo(), row.getTitle(), row.getAmount(), row.getIndent(), row.getScale(), row.getUnit(), html);
}
/**
* @param id id or number of the row.
* @return The found row or null if not found.
*/
public BusinessAssessmentRow getRow(final String id)
{
if (rows == null || id == null) {
return null;
}
for (final BusinessAssessmentRow row : rows) {
if (id.equals(row.getId()) == true || id.equals(row.getNo()) == true) {
return row;
}
}
return null;
}
public String getShortname()
{
return shortname;
}
public void setShortname(final String shortname)
{
this.shortname = shortname;
}
public int getCounter()
{
return counter;
}
/**
* Dieses Objekt kann von der benutzenden Klasse als freies Feld genutzt werden. Z. B. wird dieses Feld benutzt, um den Report zu
* erhalten, der diese BWA enthält
* @see Report#getChildBwaArray(boolean)
*/
public Object getReference()
{
return reference;
}
public void setReference(final Object reference)
{
this.reference = reference;
}
/**
* @return true if the account records are stored in the rows.
*/
public boolean isStoreAccountRecordsInRows()
{
return storeAccountRecordsInRows;
}
/**
* @param storeAccountRecordsInRows the storeAccountRecordsInRows to set
* @return this for chaining.
*/
public BusinessAssessment setStoreAccountRecordsInRows(final boolean storeAccountRecordsInRows)
{
this.storeAccountRecordsInRows = storeAccountRecordsInRows;
for (final BusinessAssessmentRow row : this.rows) {
row.setStoreAccountRecords(this.storeAccountRecordsInRows);
}
return this;
}
}