Models: Add Dtos/
This commit is contained in:
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
45
Elwig/Models/Dtos/DataTable.cs
Normal file
45
Elwig/Models/Dtos/DataTable.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
95
Elwig/Models/Dtos/DeliveryConfirmationData.cs
Normal file
95
Elwig/Models/Dtos/DeliveryConfirmationData.cs
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
Reference in New Issue
Block a user