line: import taxes, notes
This commit is contained in:
parent
18103d8e80
commit
174887f87e
4 changed files with 103 additions and 25 deletions
95
document.py
95
document.py
|
@ -6,15 +6,18 @@
|
|||
# https://portal3.gefeg.com/projectdata/invoice/deliverables/installed/publishingproject/xrechnung%20%28german%20cius%29/xrechnung_crossindustryinvoice%3B%202017-10-18.scm/html/021.htm?https://portal3.gefeg.com/projectdata/invoice/deliverables/installed/publishingproject/xrechnung%20%28german%20cius%29/xrechnung_crossindustryinvoice%3B%202017-10-18.scm/html/025.htm
|
||||
|
||||
import os.path
|
||||
import json
|
||||
from lxml import etree
|
||||
from datetime import datetime, date
|
||||
from decimal import Decimal
|
||||
from trytond.pool import PoolMeta, Pool
|
||||
from trytond.report import Report
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.exceptions import UserError
|
||||
from trytond.i18n import gettext
|
||||
from trytond.model import fields
|
||||
from trytond.pyson import Eval
|
||||
from trytond.protocols.jsonrpc import JSONEncoder
|
||||
|
||||
|
||||
xml_types = [
|
||||
|
@ -410,21 +413,18 @@ class Incoming(metaclass=PoolMeta):
|
|||
# get number of invoice-lines
|
||||
num_lines = len(xmltree.xpath(
|
||||
self._readxml_xpath(xpath_line_item), namespaces=xmltree.nsmap))
|
||||
print('\n## num_lines:', num_lines)
|
||||
lines_data = []
|
||||
for x in range(1, num_lines + 1):
|
||||
lines_data.append(
|
||||
self._readxml_invoice_line(xmltree, xpath_line_item, x))
|
||||
print('\n## lines_data:', lines_data)
|
||||
lines = [
|
||||
self._readxml_getinvoiceline(invoice, x)
|
||||
for x in lines_data]
|
||||
for x in range(len(lines)):
|
||||
lines[x].sequence = x + 1
|
||||
invoice.lines = lines
|
||||
for pos in range(len(lines)):
|
||||
invoice.lines[pos].on_change_account()
|
||||
invoice.on_change_lines()
|
||||
|
||||
raise ValueError('stop')
|
||||
invoice.on_change_lines()
|
||||
return invoice
|
||||
|
||||
def _readxml_getinvoiceline(self, invoice, line_data):
|
||||
|
@ -437,10 +437,11 @@ class Incoming(metaclass=PoolMeta):
|
|||
pool = Pool()
|
||||
Line = pool.get('account.invoice.line')
|
||||
Tax = pool.get('account.tax')
|
||||
Uom = pool.get('product.uom')
|
||||
Configuration = pool.get('document.incoming.configuration')
|
||||
ModelData = pool.get('ir.model.data')
|
||||
|
||||
cfg1 = Configuration.get_singleton()
|
||||
print('\n## line_data-vor:', line_data)
|
||||
|
||||
def get_tax_by_percent(percent):
|
||||
""" search for tax by percent of supplier tax
|
||||
|
@ -453,7 +454,7 @@ class Incoming(metaclass=PoolMeta):
|
|||
no matching tax was found
|
||||
|
||||
Returns:
|
||||
record: model 'account.tax
|
||||
tuple: (model 'account.tax, model 'product.category')
|
||||
"""
|
||||
if not (cfg1 and cfg1.product_category):
|
||||
raise UserError(gettext(
|
||||
|
@ -466,23 +467,34 @@ class Incoming(metaclass=PoolMeta):
|
|||
current_taxes = Tax.compute(
|
||||
[s_tax], Decimal('1'), 1.0, invoice.invoice_date)
|
||||
|
||||
# deny result of multiple or none taxes
|
||||
# skip result of multiple or none taxes
|
||||
if len(current_taxes) != 1:
|
||||
continue
|
||||
|
||||
if (current_taxes[0]['tax'].rate == percent) and (
|
||||
current_taxes[0]['tax'].type == 'percentage'):
|
||||
# found it
|
||||
return s_tax
|
||||
return (s_tax, pcat)
|
||||
|
||||
# no product category found
|
||||
raise UserError(gettext(
|
||||
'document_incoming_invoice_xml.msg_no_prodcat_found',
|
||||
percent=percent * Decimal('100.0')))
|
||||
|
||||
# uom
|
||||
xml_uom = Uom(ModelData.get_id('product', 'uom_unit'))
|
||||
for x_attr in line_data.get('attributes', []):
|
||||
x_uom = x_attr.get('uom', None)
|
||||
if not x_uom:
|
||||
continue
|
||||
units = Uom.search([('symbol', '=', x_uom)])
|
||||
if units:
|
||||
xml_uom = units[0]
|
||||
|
||||
line = Line(
|
||||
invoice=invoice,
|
||||
type='line',
|
||||
unit=xml_uom,
|
||||
quantity=line_data.get('quantity', {}).pop('billed', None),
|
||||
unit_price=line_data.get('unit_net_price', {}).pop('amount', None))
|
||||
line_no = line_data.pop('line_no', None)
|
||||
|
@ -494,40 +506,73 @@ class Incoming(metaclass=PoolMeta):
|
|||
line_data.pop('description', None)]
|
||||
line.description = '; '.join([x for x in descr if x])
|
||||
|
||||
# taxes
|
||||
taxes = []
|
||||
line_taxes = line_data.get('taxes', [])
|
||||
# get taxes and product-category from settings
|
||||
tax_and_category = []
|
||||
line_taxes = line_data.pop('taxes', [])
|
||||
for x in line_taxes:
|
||||
percent = x.get('percent', None)
|
||||
if (x.get('type', '') == 'VAT') and (percent is not None):
|
||||
percent = percent / Decimal('100')
|
||||
taxes.append(get_tax_by_percent(percent))
|
||||
# remove not-found-taxes
|
||||
taxes = [x for x in taxes if x]
|
||||
tax_and_category.append(get_tax_by_percent(percent))
|
||||
|
||||
# check result
|
||||
if len(line_taxes) != len(taxes):
|
||||
if len(line_taxes) != len(tax_and_category):
|
||||
raise UserError(gettext(
|
||||
'document_incoming_invoice_xml.msg_numtaxes_invalid',
|
||||
descr=line.description,
|
||||
taxin='|'.join([
|
||||
str(x.get('percent', '-')) for x in line_taxes]),
|
||||
taxout='|'.join([
|
||||
str(x.rate * Decimal('100.0')) for x in taxes])))
|
||||
line.taxes = taxes
|
||||
str(x[0].rate * Decimal('100.0'))
|
||||
for x in tax_and_category])))
|
||||
|
||||
#line.account =
|
||||
# set taxes and account for product
|
||||
line.taxes = [x[0] for x in tax_and_category]
|
||||
expense_accounts = [
|
||||
x[1].account_expense
|
||||
for x in tax_and_category if x[1].account_expense]
|
||||
if expense_accounts:
|
||||
line.account = expense_accounts[0]
|
||||
|
||||
# check if calculated 'amount' matches with amount from xml-data
|
||||
xml_amount = line_data.get('total', {}).pop('amount', None)
|
||||
if xml_amount is not None:
|
||||
if xml_amount != line.get_amount(None):
|
||||
raise UserError(gettext(
|
||||
'document_incoming_invoice_xml.msg_line_amount_invalid',
|
||||
linetxt=line.description,
|
||||
calcsum=Report.format_currency(
|
||||
line.get_amount(None), None, invoice.currency),
|
||||
xmlsum=Report.format_currency(
|
||||
xml_amount, None, invoice.currency)))
|
||||
|
||||
# cleanup used values
|
||||
for x in ['quantity', 'unit_net_price']:
|
||||
for x in ['quantity', 'unit_net_price', 'total']:
|
||||
if not line_data.get(x, {}):
|
||||
del line_data[x]
|
||||
|
||||
# note of line
|
||||
notes = [line_data.pop('line_note', None)]
|
||||
# skipped xml-data
|
||||
convert_notes = line_data.pop('convert_note', None)
|
||||
if convert_notes:
|
||||
notes.extend(
|
||||
[' '] +
|
||||
[gettext('document_incoming_invoice_xml.msg_convert_note')] +
|
||||
convert_notes
|
||||
if isinstance(convert_notes, list) else [str(convert_notes)])
|
||||
# values not used to create invoice-line
|
||||
if line_data:
|
||||
notes.extend([
|
||||
' ',
|
||||
gettext(
|
||||
'document_incoming_invoice_xml.msg_unused_linevalues'),
|
||||
json.dumps(line_data, cls=JSONEncoder, indent=3)])
|
||||
line.note = '\n'.join(x for x in notes if x)
|
||||
|
||||
line.on_change_invoice()
|
||||
|
||||
print('-- line_data-nach:', line_data, (line,))
|
||||
return line
|
||||
|
||||
|
||||
def _readxml_invoice_line(self, xmldata, xpth, pos):
|
||||
""" read invoice-line from xml
|
||||
|
||||
|
@ -712,7 +757,7 @@ class Incoming(metaclass=PoolMeta):
|
|||
('ram:TaxTotalAmount', 'tax', Decimal),
|
||||
('ram:GrandTotalAmount', 'grand', Decimal),
|
||||
('ram:TotalAllowanceChargeAmount', 'feecharge', Decimal),
|
||||
])
|
||||
])[0]
|
||||
|
||||
# notice ignored fields
|
||||
for x in [
|
||||
|
|
12
locale/de.po
12
locale/de.po
|
@ -34,6 +34,18 @@ msgctxt "model:ir.message,text:msg_numtaxes_invalid"
|
|||
msgid "Invalid number of taxes in line %(descr)s: wanted='%(taxin)s', found='%(taxout)s'."
|
||||
msgstr "Ungültige Anzahl Steuern in Zeile %(descr)s: gesucht='%(taxin)s', gefunden='%(taxout)s'."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_line_amount_invalid"
|
||||
msgid "The calculated sum '%(calcsum)s' of the line '%(linetxt)s' differs from the value '%(xmlsum)s' from the XML data."
|
||||
msgstr "Die berechnete Summe '%(calcsum)s' der Zeile '%(linetxt)s' weicht vom Wert '%(xmlsum)s' aus den XML-Daten ab."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_convert_note"
|
||||
msgid "The following XML data has not been imported:"
|
||||
msgstr "Folgende XML-Daten wurden nicht importiert:"
|
||||
|
||||
msgctxt "model:ir.message,text:msg_unused_linevalues"
|
||||
msgid "The following data was not used to generate the invoice line:"
|
||||
msgstr "Die folgenden Daten wurden für die Erzeugung der Rechnungszeile nicht verwendet:"
|
||||
|
||||
|
||||
###################################
|
||||
# document.incoming.configuration #
|
||||
|
|
12
locale/en.po
12
locale/en.po
|
@ -30,6 +30,18 @@ msgctxt "model:ir.message,text:msg_numtaxes_invalid"
|
|||
msgid "Invalid number of taxes in line %(descr)s: wanted='%(taxin)s', found='%(taxout)s'."
|
||||
msgstr "Invalid number of taxes in line %(descr)s: wanted='%(taxin)s', found='%(taxout)s'."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_line_amount_invalid"
|
||||
msgid "The calculated sum '%(calcsum)s' of the line '%(linetxt)s' differs from the value '%(xmlsum)s' from the XML data."
|
||||
msgstr "The calculated sum '%(calcsum)s' of the line '%(linetxt)s' differs from the value '%(xmlsum)s' from the XML data."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_convert_note"
|
||||
msgid "The following XML data has not been imported:"
|
||||
msgstr "The following XML data has not been imported:"
|
||||
|
||||
msgctxt "model:ir.message,text:msg_unused_linevalues"
|
||||
msgid "The following data was not used to generate the invoice line:"
|
||||
msgstr "The following data was not used to generate the invoice line:"
|
||||
|
||||
msgctxt "field:document.incoming.configuration,create_supplier:"
|
||||
msgid "Create Supplier Party"
|
||||
msgstr "Create Supplier Party"
|
||||
|
|
|
@ -26,6 +26,15 @@
|
|||
<record model="ir.message" id="msg_numtaxes_invalid">
|
||||
<field name="text">Invalid number of taxes in line %(descr)s: wanted='%(taxin)s', found='%(taxout)s'.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_line_amount_invalid">
|
||||
<field name="text">The calculated sum '%(calcsum)s' of the line '%(linetxt)s' differs from the value '%(xmlsum)s' from the XML data.</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_convert_note">
|
||||
<field name="text">The following XML data was not used:</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_unused_linevalues">
|
||||
<field name="text">The following data was not used to generate the invoice line:</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</tryton>
|
||||
|
|
Loading…
Reference in a new issue