Compare commits
4 Commits
402ffae02d
...
3ab838e27f
Author | SHA1 | Date | |
---|---|---|---|
|
3ab838e27f | ||
|
49381b06a7 | ||
|
afe19fcf7e | ||
|
ed6800e11d |
@ -1,28 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="3.1.2">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\RhSolutions.Api\RhSolutions.Api.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -1,25 +0,0 @@
|
||||
using RhSolutions.Api.Models;
|
||||
|
||||
namespace RhSolutions.Tests
|
||||
{
|
||||
public class SkuExtensionsTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("11600011001")]
|
||||
[InlineData(" 11600011001")]
|
||||
[InlineData("11600011001 ")]
|
||||
[InlineData("string 11600011001")]
|
||||
[InlineData("11600011001 string")]
|
||||
[InlineData("160001-001")]
|
||||
[InlineData("string 160001-001")]
|
||||
[InlineData("160001-001 string")]
|
||||
[InlineData("160001001")]
|
||||
[InlineData("string 160001001")]
|
||||
[InlineData("160001001 string")]
|
||||
public void TestName(string input)
|
||||
{
|
||||
Sku.TryParse(input, out IEnumerable<Sku> sku);
|
||||
Assert.Equal(new Sku("160001", "001"), sku.FirstOrDefault());
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
global using Xunit;
|
@ -1,6 +1,7 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using RhSolutions.Api.Models;
|
||||
using RhSolutions.Models;
|
||||
using RhSolutions.Api.Services;
|
||||
using System.Linq;
|
||||
|
||||
namespace RhSolutions.Api.Controllers
|
||||
{
|
||||
@ -31,17 +32,25 @@ namespace RhSolutions.Api.Controllers
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public async Task<IActionResult> PostProductsFromXls()
|
||||
public IActionResult PostProductsFromXls()
|
||||
{
|
||||
try
|
||||
{
|
||||
var products = parser.GetProducts(HttpContext);
|
||||
await foreach (var p in products)
|
||||
{
|
||||
using (p)
|
||||
var products = parser.GetProducts(HttpContext).GroupBy(p => p.ProductSku)
|
||||
.Select(g => new Product(g.Key)
|
||||
{
|
||||
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();
|
||||
|
@ -1,28 +1,27 @@
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using RhSolutions.Api.Models;
|
||||
using RhSolutions.Models;
|
||||
|
||||
namespace RhSolutions.Api.Controllers
|
||||
{
|
||||
[Route("api/[controller]")]
|
||||
public class SearchController : ControllerBase
|
||||
{
|
||||
private RhSolutionsContext context;
|
||||
[Route("api/[controller]")]
|
||||
public class SearchController : ControllerBase
|
||||
{
|
||||
private RhSolutionsContext context;
|
||||
|
||||
public SearchController(RhSolutionsContext context)
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
public SearchController(RhSolutionsContext context)
|
||||
{
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
[HttpGet]
|
||||
public IAsyncEnumerable<Product> SearchProducts([FromQuery] string query)
|
||||
{
|
||||
return context.Products
|
||||
.Where(p => EF.Functions.ToTsVector(
|
||||
"russian", string.Join(' ',
|
||||
new [] {p.ProductLine ?? string.Empty, p.Name ?? string.Empty }))
|
||||
.Matches(EF.Functions.WebSearchToTsQuery("russian", query)))
|
||||
.AsAsyncEnumerable();
|
||||
}
|
||||
}
|
||||
[HttpGet]
|
||||
public IAsyncEnumerable<Product> SearchProducts([FromQuery] string query)
|
||||
{
|
||||
return context.Products
|
||||
.Where(p => EF.Functions.ToTsVector(
|
||||
"russian", string.Join(' ', new[] { p.Name, string.Join(' ', p.ProductLines)}))
|
||||
.Matches(EF.Functions.WebSearchToTsQuery("russian", query)))
|
||||
.AsAsyncEnumerable();
|
||||
}
|
||||
}
|
||||
}
|
@ -7,19 +7,19 @@ CREATE TABLE IF NOT EXISTS "__EFMigrationsHistory" (
|
||||
START TRANSACTION;
|
||||
|
||||
CREATE TABLE "Products" (
|
||||
"Id" integer GENERATED BY DEFAULT AS IDENTITY,
|
||||
"ProductSku" text NULL,
|
||||
"DeprecatedSkus" text[] NOT NULL,
|
||||
"Id" text NOT NULL,
|
||||
"Name" text NOT NULL,
|
||||
"ProductLine" text NULL,
|
||||
"IsOnWarehouse" boolean NULL,
|
||||
"ProductSku" text NOT NULL,
|
||||
"DeprecatedSkus" text[] NOT NULL,
|
||||
"ProductLines" text[] NOT NULL,
|
||||
"IsOnWarehouse" boolean NOT NULL,
|
||||
"ProductMeasure" integer NOT NULL,
|
||||
"DeliveryMakeUp" double precision NULL,
|
||||
"Price" numeric(8,2) NOT NULL,
|
||||
"Price" numeric NOT NULL,
|
||||
CONSTRAINT "PK_Products" PRIMARY KEY ("Id")
|
||||
);
|
||||
|
||||
INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
|
||||
VALUES ('20221201071323_Init', '7.0.0');
|
||||
VALUES ('20230511043408_Init', '7.0.5');
|
||||
|
||||
COMMIT;
|
@ -1,9 +1,8 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
|
||||
rhsolutions-api:
|
||||
build: ../RhSolutions.Api
|
||||
build: ..
|
||||
container_name: rhsolutions-api
|
||||
ports:
|
||||
- 5000:5000
|
||||
@ -16,16 +15,13 @@ services:
|
||||
depends_on:
|
||||
- rhsolutions-db
|
||||
restart: unless-stopped
|
||||
|
||||
rhsolutions-db:
|
||||
container_name: rhsolutions-db
|
||||
build: ./database
|
||||
ports:
|
||||
- 5432:5432
|
||||
build: ./Database
|
||||
environment:
|
||||
- POSTGRES_USER=chebser
|
||||
- POSTGRES_PASSWORD=Rehau-987
|
||||
- POSTGRES_DB=rhsolutions
|
||||
restart: unless-stopped
|
||||
|
||||
networks:
|
||||
default:
|
||||
name: rhsolutions
|
@ -6,14 +6,14 @@ using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using RhSolutions.Api.Models;
|
||||
using RhSolutions.Models;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace RhSolutions.Api.Migrations
|
||||
{
|
||||
[DbContext(typeof(RhSolutionsContext))]
|
||||
[Migration("20221201071323_Init")]
|
||||
[Migration("20230511043408_Init")]
|
||||
partial class Init
|
||||
{
|
||||
/// <inheritdoc />
|
||||
@ -21,18 +21,15 @@ namespace RhSolutions.Api.Migrations
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "7.0.0")
|
||||
.HasAnnotation("ProductVersion", "7.0.5")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("RhSolutions.Api.Models.Product", b =>
|
||||
modelBuilder.Entity("RhSolutions.Models.Product", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<double?>("DeliveryMakeUp")
|
||||
.HasColumnType("double precision");
|
||||
@ -41,7 +38,7 @@ namespace RhSolutions.Api.Migrations
|
||||
.IsRequired()
|
||||
.HasColumnType("text[]");
|
||||
|
||||
b.Property<bool?>("IsOnWarehouse")
|
||||
b.Property<bool>("IsOnWarehouse")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("Name")
|
||||
@ -49,15 +46,17 @@ namespace RhSolutions.Api.Migrations
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<decimal>("Price")
|
||||
.HasColumnType("decimal(8,2)");
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<string>("ProductLine")
|
||||
.HasColumnType("text");
|
||||
b.Property<List<string>>("ProductLines")
|
||||
.IsRequired()
|
||||
.HasColumnType("text[]");
|
||||
|
||||
b.Property<int>("ProductMeasure")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("ProductSku")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
b.HasKey("Id");
|
@ -1,6 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
#nullable disable
|
||||
|
||||
@ -16,16 +15,15 @@ namespace RhSolutions.Api.Migrations
|
||||
name: "Products",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "integer", nullable: false)
|
||||
.Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
|
||||
ProductSku = table.Column<string>(type: "text", nullable: true),
|
||||
DeprecatedSkus = table.Column<List<string>>(type: "text[]", nullable: false),
|
||||
Id = table.Column<string>(type: "text", nullable: false),
|
||||
Name = table.Column<string>(type: "text", nullable: false),
|
||||
ProductLine = table.Column<string>(type: "text", nullable: true),
|
||||
IsOnWarehouse = table.Column<bool>(type: "boolean", nullable: true),
|
||||
ProductSku = table.Column<string>(type: "text", nullable: false),
|
||||
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),
|
||||
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 =>
|
||||
{
|
@ -5,7 +5,7 @@ using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
using RhSolutions.Api.Models;
|
||||
using RhSolutions.Models;
|
||||
|
||||
#nullable disable
|
||||
|
||||
@ -18,18 +18,15 @@ namespace RhSolutions.Api.Migrations
|
||||
{
|
||||
#pragma warning disable 612, 618
|
||||
modelBuilder
|
||||
.HasAnnotation("ProductVersion", "7.0.0")
|
||||
.HasAnnotation("ProductVersion", "7.0.5")
|
||||
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||
|
||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||
|
||||
modelBuilder.Entity("RhSolutions.Api.Models.Product", b =>
|
||||
modelBuilder.Entity("RhSolutions.Models.Product", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.ValueGeneratedOnAdd()
|
||||
.HasColumnType("integer");
|
||||
|
||||
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<int>("Id"));
|
||||
b.Property<string>("Id")
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<double?>("DeliveryMakeUp")
|
||||
.HasColumnType("double precision");
|
||||
@ -38,7 +35,7 @@ namespace RhSolutions.Api.Migrations
|
||||
.IsRequired()
|
||||
.HasColumnType("text[]");
|
||||
|
||||
b.Property<bool?>("IsOnWarehouse")
|
||||
b.Property<bool>("IsOnWarehouse")
|
||||
.HasColumnType("boolean");
|
||||
|
||||
b.Property<string>("Name")
|
||||
@ -46,15 +43,17 @@ namespace RhSolutions.Api.Migrations
|
||||
.HasColumnType("text");
|
||||
|
||||
b.Property<decimal>("Price")
|
||||
.HasColumnType("decimal(8,2)");
|
||||
.HasColumnType("numeric");
|
||||
|
||||
b.Property<string>("ProductLine")
|
||||
.HasColumnType("text");
|
||||
b.Property<List<string>>("ProductLines")
|
||||
.IsRequired()
|
||||
.HasColumnType("text[]");
|
||||
|
||||
b.Property<int>("ProductMeasure")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<string>("ProductSku")
|
||||
.IsRequired()
|
||||
.HasColumnType("text");
|
||||
|
||||
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;
|
||||
|
||||
namespace RhSolutions.Api.Models;
|
||||
namespace RhSolutions.Models;
|
||||
|
||||
public class RhSolutionsContext : DbContext
|
||||
{
|
||||
public RhSolutionsContext(DbContextOptions<RhSolutionsContext> options)
|
||||
: base(options) { }
|
||||
: base(options) { }
|
||||
|
||||
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 RhSolutions.Api.Models;
|
||||
using RhSolutions.Models;
|
||||
using RhSolutions.Api.Services;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
@ -8,13 +8,14 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ClosedXML" Version="0.97.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.0">
|
||||
<PackageReference Include="ClosedXML" Version="0.101.0" />
|
||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="7.0.5">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</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="Rhsolutions.ProductSku" Version="0.2.13" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
@ -1,35 +1,36 @@
|
||||
using ClosedXML.Excel;
|
||||
using RhSolutions.Api.Models;
|
||||
using RhSolutions.Models;
|
||||
|
||||
namespace RhSolutions.Api.Services
|
||||
{
|
||||
public class ClosedXMLParser : IPricelistParser
|
||||
{
|
||||
public async IAsyncEnumerable<Product> GetProducts(HttpContext context)
|
||||
public List<Product> GetProducts(HttpContext context)
|
||||
{
|
||||
using (var memoryStream = new MemoryStream())
|
||||
{
|
||||
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))
|
||||
{
|
||||
Dictionary<ProductSku, Product> collected = new();
|
||||
var table = GetTable(wb);
|
||||
var rows = table.DataRange.Rows();
|
||||
var enumerator = rows.GetEnumerator();
|
||||
while (enumerator.MoveNext())
|
||||
foreach (var row in rows)
|
||||
{
|
||||
if (Sku.TryParse(enumerator.Current.Field("Актуальный материал")
|
||||
.GetString(), out IEnumerable<Sku> skus))
|
||||
if (ProductSku.TryParse(row.Field("Актуальный материал")
|
||||
.GetString(), out _))
|
||||
{
|
||||
yield return ParseRow(enumerator.Current);
|
||||
products.Add(ParseRow(row));
|
||||
}
|
||||
}
|
||||
yield break;
|
||||
}
|
||||
return products;
|
||||
}
|
||||
}
|
||||
private IXLTable GetTable(XLWorkbook wb)
|
||||
@ -60,10 +61,10 @@ namespace RhSolutions.Api.Services
|
||||
.GetString()
|
||||
.Split('\n')
|
||||
.First();
|
||||
Sku.TryParse(row.Field("Актуальный материал")
|
||||
.GetString(), out IEnumerable<Sku> productSkus);
|
||||
Sku.TryParse(row.Field("Прежний материал")
|
||||
.GetString(), out IEnumerable<Sku> deprecatedSkus);
|
||||
ProductSku.TryParse(row.Field("Актуальный материал")
|
||||
.GetString(), out IEnumerable<ProductSku> productSkus);
|
||||
ProductSku.TryParse(row.Field("Прежний материал")
|
||||
.GetString(), out IEnumerable<ProductSku> deprecatedSkus);
|
||||
|
||||
string measureField = new string(row.Field("Ед. изм.")
|
||||
.GetString()
|
||||
@ -100,7 +101,7 @@ namespace RhSolutions.Api.Services
|
||||
|
||||
string onWarehouseField = row.Field("Складская программа")
|
||||
.GetString();
|
||||
bool? IsOnWarehouse;
|
||||
bool IsOnWarehouse;
|
||||
|
||||
switch (onWarehouseField)
|
||||
{
|
||||
@ -111,7 +112,7 @@ namespace RhSolutions.Api.Services
|
||||
IsOnWarehouse = false;
|
||||
break;
|
||||
default:
|
||||
IsOnWarehouse = null;
|
||||
IsOnWarehouse = false;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -123,12 +124,11 @@ namespace RhSolutions.Api.Services
|
||||
price = 0.0M;
|
||||
}
|
||||
|
||||
return new Product
|
||||
return new Product(productSkus.First())
|
||||
{
|
||||
ProductLine = productLine,
|
||||
ProductLines = new List<string>() { productLine },
|
||||
Name = productName,
|
||||
ProductSku = productSkus.First().Id,
|
||||
DeprecatedSkus = deprecatedSkus.Select(s => s.Id).ToList(),
|
||||
DeprecatedSkus = deprecatedSkus.ToList(),
|
||||
ProductMeasure = productMeasure,
|
||||
DeliveryMakeUp = productWarehouseCount,
|
||||
IsOnWarehouse = IsOnWarehouse,
|
||||
|
@ -1,9 +1,9 @@
|
||||
using RhSolutions.Api.Models;
|
||||
using RhSolutions.Models;
|
||||
|
||||
namespace RhSolutions.Api.Services
|
||||
{
|
||||
public interface IPricelistParser
|
||||
{
|
||||
public IAsyncEnumerable<Product> GetProducts(HttpContext context);
|
||||
public List<Product> GetProducts(HttpContext context);
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"sdk": {
|
||||
"version": "6.0.402"
|
||||
"version": "6.0.311"
|
||||
}
|
||||
}
|
@ -5,8 +5,6 @@ VisualStudioVersion = 17.0.31903.59
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RhSolutions.Api", "RhSolutions.Api\RhSolutions.Api.csproj", "{FD778359-7E92-4B5C-A4F9-7942A28E58F5}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RhSolutions.Api.Tests", "RhSolutions.Api.Tests\RhSolutions.Api.Tests.csproj", "{A71CCD18-1D47-4DF5-B883-AF4D1CFB4F4E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -20,9 +18,5 @@ Global
|
||||
{FD778359-7E92-4B5C-A4F9-7942A28E58F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{FD778359-7E92-4B5C-A4F9-7942A28E58F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{FD778359-7E92-4B5C-A4F9-7942A28E58F5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A71CCD18-1D47-4DF5-B883-AF4D1CFB4F4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A71CCD18-1D47-4DF5-B883-AF4D1CFB4F4E}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A71CCD18-1D47-4DF5-B883-AF4D1CFB4F4E}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A71CCD18-1D47-4DF5-B883-AF4D1CFB4F4E}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
Loading…
x
Reference in New Issue
Block a user