Search code examples
restodatadynamics-365-operations

Posting Inventory Movement Journal to D365 Finance and Operations via OData API and InventoryMovementJournalHeaders Entity


I am trying to create an Inventory Movement Journal in D365 using the OData API and the InventoryMovementJournalHeaders / InventInventoryMovementJournalHeaderEntity.

I have managed to do similar for the Counting Journal using InventoryCountingJournalHeaders as the starting point but get the following error when I try to raise an Inventory Movement Journal with InventoryMovementJournalHeaders entity:

Write failed for table row of type 'InventInventoryMovementJournalHeaderEntity'. Infolog: Warning: Field 'Journal' must be filled in.; Warning: validateWrite failed on data source 'InventJournalTable (InventJournalTable)'.

Full error message:

{
  "error": {
    "code": "",
    "message": "An error has occurred.",
    "innererror": {
      "message": "Write failed for table row of type 'InventInventoryMovementJournalHeaderEntity'. Infolog: Warning: Field 'Journal' must be filled in.; Warning: validateWrite failed on data source 'InventJournalTable (InventJournalTable)'.",
      "type": "Microsoft.Dynamics.Platform.Integration.Services.OData.AxODataWriteException",
      "stacktrace": "   at Microsoft.Dynamics.Platform.Integration.Services.OData.Update.UpdateProcessor.CreateEntity_Save(ChangeOperationContext context, ChangeInfo changeInfo)\r\n   at Microsoft.Dynamics.Platform.Integration.Services.OData.Update.UpdateManager.<>c__DisplayClass10_0.<CreateEntity>b__1(ChangeOperationContext context)\r\n   at Microsoft.Dynamics.Platform.Integration.Services.OData.Update.ChangeInfo.ExecuteActionsInCompanyContext(IEnumerable`1 actionList, ChangeOperationContext operationContext)\r\n   at Microsoft.Dynamics.Platform.Integration.Services.OData.Update.ChangeInfo.TrySave(ChangeOperationContext operationContext)\r\n   at Microsoft.Dynamics.Platform.Integration.Services.OData.Update.UpdateManager.SaveChanges()\r\n   at Microsoft.Dynamics.Platform.Integration.Services.OData.AxODataDelegatingHandler.<SaveChangesAsync>d__3.MoveNext()"
    }
  }
}

The field 'Journal' referred to in the error message does not exist in the data entity or the InventJournalTable table and I am not sending it (I have also tried to send it a field called 'Journal' but that raises an error also). This is a standard, out of the box, data entity provided by Microsoft.

Has anyone come across this error / solved it please?


Solution

  • I'm able to replicate your issue. After a closer look at the entities of both counting and movement journals, turns out that indeed the counting journal entity does support creating a new journal without specifying the value for the primary natural key, the journal number. It does this with the following code in the initValue method of the entity:

    public void initValue()
    {
        if (!this.skipNumberSequenceCheck())
        {
            NumberSeqRecordFieldHandler::enableNumberSequenceControlForField(
                this, fieldNum(InventInventoryCountingJournalHeaderEntity, JournalNumber), InventParameters::numRefInventJournalId());
        }
    
        super();
    }
    

    This code is missing in the entity for movement journals. This means that the entity does not support creation of new journals without specifying the journal number.

    You can easily customize the entity to add this support. I added the following code in a code extension for the entity. Afterwards, I was able to create new movement journals using the entity.

    [ExtensionOf(tableStr(InventInventoryMovementJournalHeaderEntity))]
    final class InventInventoryMovementJournalHeaderEntity_Tutorial_Extension
    {
        public void initValue()
        {
            if (!this.skipNumberSequenceCheck())
            {
                NumberSeqRecordFieldHandler::enableNumberSequenceControlForField(
                    this, fieldNum(InventInventoryMovementJournalHeaderEntity, JournalNumber), InventParameters::numRefInventJournalId());
            }
            
            next initValue();
        }
    
    }