Advertisement
Guest User

Untitled

a guest
Dec 6th, 2016
83
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 11.32 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using Exact.Exnet.EAFusion.EAFusionServiceTypes;
  7. using Exact.Exnet.EAFusion.ChannelIntegration.Common.Models;
  8. using Exact.Exnet.EAFusion.DataModels.ChannelInventory;
  9. using Exact.Exnet.Common;
  10. using Exact.Exnet.EAFusion.Common;
  11. using Exact.Exnet.EAFusion.DataHelper;
  12. using Exact.Exnet.EAFusion.DataModels.Sql;
  13. using System.Collections.Concurrent;
  14.  
  15. namespace Exact.Exnet.EAFusion.ChannelIntegration.Common.Integration
  16. {
  17.     /// <summary>
  18.     /// Class used to update a channel inventory row's stock fields based on data passed in a ChannelInventoryRow.
  19.     /// </summary>
  20.     /// <typeparam name="TChannelInventoryContext">Specifies the context type that allows access to the Azure Table the channel inventory row is stored in.</typeparam>
  21.     /// <typeparam name="TChannelInventoryRow">Specifies the type of the channel inventory that will be returned from the context object.</typeparam>
  22.     public class UpdateChannelInventoryRowStock<TChannelInventoryContext, TChannelInventoryRow> : ChannelIntegration.Common.Interfaces.IUpdateChannelInventoryRow, Interfaces.IDataHandler
  23.         where TChannelInventoryContext : DataModels.ChannelInventory.BaseChannelInventoryContext<TChannelInventoryRow>, new()
  24.         where TChannelInventoryRow : ChannelInventoryBase, new()
  25.     {
  26.         /// <summary>
  27.         /// Returns a channel object attached to this process.
  28.         /// </summary>
  29.         public Channel Channel
  30.         { get; set; }
  31.  
  32.         /// <summary>
  33.         /// Used to access the entities SQL framework.
  34.         /// </summary>
  35.         public EAFusionExtendedEntities Entities
  36.         { get; set; }
  37.  
  38.         /// <summary>
  39.         /// Creates an instead of the UpdateChannelInventoryRowStockData.
  40.         /// </summary>
  41.         /// <param name="channel"> The Channel which inventory is being update.</param>
  42.         /// <param name="entities"> Accessor to the entities framework. </param>
  43.         public UpdateChannelInventoryRowStock(Channel channel, EAFusionExtendedEntities entities)
  44.         {
  45.             this.Channel = channel;
  46.             this.Entities = entities;
  47.         }
  48.  
  49.         /// <summary>
  50.         /// Used to create a Channel Inventory Update Information object for the specified ChannelInventoryRow.
  51.         /// </summary>
  52.         /// <param name="channelInventoryRow">Row to be contained in the update information.</param>
  53.         /// <returns></returns>
  54.         private ChannelInventoryUpdateInformation CreateChannelInventoryUpdateInformation(ChannelInventoryRow channelInventoryRow)
  55.         {
  56.             ChannelInventoryUpdateInformation channelInventoryUpdateInformation = new ChannelInventoryUpdateInformation();
  57.  
  58.             channelInventoryUpdateInformation.ChannelInventoryRow = channelInventoryRow;
  59.  
  60.             channelInventoryUpdateInformation.UpdateType = ChannelInventoryUpdateType.StockOnly;
  61.  
  62.             return channelInventoryUpdateInformation;
  63.         }
  64.  
  65.         /// <summary>
  66.         /// Copies an parameter 'Main' channel inventroy row into another row so it can me marked for requiring a stock update.
  67.         /// </summary>
  68.         /// <param name="channelInventoryRow"> Main Channel Inventory Row.</param>
  69.         /// <returns>Returns the copied Stock Update Channel Inventory Row.</returns>
  70.         private TChannelInventoryRow CreateChannelInventoryForStockUpdate(TChannelInventoryRow channelInventoryRow)
  71.         {
  72.             // Set the Channel Inventory Row with a new partition of the ChannelIdentifier_STOCKUPDATE.
  73.             // This will create a duplicate row once saved into AzureTableStorage.
  74.             channelInventoryRow.PartitionKey = string.Format("{0}_{1}", this.Channel.Identifier, "STOCKUPDATE");
  75.  
  76.             return channelInventoryRow;
  77.  
  78.         }
  79.  
  80.         /// <summary>
  81.         /// Used to perform the update 'Stock Only' on a Channel Inventory row.
  82.         /// </summary>
  83.         /// <remarks> Channel Integrations with more specific implementations could overright this implementation with their own. </remarks>
  84.         /// <param name="channelInventoryRow">Passed from the WebService, contains data to update a Channel Inventory in EAFusion.</param>
  85.         /// <returns>Used to determine if the Channel Inventory row has been modified.</returns>
  86.         public virtual UpdateChannelInventoryRowResult UpdateChannelInventory(ChannelInventoryRow channelInventoryRow)
  87.         {
  88.             bool rowChanged = false;
  89.  
  90.             int retryCount = 0;
  91.             while (true)
  92.             {
  93.                 try
  94.                 {
  95.                     using (TChannelInventoryContext context = new TChannelInventoryContext())
  96.                     {
  97.                         TChannelInventoryRow row = context.GetExistingRow(this.Channel.Identifier, channelInventoryRow.Sku, true);
  98.  
  99.                         if(this.ModifyChannelInventoryFields(channelInventoryRow, row))
  100.                         {
  101.                             context.UpdateObject(row);
  102.                             context.SaveChanges();
  103.                         }
  104.                     }
  105.  
  106.                     //break out of the retry loop as the method will have succeeded
  107.                     break;
  108.                 }
  109.                 catch (Microsoft.WindowsAzure.Storage.StorageException ex)
  110.                 {
  111.                     //determine if the error is a concurrency error
  112.                     bool shouldRetry = ex.IsConcurrencyException() || ex.IsDuplicateException();
  113.  
  114.                     //If the exception isn't a concurrency, or this is the 3rd attempt, just throw the exception.
  115.                     if ((!shouldRetry) || retryCount > 2)
  116.                     {
  117.                         throw;
  118.                     }
  119.                     else retryCount++;
  120.                 }
  121.             }
  122.  
  123.             UpdateChannelInventoryRowResult updateChannelInventoryRowResult = new UpdateChannelInventoryRowResult()
  124.             {
  125.                 RowChanged = rowChanged
  126.             };
  127.  
  128.             return updateChannelInventoryRowResult;
  129.         }
  130.  
  131.         /// <summary>
  132.         /// Used to modified channel inventory fields for the stock update.
  133.         /// </summary>
  134.         /// <param name="channelInventoryRow">Row passed via the Web Service, contains data to update our Azure Table Storage row with.</param>
  135.         /// <param name="row"> Inventory Row from Azure Table Storage/param>
  136.         /// <returns>Returns true if the row has been modified.</returns>
  137.         protected bool ModifyChannelInventoryFields(ChannelInventoryRow channelInventoryRow, TChannelInventoryRow row)
  138.         {
  139.             bool rowModified = false;
  140.  
  141.             //Create the Update Information object, this is used to logging the results of the update routine.
  142.             ChannelInventoryUpdateInformation channelInventoryUpdateInformation = this.CreateChannelInventoryUpdateInformation(channelInventoryRow);
  143.  
  144.             if (row == null)
  145.             {
  146.                 //No inventory has been found for the specified ChannelInventoryRow, set the ResultType to display this.
  147.                 channelInventoryUpdateInformation.ResultType = ChannelInventoryUpdateResultType.InventoryRowNotFound;
  148.  
  149.                 return false;
  150.             }
  151.  
  152.             ChannelInventoryModifiedComparer<TChannelInventoryRow> channelInventoryComparison = new ChannelInventoryModifiedComparer<TChannelInventoryRow>(row);
  153.  
  154.             //Call the 'ModifyChannelInventoryQuantityField' method that is overriden by derived class, allowing then to perform their own logic.
  155.             this.ModifyChannelInventoryQuantityField(channelInventoryRow, row, ref rowModified);
  156.  
  157.             //Determine if an update is required. E.g. Has data changed.
  158.             if (rowModified)
  159.             {
  160.                 //Check the stock control type of the channel inventory row.
  161.                 this.CheckStockControlType(channelInventoryRow, row);
  162.  
  163.                 row.InventoryUpdatedLocally = true;
  164.  
  165.                 rowModified = true;
  166.  
  167.                 channelInventoryUpdateInformation.ResultType = ChannelInventoryUpdateResultType.Successful;
  168.             }
  169.             else
  170.             {
  171.                 channelInventoryUpdateInformation.ResultType = ChannelInventoryUpdateResultType.NoModificationsOccurred;
  172.             }
  173.  
  174.             List<ModifiedField> modifiedFields = channelInventoryComparison.Compare(row);
  175.             if (!modifiedFields.IsNullOrEmpty())
  176.             {
  177.                 channelInventoryUpdateInformation.ModifiedFields = new List<ModifiedField>();
  178.                 channelInventoryUpdateInformation.ModifiedFields.AddRange(modifiedFields);
  179.             }
  180.  
  181.             this.SaveChannelInventoryUpdateInformation(channelInventoryUpdateInformation);
  182.  
  183.             return rowModified;
  184.         }
  185.  
  186.         /// <summary>
  187.         /// Saves the created Channel Inventory Update information in azure table storage.
  188.         /// </summary>
  189.         /// <param name="channelInventoryUpdateInformation"> Row containing information on the update proces.</param>
  190.         private void SaveChannelInventoryUpdateInformation(ChannelInventoryUpdateInformation channelInventoryUpdateInformation)
  191.         {
  192.             using (ChannelInventoryMessageContext channelInventoryMessageContext = new ChannelInventoryMessageContext())
  193.             {
  194.                 ChannelInventoryMessage channelInventoryMessage = new ChannelInventoryMessage();
  195.  
  196.                 channelInventoryMessage.SetRowKeyAndPartitionKey(this.Channel.Identifier, channelInventoryUpdateInformation.ChannelInventoryRow.Sku);
  197.  
  198.                 channelInventoryMessage.SetMessageActionType(Exact.Exnet.EAFusion.Common.Enumerations.ChannelInventoryMessageActionType.Unknown);
  199.  
  200.                 channelInventoryMessage.SetDetails(channelInventoryUpdateInformation.ToString(), channelInventoryMessageContext);
  201.  
  202.                 channelInventoryMessage.SetMessageActionResult(ChannelInventoryMessageActionResult.Unknown);
  203.  
  204.                 channelInventoryMessageContext.AddObject(channelInventoryMessage);
  205.  
  206.                 channelInventoryMessageContext.SaveChanges();
  207.             }
  208.         }
  209.  
  210.         /// <summary>
  211.         /// Attempts to update a Channel Inventory row obtained from Table Storage based on the ChannelInventoryRow passed from the webservice.
  212.         /// </summary>
  213.         /// <remarks> Dervived classes provide their own custom implementations for this method due to integrations changining different data.</remarks>
  214.         /// <param name="channelInventoryRow">Passed from the WebService, contains data to update a Channel Inventory in EAFusion.</param>
  215.         /// <param name="row">Channel Inventory row obtained from TableStorage.</param>
  216.         /// <param name="rowModified">Used to determine if the Channel Inventory row has been modified.</param>
  217.         protected virtual void ModifyChannelInventoryQuantityField(ChannelInventoryRow channelInventoryRow, TChannelInventoryRow row, ref bool rowModified)
  218.         {
  219.             throw new InvalidOperationException(string.Format("UpdateChannelInventoryForStockOnly has not been implemented for DataType : {0}", row));
  220.         }
  221.  
  222.         private void CheckStockControlType(ChannelInventoryRow channelInventoryRow, TChannelInventoryRow row)
  223.         {
  224.             ControlStockType existingControlStockType = row.GetControlStock();
  225.  
  226.             if (channelInventoryRow.ControlStock)
  227.             {
  228.                 if (existingControlStockType != ControlStockType.ControlStock)
  229.                 {
  230.                     row.SetControlStock(ControlStockType.ControlStock);
  231.                 }
  232.             }
  233.             else
  234.             {
  235.                 if (existingControlStockType == ControlStockType.ControlStock)
  236.                 {
  237.                     row.SetControlStock(ControlStockType.NoStockControl);
  238.                 }
  239.             }
  240.         }
  241.  
  242.         /// Method used to determine if the quantity value has changed, true will be returned if the inventory row in EAFusion has been updated.
  243.         /// </summary>
  244.         /// <param name="channelInventoryRow">Channel Inventory Row included in the Update Channel Inventory web service method.</param>
  245.         /// <param name="channelInventoryBase">Channel inventory base data stored in EAFusion.</param>
  246.         /// <returns>True will be returned if the inventory row in EAFusion has been updated.</returns>
  247.         protected bool HasQuantityChanged(ChannelInventoryRow channelInventoryRow, ChannelInventoryBase channelInventoryBase)
  248.         {
  249.             bool hasChanged = false;
  250.  
  251.             //Determine if the quantity has been passed from 3EX.net
  252.             if (channelInventoryRow.Quantity.HasValue)
  253.             {
  254.                 //Determine if the quantity of the inventory row in EAFusion differs from that specfied on the channel inventory row.
  255.                 if ((channelInventoryBase.Quantity != channelInventoryRow.Quantity.Value) || (channelInventoryRow.ForceQuantityUpdate.HasValue && channelInventoryRow.ForceQuantityUpdate.Value))
  256.                 {
  257.                     hasChanged = true;
  258.                 }
  259.             }
  260.  
  261.             return hasChanged;
  262.         }
  263.     }
  264. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement