Package org.projectforge.fibu

Source Code of org.projectforge.fibu.RechnungDao

/////////////////////////////////////////////////////////////////////////////
//
// 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;

import java.io.Serializable;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.Validate;
import org.hibernate.FetchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.projectforge.access.AccessException;
import org.projectforge.access.OperationType;
import org.projectforge.common.DateHelper;
import org.projectforge.core.BaseDao;
import org.projectforge.core.BaseSearchFilter;
import org.projectforge.core.DisplayHistoryEntry;
import org.projectforge.core.MessageParam;
import org.projectforge.core.MessageParamType;
import org.projectforge.core.QueryFilter;
import org.projectforge.core.UserException;
import org.projectforge.database.SQLHelper;
import org.projectforge.fibu.kost.KostZuweisungDO;
import org.projectforge.user.UserRightId;
import org.projectforge.xml.stream.XmlObjectReader;
import org.projectforge.xml.stream.XmlObjectWriter;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public class RechnungDao extends BaseDao<RechnungDO>
{
  public static final UserRightId USER_RIGHT_ID = UserRightId.FIBU_AUSGANGSRECHNUNGEN;

  public final static int START_NUMBER = 1000;

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

  private static final Class< ? >[] ADDITIONAL_SEARCH_DOS = new Class[] { RechnungsPositionDO.class};

  private static final String[] ADDITIONAL_SEARCH_FIELDS = new String[] { "kunde.name", "projekt.name", "projekt.kunde.name",
    "positionen.text", "positionen.auftragsPosition.position", "positionen.auftragsPosition.position",
    "positionen.auftragsPosition.titel", "positionen.auftragsPosition.bemerkung"};

  private static BigDecimal defaultSteuersatz;

  private KundeDao kundeDao;

  private ProjektDao projektDao;

  private RechnungCache rechnungCache;

  public static BigDecimal getNettoSumme(final Collection<RechnungsPositionVO> col)
  {
    BigDecimal nettoSumme = BigDecimal.ZERO;
    if (col != null && col.size() > 0) {
      for (final RechnungsPositionVO pos : col) {
        nettoSumme = nettoSumme.add(pos.getNettoSumme());
      }
    }
    return nettoSumme;
  }

  static void readUiStatusFromXml(final AbstractRechnungDO< ? > rechnung)
  {
    final XmlObjectReader reader = new XmlObjectReader();
    reader.initialize(RechnungUIStatus.class);
    final String styleAsXml = rechnung.getUiStatusAsXml();
    final RechnungUIStatus status;
    if (StringUtils.isEmpty(styleAsXml) == true) {
      status = new RechnungUIStatus();
    } else {
      status = (RechnungUIStatus) reader.read(styleAsXml);
    }
    rechnung.setUiStatus(status);
  }

  static void writeUiStatusToXml(final AbstractRechnungDO< ? > rechnung)
  {
    final String uiStatusAsXml = XmlObjectWriter.writeAsXml(rechnung.getUiStatus());
    rechnung.setUiStatusAsXml(uiStatusAsXml);
  }

  public void setKundeDao(final KundeDao kundeDao)
  {
    this.kundeDao = kundeDao;
  }

  public void setProjektDao(final ProjektDao projektDao)
  {
    this.projektDao = projektDao;
  }

  public void setRechnungCache(final RechnungCache rechnungCache)
  {
    this.rechnungCache = rechnungCache;
  }

  /**
   * @return the rechnungCache
   */
  public RechnungCache getRechnungCache()
  {
    return rechnungCache;
  }

  public RechnungDao()
  {
    super(RechnungDO.class);
    userRightId = USER_RIGHT_ID;
  }

  /**
   * List of all years with invoices: select min(datum), max(datum) from t_fibu_rechnung.
   * @return
   */
  @SuppressWarnings("unchecked")
  public int[] getYears()
  {
    final List<Object[]> list = getSession().createQuery("select min(datum), max(datum) from RechnungDO t").list();
    return SQLHelper.getYears(list);
  }

  public RechnungsStatistik buildStatistik(final List<RechnungDO> list)
  {
    final RechnungsStatistik stats = new RechnungsStatistik();
    if (list == null) {
      return stats;
    }
    for (final RechnungDO rechnung : list) {
      stats.add(rechnung);
    }
    return stats;
  }

  /**
   * @param rechnung
   * @param days
   * @see DateHelper#getCalendar()
   */
  public Date calculateFaelligkeit(final RechnungDO rechnung, final int days)
  {
    if (rechnung.getDatum() == null) {
      return null;
    }
    final Calendar cal = DateHelper.getCalendar();
    cal.setTime(rechnung.getDatum());
    cal.add(Calendar.DAY_OF_YEAR, days);
    return cal.getTime();
  }

  /**
   * @param rechnung
   * @param kundeId If null, then kunde will be set to null;
   * @see BaseDao#getOrLoad(Integer)
   */
  public void setKunde(final RechnungDO rechnung, final Integer kundeId)
  {
    final KundeDO kunde = kundeDao.getOrLoad(kundeId);
    rechnung.setKunde(kunde);
  }

  /**
   * @param rechnung
   * @param projektId If null, then projekt will be set to null;
   * @see BaseDao#getOrLoad(Integer)
   */
  public void setProjekt(final RechnungDO rechnung, final Integer projektId)
  {
    final ProjektDO projekt = projektDao.getOrLoad(projektId);
    rechnung.setProjekt(projekt);
  }

  /**
   * Sets the scales of percentage and currency amounts. <br/>
   * Gutschriftsanzeigen dürfen keine Rechnungsnummer haben. Wenn eine Rechnungsnummer für neue Rechnungen gegeben wurde, so muss sie
   * fortlaufend sein. Berechnet das Zahlungsziel in Tagen, wenn nicht gesetzt, damit es indiziert wird.
   * @see org.projectforge.core.BaseDao#onSaveOrModify(org.projectforge.core.ExtendedBaseDO)
   */
  @SuppressWarnings("unchecked")
  @Override
  protected void onSaveOrModify(final RechnungDO obj)
  {
    if (obj.getTyp() == RechnungTyp.GUTSCHRIFTSANZEIGE_DURCH_KUNDEN) {
      if (obj.getNummer() != null) {
        throw new UserException("fibu.rechnung.error.gutschriftsanzeigeDarfKeineRechnungsnummerHaben");
      }
    } else {
      if (obj.getNummer() == null) {
        throw new UserException("validation.required.valueNotPresent", new MessageParam("fibu.rechnung.nummer", MessageParamType.I18N_KEY));
      }
      if (obj.getId() == null) {
        // Neue Rechnung
        final Integer next = getNextNumber(obj);
        if (next.intValue() != obj.getNummer().intValue()) {
          throw new UserException("fibu.rechnung.error.rechnungsNummerIstNichtFortlaufend");
        }
      } else {
        final List<RechnungDO> list = getHibernateTemplate().find("from RechnungDO r where r.nummer = ? and r.id <> ?",
            new Object[] { obj.getNummer(), obj.getId()});
        if (list != null && list.size() > 0) {
          throw new UserException("fibu.rechnung.error.rechnungsNummerBereitsVergeben");
        }
      }
    }
    if (obj.getZahlBetrag() != null) {
      obj.setZahlBetrag(obj.getZahlBetrag().setScale(2, RoundingMode.HALF_UP));
    }
    obj.recalculate();
    if (CollectionUtils.isEmpty(obj.getPositionen()) == true) {
      throw new UserException("fibu.rechnung.error.rechnungHatKeinePositionen");
    }
    final int size = obj.getPositionen().size();
    for (int i = size - 1; i > 0; i--) {
      // Don't remove first position, remove only the last empty positions.
      final RechnungsPositionDO position = obj.getPositionen().get(i);
      if (position.getId() == null && position.isEmpty() == true) {
        obj.getPositionen().remove(i);
      } else {
        break;
      }
    }
    writeUiStatusToXml(obj);
  }

  @Override
  protected void afterLoad(final RechnungDO obj)
  {
    readUiStatusFromXml(obj);
  }

  @Override
  protected void afterSaveOrModify(final RechnungDO obj)
  {
    rechnungCache.setExpired(); // Expire the cache because assignments to order position may be changed.
  }

  /**
   * @see org.projectforge.core.BaseDao#prepareHibernateSearch(org.projectforge.core.ExtendedBaseDO, org.projectforge.access.OperationType)
   */
  @Override
  protected void prepareHibernateSearch(final RechnungDO obj, final OperationType operationType)
  {
    projektDao.initializeProjektManagerGroup(obj.getProjekt());
  }

  @Override
  protected String[] getAdditionalSearchFields()
  {
    return ADDITIONAL_SEARCH_FIELDS;
  }

  /**
   * Fetches the cost assignments.
   * @see org.projectforge.core.BaseDao#getById(java.io.Serializable)
   */
  @Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW)
  @Override
  public RechnungDO getById(final Serializable id) throws AccessException
  {
    final RechnungDO rechnung = super.getById(id);
    for (final RechnungsPositionDO pos : rechnung.getPositionen()) {
      final List<KostZuweisungDO> list = pos.getKostZuweisungen();
      if (list != null && list.size() > 0) {
        // Kostzuweisung is initialized
      }
    }
    return rechnung;
  };

  @Override
  public List<RechnungDO> getList(final BaseSearchFilter filter)
  {
    final RechnungFilter myFilter;
    if (filter instanceof RechnungFilter) {
      myFilter = (RechnungFilter) filter;
    } else {
      myFilter = new RechnungFilter(filter);
    }
    final QueryFilter queryFilter = new QueryFilter(myFilter);
    if (myFilter.getFromDate() != null || myFilter.getToDate() != null) {
      if (myFilter.getFromDate() != null && myFilter.getToDate() != null) {
        queryFilter.add(Restrictions.between("datum", myFilter.getFromDate(), myFilter.getToDate()));
      } else if (myFilter.getFromDate() != null) {
        queryFilter.add(Restrictions.ge("datum", myFilter.getFromDate()));
      } else if (myFilter.getToDate() != null) {
        queryFilter.add(Restrictions.le("datum", myFilter.getToDate()));
      }
    } else {
      queryFilter.setYearAndMonth("datum", myFilter.getYear(), myFilter.getMonth());
    }
    queryFilter.addOrder(Order.desc("datum"));
    queryFilter.addOrder(Order.desc("nummer"));
    if (myFilter.isShowKostZuweisungStatus() == true) {
      queryFilter.setFetchMode("positionen.kostZuweisungen", FetchMode.JOIN);
    }
    final List<RechnungDO> list = getList(queryFilter);
    if (myFilter.isShowAll() == true || myFilter.isDeleted() == true) {
      return list;
    }
    final List<RechnungDO> result = new ArrayList<RechnungDO>();
    for (final RechnungDO rechnung : list) {
      if (myFilter.isShowUnbezahlt() == true) {
        if (rechnung.isBezahlt() == false) {
          result.add(rechnung);
        }
      } else if (myFilter.isShowBezahlt() == true) {
        if (rechnung.isBezahlt() == true) {
          result.add(rechnung);
        }
      } else if (myFilter.isShowUeberFaellig() == true) {
        if (rechnung.isUeberfaellig() == true) {
          result.add(rechnung);
        }
      } else {
        log.error("Unknown filter setting: " + myFilter.listType);
        break;
      }
    }
    return result;
  }

  @Override
  protected List<RechnungDO> sort(final List<RechnungDO> list)
  {
    Collections.sort(list);
    return list;
  }

  /**
   * Gets the highest Rechnungsnummer.
   * @param rechnung wird benötigt, damit geschaut werden kann, ob diese Rechnung ggf. schon existiert. Wenn sie schon eine Nummer hatte, so
   *          kann verhindert werden, dass sie eine nächst höhere Nummer bekommt. Eine solche Rechnung bekommt die alte Nummer wieder
   *          zugeordnet.
   */
  @SuppressWarnings("unchecked")
  @Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
  public Integer getNextNumber(final RechnungDO rechnung)
  {
    if (rechnung.getId() != null) {
      final RechnungDO orig = internalGetById(rechnung.getId());
      if (orig.getNummer() != null) {
        rechnung.setNummer(orig.getNummer());
        return orig.getNummer();
      }
    }
    final List<Integer> list = getSession().createQuery("select max(t.nummer) from RechnungDO t").list();
    Validate.notNull(list);
    if (list.size() == 0 || list.get(0) == null) {
      log.info("First entry of RechnungDO");
      return START_NUMBER;
    }
    Integer number = list.get(0);
    return ++number;
  }

  /**
   * Gets history entries of super and adds all history entries of the RechnungsPositionDO childs.
   * @see org.projectforge.core.BaseDao#getDisplayHistoryEntries(org.projectforge.core.ExtendedBaseDO)
   */
  @Override
  public List<DisplayHistoryEntry> getDisplayHistoryEntries(final RechnungDO obj)
  {
    final List<DisplayHistoryEntry> list = super.getDisplayHistoryEntries(obj);
    if (hasLoggedInUserHistoryAccess(obj, false) == false) {
      return list;
    }
    if (CollectionUtils.isNotEmpty(obj.getPositionen()) == true) {
      for (final RechnungsPositionDO position : obj.getPositionen()) {
        final List<DisplayHistoryEntry> entries = internalGetDisplayHistoryEntries(position);
        for (final DisplayHistoryEntry entry : entries) {
          final String propertyName = entry.getPropertyName();
          if (propertyName != null) {
            entry.setPropertyName("#" + position.getNumber() + ":" + entry.getPropertyName()); // Prepend number of positon.
          } else {
            entry.setPropertyName("#" + position.getNumber());
          }
        }
        list.addAll(entries);
        if (CollectionUtils.isNotEmpty(position.getKostZuweisungen()) == true) {
          for (final KostZuweisungDO zuweisung : position.getKostZuweisungen()) {
            final List<DisplayHistoryEntry> kostEntries = internalGetDisplayHistoryEntries(zuweisung);
            for (final DisplayHistoryEntry entry : kostEntries) {
              final String propertyName = entry.getPropertyName();
              if (propertyName != null) {
                entry.setPropertyName("#" + position.getNumber() + ".kost#" + zuweisung.getIndex() + ":" + entry.getPropertyName()); // Prepend
                // number of positon and index of zuweisung.
              } else {
                entry.setPropertyName("#" + position.getNumber() + ".kost#" + zuweisung.getIndex());
              }
            }
            list.addAll(kostEntries);
          }
        }
      }
    }
    Collections.sort(list, new Comparator<DisplayHistoryEntry>() {
      public int compare(final DisplayHistoryEntry o1, final DisplayHistoryEntry o2)
      {
        return (o2.getTimestamp().compareTo(o1.getTimestamp()));
      }
    });
    return list;
  }

  @Override
  protected Class< ? >[] getAdditionalHistorySearchDOs()
  {
    return ADDITIONAL_SEARCH_DOS;
  }

  /**
   * Returns also true, if idSet contains the id of any order position.
   * @see org.projectforge.core.BaseDao#contains(java.util.Set, org.projectforge.core.ExtendedBaseDO)
   */
  @Override
  protected boolean contains(final Set<Integer> idSet, final RechnungDO entry)
  {
    if (super.contains(idSet, entry) == true) {
      return true;
    }
    for (final RechnungsPositionDO pos : entry.getPositionen()) {
      if (idSet.contains(pos.getId()) == true) {
        return true;
      }
    }
    return false;
  }

  /**
   * Defined in application context.
   */
  public static BigDecimal getDefaultSteuersatz()
  {
    return defaultSteuersatz;
  }

  /**
   * Not static for invocation of Spring.
   * @param value
   */
  public void setDefaultSteuersatz(final BigDecimal value)
  {
    defaultSteuersatz = value;
  }

  @Override
  public RechnungDO newInstance()
  {
    return new RechnungDO();
  }

  /**
   * @see org.projectforge.core.BaseDao#useOwnCriteriaCacheRegion()
   */
  @Override
  protected boolean useOwnCriteriaCacheRegion()
  {
    return true;
  }
}
TOP

Related Classes of org.projectforge.fibu.RechnungDao

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.