Netsuite 命名空间冲突(core_2017_2.platform vs accounting_2017_2.lists)
Netsuite namespace conflict (core_2017_2.platform vs accounting_2017_2.lists)
我想从我的 Python 脚本 post 到 Netsuite 的日记条目。我正在使用 zeep 与 SuiteTalk 交谈。
我是 Netsuite 的新手,也是 SOAP 的新手。根据 Internet 示例,我设法使用以下代码通过 Python 脚本添加了一个测试客户:
def make_app_info(client):
AppInfo = client.get_type('ns4:ApplicationInfo')
app_info = AppInfo(applicationId=NS_APPID)
return app_info
def make_passport(client):
RecordRef = client.get_type('ns0:RecordRef')
Passport = client.get_type('ns0:Passport')
role = RecordRef(internalId=NS_ROLE)
return Passport(email=NS_EMAIL,
password=NS_PASSWORD,
account=NS_ACCOUNT,
role=role)
def login_client():
client = Client(WSDL_URL)
login = client.service.login(passport=make_passport(client), _soapheaders={'applicationInfo': make_app_info(client)})
return client
我用的WSDL_URL
是https://webservices.netsuite.com/wsdl/v2017_2_0/netsuite.wsdl
使用上面的客户端,下面的代码添加客户:
def add_customer():
client = login_client()
Customer = client.get_type('ns13:Customer')
customer = Customer(
lastName='Prasad',
firstName='Vikas',
email='vikasprasad@example.com',
companyName='Test Company'
)
client.service.add(customer)
add_customer()
上面添加Customer
成功到Netsuite账户,我可以在webapp的列表中看到它。
继续上面的例子,我写了这段代码来添加 JournalEntry
:
def get_record_by_type(client, type, internal_id):
RecordRef = client.get_type('ns0:RecordRef')
record = RecordRef(internalId=internal_id, type=type)
response = client.service.get(record,
_soapheaders={
'applicationInfo': make_app_info(client),
'passport': make_passport(client),
}
)
r = response.body.readResponse
if r.status.isSuccess:
return r.record
def add_journal_entry():
client = login_client()
# get subsidiary by internal id
subsidiary = get_record_by_type(client, 'subsidiary', '1')
print(subsidiary) # This prints a valid subsidiary having internal id 1
# create two journal entry lines
JournalEntryLine = client.get_type('ns31:JournalEntryLine')
credit_line = JournalEntryLine(account=get_record_by_type(client, 'account', '1'), credit=100)
debit_line = JournalEntryLine(account=get_record_by_type(client, 'account', '2'), debit=100)
print(credit_line) # This prints credit_line with a valid account having internal id 1
print(debit_line) # This prints debit_line with a valid account having internal id 2
JournalEntryLineList = client.get_type('ns31:JournalEntryLineList')
journal_entry_line_list = JournalEntryLineList(line=[credit_line, debit_line])
JournalEntry = client.get_type('ns31:JournalEntry')
journal_entry = JournalEntry(subsidiary=subsidiary, lineList=journal_entry_line_list)
client.service.add(journal_entry, _soapheaders={'passport': make_passport(client),
'applicationInfo': make_app_info(client)}) # Fails on this line.
add_journal_entry()
调用 client.service.add(...)
失败,错误为:
zeep.exceptions.Fault: org.xml.sax.SAXException: Expected
{urn:core_2017_2.platform.webservices.netsuite.com}name, found
{urn:accounting_2017_2.lists.webservices.netsuite.com}name
我确信这在 SOAP 的世界中是愚蠢的,但我不确定调试到哪个方向。为什么预期的和找到的有区别?我没有在任何地方提到任何特定的命名空间。它只是 WSDL v2017_2_0
和所有 client.get_type()
调用都是在此之上进行的。这个错误来自哪里?
在 Netsuite 用户组问过同样的问题:
https://usergroup.netsuite.com/users/forum/platform-areas/web-services-suitetalk/434717-netsuite-namespace-conflict#post434717
更新:
根据@Justin W 的回答,事实证明,我可以直接告诉 Suitetalk,而不是通过 internalId
从 Suitetalk 获取 subsidiary
和 account
,然后将它们添加到请求中type
和 internalId
使用 RecordRef
和 Suitetalk 将了解要使用什么 subsidiary
和 account
。
即subsidiary = get_record_by_type(client, 'subsidiary', '1')
可以改成subsidiary = RecordRef(internalId='1', type='subsidiary')
同样
credit_line = JournalEntryLine(account=get_record_by_type(client, 'account', '1'), credit=100)
debit_line = JournalEntryLine(account=get_record_by_type(client, 'account', '2'), debit=100)
可以改成
credit_line = JournalEntryLine(account=RecordRef(internalId='1', type='account'), credit=100)
debit_line = JournalEntryLine(account=RecordRef(internalId='2', type='account'), debit=100)
我认为你的 get_account()
returns 可能是 Account
但 JournalEntryLine.account
应该是 RecordRef
(实际上,同样的问题get_subsidiary()
还有)
我想从我的 Python 脚本 post 到 Netsuite 的日记条目。我正在使用 zeep 与 SuiteTalk 交谈。
我是 Netsuite 的新手,也是 SOAP 的新手。根据 Internet 示例,我设法使用以下代码通过 Python 脚本添加了一个测试客户:
def make_app_info(client):
AppInfo = client.get_type('ns4:ApplicationInfo')
app_info = AppInfo(applicationId=NS_APPID)
return app_info
def make_passport(client):
RecordRef = client.get_type('ns0:RecordRef')
Passport = client.get_type('ns0:Passport')
role = RecordRef(internalId=NS_ROLE)
return Passport(email=NS_EMAIL,
password=NS_PASSWORD,
account=NS_ACCOUNT,
role=role)
def login_client():
client = Client(WSDL_URL)
login = client.service.login(passport=make_passport(client), _soapheaders={'applicationInfo': make_app_info(client)})
return client
我用的WSDL_URL
是https://webservices.netsuite.com/wsdl/v2017_2_0/netsuite.wsdl
使用上面的客户端,下面的代码添加客户:
def add_customer():
client = login_client()
Customer = client.get_type('ns13:Customer')
customer = Customer(
lastName='Prasad',
firstName='Vikas',
email='vikasprasad@example.com',
companyName='Test Company'
)
client.service.add(customer)
add_customer()
上面添加Customer
成功到Netsuite账户,我可以在webapp的列表中看到它。
继续上面的例子,我写了这段代码来添加 JournalEntry
:
def get_record_by_type(client, type, internal_id):
RecordRef = client.get_type('ns0:RecordRef')
record = RecordRef(internalId=internal_id, type=type)
response = client.service.get(record,
_soapheaders={
'applicationInfo': make_app_info(client),
'passport': make_passport(client),
}
)
r = response.body.readResponse
if r.status.isSuccess:
return r.record
def add_journal_entry():
client = login_client()
# get subsidiary by internal id
subsidiary = get_record_by_type(client, 'subsidiary', '1')
print(subsidiary) # This prints a valid subsidiary having internal id 1
# create two journal entry lines
JournalEntryLine = client.get_type('ns31:JournalEntryLine')
credit_line = JournalEntryLine(account=get_record_by_type(client, 'account', '1'), credit=100)
debit_line = JournalEntryLine(account=get_record_by_type(client, 'account', '2'), debit=100)
print(credit_line) # This prints credit_line with a valid account having internal id 1
print(debit_line) # This prints debit_line with a valid account having internal id 2
JournalEntryLineList = client.get_type('ns31:JournalEntryLineList')
journal_entry_line_list = JournalEntryLineList(line=[credit_line, debit_line])
JournalEntry = client.get_type('ns31:JournalEntry')
journal_entry = JournalEntry(subsidiary=subsidiary, lineList=journal_entry_line_list)
client.service.add(journal_entry, _soapheaders={'passport': make_passport(client),
'applicationInfo': make_app_info(client)}) # Fails on this line.
add_journal_entry()
调用 client.service.add(...)
失败,错误为:
zeep.exceptions.Fault: org.xml.sax.SAXException: Expected {urn:core_2017_2.platform.webservices.netsuite.com}name, found {urn:accounting_2017_2.lists.webservices.netsuite.com}name
我确信这在 SOAP 的世界中是愚蠢的,但我不确定调试到哪个方向。为什么预期的和找到的有区别?我没有在任何地方提到任何特定的命名空间。它只是 WSDL v2017_2_0
和所有 client.get_type()
调用都是在此之上进行的。这个错误来自哪里?
在 Netsuite 用户组问过同样的问题: https://usergroup.netsuite.com/users/forum/platform-areas/web-services-suitetalk/434717-netsuite-namespace-conflict#post434717
更新:
根据@Justin W 的回答,事实证明,我可以直接告诉 Suitetalk,而不是通过 internalId
从 Suitetalk 获取 subsidiary
和 account
,然后将它们添加到请求中type
和 internalId
使用 RecordRef
和 Suitetalk 将了解要使用什么 subsidiary
和 account
。
即subsidiary = get_record_by_type(client, 'subsidiary', '1')
可以改成subsidiary = RecordRef(internalId='1', type='subsidiary')
同样
credit_line = JournalEntryLine(account=get_record_by_type(client, 'account', '1'), credit=100)
debit_line = JournalEntryLine(account=get_record_by_type(client, 'account', '2'), debit=100)
可以改成
credit_line = JournalEntryLine(account=RecordRef(internalId='1', type='account'), credit=100)
debit_line = JournalEntryLine(account=RecordRef(internalId='2', type='account'), debit=100)
我认为你的 get_account()
returns 可能是 Account
但 JournalEntryLine.account
应该是 RecordRef
(实际上,同样的问题get_subsidiary()
还有)