private StockItem BuildNewStockItem(string warehouseId, ShopifyVariant variant) { var settings = _settingsRepository.RetrieveSettings(); var defaultItemClass = settings.AcumaticaDefaultItemClass; var defaultPostingClass = settings.AcumaticaDefaultPostingClass; var defaultTaxCategory = variant.ShopifyIsTaxable.TaxCategory(settings); var shopifyVariant = _shopifyJsonService.RetrieveVariant(variant.ShopifyVariantId); var shopifyProduct = _shopifyJsonService.RetrieveProduct(variant.ShopifyProduct.ShopifyProductId); var newStockItem = new StockItem(); newStockItem.InventoryID = variant.StandardizedSku().ToValue(); newStockItem.Description = Canonizers.StandardizedStockItemTitle(shopifyProduct, shopifyVariant).ToValue(); newStockItem.DefaultPrice = ((double)shopifyVariant.price).ToValue(); newStockItem.DefaultWarehouseID = warehouseId.ToValue(); var dimensionWeight = (double)shopifyVariant.grams.ToAcumaticaOunces(); // newStockItem.WeightUOM = WeightCalc.AcumaticaUnitsOfMeasure.ToValue(); newStockItem.DimensionWeight = dimensionWeight.ToValue(); newStockItem.ItemClass = defaultItemClass.ToValue(); newStockItem.PostingClass = defaultPostingClass.ToValue(); newStockItem.TaxCategory = defaultTaxCategory.ToValue(); return(newStockItem); }
public void InsertItemSync(ShopifyVariant variant, AcumaticaStockItem stockItem, bool isSyncEnabled) { stockItem.ShopifyVariantMonsterId = variant.MonsterId; stockItem.IsSyncEnabled = isSyncEnabled; stockItem.LastUpdated = DateTime.UtcNow; Entities.SaveChanges(); }
public static IList <ShopifyVariant> Exclude( this IEnumerable <ShopifyVariant> input, ShopifyVariant exclude) { return(input .Where(x => x.ShopifyVariantId != exclude.ShopifyVariantId && x.ShopifySku != exclude.ShopifySku).ToList()); }
private void CreateSyncRecord(string sku, ShopifyVariant variantRecord) { var stockItem = _syncInventoryRepository.RetrieveStockItem(sku.StandardizedSku()); stockItem.IsVariantSynced = false; stockItem.AcumaticaInventories.ForEach(x => x.IsInventorySynced = false); _syncInventoryRepository.InsertItemSync(variantRecord, stockItem, true); }
public static string AcumaticaStockItemId(this ShopifyVariant input) { if (!input.AcumaticaStockItems.Any()) { throw new Exception("No synchronized Acumatica Stock Items"); } return(input.AcumaticaStockItems.First().ItemId); }
public static bool AreSkuAndItemIdMismatched(this ShopifyVariant input) { if (!input.IsSynced()) { return(false); } else { return(input.ShopifySku.StandardizedSku() != input.MatchedStockItem().ItemId.StandardizedSku()); } }
private int RunStockItemImport(AcumaticaStockItemImportContext context, ShopifyVariant variant) { var matchingShopifySkus = _syncRepository.RetrieveNonMissingVariants(variant.StandardizedSku()); if (matchingShopifySkus.Count > 1) { _logService.Log($"Stock Item Import: {variant.LogDescriptor()} has duplicates in Shopify - aborting"); return(StockItemPutResult.NoAction); } // Attempt to Auto-match // if (variant.IsMatched()) { _logService.Log($"Stock Item Import: {variant.LogDescriptor()} already matched - aborting"); return(StockItemPutResult.NoAction); } var stockItem = _syncRepository.RetrieveStockItem(variant.StandardizedSku()); if (stockItem != null) { if (stockItem.IsMatched()) { var msg = $"Stock Item Import: {variant.LogDescriptor()} SKU already synchronized"; _logService.Log(msg); return(StockItemPutResult.NoAction); } else { var msg = $"Stock Item Import: auto-matched {stockItem.LogDescriptor()} to {variant.LogDescriptor()}"; _logService.Log(msg); _syncRepository.InsertItemSync(variant, stockItem, context.IsSyncEnabled); return(StockItemPutResult.Synchronized); } } // Abort any further processing if (context.SynchronizeOnly == true) { return(StockItemPutResult.NoAction); } // With neither duplicates or Auto-matching having succeeded, // ... we'll create a new Stock Item in Acumatica // StockItemPush(context, variant); context.VariantsForNextInventoryReceipt.Add(variant); return(StockItemPutResult.CreatedStockItem); }
public ShopifyVariantModel MakeVariantModel(ShopifyVariant input) { var output = new ShopifyVariantModel(); output.ShopifyVariantId = input.ShopifyVariantId; output.Sku = input.ShopifySku; output.VariantTitle = input.ShopifyTitle; output.Price = (decimal)input.ShopifyPrice; output.AvailableQuantity = input.ShopifyInventoryLevels.Sum(x => x.ShopifyAvailableQuantity); output.IsMissing = input.IsMissing; output.IsLoadedInAcumatica = input.IsMatched(); return(output); }
public void ProcessMissingVariant(ShopifyVariant variantRecord) { var log = $"Shopify Variant {variantRecord.ShopifySku} ({variantRecord.ShopifyVariantId}) is missing"; _logger.Debug(log); using (var transaction = _inventoryRepository.BeginTransaction()) { // Flag as Missing and destroy synchronization // variantRecord.IsMissing = true; var stockItemRecord = variantRecord.AcumaticaStockItems.FirstOrDefault(); if (stockItemRecord != null) { // Remove the synchronization // stockItemRecord.ShopifyVariant = null; // Locate replacement Variant to sync with // var replacements = variantRecord .ShopifyProduct .NonMissingVariants() .Where(x => x.ShopifySku.StandardizedSku() == variantRecord.ShopifySku.StandardizedSku()) .ToList(); // Either no viable Duplicates, abort // if (replacements.Count == 1) { stockItemRecord.ShopifyVariant = replacements.First(); } stockItemRecord.LastUpdated = DateTime.UtcNow; _inventoryRepository.SaveChanges(); } transaction.Commit(); } }
MakeProductStockItemResults(ShopifyVariant variant, MonsterSetting settings) { var output = new ProductStockItemResultsRow(); output.ShopifyProductId = variant.ShopifyProduct.ShopifyProductId; output.ShopifyProductTitle = variant.ShopifyProduct.ShopifyTitle; output.ShopifyProductUrl = _shopifyUrlService.ShopifyProductUrl(variant.ShopifyProduct.ShopifyProductId); output.ShopifyVariantId = variant.ShopifyVariantId; output.ShopifyVariantTitle = variant.ShopifyTitle; output.ShopifyVariantSku = variant.ShopifySku; output.ShopifyVariantUrl = _shopifyUrlService.ShopifyVariantUrl( variant.ShopifyProduct.ShopifyProductId, variant.ShopifyVariantId); output.ShopifyVariantTax = variant.ShopifyIsTaxable ? "YES" : "NO"; output.ShopifyVariantPrice = variant.ShopifyPrice; output.ShopifyVariantAvailQty = variant.ShopifyInventoryLevels.Sum(x => x.ShopifyAvailableQuantity); output.IsShopifyProductDeleted = variant.ShopifyProduct.IsDeleted; output.IsShopifyVariantMissing = variant.IsMissing; output.HasDuplicateSkus = HasDuplicateSkus(variant.ShopifySku); if (variant.IsMatched()) { var stockItemRecord = variant.MatchedStockItem(); var stockItem = _acumaticaJsonService.RetrieveStockItem(stockItemRecord.ItemId); output.AcumaticaItemId = stockItemRecord.ItemId; output.AcumaticaItemDesc = stockItemRecord.AcumaticaDescription; output.AcumaticaItemUrl = _acumaticaUrlService.AcumaticaStockItemUrl(stockItemRecord.ItemId); output.AcumaticaItemTax = stockItemRecord.IsTaxable(settings).YesNoNaPlainEnglish(); output.AcumaticaItemPrice = (decimal)stockItem.DefaultPrice.value; output.AcumaticaItemAvailQty = stockItemRecord.AcumaticaInventories.Sum(x => (int)x.AcumaticaAvailQty); output.HasMismatchedSku = variant.AreSkuAndItemIdMismatched(); output.HasMismatchedTaxes = variant.AreTaxesMismatched(settings); } return(output); }
public static bool AreTaxesMismatched(this ShopifyVariant input, MonsterSetting settings) { if (!input.IsSynced()) { return(false); } if (input.ShopifyIsTaxable && input.MatchedStockItem().AcumaticaTaxCategory == settings.AcumaticaTaxableCategory) { return(false); } if (!input.ShopifyIsTaxable && input.MatchedStockItem().AcumaticaTaxCategory == settings.AcumaticaTaxExemptCategory) { return(false); } return(true); }
public void UpsertInventory( ShopifyVariant variant, InventoryItem shopifyItem, List <InventoryLevel> shopifyLevels) { var existingLevels = _inventoryRepository.RetrieveInventory(variant.ShopifyInventoryItemId); var locations = _inventoryRepository.RetreiveLocations(); foreach (var shopifyLevel in shopifyLevels) { var existingLevel = existingLevels.FirstOrDefault(x => x.ShopifyLocationId == shopifyLevel.location_id); var location = locations.First(x => x.ShopifyLocationId == shopifyLevel.location_id); if (existingLevel == null) { var newLevel = new ShopifyInventoryLevel(); newLevel.ParentMonsterId = variant.MonsterId; newLevel.ShopifyInventoryItemId = shopifyLevel.inventory_item_id; newLevel.ShopifyLocationId = shopifyLevel.location_id; newLevel.ShopifyAvailableQuantity = shopifyLevel.available ?? 0; newLevel.LocationMonsterId = location.MonsterId; newLevel.DateCreated = DateTime.UtcNow; newLevel.LastUpdated = DateTime.UtcNow; _inventoryRepository.InsertInventory(newLevel); } else { existingLevel.ShopifyAvailableQuantity = shopifyLevel.available ?? 0; existingLevel.LastUpdated = DateTime.UtcNow; _inventoryRepository.SaveChanges(); } } }
public void StockItemPush(AcumaticaStockItemImportContext context, ShopifyVariant variant) { _logService.Log(LogBuilder.CreateStockItem(variant)); var newStockItem = BuildNewStockItem(context.WarehouseId, variant); var newStockItemJson = newStockItem.SerializeToJson(); // Push to Acumatica API // var result = _distributionClient.AddNewStockItem(newStockItemJson); var item = result.DeserializeFromJson <StockItem>(); // Create Monster record // var newRecord = new AcumaticaStockItem(); newRecord.ItemId = item.InventoryID.value; _acumaticaJsonService.Upsert( AcumaticaJsonType.StockItem, item.InventoryID.value, item.SerializeToJson()); newRecord.AcumaticaDescription = item.Description.value; newRecord.AcumaticaTaxCategory = item.TaxCategory.value; newRecord.IsVariantSynced = false; newRecord.DateCreated = DateTime.UtcNow; newRecord.LastUpdated = DateTime.UtcNow; using (var transaction = _syncRepository.BeginTransaction()) { _inventoryRepository.InsertStockItems(newRecord); _syncRepository.InsertItemSync(variant, newRecord, context.IsSyncEnabled); var log = $"Created Stock Item {item.InventoryID.value} in Acumatica"; _logService.Log(log); transaction.Commit(); } }
public ShopifyVariant CreateNewVariantRecord(long parentProductId, Variant variant) { using (var transaction = _inventoryRepository.BeginTransaction()) { var data = new ShopifyVariant(); data.ParentMonsterId = parentProductId; data.ShopifyVariantId = variant.id; data.ShopifySku = variant.sku; data.ShopifyTitle = variant.title ?? ""; data.ShopifyInventoryItemId = variant.inventory_item_id; data.ShopifyIsTaxable = variant.taxable; data.ShopifyPrice = (decimal)variant.price; data.IsMissing = false; data.DateCreated = DateTime.UtcNow; data.LastUpdated = DateTime.UtcNow; _executionLogService.Log(LogBuilder.DetectedNewVariant(variant)); _inventoryRepository.InsertVariant(data); _shopifyJsonService.Upsert(ShopifyJsonType.Variant, variant.id, variant.SerializeToJson()); transaction.Commit(); return(data); } }
InventoryLevel(this ShopifyVariant input, long locationId) { return(input .ShopifyInventoryLevels .FirstOrDefault(x => x.ShopifyLocationId == locationId)); }
public static string CreateStockItem(ShopifyVariant variant) { return($"Creating Acumatica Stock Item from {variant.LogDescriptor()}"); }
/// <summary> /// Updates the specified variant on the specified product /// </summary> /// <param name="variant">The variant.</param> /// <returns></returns> public ShopifyVariant Update(ShopifyVariant variant) { return(base.Update(variant, variant.Id)); }
/// <summary> /// Creates the specified variant on the specified product /// </summary> /// <param name="variant">The variant.</param> /// <param name="productID">The product identifier.</param> /// <returns></returns> public ShopifyVariant Create(ShopifyVariant variant, long productID) { return(base.Create(variant, $"/admin/products/{productID}/variants.json")); }
public static string StandardizedSku(this ShopifyVariant input) { return(Canonizers.StandardizedSku(input.ShopifySku)); }
public void InsertVariant(ShopifyVariant variant) { Entities.ShopifyVariants.Add(variant); Entities.SaveChanges(); }
public static bool IsNotMatched(this ShopifyVariant variant) { return(!variant.IsMatched()); }
public static string LogDescriptor(this ShopifyVariant variant) { return($"Shopify Variant {variant.ShopifySku} ({variant.ShopifyVariantId})"); }
public static bool IsSynced(this ShopifyVariant input) { return(input.AcumaticaStockItems.Any()); }
public static AcumaticaStockItem MatchedStockItem(this ShopifyVariant input) { return(input.AcumaticaStockItems.FirstOrDefault()); }
public static bool IsMatched(this ShopifyVariant variant) { return(variant.AcumaticaStockItems.Any()); }