using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using Newtonsoft.Json; using PartSource.Automation.Models; using PartSource.Data; using PartSource.Data.Models; using PartSource.Services; using Ratermania.Automation.Interfaces; using Ratermania.Shopify; using Ratermania.Shopify.Exceptions; using Ratermania.Shopify.Resources; using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace PartSource.Automation.Jobs { public class UpdateFitment : IAutomationJob { private readonly ILogger _logger; private readonly ShopifyClient _shopifyClient; private readonly PartSourceContext _partSourceContext; private readonly VehicleService _vehicleService; public UpdateFitment(ILogger logger, PartSourceContext partSourceContext, ShopifyClient shopifyClient, VehicleService vehicleService) { _logger = logger; _partSourceContext = partSourceContext; _shopifyClient = shopifyClient; _vehicleService = vehicleService; } public async Task Run() { IEnumerable products = null; try { products = await _shopifyClient.Products.Get(new Dictionary { { "limit", 250 } }); } catch (Exception ex) { _logger.LogError("Failed to get products from Shopify", ex); throw; } while (products != null && products.Any()) { foreach (Product product in products) { ImportData importData = null; try { 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, 255); if (vehicles.Count > 250) { vehicles = vehicles.Take(250) .ToList(); _logger.LogInformation($"SKU {importData.VariantSku} fits more than 250 vehicles. Only the first 250 will be used."); } IList vehicleIdFitment = _vehicleService.GetVehicleIdFitment(vehicles); if (vehicleIdFitment.Count > 0) { isFitment = true; string json = JsonConvert.SerializeObject(vehicleIdFitment); if (json.Length < 100000) { Metafield vehicleMetafield = new Metafield { Namespace = "fitment", Key = "ids", Value = json, ValueType = "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 = _vehicleService.GetYmmFitment(vehicles); if (ymmFitment.Count > 0) { isFitment = true; string json = JsonConvert.SerializeObject(ymmFitment); if (json.Length < 100000) { Metafield ymmMetafield = new Metafield { Namespace = "fitment", Key = "seo", Value = json, ValueType = "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(), ValueType = "string", OwnerResource = "product", OwnerId = product.Id }; await _shopifyClient.Metafields.Add(isFitmentMetafield); List tags = new List { importData.LineCode, importData.PartNumber }; 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 > 250) { tags = tags.Take(250).ToList(); } product.Tags = string.Join(',', tags); 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); } } try { _partSourceContext.SaveChanges(); products = await _shopifyClient.Products.GetNext(); } catch (Exception ex) { _logger.LogWarning(ex, "Failed to get the next set of products. Retrying"); products = await _shopifyClient.Products.GetPrevious(); } } } } }