From 20163792052aff99d467eb814fab0d2961db7df6 Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Sat, 23 Jul 2022 17:19:19 +0200 Subject: [PATCH] ART: - aggiunta ricerca x selVal - completata ricerca veto cancellazione --- MP.Data/Controllers/MpSpecController.cs | 19 ++ MP.Data/Utils.cs | 24 ++ MP.SPEC/Components/CmpTop.razor | 8 +- MP.SPEC/Components/DataPager.razor | 56 ++++ MP.SPEC/Components/DataPager.razor.cs | 187 +++++++++++ MP.SPEC/Data/MessageService.cs | 2 +- MP.SPEC/Data/MpDataService.cs | 110 ++++-- MP.SPEC/Pages/Articoli.razor | 9 +- MP.SPEC/Pages/Articoli.razor.cs | 425 +++++++++++------------- MP.SPEC/Shared/MainLayout.razor | 3 - MP.SPEC/appsettings.json | 3 +- 11 files changed, 583 insertions(+), 263 deletions(-) create mode 100644 MP.SPEC/Components/DataPager.razor create mode 100644 MP.SPEC/Components/DataPager.razor.cs diff --git a/MP.Data/Controllers/MpSpecController.cs b/MP.Data/Controllers/MpSpecController.cs index 0009b2bb..81d20728 100644 --- a/MP.Data/Controllers/MpSpecController.cs +++ b/MP.Data/Controllers/MpSpecController.cs @@ -131,6 +131,25 @@ namespace MP.Data.Controllers return dbResult; } + + /// + /// Elenco tabella Articoli IMPIEGATI (da stored stp_ART_getUsed) + /// + /// + public List ArticoliGetUsed() + { + List dbResult = new List(); + using (var dbCtx = new MoonProContext(_configuration)) + { + dbResult = dbCtx + .DbSetArticoli + .FromSqlRaw("EXEC stp_ART_getUsed") + .AsNoTracking() + .ToList(); + } + return dbResult; + } + /// /// Elenco tabella Articoli da filtro /// diff --git a/MP.Data/Utils.cs b/MP.Data/Utils.cs index 48f7c3b4..5d70ae78 100644 --- a/MP.Data/Utils.cs +++ b/MP.Data/Utils.cs @@ -39,6 +39,30 @@ namespace MP.Data await Task.Run(() => File.WriteAllLines(path, lines.ToArray())); } + public static string redKeyArtUsed + { + get => RedHash($"CACHE:CheckArtUsed"); + } + public static string redKeyTabCheckArt + { + get => RedHash($"CACHE:TabCheckArt"); + } + + /// + /// Nome della variabile HASH da utilizzare (dato CodModulo / Server / DB impiegato da funzionalita' DbConfig) + keyName richiesto... + /// + public static string RedHash(string keyName) + { + string answ = keyName; + try + { + answ =$"MP:Data:{keyName}"; + } + catch + { } + return answ; + } + #endregion Public Methods } } \ No newline at end of file diff --git a/MP.SPEC/Components/CmpTop.razor b/MP.SPEC/Components/CmpTop.razor index e8c8b236..17a22e11 100644 --- a/MP.SPEC/Components/CmpTop.razor +++ b/MP.SPEC/Components/CmpTop.razor @@ -4,6 +4,7 @@ @using Microsoft.AspNetCore.Components.Authorization @inject AuthenticationStateProvider AuthenticationStateProvider +@inject MessageService MService
@@ -20,8 +21,11 @@
@code { - [CascadingParameter(Name ="ShowSearch")] - protected bool ShowSearch { get; set; } + protected bool ShowSearch + { + get => MService.ShowSearch; + set => MService.ShowSearch = value; + } private string userName = ""; diff --git a/MP.SPEC/Components/DataPager.razor b/MP.SPEC/Components/DataPager.razor new file mode 100644 index 00000000..54e6c829 --- /dev/null +++ b/MP.SPEC/Components/DataPager.razor @@ -0,0 +1,56 @@ +
+
+
+
+ @if (totalCount > 0) + { +
    +
  • +
  • + @for (int i = @startPage; i <= endPage; ++i) + { + var pageNum = i; +
  • + } +
  • +
  • +
+ } +
+
+
+
+ @if (showLoading) + { +
+
+
+ } +
+
+
+
+
+
+ @if (!showLoading) + { + @totalCount records + } +
+
+ @if (totalCount > 0) + { +
+ +
+ } +
+
+
+
diff --git a/MP.SPEC/Components/DataPager.razor.cs b/MP.SPEC/Components/DataPager.razor.cs new file mode 100644 index 00000000..af42ed54 --- /dev/null +++ b/MP.SPEC/Components/DataPager.razor.cs @@ -0,0 +1,187 @@ +using Microsoft.AspNetCore.Components; + +namespace MP.SPEC.Components +{ + public partial class DataPager : ComponentBase + { + #region Public Properties + + [Parameter] + public int currPage + { + get + { + return _numPage; + } + set + { + bool doReport = !_numPage.Equals(value); + if (doReport) + { + _numPage = value; + reportChangePage(); + } + } + } + + [Parameter] + public EventCallback numPageChanged { get; set; } + + [Parameter] + public EventCallback numRecordChanged { get; set; } + + [Parameter] + public int PageSize + { + get + { + return _numRecord; + } + set + { + bool doReport = !_numRecord.Equals(value); + if (doReport) + { + _numRecord = value; + reportChange(); + } + } + } + + [Parameter] + public bool showLoading + { + get + { + return _showLoading; + } + set + { + if (value) + { + Random random = new Random(); + percLoading = random.Next(30, 90); + } + else + { + percLoading = 5; + } + _showLoading = value; + } + } + + [Parameter] + public int totalCount { get; set; } = 0; + + #endregion Public Properties + + #region Protected Fields + + protected bool _showLoading = false; + + #endregion Protected Fields + + #region Protected Properties + + protected int _numPage { get; set; } = 1; + + protected int _numRecord { get; set; } = 10; + + protected int percLoading { get; set; } = 0; + + #endregion Protected Properties + + #region Protected Methods + + protected string cssActive(int numPage) + { + string answ = ""; + if (numPage == currPage) + { + answ = "active"; + } + return answ; + } + + protected override async Task OnInitializedAsync() + { + await Task.Run(() => showLoading = false); + } + + protected void PaginationItemClick(int page) + { + currPage = page; + } + + #endregion Protected Methods + + #region Private Properties + + private int endPage + { + get + { + int answ = (int)(currPage / numPages) * numPages + numPages; + answ = answ < LastPage ? answ : LastPage; + return answ; + } + } + + private int LastPage + { + get + { + return Math.Max((int)Math.Ceiling(totalCount / (double)PageSize), 1); + } + } + + private int nextBlock + { + get + { + int answ = currPage + numPages; + answ = answ < LastPage ? answ : LastPage; + return answ; + } + } + + private int numPages { get; set; } = 10; + + private int prevBlock + { + get + { + int answ = currPage - numPages; + answ = answ > 0 ? answ : 1; + return answ; + } + } + + // calcola un set 1 .. numPages centrato sulla pagina corrente... + private int startPage + { + get + { + int answ = (int)(currPage / numPages) * numPages; + answ = answ > 0 ? answ : 1; + return answ; + } + } + + #endregion Private Properties + + #region Private Methods + + private void reportChange() + { + numRecordChanged.InvokeAsync(PageSize); + } + + private void reportChangePage() + { + numPageChanged.InvokeAsync(currPage); + } + + #endregion Private Methods + } +} \ No newline at end of file diff --git a/MP.SPEC/Data/MessageService.cs b/MP.SPEC/Data/MessageService.cs index 94ec9332..809b5f53 100644 --- a/MP.SPEC/Data/MessageService.cs +++ b/MP.SPEC/Data/MessageService.cs @@ -4,7 +4,7 @@ { #region Private Fields - private string searchVal; + private string searchVal = ""; private bool showSearch; #endregion Private Fields diff --git a/MP.SPEC/Data/MpDataService.cs b/MP.SPEC/Data/MpDataService.cs index ead6f768..376cf359 100644 --- a/MP.SPEC/Data/MpDataService.cs +++ b/MP.SPEC/Data/MpDataService.cs @@ -44,7 +44,7 @@ namespace MP.SPEC.Data #if false // avvio timers... - startTimers(); + startTimers(); #endif } @@ -67,23 +67,6 @@ namespace MP.SPEC.Data #region Public Methods - public Task> ConfigGetAll() - { - return Task.FromResult(dbController.ConfigGetAll().ToList()); - } - - /// - /// Restitusice elenco articoli cercati - /// - /// - /// - /// - public async Task> ArticoliGetSearch(int numRecord, string azienda, string searchVal) - { - return await Task.FromResult(dbController.ArticoliGetSearch(numRecord, azienda, searchVal)); - } - - public async Task> AnagTipoArtLV() { return await Task.FromResult(dbController.AnagTipoArtLV()); @@ -98,6 +81,18 @@ namespace MP.SPEC.Data { return await dbController.ArticoliDeleteRecord(currRec); } + + /// + /// Restitusice elenco articoli cercati + /// + /// + /// + /// + public async Task> ArticoliGetSearch(int numRecord, string azienda, string searchVal) + { + return await Task.FromResult(dbController.ArticoliGetSearch(numRecord, azienda, searchVal)); + } + /// /// Aggiornamento record selezionato /// @@ -108,12 +103,9 @@ namespace MP.SPEC.Data return await dbController.ArticoliUpdateRecord(currRec); } - /// - /// Restitusice elenco aziende - /// - public Task> ElencoAziende() + public Task> ConfigGetAll() { - return Task.FromResult(dbController.AnagGruppiAziende()); + return Task.FromResult(dbController.ConfigGetAll().ToList()); } public void Dispose() @@ -130,6 +122,12 @@ namespace MP.SPEC.Data fastLimit = DateTime.Now.AddMinutes(1); } + /// Restitusice elenco aziende + public Task> ElencoAziende() + { + return Task.FromResult(dbController.AnagGruppiAziende()); + } + /// /// Elenco setup dei tag conf correnti /// @@ -161,6 +159,72 @@ namespace MP.SPEC.Data return Task.FromResult(dbController.MacchineGetAll()); } + /// + /// Verifica se sia possiubile cancellare articolo dato suo CodArt cercando su redis o su tab veto da DB + /// + /// + /// + public bool ArticoloDelEnabled(object CodArt) + { + bool answ = false; + string codArticolo = $"{CodArt}"; + int cacheCheckArtUsato = 1; + int.TryParse(_configuration.GetValue("ServerConf:cacheCheckArtUsato"), out cacheCheckArtUsato); + TimeSpan TTLCache = TimeSpan.FromMinutes(cacheCheckArtUsato); + // cerco in cache redis... + string redKeyArtUsed = $"{Utils.redKeyArtUsed}:{codArticolo}"; + string redKeyTabCheckArt = Utils.redKeyTabCheckArt; + string rawData = redisDb.StringGet(redKeyArtUsed); + if (!string.IsNullOrEmpty(rawData)) + { + bool.TryParse(rawData, out answ); + } + else + { + // controllo non sia stato mai prodotto sennò non posso cancellare... + try + { + // cerco in cache se ci sia la tabella con gli articoli impiegati... + string rawTable = redisDb.StringGet(redKeyTabCheckArt); + List artList = new List(); + if (!string.IsNullOrEmpty(rawTable)) + { + artList = JsonConvert.DeserializeObject>(rawTable); + } + // rileggo... + if (artList == null || artList.Count == 0) + { + artList = new List(); + var tabArticoli = dbController.ArticoliGetUsed(); + var codList = tabArticoli.Select(x => x.CodArticolo); + foreach (string cod in codList) + { + artList.Add(cod); + } + // SE fosse vuoto aggiungo comunque il cado "ND"... + if (artList.Count == 0) + { + artList.Add("ND"); + } + // salvo + rawTable = JsonConvert.SerializeObject(artList); + redisDb.StringSet(redKeyTabCheckArt, rawTable, TTLCache); + } + // cerco nella tabella: se ci fosse --> disabilitato delete + bool usato = false; + if (artList != null && artList.Count > 0) + { + usato = artList.Contains(codArticolo); + } + answ = !usato; + redisDb.StringSet(redKeyArtUsed, $"{answ}", TTLCache); + } + catch + { } + } + return answ; + } + public async Task> MseGetAll() { int maxAge = 2000; diff --git a/MP.SPEC/Pages/Articoli.razor b/MP.SPEC/Pages/Articoli.razor index d2772860..2bad5e47 100644 --- a/MP.SPEC/Pages/Articoli.razor +++ b/MP.SPEC/Pages/Articoli.razor @@ -1,10 +1,10 @@ @page "/ART" @using MP.SPEC.Components +@using MP.SPEC.Data
- @* *@
@@ -150,7 +150,10 @@ @record.Azienda - + @if (ArticoloDelEnabled(record.CodArticolo)) + { + + } } @@ -161,6 +164,6 @@ }
\ No newline at end of file diff --git a/MP.SPEC/Pages/Articoli.razor.cs b/MP.SPEC/Pages/Articoli.razor.cs index 76f811ed..27e5ad38 100644 --- a/MP.SPEC/Pages/Articoli.razor.cs +++ b/MP.SPEC/Pages/Articoli.razor.cs @@ -1,55 +1,188 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; using Microsoft.AspNetCore.Components; -using System.Net.Http; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Components.Authorization; -using Microsoft.AspNetCore.Components.Forms; -using Microsoft.AspNetCore.Components.Routing; -using Microsoft.AspNetCore.Components.Web; -using Microsoft.AspNetCore.Components.Web.Virtualization; using Microsoft.JSInterop; -using MP.Data; -using MP.SPEC; -using MP.SPEC.Shared; -using MP.SPEC.Components; using MP.SPEC.Data; namespace MP.SPEC.Pages { public partial class Articoli : ComponentBase, IDisposable { - #region Private Fields + #region Public Methods - private MP.Data.DatabaseModels.AnagArticoli? currRecord = null; - private string _selAzienda = "*"; - private string selAzienda + public string checkSelect(string CodArticolo) { - get => _selAzienda; - set + string answ = ""; + if (currRecord != null) { - if (value != _selAzienda) + try { - _selAzienda = value; - var pUpd = Task.Run(async () => - { - await Task.Delay(1); - await reloadData(); - //await InvokeAsync(() => StateHasChanged()); - }); - pUpd.Wait(); + answ = (currRecord.CodArticolo == CodArticolo) ? "table-info" : ""; } + catch + { } + } + return answ; + } + + public void Dispose() + { + MessageService.EA_SearchUpdated -= OnSeachUpdated; + } + + public async void OnSeachUpdated() + { + await InvokeAsync(() => + { + currPage = 1; + Task task = UpdateData(); + StateHasChanged(); + }); + } + + #endregion Public Methods + + #region Protected Properties + + [Inject] + protected IJSRuntime JSRuntime { get; set; } + + [Inject] + protected MpDataService MDService { get; set; } + + [Inject] + protected MessageService MessageService { get; set; } + + [Inject] + protected NavigationManager NavManager { get; set; } + + protected int totalCount + { + get + { + int answ = 0; + if (SearchRecords != null) + { + answ = SearchRecords.Count; + } + return answ; } } + #endregion Protected Properties + + #region Protected Methods + + /// + /// Crea nuovo record e va in editing... + /// + /// + protected async Task addNew() + { + currRecord = new MP.Data.DatabaseModels.AnagArticoli() + { + CodArticolo = $"_NEW_{DateTime.Now:yyyyMMdd.HHmmss}", + DescArticolo = "Nuovo articolo", + Azienda = selAzienda != "*" ? selAzienda : "MAPO", + Disegno = "", + Tipo = "ART" + }; + await Task.Delay(1); + } + + protected async Task cancel() + { + currRecord = null; + await reloadData(); + await Task.Delay(1); + } + + /// + /// Eliminazione record selezioanto (previa conferma) + /// + /// + /// + protected async Task deleteRecord(MP.Data.DatabaseModels.AnagArticoli selRec) + { + if (!await JSRuntime.InvokeAsync("confirm", "Eliminazione Articolo: sei sicuro di voler procedere?")) + return; + await Task.Delay(1); + var done = await MDService.ArticoliDeleteRecord(selRec); + currRecord = null; + await reloadData(); + await Task.Delay(1); + } + + protected void ForceReload(int newNum) + { + numRecord = newNum; + } + + protected void ForceReloadPage(int newNum) + { + currPage = newNum; + } + + protected override async Task OnInitializedAsync() + { + clearFile(); + numRecord = 10; + MessageService.ShowSearch = true; + MessageService.EA_SearchUpdated += OnSeachUpdated; + ListAziende = await MDService.ElencoAziende(); + ListTipoArt = await MDService.AnagTipoArtLV(); + await reloadData(); + } + + protected void ResetData() + { + clearFile(); + currRecord = null; + } + + protected async Task resetSel() + { + currRecord = null; + await Task.Delay(1); + } + + protected async Task selRecord(MP.Data.DatabaseModels.AnagArticoli selRec) + { + currRecord = selRec; + await Task.Delay(1); + } + + protected async Task update(MP.Data.DatabaseModels.AnagArticoli selRec) + { + if (!await JSRuntime.InvokeAsync("confirm", "Confermi di voler salvare le modifiche?")) + return; + await Task.Delay(1); + var done = await MDService.ArticoliUpdateRecord(selRec); + currRecord = null; + await reloadData(); + await Task.Delay(1); + } + + protected async Task UpdateData() + { + currRecord = null; + await reloadData(); + } + + #endregion Protected Methods + + #region Private Fields + + private string _selAzienda = "*"; + private MP.Data.DatabaseModels.AnagArticoli? currRecord = null; private string fileName = "Controlli.csv"; - private List? ListRecords; - private List? SearchRecords; + private List? ListAziende; + + private List? ListRecords; + private List? ListTipoArt; + private List? SearchRecords; + #endregion Private Fields #region Private Properties @@ -93,60 +226,42 @@ namespace MP.SPEC.Pages } } + private string selAzienda + { + get => _selAzienda; + set + { + if (value != _selAzienda) + { + _selAzienda = value; + var pUpd = Task.Run(async () => + { + await Task.Delay(1); + await reloadData(); + //await InvokeAsync(() => StateHasChanged()); + }); + pUpd.Wait(); + } + } + } + private bool ShowCharts { get; set; } = false; #endregion Private Properties - #region Protected Properties - - [Inject] - protected IJSRuntime JSRuntime { get; set; } - - [Inject] - protected MessageService MessageService { get; set; } - - [Inject] - protected NavigationManager NavManager { get; set; } - - [Inject] - protected MpDataService MDService { get; set; } - - protected int totalCount - { - get - { - int answ = 0; - if (SearchRecords != null) - { - answ = SearchRecords.Count; - } - return answ; - } - } - - #endregion Protected Properties - - #region Public Properties - -#if false - [Parameter] - public SelectData currFilter - { - get - { - return MessageService.DetailFilter; - } - set - { - MessageService.DetailFilter = value; - } - } -#endif - - #endregion Public Properties - #region Private Methods + /// + /// Seleziona record x editing + /// + /// + /// + private bool ArticoloDelEnabled(string codArt) + { + bool answ = MDService.ArticoloDelEnabled(codArt); + return answ; + } + private async void clearFile() { await Task.Run(() => File.Delete(fullPath)); @@ -169,155 +284,5 @@ namespace MP.SPEC.Pages } #endregion Private Methods - - #region Protected Methods - -#if false - protected async Task DoFilter(SelectData newFilter) - { - clearFile(); - SearchRecords = null; - ListRecords = null; - currFilter = newFilter; - await reloadData(); - } -#endif - - protected void ForceReload(int newNum) - { - numRecord = newNum; - } - - protected void ForceReloadPage(int newNum) - { - currPage = newNum; - } - - protected override async Task OnInitializedAsync() - { - clearFile(); - numRecord = 10; - MessageService.ShowSearch = false; - MessageService.EA_SearchUpdated += OnSeachUpdated; - ListAziende = await MDService.ElencoAziende(); - ListTipoArt = await MDService.AnagTipoArtLV(); - await reloadData(); - } - - protected void ResetData() - { - clearFile(); -#if false - MDService.rollBackEdit(currRecord); -#endif - currRecord = null; - } - /// - /// Seleziona record x editing - /// - /// - /// - - protected async Task selRecord(MP.Data.DatabaseModels.AnagArticoli selRec) - { - currRecord = selRec; - await Task.Delay(1); - } - - /// - /// Eliminazione record selezioanto (previa conferma) - /// - /// - /// - protected async Task deleteRecord(MP.Data.DatabaseModels.AnagArticoli selRec) - { - if (!await JSRuntime.InvokeAsync("confirm", "Eliminazione Articolo: sei sicuro di voler procedere?")) - return; - await Task.Delay(1); - var done = await MDService.ArticoliDeleteRecord(selRec); - currRecord = null; - await reloadData(); - await Task.Delay(1); - } - - /// - /// Crea nuovo record e va in editing... - /// - /// - protected async Task addNew() - { - currRecord = new MP.Data.DatabaseModels.AnagArticoli() - { - CodArticolo = $"_NEW_{DateTime.Now:yyyyMMdd.HHmmss}", - DescArticolo = "Nuovo articolo", - Azienda = selAzienda != "*" ? selAzienda : "MAPO", - Disegno = "", - Tipo = "ART" - }; - await Task.Delay(1); - } - protected async Task cancel() - { - currRecord = null; - await reloadData(); - await Task.Delay(1); - } - protected async Task update(MP.Data.DatabaseModels.AnagArticoli selRec) - { - if (!await JSRuntime.InvokeAsync("confirm", "Confermi di voler salvare le modifiche?")) - return; - await Task.Delay(1); - var done = await MDService.ArticoliUpdateRecord(selRec); - currRecord = null; - await reloadData(); - await Task.Delay(1); - } - - protected async Task resetSel() - { - currRecord = null; - await Task.Delay(1); - } - - protected async Task UpdateData() - { - currRecord = null; - await reloadData(); - } - - #endregion Protected Methods - - #region Public Methods - - public string checkSelect(string CodArticolo) - { - string answ = ""; - if (currRecord != null) - { - try - { - answ = (currRecord.CodArticolo == CodArticolo) ? "table-info" : ""; - } - catch - { } - } - return answ; - } - - public void Dispose() - { - MessageService.EA_SearchUpdated -= OnSeachUpdated; - } - - public async void OnSeachUpdated() - { - await InvokeAsync(() => - { - Task task = UpdateData(); - StateHasChanged(); - }); - } - - #endregion Public Methods } } \ No newline at end of file diff --git a/MP.SPEC/Shared/MainLayout.razor b/MP.SPEC/Shared/MainLayout.razor index f1047b4d..bf1f26cc 100644 --- a/MP.SPEC/Shared/MainLayout.razor +++ b/MP.SPEC/Shared/MainLayout.razor @@ -9,9 +9,7 @@
- -
@Body @@ -23,5 +21,4 @@
@code { - private bool ShowSearch = false; } \ No newline at end of file diff --git a/MP.SPEC/appsettings.json b/MP.SPEC/appsettings.json index d5691442..f8773551 100644 --- a/MP.SPEC/appsettings.json +++ b/MP.SPEC/appsettings.json @@ -12,6 +12,7 @@ "Redis": "localhost:6379,DefaultDatabase=1,connectTimeout=5000,syncTimeout=5000,asyncTimeout=5000,abortConnect=false,ssl=false" }, "ServerConf": { - "maxAge": "2000" + "maxAge": "2000", + "cacheCheckArtUsato": 2 } }