Updating Future items in stock

Hi, I wonder how I can update future items in stock correctly? Now if I want to update future items I need to call the update two times for it to work? If I only call the update method once, only the current stock updates, but not the future items. Se code below:
Litium version: 7.4.0

            foreach (var stockItem in stockItems)
            {
                var stockitemToUpdate = stockItem.MakeWritableClone();
                // Check if the stock item has future inventory / inventories
                if (stockitemToUpdate.CustomData is FutureInventoryItems futureInventoryItems)
                {
                    // loop through the future inventories and reduce the future stocks
                    foreach (var futureItem in futureInventoryItems.FutureItems)
                    {
                        futureItem.InStockQuantity -= item.Quantity;
                    }
                    stockitemToUpdate.CustomData = futureInventoryItems;
                }
                stockitemToUpdate.InStockQuantity -= item.Quantity;
                using (Solution.Instance.SystemToken.Use(“OrderUtilities.ReduceStockBalance”))
                {
                    {
                        _inventoryItemService.Update(stockitemToUpdate);
                        _inventoryItemService.Update(stockitemToUpdate);
                    }
                }
            }

It should be enough with calling the update method once.
You got 2 extra brackets inside using statement.

Can you share the implementation for the FutureInventoryItems-class?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Litium.ComponentModel;

namespace Columbus.Application.Inventory
{
    public class FutureInventoryItem : IReadOnly
    {
        private bool _isReadOnly { get; set; }
        public int ErpStatus { get; set; }
        public decimal InStockQuantity { get; set; }
        public DateTimeOffset AvailableDateTime { get; set; }

        bool IReadOnly.IsReadOnly => _isReadOnly;
        public void MakeReadOnly()
        {
            _isReadOnly = true;
        }

        public object MakeWritableClone()
        {
            return new FutureInventoryItem
            {
                ErpStatus = this.ErpStatus,
                InStockQuantity = this.InStockQuantity,
                AvailableDateTime = this.AvailableDateTime
            };
        }
    }
    public class FutureInventoryItems : IReadOnly
    {
        private bool _isReadOnly { get; set; }
        public List<FutureInventoryItem> FutureItems { get; set; }
        bool IReadOnly.IsReadOnly => _isReadOnly;

        public FutureInventoryItems()
        {
            FutureItems = new List<FutureInventoryItem>();
        }

        public void MakeReadOnly()
        {
            _isReadOnly = true;
        }
        public object MakeWritableClone()
        {
            return new FutureInventoryItems
            {
                FutureItems = this.FutureItems
            };
        }
    }
}

The problem is that your FutureInventoryItems and FutureInventoryItem classes are not implementing the IReadOnly interface in the correct way.

Example the FutureInventoryItems.MakeWritableClone() is returning an object that referensing to the same FutureItems collection (not a clone of the collection but the same instance) so when the cloned version is changed, also the object in cache will be changed. During update operation the item in cache and the updated item is compared and they are the same (the reference to the same for the FutureItems collection) and the objects will be the same.

If we take for example the TextOption that exists in the product we also have an inner collection; Items that are of the interface IList<Item> instead of the List<Item>. The reason to use the interface one is that when the object will be read only, the IList<> will be a read only version and otherwise a List<>.

using System.Collections.Generic;
using Litium.ComponentModel;

namespace Litium.FieldFramework.FieldTypes
{
    /// <summary>
    /// Class TextOption.
    /// </summary>
    /// <seealso cref="Litium.ComponentModel.ObjectBase" />
    public class TextOption : ObjectBase
    {
        private IList<Item> _items = new List<Item>();
        private bool _multiSelect;
        private bool _manualSort;

        /// <summary>
        /// Gets or sets the items.
        /// </summary>
        /// <value>The items.</value>
        public virtual IList<Item> Items
        {
            get { return _items; }
            set
            {
                ThrowIfReadOnly();
                _items = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [multi select].
        /// </summary>
        /// <value><c>true</c> if [multi select]; otherwise, <c>false</c>.</value>
        public virtual bool MultiSelect
        {
            get { return _multiSelect; }
            set
            {
                ThrowIfReadOnly();
                _multiSelect = value;
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [manual sort].
        /// </summary>
        /// <value><c>true</c> if [manual sort]; otherwise, <c>false</c>.</value>
        public virtual bool ManualSort
        {
            get { return _manualSort; }
            set
            {
                ThrowIfReadOnly();
                _manualSort = value;
            }
        }

        /// <summary>
        /// Class Item.
        /// </summary>
        /// <seealso cref="Litium.ComponentModel.ObjectBase" />
        public class Item : ObjectBase
        {
            private IDictionary<string, string> _name = new Dictionary<string, string>();
            private string _value;

            /// <summary>
            /// Gets or sets the name.
            /// </summary>
            /// <value>The name.</value>
            public virtual IDictionary<string, string> Name
            {
                get { return _name; }
                set
                {
                    ThrowIfReadOnly();
                    _name = value;
                }
            }

            /// <summary>
            /// Gets or sets the value.
            /// </summary>
            /// <value>The value.</value>
            public virtual string Value
            {
                get { return _value; }
                set
                {
                    ThrowIfReadOnly();
                    _value = value;
                }
            }
        }
    }
}

ObjectBase and ObjectBase<> are base classes that have helper methods to transform all the properties from/to read only so the manual creation of the object is not needed.

1 Like

Thanks, we forgot to clone the object properly in makewritableclone()

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.