read parties of supplier+company from xml + tests
This commit is contained in:
parent
8a48fb7236
commit
0a4e933188
6 changed files with 338 additions and 13 deletions
201
document.py
201
document.py
|
@ -8,7 +8,7 @@
|
||||||
import os.path
|
import os.path
|
||||||
from lxml import etree
|
from lxml import etree
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from trytond.pool import PoolMeta
|
from trytond.pool import PoolMeta, Pool
|
||||||
from trytond.transaction import Transaction
|
from trytond.transaction import Transaction
|
||||||
from trytond.exceptions import UserError
|
from trytond.exceptions import UserError
|
||||||
from trytond.i18n import gettext
|
from trytond.i18n import gettext
|
||||||
|
@ -116,7 +116,9 @@ class Incoming(metaclass=PoolMeta):
|
||||||
if not allow_list:
|
if not allow_list:
|
||||||
break
|
break
|
||||||
if not allow_list:
|
if not allow_list:
|
||||||
return result[0]
|
if result:
|
||||||
|
return result[0]
|
||||||
|
return None
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _readxml_getattrib(self, xmltree, tags, attrib, vtype=None):
|
def _readxml_getattrib(self, xmltree, tags, attrib, vtype=None):
|
||||||
|
@ -141,6 +143,150 @@ class Incoming(metaclass=PoolMeta):
|
||||||
result = vtype(result)
|
result = vtype(result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def _readxml_find_party(self, party_data):
|
||||||
|
""" find party by search with data from xml-file
|
||||||
|
|
||||||
|
Args:
|
||||||
|
party_data (dict): data of party read from xml
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: id of party or None
|
||||||
|
"""
|
||||||
|
pool = Pool()
|
||||||
|
Party = pool.get('party.party')
|
||||||
|
Address = pool.get('party.address')
|
||||||
|
|
||||||
|
if party_data['name']:
|
||||||
|
query = [(
|
||||||
|
'name', 'ilike',
|
||||||
|
'%%%(name)s%%' % {'name': party_data['name']})]
|
||||||
|
|
||||||
|
if len(set({'postal_code', 'street', 'city'}).intersection(
|
||||||
|
set(party_data.keys()))) == 3:
|
||||||
|
# ignore capitalization
|
||||||
|
address_sql = Address.search([
|
||||||
|
('city', 'ilike', party_data['city']),
|
||||||
|
('postal_code', '=', party_data['postal_code']),
|
||||||
|
('street', 'ilike',
|
||||||
|
party_data['street'].split('\n')[0] + '%')],
|
||||||
|
query=True)
|
||||||
|
query.append(('addresses', 'in', address_sql))
|
||||||
|
party = Party.search(query)
|
||||||
|
if party:
|
||||||
|
# we use this party if its a exact match
|
||||||
|
if len(party) == 1:
|
||||||
|
return party[0].id
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _readxml_create_party(self, partydata):
|
||||||
|
""" create party with data from xml
|
||||||
|
|
||||||
|
Args:
|
||||||
|
partydata (dict): data of party, read from xml
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
int: id of created party
|
||||||
|
"""
|
||||||
|
pool = Pool()
|
||||||
|
Party = pool.get('party.party')
|
||||||
|
Invoice = pool.get('account.invoice')
|
||||||
|
Company = pool.get('company.company')
|
||||||
|
|
||||||
|
if not partydata['name']:
|
||||||
|
return None
|
||||||
|
|
||||||
|
to_create = {'name': partydata['name']}
|
||||||
|
address = {
|
||||||
|
x: partydata[x]
|
||||||
|
for x in ['street', 'postal_code', 'city', 'country',
|
||||||
|
'subdivision']
|
||||||
|
if x in partydata.keys()}
|
||||||
|
|
||||||
|
# if no country, we use the company-country
|
||||||
|
if 'country' not in address.keys():
|
||||||
|
company = Invoice.default_company()
|
||||||
|
if company:
|
||||||
|
company = Company(company)
|
||||||
|
company_address = company.party.address_get()
|
||||||
|
if company_address and company_address.country:
|
||||||
|
address['country'] = company_address.country.id
|
||||||
|
if address:
|
||||||
|
to_create['addresses'] = [('create', [address])]
|
||||||
|
|
||||||
|
party, = Party.create([to_create])
|
||||||
|
return party.id
|
||||||
|
|
||||||
|
def _readxml_party_data(self, xmltree, tags, create_party=False):
|
||||||
|
""" read party data
|
||||||
|
|
||||||
|
Args:
|
||||||
|
xmltree (xmldata): XML-tree
|
||||||
|
tags (list): tags to build xpath
|
||||||
|
create_party (boolean, optional): create party if not found
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
dict: data of party
|
||||||
|
"""
|
||||||
|
pool = Pool()
|
||||||
|
Country = pool.get('country.country')
|
||||||
|
SubDivision = pool.get('country.subdivision')
|
||||||
|
|
||||||
|
result = {}
|
||||||
|
# name
|
||||||
|
result['name'] = self._readxml_getvalue(
|
||||||
|
xmltree, tags + ['ram:Name'])
|
||||||
|
result['postal_code'] = self._readxml_getvalue(
|
||||||
|
xmltree, tags + ['ram:PostalTradeAddress', 'ram:PostcodeCode'])
|
||||||
|
if not result['postal_code']:
|
||||||
|
del result['postal_code']
|
||||||
|
|
||||||
|
# address, max. 3 lines
|
||||||
|
result['street'] = [self._readxml_getvalue(
|
||||||
|
xmltree, tags + ['ram:PostalTradeAddress', 'ram:LineOne'])]
|
||||||
|
result['street'].append(self._readxml_getvalue(
|
||||||
|
xmltree, tags + ['ram:PostalTradeAddress', 'ram:LineTwo']))
|
||||||
|
result['street'].append(self._readxml_getvalue(
|
||||||
|
xmltree, tags + ['ram:PostalTradeAddress', 'ram:LineThree']))
|
||||||
|
result['street'] = '\n'.join([x for x in result['street'] if x])
|
||||||
|
if not result['street']:
|
||||||
|
del result['street']
|
||||||
|
|
||||||
|
# city
|
||||||
|
result['city'] = self._readxml_getvalue(
|
||||||
|
xmltree, tags + ['ram:PostalTradeAddress', 'ram:CityName'])
|
||||||
|
if not result['city']:
|
||||||
|
del result['city']
|
||||||
|
|
||||||
|
# country
|
||||||
|
country_code = self._readxml_getvalue(
|
||||||
|
xmltree,
|
||||||
|
tags + ['ram:PostalTradeAddress', 'ram:CountryID'])
|
||||||
|
if country_code:
|
||||||
|
country = Country.search([('code', '=', country_code.upper())])
|
||||||
|
if country:
|
||||||
|
result['country'] = country[0].id
|
||||||
|
|
||||||
|
# subdivision
|
||||||
|
subdivision = self._readxml_getvalue(
|
||||||
|
xmltree,
|
||||||
|
tags + ['ram:PostalTradeAddress', 'ram:CountrySubDivisionName'])
|
||||||
|
if subdivision and ('country' in result.keys()):
|
||||||
|
subdiv = SubDivision.search([
|
||||||
|
('name', '=', subdivision),
|
||||||
|
('country', '=', result['country'])])
|
||||||
|
if subdiv:
|
||||||
|
result['subdivision'] = subdiv[0].id
|
||||||
|
|
||||||
|
party_id = self._readxml_find_party(result)
|
||||||
|
if party_id:
|
||||||
|
result['party'] = party_id
|
||||||
|
else:
|
||||||
|
if create_party:
|
||||||
|
party_id = self._readxml_create_party(result)
|
||||||
|
if party_id:
|
||||||
|
result['party'] = party_id
|
||||||
|
return result
|
||||||
|
|
||||||
def _readxml_facturx_extended(self, invoice, xmltree):
|
def _readxml_facturx_extended(self, invoice, xmltree):
|
||||||
""" read factur-x extended
|
""" read factur-x extended
|
||||||
|
|
||||||
|
@ -150,6 +296,10 @@ class Incoming(metaclass=PoolMeta):
|
||||||
Returns:
|
Returns:
|
||||||
record: model account.invoice
|
record: model account.invoice
|
||||||
"""
|
"""
|
||||||
|
Configuration = Pool().get('document.incoming.configuration')
|
||||||
|
|
||||||
|
config = Configuration.get_singleton()
|
||||||
|
|
||||||
# check invoice-type:
|
# check invoice-type:
|
||||||
# allowed codes 380 incoice, 381 credit note
|
# allowed codes 380 incoice, 381 credit note
|
||||||
inv_code = self._readxml_getvalue(xmltree, [
|
inv_code = self._readxml_getvalue(xmltree, [
|
||||||
|
@ -189,13 +339,46 @@ class Incoming(metaclass=PoolMeta):
|
||||||
if note_list:
|
if note_list:
|
||||||
invoice.description = note_list[0].get('Content', None)
|
invoice.description = note_list[0].get('Content', None)
|
||||||
invoice.comment = '\n'.join([
|
invoice.comment = '\n'.join([
|
||||||
'%(code)s%(subj)s%(msg)s' % {
|
'%(code)s%(subj)s%(msg)s' % {
|
||||||
'code': ('Code=%s, ' % x.get('ContentCode', ''))
|
'code': ('Code=%s, ' % x.get('ContentCode', ''))
|
||||||
if x.get('ContentCode', '') else '',
|
if x.get('ContentCode', '') else '',
|
||||||
'subj': ('Subject=%s, ' % x.get('SubjectCode', ''))
|
'subj': ('Subject=%s, ' % x.get('SubjectCode', ''))
|
||||||
if x.get('SubjectCode', '') else '',
|
if x.get('SubjectCode', '') else '',
|
||||||
'msg': x.get('Content', ''),
|
'msg': x.get('Content', ''),
|
||||||
} for x in note_list[1:]])
|
} for x in note_list[1:]])
|
||||||
|
|
||||||
|
# supplier party
|
||||||
|
add_party = config and config.create_supplier
|
||||||
|
seller_party = self._readxml_party_data(xmltree, [
|
||||||
|
'rsm:CrossIndustryInvoice', 'rsm:SupplyChainTradeTransaction',
|
||||||
|
'ram:ApplicableHeaderTradeAgreement',
|
||||||
|
'ram:SellerTradeParty'], create_party=add_party)
|
||||||
|
if seller_party:
|
||||||
|
if 'party' in seller_party.keys():
|
||||||
|
invoice.party = seller_party['party']
|
||||||
|
invoice.on_change_party()
|
||||||
|
else:
|
||||||
|
raise UserError(gettext(
|
||||||
|
'document_incoming_invoice_xml.msg_no_supplierparty',
|
||||||
|
partytxt=', '.join([
|
||||||
|
seller_party[x].replace('\n', '; ')
|
||||||
|
for x in seller_party.keys()])))
|
||||||
|
|
||||||
|
# company party
|
||||||
|
buyer_party = self._readxml_party_data(xmltree, [
|
||||||
|
'rsm:CrossIndustryInvoice', 'rsm:SupplyChainTradeTransaction',
|
||||||
|
'ram:ApplicableHeaderTradeAgreement',
|
||||||
|
'ram:BuyerTradeParty'], create_party=False)
|
||||||
|
# check if we found our company
|
||||||
|
if config and not config.accept_other_company:
|
||||||
|
company_party_id = self._readxml_find_party(buyer_party)
|
||||||
|
if not (company_party_id and
|
||||||
|
(company_party_id == self.company.party.id)):
|
||||||
|
raise UserError(gettext(
|
||||||
|
'document_incoming_invoice_xml.msg_not_our_company',
|
||||||
|
partytxt=', '.join([
|
||||||
|
buyer_party[x].replace('\n', '; ')
|
||||||
|
for x in buyer_party.keys()])))
|
||||||
|
|
||||||
return invoice
|
return invoice
|
||||||
|
|
||||||
|
|
28
locale/de.po
28
locale/de.po
|
@ -13,3 +13,31 @@ msgstr "XML import für %(xmltype)s nicht implementiert."
|
||||||
msgctxt "model:ir.message,text:msg_convert_error"
|
msgctxt "model:ir.message,text:msg_convert_error"
|
||||||
msgid "Conversion error: %(msg)s."
|
msgid "Conversion error: %(msg)s."
|
||||||
msgstr "Konvertierfehler: %(msg)s."
|
msgstr "Konvertierfehler: %(msg)s."
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,text:msg_no_supplierparty"
|
||||||
|
msgid "Supplier party '%(partytxt)s' not found. Auto-creation is currently turned off."
|
||||||
|
msgstr "Lieferantenpartei '%(partytxt)s' nicht gefunden. Das automatische Erstellen ist derzeit ausgeschaltet."
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,text:msg_not_our_company"
|
||||||
|
msgid "The buyer party '%(partytxt)s' differs from the corporate party."
|
||||||
|
msgstr "Die Käuferpartei '%(partytxt)s' weicht von der Unternehmenspartei ab."
|
||||||
|
|
||||||
|
|
||||||
|
###################################
|
||||||
|
# document.incoming.configuration #
|
||||||
|
###################################
|
||||||
|
msgctxt "field:document.incoming.configuration,create_supplier:"
|
||||||
|
msgid "Create Supplier Party"
|
||||||
|
msgstr "Lieferantenpartei erstellen"
|
||||||
|
|
||||||
|
msgctxt "help:document.incoming.configuration,create_supplier:"
|
||||||
|
msgid "Creates the vendor party if it does not exist. Generates an import error when turned off and the party is missing."
|
||||||
|
msgstr "Erstellt die Lieferantenpartei, sofern sie nicht vorhanden ist. Erzeugt einem Importfehler wenn ausgeschaltet und die Partei fehlt."
|
||||||
|
|
||||||
|
msgctxt "field:document.incoming.configuration,accept_other_company:"
|
||||||
|
msgid "Accept other company"
|
||||||
|
msgstr "anderes Unternehmen akzeptieren"
|
||||||
|
|
||||||
|
msgctxt "help:document.incoming.configuration,accept_other_company:"
|
||||||
|
msgid "Accepts invoices created for a company other than the current one."
|
||||||
|
msgstr "Akzeptiert Rechnungen welche für ein anderes Unternehmen als das aktuelle erstellt wurden."
|
||||||
|
|
23
locale/en.po
23
locale/en.po
|
@ -10,3 +10,26 @@ msgctxt "model:ir.message,text:msg_convert_error"
|
||||||
msgid "Conversion error: %(msg)s."
|
msgid "Conversion error: %(msg)s."
|
||||||
msgstr "Conversion error: %(msg)s."
|
msgstr "Conversion error: %(msg)s."
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,text:msg_no_supplierparty"
|
||||||
|
msgid "Supplier party '%(partytxt)s' not found. Auto-creation is currently turned off."
|
||||||
|
msgstr "Supplier party '%(partytxt)s' not found. Auto-creation is currently turned off."
|
||||||
|
|
||||||
|
msgctxt "model:ir.message,text:msg_not_our_company"
|
||||||
|
msgid "The buyer party '%(partytxt)s' differs from the corporate party."
|
||||||
|
msgstr "The buyer party '%(partytxt)s' differs from the corporate party."
|
||||||
|
|
||||||
|
msgctxt "field:document.incoming.configuration,create_supplier:"
|
||||||
|
msgid "Create Supplier Party"
|
||||||
|
msgstr "Create Supplier Party"
|
||||||
|
|
||||||
|
msgctxt "help:document.incoming.configuration,create_supplier:"
|
||||||
|
msgid "Creates the vendor party if it does not exist. Generates an import error when turned off and the party is missing."
|
||||||
|
msgstr "Creates the vendor party if it does not exist. Generates an import error when turned off and the party is missing."
|
||||||
|
|
||||||
|
msgctxt "field:document.incoming.configuration,accept_other_company:"
|
||||||
|
msgid "Accept other company"
|
||||||
|
msgstr "Accept other company"
|
||||||
|
|
||||||
|
msgctxt "help:document.incoming.configuration,accept_other_company:"
|
||||||
|
msgid "Accepts invoices created for a company other than the current one."
|
||||||
|
msgstr "Accepts invoices created for a company other than the current one."
|
||||||
|
|
|
@ -11,7 +11,12 @@
|
||||||
<record model="ir.message" id="msg_convert_error">
|
<record model="ir.message" id="msg_convert_error">
|
||||||
<field name="text">Conversion error: %(msg)s.</field>
|
<field name="text">Conversion error: %(msg)s.</field>
|
||||||
</record>
|
</record>
|
||||||
|
<record model="ir.message" id="msg_no_supplierparty">
|
||||||
|
<field name="text">Supplier party '%(partytxt)s' not found. Auto-creation is currently turned off.</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_not_our_company">
|
||||||
|
<field name="text">The buyer party '%(partytxt)s' differs from the corporate party.</field>
|
||||||
|
</record>
|
||||||
|
|
||||||
</data>
|
</data>
|
||||||
</tryton>
|
</tryton>
|
||||||
|
|
|
@ -7,7 +7,34 @@ import os.path
|
||||||
from datetime import date
|
from datetime import date
|
||||||
from trytond.tests.test_tryton import with_transaction
|
from trytond.tests.test_tryton import with_transaction
|
||||||
from trytond.pool import Pool
|
from trytond.pool import Pool
|
||||||
|
from trytond.exceptions import UserError
|
||||||
from trytond.modules.company.tests import create_company, set_company
|
from trytond.modules.company.tests import create_company, set_company
|
||||||
|
from trytond.modules.account.tests import create_chart, get_fiscalyear
|
||||||
|
|
||||||
|
|
||||||
|
def set_invoice_sequences(fiscalyear):
|
||||||
|
pool = Pool()
|
||||||
|
Sequence = pool.get('ir.sequence.strict')
|
||||||
|
SequenceType = pool.get('ir.sequence.type')
|
||||||
|
InvoiceSequence = pool.get('account.fiscalyear.invoice_sequence')
|
||||||
|
ModelData = pool.get('ir.model.data')
|
||||||
|
|
||||||
|
sequence = Sequence(
|
||||||
|
name=fiscalyear.name,
|
||||||
|
sequence_type=SequenceType(ModelData.get_id(
|
||||||
|
'account_invoice', 'sequence_type_account_invoice')),
|
||||||
|
company=fiscalyear.company,
|
||||||
|
)
|
||||||
|
sequence.save()
|
||||||
|
fiscalyear.invoice_sequences = []
|
||||||
|
invoice_sequence = InvoiceSequence()
|
||||||
|
invoice_sequence.fiscalyear = fiscalyear
|
||||||
|
invoice_sequence.in_invoice_sequence = sequence
|
||||||
|
invoice_sequence.in_credit_note_sequence = sequence
|
||||||
|
invoice_sequence.out_invoice_sequence = sequence
|
||||||
|
invoice_sequence.out_credit_note_sequence = sequence
|
||||||
|
invoice_sequence.save()
|
||||||
|
return fiscalyear
|
||||||
|
|
||||||
|
|
||||||
class DocumentTestCase(object):
|
class DocumentTestCase(object):
|
||||||
|
@ -26,16 +53,38 @@ class DocumentTestCase(object):
|
||||||
task.run()
|
task.run()
|
||||||
Queue.delete(tasks)
|
Queue.delete(tasks)
|
||||||
|
|
||||||
|
def prep_fiscalyear(self, company1):
|
||||||
|
""" prepare fiscal year, sequences...
|
||||||
|
"""
|
||||||
|
pool = Pool()
|
||||||
|
FiscalYear = pool.get('account.fiscalyear')
|
||||||
|
|
||||||
|
fisc_year = get_fiscalyear(company1, today=date(2025, 1, 15))
|
||||||
|
set_invoice_sequences(fisc_year)
|
||||||
|
fisc_year.save()
|
||||||
|
FiscalYear.create_period([fisc_year])
|
||||||
|
|
||||||
@with_transaction()
|
@with_transaction()
|
||||||
def test_xmldoc_import_facturx(self):
|
def test_xmldoc_import_facturx(self):
|
||||||
""" create incoming-document, load xml, detect type
|
""" create incoming-document, load xml, detect type
|
||||||
"""
|
"""
|
||||||
pool = Pool()
|
pool = Pool()
|
||||||
IncDocument = pool.get('document.incoming')
|
IncDocument = pool.get('document.incoming')
|
||||||
|
Configuration = pool.get('document.incoming.configuration')
|
||||||
|
Party = pool.get('party.party')
|
||||||
|
|
||||||
company = create_company('m-ds')
|
company = create_company('m-ds')
|
||||||
with set_company(company):
|
with set_company(company):
|
||||||
|
|
||||||
|
create_chart(company=company, tax=True)
|
||||||
|
self.prep_fiscalyear(company)
|
||||||
|
|
||||||
|
config = Configuration()
|
||||||
|
config.save()
|
||||||
|
|
||||||
|
self.assertEqual(config.create_supplier, True)
|
||||||
|
self.assertEqual(config.accept_other_company, False)
|
||||||
|
|
||||||
to_create = []
|
to_create = []
|
||||||
with open(os.path.join(
|
with open(os.path.join(
|
||||||
os.path.split(__file__)[0],
|
os.path.split(__file__)[0],
|
||||||
|
@ -52,6 +101,36 @@ class DocumentTestCase(object):
|
||||||
b'<?xml version="1.0" encoding="UTF-8"?>\n' +
|
b'<?xml version="1.0" encoding="UTF-8"?>\n' +
|
||||||
b'<rsm:CrossIndustryInvoice xmlns'))
|
b'<rsm:CrossIndustryInvoice xmlns'))
|
||||||
|
|
||||||
|
# no supplier-party in db
|
||||||
|
self.assertEqual(
|
||||||
|
Party.search_count([('name', '=', 'Name of the Supplier')]),
|
||||||
|
0)
|
||||||
|
|
||||||
|
# check fail if missing supplier
|
||||||
|
config.create_supplier = False
|
||||||
|
config.save()
|
||||||
|
self.assertRaisesRegex(
|
||||||
|
UserError,
|
||||||
|
"Supplier party 'Name of the Supplier, 12345, " +
|
||||||
|
"Street of Supplier No 1, Berlin' not found. " +
|
||||||
|
"Auto-creation is currently turned off.",
|
||||||
|
document._process_supplier_invoice)
|
||||||
|
|
||||||
|
config.create_supplier = True
|
||||||
|
config.accept_other_company = False
|
||||||
|
config.save()
|
||||||
|
|
||||||
|
# check fail if invoice is not for our company
|
||||||
|
self.assertRaisesRegex(
|
||||||
|
UserError,
|
||||||
|
"The buyer party 'Our Company, 23456, Address Line 1; " +
|
||||||
|
"Address Line 2, Potsdam' differs from the corporate party.",
|
||||||
|
document._process_supplier_invoice)
|
||||||
|
|
||||||
|
config.create_supplier = True
|
||||||
|
config.accept_other_company = True
|
||||||
|
config.save()
|
||||||
|
|
||||||
invoice = document._process_supplier_invoice()
|
invoice = document._process_supplier_invoice()
|
||||||
print('\n## invoice:', (invoice,))
|
print('\n## invoice:', (invoice,))
|
||||||
self.assertEqual(invoice.type, 'in')
|
self.assertEqual(invoice.type, 'in')
|
||||||
|
@ -64,6 +143,13 @@ class DocumentTestCase(object):
|
||||||
invoice.comment,
|
invoice.comment,
|
||||||
'Code=1, Some notes to the customer.\n' +
|
'Code=1, Some notes to the customer.\n' +
|
||||||
'Code=22, Subject=42, Goes to field comment.')
|
'Code=22, Subject=42, Goes to field comment.')
|
||||||
|
self.assertEqual(invoice.party.rec_name, 'Name of the Supplier')
|
||||||
|
self.assertEqual(invoice.account.rec_name, 'Main Payable')
|
||||||
|
|
||||||
|
# now we have the supplier-party
|
||||||
|
self.assertEqual(
|
||||||
|
Party.search_count([('name', '=', 'Name of the Supplier')]),
|
||||||
|
1)
|
||||||
invoice.save()
|
invoice.save()
|
||||||
|
|
||||||
print('\n## invoice:', invoice)
|
print('\n## invoice:', invoice)
|
||||||
|
|
|
@ -54,19 +54,19 @@
|
||||||
</ram:IncludedSupplyChainTradeLineItem>
|
</ram:IncludedSupplyChainTradeLineItem>
|
||||||
<ram:ApplicableHeaderTradeAgreement>
|
<ram:ApplicableHeaderTradeAgreement>
|
||||||
<ram:SellerTradeParty>
|
<ram:SellerTradeParty>
|
||||||
<ram:Name>Name of the Comany</ram:Name>
|
<ram:Name>Name of the Supplier</ram:Name>
|
||||||
<ram:SpecifiedLegalOrganization>
|
<ram:SpecifiedLegalOrganization>
|
||||||
</ram:SpecifiedLegalOrganization>
|
</ram:SpecifiedLegalOrganization>
|
||||||
<ram:PostalTradeAddress>
|
<ram:PostalTradeAddress>
|
||||||
<ram:PostcodeCode>12345</ram:PostcodeCode>
|
<ram:PostcodeCode>12345</ram:PostcodeCode>
|
||||||
<ram:LineOne>Street of Company No 1</ram:LineOne>
|
<ram:LineOne>Street of Supplier No 1</ram:LineOne>
|
||||||
<ram:CityName>Berlin</ram:CityName>
|
<ram:CityName>Berlin</ram:CityName>
|
||||||
<ram:CountryID>DE</ram:CountryID>
|
<ram:CountryID>DE</ram:CountryID>
|
||||||
<ram:CountrySubDivisionName>Berlin</ram:CountrySubDivisionName>
|
<ram:CountrySubDivisionName>Berlin</ram:CountrySubDivisionName>
|
||||||
</ram:PostalTradeAddress>
|
</ram:PostalTradeAddress>
|
||||||
</ram:SellerTradeParty>
|
</ram:SellerTradeParty>
|
||||||
<ram:BuyerTradeParty>
|
<ram:BuyerTradeParty>
|
||||||
<ram:Name>Customer Company</ram:Name>
|
<ram:Name>Our Company</ram:Name>
|
||||||
<ram:SpecifiedLegalOrganization>
|
<ram:SpecifiedLegalOrganization>
|
||||||
</ram:SpecifiedLegalOrganization>
|
</ram:SpecifiedLegalOrganization>
|
||||||
<ram:PostalTradeAddress>
|
<ram:PostalTradeAddress>
|
||||||
|
|
Loading…
Reference in a new issue