namespace EgwCoreLib.Lux.Data.Repository.Sales { public class OfferRepository : BaseRepository, IOfferRepository { #region Public Constructors public OfferRepository(IDbContextFactory ctxFactory) : base(ctxFactory) { } #endregion Public Constructors #region Public Methods /// public async Task AddAsync(OfferModel entity) { await using var dbCtx = await CreateContextAsync(); await dbCtx.DbSetOffer.AddAsync(entity); return await dbCtx.SaveChangesAsync() > 0; } /// public async Task CheckExpiredAsync() { await using var dbCtx = await CreateContextAsync(); DateTime adesso = DateTime.Now; // recupero offerta... var listExpired = await dbCtx .DbSetOffer .Where(x => x.ValidUntil < adesso && x.OffertState == OfferStates.Open) .ToListAsync(); // se trovo le aggiorno come stato if (listExpired != null) { foreach (var item in listExpired) { item.OffertState = OfferStates.Expired; dbCtx.Entry(item).State = EntityState.Modified; } // salvo TUTTI i cambiamenti... return await dbCtx.SaveChangesAsync() > 0; } else { return false; } } /// public async Task CloneAsync(OfferModel rec2clone) { await using var dbCtx = await CreateContextAsync(); // Wrap in transaction for atomicity (parent + children clone) await using var tx = await dbCtx.Database.BeginTransactionAsync(); try { DateTime now = DateTime.Now; var currRec = await dbCtx.DbSetOffer .Include(x => x.OfferRowNav) .FirstOrDefaultAsync(x => x.OfferID == rec2clone.OfferID); if (currRec == null) return false; DateTime adesso = DateTime.Now; var lastRec = dbCtx .DbSetOffer .Where(x => x.RefYear == adesso.Year) .OrderByDescending(x => x.RefNum) .FirstOrDefault(); int newRefNum = lastRec != null ? lastRec.RefNum + 1 : 1; // 2. Creo il nuovo parent var newRec = new OfferModel() { ConsNote = rec2clone.ConsNote, CustomerID = rec2clone.CustomerID, DealerID = rec2clone.DealerID, Description = rec2clone.Description, DictPresel = rec2clone.DictPresel, Discount = rec2clone.Discount, DueDateProm = rec2clone.DueDateProm, DueDateReq = rec2clone.DueDateReq, Envir = rec2clone.Envir, Inserted = adesso, Modified = adesso, OffertState = OfferStates.Open, RefNum = newRefNum, RefRev = 1, RefYear = adesso.Year, ValidUntil = currRec.ValidUntil }; // 3. Clono i child // sistemo child... newRec.OfferRowNav = currRec.OfferRowNav .Select(c => new OfferRowModel() { AwaitBom = c.AwaitBom, AwaitPrice = c.AwaitPrice, BomCost = c.BomCost, BomOk = c.BomOk, BomPrice = c.BomPrice, Envir = c.Envir, FileName = c.FileName, FileResource = c.FileResource, FileSize = c.FileSize, Inserted = adesso, ItemBOM = c.ItemBOM, ItemJCD = c.ItemJCD, ItemOk = c.ItemOk, ItemSteps = c.ItemSteps, ItemTags = c.ItemTags, JobID = c.JobID, Modified = c.Modified, Note = c.Note, ProdItemQty = c.ProdItemQty, Qty = c.Qty, RowNum = c.RowNum, SellingItemID = c.SellingItemID, SerStruct = c.SerStruct, StepCost = c.StepCost, StepFlowTime = c.StepFlowTime, StepLeadTime = c.StepLeadTime, StepPrice = c.StepPrice, //OrderID = dbRec.OrderID, OfferRowUID = c.OfferRowDtx }) .ToList(); // 4. Aggiungo il nuovo parent (EF aggiunge anche i child) dbCtx.DbSetOffer.Add(newRec); // 5. Salvo tutto in transazione await dbCtx.SaveChangesAsync(); await tx.CommitAsync(); return true; } catch { await tx.RollbackAsync(); throw; } } /// public async Task DeleteAsync(OfferModel entity) { await using var dbCtx = await CreateContextAsync(); dbCtx.DbSetOffer.Remove(entity); return await dbCtx.SaveChangesAsync() > 0; } /// public async Task> GetAllAsync() { await using var dbCtx = await CreateContextAsync(); return await dbCtx.DbSetOffer .Include(c => c.CustomerNav) .Include(d => d.DealerNav) .Include(o => o.OfferRowNav) .AsNoTracking() .ToListAsync(); } /// public async Task> GetBomItemsAsync() { await using var dbCtx = await CreateContextAsync(); return await dbCtx.DbSetItem .Where(x => x.ItemType == ItemClassType.Bom || x.ItemType == ItemClassType.BomAlt) .ToListAsync(); } /// public async Task GetByIdAsync(int recId) { await using var dbCtx = await CreateContextAsync(); return await dbCtx .DbSetOffer .Where(x => x.OfferID == recId) .Include(c => c.CustomerNav) .Include(d => d.DealerNav) .Include(o => o.OfferRowNav) .ThenInclude(s => s.SellingItemNav) .FirstOrDefaultAsync(); } /// public async Task> GetFiltAsync(DateTime inizio, DateTime fine) { await using var dbCtx = await CreateContextAsync(); return await dbCtx.DbSetOffer .Where(x => x.Inserted >= inizio && x.Inserted <= fine) .Include(c => c.CustomerNav) .Include(d => d.DealerNav) .Include(o => o.OfferRowNav) .AsNoTracking() .ToListAsync(); } /// public async Task> GetItemGroupsAsync() { await using var dbCtx = await CreateContextAsync(); return await dbCtx.DbSetItemGroup.ToListAsync(); } /// public async Task> GetRowsAsync(int recId) { await using var dbCtx = await CreateContextAsync(); return await dbCtx.DbSetOfferRow .Where(x => x.OfferID == recId) .ToListAsync(); } /// public async Task SaveRowsAsync(List rows) { // Add validation for null or empty list if (rows == null || rows.Count == 0) return false; await using var dbCtx = await CreateContextAsync(); // Wrap in transaction for atomicity (batch update multiple rows) await using var tx = await dbCtx.Database.BeginTransactionAsync(); try { foreach (var row in rows) dbCtx.Entry(row).State = EntityState.Modified; bool done = await dbCtx.SaveChangesAsync() > 0; if (done) await tx.CommitAsync(); return done; } catch { await tx.RollbackAsync(); throw; } } /// public async Task UpdateAsync(OfferModel entity) { await using var dbCtx = await CreateContextAsync(); // Recuperiamo l'entità tracciata dal context var trackedEntity = await dbCtx.DbSetOffer.FirstOrDefaultAsync(x => x.OfferID == entity.OfferID); if (trackedEntity != null) { // verifico eventuale riapertura SE fosse expired ma la data è valida... if (trackedEntity.OffertState == OfferStates.Expired && entity.ValidUntil > DateTime.Today) { entity.OffertState = OfferStates.Open; } // Aggiorna i valori dell'entità tracciata con quelli della nuova dbCtx.Entry(trackedEntity).CurrentValues.SetValues(entity); } else { dbCtx.DbSetOffer.Update(entity); } return await dbCtx.SaveChangesAsync() > 0; } #endregion Public Methods } }