using Microsoft.EntityFrameworkCore; using Newtonsoft.Json; using PartSource.Automation.Jobs.Interfaces; using PartSource.Automation.Models; using PartSource.Data; using PartSource.Data.Models; using PartSource.Services; using Ratermania.Shopify; using Ratermania.Shopify.Resources; using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; namespace PartSource.Automation.Jobs { public class UpdatePositioning : IAutomationJob { private readonly ShopifyClient _shopifyClient; private readonly PartSourceContext _partSourceContext; private readonly VehicleService _vehicleService; public UpdatePositioning(PartSourceContext partSourceContext, ShopifyClient shopifyClient, VehicleService vehicleService) { _partSourceContext = partSourceContext; _shopifyClient = shopifyClient; _vehicleService = vehicleService; } public async Task Run() { IDictionary parameters = new Dictionary { { "limit", 250 } }; IEnumerable products = await _shopifyClient.Products.Get(parameters); while (products != null && products.Any()) { foreach (Product product in products) { try { ImportData importData = _partSourceContext.ImportData.FirstOrDefault(i => i.VariantSku == product.Variants[0].Sku); if (importData == null || importData?.LineCode == "SVG") // Headlights go in front, DUH { continue; } IList fitments = GetPositionOrderedFitments(importData?.PartNumber, importData?.LineCode); IList vehicles = _vehicleService.GetVehiclesForPart(importData?.PartNumber, importData?.LineCode); if (fitments.Count == 0 || vehicles.Count == 0) { continue; } //await DeletePositionMetafields(product.Id); //string currentPosition = fitments[0].Position; //List vehicleIds = new List(); //foreach (Fitment fitment in fitments) //{ // if (fitment.Position != currentPosition) // { // await SavePositionMetafield(product, vehicleIds, currentPosition); // currentPosition = fitment.Position; // vehicleIds = new List(); // } // // We don't need to DCF map because these are both sourced from WHI // IList fitmentVehicleIds = vehicles.Where(v => v.BaseVehicleId == fitment.BaseVehicleId && v.EngineConfigId == fitment.EngineConfigId) // .Select(v => v.VehicleToEngineConfigId) // .Distinct() // .ToList(); // vehicleIds.AddRange(fitmentVehicleIds); //} //await SavePositionMetafield(product, vehicleIds, currentPosition); IList notes = fitments.Select(f => f.NoteText) .Distinct() .ToList(); IList vehicleNotes = new List(); foreach (string noteText in notes) { IList vehicleIds = fitments.Where(f => f.NoteText == noteText) .Select(f => new { f.EngineConfigId, f.BaseVehicleId }) .SelectMany(f => vehicles.Where(v => v.BaseVehicleId == f.BaseVehicleId && v.EngineConfigId == f.EngineConfigId)) .Select(v => v.VehicleToEngineConfigId) .ToList(); vehicleNotes.Add(new { noteText, vehicleIds }); } string json = JsonConvert.SerializeObject(vehicleNotes); if (json.Length >= 100000) { continue; } Metafield vehicleMetafield = new Metafield { Namespace = "fitment", Key = "note_text", Value = json, ValueType = "json_string", OwnerResource = "product", OwnerId = product.Id }; await _shopifyClient.Metafields.Add(vehicleMetafield); //importData.UpdatedAt = DateTime.Now; //importData.UpdateType = "Positioning"; ; } catch (Exception ex) { Console.WriteLine($"{product.Id}: {ex.Message}"); } } try { Console.Write('.'); // await _partSourceContext.SaveChangesAsync(); products = await _shopifyClient.Products.GetNext(); } catch (Exception ex) { Console.WriteLine($"Retrying: {ex.Message}"); products = await _shopifyClient.Products.GetPrevious(); } } return new AutomationJobResult { Message = "Positioning updated successfully", IsSuccess = true }; } private IList GetPositionOrderedFitments(string partNumber, string lineCode) { partNumber = Regex.Replace(partNumber, "[^a-zA-Z0-9]", string.Empty); IQueryable whiCodes = _partSourceContext.DcfMappings .Where(d => d.LineCode == lineCode) .Select(d => d.WhiCode); return _partSourceContext.Fitments .Where(f => f.PartNumber == partNumber && whiCodes.Contains(f.LineCode) && !string.IsNullOrEmpty(f.Position)) .OrderBy(f => f.Position) .ToList(); } [SuppressMessage("Globalization", "CA1308:Normalize strings to uppercase", Justification = "It's a Shopify metafield key")] private async Task SavePositionMetafield(Product product, IList vehicleIds, string position) { if (vehicleIds.Count == 0) { return; } string json = JsonConvert.SerializeObject(vehicleIds); if (json.Length >= 100000) { // TODO: Logging return; } string key = position.ToLowerInvariant().Replace(" ", "_"); if (key.Length > 20) { key = key.Substring(0, 20); } Metafield vehicleMetafield = new Metafield { Namespace = "position", Key = key, Value = json, ValueType = "json_string", OwnerResource = "product", OwnerId = product.Id }; System.Diagnostics.Debug.WriteLine(json); await _shopifyClient.Metafields.Add(vehicleMetafield); } } }