- aggiunta ricerca x selVal
- completata ricerca veto cancellazione
This commit is contained in:
Samuele Locatelli
2022-07-23 17:19:19 +02:00
parent 0ad15c90c3
commit 2016379205
11 changed files with 583 additions and 263 deletions
+19
View File
@@ -131,6 +131,25 @@ namespace MP.Data.Controllers
return dbResult;
}
/// <summary>
/// Elenco tabella Articoli IMPIEGATI (da stored stp_ART_getUsed)
/// </summary>
/// <returns></returns>
public List<DatabaseModels.AnagArticoli> ArticoliGetUsed()
{
List<DatabaseModels.AnagArticoli> dbResult = new List<DatabaseModels.AnagArticoli>();
using (var dbCtx = new MoonProContext(_configuration))
{
dbResult = dbCtx
.DbSetArticoli
.FromSqlRaw("EXEC stp_ART_getUsed")
.AsNoTracking()
.ToList();
}
return dbResult;
}
/// <summary>
/// Elenco tabella Articoli da filtro
/// </summary>
+24
View File
@@ -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");
}
/// <summary>
/// Nome della variabile HASH da utilizzare (dato CodModulo / Server / DB impiegato da funzionalita' DbConfig) + keyName richiesto...
/// </summary>
public static string RedHash(string keyName)
{
string answ = keyName;
try
{
answ =$"MP:Data:{keyName}";
}
catch
{ }
return answ;
}
#endregion Public Methods
}
}
+6 -2
View File
@@ -4,6 +4,7 @@
@using Microsoft.AspNetCore.Components.Authorization
@inject AuthenticationStateProvider AuthenticationStateProvider
@inject MessageService MService
<div class="d-flex w-100 justify-content-between">
<div class="px-2">
@@ -20,8 +21,11 @@
</div>
@code {
[CascadingParameter(Name ="ShowSearch")]
protected bool ShowSearch { get; set; }
protected bool ShowSearch
{
get => MService.ShowSearch;
set => MService.ShowSearch = value;
}
private string userName = "";
+56
View File
@@ -0,0 +1,56 @@
<div class="row">
<div class="col-12 col-lg-8 text-left">
<div class="row">
<div class="col-12 small">
@if (totalCount > 0)
{
<ul class="pagination pagination-sm mb-1">
<li class="page-item"><button class="page-link" @onclick="() => PaginationItemClick(1)"><i class="fas fa-angle-double-left"></i></button></li>
<li class="page-item"><button class="page-link" @onclick="() => PaginationItemClick(prevBlock)"><i class="fas fa-angle-left"></i></button></li>
@for (int i = @startPage; i <= endPage; ++i)
{
var pageNum = i;
<li class="page-item @cssActive(pageNum)"><button class="page-link" @onclick="() => PaginationItemClick(pageNum)">@pageNum</button></li>
}
<li class="page-item"><button class="page-link" @onclick="() => PaginationItemClick(nextBlock)"><i class="fas fa-angle-right"></i></button></li>
<li class="page-item"><button class="page-link" @onclick="() => PaginationItemClick(LastPage)"><i class="fas fa-angle-double-right"></i></button></li>
</ul>
}
</div>
</div>
<div class="row">
<div class="col-12 small">
@if (showLoading)
{
<div class="progress" style="height: 10px;">
<div class="progress-bar progress-bar-striped progress-bar-animated" style="width:@percLoading%;"></div>
</div>
}
</div>
</div>
</div>
<div class="col-12 col-lg-4">
<div class="d-flex">
<div class="p-1 flex-fill">
@if (!showLoading)
{
<span>@totalCount records</span>
}
</div>
<div class="p-1 small">
@if (totalCount > 0)
{
<div class="input-group input-group-sm">
<select @bind="@PageSize" class="form-select form-select-sm text-end">
<option value="5">5</option>
<option value="10">10</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
</div>
}
</div>
</div>
</div>
</div>
+187
View File
@@ -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<int> numPageChanged { get; set; }
[Parameter]
public EventCallback<int> 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
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
{
#region Private Fields
private string searchVal;
private string searchVal = "";
private bool showSearch;
#endregion Private Fields
+87 -23
View File
@@ -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<List<ConfigModel>> ConfigGetAll()
{
return Task.FromResult(dbController.ConfigGetAll().ToList());
}
/// <summary>
/// Restitusice elenco articoli cercati
/// </summary>
/// <param name="numRecord"></param>
/// <param name="searchVal"></param>
/// <returns></returns>
public async Task<List<AnagArticoli>> ArticoliGetSearch(int numRecord, string azienda, string searchVal)
{
return await Task.FromResult(dbController.ArticoliGetSearch(numRecord, azienda, searchVal));
}
public async Task<List<ListValues>> AnagTipoArtLV()
{
return await Task.FromResult(dbController.AnagTipoArtLV());
@@ -98,6 +81,18 @@ namespace MP.SPEC.Data
{
return await dbController.ArticoliDeleteRecord(currRec);
}
/// <summary>
/// Restitusice elenco articoli cercati
/// </summary>
/// <param name="numRecord"></param>
/// <param name="searchVal"></param>
/// <returns></returns>
public async Task<List<AnagArticoli>> ArticoliGetSearch(int numRecord, string azienda, string searchVal)
{
return await Task.FromResult(dbController.ArticoliGetSearch(numRecord, azienda, searchVal));
}
/// <summary>
/// Aggiornamento record selezionato
/// </summary>
@@ -108,12 +103,9 @@ namespace MP.SPEC.Data
return await dbController.ArticoliUpdateRecord(currRec);
}
/// <summary>
/// Restitusice elenco aziende
/// <returns></returns>
public Task<List<AnagGruppi>> ElencoAziende()
public Task<List<ConfigModel>> 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);
}
/// <summary> Restitusice elenco aziende <returns></returns>
public Task<List<AnagGruppi>> ElencoAziende()
{
return Task.FromResult(dbController.AnagGruppiAziende());
}
/// <summary>
/// Elenco setup dei tag conf correnti
/// </summary>
@@ -161,6 +159,72 @@ namespace MP.SPEC.Data
return Task.FromResult(dbController.MacchineGetAll());
}
/// <summary>
/// Verifica se sia possiubile cancellare articolo dato suo CodArt cercando su redis o su tab veto da DB
/// </summary>
/// <param name="CodArt"></param>
/// <returns></returns>
public bool ArticoloDelEnabled(object CodArt)
{
bool answ = false;
string codArticolo = $"{CodArt}";
int cacheCheckArtUsato = 1;
int.TryParse(_configuration.GetValue<string>("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<string> artList = new List<string>();
if (!string.IsNullOrEmpty(rawTable))
{
artList = JsonConvert.DeserializeObject<List<string>>(rawTable);
}
// rileggo...
if (artList == null || artList.Count == 0)
{
artList = new List<string>();
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<List<MappaStatoExpl>> MseGetAll()
{
int maxAge = 2000;
+6 -3
View File
@@ -1,10 +1,10 @@
@page "/ART"
@using MP.SPEC.Components
@using MP.SPEC.Data
<div class="card">
<div class="card-header table-primary">
@* <SelectionFilter SelFilter="currFilter" filterChanged="DoFilter" filterReset="ResetFilter" chartVisible="ShowCharts" chartsToggle="ToggleChart" ChartEnabled="true"></SelectionFilter>*@
<div class="d-flex justify-content-between">
<div class="px-2">
<div class="d-flex justify-content-between">
@@ -150,7 +150,10 @@
</td>
<td>@record.Azienda</td>
<td>
<button @onclick="() => deleteRecord(record)" class="btn btn-danger btn-sm"><i class="bi bi-trash-fill"></i></button>
@if (ArticoloDelEnabled(record.CodArticolo))
{
<button @onclick="() => deleteRecord(record)" class="btn btn-danger btn-sm"><i class="bi bi-trash-fill"></i></button>
}
</td>
</tr>
}
@@ -161,6 +164,6 @@
}
</div>
<div class="card-footer py-1">
@*<DataPager PageSize="numRecord" currPage="currPage" numRecordChanged="ForceReload" numPageChanged="ForceReloadPage" totalCount="totalCount" showLoading="isLoading" exportRequested="ExportCsv" fileName="@fileName" />*@
<DataPager PageSize="numRecord" currPage="currPage" numRecordChanged="ForceReload" numPageChanged="ForceReloadPage" totalCount="totalCount" showLoading="isLoading" />
</div>
</div>
+195 -230
View File
@@ -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
/// <summary>
/// Crea nuovo record e va in editing...
/// </summary>
/// <returns></returns>
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);
}
/// <summary>
/// Eliminazione record selezioanto (previa conferma)
/// </summary>
/// <param name="selRec"></param>
/// <returns></returns>
protected async Task deleteRecord(MP.Data.DatabaseModels.AnagArticoli selRec)
{
if (!await JSRuntime.InvokeAsync<bool>("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<bool>("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<MP.Data.DatabaseModels.AnagArticoli>? ListRecords;
private List<MP.Data.DatabaseModels.AnagArticoli>? SearchRecords;
private List<MP.Data.DatabaseModels.AnagGruppi>? ListAziende;
private List<MP.Data.DatabaseModels.AnagArticoli>? ListRecords;
private List<MP.Data.DatabaseModels.ListValues>? ListTipoArt;
private List<MP.Data.DatabaseModels.AnagArticoli>? 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
/// <summary>
/// Seleziona record x editing
/// </summary>
/// <param name="selRec"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Seleziona record x editing
/// </summary>
/// <param name="selRec"></param>
/// <returns></returns>
protected async Task selRecord(MP.Data.DatabaseModels.AnagArticoli selRec)
{
currRecord = selRec;
await Task.Delay(1);
}
/// <summary>
/// Eliminazione record selezioanto (previa conferma)
/// </summary>
/// <param name="selRec"></param>
/// <returns></returns>
protected async Task deleteRecord(MP.Data.DatabaseModels.AnagArticoli selRec)
{
if (!await JSRuntime.InvokeAsync<bool>("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);
}
/// <summary>
/// Crea nuovo record e va in editing...
/// </summary>
/// <returns></returns>
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<bool>("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
}
}
-3
View File
@@ -9,9 +9,7 @@
<main>
<div class="top-row px-4 justify-content-between">
<CascadingValue Value="@ShowSearch" Name="ShowSearch">
<CmpTop></CmpTop>
</CascadingValue>
</div>
<article class="content pt-0 m-2">
@Body
@@ -23,5 +21,4 @@
</div>
@code {
private bool ShowSearch = false;
}
+2 -1
View File
@@ -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
}
}