web
You’re offline. This is a read only version of the page.
close
Skip to main content

Announcements

No record found.

News and Announcements icon
Community site session details

Community site session details

Session Id :
Finance | Project Operations, Human Resources, ...
Answered

Auto-receive on the shipment on standard form

(1) ShareShare
ReportReport
Posted on by 275

I am working on a customization in Dynamics 365 Finance and Operations related to the transfer order shipping process. Specifically, I want to automatically set the "AutoReceive" checkbox to Yes when the "from" and "to" sites are the same, and to No when they are different.

I have implemented an event handler to achieve this within the standard InventTransferParmShip form. However, I am encountering an issue where no data is being loaded into the  inventtransferparmtable or inventdim when I try to apply this logic. I am  not very experienced in standard form customization any help will be appreciated. 
Environment: Dynamics 365 Finance & Operations

[ExtensionOf(formStr(InventTransferParmShip))]
final class InventTransferParmShip_AcxJewellery_Extension
{
  [formeventhandler(formstr(inventtransferparmship), formeventtype::Activated)]
  public static void inventtransferparmship_oninitialized(xformrun sender, formeventargs e)
  {

    formdatasource inventtransferparmtableds = sender.datasource(formdatasourcestr(inventtransferparmship, inventtransferparmtable));
    formdatasource inventdimds = sender.datasource(formdatasourcestr(inventtransferparmship, inventdim));

    inventtransferparmtable inventtransferparmtable = inventtransferparmtableds.cursor(); (no data)
    inventdim inventdim = inventdimds.cursor(); (no data)

    if (inventdim)
    {
      inventlocation inventlocation;
      inventsiteid locationsiteid = "";


      select firstonly inventlocation
                where inventlocation.inventlocationid == inventdim.inventlocationid;

      if (inventlocation)
      {
        locationsiteid = inventlocation.inventsiteid;
      }

      inventsiteid sitesiteid = inventdim.inventsiteid;


      if (locationsiteid == sitesiteid && locationsiteid != "")
      {
        inventtransferparmtable.autoreceiveqty = noyes::yes;
      }
      else
      {
        inventtransferparmtable.autoreceiveqty = noyes::no;
      }

      inventtransferparmtableds.reread();
      inventtransferparmtableds.refresh();
    }
  }
 
}
 
I have the same question (0)
  • Martin Dráb Profile Picture
    239,519 Most Valuable Professional on at
    You should describe your problem instead of just saying that you have "an issue". It seems to me that you aren't comparing From and To sites at all. You're looking at the same InventDim record in both cases. You're effectively checking whether the selected warehouse belongs to the selected site, which should always be the case.
     
    Also, the location of your code looks strange the me; shouldn't you run the logic when changing the From or To site (or creating a new record)?
     
    By the way, it's very confusing that you named the method inventtransferparmship_oninitialized while it's isn't about the OnInitialized event.
     
    (Moved from Dynamics AX forum.)
  • Ayushaman Profile Picture
    275 on at
    Hi Martin !
     
    Thanks for your help in refining the approach.

    The requirement is to compare the From and To SiteId values: if they match, the AutoReceive functionality should be enabled, otherwise, it should remain disabled on the InventTransferParmShip form. In this case, the From SiteId is accessible as a dimension field, while the To SiteId needs to be retrieved from the selected warehouse for comparison. I’ve attached a screenshot for reference.
    Regarding the location of the code, I created an extension of the form with an event handler to enable or disable the AutoReceiveQty functionality during form load, Please find the attached screenshot for reference :


    Regarding the method named `inventtransferparmship_oninitialized`, I initially attempted to use the `OnInitialized` event, which I forgot to mention in the code snippet. However, since the data wasn't loaded at the `OnInitialized` stage, I switched to the `OnActivated` event where the data was fully available. Generally i do these cosmetic changes once the code works. Apologies for not being thorough about the details.

    Regards,
    Ayushaman
     
     
  • Verified answer
    Ayushaman Profile Picture
    275 on at
     final class InventTransferParmShip_Extension
    {
        int active()
      {
        int ret;
        ret = next active();
        if(ret)
        {
          InventTransferParmTable  inventTransferParmTable = this.cursor();
          InventTransferTable inventTransferTable;
          str  Transfer;
    
          Transfer =  inventTransferParmTable.TransferId;
          if (Transfer)
          {
            
            select firstOnly inventTransferTable
                where inventTransferTable.TransferId ==Transfer;
    
            
            if (inventTransferTable)
            {
              
              InventLocation inventLocationFrom = InventLocation::find(inventTransferTable.InventLocationIdFrom);
    
              
              if (inventLocationFrom.InventSiteId == inventTransferTable.InventLocationIdTo)
              {
                inventTransferParmTable.AutoReceiveQty = NoYes::Yes;
              }
              else
              {
                inventTransferParmTable.AutoReceiveQty = NoYes::No;
              }
    
              inventTransferParmTable.reread();
              
             
            }
           
          }
        }
        return ret;
      }
    
    }

    For customisation on events of standard form i used.

    Thanks ,
    Ayushaman
     
  • Martin Dráb Profile Picture
    239,519 Most Valuable Professional on at
    You have a few obvious bugs there.
     
    You're comparing a site ID (inventLocationFrom.InventSiteId) with a warehouse ID (inventTransferTable.InventLocationIdTo). Your requirement was comparing sites, therefore the wrong value is the latter one.
     
    Also, you set a value to inventTransferParmTable.AutoReceiveQty, but you immediately throw away the modified value by calling inventTransferParmTable.reread().
     
    And as I already mentioned, doing it in active() is wrong. You would harm performance by running DB queries and data updates every time when you select a record, there is no point in updating the data if inventory dimensions didn't change and you could cause recursive calls of active().
     
    You've marked your code as the verified answer, but it doesn't look like you actually verified that your code worked.
  • Ayushaman Profile Picture
    275 on at

    Hi Martin,

    Thank you for your feedback.

    Regarding the first issue, I have since corrected the code by retrieving the To site ID, so it is now functioning properly at the very least.

    Initially, the code was working fine based on my requirements, but as you pointed out, there were some flaws, which I have rolled back for now.

    To clarify my current requirement, I need a solution to mark all transfer orders as Received for those that are shipped and have the same site ID. Do you think it would be possible to achieve this through a batch job? Ideally, this batch job would fetch all relevant transfer orders and mark them as received on a scheduled basis.
    and thats why  i also  tried to implement that autoreceive button to enable with these condition while shipping.

    I would appreciate any suggestions or insights on how to best implement this.

    Thanks again for your help!
    Ayushaman

  • Suggested answer
    Martin Dráb Profile Picture
    239,519 Most Valuable Professional on at
    Yes, I do think that such a thing can be done in a batch and I think that using an (optionally) batchable operation would be a much better design than your changes in the form.
     
    You seem to need two things: a function to ship transfer orders based on your criteria and to automatically set the AutoReceive flag.
     
    The first part is there out-of-the-box. Go to Inventory management > Periodic tasks > Transfer update > Ship transfer order and notice the Select button (which allows you to select the criteria) and OK and Batch buttons to run the shipment (potentially as a batch job). Therefore you don't need to develop any new batch.
     
    Then you want to set the AutoReceive when creating InventTransferParmTable records. InventTransferMulti.updateInventTransferParmTable() may be the right place.
     
    It's a pity that you didn't tell us your actual requirement, so we discussed little details of your design instead of designing a better solution. Please think about it in your future threads.
  • Ayushaman Profile Picture
    275 on at
    Hi Martin !
     
    Thanks for the prompt response . As per you suggestion i will keep in mind to brief about the requirement before pointing out issues.
     
    As per your guidance i have extended InventTransferMulti class and written the logic 
    [ExtensionOf(classStr(InventTransferMulti))]
    public final class InventTransferMulti_Extension
    {
        protected void updateInventTransferParmTable(InventTransferParmTable _inventTransferParmTable, InventTransferTable _inventTransferTable)
        {
           
            next updateInventTransferParmTable(_inventTransferParmTable, _inventTransferTable);
    
           
            if (!_inventTransferTable)
            {
                _inventTransferTable = InventTransferTable::find(_inventTransferParmTable.TransferId);
    
                if (!_inventTransferTable)
                {
                    throw error(strFmt("InventTransferTable record not found for TransferId: %1", _inventTransferParmTable.TransferId));
                }
            }
    
            
            if (_inventTransferTable.TransferStatus == InventTransferStatus::Shipped)
            {
                InventLocation inventLocationFrom = InventLocation::find(_inventTransferTable.InventLocationIdFrom);
                InventLocation inventLocationTo = InventLocation::find(_inventTransferTable.InventLocationIdTo);
    
            
                if (inventLocationFrom.InventSiteId == inventLocationTo.InventSiteId && !_inventTransferParmTable.AutoReceiveQty)
                {
                 
                    select forUpdate _inventTransferParmTable
                      where  _inventTransferParmTable.TransferId == _inventTransferParmTable.TransferId;
    
                   
    
                        ttsBegin;
                        _inventTransferParmTable.AutoReceiveQty = true;
                        _inventTransferParmTable.update();
                        ttsCommit;
                   
                }
            }
        }
    }
    when i try to receive the transfer order i am getting error "Cannot create a record in Transfer order - update table (InventTransferParmTable). The record already exists," . I am not getting why this issue is coming even when i am updating a existing record. It seems while debugging  its calling main method of inventTransferMultiShip thats where it get stuck. 

    Thanks again for your help!
    Ayushaman
     
  • Suggested answer
    Martin Dráb Profile Picture
    239,519 Most Valuable Professional on at
    Remove your code where you're re-reading _inventTransferParmTable and saving it. You should just assign field values; InventTransferMulti.insert() handles the saving just after calling updateInventTransferParmTable().
     
     
    The whole thing blows up when you replace the record to be inserted with an existing one.
  • Ayushaman Profile Picture
    275 on at
    Martin!
     
    I didn't get you properly. the below shared code in thread is only working and i am not rereading the table in that the above code which i shared in description i removed it . Are you talking about this section 
      select forUpdate _inventTransferParmTable
                      where  _inventTransferParmTable.TransferId == _inventTransferParmTable.TransferId;
    Should i need to call the insert method also? I am getting confused i think can you help me clarify?I really appreciate it .

    Thanks 
    Ayushaman
  • Martin Dráb Profile Picture
    239,519 Most Valuable Professional on at
    No, it's not working. The bug in your code (that I described below) is the cause of the error Cannot create a record in Transfer order - update table (InventTransferParmTable). The record already exists.".
     
    Your code:
    select forUpdate _inventTransferParmTable
        where _inventTransferParmTable.TransferId == _inventTransferParmTable.TransferId;
    finds a wrong record in InventTransferParmTable and replaces the correct value of _inventTransferParmTable with a wrong one.
     
    No, you mustn't call insert(); you would just cause the same error (The record already exists). As I showed you in the screenshot, insert() is already called by F&O. Your goal is changing a value of a single field, not to create an additional record.
     

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Introducing the 2026 Season 1 community Super Users

Congratulations to our 2026 Super Stars!

Meet the Microsoft Dynamics 365 Contact Center Champions

We are thrilled to have these Champions in our Community!

Congratulations to the April Top 10 Community Leaders

These are the community rock stars!

Leaderboard > Finance | Project Operations, Human Resources, AX, GP, SL

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 662 Super User 2026 Season 1

#2
Giorgio Bonacorsi Profile Picture

Giorgio Bonacorsi 660

#3
Subra Profile Picture

Subra 489

Last 30 days Overall leaderboard

Product updates

Dynamics 365 release plans