Acumatica:如何在 ruby 中创建新客户?
Acumatica: How to create new customer in ruby?
我需要在 ruby 中使用 SOAP API 创建客户(我们想在 Rails 项目上使用来自 Ruby 的 Acumatica api)。
目前我使用 Savon gem 的代码如下所示:
client = Savon.client(wsdl: 'wsdl.wsdl') # sample wsdl path
response = client.call :login, message: { name: '', password: '' }
auth_cookies = response.http.cookies
class ServiceRequest
def to_s
builder = Builder::XmlMarkup.new
builder.instruct!(:xml, encoding: 'UTF-8')
# ... problem is here, I don't know how XML request should look like
builder
end
end
p client.call :submit, message: ServiceRequest.new, cookies: auth_cookies
问题是,我不知道 XML 请求应该是什么样子。
C# 请求看起来像这样(只是来自文档的示例):
PO302000result = context.PO302000Submit(
new Command[]
{ new Value { Value = "PORE000079", LinkedCommand =
PO302000.DocumentSummary.ReceiptNbr},
new Value { Value = "OK", LinkedCommand =
PO302000.AddPurchaseOrderLine.ServiceCommands.DialogAnswer,
PO302000.Actions.AddPOOrderLine, new Key { Value = "='PORG000084'", FieldName = Commit = true },
PO302000.AddPurchaseOrderLine.OrderNbr.FieldName, ObjectName =
PO302000.AddPurchaseOrderLine.OrderNbr.ObjectName },
new Key { Value = "='CPU00004'", FieldName =
PO302000.AddPurchaseOrderLine.InventoryID.FieldName, ObjectName =
PO302000.AddPurchaseOrderLine.InventoryID.ObjectName },
new Value{ Value = "True", LinkedCommand =
PO302000.AddPurchaseOrderLine.Selected, Commit = true },
PO302000.Actions.AddPOOrderLine2
new Key{ Value = "='CPU00004'", FieldName =
PO302000.DocumentDetails_.InventoryID.FieldName, ObjectName =
PO302000.DocumentDetails_.InventoryID.ObjectName},
new Value{ Value = "1.00", LinkedCommand =
PO302000.DocumentDetails_.ReceiptQty, Commit = true},
// the next part of code is needed if you use Serial items
PO302000.BinLotSerialNumbers.ServiceCommands.NewRow,
new Value { Value = "R01", LinkedCommand =
PO302000.BinLotSerialNumbers.Location },
PO302000.Actions.Save
} );
但我不知道XML这段代码会产生什么样的结果。看起来我们有带值的命令数组,然后是操作名称。但是这种代码渲染的是什么 XML 呢?也许一些 C# 或 Java 的人可以复制我的 xml 请求由那种代码呈现的样本?
非常感谢。
基本上手动生成 XML SOAP 包是个坏主意,你应该有一些包装器,这必须简化你的代码。
无论如何,下面的C#代码+XMLSOAP请求
Content[] result = context.Submit(
new Command[]
{
new Value { Value = "PORE000079", LinkedCommand = PO302000.DocumentSummary.ReceiptNbr}
,new Value { Value = "OK", LinkedCommand = PO302000.AddPurchaseOrderLine.ServiceCommands.DialogAnswer, Commit = true }
,PO302000.Actions.AddPOOrderLine
,new Key { Value = "='PORG000077'", FieldName = PO302000.AddPurchaseOrderLine.OrderNbr.FieldName, ObjectName = PO302000.AddPurchaseOrderLine.OrderNbr.ObjectName }
,new Key { Value = "='CPU00004'", FieldName = PO302000.AddPurchaseOrderLine.InventoryID.FieldName, ObjectName = PO302000.AddPurchaseOrderLine.InventoryID.ObjectName }
,new Value{ Value = "True", LinkedCommand = PO302000.AddPurchaseOrderLine.Selected, Commit = true }
,PO302000.Actions.AddPOOrderLine2
,new Key{ Value = "='CPU00004'", FieldName = PO302000.DocumentDetails.InventoryID.FieldName, ObjectName = PO302000.DocumentDetails.InventoryID.ObjectName}
,new Value{ Value = "1.00", LinkedCommand = PO302000.DocumentDetails.ReceiptQty, Commit = true}
// the next part of code is needed if you use Serial items
,PO302000.BinLotSerialNumbers.ServiceCommands.NewRow
,new Value { Value = "R01", LinkedCommand = PO302000.BinLotSerialNumbers.Location }
,new Value { Value = "1.00", LinkedCommand = PO302000.BinLotSerialNumbers.Quantity, Commit = true }
,new Value { Value = "25.00", LinkedCommand = PO302000.DocumentDetails.UnitCost, Commit = true }
,new Key { Value = "='CPU00004'", FieldName = PO302000.DocumentDetails.InventoryID.FieldName, ObjectName = PO302000.DocumentDetails.InventoryID.ObjectName }
,new Value { Value = "0.00", LinkedCommand = PO302000.DocumentDetails.ReceiptQty, Commit = true }
,PO302000.Actions.Save
}
);
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><Submit xmlns="http://www.acumatica.com/typed/"><commands><Command xsi:type="Value"><Value>PORE000079</Value><LinkedCommand xsi:type="Field"><FieldName>ReceiptNbr</FieldName><ObjectName>Document</ObjectName><Value>ReceiptNbr</Value><Commit>true</Commit><LinkedCommand xsi:type="Action"><FieldName>cancel</FieldName><ObjectName>Document</ObjectName><LinkedCommand xsi:type="Key"><FieldName>ReceiptNbr</FieldName><ObjectName>Document</ObjectName><Value>=[Document.ReceiptNbr]</Value><LinkedCommand xsi:type="Key"><FieldName>ReceiptType</FieldName><ObjectName>Document</ObjectName><Value>=[Document.ReceiptType]</Value></LinkedCommand></LinkedCommand></LinkedCommand></LinkedCommand></Command><Command xsi:type="Value"><Value>OK</Value><Commit>true</Commit><LinkedCommand xsi:type="Answer"><ObjectName>poLinesSelection</ObjectName><Value>='Yes'</Value></LinkedCommand></Command><Command xsi:type="Action"><FieldName>AddPOOrderLine</FieldName><ObjectName>Document</ObjectName><Commit>true</Commit></Command><Command xsi:type="Key"><FieldName>OrderNbr</FieldName><ObjectName>poLinesSelection</ObjectName><Value>='PORG000077'</Value></Command><Command xsi:type="Key"><FieldName>InventoryID</FieldName><ObjectName>poLinesSelection</ObjectName><Value>='CPU00004'</Value></Command><Command xsi:type="Value"><Value>True</Value><Commit>true</Commit><LinkedCommand xsi:type="Field"><FieldName>Selected</FieldName><ObjectName>poLinesSelection</ObjectName><Value>Selected</Value><Commit>true</Commit></LinkedCommand></Command><Command xsi:type="Action"><FieldName>AddPOOrderLine2</FieldName><ObjectName>Document</ObjectName><Commit>true</Commit></Command><Command xsi:type="Key"><FieldName>InventoryID</FieldName><ObjectName>transactions</ObjectName><Value>='CPU00004'</Value></Command><Command xsi:type="Value"><Value>1.00</Value><Commit>true</Commit><LinkedCommand xsi:type="Field"><FieldName>ReceiptQty</FieldName><ObjectName>transactions</ObjectName><Value>ReceiptQty</Value><Commit>true</Commit></LinkedCommand></Command><Command xsi:type="NewRow"><ObjectName>splits</ObjectName></Command><Command xsi:type="Value"><Value>R01</Value><LinkedCommand xsi:type="Field"><FieldName>LocationID</FieldName><ObjectName>splits</ObjectName><Value>Location</Value></LinkedCommand></Command><Command xsi:type="Value"><Value>1.00</Value><Commit>true</Commit><LinkedCommand xsi:type="Field"><FieldName>Qty</FieldName><ObjectName>splits</ObjectName><Value>Quantity</Value></LinkedCommand></Command><Command xsi:type="Value"><Value>25.00</Value><Commit>true</Commit><LinkedCommand xsi:type="Field"><FieldName>CuryUnitCost</FieldName><ObjectName>transactions</ObjectName><Value>UnitCost</Value></LinkedCommand></Command><Command xsi:type="Key"><FieldName>InventoryID</FieldName><ObjectName>transactions</ObjectName><Value>='CPU00004'</Value></Command><Command xsi:type="Value"><Value>0.00</Value><Commit>true</Commit><LinkedCommand xsi:type="Field"><FieldName>ReceiptQty</FieldName><ObjectName>transactions</ObjectName><Value>ReceiptQty</Value><Commit>true</Commit></LinkedCommand></Command><Command xsi:type="Action"><FieldName>Save</FieldName><ObjectName>Document</ObjectName></Command></commands></Submit></soap:Body></soap:Envelope>
最后我做了什么:
gem install 'mumboe-soap4r' # not soap4r,
# because soap4r is old and bugged with newer rubies
那我运行
wsdl2ruby.rb --wsdl customer.wsdl --type client
其中 wsdl2ruby.rb 与 mumboe-soap4r gem 一起安装。将 customer.wsdl 替换为您的 wsdl 路径,可以是 URL 或文件系统路径。
在 运行 此命令之后创建了下一个文件:
default.rb
defaultMappingRegistry.rb
defaultDriver.rb
ScreenClient.rb
使用这些文件,您可以编写类似于 C# 代码的代码或 php 与 acumatica 交互的代码 API:
require_relative 'defaultDriver'
require 'soap/wsdlDriver'
# this is my helper method to make life easier
def prepare_value(value, command, need_commit = false, ignore = false)
value_command = Value.new
value_command.value = value
value_command.linkedCommand = command
value_command.ignoreError = ignore unless ignore.nil?
value_command.commit = need_commit unless need_commit.nil?
value_command
end
soap_client = SOAP::WSDLDriverFactory.new('customer.wsdl').create_rpc_driver
soap_client.login(name: '', password: '').loginResult
screen = soap_client.getSchema(nil)
soap_client.clear(nil)
content = screen.getSchemaResult
# p schema
p customer = content.customerSummary.customerID
p customer_name = content.customerSummary.customerName
country = content.generalInfoMainAddress.country
customer_class = content.generalInfoFinancialSettings.customerClass
commands = ArrayOfCommand.new
commands << prepare_value('ABBA', customer_name)
commands << prepare_value('US', country)
commands << prepare_value('MERCHANT', customer_class)
commands << content.actions.insert
commands << customer.clone # to return
p commands
p soap_client.submit(commands)
希望对大家有所帮助。
实际上 'mumboe-soap4r' 或 'soap2r' 或 'soap4r' 不适用于 Acumatica 香皂 API。他们太旧而且有马车。
最后我使用的是 Savon gem(版本 2)。我正在使用 XmlMarkup class 创建消息。但是我怎么知道我应该创建什么 XML 呢?为了知道这一点,我在 .net 中创建 soap 请求,然后我看到正确的 XML 请求是什么样的,然后我才使用 Savon gem 创建 soap 请求。太多的工作,但我现在不知道更好的方法。有用。
为了让 Savon 与 Acumatica 一起工作 API 我设置了下一个选项:
client = Savon.client do
wsdl 'http://path/Soap/AR303000.asmx?wsdl'
log true
namespaces 'xmlns:soap' => 'http://schemas.xmlsoap.org/soap/envelope/'
env_namespace 'soap'
namespace_identifier nil
element_form_default ''
end
别忘了传递 auth cookies
response = client.call(:login, message: { name: '', password: '' })
auth_cookies = response.http.cookies
创建您的客户xml,然后提交
m = build_create_submit(customer_name)
response = client.call(:submit, message: m, cookies: auth_cookies)
# get customer id of newly created customer
customer_id = response.try(:hash).try(:[], :envelope).
try(:[], :body).
try(:[], :submit_response).
try(:[], :submit_result).
try(:[], :content).
try(:[], :customer_summary).
try(:[], :customer_id).
try(:[], :value)
我需要在 ruby 中使用 SOAP API 创建客户(我们想在 Rails 项目上使用来自 Ruby 的 Acumatica api)。
目前我使用 Savon gem 的代码如下所示:
client = Savon.client(wsdl: 'wsdl.wsdl') # sample wsdl path
response = client.call :login, message: { name: '', password: '' }
auth_cookies = response.http.cookies
class ServiceRequest
def to_s
builder = Builder::XmlMarkup.new
builder.instruct!(:xml, encoding: 'UTF-8')
# ... problem is here, I don't know how XML request should look like
builder
end
end
p client.call :submit, message: ServiceRequest.new, cookies: auth_cookies
问题是,我不知道 XML 请求应该是什么样子。
C# 请求看起来像这样(只是来自文档的示例):
PO302000result = context.PO302000Submit(
new Command[]
{ new Value { Value = "PORE000079", LinkedCommand =
PO302000.DocumentSummary.ReceiptNbr},
new Value { Value = "OK", LinkedCommand =
PO302000.AddPurchaseOrderLine.ServiceCommands.DialogAnswer,
PO302000.Actions.AddPOOrderLine, new Key { Value = "='PORG000084'", FieldName = Commit = true },
PO302000.AddPurchaseOrderLine.OrderNbr.FieldName, ObjectName =
PO302000.AddPurchaseOrderLine.OrderNbr.ObjectName },
new Key { Value = "='CPU00004'", FieldName =
PO302000.AddPurchaseOrderLine.InventoryID.FieldName, ObjectName =
PO302000.AddPurchaseOrderLine.InventoryID.ObjectName },
new Value{ Value = "True", LinkedCommand =
PO302000.AddPurchaseOrderLine.Selected, Commit = true },
PO302000.Actions.AddPOOrderLine2
new Key{ Value = "='CPU00004'", FieldName =
PO302000.DocumentDetails_.InventoryID.FieldName, ObjectName =
PO302000.DocumentDetails_.InventoryID.ObjectName},
new Value{ Value = "1.00", LinkedCommand =
PO302000.DocumentDetails_.ReceiptQty, Commit = true},
// the next part of code is needed if you use Serial items
PO302000.BinLotSerialNumbers.ServiceCommands.NewRow,
new Value { Value = "R01", LinkedCommand =
PO302000.BinLotSerialNumbers.Location },
PO302000.Actions.Save
} );
但我不知道XML这段代码会产生什么样的结果。看起来我们有带值的命令数组,然后是操作名称。但是这种代码渲染的是什么 XML 呢?也许一些 C# 或 Java 的人可以复制我的 xml 请求由那种代码呈现的样本?
非常感谢。
基本上手动生成 XML SOAP 包是个坏主意,你应该有一些包装器,这必须简化你的代码。
无论如何,下面的C#代码+XMLSOAP请求
Content[] result = context.Submit(
new Command[]
{
new Value { Value = "PORE000079", LinkedCommand = PO302000.DocumentSummary.ReceiptNbr}
,new Value { Value = "OK", LinkedCommand = PO302000.AddPurchaseOrderLine.ServiceCommands.DialogAnswer, Commit = true }
,PO302000.Actions.AddPOOrderLine
,new Key { Value = "='PORG000077'", FieldName = PO302000.AddPurchaseOrderLine.OrderNbr.FieldName, ObjectName = PO302000.AddPurchaseOrderLine.OrderNbr.ObjectName }
,new Key { Value = "='CPU00004'", FieldName = PO302000.AddPurchaseOrderLine.InventoryID.FieldName, ObjectName = PO302000.AddPurchaseOrderLine.InventoryID.ObjectName }
,new Value{ Value = "True", LinkedCommand = PO302000.AddPurchaseOrderLine.Selected, Commit = true }
,PO302000.Actions.AddPOOrderLine2
,new Key{ Value = "='CPU00004'", FieldName = PO302000.DocumentDetails.InventoryID.FieldName, ObjectName = PO302000.DocumentDetails.InventoryID.ObjectName}
,new Value{ Value = "1.00", LinkedCommand = PO302000.DocumentDetails.ReceiptQty, Commit = true}
// the next part of code is needed if you use Serial items
,PO302000.BinLotSerialNumbers.ServiceCommands.NewRow
,new Value { Value = "R01", LinkedCommand = PO302000.BinLotSerialNumbers.Location }
,new Value { Value = "1.00", LinkedCommand = PO302000.BinLotSerialNumbers.Quantity, Commit = true }
,new Value { Value = "25.00", LinkedCommand = PO302000.DocumentDetails.UnitCost, Commit = true }
,new Key { Value = "='CPU00004'", FieldName = PO302000.DocumentDetails.InventoryID.FieldName, ObjectName = PO302000.DocumentDetails.InventoryID.ObjectName }
,new Value { Value = "0.00", LinkedCommand = PO302000.DocumentDetails.ReceiptQty, Commit = true }
,PO302000.Actions.Save
}
);
<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><Submit xmlns="http://www.acumatica.com/typed/"><commands><Command xsi:type="Value"><Value>PORE000079</Value><LinkedCommand xsi:type="Field"><FieldName>ReceiptNbr</FieldName><ObjectName>Document</ObjectName><Value>ReceiptNbr</Value><Commit>true</Commit><LinkedCommand xsi:type="Action"><FieldName>cancel</FieldName><ObjectName>Document</ObjectName><LinkedCommand xsi:type="Key"><FieldName>ReceiptNbr</FieldName><ObjectName>Document</ObjectName><Value>=[Document.ReceiptNbr]</Value><LinkedCommand xsi:type="Key"><FieldName>ReceiptType</FieldName><ObjectName>Document</ObjectName><Value>=[Document.ReceiptType]</Value></LinkedCommand></LinkedCommand></LinkedCommand></LinkedCommand></Command><Command xsi:type="Value"><Value>OK</Value><Commit>true</Commit><LinkedCommand xsi:type="Answer"><ObjectName>poLinesSelection</ObjectName><Value>='Yes'</Value></LinkedCommand></Command><Command xsi:type="Action"><FieldName>AddPOOrderLine</FieldName><ObjectName>Document</ObjectName><Commit>true</Commit></Command><Command xsi:type="Key"><FieldName>OrderNbr</FieldName><ObjectName>poLinesSelection</ObjectName><Value>='PORG000077'</Value></Command><Command xsi:type="Key"><FieldName>InventoryID</FieldName><ObjectName>poLinesSelection</ObjectName><Value>='CPU00004'</Value></Command><Command xsi:type="Value"><Value>True</Value><Commit>true</Commit><LinkedCommand xsi:type="Field"><FieldName>Selected</FieldName><ObjectName>poLinesSelection</ObjectName><Value>Selected</Value><Commit>true</Commit></LinkedCommand></Command><Command xsi:type="Action"><FieldName>AddPOOrderLine2</FieldName><ObjectName>Document</ObjectName><Commit>true</Commit></Command><Command xsi:type="Key"><FieldName>InventoryID</FieldName><ObjectName>transactions</ObjectName><Value>='CPU00004'</Value></Command><Command xsi:type="Value"><Value>1.00</Value><Commit>true</Commit><LinkedCommand xsi:type="Field"><FieldName>ReceiptQty</FieldName><ObjectName>transactions</ObjectName><Value>ReceiptQty</Value><Commit>true</Commit></LinkedCommand></Command><Command xsi:type="NewRow"><ObjectName>splits</ObjectName></Command><Command xsi:type="Value"><Value>R01</Value><LinkedCommand xsi:type="Field"><FieldName>LocationID</FieldName><ObjectName>splits</ObjectName><Value>Location</Value></LinkedCommand></Command><Command xsi:type="Value"><Value>1.00</Value><Commit>true</Commit><LinkedCommand xsi:type="Field"><FieldName>Qty</FieldName><ObjectName>splits</ObjectName><Value>Quantity</Value></LinkedCommand></Command><Command xsi:type="Value"><Value>25.00</Value><Commit>true</Commit><LinkedCommand xsi:type="Field"><FieldName>CuryUnitCost</FieldName><ObjectName>transactions</ObjectName><Value>UnitCost</Value></LinkedCommand></Command><Command xsi:type="Key"><FieldName>InventoryID</FieldName><ObjectName>transactions</ObjectName><Value>='CPU00004'</Value></Command><Command xsi:type="Value"><Value>0.00</Value><Commit>true</Commit><LinkedCommand xsi:type="Field"><FieldName>ReceiptQty</FieldName><ObjectName>transactions</ObjectName><Value>ReceiptQty</Value><Commit>true</Commit></LinkedCommand></Command><Command xsi:type="Action"><FieldName>Save</FieldName><ObjectName>Document</ObjectName></Command></commands></Submit></soap:Body></soap:Envelope>
最后我做了什么:
gem install 'mumboe-soap4r' # not soap4r,
# because soap4r is old and bugged with newer rubies
那我运行
wsdl2ruby.rb --wsdl customer.wsdl --type client
其中 wsdl2ruby.rb 与 mumboe-soap4r gem 一起安装。将 customer.wsdl 替换为您的 wsdl 路径,可以是 URL 或文件系统路径。
在 运行 此命令之后创建了下一个文件:
default.rb
defaultMappingRegistry.rb
defaultDriver.rb
ScreenClient.rb
使用这些文件,您可以编写类似于 C# 代码的代码或 php 与 acumatica 交互的代码 API:
require_relative 'defaultDriver'
require 'soap/wsdlDriver'
# this is my helper method to make life easier
def prepare_value(value, command, need_commit = false, ignore = false)
value_command = Value.new
value_command.value = value
value_command.linkedCommand = command
value_command.ignoreError = ignore unless ignore.nil?
value_command.commit = need_commit unless need_commit.nil?
value_command
end
soap_client = SOAP::WSDLDriverFactory.new('customer.wsdl').create_rpc_driver
soap_client.login(name: '', password: '').loginResult
screen = soap_client.getSchema(nil)
soap_client.clear(nil)
content = screen.getSchemaResult
# p schema
p customer = content.customerSummary.customerID
p customer_name = content.customerSummary.customerName
country = content.generalInfoMainAddress.country
customer_class = content.generalInfoFinancialSettings.customerClass
commands = ArrayOfCommand.new
commands << prepare_value('ABBA', customer_name)
commands << prepare_value('US', country)
commands << prepare_value('MERCHANT', customer_class)
commands << content.actions.insert
commands << customer.clone # to return
p commands
p soap_client.submit(commands)
希望对大家有所帮助。
实际上 'mumboe-soap4r' 或 'soap2r' 或 'soap4r' 不适用于 Acumatica 香皂 API。他们太旧而且有马车。
最后我使用的是 Savon gem(版本 2)。我正在使用 XmlMarkup class 创建消息。但是我怎么知道我应该创建什么 XML 呢?为了知道这一点,我在 .net 中创建 soap 请求,然后我看到正确的 XML 请求是什么样的,然后我才使用 Savon gem 创建 soap 请求。太多的工作,但我现在不知道更好的方法。有用。
为了让 Savon 与 Acumatica 一起工作 API 我设置了下一个选项:
client = Savon.client do
wsdl 'http://path/Soap/AR303000.asmx?wsdl'
log true
namespaces 'xmlns:soap' => 'http://schemas.xmlsoap.org/soap/envelope/'
env_namespace 'soap'
namespace_identifier nil
element_form_default ''
end
别忘了传递 auth cookies
response = client.call(:login, message: { name: '', password: '' })
auth_cookies = response.http.cookies
创建您的客户xml,然后提交
m = build_create_submit(customer_name)
response = client.call(:submit, message: m, cookies: auth_cookies)
# get customer id of newly created customer
customer_id = response.try(:hash).try(:[], :envelope).
try(:[], :body).
try(:[], :submit_response).
try(:[], :submit_result).
try(:[], :content).
try(:[], :customer_summary).
try(:[], :customer_id).
try(:[], :value)