This commit is contained in:
parent
0da67c4717
commit
7ef04f118b
106
OD.WebApplication/Context/ApplicationContextHelper.cs
Normal file
106
OD.WebApplication/Context/ApplicationContextHelper.cs
Normal file
@ -0,0 +1,106 @@
|
||||
namespace OD.WebApplication.Context
|
||||
{
|
||||
public static class ApplicationContextHelper
|
||||
{
|
||||
public static string[] BusinessApplicationCategories =
|
||||
{
|
||||
"Metrónomos, afinadores, atriles, accesorios y complementos en general",
|
||||
"Contrabajo y arcos",
|
||||
"Cuerdas de violín, viola, violonchelo y contrabajo",
|
||||
"Pastillas, afinadores, puentes, cordales, soportes y accesorios de cuerda",
|
||||
"Viola y arcos de viola",
|
||||
"Violín y arcos de violín",
|
||||
"Violonchelo y arcos",
|
||||
"Amplificadores, cabezales y bafles de guitarra y bajo",
|
||||
"Bajos eléctricos y acústicos",
|
||||
"Bandurrias",
|
||||
"Cuerdas de instrumentos de cuerda punteada",
|
||||
"Estuches, fundas y soportes para instrumentos de cuerda punteada",
|
||||
"Guitarras acústicas amplificadas",
|
||||
"Guitarras acústicas no amplificadas",
|
||||
"Guitarras eléctricas",
|
||||
"Guitarras españolas amplificadas",
|
||||
"Guitarras españolas no amplificadas",
|
||||
"Laúdes",
|
||||
"Procesadores de guitarra, pedales, pedaleras, pastillas, mocrófonos de guitara y afinadores",
|
||||
"Púas, puentes, cejuelas, tornillos, cordales, clavijas y accesorios en general de guitarra e instrumentos de cuerda p",
|
||||
"Timples, ukeleles y otros instrumentos de cuerda punteada",
|
||||
"Lámaras, focos, procesadores y mesas iluminación",
|
||||
"Líquido y máquinas de humo",
|
||||
"Software secuenciador, editor, procesador y grabador de sonido y sus complementos, aso como programas en general",
|
||||
"Torres, bolas y complementos de iluminación",
|
||||
"Armónicas, acordeones e instrumentos de lengüeta y sus complementos",
|
||||
"Baterías acústicas y digitales",
|
||||
"Cajones rumberos, claves, sonajas y otros instrumentos no incluidos en otra familia",
|
||||
"Marimbas, xilófonos, metalófonos e instrumentos con escala afinada",
|
||||
"Platos",
|
||||
"Soportes, racks, fundas, banquetas, parches, membranas, baquetas y accesorios de percusión en general",
|
||||
"Timbales, bombos, tambores, cajas panderetas y otros instrumentos de membrana",
|
||||
"Estuches, fundas, banquetas y accesorios de piano",
|
||||
"Pianos de Cola Nuevos con o sin módulo",
|
||||
"Pianos de Cola Usados",
|
||||
"Pianos Digitales con ritmos",
|
||||
"Pianos Digitales sin ritmos",
|
||||
"Pianos Verticales Nuevos con o sin módulo",
|
||||
"Pianos Verticales Usados con o sin módulo",
|
||||
"Libretas, block y papel pautado",
|
||||
"Libros y partituras de canto",
|
||||
"Libros y partituras de clarinete",
|
||||
"Libros y partituras de contrabajo",
|
||||
"Libros y partituras de fagot",
|
||||
"Libros y partituras de flauta, dulzaina y gaita",
|
||||
"Libros y partituras de guitarra y cuerda punteada",
|
||||
"Libros y partituras de música de cámara",
|
||||
"Libros y partituras de oboe",
|
||||
"Libros y partituras de orquesta",
|
||||
"Libros y partituras de percusión",
|
||||
"Libros y partituras de piano",
|
||||
"Libros y partituras de saxo",
|
||||
"Libros y partituras de solfeo, armonía, Historia de la Música y textos en general",
|
||||
"Libros y partituras de teclado y acordeón",
|
||||
"Libros y partituras de trombón, tuba y bombardino",
|
||||
"Libros y partituras de trompa",
|
||||
"Libros y partituras de trompeta",
|
||||
"Libros y partituras de viola",
|
||||
"Libros y partituras de violín",
|
||||
"Libros y partituras de violonchelo",
|
||||
"Alquiler de piano, teclados y otros aparatos",
|
||||
"Servicios de afinación, reparación y transporte de pianos",
|
||||
"Servicios de reparación de bafles, etapas y sistemas de amplificación y procesado de sonido",
|
||||
"Servicios de reparación de teclados e instrumentos digitales",
|
||||
"Servicios de reparación y ajuste de guitarras",
|
||||
"Servicios de reparación y ajuste de instrumentos de cuerda",
|
||||
"Servicios de reparación y ajuste de instrumentos de viento",
|
||||
"Bafles, altavoces y monitores normales o inalámbricos",
|
||||
"Cables y conectores",
|
||||
"Etapas de potencia",
|
||||
"Grabadores de sonido y sus soportes",
|
||||
"Mesas de mezcla, cabezales, equipos integrados, amplificadores (combos) multiuso y mezcladores",
|
||||
"Micrófonos normales e inalámbricos",
|
||||
"Procesadores de efectos, pachbay, puertas de ruido, divisores, ecualizadores y otros sistemas de procesado de sonido",
|
||||
"Soportes de micro, columna y torres, racks, auriculares y accesorios en general de amplificación",
|
||||
"Accesorios de informática en general",
|
||||
"CD y DVD",
|
||||
"Librerías de sonidos y midifiles",
|
||||
"OTRO",
|
||||
"Tarjetas de sonido e interfaces de ordenador con o sin software",
|
||||
"Alimentadores, fundas, estuches, pedales, soportes y accesorios de teclado y módulos",
|
||||
"Cajas de ritmos y módulos de DJ",
|
||||
"Módulos arregladores con ritmos y secuenciadores",
|
||||
"Módulos de sonido, sintetizadores y samplers",
|
||||
"Módulos digitales de percusión",
|
||||
"Órganos y teclados litúrgicos",
|
||||
"Teclados con ritmos",
|
||||
"Teclados Sintetizadores, Workstation y samplers",
|
||||
"Teclados y mesas controladores",
|
||||
"Cañas, boquillas, abrazaderas, estuches, fundas, soportes, atriles, accesorios y complementos de viento",
|
||||
"Clarinete",
|
||||
"Flauta travesera y de pico",
|
||||
"Oboe, fliscorno, bombardino, fagot, helicón, tuba y otros instrumentos de viento",
|
||||
"Saxo",
|
||||
"Trombón",
|
||||
"Trompa",
|
||||
"Trompetas y cornetas"
|
||||
};
|
||||
}
|
||||
}
|
@ -1,8 +1,10 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using AutoMapper;
|
||||
using CsvHelper;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using OD.WebApplication.Models;
|
||||
@ -12,30 +14,78 @@ namespace OD.WebApplication.Controllers
|
||||
public class HomeController : Controller
|
||||
{
|
||||
private readonly ILogger<HomeController> _logger;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public HomeController(ILogger<HomeController> logger)
|
||||
public HomeController(ILogger<HomeController> logger, IMapper mapper)
|
||||
{
|
||||
_logger = logger;
|
||||
_mapper = mapper;
|
||||
}
|
||||
|
||||
public IActionResult Index()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
public IActionResult Upload()
|
||||
{
|
||||
return View();
|
||||
}
|
||||
|
||||
public async Task<IActionResult> UploadCSV()
|
||||
{
|
||||
return Ok();
|
||||
}
|
||||
|
||||
public IActionResult Privacy()
|
||||
[HttpPost]
|
||||
[ValidateAntiForgeryToken]
|
||||
public IActionResult UploadCSV(HomeViewModel model)
|
||||
{
|
||||
return View();
|
||||
try
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
using var reader = new StreamReader(model.FileAttach.OpenReadStream());
|
||||
using var csvReader = new CsvReader(reader, CultureInfo.GetCultureInfo("es-ES"));
|
||||
csvReader.Configuration.BadDataFound = null;
|
||||
csvReader.Configuration.HeaderValidated = null;
|
||||
csvReader.Configuration.MissingFieldFound = null;
|
||||
csvReader.Configuration.Delimiter = ";";
|
||||
var originDto = new List<OriginDataModel>();
|
||||
csvReader.Read();
|
||||
csvReader.ReadHeader();
|
||||
while (csvReader.Read())
|
||||
{
|
||||
var record = new OriginDataModel
|
||||
{
|
||||
Id = csvReader.GetField("ID"),
|
||||
Categories = csvReader.GetField<string>("Categorías"),
|
||||
Manufacturer = csvReader.GetField<string>("Fabricante"),
|
||||
PriceListingWithoutVAT = decimal.Parse(csvReader.GetField("Precio tiendas sin IVA")),
|
||||
PricePublicWithoutVAT = decimal.Parse(csvReader.GetField("PVP sin IVA")),
|
||||
PriceRecommendedWithoutVAT = decimal.Parse(csvReader.GetField("PVR sin IVA")),
|
||||
Stock = decimal.Parse(csvReader.GetField("Stock")),
|
||||
Volume = float.Parse(csvReader.GetField("Volumen")),
|
||||
Name = csvReader.GetField("Nombre"),
|
||||
LongDesc = csvReader.GetField("Descripción larga"),
|
||||
ShortDesc = csvReader.GetField("Descripción breve"),
|
||||
ImageUrls = csvReader.GetField("Imagen"),
|
||||
Ean13 = csvReader.GetField("EAN13"),
|
||||
Sda = csvReader.GetField("SDA")
|
||||
};
|
||||
originDto.Add(record);
|
||||
}
|
||||
|
||||
var destinationDto = _mapper.Map<List<OriginDataModel>, List<DestinationDataModel>>(originDto);
|
||||
|
||||
var ms = new MemoryStream();
|
||||
var sw = new StreamWriter(ms);
|
||||
using var csvWriter = new CsvWriter(sw, CultureInfo.GetCultureInfo("es-ES"));
|
||||
csvWriter.Configuration.Delimiter = ",";
|
||||
csvWriter.WriteRecords(destinationDto);
|
||||
sw.Flush();
|
||||
ms.Position = 0;
|
||||
return File(ms.ToArray(), "text/csv", "result.csv");
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Attempted to perform an invalid conversion");
|
||||
return new ErrorMessageResult(new ErrorResult { Exception = ex });
|
||||
}
|
||||
|
||||
return Ok();
|
||||
}
|
||||
|
||||
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
|
||||
|
28
OD.WebApplication/Models/DestinationDataModel.cs
Normal file
28
OD.WebApplication/Models/DestinationDataModel.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using CsvHelper.Configuration.Attributes;
|
||||
|
||||
namespace OD.WebApplication.Models
|
||||
{
|
||||
public class DestinationDataModel
|
||||
{
|
||||
[Name("categ_id")]
|
||||
public string Category { get; set; }
|
||||
|
||||
[Name("brand")]
|
||||
public string Brand { get; set; }
|
||||
|
||||
[Name("name")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[Name("alternate_code")]
|
||||
public string AlternateCode { get; set; }
|
||||
|
||||
[Name("list_price")]
|
||||
public int StorePriceWithVAT { get; set; }
|
||||
|
||||
[Name("online_price")]
|
||||
public int OnlinePriceWithVAT { get; set; }
|
||||
|
||||
[Name("online_value_price")]
|
||||
public int OnlineValueWihtVAT { get; set; }
|
||||
}
|
||||
}
|
27
OD.WebApplication/Models/ErrorMessageResult.cs
Normal file
27
OD.WebApplication/Models/ErrorMessageResult.cs
Normal file
@ -0,0 +1,27 @@
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.DataProtection.Internal;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace OD.WebApplication.Models
|
||||
{
|
||||
public class ErrorMessageResult : IActionResult
|
||||
{
|
||||
private readonly ErrorResult _result;
|
||||
|
||||
public ErrorMessageResult(ErrorResult result)
|
||||
{
|
||||
_result = result;
|
||||
}
|
||||
|
||||
public async Task ExecuteResultAsync(ActionContext context)
|
||||
{
|
||||
var objectResult = new ObjectResult(_result.Exception)
|
||||
{
|
||||
StatusCode = StatusCodes.Status500InternalServerError
|
||||
};
|
||||
|
||||
await objectResult.ExecuteResultAsync(context);
|
||||
}
|
||||
}
|
||||
}
|
9
OD.WebApplication/Models/ErrorResult.cs
Normal file
9
OD.WebApplication/Models/ErrorResult.cs
Normal file
@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace OD.WebApplication.Models
|
||||
{
|
||||
public class ErrorResult
|
||||
{
|
||||
public Exception Exception { get; set; }
|
||||
}
|
||||
}
|
11
OD.WebApplication/Models/HomeViewModel.cs
Normal file
11
OD.WebApplication/Models/HomeViewModel.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using System.IO;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
|
||||
namespace OD.WebApplication.Models
|
||||
{
|
||||
public class HomeViewModel
|
||||
{
|
||||
public IFormFile FileAttach { get; set; }
|
||||
}
|
||||
}
|
49
OD.WebApplication/Models/OriginDataModel.cs
Normal file
49
OD.WebApplication/Models/OriginDataModel.cs
Normal file
@ -0,0 +1,49 @@
|
||||
using CsvHelper.Configuration.Attributes;
|
||||
|
||||
namespace OD.WebApplication.Models
|
||||
{
|
||||
public class OriginDataModel
|
||||
{
|
||||
[Name("ID")]
|
||||
public string Id { get; set; }
|
||||
|
||||
[Name("Categorías")]
|
||||
public string Categories { get; set; }
|
||||
|
||||
[Name("Fabricante")]
|
||||
public string Manufacturer { get; set; }
|
||||
|
||||
[Name("Precio tiendas sin IVA")]
|
||||
public decimal PriceListingWithoutVAT { get; set; }
|
||||
|
||||
[Name("PVP sin IVA")]
|
||||
public decimal PricePublicWithoutVAT { get; set; }
|
||||
|
||||
[Name("PVR sin IVA")]
|
||||
public decimal PriceRecommendedWithoutVAT { get; set; }
|
||||
|
||||
[Name("Stock")]
|
||||
public decimal Stock { get; set; }
|
||||
|
||||
[Name("Volumen")]
|
||||
public float Volume { get; set; }
|
||||
|
||||
[Name("Nombre")]
|
||||
public string Name { get; set; }
|
||||
|
||||
[Name("Descripción larga")]
|
||||
public string LongDesc { get; set; }
|
||||
|
||||
[Name("Descripción breve")]
|
||||
public string ShortDesc { get; set; }
|
||||
|
||||
[Name("Imagen")]
|
||||
public string ImageUrls { get; set; }
|
||||
|
||||
[Name("EAN13")]
|
||||
public string Ean13 { get; set; }
|
||||
|
||||
[Name("SDA")]
|
||||
public string Sda { get; set; }
|
||||
}
|
||||
}
|
@ -5,10 +5,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="Views\Home\Upload.cshtml">
|
||||
<ExcludeFromSingleFile>true</ExcludeFromSingleFile>
|
||||
<CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
|
||||
</Content>
|
||||
<PackageReference Include="AutoMapper" Version="10.0.0" />
|
||||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="8.0.0" />
|
||||
<PackageReference Include="CsvHelper" Version="15.0.5" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
53
OD.WebApplication/Profiles/OriginToDestinationProfile.cs
Normal file
53
OD.WebApplication/Profiles/OriginToDestinationProfile.cs
Normal file
@ -0,0 +1,53 @@
|
||||
using System.Linq;
|
||||
using AutoMapper;
|
||||
using AutoMapper.Internal;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using OD.WebApplication.Context;
|
||||
using OD.WebApplication.Models;
|
||||
|
||||
namespace OD.WebApplication.Profiles
|
||||
{
|
||||
public class OriginToDestinationProfile : Profile
|
||||
{
|
||||
public OriginToDestinationProfile()
|
||||
{
|
||||
CreateMap<OriginDataModel, DestinationDataModel>()
|
||||
.ForMember(dest => dest.Category, opt => opt.MapFrom(src=> ResolveCategory(src)))
|
||||
.ForMember(dest => dest.Brand, opt => opt.MapFrom(src => src.Manufacturer))
|
||||
.ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.Name))
|
||||
.ForMember(dest => dest.AlternateCode, opt => opt.MapFrom(src => ResolveAlternateCode(src)))
|
||||
.ForMember(dest => dest.StorePriceWithVAT, opt => opt.MapFrom(src => ResolveAddVAT(src.PriceListingWithoutVAT)))
|
||||
.ForMember(dest => dest.OnlinePriceWithVAT, opt => opt.MapFrom(src => ResolveAddVAT(src.PricePublicWithoutVAT)))
|
||||
.ForMember(dest => dest.OnlineValueWihtVAT, opt => opt.MapFrom(src => ResolveAddVAT(src.PriceRecommendedWithoutVAT)));
|
||||
}
|
||||
|
||||
private static string ResolveCategory(OriginDataModel src)
|
||||
{
|
||||
var categories = src.Categories.Split(',').ToList();
|
||||
categories = categories.Select(del => del.Trim()).ToList();
|
||||
foreach (var category in categories)
|
||||
{
|
||||
if (ApplicationContextHelper.BusinessApplicationCategories.Any(x =>
|
||||
x.Contains(category) || category.Contains(x)))
|
||||
{
|
||||
return ApplicationContextHelper.BusinessApplicationCategories.First(x =>
|
||||
x.Contains(category) || category.Contains(x));
|
||||
}
|
||||
}
|
||||
|
||||
return "OTRO";
|
||||
}
|
||||
|
||||
private static string ResolveAlternateCode(OriginDataModel src)
|
||||
{
|
||||
return src.ShortDesc.ToUpper().Replace(" ", "");
|
||||
}
|
||||
|
||||
private static int ResolveAddVAT(decimal input)
|
||||
{
|
||||
const decimal vat = 0.21m;
|
||||
var result = decimal.Round(input * vat + input);
|
||||
return decimal.ToInt32(result);
|
||||
}
|
||||
}
|
||||
}
|
@ -8,6 +8,9 @@ using Microsoft.AspNetCore.HttpsPolicy;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using AutoMapper;
|
||||
using OD.WebApplication.Context;
|
||||
using OD.WebApplication.Profiles;
|
||||
|
||||
namespace OD.WebApplication
|
||||
{
|
||||
@ -24,6 +27,7 @@ namespace OD.WebApplication
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddControllersWithViews();
|
||||
services.AddAutoMapper(typeof(Startup));
|
||||
}
|
||||
|
||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||
|
@ -1,8 +1,21 @@
|
||||
@{
|
||||
ViewData["Title"] = "Home Page";
|
||||
@using Microsoft.AspNetCore.Mvc.Rendering
|
||||
@model HomeViewModel
|
||||
@{
|
||||
ViewData["Title"] = "Upload page";
|
||||
}
|
||||
|
||||
<div class="text-center">
|
||||
<h1 class="display-4">Welcome</h1>
|
||||
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
|
||||
<h4>Escoge el CSV a parsear</h4>
|
||||
<br/>
|
||||
@using (Html.BeginForm("UploadCSV", "Home", FormMethod.Post, new {id = "loginForm", enctype = "multipart/form-data"}))
|
||||
{
|
||||
@Html.AntiForgeryToken()
|
||||
<div class="form-group">
|
||||
<label asp-for="@Model.FileAttach"></label>
|
||||
<input asp-for="@Model.FileAttach" type="file">
|
||||
<span asp-validation-for="@Model.FileAttach"></span>
|
||||
</div>
|
||||
<input class="btn btn-outline-primary" type="submit"/>
|
||||
}
|
||||
|
||||
</div>
|
@ -1,6 +0,0 @@
|
||||
@{
|
||||
ViewData["Title"] = "Privacy Policy";
|
||||
}
|
||||
<h1>@ViewData["Title"]</h1>
|
||||
|
||||
<p>Use this page to detail your site's privacy policy.</p>
|
@ -1,18 +0,0 @@
|
||||
@using Microsoft.AspNetCore.Mvc.Rendering
|
||||
@{
|
||||
ViewData["Title"] = "Upload page";
|
||||
}
|
||||
|
||||
<div class="text-center">
|
||||
<h4>Escoge el CSV a parsear</h4>
|
||||
<br/>
|
||||
@using (Html.BeginForm("UploadCSV", "Home", FormMethod.Post, new {id = "loginForm"}))
|
||||
{
|
||||
@Html.AntiForgeryToken()
|
||||
<div class="form-group">
|
||||
Do your magic pablo
|
||||
</div>
|
||||
<input class="btn btn-outline-primary" type="submit"/>
|
||||
}
|
||||
|
||||
</div>
|
@ -21,12 +21,6 @@
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Upload">Upload</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@ -40,7 +34,7 @@
|
||||
|
||||
<footer class="border-top footer text-muted">
|
||||
<div class="container">
|
||||
© 2020 - OD.WebApplication - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
|
||||
© 2020 - SI
|
||||
</div>
|
||||
</footer>
|
||||
<script src="~/lib/jquery/dist/jquery.min.js"></script>
|
||||
|
Loading…
Reference in New Issue
Block a user