Files
magman/MagMan.Data.Tenant/Services/TenantService.cs
T
2024-01-22 19:47:52 +01:00

670 lines
24 KiB
C#

using MagMan.Core;
using MagMan.Core.DTO;
using MagMan.Data.Tenant.Controllers;
using MagMan.Data.Tenant.DbModels;
using Microsoft.Extensions.Configuration;
using Newtonsoft.Json;
using NLog;
using NLog.Fluent;
using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Runtime;
using System.Text;
using System.Threading.Tasks;
namespace MagMan.Data.Tenant.Services
{
public class TenantService : BaseServ
{
#region Public Fields
public TenantController dbController = null!;
#endregion Public Fields
#region Public Constructors
public TenantService(IConfiguration configuration, IConnectionMultiplexer redisConnMult)
{
Log.Info("TenantService starting...");
_configuration = configuration;
// Conf cache
redisConn = redisConnMult;
redisDb = this.redisConn.GetDatabase();
// json serializer... FIX errore loop circolare https://www.ryadel.com/en/jsonserializationexception-self-referencing-loop-detected-error-fix-entity-framework-asp-net-core/
JSSettings = new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
};
// cod app
CodApp = _configuration["CodApp"];
DbServerAddr = _configuration["DbConfig:Server"];
dbController = new TenantController();
// chiudo log
Log.Info("TenantService started!");
}
#endregion Public Constructors
#region Public Methods
/// <summary>
/// Elimina Item da magazzino + refresh cache
/// </summary>
/// <param name="nKey">Key di riferimento</param>
/// <param name="rec2del">Item da eliminare</param>
/// <returns></returns>
public async Task<bool> ItemDelete(int nKey, RawItemModel rec2del)
{
bool fatto = false;
string cString = ConnString(nKey);
try
{
fatto = dbController.ItemDelete(cString, rec2del);
if (fatto)
{
await FlushRedisCache();
}
}
catch (Exception exc)
{
Log.Error($"Error during ItemDelete:{Environment.NewLine}{exc}");
}
return fatto;
}
/// <summary>
/// Converte il DTO in ItemModel
/// </summary>
/// <param name="origItem">DTO di partenza</param>
/// <param name="isActive">Parametro active da impostare</param>
/// <returns></returns>
public RawItemModel ItemFromDto(ItemDTO origItem, bool isActive)
{
RawItemModel answ = new RawItemModel()
{
MatId = origItem.MatId,
Note = origItem.Note,
LMm = origItem.LMm,
WMm = origItem.WMm,
HMm = origItem.HMm,
IsRemn = origItem.IsRemn,
Location = origItem.Location,
QtyAvail = origItem.QtyAvail,
IsActive = isActive
};
return answ;
}
/// <summary>
/// Lista Items gestiti a magazzino
/// </summary>
/// <param name="nKey">Key di riferimento</param>
/// <returns></returns>
public async Task<List<RawItemModel>> ItemGetAll(int nKey)
{
string source = "DB";
string cString = ConnString(nKey);
List<RawItemModel>? dbResult = new List<RawItemModel>();
try
{
string currKey = $"{Const.rKeyConfig}:ItemList:{nKey}";
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string? rawData = await redisDb.StringGetAsync(currKey);
if (!string.IsNullOrEmpty(rawData))
{
source = "REDIS";
var tempResult = JsonConvert.DeserializeObject<List<RawItemModel>>(rawData);
if (tempResult == null)
{
dbResult = new List<RawItemModel>();
}
else
{
dbResult = tempResult;
}
}
else
{
dbResult = dbController.ItemGetAll(cString);
rawData = JsonConvert.SerializeObject(dbResult, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, LongCache);
}
if (dbResult == null)
{
dbResult = new List<RawItemModel>();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"ItemGetAll | {source} in: {ts.TotalMilliseconds} ms");
}
catch (Exception exc)
{
Log.Error($"Error during ItemGetAll:{Environment.NewLine}{exc}");
}
return dbResult;
}
/// <summary>
/// Lista Items gestiti a magazzino x materiale
/// </summary>
/// <param name="nKey">Key di riferimento</param>
/// <param name="matID">ID del materiale x cui filtrare, 0 = tutti</param>
/// <returns></returns>
public async Task<List<RawItemModel>> ItemGetByMat(int nKey, int matID)
{
string source = "DB";
string cString = ConnString(nKey);
List<RawItemModel>? dbResult = new List<RawItemModel>();
try
{
string currKey = $"{Const.rKeyConfig}:{nKey}:ItemList:{matID}";
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string? rawData = await redisDb.StringGetAsync(currKey);
if (!string.IsNullOrEmpty(rawData))
{
source = "REDIS";
var tempResult = JsonConvert.DeserializeObject<List<RawItemModel>>(rawData);
if (tempResult == null)
{
dbResult = new List<RawItemModel>();
}
else
{
dbResult = tempResult;
}
}
else
{
dbResult = dbController.ItemGetByMat(cString, matID);
rawData = JsonConvert.SerializeObject(dbResult, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, LongCache);
}
if (dbResult == null)
{
dbResult = new List<RawItemModel>();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"ItemGetByMat | {source} in: {ts.TotalMilliseconds} ms");
}
catch (Exception exc)
{
Log.Error($"Error during ItemGetByMat:{Environment.NewLine}{exc}");
}
return dbResult;
}
/// <summary> Update record Item + refresh cache </summary> <param name="nKey">Key di
/// riferimento</param> <param name="currItem">Item interesato</param> <param
/// name="deltaQty">quantità da aggiornare (se <0 è consumo)</param> <returns></returns>
public async Task<bool> ItemModQty(int nKey, RawItemModel currItem, int deltaQty)
{
bool fatto = false;
string cString = ConnString(nKey);
try
{
fatto = dbController.ItemModQty(cString, currItem, deltaQty);
if (fatto)
{
await FlushRedisCache();
}
}
catch (Exception exc)
{
Log.Error($"Error during ItemModQty:{Environment.NewLine}{exc}");
}
return fatto;
}
/// <summary>
/// Update record Item + refresh cache
/// </summary>
/// <param name="nKey">Key di riferimento</param>
/// <param name="currItem">Item interesato</param>
/// <returns></returns>
public async Task<bool> ItemUpdate(int nKey, RawItemModel currItem)
{
bool fatto = false;
string cString = ConnString(nKey);
try
{
fatto = dbController.ItemUpdate(cString, currItem);
if (fatto)
{
await FlushRedisCache();
}
}
catch (Exception exc)
{
Log.Error($"Error during ItemUpdate:{Environment.NewLine}{exc}");
}
return fatto;
}
/// <summary>
/// Elimina Materiale da magazzino + refresh cache
/// </summary>
/// <param name="nKey">Key di riferimento</param>
/// <param name="rec2del">Item da eliminare</param>
/// <returns></returns>
public async Task<bool> MaterialDelete(int nKey, MaterialModel rec2del)
{
bool fatto = false;
string cString = ConnString(nKey);
try
{
fatto = dbController.MaterialDelete(cString, rec2del);
if (fatto)
{
await FlushRedisCache();
}
}
catch (Exception exc)
{
Log.Error($"Error during MaterialDelete:{Environment.NewLine}{exc}");
}
return fatto;
}
/// <summary>
/// Converte il DTO in MaterialModel
/// </summary>
/// <param name="origItem"></param>
/// <returns></returns>
public MaterialModel MaterialFromDto(MaterialDTO origItem)
{
MaterialModel answ = new MaterialModel()
{
MatId = origItem.MatId,
MatCode = origItem.MatCode,
MatDesc = origItem.MatDesc,
LMm = origItem.LMm,
WMm = origItem.WMm,
HMm = origItem.HMm
};
return answ;
}
/// <summary>
/// Lista Materiali gestiti a magazzino
/// </summary>
/// <param name="nKey">Key di riferimento</param>
/// <param name="withChild">Se true allora include record child (Items)</param>
/// <returns></returns>
public async Task<List<MaterialModel>> MaterialGetAll(int nKey, bool withChild)
{
string source = "DB";
string cString = ConnString(nKey);
List<MaterialModel>? dbResult = new List<MaterialModel>();
try
{
string dType = withChild ? "MaterialsFull" : "Materials";
string currKey = $"{Const.rKeyConfig}:{dType}:{nKey}";
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string? rawData = await redisDb.StringGetAsync(currKey);
if (!string.IsNullOrEmpty(rawData))
{
source = "REDIS";
var tempResult = JsonConvert.DeserializeObject<List<MaterialModel>>(rawData);
if (tempResult == null)
{
dbResult = new List<MaterialModel>();
}
else
{
dbResult = tempResult;
}
}
else
{
dbResult = dbController.MaterialGetAll(cString, withChild);
rawData = JsonConvert.SerializeObject(dbResult, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, LongCache);
// per evitare loopback uso deserialize...
var tempResult = JsonConvert.DeserializeObject<List<MaterialModel>>(rawData);
if (tempResult != null)
{
dbResult = tempResult;
}
}
if (dbResult == null)
{
dbResult = new List<MaterialModel>();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"MaterialGetAll | {source} in: {ts.TotalMilliseconds} ms");
}
catch (Exception exc)
{
Log.Error($"Error during MaterialGetAll:{Environment.NewLine}{exc}");
}
return dbResult;
}
/// <summary>
/// Lista Materiali gestiti a magazzino
/// </summary>
/// <param name="nKey">Key di riferimento</param>
/// <param name="matID">Materiale richiesto</param>
/// <param name="withChild">Se true allora include record child (Items)</param>
/// <returns></returns>
public async Task<List<MaterialModel>> MaterialGetFilt(int nKey, int matID, bool withChild)
{
string source = "DB";
string cString = ConnString(nKey);
List<MaterialModel>? dbResult = new List<MaterialModel>();
try
{
string dType = withChild ? "MatInvFull" : "MatInv";
string currKey = $"{Const.rKeyConfig}:{dType}:{nKey}:{matID}";
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string? rawData = await redisDb.StringGetAsync(currKey);
if (!string.IsNullOrEmpty(rawData) && rawData.Length > 2)
{
source = "REDIS";
var tempResult = JsonConvert.DeserializeObject<List<MaterialModel>>(rawData);
if (tempResult == null)
{
dbResult = new List<MaterialModel>();
}
else
{
dbResult = tempResult;
}
}
else
{
dbResult = dbController.MaterialGetFilt(cString, matID, withChild);
rawData = JsonConvert.SerializeObject(dbResult, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, LongCache);
// per evitare loopback uso deserialize...
var tempResult = JsonConvert.DeserializeObject<List<MaterialModel>>(rawData);
if (tempResult != null)
{
dbResult = tempResult;
}
}
if (dbResult == null)
{
dbResult = new List<MaterialModel>();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"MaterialGetFilt | {source} in: {ts.TotalMilliseconds} ms");
}
catch (Exception exc)
{
Log.Error($"Error during MaterialGetFilt:{Environment.NewLine}{exc}");
}
return dbResult;
}
/// <summary>
/// Update record Materiale + refresh cache
/// </summary>
/// <param name="nKey">Key di riferimento</param>
/// <param name="currItem"></param>
/// <returns></returns>
public async Task<bool> MaterialUpdate(int nKey, MaterialModel currItem)
{
bool fatto = false;
string cString = ConnString(nKey);
try
{
fatto = dbController.MaterialUpdate(cString, currItem);
if (fatto)
{
await FlushRedisCache();
}
}
catch (Exception exc)
{
Log.Error($"Error during MaterialUpdate:{Environment.NewLine}{exc}");
}
return fatto;
}
/// <summary>
/// Elimina record Project + refresh cache
/// </summary>
/// <param name="nKey">Key di riferimento</param>
/// <param name="rec2del">Item da eliminare</param>
/// <returns></returns>
public async Task<bool> ProjectDelete(int nKey, ProjModel rec2del)
{
bool fatto = false;
string cString = ConnString(nKey);
try
{
fatto = dbController.ProjectDelete(cString, rec2del);
if (fatto)
{
await FlushRedisCache();
}
}
catch (Exception exc)
{
Log.Error($"Error during ProjectDelete:{Environment.NewLine}{exc}");
}
return fatto;
}
/// <summary>
/// Converte il DTO in ItemModel
/// </summary>
/// <param name="origItem">DTO di partenza</param>
/// <returns></returns>
public ProjModel ProjectFromDto(ProjectDTO origItem)
{
ProjModel answ = new ProjModel()
{
MachineID = origItem.MachineID,
KeyNum = origItem.KeyNum,
ProjExtDbId = origItem.ProjExtDbId,
ProjExtId = origItem.ProjExtId,
BTLFileName = origItem.BTLFileName,
PType = origItem.PType,
Machine = origItem.Machine,
ProjDescription = origItem.ProjDescription,
DtCreated = origItem.DtCreated,
DtLastAction = origItem.DtLastAction,
DtSchedule = origItem.DtSchedule,
DtStartProd = origItem.DtStartProd,
ListName = origItem.ListName,
ProcTimeEst = origItem.ProcTimeEst,
ProcTimeReal = origItem.ProcTimeReal,
IsActive = origItem.IsActive,
IsArchived = origItem.IsArchived
};
return answ;
}
/// <summary>
/// Lista Projects gestiti a magazzino
/// </summary>
/// <param name="nKey">Key di riferimento</param>
/// <returns></returns>
public async Task<List<ProjModel>> ProjectGetAll(int nKey)
{
string source = "DB";
string cString = ConnString(nKey);
List<ProjModel>? dbResult = new List<ProjModel>();
try
{
string currKey = $"{Const.rKeyConfig}:ProjList:{nKey}";
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string? rawData = await redisDb.StringGetAsync(currKey);
if (!string.IsNullOrEmpty(rawData))
{
source = "REDIS";
var tempResult = JsonConvert.DeserializeObject<List<ProjModel>>(rawData);
if (tempResult == null)
{
dbResult = new List<ProjModel>();
}
else
{
dbResult = tempResult;
}
}
else
{
dbResult = dbController.ProjectGetAll(cString);
rawData = JsonConvert.SerializeObject(dbResult, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, LongCache);
}
if (dbResult == null)
{
dbResult = new List<ProjModel>();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"ProjectGetAll | {source} in: {ts.TotalMilliseconds} ms");
}
catch (Exception exc)
{
Log.Error($"Error during ProjectGetAll:{Environment.NewLine}{exc}");
}
return dbResult;
}
/// <summary>
/// Lista Items gestiti a magazzino x materiale
/// </summary>
/// <param name="nKey">Key di riferimento</param>
/// <param name="numKey">ID del materiale x cui filtrare, 0 = tutti</param>
/// <returns></returns>
public async Task<List<ProjModel>> ProjectGetByNumKey(int nKey, int numKey)
{
string source = "DB";
string cString = ConnString(nKey);
List<ProjModel>? dbResult = new List<ProjModel>();
try
{
string currKey = $"{Const.rKeyConfig}:{nKey}:ProjList:{numKey}";
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string? rawData = await redisDb.StringGetAsync(currKey);
if (!string.IsNullOrEmpty(rawData))
{
source = "REDIS";
var tempResult = JsonConvert.DeserializeObject<List<ProjModel>>(rawData);
if (tempResult == null)
{
dbResult = new List<ProjModel>();
}
else
{
dbResult = tempResult;
}
}
else
{
dbResult = dbController.ProjectGetByNumKey(cString, numKey);
rawData = JsonConvert.SerializeObject(dbResult, JSSettings);
await redisDb.StringSetAsync(currKey, rawData, LongCache);
}
if (dbResult == null)
{
dbResult = new List<ProjModel>();
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Debug($"ProjectGetByNumKey | {source} in: {ts.TotalMilliseconds} ms");
}
catch (Exception exc)
{
Log.Error($"Error during ProjectGetByNumKey:{Environment.NewLine}{exc}");
}
return dbResult;
}
/// <summary>
/// Update record Item + refresh cache
/// </summary>
/// <param name="nKey">Key di riferimento</param>
/// <param name="currItem">Item interesato</param>
/// <returns></returns>
public async Task<bool> ProjectUpdate(int nKey, ProjModel currItem)
{
bool fatto = false;
string cString = ConnString(nKey);
try
{
fatto = dbController.ProjectUpdate(cString, currItem);
if (fatto)
{
await FlushRedisCache();
}
}
catch (Exception exc)
{
Log.Error($"Error during ProjectUpdate:{Environment.NewLine}{exc}");
}
return fatto;
}
#endregion Public Methods
#region Private Fields
private static JsonSerializerSettings? JSSettings;
#endregion Private Fields
#region Private Properties
private string CodApp { get; set; } = "";
private Dictionary<int, string> ConnStringLUT { get; set; } = new Dictionary<int, string>();
private string DbServerAddr { get; set; } = "";
#endregion Private Properties
#region Private Methods
/// <summary>
/// Restituisce la stringa di connessione al DB data la Key di riferimento, effettuando
/// verifica ed eventuale migration
/// </summary>
/// <param name="nKey"></param>
/// <returns></returns>
private string ConnString(int nKey)
{
string answ = "";
if (ConnStringLUT.ContainsKey(nKey))
{
answ = ConnStringLUT[nKey];
}
else
{
// calcolo e aggiungo
answ = DbConfig.CustomerConnString(DbServerAddr, nKey);
// verifico eventuale creazione/migrazione...
DbConfig.InitDb(DbServerAddr, nKey);
// verifico se serve applicazione migrazioni
DbConfig.ExecMigrationMain();
// aggiungo a LUT
ConnStringLUT.Add(nKey, answ);
}
return answ;
}
#endregion Private Methods
}
}