Merge pull request 'Add support for inventory timestamps' (#2) from InventoryTimestamps into master
Reviewed-on: #2
This commit is contained in:
@@ -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
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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()
|
||||||
@@ -50,37 +51,67 @@ namespace PartSource.Automation.Jobs
|
|||||||
string file = _ftpService.Download($"{lastUploadedFile.Filename}");
|
string file = _ftpService.Download($"{lastUploadedFile.Filename}");
|
||||||
|
|
||||||
using SqlConnection connection = new SqlConnection(_connectionString);
|
using SqlConnection connection = new SqlConnection(_connectionString);
|
||||||
connection.Open();
|
connection.Open();
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)))
|
||||||
|
|||||||
@@ -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>()
|
||||||
|
|||||||
@@ -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; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user