Files
lux/EgwCoreLib.Lux.Data/Repository/Items/ItemRepository.cs
T
2026-03-24 16:01:34 +01:00

282 lines
11 KiB
C#

using EgwCoreLib.Lux.Core.RestPayload;
using EgwCoreLib.Lux.Data.DbModel.Items;
using Microsoft.EntityFrameworkCore;
using System.Globalization;
using static EgwCoreLib.Lux.Core.Enums;
namespace EgwCoreLib.Lux.Data.Repository.Items
{
public class ItemRepository : BaseRepository, IItemRepository
{
#region Public Constructors
public ItemRepository(IDbContextFactory<DataLayerContext> ctxFactory) : base(ctxFactory)
{
}
#endregion Public Constructors
#region Public Methods
public async Task<bool> AddAsync(ItemModel entity)
{
await using var dbCtx = await CreateContextAsync();
await dbCtx.DbSetItem.AddAsync(entity);
return await dbCtx.SaveChangesAsync() > 0;
}
public async Task<bool> DeleteAsync(ItemModel entity)
{
await using var dbCtx = await CreateContextAsync();
dbCtx.DbSetItem.Remove(entity);
return await dbCtx.SaveChangesAsync() > 0;
}
public async Task<List<ItemModel>> GetAltAsync(int recId)
{
await using var dbCtx = await CreateContextAsync();
List<ItemModel> dbResult = new List<ItemModel>();
// cerco singolo record x partire...
var currRec = dbCtx
.DbSetItem
.Where(x => x.ItemID == recId)
.FirstOrDefault();
if ((currRec != null))
{
// se è un record che ha parentId > 0 --> cerco da quello record analoghi + parent
if (currRec.ItemIDParent > 0)
{
dbResult = await dbCtx
.DbSetItem
.Where(x => x.ItemID == currRec.ItemIDParent || x.ItemIDParent == currRec.ItemIDParent)
.ToListAsync();
}
// altrimenti cerco child collegati
else
{
dbResult = await dbCtx
.DbSetItem
.Where(x => x.ItemID == currRec.ItemID || x.ItemIDParent == currRec.ItemID)
.ToListAsync();
}
}
return dbResult;
}
public async Task<ItemModel?> GetByIdAsync(int recId)
{
await using var dbCtx = await CreateContextAsync();
return await dbCtx.DbSetItem
.Where(x => x.ItemID == recId)
.FirstOrDefaultAsync();
}
public async Task<List<ItemModel>> GetFiltAsync(string CodGroup, ItemClassType ItemType)
{
await using var dbCtx = await CreateContextAsync();
return await dbCtx.DbSetItem
.Where(x => (string.IsNullOrEmpty(CodGroup) || x.CodGroup == CodGroup) && (ItemType == ItemClassType.ND || x.ItemType == ItemType))
.AsNoTracking()
.Include(g => g.ItemGroupNav)
.ToListAsync();
}
public async Task<List<ItemModel>> GetSearchAsync(string term)
{
await using var dbCtx = await CreateContextAsync();
return await dbCtx.DbSetItem
.Where(x => x.Description.Contains(term, StringComparison.InvariantCultureIgnoreCase) || x.ExtItemCode.Contains(term, StringComparison.InvariantCultureIgnoreCase) || x.SupplCode.Contains(term, StringComparison.InvariantCultureIgnoreCase))
.AsNoTracking()
//.Include(g => g.ItemGroupNav)
.ToListAsync();
}
public async Task<bool> MassUpdateAsync(List<BomItemDTO> list2upd, double setCost, double defMargin, double defQtyMax, string defUM, int roundVal = 0, double scaleFactor = 1_000_000.0)
{
bool answ = false;
if (list2upd == null || !list2upd.Any())
return answ;
await using var dbCtx = await CreateContextAsync();
// Validate input
if (setCost <= 0)
throw new ArgumentException("setCost must be greater than 0.");
// Step 1: Extract width and height from ExtItemCode
var itemUpdates = new List<ItemModel>();
foreach (var item in list2upd)
{
if (string.IsNullOrWhiteSpace(item.ItemCode))
continue;
// Try to parse ExtItemCode: "Pine-200.0x360.0"
if (!item.ItemCode.Contains("-") || !item.ItemCode.Contains("x"))
{
// Skip invalid format
continue;
}
// Split by "-" to get prefix and number part
var parts = item.ItemCode.Split('-', 2);
if (parts.Length < 2)
{
continue;
}
string numberPart = parts[1]; // e.g. "200.0x360.0"
// Split by "x" to get width and height
var widthHeight = numberPart.Split('x', 2);
if (widthHeight.Length < 2)
{
continue;
}
if (!double.TryParse(widthHeight[0], NumberStyles.Any, CultureInfo.InvariantCulture, out double width) ||
!double.TryParse(widthHeight[1], NumberStyles.Any, CultureInfo.InvariantCulture, out double height))
{
continue;
}
// Step 2: Calculate Cost using formula:
// Cost = setCost / 1,000,000 * width * height
double calculatedCost = (setCost / scaleFactor) * width * height;
// if requested do round ceiling
if (roundVal > 0)
{
calculatedCost = Math.Ceiling(calculatedCost / roundVal) * roundVal;
}
// Optional: you can also apply margin to cost if needed, but you said "Cost = ..."
// So we're just computing it based on width/height
// Step 4: Create a new ItemModel with updated values
var updatedItem = new ItemModel
{
ItemID = item.ItemID,
ExtItemCode = item.ItemCode, // keep original
Cost = calculatedCost,
Margin = defMargin,
QtyMax = defQtyMax,
UM = defUM
};
itemUpdates.Add(updatedItem);
}
// Step 5: Update database using EF Core (EF Core doesn't support "update" on entire list directly)
// We'll use .UpdateRange() or a raw update via .Where() and .SetProperty()
// ✅ Use EF Core's Update method (for bulk update)
if (itemUpdates.Any())
{
// Update only the ones that exist in the DB
var existingItems = await dbCtx.DbSetItem
.Where(i => itemUpdates.Select(ui => ui.ItemID).Contains(i.ItemID))
.ToListAsync();
if (existingItems.Any())
{
// Update existing records using EF Core's Update method
foreach (var updatedItem in itemUpdates)
{
var existing = existingItems.FirstOrDefault(i => i.ItemID == updatedItem.ItemID);
if (existing != null)
{
// Update only the fields we're setting
existing.Cost = updatedItem.Cost;
existing.Margin = updatedItem.Margin;
existing.QtyMax = updatedItem.QtyMax;
}
}
answ = await dbCtx.SaveChangesAsync() > 0;
}
}
return answ;
}
public async Task<bool> UpdateAsync(ItemModel entity)
{
await using var dbCtx = await CreateContextAsync();
// Recuperiamo l'entità tracciata dal context
var trackedEntity = await dbCtx.DbSetItem.FirstOrDefaultAsync(x => x.ItemID == entity.ItemID);
if (trackedEntity != null)
{
// Aggiorna i valori dell'entità tracciata con quelli della nuova
dbCtx.Entry(trackedEntity).CurrentValues.SetValues(entity);
}
else
{
dbCtx.DbSetItem.Update(entity);
}
return await dbCtx.SaveChangesAsync() > 0;
}
public async Task<bool> UpsertFromBomAsync(List<BomItemDTO> bomList)
{
await using var dbCtx = await CreateContextAsync();
// Wrap in transaction for atomicity
await using var tx = await dbCtx.Database.BeginTransactionAsync();
try
{
// prendo solo elementi a prezzo 0 da salvare sul DB
var item2save = bomList
.Where(x => x.Price == 0)
.ToList();
List<ItemModel> listInserted = new List<ItemModel>();
// ciclo x ogni elemento della BOM, cercando x gruppo e ExtItemCode
foreach (var item in item2save)
{
var currRec = dbCtx
.DbSetItem
.Where(x => x.CodGroup == item.ClassCode && x.ExtItemCode == item.ItemCode)
.FirstOrDefault();
// se nullo --> verifico x inserire!!!
if (currRec == null)
{
// verifico NON sia tra gli list2upd già in fase di inserimento
if (!listInserted.Any(x => x.CodGroup == item.ClassCode && x.ExtItemCode == item.ItemCode))
{
ItemModel newRec = new ItemModel()
{
CodGroup = item.ClassCode,
ItemType = Core.Enums.ItemClassType.Bom,
IsService = false,
// da calcolare meglio x gruppo
ItemCode = 0,
ExtItemCode = item.ItemCode,
SupplCode = "BOM ITEM",
Description = $"BOM | {item.ClassCode} | {item.ItemCode}",
Cost = 0,
Margin = 0,
QtyMin = 0,
QtyMax = 0,
UM = "#"
};
dbCtx.DbSetItem.Add(newRec);
listInserted.Add(newRec);
}
}
}
bool done = await dbCtx.SaveChangesAsync() > 0;
await tx.CommitAsync();
return done;
}
catch
{
await tx.RollbackAsync();
throw;
}
}
#endregion Public Methods
}
}