540 lines
No EOL
24 KiB
Java
540 lines
No EOL
24 KiB
Java
package com.alexanderlogistics.einvoice;
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.text.NumberFormat;
|
|
import java.text.SimpleDateFormat;
|
|
import java.util.Collection;
|
|
import java.util.Date;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.Map;
|
|
import java.util.logging.Logger;
|
|
|
|
import javax.xml.parsers.DocumentBuilder;
|
|
import javax.xml.parsers.DocumentBuilderFactory;
|
|
import javax.xml.parsers.ParserConfigurationException;
|
|
import javax.xml.transform.TransformerException;
|
|
import javax.xml.xpath.XPath;
|
|
import javax.xml.xpath.XPathConstants;
|
|
import javax.xml.xpath.XPathExpression;
|
|
import javax.xml.xpath.XPathExpressionException;
|
|
import javax.xml.xpath.XPathFactory;
|
|
|
|
import org.imixs.archive.core.SnapshotService;
|
|
import org.imixs.einvoice.EInvoiceFormatException;
|
|
import org.imixs.einvoice.EInvoiceModel;
|
|
import org.imixs.einvoice.EInvoiceModelFactory;
|
|
import org.imixs.einvoice.EInvoiceModelKSeF;
|
|
import org.imixs.einvoice.EInvoiceNS;
|
|
import org.imixs.einvoice.TradeParty;
|
|
import org.imixs.workflow.FileData;
|
|
import org.imixs.workflow.ItemCollection;
|
|
import org.imixs.workflow.SignalAdapter;
|
|
import org.imixs.workflow.engine.DocumentService;
|
|
import org.imixs.workflow.engine.WorkflowService;
|
|
import org.imixs.workflow.exceptions.AdapterException;
|
|
import org.imixs.workflow.exceptions.PluginException;
|
|
import org.imixs.workflow.exceptions.QueryException;
|
|
import org.imixs.workflow.util.XMLParser;
|
|
import org.w3c.dom.Document;
|
|
import org.w3c.dom.Element;
|
|
import org.w3c.dom.Node;
|
|
import org.w3c.dom.NodeList;
|
|
import org.xml.sax.InputSource;
|
|
import org.xml.sax.SAXException;
|
|
|
|
import com.alexanderlogistics.BusinessPartnerService;
|
|
import com.alexanderlogistics.InvoiceService;
|
|
import com.alexanderlogistics.InvoiceUtil;
|
|
import com.alexanderlogistics.xml.CargosoftXMLInvoiceImportService;
|
|
|
|
import jakarta.inject.Inject;
|
|
|
|
/**
|
|
* The KSeFAdapter converts a Cargosoft outbound invoice into a KSeF FA(3) XML
|
|
* e-invoice and sends the xml file to the polish KSeF API.
|
|
* <p>
|
|
* The adapter is configured via the BPMN model:
|
|
*
|
|
* <pre>
|
|
* {@code
|
|
* <ksef name="create">
|
|
* <textblock>textblock-ref</textblock>
|
|
* <template>filename</template>
|
|
* <debug>true</debug>
|
|
* </ksef>
|
|
* }
|
|
* </pre>
|
|
*
|
|
* <p>
|
|
* <b>Architecture:</b> The adapter handles invoice header data (parties,
|
|
* dates, invoice type, currency code, KOR/correction data). All logic
|
|
* concerning invoice positions ({@code <FaWiersz>}) and summary fields
|
|
* ({@code P_13_x}, {@code P_14_x}, {@code P_14_xW}, {@code P_15},
|
|
* {@code KursWalutyZ}) is delegated to {@link KSeFInvoiceLineBuilder}, which
|
|
* uses the CargoSoft VAT code per position to determine the correct target
|
|
* field in the {@code <Fa>} block.
|
|
*
|
|
* <p>
|
|
* <b>NIP:</b> The adapter needs the NIP (vat-id). If we do not find the
|
|
* partner.vat in the business object, we do a lookup on the D-Cargosoft
|
|
* object and try the vat id from there.
|
|
*
|
|
* @version 2.0
|
|
* @author rsoika
|
|
*/
|
|
public class KSeFAdapter implements SignalAdapter {
|
|
|
|
final String TYPE_TEXTBLOCK = "textblock";
|
|
public static final String DOCUMENT_ERROR = "DOCUMENT_ERROR";
|
|
public static final String CONFIG_ERROR = "CONFIG_ERROR";
|
|
public static final String API_ERROR = "API_ERROR";
|
|
public static final String BUSINESSPARTNER_ERROR = "BUSINESSPARTNER_ERROR";
|
|
public static final String LINE_ITEMS_PROPERTY = "invoice.items";
|
|
private static Logger logger = Logger.getLogger(EInvoiceAdapter.class.getName());
|
|
|
|
public static SimpleDateFormat dateFormatter = new SimpleDateFormat("dd.MM.yyyy", Locale.GERMAN);
|
|
public static NumberFormat numberFormat = NumberFormat.getInstance(Locale.GERMANY);
|
|
boolean debug = false;
|
|
|
|
@Inject
|
|
WorkflowService workflowService;
|
|
|
|
@Inject
|
|
DocumentService documentService;
|
|
|
|
@Inject
|
|
SnapshotService snapshotService;
|
|
|
|
@Inject
|
|
BusinessPartnerService businessPartnerService;
|
|
|
|
@Inject
|
|
InvoiceService invoiceService;
|
|
|
|
@Override
|
|
public ItemCollection execute(ItemCollection workitem, ItemCollection event)
|
|
throws AdapterException, PluginException {
|
|
|
|
logger.info("├── 🔜 Convert Invoice to KSeF...");
|
|
|
|
// Read configuration
|
|
ItemCollection eInvoiceConfig = workflowService.evalWorkflowResult(event, "ksef", workitem, false);
|
|
if (eInvoiceConfig == null || !eInvoiceConfig.hasItem("CREATE")) {
|
|
throw new PluginException(EInvoiceAdapter.class.getSimpleName(), CONFIG_ERROR,
|
|
"missing e-invoice/ksef configuration in model event - please check model configuration");
|
|
}
|
|
ItemCollection ksefCreateDefinition = XMLParser.parseItemStructure(eInvoiceConfig.getItemValueString("CREATE"));
|
|
|
|
try {
|
|
// Load the e-invoice template
|
|
FileData xmlFileData = loadXMLTemplate(workitem, ksefCreateDefinition);
|
|
|
|
updateEInvoice(xmlFileData, workitem);
|
|
|
|
// Append XML document
|
|
logger.info("│ ├── attach KSeF e-invoice...");
|
|
workitem.addFileData(xmlFileData);
|
|
|
|
} catch (PluginException e) {
|
|
throw new AdapterException(e);
|
|
}
|
|
|
|
return workitem;
|
|
}
|
|
|
|
/**
|
|
* Updates the e-invoice template with the data stored in the workitem.
|
|
* <p>
|
|
* The method handles invoice header data (parties, invoice type, dates,
|
|
* currency code, KOR data) and then delegates the entire line-item and
|
|
* summary construction to {@link KSeFInvoiceLineBuilder}.
|
|
*
|
|
* @param fileDataXMLTemplate the XML template to be filled
|
|
* @param workitem the workitem holding the invoice data
|
|
* @throws PluginException if the model cannot be parsed or written
|
|
*/
|
|
public void updateEInvoice(FileData fileDataXMLTemplate, ItemCollection workitem) throws PluginException {
|
|
|
|
try {
|
|
EInvoiceModel model = EInvoiceModelFactory.read(new ByteArrayInputStream(fileDataXMLTemplate.getContent()));
|
|
|
|
model.setId(workitem.getItemValueString("invoice.number"));
|
|
|
|
// Issue date
|
|
model.setIssueDateTime(workitem.getItemValueLocalDate("invoice.date"));
|
|
|
|
// Performance date - resync from Cargosoft XML if missing
|
|
if (workitem.getItemValueDate("invoice.performancedate") == null) {
|
|
syncPerformanceDate(workitem);
|
|
}
|
|
|
|
// CargoSoft VAT code per child item - resync from Cargosoft XML if any
|
|
// child item is missing it (legacy data created before the import was
|
|
// extended to capture cargosoft.vat.code)
|
|
if (isAnyChildMissingVatCode(workitem)) {
|
|
syncCargosoftVatCodes(workitem);
|
|
}
|
|
((EInvoiceModelKSeF) model)
|
|
.setPerformanceDateTime(workitem.getItemValueLocalDate("invoice.performancedate"));
|
|
|
|
// Buyer address
|
|
TradeParty billingAddress = buildAddress(workitem, "buyer", model);
|
|
model.setTradeParty(billingAddress);
|
|
|
|
// Tax type derived from NIP - 1=Poland, 2=EU, 3=Other
|
|
// Still used by setTradeParty (NIP vs. NrID decision via prefix)
|
|
((EInvoiceModelKSeF) model).setTaxType(workitem.getItemValueString("partner.vat"));
|
|
workitem.setItemValue("invoice.tax.type", ((EInvoiceModelKSeF) model).getTaxType());
|
|
|
|
// Invoice type (RodzajFaktury) -> VAT or KOR
|
|
Element elementFa = model.findOrCreateChildNode(model.getRoot(), EInvoiceNS.KSEF, "Fa");
|
|
|
|
if (isKorrekturRechnung(workitem)) {
|
|
((EInvoiceModelKSeF) model).setRodzajFaktury("KOR");
|
|
logger.info("│ ├── invoice type=KOR");
|
|
|
|
// Correction data (DaneFaKorygowanej) - required for KOR invoices
|
|
Element daneFaKorygowanej = model.findOrCreateChildNodeAfter(
|
|
elementFa, EInvoiceNS.KSEF, "DaneFaKorygowanej", "RodzajFaktury");
|
|
|
|
Date correctionInvoiceDate = workitem.getItemValueDate("invoice.date");
|
|
ItemCollection correctionInvoice = invoiceService
|
|
.findOutboundInvoiceByNumber(workitem.getItemValueString("invoice.CorrectionInvoiceNumber"));
|
|
if (correctionInvoice != null) {
|
|
correctionInvoiceDate = correctionInvoice.getItemValueDate("invoice.date");
|
|
logger.info("│ ├── found original invoice, date: " + correctionInvoiceDate);
|
|
} else {
|
|
logger.info("│ ├── ⚠️ original invoice not found, using current date as fallback");
|
|
}
|
|
|
|
// Original invoice date - required
|
|
if (correctionInvoiceDate != null) {
|
|
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
|
|
String sCorrectionDate = formatter.format(correctionInvoiceDate);
|
|
model.updateElementValue(daneFaKorygowanej, EInvoiceNS.KSEF,
|
|
"DataWystFaKorygowanej", sCorrectionDate);
|
|
}
|
|
|
|
// Original invoice number - required
|
|
model.updateElementValue(daneFaKorygowanej, EInvoiceNS.KSEF,
|
|
"NrFaKorygowanej", workitem.getItemValueString("invoice.CorrectionInvoiceNumber"));
|
|
|
|
// NrKSeFN = 1 means the original invoice was issued outside KSeF
|
|
model.updateElementValue(daneFaKorygowanej, EInvoiceNS.KSEF, "NrKSeFN", "1");
|
|
|
|
} else {
|
|
((EInvoiceModelKSeF) model).setRodzajFaktury("VAT");
|
|
logger.info("│ ├── invoice type=VAT");
|
|
}
|
|
|
|
// Currency code
|
|
model.updateElementValue(elementFa, EInvoiceNS.KSEF, "KodWaluty",
|
|
workitem.getItemValueString("invoice.currency"));
|
|
|
|
// ================================================================
|
|
// Delegate: line items, summary fields, foreign currency fields.
|
|
// The builder uses the CargoSoft VAT code per position to write
|
|
// each amount into the correct P_13_x / P_14_x / P_14_xW field.
|
|
// ================================================================
|
|
new KSeFInvoiceLineBuilder().build((EInvoiceModelKSeF) model, workitem);
|
|
|
|
// Due date - written at the end of the XML tree
|
|
model.setDueDateTime(workitem.getItemValueLocalDate("invoice.duedate"));
|
|
|
|
// Persist the modified template
|
|
fileDataXMLTemplate.setContent(model.getContent());
|
|
|
|
} catch (FileNotFoundException | EInvoiceFormatException | TransformerException e) {
|
|
throw new PluginException(this.getClass().getName(), DOCUMENT_ERROR, e.getMessage(), e);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Helper to resync the {@code invoice.performancedate} from the Cargosoft
|
|
* source XML if it is not yet set on the workitem.
|
|
*/
|
|
private void syncPerformanceDate(ItemCollection workitem) throws PluginException {
|
|
|
|
if (!workitem.hasItem("invoice.performancedate")) {
|
|
try {
|
|
logger.info("----Resync cargosoft performancedate....");
|
|
DocumentBuilder documentBuilder;
|
|
FileData cargoXML = snapshotService.getWorkItemFile(workitem.getUniqueID(),
|
|
workitem.getItemValueString("cargosoft.import.filename"));
|
|
if (cargoXML != null) {
|
|
InputStream inputStream = new ByteArrayInputStream(cargoXML.getContent());
|
|
InputSource inputSource = new InputSource(inputStream);
|
|
|
|
documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
|
Document doc = documentBuilder.parse(inputSource);
|
|
|
|
CargosoftXMLInvoiceImportService.readXMLValue(doc,
|
|
"/Invoices/Invoice/InvoiceHeader/PerformanceDate",
|
|
workitem, "invoice.performancedate",
|
|
Date.class);
|
|
|
|
// Fallback to invoice date if no performance date was found
|
|
if (workitem.getItemValueDate("invoice.performancedate") == null) {
|
|
workitem.setItemValue("invoice.performancedate", workitem.getItemValueDate("invoice.date"));
|
|
}
|
|
}
|
|
} catch (ParserConfigurationException | SAXException | IOException e) {
|
|
throw new PluginException(CargosoftXMLInvoiceImportService.class.getName(), "XML_ERROR",
|
|
e.getMessage());
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns {@code true} if at least one entry of {@code _childitems} does
|
|
* not yet have the item {@code cargosoft.vat.code} populated. This can
|
|
* happen for legacy workitems that were imported before the Cargosoft
|
|
* import was extended to capture the VAT code per row.
|
|
*/
|
|
private boolean isAnyChildMissingVatCode(ItemCollection workitem) {
|
|
List<ItemCollection> childItems = InvoiceUtil.explodeChildList(workitem, "_childitems");
|
|
if (childItems == null || childItems.isEmpty()) {
|
|
return false;
|
|
}
|
|
for (ItemCollection child : childItems) {
|
|
if (child.getItemValueString("cargosoft.vat.code").isBlank()) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Resync of the {@code cargosoft.vat.code} item on each child of
|
|
* {@code _childitems} from the original Cargosoft import XML.
|
|
* <p>
|
|
* Strategy: parse all {@code <InvoiceRow>} elements of the source XML in
|
|
* document order, skipping rows whose {@code BillingCode} is
|
|
* {@code "WÄHRUNG"} or {@code "KURS"} (special non-position rows). The
|
|
* remaining rows are paired with the {@code _childitems} entries by their
|
|
* one-based position number ({@code numpos}). Each child item without a
|
|
* VAT code receives the value extracted from its matching XML row.
|
|
* <p>
|
|
* Rows where the VAT code cannot be extracted are silently skipped here;
|
|
* the {@link com.alexanderlogistics.einvoice.KSeFInvoiceLineBuilder} will
|
|
* later fail with a {@link PluginException} for that specific position,
|
|
* which is the desired behaviour.
|
|
*/
|
|
private void syncCargosoftVatCodes(ItemCollection workitem) throws PluginException {
|
|
|
|
try {
|
|
logger.info("----Resync cargosoft.vat.code....");
|
|
|
|
FileData cargoXML = snapshotService.getWorkItemFile(workitem.getUniqueID(),
|
|
workitem.getItemValueString("cargosoft.import.filename"));
|
|
if (cargoXML == null) {
|
|
logger.warning("│ ├── ⚠️ Cargosoft source XML not found - cannot resync vat codes");
|
|
return;
|
|
}
|
|
|
|
InputStream inputStream = new ByteArrayInputStream(cargoXML.getContent());
|
|
InputSource inputSource = new InputSource(inputStream);
|
|
DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
|
Document doc = documentBuilder.parse(inputSource);
|
|
|
|
// Build a map: numpos (1-based position number) -> vatCode
|
|
// by iterating the InvoiceRow elements in document order, skipping
|
|
// the special rows for currency / exchange-rate metadata.
|
|
XPath xPath = XPathFactory.newInstance().newXPath();
|
|
XPathExpression billingCodeExpr = xPath.compile("BillingCode/Codes/Code");
|
|
XPathExpression vatCodeExpr = xPath.compile(
|
|
"InvoiceAmount/VATInformation/VAT/Codes/Code[@Type='cs']/text()");
|
|
|
|
Map<Integer, String> vatCodeByPos = new HashMap<>();
|
|
NodeList rowList = doc.getElementsByTagName("InvoiceRow");
|
|
int posCounter = 0;
|
|
for (int i = 0; i < rowList.getLength(); i++) {
|
|
Node rowNode = rowList.item(i);
|
|
if (rowNode.getNodeType() != Node.ELEMENT_NODE) {
|
|
continue;
|
|
}
|
|
String billingCode = (String) billingCodeExpr.evaluate(rowNode, XPathConstants.STRING);
|
|
if ("WÄHRUNG".equals(billingCode) || "KURS".equals(billingCode)) {
|
|
continue;
|
|
}
|
|
posCounter++;
|
|
|
|
String vatCode = (String) vatCodeExpr.evaluate(rowNode, XPathConstants.STRING);
|
|
if (vatCode != null && !vatCode.isBlank()) {
|
|
vatCodeByPos.put(posCounter, vatCode);
|
|
}
|
|
}
|
|
|
|
// Patch each child item that is still missing the vat code,
|
|
// matching by numpos. Re-implode the list at the end.
|
|
List<ItemCollection> childItems = InvoiceUtil.explodeChildList(workitem, "_childitems");
|
|
boolean changed = false;
|
|
for (ItemCollection child : childItems) {
|
|
if (!child.getItemValueString("cargosoft.vat.code").isBlank()) {
|
|
continue;
|
|
}
|
|
int numpos;
|
|
try {
|
|
numpos = Integer.parseInt(child.getItemValueString("numpos"));
|
|
} catch (NumberFormatException nfe) {
|
|
logger.warning("│ ├── ⚠️ child item without numpos - cannot resync vat code");
|
|
continue;
|
|
}
|
|
String vatCode = vatCodeByPos.get(numpos);
|
|
if (vatCode != null) {
|
|
child.setItemValue("cargosoft.vat.code", vatCode);
|
|
changed = true;
|
|
logger.info("│ ├── resynced numpos=" + numpos + " cargosoft.vat.code=" + vatCode);
|
|
} else {
|
|
logger.warning("│ ├── ⚠️ no matching InvoiceRow for numpos=" + numpos);
|
|
}
|
|
}
|
|
if (changed) {
|
|
InvoiceUtil.implodeChildList(workitem, childItems);
|
|
}
|
|
|
|
} catch (ParserConfigurationException | SAXException | IOException | XPathExpressionException e) {
|
|
throw new PluginException(CargosoftXMLInvoiceImportService.class.getName(), "XML_ERROR",
|
|
e.getMessage());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns {@code true} if the workitem represents a correction invoice.
|
|
*/
|
|
private boolean isKorrekturRechnung(ItemCollection workitem) {
|
|
return ("true".equals(workitem.getItemValueString("invoice.correction"))
|
|
&& !workitem.getItemValueString("invoice.CorrectionInvoiceNumber").isEmpty());
|
|
}
|
|
|
|
/**
|
|
* Builds a TradeParty (buyer/seller) from the business partner data.
|
|
* <p>
|
|
* If the business partner is missing the {@code partner.vat} item, a
|
|
* one-time migration step tries to read the VAT ID from the legacy
|
|
* {@code cargosoftkreditor} object.
|
|
*/
|
|
public TradeParty buildAddress(ItemCollection workitem, String type, EInvoiceModel model) throws PluginException {
|
|
|
|
String partnerID = workitem.getItemValueString("partner.id");
|
|
if (partnerID == null || partnerID.isEmpty()) {
|
|
throw new PluginException(this.getClass().getName(), DOCUMENT_ERROR, "Missing partnerID");
|
|
}
|
|
|
|
ItemCollection businessPartner = businessPartnerService.getBusinessPartnerByID(partnerID);
|
|
if (businessPartner == null) {
|
|
throw new PluginException(this.getClass().getName(), DOCUMENT_ERROR,
|
|
"Business Partner ID '" + partnerID + "' does not exist");
|
|
}
|
|
|
|
// Migration: resync partner.vat from legacy cargosoftkreditor object if missing
|
|
if (businessPartner.getItemValueString("partner.vat").isEmpty()) {
|
|
logger.info("│ ├── BusinessPartner " + partnerID + " does not provide vat-id - try to migrate....");
|
|
String dNumber = businessPartner.getItemValueString("dbtr.number");
|
|
if (!dNumber.isEmpty()) {
|
|
try {
|
|
String query = "(type:cargosoftkreditor) AND (name:" + dNumber + ")";
|
|
List<ItemCollection> result = documentService.find(query, 1, 0);
|
|
if (result != null && result.size() > 0) {
|
|
ItemCollection creditorData = result.get(0);
|
|
String vatID = creditorData.getItemValueString("_vendor_vat_registration_id");
|
|
logger.info("│ ├── synchronize VAT Registration ID: " + vatID);
|
|
businessPartner.setItemValue("partner.vat", vatID);
|
|
documentService.saveByNewTransaction(businessPartner);
|
|
}
|
|
} catch (Exception e) {
|
|
logger.info("│ ├── ⚠️ Failed to sync BusinessPartner : " + e.getMessage());
|
|
}
|
|
}
|
|
}
|
|
|
|
TradeParty tradeParty = new TradeParty(type);
|
|
tradeParty.setName(businessPartner.getItemValueString("partner.name"));
|
|
tradeParty.setCountryId(businessPartner.getItemValueString("partner.country"));
|
|
tradeParty.setCityName(businessPartner.getItemValueString("partner.city"));
|
|
tradeParty.setPostcodeCode(businessPartner.getItemValueString("partner.zip"));
|
|
tradeParty.setStreetAddress(businessPartner.getItemValueString("partner.address"));
|
|
|
|
if ("buyer".equals(type)) {
|
|
String partnerVAT = businessPartner.getItemValueString("partner.vat");
|
|
if (partnerVAT.isBlank()) {
|
|
logger.warning("│ ├── ⚠️ Business Partner ID '" + partnerID + "' does not contain a VAT ID !");
|
|
}
|
|
workitem.setItemValue("partner.vat", partnerVAT);
|
|
tradeParty.setVatNumber(partnerVAT);
|
|
|
|
// Update or create NrKlienta element directly under Podmiot2
|
|
Element podmiot2 = model.findOrCreateChildNode(model.getRoot(), EInvoiceNS.KSEF, "Podmiot2");
|
|
model.updateElementValue(podmiot2, EInvoiceNS.KSEF, "NrKlienta",
|
|
businessPartner.getItemValueString("dbtr.number"));
|
|
}
|
|
|
|
return tradeParty;
|
|
}
|
|
|
|
/**
|
|
* Loads the e-invoice XML template referenced by the configuration.
|
|
*/
|
|
private FileData loadXMLTemplate(ItemCollection workitem, ItemCollection config)
|
|
throws PluginException {
|
|
|
|
String textblock = config.getItemValueString("textblock");
|
|
String template = config.getItemValueString("template");
|
|
String sourceName = config.getItemValueString("source");
|
|
|
|
try {
|
|
debug = Boolean.parseBoolean(config.getItemValueString("debug"));
|
|
} catch (Exception e) {
|
|
// ignore - debug remains false
|
|
}
|
|
String targetName = "ksef.xml";
|
|
|
|
sourceName = workflowService.adaptText(sourceName, workitem);
|
|
|
|
if ((template == null || template.isEmpty()) || (textblock == null || textblock.isEmpty())) {
|
|
throw new PluginException(EInvoiceAdapter.class.getSimpleName(),
|
|
CONFIG_ERROR,
|
|
"invalid e-invoice configuration in model event - textblock/template reference not defined!");
|
|
}
|
|
|
|
FileData fileData = loadTextBlockFileData(textblock, template);
|
|
|
|
if (fileData == null) {
|
|
throw new PluginException(EInvoiceAdapter.class.getSimpleName(),
|
|
CONFIG_ERROR,
|
|
"invalid e-invoice configuration in model event - textblock/template: " + textblock + "/" + template
|
|
+ " not found!");
|
|
}
|
|
fileData.setName(targetName);
|
|
|
|
return fileData;
|
|
}
|
|
|
|
/**
|
|
* Returns a text-block FileData by name and filename.
|
|
*/
|
|
public FileData loadTextBlockFileData(String name, String fileName) {
|
|
ItemCollection textBlockItemCollection = null;
|
|
|
|
String sQuery = "(type:\"" + TYPE_TEXTBLOCK + "\" AND txtname:\"" + name + "\")";
|
|
Collection<ItemCollection> col;
|
|
try {
|
|
col = documentService.find(sQuery, 1, 0);
|
|
if (col.size() > 0) {
|
|
textBlockItemCollection = col.iterator().next();
|
|
return snapshotService.getWorkItemFile(textBlockItemCollection.getUniqueID(), fileName);
|
|
} else {
|
|
logger.warning("Missing text-block : '" + name + "'");
|
|
}
|
|
} catch (QueryException e) {
|
|
logger.warning("getTextBlock - invalid query: " + e.getMessage());
|
|
}
|
|
|
|
return null;
|
|
}
|
|
} |