237 lines
7.9 KiB
C#
237 lines
7.9 KiB
C#
namespace EgwCoreLib.Lux.Data.Services.Sales
|
|
{
|
|
public class OfferService : BaseServ, IOfferService
|
|
{
|
|
#region Public Constructors
|
|
|
|
public OfferService(
|
|
IConfiguration config,
|
|
IConnectionMultiplexer redis,
|
|
IOfferRepository repo) : base(config, redis)
|
|
{
|
|
_className = "Offer";
|
|
_repo = repo;
|
|
}
|
|
|
|
#endregion Public Constructors
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary>
|
|
/// Verifica offerte scadute, con update sul DB
|
|
/// </summary>
|
|
public async Task<bool> CheckExpiredAsync()
|
|
{
|
|
return await TraceAsync($"{_className}.CheckExpired", async (activity) =>
|
|
{
|
|
// eseguo clone
|
|
var result = await _repo.CheckExpiredAsync();
|
|
|
|
// se eseguito, pulisco la cache correlata
|
|
if (result)
|
|
{
|
|
await FlushCacheOffersAsync();
|
|
}
|
|
return result;
|
|
});
|
|
}
|
|
/// <summary>
|
|
/// Esegue il cloning completo di un Offer e di TUTTE le relative righe...
|
|
/// </summary>
|
|
/// <param name="rec2clone"></param>
|
|
/// <returns></returns>
|
|
public async Task<bool> CloneAsync(OfferModel rec2clone)
|
|
{
|
|
return await TraceAsync($"{_className}.Clone", async (activity) =>
|
|
{
|
|
// eseguo clone
|
|
var result = await _repo.CloneAsync(rec2clone);
|
|
|
|
// se eseguito, pulisco la cache correlata
|
|
if (result)
|
|
{
|
|
await FlushCacheOffersAsync();
|
|
}
|
|
return result;
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reset cache sistema x Offerte modalità async
|
|
/// </summary>
|
|
public async Task<bool> FlushCacheOffersAsync()
|
|
{
|
|
return await TraceAsync($"{_className}.FlushCache", async (activity) =>
|
|
{
|
|
string operation = "FlushCache";
|
|
activity?.SetTag("db.operation", operation);
|
|
|
|
await ClearCacheAsync($"{_redisBaseKey}:{_className}:*");
|
|
await ClearCacheAsync($"{_redisBaseKey}:OfferRows:*");
|
|
//await ClearCacheAsync($"{_redisBaseKey}:Offers:*");
|
|
|
|
return true;
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elenco completo Offer da DB
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task<List<OfferModel>> GetAllAsync()
|
|
{
|
|
// Uso helper TraceAsync che gestisce automaticamente StartActivity, Log e Exception tracking
|
|
return await TraceAsync($"{_className}.GetAllAsync", async (activity) =>
|
|
{
|
|
return await GetOrSetCacheAsync(
|
|
$"{_redisBaseKey}:{_className}:ALL",
|
|
async () => await _repo.GetAllAsync(),
|
|
LongCache
|
|
);
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// <inheritdoc />
|
|
/// </summary>
|
|
public async Task<OfferModel?> GetByIdAsync(int OfferID)
|
|
{
|
|
// Uso helper TraceAsync che gestisce automaticamente StartActivity, Log e Exception tracking
|
|
return await TraceAsync($"{_className}.GetFilt", async (activity) =>
|
|
{
|
|
return await GetOrSetCacheAsync(
|
|
$"{_redisBaseKey}:{_className}:ById:{OfferID}",
|
|
async () => await _repo.GetByIdAsync(OfferID),
|
|
LongCache
|
|
);
|
|
});
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Elenco completo Offer da DB
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task<List<OfferModel>> 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 Offer indicato
|
|
/// </summary>
|
|
/// <param name="OfferId"></param>
|
|
/// <returns></returns>
|
|
public async Task<bool> UpdateCostAsync(int OfferId)
|
|
{
|
|
return await TraceAsync($"{_className}.UpdateCost", async (activity) =>
|
|
{
|
|
// 1. Recupero dati
|
|
var rows = await _repo.GetRowsAsync(OfferId);
|
|
if (rows.Count == 0)
|
|
return false;
|
|
|
|
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 FlushCacheOffersAsync();
|
|
}
|
|
|
|
return result;
|
|
});
|
|
}
|
|
|
|
/// <summary>
|
|
/// Upsert record Offer
|
|
/// </summary>
|
|
/// <param name="updRec"></param>
|
|
/// <returns></returns>
|
|
public async Task<bool> UpsertAsync(OfferModel upsRec)
|
|
{
|
|
return await TraceAsync($"{_className}.Upsert", async (activity) =>
|
|
{
|
|
var currRec = await _repo.GetByIdAsync(upsRec.OfferID);
|
|
|
|
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 FlushCacheOffersAsync();
|
|
}
|
|
|
|
return success;
|
|
});
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Private Fields
|
|
|
|
private readonly string _className;
|
|
private readonly IOfferRepository _repo;
|
|
|
|
#endregion Private Fields
|
|
}
|
|
} |