MemberList: Allow filtering area commitments
This commit is contained in:
@ -1,5 +1,6 @@
|
|||||||
using Elwig.Models.Dtos;
|
using Elwig.Models.Dtos;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Elwig.Documents {
|
namespace Elwig.Documents {
|
||||||
public class MemberList : Document {
|
public class MemberList : Document {
|
||||||
@ -9,9 +10,17 @@ namespace Elwig.Documents {
|
|||||||
public string Filter;
|
public string Filter;
|
||||||
public IEnumerable<MemberListRow> Members;
|
public IEnumerable<MemberListRow> Members;
|
||||||
|
|
||||||
|
public string[] AreaComFilters;
|
||||||
|
public bool FilterAreaComs => AreaComFilters.Length > 0;
|
||||||
|
|
||||||
public MemberList(string filter, IEnumerable<MemberListRow> members) : base(Name) {
|
public MemberList(string filter, IEnumerable<MemberListRow> members) : base(Name) {
|
||||||
Filter = filter;
|
Filter = filter;
|
||||||
Members = members;
|
Members = members;
|
||||||
|
AreaComFilters = [..members
|
||||||
|
.SelectMany(m => m.AreaCommitmentsFiltered)
|
||||||
|
.Select(c => c.VtrgId)
|
||||||
|
.Distinct()
|
||||||
|
.Order()];
|
||||||
}
|
}
|
||||||
|
|
||||||
public MemberList(string filter, MemberListData data) :
|
public MemberList(string filter, MemberListData data) :
|
||||||
|
@ -8,30 +8,61 @@
|
|||||||
<h2>@Model.Filter</h2>
|
<h2>@Model.Filter</h2>
|
||||||
<table class="members">
|
<table class="members">
|
||||||
<colgroup>
|
<colgroup>
|
||||||
<col style="width: 8mm;"/>
|
|
||||||
<col style="width: 42mm;"/>
|
|
||||||
<col style="width: 40mm;"/>
|
|
||||||
<col style="width: 8mm;"/>
|
<col style="width: 8mm;"/>
|
||||||
<col style="width: 20mm;"/>
|
@if (Model.AreaComFilters.Length > 1) {
|
||||||
|
<col style="width: 38mm;"/>
|
||||||
|
} else {
|
||||||
|
<col style="width: 42mm;"/>
|
||||||
|
}
|
||||||
|
@if (Model.AreaComFilters.Length > 1) {
|
||||||
|
<col style="width: 36mm;"/>
|
||||||
|
} else {
|
||||||
|
<col style="width: 40mm;"/>
|
||||||
|
}
|
||||||
|
<col style="width: 8mm;"/>
|
||||||
|
@if (Model.AreaComFilters.Length > 1) {
|
||||||
|
<col style="width: 18mm;"/>
|
||||||
|
} else {
|
||||||
|
<col style="width: 20mm;"/>
|
||||||
|
}
|
||||||
<col style="width: 12mm;"/>
|
<col style="width: 12mm;"/>
|
||||||
<col style="width: 5mm;" />
|
<col style="width: 5mm;"/>
|
||||||
<col style="width: 18mm;"/>
|
@if (Model.AreaComFilters.Length > 1) {
|
||||||
|
<col style="width: 16mm;"/>
|
||||||
|
} else {
|
||||||
|
<col style="width: 18mm;"/>
|
||||||
|
}
|
||||||
<col style="width: 12mm;"/>
|
<col style="width: 12mm;"/>
|
||||||
|
@if (Model.AreaComFilters.Length > 1) {
|
||||||
|
<col style="width: 12mm;"/>
|
||||||
|
}
|
||||||
</colgroup>
|
</colgroup>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th rowspan="2">Nr.</th>
|
@{
|
||||||
<th rowspan="2" style="text-align: left;">Name</th>
|
var headerSpan = Model.FilterAreaComs ? 3 : 2;
|
||||||
<th rowspan="2" style="text-align: left;">Adresse</th>
|
}
|
||||||
<th rowspan="2">PLZ</th>
|
<th rowspan="@headerSpan">Nr.</th>
|
||||||
<th rowspan="2" style="text-align: left;">Ort</th>
|
<th rowspan="@headerSpan" style="text-align: left;">Name</th>
|
||||||
<th rowspan="2">Betr.-Nr.</th>
|
<th rowspan="@headerSpan" style="text-align: left;">Adresse</th>
|
||||||
<th rowspan="2">GA</th>
|
<th rowspan="@headerSpan">PLZ</th>
|
||||||
<th rowspan="2" style="text-align: left;">Stamm-KG</th>
|
<th rowspan="@headerSpan" style="text-align: left;">Ort</th>
|
||||||
<th>Geb. Fl.</th>
|
<th rowspan="@headerSpan">Betr.-Nr.</th>
|
||||||
|
<th rowspan="@headerSpan">GA</th>
|
||||||
|
<th rowspan="@headerSpan" style="text-align: left;">Stamm-KG</th>
|
||||||
|
<th colspan="@(Model.FilterAreaComs ? Model.AreaComFilters.Length : 1)">Geb. Fl.</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
@if (Model.FilterAreaComs) {
|
||||||
|
<tr>
|
||||||
|
@foreach (var vtrgId in Model.AreaComFilters) {
|
||||||
|
<th>@vtrgId</th>
|
||||||
|
}
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
<tr>
|
<tr>
|
||||||
<th class="unit">[m²]</th>
|
@for (int i = 0; i < Math.Max(Model.AreaComFilters.Length, 1); i++) {
|
||||||
|
<th class="unit">[m²]</th>
|
||||||
|
}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="small">
|
<tbody class="small">
|
||||||
@ -40,22 +71,28 @@
|
|||||||
}
|
}
|
||||||
@foreach (var m in Model.Members) {
|
@foreach (var m in Model.Members) {
|
||||||
if (lastBranch != null && m.Branch != lastBranch) {
|
if (lastBranch != null && m.Branch != lastBranch) {
|
||||||
<tr class="spacing"><td colspan="9"></td></tr>
|
<tr class="spacing"><td colspan="@(8 + Math.Max(Model.AreaComFilters.Length, 1))"></td></tr>
|
||||||
<tr class="header">
|
<tr class="header">
|
||||||
<th colspan="9">@m.Branch</th>
|
<th colspan="@(8 + Math.Max(Model.AreaComFilters.Length, 1))">@m.Branch</th>
|
||||||
</tr>
|
</tr>
|
||||||
lastBranch = m.Branch;
|
lastBranch = m.Branch;
|
||||||
}
|
}
|
||||||
<tr>
|
<tr>
|
||||||
<td class="number" rowspan="@(m.BillingName != null ? 2 : 1)">@m.MgNr</td>
|
<td class="number" rowspan="@(m.BillingName != null ? 2 : 1)">@m.MgNr</td>
|
||||||
<td>@m.Name1.Replace('ß', 'ẞ').ToUpper() @m.Name2</td>
|
<td>@m.AdminName1 @m.Name2</td>
|
||||||
<td>@m.Address</td>
|
<td>@m.Address</td>
|
||||||
<td>@m.Plz</td>
|
<td>@m.Plz</td>
|
||||||
<td class="tiny">@m.Locality</td>
|
<td class="tiny">@m.Locality</td>
|
||||||
<td>@m.LfbisNr</td>
|
<td>@m.LfbisNr</td>
|
||||||
<td class="number">@m.BusinessShares</td>
|
<td class="number">@m.BusinessShares</td>
|
||||||
<td class="tiny">@m.DefaultKg</td>
|
<td class="tiny">@m.DefaultKg</td>
|
||||||
<td class="number">@($"{m.AreaCommitment:N0}")</td>
|
@if (Model.AreaComFilters.Length > 0) {
|
||||||
|
foreach (var v in Model.AreaComFilters) {
|
||||||
|
<td class="number">@($"{m.AreaCommitmentsFiltered.FirstOrDefault(c => c.VtrgId == v).Area:N0}")</td>
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
<td class="number">@($"{m.AreaCommitment:N0}")</td>
|
||||||
|
}
|
||||||
</tr>
|
</tr>
|
||||||
if (m.BillingName != null) {
|
if (m.BillingName != null) {
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -31,6 +31,7 @@ namespace Elwig.Models.Dtos {
|
|||||||
("EntryDate", "Eintritt", null, 20),
|
("EntryDate", "Eintritt", null, 20),
|
||||||
("ExitDate", "Austritt", null, 20),
|
("ExitDate", "Austritt", null, 20),
|
||||||
("AreaCommitment", "geb. Fläche", "m²", 20),
|
("AreaCommitment", "geb. Fläche", "m²", 20),
|
||||||
|
("AreaCommitmentsFiltered", "geb. Fläche", "Vtrg.|m²", 30),
|
||||||
("UstIdNr", "UID", null, 25),
|
("UstIdNr", "UID", null, 25),
|
||||||
("Iban", "IBAN", null, 45),
|
("Iban", "IBAN", null, 45),
|
||||||
("Bic", "BIC", null, 30),
|
("Bic", "BIC", null, 30),
|
||||||
@ -45,8 +46,8 @@ namespace Elwig.Models.Dtos {
|
|||||||
base(MemberList.Name, MemberList.Name, string.Join(" / ", filterNames), rows, FieldNames) {
|
base(MemberList.Name, MemberList.Name, string.Join(" / ", filterNames), rows, FieldNames) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static async Task<MemberListData> FromQuery(IQueryable<Member> query, List<string> filterNames) {
|
public static async Task<MemberListData> FromQuery(IQueryable<Member> query, List<string> filterNames, IEnumerable<string> filterAreaCom) {
|
||||||
var areaCom = await query.ToDictionaryAsync(m => m.MgNr, m => Utils.ActiveAreaCommitments(m.AreaCommitments).Sum(c => c.Area));
|
var areaComs = await query.ToDictionaryAsync(m => m.MgNr, m => Utils.ActiveAreaCommitments(m.AreaCommitments));
|
||||||
return new((await query
|
return new((await query
|
||||||
.Include(m => m.DefaultWbKg!.AtKg)
|
.Include(m => m.DefaultWbKg!.AtKg)
|
||||||
.Include(m => m.Branch)
|
.Include(m => m.Branch)
|
||||||
@ -55,13 +56,17 @@ namespace Elwig.Models.Dtos {
|
|||||||
.Include(m => m.TelephoneNumbers)
|
.Include(m => m.TelephoneNumbers)
|
||||||
.Include(m => m.EmailAddresses)
|
.Include(m => m.EmailAddresses)
|
||||||
.AsSplitQuery()
|
.AsSplitQuery()
|
||||||
.ToListAsync()).Select(m => new MemberListRow(m, areaCom[m.MgNr])), filterNames);
|
.ToListAsync()).Select(m => new MemberListRow(m,
|
||||||
|
areaComs[m.MgNr].Sum(c => c.Area),
|
||||||
|
areaComs[m.MgNr].Where(c => filterAreaCom.Contains(c.VtrgId)).GroupBy(c => c.VtrgId).ToDictionary(g => g.Key, g => g.Sum(c => c.Area)))),
|
||||||
|
filterNames);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class MemberListRow {
|
public class MemberListRow {
|
||||||
public int MgNr;
|
public int MgNr;
|
||||||
public string? Name1;
|
public string? Name1;
|
||||||
|
public string? AdminName1;
|
||||||
public string? Name2;
|
public string? Name2;
|
||||||
public string? DefaultKg;
|
public string? DefaultKg;
|
||||||
public string? Branch;
|
public string? Branch;
|
||||||
@ -78,6 +83,7 @@ namespace Elwig.Models.Dtos {
|
|||||||
public string? Iban;
|
public string? Iban;
|
||||||
public string? Bic;
|
public string? Bic;
|
||||||
public int? AreaCommitment;
|
public int? AreaCommitment;
|
||||||
|
public (string VtrgId, int Area)[] AreaCommitmentsFiltered;
|
||||||
public bool IsBuchführend;
|
public bool IsBuchführend;
|
||||||
public bool IsOrganic;
|
public bool IsOrganic;
|
||||||
public bool IsActive;
|
public bool IsActive;
|
||||||
@ -89,9 +95,10 @@ namespace Elwig.Models.Dtos {
|
|||||||
public string? AdditionalContact;
|
public string? AdditionalContact;
|
||||||
public string? Comment;
|
public string? Comment;
|
||||||
|
|
||||||
public MemberListRow(Member m, int? areaCom = null) {
|
public MemberListRow(Member m, int? areaCom = null, Dictionary<string, int>? filtered = null) {
|
||||||
MgNr = m.MgNr;
|
MgNr = m.MgNr;
|
||||||
Name1 = m.Name;
|
Name1 = m.Name;
|
||||||
|
AdminName1 = m.AdministrativeName1;
|
||||||
Name2 = m.AdministrativeName2;
|
Name2 = m.AdministrativeName2;
|
||||||
DefaultKg = m.DefaultKg?.Name;
|
DefaultKg = m.DefaultKg?.Name;
|
||||||
Branch = m.Branch?.Name;
|
Branch = m.Branch?.Name;
|
||||||
@ -125,6 +132,7 @@ namespace Elwig.Models.Dtos {
|
|||||||
.Concat(m.EmailAddresses.OrderBy(a => a.Nr).Select(a => a.Address).Except([EmailAddress])));
|
.Concat(m.EmailAddresses.OrderBy(a => a.Nr).Select(a => a.Address).Except([EmailAddress])));
|
||||||
Comment = m.Comment;
|
Comment = m.Comment;
|
||||||
AreaCommitment = areaCom == 0 ? null : areaCom;
|
AreaCommitment = areaCom == 0 ? null : areaCom;
|
||||||
|
AreaCommitmentsFiltered = filtered != null ? filtered.OrderBy(f => f.Key).Select(f => (f.Key, f.Value)).ToArray() : [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -420,7 +420,7 @@ namespace Elwig.Services {
|
|||||||
if (d.ShowDialog() == true) {
|
if (d.ShowDialog() == true) {
|
||||||
Mouse.OverrideCursor = Cursors.AppStarting;
|
Mouse.OverrideCursor = Cursors.AppStarting;
|
||||||
try {
|
try {
|
||||||
var data = await MemberListData.FromQuery(query, filterNames);
|
var data = await MemberListData.FromQuery(query, filterNames, filterNames.Where(f => f.StartsWith("Flächenbindung")).Select(f => f.Split(' ')[^1]));
|
||||||
using var ods = new OdsFile(d.FileName);
|
using var ods = new OdsFile(d.FileName);
|
||||||
await ods.AddTable(data);
|
await ods.AddTable(data);
|
||||||
} catch (Exception exc) {
|
} catch (Exception exc) {
|
||||||
@ -487,7 +487,7 @@ namespace Elwig.Services {
|
|||||||
} else {
|
} else {
|
||||||
Mouse.OverrideCursor = Cursors.AppStarting;
|
Mouse.OverrideCursor = Cursors.AppStarting;
|
||||||
try {
|
try {
|
||||||
var data = await MemberListData.FromQuery(query, filterNames);
|
var data = await MemberListData.FromQuery(query, filterNames, filterNames.Where(f => f.StartsWith("Flächenbindung")).Select(f => f.Split(' ')[^1]));
|
||||||
using var doc = new MemberList(string.Join(" / ", filterNames), data);
|
using var doc = new MemberList(string.Join(" / ", filterNames), data);
|
||||||
await Utils.ExportDocument(doc, mode);
|
await Utils.ExportDocument(doc, mode);
|
||||||
} catch (Exception exc) {
|
} catch (Exception exc) {
|
||||||
|
@ -9,7 +9,7 @@ namespace Tests.DocumentTests {
|
|||||||
[Test]
|
[Test]
|
||||||
public async Task Test_01_TwoMembers() {
|
public async Task Test_01_TwoMembers() {
|
||||||
using var ctx = new AppDbContext();
|
using var ctx = new AppDbContext();
|
||||||
var data = await MemberListData.FromQuery(ctx.Members, []);
|
var data = await MemberListData.FromQuery(ctx.Members, [], []);
|
||||||
using var doc = new MemberList("Alle Mitglieder", data);
|
using var doc = new MemberList("Alle Mitglieder", data);
|
||||||
var text = await Utils.GeneratePdfText(doc, true);
|
var text = await Utils.GeneratePdfText(doc, true);
|
||||||
var table = Utils.ExtractTable(text);
|
var table = Utils.ExtractTable(text);
|
||||||
|
Reference in New Issue
Block a user