Пример #1
0
        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);
        }
Пример #2
0
 public void InsertItemSync(ShopifyVariant variant, AcumaticaStockItem stockItem, bool isSyncEnabled)
 {
     stockItem.ShopifyVariantMonsterId = variant.MonsterId;
     stockItem.IsSyncEnabled           = isSyncEnabled;
     stockItem.LastUpdated             = DateTime.UtcNow;
     Entities.SaveChanges();
 }
Пример #3
0
 public static IList <ShopifyVariant> Exclude(
     this IEnumerable <ShopifyVariant> input,
     ShopifyVariant exclude)
 {
     return(input
            .Where(x => x.ShopifyVariantId != exclude.ShopifyVariantId &&
                   x.ShopifySku != exclude.ShopifySku).ToList());
 }
Пример #4
0
        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);
        }
Пример #5
0
        public static string AcumaticaStockItemId(this ShopifyVariant input)
        {
            if (!input.AcumaticaStockItems.Any())
            {
                throw new Exception("No synchronized Acumatica Stock Items");
            }

            return(input.AcumaticaStockItems.First().ItemId);
        }
Пример #6
0
 public static bool AreSkuAndItemIdMismatched(this ShopifyVariant input)
 {
     if (!input.IsSynced())
     {
         return(false);
     }
     else
     {
         return(input.ShopifySku.StandardizedSku() != input.MatchedStockItem().ItemId.StandardizedSku());
     }
 }
Пример #7
0
        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);
        }
Пример #8
0
        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);
        }
Пример #9
0
        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();
            }
        }
Пример #10
0
        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);
        }
Пример #11
0
        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);
        }
Пример #12
0
        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();
                }
            }
        }
Пример #13
0
        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();
            }
        }
Пример #14
0
        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);
            }
        }
Пример #15
0
 InventoryLevel(this ShopifyVariant input, long locationId)
 {
     return(input
            .ShopifyInventoryLevels
            .FirstOrDefault(x => x.ShopifyLocationId == locationId));
 }
Пример #16
0
 public static string CreateStockItem(ShopifyVariant variant)
 {
     return($"Creating Acumatica Stock Item from {variant.LogDescriptor()}");
 }
Пример #17
0
 /// <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));
 }
Пример #18
0
 /// <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"));
 }
Пример #19
0
 public static string StandardizedSku(this ShopifyVariant input)
 {
     return(Canonizers.StandardizedSku(input.ShopifySku));
 }
 public void InsertVariant(ShopifyVariant variant)
 {
     Entities.ShopifyVariants.Add(variant);
     Entities.SaveChanges();
 }
Пример #21
0
 public static bool IsNotMatched(this ShopifyVariant variant)
 {
     return(!variant.IsMatched());
 }
Пример #22
0
 public static string LogDescriptor(this ShopifyVariant variant)
 {
     return($"Shopify Variant {variant.ShopifySku} ({variant.ShopifyVariantId})");
 }
Пример #23
0
 public static bool IsSynced(this ShopifyVariant input)
 {
     return(input.AcumaticaStockItems.Any());
 }
Пример #24
0
 public static AcumaticaStockItem MatchedStockItem(this ShopifyVariant input)
 {
     return(input.AcumaticaStockItems.FirstOrDefault());
 }
Пример #25
0
 public static bool IsMatched(this ShopifyVariant variant)
 {
     return(variant.AcumaticaStockItems.Any());
 }