diff --git a/edocument.py b/edocument.py
index ef0ae91..077398b 100644
--- a/edocument.py
+++ b/edocument.py
@@ -22,6 +22,19 @@ class Invoice(Invoice):
if getattr(self.invoice, 'sales', None) is not None:
return ', '.join([x.number for x in self.invoice.sales])
+ def negate_amount(self, amount):
+ """ amount * -1.0
+ """
+ if amount is not None and amount:
+ if isinstance(amount, Decimal):
+ return amount.copy_negate()
+ elif isinstance(amount, float):
+ return -1.0 * amount
+ elif isinstance(amount, int):
+ return -1 * amount
+ else :
+ return amount
+
def prepaid_amount(self, invoice):
""" compute already paid amount
"""
@@ -108,7 +121,12 @@ class Invoice(Invoice):
loader = genshi.template.TemplateLoader(
os.path.join(os.path.dirname(__file__), 'template'),
auto_reload=True)
- return loader.load(os.path.join(version, 'XRechnung.xml'))
+ if self.type_code in ['380', '389']:
+ return loader.load(os.path.join(version, 'XRechnung_invoice.xml'))
+ elif self.type_code in ['381', '261']:
+ return loader.load(os.path.join(version, 'XRechnung_credit.xml'))
+ else :
+ raise ValueError('invalid type-code "%s"' % self.type_code)
else:
return super(Invoice, self)._get_template(version)
diff --git a/template/XRechnung-2.2/XRechnung_credit.xml b/template/XRechnung-2.2/XRechnung_credit.xml
new file mode 100644
index 0000000..e12ba91
--- /dev/null
+++ b/template/XRechnung-2.2/XRechnung_credit.xml
@@ -0,0 +1,182 @@
+
+
+
+
+ ${', '.join((getattr(value, 'street', None) or '').split('\n'))}
+ ${getattr(value, 'city', None) or ''}
+ ${getattr(value, 'postal_code', None) or ''}
+
+ ${getattr(getattr(value, 'country', None), 'code', None)}
+
+
+
+
+ ${this.taxident_data(value)['code']}
+
+ ${this.taxident_data(value)['id']}
+
+
+
+
+ ${value.name}
+
+ ${value.phone}
+
+
+ ${value.email}
+
+
+
+
+ ${value.name}
+ ${this.taxident_data(this.seller_trade_tax_identifier)['code']}
+
+
+
+
+ ${value.bank_accounts[0].numbers[0].number_compact}
+ ${value.name}
+
+
+
+
+ ${this.tax_category_code(value)}
+ ${this.tax_rate(value)}
+ ${value.legal_notice or '-'}
+
+ VAT
+
+
+
+
+
+ ${this.negate_amount(value.base)}
+ ${this.negate_amount(value.amount)}
+
+ ${TaxCategory(value.tax, True)}
+
+
+
+
+
+
+ ${value.id}
+ ${this.negate_amount(value.quantity)}
+ ${this.negate_amount(value.amount)}
+
+ ${value.description or getattr(value.product, 'name', None)}
+
+ ${value.product.code}
+
+
+ ${TaxCategory(this.invoice_line_tax(value))}
+
+
+
+ ${value.unit_price}
+
+
+
+
+ urn:cen.eu:en16931:2017#compliant#urn:xoev-de:kosit:standard:xrechnung_2.1
+ ${this.invoice.number}
+ ${this.invoice.invoice_date.isoformat()}
+ ${this.type_code}
+ ${this.invoice_note()}
+ ${this.invoice.currency.code}
+ ${this.invoice.party.get_xrechnung_route_id()}
+
+ ${this.invoice.reference}
+ ${this.sales_order_nums()}
+
+
+ vertrags-nr
+
+
+ proj-referenz
+
+
+
+
+ ${PostalAddress(this.seller_trade_address)}
+
+
+ ${PartyTaxScheme(this.seller_trade_tax_identifier)}
+
+
+ ${PartyLegalEntity(this.seller_trade_party)}
+
+
+ ${Contact(this.seller_trade_party)}
+
+
+
+
+
+
+ ${this.buyer_trade_party.code}
+
+
+ ${PostalAddress(this.buyer_trade_address)}
+
+
+ ${PartyTaxScheme(this.buyer_trade_tax_identifier)}
+
+
+ ${PartyLegalEntity(this.buyer_trade_party, False)}
+
+
+ ${Contact(this.buyer_trade_party)}
+
+
+
+
+ 30
+ ${this.payment_reference}
+
+ ${PayeeFinancialAccount(this.seller_trade_party)}
+
+
+
+ ${this.invoice.payment_term.rec_name}
+
+
+ false
+ Neukundenrabatt
+ 5.00
+
+ S
+ 19.00
+
+ VAT
+
+
+
+
+ ${this.negate_amount(this.invoice.tax_amount)}
+
+ ${TaxSubTotal(taxline)}
+
+
+
+ ${this.negate_amount(this.invoice.untaxed_amount)}
+ ${this.negate_amount(this.invoice.untaxed_amount)}
+ ${this.negate_amount(this.invoice.total_amount)}
+ 0.00
+ 0.00
+ ${this.negate_amount(this.prepaid_amount(this.invoice))}
+ ${this.negate_amount(this.invoice.amount_to_pay)}
+
+
+ ${CreditNoteLine(line)}
+
+
diff --git a/template/XRechnung-2.2/XRechnung.xml b/template/XRechnung-2.2/XRechnung_invoice.xml
similarity index 95%
rename from template/XRechnung-2.2/XRechnung.xml
rename to template/XRechnung-2.2/XRechnung_invoice.xml
index b07ad43..a1de5bf 100644
--- a/template/XRechnung-2.2/XRechnung.xml
+++ b/template/XRechnung-2.2/XRechnung_invoice.xml
@@ -27,8 +27,12 @@
${value.name}
- ${value.phone}
- ${value.email}
+
+ ${value.phone}
+
+
+ ${value.email}
+
diff --git a/tests/test_edocument.py b/tests/test_edocument.py
index c2cdad8..85c1016 100644
--- a/tests/test_edocument.py
+++ b/tests/test_edocument.py
@@ -15,8 +15,8 @@ class EdocTestCase(ModuleTestCase):
module = 'edocument_xrechnung'
@with_transaction()
- def test_xrechn_export_xml(self):
- """ run export
+ def test_xrechn_export_xml_invoice(self):
+ """ run export - invoice
"""
pool = Pool()
Template = pool.get('edocument.xrechnung.invoice')
@@ -47,7 +47,56 @@ class EdocTestCase(ModuleTestCase):
template = Template(invoice)
invoice_string = template.render('XRechnung-2.2')
- with open('xrechnung-test.xml', 'wt') as fhdl:
+ with open('xrechnung-test-invoice.xml', 'wt') as fhdl:
+ fhdl.write(invoice_string.decode('utf8'))
+
+ @with_transaction()
+ def test_xrechn_export_xml_creditnote(self):
+ """ run export - creditnote
+ """
+ pool = Pool()
+ Template = pool.get('edocument.xrechnung.invoice')
+ Identifier = pool.get('party.identifier')
+ Party = pool.get('party.party')
+ Bank = pool.get('bank')
+ BankAccount = pool.get('bank.account')
+ BankNumber = pool.get('bank.account.number')
+
+ invoice = get_invoice()
+
+ # credit note
+ invoice.lines[0].quantity = -1
+ invoice.lines[0].amount = Decimal('-100.0')
+ invoice.taxes[0].base = Decimal('-100.0')
+ invoice.taxes[0].amount = Decimal('-10.0')
+ invoice.untaxed_amount = Decimal('-100.0')
+ invoice.tax_amount = Decimal('-10.0')
+ invoice.total_amount = Decimal('-110.0')
+ invoice.lines_to_pay[0].debit = Decimal('-110.0')
+
+ invoice.party.get_xrechnung_route_id = Mock(
+ return_value='xrechn-route-id-123')
+ invoice.company.party.bank_accounts = [
+ Mock(
+ spec=BankAccount,
+ currency=invoice.currency,
+ bank=Mock(spec=Bank, party=Mock(spec=Party, name='Bank')),
+ owners=[invoice.company.party],
+ numbers=[Mock(spec=BankNumber, type='other', number='123456')],
+ )]
+ invoice.description = 'description of invoice'
+ invoice.comment = 'note line 1\nnote line 2'
+ invoice.taxes[0].tax.rate = Decimal('0.1')
+ invoice.identifiers = [
+ Mock(
+ spec=Identifier,
+ type='edoc_route_id',
+ code='xrechn-route-id-123')
+ ]
+
+ template = Template(invoice)
+ invoice_string = template.render('XRechnung-2.2')
+ with open('xrechnung-test-creditnote.xml', 'wt') as fhdl:
fhdl.write(invoice_string.decode('utf8'))
# end EdocTestCase