diff --git a/PartSource.Automation/Jobs/AddAndUpdateProducts.cs b/PartSource.Automation/Jobs/AddAndUpdateProducts.cs index 7a1b8d6..50223e9 100644 --- a/PartSource.Automation/Jobs/AddAndUpdateProducts.cs +++ b/PartSource.Automation/Jobs/AddAndUpdateProducts.cs @@ -30,7 +30,7 @@ namespace PartSource.Automation.Jobs await SyncronizeIdsAndSkus(); //await AddSkus(); - // await AddVariants(); + // await AddVariants(); return new AutomationJobResult { @@ -43,12 +43,13 @@ namespace PartSource.Automation.Jobs /// private async Task SyncronizeIdsAndSkus() { - IEnumerable products = await _shopifyClient.Products.Get(); + IEnumerable products = await _shopifyClient.Products.Get(new Dictionary { { "limit", 250 } }); - _partSourceContext.Database.ExecuteSqlCommand("UPDATE ImportData SET ShopifyId = NULL"); + //_partSourceContext.Database.ExecuteSqlCommand("UPDATE ImportData SET ShopifyId = NULL"); while (products != null && products.Any()) { + foreach (Product product in products) { foreach (Variant variant in product.Variants) @@ -62,16 +63,19 @@ namespace PartSource.Automation.Jobs } } - await _partSourceContext.SaveChangesAsync(); - try { - products = await _shopifyClient.Products.GetNext(); + await _partSourceContext.SaveChangesAsync(); } catch { - products = await _shopifyClient.Products.GetPrevious(); + Console.WriteLine("Failed to save a batch of products"); + } + + finally + { + products = await _shopifyClient.Products.GetNext(); } } } @@ -85,7 +89,7 @@ namespace PartSource.Automation.Jobs .ToList(); // items = items.Where(i => i.Title == items.First().Title).ToList(); - // + // foreach (ImportData importData in items) { try @@ -145,12 +149,12 @@ namespace PartSource.Automation.Jobs Title = importData.Title, Vendor = importData.Vendor, Tags = string.Join(",", productTags), - Published = true, //ProductType = importData.FINELINE_NM, Images = productImages.ToArray(), //Variants = productVariants.ToArray(), CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now + UpdatedAt = DateTime.Now, + PublishedAt = DateTime.Now }; requestData = await _shopifyClient.Products.Add(requestData); @@ -259,12 +263,12 @@ namespace PartSource.Automation.Jobs Title = items[0].Title, Vendor = items[0].Vendor, Tags = string.Join(",", productTags), - Published = true, //ProductType = importData.FINELINE_NM, Images = productImages.ToArray(), //Variants = productVariants.ToArray(), CreatedAt = DateTime.Now, - UpdatedAt = DateTime.Now + UpdatedAt = DateTime.Now, + PublishedAt = DateTime.Now }; requestData = await _shopifyClient.Products.Add(requestData); diff --git a/PartSource.Automation/Jobs/UpdateFitment - Copy.cs b/PartSource.Automation/Jobs/UpdateFitment - Copy.cs index e5bc930..3e5c536 100644 --- a/PartSource.Automation/Jobs/UpdateFitment - Copy.cs +++ b/PartSource.Automation/Jobs/UpdateFitment - Copy.cs @@ -19,6 +19,7 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; using Ratermania.Shopify; using Ratermania.Shopify.Resources; +using Ratermania.Shopify.Exceptions; namespace PartSource.Automation.Jobs { @@ -40,29 +41,50 @@ namespace PartSource.Automation.Jobs public async Task Run() { - IList parts = _partSourceContext.ImportData - .Where(p => p.UpdatedAt < DateTime.Now.AddDays(-3)) - .Take(50) - .ToList(); + IEnumerable products = null; - while (parts != null && parts.Count > 0) + try { - foreach (ImportData importData in parts) + products = await _shopifyClient.Products.Get(new Dictionary { { "limit", 250 } }); + } + + catch (Exception ex) + { + // TODO: Logging + return new AutomationJobResult + { + Message = "Failed to get products from Shopify", + IsSuccess = false + }; + } + + while (products != null && products.Any()) + { + foreach (Product product in products) { try { - Product product = await _shopifyClient.Products.GetById(importData.ShopifyId.GetValueOrDefault()); - if (product == null) + ImportData importData = await _partSourceContext.ImportData + .Where(i => i.ShopifyId == product.Id && i.UpdatedAt <= DateTime.Now.AddDays(-7)) + .FirstOrDefaultAsync(); + + if (importData == null) { continue; } - bool isFitment = false; - IList vehicles = _vehicleService.GetVehiclesForPart(importData.PartNumber, importData.LineCode); + IList vehicles = _vehicleService.GetVehiclesForPart(importData.PartNumber, importData.LineCode, 255); + + if (vehicles.Count > 250) + { + continue; + } + IList vehicleIdFitment = _vehicleService.GetVehicleIdFitment(vehicles); - if (vehicleIdFitment.Count > 0) + + if (vehicleIdFitment.Count > 0 && vehicleIdFitment.Count <= 250) { isFitment = true; @@ -121,11 +143,25 @@ namespace PartSource.Automation.Jobs await _shopifyClient.Metafields.Add(isFitmentMetafield); + + //Metafield noteTextMetafield = new Metafield + //{ + // Namespace = "Flags", + // Key = "IsFitment", + // Value = isFitment.ToString(), + // ValueType = "string", + // OwnerResource = "product", + // OwnerId = product.Id + //}; + + //await _shopifyClient.Metafields.Add(noteTextMetafield); + + List tags = new List - { - importData.LineCode, - importData.PartNumber - }; + { + importData.LineCode, + importData.PartNumber + }; for (int j = 0; j < vehicleIdFitment.Count; j += 25) { @@ -143,25 +179,32 @@ namespace PartSource.Automation.Jobs await _shopifyClient.Products.Update(product); + importData.IsFitment = isFitment; importData.UpdatedAt = DateTime.Now; importData.UpdateType = "Fitment"; } - + + catch (ShopifyClientException ex) + { + // TODO: Log + } + catch (Exception ex) { - if (!ex.Message.Contains("response content", StringComparison.InvariantCultureIgnoreCase)) - { - Console.WriteLine($"{importData.VariantSku}: {ex.Message}"); - } + // TODO: Log } } - await _partSourceContext.SaveChangesAsync(); + try + { + _partSourceContext.SaveChanges(); + products = await _shopifyClient.Products.GetNext(); + } - parts = _partSourceContext.ImportData - .Where(p => p.UpdatedAt < DateTime.Now.AddDays(-3)) - .Take(50) - .ToList(); + catch (Exception ex) + { + products = await _shopifyClient.Products.GetNext(); + } } diff --git a/PartSource.Automation/Jobs/UpdatePositioning.cs b/PartSource.Automation/Jobs/UpdatePositioning.cs index 0f47758..fe86a8c 100644 --- a/PartSource.Automation/Jobs/UpdatePositioning.cs +++ b/PartSource.Automation/Jobs/UpdatePositioning.cs @@ -31,6 +31,10 @@ namespace PartSource.Automation.Jobs public async Task Run() { + IList importDataz = _partSourceContext.ImportData.ToList(); + + return new AutomationJobResult(); + IDictionary parameters = new Dictionary { { "limit", 250 } @@ -59,7 +63,7 @@ namespace PartSource.Automation.Jobs continue; } - await DeletePositionMetafields(product.Id); + //await DeletePositionMetafields(product.Id); string currentPosition = fitments[0].Position; List vehicleIds = new List(); @@ -85,6 +89,8 @@ namespace PartSource.Automation.Jobs await SavePositionMetafield(product, vehicleIds, currentPosition); + + importData.UpdatedAt = DateTime.Now; importData.UpdateType = "Positioning"; @@ -169,22 +175,5 @@ namespace PartSource.Automation.Jobs await _shopifyClient.Metafields.Add(vehicleMetafield); } - - private async Task DeletePositionMetafields(long shopifyId) - { - IDictionary parameters = new Dictionary - { - { "metafield[owner_id]", shopifyId}, - { "metafield[owner_resource]", "product" }, - { "namespace", "position" }, - }; - - IEnumerable metafields = await _shopifyClient.Metafields.Get(parameters); - - foreach (Metafield metafield in metafields) - { - await _shopifyClient.Metafields.Delete(metafield); - } - } } } diff --git a/PartSource.Automation/Jobs/UpdatePricing.cs b/PartSource.Automation/Jobs/UpdatePricing.cs index a0baf89..b538d18 100644 --- a/PartSource.Automation/Jobs/UpdatePricing.cs +++ b/PartSource.Automation/Jobs/UpdatePricing.cs @@ -1,4 +1,6 @@ -using PartSource.Automation.Jobs.Interfaces; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging.Abstractions; +using PartSource.Automation.Jobs.Interfaces; using PartSource.Automation.Models; using PartSource.Data; using PartSource.Data.Models; @@ -27,11 +29,13 @@ namespace PartSource.Automation.Jobs public async Task Run() { IEnumerable products = null; + IEnumerable prices = null; int updateCount = 0; try { - products = await _shopifyClient.Products.Get(); + products = await _shopifyClient.Products.Get(new Dictionary { { "limit", 250 } }); + prices = await _partSourceContext.PartPrices.ToListAsync(); } catch (Exception ex) @@ -50,8 +54,9 @@ namespace PartSource.Automation.Jobs { if (product.Variants.Length > 0) { + Variant variant = product.Variants[0]; - PartPrice partPrice = _partSourceContext.PartPrices.Where(p => p.SKU == variant.Sku).FirstOrDefault(); + PartPrice partPrice = prices.Where(p => p.SKU == variant.Sku).FirstOrDefault(); if (partPrice == null || !partPrice.Your_Price.HasValue || !partPrice.Compare_Price.HasValue) { @@ -65,7 +70,8 @@ namespace PartSource.Automation.Jobs product.Variants[0].Price = partPrice.Your_Price.Value; product.Variants[0].CompareAtPrice = partPrice.Compare_Price.Value; - product.PublishedAt = partPrice.Active.ToUpperInvariant() == "Y" ? DateTime.Now : default; + product.PublishedAt = partPrice.Active.Trim().ToUpperInvariant() == "Y" ? (DateTime?)DateTime.Now : null; + product.PublishedScope = PublishedScope.Global; Metafield metafield = new Metafield { @@ -81,29 +87,37 @@ namespace PartSource.Automation.Jobs { await _shopifyClient.Metafields.Add(metafield); await _shopifyClient.Products.Update(product); - + updateCount++; + + } catch (Exception ex) { - + Console.WriteLine("bad update"); } } } catch (Exception ex) { - ; + Console.WriteLine("failed getting parts"); } } } - _partSourceContext.SaveChanges(); + // _partSourceContext.SaveChanges(); try { + //await _shopifyClient.Products.SaveChanges(); + products = await _shopifyClient.Products.GetNext(); + + Console.SetCursorPosition(0, 2); + Console.Clear(); + Console.Write($"Updated: {updateCount} "); } catch (Exception ex) diff --git a/PartSource.Automation/Properties/launchSettings.json b/PartSource.Automation/Properties/launchSettings.json index 9c692e8..4e4d7f7 100644 --- a/PartSource.Automation/Properties/launchSettings.json +++ b/PartSource.Automation/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "PartSource.Automation": { "commandName": "Project", - "commandLineArgs": "AddAndUpdateProducts", + "commandLineArgs": "UpdatePositioning", "environmentVariables": { "PS_AUTOMATION_ENVIRONMENT": "development" } diff --git a/PartSource.Backoffice/App.xaml b/PartSource.Backoffice/App.xaml new file mode 100644 index 0000000..db7a790 --- /dev/null +++ b/PartSource.Backoffice/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/PartSource.Backoffice/App.xaml.cs b/PartSource.Backoffice/App.xaml.cs new file mode 100644 index 0000000..5c05ff2 --- /dev/null +++ b/PartSource.Backoffice/App.xaml.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Data; +using System.Linq; +using System.Threading.Tasks; +using System.Windows; + +namespace PartSource.Backoffice +{ + /// + /// Interaction logic for App.xaml + /// + public partial class App : Application + { + } +} diff --git a/PartSource.Backoffice/AssemblyInfo.cs b/PartSource.Backoffice/AssemblyInfo.cs new file mode 100644 index 0000000..427f202 --- /dev/null +++ b/PartSource.Backoffice/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] diff --git a/PartSource.Backoffice/Components/MenuBar.xaml b/PartSource.Backoffice/Components/MenuBar.xaml new file mode 100644 index 0000000..b42c8ae --- /dev/null +++ b/PartSource.Backoffice/Components/MenuBar.xaml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/PartSource.Backoffice/Components/MenuBar.xaml.cs b/PartSource.Backoffice/Components/MenuBar.xaml.cs new file mode 100644 index 0000000..953b933 --- /dev/null +++ b/PartSource.Backoffice/Components/MenuBar.xaml.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace PartSource.Backoffice.Components +{ + /// + /// Interaction logic for MenuBar.xaml + /// + public partial class MenuBar : UserControl + { + public MenuBar() + { + InitializeComponent(); + } + + private void MenuItem_Click(object sender, RoutedEventArgs e) + { + // TODO: Check if any tasks are running + + Application.Current.MainWindow.Close(); + } + } +} diff --git a/PartSource.Backoffice/Components/ProgressDisplay.xaml b/PartSource.Backoffice/Components/ProgressDisplay.xaml new file mode 100644 index 0000000..3d818e2 --- /dev/null +++ b/PartSource.Backoffice/Components/ProgressDisplay.xaml @@ -0,0 +1,20 @@ + + + + + + Current Operation: + + + + + + diff --git a/PartSource.Backoffice/Components/ProgressDisplay.xaml.cs b/PartSource.Backoffice/Components/ProgressDisplay.xaml.cs new file mode 100644 index 0000000..754db5d --- /dev/null +++ b/PartSource.Backoffice/Components/ProgressDisplay.xaml.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace PartSource.Backoffice.Components +{ + /// + /// Interaction logic for StatusBars.xaml + /// + public partial class ProgressDisplay : UserControl + { + public ProgressDisplay() + { + InitializeComponent(); + } + } +} diff --git a/PartSource.Backoffice/Components/TaskSetup.xaml b/PartSource.Backoffice/Components/TaskSetup.xaml new file mode 100644 index 0000000..c8a008f --- /dev/null +++ b/PartSource.Backoffice/Components/TaskSetup.xaml @@ -0,0 +1,16 @@ + + + + Metafield Groups: + + + + diff --git a/PartSource.Backoffice/Components/TaskSetup.xaml.cs b/PartSource.Backoffice/Components/TaskSetup.xaml.cs new file mode 100644 index 0000000..f725008 --- /dev/null +++ b/PartSource.Backoffice/Components/TaskSetup.xaml.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace PartSource.Backoffice.Components +{ + /// + /// Interaction logic for TaskSetup.xaml + /// + public partial class TaskSetup : UserControl + { + public TaskSetup() + { + InitializeComponent(); + } + } +} diff --git a/PartSource.Backoffice/MainWindow.xaml b/PartSource.Backoffice/MainWindow.xaml new file mode 100644 index 0000000..ed63ec2 --- /dev/null +++ b/PartSource.Backoffice/MainWindow.xaml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + +