138 lines
3.3 KiB
C#
138 lines
3.3 KiB
C#
using ClosedXML.Excel;
|
||
using RhSolutions.Models;
|
||
|
||
namespace RhSolutions.Api.Services
|
||
{
|
||
public class ClosedXMLParser : IPricelistParser
|
||
{
|
||
public List<Product> GetProducts(HttpContext context)
|
||
{
|
||
using (var memoryStream = new MemoryStream())
|
||
{
|
||
if (context == null)
|
||
{
|
||
return new List<Product>();
|
||
}
|
||
|
||
context.Request.Body.CopyToAsync(memoryStream).GetAwaiter().GetResult();
|
||
List<Product> products = new();
|
||
using (var wb = new XLWorkbook(memoryStream))
|
||
{
|
||
var table = GetTable(wb);
|
||
var rows = table.DataRange.Rows();
|
||
foreach (var row in rows)
|
||
{
|
||
if (ProductSku.TryParse(row.Field("Актуальный материал")
|
||
.GetString(), out _))
|
||
{
|
||
products.Add(ParseRow(row));
|
||
}
|
||
}
|
||
}
|
||
return products;
|
||
}
|
||
}
|
||
private IXLTable GetTable(XLWorkbook wb)
|
||
{
|
||
var ws = wb.Worksheets.First();
|
||
ws.AutoFilter.IsEnabled = false;
|
||
try
|
||
{
|
||
var firstCellAddress = ws.Search("Программа", System.Globalization.CompareOptions.IgnoreCase)
|
||
.First()
|
||
.Address;
|
||
|
||
var lastCellAddress = ws.LastCellUsed().Address;
|
||
|
||
return ws.Range(firstCellAddress, lastCellAddress).AsTable();
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
throw new Exception($"Exception on parsing {ws.Name}:\n{ex.Message}");
|
||
}
|
||
}
|
||
|
||
private Product ParseRow(IXLTableRow row)
|
||
{
|
||
string productLine = row.Field("Программа")
|
||
.GetString();
|
||
string productName = row.Field("Наименование")
|
||
.GetString()
|
||
.Split('\n')
|
||
.First();
|
||
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()
|
||
.ToLower()
|
||
.Where(c => char.IsLetterOrDigit(c))
|
||
.ToArray());
|
||
Measure productMeasure;
|
||
|
||
switch (measureField)
|
||
{
|
||
case "кг":
|
||
productMeasure = Measure.Kg;
|
||
break;
|
||
case "м":
|
||
productMeasure = Measure.M;
|
||
break;
|
||
case "м2":
|
||
productMeasure = Measure.M2;
|
||
break;
|
||
case "шт":
|
||
productMeasure = Measure.P;
|
||
break;
|
||
default:
|
||
throw new ArgumentException();
|
||
}
|
||
|
||
string shippingSizeField = row.Field("Единица поставки")
|
||
.GetString();
|
||
|
||
if (!double.TryParse(shippingSizeField, out double productWarehouseCount))
|
||
{
|
||
productWarehouseCount = 0.0;
|
||
}
|
||
|
||
string onWarehouseField = row.Field("Складская программа")
|
||
.GetString();
|
||
bool IsOnWarehouse;
|
||
|
||
switch (onWarehouseField)
|
||
{
|
||
case "x":
|
||
IsOnWarehouse = true;
|
||
break;
|
||
case "под заказ":
|
||
IsOnWarehouse = false;
|
||
break;
|
||
default:
|
||
IsOnWarehouse = false;
|
||
break;
|
||
}
|
||
|
||
string priceField = row.Field("Цена брутто \nЕВРО\nбез НДС")
|
||
.GetString();
|
||
|
||
if (!decimal.TryParse(priceField, out decimal price))
|
||
{
|
||
price = 0.0M;
|
||
}
|
||
|
||
return new Product(productSkus.First())
|
||
{
|
||
ProductLines = new List<string>() { productLine },
|
||
Name = productName,
|
||
DeprecatedSkus = deprecatedSkus.ToList(),
|
||
ProductMeasure = productMeasure,
|
||
DeliveryMakeUp = productWarehouseCount,
|
||
IsOnWarehouse = IsOnWarehouse,
|
||
Price = price
|
||
};
|
||
}
|
||
}
|
||
} |