Update products class
This commit is contained in:
parent
49381b06a7
commit
3ab838e27f
@ -1,6 +1,7 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using RhSolutions.Api.Models;
|
using RhSolutions.Models;
|
||||||
using RhSolutions.Api.Services;
|
using RhSolutions.Api.Services;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace RhSolutions.Api.Controllers
|
namespace RhSolutions.Api.Controllers
|
||||||
{
|
{
|
||||||
@ -31,17 +32,25 @@ namespace RhSolutions.Api.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<IActionResult> PostProductsFromXls()
|
public IActionResult PostProductsFromXls()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var products = parser.GetProducts(HttpContext);
|
var products = parser.GetProducts(HttpContext).GroupBy(p => p.ProductSku)
|
||||||
await foreach (var p in products)
|
.Select(g => new Product(g.Key)
|
||||||
{
|
|
||||||
using (p)
|
|
||||||
{
|
{
|
||||||
dbContext.Add<Product>(p);
|
Name = g.First().Name,
|
||||||
}
|
DeprecatedSkus = g.SelectMany(p => p.DeprecatedSkus).ToList(),
|
||||||
|
ProductLines = g.SelectMany(p => p.ProductLines).Distinct().ToList(),
|
||||||
|
IsOnWarehouse = g.Any(p => p.IsOnWarehouse == true),
|
||||||
|
ProductMeasure = g.First().ProductMeasure,
|
||||||
|
DeliveryMakeUp = g.First().DeliveryMakeUp,
|
||||||
|
Price = g.First().Price
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach (var p in products)
|
||||||
|
{
|
||||||
|
dbContext.Add<Product>(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
dbContext.SaveChanges();
|
dbContext.SaveChanges();
|
||||||
|
@ -1,28 +1,27 @@
|
|||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using RhSolutions.Api.Models;
|
using RhSolutions.Models;
|
||||||
|
|
||||||
namespace RhSolutions.Api.Controllers
|
namespace RhSolutions.Api.Controllers
|
||||||
{
|
{
|
||||||
[Route("api/[controller]")]
|
[Route("api/[controller]")]
|
||||||
public class SearchController : ControllerBase
|
public class SearchController : ControllerBase
|
||||||
{
|
{
|
||||||
private RhSolutionsContext context;
|
private RhSolutionsContext context;
|
||||||
|
|
||||||
public SearchController(RhSolutionsContext context)
|
public SearchController(RhSolutionsContext context)
|
||||||
{
|
{
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet]
|
[HttpGet]
|
||||||
public IAsyncEnumerable<Product> SearchProducts([FromQuery] string query)
|
public IAsyncEnumerable<Product> SearchProducts([FromQuery] string query)
|
||||||
{
|
{
|
||||||
return context.Products
|
return context.Products
|
||||||
.Where(p => EF.Functions.ToTsVector(
|
.Where(p => EF.Functions.ToTsVector(
|
||||||
"russian", string.Join(' ',
|
"russian", string.Join(' ', new[] { p.Name, string.Join(' ', p.ProductLines)}))
|
||||||
new [] {p.ProductLine ?? string.Empty, p.Name ?? string.Empty }))
|
.Matches(EF.Functions.WebSearchToTsQuery("russian", query)))
|
||||||
.Matches(EF.Functions.WebSearchToTsQuery("russian", query)))
|
.AsAsyncEnumerable();
|
||||||
.AsAsyncEnumerable();
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
@ -7,19 +7,19 @@ CREATE TABLE IF NOT EXISTS "__EFMigrationsHistory" (
|
|||||||
START TRANSACTION;
|
START TRANSACTION;
|
||||||
|
|
||||||
CREATE TABLE "Products" (
|
CREATE TABLE "Products" (
|
||||||
"Id" integer GENERATED BY DEFAULT AS IDENTITY,
|
"Id" text NOT NULL,
|
||||||
"ProductSku" text NULL,
|
|
||||||
"DeprecatedSkus" text[] NOT NULL,
|
|
||||||
"Name" text NOT NULL,
|
"Name" text NOT NULL,
|
||||||
"ProductLine" text NULL,
|
"ProductSku" text NOT NULL,
|
||||||
"IsOnWarehouse" boolean NULL,
|
"DeprecatedSkus" text[] NOT NULL,
|
||||||
|
"ProductLines" text[] NOT NULL,
|
||||||
|
"IsOnWarehouse" boolean NOT NULL,
|
||||||
"ProductMeasure" integer NOT NULL,
|
"ProductMeasure" integer NOT NULL,
|
||||||
"DeliveryMakeUp" double precision NULL,
|
"DeliveryMakeUp" double precision NULL,
|
||||||
"Price" numeric(8,2) NOT NULL,
|
"Price" numeric NOT NULL,
|
||||||
CONSTRAINT "PK_Products" PRIMARY KEY ("Id")
|
CONSTRAINT "PK_Products" PRIMARY KEY ("Id")
|
||||||
);
|
);
|
||||||
|
|
||||||
INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
|
INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
|
||||||
VALUES ('20221201071323_Init', '7.0.0');
|
VALUES ('20230511043408_Init', '7.0.5');
|
||||||
|
|
||||||
COMMIT;
|
COMMIT;
|
@ -6,14 +6,14 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
|
|||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
using RhSolutions.Api.Models;
|
using RhSolutions.Models;
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
namespace RhSolutions.Api.Migrations
|
namespace RhSolutions.Api.Migrations
|
||||||
{
|
{
|
||||||
[DbContext(typeof(RhSolutionsContext))]
|
[DbContext(typeof(RhSolutionsContext))]
|
||||||
[Migration("20221201071323_Init")]
|
[Migration("20230511043408_Init")]
|
||||||
partial class Init
|
partial class Init
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@ -21,18 +21,15 @@ namespace RhSolutions.Api.Migrations
|
|||||||
{
|
{
|
||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.HasAnnotation("ProductVersion", "7.0.0")
|
.HasAnnotation("ProductVersion", "7.0.5")
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
modelBuilder.Entity("RhSolutions.Api.Models.Product", b =>
|
modelBuilder.Entity("RhSolutions.Models.Product", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<string>("Id")
|
||||||
.ValueGeneratedOnAdd()
|
.HasColumnType("text");
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<double?>("DeliveryMakeUp")
|
b.Property<double?>("DeliveryMakeUp")
|
||||||
.HasColumnType("double precision");
|
.HasColumnType("double precision");
|
||||||
@ -41,7 +38,7 @@ namespace RhSolutions.Api.Migrations
|
|||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text[]");
|
.HasColumnType("text[]");
|
||||||
|
|
||||||
b.Property<bool?>("IsOnWarehouse")
|
b.Property<bool>("IsOnWarehouse")
|
||||||
.HasColumnType("boolean");
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
b.Property<string>("Name")
|
b.Property<string>("Name")
|
||||||
@ -49,15 +46,17 @@ namespace RhSolutions.Api.Migrations
|
|||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.Property<decimal>("Price")
|
b.Property<decimal>("Price")
|
||||||
.HasColumnType("decimal(8,2)");
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
b.Property<string>("ProductLine")
|
b.Property<List<string>>("ProductLines")
|
||||||
.HasColumnType("text");
|
.IsRequired()
|
||||||
|
.HasColumnType("text[]");
|
||||||
|
|
||||||
b.Property<int>("ProductMeasure")
|
b.Property<int>("ProductMeasure")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
b.Property<string>("ProductSku")
|
b.Property<string>("ProductSku")
|
||||||
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
@ -1,6 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.EntityFrameworkCore.Migrations;
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
@ -16,16 +15,15 @@ namespace RhSolutions.Api.Migrations
|
|||||||
name: "Products",
|
name: "Products",
|
||||||
columns: table => new
|
columns: table => new
|
||||||
{
|
{
|
||||||
Id = table.Column<int>(type: "integer", nullable: false)
|
Id = table.Column<string>(type: "text", nullable: false),
|
||||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
|
||||||
ProductSku = table.Column<string>(type: "text", nullable: true),
|
|
||||||
DeprecatedSkus = table.Column<List<string>>(type: "text[]", nullable: false),
|
|
||||||
Name = table.Column<string>(type: "text", nullable: false),
|
Name = table.Column<string>(type: "text", nullable: false),
|
||||||
ProductLine = table.Column<string>(type: "text", nullable: true),
|
ProductSku = table.Column<string>(type: "text", nullable: false),
|
||||||
IsOnWarehouse = table.Column<bool>(type: "boolean", nullable: true),
|
DeprecatedSkus = table.Column<List<string>>(type: "text[]", nullable: false),
|
||||||
|
ProductLines = table.Column<List<string>>(type: "text[]", nullable: false),
|
||||||
|
IsOnWarehouse = table.Column<bool>(type: "boolean", nullable: false),
|
||||||
ProductMeasure = table.Column<int>(type: "integer", nullable: false),
|
ProductMeasure = table.Column<int>(type: "integer", nullable: false),
|
||||||
DeliveryMakeUp = table.Column<double>(type: "double precision", nullable: true),
|
DeliveryMakeUp = table.Column<double>(type: "double precision", nullable: true),
|
||||||
Price = table.Column<decimal>(type: "numeric(8,2)", nullable: false)
|
Price = table.Column<decimal>(type: "numeric", nullable: false)
|
||||||
},
|
},
|
||||||
constraints: table =>
|
constraints: table =>
|
||||||
{
|
{
|
@ -5,7 +5,7 @@ using Microsoft.EntityFrameworkCore;
|
|||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
using RhSolutions.Api.Models;
|
using RhSolutions.Models;
|
||||||
|
|
||||||
#nullable disable
|
#nullable disable
|
||||||
|
|
||||||
@ -18,18 +18,15 @@ namespace RhSolutions.Api.Migrations
|
|||||||
{
|
{
|
||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder
|
modelBuilder
|
||||||
.HasAnnotation("ProductVersion", "7.0.0")
|
.HasAnnotation("ProductVersion", "7.0.5")
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
modelBuilder.Entity("RhSolutions.Api.Models.Product", b =>
|
modelBuilder.Entity("RhSolutions.Models.Product", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<string>("Id")
|
||||||
.ValueGeneratedOnAdd()
|
.HasColumnType("text");
|
||||||
.HasColumnType("integer");
|
|
||||||
|
|
||||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
|
||||||
|
|
||||||
b.Property<double?>("DeliveryMakeUp")
|
b.Property<double?>("DeliveryMakeUp")
|
||||||
.HasColumnType("double precision");
|
.HasColumnType("double precision");
|
||||||
@ -38,7 +35,7 @@ namespace RhSolutions.Api.Migrations
|
|||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("text[]");
|
.HasColumnType("text[]");
|
||||||
|
|
||||||
b.Property<bool?>("IsOnWarehouse")
|
b.Property<bool>("IsOnWarehouse")
|
||||||
.HasColumnType("boolean");
|
.HasColumnType("boolean");
|
||||||
|
|
||||||
b.Property<string>("Name")
|
b.Property<string>("Name")
|
||||||
@ -46,15 +43,17 @@ namespace RhSolutions.Api.Migrations
|
|||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.Property<decimal>("Price")
|
b.Property<decimal>("Price")
|
||||||
.HasColumnType("decimal(8,2)");
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
b.Property<string>("ProductLine")
|
b.Property<List<string>>("ProductLines")
|
||||||
.HasColumnType("text");
|
.IsRequired()
|
||||||
|
.HasColumnType("text[]");
|
||||||
|
|
||||||
b.Property<int>("ProductMeasure")
|
b.Property<int>("ProductMeasure")
|
||||||
.HasColumnType("integer");
|
.HasColumnType("integer");
|
||||||
|
|
||||||
b.Property<string>("ProductSku")
|
b.Property<string>("ProductSku")
|
||||||
|
.IsRequired()
|
||||||
.HasColumnType("text");
|
.HasColumnType("text");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
namespace RhSolutions.Api.Models
|
|
||||||
{
|
|
||||||
public enum Measure { Kg, M, M2, P }
|
|
||||||
}
|
|
@ -1,34 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
|
||||||
using System.Diagnostics;
|
|
||||||
using System.Text.Json.Serialization;
|
|
||||||
|
|
||||||
namespace RhSolutions.Api.Models
|
|
||||||
{
|
|
||||||
public partial class Product : IDisposable
|
|
||||||
{
|
|
||||||
[Key]
|
|
||||||
[JsonIgnore]
|
|
||||||
public int Id { get; set; }
|
|
||||||
public string ProductSku { get; set; } = string.Empty;
|
|
||||||
public List<string> DeprecatedSkus { get; set; } = new();
|
|
||||||
public string Name { get; set; } = string.Empty;
|
|
||||||
public string ProductLine { get; set; } = string.Empty;
|
|
||||||
public bool? IsOnWarehouse { get; set; }
|
|
||||||
public Measure ProductMeasure { get; set; }
|
|
||||||
public double? DeliveryMakeUp { get; set; }
|
|
||||||
|
|
||||||
[Column(TypeName = "decimal(8,2)")]
|
|
||||||
public decimal Price { get; set; }
|
|
||||||
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
Debug.WriteLine($"{this} disposed");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"({ProductSku}) {Name}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +1,21 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
namespace RhSolutions.Api.Models;
|
namespace RhSolutions.Models;
|
||||||
|
|
||||||
public class RhSolutionsContext : DbContext
|
public class RhSolutionsContext : DbContext
|
||||||
{
|
{
|
||||||
public RhSolutionsContext(DbContextOptions<RhSolutionsContext> options)
|
public RhSolutionsContext(DbContextOptions<RhSolutionsContext> options)
|
||||||
: base(options) { }
|
: base(options) { }
|
||||||
|
|
||||||
public DbSet<Product> Products => Set<Product>();
|
public DbSet<Product> Products => Set<Product>();
|
||||||
|
|
||||||
|
protected override void OnModelCreating(ModelBuilder builder)
|
||||||
|
{
|
||||||
|
builder.Entity<Product>()
|
||||||
|
.Property(e => e.ProductSku)
|
||||||
|
.HasConversion(v => v.ToString(), v => new ProductSku(v));
|
||||||
|
builder.Entity<Product>()
|
||||||
|
.Property(e => e.DeprecatedSkus)
|
||||||
|
.HasPostgresArrayConversion<ProductSku, string>(v => v.ToString(), v => new ProductSku(v));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,127 +0,0 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
|
|
||||||
namespace RhSolutions.Api.Models
|
|
||||||
{
|
|
||||||
public class Sku
|
|
||||||
{
|
|
||||||
private const string matchPattern = @"([1\D]|\b)(?<Article>\d{6})([1\s-]|)(?<Variant>\d{3})\b";
|
|
||||||
private string? _article;
|
|
||||||
private string? _variant;
|
|
||||||
|
|
||||||
public Sku(string article, string variant)
|
|
||||||
{
|
|
||||||
Article = article;
|
|
||||||
Variant = variant;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Key]
|
|
||||||
public string Id
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return $"1{Article}1{Variant}";
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (TryParse(value, out IEnumerable<Sku> skus))
|
|
||||||
{
|
|
||||||
if (skus.Count() > 1)
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"More than one valid sku detected: {value}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this.Article = skus.First().Article;
|
|
||||||
this.Variant = skus.First().Variant;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"Invalid sku input: {value}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public string? Article
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _article;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value == null || value.Length != 6 || value.Where(c => char.IsDigit(c)).Count() != 6)
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"Wrong Article: {Article}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_article = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public string? Variant
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
return _variant;
|
|
||||||
}
|
|
||||||
set
|
|
||||||
{
|
|
||||||
if (value == null || value.Length != 3 || value.Where(c => char.IsDigit(c)).Count() != 3)
|
|
||||||
{
|
|
||||||
throw new ArgumentException($"Wrong Variant: {Variant}");
|
|
||||||
}
|
|
||||||
else _variant = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static IEnumerable<Sku> GetValidSkus(string line)
|
|
||||||
{
|
|
||||||
MatchCollection matches = Regex.Matches(line, matchPattern);
|
|
||||||
if (matches.Count == 0)
|
|
||||||
{
|
|
||||||
yield break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
foreach (Match m in matches)
|
|
||||||
{
|
|
||||||
yield return new Sku(m.Groups["Article"].Value, m.Groups["Variant"].Value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryParse(string line, out IEnumerable<Sku> skus)
|
|
||||||
{
|
|
||||||
MatchCollection matches = Regex.Matches(line, matchPattern);
|
|
||||||
if (matches.Count == 0)
|
|
||||||
{
|
|
||||||
skus = Enumerable.Empty<Sku>();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
else
|
|
||||||
{
|
|
||||||
skus = GetValidSkus(line);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool Equals(object? obj)
|
|
||||||
{
|
|
||||||
return obj is Sku sku &&
|
|
||||||
Article!.Equals(sku.Article) &&
|
|
||||||
Variant!.Equals(sku.Variant);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int GetHashCode()
|
|
||||||
{
|
|
||||||
return HashCode.Combine(Article, Variant);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return $"1{Article}1{Variant}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using RhSolutions.Api.Models;
|
using RhSolutions.Models;
|
||||||
using RhSolutions.Api.Services;
|
using RhSolutions.Api.Services;
|
||||||
|
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
|
@ -8,13 +8,14 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="ClosedXML" Version="0.97.0" />
|
<PackageReference Include="ClosedXML" Version="0.101.0" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.0">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.5">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.0" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="7.0.4" />
|
||||||
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.Design" Version="1.1.0" />
|
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL.Design" Version="1.1.0" />
|
||||||
|
<PackageReference Include="Rhsolutions.ProductSku" Version="0.2.13" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
@ -1,35 +1,36 @@
|
|||||||
using ClosedXML.Excel;
|
using ClosedXML.Excel;
|
||||||
using RhSolutions.Api.Models;
|
using RhSolutions.Models;
|
||||||
|
|
||||||
namespace RhSolutions.Api.Services
|
namespace RhSolutions.Api.Services
|
||||||
{
|
{
|
||||||
public class ClosedXMLParser : IPricelistParser
|
public class ClosedXMLParser : IPricelistParser
|
||||||
{
|
{
|
||||||
public async IAsyncEnumerable<Product> GetProducts(HttpContext context)
|
public List<Product> GetProducts(HttpContext context)
|
||||||
{
|
{
|
||||||
using (var memoryStream = new MemoryStream())
|
using (var memoryStream = new MemoryStream())
|
||||||
{
|
{
|
||||||
if (context == null)
|
if (context == null)
|
||||||
{
|
{
|
||||||
yield break;
|
return new List<Product>();
|
||||||
}
|
}
|
||||||
|
|
||||||
await context.Request.Body.CopyToAsync(memoryStream);
|
context.Request.Body.CopyToAsync(memoryStream).GetAwaiter().GetResult();
|
||||||
|
List<Product> products = new();
|
||||||
using (var wb = new XLWorkbook(memoryStream))
|
using (var wb = new XLWorkbook(memoryStream))
|
||||||
{
|
{
|
||||||
|
Dictionary<ProductSku, Product> collected = new();
|
||||||
var table = GetTable(wb);
|
var table = GetTable(wb);
|
||||||
var rows = table.DataRange.Rows();
|
var rows = table.DataRange.Rows();
|
||||||
var enumerator = rows.GetEnumerator();
|
foreach (var row in rows)
|
||||||
while (enumerator.MoveNext())
|
|
||||||
{
|
{
|
||||||
if (Sku.TryParse(enumerator.Current.Field("Актуальный материал")
|
if (ProductSku.TryParse(row.Field("Актуальный материал")
|
||||||
.GetString(), out IEnumerable<Sku> skus))
|
.GetString(), out _))
|
||||||
{
|
{
|
||||||
yield return ParseRow(enumerator.Current);
|
products.Add(ParseRow(row));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
yield break;
|
|
||||||
}
|
}
|
||||||
|
return products;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private IXLTable GetTable(XLWorkbook wb)
|
private IXLTable GetTable(XLWorkbook wb)
|
||||||
@ -60,10 +61,10 @@ namespace RhSolutions.Api.Services
|
|||||||
.GetString()
|
.GetString()
|
||||||
.Split('\n')
|
.Split('\n')
|
||||||
.First();
|
.First();
|
||||||
Sku.TryParse(row.Field("Актуальный материал")
|
ProductSku.TryParse(row.Field("Актуальный материал")
|
||||||
.GetString(), out IEnumerable<Sku> productSkus);
|
.GetString(), out IEnumerable<ProductSku> productSkus);
|
||||||
Sku.TryParse(row.Field("Прежний материал")
|
ProductSku.TryParse(row.Field("Прежний материал")
|
||||||
.GetString(), out IEnumerable<Sku> deprecatedSkus);
|
.GetString(), out IEnumerable<ProductSku> deprecatedSkus);
|
||||||
|
|
||||||
string measureField = new string(row.Field("Ед. изм.")
|
string measureField = new string(row.Field("Ед. изм.")
|
||||||
.GetString()
|
.GetString()
|
||||||
@ -100,7 +101,7 @@ namespace RhSolutions.Api.Services
|
|||||||
|
|
||||||
string onWarehouseField = row.Field("Складская программа")
|
string onWarehouseField = row.Field("Складская программа")
|
||||||
.GetString();
|
.GetString();
|
||||||
bool? IsOnWarehouse;
|
bool IsOnWarehouse;
|
||||||
|
|
||||||
switch (onWarehouseField)
|
switch (onWarehouseField)
|
||||||
{
|
{
|
||||||
@ -111,7 +112,7 @@ namespace RhSolutions.Api.Services
|
|||||||
IsOnWarehouse = false;
|
IsOnWarehouse = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
IsOnWarehouse = null;
|
IsOnWarehouse = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,12 +124,11 @@ namespace RhSolutions.Api.Services
|
|||||||
price = 0.0M;
|
price = 0.0M;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Product
|
return new Product(productSkus.First())
|
||||||
{
|
{
|
||||||
ProductLine = productLine,
|
ProductLines = new List<string>() { productLine },
|
||||||
Name = productName,
|
Name = productName,
|
||||||
ProductSku = productSkus.First().Id,
|
DeprecatedSkus = deprecatedSkus.ToList(),
|
||||||
DeprecatedSkus = deprecatedSkus.Select(s => s.Id).ToList(),
|
|
||||||
ProductMeasure = productMeasure,
|
ProductMeasure = productMeasure,
|
||||||
DeliveryMakeUp = productWarehouseCount,
|
DeliveryMakeUp = productWarehouseCount,
|
||||||
IsOnWarehouse = IsOnWarehouse,
|
IsOnWarehouse = IsOnWarehouse,
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
using RhSolutions.Api.Models;
|
using RhSolutions.Models;
|
||||||
|
|
||||||
namespace RhSolutions.Api.Services
|
namespace RhSolutions.Api.Services
|
||||||
{
|
{
|
||||||
public interface IPricelistParser
|
public interface IPricelistParser
|
||||||
{
|
{
|
||||||
public IAsyncEnumerable<Product> GetProducts(HttpContext context);
|
public List<Product> GetProducts(HttpContext context);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"sdk": {
|
"sdk": {
|
||||||
"version": "6.0.402"
|
"version": "6.0.311"
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user