Ricetta:
- completata serializzazione ricetta in modo parametrico/composto
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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
@@ -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,5 +1,5 @@
|
||||
{
|
||||
"TemplateFile": "TemplateOutput.tpl",
|
||||
"TemplateFile": "Fimat/TemplateOutput.tpl",
|
||||
"NumRow": 2,
|
||||
"HeadConf": {
|
||||
"ListKeys": {
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
"A_Recipe": {
|
||||
"DesRecipe": {
|
||||
"DesData": {
|
||||
[[TemplateHead.json]]
|
||||
||PlaceholderHeader||
|
||||
},
|
||||
"ColRecipe": [
|
||||
[[TemplateRows.json]]
|
||||
]
|
||||
"ColRecipe": [
|
||||
||SROW:{"ColData":{||
|
||||
||PlaceholderRows||
|
||||
||EROW:}}||
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
+112
-1
@@ -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,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 @@
|
||||
6.16.2302.916
|
||||
6.16.2302.1311
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user