Implementazione testata ordini
This commit is contained in:
@@ -294,293 +294,6 @@ namespace EgwCoreLib.Lux.Data.Controllers
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Esegue il cloning completo di un offerta e di TUTTE le relative righe di offerta...
|
||||
/// </summary>
|
||||
/// <param name="rec2clone"></param>
|
||||
/// <returns></returns>
|
||||
internal async Task<bool> OfferClone(OfferModel rec2clone)
|
||||
{
|
||||
bool answ = false;
|
||||
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
||||
using (DataLayerContext dbCtx = new DataLayerContext())
|
||||
{
|
||||
try
|
||||
{
|
||||
DateTime adesso = DateTime.Now;
|
||||
// recupero offerta...
|
||||
var currRec = dbCtx
|
||||
.DbSetOffer
|
||||
.Where(x => x.OfferID == rec2clone.OfferID)
|
||||
.Include(x => x.OfferRowNav)
|
||||
.FirstOrDefault();
|
||||
|
||||
// ultimo record OFFERTA x calcolo refNum
|
||||
var lastRec = dbCtx
|
||||
.DbSetOffer
|
||||
.Where(x => x.RefYear == adesso.Year)
|
||||
.OrderByDescending(x => x.RefNum)
|
||||
.FirstOrDefault();
|
||||
int newRefNum = lastRec != null ? lastRec.RefNum + 1 : 1;
|
||||
|
||||
// se trovo --> duplico!
|
||||
if (currRec != null)
|
||||
{
|
||||
// recupero ultimo num offerta dell'anno corrente...
|
||||
OfferModel 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
|
||||
};
|
||||
|
||||
// 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();
|
||||
|
||||
// infine aggiungo riga ordine e relativi child
|
||||
dbCtx.DbSetOffer.Add(newRec);
|
||||
}
|
||||
|
||||
// salvo TUTTI i cambiamenti...
|
||||
var result = await dbCtx.SaveChangesAsync();
|
||||
answ = result > 0;
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Log.Error($"Eccezione durante OfferClone{Environment.NewLine}{exc}");
|
||||
}
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco completo offerte da DB
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal async Task<List<OfferModel>> OfferGetAll()
|
||||
{
|
||||
List<OfferModel> dbResult = new List<OfferModel>();
|
||||
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
||||
using (DataLayerContext dbCtx = new DataLayerContext())
|
||||
{
|
||||
try
|
||||
{
|
||||
dbResult = await dbCtx
|
||||
.DbSetOffer
|
||||
.Include(c => c.CustomerNav)
|
||||
.Include(d => d.DealerNav)
|
||||
.Include(o => o.OfferRowNav)
|
||||
.ToListAsync();
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Log.Error($"Eccezione durante OfferGetAll{Environment.NewLine}{exc}");
|
||||
}
|
||||
}
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco offerte da DB filtrate x periodo e stato
|
||||
/// </summary>
|
||||
/// <param name="inizio"></param>
|
||||
/// <param name="fine"></param>
|
||||
/// <returns></returns>
|
||||
internal async Task<List<OfferModel>> OfferGetFilt(DateTime inizio, DateTime fine)
|
||||
{
|
||||
List<OfferModel> dbResult = new List<OfferModel>();
|
||||
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
||||
using (DataLayerContext dbCtx = new DataLayerContext())
|
||||
{
|
||||
try
|
||||
{
|
||||
dbResult = await dbCtx
|
||||
.DbSetOffer
|
||||
.Where(x => x.Inserted >= inizio && x.Inserted <= fine)
|
||||
.Include(c => c.CustomerNav)
|
||||
.Include(d => d.DealerNav)
|
||||
.Include(o => o.OfferRowNav)
|
||||
.ToListAsync();
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Log.Error($"Eccezione durante OfferGetFilt{Environment.NewLine}{exc}");
|
||||
}
|
||||
}
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua update dei costi di tutte le righe dell'offerta indicata
|
||||
/// </summary>
|
||||
/// <param name="OfferID"></param>
|
||||
/// <returns></returns>
|
||||
internal async Task<bool> OffertUpdateCost(int OfferID)
|
||||
{
|
||||
bool answ = false;
|
||||
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
||||
using (DataLayerContext dbCtx = new DataLayerContext())
|
||||
{
|
||||
try
|
||||
{
|
||||
// recupero righe offerta...
|
||||
var offRowList = dbCtx
|
||||
.DbSetOfferRow
|
||||
.Where(x => x.OfferID == OfferID)
|
||||
.ToList();
|
||||
|
||||
// recupero l'elenco degli itemGroup gestiti
|
||||
var itemGroupList = dbCtx
|
||||
.DbSetItemGroup
|
||||
.ToList();
|
||||
|
||||
// recupero il subset item da BOM / BomAlt...
|
||||
var bomGenList = dbCtx
|
||||
.DbSetItem
|
||||
.Where(x => (x.ItemType == Core.Enums.ItemClassType.Bom || x.ItemType == Core.Enums.ItemClassType.BomAlt))
|
||||
.ToList();
|
||||
|
||||
// ciclo!
|
||||
foreach (var currRec in offRowList)
|
||||
{
|
||||
// se contiene qualcosa x BOM...
|
||||
if (!string.IsNullOrEmpty(currRec.ItemBOM) && currRec.ItemBOM.Length > 2)
|
||||
{
|
||||
// deserializzo
|
||||
var bomList = JsonConvert.DeserializeObject<List<BomItemDTO>>(currRec.ItemBOM);
|
||||
// se ho trovato elementi...
|
||||
if (bomList != null)
|
||||
{
|
||||
// calcolo il NUOVO costo e lo aggiorno...
|
||||
double totCost = 0;
|
||||
double totPrice = 0;
|
||||
int totItemQty = 0;
|
||||
int numGroupOk = 0;
|
||||
int numItemOk = 0;
|
||||
int numElems = bomList.Count;
|
||||
// validazione e completamento BOM
|
||||
BomCalculator.Validate(itemGroupList, bomGenList, ref bomList, null, ref totCost, ref totPrice, ref totItemQty, ref numGroupOk, ref numItemOk);
|
||||
// salvo BOM...
|
||||
string itemBom = JsonConvert.SerializeObject(bomList);
|
||||
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;
|
||||
dbCtx.Entry(currRec).State = EntityState.Modified;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// salvo TUTTI i cambiamenti...
|
||||
var result = await dbCtx.SaveChangesAsync();
|
||||
answ = result > 0;
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Log.Error($"Eccezione durante OffertUpdateCost{Environment.NewLine}{exc}");
|
||||
}
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add record offerta
|
||||
/// </summary>
|
||||
/// <param name="updRec"></param>
|
||||
/// <returns></returns>
|
||||
internal async Task<bool> OffertUpsert(OfferModel updRec)
|
||||
{
|
||||
bool answ = false;
|
||||
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
||||
using (DataLayerContext dbCtx = new DataLayerContext())
|
||||
{
|
||||
try
|
||||
{
|
||||
// recupero offerta...
|
||||
var currRec = dbCtx
|
||||
.DbSetOffer
|
||||
.Where(x => x.OfferID == updRec.OfferID)
|
||||
.FirstOrDefault();
|
||||
|
||||
// se non trovo aggiungo
|
||||
if (currRec == null)
|
||||
{
|
||||
dbCtx.DbSetOffer.Add(updRec);
|
||||
}
|
||||
// altrimenti aggiorno
|
||||
else
|
||||
{
|
||||
// verifico eventuale riapertura SE fosse expired ma la data è valida...
|
||||
if (currRec.OffertState == OfferStates.Expired && updRec.ValidUntil > DateTime.Today)
|
||||
{
|
||||
updRec.OffertState = OfferStates.Open;
|
||||
}
|
||||
dbCtx.Entry(currRec).CurrentValues.SetValues(updRec);
|
||||
}
|
||||
|
||||
// salvo TUTTI i cambiamenti...
|
||||
var result = await dbCtx.SaveChangesAsync();
|
||||
answ = result > 0;
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Log.Error($"Eccezione durante OffertUpsert{Environment.NewLine}{exc}");
|
||||
}
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Recupera da DB riga offerta dato Primary ID
|
||||
/// </summary>
|
||||
@@ -1126,6 +839,7 @@ namespace EgwCoreLib.Lux.Data.Controllers
|
||||
return answ;
|
||||
}
|
||||
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Restituisce record ordine + righe Ordine dato ID
|
||||
/// </summary>
|
||||
@@ -1303,7 +1017,7 @@ namespace EgwCoreLib.Lux.Data.Controllers
|
||||
catch (Exception exc)
|
||||
{
|
||||
await transaction.RollbackAsync();
|
||||
Log.Error($"Eccezione durante OrderFromOffer{Environment.NewLine}{exc}");
|
||||
Log.Error($"Eccezione durante CloneOfferAsync{Environment.NewLine}{exc}");
|
||||
}
|
||||
}
|
||||
return newRec;
|
||||
@@ -1339,6 +1053,49 @@ namespace EgwCoreLib.Lux.Data.Controllers
|
||||
return dbResult;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add record
|
||||
/// </summary>
|
||||
/// <param name="updRec"></param>
|
||||
/// <returns></returns>
|
||||
internal async Task<bool> OrderUpsert(OrderModel updRec)
|
||||
{
|
||||
bool answ = false;
|
||||
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
||||
using (DataLayerContext dbCtx = new DataLayerContext())
|
||||
{
|
||||
try
|
||||
{
|
||||
// recupero offerta...
|
||||
var currRec = dbCtx
|
||||
.DbSetOrder
|
||||
.Where(x => x.OrderID == updRec.OrderID)
|
||||
.FirstOrDefault();
|
||||
|
||||
// se non trovo aggiungo
|
||||
if (currRec == null)
|
||||
{
|
||||
dbCtx.DbSetOrder.Add(updRec);
|
||||
}
|
||||
// altrimenti aggiorno
|
||||
else
|
||||
{
|
||||
dbCtx.Entry(currRec).CurrentValues.SetValues(updRec);
|
||||
}
|
||||
|
||||
// salvo TUTTI i cambiamenti...
|
||||
var result = await dbCtx.SaveChangesAsync();
|
||||
answ = result > 0;
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Log.Error($"Eccezione durante OrderUpsert{Environment.NewLine}{exc}");
|
||||
}
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Elimina riga e sposta eventuali righe successive...
|
||||
/// </summary>
|
||||
@@ -1957,47 +1714,6 @@ namespace EgwCoreLib.Lux.Data.Controllers
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add record
|
||||
/// </summary>
|
||||
/// <param name="updRec"></param>
|
||||
/// <returns></returns>
|
||||
internal async Task<bool> OrderUpsert(OrderModel updRec)
|
||||
{
|
||||
bool answ = false;
|
||||
//using (DataLayerContext dbCtx = new DataLayerContext(_config))
|
||||
using (DataLayerContext dbCtx = new DataLayerContext())
|
||||
{
|
||||
try
|
||||
{
|
||||
// recupero offerta...
|
||||
var currRec = dbCtx
|
||||
.DbSetOrder
|
||||
.Where(x => x.OrderID == updRec.OrderID)
|
||||
.FirstOrDefault();
|
||||
|
||||
// se non trovo aggiungo
|
||||
if (currRec == null)
|
||||
{
|
||||
dbCtx.DbSetOrder.Add(updRec);
|
||||
}
|
||||
// altrimenti aggiorno
|
||||
else
|
||||
{
|
||||
dbCtx.Entry(currRec).CurrentValues.SetValues(updRec);
|
||||
}
|
||||
|
||||
// salvo TUTTI i cambiamenti...
|
||||
var result = await dbCtx.SaveChangesAsync();
|
||||
answ = result > 0;
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Log.Error($"Eccezione durante OrderUpsert{Environment.NewLine}{exc}");
|
||||
}
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco record Fasi da DB
|
||||
|
||||
@@ -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
|
||||
{
|
||||
@@ -8,14 +9,28 @@ namespace EgwCoreLib.Lux.Data.Repository.Sales
|
||||
|
||||
Task<bool> AddAsync(OrderModel entity);
|
||||
|
||||
Task<OrderModel?> CloneOfferAsync(OfferModel rec2clone);
|
||||
|
||||
Task<bool> DeleteAsync(OrderModel entity);
|
||||
|
||||
Task<List<OrderModel>> GetAllAsync();
|
||||
|
||||
Task<List<ItemModel>> GetBomItemsAsync();
|
||||
|
||||
Task<OrderModel?> GetByIdAsync(int recId);
|
||||
|
||||
Task<List<OrderModel>> GetFiltAsync(DateTime inizio, DateTime fine);
|
||||
|
||||
Task<List<ItemGroupModel>> GetItemGroupsAsync();
|
||||
|
||||
Task<List<OrderRowModel>> GetRowsAsync(int recId);
|
||||
|
||||
Task<bool> SaveRowsAsync(List<OrderRowModel> rows);
|
||||
|
||||
Task<bool> UpdateAsync(OrderModel entity);
|
||||
|
||||
Task<bool> UpdateCostAsync(int OrderID);
|
||||
|
||||
#endregion Public Methods
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,328 @@
|
||||
using EgwCoreLib.Lux.Core.RestPayload;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Items;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Production;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Sales;
|
||||
using EgwCoreLib.Lux.Data.Domains;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Newtonsoft.Json;
|
||||
using static EgwCoreLib.Lux.Core.Enums;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.Repository.Sales
|
||||
{
|
||||
public class OrderRepository : BaseRepository, IOrderRepository
|
||||
{
|
||||
#region Public Constructors
|
||||
|
||||
public OrderRepository(IDbContextFactory<DataLayerContext> ctxFactory) : base(ctxFactory)
|
||||
{
|
||||
}
|
||||
|
||||
#endregion Public Constructors
|
||||
|
||||
#region Public Methods
|
||||
|
||||
public async Task<bool> AddAsync(OrderModel entity)
|
||||
{
|
||||
await using var dbCtx = await CreateContextAsync();
|
||||
await dbCtx.DbSetOrder.AddAsync(entity);
|
||||
return await dbCtx.SaveChangesAsync() > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Esegue il cloning completo di un Offerta e di TUTTE le relative righe...
|
||||
/// </summary>
|
||||
/// <param name="rec2clone"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<OrderModel?> CloneOfferAsync(OfferModel rec2clone)
|
||||
{
|
||||
OrderModel? newRec = null;
|
||||
await using var dbCtx = await CreateContextAsync();
|
||||
// avvio transazione
|
||||
using var transaction = 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
|
||||
})
|
||||
.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 transaction.CommitAsync();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
await transaction.RollbackAsync();
|
||||
// sollevo exception
|
||||
throw;
|
||||
}
|
||||
return newRec;
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteAsync(OrderModel entity)
|
||||
{
|
||||
await using var dbCtx = await CreateContextAsync();
|
||||
dbCtx.DbSetOrder.Remove(entity);
|
||||
return await dbCtx.SaveChangesAsync() > 0;
|
||||
}
|
||||
|
||||
public async Task<List<OrderModel>> 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<List<ItemModel>> 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<OrderModel?> GetByIdAsync(int recId)
|
||||
{
|
||||
await using var dbCtx = await CreateContextAsync();
|
||||
return await dbCtx.DbSetOrder.FirstOrDefaultAsync(x => x.OrderID == recId);
|
||||
}
|
||||
|
||||
public async Task<List<OrderModel>> 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)
|
||||
.AsNoTracking()
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<List<ItemGroupModel>> GetItemGroupsAsync()
|
||||
{
|
||||
await using var dbCtx = await CreateContextAsync();
|
||||
return await dbCtx.DbSetItemGroup.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<List<OrderRowModel>> GetRowsAsync(int recId)
|
||||
{
|
||||
await using var dbCtx = await CreateContextAsync();
|
||||
return await dbCtx.DbSetOrderRow
|
||||
.Where(x => x.OrderID == recId)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<bool> SaveRowsAsync(List<OrderRowModel> rows)
|
||||
{
|
||||
await using var dbCtx = await CreateContextAsync();
|
||||
foreach (var row in rows)
|
||||
dbCtx.Entry(row).State = EntityState.Modified;
|
||||
|
||||
return await dbCtx.SaveChangesAsync() > 0;
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateAsync(OrderModel entity)
|
||||
{
|
||||
await using var dbCtx = await CreateContextAsync();
|
||||
// Recuperiamo l'entità tracciata dal context
|
||||
var trackedEntity = dbCtx.DbSetOrder.Local.FirstOrDefault(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;
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateCostAsync(int OrderID)
|
||||
{
|
||||
await using var dbCtx = await CreateContextAsync();
|
||||
|
||||
// recupero righe Orderta...
|
||||
var offRowList = await dbCtx
|
||||
.DbSetOrderRow
|
||||
.Where(x => x.OrderID == OrderID)
|
||||
.ToListAsync();
|
||||
|
||||
// recupero l'elenco degli itemGroup gestiti
|
||||
var itemGroupList = await dbCtx
|
||||
.DbSetItemGroup
|
||||
.ToListAsync();
|
||||
|
||||
// recupero il subset item da BOM / BomAlt...
|
||||
var bomGenList = await dbCtx
|
||||
.DbSetItem
|
||||
.Where(x => (x.ItemType == Core.Enums.ItemClassType.Bom || x.ItemType == Core.Enums.ItemClassType.BomAlt))
|
||||
.ToListAsync();
|
||||
|
||||
// ciclo!
|
||||
foreach (var currRec in offRowList)
|
||||
{
|
||||
// se contiene qualcosa x BOM...
|
||||
if (!string.IsNullOrEmpty(currRec.ItemBOM) && currRec.ItemBOM.Length > 2)
|
||||
{
|
||||
// deserializzo
|
||||
var bomList = JsonConvert.DeserializeObject<List<BomItemDTO>>(currRec.ItemBOM);
|
||||
// se ho trovato elementi...
|
||||
if (bomList != null)
|
||||
{
|
||||
// calcolo il NUOVO costo e lo aggiorno...
|
||||
double totCost = 0;
|
||||
double totPrice = 0;
|
||||
int totItemQty = 0;
|
||||
int numGroupOk = 0;
|
||||
int numItemOk = 0;
|
||||
int numElems = bomList.Count;
|
||||
// validazione e completamento BOM
|
||||
BomCalculator.Validate(itemGroupList, bomGenList, ref bomList, null, ref totCost, ref totPrice, ref totItemQty, ref numGroupOk, ref numItemOk);
|
||||
// salvo BOM...
|
||||
string itemBom = JsonConvert.SerializeObject(bomList);
|
||||
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;
|
||||
dbCtx.Entry(currRec).State = EntityState.Modified;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return await dbCtx.SaveChangesAsync() > 0;
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
}
|
||||
}
|
||||
@@ -316,154 +316,6 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
return result;
|
||||
}
|
||||
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Esegue clone completo dell'offerta indicata e svuota la cache
|
||||
/// </summary>
|
||||
/// <param name="rec2clone"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> OfferClone(OfferModel rec2clone)
|
||||
{
|
||||
using var activity = StartActivity();
|
||||
string source = "DB+REDIS";
|
||||
// calcolo
|
||||
bool fatto = await dbController.OfferClone(rec2clone);
|
||||
// svuoto cache...
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Offers:*");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OfferRows:*");
|
||||
activity?.SetTag("data.source", source);
|
||||
LogTrace($"{source} | trace: {activity?.TraceId} | {activity?.Duration.TotalMilliseconds}ms");
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco completo offerte da DB
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<OfferModel>> OfferGetAll()
|
||||
{
|
||||
using var activity = StartActivity();
|
||||
string source = "DB";
|
||||
List<OfferModel>? result = new List<OfferModel>();
|
||||
// cerco in redis...
|
||||
string currKey = $"{redisBaseKey}:Offers:ALL";
|
||||
RedisValue rawData = await _redisDb.StringGetAsync(currKey);
|
||||
//if (!string.IsNullOrEmpty($"{rawData}"))
|
||||
if (rawData.HasValue)
|
||||
{
|
||||
result = JsonConvert.DeserializeObject<List<OfferModel>>($"{rawData}");
|
||||
source = "REDIS";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await dbController.OfferGetAll();
|
||||
// serializzo e salvo con config x evitare loop...
|
||||
rawData = JsonConvert.SerializeObject(result, JSSettings);
|
||||
await _redisDb.StringSetAsync(currKey, rawData, LongCache);
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
result = new List<OfferModel>();
|
||||
}
|
||||
activity?.SetTag("data.source", source);
|
||||
LogTrace($"{source} | trace: {activity?.TraceId} | {activity?.Duration.TotalMilliseconds}ms");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco offerte da DB filtrate x periodo e stato
|
||||
/// </summary>
|
||||
/// <param name="inizio"></param>
|
||||
/// <param name="fine"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<List<OfferModel>> OfferGetFilt(DateTime inizio, DateTime fine)
|
||||
{
|
||||
using var activity = StartActivity();
|
||||
string source = "DB";
|
||||
List<OfferModel>? result = new List<OfferModel>();
|
||||
// cerco in redis...
|
||||
string currKey = $"{redisBaseKey}:Offers:Filt:{inizio:yyMMdd-HHmm}:{fine:yyMMdd-HHmm}";
|
||||
RedisValue rawData = await _redisDb.StringGetAsync(currKey);
|
||||
if (rawData.HasValue)
|
||||
{
|
||||
result = JsonConvert.DeserializeObject<List<OfferModel>>($"{rawData}");
|
||||
source = "REDIS";
|
||||
}
|
||||
else
|
||||
{
|
||||
result = await dbController.OfferGetFilt(inizio, fine);
|
||||
// serializzo e salvo con config x evitare loop...
|
||||
rawData = JsonConvert.SerializeObject(result, JSSettings);
|
||||
await _redisDb.StringSetAsync(currKey, rawData, LongCache);
|
||||
}
|
||||
if (result == null)
|
||||
{
|
||||
result = new List<OfferModel>();
|
||||
}
|
||||
activity?.SetTag("data.source", source);
|
||||
LogTrace($"{source} | trace: {activity?.TraceId} | {activity?.Duration.TotalMilliseconds}ms");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua update dei costi di tutte le righe dell'offerta indicata
|
||||
/// </summary>
|
||||
/// <param name="OfferID">Key</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> OffertUpdateCost(int OfferID)
|
||||
{
|
||||
using var activity = StartActivity();
|
||||
string source = "DB+REDIS";
|
||||
// calcolo
|
||||
bool fatto = await dbController.OffertUpdateCost(OfferID);
|
||||
// svuoto cache...
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Offers:*");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OfferRows:*");
|
||||
activity?.SetTag("data.source", source);
|
||||
LogTrace($"{source} | trace: {activity?.TraceId} | {activity?.Duration.TotalMilliseconds}ms");
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua Add complessivo record offerta
|
||||
/// </summary>
|
||||
/// <param name="updRec">Key</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> OffertUpsert(OfferModel updRec)
|
||||
{
|
||||
using var activity = StartActivity();
|
||||
string source = "DB+REDIS";
|
||||
// calcolo
|
||||
bool fatto = await dbController.OffertUpsert(updRec);
|
||||
// svuoto cache...
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Offers:*");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OfferRows:*");
|
||||
activity?.SetTag("data.source", source);
|
||||
LogTrace($"{source} | trace: {activity?.TraceId} | {activity?.Duration.TotalMilliseconds}ms");
|
||||
return fatto;
|
||||
}
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Effettua update dei costi di tutte le righe dell'ordine indicata
|
||||
/// </summary>
|
||||
/// <param name="OfferID">Key</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> OrderUpdateCost(int OrderID)
|
||||
{
|
||||
using var activity = StartActivity();
|
||||
bool fatto = false;
|
||||
string source = "DB+REDIS";
|
||||
// calcolo
|
||||
#if false
|
||||
fatto = await dbController.OrderUpdateCost(OrderID);
|
||||
#endif
|
||||
// svuoto cache...
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Offers:*");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OfferRows:*");
|
||||
activity?.SetTag("data.source", source);
|
||||
LogTrace($"{source} | trace: {activity?.TraceId} | {activity?.Duration.TotalMilliseconds}ms");
|
||||
return fatto;
|
||||
}
|
||||
/// <summary>
|
||||
/// Elenco righe offerta specificata
|
||||
/// </summary>
|
||||
@@ -799,6 +651,26 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
}
|
||||
|
||||
|
||||
#if false
|
||||
/// <summary>
|
||||
/// Effettua update dei costi di tutte le righe dell'ordine indicata
|
||||
/// </summary>
|
||||
/// <param name="OfferID">Key</param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> OrderUpdateCost(int OrderID)
|
||||
{
|
||||
using var activity = StartActivity();
|
||||
bool fatto = false;
|
||||
string source = "DB+REDIS";
|
||||
// calcolo
|
||||
//fatto = await dbController.OrderUpdateCost(OrderID);
|
||||
// svuoto cache...
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Offers:*");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OfferRows:*");
|
||||
activity?.SetTag("data.source", source);
|
||||
LogTrace($"{source} | trace: {activity?.TraceId} | {activity?.Duration.TotalMilliseconds}ms");
|
||||
return fatto;
|
||||
}
|
||||
/// <summary>
|
||||
/// Restituisce record ordine + righe Ordine dato ID
|
||||
/// </summary>
|
||||
@@ -859,22 +731,6 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
return newOrd;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converte il campo raw della BOM in lista oggetti da gestire
|
||||
/// </summary>
|
||||
/// <param name="currRec"></param>
|
||||
/// <returns></returns>
|
||||
public List<BomItemDTO> OrderGetBomList(OrderRowModel currRec)
|
||||
{
|
||||
List<BomItemDTO> answ = new List<BomItemDTO>();
|
||||
var bomList = JsonConvert.DeserializeObject<List<BomItemDTO>>(currRec.ItemBOM);
|
||||
if (bomList != null)
|
||||
{
|
||||
answ = bomList;
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco ordini da DB filtrate x periodo e stato
|
||||
/// </summary>
|
||||
@@ -910,6 +766,44 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua upsert complessivo Ordine
|
||||
/// </summary>
|
||||
/// <param name="updRec"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> OrderUpsert(OrderModel updRec)
|
||||
{
|
||||
using var activity = StartActivity();
|
||||
string source = "DB+REDIS";
|
||||
// calcolo
|
||||
bool fatto = await dbController.OrderUpsert(updRec);
|
||||
// svuoto cache...
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Orders:*");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OrderRows:*");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OrderRowsByState:*");
|
||||
activity?.SetTag("data.source", source);
|
||||
LogTrace($"{source} | trace: {activity?.TraceId} | {activity?.Duration.TotalMilliseconds}ms");
|
||||
return fatto;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Converte il campo raw della BOM in lista oggetti da gestire
|
||||
/// </summary>
|
||||
/// <param name="currRec"></param>
|
||||
/// <returns></returns>
|
||||
public List<BomItemDTO> OrderGetBomList(OrderRowModel currRec)
|
||||
{
|
||||
List<BomItemDTO> answ = new List<BomItemDTO>();
|
||||
var bomList = JsonConvert.DeserializeObject<List<BomItemDTO>>(currRec.ItemBOM);
|
||||
if (bomList != null)
|
||||
{
|
||||
answ = bomList;
|
||||
}
|
||||
return answ;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua eliminazione della riga Ordine
|
||||
/// </summary>
|
||||
@@ -1214,25 +1108,6 @@ namespace EgwCoreLib.Lux.Data.Services
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua upsert complessivo Ordine
|
||||
/// </summary>
|
||||
/// <param name="updRec"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> OrderUpsert(OrderModel updRec)
|
||||
{
|
||||
using var activity = StartActivity();
|
||||
string source = "DB+REDIS";
|
||||
// calcolo
|
||||
bool fatto = await dbController.OrderUpsert(updRec);
|
||||
// svuoto cache...
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:Orders:*");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OrderRows:*");
|
||||
await ExecFlushRedisPatternAsync((RedisValue)$"{redisBaseKey}:OrderRowsByState:*");
|
||||
activity?.SetTag("data.source", source);
|
||||
LogTrace($"{source} | trace: {activity?.TraceId} | {activity?.Duration.TotalMilliseconds}ms");
|
||||
return fatto;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco completo Fasi
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
using EgwCoreLib.Lux.Data.DbModel.Sales;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.Services.Sales
|
||||
{
|
||||
public interface IOrderService
|
||||
{
|
||||
#region Public Methods
|
||||
|
||||
Task<OrderModel?> CloneOfferAsync(OfferModel rec2clone);
|
||||
|
||||
Task<List<OrderModel>> GetFiltAsync(DateTime inizio, DateTime fine);
|
||||
|
||||
Task<OrderModel?> GetByIdAsync(int recId, bool doForce);
|
||||
|
||||
Task<bool> UpsertAsync(OrderModel upsRec);
|
||||
|
||||
Task<bool> UpdateCostAsync(int OrderId);
|
||||
|
||||
#endregion Public Methods
|
||||
}
|
||||
}
|
||||
@@ -89,7 +89,7 @@ namespace EgwCoreLib.Lux.Data.Services.Sales
|
||||
/// <returns></returns>
|
||||
public async Task<bool> UpdateCostAsync(int OfferId)
|
||||
{
|
||||
return await TraceAsync($"{_className}.Upsert", async (activity) =>
|
||||
return await TraceAsync($"{_className}.UpdateCost", async (activity) =>
|
||||
{
|
||||
// 1. Recupero dati
|
||||
var rows = await _repo.GetRowsAsync(OfferId);
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
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;
|
||||
|
||||
namespace EgwCoreLib.Lux.Data.Services.Sales
|
||||
{
|
||||
public class OrderService : BaseServ, IOrderService
|
||||
{
|
||||
#region Public Constructors
|
||||
|
||||
public OrderService(
|
||||
IConfiguration config,
|
||||
IConnectionMultiplexer redis,
|
||||
IOrderRepository repo) : base(config, redis)
|
||||
{
|
||||
_className = "Order";
|
||||
_repo = repo;
|
||||
}
|
||||
|
||||
#endregion Public Constructors
|
||||
|
||||
#region Public Methods
|
||||
|
||||
/// <summary>
|
||||
/// Genera un nuovo record ordine:
|
||||
/// - cloning completo di un offerta + TUTTE le relative righe di offerta + rif offerta
|
||||
/// - generazione prodItems x etichette
|
||||
/// </summary>
|
||||
/// <param name="rec2clone"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<OrderModel?> CloneOfferAsync(OfferModel rec2clone)
|
||||
{
|
||||
return await TraceAsync($"{_className}.CloneOffer", async (activity) =>
|
||||
{
|
||||
// eseguo clone
|
||||
var result = await _repo.CloneOfferAsync(rec2clone);
|
||||
|
||||
// se eseguito, pulisco la cache correlata
|
||||
if (result != null)
|
||||
{
|
||||
// Invalido sia la lista classi che eventuali dettagli correlati
|
||||
await ClearCacheAsync($"{_redisBaseKey}:{_className}:*");
|
||||
await ClearCacheAsync($"{_redisBaseKey}:OrderRows:*");
|
||||
await ClearCacheAsync($"{_redisBaseKey}:OrderRowsByState:*");
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<OrderModel?> GetByIdAsync(int recId, bool doForce)
|
||||
{
|
||||
// Uso helper TraceAsync che gestisce automaticamente StartActivity, Log e Exception tracking
|
||||
return await TraceAsync($"{_className}.GetFilt", async (activity) =>
|
||||
{
|
||||
if (doForce)
|
||||
{
|
||||
return await _repo.GetByIdAsync(recId) ?? new OrderModel();
|
||||
}
|
||||
else
|
||||
{
|
||||
return await GetOrSetCacheAsync(
|
||||
$"{_redisBaseKey}:{_className}:ById:{recId}",
|
||||
async () => await _repo.GetByIdAsync(recId),
|
||||
LongCache
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Elenco completo Order da DB
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public async Task<List<OrderModel>> GetFiltAsync(DateTime inizio, DateTime fine)
|
||||
{
|
||||
// Uso helper TraceAsync che gestisce automaticamente StartActivity, Log e Exception tracking
|
||||
return await TraceAsync($"{_className}.GetFilt", async (activity) =>
|
||||
{
|
||||
return await GetOrSetCacheAsync(
|
||||
$"{_redisBaseKey}:{_className}:Filt:{inizio:yyMMdd-HHmm}:{fine:yyMMdd-HHmm}",
|
||||
async () => await _repo.GetFiltAsync(inizio, fine),
|
||||
LongCache
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Effettua update dei costi di tutte le righe del Order indicato
|
||||
/// </summary>
|
||||
/// <param name="OrderId"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> UpdateCostAsync(int OrderId)
|
||||
{
|
||||
return await TraceAsync($"{_className}.UpdateCost", async (activity) =>
|
||||
{
|
||||
// 1. Recupero dati
|
||||
var rows = await _repo.GetRowsAsync(OrderId);
|
||||
var itemGroups = await _repo.GetItemGroupsAsync();
|
||||
var bomItems = await _repo.GetBomItemsAsync();
|
||||
|
||||
// 2. Calcolo costi BOM
|
||||
foreach (var row in rows)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(row.ItemBOM) && row.ItemBOM.Length > 2)
|
||||
{
|
||||
var bomList = JsonConvert.DeserializeObject<List<BomItemDTO>>(row.ItemBOM);
|
||||
if (bomList != null)
|
||||
{
|
||||
double totCost = 0;
|
||||
double totPrice = 0;
|
||||
int totItemQty = 0;
|
||||
int numGroupOk = 0;
|
||||
int numItemOk = 0;
|
||||
|
||||
BomCalculator.Validate(
|
||||
itemGroups,
|
||||
bomItems,
|
||||
ref bomList,
|
||||
null,
|
||||
ref totCost,
|
||||
ref totPrice,
|
||||
ref totItemQty,
|
||||
ref numGroupOk,
|
||||
ref numItemOk
|
||||
);
|
||||
|
||||
row.ItemBOM = JsonConvert.SerializeObject(bomList);
|
||||
row.BomCost = Math.Round(totCost, 3);
|
||||
row.BomPrice = Math.Round(totPrice, 3);
|
||||
row.BomOk = bomList.Count == numGroupOk;
|
||||
row.ItemOk = bomList.Count == numItemOk;
|
||||
row.ProdItemQty = totItemQty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. Salvo
|
||||
var result = await _repo.SaveRowsAsync(rows);
|
||||
|
||||
if (result)
|
||||
{
|
||||
// 4. Invalido cache
|
||||
await ClearCacheAsync($"{_redisBaseKey}:{_className}:*");
|
||||
await ClearCacheAsync($"{_redisBaseKey}:OrderRows:*");
|
||||
await ClearCacheAsync($"{_redisBaseKey}:OrderRowsByState:*");
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Upsert record Order
|
||||
/// </summary>
|
||||
/// <param name="updRec"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<bool> UpsertAsync(OrderModel upsRec)
|
||||
{
|
||||
return await TraceAsync($"{_className}.Upsert", async (activity) =>
|
||||
{
|
||||
var currRec = await _repo.GetByIdAsync(upsRec.OrderID);
|
||||
|
||||
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}:{_className}:*");
|
||||
await ClearCacheAsync($"{_redisBaseKey}:OrderRows:*");
|
||||
await ClearCacheAsync($"{_redisBaseKey}:OrderRowsByState:*");
|
||||
}
|
||||
|
||||
return success;
|
||||
});
|
||||
}
|
||||
|
||||
#endregion Public Methods
|
||||
|
||||
#region Private Fields
|
||||
|
||||
private readonly string _className;
|
||||
private readonly IOrderRepository _repo;
|
||||
|
||||
#endregion Private Fields
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Version>1.1.2603.1716</Version>
|
||||
<Version>1.1.2603.1717</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -183,6 +183,7 @@ builder.Services.AddScoped<IItemRepository, ItemRepository>();
|
||||
builder.Services.AddScoped<IJobStepRepository, JobStepRepository>();
|
||||
builder.Services.AddScoped<IJobTaskRepository, JobTaskRepository>();
|
||||
builder.Services.AddScoped<IOfferRepository, OfferRepository>();
|
||||
builder.Services.AddScoped<IOrderRepository, OrderRepository>();
|
||||
builder.Services.AddScoped<IResourceRepository, ResourceRepository>();
|
||||
builder.Services.AddScoped<ISellingItemRepository, SellingItemRepository>();
|
||||
builder.Services.AddScoped<ITemplateRepository, TemplateRepository>();
|
||||
@@ -199,6 +200,7 @@ builder.Services.AddScoped<IItemService, ItemService>();
|
||||
builder.Services.AddScoped<IJobStepService, JobStepService>();
|
||||
builder.Services.AddScoped<IJobTaskService, JobTaskService>();
|
||||
builder.Services.AddScoped<IOfferService, OfferService>();
|
||||
builder.Services.AddScoped<IOrderService, OrderService>();
|
||||
builder.Services.AddScoped<IResourceService, ResourceService>();
|
||||
builder.Services.AddScoped<ISellingItemService, SellingItemService>();
|
||||
builder.Services.AddScoped<ITemplateService, TemplateService>();
|
||||
|
||||
@@ -8,6 +8,7 @@ using EgwCoreLib.Lux.Data.DbModel.Sales;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Utils;
|
||||
using EgwCoreLib.Lux.Data.Services;
|
||||
using EgwCoreLib.Lux.Data.Services.Config;
|
||||
using EgwCoreLib.Lux.Data.Services.Sales;
|
||||
using EgwCoreLib.Lux.Data.Services.Utils;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Forms;
|
||||
@@ -362,6 +363,9 @@ namespace Lux.UI.Components.Compo
|
||||
[Inject]
|
||||
private DataLayerServices DLService { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
private IOrderService OrdService { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
private IEnvirParamService EPService { get; set; } = null!;
|
||||
|
||||
@@ -820,7 +824,7 @@ namespace Lux.UI.Components.Compo
|
||||
await InvokeAsync(StateHasChanged);
|
||||
await Task.Delay(300);
|
||||
}
|
||||
await DLService.OrderUpdateCost(OrderID);
|
||||
await OrdService.UpdateCostAsync(OrderID);
|
||||
if (forceResetCalc)
|
||||
{
|
||||
await Task.Delay(300);
|
||||
@@ -1528,7 +1532,7 @@ namespace Lux.UI.Components.Compo
|
||||
IconCss = "fa-solid fa-hourglass-start"
|
||||
});
|
||||
CurrRecord.LogHistory = currHist;
|
||||
await DLService.OrderUpsert(CurrRecord);
|
||||
await OrdService.UpsertAsync(CurrRecord);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,7 +71,10 @@ namespace Lux.UI.Components.Pages
|
||||
protected IJSRuntime JSRuntime { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
private IOfferService OService { get; set; } = default!;
|
||||
private IOfferService OffService { get; set; } = default!;
|
||||
|
||||
[Inject]
|
||||
private IOrderService OrdService { get; set; } = default!;
|
||||
|
||||
|
||||
[Inject]
|
||||
@@ -111,7 +114,7 @@ namespace Lux.UI.Components.Pages
|
||||
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Confermi di voler duplicare interamente l'offerta selezionata?{Environment.NewLine}---------------------------{Environment.NewLine}Env: {rec2clone.Envir} | {rec2clone.OfferCode}{Environment.NewLine}{rec2clone.Description}{Environment.NewLine}Articoli: {rec2clone.NumItems}{Environment.NewLine}---------------------------{Environment.NewLine}Importo: {rec2clone.TotalPrice:C2}"))
|
||||
return;
|
||||
// clona intera offerta + tutte le righe...
|
||||
await OService.CloneAsync(rec2clone);
|
||||
await OffService.CloneAsync(rec2clone);
|
||||
await ReloadData();
|
||||
UpdateTable();
|
||||
}
|
||||
@@ -129,7 +132,7 @@ namespace Lux.UI.Components.Pages
|
||||
if (!await JSRuntime.InvokeAsync<bool>("confirm", $"Vuoi uscire salvando?"))
|
||||
return;
|
||||
// salvo record
|
||||
await OService.UpsertAsync(updRec);
|
||||
await OffService.UpsertAsync(updRec);
|
||||
}
|
||||
|
||||
protected void DoSelect(OfferModel curRec)
|
||||
@@ -192,7 +195,7 @@ namespace Lux.UI.Components.Pages
|
||||
return;
|
||||
|
||||
// creazione nuovo ordine da offerta
|
||||
var newOrd = await DLService.OrderFromOffer(currRec);
|
||||
var newOrd = await OrdService.CloneOfferAsync(currRec);
|
||||
|
||||
if (newOrd != null)
|
||||
{
|
||||
@@ -274,7 +277,7 @@ namespace Lux.UI.Components.Pages
|
||||
});
|
||||
newOrd.LogHistory = currHist;
|
||||
//OrderHist = listOrdRow.LogHistory;
|
||||
await DLService.OrderUpsert(newOrd);
|
||||
await OrdService.UpsertAsync(newOrd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -282,7 +285,7 @@ namespace Lux.UI.Components.Pages
|
||||
}
|
||||
|
||||
currRec.OffertState = newStatus;
|
||||
await OService.UpsertAsync(currRec);
|
||||
await OffService.UpsertAsync(currRec);
|
||||
await ReloadData();
|
||||
UpdateTable();
|
||||
}
|
||||
@@ -397,7 +400,7 @@ namespace Lux.UI.Components.Pages
|
||||
private async Task DoSave(OfferModel updRec)
|
||||
{
|
||||
// salvo record
|
||||
await OService.UpsertAsync(updRec);
|
||||
await OffService.UpsertAsync(updRec);
|
||||
// cambio step
|
||||
CompileStep nextStep = currStep < CompileStep.FinalCheck ? currStep + 1 : currStep;
|
||||
AdvStep(nextStep);
|
||||
@@ -448,7 +451,7 @@ namespace Lux.UI.Components.Pages
|
||||
private async Task ReloadData()
|
||||
{
|
||||
await DLService.OffersCheckExpired();
|
||||
AllRecords = await OService.GetFiltAsync(PeriodoSel.Inizio, PeriodoSel.Fine);
|
||||
AllRecords = await OffService.GetFiltAsync(PeriodoSel.Inizio, PeriodoSel.Fine);
|
||||
DoFilter();
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ using EgwCoreLib.Lux.Data.DbModel.Config;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Sales;
|
||||
using EgwCoreLib.Lux.Data.Services;
|
||||
using EgwCoreLib.Lux.Data.Services.Config;
|
||||
using EgwCoreLib.Lux.Data.Services.Sales;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
using NLog;
|
||||
@@ -46,6 +47,9 @@ namespace Lux.UI.Components.Pages
|
||||
[Inject]
|
||||
protected DataLayerServices DLService { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
private IOrderService OrdService { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
private IEnvirParamService EPService { get; set; } = null!;
|
||||
|
||||
@@ -156,7 +160,7 @@ namespace Lux.UI.Components.Pages
|
||||
|
||||
currRec.LogHistory = new List<TaskHistDTO>();
|
||||
OrderHist = currRec.LogHistory;
|
||||
await DLService.OrderUpsert(currRec);
|
||||
await OrdService.UpsertAsync(currRec);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -306,7 +310,7 @@ namespace Lux.UI.Components.Pages
|
||||
});
|
||||
currRec.LogHistory = currHist;
|
||||
OrderHist = currRec.LogHistory;
|
||||
await DLService.OrderUpsert(currRec);
|
||||
await OrdService.UpsertAsync(currRec);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -435,7 +439,7 @@ namespace Lux.UI.Components.Pages
|
||||
private async Task DoSave(OrderModel updRec)
|
||||
{
|
||||
// salvo record
|
||||
await DLService.OrderUpsert(updRec);
|
||||
await OrdService.UpsertAsync(updRec);
|
||||
// cambio step
|
||||
CompileStep nextStep = currStep < CompileStep.FinalCheck ? currStep + 1 : currStep;
|
||||
AdvStep(nextStep);
|
||||
@@ -525,7 +529,7 @@ namespace Lux.UI.Components.Pages
|
||||
private async Task ReloadData()
|
||||
{
|
||||
await DLService.OffersCheckExpired();
|
||||
AllRecords = await DLService.OrderGetFilt(PeriodoSel.Inizio, PeriodoSel.Fine);
|
||||
AllRecords = await OrdService.GetFiltAsync(PeriodoSel.Inizio, PeriodoSel.Fine);
|
||||
DoFilter();
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using EgwCoreLib.Lux.Data.DbModel.Production;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Sales;
|
||||
using EgwCoreLib.Lux.Data.DbModel.Utils;
|
||||
using EgwCoreLib.Lux.Data.Services;
|
||||
using EgwCoreLib.Lux.Data.Services.Sales;
|
||||
using EgwCoreLib.Lux.Data.Services.Utils;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
@@ -83,6 +84,9 @@ namespace Lux.UI.Components.Pages
|
||||
[Inject]
|
||||
private IJSRuntime JSRuntime { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
private IOrderService OrdService { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
private ProdService PService { get; set; } = null!;
|
||||
|
||||
@@ -429,7 +433,7 @@ namespace Lux.UI.Components.Pages
|
||||
|
||||
var currPOR = ListEstimRecords?.FirstOrDefault(x => x.OrderRowID == prodGroupItem.OrderRowID) ?? new OrderRowModel();
|
||||
|
||||
var currRec = await DLService.OrderById(currPOR.OrderID, true);
|
||||
var currRec = await OrdService.GetByIdAsync(currPOR.OrderID, true);
|
||||
|
||||
var dictReq = new Dictionary<string, double>();
|
||||
// verifico se ho 1 sola macchina o molte...
|
||||
@@ -502,7 +506,7 @@ namespace Lux.UI.Components.Pages
|
||||
IconCss = "fa-solid fa-hourglass-start"
|
||||
});
|
||||
currRec.LogHistory = currHist;
|
||||
await DLService.OrderUpsert(currRec);
|
||||
await OrdService.UpsertAsync(currRec);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UserSecretsId>aspnet-Lux.UI-a758c101-a2f4-4e38-977d-1c4887dbbd50</UserSecretsId>
|
||||
<Version>1.1.2603.1716</Version>
|
||||
<Version>1.1.2603.1717</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -221,6 +221,7 @@ builder.Services.AddScoped<IItemRepository, ItemRepository>();
|
||||
builder.Services.AddScoped<IJobStepRepository, JobStepRepository>();
|
||||
builder.Services.AddScoped<IJobTaskRepository, JobTaskRepository>();
|
||||
builder.Services.AddScoped<IOfferRepository, OfferRepository>();
|
||||
builder.Services.AddScoped<IOrderRepository, OrderRepository>();
|
||||
builder.Services.AddScoped<IResourceRepository, ResourceRepository>();
|
||||
builder.Services.AddScoped<ISellingItemRepository, SellingItemRepository>();
|
||||
builder.Services.AddScoped<ITemplateRepository, TemplateRepository>();
|
||||
@@ -237,6 +238,7 @@ builder.Services.AddScoped<IItemService, ItemService>();
|
||||
builder.Services.AddScoped<IJobStepService, JobStepService>();
|
||||
builder.Services.AddScoped<IJobTaskService, JobTaskService>();
|
||||
builder.Services.AddScoped<IOfferService, OfferService>();
|
||||
builder.Services.AddScoped<IOrderService, OrderService>();
|
||||
builder.Services.AddScoped<IResourceService, ResourceService>();
|
||||
builder.Services.AddScoped<ISellingItemService, SellingItemService>();
|
||||
builder.Services.AddScoped<ITemplateService, TemplateService>();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<body>
|
||||
<i>LUX - Web Windows MES</i>
|
||||
<h4>Versione: 1.1.2603.1716</h4>
|
||||
<h4>Versione: 1.1.2603.1717</h4>
|
||||
<br /> Note di rilascio:
|
||||
<ul>
|
||||
<li>
|
||||
|
||||
@@ -1 +1 @@
|
||||
1.1.2603.1716
|
||||
1.1.2603.1717
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<item>
|
||||
<version>1.1.2603.1716</version>
|
||||
<version>1.1.2603.1717</version>
|
||||
<url>http://nexus.steamware.net/repository/SWS/GPW/stable/GPW.UI.zip</url>
|
||||
<changelog>http://nexus.steamware.net/repository/SWS/GPW/stable/ChangeLog.html</changelog>
|
||||
<mandatory>false</mandatory>
|
||||
|
||||
Reference in New Issue
Block a user