org.projectforge.business.fibu.AbstractRechnungsPositionDO.java Source code

Java tutorial

Introduction

Here is the source code for org.projectforge.business.fibu.AbstractRechnungsPositionDO.java

Source

/////////////////////////////////////////////////////////////////////////////
//
// 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.business.fibu;

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

import javax.persistence.Column;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.projectforge.business.fibu.kost.KostZuweisungDO;
import org.projectforge.framework.persistence.api.PFPersistancyBehavior;
import org.projectforge.framework.persistence.api.ShortDisplayNameCapable;
import org.projectforge.framework.persistence.entities.DefaultBaseDO;
import org.projectforge.framework.utils.CurrencyHelper;
import org.projectforge.framework.utils.NumberHelper;

/**
 * Reprsentiert eine Position innerhalb eine Rechnung.
 * 
 * @author Kai Reinhard (k.reinhard@micromata.de)
 */
@MappedSuperclass
public abstract class AbstractRechnungsPositionDO extends DefaultBaseDO implements ShortDisplayNameCapable {
    private static final long serialVersionUID = 4132530394057069876L;

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

    protected short number;

    protected String text;

    protected BigDecimal menge;

    protected BigDecimal einzelNetto;

    protected BigDecimal vat;

    @PFPersistancyBehavior(autoUpdateCollectionEntries = true)
    protected List<KostZuweisungDO> kostZuweisungen = null;

    @Column
    public short getNumber() {
        return number;
    }

    public AbstractRechnungsPositionDO setNumber(final short number) {
        this.number = number;
        return this;
    }

    @Column(scale = 5, precision = 18)
    public BigDecimal getMenge() {
        return menge;
    }

    public AbstractRechnungsPositionDO setMenge(final BigDecimal menge) {
        this.menge = menge;
        return this;
    }

    @Column(name = "einzel_netto", scale = 2, precision = 18)
    public BigDecimal getEinzelNetto() {
        return einzelNetto;
    }

    public AbstractRechnungsPositionDO setEinzelNetto(final BigDecimal einzelNetto) {
        this.einzelNetto = einzelNetto;
        return this;
    }

    @Column(scale = 5, precision = 10)
    public BigDecimal getVat() {
        return vat;
    }

    public AbstractRechnungsPositionDO setVat(final BigDecimal vat) {
        if (vat != null) {
            this.vat = vat.stripTrailingZeros();
        } else {
            this.vat = vat;
        }
        return this;
    }

    @Transient
    public BigDecimal getNetSum() {
        if (this.menge != null) {
            if (this.einzelNetto != null) {
                return CurrencyHelper.multiply(this.menge, this.einzelNetto);
            } else {
                return BigDecimal.ZERO;
            }
        } else {
            return this.einzelNetto != null ? this.einzelNetto : BigDecimal.ZERO;
        }
    }

    @Transient
    public BigDecimal getBruttoSum() {
        final BigDecimal netSum = getNetSum();
        if (vat != null) {
            return netSum.add(CurrencyHelper.multiply(netSum, vat));
        } else {
            return netSum;
        }
    }

    @Transient
    public BigDecimal getVatAmount() {
        final BigDecimal netSum = getNetSum();
        if (vat != null) {
            return CurrencyHelper.multiply(netSum, vat);
        } else {
            return BigDecimal.ZERO;
        }
    }

    @Column(name = "s_text", length = 1000)
    public String getText() {
        return text;
    }

    public AbstractRechnungsPositionDO setText(final String text) {
        this.text = text;
        return this;
    }

    /**
     * Get the position entries for this object.
     */
    @Transient
    public abstract List<KostZuweisungDO> getKostZuweisungen();

    public AbstractRechnungsPositionDO setKostZuweisungen(final List<KostZuweisungDO> kostZuweisungen) {
        this.kostZuweisungen = kostZuweisungen;
        return this;
    }

    /**
     * @param idx Index of the cost assignment not index of collection.
     * @return KostZuweisungDO with given index or null, if not exist.
     */
    public KostZuweisungDO getKostZuweisung(final int index) {
        if (kostZuweisungen == null) {
            log.error("Can't get cost assignment with index " + index + " because no cost assignments given.");
            return null;
        }
        for (final KostZuweisungDO zuweisung : kostZuweisungen) {
            if (index == zuweisung.getIndex()) {
                return zuweisung;
            }
        }
        log.error("Can't found cost assignment with index " + index);
        return null;
    }

    public AbstractRechnungsPositionDO addKostZuweisung(final KostZuweisungDO kostZuweisung) {
        ensureAndGetKostzuweisungen();
        short index = 0;
        for (final KostZuweisungDO zuweisung : kostZuweisungen) {
            if (zuweisung.getIndex() >= index) {
                index = zuweisung.getIndex();
                index++;
            }
        }
        kostZuweisung.setIndex(index);
        setThis(kostZuweisung);
        this.kostZuweisungen.add(kostZuweisung);
        return this;
    }

    /**
     * @return The total net sum of all assigned cost entries multiplied with the vat of this position.
     */
    @Transient
    public BigDecimal getKostZuweisungGrossSum() {
        return CurrencyHelper.getGrossAmount(getKostZuweisungsNetSum(), vat);
    }

    /**
     * kostZuweisung.setEingangsrechnungsPosition(this);
     * 
     * @param kostZuweisung
     */
    protected abstract void setThis(final KostZuweisungDO kostZuweisung);

    protected abstract AbstractRechnungsPositionDO newInstance();

    /**
     * this.getEingangsrechnung()
     */
    @Transient
    protected abstract AbstractRechnungDO<?> getRechnung();

    @Transient
    public Integer getRechnungId() {
        if (getRechnung() == null) {
            return null;
        } else {
            return getRechnung().getId();
        }
    }

    /**
     * setEingangsrechnung(rechnung)
     */
    protected abstract AbstractRechnungsPositionDO setRechnung(final AbstractRechnungDO<?> rechnung);

    /**
     * Does only work for not already persisted entries (meaning entries without an id / pk) and only the last entry of
     * the list. Otherwise this method logs an error message and do nothing else.
     * 
     * @param idx
     * @see #isKostZuweisungDeletable(KostZuweisungDO)
     */
    public AbstractRechnungsPositionDO deleteKostZuweisung(final int idx) {
        final KostZuweisungDO zuweisung = getKostZuweisung(idx);
        if (zuweisung == null) {
            return this;
        }
        if (isKostZuweisungDeletable(zuweisung) == false) {
            log.error(
                    "Deleting of cost assignements which are already persisted (a id / pk already exists) or not are not the last entry is not supported. Do nothing.");
            return this;
        }
        this.kostZuweisungen.remove(zuweisung);
        return this;
    }

    /**
     * Only the last entry of cost assignments is deletable if not already persisted (no id/pk given).
     * 
     * @param zuweisung
     * @return
     */
    public boolean isKostZuweisungDeletable(final KostZuweisungDO zuweisung) {
        if (zuweisung == null) {
            return false;
        }
        if ((this instanceof EingangsrechnungsPositionDO
                && zuweisung.getEingangsrechnungsPositionId() != this.getId())
                || this instanceof RechnungsPositionDO && zuweisung.getRechnungsPositionId() != this.getId()) {
            log.error("Oups, given cost assignment is not assigned to this invoice position.");
            return false;
        }
        if (zuweisung.getId() != null) {
            return false;
        }
        // if (zuweisung.getIndex() + 1 < this.kostZuweisungen.size()) {
        // return false;
        // }
        return true;
    }

    public List<KostZuweisungDO> ensureAndGetKostzuweisungen() {
        if (this.kostZuweisungen == null) {
            setKostZuweisungen(new ArrayList<KostZuweisungDO>());
        }
        return getKostZuweisungen();
    }

    /**
     * @return The net value as sum of all cost assignements.
     */
    @Transient
    public BigDecimal getKostZuweisungsNetSum() {
        BigDecimal sum = BigDecimal.ZERO;
        if (CollectionUtils.isNotEmpty(this.kostZuweisungen) == true) {
            for (final KostZuweisungDO zuweisung : this.kostZuweisungen) {
                sum = NumberHelper.add(sum, zuweisung.getNetto());
            }
        }
        return sum;
    }

    @Transient
    public BigDecimal getKostZuweisungNetFehlbetrag() {
        return getKostZuweisungsNetSum().subtract(getNetSum());
    }

    /**
     * Clones this including cost assignments and order position (without id's).
     * 
     * @return
     */
    public AbstractRechnungsPositionDO newClone() {
        final AbstractRechnungsPositionDO rechnungsPosition = newInstance();
        rechnungsPosition.copyValuesFrom(this, "id", "kostZuweisungen");
        if (this.getKostZuweisungen() != null) {
            for (final KostZuweisungDO origKostZuweisung : this.getKostZuweisungen()) {
                final KostZuweisungDO kostZuweisung = origKostZuweisung.newClone();
                rechnungsPosition.addKostZuweisung(kostZuweisung);
            }
        }
        return rechnungsPosition;
    }

    @Transient
    public boolean isEmpty() {
        if (StringUtils.isBlank(text) == false) {
            return false;
        }
        return (NumberHelper.isNotZero(einzelNetto) == false);
    }

    @Override
    public boolean equals(final Object o) {
        if (o instanceof AbstractRechnungsPositionDO) {
            final AbstractRechnungsPositionDO other = (AbstractRechnungsPositionDO) o;
            if (ObjectUtils.equals(this.getNumber(), other.getNumber()) == false) {
                return false;
            }
            if (ObjectUtils.equals(this.getRechnungId(), other.getRechnungId()) == false) {
                return false;
            }
            return true;
        }
        return false;
    }

    @Override
    public int hashCode() {
        final HashCodeBuilder hcb = new HashCodeBuilder();
        hcb.append(getNumber());
        if (getRechnung() != null) {
            hcb.append(getRechnung().getId());
        }
        return hcb.toHashCode();
    }

    @Override
    @Transient
    public String getShortDisplayName() {
        return String.valueOf(number);
    }
}