mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-02 13:45:10 -05:00
Just messing around
This commit is contained in:
parent
452ea2ccf9
commit
01706dd391
@ -32,7 +32,7 @@ repos:
|
||||
rev: v2.3.0
|
||||
hooks:
|
||||
- id: codespell
|
||||
exclude: "(^src-ui/src/locale/)|(^src-ui/e2e/)|(^src/paperless_mail/tests/samples/)"
|
||||
exclude: "(^src-ui/src/locale/)|(^src-ui/e2e/)|(^src/paperless_mail/tests/samples/)|(^src/paperless_einvoice/tests/samples/)|(^src/paperless_einvoice/templates/)"
|
||||
exclude_types:
|
||||
- pofile
|
||||
- json
|
||||
|
1
Pipfile
1
Pipfile
@ -20,6 +20,7 @@ django-multiselectfield = "*"
|
||||
django-soft-delete = "*"
|
||||
djangorestframework = "~=3.15.2"
|
||||
djangorestframework-guardian = "*"
|
||||
drafthorse = "*"
|
||||
drf-writable-nested = "*"
|
||||
bleach = "*"
|
||||
celery = {extras = ["redis"], version = "*"}
|
||||
|
18
Pipfile.lock
generated
18
Pipfile.lock
generated
@ -1,7 +1,7 @@
|
||||
{
|
||||
"_meta": {
|
||||
"hash": {
|
||||
"sha256": "148cd379b8ceeb857ea817bea1432821d8ea20ffe8d0bfc04c89871a87b87b0f"
|
||||
"sha256": "bf51fa211450fbf310e070739f225429fd7947eb72ba2a48b6bc92a1cd4cb51e"
|
||||
},
|
||||
"pipfile-spec": 6,
|
||||
"requires": {},
|
||||
@ -629,6 +629,14 @@
|
||||
"index": "pypi",
|
||||
"version": "==0.3.0"
|
||||
},
|
||||
"drafthorse": {
|
||||
"hashes": [
|
||||
"sha256:4d16a6dd60708676465e63ac7ff1b5f140e8c1c58be7d0eda66bc309814fc5c5",
|
||||
"sha256:e67d9f21bbada2282e5f63257c01cc56f8cb2667000f67e68bbddf6956484375"
|
||||
],
|
||||
"index": "pypi",
|
||||
"version": "==2.4.0"
|
||||
},
|
||||
"drf-writable-nested": {
|
||||
"hashes": [
|
||||
"sha256:d8ddc606dc349e56373810842965712a5789e6a5ca7704729d15429b95f8f2ee"
|
||||
@ -1668,6 +1676,14 @@
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==2.9.0"
|
||||
},
|
||||
"pypdf": {
|
||||
"hashes": [
|
||||
"sha256:3bd4f503f4ebc58bae40d81e81a9176c400cbbac2ba2d877367595fb524dfdfc",
|
||||
"sha256:425a129abb1614183fd1aca6982f650b47f8026867c0ce7c4b9f281c443d2740"
|
||||
],
|
||||
"markers": "python_version >= '3.8'",
|
||||
"version": "==5.1.0"
|
||||
},
|
||||
"python-dateutil": {
|
||||
"hashes": [
|
||||
"sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3",
|
||||
|
@ -1089,6 +1089,10 @@ TIKA_GOTENBERG_ENDPOINT = os.getenv(
|
||||
if TIKA_ENABLED:
|
||||
INSTALLED_APPS.append("paperless_tika.apps.PaperlessTikaConfig")
|
||||
|
||||
EINVOICE_PARSER_ENABLED = __get_boolean("PAPERLESS_EINVOICE_PARSER_ENABLED", "NO")
|
||||
if EINVOICE_PARSER_ENABLED and TIKA_ENABLED:
|
||||
INSTALLED_APPS.append("paperless_einvoice.apps.PaperlessEInvoiceConfig")
|
||||
|
||||
AUDIT_LOG_ENABLED = __get_boolean("PAPERLESS_AUDIT_LOG_ENABLED", "true")
|
||||
if AUDIT_LOG_ENABLED:
|
||||
INSTALLED_APPS.append("auditlog")
|
||||
|
0
src/paperless_einvoice/__init__.py
Normal file
0
src/paperless_einvoice/__init__.py
Normal file
15
src/paperless_einvoice/apps.py
Normal file
15
src/paperless_einvoice/apps.py
Normal file
@ -0,0 +1,15 @@
|
||||
from django.apps import AppConfig
|
||||
from django.conf import settings
|
||||
|
||||
from paperless_einvoice.signals import einvoice_consumer_declaration
|
||||
|
||||
|
||||
class PaperlessEInvoiceConfig(AppConfig):
|
||||
name = "paperless_einvoice"
|
||||
|
||||
def ready(self):
|
||||
from documents.signals import document_consumer_declaration
|
||||
|
||||
if settings.TIKA_ENABLED and settings.EINVOICE_PARSER_ENABLED:
|
||||
document_consumer_declaration.connect(einvoice_consumer_declaration)
|
||||
AppConfig.ready(self)
|
86
src/paperless_einvoice/parsers.py
Normal file
86
src/paperless_einvoice/parsers.py
Normal file
@ -0,0 +1,86 @@
|
||||
from pathlib import Path
|
||||
|
||||
from django.conf import settings
|
||||
from drafthorse.models.document import Document
|
||||
from gotenberg_client import GotenbergClient
|
||||
from gotenberg_client.options import MarginType
|
||||
from gotenberg_client.options import MarginUnitType
|
||||
from gotenberg_client.options import PageMarginsType
|
||||
from gotenberg_client.options import PageSize
|
||||
from gotenberg_client.options import PdfAFormat
|
||||
from jinja2 import Template
|
||||
|
||||
from documents.parsers import ParseError
|
||||
from paperless.models import OutputTypeChoices
|
||||
from paperless_tika.parsers import TikaDocumentParser
|
||||
|
||||
|
||||
class EInvoiceDocumentParser(TikaDocumentParser):
|
||||
"""
|
||||
This parser parses e-invoices using Tika and Gotenberg
|
||||
"""
|
||||
|
||||
logging_name = "paperless.parsing.einvoice"
|
||||
|
||||
def convert_to_pdf(self, document_path: Path, file_name):
|
||||
pdf_path = Path(self.tempdir) / "convert.pdf"
|
||||
self.log.info(f"Converting {document_path} to PDF as {pdf_path}")
|
||||
|
||||
with document_path.open("r") as f:
|
||||
xml = f.read().encode("utf-8")
|
||||
invoice = Document.parse(xml)
|
||||
context = {
|
||||
"id": invoice.trade.agreement.seller.name,
|
||||
}
|
||||
template = Template("templates/invoice.j2.html")
|
||||
html_file = Path(self.tempdir) / "invoice_as_html.html"
|
||||
html_file.write_text(
|
||||
template.render(context),
|
||||
)
|
||||
|
||||
with (
|
||||
GotenbergClient(
|
||||
host=settings.TIKA_GOTENBERG_ENDPOINT,
|
||||
timeout=settings.CELERY_TASK_TIME_LIMIT,
|
||||
) as client,
|
||||
client.chromium.html_to_pdf() as route,
|
||||
):
|
||||
# Set the output format of the resulting PDF
|
||||
if settings.OCR_OUTPUT_TYPE in {
|
||||
OutputTypeChoices.PDF_A,
|
||||
OutputTypeChoices.PDF_A2,
|
||||
}:
|
||||
route.pdf_format(PdfAFormat.A2b)
|
||||
elif settings.OCR_OUTPUT_TYPE == OutputTypeChoices.PDF_A1:
|
||||
self.log.warning(
|
||||
"Gotenberg does not support PDF/A-1a, choosing PDF/A-2b instead",
|
||||
)
|
||||
route.pdf_format(PdfAFormat.A2b)
|
||||
elif settings.OCR_OUTPUT_TYPE == OutputTypeChoices.PDF_A3:
|
||||
route.pdf_format(PdfAFormat.A3b)
|
||||
|
||||
try:
|
||||
response = (
|
||||
route.index(html_file)
|
||||
.resource(Path(__file__).parent / "templates" / "invoice.css")
|
||||
.margins(
|
||||
PageMarginsType(
|
||||
top=MarginType(0.1, MarginUnitType.Inches),
|
||||
bottom=MarginType(0.1, MarginUnitType.Inches),
|
||||
left=MarginType(0.1, MarginUnitType.Inches),
|
||||
right=MarginType(0.1, MarginUnitType.Inches),
|
||||
),
|
||||
)
|
||||
.size(PageSize(height=11.7, width=8.27))
|
||||
.scale(1.0)
|
||||
.run()
|
||||
)
|
||||
|
||||
pdf_path.write_bytes(response.content)
|
||||
|
||||
return pdf_path
|
||||
|
||||
except Exception as err:
|
||||
raise ParseError(
|
||||
f"Error while converting document to PDF: {err}",
|
||||
) from err
|
15
src/paperless_einvoice/signals.py
Normal file
15
src/paperless_einvoice/signals.py
Normal file
@ -0,0 +1,15 @@
|
||||
def get_parser(*args, **kwargs):
|
||||
from paperless_einvoice.parsers import EInvoiceDocumentParser
|
||||
|
||||
return EInvoiceDocumentParser(*args, **kwargs)
|
||||
|
||||
|
||||
def einvoice_consumer_declaration(sender, **kwargs):
|
||||
return {
|
||||
"parser": get_parser,
|
||||
"weight": 10,
|
||||
"mime_types": {
|
||||
"text/xml": ".xml",
|
||||
"application/xml": ".xml",
|
||||
},
|
||||
}
|
138
src/paperless_einvoice/templates/invoice.css
Normal file
138
src/paperless_einvoice/templates/invoice.css
Normal file
@ -0,0 +1,138 @@
|
||||
@charset "UTF-8";
|
||||
|
||||
@page {
|
||||
margin: 3cm;
|
||||
|
||||
@bottom-left {
|
||||
color: #1ee494;
|
||||
font-family: Pacifico;
|
||||
}
|
||||
|
||||
@bottom-center {
|
||||
content: string(title);
|
||||
color: #a9a;
|
||||
font-family: Pacifico;
|
||||
font-size: 9pt;
|
||||
}
|
||||
}
|
||||
|
||||
footer {
|
||||
width: 0;
|
||||
height: 0;
|
||||
visibility: hidden;
|
||||
string-set: title content();
|
||||
}
|
||||
|
||||
html {
|
||||
color: #14213d;
|
||||
font-family: Source Sans Pro;
|
||||
font-size: 11pt;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
html body {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html h1 {
|
||||
color: #1ee494;
|
||||
font-family: Pacifico;
|
||||
font-size: 40pt;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html aside {
|
||||
display: flex;
|
||||
margin: 2em 0 4em;
|
||||
}
|
||||
|
||||
html aside address {
|
||||
font-style: normal;
|
||||
white-space: pre-line;
|
||||
}
|
||||
|
||||
html aside address#from {
|
||||
color: #a9a;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
html aside address#to {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
html dl {
|
||||
text-align: right;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
html dl dt,
|
||||
html dl dd {
|
||||
display: inline;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html dl dt {
|
||||
color: #a9a;
|
||||
}
|
||||
|
||||
html dl dt::before {
|
||||
content: '';
|
||||
display: block;
|
||||
}
|
||||
|
||||
html dl dt::after {
|
||||
content: ':';
|
||||
}
|
||||
|
||||
html table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
html table th {
|
||||
border-bottom: .2mm solid #a9a;
|
||||
color: #a9a;
|
||||
font-size: 10pt;
|
||||
font-weight: 400;
|
||||
padding-bottom: .25cm;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
html table td {
|
||||
padding-top: 7mm;
|
||||
}
|
||||
|
||||
html table td:last-of-type {
|
||||
color: #1ee494;
|
||||
font-weight: bold;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
html table th,
|
||||
html table td {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
html table th:first-of-type,
|
||||
html table td:first-of-type {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
html table th:last-of-type,
|
||||
html table td:last-of-type {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
html table#total {
|
||||
background: #f6f6f6;
|
||||
border-color: #f6f6f6;
|
||||
border-style: solid;
|
||||
border-width: 2cm 3cm;
|
||||
bottom: 0;
|
||||
font-size: 20pt;
|
||||
margin: 0 -3cm;
|
||||
position: absolute;
|
||||
width: 18cm;
|
||||
}
|
80
src/paperless_einvoice/templates/invoice.j2.html
Normal file
80
src/paperless_einvoice/templates/invoice.j2.html
Normal file
@ -0,0 +1,80 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>
|
||||
Rechnung {{ id }}
|
||||
</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Rechnung</h1>
|
||||
|
||||
<p id="fromaddress">
|
||||
<u>westnetz w.V., Karl-Heine-Str. 93, 04229 Leipzig</u>
|
||||
</p>
|
||||
<p id="toaddress">
|
||||
{{ address | join("<br />") }}
|
||||
</p>
|
||||
|
||||
|
||||
<table class="infoheader">
|
||||
<tr>
|
||||
<th>Rechnungsnummer</th>
|
||||
<th>Leistungszeitraum</th>
|
||||
<th>Rechnungsdatum</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="info">{{ id }}</td>
|
||||
<td class="info">{{ period }}</td>
|
||||
<td class="info">{{ date }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<h2>Rechnungspositionen</h2>
|
||||
<table class="positions">
|
||||
<tr>
|
||||
<th id="tablepos">Pos.</th>
|
||||
<th id="tabledesc">Beschreibung</th>
|
||||
<th id="tablesingle">Einzelpreis</th>
|
||||
<th id="tablequantity">Anzahl</th>
|
||||
<th id="tabletotal">Gesamtpreis</th>
|
||||
</tr>
|
||||
{% for item in items %}
|
||||
<tr class="position">
|
||||
<td class="positions">{{ item.item }}</td>
|
||||
<td class="positions">{{ item.description }}</td>
|
||||
<td class="positions">{{ item.price }}</td>
|
||||
<td class="positions">{{ item.quantity }}</td>
|
||||
<td class="positions">{{ item.subtotal }}</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
|
||||
<table class="positions sum">
|
||||
<tr>
|
||||
<th>Nettobetrag</th>
|
||||
<th>Mehrwertsteuer (19%)</th>
|
||||
<th>Rechnungsbetrag</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="total">{{ total_net }}</td>
|
||||
<td class="total">{{ total_vat }}</td>
|
||||
<td class="total strong">{{ total_gross }}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
|
||||
<h2>Hinweise</h2>
|
||||
<p>
|
||||
Alle Preise verstehen sich in Euro und sind innerhalb von 14 Tagen auf das nebenstehend angegebene Konto zu überweisen. Um eine möglichst fehlerfreie Verbuchung ihrer Einzahlungen vornehmen zu können, bitten wir um die Angabe der Rechnungsnummer {{ id }} im Verwendungszeck. Bei Daueraufträgen benötigen wir zumindest ihre Kundennummer {{ cid }}.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Diese Rechnung wurde maschinell erstellt und ist auch ohne Unterschrift gültig.
|
||||
</p>
|
||||
|
||||
<embed src="file:///{{ logo_asset_file }}" id="logo" />
|
||||
|
||||
</body>
|
||||
</html>
|
0
src/paperless_einvoice/tests/__init__.py
Normal file
0
src/paperless_einvoice/tests/__init__.py
Normal file
25
src/paperless_einvoice/tests/conftest.py
Normal file
25
src/paperless_einvoice/tests/conftest.py
Normal file
@ -0,0 +1,25 @@
|
||||
from collections.abc import Generator
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from paperless_einvoice.parsers import EInvoiceDocumentParser
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def einvoice_parser() -> Generator[EInvoiceDocumentParser, None, None]:
|
||||
try:
|
||||
parser = EInvoiceDocumentParser(logging_group=None)
|
||||
yield parser
|
||||
finally:
|
||||
parser.cleanup()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def sample_dir() -> Path:
|
||||
return (Path(__file__).parent / Path("samples")).resolve()
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def sample_xml_file(sample_dir: Path) -> Path:
|
||||
return sample_dir / "zugferd_2p1_BASIC-WL_Einfach.xml"
|
@ -0,0 +1,176 @@
|
||||
<?xml version='1.0' encoding='UTF-8' ?>
|
||||
<!-- English disclaimer below.-->
|
||||
<!--Nutzungsrechte
|
||||
ZUGFeRD Datenformat Version 2.2.0, 14.02.2022
|
||||
Beispiel Version 14.02.2022
|
||||
|
||||
Zweck des Forums elektronisch Rechnung Deutschland, welches am 31. März 2010 under der Arbeitsgemeinschaft für
|
||||
wirtschaftliche Verwaltung e. V. gegründet wurde, ist u. a. die Schaffung und Spezifizierung eines offenen Datenformats
|
||||
für strukturierten elektronischen Datenaustausch auf der Grundlage oftener und nicht diskriminierender, standardisierter
|
||||
Technologien („ZUGFeRD Datenformat“).
|
||||
|
||||
Das ZUGFeRD Datenformat wird nach Maßgabe des FeRD sowohl Unternehmen also auch der öffentlichen Verwaltung
|
||||
frei zugänglich gemacht. Hierfür bietet FeRD allen Unternehmen und Organisationen der öffentlichen Verwaltung eine
|
||||
Lizenz für die Nutzung des urheberrechtlich geschützten ZUGFeRD-Datenformats zu fairen, sachgerechten und nicht
|
||||
diskriminierenden Bedingungen an.
|
||||
|
||||
Die Spezifikation des FeRD zur Implementierung des ZUGFeRD Datenformats ist in ihrer jeweils geltenden Fassung
|
||||
abrufbar under www.ferd-net.de.
|
||||
|
||||
Im Einzelnen schließt die Nutzungsgewährung ein:
|
||||
=====================================
|
||||
|
||||
FeRD räumt eine Lizenz für die Nutzung des urheberrechtlich geschützten ZUGFeRD Datenformats in der jeweils
|
||||
geltenden und akzeptierten Fassung (www.ferd-net.de) ein.
|
||||
Die Lizenz beinhaltet ein unwiderrufliches Nutzungsrecht einschließlich des Rechts der Weiterentwicklung,
|
||||
Weiterbearbeitung und Verbindung mit anderen Produkten.
|
||||
Die Lizenz gilt insbesondere für die Entwicklung, die Gestaltung, die Herstellung, den Verkauf, die Nutzung oder
|
||||
anderweitige Verwendung des ZUGFeRD Datenformats für Hardware- und/oder Softwareprodukte sowie sonstige
|
||||
Anwendungen und Dienste.
|
||||
Diese Lizenz schließt nicht die wesentlichen Patente der Mitglieder von FeRD ein. Also wesentliche Patente sind Patente
|
||||
und Patentanmeldungen weltweit zu verstehen, die einen oder mehrere Patentansprüche beinhalten, bei denen es sich um
|
||||
notwendige Ansprüche handelt. Notwendige Ansprüche sind lediglich jene Ansprüche der Wesentlichen Patente, die durch
|
||||
die Implementierung des ZUGFeRD Datenformats notwendigerweise verletzt würden.
|
||||
Der Lizenznehmer ist berechtigt, seinen jeweiligen Konzerngesellschaften ein unbefristetes, weltweites, nicht übertragbares,
|
||||
unwiderrufliches Nutzungsrecht einschließlich des Rechts der Weiterentwicklung, Weiterbearbeitung und Verbindung mit
|
||||
anderen Produkten einzuräumen.
|
||||
|
||||
Die Lizenz wird kostenfrei zur Verfügung gestellt.
|
||||
|
||||
Außer im Falle vorsätzlichen Verschuldens oder grober Fahrlässigkeit haftet FeRD weder für Nutzungsausfall, entgangenen
|
||||
Gewinn, Datenverlust, Kommunikationsverlust, Einnahmeausfall, Vertragseinbußen, Geschäftsausfall oder für Kosten,
|
||||
Schäden, Verluste oder Haftpflichten im Zusammenhang mit einer Unterbrechung der Geschäftstätigkeit, noch für konkrete,
|
||||
beiläufig entstandene, mittelbare Schäden, Straf- oder Folgeschäden und zwar auch dann nicht, wenn die Möglichkeit der
|
||||
Kosten, Verluste bzw. Schäden hätte normalerweise vorhergesehen werden können.-->
|
||||
|
||||
<!--Right of use
|
||||
ZUGFeRD Data format version 2.2.0, February 14th, 2022
|
||||
|
||||
The purpose of the Forum elektronische Rechnung Deutschland (FeRD), which was founded on March 31, 2010 under the
|
||||
umbrella of Arbeitsgemeinschaft für wirtschaftliche Verwaltung e. V., is, among other things, to create and specify an
|
||||
open data format for structured electronic data exchange on the basis of open and non discriminatory, standardised
|
||||
technologies ("ZUGFeRD data format").
|
||||
|
||||
The ZUGFeRD data format is used by both companies and public administration according to the FeRD
|
||||
made freely accessible. For this purpose FeRD offers all companies and organisations of the public administration a
|
||||
License to use the copyrighted ZUGFeRD data format in a fair, appropriate and non
|
||||
discriminatory conditions.
|
||||
|
||||
The specification of the FeRD for the implementation of the ZUGFeRD data format is, in its currently valid version
|
||||
available at www.ferd-net.de.
|
||||
|
||||
In detail, the grant of use includes
|
||||
=====================================
|
||||
|
||||
FeRD grants a license for the use of the copyrighted ZUGFeRD data format in the respective
|
||||
valid and accepted version (www.ferd-net.de).
|
||||
The license includes an irrevocable right of use including the right of further development,
|
||||
Further processing and connection with other products.
|
||||
The license applies in particular to the development, design, production, sale, use or
|
||||
other use of the ZUGFeRD data format for hardware and/or software products and other
|
||||
applications and services.
|
||||
This license does not include the essential patents of the members of FeRD. The essential patents are patents
|
||||
and patent applications worldwide which contain one or more claims that are
|
||||
necessary claims. Necessary claims are only those claims of the essential patents which are
|
||||
the implementation of the ZUGFeRD data format would necessarily be violated.
|
||||
The Licensee is entitled to provide its respective group companies with an unlimited, worldwide, non-transferable,
|
||||
irrevocable right of use including the right of further development, further processing and connection with
|
||||
other products.
|
||||
|
||||
The license is provided free of charge.
|
||||
|
||||
Except in the case of intentional fault or gross negligence, FeRD is not liable for loss of use, loss of
|
||||
Profit, loss of data, loss of communication, loss of revenue, loss of contracts, loss of business or for costs
|
||||
damages, losses or liabilities in connection with an interruption of business, nor for concrete,
|
||||
incidental, indirect, punitive or consequential damages, even if the possibility of
|
||||
costs, losses or damages could normally have been foreseen.-->
|
||||
|
||||
<rsm:CrossIndustryInvoice xmlns:rsm="urn:un:unece:uncefact:data:standard:CrossIndustryInvoice:100" xmlns:qdt="urn:un:unece:uncefact:data:standard:QualifiedDataType:100" xmlns:ram="urn:un:unece:uncefact:data:standard:ReusableAggregateBusinessInformationEntity:100" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:udt="urn:un:unece:uncefact:data:standard:UnqualifiedDataType:100">
|
||||
<rsm:ExchangedDocumentContext>
|
||||
<ram:GuidelineSpecifiedDocumentContextParameter>
|
||||
<ram:ID>urn:factur-x.eu:1p0:basicwl</ram:ID>
|
||||
</ram:GuidelineSpecifiedDocumentContextParameter>
|
||||
</rsm:ExchangedDocumentContext>
|
||||
<rsm:ExchangedDocument>
|
||||
<ram:ID>TX-471102</ram:ID>
|
||||
<ram:TypeCode>380</ram:TypeCode>
|
||||
<ram:IssueDateTime>
|
||||
<udt:DateTimeString format="102">20191030</udt:DateTimeString>
|
||||
</ram:IssueDateTime>
|
||||
<ram:IncludedNote>
|
||||
<ram:Content>Rechnung gemäß Taxifahrt vom 29.10.2019</ram:Content>
|
||||
</ram:IncludedNote>
|
||||
<ram:IncludedNote>
|
||||
<ram:Content>Taxiunternehmen TX GmbH
|
||||
Lieferantenstraße 20
|
||||
10369 Berlin
|
||||
Deutschland
|
||||
Geschäftsführer: Hans Mustermann
|
||||
Handelsregisternummer: H A 123
|
||||
</ram:Content>
|
||||
</ram:IncludedNote>
|
||||
<ram:IncludedNote>
|
||||
<ram:Content>Unsere GLN: 4000001123452
|
||||
Ihre GLN: 4000001987658
|
||||
Ihre Kundennummer: GE2020211
|
||||
</ram:Content>
|
||||
</ram:IncludedNote>
|
||||
</rsm:ExchangedDocument>
|
||||
<rsm:SupplyChainTradeTransaction>
|
||||
<ram:ApplicableHeaderTradeAgreement>
|
||||
<ram:SellerTradeParty>
|
||||
<ram:Name>Taxiunternehmen TX GmbH</ram:Name>
|
||||
<ram:PostalTradeAddress>
|
||||
<ram:PostcodeCode>10369</ram:PostcodeCode>
|
||||
<ram:LineOne>Lieferantenstraße 20</ram:LineOne>
|
||||
<ram:CityName>Berlin</ram:CityName>
|
||||
<ram:CountryID>DE</ram:CountryID>
|
||||
</ram:PostalTradeAddress>
|
||||
<ram:SpecifiedTaxRegistration>
|
||||
<ram:ID schemeID="VA">DE123456789</ram:ID>
|
||||
</ram:SpecifiedTaxRegistration>
|
||||
</ram:SellerTradeParty>
|
||||
<ram:BuyerTradeParty>
|
||||
<ram:Name>Taxi-Gast AG Mitte</ram:Name>
|
||||
<ram:PostalTradeAddress>
|
||||
<ram:PostcodeCode>13351</ram:PostcodeCode>
|
||||
<ram:LineOne>Hans Mustermann</ram:LineOne>
|
||||
<ram:LineTwo>Kundenstraße 15</ram:LineTwo>
|
||||
<ram:CityName>Berlin</ram:CityName>
|
||||
<ram:CountryID>DE</ram:CountryID>
|
||||
</ram:PostalTradeAddress>
|
||||
</ram:BuyerTradeParty>
|
||||
</ram:ApplicableHeaderTradeAgreement>
|
||||
<ram:ApplicableHeaderTradeDelivery>
|
||||
<ram:ActualDeliverySupplyChainEvent>
|
||||
<ram:OccurrenceDateTime>
|
||||
<udt:DateTimeString format="102">20191029</udt:DateTimeString>
|
||||
</ram:OccurrenceDateTime>
|
||||
</ram:ActualDeliverySupplyChainEvent>
|
||||
</ram:ApplicableHeaderTradeDelivery>
|
||||
<ram:ApplicableHeaderTradeSettlement>
|
||||
<ram:InvoiceCurrencyCode>EUR</ram:InvoiceCurrencyCode>
|
||||
<ram:ApplicableTradeTax>
|
||||
<ram:CalculatedAmount>1.18</ram:CalculatedAmount>
|
||||
<ram:TypeCode>VAT</ram:TypeCode>
|
||||
<ram:BasisAmount>16.90</ram:BasisAmount>
|
||||
<ram:CategoryCode>S</ram:CategoryCode>
|
||||
<ram:RateApplicablePercent>7</ram:RateApplicablePercent>
|
||||
</ram:ApplicableTradeTax>
|
||||
<ram:SpecifiedTradePaymentTerms>
|
||||
<ram:DueDateDateTime>
|
||||
<udt:DateTimeString format="102">20191129</udt:DateTimeString>
|
||||
</ram:DueDateDateTime>
|
||||
</ram:SpecifiedTradePaymentTerms>
|
||||
<ram:SpecifiedTradeSettlementHeaderMonetarySummation>
|
||||
<ram:LineTotalAmount>16.90</ram:LineTotalAmount>
|
||||
<ram:ChargeTotalAmount>0.00</ram:ChargeTotalAmount>
|
||||
<ram:AllowanceTotalAmount>0.00</ram:AllowanceTotalAmount>
|
||||
<ram:TaxBasisTotalAmount>16.90</ram:TaxBasisTotalAmount>
|
||||
<ram:TaxTotalAmount currencyID="EUR">1.18</ram:TaxTotalAmount>
|
||||
<ram:GrandTotalAmount>18.08</ram:GrandTotalAmount>
|
||||
<ram:DuePayableAmount>18.08</ram:DuePayableAmount>
|
||||
</ram:SpecifiedTradeSettlementHeaderMonetarySummation>
|
||||
</ram:ApplicableHeaderTradeSettlement>
|
||||
</rsm:SupplyChainTradeTransaction>
|
||||
</rsm:CrossIndustryInvoice>
|
19
src/paperless_einvoice/tests/test_einvoice_parser.py
Normal file
19
src/paperless_einvoice/tests/test_einvoice_parser.py
Normal file
@ -0,0 +1,19 @@
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from pytest_django.fixtures import SettingsWrapper
|
||||
from pytest_httpx import HTTPXMock
|
||||
|
||||
from paperless_einvoice.parsers import EInvoiceDocumentParser
|
||||
|
||||
|
||||
@pytest.mark.django_db()
|
||||
class TestEInvoiceParser:
|
||||
def test_parse(
|
||||
self,
|
||||
httpx_mock: HTTPXMock,
|
||||
settings: SettingsWrapper,
|
||||
einvoice_parser: EInvoiceDocumentParser,
|
||||
sample_xml_file: Path,
|
||||
):
|
||||
return None
|
Loading…
x
Reference in New Issue
Block a user