Ejemplo n.º 1
0
        public void UpdateInventoryLevels(AcumaticaStockItem stockItem)
        {
            if (MonsterConfig.Settings.DisableShopifyPut)
            {
                _executionLogService.Log(LogBuilder.ShopifyPutDisabled());
                return;
            }

            var variant =
                _inventoryRepository
                .RetrieveVariant(stockItem.MatchedVariant().ShopifyVariantId);

            if (variant.IsMissing)
            {
                _logger.Debug(
                    $"Skipping Inventory Update for " +
                    $"Variant {variant.ShopifySku} ({variant.ShopifyVariantId}) " +
                    $"StockItem {stockItem} - reason: Missing Variant");
                return;
            }

            if (variant.ShopifyProduct.IsDeleted)
            {
                _logger.Debug(
                    $"Skipping Inventory Update for " +
                    $"Variant {variant.ShopifySku} ({variant.ShopifyVariantId}) " +
                    $"StockItem {stockItem} - reason: Deleted Parent Product");
                return;
            }

            foreach (var level in variant.ShopifyInventoryLevels)
            {
                UpdateInventoryLevel(stockItem, level);
            }
        }
Ejemplo n.º 2
0
 public void InsertItemSync(ShopifyVariant variant, AcumaticaStockItem stockItem, bool isSyncEnabled)
 {
     stockItem.ShopifyVariantMonsterId = variant.MonsterId;
     stockItem.IsSyncEnabled           = isSyncEnabled;
     stockItem.LastUpdated             = DateTime.UtcNow;
     Entities.SaveChanges();
 }
Ejemplo n.º 3
0
        private InventorySyncStatus MakeSyncStatus(AcumaticaStockItem input)
        {
            var settings = _settingsRepository.RetrieveSettings();

            var output = new InventorySyncStatus();

            output.StockItemId   = input.ItemId;
            output.TaxCategoryId = input.AcumaticaTaxCategory;

            output.IsStockItemPriceSynced     = input.IsVariantSynced;
            output.IsStockItemInventorySynced = input.AcumaticaInventories.All(x => x.IsInventorySynced);
            output.IsTaxCategoryValid         = input.IsValidTaxCategory(settings);

            if (input.IsMatched())
            {
                var variant = input.MatchedVariant();
                output.ShopifyVariantId          = variant.ShopifyVariantId;
                output.ShopifyVariantSku         = variant.ShopifySku;
                output.IsShopifyVariantMissing   = variant.IsMissing;
                output.ShopifyInventoryIsTracked = variant.ShopifyIsTracked;
            }
            else
            {
                output.IsShopifyVariantMissing = true;
            }

            return(output);
        }
Ejemplo n.º 4
0
        public static VariantAndStockItemDto Make(
            AcumaticaStockItem input,
            Func <long, long, string> variantUrlService,
            Func <string, string> stockItemUrlService)
        {
            var output = new VariantAndStockItemDto();

            output.MonsterVariantId    = input.ShopifyVariant.MonsterId;
            output.ShopifyProductId    = input.ShopifyVariant.ShopifyProduct.ShopifyProductId;
            output.ShopifyProductTitle = input.ShopifyVariant.ShopifyProduct.ShopifyTitle;
            output.ShopifyProductType  = input.ShopifyVariant.ShopifyProduct.ShopifyProductType;
            output.ShopifyVendor       = input.ShopifyVariant.ShopifyProduct.ShopifyVendor;
            output.ShopifyVariantId    = input.ShopifyVariant.ShopifyVariantId;
            output.ShopifySku          = input.ShopifyVariant.ShopifySku;
            output.ShopifyVariantTitle = input.ShopifyVariant.ShopifyTitle;

            output.ShopifyVariantUrl
                = variantUrlService(
                      input.ShopifyVariant.ShopifyProduct.ShopifyProductId,
                      input.ShopifyVariant.ShopifyVariantId);

            output.AcumaticaItemId       = input.ItemId;
            output.AcumaticaDescription  = input.AcumaticaDescription;
            output.AcumaticaStockItemUrl = stockItemUrlService(input.ItemId);

            output.IsSyncEnabled = input.IsSyncEnabled;

            return(output);
        }
Ejemplo n.º 5
0
        private void UpdateShopifyVariant(AcumaticaStockItem stockItemRecord, bool setTracking)
        {
            var settings      = _settingsRepository.RetrieveSettings();
            var variantRecord = stockItemRecord.MatchedVariant();
            var stockItemObj  = _acumaticaJsonService.RetrieveStockItem(stockItemRecord.ItemId);

            // Build the Shopify DTO
            //
            var variantShopifyId = variantRecord.ShopifyVariantId;
            var variantSku       = variantRecord.ShopifySku;

            // Push the update via Variant API
            //
            var id      = variantShopifyId;
            var taxable = stockItemRecord.IsTaxable(settings).Value;

            var price =
                settings.InventorySyncPrice
                    ? (decimal)stockItemObj.DefaultPrice.value
                    : (decimal?)null;

            var grams =
                settings.InventorySyncWeight
                    ? stockItemObj.DimensionWeight.value.ToShopifyGrams()
                    : (int?)null;

            string json = VariantUpdate.Make(id, taxable, price, grams);

            _productApi.UpdateVariantPrice(variantShopifyId, json);


            using (var transaction = _syncInventoryRepository.BeginTransaction())
            {
                var log = LogBuilder.UpdateShopifyVariantPrice(variantSku, taxable, price, grams);
                _executionLogService.Log(log);

                // Update Stock Item record
                //
                stockItemRecord.IsVariantSynced = true;
                stockItemRecord.LastUpdated     = DateTime.UtcNow;

                // Update Variant record
                //
                variantRecord.ShopifyIsTaxable = taxable;
                if (price.HasValue)
                {
                    variantRecord.ShopifyPrice = price.Value;
                }
                if (setTracking)
                {
                    variantRecord.ShopifyIsTracked = true;
                }

                _syncInventoryRepository.SaveChanges();
                transaction.Commit();
            }
        }
        public static AcumaticaStockItemModel Make(
            AcumaticaStockItem stockItem, Func <string, string> stockItemUrlBuilder)
        {
            var output = new AcumaticaStockItemModel();

            output.ItemId         = stockItem.ItemId;
            output.Description    = stockItem.AcumaticaDescription;
            output.AcumaticaUrl   = stockItemUrlBuilder(stockItem.ItemId);
            output.QuantityOnHand = (int)stockItem.AcumaticaInventories.Sum(x => x.AcumaticaAvailQty);

            return(output);
        }
Ejemplo n.º 7
0
        public static bool?IsTaxable(this AcumaticaStockItem input, MonsterSetting settings)
        {
            if (input.AcumaticaTaxCategory == settings.AcumaticaTaxableCategory)
            {
                return(true);
            }

            if (input.AcumaticaTaxCategory == settings.AcumaticaTaxExemptCategory)
            {
                return(false);
            }

            return(null);
        }
Ejemplo n.º 8
0
        public void UpdatePriceAndCost(AcumaticaStockItem stockItemRecord, bool setTracking = false)
        {
            if (MonsterConfig.Settings.DisableShopifyPut)
            {
                _executionLogService.Log(LogBuilder.ShopifyPutDisabled());
                return;
            }

            if (!stockItemRecord.IsMatched())
            {
                return;
            }

            UpdateShopifyVariant(stockItemRecord, setTracking);
            UpdateVariantCostOfGoods(stockItemRecord, setTracking);
        }
Ejemplo n.º 9
0
        public void UpsertStockItemToPersist(List <StockItem> items)
        {
            foreach (var item in items)
            {
                var existingData = _inventoryRepository.RetreiveStockItem(item.InventoryID.value);

                using (var transaction = _inventoryRepository.BeginTransaction())
                {
                    if (existingData == null)
                    {
                        var newData = new AcumaticaStockItem();
                        newData.ItemId = item.InventoryID.value;
                        newData.AcumaticaDescription  = item.Description.value;
                        newData.AcumaticaTaxCategory  = item.TaxCategory.value;
                        newData.AcumaticaDefaultPrice = (decimal)item.DefaultPrice.value;
                        newData.AcumaticaLastCost     = (decimal)item.LastCost.value;

                        newData.IsVariantSynced = false;
                        newData.DateCreated     = DateTime.UtcNow;
                        newData.LastUpdated     = DateTime.UtcNow;

                        _executionLogService.Log(LogBuilder.DetectedNewStockItem(newData));
                        _inventoryRepository.InsertStockItems(newData);
                    }
                    else
                    {
                        existingData.AcumaticaDescription  = item.Description.value;
                        existingData.AcumaticaTaxCategory  = item.TaxCategory.value;
                        existingData.AcumaticaDefaultPrice = (decimal)item.DefaultPrice.value;
                        existingData.AcumaticaLastCost     = (decimal)item.LastCost.value;
                        existingData.IsVariantSynced       = false;
                        existingData.LastUpdated           = DateTime.UtcNow;

                        _executionLogService.Log(LogBuilder.DetectedChangeToStockItem(existingData));
                        _inventoryRepository.SaveChanges();
                    }

                    _acumaticaJsonService.Upsert(
                        AcumaticaJsonType.StockItem, item.InventoryID.value, item.SerializeToJson());

                    transaction.Commit();
                }
            }
        }
Ejemplo n.º 10
0
        private void UpdateInventoryLevel(AcumaticaStockItem stockItem, ShopifyInventoryLevel level)
        {
            var location         = _syncInventoryRepository.RetrieveLocation(level.ShopifyLocationId);
            var warehouseIds     = location.MatchedWarehouseIds();
            var warehouseDetails = stockItem.Inventory(warehouseIds);

            var available = (int)warehouseDetails.Sum(x => x.AcumaticaAvailQty);
            var sku       = level.ShopifyVariant.ShopifySku;

            var levelDto = new InventoryLevel
            {
                inventory_item_id = level.ShopifyInventoryItemId,
                available         = available,
                location_id       = location.ShopifyLocationId,
            };

            var levelJson = levelDto.SerializeToJson();

            _inventoryApi.SetInventoryLevels(levelJson);


            using (var transaction = _syncInventoryRepository.BeginTransaction())
            {
                var log = $"Updated Shopify Variant {sku} " +
                          $"in Location {location.ShopifyLocationName} to Available Qty {available}";

                _executionLogService.Log(log);

                warehouseDetails.ForEach(x => x.IsInventorySynced = true);

                // Update Shopify Inventory Level records
                //
                level.ShopifyAvailableQuantity = available;
                level.LastUpdated = DateTime.UtcNow;

                _inventoryRepository.SaveChanges();
                transaction.Commit();
            }
        }
Ejemplo n.º 11
0
        private void UpdateVariantCostOfGoods(AcumaticaStockItem stockItemRecord, bool setTracking)
        {
            var variantRecord = stockItemRecord.MatchedVariant();
            var costOfGoods   = stockItemRecord.AcumaticaLastCost;

            // Push the cost of goods via Inventory API
            //
            string content;

            if (setTracking)
            {
                var inventoryItem = new InventoryItem();
                inventoryItem.id      = variantRecord.ShopifyInventoryItemId;
                inventoryItem.cost    = costOfGoods;
                inventoryItem.tracked = true;
                content = new { inventory_item = inventoryItem }.SerializeToJson();
            }
            else
            {
                var inventoryItem = new InventoryItemUpdate();
                inventoryItem.id   = variantRecord.ShopifyInventoryItemId;
                inventoryItem.cost = costOfGoods;
                content            = new { inventory_item = inventoryItem }.SerializeToJson();
            }

            _inventoryApi.SetInventoryCost(variantRecord.ShopifyInventoryItemId, content);

            using (var transaction = _syncInventoryRepository.BeginTransaction())
            {
                var log = LogBuilder.UpdateShopifyVariantCogsOfGoods(variantRecord.ShopifySku, costOfGoods);
                _executionLogService.Log(log);

                variantRecord.ShopifyCost = costOfGoods;
                _syncInventoryRepository.SaveChanges();
                transaction.Commit();
            }
        }
Ejemplo n.º 12
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();
            }
        }
Ejemplo n.º 13
0
 public static string DetectedChangeToStockItem(AcumaticaStockItem item)
 {
     return($"Detected change to {item.LogDescriptor()}");
 }
Ejemplo n.º 14
0
 public static string DetectedNewStockItem(AcumaticaStockItem item)
 {
     return($"Detected new {item.LogDescriptor()}");
 }
Ejemplo n.º 15
0
 public static string LogDescriptor(this AcumaticaStockItem stockItem)
 {
     return($"Acumatica Stock Item {stockItem.ItemId}");
 }
Ejemplo n.º 16
0
 public static bool IsValidTaxCategory(this AcumaticaStockItem input, MonsterSetting settings)
 {
     return(input.IsTaxable(settings).HasValue);
 }
Ejemplo n.º 17
0
 public static string UpdateShopifyPrice(AcumaticaStockItem item)
 {
     return($"Updating Shopify Price for {item.LogDescriptor()}");
 }
Ejemplo n.º 18
0
 public static string UpdateShopifyInventory(AcumaticaStockItem item)
 {
     return($"Updating {item.LogDescriptor()}");
 }
Ejemplo n.º 19
0
 public void DeleteItemSyncs(AcumaticaStockItem stockItem)
 {
     stockItem.IsSyncEnabled           = false;
     stockItem.ShopifyVariantMonsterId = null;
     Entities.SaveChanges();
 }
Ejemplo n.º 20
0
 public static bool IsMatched(this AcumaticaStockItem input)
 {
     return(input.ShopifyVariant != null);
 }
Ejemplo n.º 21
0
 public static ShopifyVariant MatchedVariant(this AcumaticaStockItem stockItem)
 {
     return(stockItem.ShopifyVariant);
 }
Ejemplo n.º 22
0
 public void InsertStockItems(AcumaticaStockItem item)
 {
     Entities.AcumaticaStockItems.Add(item);
     Entities.SaveChanges();
 }
Ejemplo n.º 23
0
 public static List <AcumaticaInventory> Inventory(this AcumaticaStockItem input, List <string> warehouseIds)
 {
     return(input.AcumaticaInventories
            .Where(x => warehouseIds.Contains(x.AcumaticaWarehouseId.Trim())).ToList());
 }