read_listdata() --> classmethod

This commit is contained in:
Frederik Jaeckel 2025-01-17 12:53:11 +01:00
parent cf98fdf2ad
commit 530f37a06b

View file

@ -7,6 +7,7 @@
import os.path import os.path
import json import json
import copy
from lxml import etree from lxml import etree
from datetime import datetime, date from datetime import datetime, date
from decimal import Decimal from decimal import Decimal
@ -633,6 +634,8 @@ class Incoming(metaclass=PoolMeta):
line.account = expense_accounts[0] line.account = expense_accounts[0]
# check if calculated 'amount' matches with amount from xml-data # check if calculated 'amount' matches with amount from xml-data
assert invoice.currency is not None
xml_amount = line_data.get('total', {}).pop('amount', None) xml_amount = line_data.get('total', {}).pop('amount', None)
if xml_amount is not None: if xml_amount is not None:
if xml_amount != line.get_amount(None): if xml_amount != line.get_amount(None):
@ -667,10 +670,43 @@ class Incoming(metaclass=PoolMeta):
'document_incoming_invoice_xml.msg_unused_linevalues'), 'document_incoming_invoice_xml.msg_unused_linevalues'),
json.dumps(line_data, cls=JSONEncoder, indent=3)]) json.dumps(line_data, cls=JSONEncoder, indent=3)])
line.note = '\n'.join(x for x in notes if x) line.note = '\n'.join(x for x in notes if x)
line.on_change_invoice() line.on_change_invoice()
return line return line
def _readxml_read_listdata(self, xmldata, xpth, xtag, key_list):
""" read list of values from xml
Args:
xmldata (xtree): xml-tree
xpth (list): list of xml-tags until index-counter
pos (int): position in list
xtag (str): xml-tag to read as list
key_list (list): [('<xtag>', '<key>')]
Returns:
list: list of dict
"""
if isinstance(xtag, str):
xtag = [xtag]
xpath_list = xpth + xtag
num_listitem = len(xmldata.xpath(
self._readxml_xpath(xpath_list), namespaces=xmldata.nsmap))
listdata = []
for x in range(1, num_listitem + 1):
values = {}
for list_item in key_list:
(xkey, key, xtype) = (
list_item if len(list_item) == 3
else tuple(list(list_item) + [None]))
value = self._readxml_getvalue(
xmldata, xpath_list + [x, xkey], vtype=xtype)
if value is not None:
values[key] = value
if values:
listdata.append(values)
return listdata
def _readxml_invoice_line(self, xmldata, xpth, pos): def _readxml_invoice_line(self, xmldata, xpth, pos):
""" read invoice-line from xml """ read invoice-line from xml
@ -682,43 +718,13 @@ class Incoming(metaclass=PoolMeta):
Returns: Returns:
dict: invoice line data dict: invoice line data
""" """
def read_listdata(xtag, key_list): xpath_line = xpth + [pos]
""" read list of values from xml
Args:
xtag (str): xml-tag to read as list
key_list (list): [('<xtag>', '<key>')]
Returns:
list: list of dict
"""
if isinstance(xtag, str):
xtag = [xtag]
xpath_list = xpth + [pos] + xtag
num_listitem = len(xmldata.xpath(
self._readxml_xpath(xpath_list), namespaces=xmldata.nsmap))
listdata = []
for x in range(1, num_listitem + 1):
values = {}
for list_item in key_list:
(xkey, key, xtype) = (
list_item if len(list_item) == 3
else tuple(list(list_item) + [None]))
value = self._readxml_getvalue(
xmldata, xpath_list + [x, xkey], vtype=xtype)
if value is not None:
values[key] = value
if values:
listdata.append(values)
return listdata
result = {'convert_note': []} result = {'convert_note': []}
result['line_no'] = self._readxml_getvalue(xmldata, xpth + [pos] + [ result['line_no'] = self._readxml_getvalue(xmldata, xpath_line + [
'ram:AssociatedDocumentLineDocument', 'ram:LineID']) 'ram:AssociatedDocumentLineDocument', 'ram:LineID'])
result['line_note'] = '\n'.join(self._readxml_getvalue( result['line_note'] = '\n'.join(self._readxml_getvalue(
xmldata, xpth + [pos] + [ xmldata, xpath_line + [
'ram:AssociatedDocumentLineDocument', 'ram:IncludedNote', 'ram:AssociatedDocumentLineDocument', 'ram:IncludedNote',
'ram:Content'], allow_list=True)) 'ram:Content'], allow_list=True))
@ -736,34 +742,38 @@ class Incoming(metaclass=PoolMeta):
('ram:ModelName', 'model_name'), ('ram:ModelName', 'model_name'),
('ram:OriginTradeCountry', 'trade_country') ('ram:OriginTradeCountry', 'trade_country')
]: ]:
result[key] = self._readxml_getvalue(xmldata, xpth + [pos] + [ result[key] = self._readxml_getvalue(xmldata, xpath_line + [
'ram:SpecifiedTradeProduct', xkey]) 'ram:SpecifiedTradeProduct', xkey])
# attributes of product # attributes of product
result['attributes'] = read_listdata([ result['attributes'] = self._readxml_read_listdata(
'ram:SpecifiedTradeProduct', xmldata, xpath_line, [
'ram:ApplicableProductCharacteristic'], [ 'ram:SpecifiedTradeProduct',
'ram:ApplicableProductCharacteristic'], [
('ram:TypeCode', 'code'), ('ram:TypeCode', 'code'),
('ram:Description', 'description'), ('ram:Description', 'description'),
('ram:ValueMeasure', 'uom'), ('ram:ValueMeasure', 'uom'),
('ram:ValueY', 'value')]) ('ram:ValueY', 'value')])
# classification of product # classification of product
result['classification'] = read_listdata([ result['classification'] = self._readxml_read_listdata(
'ram:SpecifiedTradeProduct', xmldata, xpath_line, [
'ram:DesignatedProductClassification'], [ 'ram:SpecifiedTradeProduct',
'ram:DesignatedProductClassification'], [
('ram:ClassCode', 'code'), ('ram:ClassCode', 'code'),
('ram:ClassName', 'name')]) ('ram:ClassName', 'name')])
# serial-numbers of product # serial-numbers of product
result['serialno'] = read_listdata([ result['serialno'] = self._readxml_read_listdata(
'ram:SpecifiedTradeProduct', xmldata, xpath_line, [
'ram:IndividualTradeProductInstance'], [ 'ram:SpecifiedTradeProduct',
'ram:IndividualTradeProductInstance'], [
('ram:BatchID', 'lot'), ('ram:BatchID', 'lot'),
('ram:SupplierAssignedSerialID', 'serial')]) ('ram:SupplierAssignedSerialID', 'serial')])
# referenced product # referenced product
result['refprod'] = read_listdata( result['refprod'] = self._readxml_read_listdata(
xmldata, xpath_line,
['ram:SpecifiedTradeProduct', 'ram:IncludedReferencedProduct'], [ ['ram:SpecifiedTradeProduct', 'ram:IncludedReferencedProduct'], [
('ram:ID', 'id'), ('ram:ID', 'id'),
('ram:GlobalID', 'global_id'), ('ram:GlobalID', 'global_id'),
@ -775,12 +785,13 @@ class Incoming(metaclass=PoolMeta):
]) ])
# net price # net price
xpath_netprice = xpth + [pos] + [ xpath_netprice = xpath_line + [
'ram:SpecifiedLineTradeAgreement', 'ram:NetPriceProductTradePrice'] 'ram:SpecifiedLineTradeAgreement', 'ram:NetPriceProductTradePrice']
if self._readxml_getvalue(xmldata, xpath_netprice): if self._readxml_getvalue(xmldata, xpath_netprice):
result['unit_net_price'] = read_listdata([ result['unit_net_price'] = self._readxml_read_listdata(
'ram:SpecifiedLineTradeAgreement', xmldata, xpath_line, [
'ram:NetPriceProductTradePrice'], [ 'ram:SpecifiedLineTradeAgreement',
'ram:NetPriceProductTradePrice'], [
('ram:ChargeAmount', 'amount', Decimal), ('ram:ChargeAmount', 'amount', Decimal),
('ram:BasisQuantity', 'basequantity', Decimal)])[0] ('ram:BasisQuantity', 'basequantity', Decimal)])[0]
# notice ignored field # notice ignored field
@ -791,13 +802,14 @@ class Incoming(metaclass=PoolMeta):
xpath_netprice + ['ram:AppliedTradeAllowanceCharge'])) xpath_netprice + ['ram:AppliedTradeAllowanceCharge']))
# gross price # gross price
xpath_grossprice = xpth + [pos] + [ xpath_grossprice = xpath_line + [
'ram:SpecifiedLineTradeAgreement', 'ram:SpecifiedLineTradeAgreement',
'ram:GrossPriceProductTradePrice'] 'ram:GrossPriceProductTradePrice']
if self._readxml_getvalue(xmldata, xpath_grossprice): if self._readxml_getvalue(xmldata, xpath_grossprice):
result['unit_gross_price'] = read_listdata([ result['unit_gross_price'] = self._readxml_read_listdata(
'ram:SpecifiedLineTradeAgreement', xmldata, xpath_line, [
'ram:GrossPriceProductTradePrice'], [ 'ram:SpecifiedLineTradeAgreement',
'ram:GrossPriceProductTradePrice'], [
('ram:ChargeAmount', 'amount', Decimal), ('ram:ChargeAmount', 'amount', Decimal),
('ram:BasisQuantity', 'basequantity', Decimal)])[0] ('ram:BasisQuantity', 'basequantity', Decimal)])[0]
# notice ignored field # notice ignored field
@ -809,9 +821,10 @@ class Incoming(metaclass=PoolMeta):
['ram:AppliedTradeAllowanceCharge'])) ['ram:AppliedTradeAllowanceCharge']))
# quantity # quantity
xpath_quantity = xpth + [pos] + ['ram:SpecifiedLineTradeDelivery'] xpath_quantity = xpath_line + ['ram:SpecifiedLineTradeDelivery']
result['quantity'] = read_listdata( result['quantity'] = self._readxml_read_listdata(
['ram:SpecifiedLineTradeDelivery'], [ xmldata, xpath_line, [
'ram:SpecifiedLineTradeDelivery'], [
('ram:BilledQuantity', 'billed', Decimal), ('ram:BilledQuantity', 'billed', Decimal),
('ram:ChargeFreeQuantity', 'chargefree', Decimal), ('ram:ChargeFreeQuantity', 'chargefree', Decimal),
('ram:PackageQuantity', 'package', Decimal), ('ram:PackageQuantity', 'package', Decimal),
@ -829,8 +842,8 @@ class Incoming(metaclass=PoolMeta):
'skip: ' + self._readxml_xpath(xp_to_check)) 'skip: ' + self._readxml_xpath(xp_to_check))
# taxes # taxes
xpath_trade = xpth + [pos] + ['ram:SpecifiedLineTradeSettlement'] xpath_trade = xpath_line + ['ram:SpecifiedLineTradeSettlement']
result['taxes'] = read_listdata([ result['taxes'] = self._readxml_read_listdata(xmldata, xpath_line, [
'ram:SpecifiedLineTradeSettlement', 'ram:SpecifiedLineTradeSettlement',
'ram:ApplicableTradeTax'], [ 'ram:ApplicableTradeTax'], [
('ram:CalculatedAmount', 'amount', Decimal), ('ram:CalculatedAmount', 'amount', Decimal),
@ -846,7 +859,7 @@ class Incoming(metaclass=PoolMeta):
('ram:RateApplicablePercent', 'percent', Decimal)]) ('ram:RateApplicablePercent', 'percent', Decimal)])
# total amounts # total amounts
result['total'] = read_listdata([ result['total'] = self._readxml_read_listdata(xmldata, xpath_line, [
'ram:SpecifiedLineTradeSettlement', 'ram:SpecifiedLineTradeSettlement',
'ram:SpecifiedTradeSettlementLineMonetarySummation'], [ 'ram:SpecifiedTradeSettlementLineMonetarySummation'], [
('ram:LineTotalAmount', 'amount', Decimal), ('ram:LineTotalAmount', 'amount', Decimal),