- completata serializzazione ricetta in modo parametrico/composto
This commit is contained in:
Samuele Locatelli
2023-02-13 11:55:50 +01:00
parent 14d4534e5c
commit 0b40b0cd22
15 changed files with 340 additions and 26 deletions
+81 -2
View File
@@ -60,6 +60,29 @@ namespace MP.Data.Controllers
{ }
return answ;
}
/// <summary>
/// Ricerca ricetta su MongoDB dato ID MongoDB
/// </summary>
/// <param name="mID"></param>
/// <returns></returns>
public async Task<RecipeModel> RecipeGetByID(string mID)
{
await Task.Delay(1);
RecipeModel answ = new RecipeModel();
try
{
// definisco filtro
var filtBuilder = Builders<RecipeModel>.Filter;
var filter = filtBuilder.Eq<string>("_id", mID);
var collectionData = mongoDb.GetCollection<RecipeModel>("RecipeArchive");
// recupero
answ = collectionData.Find(filter).Project<RecipeModel>("{_id: 0}").FirstOrDefault<RecipeModel>();
}
catch
{ }
return answ;
}
/// <summary>
/// Salva ricetta su MongoDB
/// </summary>
@@ -99,8 +122,6 @@ namespace MP.Data.Controllers
public RecipeModel InitRecipe(string confPath, int idxPODL, Dictionary<string, string> CalcArgs)
{
RecipeModel answ = new RecipeModel();
// recupero dati da PODL...
// per prima cosa leggo file di conf x inizializzare ricetta...
string fullPath = RecipePath(confPath);
bool fileOk = File.Exists(fullPath);
@@ -115,6 +136,64 @@ namespace MP.Data.Controllers
return answ;
}
/// <summary>
/// Ricetta in formato calcolato (string)
/// </summary>
public string CalcRecipe(RecipeModel currRecipe)
{
string answ = "";
// per prima cosa leggo file di conf x inizializzare ricetta...
string fullPath = RecipePath(currRecipe.TemplateFile);
bool fileOk = File.Exists(fullPath);
if (fileOk)
{
// preparo dati header
var headStrings = currRecipe.HeadVal.Select(x => $"\"{x.Key}\": \"{x.Value}\"").ToList();
string headVals = string.Join(",", headStrings);
// leggo template
string rawData = File.ReadAllText(fullPath);
// recupero configurazione x inizio/fine righe
string[] righe = rawData.Split(Environment.NewLine);
List<string> righeRed = new List<string>();
string sRow = "";
string eRow = "";
foreach (var riga in righe)
{
if (riga.Trim().StartsWith("||SROW:"))
{
sRow = riga.Trim().Replace("||SROW:", "").Replace("||", "");
}
else if (riga.Trim().StartsWith("||EROW:"))
{
eRow = riga.Trim().Replace("||EROW:", "").Replace("||", "");
}
else
{
righeRed.Add(riga);
}
}
// rigenero righe senza le parti da ripetere...
rawData = string.Join(Environment.NewLine, righeRed);
// effettuo sostituzione...
answ = rawData.Replace("||PlaceholderHeader||", headVals);
// per le righe prima calcolo blocchi ripetuti
List<string> rowComp = new List<string>();
foreach (var item in currRecipe.RowsVal)
{
var rowsStrings = item.Value.Select(x => $"\"{x.Key}\": \"{x.Value}\"").ToList();
rowComp.Add($"{Environment.NewLine}{sRow}{string.Join(",", rowsStrings)}{eRow}");
}
string rowsVals = string.Join(",", rowComp);
//...poi sostituisco
answ = answ.Replace("||PlaceholderRows||", rowsVals);
}
return answ;
}
private MongoClient client = new MongoClient("mongodb://localhost:27017");
private static IConfiguration _configuration;
+33 -3
View File
@@ -50,7 +50,7 @@ namespace MP.Data.MgModels
public List<Element> getNewRow(Dictionary<string, string> CalcArgs)
{
List<Element> rowList = new List<Element>();
rowList= ElementConverter(this.RowsConf.ListKeys, CalcArgs);
rowList = ElementConverter(this.RowsConf.ListKeys, CalcArgs);
return rowList;
}
@@ -138,7 +138,7 @@ namespace MP.Data.MgModels
this.Key = rawKey;
this.OrigVal = rawVal;
this.Value = rawVal;
// cerco se ho uno dei 3 caratteri (C/E/F):
// cerco se ho uno dei 3 caratteri (C/E/F/S):
if (rawVal.Length >= 2 && rawVal.Substring(1, 1) == ":")
{
string selTipo = rawVal.Substring(0, 2);
@@ -169,6 +169,20 @@ namespace MP.Data.MgModels
this.Value = rawVal.Substring(2);
break;
case "S:":
this.Type = KeyType.Calc;
// recupero item x ricerca in dizionario...
string sKey = rawVal.Substring(2);
if (CalcArgs.ContainsKey(sKey))
{
this.Value = CalcArgs[sKey];
}
else
{
this.Value = sKey;
}
break;
default:
this.Type = KeyType.None;
break;
@@ -219,10 +233,26 @@ namespace MP.Data.MgModels
public enum KeyType
{
None = 0,
/// <summary>
/// Campo calcolato (NON modificabile)
/// </summary>
Calc,
/// <summary>
/// Valore da Enum
/// </summary>
Enum,
/// <summary>
/// Valore fisso
/// </summary>
Fixed,
Free
/// <summary>
/// Valore libero
/// </summary>
Free,
/// <summary>
/// Campo suggerito (=calcolato modificabile)
/// </summary>
Suggested
}
#endregion Public Enums
+20 -4
View File
@@ -13,6 +13,7 @@ else
<h4>Testata Ricetta</h4>
</div>
<div>
<a href="api/recipe/@IdxPODL" target="_blank">Display</a>
@if (!showHead)
{
<span class="px-2"><b>@CurrRecipe?.HeadVal.Count</b> par</span>
@@ -41,15 +42,14 @@ else
{
<div class="col-3">
<div class="form-floating">
@*<small class="form-label small">@item.Key</small>*@
@if (item.Type == RecipeModel.Element.KeyType.Fixed)
@if (item.Type == RecipeModel.Element.KeyType.Fixed || item.Type == RecipeModel.Element.KeyType.Calc)
{
<input type="text" class="form-control" @bind="@item.Value" disabled>
}
else if (item.Type == MP.Data.MgModels.RecipeModel.Element.KeyType.Enum)
{
<select class="form-select" @bind="@item.Value">
@foreach (var enumItem in GetListByType(item.EnumType))
@foreach (var enumItem in GetHeadListByType(item.EnumType))
{
<option value="@enumItem.Key">@enumItem.Value</option>
}
@@ -121,7 +121,23 @@ else
{
<div class="col-3">
<div class="form-floating">
<input type="text" class="form-control" placeholder="@item.Key" @bind-value="@item.Value">
@if (item.Type == RecipeModel.Element.KeyType.Fixed || item.Type == RecipeModel.Element.KeyType.Calc)
{
<input type="text" class="form-control" @bind="@item.Value" disabled>
}
else if (item.Type == MP.Data.MgModels.RecipeModel.Element.KeyType.Enum)
{
<select class="form-select" @bind="@item.Value">
@foreach (var enumItem in GetRowListByType(item.EnumType))
{
<option value="@enumItem.Key">@enumItem.Value</option>
}
</select>
}
else
{
<input type="text" class="form-control" placeholder="@item.Key" @bind="@item.Value">
}
<label>@item.Key</label>
</div>
</div>
+22 -4
View File
@@ -45,10 +45,10 @@ namespace MP.SPEC.Components
await ReloadData();
}
protected Dictionary<string, string> GetListByType(string DictType)
protected Dictionary<string, string> GetHeadListByType(string DictType)
{
Dictionary<string, string> answ = new Dictionary<string, string>();
// inn primis il "selezionare"
// in primis il "selezionare"
answ.Add("", "--- Selezionare ---");
// cerco tipo in enums...
if (CurrRecipe != null && CurrRecipe.HeadConf.EnumVal.ContainsKey(DictType))
@@ -60,6 +60,21 @@ namespace MP.SPEC.Components
}
return answ;
}
protected Dictionary<string, string> GetRowListByType(string DictType)
{
Dictionary<string, string> answ = new Dictionary<string, string>();
// in primis il "selezionare"
answ.Add("", "--- Selezionare ---");
// cerco tipo in enums...
if (CurrRecipe != null && CurrRecipe.RowsConf.EnumVal.ContainsKey(DictType))
{
foreach (var item in CurrRecipe.RowsConf.EnumVal[DictType])
{
answ.Add(item.Key, item.Value);
}
}
return answ;
}
protected override async Task OnParametersSetAsync()
{
@@ -116,9 +131,12 @@ namespace MP.SPEC.Components
{
// sistemo lista bool x righe
showRows = new Dictionary<string, bool>();
for (int i = 1; i <= CurrRecipe.RowsVal.Count; i++)
if (CurrRecipe != null)
{
showRows.Add($"{i}", false);
for (int i = 1; i <= CurrRecipe.RowsVal.Count; i++)
{
showRows.Add($"{i}", false);
}
}
}
+43
View File
@@ -0,0 +1,43 @@
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using MP.Data.MgModels;
using MP.SPEC.Data;
using NLog;
namespace MP.SPEC.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class RecipeController : ControllerBase
{
/// <summary>
/// Dataservice x accesso DB
/// </summary>
protected MpDataService DService { get; set; }
public RecipeController(IConfiguration configuration, MpDataService DataService)
{
Log.Info("Starting MpDataService INIT");
_configuration = configuration;
DService = DataService;
Log.Info("Avviata classe Recipe");
}
private static IConfiguration _configuration = null!;
private static Logger Log = LogManager.GetCurrentClassLogger();
[HttpGet("GetRecipe")]
public async Task<string> GetRecipe(int idxPODL)
{
string answ = "";
var reqRecipe = await DService.RecipeGetByPODL(idxPODL);
if(reqRecipe!=null)
{
answ = DService.CalcRecipe(reqRecipe);
}
return answ;
}
}
}
+6
View File
@@ -82,6 +82,7 @@ namespace MP.SPEC.Data
{
return mongoController.InitRecipe(confPath, idxPODL, CalcArgs);
}
/// <summary>
/// Salva ricetta su MongoDB
/// </summary>
@@ -111,6 +112,11 @@ namespace MP.SPEC.Data
return result;
}
public string CalcRecipe(RecipeModel currRecipe)
{
return mongoController.CalcRecipe(currRecipe);
}
#region Public Methods
/// <summary>
+4 -2
View File
@@ -5,7 +5,7 @@
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<RootNamespace>MP.SPEC</RootNamespace>
<Version>6.16.2302.916</Version>
<Version>6.16.2302.1311</Version>
</PropertyGroup>
<ItemGroup>
@@ -17,7 +17,9 @@
</ItemGroup>
<ItemGroup>
<Content Include="Recipe\Fimat\TemplateOutput.tpl" />
<Content Include="Recipe\Fimat\TemplateOutput.tpl">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
+8 -2
View File
@@ -65,7 +65,13 @@ app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
//app.MapBlazorHub();
//app.MapFallbackToPage("/_Host");
app.Run();
+1 -1
View File
@@ -1,5 +1,5 @@
{
"TemplateFile": "TemplateOutput.tpl",
"TemplateFile": "Fimat/TemplateOutput.tpl",
"NumRow": 2,
"HeadConf": {
"ListKeys": {
+7 -4
View File
@@ -2,10 +2,13 @@
"A_Recipe": {
"DesRecipe": {
"DesData": {
[[TemplateHead.json]]
||PlaceholderHeader||
},
"ColRecipe": [
[[TemplateRows.json]]
]
"ColRecipe": [
||SROW:{"ColData":{||
||PlaceholderRows||
||EROW:}}||
]
}
}
}
+112 -1
View File
@@ -1,13 +1,124 @@
# Ricette
- [Ricette](#ricette)
- [Gestione formati e tag x ricette](#gestione-formati-e-tag-x-ricette)
- [Definizione tag ricette](#definizione-tag-ricette)
- [Esempio tracciato Template](#esempio-tracciato-template)
- [Esempio tracciato configurazione complessivo](#esempio-tracciato-configurazione-complessivo)
- [Campi Calcolati](#campi-calcolati)
# Gestione formati e tag x ricette
Nelle ricette ci possono essere campi liberi, campi da enum (da configurare nel json) e campi calcolati
Nelle ricette ci possono essere campi liberi, campi da enum (da configurare nel json) e campi calcolati.
E' utile riportare un esempio di tracciato finale desiderato insieme ad un file template tpl da cui attingere x la realizzazione insieme ai campi definiti x testata e corpo.
In particolare sia per testata che corpo sono indicati casi di dati enumerativi (in modo che sia usato uno tra i valori ammessi)
## Definizione tag ricette
I tag ammessi x le ricette sono di seguito riassunti e definiti:
| Cod | Significato | Definizione |
|-----|-------------|--------------------------------------------|
| C | Calcolato | Campo calcolato (NON modificabile) |
| E | Enum | IdxODL numerico |
| F | Fixed | IdxODL numerico |
| S | Suggested | Campo calcolato e suggerito (modificabile) |
IN particolare gli Enum sono poi da riportare nella struttura degli EnumVal che deve completare i valori di testata o di corpo.
## Esempio tracciato Template
Ecco un esempio di template
```csharp
{
"A_Recipe": {
"DesRecipe": {
"DesData": {
||PlaceholderHeader||
},
"ColRecipe": [
||SROW:{"ColData":{||
||PlaceholderRows||
||EROW":}}||
]
}
}
```
il blocco <code>||PlaceholderHeader||</code> verrà sostituito per intero dai valori di testata.
Il blocco delel righe è invece più complesso e composto da 3 parti:
* nel primo blocco, <code>||SROW:{"ColData":{||</code>, si cerca start riga e si prende il valore compreso tra ||SROW:: e || come testata riga da ripetere
* nel secondo blocco si sostituiscono tutti i valori della riga i-esima
* nel terzo blocco <code>||EROW":}}||</code> si sistema la chiusura della riga (end row)
## Esempio tracciato configurazione complessivo
```json
{
"TemplateFile": "TemplateOutput.tpl",
"NumRow": 2,
"HeadConf": {
"ListKeys": {
"CustDrumCode": "F:",
"Taglio-N": "F:1",
"LotID": "C:IdxPODL",
"OrderCode": "C:CodePODL",
"Prio": "E:Priority",
"DrumType": "E:DrumType",
"Customer": "Tenditalia",
"Design": "DESIGN",
"Quantity-kg": "1.00"
},
"EnumVal": {
"Priority": {
"N": "Normal",
"H": "Hight"
},
"DrumType": {
"1": "Small",
"2": "Medium",
"3": "Big"
}
}
},
"RowsConf": {
"ListKeys": {
"Weight-gr-prev": "F:0.00",
"CompNumber": "C:RowNum",
"ColourCode": "C001",
"Description": "COLOR1",
"TypComp": "E:ColType",
"PartsWeight": "1.00",
"PartsPerc": "0.10",
"Weight-gr": "30.00"
},
"EnumVal": {
"ColType": {
"C": "Color",
"A": "Thickener",
"X": "Auxiliaries"
}
}
}
}
```
Come si può notare, il tracciato di configurazione comprende i seguenti blocchi:
| Blocco | descrizione |
|-------------------|--------------------------------------|
| HeadConf | Configurazione campi testata |
| HeadConf:ListKeys | Elenco chiavi/valori x testata |
| HeadConf:EnumVal | Elenco enumerativi ammessi x testata |
| RowsConf | Configurazione campi riga |
| RowsConf:ListKeys | Elenco chiavi/valori x righe |
| RowsConf:EnumVal | Elenco enumerativi ammessi x righe |
## Campi Calcolati
Binary file not shown.
+1 -1
View File
@@ -1,6 +1,6 @@
<body>
<i>Modulo MAPOSPEC </i>
<h4>Versione: 6.16.2302.916</h4>
<h4>Versione: 6.16.2302.1311</h4>
<br /> Note di rilascio:
<ul>
<li>
+1 -1
View File
@@ -1 +1 @@
6.16.2302.916
6.16.2302.1311
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<item>
<version>6.16.2302.916</version>
<version>6.16.2302.1311</version>
<url>https://nexus.steamware.net/repository/SWS/MP-SPEC/stable/LAST/MP.SPEC.zip</url>
<changelog>https://nexus.steamware.net/repository/SWS/MP-SPEC/stable/LAST/ChangeLog.html</changelog>
<mandatory>false</mandatory>