Когда я создаю 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()
1..ctor (IEnumerable
at System.Collections.Generic.List1 collection)
1 источник)
at System.Linq.Enumerable.ToList[TSource](IEnumerable
в PX.Api.SyExportContext..ctor (сопоставление SYMapping, IEnumerable1 fields, String[] providerFields, Dictionary
2 viewFilters, Boolean breakOnError, запуск Int32, счетчик Int32, словарь2 selectorViews, String rowFilterField)
2 viewFilters)
at PX.Api.ScreenUtils.Submit(String screenId, Command[] commands, SchemaMode schemaMode, PXGraph& graph, String& redirectContainerView, String& redirectScreen, Boolean mobile, Dictionary
в PX.Api.Services.ScreenService.Submit (идентификатор строки, IEnumerable1 commands, SchemaMode schemaMode, Boolean mobile, PXGraph& forceGraph, String& redirectContainerView, String& redirectScreen, Dictionary
2 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;
}
Не знаю почему? Пожалуйста, помогите мне объяснить этот случай.
Как упомянул @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);
Других решений пока нет …