[ADD] l10n_no_edi: added support for EHF3

EHF3 is the Norvegian standard for Peppol. This module generates xml (based on BIS3 with NO country profile) to be submitted on the Peppol network.

TASK ID: 2528203

closes odoo/odoo#70679

Related: odoo/enterprise#20050
Signed-off-by: Laurent Smet <smetl@users.noreply.github.com>
This commit is contained in:
Benjamin Frantzen (bfr)
2021-08-17 09:39:57 +00:00
parent 4d2c7903f6
commit d22b517838
18 changed files with 922 additions and 1 deletions
@@ -106,6 +106,12 @@ class AccountEdiFormat(models.Model):
# Import
####################################################
def _get_bis3_namespaces(self):
return {
'cac': 'urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2',
'cbc': 'urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2',
}
def _bis3_get_extra_partner_domains(self, tree):
""" Returns an additional domain to find the partner of the invoice based on specific implementation of BIS3.
TO OVERRIDE
@@ -35,7 +35,7 @@ class AccountEdiFormat(models.Model):
return [('l10n_nl_kvk', '=', endpoint.text)]
elif scheme == '0190' and endpoint.text:
return [('l10n_nl_oin', '=', endpoint.text)]
return []
return super()._bis3_get_extra_partner_domains(tree)
####################################################
# Export
+2
View File
@@ -21,6 +21,8 @@ Updated for Odoo 9 by Bringsvor Consulting AS <www.bringsvor.com>
'data/account.account.template.csv',
'data/account_tax_data.xml',
'data/account_chart_template_data.xml',
'views/res_partner_views.xml',
'views/res_company_views.xml',
],
'demo': [
'demo/demo_company.xml',
+1
View File
@@ -11,6 +11,7 @@
<field name="phone">+47 406 12 345</field>
<field name="email">info@company.noexample.com</field>
<field name="website">www.noexample.com</field>
<field name="l10n_no_bronnoysund_number">123456785</field>
</record>
<record id="demo_company_no" model="res.company">
+2
View File
@@ -3,3 +3,5 @@
from . import account_journal
from . import account_move
from . import res_partner
from . import res_company
+8
View File
@@ -0,0 +1,8 @@
# coding: utf-8
from odoo import fields, models
class ResCompany(models.Model):
_inherit = 'res.company'
l10n_no_bronnoysund_number = fields.Char(related='partner_id.l10n_no_bronnoysund_number', readonly=False)
+8
View File
@@ -0,0 +1,8 @@
# coding: utf-8
from odoo import fields, models
class ResPartner(models.Model):
_inherit = 'res.partner'
l10n_no_bronnoysund_number = fields.Char(string='Register of Legal Entities (Brønnøysund Register Center)', size=9)
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="res_company_form_inherit_no" model="ir.ui.view">
<field name="name">res.company.form.inherit.l10n.no</field>
<field name="model">res.company</field>
<field name="inherit_id" ref="base.view_company_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='vat']" position="after">
<field name="l10n_no_bronnoysund_number" attrs="{'invisible': [('country_code', '!=', 'NO')]}"/>
</xpath>
</field>
</record>
</data>
</odoo>
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_partner_form_inherit_l10n_no" model="ir.ui.view">
<field name="name">res.partner.form.inherit.l10n_no</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='vat']" position="after">
<field name="l10n_no_bronnoysund_number" attrs="{'invisible': ['|', ('country_code', '!=', 'NO'), ('is_company', '=', False)]}"/>
</xpath>
</field>
</record>
</odoo>
+4
View File
@@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import models
+19
View File
@@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
{
'name': 'Norway - E-Invoicing (EHF 3)',
'icon': '/l10n_no/static/description/icon.png',
'version': '0.1',
'category': 'Accounting/Localizations/EDI',
'summary': 'E-Invoicing, Universal Business Language (EHF 3)',
'description': """
EHF 3 is the Norvegian implementation of EN 16931 norm.
""",
'depends': ['l10n_no', 'account_edi_ubl_bis3'],
'data': [
'data/account_edi_data.xml',
'data/ehf_3_template.xml',
],
'installable': True,
'auto_install': True,
'license': 'LGPL-3',
}
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="edi_ehf_3" model="account.edi.format">
<field name="name">EHF 3 (Norway)</field>
<field name="code">ehf_3</field>
</record>
</data>
</odoo>
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<template id="export_ehf_3_invoice_partner" inherit_id="account_edi_ubl_bis3.export_bis3_invoice_partner" primary="True">
<xpath expr="//*[local-name()='PartyTaxScheme']" position="after">
<cac:PartyTaxScheme xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
<cbc:CompanyID>Foretaksregisteret</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>TAX</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
</xpath>
</template>
<template id="export_ehf_3_invoice" inherit_id="account_edi_ubl_bis3.export_bis3_invoice" primary="True">
<!-- Only for the supplier, append Foretaksregisteret, see rule NO-R-002 -->
<xpath expr="//*[local-name()='AccountingSupplierParty']" position="replace">
<cac:AccountingSupplierParty t-call="l10n_no_edi.export_ehf_3_invoice_partner"
xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2">
<t t-set="partner_vals" t-value="supplier_vals"/>
</cac:AccountingSupplierParty>
</xpath>
</template>
</data>
</odoo>
+3
View File
@@ -0,0 +1,3 @@
# -*- encoding: utf-8 -*-
from . import account_edi_format
@@ -0,0 +1,116 @@
# -*- coding: utf-8 -*-
from odoo import models, _
from odoo.addons.account_edi_ubl_bis3.models.account_edi_format import COUNTRY_EAS
class AccountEdiFormat(models.Model):
_inherit = 'account.edi.format'
####################################################
# Import
####################################################
def _is_ubl(self, filename, tree):
""" OVERRIDE so that the generic ubl parser does not parse BIS3 any longer.
"""
is_ubl = super()._is_ubl(filename, tree)
return is_ubl and not self._is_ehf_3(filename, tree)
def _is_ehf_3(self, filename, tree):
ns = self._get_bis3_namespaces()
return tree.tag == '{urn:oasis:names:specification:ubl:schema:xsd:Invoice-2}Invoice' \
and 'peppol' in tree.findtext('./cbc:ProfileID', '', namespaces=ns) \
and tree.xpath(
"./cac:AccountingSupplierParty/cac:Party/cac:PartyTaxScheme/cbc:CompanyID[text()='Foretaksregisteret']",
namespaces=ns) is not None
def _bis3_get_extra_partner_domains(self, tree):
if self.code == 'ehf_3':
ns = self._get_bis3_namespaces()
bronnoysund = tree.xpath('./cac:AccountingSupplierParty/cac:Party/cbc:EndpointID[@schemeID="0192"]/text()', namespaces=ns)
if bronnoysund:
return [('l10n_no_bronnoysund_number', '=', bronnoysund[0])]
return super()._bis3_get_extra_partner_domains(tree)
####################################################
# Export
####################################################
def _get_ehf_3_values(self, invoice):
values = super()._get_bis3_values(invoice)
for partner_vals in (values['customer_vals'], values['supplier_vals']):
partner = partner_vals['partner']
if partner.country_code == 'NO':
partner_vals.update(
bis3_endpoint=partner.l10n_no_bronnoysund_number,
bis3_endpoint_scheme='0192',
)
return values
def _export_ehf_3(self, invoice):
self.ensure_one()
# Create file content.
xml_content = self.env.ref('l10n_no_edi.export_ehf_3_invoice')._render(self._get_ehf_3_values(invoice))
vat = invoice.company_id.partner_id.commercial_partner_id.vat
xml_name = 'ehf-%s%s%s.xml' % (vat or '', '-' if vat else '', invoice.name.replace('/', '_'))
return self.env['ir.attachment'].create({
'name': xml_name,
'raw': xml_content.encode(),
'res_model': 'account.move',
'res_id': invoice.id,
'mimetype': 'application/xml'
})
####################################################
# Account.edi.format override
####################################################
def _check_move_configuration(self, invoice):
errors = super()._check_move_configuration(invoice)
if self.code != 'ehf_3':
return errors
supplier = invoice.company_id.partner_id.commercial_partner_id
if supplier.country_code == 'NO' and not supplier.l10n_no_bronnoysund_number:
errors.append(_("The supplier %r must have a Bronnoysund company registry.", supplier.display_name))
if supplier.country_code != 'NO' and supplier.country_code not in COUNTRY_EAS:
errors.append(_("The supplier %r is from a country that is not supported for EHF (Bis3)", supplier.display_name))
customer = invoice.commercial_partner_id
if customer.country_code == 'NO' and not customer.l10n_no_bronnoysund_number:
errors.append(_("The customer %r must have a Bronnoysund company registry.", customer.display_name))
if customer.country_code != 'NO' and customer.country_code not in COUNTRY_EAS:
errors.append(_("The customer %r is from a country that is not supported for EHF (Bis3)", customer.display_name))
return errors
def _is_compatible_with_journal(self, journal):
self.ensure_one()
if self.code != 'ehf_3':
return super()._is_compatible_with_journal(journal)
return journal.type == 'sale' and journal.country_code == 'NO'
def _post_invoice_edi(self, invoices):
self.ensure_one()
if self.code != 'ehf_3':
return super()._post_invoice_edi(invoices)
invoice = invoices # no batch ensure that there is only one invoice
attachment = self._export_ehf_3(invoice)
return {invoice: {'attachment': attachment}}
def _create_invoice_from_xml_tree(self, filename, tree):
self.ensure_one()
if self.code == 'ehf_3' and self._is_ehf_3(filename, tree):
return self._decode_bis3(tree, self.env['account.move'])
return super()._create_invoice_from_xml_tree(filename, tree)
def _update_invoice_from_xml_tree(self, filename, tree, invoice):
self.ensure_one()
if self.code == 'ehf_3' and self._is_ehf_3(filename, tree):
return self._decode_bis3(tree, invoice)
return super()._update_invoice_from_xml_tree(filename, tree, invoice)
@@ -0,0 +1,457 @@
<?xml version='1.0' encoding='UTF-8'?>
<Invoice xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0</cbc:CustomizationID>
<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
<cbc:ID>TOSL108</cbc:ID>
<cbc:IssueDate>2013-06-30</cbc:IssueDate>
<cbc:DueDate>2013-07-20</cbc:DueDate>
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
<cbc:Note>Ordered in our booth at the convention.</cbc:Note>
<cbc:TaxPointDate>2013-06-30</cbc:TaxPointDate>
<cbc:DocumentCurrencyCode>NOK</cbc:DocumentCurrencyCode>
<cbc:AccountingCost>Project cost code 123</cbc:AccountingCost>
<cbc:BuyerReference>3150bdn</cbc:BuyerReference>
<cac:InvoicePeriod>
<cbc:StartDate>2013-06-01</cbc:StartDate>
<cbc:EndDate>2013-06-30</cbc:EndDate>
</cac:InvoicePeriod>
<cac:OrderReference>
<cbc:ID>123</cbc:ID>
</cac:OrderReference>
<cac:ContractDocumentReference>
<cbc:ID>Contract321</cbc:ID>
</cac:ContractDocumentReference>
<cac:AdditionalDocumentReference>
<cbc:ID>Doc1</cbc:ID>
<cbc:DocumentDescription>Timesheet</cbc:DocumentDescription>
<cac:Attachment>
<cac:ExternalReference>
<cbc:URI>http://www.suppliersite.eu/sheet001.html</cbc:URI>
</cac:ExternalReference>
</cac:Attachment>
</cac:AdditionalDocumentReference>
<cac:AdditionalDocumentReference>
<cbc:ID>Doc2</cbc:ID>
<cbc:DocumentDescription>EHF specification</cbc:DocumentDescription>
<cac:Attachment>
<cbc:EmbeddedDocumentBinaryObject mimeCode="application/pdf" filename="Hours-spent.csv">VGVzdCBiYXNlIDY0IGVuY29kaW5n</cbc:EmbeddedDocumentBinaryObject>
</cac:Attachment>
</cac:AdditionalDocumentReference>
<cac:AccountingSupplierParty>
<cac:Party>
<cbc:EndpointID schemeID="0192">864234232</cbc:EndpointID>
<cac:PartyIdentification>
<cbc:ID schemeID="0088">1238764941386</cbc:ID>
</cac:PartyIdentification>
<cac:PartyName>
<cbc:Name>partner_a</cbc:Name>
</cac:PartyName>
<cac:PostalAddress>
<cbc:StreetName>Main street 34</cbc:StreetName>
<cbc:AdditionalStreetName>Suite 123</cbc:AdditionalStreetName>
<cbc:CityName>Big city</cbc:CityName>
<cbc:PostalZone>54321</cbc:PostalZone>
<cbc:CountrySubentity>RegionA</cbc:CountrySubentity>
<cac:Country>
<cbc:IdentificationCode>NO</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>NO864234232MVA</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyTaxScheme>
<cbc:CompanyID>Foretaksregisteret</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>TAX</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>The Sellercompany ASA</cbc:RegistrationName>
<cbc:CompanyID schemeID="0192">864234232</cbc:CompanyID>
</cac:PartyLegalEntity>
<cac:Contact>
<cbc:Name>Antonio Salesmacher</cbc:Name>
<cbc:Telephone>46211230</cbc:Telephone>
<cbc:ElectronicMail>antonio@salescompany.no</cbc:ElectronicMail>
</cac:Contact>
</cac:Party>
</cac:AccountingSupplierParty>
<cac:AccountingCustomerParty>
<cac:Party>
<cbc:EndpointID schemeID="0192">987654325</cbc:EndpointID>
<cac:PartyIdentification>
<cbc:ID schemeID="0088">3456789012098</cbc:ID>
</cac:PartyIdentification>
<cac:PartyName>
<cbc:Name>The Buyercompany</cbc:Name>
</cac:PartyName>
<cac:PostalAddress>
<cbc:StreetName>Anystreet 8</cbc:StreetName>
<cbc:AdditionalStreetName>Back door</cbc:AdditionalStreetName>
<cbc:CityName>Anytown</cbc:CityName>
<cbc:PostalZone>101</cbc:PostalZone>
<cbc:CountrySubentity>RegionB</cbc:CountrySubentity>
<cac:Country>
<cbc:IdentificationCode>NO</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>NO987654325MVA</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>Buyercompany ASA</cbc:RegistrationName>
<cbc:CompanyID schemeID="0192">987654325</cbc:CompanyID>
</cac:PartyLegalEntity>
<cac:Contact>
<cbc:Name>John Doe</cbc:Name>
<cbc:Telephone>5121230</cbc:Telephone>
<cbc:ElectronicMail>john@buyercompany.no</cbc:ElectronicMail>
</cac:Contact>
</cac:Party>
</cac:AccountingCustomerParty>
<cac:PayeeParty>
<cac:PartyIdentification>
<cbc:ID schemeID="0088">2298740918237</cbc:ID>
</cac:PartyIdentification>
<cac:PartyName>
<cbc:Name>Ebeneser Scrooge AS</cbc:Name>
</cac:PartyName>
<cac:PartyLegalEntity>
<cbc:CompanyID schemeID="0192">999999999</cbc:CompanyID>
</cac:PartyLegalEntity>
</cac:PayeeParty>
<cac:TaxRepresentativeParty>
<cac:PartyName>
<cbc:Name>Tax handling company AS</cbc:Name>
</cac:PartyName>
<cac:PostalAddress>
<cbc:StreetName>Regent street</cbc:StreetName>
<cbc:AdditionalStreetName>Front door</cbc:AdditionalStreetName>
<cbc:CityName>Newtown</cbc:CityName>
<cbc:PostalZone>101</cbc:PostalZone>
<cbc:CountrySubentity>RegionC</cbc:CountrySubentity>
<cac:Country>
<cbc:IdentificationCode>NO</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>NO999999999MVA</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
</cac:TaxRepresentativeParty>
<cac:Delivery>
<cbc:ActualDeliveryDate>2013-06-15</cbc:ActualDeliveryDate>
<cac:DeliveryLocation>
<cbc:ID schemeID="0088">6754238987643</cbc:ID>
</cac:DeliveryLocation>
</cac:Delivery>
<cac:PaymentMeans>
<cbc:PaymentMeansCode>31</cbc:PaymentMeansCode>
<cbc:PaymentID>0003434323213231</cbc:PaymentID>
<cac:PayeeFinancialAccount>
<cbc:ID>86011117947</cbc:ID>
<cac:FinancialInstitutionBranch>
<cbc:ID>DNBANOKK</cbc:ID>
</cac:FinancialInstitutionBranch>
</cac:PayeeFinancialAccount>
</cac:PaymentMeans>
<cac:PaymentTerms>
<cbc:Note>2 % discount if paid within 2 days. Penalty percentage 10% from due date</cbc:Note>
</cac:PaymentTerms>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>true</cbc:ChargeIndicator>
<cbc:AllowanceChargeReasonCode>FC</cbc:AllowanceChargeReasonCode>
<cbc:AllowanceChargeReason>Freight</cbc:AllowanceChargeReason>
<cbc:Amount currencyID="NOK">100</cbc:Amount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>25</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:AllowanceCharge>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<cbc:AllowanceChargeReasonCode>95</cbc:AllowanceChargeReasonCode>
<cbc:AllowanceChargeReason>Promotion discount</cbc:AllowanceChargeReason>
<cbc:Amount currencyID="NOK">100</cbc:Amount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>25</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:AllowanceCharge>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="NOK">365.28</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="NOK">1460.5</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="NOK">365.13</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>25</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="NOK">1</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="NOK">0.15</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>15</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="NOK">-25</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="NOK">0</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>E</cbc:ID>
<cbc:Percent>0</cbc:Percent>
<cbc:TaxExemptionReason>Exempt New Means of Transport</cbc:TaxExemptionReason>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="NOK">1436.5</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="NOK">1436.5</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="NOK">1801.78</cbc:TaxInclusiveAmount>
<cbc:AllowanceTotalAmount currencyID="NOK">100</cbc:AllowanceTotalAmount>
<cbc:ChargeTotalAmount currencyID="NOK">100</cbc:ChargeTotalAmount>
<cbc:PrepaidAmount currencyID="NOK">1000</cbc:PrepaidAmount>
<cbc:PayableRoundingAmount currencyID="NOK">0.22</cbc:PayableRoundingAmount>
<cbc:PayableAmount currencyID="NOK">802.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:Note>Scratch on box</cbc:Note>
<cbc:InvoicedQuantity unitCode="NAR">1</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="NOK">1273</cbc:LineExtensionAmount>
<cbc:AccountingCost>BookingCode001</cbc:AccountingCost>
<cac:InvoicePeriod>
<cbc:StartDate>2013-06-01</cbc:StartDate>
<cbc:EndDate>2013-06-30</cbc:EndDate>
</cac:InvoicePeriod>
<cac:OrderLineReference>
<cbc:LineID>1</cbc:LineID>
</cac:OrderLineReference>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<cbc:AllowanceChargeReason>Damage</cbc:AllowanceChargeReason>
<cbc:Amount currencyID="NOK">12</cbc:Amount>
</cac:AllowanceCharge>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>true</cbc:ChargeIndicator>
<cbc:AllowanceChargeReason>Testing</cbc:AllowanceChargeReason>
<cbc:Amount currencyID="NOK">12</cbc:Amount>
</cac:AllowanceCharge>
<cac:Item>
<cbc:Description>Processor: Intel Core 2 Duo SU9400 LV (1.4GHz). RAM: 3MB. Screen 1440x900</cbc:Description>
<cbc:Name>Laptop computer</cbc:Name>
<cac:SellersItemIdentification>
<cbc:ID>JB007</cbc:ID>
</cac:SellersItemIdentification>
<cac:StandardItemIdentification>
<cbc:ID schemeID="0088">1234567890124</cbc:ID>
</cac:StandardItemIdentification>
<cac:OriginCountry>
<cbc:IdentificationCode>DE</cbc:IdentificationCode>
</cac:OriginCountry>
<cac:CommodityClassification>
<cbc:ItemClassificationCode listID="MP">12344321</cbc:ItemClassificationCode>
</cac:CommodityClassification>
<cac:CommodityClassification>
<cbc:ItemClassificationCode listID="STI">65434568</cbc:ItemClassificationCode>
</cac:CommodityClassification>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>25</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
<cac:AdditionalItemProperty>
<cbc:Name>Color</cbc:Name>
<cbc:Value>Black</cbc:Value>
</cac:AdditionalItemProperty>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="NOK">1273</cbc:PriceAmount>
<cbc:BaseQuantity>1</cbc:BaseQuantity>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<cbc:Amount currencyID="NOK">227</cbc:Amount>
<cbc:BaseAmount currencyID="NOK">1500</cbc:BaseAmount>
</cac:AllowanceCharge>
</cac:Price>
</cac:InvoiceLine>
<cac:InvoiceLine>
<cbc:ID>2</cbc:ID>
<cbc:Note>Cover is slightly damaged.</cbc:Note>
<cbc:InvoicedQuantity unitCode="NAR">-1</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="NOK">-3.96</cbc:LineExtensionAmount>
<cbc:AccountingCost>BookingCode002</cbc:AccountingCost>
<cac:OrderLineReference>
<cbc:LineID>5</cbc:LineID>
</cac:OrderLineReference>
<cac:Item>
<cbc:Name>Returned "Advanced computing" book</cbc:Name>
<cac:SellersItemIdentification>
<cbc:ID>JB008</cbc:ID>
</cac:SellersItemIdentification>
<cac:StandardItemIdentification>
<cbc:ID schemeID="0088">1234567890125</cbc:ID>
</cac:StandardItemIdentification>
<cac:CommodityClassification>
<cbc:ItemClassificationCode listID="MP">32344324</cbc:ItemClassificationCode>
</cac:CommodityClassification>
<cac:CommodityClassification>
<cbc:ItemClassificationCode listID="STI">65434567</cbc:ItemClassificationCode>
</cac:CommodityClassification>
<cac:ClassifiedTaxCategory>
<cbc:ID schemeID="UNCL5305">S</cbc:ID>
<cbc:Percent>15</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="NOK">3.96</cbc:PriceAmount>
<cbc:BaseQuantity>1</cbc:BaseQuantity>
</cac:Price>
</cac:InvoiceLine>
<cac:InvoiceLine>
<cbc:ID>3</cbc:ID>
<cbc:InvoicedQuantity unitCode="NAR">2</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="NOK">4.96</cbc:LineExtensionAmount>
<cbc:AccountingCost>BookingCode003</cbc:AccountingCost>
<cac:OrderLineReference>
<cbc:LineID>3</cbc:LineID>
</cac:OrderLineReference>
<cac:Item>
<cbc:Name>"Computing for dummies" book</cbc:Name>
<cac:SellersItemIdentification>
<cbc:ID>JB009</cbc:ID>
</cac:SellersItemIdentification>
<cac:StandardItemIdentification>
<cbc:ID schemeID="0088">1234567890126</cbc:ID>
</cac:StandardItemIdentification>
<cac:CommodityClassification>
<cbc:ItemClassificationCode listID="MP">32344324</cbc:ItemClassificationCode>
</cac:CommodityClassification>
<cac:CommodityClassification>
<cbc:ItemClassificationCode listID="STI">65434566</cbc:ItemClassificationCode>
</cac:CommodityClassification>
<cac:ClassifiedTaxCategory>
<cbc:ID schemeID="UNCL5305">S</cbc:ID>
<cbc:Percent>15</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="NOK">2.48</cbc:PriceAmount>
<cbc:BaseQuantity>1</cbc:BaseQuantity>
<cac:AllowanceCharge>
<cbc:ChargeIndicator>false</cbc:ChargeIndicator>
<cbc:Amount currencyID="NOK">0.27</cbc:Amount>
<cbc:BaseAmount currencyID="NOK">2.75</cbc:BaseAmount>
</cac:AllowanceCharge>
</cac:Price>
</cac:InvoiceLine>
<cac:InvoiceLine>
<cbc:ID>4</cbc:ID>
<cbc:InvoicedQuantity unitCode="NAR">-1</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="NOK">-25</cbc:LineExtensionAmount>
<cbc:AccountingCost>BookingCode004</cbc:AccountingCost>
<cac:OrderLineReference>
<cbc:LineID>2</cbc:LineID>
</cac:OrderLineReference>
<cac:Item>
<cbc:Name>Returned IBM 5150 desktop</cbc:Name>
<cac:SellersItemIdentification>
<cbc:ID>JB010</cbc:ID>
</cac:SellersItemIdentification>
<cac:StandardItemIdentification>
<cbc:ID schemeID="0088">1234567890127</cbc:ID>
</cac:StandardItemIdentification>
<cac:CommodityClassification>
<cbc:ItemClassificationCode listID="MP">12344322</cbc:ItemClassificationCode>
</cac:CommodityClassification>
<cac:CommodityClassification>
<cbc:ItemClassificationCode listID="STI">65434565</cbc:ItemClassificationCode>
</cac:CommodityClassification>
<cac:ClassifiedTaxCategory>
<cbc:ID schemeID="UNCL5305">E</cbc:ID>
<cbc:Percent>0</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="NOK">25</cbc:PriceAmount>
<cbc:BaseQuantity>1</cbc:BaseQuantity>
</cac:Price>
</cac:InvoiceLine>
<cac:InvoiceLine>
<cbc:ID>5</cbc:ID>
<cbc:InvoicedQuantity unitCode="MTR">250</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="NOK">187.5</cbc:LineExtensionAmount>
<cbc:AccountingCost>BookingCode005</cbc:AccountingCost>
<cac:OrderLineReference>
<cbc:LineID>4</cbc:LineID>
</cac:OrderLineReference>
<cac:Item>
<cbc:Name>Network cable</cbc:Name>
<cac:SellersItemIdentification>
<cbc:ID>JB011</cbc:ID>
</cac:SellersItemIdentification>
<cac:StandardItemIdentification>
<cbc:ID schemeID="0088">1234567890128</cbc:ID>
</cac:StandardItemIdentification>
<cac:CommodityClassification>
<cbc:ItemClassificationCode listID="MP">12344325</cbc:ItemClassificationCode>
</cac:CommodityClassification>
<cac:CommodityClassification>
<cbc:ItemClassificationCode listID="STI">65434564</cbc:ItemClassificationCode>
</cac:CommodityClassification>
<cac:ClassifiedTaxCategory>
<cbc:ID schemeID="UNCL5305">S</cbc:ID>
<cbc:Percent>25</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
<cac:AdditionalItemProperty>
<cbc:Name>Type</cbc:Name>
<cbc:Value>Cat5</cbc:Value>
</cac:AdditionalItemProperty>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="NOK">0.75</cbc:PriceAmount>
<cbc:BaseQuantity>1</cbc:BaseQuantity>
</cac:Price>
</cac:InvoiceLine>
</Invoice>
+3
View File
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import test_ehf
+224
View File
@@ -0,0 +1,224 @@
# -*- coding: utf-8 -*-
from odoo.addons.account_edi.tests.common import AccountEdiTestCommon
from odoo.tests import tagged
from freezegun import freeze_time
@tagged('post_install_l10n', 'post_install', '-at_install')
class TestUBL(AccountEdiTestCommon):
@classmethod
def setUpClass(cls, chart_template_ref='l10n_no.no_chart_template', edi_format_ref='l10n_no_edi.edi_ehf_3'):
super().setUpClass(chart_template_ref=chart_template_ref, edi_format_ref=edi_format_ref)
cls.company_data['company'].partner_id.write({
'street': 'Archefstraat 42',
'zip': '1000',
'city': 'Amsterdam',
'country_id': cls.env.ref('base.no').id,
'l10n_no_bronnoysund_number': '987654325',
'vat': 'NO987654325MVA',
})
cls.partner_a.write({
'l10n_no_bronnoysund_number': '864234232',
'country_id': cls.env.ref('base.no').id,
'vat': 'NO864234232MVA',
})
bank_account = cls.env['res.partner.bank'].create({
'acc_number': '86011117947',
'partner_id': cls.partner_a.id,
})
cls.tax_sale_b.write({
'amount': 15
})
cls.invoice = cls.env['account.move'].create({
'partner_id': cls.partner_a.id,
'move_type': 'out_invoice',
'partner_bank_id': bank_account.id,
'invoice_date_due': '2020-12-16',
'invoice_line_ids': [
(0, 0, {
'product_id': cls.product_a.id,
'quantity': 150,
'price_unit': 250,
'discount': 10,
'tax_ids': [(6, 0, cls.tax_sale_a.ids)],
}),
(0, 0, {
'product_id': cls.product_b.id,
'quantity': 12,
'price_unit': 100,
'tax_ids': [(6, 0, cls.tax_sale_b.ids)],
}),
]
})
cls.expected_invoice_values = '''
<Invoice xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2" xmlns="urn:oasis:names:specification:ubl:schema:xsd:Invoice-2" xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2">
<cbc:CustomizationID>urn:cen.eu:en16931:2017#compliant#urn:fdc:peppol.eu:2017:poacc:billing:3.0</cbc:CustomizationID>
<cbc:ProfileID>urn:fdc:peppol.eu:2017:poacc:billing:01:1.0</cbc:ProfileID>
<cbc:ID>INV/2020/00001</cbc:ID>
<cbc:IssueDate>2020-12-16</cbc:IssueDate>
<cbc:DueDate>2020-12-16</cbc:DueDate>
<cbc:InvoiceTypeCode>380</cbc:InvoiceTypeCode>
<cbc:DocumentCurrencyCode>NOK</cbc:DocumentCurrencyCode>
<cbc:BuyerReference>partner_a</cbc:BuyerReference>
<cac:AccountingSupplierParty>
<cac:Party>
<cbc:EndpointID schemeID="0192">987654325</cbc:EndpointID>
<cac:PartyName>
<cbc:Name>company_1_data</cbc:Name>
</cac:PartyName>
<cac:PostalAddress>
<cbc:StreetName>Archefstraat 42</cbc:StreetName>
<cbc:CityName>Amsterdam</cbc:CityName>
<cbc:PostalZone>1000</cbc:PostalZone>
<cac:Country>
<cbc:IdentificationCode>NO</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>NO987654325MVA</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyTaxScheme>
<cbc:CompanyID>Foretaksregisteret</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>TAX</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>company_1_data</cbc:RegistrationName>
</cac:PartyLegalEntity>
<cac:Contact>
<cbc:Name>company_1_data</cbc:Name>
</cac:Contact>
</cac:Party>
</cac:AccountingSupplierParty>
<cac:AccountingCustomerParty>
<cac:Party>
<cbc:EndpointID schemeID="0192">864234232</cbc:EndpointID>
<cac:PartyName>
<cbc:Name>partner_a</cbc:Name>
</cac:PartyName>
<cac:PostalAddress>
<cac:Country>
<cbc:IdentificationCode>NO</cbc:IdentificationCode>
</cac:Country>
</cac:PostalAddress>
<cac:PartyTaxScheme>
<cbc:CompanyID>NO864234232MVA</cbc:CompanyID>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:PartyTaxScheme>
<cac:PartyLegalEntity>
<cbc:RegistrationName>partner_a</cbc:RegistrationName>
</cac:PartyLegalEntity>
<cac:Contact>
<cbc:Name>partner_a</cbc:Name>
</cac:Contact>
</cac:Party>
</cac:AccountingCustomerParty>
<cac:PaymentMeans>
<cbc:PaymentMeansCode>31</cbc:PaymentMeansCode>
<cac:PayeeFinancialAccount>
<cbc:ID>86011117947</cbc:ID>
</cac:PayeeFinancialAccount>
</cac:PaymentMeans>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="NOK">8617.50</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="NOK">33750.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="NOK">8437.50</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>25.0</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal><cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="NOK">1200.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="NOK">180.00</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>15.0</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="NOK">34950.00</cbc:LineExtensionAmount>
<cbc:TaxExclusiveAmount currencyID="NOK">34950.00</cbc:TaxExclusiveAmount>
<cbc:TaxInclusiveAmount currencyID="NOK">43567.50</cbc:TaxInclusiveAmount>
<cbc:PrepaidAmount currencyID="NOK">0.00</cbc:PrepaidAmount>
<cbc:PayableAmount currencyID="NOK">43567.50</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<cac:InvoiceLine>
<cbc:ID>1</cbc:ID>
<cbc:Note>Discount (10.0 %)</cbc:Note>
<cbc:InvoicedQuantity unitCode="ZZ">150.0</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="NOK">33750.00</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Description>product_a</cbc:Description>
<cbc:Name>product_a</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>25.0</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="NOK">225.00</cbc:PriceAmount>
<cbc:BaseQuantity>150.0</cbc:BaseQuantity>
</cac:Price>
</cac:InvoiceLine>
<cac:InvoiceLine>
<cbc:ID>2</cbc:ID>
<cbc:InvoicedQuantity unitCode="ZZ">12.0</cbc:InvoicedQuantity>
<cbc:LineExtensionAmount currencyID="NOK">1200.00</cbc:LineExtensionAmount>
<cac:Item>
<cbc:Description>product_b</cbc:Description>
<cbc:Name>product_b</cbc:Name>
<cac:ClassifiedTaxCategory>
<cbc:ID>S</cbc:ID>
<cbc:Percent>15.0</cbc:Percent>
<cac:TaxScheme>
<cbc:ID>VAT</cbc:ID>
</cac:TaxScheme>
</cac:ClassifiedTaxCategory>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="NOK">100.00</cbc:PriceAmount>
<cbc:BaseQuantity>12.0</cbc:BaseQuantity>
</cac:Price>
</cac:InvoiceLine>
</Invoice>
'''
def test_ehf_import(self):
invoice = self.env['account.move'].with_context(default_move_type='in_invoice').create({})
invoice_count = self.env['account.move'].search_count([])
self.update_invoice_from_file('l10n_no_edi', 'test_xml_file', 'ehf_test.xml', invoice)
self.assertEqual(self.env['account.move'].search_count([]), invoice_count)
self.assertRecordValues(invoice, [{
'partner_id': self.partner_a.id,
'amount_total': 1801.78,
'amount_tax': 365.28,
}])
@freeze_time('2020-12-16')
def test_ehf_export(self):
self.assert_generated_file_equal(self.invoice, self.expected_invoice_values)