Acumatica API Создать SalesOrder с несколькими строками DocumentDetails

Когда я создаю SalesOrder с несколькими DocumentDetails в PHP, вот мой код

$SO301000Submit->commands = array
(
$acumatica->prepareValue("SO", $SO301000GetSchema->OrderSummary->OrderType),
$SO301000GetSchema->Actions->Insert,
$acumatica->prepareValue("ACTIVESTAF", $SO301000GetSchema->OrderSummary->Customer),

$SO301000GetSchema->DocumentDetails->ServiceCommands->NewRow,
$acumatica->prepareValue("HQ", $SO301000GetSchema->DocumentDetails->Branch),
$acumatica->prepareValue("AALEGO500", $SO301000GetSchema->DocumentDetails->InventoryID),
$acumatica->prepareValue("WHOLESALE", $SO301000GetSchema->DocumentDetails->Warehouse, true),

$SO301000GetSchema->DocumentDetails->ServiceCommands->NewRow,
$acumatica->prepareValue("VA", $SO301000GetSchema->DocumentDetails->Branch),
$acumatica->prepareValue("AAPOWERAID", $SO301000GetSchema->DocumentDetails->InventoryID),
$acumatica->prepareValue("RETAIL", $SO301000GetSchema->DocumentDetails->Warehouse, true),$SO301000GetSchema->Actions->Save,
$SO301000GetSchema->OrderSummary->OrderNbr
);
$result = $acumatica->client->SO301000Submit($SO301000Submit);

Вернет ошибку

System.Web.Services.Protocols.SoapException: серверу не удалось обработать запрос. —> System.NullReferenceException: ссылка на объект не установлена ​​для экземпляра объекта.
в PX.Api.SyImportContext.ParseCommand (SyCommand cmd)
в PX.Api.SyExportContext.ParseCommand (поле SYMappingField)
в System.Linq.Enumerable.WhereSelectArrayIterator2.MoveNext()
at System.Collections.Generic.List
1..ctor (IEnumerable1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable
1 источник)
в PX.Api.SyExportContext..ctor (сопоставление SYMapping, IEnumerable1 fields, String[] providerFields, Dictionary2 viewFilters, Boolean breakOnError, запуск Int32, счетчик Int32, словарь2 selectorViews, String rowFilterField)
at PX.Api.ScreenUtils.Submit(String screenId, Command[] commands, SchemaMode schemaMode, PXGraph& graph, String& redirectContainerView, String& redirectScreen, Boolean mobile, Dictionary
2 viewFilters)
в PX.Api.Services.ScreenService.Submit (идентификатор строки, IEnumerable1 commands, SchemaMode schemaMode, Boolean mobile, PXGraph& forceGraph, String& redirectContainerView, String& redirectScreen, Dictionary2 viewFilters)
в PX.Api.Services.ScreenService.Submit (идентификатор строки, команды IEnumerable`1, схема-режим SchemaMode)
в PX.Api.Soap.Screen.ScreenGate.Submit (команды Command [])
— Конец внутренней трассировки стека исключений —

Но если я уменьшу код с одним DocumentDetails, как показано ниже:

$SO301000Submit->commands = array
(
$acumatica->prepareValue("SO", $SO301000GetSchema->OrderSummary->OrderType),
$SO301000GetSchema->Actions->Insert,
$acumatica->prepareValue("ACTIVESTAF", $SO301000GetSchema->OrderSummary->Customer),

$SO301000GetSchema->DocumentDetails->ServiceCommands->NewRow,
$acumatica->prepareValue("HQ", $SO301000GetSchema->DocumentDetails->Branch),
$acumatica->prepareValue("AALEGO500", $SO301000GetSchema->DocumentDetails->InventoryID),
$acumatica->prepareValue("WHOLESALE", $SO301000GetSchema->DocumentDetails->Warehouse, true),

$SO301000GetSchema->Actions->Save,
$SO301000GetSchema->OrderSummary->OrderNbr
);
$result = $acumatica->client->SO301000Submit($SO301000Submit);

Затем все в порядке, SalesOrder создан.

Вот функция prepareValue:

public function prepareValue($value, $command, $needcommit = false, $ignore = false)
{
$value_command = new ObjectDocument\Value();
$value_command->Value = $value;
$value_command->LinkedCommand = $command;
if($needcommit) $value_command->Commit = true;

$soapvar = new \SoapVar($value_command, SOAP_ENC_OBJECT, "Value", "http://www.acumatica.com/generic/");
return $soapvar;
}

Не знаю почему? Пожалуйста, помогите мне объяснить этот случай.

1

Решение

Как упомянул @Gabriel, SOAP-сообщение, которое отправляется PHP немного отличается.
Проблема в том, что XML созданный по запросу из PHP вводит идентификатор в XML и затем, где бы он ни находил один и тот же узел, он просто передает идентификатор в качестве ссылки.

Пример (ниже сообщение SOAP перехватывается с помощью Fiddler): —

введите описание изображения здесь

Чтобы преодолеть это, создайте два разных предмета с одинаковой структурой. Вы можете использовать clone

Создать новую функцию PrepareValueExt как показано ниже и используйте его для линий.

public function PrepareValueExt($value, $command, $needcommit=false, $ignore=false)
{
$value_command = new Value();
$value_command->Value = $value;
$value_command->LinkedCommand = clone $command;
//$value_command->IgnoreError = $ignore;
if($needcommit) $value_command->Commit = true;

return($value_command);
}

И изменить код для NewRow, а также:

array_push($command, clone $schema->DocumentDetails->ServiceCommands->NewRow);
1

Другие решения

Других решений пока нет …