+ * Im Gegensatz zum FTPImportService werden die XML Dateien nach einem + * speziellen + * Verfahren geparsed und dann als Ausgangsrechnungen importiert. + * Der Service ersetzt den alten DATEV Import. Falls eine Rechnung schon + * existiert (Rechnungsnummer) wird der Datensatz vom FTP Laufwerk gelöscht und + * nicht importiert. + *
+ * In den Optionen muss die option "mandant.id" hinterlegt sein. Stimmt
+ * diese beim Import nicht mit der Mandanten Nummer in der XML Datei überein,
+ * wird das XML Dokument gelöscht und nicht importiert.
+ *
+ *
+ *
+ * @author rsoika
+ *
+ */
+@Stateless
+public class CargosoftXMLInvoiceImportImportService {
+
+ private static Logger logger = Logger.getLogger(CargosoftXMLInvoiceImportImportService.class.getName());
+ public static final String OPTION_MANDANT_ID = "mandant.id";
+
+ @EJB
+ WorkflowService workflowService;
+
+ @EJB
+ ModelService modelService;
+
+ @EJB
+ DocumentImportService documentImportService;
+
+ /**
+ * This method reacts on a CDI ImportEvent and reads documents form a ftp
+ * server.
+ *
+ *
+ */
+ public void onEvent(@Observes DocumentImportEvent event) {
+
+ // check if source is already completed
+ if (event.getResult() == DocumentImportEvent.PROCESSING_COMPLETED) {
+ logger.finest("...... import source already completed - no processing will be performed.");
+ return;
+ }
+
+ if (!"CARGOSOFT_INVOICE_XML".equalsIgnoreCase(event.getSource().getItemValueString("type"))) {
+ // ignore data source
+ logger.finest("...... type '" + event.getSource().getItemValueString("type") + "' skipped.");
+ return;
+ }
+
+ Properties sourceOptions = documentImportService.getOptionsProperties(event.getSource());
+ // Read Mandand ID form Option list
+ String mandantID = sourceOptions.getProperty(OPTION_MANDANT_ID, "");
+ if (mandantID == null || mandantID.isEmpty()) {
+ documentImportService.logMessage("...CARGOSOFT_INVOICE_XML Import failed - missing mandant.id in options!",
+ event);
+ event.setResult(DocumentImportEvent.PROCESSING_ERROR);
+ return;
+ }
+
+ documentImportService.logMessage("...CARGOSOFT_INVOICE_XML Import started: mandant.id=" + mandantID,
+ event);
+ String ftpServer = event.getSource().getItemValueString(DocumentImportService.SOURCE_ITEM_SERVER);
+ String ftpPort = event.getSource().getItemValueString(DocumentImportService.SOURCE_ITEM_PORT);
+ String ftpUser = event.getSource().getItemValueString(DocumentImportService.SOURCE_ITEM_USER);
+ String ftpPassword = event.getSource().getItemValueString(DocumentImportService.SOURCE_ITEM_PASSWORD);
+ String ftpPath = event.getSource().getItemValueString(DocumentImportService.SOURCE_ITEM_SELECTOR);
+
+ if (!ftpPath.startsWith("/") && !ftpPath.startsWith("./")) {
+ ftpPath = "/" + ftpPath;
+ }
+ if (!ftpPath.endsWith("/")) {
+ ftpPath = ftpPath + "/";
+ }
+
+ // if no server is given we exit
+ if (ftpServer.isEmpty()) {
+ logger.warning("...... no server specified!");
+ return;
+ }
+
+ if (ftpPort.isEmpty()) {
+ // set default port
+ ftpPort = "21";
+ }
+
+ FTPClient ftpClient = null;
+ try {
+ logger.finest("......read directories ...");
+
+ documentImportService.logMessage("...connecting to FTP server: " + ftpServer, event);
+
+ // TLS
+ ftpClient = new FTPSClient("TLS", false);
+ ftpClient.setControlEncoding("UTF-8");
+ ftpClient.connect(ftpServer, Integer.parseInt(ftpPort));
+ if (ftpClient.login(ftpUser, ftpPassword) == false) {
+ documentImportService.logMessage("FTP file transfer failed: login failed!", event);
+ event.setResult(DocumentImportEvent.PROCESSING_ERROR);
+ return;
+ }
+
+ ftpClient.enterLocalPassiveMode();
+ logger.finest("...... FileType=" + FTP.BINARY_FILE_TYPE);
+ ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
+ ftpClient.setControlEncoding("UTF-8");
+
+ // try to enter the working directory....
+ boolean bWorkingDir = ftpClient.changeWorkingDirectory(ftpPath);
+ if (bWorkingDir == true) {
+
+ documentImportService.logMessage("...working directory: " + ftpClient.printWorkingDirectory(), event);
+
+ // scann directories...
+
+ FTPFile[] subDirectories = ftpClient.listDirectories(ftpPath);
+
+ for (FTPFile ftpSubDirectory : subDirectories) {
+ ItemCollection space = null;
+
+ String ftpSubDirectoryName = ftpSubDirectory.getName();
+
+ logger.info("......scan files from path=" + ftpPath
+ + ftpSubDirectory.getName());
+
+ /*
+ * Nun importieren wir alle Files
+ */
+
+ FTPFile[] allFiles = ftpClient.listFiles(ftpPath + ftpSubDirectory.getName());
+
+ /*
+ * create a new workitem for each document
+ */
+
+ int count = 0;
+ if (allFiles.length > 0) {
+ documentImportService.logMessage("..." + allFiles.length + " files found ", event);
+ ftpClient.changeWorkingDirectory(ftpPath + ftpSubDirectory.getName());
+
+ for (FTPFile file : allFiles) {
+ // if this is a directory or symlink then we do ignore this entry
+ if (!file.isFile()) {
+ documentImportService.logMessage(
+ "...'" + file.getName() + "' is not a valid file, object will be ignored!",
+ event);
+ continue;
+ }
+ logger.info("import file " + file.getName() + "...");
+ // String fullFileName = ftpPath + "/" + file.getName();
+ try (ByteArrayOutputStream is = new ByteArrayOutputStream();) {
+ ftpClient.retrieveFile(file.getName(), is);
+ byte[] rawData = is.toByteArray();
+ if (rawData != null && rawData.length > 0) {
+ logger.finest("......file '" + file.getName() + "' successfull read - bytes size = "
+ + rawData.length);
+ // create new workitem
+ createWorkitem(event.getSource(), file.getName(), rawData, space);
+ // documentImportService.logMessage("....imported '" + file.getName() + "'",
+ // event);
+ count++;
+ } else {
+ documentImportService.logMessage("...Warning - invalid file content '"
+ + file.getName() + "' - file will be deleted!", event);
+ }
+ // finally delete the file....
+ ftpClient.deleteFile(file.getName());
+ } catch (AccessDeniedException | ProcessingErrorException | PluginException
+ | ModelException e) {
+
+ documentImportService.logMessage("...FTP import failed: " + e.getMessage(), event);
+ event.setResult(DocumentImportEvent.PROCESSING_ERROR);
+ return;
+ }
+ }
+ documentImportService.logMessage("..." + count + " new files imported.", event);
+
+ } else {
+ documentImportService.logMessage("...no files found, directory '" + ftpPath + "' is empty",
+ event);
+ }
+ }
+ } else {
+ documentImportService.logMessage("...failed to change into working directory: " + ftpPath, event);
+ }
+
+ } catch (IOException e) {
+ logger.severe("FTP I/O Error: " + e.getMessage());
+ int r = ftpClient.getReplyCode();
+ logger.severe("FTP ReplyCode=" + r);
+
+ documentImportService.logMessage("...FTP file transfer failed (replyCode=" + r + ") : " + e.getMessage(),
+ event);
+ event.setResult(DocumentImportEvent.PROCESSING_ERROR);
+ return;
+
+ } finally {
+ // do logout....
+ try {
+
+ ftpClient.logout();
+ ftpClient.disconnect();
+ } catch (IOException e) {
+ documentImportService.logMessage("...FTP file transfer failed: " + e.getMessage(), event);
+ event.setResult(DocumentImportEvent.PROCESSING_ERROR);
+ return;
+ }
+ }
+
+ // completed
+ event.setResult(DocumentImportEvent.PROCESSING_COMPLETED);
+
+ }
+
+ /**
+ * Creates and processes a new workitem with a given xml information from the
+ * filedata
+ *
+ *
+ * @return
+ * @throws ModelException
+ * @throws PluginException
+ * @throws ProcessingErrorException
+ * @throws AccessDeniedException
+ */
+ public ItemCollection createWorkitem(ItemCollection source, String fileName, byte[] rawData, ItemCollection space)
+ throws AccessDeniedException, ProcessingErrorException, PluginException, ModelException {
+ ItemCollection workitem = new ItemCollection();
+ workitem.model(source.getItemValueString(DocumentImportService.SOURCE_ITEM_MODELVERSION));
+ workitem.task(source.getItemValueInteger(DocumentImportService.SOURCE_ITEM_TASK));
+ workitem.event(source.getItemValueInteger(DocumentImportService.SOURCE_ITEM_EVENT));
+ workitem.setWorkflowGroup(source.getItemValueString("workflowgroup"));
+
+ return workitem;
+ }
+
+}
diff --git a/office-alexander-logistics-app/src/main/webapp/pages/admin/document_import.xhtml b/office-alexander-logistics-app/src/main/webapp/pages/admin/document_import.xhtml
index 20472b8..74378cf 100644
--- a/office-alexander-logistics-app/src/main/webapp/pages/admin/document_import.xhtml
+++ b/office-alexander-logistics-app/src/main/webapp/pages/admin/document_import.xhtml
@@ -1,13 +1,8 @@
- Define a crontab to schedule the import processor. Define a crontab to schedule the
+ import processor. Define a destination IMAP server and assign mail addresses to specific workflow groups. Define a destination IMAP server and
+ assign mail addresses to specific workflow groups. A selector can be an optional regular expression to be used to select a subset of data A selector can be an optional regular
+ expression to be used to select a subset of data
+
-
-
-
-
+ Pos
- Type
- Workflowgroup
- Modelversion
- Task
- Event
-
-
-
-
+
- Pos
+ Type
+ Workflowgroup
+ Modelversion
+ Task
+ Event
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Order ID #
+
+ Order ID #
+
-
+
-
-
+
@@ -287,35 +297,34 @@