namespace EgwCoreLib.Lux.Data.Repository.Sales { public class OrderRepository : BaseRepository, IOrderRepository { #region Public Constructors public OrderRepository(IDbContextFactory ctxFactory) : base(ctxFactory) { } #endregion Public Constructors #region Public Methods /// public async Task AddAsync(OrderModel entity) { await using var dbCtx = await CreateContextAsync(); await dbCtx.DbSetOrder.AddAsync(entity); return await dbCtx.SaveChangesAsync() > 0; } /// public async Task CloneOfferAsync(OfferModel rec2clone) { OrderModel? newRec = null; await using var dbCtx = await CreateContextAsync(); // avvio transazione 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 null; DateTime adesso = DateTime.Now; var lastRec = dbCtx .DbSetOrder .Where(x => x.RefYear == adesso.Year) .OrderByDescending(x => x.RefNum) .FirstOrDefault(); int newRefNum = lastRec != null ? lastRec.RefNum + 1 : 1; // 2. Creo il nuovo parent newRec = new OrderModel() { 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, OfferID = rec2clone.OfferID, OrderState = OrderStates.Created, RefNum = newRefNum, RefRev = 1, RefYear = adesso.Year, ValidUntil = currRec.ValidUntil }; // 3. Clono i child // sistemo child... newRec.OrderRowNav = currRec.OfferRowNav .Select(c => new OrderRowModel() { 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 = adesso, 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, ImgType = c.ImgType }) .ToList(); // 4. Aggiungo il nuovo parent (EF aggiunge anche i child) dbCtx.DbSetOrder.Add(newRec); // 5. Salvo tutto var numSave = await dbCtx.SaveChangesAsync(); // se ok sistemo UID... if (numSave > 0 && newRec != null) { // sistemo UID... foreach (var item in newRec.OrderRowNav) { item.OrderRowUID = item.OrderRowCode; // alternativa da valutare.. if (false) { // genero tanti record collegati alla riga d'ordine... for (int i = 0; i < item.ProdItemQtyTot; i++) { var child = new ProductionItemModel { OrderRowID = item.OrderRowID, //OrderRowNav = item, ItemCode = i + 1, ExtItemCode = $"{item.OrderRowCode}-{i + 1:000}", ProdBatchID = null }; // aggiungo record item.ProdItemNav.Add(child); } } else { item.ProdItemNav = Enumerable.Range(1, (int)item.ProdItemQtyTot) .Select(i => new ProductionItemModel { //OrderRowID = item.OrderRowID, OrderRowNav = item, ItemCode = i, ExtItemCode = $"{item.OrderRowCode}-{i:000}", ProdBatchID = null, ProdItemTag = null //nullo e POI verrà sistemato }) .ToList(); } dbCtx.Entry(item).State = EntityState.Modified; } // salvo ulteriori variazioni await dbCtx.SaveChangesAsync(); // tutti gli ordini e anno corrente... await dbCtx.Database.ExecuteSqlRawAsync("CALL stp_ProdItem_UpdateProdItemTag(0,0);"); // committo in un unica transazione (da provare!!!) await tx.CommitAsync(); } } catch { await tx.RollbackAsync(); throw; } return newRec; } /// public async Task DeleteAsync(OrderModel entity) { await using var dbCtx = await CreateContextAsync(); dbCtx.DbSetOrder.Remove(entity); return await dbCtx.SaveChangesAsync() > 0; } /// public async Task> GetAllAsync() { await using var dbCtx = await CreateContextAsync(); return await dbCtx.DbSetOrder .Include(c => c.CustomerNav) .Include(d => d.DealerNav) .Include(o => o.OrderRowNav) .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.DbSetOrder .Where(x => x.OrderID == recId) .Include(c => c.CustomerNav) .Include(d => d.DealerNav) .Include(o => o.OrderRowNav) .ThenInclude(s => s.SellingItemNav) .FirstOrDefaultAsync(); } /// public async Task> GetFiltAsync(DateTime inizio, DateTime fine) { await using var dbCtx = await CreateContextAsync(); return await dbCtx.DbSetOrder .Where(x => x.Inserted >= inizio && x.Inserted <= fine) .Include(c => c.CustomerNav) .Include(d => d.DealerNav) .Include(o => o.OrderRowNav) .ThenInclude(s => s.SellingItemNav) .Include(o => o.OrderRowNav) .ThenInclude(s => s.MatReqNav) .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.DbSetOrderRow .Where(x => x.OrderID == 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(OrderModel entity) { await using var dbCtx = await CreateContextAsync(); // Recuperiamo l'entità tracciata dal context var trackedEntity = await dbCtx.DbSetOrder.FirstOrDefaultAsync(x => x.OrderID == entity.OrderID); if (trackedEntity != null) { // Aggiorna i valori dell'entità tracciata con quelli della nuova dbCtx.Entry(trackedEntity).CurrentValues.SetValues(entity); } else { dbCtx.DbSetOrder.Update(entity); } return await dbCtx.SaveChangesAsync() > 0; } #endregion Public Methods } }