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