From 469fb0ff5f0ed0e206a65581357ba49943503607 Mon Sep 17 00:00:00 2001 From: Tom Raterman Date: Wed, 11 Oct 2023 13:52:53 -0400 Subject: [PATCH] DBContext changes --- PartSource.Automation/Jobs/UpdateFitment.cs | 439 +++++++++++--------- PartSource.Data/Contexts/FitmentContext.cs | 3 +- 2 files changed, 245 insertions(+), 197 deletions(-) diff --git a/PartSource.Automation/Jobs/UpdateFitment.cs b/PartSource.Automation/Jobs/UpdateFitment.cs index 3b74881..8b1f9de 100644 --- a/PartSource.Automation/Jobs/UpdateFitment.cs +++ b/PartSource.Automation/Jobs/UpdateFitment.cs @@ -38,212 +38,259 @@ namespace PartSource.Automation.Jobs IEnumerable products = null; - try + IList partTypes = new List { - products = await _shopifyClient.Products.Get(new Dictionary { { "limit", 250 }, { "product_type", "CA111-SC250-FL25049_Entry Ball Joints" } }); - //products = new List - //{ - // await _shopifyClient.Products.GetById(4388919574575) - //}; - } + "CA115-SC118-FL11803_Custom Lighting Accessories", + "CA117-SC141-FL14106_Jeep Accessories", + "CA117-SC141-FL14134_Truck Running Board and Steps", + "CA117-SC141-FL14199_Bumpers, Bull Bars & Brush Guards", + "CA117-SC157-FL15704_Headache Rack Frames", + "CA117-SC158-FL15802_Salters and Plow Accessories", + "CA117-SC699-FL69902_Crossover Boxes", + "CA117-SC699-FL69903_Specialty Boxes", + "CA117-SC699-FL69904_Transfer Tanks", + "CA135-SC176-FL17601_Trailer Lighting, Stop, Turn, Tail", + "CA135-SC186-FL18607_Roof Racks", + "CA135-SC186-FL18608_Bike Carriers", + "CA135-SC186-FL18609_Cargo Accessories", + "CA135-SC186-FL18610_Cargo Carriers", + "CA135-SC186-FL18611_Watersport Carriers", + "CA135-SC192-FL19201_Class 1 Hitches", + "CA135-SC192-FL19202_Class 2 Hitches", + "CA135-SC192-FL19203_Class 3 Hitches", + "CA135-SC192-FL19204_Towing, Heavy Duty", + "CA135-SC192-FL19205_Towing Electrical, Vehicle Specific", + "CA135-SC192-FL19206_Trailer Parts & Accessories", + "CA135-SC192-FL19207_Trailer Winches, Jacks & Couplers", + "CA135-SC192-FL19208_Class 5 Hitches", + "CA135-SC192-FL19221_Towing Electrical, Connectors & Adapters", + "CA135-SC192-FL19230_Towing Electrical, Controls & Converters", + "CA135-SC192-FL19235_Towing Electrical, Harnesses", + "CA135-SC192-FL19240_Towing Security, Non-Locking", + "CA135-SC192-FL19245_Towing Class V", + "CA135-SC192-FL19280_Towing Balls", + "CA135-SC192-FL19281_Towing Ball Mounts", + "CA135-SC192-FL19282_Towing Security, Locking", + "CA135-SC192-FL19283_Towing Kits & Acc" + }; - catch (Exception ex) + foreach (string partType in partTypes) { - _logger.LogError("Failed to get products from Shopify", ex); - throw; - } - - int i = 1; - - while (products != null && products.Any()) - { - foreach (Product product in products) - { - ImportData importData = null; - - try - { - IEnumerable metafields = await _shopifyClient.Metafields.Get(new Dictionary { { "metafield[owner_id]", product.Id }, { "metafield[owner_resource]", "product" } }); - importData = new ImportData - { - LineCode = metafields.FirstOrDefault(m => m.Key == "custom_label_0")?.Value ?? string.Empty, - PartNumber = metafields.FirstOrDefault(m => m.Key == "custom_label_1")?.Value ?? string.Empty, - VariantSku = product.Variants[0].Sku // They know we can't do fitment for variants - }; - - bool isFitment = false; - string bodyHtml = product.BodyHtml.Substring(0, product.BodyHtml.IndexOf("") + "".Length); - - IList vehicles = _vehicleFitmentService.GetVehiclesForPart(importData.PartNumber, importData.LineCode); - IList vehicleIdFitment = _vehicleFitmentService.GetVehicleIdFitment(vehicles); - - if (vehicleIdFitment.Count > 0) - { - string vehicleIdString = string.Join(',', vehicleIdFitment.Select(j => $"v{j}")); - - bodyHtml += $"
{vehicleIdString}
"; - - isFitment = true; - - string json = JsonConvert.SerializeObject(vehicleIdFitment); - if (json.Length < 100000) - { - Metafield vehicleMetafield = new Metafield - { - Namespace = "fitment", - Key = "ids", - Value = json, - Type = "json_string", - OwnerResource = "product", - OwnerId = product.Id - }; - - await _shopifyClient.Metafields.Add(vehicleMetafield); - } - - else - { - _logger.LogWarning($"Vehicle ID fitment data for SKU {importData.VariantSku} is too large for Shopify and cannot be added."); - continue; - } - } - - IList ymmFitment = _vehicleFitmentService.GetYmmFitment(vehicles); - if (ymmFitment.Count > 0) - { - isFitment = true; - - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.AppendLine(""); - - foreach (string fitment in ymmFitment) - { - try - { - string[] parts = fitment.Split(' ', 2); - - stringBuilder.AppendLine($""); - } - - catch - { - // This is still a POC at this point. Oh well... - } - } - - stringBuilder.AppendLine("
This Part Fits
{parts[1]}{parts[0].Replace("-", ", ")}
"); - - bodyHtml += $"
{stringBuilder.ToString()}
"; - - string json = JsonConvert.SerializeObject(ymmFitment); - if (json.Length < 100000) - { - Metafield ymmMetafield = new Metafield - { - Namespace = "fitment", - Key = "seo", - Value = json, - Type = "json_string", - OwnerResource = "product", - OwnerId = product.Id - }; - - await _shopifyClient.Metafields.Add(ymmMetafield); - } - - else - { - _logger.LogWarning($"Year/make/model fitment data for SKU {importData.VariantSku} is too large for Shopify and cannot be added."); - continue; - } - } - - Metafield isFitmentMetafield = new Metafield - { - Namespace = "Flags", - Key = "IsFitment", - Value = isFitment.ToString(), - Type = "string", - OwnerResource = "product", - OwnerId = product.Id - }; - - await _shopifyClient.Metafields.Add(isFitmentMetafield); - - //Metafield lineCodeMetafield = new Metafield - //{ - // Namespace = "google", - // Key = "custom_label_0", - // Value = importData.LineCode, - // Type = "string", - // OwnerResource = "product", - // OwnerId = product.Id - //}; - - //await _shopifyClient.Metafields.Add(lineCodeMetafield); - - //Metafield partNumberMetafield = new Metafield - //{ - // Namespace = "google", - // Key = "custom_label_1", - // Value = importData.PartNumber, - // Type = "string", - // OwnerResource = "product", - // OwnerId = product.Id - //}; - - //await _shopifyClient.Metafields.Add(partNumberMetafield); - - List tags = new List(); - - for (int j = 0; j < vehicleIdFitment.Count; j += 25) - { - tags.Add(string.Join('-', vehicleIdFitment.Skip(j).Take(25).Select(j => $"v{j}"))); - } - - tags.AddRange(ymmFitment); - - if (tags.Count > 249) - { - tags = tags.Take(249).ToList(); - } - - string zzzIsFitment = isFitment - ? "zzzIsFitment=true" - : "zzzIsFitment=false"; - - tags.Add(zzzIsFitment); - - product.Tags = string.Join(',', tags); - product.BodyHtml = bodyHtml; - await _shopifyClient.Products.Update(product); - - importData.IsFitment = isFitment; - importData.UpdatedAt = DateTime.Now; - importData.UpdateType = "Fitment"; - } - - catch (Exception ex) - { - _logger.LogError($"Failed to updated fitment data for SKU {importData?.VariantSku} - {ex.Message}", ex); - } - - } try { - Console.WriteLine(i); - - _partSourceContext.SaveChanges(); - products = await _shopifyClient.Products.GetNext(); - - i++; + products = await _shopifyClient.Products.Get(new Dictionary { { "limit", 250 }, { "product_type", partType } }); + //products = new List + //{ + // await _shopifyClient.Products.GetById(4388919574575) + //}; } catch (Exception ex) { - _logger.LogWarning(ex, "Failed to get the next set of products. Retrying"); - products = await _shopifyClient.Products.GetPrevious(); + _logger.LogError("Failed to get products from Shopify", ex); + throw; } + + int i = 1; + + while (products != null && products.Any()) + { + foreach (Product product in products) + { + ImportData importData = null; + + try + { + IEnumerable metafields = await _shopifyClient.Metafields.Get(new Dictionary { { "metafield[owner_id]", product.Id }, { "metafield[owner_resource]", "product" } }); + importData = new ImportData + { + LineCode = metafields.FirstOrDefault(m => m.Key == "custom_label_0")?.Value ?? string.Empty, + PartNumber = metafields.FirstOrDefault(m => m.Key == "custom_label_1")?.Value ?? string.Empty, + VariantSku = product.Variants[0].Sku // They know we can't do fitment for variants + }; + + bool isFitment = false; + string bodyHtml = product.BodyHtml.Substring(0, product.BodyHtml.IndexOf("") + "".Length); + + IList vehicles = _vehicleFitmentService.GetVehiclesForPart(importData.PartNumber, importData.LineCode); + IList vehicleIdFitment = _vehicleFitmentService.GetVehicleIdFitment(vehicles); + + if (!vehicleIdFitment.Any()) + { + Console.WriteLine($"No fitment data for SKU {importData.VariantSku}"); + continue; + } + + if (vehicleIdFitment.Count > 0) + { + string vehicleIdString = string.Join(',', vehicleIdFitment.Select(j => $"v{j}")); + + bodyHtml += $"
{vehicleIdString}
"; + + isFitment = true; + + string json = JsonConvert.SerializeObject(vehicleIdFitment); + if (json.Length < 100000) + { + Metafield vehicleMetafield = new Metafield + { + Namespace = "fitment", + Key = "ids", + Value = json, + Type = "json_string", + OwnerResource = "product", + OwnerId = product.Id + }; + + await _shopifyClient.Metafields.Add(vehicleMetafield); + } + + else + { + _logger.LogWarning($"Vehicle ID fitment data for SKU {importData.VariantSku} is too large for Shopify and cannot be added."); + continue; + } + } + + IList ymmFitment = _vehicleFitmentService.GetYmmFitment(vehicles); + if (ymmFitment.Count > 0) + { + isFitment = true; + + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.AppendLine(""); + + foreach (string fitment in ymmFitment) + { + try + { + string[] parts = fitment.Split(' ', 2); + + stringBuilder.AppendLine($""); + } + + catch + { + // This is still a POC at this point. Oh well... + } + } + + stringBuilder.AppendLine("
This Part Fits
{parts[1]}{parts[0].Replace("-", ", ")}
"); + + bodyHtml += $"
{stringBuilder.ToString()}
"; + + string json = JsonConvert.SerializeObject(ymmFitment); + if (json.Length < 100000) + { + Metafield ymmMetafield = new Metafield + { + Namespace = "fitment", + Key = "seo", + Value = json, + Type = "json_string", + OwnerResource = "product", + OwnerId = product.Id + }; + + await _shopifyClient.Metafields.Add(ymmMetafield); + } + + else + { + _logger.LogWarning($"Year/make/model fitment data for SKU {importData.VariantSku} is too large for Shopify and cannot be added."); + continue; + } + } + + Metafield isFitmentMetafield = new Metafield + { + Namespace = "Flags", + Key = "IsFitment", + Value = isFitment.ToString(), + Type = "string", + OwnerResource = "product", + OwnerId = product.Id + }; + + await _shopifyClient.Metafields.Add(isFitmentMetafield); + + //Metafield lineCodeMetafield = new Metafield + //{ + // Namespace = "google", + // Key = "custom_label_0", + // Value = importData.LineCode, + // Type = "string", + // OwnerResource = "product", + // OwnerId = product.Id + //}; + + //await _shopifyClient.Metafields.Add(lineCodeMetafield); + + //Metafield partNumberMetafield = new Metafield + //{ + // Namespace = "google", + // Key = "custom_label_1", + // Value = importData.PartNumber, + // Type = "string", + // OwnerResource = "product", + // OwnerId = product.Id + //}; + + //await _shopifyClient.Metafields.Add(partNumberMetafield); + + List tags = new List(); + + for (int j = 0; j < vehicleIdFitment.Count; j += 25) + { + tags.Add(string.Join('-', vehicleIdFitment.Skip(j).Take(25).Select(j => $"v{j}"))); + } + + tags.AddRange(ymmFitment); + + if (tags.Count > 249) + { + tags = tags.Take(249).ToList(); + } + + string zzzIsFitment = isFitment + ? "zzzIsFitment=true" + : "zzzIsFitment=false"; + + tags.Add(zzzIsFitment); + + product.Tags = string.Join(',', tags); + product.BodyHtml = bodyHtml; + await _shopifyClient.Products.Update(product); + + importData.IsFitment = isFitment; + importData.UpdatedAt = DateTime.Now; + importData.UpdateType = "Fitment"; + } + + catch (Exception ex) + { + _logger.LogError($"Failed to updated fitment data for SKU {importData?.VariantSku} - {ex.Message}", ex); + } + + } + try + { + Console.WriteLine(i); + + _partSourceContext.SaveChanges(); + products = await _shopifyClient.Products.GetNext(); + + i++; + } + + catch (Exception ex) + { + _logger.LogWarning(ex, "Failed to get the next set of products. Retrying"); + products = await _shopifyClient.Products.GetPrevious(); + } + } + + Console.WriteLine($"Finished {partType}"); } } } diff --git a/PartSource.Data/Contexts/FitmentContext.cs b/PartSource.Data/Contexts/FitmentContext.cs index af33cc3..d55c722 100644 --- a/PartSource.Data/Contexts/FitmentContext.cs +++ b/PartSource.Data/Contexts/FitmentContext.cs @@ -30,8 +30,9 @@ namespace PartSource.Data.Contexts modelBuilder.Entity().HasKey(d => new { d.LineCode, d.WhiCode }); modelBuilder.Entity().HasKey(f => new { f.BaseVehicleId, f.EngineConfigId, f.LineCode, f.PartNumber }); modelBuilder.Entity().HasKey(f => new { f.BaseVehicleId, f.PartNumber, f.LineCode, f.Position}); + modelBuilder.Entity().HasNoKey(); - foreach (IMutableEntityType entityType in modelBuilder.Model.GetEntityTypes()) + foreach (IMutableEntityType entityType in modelBuilder.Model.GetEntityTypes()) { entityType.SetTableName(entityType.ClrType.Name); }