diff --git a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/datev/CargosoftExportScheduler.java b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/datev/CargosoftExportScheduler.java index 74dbf44..342e0ce 100644 --- a/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/datev/CargosoftExportScheduler.java +++ b/office-alexander-logistics-app/src/main/java/com/alexanderlogistics/datev/CargosoftExportScheduler.java @@ -22,7 +22,9 @@ *******************************************************************************/ package com.alexanderlogistics.datev; -import java.io.ByteArrayOutputStream; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; import java.text.DateFormat; import java.text.DecimalFormat; import java.text.SimpleDateFormat; @@ -31,6 +33,10 @@ import java.util.logging.Logger; import javax.ejb.EJB; +import org.apache.commons.net.ftp.FTP; +import org.apache.commons.net.ftp.FTPClient; +import org.apache.commons.net.ftp.FTPSClient; +import org.imixs.workflow.FileData; import org.imixs.workflow.ItemCollection; import org.imixs.workflow.engine.DocumentService; import org.imixs.workflow.engine.ModelService; @@ -39,10 +45,16 @@ import org.imixs.workflow.engine.WorkflowService; import org.imixs.workflow.engine.scheduler.Scheduler; import org.imixs.workflow.engine.scheduler.SchedulerException; import org.imixs.workflow.engine.scheduler.SchedulerService; +import org.imixs.workflow.exceptions.PluginException; import org.imixs.workflow.exceptions.QueryException; /** - * The CargosoftExportScheduler exports a csv file with kreditor data + * The CargosoftExportScheduler exportier eine csv Datei auf eine FTP Laufwerk + * mit allen noch offenen Rechnungen. Diese Datei wird von Cargosoft ann + * verwendet um den Kreditramen für einen kunden zu ermitteln. Es werden + * praktisch von Cargosoft nur die offenen Salen aus unserer CSV Datei pro + * Kreditor ermittelt. (Wir könnten sozusagen auch direkt das ergeniss liefern, + * aber so ist die aktuelel Carhosoft Schnittstelle implementiert). *

* The class implements the interface * _org.imixs.workflow.engine.scheduler.Scheduler_ and can be used in @@ -55,6 +67,7 @@ import org.imixs.workflow.exceptions.QueryException; public class CargosoftExportScheduler implements Scheduler { public static final int MAX_COUNT = 999; + public static final String FTP_ERROR = "FTP_ERROR"; public static DateFormat dateFormat = new SimpleDateFormat("ddMMyyyy"); public static DecimalFormat decimalFormat = new DecimalFormat("0.00"); @@ -84,16 +97,12 @@ public class CargosoftExportScheduler implements Scheduler { * @throws QueryException */ public ItemCollection run(ItemCollection configuration) throws SchedulerException { - ByteArrayOutputStream outputStream = null; List invoices = null; - String reportName = ""; - ItemCollection datevExport = null; - int maxCount = configuration.getItemValueInteger("_maxcount"); - if (maxCount == 0) { - maxCount = -1; - } + StringBuffer buffer = new StringBuffer(); + int lines = 0; - logger.info("....export to Cargosoft..."); + configuration.removeItem("_scheduler_logmessage"); + logMessage(configuration, "....export to Cargosoft..."); // $taskID<5900 String sQuery = "(type:workitem AND $modelversion:rechnungsausgang* AND $taskid:[5000 TO 5899])"; @@ -101,7 +110,7 @@ public class CargosoftExportScheduler implements Scheduler { // find the textblock... invoices = documentService.find(sQuery, 9999, 0); } catch (QueryException e) { - logger.warning("failed to search invoices by query: " + e.getMessage()); + logMessage(configuration, "failed to search invoices by query: " + e.getMessage()); } if (invoices != null && invoices.size() > 0) { @@ -143,20 +152,105 @@ public class CargosoftExportScheduler implements Scheduler { line = line + ";0,000000;0,00;"; } - - //77 ; - int i=77; - while(i>0) { + // auffüllen mit 77 mal ';' + int i = 77; + while (i > 0) { line = line + ";"; i--; } - - logger.info(line); + buffer.append(line + "\n"); + lines++; } } + // transfer file via FTP... + FileData fileData = new FileData("OPD28.txt", String.valueOf(buffer).getBytes(), null, null); + + put(configuration, fileData); + + logMessage(configuration, "...Export completed: " + lines + " lines"); return configuration; } + private void logMessage(ItemCollection configuration, String message) { + configuration.appendItemValue("_scheduler_logmessage", message); + logger.info(message); + } + + /** + * Diese Hilfsmehtode überträgt eine Datei an einen FTP Server. Die + * Verbindugnsdaten stehen im Configuraiton Workitem. + * + * @param fileData object + * @throws PluginException + */ + public void put(ItemCollection configuration, FileData fileData) { + + String ftpServer = configuration.getItemValueString("_datev_ftp_host"); + String ftpUser = configuration.getItemValueString("_datev_ftp_userid"); + String ftpPassword = configuration.getItemValueString("_datev_ftp_password"); + String ftpWorkingPath = configuration.getItemValueString("_datev_ftp_path_buchungsstapel"); + int ftpPort = configuration.getItemValueInteger("_datev_ftp_port"); + if (ftpPort <= 0) { + // set default port + ftpPort = 21; + } + + String fileName = fileData.getName(); + + // Compute file path + if (!ftpWorkingPath.startsWith("/")) { + ftpWorkingPath = "/" + ftpWorkingPath; + } + if (!ftpWorkingPath.endsWith("/")) { + ftpWorkingPath = ftpWorkingPath + "/"; + } + InputStream writer = null; + + FTPClient ftpClient = null; + try { + logMessage(configuration, "......put " + fileName + " to FTP server: " + ftpServer + "..."); + ftpClient = new FTPSClient("TLS", false); + ftpClient.setBufferSize(8192); + ftpClient.connect(ftpServer, ftpPort); + if (ftpClient.login(ftpUser, ftpPassword) == false) { + logMessage(configuration, "FTP file transfer failed: login failed!"); + } + ftpClient.enterLocalPassiveMode(); + ftpClient.setFileType(FTP.ASCII_FILE_TYPE); + ftpClient.setControlEncoding("UTF-8"); + + // verify directories + if (!ftpClient.changeWorkingDirectory(ftpWorkingPath)) { + logMessage(configuration, "FTP file transfer failed: missing working directory '" + ftpWorkingPath + + "' : " + ftpClient.getReplyString()); + } + + // upload file to FTP server. + writer = new ByteArrayInputStream(fileData.getContent()); + + if (!ftpClient.storeFile(fileName, writer)) { + logMessage(configuration, "FTP file transfer failed: unable to write '" + ftpWorkingPath + fileName + + "' : " + ftpClient.getReplyString()); + } + + logMessage(configuration, "...." + ftpWorkingPath + fileName + " transfered successfull to " + ftpServer); + + } catch (IOException e) { + logMessage(configuration, "FTP file transfer failed: " + e.getMessage()); + } finally { + // do logout.... + try { + if (writer != null) { + writer.close(); + } + ftpClient.logout(); + ftpClient.disconnect(); + } catch (IOException e) { + logMessage(configuration, "FTP file transfer failed: " + e.getMessage()); + } + } + } + } diff --git a/office-alexander-logistics-app/src/main/webapp/pages/admin/cargosoft_export.xhtml b/office-alexander-logistics-app/src/main/webapp/pages/admin/cargosoft_export.xhtml index 29f9c23..fa5a403 100644 --- a/office-alexander-logistics-app/src/main/webapp/pages/admin/cargosoft_export.xhtml +++ b/office-alexander-logistics-app/src/main/webapp/pages/admin/cargosoft_export.xhtml @@ -94,18 +94,10 @@ -

-
FTP Verzeichnis
-
- - -
-
+

- Die Verzeichnisse - werden mit der DATEV Mandanten ID ergänzt und müssen vor dem - Export angelegt worden sein! + In diesem Verzeichniss werden die Belegdaten + im DATEV Format abgelegt.

Scheduler