Models: Add Dtos/

This commit is contained in:
2023-11-12 19:38:36 +01:00
parent 32f229b0a5
commit 2cdde60644
5 changed files with 164 additions and 43 deletions

View File

@ -1,33 +1,25 @@
using Elwig.Helpers; using Elwig.Helpers;
using Elwig.Models.Dtos;
using Elwig.Models.Entities; using Elwig.Models.Entities;
using Microsoft.EntityFrameworkCore;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
namespace Elwig.Documents { namespace Elwig.Documents {
public class DeliveryConfirmation : BusinessDocument { public class DeliveryConfirmation : BusinessDocument {
public Season Season; public Season Season;
public IEnumerable<DeliveryPart> Deliveries; public DeliveryConfirmationData Data;
public string? Text = App.Client.TextDeliveryConfirmation; public string? Text = App.Client.TextDeliveryConfirmation;
public Dictionary<string, (string, int, int, int, int)> MemberBuckets; public Dictionary<string, (string, int, int, int, int)> MemberBuckets;
public DeliveryConfirmation(AppDbContext ctx, int year, Member m, IEnumerable<DeliveryPart>? deliveries = null) : public DeliveryConfirmation(AppDbContext ctx, int year, Member m, DeliveryConfirmationData data) :
base($"Anlieferungsbestätigung {year}", m) { base($"Anlieferungsbestätigung {year}", m) {
Season = ctx.Seasons.Find(year) ?? throw new ArgumentException("invalid season"); Season = ctx.Seasons.Find(year) ?? throw new ArgumentException("invalid season");
ShowDateAndLocation = true; ShowDateAndLocation = true;
UseBillingAddress = true; UseBillingAddress = true;
IncludeSender = true; IncludeSender = true;
DocumentId = $"Anl.-Best. {Season.Year}/{m.MgNr}"; DocumentId = $"Anl.-Best. {Season.Year}/{m.MgNr}";
Deliveries = deliveries ?? ctx.DeliveryParts.FromSqlRaw($""" Data = data;
SELECT p.*
FROM v_delivery v
JOIN delivery_part p ON (p.year, p.did, p.dpnr) = (v.year, v.did, v.dpnr)
WHERE (v.year, v.mgnr) = ({Season.Year}, {m.MgNr})
ORDER BY v.sortid, v.abgewertet ASC, v.attribute_prio DESC, COALESCE(v.attrid, '~'), v.kmw DESC, v.lsnr, v.dpnr
""")
.ToList();
MemberBuckets = ctx.GetMemberBuckets(Season.Year, m.MgNr).GetAwaiter().GetResult(); MemberBuckets = ctx.GetMemberBuckets(Season.Year, m.MgNr).GetAwaiter().GetResult();
} }
} }

View File

@ -41,39 +41,35 @@
</thead> </thead>
<tbody> <tbody>
@{ @{
var lastSortId = ""; var lastVariant = "";
} }
@foreach (var p in Model.Deliveries) { @foreach (var p in Model.Data.Rows) {
var buckets = p.Buckets.Where(b => b.Value > 0).OrderByDescending(b => b.BktNr).ToArray(); var rows = Math.Max(p.Buckets.Length, p.Modifiers.Length + 1);
var rowsBuckets = buckets.Length;
var mods = p.Modifiers.Select(m => m.Name).ToArray();
var rowsMod = mods.Length + 1;
var rows = Math.Max(rowsBuckets, rowsMod);
var first = true; var first = true;
@for (int i = 0; i < rows; i++) { @for (int i = 0; i < rows; i++) {
<tr class="@(first ? "first" : "") @(p.SortId != lastSortId && lastSortId != "" ? "new": "") @(rows > i + 1 ? "trailing" : "")"> <tr class="@(first ? "first" : "") @(p.Variant != lastVariant && lastVariant != "" ? "new": "") @(rows > i + 1 ? "trailing" : "")">
@if (first) { @if (first) {
<td rowspan="@rows">@p.Delivery.LsNr</td> <td rowspan="@rows">@p.LsNr</td>
<td rowspan="@rows">@p.DPNr</td> <td rowspan="@rows">@p.DPNr</td>
<td class="small">@p.Variant.Name</td> <td class="small">@p.Variant</td>
<td class="small">@p.Attribute?.Name</td> <td class="small">@p.Attribute</td>
<td class="small">@p.Quality.Name</td> <td class="small">@p.QualityLevel</td>
<td rowspan="@rows" class="grad">@($"{p.Oe:N0}")</td> <td rowspan="@rows" class="grad">@($"{p.Oe:N0}")</td>
<td rowspan="@rows" class="grad">@($"{p.Kmw:N1}")</td> <td rowspan="@rows" class="grad">@($"{p.Kmw:N1}")</td>
} }
@if (i > 0 && i <= mods.Length) { @if (i > 0 && i <= p.Modifiers.Length) {
<td colspan="3" class="mod">@(mods[i - 1])</td> <td colspan="3" class="mod">@(p.Modifiers[i - 1])</td>
} else if (i > 0) { } else if (i > 0) {
<td colspan="3"></td> <td colspan="3"></td>
} }
@if (i < buckets.Length) { @if (i < p.Buckets.Length) {
var bucket = buckets[i]; var bucket = p.Buckets[i];
<td class="geb">@(bucket.Discr == "_" ? "ungeb." : $"geb. {p.SortId}{bucket.Discr}"):</td> <td class="geb">@bucket.Item1:</td>
<td class="weight">@($"{bucket.Value:N0}")</td> <td class="weight">@($"{bucket.Item2:N0}")</td>
} else { } else {
<td colspan="2"></td> <td colspan="2"></td>
} }
@if (i == buckets.Length - 1) { @if (i == p.Buckets.Length - 1) {
<td class="weight">@($"{p.Weight:N0}")</td> <td class="weight">@($"{p.Weight:N0}")</td>
} else { } else {
<td></td> <td></td>
@ -83,12 +79,12 @@
first = false; first = false;
} }
</tr> </tr>
lastSortId = p.SortId; lastVariant = p.Variant;
} }
} }
<tr class="sum"> <tr class="sum">
<td colspan="8">Gesamt:</td> <td colspan="8">Gesamt:</td>
<td colspan="2" class="weight">@($"{Model.Deliveries.Sum(p => p.Weight):N0}")</td> <td colspan="2" class="weight">@($"{Model.Data.Rows.Sum(p => p.Weight):N0}")</td>
<td></td> <td></td>
</tr> </tr>
</tbody> </tbody>

View File

@ -0,0 +1,45 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace Elwig.Models.Dtos {
public class DataTable<T> {
public string Name { get; set; }
public string FullName { get; set; }
public IEnumerable<T> Rows { get; private set; }
public int RowNum => Rows.Count();
public IEnumerable<string> ColumnNames => _fieldMap.Select(m => m.Item2);
public int ColNum => ColumnNames.Count();
private readonly FieldInfo[] _fields;
private readonly (FieldInfo, string)[] _fieldMap;
public DataTable(string name, string fullName, IEnumerable<T> rows, IEnumerable<(string, string)>? colNames = null) {
_fields = typeof(T).GetFields();
var dict = colNames?.ToDictionary(n => n.Item1, n => n.Item2);
_fieldMap = (dict == null ? _fields.Select(f => (f, f.Name)) : _fields.Select(f => (f, dict[f.Name]))).ToArray();
Name = name;
FullName = fullName;
Rows = rows;
}
public DataTable(string name, IEnumerable<T> rows, IEnumerable<(string, string)>? colNames = null) :
this(name, name, rows, colNames) { }
protected IEnumerable<(string, object?)> GetNamedRowData(T row) {
return _fieldMap.Select(i => (i.Item2, i.Item1.GetValue(row)));
}
protected IEnumerable<object?> GetRowData(T row) {
return GetNamedRowData(row).Select(i => i.Item2);
}
public IEnumerable<IEnumerable<object?>> GetData() {
return Rows.Select(GetRowData);
}
public IEnumerable<IEnumerable<(string, object?)>> GetNamedData() {
return Rows.Select(GetNamedRowData);
}
}
}

View File

@ -0,0 +1,95 @@
using Elwig.Models.Entities;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Elwig.Models.Dtos {
public class DeliveryConfirmationData : DataTable<DeliveryConfirmationRow> {
private static readonly (string, string)[] _fields = new[] {
("LsNr", "LsNr."),
("DPNr", "Pos."),
("Variant", "Sorte"),
("Attribute", "Attribut"),
("Modifiers", "Zu-/Abschläge"),
("QualityLevel", "Qualitätsstufe"),
("GradationOe", "°Oe"),
("GradationKmw", "°KMW"),
("Commitment", "Flächenbindung"),
("Weight", "Gewicht"),
};
public int MgNr { get; private set; }
private DeliveryConfirmationData(IEnumerable<DeliveryConfirmationRow> rows, int mgnr) :
base("Anl.-Best.", "Anlieferungsbestätigung", rows, _fields) {
MgNr = mgnr;
}
public static async Task<IDictionary<int, DeliveryConfirmationData>> ForSeason(DbSet<DeliveryPart> table, int year) {
return (await FromDbSet(table, year).ToListAsync())
.GroupBy(
p => p.Delivery.MgNr,
p => new DeliveryConfirmationRow(p),
(k, g) => new DeliveryConfirmationData(g, k)
).ToDictionary(d => d.MgNr, d => d);
}
public static async Task<DeliveryConfirmationData> ForMember(DbSet<DeliveryPart> table, int year, int mgnr) {
return new DeliveryConfirmationData((await FromDbSet(table, year, mgnr).ToListAsync()).Select(p => new DeliveryConfirmationRow(p)), mgnr);
}
private static IQueryable<DeliveryPart> FromDbSet(DbSet<DeliveryPart> table, int? year = null, int? mgnr = null) {
var y = year?.ToString() ?? "NULL";
var m = mgnr?.ToString() ?? "NULL";
return table.FromSqlRaw($"""
SELECT p.*
FROM v_delivery v
JOIN delivery_part p ON (p.year, p.did, p.dpnr) = (v.year, v.did, v.dpnr)
WHERE (p.year = {y} OR {y} IS NULL) AND (v.mgnr = {m} OR {m} IS NULL)
ORDER BY p.year, v.mgnr, v.sortid, v.abgewertet ASC, v.attribute_prio DESC, COALESCE(v.attrid, '~'), v.kmw DESC, v.lsnr, v.dpnr
""")
.Include(p => p.Delivery)
.Include(p => p.Variant)
.Include(p => p.Attribute)
.Include(p => p.Quality)
.Include(p => p.Buckets)
.Include(p => p.PartModifiers).ThenInclude(m => m.Modifier);
}
}
public class DeliveryConfirmationRow {
public string LsNr { get; set; }
public int DPNr { get; set; }
public string Variant { get; set; }
public string? Attribute { get; set; }
public string QualityLevel { get; set; }
public double Oe { get; set; }
public double Kmw { get; set; }
public string[] Modifiers { get; set; }
public int Weight { get; set; }
public (string, int)[] Buckets { get; set; }
public DeliveryConfirmationRow(DeliveryPart p) {
var d = p.Delivery;
LsNr = d.LsNr;
DPNr = p.DPNr;
Variant = p.Variant.Name;
Attribute = p.Attribute?.Name;
QualityLevel = p.Quality.Name;
Oe = p.Oe;
Kmw = p.Kmw;
Modifiers = p.Modifiers
.Select(m => m.Name)
.ToArray();
Weight = p.Weight;
Buckets = p.Buckets
.Where(b => b.Value > 0)
.OrderByDescending(b => b.BktNr)
.Select(b => (b.Discr == "_" ? "ungeb." : $"geb. {p.SortId}{b.Discr}", b.Value))
.ToArray();
}
}
}

View File

@ -1,4 +1,5 @@
using Elwig.Documents; using Elwig.Documents;
using Elwig.Models.Dtos;
using Elwig.Models.Entities; using Elwig.Models.Entities;
using Elwig.Windows; using Elwig.Windows;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@ -84,17 +85,9 @@ namespace Elwig.Dialogs {
list = list.Where((_, n) => n % 10 == r); list = list.Where((_, n) => n % 10 == r);
} }
var deliveries = await Context.DeliveryParts.FromSqlRaw($""" var data = await DeliveryConfirmationData.ForSeason(Context.DeliveryParts, Year);
SELECT p.*
FROM v_delivery v
JOIN delivery_part p ON (p.year, p.did, p.dpnr) = (v.year, v.did, v.dpnr)
WHERE v.year = {Year}
ORDER BY v.sortid, v.abgewertet ASC, v.attribute_prio DESC, COALESCE(v.attrid, '~'), v.kmw DESC, v.lsnr, v.dpnr
""")
.ToListAsync();
using var doc = Document.Merge(list.Select(m => using var doc = Document.Merge(list.Select(m =>
new DeliveryConfirmation(Context, Year, m, deliveries.Where(d => d.Delivery.MgNr == m.MgNr).ToList()) { new DeliveryConfirmation(Context, Year, m, data[m.MgNr]) {
//DoubleSided = true //DoubleSided = true
} }
)); ));