namespace EgwCoreLib.Lux.Data.Services.Sales { public class OrderRowService : BaseServ, IOrderRowService { #region Public Constructors public OrderRowService( IConfiguration config, IConnectionMultiplexer redis, IOrderRowRepository repo) : base(config, redis) { _className = "OrderRow"; _repo = repo; } #endregion Public Constructors #region Public Methods /// public async Task DeleteAsync(OrderRowModel rec2del) { return await TraceAsync($"{_className}.Delete", async (activity) => { var dbResult = await _repo.GetByIdAsync(rec2del.OrderRowID); if (dbResult == null) return false; bool success = await _repo.DeleteAsync(dbResult); if (success) { await ClearCacheAsync($"{_redisBaseKey}:Order:*"); await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); } return success; }); } /// public async Task FixImgTypeAsync(int OrderId) { return await TraceAsync($"{_className}.FixImgType", async (activity) => { // 1. Recupero righe var rows = await _repo.GetByParentAsync(OrderId); 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}:Order:*"); await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); } return true; }); } /// public async Task> FixUidAsync(int OrderId) { return await TraceAsync($"{_className}.FixUid", async (activity) => { List result = new List(); // 1. Recupero righe var rows = await _repo.GetByParentAsync(OrderId); if (rows == null) return result; // 2. Trovo quelle da sistemare var list2fix = rows .Where(x => string.IsNullOrEmpty(x.OrderRowUID) || x.OrderRowUID != x.OrderRowCode) .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.OrderRowCode) .ToList() ?? new List(); // 5. Aggiorno i record foreach (var row in list2fix) row.OrderRowUID = row.OrderRowCode; // 6. Salvo bool success = await _repo.SaveRowsAsync(list2fix); if (success) { await ClearCacheAsync($"{_redisBaseKey}:Order:*"); await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); } return result; }); } /// public async Task GetByIdAsync(int OrderRowId) { return await TraceAsync($"{_className}.GetById", async (activity) => { return await GetOrSetCacheAsync( $"{_redisBaseKey}:{_className}:ById:{OrderRowId}", async () => await _repo.GetByIdAsync(OrderRowId), LongCache ); }); } /// public async Task> GetByParentAsync(int OrderId) { return await TraceAsync($"{_className}.GetByParent", async (activity) => { return await GetOrSetCacheAsync( $"{_redisBaseKey}:{_className}:ByParent:{OrderId}", async () => await _repo.GetByParentAsync(OrderId), LongCache ); }); } /// public async Task> GetByStateAsync(OrderStates reqState, DateTime dtStart, DateTime dtEnd) { return await TraceAsync($"{_className}.GetByState", async (activity) => { return await GetOrSetCacheAsync( $"{_redisBaseKey}:{_className}:ByState:{reqState}:{dtStart:yyyy-MM-dd}:{dtEnd:yyyy-MM-dd}", async () => await _repo.GetByStateAsync(reqState, dtStart, dtEnd), LongCache ); }); } /// public async Task> GetByStateMinAsync(OrderStates reqState, DateTime dtStart, DateTime dtEnd) { return await TraceAsync($"{_className}.GetByStateMin", async (activity) => { return await GetOrSetCacheAsync( $"{_redisBaseKey}:{_className}:ByStateMin:{reqState}:{dtStart:yyyy-MM-dd}:{dtEnd:yyyy-MM-dd}", async () => await _repo.GetByStateMinAsync(reqState, dtStart, dtEnd), LongCache ); }); } /// public async Task GetByUidAsync(string OrderRowUid) { return await TraceAsync($"{_className}.GetByUid", async (activity) => { return await GetOrSetCacheAsync( $"{_redisBaseKey}:{_className}:ByUid:{OrderRowUid}", async () => await _repo.GetByUidAsync(OrderRowUid), LongCache ); }); } /// public async Task UpdateAwaitStateAsync(int OrderRowId, bool? awaitBom, bool? awaitPrice, bool flushCache = false) { return await TraceAsync($"{_className}.UpdateAwaitState", async (activity) => { var currRec = await _repo.GetByIdAsync(OrderRowId); if (currRec == null) return false; 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}:Order:*"); await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); } return success; }); } /// public async Task UpdateBomAsync(int OrderRowID, List newBomList) { return await TraceAsync($"{_className}.UpdateBom", async (activity) => { var currRec = await _repo.GetByIdAsync(OrderRowID); 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; // setto ok await di BOM e Price currRec.AwaitBom = false; currRec.AwaitPrice = false; currRec.ProdItemQty = totItemQty; activity?.SetTag("db.operation", "UpdateBomById"); bool success = await _repo.UpdateAsync(currRec); if (success) { await ClearCacheAsync($"{_redisBaseKey}:Order:*"); await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); } return success; }); } /// public async Task UpdateBomAsync(string uID, List newBomList) { return await TraceAsync($"{_className}.UpdateBom", async (activity) => { var currRec = await _repo.GetByUidAsync(uID); 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; // setto ok await di BOM e Price currRec.AwaitBom = false; currRec.AwaitPrice = false; currRec.ProdItemQty = totItemQty; activity?.SetTag("db.operation", "UpdateBomByUid"); bool success = await _repo.UpdateAsync(currRec); if (success) { await ClearCacheAsync($"{_redisBaseKey}:Order:*"); await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); } return success; }); } /// public async Task UpdateFileDataAsync(OrderRowModel updRec) { return await TraceAsync($"{_className}.UpdateFileData", async (activity) => { var currRec = await _repo.GetByIdAsync(updRec.OrderRowID); 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}:Order:*"); await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); } return success; }); } /// public async Task UpdateSerStructAsync(int OrderRowID, string serStruct) { return await TraceAsync($"{_className}.UpdateSerStruct", async (activity) => { var currRec = await _repo.GetByIdAsync(OrderRowID); if (currRec == null) return false; currRec.SerStruct = serStruct; activity?.SetTag("db.operation", "UPDATE"); bool success = await _repo.UpdateAsync(currRec); if (success) { await ClearCacheAsync($"{_redisBaseKey}:Order:*"); await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); } return success; }); } /// public async Task UpdateStateAsync(int orderRowID, OrderStates reqState) { return await TraceAsync($"{_className}.UpdateState", async (activity) => { var currRec = await _repo.GetByIdAsync(orderRowID); if (currRec == null) return false; currRec.OrderRowState = reqState; activity?.SetTag("db.operation", "UPDATE"); bool success = await _repo.UpdateAsync(currRec); if (success) { await ClearCacheAsync($"{_redisBaseKey}:Order:*"); await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); } return success; }); } public async Task ValidateAsync(List list2chk) { return await TraceAsync($"{_className}.Validate", async (activity) => { activity?.SetTag("db.operation", "Validate"); var success = await _repo.ValidateAsync(list2chk); await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); await ClearCacheAsync($"{_redisBaseKey}:Order:*"); await ClearCacheAsync($"{_redisBaseKey}:Orders:*"); await ClearCacheAsync($"{_redisBaseKey}:OrderRowsByState:*"); return success; }); } /// public async Task UpsertAsync(OrderRowModel upsRec) { return await TraceAsync($"{_className}.Upsert", async (activity) => { OrderRowModel? currRec = await _repo.GetByIdAsync(upsRec.OrderRowID); 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) { // sistemo UID... await FixUidAsync(upsRec.OrderID); await FixImgTypeAsync(upsRec.OrderID); currRec = await _repo.GetByIdAsync(upsRec.OrderRowID); } else { // svuoto comunque cache... await ClearCacheAsync($"{_redisBaseKey}:Order:*"); await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); } return currRec; }); } /// public async Task SaveProdEstAsync(string uID, string prodEstim) { return await TraceAsync($"{_className}.UpsertProdEst", async (activity) => { activity?.SetTag("db.operation", "UpsertProdEst"); var success = await _repo.SaveProdEstAsync(uID, prodEstim); await ClearCacheAsync($"{_redisBaseKey}:{_className}:*"); return success; }); } #endregion Public Methods #region Private Fields private readonly string _className; private readonly IOrderRowRepository _repo; #endregion Private Fields } }