Package org.projectforge.fibu.datev

Source Code of org.projectforge.fibu.datev.BuchungssatzExcelImporter

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

import java.io.InputStream;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.projectforge.common.DateHolder;
import org.projectforge.common.DatePrecision;
import org.projectforge.common.ImportStorage;
import org.projectforge.common.ImportedElement;
import org.projectforge.common.ImportedSheet;
import org.projectforge.core.ActionLog;
import org.projectforge.core.UserException;
import org.projectforge.excel.ExcelImport;
import org.projectforge.fibu.KontoDO;
import org.projectforge.fibu.KontoDao;
import org.projectforge.fibu.KostFormatter;
import org.projectforge.fibu.kost.BuchungssatzDO;
import org.projectforge.fibu.kost.Kost1DO;
import org.projectforge.fibu.kost.Kost1Dao;
import org.projectforge.fibu.kost.Kost2DO;
import org.projectforge.fibu.kost.Kost2Dao;
import org.projectforge.user.PFUserContext;

public class BuchungssatzExcelImporter
{
  private static final Logger log = Logger.getLogger(BuchungssatzExcelImporter.class);

  /** In dieser Zeile stehen die Überschriften der Spalten für die Buchungssätze. */
  public static final int ROW_COLUMNNAMES = 0;

  /**
   * Die Spalte SH ist zweimal vertreten und muss einmal umbenannt werden. Das Vorkommen der zweiten Spalte SH wird bis zu maximal
   * MAX_COLUMNS gesucht.
   */
  public static final short MAX_COLUMNS = 20;

  private final KontoDao kontoDao;

  private final Kost1Dao kost1Dao;

  private final Kost2Dao kost2Dao;

  private final ImportStorage<BuchungssatzDO> storage;

  private final ActionLog actionLog;

  public BuchungssatzExcelImporter(final ImportStorage<BuchungssatzDO> storage, final KontoDao kontoDao, final Kost1Dao kost1Dao,
      final Kost2Dao kost2Dao, final ActionLog actionLog)
  {
    this.storage = storage;
    this.kontoDao = kontoDao;
    this.kost1Dao = kost1Dao;
    this.kost2Dao = kost2Dao;
    this.actionLog = actionLog;
  }

  public void doImport(final InputStream is) throws Exception
  {
    final ExcelImport<BuchungssatzImportRow> imp = new ExcelImport<BuchungssatzImportRow>(is);
    for (short idx = 0; idx < imp.getWorkbook().getNumberOfSheets(); idx++) {
      final ImportedSheet<BuchungssatzDO> sheet = importBuchungssaetze(imp, idx);
      if (sheet != null) {
        storage.addSheet(sheet);
      }
    }
  }

  private ImportedSheet<BuchungssatzDO> importBuchungssaetze(final ExcelImport<BuchungssatzImportRow> imp, final int idx) throws Exception
  {
    ImportedSheet<BuchungssatzDO> importedSheet = null;
    imp.setActiveSheet(idx);
    final String name = imp.getWorkbook().getSheetName(idx);
    int m = -1;
    try {
      m = new Integer(name) - 1; // Achtung: month beginnt bei 01 - Januar, während Java mit 0 - Januar rechnet (also - 1).
    } catch (final NumberFormatException ex) {
      // ignore
    }
    if (m >= 0 && m <= 11) {
      actionLog.logInfo("Importing sheet '" + name + "'.");
      final HSSFSheet sheet = imp.getWorkbook().getSheetAt(idx);
      importedSheet = importBuchungssaetze(imp, sheet, m);
    } else {
      log.info("Ignoring sheet '" + name + "' for importing Buchungssätze.");
    }
    return importedSheet;
  }

  private ImportedSheet<BuchungssatzDO> importBuchungssaetze(final ExcelImport<BuchungssatzImportRow> imp, final HSSFSheet sheet,
      final int month) throws Exception
      {
    final ImportedSheet<BuchungssatzDO> importedSheet = new ImportedSheet<BuchungssatzDO>();
    imp.setNameRowIndex(ROW_COLUMNNAMES);
    imp.setStartingRowIndex(ROW_COLUMNNAMES + 1);
    imp.setRowClass(BuchungssatzImportRow.class);

    final Map<String, String> map = new HashMap<String, String>();
    map.put("SatzNr.", "satzNr");
    map.put("Satz-Nr.", "satzNr");
    map.put("Betrag", "betrag");
    map.put("SH", "sh"); // Nicht eindeutig!
    map.put("Konto", "konto");
    map.put("Kostenstelle/-träger", "kost2");
    map.put("Kost2", "kost2");
    map.put("Menge", "menge");
    map.put("SH2", "sh2");
    map.put("Beleg", "beleg");
    map.put("Datum", "datum");
    map.put("Gegenkonto", "gegenkonto");
    map.put("Text", "text");
    map.put("Alt.-Kst.", "kost1");
    map.put("Kost1", "kost1");
    map.put("Beleg 2", "beleg2");
    map.put("KR-BSNr.", "kr_bsnr");
    map.put("ZI", "zi");
    map.put("Kommentar", "comment");
    map.put("Bemerkung", "comment");
    imp.setColumnMapping(map);

    BuchungssatzImportRow[] rows = new BuchungssatzImportRow[0];
    rename2ndSH(sheet);
    rows = imp.convertToRows(BuchungssatzImportRow.class);
    if (rows == null || rows.length == 0) {
      return null;
    }
    int year = 0;
    for (int i = 0; i < rows.length; i++) {
      ImportedElement<BuchungssatzDO> element;
      try {
        element = convertBuchungssatz(rows[i]);
      } catch (final RuntimeException ex) {
        throw new RuntimeException("Im Blatt '" + sheet.getSheetName() + "', in Zeile " + (i + 2) + ": " + ex.getMessage(), ex);
      }
      if (element == null) {
        // Empty row:
        continue;
      }
      final BuchungssatzDO satz = element.getValue();
      final DateHolder date = new DateHolder(satz.getDatum(), DatePrecision.DAY, Locale.GERMAN);
      if (year == 0) {
        year = date.getYear();
      } else if (year != date.getYear()) {
        final String msg = "Not supported: Buchungssätze innerhalb eines Excel-Sheets liegen in verschiedenen Jahren: Im Blatt '" + sheet.getSheetName() + "', in Zeile " + (i + 2);
        actionLog.logError(msg);
        throw new UserException(msg);
      }
      if (date.getMonth() > month) {
        final String msg = "Buchungssätze können nicht in die Zukunft für den aktuellen Monat '"
            + KostFormatter.formatBuchungsmonat(year, date.getMonth())
            + " gebucht werden! "
            + satz;
        actionLog.logError(msg);
        throw new RuntimeException(msg);
      } else if (date.getMonth() < month) {
        final String msg = "Buchungssatz liegt vor Monat '" + KostFormatter.formatBuchungsmonat(year, month) + "' (OK): " + satz;
        actionLog.logInfo(msg);
      }
      satz.setYear(year);
      satz.setMonth(month);
      importedSheet.addElement(element);
      log.debug(satz);
    }
    importedSheet.setName(KostFormatter.formatBuchungsmonat(year, month));
    importedSheet.setProperty("year", year);
    importedSheet.setProperty("month", month);
    return importedSheet;
      }

  /**
   * Dummerweise ist im DATEV-Export die Spalte SH zweimal vertreten. Da wir SH aber für Haben/Soll auswerten müssen, müssen die Spalten
   * unterschiedlich heißen. Die zweite Spalte wird hier in SH2 umbenannt, sofern vorhanden.
   * @param sheet
   */
  private void rename2ndSH(final HSSFSheet sheet)
  {
    try {
      final HSSFRow row = sheet.getRow(ROW_COLUMNNAMES);
      if (row == null) {
        return;
      }
      short numberOfSH = 0;
      for (int col = 0; col < MAX_COLUMNS; col++) {
        final HSSFCell cell = row.getCell(col);
        if (cell == null) {
          break;
        }
        final String name = cell.getStringCellValue();
        log.debug("Processing column '" + name + "'");
        if ("SH".equals(cell.getStringCellValue()) == true) {
          numberOfSH++;
          if (numberOfSH == 2) {
            log.debug("Renaming 2nd column 'SH' to 'SH2' (column no. " + col + ").");
            cell.setCellValue("SH2");
          }
        }
      }
    } catch (final Exception ex) {
      log.error(ex.getMessage(), ex);
      throw new UserException(PFUserContext.getLocalizedString("finance.datev.import.error.titleRowMissed"));
    }
  }

  private ImportedElement<BuchungssatzDO> convertBuchungssatz(final BuchungssatzImportRow row) throws Exception
  {
    if (row.isEmpty() == true) {
      return null;
    }
    final ImportedElement<BuchungssatzDO> element = new ImportedElement<BuchungssatzDO>(storage.nextVal(), BuchungssatzDO.class,
        DatevImportDao.BUCHUNGSSATZ_DIFF_PROPERTIES);
    final BuchungssatzDO satz = new BuchungssatzDO();
    element.setValue(satz);
    satz.setBeleg(row.beleg);
    satz.setBetrag(row.betrag);
    satz.setSH(row.sh);
    satz.setDatum(row.datum);
    satz.setSatznr(row.satzNr);
    satz.setText(StringUtils.replace(row.text, "^", ""));
    satz.setMenge(row.menge);
    satz.setComment(row.comment);
    KontoDO konto = kontoDao.getKonto(row.konto);
    if (konto != null) {
      satz.setKonto(konto);
    } else {
      element.putErrorProperty("konto", row.konto);
    }
    konto = kontoDao.getKonto(row.gegenkonto);
    if (konto != null) {
      satz.setGegenKonto(konto);
    } else {
      element.putErrorProperty("gegenkonto", row.gegenkonto);
    }
    int[] values = KostFormatter.splitKost(row.getKost1());
    final Kost1DO kost1 = kost1Dao.getKost1(values[0], values[1], values[2], values[3]);
    if (kost1 != null) {
      satz.setKost1(kost1);
    } else {
      element.putErrorProperty("kost1", KostFormatter.formatKost(row.kost1));
    }
    values = KostFormatter.splitKost(row.getKost2());
    final Kost2DO kost2 = kost2Dao.getKost2(values[0], values[1], values[2], values[3]);
    if (kost2 != null) {
      satz.setKost2(kost2);
    } else {
      element.putErrorProperty("kost2", KostFormatter.formatKost(row.kost2));
    }
    satz.calculate();
    return element;
  }
}
TOP

Related Classes of org.projectforge.fibu.datev.BuchungssatzExcelImporter

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.