Skip to main content
Answer

Is It Possible to Allow Concurrent Updates To Detail Lines Of A Document?

  • January 1, 2025
  • 6 replies
  • 197 views

MichaelShirk
Captain II
Forum|alt.badge.img+5

I’ve created a custom header/detail screen to help us with physical inventory review and reconciliation. Physical Inventory is always on a tight timeline, and we really need to somehow be able to have multiple users working on the same document simultaneously.

Obviously they still shouldn’t be allowed to modify the same detail records at the same time, but I want to allow both to access and update different lines of the same detail document at the same time. 
 

Is there any way possible to do this?
 

I appreciate any ideas.

Best answer by davidnavasardyan

@MichaelShirk Unfortunately, this is not possible. As we know, data must be cached before it can be persisted to the database. However, Acumatica does not share the same graph cache concurrently, making it impossible to modify the same document with different data at the same time. Doing so would lead to ambiguous and potentially corrupted data.

6 replies

davidnavasardyan
Jr Varsity I
Forum|alt.badge.img+3

@MichaelShirk Unfortunately, this is not possible. As we know, data must be cached before it can be persisted to the database. However, Acumatica does not share the same graph cache concurrently, making it impossible to modify the same document with different data at the same time. Doing so would lead to ambiguous and potentially corrupted data.


Yuriy Zaletskyy
Jr Varsity I
Forum|alt.badge.img+3

That is against Optimistic Concurency model of Acumatica. Optimistic concurency means, that everyone can open the document, but saved changes will be performed by the only one.

As kind of workaround, it is possible to make via SignalR and javascript and hubproxy notify other users, if they deal with the same order. 


Forum|alt.badge.img+7
  • Captain II
  • January 2, 2025

I’d be tempted to look at an alternate mechanic for the count collection. Without knowing much about your custom screen I’ll make the assumption that you have a simplified data collection screen where the total count of the inventory will be reviewed and then sent along to the regular Acumatica processing.

One thought I had would be to create a parallel header/detail setup but include another column in your primary key for both the header and the table of User ID.

On your existing form, you’d have an action button to “spawn count sheet” and that process would ask for a User ID. This will generate a copy of the count sheet but it’s for that user to perform the counts. They can enter their values without impacting any other user updates.

When all the count sheets are in (or at any time you want) you go back to your original custom screen and run an action called “Consolidate Counts”. It will pull in the inventory counts from the user’s count sheets. Thus you have just one process that it updating this screen for the final review before sending along to be released.

There are some potential benefits to breaking up the count sheets that was as you can control the logic on how the user’s count sheets are populated. You can build them by warehouse/zone/etc. Then, taking this a step further, each user can have their own mobile screen where they are entering the counts.

Just some ideas to ponder.


MichaelShirk
Captain II
Forum|alt.badge.img+5
  • Author
  • Captain II
  • January 2, 2025

Thank you ​@davidnavasardyan  and ​@Yuriy Zaletskyy ,

This is what I understood as well, but I was hoping there was a trick to making it work. 

We’ll have to explore alternative solutions.


mariankharechko60
Jr Varsity I

While Acumatica's default framework strongly relies on caching and its internal validation mechanisms, it is possible to bypass these by using direct database updates through PXDatabase.Update. Below is an approach that leverages a custom action, Custom Save, which omits the standard caching model for saving changes to the database directly:

public PXAction<SOOrder> CustomSave;
        [PXButton(CommitChanges = true)]
        [PXUIField(DisplayName = "Custom Save", MapEnableRights = PXCacheRights.Update, MapViewRights = PXCacheRights.Update)]
        public virtual IEnumerable customSave(PXAdapter adapter)
        {
            try
            {
                PXLongOperation.StartOperation(Base, () =>
                {
                    SaveCustomChanges();
                });
            }
            catch (PXException ex)
            {
                PXTrace.WriteError(ex);
                throw;
            }
            return adapter.Get();
        }

        private void SaveCustomChanges()
        {
            using (PXTransactionScope ts = new PXTransactionScope())
            {
                var lineCache = Base.Transactions.Cache.Updated;

                foreach (SOLine line in lineCache)
                {

                    PXDatabase.Update<SOLine>(
                        new PXDataFieldAssign<SOLine.orderQty>(PXDbType.Decimal, line.Qty),
                        new PXDataFieldRestrict<SOLine.orderNbr>(PXDbType.NVarChar, line.OrderNbr),
                        new PXDataFieldRestrict<SOLine.lineNbr>(PXDbType.Int, line.LineNbr)
                    );
                }

                ts.Complete();
            }

            Base.Transactions.Cache.Clear();
            Base.Transactions.View.RequestRefresh();
        }

This method works but comes with its own risks and limitations. Use this approach only if the requirements cannot be met within the standard Acumatica framework and you're prepared to manage the potential implications manually.


Tony Lanzer
Pro III
Forum|alt.badge.img+2
  • Pro III
  • January 6, 2025

@MichaelShirk As others have mentioned, standard Acumatica doesn’t support it.  I can envision a further customized design solution that might work, though.  If the user was added as part of the primary key of a child detail line, those records could then be edited independently.  Then a reconcile/merge process could be triggered to update the parent detail line automatically (or even manually) and according to your rules.