diff --git a/EgwCoreLib.Lux.Data/Controllers/LuxController.cs b/EgwCoreLib.Lux.Data/Controllers/LuxController.cs index 68df263..8918bc8 100644 --- a/EgwCoreLib.Lux.Data/Controllers/LuxController.cs +++ b/EgwCoreLib.Lux.Data/Controllers/LuxController.cs @@ -404,7 +404,6 @@ namespace EgwCoreLib.Lux.Data.Controllers return dbResult; } - /// Elimina riga e sposta eventuali righe successive... /// /// diff --git a/EgwCoreLib.Lux.Data/Repository/Sales/IOfferRepository.cs b/EgwCoreLib.Lux.Data/Repository/Sales/IOfferRepository.cs index 0dcf1a4..6b0a2f2 100644 --- a/EgwCoreLib.Lux.Data/Repository/Sales/IOfferRepository.cs +++ b/EgwCoreLib.Lux.Data/Repository/Sales/IOfferRepository.cs @@ -29,7 +29,7 @@ namespace EgwCoreLib.Lux.Data.Repository.Sales Task UpdateAsync(OfferModel entity); - Task UpdateCostAsync(int OfferID); + Task UpdateCostAsync(int offerId); #endregion Public Methods } diff --git a/EgwCoreLib.Lux.Data/Repository/Sales/IOfferRowRepository.cs b/EgwCoreLib.Lux.Data/Repository/Sales/IOfferRowRepository.cs index c33c1c7..37090eb 100644 --- a/EgwCoreLib.Lux.Data/Repository/Sales/IOfferRowRepository.cs +++ b/EgwCoreLib.Lux.Data/Repository/Sales/IOfferRowRepository.cs @@ -1,4 +1,5 @@ -using EgwCoreLib.Lux.Data.DbModel.Sales; +using EgwCoreLib.Lux.Data.DbModel.Items; +using EgwCoreLib.Lux.Data.DbModel.Sales; namespace EgwCoreLib.Lux.Data.Repository.Sales { @@ -10,17 +11,20 @@ namespace EgwCoreLib.Lux.Data.Repository.Sales Task DeleteAsync(OfferRowModel entity); - Task GetByUidAsync(string offerRowUid); + Task> GetBomItemsAsync(); Task GetByIdAsync(int offerRowId); Task> GetByParentAsync(int offerId); + Task GetByUidAsync(string offerRowUid); + + Task> GetItemGroupsAsync(); + Task SaveRowsAsync(List rows); Task UpdateAsync(OfferRowModel entity); - #endregion Public Methods } -} +} \ No newline at end of file diff --git a/EgwCoreLib.Lux.Data/Repository/Sales/OfferRowRepository.cs b/EgwCoreLib.Lux.Data/Repository/Sales/OfferRowRepository.cs index 421f2cd..365ed26 100644 --- a/EgwCoreLib.Lux.Data/Repository/Sales/OfferRowRepository.cs +++ b/EgwCoreLib.Lux.Data/Repository/Sales/OfferRowRepository.cs @@ -1,5 +1,7 @@ -using EgwCoreLib.Lux.Data.DbModel.Sales; +using EgwCoreLib.Lux.Data.DbModel.Items; +using EgwCoreLib.Lux.Data.DbModel.Sales; using Microsoft.EntityFrameworkCore; +using static EgwCoreLib.Lux.Core.Enums; namespace EgwCoreLib.Lux.Data.Repository.Sales { @@ -22,7 +24,6 @@ namespace EgwCoreLib.Lux.Data.Repository.Sales return await dbCtx.SaveChangesAsync() > 0; } - public async Task DeleteAsync(OfferRowModel entity) { await using var dbCtx = await CreateContextAsync(); @@ -30,13 +31,12 @@ namespace EgwCoreLib.Lux.Data.Repository.Sales return await dbCtx.SaveChangesAsync() > 0; } - - public async Task GetByUidAsync(string offerRowUid) + public async Task> GetBomItemsAsync() { await using var dbCtx = await CreateContextAsync(); - return await dbCtx.DbSetOfferRow - .Include(r => r.SellingItemNav) - .FirstOrDefaultAsync(x => x.OfferRowUID == offerRowUid); + return await dbCtx.DbSetItem + .Where(x => x.ItemType == ItemClassType.Bom || x.ItemType == ItemClassType.BomAlt) + .ToListAsync(); } public async Task GetByIdAsync(int offerRowId) @@ -47,7 +47,6 @@ namespace EgwCoreLib.Lux.Data.Repository.Sales .FirstOrDefaultAsync(x => x.OfferRowID == offerRowId); } - public async Task> GetByParentAsync(int offerId) { await using var dbCtx = await CreateContextAsync(); @@ -57,6 +56,20 @@ namespace EgwCoreLib.Lux.Data.Repository.Sales .ToListAsync(); } + public async Task GetByUidAsync(string offerRowUid) + { + await using var dbCtx = await CreateContextAsync(); + return await dbCtx.DbSetOfferRow + .Include(r => r.SellingItemNav) + .FirstOrDefaultAsync(x => x.OfferRowUID == offerRowUid); + } + + public async Task> GetItemGroupsAsync() + { + await using var dbCtx = await CreateContextAsync(); + return await dbCtx.DbSetItemGroup.ToListAsync(); + } + public async Task SaveRowsAsync(List rows) { await using var dbCtx = await CreateContextAsync(); @@ -86,4 +99,4 @@ namespace EgwCoreLib.Lux.Data.Repository.Sales #endregion Public Methods } -} +} \ No newline at end of file diff --git a/EgwCoreLib.Lux.Data/Services/Sales/IOfferRowService.cs b/EgwCoreLib.Lux.Data/Services/Sales/IOfferRowService.cs index 8806562..1980a53 100644 --- a/EgwCoreLib.Lux.Data/Services/Sales/IOfferRowService.cs +++ b/EgwCoreLib.Lux.Data/Services/Sales/IOfferRowService.cs @@ -1,4 +1,5 @@ -using EgwCoreLib.Lux.Data.DbModel.Sales; +using EgwCoreLib.Lux.Core.RestPayload; +using EgwCoreLib.Lux.Data.DbModel.Sales; namespace EgwCoreLib.Lux.Data.Services.Sales { @@ -6,21 +7,25 @@ namespace EgwCoreLib.Lux.Data.Services.Sales { #region Public Methods - Task CloneAsync(OfferRowModel rec2clone); - Task DeleteAsync(OfferRowModel model); - Task> FixRowUidAsync(int OfferId); + Task> FixUidAsync(int offerId); - Task> GetAllAsync(); + Task FixImgTypeAsync(int offerId); - Task> GetByParentAsync(int OfferId); + Task GetByUidAsync(string offerRowUid); - Task UpdateAwaitStateAsync(int OfferRowId, bool? awaitBom, bool? awaitPrice, bool flushCache = false); + Task GetByIdAsync(int offerRowId); + + Task> GetByParentAsync(int offerId); + + Task UpdateAwaitStateAsync(int offerRowId, bool? awaitBom, bool? awaitPrice, bool flushCache = false); + + Task UpdateBomAsync(int OfferRowID, List newBomList); Task UpdateFileDataAsync(OfferRowModel updRec); - Task UpdateSerStructAsync(int OfferRowID, string serStruct); + Task UpdateSerStructAsync(int offerRowID, string serStruct); Task UpsertAsync(OfferRowModel upsRec); diff --git a/EgwCoreLib.Lux.Data/Services/Sales/OfferRowService.cs b/EgwCoreLib.Lux.Data/Services/Sales/OfferRowService.cs new file mode 100644 index 0000000..1cb4cb1 --- /dev/null +++ b/EgwCoreLib.Lux.Data/Services/Sales/OfferRowService.cs @@ -0,0 +1,381 @@ +using EgwCoreLib.Lux.Core.RestPayload; +using EgwCoreLib.Lux.Data.DbModel.Sales; +using EgwCoreLib.Lux.Data.Domains; +using EgwCoreLib.Lux.Data.Repository.Sales; +using Microsoft.Extensions.Configuration; +using Newtonsoft.Json; +using StackExchange.Redis; +using static EgwCoreLib.Lux.Core.Enums; + +namespace EgwCoreLib.Lux.Data.Services.Sales +{ + public class OfferRowService : BaseServ, IOfferRowService + { + #region Public Constructors + + public OfferRowService( + IConfiguration config, + IConnectionMultiplexer redis, + IOfferRowRepository repo) : base(config, redis) + { + _className = "OfferRow"; + _repo = repo; + } + + #endregion Public Constructors + + #region Public Methods + + /// + /// Eliminazione record + /// + /// + /// + public async Task DeleteAsync(OfferRowModel rec2del) + { + return await TraceAsync($"{_className}.Delete", async (activity) => + { + var dbResult = await _repo.GetByIdAsync(rec2del.OfferRowID); + if (dbResult == null) return false; + + bool success = await _repo.DeleteAsync(dbResult); + + if (success) + { + await ClearCacheAsync($"{_redisBaseKey}:Offer:*"); + await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); + } + + return success; + }); + } + + /// + /// Effettua fix UID righe child del temoplate indicato e restituisce elenco UID da chiamare x refresh + /// + /// Key + /// + public async Task> FixUidAsync(int offerId) + { + return await TraceAsync($"{_className}.FixUid", async (activity) => + { + List result = new List(); + + // 1. Recupero righe + var rows = await _repo.GetByParentAsync(offerId); + if (rows == null) + return result; + + // 2. Trovo quelle da sistemare + var list2fix = rows + .Where(x => string.IsNullOrEmpty(x.OfferRowUID) || x.OfferRowUID != x.OfferRowDtx) + .ToList(); + + // 3. Se non c’è nulla da fare → ritorno + if (list2fix.Count == 0) + return result; + + // 4. Preparo la lista da restituire + result = list2fix + .Select(x => x.OfferRowDtx) + .ToList() ?? new List(); + + // 5. Aggiorno i record + foreach (var row in list2fix) + row.OfferRowUID = row.OfferRowDtx; + + // 6. Salvo + bool success = await _repo.SaveRowsAsync(list2fix); + + if (success) + { + await ClearCacheAsync($"{_redisBaseKey}:Offer:*"); + await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); + } + + return result; + }); + } + + /// + /// Effettua fix TipoImg righe child dell' Offer indicato + /// + /// Key + /// + public async Task FixImgTypeAsync(int offerId) + { + return await TraceAsync($"{_className}.FixImgType", async (activity) => + { + // 1. Recupero righe + var rows = await _repo.GetByParentAsync(offerId); + if (rows == null) return false; + + // 2. Trovo quelle da sistemare + var list2fix = rows + .Where(x => x.ImgType == ImageType.ND) + .ToList(); + + // 3. Se non c’è nulla da fare → ritorno + if (list2fix.Count == 0) + return false; + + + // 5. Aggiorno i record + foreach (var row in list2fix) + { + // se è calcolato il selling item --> img calcolata + if (row.SellingItemNav != null && (row.SellingItemNav.SourceType == ItemSourceType.Jwd || row.SellingItemNav.SourceType == ItemSourceType.FileBTL)) + { + row.ImgType = ImageType.Calculated; + } + } + + // 6. Salvo + bool success = await _repo.SaveRowsAsync(list2fix); + + if (success) + { + await ClearCacheAsync($"{_redisBaseKey}:Offer:*"); + await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); + } + + return true; + }); + } + + public async Task GetByUidAsync(string offerRowUid) + { + return await TraceAsync($"{_className}.GetByUid", async (activity) => + { + return await GetOrSetCacheAsync( + $"{_redisBaseKey}:{_className}:ByUid:{offerRowUid}", + async () => await _repo.GetByUidAsync(offerRowUid), + LongCache + ); + }); + } + + public async Task GetByIdAsync(int offerRowId) + { + return await TraceAsync($"{_className}.GetById", async (activity) => + { + return await GetOrSetCacheAsync( + $"{_redisBaseKey}:{_className}:ById:{offerRowId}", + async () => await _repo.GetByIdAsync(offerRowId), + LongCache + ); + }); + } + + /// + /// Elenco filtrato (parent) OfferRow da DB + /// + /// + /// + public async Task> GetByParentAsync(int offerId) + { + return await TraceAsync($"{_className}.GetByParent", async (activity) => + { + return await GetOrSetCacheAsync( + $"{_redisBaseKey}:{_className}:ByParent:{offerId}", + async () => await _repo.GetByParentAsync(offerId), + LongCache + ); + }); + } + + public async Task UpdateAwaitStateAsync(int OfferRowId, bool? awaitBom, bool? awaitPrice, bool flushCache = false) + { + return await TraceAsync($"{_className}.UpdateAwaitState", async (activity) => + { + var currRec = await _repo.GetByIdAsync(OfferRowId); + + if (currRec == null) + return false; + + //modalità vecchia + //if (awaitBom.HasValue) + // currRec.AwaitBom = awaitBom.Value; + + //if (awaitPrice.HasValue) + // currRec.AwaitPrice = awaitPrice.Value; + + currRec.AwaitBom = awaitBom ?? currRec.AwaitBom; + currRec.AwaitPrice = awaitPrice ?? currRec.AwaitPrice; + + activity?.SetTag("db.operation", "UPDATE"); + + bool success = await _repo.UpdateAsync(currRec); + + if (success && flushCache) + { + await ClearCacheAsync($"{_redisBaseKey}:Offer:*"); + await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); + } + + return success; + }); + } + + /// + /// Effettua update delle info legate al file per il Offer indicato + /// + /// Riga Offer coi dati da aggiornare + /// + public async Task UpdateFileDataAsync(OfferRowModel updRec) + { + return await TraceAsync($"{_className}.UpdateFileData", async (activity) => + { + var currRec = await _repo.GetByIdAsync(updRec.OfferRowID); + + if (currRec == null) + return false; + + currRec.FileName = updRec.FileName; + currRec.FileResource = updRec.FileResource; + currRec.FileSize = updRec.FileSize; + currRec.SerStruct = updRec.SerStruct; + + activity?.SetTag("db.operation", "UPDATE"); + + bool success = await _repo.UpdateAsync(currRec); + + if (success) + { + await ClearCacheAsync($"{_redisBaseKey}:Offer:*"); + await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); + } + + return success; + }); + } + + + /// + /// Effettua update del valore serializzato della Riga Offer + /// + /// ID Riga Offer da aggiornare + /// Serializzazione oggetto (es JWD) + /// + public async Task UpdateBomAsync(int OfferRowID, List newBomList) + { + return await TraceAsync($"{_className}.UpdateBom", async (activity) => + { + var currRec = await _repo.GetByIdAsync(OfferRowID); + if (currRec == null) + return false; + + var itemGroups = await _repo.GetItemGroupsAsync(); + var bomItems = await _repo.GetBomItemsAsync(); + + + // calcolo il NUOVO costo e lo aggiorno... + double totCost = 0; + double totPrice = 0; + int totItemQty = 0; + int numGroupOk = 0; + int numItemOk = 0; + int numElems = newBomList.Count; + // validazione e completamento BOM + BomCalculator.Validate(itemGroups, bomItems, ref newBomList, null, ref totCost, ref totPrice, ref totItemQty, ref numGroupOk, ref numItemOk); + // salvo BOM... + string itemBom = JsonConvert.SerializeObject(newBomList); + currRec.ItemBOM = itemBom; + // salvo arrotondato alla 3° decimale + currRec.BomCost = Math.Round(totCost, 3); + currRec.BomPrice = Math.Round(totPrice, 3); + currRec.BomOk = numElems == numGroupOk; + currRec.ItemOk = numElems == numItemOk; + currRec.ProdItemQty = totItemQty; + + activity?.SetTag("db.operation", "UPDATE"); + + bool success = await _repo.UpdateAsync(currRec); + + if (success) + { + await ClearCacheAsync($"{_redisBaseKey}:Offer:*"); + await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); + } + + return success; + }); + } + + /// + /// Effettua update del valore serializzato della Riga Offer + /// + /// ID Riga Offer da aggiornare + /// Serializzazione oggetto (es JWD) + /// + public async Task UpdateSerStructAsync(int OfferRowID, string serStruct) + { + return await TraceAsync($"{_className}.UpdateSerStruct", async (activity) => + { + var currRec = await _repo.GetByIdAsync(OfferRowID); + + if (currRec == null) + return false; + + currRec.SerStruct = serStruct; + + activity?.SetTag("db.operation", "UPDATE"); + + bool success = await _repo.UpdateAsync(currRec); + + if (success) + { + await ClearCacheAsync($"{_redisBaseKey}:Offer:*"); + await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); + } + + return success; + }); + } + + /// + /// Upsert record OfferRow + /// + /// + /// + public async Task UpsertAsync(OfferRowModel upsRec) + { + return await TraceAsync($"{_className}.Upsert", async (activity) => + { + var currRec = await _repo.GetByIdAsync(upsRec.OfferRowID); + + string operation = "UPDATE"; + bool success = false; + + if (currRec != null) + { + success = await _repo.UpdateAsync(upsRec); + } + else + { + operation = "INSERT"; + success = await _repo.AddAsync(upsRec); + } + + activity?.SetTag("db.operation", operation); + + if (success) + { + await ClearCacheAsync($"{_redisBaseKey}:Offer:*"); + await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); + } + + return success; + }); + } + + #endregion Public Methods + + #region Private Fields + + private readonly string _className; + private readonly IOfferRowRepository _repo; + + #endregion Private Fields + } +} diff --git a/Lux.API/Lux.API.csproj b/Lux.API/Lux.API.csproj index 2e7592c..d9e481b 100644 --- a/Lux.API/Lux.API.csproj +++ b/Lux.API/Lux.API.csproj @@ -4,7 +4,7 @@ net8.0 enable enable - 1.1.2603.1718 + 1.1.2603.1719 diff --git a/Lux.UI/Lux.UI.csproj b/Lux.UI/Lux.UI.csproj index b86bd3d..f598ff9 100644 --- a/Lux.UI/Lux.UI.csproj +++ b/Lux.UI/Lux.UI.csproj @@ -5,7 +5,7 @@ enable enable aspnet-Lux.UI-a758c101-a2f4-4e38-977d-1c4887dbbd50 - 1.1.2603.1718 + 1.1.2603.1719 diff --git a/Resources/ChangeLog.html b/Resources/ChangeLog.html index 11569c6..ad814d6 100644 --- a/Resources/ChangeLog.html +++ b/Resources/ChangeLog.html @@ -1,6 +1,6 @@ LUX - Web Windows MES -

Versione: 1.1.2603.1718

+

Versione: 1.1.2603.1719


Note di rilascio:
  • diff --git a/Resources/VersNum.txt b/Resources/VersNum.txt index a47d7f5..c660cc3 100644 --- a/Resources/VersNum.txt +++ b/Resources/VersNum.txt @@ -1 +1 @@ -1.1.2603.1718 +1.1.2603.1719 diff --git a/Resources/manifest.xml b/Resources/manifest.xml index 0bfae75..6643fe0 100644 --- a/Resources/manifest.xml +++ b/Resources/manifest.xml @@ -1,6 +1,6 @@ - 1.1.2603.1718 + 1.1.2603.1719 http://nexus.steamware.net/repository/SWS/GPW/stable/GPW.UI.zip http://nexus.steamware.net/repository/SWS/GPW/stable/ChangeLog.html false