xml invoice import
This commit is contained in:
parent
f9169a184b
commit
2203a41d3b
3 changed files with 190 additions and 69 deletions
|
|
@ -8,12 +8,9 @@ import java.text.ParseException;
|
|||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
|
|
@ -33,6 +30,7 @@ import org.imixs.workflow.exceptions.QueryException;
|
|||
|
||||
import com.alexanderlogistics.InvoiceUtil;
|
||||
import com.alexanderlogistics.KreditorDebitorService;
|
||||
import com.alexanderlogistics.mahnlauf.MahnlaufService;
|
||||
|
||||
/**
|
||||
* Der DatevCargosoftImportAdapter liest eine von Cargosoft bereitgestellte
|
||||
|
|
@ -126,6 +124,9 @@ public class DatevCargosoftImportAdapter implements SignalAdapter {
|
|||
@Inject
|
||||
TeamService teamService;
|
||||
|
||||
@Inject
|
||||
MahnlaufService mahnlaufService;
|
||||
|
||||
private String INITIAL_MODEL_VERSION_INVOICE;
|
||||
private int INITIAL_TASK_ID_INVOICE;
|
||||
private int INITIAL_EVENT_ID_INVOICE;
|
||||
|
|
@ -206,7 +207,7 @@ public class DatevCargosoftImportAdapter implements SignalAdapter {
|
|||
SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyyMMdd");
|
||||
|
||||
// load spaces Pos Expressions
|
||||
Map<String, List<String>> spacePosMappings = loadSpacePosMappings();
|
||||
Map<String, List<String>> spacePosMappings = mahnlaufService.loadSpacePosMappings();
|
||||
|
||||
ItemCollection invoiceWorkitem = null;
|
||||
List<ItemCollection> splitBuchungen = new ArrayList<ItemCollection>();
|
||||
|
|
@ -385,27 +386,6 @@ public class DatevCargosoftImportAdapter implements SignalAdapter {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that loads all expressions from the spaces
|
||||
*
|
||||
* @return List of list of expressions
|
||||
*/
|
||||
private Map<String, List<String>> loadSpacePosMappings() {
|
||||
Map<String, List<String>> result = new HashMap<>();
|
||||
// als erstes lesen wir die pos.mappings aus den Spaces ein, auf die dann eine
|
||||
// Rechnung emapped werden kann.
|
||||
List<ItemCollection> spaces_subs = teamService.getSpaces();
|
||||
for (ItemCollection stub : spaces_subs) {
|
||||
// load full workitem
|
||||
ItemCollection space = documentService.load(stub.getUniqueID());
|
||||
if (space != null) {
|
||||
result.put(space.getUniqueID(), space.getItemValueList("pos.mapping", String.class));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method returns a new empty invoice ItemCollection.
|
||||
* <p>
|
||||
|
|
@ -525,27 +505,29 @@ public class DatevCargosoftImportAdapter implements SignalAdapter {
|
|||
}
|
||||
|
||||
// Jezt noch das Space mapping
|
||||
// dazu kucken wir in alle spaces den config wert 'pos.mapping'
|
||||
String text = datevWorkitem.getItemValueString("invoice.text");
|
||||
if (!text.isEmpty()) {
|
||||
boolean found = false;
|
||||
for (Map.Entry<String, List<String>> entry : spacePosMappings.entrySet()) {
|
||||
List<String> expressionsList = entry.getValue();
|
||||
for (String expr : expressionsList) {
|
||||
Pattern p = Pattern.compile(expr);
|
||||
Matcher m = p.matcher(text);
|
||||
if (m.find()) {
|
||||
// we have a match
|
||||
datevWorkitem.setItemValue("space.ref", entry.getKey());
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
mahnlaufService.mapInvoiceTextToSpace(datevWorkitem, spacePosMappings);
|
||||
// // dazu kucken wir in alle spaces den config wert 'pos.mapping'
|
||||
// String text = datevWorkitem.getItemValueString("invoice.text");
|
||||
// if (!text.isEmpty()) {
|
||||
// boolean found = false;
|
||||
// for (Map.Entry<String, List<String>> entry : spacePosMappings.entrySet()) {
|
||||
// List<String> expressionsList = entry.getValue();
|
||||
// for (String expr : expressionsList) {
|
||||
// Pattern p = Pattern.compile(expr);
|
||||
// Matcher m = p.matcher(text);
|
||||
// if (m.find()) {
|
||||
// // we have a match
|
||||
// datevWorkitem.setItemValue("space.ref", entry.getKey());
|
||||
// found = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// if (found) {
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// Processe die Invoice
|
||||
datevWorkitem.model(INITIAL_MODEL_VERSION_INVOICE).task(INITIAL_TASK_ID_INVOICE)
|
||||
.event(INITIAL_EVENT_ID_INVOICE);
|
||||
|
|
|
|||
|
|
@ -27,13 +27,21 @@
|
|||
|
||||
package com.alexanderlogistics.mahnlauf;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.annotation.security.DeclareRoles;
|
||||
import javax.annotation.security.RolesAllowed;
|
||||
import javax.annotation.security.RunAs;
|
||||
import javax.ejb.Singleton;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.imixs.marty.team.TeamService;
|
||||
import org.imixs.workflow.ItemCollection;
|
||||
import org.imixs.workflow.engine.DocumentService;
|
||||
import org.imixs.workflow.engine.WorkflowService;
|
||||
import org.imixs.workflow.exceptions.AccessDeniedException;
|
||||
import org.imixs.workflow.exceptions.ModelException;
|
||||
|
|
@ -58,22 +66,24 @@ import org.imixs.workflow.exceptions.ProcessingErrorException;
|
|||
@RunAs("org.imixs.ACCESSLEVEL.MANAGERACCESS")
|
||||
public class MahnlaufService {
|
||||
|
||||
public static final int TASK_MAHNLAUF_START = 5100;
|
||||
public static final int TASK_MAHNLAUF_END = 5299;
|
||||
public static final int EVENT_MAHNLAUF_EXECUTE = 300;
|
||||
|
||||
public static final int TASK_MAHNLAUF_START = 5100;
|
||||
public static final int TASK_MAHNLAUF_END = 5299;
|
||||
public static final int EVENT_MAHNLAUF_EXECUTE = 300;
|
||||
|
||||
public static final String ITEM_DBTR_NUMBER = "dbtr.number";
|
||||
public static final String ITEM_DBTR_NAME = "dbtr.name";
|
||||
public static final String ITEM_DBTR_EMAIL = "dbtr.mail";
|
||||
public static final String ERROR_CONFIG = "CONFIG_ERROR";
|
||||
public static final String ERROR_WORKFLOW = "ERROR_WORKFLOW";
|
||||
|
||||
public static final String ITEM_DBTR_NUMBER = "dbtr.number";
|
||||
public static final String ITEM_DBTR_NAME = "dbtr.name";
|
||||
public static final String ITEM_DBTR_EMAIL = "dbtr.mail";
|
||||
public static final String ERROR_CONFIG = "CONFIG_ERROR";
|
||||
public static final String ERROR_WORKFLOW = "ERROR_WORKFLOW";
|
||||
|
||||
@Inject
|
||||
WorkflowService workflowService;
|
||||
|
||||
@Inject
|
||||
TeamService teamService;
|
||||
|
||||
@Inject
|
||||
DocumentService documentService;
|
||||
|
||||
/**
|
||||
* * Diese Method processed eine Invoice mit Manager Rechnten
|
||||
|
|
@ -92,4 +102,55 @@ public class MahnlaufService {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method that loads all expressions from the spaces
|
||||
*
|
||||
* @return List of list of expressions
|
||||
*/
|
||||
public Map<String, List<String>> loadSpacePosMappings() {
|
||||
Map<String, List<String>> result = new HashMap<>();
|
||||
// als erstes lesen wir die pos.mappings aus den Spaces ein, auf die dann eine
|
||||
// Rechnung emapped werden kann.
|
||||
List<ItemCollection> spaces_subs = teamService.getSpaces();
|
||||
for (ItemCollection stub : spaces_subs) {
|
||||
// load full workitem
|
||||
ItemCollection space = documentService.load(stub.getUniqueID());
|
||||
if (space != null) {
|
||||
result.put(space.getUniqueID(), space.getItemValueList("pos.mapping", String.class));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hilfsmethode zum errechnen des richtigen Spaces zu einer invoice.text Positon
|
||||
*
|
||||
* @param workitem
|
||||
* @param spacePosMappings
|
||||
*/
|
||||
public void mapInvoiceTextToSpace(ItemCollection workitem, Map<String, List<String>> spacePosMappings) {
|
||||
// Jezt noch das Space mapping
|
||||
// dazu kucken wir in alle spaces den config wert 'pos.mapping'
|
||||
String text = workitem.getItemValueString("invoice.text");
|
||||
if (!text.isEmpty()) {
|
||||
boolean found = false;
|
||||
for (Map.Entry<String, List<String>> entry : spacePosMappings.entrySet()) {
|
||||
List<String> expressionsList = entry.getValue();
|
||||
for (String expr : expressionsList) {
|
||||
Pattern p = Pattern.compile(expr);
|
||||
Matcher m = p.matcher(text);
|
||||
if (m.find()) {
|
||||
// we have a match
|
||||
workitem.setItemValue("space.ref", entry.getKey());
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ import java.text.SimpleDateFormat;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.TimeZone;
|
||||
import java.util.logging.Logger;
|
||||
|
|
@ -44,6 +45,7 @@ import java.util.logging.Logger;
|
|||
import javax.ejb.EJB;
|
||||
import javax.ejb.Stateless;
|
||||
import javax.enterprise.event.Observes;
|
||||
import javax.inject.Inject;
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
|
|
@ -76,6 +78,8 @@ import org.xml.sax.InputSource;
|
|||
import org.xml.sax.SAXException;
|
||||
|
||||
import com.alexanderlogistics.InvoiceUtil;
|
||||
import com.alexanderlogistics.KreditorDebitorService;
|
||||
import com.alexanderlogistics.mahnlauf.MahnlaufService;
|
||||
|
||||
/**
|
||||
* Der CargosoftXMLInvoiceImportImportService erweitert den FTPImportService und
|
||||
|
|
@ -110,12 +114,19 @@ public class CargosoftXMLInvoiceImportImportService {
|
|||
|
||||
@EJB
|
||||
DocumentService documentService;
|
||||
|
||||
@EJB
|
||||
ModelService modelService;
|
||||
|
||||
@EJB
|
||||
KreditorDebitorService kreditorDebitorService;
|
||||
|
||||
@EJB
|
||||
DocumentImportService documentImportService;
|
||||
|
||||
@Inject
|
||||
MahnlaufService mahnlaufService;
|
||||
|
||||
/**
|
||||
* This method reacts on a CDI ImportEvent and reads documents form a ftp
|
||||
* server.
|
||||
|
|
@ -226,6 +237,10 @@ public class CargosoftXMLInvoiceImportImportService {
|
|||
private void scannFTPDirectory(FTPClient ftpClient, String ftpPath, String mandantID, DocumentImportEvent event)
|
||||
throws PluginException {
|
||||
try {
|
||||
|
||||
// load spaces Pos Expressions
|
||||
Map<String, List<String>> spacePosMappings = mahnlaufService.loadSpacePosMappings();
|
||||
|
||||
logger.finest("......read directory " + ftpPath);
|
||||
// try to enter the working directory and read all files...
|
||||
boolean bWorkingDir = ftpClient.changeWorkingDirectory(ftpPath);
|
||||
|
|
@ -256,7 +271,7 @@ public class CargosoftXMLInvoiceImportImportService {
|
|||
logger.finest("......file '" + file.getName() + "' successful read - bytes size = "
|
||||
+ rawData.length);
|
||||
// create new workitem
|
||||
invoice = createWorkitem(event.getSource(), file.getName(), rawData);
|
||||
invoice = createWorkitem(event.getSource(), file.getName(), rawData, spacePosMappings);
|
||||
if (invoice == null) {
|
||||
// no new data found
|
||||
continue;
|
||||
|
|
@ -319,7 +334,8 @@ public class CargosoftXMLInvoiceImportImportService {
|
|||
* @throws ProcessingErrorException
|
||||
* @throws AccessDeniedException
|
||||
*/
|
||||
public ItemCollection createWorkitem(ItemCollection source, String fileName, byte[] rawData)
|
||||
public ItemCollection createWorkitem(ItemCollection source, String fileName, byte[] rawData,
|
||||
Map<String, List<String>> spacePosMappings)
|
||||
throws AccessDeniedException, ProcessingErrorException, PluginException, ModelException {
|
||||
ItemCollection workitem = new ItemCollection();
|
||||
workitem.model(source.getItemValueString(DocumentImportService.SOURCE_ITEM_MODELVERSION));
|
||||
|
|
@ -361,8 +377,20 @@ public class CargosoftXMLInvoiceImportImportService {
|
|||
return null;
|
||||
}
|
||||
|
||||
readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/InvoiceAmount/NetAmount/Amount/Value",
|
||||
workitem, "invoice.total", String.class);
|
||||
readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/InvoiceType/Codes/Code",
|
||||
workitem, "invoice.type", String.class);
|
||||
|
||||
// Gutschrift oder Rechnung?
|
||||
if ("G".equals(workitem.getItemValueString("invoice.type"))) {
|
||||
readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/InvoiceAmount/NetAmount/Amount/Value",
|
||||
workitem, "invoice.total", Double.class);
|
||||
workitem.setItemValue("invoice.saldo", -workitem.getItemValueDouble("invoice.total"));
|
||||
workitem.setItemValue("invoice.total", -workitem.getItemValueDouble("invoice.total"));
|
||||
} else {
|
||||
readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/InvoiceAmount/NetAmount/Amount/Value",
|
||||
workitem, "invoice.total", Double.class);
|
||||
workitem.setItemValue("invoice.saldo", workitem.getItemValueDouble("invoice.total"));
|
||||
}
|
||||
|
||||
readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/InvoiceCurrency/Codes/Code",
|
||||
workitem, "invoice.currency", String.class);
|
||||
|
|
@ -370,6 +398,10 @@ public class CargosoftXMLInvoiceImportImportService {
|
|||
readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/InvoiceDate",
|
||||
workitem, "invoice.date", Date.class);
|
||||
|
||||
readXMLValue(doc,
|
||||
"/Invoices/Invoice/InvoiceHeader/PaymentConditions/PaymentCondition/Codes/Code[@Type='cs']",
|
||||
workitem, "payment.term", String.class);
|
||||
|
||||
readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/PaymentConditions/DueDate",
|
||||
workitem, "invoice.duedate", Date.class);
|
||||
|
||||
|
|
@ -379,10 +411,21 @@ public class CargosoftXMLInvoiceImportImportService {
|
|||
if (dbtrNumber.startsWith("K") || dbtrNumber.startsWith("D")) {
|
||||
workitem.setItemValue("dbtr.number", dbtrNumber.substring(1));
|
||||
}
|
||||
// lookup debitor and set name
|
||||
try {
|
||||
ItemCollection dbtr = kreditorDebitorService.findDebitor(dbtrNumber);
|
||||
if (dbtr != null) {
|
||||
workitem.setItemValue("dbtr.name", dbtr.getItemValueString("_vendor_name"));
|
||||
}
|
||||
} catch (PluginException e) {
|
||||
// e.printStackTrace();
|
||||
}
|
||||
|
||||
// Row Positions lesen
|
||||
// InvoiceRows/InvoiceRow
|
||||
readXMLRows(doc, workitem);
|
||||
// Jetzt noch das Space mapping
|
||||
mahnlaufService.mapInvoiceTextToSpace(workitem, spacePosMappings);
|
||||
|
||||
// read filename
|
||||
readXMLValue(doc, "/Invoices/Invoice/InvoiceHeader/Attachments/Attachment/Filename",
|
||||
|
|
@ -404,9 +447,6 @@ public class CargosoftXMLInvoiceImportImportService {
|
|||
return workitem;
|
||||
}
|
||||
|
||||
public <T> void getMist(String itemName, Class<T> itemType) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads a tag value from the xml tree and set the value into the given
|
||||
* workitem.
|
||||
|
|
@ -447,11 +487,11 @@ public class CargosoftXMLInvoiceImportImportService {
|
|||
}
|
||||
return;
|
||||
}
|
||||
if (itemType == Double.class) {
|
||||
if (itemType == Double.class && value != null && !value.isEmpty()) {
|
||||
workitem.setItemValue(itemName, Double.parseDouble(value));
|
||||
return;
|
||||
}
|
||||
if (itemType == Integer.class) {
|
||||
if (itemType == Integer.class && value != null && !value.isEmpty()) {
|
||||
workitem.setItemValue(itemName, Integer.parseInt(value));
|
||||
return;
|
||||
}
|
||||
|
|
@ -495,6 +535,11 @@ public class CargosoftXMLInvoiceImportImportService {
|
|||
XPathExpression netAmountCurrencyExpr = xPath
|
||||
.compile("InvoiceAmount/NetAmount/Amount/Currency/Codes/Code[@Type='cs']/text()");
|
||||
XPathExpression netAmountValueExpr = xPath.compile("InvoiceAmount/NetAmount/Amount/Value/text()");
|
||||
XPathExpression netAmountExchangeRateExpr = xPath
|
||||
.compile("InvoiceAmount/NetAmount/Amount/ExchangeRate/text()");
|
||||
|
||||
XPathExpression netActivityTypeExpr = xPath
|
||||
.compile("InvoiceAmount/ActivityType/Codes/Code[@Type='cs']/text()");
|
||||
|
||||
NodeList rowList = doc.getElementsByTagName("InvoiceRow");
|
||||
for (int i = 0; i < rowList.getLength(); i++) {
|
||||
|
|
@ -505,10 +550,41 @@ public class CargosoftXMLInvoiceImportImportService {
|
|||
// Get the FileNumber value
|
||||
String fileNumber = (String) fileNumberExpr.evaluate(rowNode, XPathConstants.STRING);
|
||||
childItemCol.setItemValue("datev.text", fileNumber);
|
||||
|
||||
// speichere die Position in invoice.positions zur suche nach dem
|
||||
// Positionskennzeichen
|
||||
workitem.appendItemValue("invoice.positions", fileNumber);
|
||||
|
||||
String currency = (String) netAmountCurrencyExpr.evaluate(rowNode, XPathConstants.STRING);
|
||||
childItemCol.setItemValue("datev.wkz", currency);
|
||||
// Umsatz
|
||||
String umsatz = (String) netAmountValueExpr.evaluate(rowNode, XPathConstants.STRING);
|
||||
childItemCol.setItemValue("datev.umsatz", Double.parseDouble(umsatz));
|
||||
double dUmsatz = Double.parseDouble(umsatz);
|
||||
childItemCol.setItemValue("datev.umsatz", dUmsatz);
|
||||
// Kurs
|
||||
String kurs = (String) netAmountExchangeRateExpr.evaluate(rowNode, XPathConstants.STRING);
|
||||
if (kurs != null && !kurs.isEmpty()) {
|
||||
Double dKurs = Double.parseDouble(kurs);
|
||||
childItemCol.setItemValue("datev.kurs", dKurs);
|
||||
// Basisumsatz
|
||||
if (dKurs != 0) {
|
||||
double basisUmsatz = dUmsatz / dKurs;
|
||||
double gerundeterBasisUmsatz = Math.round(basisUmsatz * 100) / 100.0;
|
||||
childItemCol.setItemValue("datev.basisumsatz", gerundeterBasisUmsatz);
|
||||
}
|
||||
}
|
||||
|
||||
String activityType = (String) netActivityTypeExpr.evaluate(rowNode, XPathConstants.STRING);
|
||||
childItemCol.setItemValue("category", activityType);
|
||||
|
||||
// Invoice Type S/H
|
||||
if ("G".equals(workitem.getItemValueString("invoice.type"))) {
|
||||
// Gutschrift
|
||||
childItemCol.setItemValue("datev.shzeichen", "S");
|
||||
} else {
|
||||
// Rechnung
|
||||
childItemCol.setItemValue("datev.shzeichen", "H");
|
||||
}
|
||||
|
||||
childItems.add(childItemCol);
|
||||
}
|
||||
|
|
@ -521,6 +597,8 @@ public class CargosoftXMLInvoiceImportImportService {
|
|||
|
||||
// Set child items
|
||||
InvoiceUtil.implodeChildList(workitem, childItems);
|
||||
// invoice.text ist erste position
|
||||
workitem.setItemValue("invoice.text", workitem.getItemValueString("invoice.positions"));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue