Compare commits

...

2 Commits

8 changed files with 60 additions and 31 deletions

View File

@@ -23,7 +23,7 @@ namespace PartSource.Api.Controllers
[Route("sku/{sku}/storeNumber/{storeNumber}")] [Route("sku/{sku}/storeNumber/{storeNumber}")]
public async Task<ActionResult> GetInventory(int sku, int storeNumber) public async Task<ActionResult> GetInventory(int sku, int storeNumber)
{ {
PartsAvailability inventory = await _inventoryService.GetInventory(sku, storeNumber); PartAvailability inventory = await _inventoryService.GetInventory(sku, storeNumber);
if (inventory == null) if (inventory == null)
{ {
@@ -36,7 +36,8 @@ namespace PartSource.Api.Controllers
{ {
StoreNumber = inventory.Store, StoreNumber = inventory.Store,
Sku = sku, Sku = sku,
Quantity = inventory.QTY Quantity = inventory.QTY,
Updated = inventory.Updated ?? System.DateTime.MinValue
} }
}); });
} }

View File

@@ -53,7 +53,7 @@ namespace PartSource.Automation.Jobs
connection.Open(); connection.Open();
using SqlCommand command = new SqlCommand("TRUNCATE TABLE PartAvailability", connection); using SqlCommand command = new SqlCommand("TRUNCATE TABLE PartAvailability", connection);
await command.ExecuteNonQueryAsync(); await command.ExecuteNonQueryAsync(token);
using SqlBulkCopy bulk = new SqlBulkCopy(connection) using SqlBulkCopy bulk = new SqlBulkCopy(connection)
{ {
@@ -61,7 +61,7 @@ namespace PartSource.Automation.Jobs
BulkCopyTimeout = 14400 BulkCopyTimeout = 14400
}; };
bulk.WriteToServer(dataTable); await bulk.WriteToServerAsync(dataTable, token);
_ftpService.Delete(lastUploadedFile.Filename); _ftpService.Delete(lastUploadedFile.Filename);
@@ -74,6 +74,7 @@ namespace PartSource.Automation.Jobs
dataTable.Columns.Add("Store", typeof(int)); dataTable.Columns.Add("Store", typeof(int));
dataTable.Columns.Add("SKU", typeof(string)); dataTable.Columns.Add("SKU", typeof(string));
dataTable.Columns.Add("QTY", typeof(int)); dataTable.Columns.Add("QTY", typeof(int));
dataTable.Columns.Add("Updated", typeof(DateTime));
using StreamReader reader = new StreamReader(filename); using StreamReader reader = new StreamReader(filename);
string line = reader.ReadLine(); // Burn the header row string line = reader.ReadLine(); // Burn the header row
@@ -91,9 +92,10 @@ namespace PartSource.Automation.Jobs
string sku = columns[1].Trim(); string sku = columns[1].Trim();
if (int.TryParse(columns[0], out int store) if (int.TryParse(columns[0], out int store)
&& !string.IsNullOrEmpty(sku) && !string.IsNullOrEmpty(sku)
&& int.TryParse(columns[2], out int quantity)) && int.TryParse(columns[2], out int quantity)
&& DateTime.TryParse(columns[3], out DateTime updated))
{ {
dataTable.Rows.Add(new object[] { store, sku, quantity }); dataTable.Rows.Add(new object[] { store, sku, quantity, updated });
} }
} }

View File

@@ -24,7 +24,7 @@ namespace PartSource.Automation.Jobs.POC
private readonly PartSourceContext _partSourceContext; private readonly PartSourceContext _partSourceContext;
private readonly FitmentContext _fitmentContext; private readonly FitmentContext _fitmentContext;
public GetImageUrls(NexpartService nexpartService, PartSourceContext partSourceContext, FitmentContext fitmentContext) public ImageList(NexpartService nexpartService, PartSourceContext partSourceContext, FitmentContext fitmentContext)
{ {
_nexpartService = nexpartService; _nexpartService = nexpartService;
_partSourceContext = partSourceContext; _partSourceContext = partSourceContext;

View File

@@ -32,6 +32,7 @@ namespace PartSource.Automation.Jobs
_logger = logger; _logger = logger;
} }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Security", "CA2100:Review SQL queries for security vulnerabilities")]
public async Task Run(CancellationToken token, params string[] arguments) public async Task Run(CancellationToken token, params string[] arguments)
{ {
FtpFileInfo lastUploadedFile = _ftpService.ListFilesExtended() FtpFileInfo lastUploadedFile = _ftpService.ListFilesExtended()
@@ -55,29 +56,59 @@ namespace PartSource.Automation.Jobs
using StreamReader reader = new StreamReader(file); using StreamReader reader = new StreamReader(file);
string line = reader.ReadLine(); // Burn the header row string line = reader.ReadLine(); // Burn the header row
IDictionary<string, object> parameters = new Dictionary<string, object>();
string command = string.Empty;
int i = 0;
while (reader.Peek() > 0) while (reader.Peek() > 0)
{ {
line = reader.ReadLine(); line = reader.ReadLine();
string[] columns = line.Split("|"); string[] columns = line.Split("|");
for (int i = 0; i < columns.Length; i++) for (int j = 0; j < columns.Length; j++)
{ {
columns[i] = columns[i].Replace("\"", string.Empty); columns[j] = columns[j].Replace("\"", string.Empty);
} }
if (int.TryParse(columns[0], out int store) if (int.TryParse(columns[0], out int store)
&& int.TryParse(columns[1], out int sku) && int.TryParse(columns[1], out int sku)
&& int.TryParse(columns[2], out int quantity)) && int.TryParse(columns[2], out int quantity)
&& DateTime.TryParse(columns[3], out DateTime updated))
{ {
using SqlCommand sqlCommand = new SqlCommand("UPDATE PartAvailability SET QTY = @qty WHERE SKU = @sku AND Store = @store", connection); command += $"UPDATE PartAvailability SET QTY = @qty_{i}, Updated = @updated_{i} WHERE SKU = @sku_{i} AND Store = @store_{i};";
sqlCommand.Parameters.Add(new SqlParameter("qty", quantity));
sqlCommand.Parameters.Add(new SqlParameter("sku", sku));
sqlCommand.Parameters.Add(new SqlParameter("store", store));
await sqlCommand.ExecuteNonQueryAsync(); parameters.Add($"qty_{i}", quantity);
parameters.Add($"store_{i}", store);
parameters.Add($"sku_{i}", sku);
parameters.Add($"updated_{i}", updated);
i++;
}
if (i == 250)
{
using SqlCommand nested = new SqlCommand(command, connection);
foreach (KeyValuePair<string, object> parameter in parameters)
{
nested.Parameters.Add(new SqlParameter(parameter.Key, parameter.Value));
}
await nested.ExecuteNonQueryAsync(token);
parameters.Clear();
command = string.Empty;
i = 0;
} }
} }
using SqlCommand sqlCommand = new SqlCommand(command, connection);
foreach (KeyValuePair<string, object> parameter in parameters)
{
sqlCommand.Parameters.Add(new SqlParameter(parameter.Key, parameter.Value));
}
await sqlCommand.ExecuteNonQueryAsync(token);
_ftpService.Delete(lastUploadedFile.Filename); _ftpService.Delete(lastUploadedFile.Filename);
return; return;

View File

@@ -75,7 +75,7 @@ namespace PartSource.Automation
.AddAutomation(options => .AddAutomation(options =>
{ {
options.HasBaseInterval(new TimeSpan(0, 5, 0)) options.HasBaseInterval(new TimeSpan(0, 5, 0))
.HasMaxFailures(1) .HasMaxFailures(5)
//.HasJob<TestJob>(options => options.HasInterval(new TimeSpan(7, 0, 0, 0))); //.HasJob<TestJob>(options => options.HasInterval(new TimeSpan(7, 0, 0, 0)));
// //
//.HasJob<SyncronizeProducts>(options => options.HasInterval(new TimeSpan(24, 0, 0))) //.HasJob<SyncronizeProducts>(options => options.HasInterval(new TimeSpan(24, 0, 0)))

View File

@@ -32,7 +32,7 @@ namespace PartSource.Data.Contexts
public DbSet<Vehicle> Vehicles { get; set; } public DbSet<Vehicle> Vehicles { get; set; }
public DbSet<PartsAvailability> PartAvailabilities { get; set; } public DbSet<PartAvailability> PartAvailabilities { get; set; }
public DbSet<BaseVehicle> BaseVehicles { get; set; } public DbSet<BaseVehicle> BaseVehicles { get; set; }
@@ -48,7 +48,7 @@ namespace PartSource.Data.Contexts
{ {
base.OnModelCreating(modelBuilder); base.OnModelCreating(modelBuilder);
modelBuilder.Entity<PartsAvailability>().HasKey(p => new { p.Store, p.SKU }); modelBuilder.Entity<PartAvailability>().HasKey(p => new { p.Store, p.SKU });
modelBuilder.Entity<DcfMapping>().HasKey(d => new { d.LineCode, d.WhiCode }); modelBuilder.Entity<DcfMapping>().HasKey(d => new { d.LineCode, d.WhiCode });
modelBuilder.Entity<ShopifyChangelog>() modelBuilder.Entity<ShopifyChangelog>()

View File

@@ -1,9 +1,10 @@
using System.ComponentModel.DataAnnotations; using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace PartSource.Data.Models namespace PartSource.Data.Models
{ {
public class PartsAvailability public class PartAvailability
{ {
[Column(Order = 0)] [Column(Order = 0)]
[DatabaseGenerated(DatabaseGeneratedOption.None)] [DatabaseGenerated(DatabaseGeneratedOption.None)]
@@ -13,14 +14,8 @@ namespace PartSource.Data.Models
[DatabaseGenerated(DatabaseGeneratedOption.None)] [DatabaseGenerated(DatabaseGeneratedOption.None)]
public int SKU { get; set; } public int SKU { get; set; }
[Column("Line Code")]
[StringLength(50)]
public string Line_Code { get; set; }
[Column("Part Number")]
[StringLength(50)]
public string Part_Number { get; set; }
public int? QTY { get; set; } public int? QTY { get; set; }
public DateTime? Updated { get; set; }
} }
} }

View File

@@ -21,7 +21,7 @@ namespace PartSource.Services
_fitmentContext = fitmentContext; _fitmentContext = fitmentContext;
} }
public async Task<PartsAvailability> GetInventory(int sku, int storeNumber) public async Task<PartAvailability> GetInventory(int sku, int storeNumber)
{ {
return await _partSourceContext.PartAvailabilities.FirstOrDefaultAsync(s => s.Store == storeNumber && s.SKU == sku); return await _partSourceContext.PartAvailabilities.FirstOrDefaultAsync(s => s.Store == storeNumber && s.SKU == sku);
} }