Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using Exact.Exnet.EAFusion.EAFusionServiceTypes;
- using Exact.Exnet.EAFusion.ChannelIntegration.Common.Models;
- using Exact.Exnet.EAFusion.DataModels.ChannelInventory;
- using Exact.Exnet.Common;
- using Exact.Exnet.EAFusion.Common;
- using Exact.Exnet.EAFusion.DataHelper;
- using Exact.Exnet.EAFusion.DataModels.Sql;
- using System.Collections.Concurrent;
- namespace Exact.Exnet.EAFusion.ChannelIntegration.Common.Integration
- {
- /// <summary>
- /// Class used to update a channel inventory row's stock fields based on data passed in a ChannelInventoryRow.
- /// </summary>
- /// <typeparam name="TChannelInventoryContext">Specifies the context type that allows access to the Azure Table the channel inventory row is stored in.</typeparam>
- /// <typeparam name="TChannelInventoryRow">Specifies the type of the channel inventory that will be returned from the context object.</typeparam>
- public class UpdateChannelInventoryRowStock<TChannelInventoryContext, TChannelInventoryRow> : ChannelIntegration.Common.Interfaces.IUpdateChannelInventoryRow, Interfaces.IDataHandler
- where TChannelInventoryContext : DataModels.ChannelInventory.BaseChannelInventoryContext<TChannelInventoryRow>, new()
- where TChannelInventoryRow : ChannelInventoryBase, new()
- {
- /// <summary>
- /// Returns a channel object attached to this process.
- /// </summary>
- public Channel Channel
- { get; set; }
- /// <summary>
- /// Used to access the entities SQL framework.
- /// </summary>
- public EAFusionExtendedEntities Entities
- { get; set; }
- /// <summary>
- /// Creates an instead of the UpdateChannelInventoryRowStockData.
- /// </summary>
- /// <param name="channel"> The Channel which inventory is being update.</param>
- /// <param name="entities"> Accessor to the entities framework. </param>
- public UpdateChannelInventoryRowStock(Channel channel, EAFusionExtendedEntities entities)
- {
- this.Channel = channel;
- this.Entities = entities;
- }
- /// <summary>
- /// Used to create a Channel Inventory Update Information object for the specified ChannelInventoryRow.
- /// </summary>
- /// <param name="channelInventoryRow">Row to be contained in the update information.</param>
- /// <returns></returns>
- private ChannelInventoryUpdateInformation CreateChannelInventoryUpdateInformation(ChannelInventoryRow channelInventoryRow)
- {
- ChannelInventoryUpdateInformation channelInventoryUpdateInformation = new ChannelInventoryUpdateInformation();
- channelInventoryUpdateInformation.ChannelInventoryRow = channelInventoryRow;
- channelInventoryUpdateInformation.UpdateType = ChannelInventoryUpdateType.StockOnly;
- return channelInventoryUpdateInformation;
- }
- /// <summary>
- /// Copies an parameter 'Main' channel inventroy row into another row so it can me marked for requiring a stock update.
- /// </summary>
- /// <param name="channelInventoryRow"> Main Channel Inventory Row.</param>
- /// <returns>Returns the copied Stock Update Channel Inventory Row.</returns>
- private TChannelInventoryRow CreateChannelInventoryForStockUpdate(TChannelInventoryRow channelInventoryRow)
- {
- // Set the Channel Inventory Row with a new partition of the ChannelIdentifier_STOCKUPDATE.
- // This will create a duplicate row once saved into AzureTableStorage.
- channelInventoryRow.PartitionKey = string.Format("{0}_{1}", this.Channel.Identifier, "STOCKUPDATE");
- return channelInventoryRow;
- }
- /// <summary>
- /// Used to perform the update 'Stock Only' on a Channel Inventory row.
- /// </summary>
- /// <remarks> Channel Integrations with more specific implementations could overright this implementation with their own. </remarks>
- /// <param name="channelInventoryRow">Passed from the WebService, contains data to update a Channel Inventory in EAFusion.</param>
- /// <returns>Used to determine if the Channel Inventory row has been modified.</returns>
- public virtual UpdateChannelInventoryRowResult UpdateChannelInventory(ChannelInventoryRow channelInventoryRow)
- {
- bool rowChanged = false;
- int retryCount = 0;
- while (true)
- {
- try
- {
- using (TChannelInventoryContext context = new TChannelInventoryContext())
- {
- TChannelInventoryRow row = context.GetExistingRow(this.Channel.Identifier, channelInventoryRow.Sku, true);
- if(this.ModifyChannelInventoryFields(channelInventoryRow, row))
- {
- context.UpdateObject(row);
- context.SaveChanges();
- }
- }
- //break out of the retry loop as the method will have succeeded
- break;
- }
- catch (Microsoft.WindowsAzure.Storage.StorageException ex)
- {
- //determine if the error is a concurrency error
- bool shouldRetry = ex.IsConcurrencyException() || ex.IsDuplicateException();
- //If the exception isn't a concurrency, or this is the 3rd attempt, just throw the exception.
- if ((!shouldRetry) || retryCount > 2)
- {
- throw;
- }
- else retryCount++;
- }
- }
- UpdateChannelInventoryRowResult updateChannelInventoryRowResult = new UpdateChannelInventoryRowResult()
- {
- RowChanged = rowChanged
- };
- return updateChannelInventoryRowResult;
- }
- /// <summary>
- /// Used to modified channel inventory fields for the stock update.
- /// </summary>
- /// <param name="channelInventoryRow">Row passed via the Web Service, contains data to update our Azure Table Storage row with.</param>
- /// <param name="row"> Inventory Row from Azure Table Storage/param>
- /// <returns>Returns true if the row has been modified.</returns>
- protected bool ModifyChannelInventoryFields(ChannelInventoryRow channelInventoryRow, TChannelInventoryRow row)
- {
- bool rowModified = false;
- //Create the Update Information object, this is used to logging the results of the update routine.
- ChannelInventoryUpdateInformation channelInventoryUpdateInformation = this.CreateChannelInventoryUpdateInformation(channelInventoryRow);
- if (row == null)
- {
- //No inventory has been found for the specified ChannelInventoryRow, set the ResultType to display this.
- channelInventoryUpdateInformation.ResultType = ChannelInventoryUpdateResultType.InventoryRowNotFound;
- return false;
- }
- ChannelInventoryModifiedComparer<TChannelInventoryRow> channelInventoryComparison = new ChannelInventoryModifiedComparer<TChannelInventoryRow>(row);
- //Call the 'ModifyChannelInventoryQuantityField' method that is overriden by derived class, allowing then to perform their own logic.
- this.ModifyChannelInventoryQuantityField(channelInventoryRow, row, ref rowModified);
- //Determine if an update is required. E.g. Has data changed.
- if (rowModified)
- {
- //Check the stock control type of the channel inventory row.
- this.CheckStockControlType(channelInventoryRow, row);
- row.InventoryUpdatedLocally = true;
- rowModified = true;
- channelInventoryUpdateInformation.ResultType = ChannelInventoryUpdateResultType.Successful;
- }
- else
- {
- channelInventoryUpdateInformation.ResultType = ChannelInventoryUpdateResultType.NoModificationsOccurred;
- }
- List<ModifiedField> modifiedFields = channelInventoryComparison.Compare(row);
- if (!modifiedFields.IsNullOrEmpty())
- {
- channelInventoryUpdateInformation.ModifiedFields = new List<ModifiedField>();
- channelInventoryUpdateInformation.ModifiedFields.AddRange(modifiedFields);
- }
- this.SaveChannelInventoryUpdateInformation(channelInventoryUpdateInformation);
- return rowModified;
- }
- /// <summary>
- /// Saves the created Channel Inventory Update information in azure table storage.
- /// </summary>
- /// <param name="channelInventoryUpdateInformation"> Row containing information on the update proces.</param>
- private void SaveChannelInventoryUpdateInformation(ChannelInventoryUpdateInformation channelInventoryUpdateInformation)
- {
- using (ChannelInventoryMessageContext channelInventoryMessageContext = new ChannelInventoryMessageContext())
- {
- ChannelInventoryMessage channelInventoryMessage = new ChannelInventoryMessage();
- channelInventoryMessage.SetRowKeyAndPartitionKey(this.Channel.Identifier, channelInventoryUpdateInformation.ChannelInventoryRow.Sku);
- channelInventoryMessage.SetMessageActionType(Exact.Exnet.EAFusion.Common.Enumerations.ChannelInventoryMessageActionType.Unknown);
- channelInventoryMessage.SetDetails(channelInventoryUpdateInformation.ToString(), channelInventoryMessageContext);
- channelInventoryMessage.SetMessageActionResult(ChannelInventoryMessageActionResult.Unknown);
- channelInventoryMessageContext.AddObject(channelInventoryMessage);
- channelInventoryMessageContext.SaveChanges();
- }
- }
- /// <summary>
- /// Attempts to update a Channel Inventory row obtained from Table Storage based on the ChannelInventoryRow passed from the webservice.
- /// </summary>
- /// <remarks> Dervived classes provide their own custom implementations for this method due to integrations changining different data.</remarks>
- /// <param name="channelInventoryRow">Passed from the WebService, contains data to update a Channel Inventory in EAFusion.</param>
- /// <param name="row">Channel Inventory row obtained from TableStorage.</param>
- /// <param name="rowModified">Used to determine if the Channel Inventory row has been modified.</param>
- protected virtual void ModifyChannelInventoryQuantityField(ChannelInventoryRow channelInventoryRow, TChannelInventoryRow row, ref bool rowModified)
- {
- throw new InvalidOperationException(string.Format("UpdateChannelInventoryForStockOnly has not been implemented for DataType : {0}", row));
- }
- private void CheckStockControlType(ChannelInventoryRow channelInventoryRow, TChannelInventoryRow row)
- {
- ControlStockType existingControlStockType = row.GetControlStock();
- if (channelInventoryRow.ControlStock)
- {
- if (existingControlStockType != ControlStockType.ControlStock)
- {
- row.SetControlStock(ControlStockType.ControlStock);
- }
- }
- else
- {
- if (existingControlStockType == ControlStockType.ControlStock)
- {
- row.SetControlStock(ControlStockType.NoStockControl);
- }
- }
- }
- /// Method used to determine if the quantity value has changed, true will be returned if the inventory row in EAFusion has been updated.
- /// </summary>
- /// <param name="channelInventoryRow">Channel Inventory Row included in the Update Channel Inventory web service method.</param>
- /// <param name="channelInventoryBase">Channel inventory base data stored in EAFusion.</param>
- /// <returns>True will be returned if the inventory row in EAFusion has been updated.</returns>
- protected bool HasQuantityChanged(ChannelInventoryRow channelInventoryRow, ChannelInventoryBase channelInventoryBase)
- {
- bool hasChanged = false;
- //Determine if the quantity has been passed from 3EX.net
- if (channelInventoryRow.Quantity.HasValue)
- {
- //Determine if the quantity of the inventory row in EAFusion differs from that specfied on the channel inventory row.
- if ((channelInventoryBase.Quantity != channelInventoryRow.Quantity.Value) || (channelInventoryRow.ForceQuantityUpdate.HasValue && channelInventoryRow.ForceQuantityUpdate.Value))
- {
- hasChanged = true;
- }
- }
- return hasChanged;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement