1
votes

When I create a SalesOrder with multi DocumentDetails in PHP, here is my code

$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);

It will return the error

System.Web.Services.Protocols.SoapException: Server was unable to process request. ---> System.NullReferenceException: Object reference not set to an instance of an object. at PX.Api.SyImportContext.ParseCommand(SyCommand cmd) at PX.Api.SyExportContext.ParseCommand(SYMappingField field) at System.Linq.Enumerable.WhereSelectArrayIterator2.MoveNext() at System.Collections.Generic.List1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source) at PX.Api.SyExportContext..ctor(SYMapping mapping, IEnumerable1 fields, String[] providerFields, Dictionary2 viewFilters, Boolean breakOnError, Int32 start, Int32 count, Dictionary2 selectorViews, String rowFilterField) at PX.Api.ScreenUtils.Submit(String screenId, Command[] commands, SchemaMode schemaMode, PXGraph& graph, String& redirectContainerView, String& redirectScreen, Boolean mobile, Dictionary2 viewFilters) at PX.Api.Services.ScreenService.Submit(String id, IEnumerable1 commands, SchemaMode schemaMode, Boolean mobile, PXGraph& forceGraph, String& redirectContainerView, String& redirectScreen, Dictionary2 viewFilters) at PX.Api.Services.ScreenService.Submit(String id, IEnumerable`1 commands, SchemaMode schemaMode) at PX.Api.Soap.Screen.ScreenGate.Submit(Command[] commands) --- End of inner exception stack trace ---

But if I reduce code with single DocumentDetails as below:

$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);

Then, Everything is OK, a SalesOrder is created.

Here is function 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;
}

I don't know why? Please help me to explain this case.

1
We tried the same set of commands here with a C# console application, and it worked. I suspect that the SOAP message that is sent by PHP is slightly different, which is causing our server to crash. - Gabriel
Also, can you take a look at the SOAP message that is generated and maybe paste it here? It will allow us to see what's missing and the difference with our message. - Gabriel
Did you find a solution? - Gabriel
Sorry for late reply. I just release from other project. Mr @DChhapgar make a perfect answer for my trouble. Thank you so much. - Thuy Tran
Glad to know that @DChhapgar helped you! Please accept his answer so that this question is mark as answered :) - Gabriel

1 Answers

1
votes

As @Gabriel mentioned, SOAP message that is sent by PHP is slightly different. Issue is that the XML created for the request from PHP introduces the id in the XML and then wherever it finds the same node it just passes the id as the reference.

Example (below SOAP message is captured using Fiddler):-

enter image description here

To overcome this, create two different items with the same structure. You may utilize clone

Create new function PrepareValueExt as below and use it for lines.

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);
}

And Change code for NewRow as well:

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