328 lines
14 KiB
C#
328 lines
14 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Identity;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
|
using Microsoft.AspNetCore.Mvc.Rendering;
|
|
using EveryThing.Data;
|
|
using EveryThing.Models;
|
|
using EveryThing.Models.Project;
|
|
using Microsoft.AspNetCore.Http;
|
|
using System.IO;
|
|
using Microsoft.AspNetCore.Hosting;
|
|
using ClosedXML.Excel;
|
|
using EveryThing.Models.CodeTable;
|
|
|
|
namespace EveryThing.Pages.Projects
|
|
{
|
|
[Authorize(Roles = "Administrator,ProjecThingUser")]
|
|
public class CreatePartItemImportExcelModel : PageModel
|
|
{
|
|
private readonly IWebHostEnvironment _hostingEnvironment;
|
|
private readonly ApplicationDbContext _context;
|
|
private readonly UserManager<IdentityApplicationUser> _userManager;
|
|
private readonly SignInManager<IdentityApplicationUser> _loginManager;
|
|
private readonly RoleManager<IdentityApplicationRole> _roleManager;
|
|
|
|
public CreatePartItemImportExcelModel(ApplicationDbContext context, UserManager<IdentityApplicationUser> userManager, SignInManager<IdentityApplicationUser> loginManager, RoleManager<IdentityApplicationRole> roleManager, IWebHostEnvironment environment)
|
|
{
|
|
_context = context;
|
|
_userManager = userManager;
|
|
_loginManager = loginManager;
|
|
_roleManager = roleManager;
|
|
_hostingEnvironment = environment;
|
|
}
|
|
|
|
[BindProperty]
|
|
public int IdProject { get; set; }
|
|
[BindProperty]
|
|
public int IdProjectPart { get; set; }
|
|
[BindProperty]
|
|
public string FileName { get; set; }
|
|
[BindProperty]
|
|
public List<ExcelItem> ExcelItems { get; set; }
|
|
[BindProperty]
|
|
public string SelectedItems { get; set; }
|
|
|
|
|
|
public IActionResult OnGet(int idProject, int idProjectPart)
|
|
{
|
|
IdProject = idProject;
|
|
IdProjectPart = idProjectPart;
|
|
ExcelItems = new List<ExcelItem>();
|
|
|
|
return Page();
|
|
}
|
|
|
|
public async Task<IActionResult> OnPostUpload(int idProject, int idProjectPart, List<IFormFile> postedFiles)
|
|
{
|
|
if (postedFiles == null
|
|
|| postedFiles.Count != 1)
|
|
{
|
|
return new JsonResult(new { successful = false, error = "Izberite eno datoteko." });
|
|
}
|
|
var path = Path.Combine(_hostingEnvironment.WebRootPath, "Uploads", "TempExcelImport");
|
|
if (!Directory.Exists(path))
|
|
{
|
|
Directory.CreateDirectory(path);
|
|
}
|
|
else
|
|
{
|
|
//Pocistimo mapo
|
|
foreach (var fileInfo in new DirectoryInfo(path).GetFiles("*.*"))
|
|
{
|
|
fileInfo.Delete();
|
|
}
|
|
}
|
|
|
|
var postedFile = postedFiles[0];
|
|
|
|
var fileName = postedFile.FileName;
|
|
await using (var stream = new FileStream(Path.Combine(path, fileName), FileMode.Create))
|
|
{
|
|
await postedFile.CopyToAsync(stream);
|
|
}
|
|
|
|
// Read excel headers
|
|
var excelItems = new List<ExcelItem>();
|
|
var filePath = Path.Combine(path, fileName);
|
|
var xlWorkbook = new XLWorkbook(filePath);
|
|
var worksheet = xlWorkbook.Worksheet(1);
|
|
|
|
int i = 1;
|
|
if (!worksheet.Row(i).IsEmpty())
|
|
{
|
|
IXLRow row = worksheet.Row(i);
|
|
int j = 1;
|
|
while (!row.Cell(j).IsEmpty())
|
|
{
|
|
excelItems.Add(new ExcelItem
|
|
{
|
|
CellIndex = j,
|
|
Name = row.Cell(j).Value.ToString(),
|
|
});
|
|
j++;
|
|
}
|
|
}
|
|
|
|
// Build mapping options
|
|
var mappingOptions = typeof(Models.Project.ProjectPartItem).GetProperties()
|
|
.Where(x => x.GetCustomAttributes(true).Length > 0 && x.GetCustomAttributes(true).Any(y => y.GetType() == typeof(System.ComponentModel.DataAnnotations.DisplayAttribute)))
|
|
.Select(x => new
|
|
{
|
|
name = x.Name,
|
|
display = ((System.ComponentModel.DataAnnotations.DisplayAttribute)x.GetCustomAttributes(true).First(y => y.GetType() == typeof(System.ComponentModel.DataAnnotations.DisplayAttribute))).Name
|
|
}).ToList();
|
|
|
|
return new JsonResult(new { successful = true, fileName, excelItems, mappingOptions });
|
|
}
|
|
|
|
public async Task<IActionResult> OnPostImport(string selectedItems, string fileName, int idProjectPart, int idProject)
|
|
{
|
|
FileName = fileName;
|
|
IdProjectPart = idProjectPart;
|
|
IdProject = idProject;
|
|
|
|
if (string.IsNullOrEmpty(selectedItems))
|
|
{
|
|
return new JsonResult(new { successful = false, error = "Izberite vsaj eno polje." });
|
|
}
|
|
var user = _userManager.GetUserAsync(User).Result;
|
|
|
|
var excelItems = new List<ExcelItem>();
|
|
|
|
var items = selectedItems.Split('#');
|
|
foreach (var item in items)
|
|
{
|
|
var itemData = item.Split(';');
|
|
if (itemData.Length != 2)
|
|
continue;
|
|
|
|
excelItems.Add(new ExcelItem
|
|
{
|
|
CellIndex = Convert.ToInt32(itemData[0]),
|
|
Name = itemData[1],
|
|
});
|
|
}
|
|
|
|
var path = Path.Combine(_hostingEnvironment.WebRootPath, "Uploads", "TempExcelImport", FileName);
|
|
|
|
var xlWorkbook = new XLWorkbook(path);
|
|
|
|
//ONLY FIRST LIST
|
|
var worksheet = xlWorkbook.Worksheet(1);
|
|
|
|
// Build display name lookup for properties
|
|
var propertyDisplayNames = typeof(Models.Project.ProjectPartItem).GetProperties()
|
|
.Where(x => x.GetCustomAttributes(true).Any(y => y is System.ComponentModel.DataAnnotations.DisplayAttribute))
|
|
.ToDictionary(
|
|
x => x.Name,
|
|
x => ((System.ComponentModel.DataAnnotations.DisplayAttribute)x.GetCustomAttributes(true).First(y => y is System.ComponentModel.DataAnnotations.DisplayAttribute)).Name
|
|
);
|
|
|
|
// Validation pass - check all rows before importing
|
|
var errors = new List<object>();
|
|
int validationRow = 2; // Skip header
|
|
while (!worksheet.Row(validationRow).IsEmpty())
|
|
{
|
|
IXLRow row = worksheet.Row(validationRow);
|
|
|
|
// Check if all mapped cells in the row are empty
|
|
bool allEmpty = excelItems.All(ei =>
|
|
row.Cell(ei.CellIndex) == null || string.IsNullOrWhiteSpace(row.Cell(ei.CellIndex).Value.ToString()));
|
|
|
|
if (allEmpty)
|
|
{
|
|
errors.Add(new { row = validationRow, property = "-", value = "", message = "Vsa polja v vrstici so prazna." });
|
|
validationRow++;
|
|
continue;
|
|
}
|
|
|
|
foreach (var excelItem in excelItems)
|
|
{
|
|
if (row.Cell(excelItem.CellIndex) == null)
|
|
continue;
|
|
|
|
string value = row.Cell(excelItem.CellIndex).Value.ToString();
|
|
string displayName = propertyDisplayNames.ContainsKey(excelItem.Name) ? propertyDisplayNames[excelItem.Name] : excelItem.Name;
|
|
|
|
// Empty individual cells are allowed - skip validation
|
|
if (string.IsNullOrWhiteSpace(value))
|
|
continue;
|
|
|
|
if (excelItem.Name is "IdItemFk" or "IdMaterialFk" or "IdMaterialSupplierFk")
|
|
{
|
|
// These are text lookups, no type conversion needed
|
|
continue;
|
|
}
|
|
|
|
// Validate type conversion for other properties
|
|
var propertyInfo = typeof(Models.Project.ProjectPartItem).GetProperties().FirstOrDefault(x => x.Name == excelItem.Name);
|
|
if (propertyInfo != null)
|
|
{
|
|
try
|
|
{
|
|
var targetType = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType;
|
|
Convert.ChangeType(value, targetType);
|
|
}
|
|
catch
|
|
{
|
|
errors.Add(new { row = validationRow, property = displayName, value, message = $"Ni mogoče pretvoriti v tip {propertyInfo.PropertyType.Name}." });
|
|
}
|
|
}
|
|
}
|
|
validationRow++;
|
|
}
|
|
|
|
if (errors.Count > 0)
|
|
{
|
|
return new JsonResult(new { successful = false, validationErrors = errors });
|
|
}
|
|
|
|
var insertedParts = _context.ProjectPartItems.Where(x => x.IdProjectPartFk == IdProjectPart);
|
|
|
|
var currentPositionNumber = insertedParts.Any()
|
|
? insertedParts.Max(x => x.ProjectPartItemNumber)
|
|
: 0;
|
|
|
|
if (currentPositionNumber <= 0)
|
|
currentPositionNumber = 0;
|
|
|
|
int i = 2;//Skip header
|
|
while (!worksheet.Row(i).IsEmpty())
|
|
{
|
|
currentPositionNumber++;
|
|
IXLRow row = worksheet.Row(i);
|
|
var newPosition = new Models.Project.ProjectPartItem
|
|
{
|
|
IdProjectPartFk = IdProjectPart,
|
|
NumberOfItems = 1,
|
|
NumberOfSets = 1,
|
|
IdMaterialSupplierFk = _context.CodeTablePartners.First().IdPartner,
|
|
ProjectPartItemNumber = currentPositionNumber
|
|
};
|
|
|
|
foreach (var excelItem in excelItems)
|
|
{
|
|
if (row.Cell(excelItem.CellIndex) == null)
|
|
continue;
|
|
|
|
string value = row.Cell(excelItem.CellIndex).Value.ToString();
|
|
|
|
if (string.IsNullOrWhiteSpace(value))
|
|
continue;
|
|
|
|
if (excelItem.Name is "IdItemFk" or "IdMaterialFk")
|
|
{
|
|
var completableItem = _context.CodeTableItems.FirstOrDefault(x => x.Title == value && x.Active == true);
|
|
if (completableItem == null)
|
|
{
|
|
//Add new if not exists
|
|
completableItem = new Models.CodeTable.CodeTableItem
|
|
{
|
|
Active = true,
|
|
IdCompanyFk = user.IdCompanyFk,
|
|
Title = value,
|
|
CodeTableItemType = excelItem.Name == "IdMaterialFk" ? CodeTableItemType.Material : CodeTableItemType.Product
|
|
};
|
|
_context.CodeTableItems.Add(completableItem);
|
|
await _context.SaveChangesAsync();
|
|
}
|
|
if (excelItem.Name == "IdItemFk")
|
|
newPosition.IdItemFk = completableItem.IdItem;
|
|
else
|
|
newPosition.IdMaterialFk = completableItem.IdItem;
|
|
}
|
|
else if (excelItem.Name is "IdMaterialSupplierFk")
|
|
{
|
|
var tmpPartner = _context.CodeTablePartners.FirstOrDefault(x => x.Title == value && x.Active == true);
|
|
if (tmpPartner == null)
|
|
{
|
|
//Add new if not exists
|
|
tmpPartner = new CodeTablePartner()
|
|
{
|
|
Active = true,
|
|
IdCompanyFk = user.IdCompanyFk,
|
|
Title = value,
|
|
Supplier = true,
|
|
IdCountryFk = _context.CodeTableCountries.First(x => x.Code == "SI").IdCountry,
|
|
City = "",
|
|
Street = "",
|
|
HouseNumber = "",
|
|
PostNumber = 0,
|
|
Post = "",
|
|
};
|
|
_context.CodeTablePartners.Add(tmpPartner);
|
|
await _context.SaveChangesAsync();
|
|
}
|
|
|
|
newPosition.IdMaterialSupplierFk = tmpPartner.IdPartner;
|
|
}
|
|
else
|
|
{
|
|
var propertyInfo = newPosition.GetType().GetProperties().First(x => x.Name == excelItem.Name);
|
|
object propertyValue = Convert.ChangeType(value, Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType);
|
|
propertyInfo.SetValue(newPosition, propertyValue);
|
|
}
|
|
}
|
|
_context.ProjectPartItems.Add(newPosition);
|
|
await _context.SaveChangesAsync();
|
|
i++;
|
|
}
|
|
|
|
System.IO.File.Delete(path);
|
|
|
|
return new JsonResult(new { successful = true, redirectUrl = Url.Page("./Edit", new { id = IdProject }) });
|
|
}
|
|
|
|
public class ExcelItem
|
|
{
|
|
public int CellIndex { get; set; }
|
|
public string Name { get; set; }
|
|
}
|
|
}
|
|
}
|