From cec9e7700ee3b996edb174dae3db87d43c4ec54a Mon Sep 17 00:00:00 2001 From: HorstOeko Date: Wed, 16 Aug 2023 16:24:25 +0200 Subject: [PATCH 1/3] #14 Introducing the ZugferdDocumentPdfMerger --- src/ZugferdDocumentAbstractPdfBuilder.php | 287 ++++++++++++++++++++++ src/ZugferdDocumentPdfBuilder.php | 222 +---------------- src/ZugferdDocumentPdfMerger.php | 172 +++++++++++++ 3 files changed, 472 insertions(+), 209 deletions(-) create mode 100644 src/ZugferdDocumentAbstractPdfBuilder.php create mode 100644 src/ZugferdDocumentPdfMerger.php diff --git a/src/ZugferdDocumentAbstractPdfBuilder.php b/src/ZugferdDocumentAbstractPdfBuilder.php new file mode 100644 index 00000000..530ea561 --- /dev/null +++ b/src/ZugferdDocumentAbstractPdfBuilder.php @@ -0,0 +1,287 @@ + + * @license https://opensource.org/licenses/MIT MIT + * @link https://github.com/horstoeko/zugferd + */ +abstract class ZugferdDocumentAbstractPdfBuilder +{ + /** + * Instance of the pdfwriter + * + * @var ZugferdPdfWriter + */ + private $pdfWriter = null; + + /** + * Contains the data of the original PDF documjent + * + * @var string + */ + private $pdfData = ""; + + /** + * Constructor + * + * @param ZugferdDocumentBuilder $documentBuiler + * The instance of the document builder. Needed to get the XML data + * @param string $pdfData + * The full filename or a string containing the binary pdf data. This + * is the original PDF (e.g. created by a ERP system) + */ + public function __construct(string $pdfData) + { + $this->pdfData = $pdfData; + $this->pdfWriter = new ZugferdPdfWriter(); + } + + /** + * Generates the final document + * + * @return ZugferdDocumentAbstractPdfBuilder + */ + public function generateDocument(): ZugferdDocumentAbstractPdfBuilder + { + $this->startCreatePdf(); + + return $this; + } + + /** + * Saves the document generated with generateDocument to a file + * + * @param string $toFilename + * The full qualified filename to which the generated PDF (with attachment) + * is stored + * @return ZugferdDocumentAbstractPdfBuilder + */ + public function saveDocument(string $toFilename): ZugferdDocumentAbstractPdfBuilder + { + $this->pdfWriter->Output($toFilename, 'F'); + + return $this; + } + + /** + * Get the content of XML to attach + * + * @return string + */ + protected abstract function getXmlContent(): string; + + /** + * Get the filename of the XML to attach + * + * @return string + */ + protected abstract function getXmlAttachmentFilename(): string; + + /** + * Get the XMP name for the XML to attach + * + * @return string + */ + protected abstract function getXmlAttachmentXmpName(): string; + + /** + * Internal function which sets up the PDF + * + * @return void + */ + private function startCreatePdf(): void + { + // Get PDF data + + $pdfDataRef = null; + + if ($this->pdfDataIsFile($this->pdfData)) { + $pdfDataRef = $this->pdfData; + } elseif (is_string($this->pdfData)) { + $pdfDataRef = PdfStreamReader::createByString($this->pdfData); + } + + // Get XML data from Builder + + $documentBuilderXmlDataRef = PdfStreamReader::createByString($this->getXmlContent()); + + // Start + + $this->pdfWriter->attach( + $documentBuilderXmlDataRef, + $this->getXmlAttachmentFilename(), + 'Factur-X Invoice', + 'Data', + 'text#2Fxml' + ); + + $this->pdfWriter->openAttachmentPane(); + + // Copy pages from the original PDF + + $pageCount = $this->pdfWriter->setSourceFile($pdfDataRef); + + for ($pageNumber = 1; $pageNumber <= $pageCount; ++$pageNumber) { + $pageContent = $this->pdfWriter->importPage($pageNumber, '/MediaBox'); + $this->pdfWriter->AddPage(); + $this->pdfWriter->useTemplate($pageContent, 0, 0, null, null, true); + } + + // Set PDF version 1.7 according to PDF/A-3 ISO 32000-1 + + $this->pdfWriter->setPdfVersion('1.7', true); + + // Update meta data (e.g. such as author, producer, title) + + $this->updatePdfMetadata(); + } + + /** + * Update PDF metadata to according to FacturX/ZUGFeRD XML data. + * + * @return void + */ + private function updatePdfMetadata(): void + { + $pdfMetadataInfos = $this->preparePdfMetadata(); + $this->pdfWriter->setPdfMetadataInfos($pdfMetadataInfos); + + $xmp = simplexml_load_file(PathUtils::combinePathWithFile(ZugferdSettings::getAssetDirectory(), 'facturx_extension_schema.xmp')); + $descriptionNodes = $xmp->xpath('rdf:Description'); + + $descFx = $descriptionNodes[0]; + $descFx->children('fx', true)->{'ConformanceLevel'} = strtoupper($this->getXmlAttachmentXmpName()); + $this->pdfWriter->addMetadataDescriptionNode($descFx->asXML()); + + $this->pdfWriter->addMetadataDescriptionNode($descriptionNodes[1]->asXML()); + + $descPdfAid = $descriptionNodes[2]; + $this->pdfWriter->addMetadataDescriptionNode($descPdfAid->asXML()); + + $descDc = $descriptionNodes[3]; + $descNodes = $descDc->children('dc', true); + $descNodes->title->children('rdf', true)->Alt->li = $pdfMetadataInfos['title']; + $descNodes->creator->children('rdf', true)->Seq->li = $pdfMetadataInfos['author']; + $descNodes->description->children('rdf', true)->Alt->li = $pdfMetadataInfos['subject']; + $this->pdfWriter->addMetadataDescriptionNode($descDc->asXML()); + + $descAdobe = $descriptionNodes[4]; + $descAdobe->children('pdf', true)->{'Producer'} = 'FPDF'; + $this->pdfWriter->addMetadataDescriptionNode($descAdobe->asXML()); + + $descXmp = $descriptionNodes[5]; + $xmpNodes = $descXmp->children('xmp', true); + $xmpNodes->{'CreatorTool'} = sprintf('Factur-X PHP library v%s by HorstOeko', ZugferdPackageVersion::getInstalledVersion()); + $xmpNodes->{'CreateDate'} = $pdfMetadataInfos['createdDate']; + $xmpNodes->{'ModifyDate'} = $pdfMetadataInfos['modifiedDate']; + $this->pdfWriter->addMetadataDescriptionNode($descXmp->asXML()); + } + + /** + * Prepare PDF Metadata informations from FacturX/ZUGFeRD XML. + * + * @return array + */ + private function preparePdfMetadata(): array + { + $invoiceInformations = $this->extractInvoiceInformations(); + + $dateString = date('Y-m-d', strtotime($invoiceInformations['date'])); + $title = sprintf('%s : %s %s', $invoiceInformations['seller'], $invoiceInformations['docTypeName'], $invoiceInformations['invoiceId']); + $subject = sprintf('FacturX/ZUGFeRD %s %s dated %s issued by %s', $invoiceInformations['docTypeName'], $invoiceInformations['invoiceId'], $dateString, $invoiceInformations['seller']); + + $pdfMetadata = array( + 'author' => $invoiceInformations['seller'], + 'keywords' => sprintf('%s, FacturX/ZUGFeRD', $invoiceInformations['docTypeName']), + 'title' => $title, + 'subject' => $subject, + 'createdDate' => $invoiceInformations['date'], + 'modifiedDate' => date('Y-m-d\TH:i:s') . '+00:00', + ); + + return $pdfMetadata; + } + + /** + * Extract major invoice information from FacturX/ZUGFeRD XML. + * + * @return array + */ + protected function extractInvoiceInformations(): array + { + $domDocument = new DOMDocument(); + $domDocument->loadXML($this->getXmlContent()); + + $xpath = new DOMXPath($domDocument); + + $dateXpath = $xpath->query('//rsm:ExchangedDocument/ram:IssueDateTime/udt:DateTimeString'); + $date = $dateXpath->item(0)->nodeValue; + $dateReformatted = date('Y-m-d\TH:i:s', strtotime($date)) . '+00:00'; + + $invoiceIdXpath = $xpath->query('//rsm:ExchangedDocument/ram:ID'); + $invoiceId = $invoiceIdXpath->item(0)->nodeValue; + + $sellerXpath = $xpath->query('//ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:Name'); + $sellerName = $sellerXpath->item(0)->nodeValue; + + $docTypeXpath = $xpath->query('//rsm:ExchangedDocument/ram:TypeCode'); + $docTypeCode = $docTypeXpath->item(0)->nodeValue; + + switch ($docTypeCode) { + case ZugferdInvoiceType::CREDITNOTE: + $docTypeName = 'Credit Note'; + break; + default: + $docTypeName = 'Invoice'; + break; + } + + $invoiceInformation = array( + 'invoiceId' => $invoiceId, + 'docTypeName' => $docTypeName, + 'seller' => $sellerName, + 'date' => $dateReformatted, + ); + + return $invoiceInformation; + } + + /** + * Returns true if the submittet parameter $pdfData is a valid file. + * Otherwise it will return false + * + * @param string $pdfData + * @return boolean + */ + private function pdfDataIsFile($pdfData): bool + { + try { + return @is_file($pdfData); + } catch (\TypeError $ex) { + return false; + } + } +} \ No newline at end of file diff --git a/src/ZugferdDocumentPdfBuilder.php b/src/ZugferdDocumentPdfBuilder.php index 2f1945d2..a9049c77 100644 --- a/src/ZugferdDocumentPdfBuilder.php +++ b/src/ZugferdDocumentPdfBuilder.php @@ -9,12 +9,8 @@ namespace horstoeko\zugferd; -use \horstoeko\zugferd\codelists\ZugferdInvoiceType; -use \horstoeko\zugferd\ZugferdPackageVersion; -use \horstoeko\zugferd\ZugferdPdfWriter; -use \setasign\Fpdi\PdfParser\StreamReader as PdfStreamReader; -use \horstoeko\stringmanagement\PathUtils; -use \horstoeko\zugferd\ZugferdSettings; +use horstoeko\zugferd\ZugferdDocumentAbstractPdfBuilder; +use horstoeko\zugferd\ZugferdDocumentBuilder; /** * Class representing the facillity adding XML data from ZugferdDocumentBuilder @@ -26,7 +22,7 @@ * @license https://opensource.org/licenses/MIT MIT * @link https://github.com/horstoeko/zugferd */ -class ZugferdDocumentPdfBuilder +class ZugferdDocumentPdfBuilder extends ZugferdDocumentAbstractPdfBuilder { /** * Internal reference to the xml builder instance @@ -35,20 +31,6 @@ class ZugferdDocumentPdfBuilder */ private $documentBuiler = null; - /** - * Instance of the pdfwriter - * - * @var ZugferdPdfWriter - */ - private $pdfWriter = null; - - /** - * Contains the data of the original PDF documjent - * - * @var string - */ - private $pdfData = ""; - /** * Constructor * @@ -61,209 +43,31 @@ class ZugferdDocumentPdfBuilder public function __construct(ZugferdDocumentBuilder $documentBuiler, string $pdfData) { $this->documentBuiler = $documentBuiler; - $this->pdfData = $pdfData; - $this->pdfWriter = new ZugferdPdfWriter(); - } - /** - * Generates the final document - * - * @return ZugferdDocumentPdfBuilder - */ - public function generateDocument(): ZugferdDocumentPdfBuilder - { - $this->startCreatePdf(); - - return $this; + parent::__construct($pdfData); } /** - * Saves the document generated with generateDocument to a file - * - * @param string $toFilename - * The full qualified filename to which the generated PDF (with attachment) - * is stored - * @return ZugferdDocumentPdfBuilder + * @inheritDoc */ - public function saveDocument(string $toFilename): ZugferdDocumentPdfBuilder + protected function getXmlContent(): string { - $this->pdfWriter->Output($toFilename, 'F'); - - return $this; + return $this->documentBuiler->getContentAsDomDocument()->saveXML(); } /** - * Internal function which sets up the PDF - * - * @return void + * @inheritDoc */ - private function startCreatePdf(): void + protected function getXmlAttachmentFilename(): string { - // Get PDF data - - $pdfDataRef = null; - - if ($this->pdfDataIsFile($this->pdfData)) { - $pdfDataRef = $this->pdfData; - } elseif (is_string($this->pdfData)) { - $pdfDataRef = PdfStreamReader::createByString($this->pdfData); - } - - // Get XML data from Builder - - $documentBuilderXmlDataRef = PdfStreamReader::createByString($this->documentBuiler->getContentAsDomDocument()->saveXML()); - - // Start - - $this->pdfWriter->attach( - $documentBuilderXmlDataRef, - $this->documentBuiler->getProfileDefinition()['attachmentfilename'], - 'Factur-X Invoice', - 'Data', - 'text#2Fxml' - ); - - $this->pdfWriter->openAttachmentPane(); - - // Copy pages from the original PDF - - $pageCount = $this->pdfWriter->setSourceFile($pdfDataRef); - - for ($pageNumber = 1; $pageNumber <= $pageCount; ++$pageNumber) { - $pageContent = $this->pdfWriter->importPage($pageNumber, '/MediaBox'); - $this->pdfWriter->AddPage(); - $this->pdfWriter->useTemplate($pageContent, 0, 0, null, null, true); - } - - // Set PDF version 1.7 according to PDF/A-3 ISO 32000-1 - - $this->pdfWriter->setPdfVersion('1.7', true); - - // Update meta data (e.g. such as author, producer, title) - - $this->updatePdfMetadata(); + return $this->documentBuiler->getProfileDefinition()['attachmentfilename']; } /** - * Update PDF metadata to according to FacturX/ZUGFeRD XML data. - * - * @return void - */ - private function updatePdfMetadata(): void - { - $pdfMetadataInfos = $this->preparePdfMetadata(); - $this->pdfWriter->setPdfMetadataInfos($pdfMetadataInfos); - - $xmp = simplexml_load_file(PathUtils::combinePathWithFile(ZugferdSettings::getAssetDirectory(), 'facturx_extension_schema.xmp')); - $descriptionNodes = $xmp->xpath('rdf:Description'); - - $descFx = $descriptionNodes[0]; - $descFx->children('fx', true)->{'ConformanceLevel'} = strtoupper($this->documentBuiler->getProfileDefinition()["xmpname"]); - $this->pdfWriter->addMetadataDescriptionNode($descFx->asXML()); - - $this->pdfWriter->addMetadataDescriptionNode($descriptionNodes[1]->asXML()); - - $descPdfAid = $descriptionNodes[2]; - $this->pdfWriter->addMetadataDescriptionNode($descPdfAid->asXML()); - - $descDc = $descriptionNodes[3]; - $descNodes = $descDc->children('dc', true); - $descNodes->title->children('rdf', true)->Alt->li = $pdfMetadataInfos['title']; - $descNodes->creator->children('rdf', true)->Seq->li = $pdfMetadataInfos['author']; - $descNodes->description->children('rdf', true)->Alt->li = $pdfMetadataInfos['subject']; - $this->pdfWriter->addMetadataDescriptionNode($descDc->asXML()); - - $descAdobe = $descriptionNodes[4]; - $descAdobe->children('pdf', true)->{'Producer'} = 'FPDF'; - $this->pdfWriter->addMetadataDescriptionNode($descAdobe->asXML()); - - $descXmp = $descriptionNodes[5]; - $xmpNodes = $descXmp->children('xmp', true); - $xmpNodes->{'CreatorTool'} = sprintf('Factur-X PHP library v%s by HorstOeko', ZugferdPackageVersion::getInstalledVersion()); - $xmpNodes->{'CreateDate'} = $pdfMetadataInfos['createdDate']; - $xmpNodes->{'ModifyDate'} = $pdfMetadataInfos['modifiedDate']; - $this->pdfWriter->addMetadataDescriptionNode($descXmp->asXML()); - } - - /** - * Prepare PDF Metadata informations from FacturX/ZUGFeRD XML. - * - * @return array - */ - private function preparePdfMetadata(): array - { - $invoiceInformations = $this->extractInvoiceInformations(); - - $dateString = date('Y-m-d', strtotime($invoiceInformations['date'])); - $title = sprintf('%s : %s %s', $invoiceInformations['seller'], $invoiceInformations['docTypeName'], $invoiceInformations['invoiceId']); - $subject = sprintf('FacturX/ZUGFeRD %s %s dated %s issued by %s', $invoiceInformations['docTypeName'], $invoiceInformations['invoiceId'], $dateString, $invoiceInformations['seller']); - - $pdfMetadata = array( - 'author' => $invoiceInformations['seller'], - 'keywords' => sprintf('%s, FacturX/ZUGFeRD', $invoiceInformations['docTypeName']), - 'title' => $title, - 'subject' => $subject, - 'createdDate' => $invoiceInformations['date'], - 'modifiedDate' => date('Y-m-d\TH:i:s') . '+00:00', - ); - - return $pdfMetadata; - } - - /** - * Extract major invoice information from FacturX/ZUGFeRD XML. - * - * @return array - */ - protected function extractInvoiceInformations(): array - { - $xpath = $this->documentBuiler->getContentAsDomXPath(); - - $dateXpath = $xpath->query('//rsm:ExchangedDocument/ram:IssueDateTime/udt:DateTimeString'); - $date = $dateXpath->item(0)->nodeValue; - $dateReformatted = date('Y-m-d\TH:i:s', strtotime($date)) . '+00:00'; - - $invoiceIdXpath = $xpath->query('//rsm:ExchangedDocument/ram:ID'); - $invoiceId = $invoiceIdXpath->item(0)->nodeValue; - - $sellerXpath = $xpath->query('//ram:ApplicableHeaderTradeAgreement/ram:SellerTradeParty/ram:Name'); - $sellerName = $sellerXpath->item(0)->nodeValue; - - $docTypeXpath = $xpath->query('//rsm:ExchangedDocument/ram:TypeCode'); - $docTypeCode = $docTypeXpath->item(0)->nodeValue; - - switch ($docTypeCode) { - case ZugferdInvoiceType::CREDITNOTE: - $docTypeName = 'Credit Note'; - break; - default: - $docTypeName = 'Invoice'; - break; - } - - $invoiceInformation = array( - 'invoiceId' => $invoiceId, - 'docTypeName' => $docTypeName, - 'seller' => $sellerName, - 'date' => $dateReformatted, - ); - - return $invoiceInformation; - } - - /** - * Returns true if the submittet parameter $pdfData is a valid file. - * Otherwise it will return false - * - * @param string $pdfData - * @return boolean + * @inheritDoc */ - private function pdfDataIsFile($pdfData): bool + protected function getXmlAttachmentXmpName(): string { - try { - return @is_file($pdfData); - } catch (\TypeError $ex) { - return false; - } + return $this->documentBuiler->getProfileDefinition()["xmpname"]; } } diff --git a/src/ZugferdDocumentPdfMerger.php b/src/ZugferdDocumentPdfMerger.php new file mode 100644 index 00000000..02fc6abe --- /dev/null +++ b/src/ZugferdDocumentPdfMerger.php @@ -0,0 +1,172 @@ + + * @license https://opensource.org/licenses/MIT MIT + * @link https://github.com/horstoeko/zugferd + */ +class ZugferdDocumentPdfMerger extends ZugferdDocumentAbstractPdfBuilder +{ + /** + * Internal reference to the xml data (file or data-string) + * + * @var string + */ + private $xmlDataOrFilename = ""; + + /** + * Cached XML data + * + * @var string + */ + private $xmlDataCache = ""; + + /** + * Flag that indicated (if true) the data are always reloaded + * + * @var boolean + */ + private $xmlDataCacheDisabled = false; + + /** + * Constructor + * + * @param string $xmlDataOrFilename + * The XML data as a string or the full qualified path to an XML-File + * containing the XML-data + * @param string $pdfData + * The full filename or a string containing the binary pdf data. This + * is the original PDF (e.g. created by a ERP system) + */ + public function __construct(string $xmlDataOrFilename, string $pdfData) + { + $this->xmlDataOrFilename = $xmlDataOrFilename; + + parent::__construct($pdfData); + } + + /** + * Enable the XML cache + * + * @return ZugferdDocumentPdfMerger + */ + public function enableXmlDataCache(): ZugferdDocumentPdfMerger + { + $this->xmlDataCacheDisabled = false; + + return $this; + } + + /** + * Disable the XML cache + * + * @return ZugferdDocumentPdfMerger + */ + public function disableXmlDataCache(): ZugferdDocumentPdfMerger + { + $this->xmlDataCacheDisabled = true; + + return $this; + } + + /** + * @inheritDoc + */ + protected function getXmlContent(): string + { + if ($this->xmlDataCache && ($this->xmlDataCacheDisabled !== true)) { + return $this->xmlDataCache; + } + + if ($this->xmlDataIsFile()) { + $xmlContent = file_get_contents($this->xmlDataOrFilename); + if ($xmlContent === false) { + throw new Exception('Could read XML file...'); + } + } else { + $xmlContent = $this->xmlDataOrFilename; + } + + $this->xmlDataCache = $xmlContent; + + return $xmlContent; + } + + /** + * @inheritDoc + */ + protected function getXmlAttachmentFilename(): string + { + return $this->getProfileDefinition()['attachmentfilename']; + } + + /** + * @inheritDoc + */ + protected function getXmlAttachmentXmpName(): string + { + return $this->getProfileDefinition()["xmpname"]; + } + + /** + * Returns true if the submitted $xmlDataOrFilename is a valid file. + * Otherwise it will return false + * + * @return boolean + */ + private function xmlDataIsFile(): bool + { + try { + return @is_file($this->xmlDataOrFilename); + } catch (\TypeError $ex) { + return false; + } + } + + /** + * Guess the profile type of the readden xml document + * + * @codeCoverageIgnore + * + * @return array + * @throws Exception + */ + private function getProfileDefinition(): array + { + $xmlContent = $this->getXmlContent(); + + $xmldocument = new SimpleXMLElement($xmlContent); + $typeelement = $xmldocument->xpath('/rsm:CrossIndustryInvoice/rsm:ExchangedDocumentContext/ram:GuidelineSpecifiedDocumentContextParameter/ram:ID'); + + if (!is_array($typeelement) || !isset($typeelement[0])) { + throw new Exception('Coult not determaine the profile...'); + } + + foreach (ZugferdProfiles::PROFILEDEF as $profile => $profiledef) { + if ($typeelement[0] == $profiledef["contextparameter"]) { + return $profiledef; + } + } + + throw new Exception('Could not determine the profile...'); + } +} From 75e7ff61aa92b6cccfb9583c26f3b7bec41993d9 Mon Sep 17 00:00:00 2001 From: HorstOeko Date: Wed, 16 Aug 2023 16:29:29 +0200 Subject: [PATCH 2/3] #14 Final ZugferdDocumentPdfMerger --- src/ZugferdDocumentAbstractPdfBuilder.php | 11 +++++++++++ src/ZugferdDocumentPdfBuilder.php | 11 ----------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/ZugferdDocumentAbstractPdfBuilder.php b/src/ZugferdDocumentAbstractPdfBuilder.php index 530ea561..108a3342 100644 --- a/src/ZugferdDocumentAbstractPdfBuilder.php +++ b/src/ZugferdDocumentAbstractPdfBuilder.php @@ -86,6 +86,17 @@ public function saveDocument(string $toFilename): ZugferdDocumentAbstractPdfBuil return $this; } + /** + * Returns the PDF as a string + * + * @param string $toFilename + * @return string + */ + public function downloadString(string $toFilename): string + { + return $this->pdfWriter->Output($toFilename, 'S'); + } + /** * Get the content of XML to attach * diff --git a/src/ZugferdDocumentPdfBuilder.php b/src/ZugferdDocumentPdfBuilder.php index 303536a9..a9049c77 100644 --- a/src/ZugferdDocumentPdfBuilder.php +++ b/src/ZugferdDocumentPdfBuilder.php @@ -54,17 +54,6 @@ protected function getXmlContent(): string { return $this->documentBuiler->getContentAsDomDocument()->saveXML(); } - - /** - * Returns the PDF as a string - * - * @param string $toFilename - * @return string - */ - public function downloadString(string $toFilename): string - { - return $this->pdfWriter->Output($toFilename, 'S'); - } /** * @inheritDoc From a0eaa90386072e68eda6bea7dff1ace580dce6b7 Mon Sep 17 00:00:00 2001 From: HorstOeko Date: Wed, 16 Aug 2023 16:37:49 +0200 Subject: [PATCH 3/3] #14 Added Example for ZugferdDocumentPdfMerger (En16931PdfMerger) --- examples/En16931PdfMerger.php | 9 ++ examples/invoice_1.xml | 175 ++++++++++++++++++++++++++++++++++ 2 files changed, 184 insertions(+) create mode 100644 examples/En16931PdfMerger.php create mode 100644 examples/invoice_1.xml diff --git a/examples/En16931PdfMerger.php b/examples/En16931PdfMerger.php new file mode 100644 index 00000000..588aa115 --- /dev/null +++ b/examples/En16931PdfMerger.php @@ -0,0 +1,9 @@ +generateDocument(); +$pdfMerger->saveDocument(dirname(__FILE__) . "/fullpdf.pdf"); diff --git a/examples/invoice_1.xml b/examples/invoice_1.xml new file mode 100644 index 00000000..4f634e3a --- /dev/null +++ b/examples/invoice_1.xml @@ -0,0 +1,175 @@ + + + + + urn:cen.eu:en16931:2017 + + + + 471102 + 380 + + 20180305 + + + Rechnung gemäß Bestellung vom 01.03.2018. + + + Lieferant GmbH + Lieferantenstraße 20 + 80333 München + Deutschland + Geschäftsführer: Hans Muster + Handelsregisternummer: H A 123 + + REG + + + + + + 1 + + + 4012345001235 + TB100A4 + Trennblätter A4 + + + + 9.90 + + + 9.90 + + + + 20.00 + + + + VAT + S + 19.00 + + + 198.00 + + + + + + 2 + + + 4000050986428 + ARNR2 + Joghurt Banane + + + + 5.50 + + + 5.50 + + + + 50.00 + + + + VAT + S + 7.00 + + + 275.00 + + + + + 34676-342323 + + 549910 + 4000001123452 + Lieferant GmbH + + Heinz Mükker + Buchhaltung + + +49-111-2222222 + + + info@lieferant.de + + + + 80333 + Lieferantenstraße 20 + München + DE + + + 201/113/40209 + + + DE123456789 + + + + GE2020211 + Kunden AG Mitte + + 69876 + Kundenstraße 15 + Frankfurt + DE + + + + + + + 20180305 + + + + + EUR + + 58 + + DE12500105170648489890 + + + + 19.25 + VAT + 275.00 + S + 7.00 + + + 37.62 + VAT + 198.00 + S + 19.00 + + + Zahlbar innerhalb 30 Tagen netto bis 04.04.2018, 3% Skonto innerhalb 10 Tagen bis 15.03.2018 + + + 473.00 + 0.00 + 0.00 + 473.00 + 56.87 + 529.87 + 0.00 + 529.87 + + + +