Compare commits
	
		
			10 Commits
		
	
	
		
			v0.5.0
			...
			ed78c8facb
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| ed78c8facb | |||
| b096163ed3 | |||
| 486655d071 | |||
| d485f0fda1 | |||
| 8509f04d4d | |||
| 3ee7a6e75e | |||
| 8b96b65c8c | |||
| db8a449785 | |||
| 2cdde60644 | |||
| 32f229b0a5 | 
| @@ -1,5 +1,5 @@ | |||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
|  |  | ||||||
| namespace Elwig.Documents { | namespace Elwig.Documents { | ||||||
|     public abstract class BusinessDocument : Document { |     public abstract class BusinessDocument : Document { | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
|  |  | ||||||
| namespace Elwig.Documents { | namespace Elwig.Documents { | ||||||
|     public class BusinessLetter : BusinessDocument { |     public class BusinessLetter : BusinessDocument { | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Linq; | using System.Linq; | ||||||
|   | |||||||
| @@ -1,33 +1,25 @@ | |||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
| using Elwig.Models; | using Elwig.Models.Dtos; | ||||||
| using Microsoft.EntityFrameworkCore; | using Elwig.Models.Entities; | ||||||
| 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.Gradation.Oe:N0}")</td> | ||||||
|                             <td rowspan="@rows" class="grad">@($"{p.Kmw:N1}")</td> |                             <td rowspan="@rows" class="grad">@($"{p.Gradation.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.Name:</td> | ||||||
|                             <td class="weight">@($"{bucket.Value:N0}")</td> |                             <td class="weight">@($"{bucket.Value: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> | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
|  |  | ||||||
| namespace Elwig.Documents { | namespace Elwig.Documents { | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
|  |  | ||||||
| namespace Elwig.Documents { | namespace Elwig.Documents { | ||||||
|     public class Letterhead : BusinessDocument { |     public class Letterhead : BusinessDocument { | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using System.IO; | using System.IO; | ||||||
| @@ -9,6 +9,7 @@ using Microsoft.Extensions.Logging; | |||||||
| using Microsoft.Data.Sqlite; | using Microsoft.Data.Sqlite; | ||||||
| using System.Text.RegularExpressions; | using System.Text.RegularExpressions; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
|  | using Elwig.Models.Dtos; | ||||||
|  |  | ||||||
| namespace Elwig.Helpers { | namespace Elwig.Helpers { | ||||||
|     public class AppDbContext : DbContext { |     public class AppDbContext : DbContext { | ||||||
| @@ -45,6 +46,10 @@ namespace Elwig.Helpers { | |||||||
|         public DbSet<PaymentMember> MemberPayments { get; private set; } |         public DbSet<PaymentMember> MemberPayments { get; private set; } | ||||||
|         public DbSet<Credit> Credits { get; private set; } |         public DbSet<Credit> Credits { get; private set; } | ||||||
|  |  | ||||||
|  |         public DbSet<OverUnderDeliveryRow> OverUnderDeliveryRows { get; private set; } | ||||||
|  |         public DbSet<AreaComUnderDeliveryRowSingle> AreaComUnderDeliveryRows { get; private set; } | ||||||
|  |         public DbSet<MemberDeliveryPerVariantRowSingle> MemberDeliveryPerVariantRows { get; private set; } | ||||||
|  |  | ||||||
|         private readonly StreamWriter? LogFile = null; |         private readonly StreamWriter? LogFile = null; | ||||||
|         public static DateTime LastWriteTime => File.GetLastWriteTime(App.Config.DatabaseFile); |         public static DateTime LastWriteTime => File.GetLastWriteTime(App.Config.DatabaseFile); | ||||||
|         public DateTime SavedLastWriteTime { get; private set; } |         public DateTime SavedLastWriteTime { get; private set; } | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Linq; | using System.Linq; | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
| using Microsoft.Data.Sqlite; | using Microsoft.Data.Sqlite; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Linq; | using System.Linq; | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| using Elwig.Helpers.Billing; | using Elwig.Helpers.Billing; | ||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.IO; | using System.IO; | ||||||
|   | |||||||
							
								
								
									
										268
									
								
								Elwig/Helpers/Export/Ods.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										268
									
								
								Elwig/Helpers/Export/Ods.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,268 @@ | |||||||
|  | using Elwig.Models.Dtos; | ||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder; | ||||||
|  | using System.IO; | ||||||
|  | using System.IO.Compression; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  |  | ||||||
|  | namespace Elwig.Helpers.Export { | ||||||
|  |     public class OdsFile : IDisposable { | ||||||
|  |  | ||||||
|  |         protected readonly string FileName; | ||||||
|  |         protected readonly ZipArchive ZipArchive; | ||||||
|  |         protected StreamWriter? Content; | ||||||
|  |         private readonly List<string> _tables; | ||||||
|  |  | ||||||
|  |         public OdsFile(string filename) { | ||||||
|  |             FileName = filename; | ||||||
|  |             File.Delete(filename); | ||||||
|  |             ZipArchive = ZipFile.Open(FileName, ZipArchiveMode.Create); | ||||||
|  |             _tables = new(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public void Dispose() { | ||||||
|  |             AddTrailer().GetAwaiter().GetResult(); | ||||||
|  |             ZipArchive?.Dispose(); | ||||||
|  |             GC.SuppressFinalize(this); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private async Task AddHeader() { | ||||||
|  |             var mimetype = ZipArchive.CreateEntry("mimetype", CompressionLevel.NoCompression); | ||||||
|  |             using (var writer = new StreamWriter(mimetype.Open(), Utils.UTF8)) { | ||||||
|  |                 await writer.WriteAsync("application/vnd.oasis.opendocument.spreadsheet"); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             var manifest = ZipArchive.CreateEntry("META-INF/manifest.xml"); | ||||||
|  |             using (var writer = new StreamWriter(manifest.Open(), Utils.UTF8)) { | ||||||
|  |                 await writer.WriteAsync(""" | ||||||
|  |                     <?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||||||
|  |                     <manifest:manifest xmlns:manifest="urn:oasis:names:tc:opendocument:xmlns:manifest:1.0" manifest:version="1.3"> | ||||||
|  |                      <manifest:file-entry manifest:full-path="/" manifest:version="1.3" manifest:media-type="application/vnd.oasis.opendocument.spreadsheet"/> | ||||||
|  |                      <manifest:file-entry manifest:full-path="content.xml" manifest:media-type="text/xml"/> | ||||||
|  |                      <manifest:file-entry manifest:full-path="styles.xml" manifest:media-type="text/xml"/> | ||||||
|  |                      <manifest:file-entry manifest:full-path="meta.xml" manifest:media-type="text/xml"/> | ||||||
|  |                      <manifest:file-entry manifest:full-path="settings.xml" manifest:media-type="text/xml"/> | ||||||
|  |                     </manifest:manifest> | ||||||
|  |  | ||||||
|  |                     """); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             var styles = ZipArchive.CreateEntry("styles.xml"); | ||||||
|  |             using (var writer = new StreamWriter(styles.Open(), Utils.UTF8)) { | ||||||
|  |                 await writer.WriteAsync(""" | ||||||
|  |                     <?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||||||
|  |                     <office:document-styles xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" office:version="1.3"> | ||||||
|  |                     </office:document-styles> | ||||||
|  |  | ||||||
|  |                     """); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             var meta = ZipArchive.CreateEntry("meta.xml"); | ||||||
|  |             using (var writer = new StreamWriter(meta.Open(), Utils.UTF8)) { | ||||||
|  |                 var now = DateTime.UtcNow.ToString("yyyy-MM-ddTHH:mm:ssZ"); | ||||||
|  |                 await writer.WriteAsync($""" | ||||||
|  |                     <?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||||||
|  |                     <office:document-meta xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" xmlns:dc="http://purl.org/dc/elements/1.1/" office:version="1.3"> | ||||||
|  |                      <office:meta> | ||||||
|  |                       <meta:generator>Elwig {App.Version}</meta:generator> | ||||||
|  |                       <meta:initial-creator>Elwig</meta:initial-creator> | ||||||
|  |                       <dc:creator>Elwig</dc:creator> | ||||||
|  |                       <meta:creation-date>{now}</meta:creation-date> | ||||||
|  |                       <dc:date>{now}</dc:date> | ||||||
|  |                      </office:meta> | ||||||
|  |                     </office:document-meta> | ||||||
|  |  | ||||||
|  |                     """); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             var content = ZipArchive.CreateEntry("content.xml"); | ||||||
|  |             Content = new StreamWriter(content.Open(), Utils.UTF8); | ||||||
|  |             await Content.WriteAsync(""" | ||||||
|  |                 <?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||||||
|  |                 <office:document-content xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0" xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" office:version="1.3"> | ||||||
|  |                  <office:automatic-styles> | ||||||
|  |                   <style:default-style style:family="table-cell"> | ||||||
|  |                    <style:text-properties fo:language="de" fo:country="AT"/> | ||||||
|  |                   </style:default-style> | ||||||
|  |                   <style:style style:name="default" style:family="table-cell"> | ||||||
|  |                    <style:table-cell-properties style:vertical-align="top"/> | ||||||
|  |                   </style:style> | ||||||
|  |  | ||||||
|  |                 """); | ||||||
|  |  | ||||||
|  |             for (int i = 1; i <= 100; i++) { | ||||||
|  |                 await Content.WriteAsync($"  <style:style style:name=\"colw{i}\" style:family=\"table-column\"><style:table-column-properties style:column-width=\"{i}mm\"/></style:style>\r\n"); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             await Content.WriteAsync(""" | ||||||
|  |                   <style:style style:name="header" style:family="table-cell" style:parent-style-name="default"> | ||||||
|  |                    <style:table-cell-properties style:text-align-source="fix" style:repeat-content="false"/> | ||||||
|  |                    <style:paragraph-properties fo:text-align="center"/> | ||||||
|  |                    <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"  fo:font-size="16pt"/> | ||||||
|  |                   </style:style> | ||||||
|  |                   <style:style style:name="th" style:family="table-cell" style:parent-style-name="default"> | ||||||
|  |                    <style:table-cell-properties style:text-align-source="fix" style:repeat-content="false" style:vertical-align="middle"/> | ||||||
|  |                    <style:paragraph-properties fo:text-align="center"/> | ||||||
|  |                    <style:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/> | ||||||
|  |                   </style:style> | ||||||
|  |                   <number:number-style style:name="nperc"> | ||||||
|  |                    <number:number number:decimal-places="1" number:min-decimal-places="1" number:min-integer-digits="1"/> | ||||||
|  |                   </number:number-style> | ||||||
|  |                   <style:style style:name="perc" style:family="table-cell" style:parent-style-name="default" style:data-style-name="nperc"/> | ||||||
|  |                  </office:automatic-styles> | ||||||
|  |                  <office:body> | ||||||
|  |                   <office:spreadsheet> | ||||||
|  |                    <table:calculation-settings table:case-sensitive="false" table:search-criteria-must-apply-to-whole-cell="true" table:use-wildcards="true" table:use-regular-expressions="false" table:automatic-find-labels="false"/> | ||||||
|  |  | ||||||
|  |                 """); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private async Task AddTrailer() { | ||||||
|  |             if (Content == null) await AddHeader(); | ||||||
|  |             if (Content == null) return; | ||||||
|  |  | ||||||
|  |             await Content.WriteAsync(""" | ||||||
|  |                   </office:spreadsheet> | ||||||
|  |                  </office:body> | ||||||
|  |                 </office:document-content> | ||||||
|  |  | ||||||
|  |                 """); | ||||||
|  |             Content.Close(); | ||||||
|  |             Content.Dispose(); | ||||||
|  |             Content = null; | ||||||
|  |  | ||||||
|  |             var settings = ZipArchive.CreateEntry("settings.xml"); | ||||||
|  |             using (var writer = new StreamWriter(settings.Open(), Utils.UTF8)) { | ||||||
|  |                 await writer.WriteAsync(""" | ||||||
|  |                     <?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||||||
|  |                     <office:document-settings xmlns:config="urn:oasis:names:tc:opendocument:xmlns:config:1.0" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ooo="http://openoffice.org/2004/office" xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" office:version="1.3"> | ||||||
|  |                      <office:settings> | ||||||
|  |                       <config:config-item-set config:name="ooo:view-settings"> | ||||||
|  |                        <config:config-item-map-indexed config:name="Views"> | ||||||
|  |                         <config:config-item-map-entry> | ||||||
|  |                          <config:config-item-map-named config:name="Tables"> | ||||||
|  |  | ||||||
|  |                     """); | ||||||
|  |  | ||||||
|  |                 foreach (var tbl in _tables) { | ||||||
|  |                     await writer.WriteAsync($""" | ||||||
|  |                               <config:config-item-map-entry config:name="{tbl}"> | ||||||
|  |                                <config:config-item config:name="VerticalSplitMode" config:type="short">2</config:config-item> | ||||||
|  |                                <config:config-item config:name="VerticalSplitPosition" config:type="int">4</config:config-item> | ||||||
|  |                                <config:config-item config:name="PositionBottom" config:type="int">4</config:config-item> | ||||||
|  |                               </config:config-item-map-entry> | ||||||
|  |  | ||||||
|  |                         """); | ||||||
|  |                 } | ||||||
|  |  | ||||||
|  |                 await writer.WriteAsync(""" | ||||||
|  |                          </config:config-item-map-named> | ||||||
|  |                         </config:config-item-map-entry> | ||||||
|  |                        </config:config-item-map-indexed> | ||||||
|  |                       </config:config-item-set> | ||||||
|  |                      </office:settings> | ||||||
|  |                     </office:document-settings> | ||||||
|  |  | ||||||
|  |                     """); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public async Task AddTable<T>(DataTable<T> table) { | ||||||
|  |             if (Content == null) await AddHeader(); | ||||||
|  |             if (Content == null) return; | ||||||
|  |             var totalSpan = table.ColumnSpans.Sum(); | ||||||
|  |  | ||||||
|  |             _tables.Add(table.Name); | ||||||
|  |             await Content.WriteAsync($"    <table:table table:name=\"{table.Name}\" table:default-cell-style-name=\"default\">\r\n"); | ||||||
|  |             foreach (var (s, w) in table.ColumnSpans.Zip(table.ColumnWidths)) { | ||||||
|  |                 for (int i = 0; i < s; i++) { | ||||||
|  |                     await Content.WriteAsync("     <table:table-column" + (w != null ? $" table:style-name=\"colw{w / s}\"" : "") + "/>\r\n"); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             await Content.WriteAsync( | ||||||
|  |                 $"     <table:table-row>\r\n" + | ||||||
|  |                 FormatCell(table.FullName, colSpan: totalSpan, style: "header") + | ||||||
|  |                 $"     </table:table-row>\r\n" + | ||||||
|  |                 $"     <table:table-row>\r\n" + | ||||||
|  |                 $"      <table:table-cell table:number-columns-repeated=\"{totalSpan}\"/>\r\n" + | ||||||
|  |                 $"     </table:table-row>\r\n" + | ||||||
|  |                 $"     <table:table-row>\r\n"); | ||||||
|  |             foreach (var (name, span, units) in table.ColumnNames.Zip(table.ColumnSpans, table.ColumnUnits)) { | ||||||
|  |                 var hasUnits = units.Length > 0; | ||||||
|  |                 await Content.WriteAsync(FormatCell(name, colSpan: span, rowSpan: hasUnits ? 1 : 2, style: "th")); | ||||||
|  |             } | ||||||
|  |             await Content.WriteAsync("     </table:table-row>\r\n     <table:table-row>\r\n"); | ||||||
|  |             foreach (var (span, units) in table.ColumnSpans.Zip(table.ColumnUnits)) { | ||||||
|  |                 if (units.Length == 0) { | ||||||
|  |                     await Content.WriteAsync($"      <table:covered-table-cell table:number-columns-repeated=\"{span}\"/>\r\n"); | ||||||
|  |                     continue; | ||||||
|  |                 } | ||||||
|  |                 foreach (var u in units) { | ||||||
|  |                     await Content.WriteAsync(FormatCell(u == null ? null : $"[{u}]", style: "th")); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             await Content.WriteAsync("     </table:table-row>\r\n"); | ||||||
|  |  | ||||||
|  |             foreach (var row in table.GetData()) { | ||||||
|  |                 await FormatRow(row, table.ColumnUnits); | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             await Content.WriteAsync("    </table:table>\r\n"); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         protected async Task FormatRow(IEnumerable<object?> row, IEnumerable<string?[]?> colUnits) { | ||||||
|  |             if (Content == null) throw new InvalidOperationException(); | ||||||
|  |             var arrays = row.Where(c => c is Array).Cast<Array>().Select(c => c.Length).ToArray(); | ||||||
|  |             int rowNum = Math.Max(1, arrays.Length > 0 ? arrays.Max() : 0); | ||||||
|  |             for (int i = 0; i < rowNum; i++) { | ||||||
|  |                 await Content.WriteAsync("     <table:table-row>\r\n"); | ||||||
|  |                 foreach (var (data, units) in row.Zip(colUnits)) { | ||||||
|  |                     if (data is Array a) { | ||||||
|  |                         await Content.WriteAsync(i < a.Length ? FormatCell(a.GetValue(i), units: units) : $"      <table:table-cell table:number-columns-repeated=\"{GetSubCols(a.GetType().GetElementType())}\"/>\r\n"); | ||||||
|  |                     } else { | ||||||
|  |                         await Content.WriteAsync(FormatCell(data, rowSpan: i == 0 ? rowNum : 1, isCovered: i > 0, units: units)); | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |                 await Content.WriteAsync("     </table:table-row>\r\n"); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static int GetSubCols(Type? type) { | ||||||
|  |             if (type != null && type.IsValueType == true && type.Name.StartsWith("ValueTuple")) | ||||||
|  |                 return type.GetFields().Length; | ||||||
|  |             return 1; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         protected static string FormatCell(object? data, int rowSpan = 1, int colSpan = 1, string? style = "default", bool isCovered = false, string?[]? units = null) { | ||||||
|  |             if (data?.GetType().IsValueType == true && data.GetType().Name.StartsWith("ValueTuple")) | ||||||
|  |                 return string.Join("", data.GetType().GetFields().Zip(units ?? Array.Empty<string?>()) | ||||||
|  |                     .Select(p => FormatCell(p.First.GetValue(data), rowSpan, colSpan, style, isCovered, new[] { p.Second })) | ||||||
|  |                 ); | ||||||
|  |  | ||||||
|  |             var add = (style != null ? $" table:style-name=\"{style}\"" : "") + (rowSpan > 1 || colSpan > 1 ? $" table:number-rows-spanned=\"{rowSpan}\" table:number-columns-spanned=\"{colSpan}\"" : ""); | ||||||
|  |             string ct = isCovered ? "table:covered-table-cell" : "table:table-cell"; | ||||||
|  |             var isPercent = units != null && units.Length > 0 && units[0] == "%"; | ||||||
|  |  | ||||||
|  |             string c; | ||||||
|  |             if (data == null) { | ||||||
|  |                 c = $"<{ct}{add}/>"; | ||||||
|  |             } else if (data is float || data is double || data is byte || data is char || | ||||||
|  |                        data is short || data is ushort || data is int || data is uint || data is long || data is ulong) { | ||||||
|  |  | ||||||
|  |                 double v = double.Parse(data?.ToString() ?? "0"); | ||||||
|  |                 if (isPercent) { | ||||||
|  |                     data = $"{v:N1}"; | ||||||
|  |                     add = string.Join(" ", add.Split(" ").Select(p => p.StartsWith("table:style-name=") ? "table:style-name=\"perc\"" : p)); | ||||||
|  |                 } | ||||||
|  |                 c = $"<{ct} office:value-type=\"float\" calcext:value-type=\"float\" office:value=\"{v.ToString()?.Replace(",", ".")}\"{add}><text:p>{data}</text:p></{ct}>"; | ||||||
|  |             } else { | ||||||
|  |                 c = $"<{ct} office:value-type=\"string\" calcext:value-type=\"string\"{add}><text:p>{data}</text:p></{ct}>"; | ||||||
|  |             } | ||||||
|  |  | ||||||
|  |             return $"      {c}\r\n" + (colSpan > 1 ? $"      <table:covered-table-cell table:number-rows-repeated=\"{colSpan - 1}\"/>\r\n" : ""); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
|  |  | ||||||
| namespace Elwig.Helpers { | namespace Elwig.Helpers { | ||||||
|     public interface IAddress { |     public interface IAddress { | ||||||
|   | |||||||
| @@ -10,7 +10,7 @@ using System.Net.Sockets; | |||||||
| using Elwig.Dialogs; | using Elwig.Dialogs; | ||||||
| using System.Text; | using System.Text; | ||||||
| using System.Numerics; | using System.Numerics; | ||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
|  |  | ||||||
| namespace Elwig.Helpers { | namespace Elwig.Helpers { | ||||||
|     public static partial class Utils { |     public static partial class Utils { | ||||||
|   | |||||||
| @@ -2,7 +2,7 @@ using System; | |||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| using System.Windows.Controls; | using System.Windows.Controls; | ||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
|  |  | ||||||
| namespace Elwig.Helpers { | namespace Elwig.Helpers { | ||||||
|     public static class Validator { |     public static class Validator { | ||||||
|   | |||||||
							
								
								
									
										109
									
								
								Elwig/Models/Dtos/AreaComUnderDeliveyData.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								Elwig/Models/Dtos/AreaComUnderDeliveyData.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,109 @@ | |||||||
|  | using Microsoft.EntityFrameworkCore; | ||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.ComponentModel.DataAnnotations.Schema; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  |  | ||||||
|  | namespace Elwig.Models.Dtos { | ||||||
|  |     public class AreaComUnderDeliveryData : DataTable<AreaComUnderDeliveryRow> { | ||||||
|  |  | ||||||
|  |         private static readonly (string, string, string?, int)[] FieldNames = new[] { | ||||||
|  |             ("MgNr", "MgNr.", null, 12), | ||||||
|  |             ("Name", "Name", null, 40), | ||||||
|  |             ("GivenName", "Vorname", null, 40), | ||||||
|  |             ("Address", "Adresse", null, 60), | ||||||
|  |             ("Plz", "PLZ", null, 10), | ||||||
|  |             ("Locality", "Ort", null, 60), | ||||||
|  |             ("VtrgIds", "Vertrag", null, 14), | ||||||
|  |             ("Areas", "Fläche", "m²", 16), | ||||||
|  |             ("DeliveryObligations", "Lieferpflicht", "kg", 22), | ||||||
|  |             ("Weights", "Geliefert", "kg", 22), | ||||||
|  |             ("UnderDeliveries", "Unterliefert", "kg", 22), | ||||||
|  |             ("Percents", "Prozent", "%", 16), | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         public AreaComUnderDeliveryData(IEnumerable<AreaComUnderDeliveryRow> rows, int year) : | ||||||
|  |             base($"Unterlieferungen FB", $"Unterlieferungen laut Flächenbindungen {year}", rows, FieldNames) { | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static async Task<AreaComUnderDeliveryData> ForSeason(DbSet<AreaComUnderDeliveryRowSingle> table, int year) { | ||||||
|  |             return new AreaComUnderDeliveryData( | ||||||
|  |                 (await FromDbSet(table, year)).GroupBy( | ||||||
|  |                     r => r.MgNr, | ||||||
|  |                     (k, g) => new AreaComUnderDeliveryRow(g) | ||||||
|  |               ), year); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static async Task<IEnumerable<AreaComUnderDeliveryRowSingle>> FromDbSet(DbSet<AreaComUnderDeliveryRowSingle> table, int year) { | ||||||
|  |             return await table.FromSqlRaw($""" | ||||||
|  |                     SELECT m.mgnr, m.family_name, m.given_name, p.plz, o.name AS ort, m.address, | ||||||
|  |                             c.bucket, c.area, u.min_kg, u.weight | ||||||
|  |                     FROM member m | ||||||
|  |                         LEFT JOIN AT_plz_dest p ON p.id = m.postal_dest | ||||||
|  |                         LEFT JOIN AT_ort o ON o.okz = p.okz | ||||||
|  |                         LEFT JOIN v_area_commitment_bucket_strict c ON c.mgnr = m.mgnr AND c.year = {year} | ||||||
|  |                         JOIN v_under_delivery u ON (u.mgnr, u.bucket, u.year) = (m.mgnr, c.bucket, c.year) | ||||||
|  |                     WHERE m.active = 1 | ||||||
|  |                     ORDER BY m.mgnr, c.bucket | ||||||
|  |                     """).ToListAsync(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public class AreaComUnderDeliveryRow { | ||||||
|  |         public int MgNr; | ||||||
|  |         public string Name; | ||||||
|  |         public string GivenName; | ||||||
|  |         public string Address; | ||||||
|  |         public int Plz; | ||||||
|  |         public string Locality; | ||||||
|  |         public string[] VtrgIds; | ||||||
|  |         public int[] Areas; | ||||||
|  |         public int[] DeliveryObligations; | ||||||
|  |         public int[] Weights; | ||||||
|  |         public int?[] UnderDeliveries => Weights.Zip(DeliveryObligations) | ||||||
|  |             .Select(v => v.First < v.Second ? (int?)v.First - v.Second : null) | ||||||
|  |             .ToArray(); | ||||||
|  |         public double?[] Percents => Weights.Zip(DeliveryObligations) | ||||||
|  |             .Select(v => v.First < v.Second ? (double?)v.First * 100.0 / v.Second - 100.0 : null) | ||||||
|  |             .ToArray(); | ||||||
|  |  | ||||||
|  |         public AreaComUnderDeliveryRow(IEnumerable<AreaComUnderDeliveryRowSingle> rows) { | ||||||
|  |             var f = rows.First(); | ||||||
|  |             MgNr = f.MgNr; | ||||||
|  |             Name = f.Name; | ||||||
|  |             GivenName = f.GivenName; | ||||||
|  |             Address = f.Address; | ||||||
|  |             Plz = f.Plz; | ||||||
|  |             Locality = f.Locality.Split(",")[0]; | ||||||
|  |             VtrgIds = rows.Select(r => r.VtrgId).ToArray(); | ||||||
|  |             Areas = rows.Select(r => r.Area).ToArray(); | ||||||
|  |             DeliveryObligations = rows.Select(r => r.DeliveryObligation).ToArray(); | ||||||
|  |             Weights = rows.Select(r => r.Weight).ToArray(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     [Keyless] | ||||||
|  |     public class AreaComUnderDeliveryRowSingle { | ||||||
|  |         [Column("mgnr")] | ||||||
|  |         public int MgNr { get; set; } | ||||||
|  |         [Column("family_name")] | ||||||
|  |         public string Name { get; set; } | ||||||
|  |         [Column("given_name")] | ||||||
|  |         public string GivenName { get; set; } | ||||||
|  |         [Column("address")] | ||||||
|  |         public string Address { get; set; } | ||||||
|  |         [Column("plz")] | ||||||
|  |         public int Plz { get; set; } | ||||||
|  |         [Column("ort")] | ||||||
|  |         public string Locality { get; set; } | ||||||
|  |         [Column("bucket")] | ||||||
|  |         public string VtrgId { get; set; } | ||||||
|  |         [Column("area")] | ||||||
|  |         public int Area { get; set; } | ||||||
|  |         [Column("min_kg")] | ||||||
|  |         public int DeliveryObligation { get; set; } | ||||||
|  |         [Column("weight")] | ||||||
|  |         public int Weight { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										86
									
								
								Elwig/Models/Dtos/DataTable.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								Elwig/Models/Dtos/DataTable.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | |||||||
|  | using System; | ||||||
|  | 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 int ColNum => ColumnNames.Count(); | ||||||
|  |  | ||||||
|  |         public IEnumerable<(string, Type?)> ColumnDefs => _map.Select(m => (m.Item1, m.Item2?.PropertyType ?? m.Item3?.FieldType)); | ||||||
|  |         public IEnumerable<string> ColumnNames => ColumnDefs.Select(m => m.Item1); | ||||||
|  |         public IEnumerable<Type?> ColumnTypes => ColumnDefs.Select(m => m.Item2); | ||||||
|  |         public IEnumerable<Type?> ColumnFlatTypes { get; private set; } | ||||||
|  |         public IEnumerable<int> ColumnSpans { get; private set; } | ||||||
|  |         public IEnumerable<int?> ColumnWidths { get; private set; } | ||||||
|  |         public IEnumerable<string?[]> ColumnUnits { get; private set; } | ||||||
|  |  | ||||||
|  |         private readonly PropertyInfo[] _properties; | ||||||
|  |         private readonly FieldInfo[] _fields; | ||||||
|  |         private readonly (string, PropertyInfo?, FieldInfo?)[] _map; | ||||||
|  |  | ||||||
|  |         public DataTable(string name, string fullName, IEnumerable<T> rows, IEnumerable<(string, string, string?, int?)>? colNames = null) { | ||||||
|  |             _fields = typeof(T).GetFields(); | ||||||
|  |             _properties = typeof(T).GetProperties(); | ||||||
|  |             colNames ??= _properties.Select(p => p.Name).Union(_fields.Select(f => f.Name)).Select(i => (i, i, (string?)null, (int?)null)).ToList(); | ||||||
|  |             _map = colNames.Select(n => (n.Item2, _properties.FirstOrDefault(p => p?.Name == n.Item1, null), _fields.FirstOrDefault(f => f?.Name == n.Item1, null))).ToArray(); | ||||||
|  |             Name = name; | ||||||
|  |             FullName = fullName; | ||||||
|  |             Rows = rows; | ||||||
|  |             ColumnFlatTypes = ColumnTypes.SelectMany(type => { | ||||||
|  |                 var elType = type?.GetElementType(); | ||||||
|  |                 return type != null && type.IsValueType && type.Name.StartsWith("ValueTuple") ? type.GetFields().Select(f => f.FieldType) : | ||||||
|  |                        type != null && elType != null && type.IsArray && elType.IsValueType && elType.Name.StartsWith("ValueTuple") ? elType.GetFields().Select(f => f.FieldType) : | ||||||
|  |                        new Type?[] { type }; | ||||||
|  |             }).ToList(); | ||||||
|  |             ColumnSpans = ColumnTypes.Select(type => { | ||||||
|  |                 var elType = type?.GetElementType(); | ||||||
|  |                 return type != null && type.IsValueType && type.Name.StartsWith("ValueTuple") ? type.GetFields().Length : | ||||||
|  |                        type != null && elType != null && type.IsArray && elType.IsValueType && elType.Name.StartsWith("ValueTuple") ? elType.GetFields().Length : 1; | ||||||
|  |             }).ToList(); | ||||||
|  |             ColumnWidths = colNames.Select(c => c.Item4).ToList(); | ||||||
|  |             ColumnUnits = colNames.Select(c => c.Item3?.Split("|").Select(p => p.Length == 0 ? null : p).ToArray() ?? Array.Empty<string?>()).ToList(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public DataTable(string name, string fullName, IEnumerable<T> rows, IEnumerable<(string, string, string?)>? colNames = null) : | ||||||
|  |             this(name, fullName, rows, colNames?.Select(c => (c.Item1, c.Item2, c.Item3, (int?)null))) { | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public DataTable(string name, IEnumerable<T> rows, IEnumerable<(string, string, string?)>? colNames = null) : | ||||||
|  |             this(name, name, rows, colNames) { | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public DataTable(string name, IEnumerable<T> rows, IEnumerable<(string, string, string?, int?)>? colNames = null) : | ||||||
|  |             this(name, name, rows, colNames) { | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public DataTable(string name, IEnumerable<T> rows, IEnumerable<(string, string, string?, int)>? colNames = null) : | ||||||
|  |             this(name, name, rows, colNames) { | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public DataTable(string name, string fullName, IEnumerable<T> rows, IEnumerable<(string, string, string?, int)>? colNames = null) : | ||||||
|  |             this(name, fullName, rows, colNames?.Select(c => (c.Item1, c.Item2, c.Item3, (int?)c.Item4))) { | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         protected IEnumerable<(string, object?)> GetNamedRowData(T row) { | ||||||
|  |             return _map.Select(i => (i.Item1, i.Item2?.GetValue(row) ?? i.Item3?.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); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										97
									
								
								Elwig/Models/Dtos/DeliveryConfirmationData.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								Elwig/Models/Dtos/DeliveryConfirmationData.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | |||||||
|  | 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, string?, int)[] FieldNames = new[] { | ||||||
|  |             ("LsNr", "LsNr.", null, 26), | ||||||
|  |             ("DPNr", "Pos.", null, 8), | ||||||
|  |             ("Variant", "Sorte", null, 40), | ||||||
|  |             ("Attribute", "Attribut", null, 20), | ||||||
|  |             ("Modifiers", "Zu-/Abschläge", null, 30), | ||||||
|  |             ("QualityLevel", "Qualitätsstufe", null, 25), | ||||||
|  |             ("Gradation", "Gradation", "°Oe|°KMW", 32), | ||||||
|  |             ("Buckets", "Flächenbindung", "|kg", 36), | ||||||
|  |             ("Weight", "Gewicht", "kg", 16), | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         private readonly int MgNr; | ||||||
|  |  | ||||||
|  |         private DeliveryConfirmationData(IEnumerable<DeliveryConfirmationRow> rows, int year, Member m) : | ||||||
|  |             base($"Anlieferungsbestätigung", $"Anlieferungsbestätigung {year} – {m.AdministrativeName}", rows, FieldNames) { | ||||||
|  |             MgNr = m.MgNr; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static async Task<IDictionary<int, DeliveryConfirmationData>> ForSeason(DbSet<DeliveryPart> table, int year) { | ||||||
|  |             return (await FromDbSet(table, year)) | ||||||
|  |                 .GroupBy( | ||||||
|  |                     p => p.Delivery.Member, | ||||||
|  |                     p => new DeliveryConfirmationRow(p), | ||||||
|  |                     (k, g) => new DeliveryConfirmationData(g, year, k) | ||||||
|  |                 ).ToDictionary(d => d.MgNr, d => d); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static async Task<DeliveryConfirmationData> ForMember(DbSet<DeliveryPart> table, int year, Member m) { | ||||||
|  |             return new DeliveryConfirmationData((await FromDbSet(table, year, m.MgNr)).Select(p => new DeliveryConfirmationRow(p)), year, m); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static async Task<IEnumerable<DeliveryPart>> FromDbSet(DbSet<DeliveryPart> table, int? year = null, int? mgnr = null) { | ||||||
|  |             var y = year?.ToString() ?? "NULL"; | ||||||
|  |             var m = mgnr?.ToString() ?? "NULL"; | ||||||
|  |             IQueryable<DeliveryPart> q = table; | ||||||
|  |             if (year != null) q = q.Where(p => p.Year == year); | ||||||
|  |             if (mgnr != null) q = q.Where(p => p.Delivery.MgNr == mgnr); | ||||||
|  |             await q | ||||||
|  |                  .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) | ||||||
|  |                  .LoadAsync(); | ||||||
|  |             return await 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 | ||||||
|  |                     """).ToListAsync(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public class DeliveryConfirmationRow { | ||||||
|  |         public string LsNr; | ||||||
|  |         public int DPNr; | ||||||
|  |         public string Variant; | ||||||
|  |         public string? Attribute; | ||||||
|  |         public string QualityLevel; | ||||||
|  |         public (double Oe, double Kmw) Gradation; | ||||||
|  |         public string[] Modifiers; | ||||||
|  |         public int Weight; | ||||||
|  |         public (string Name, int Value)[] Buckets; | ||||||
|  |  | ||||||
|  |         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; | ||||||
|  |             Gradation = (p.Oe, 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(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										118
									
								
								Elwig/Models/Dtos/MemberDeliveryPerVariantData.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								Elwig/Models/Dtos/MemberDeliveryPerVariantData.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,118 @@ | |||||||
|  | using Microsoft.EntityFrameworkCore; | ||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.ComponentModel.DataAnnotations.Schema; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  |  | ||||||
|  | namespace Elwig.Models.Dtos { | ||||||
|  |     public class MemberDeliveryPerVariantData : DataTable<MemberDeliveryPerVariantRow> { | ||||||
|  |  | ||||||
|  |         private static readonly (string, string, string?, int)[] FieldNames = new[] { | ||||||
|  |             ("MgNr", "MgNr.", null, 12), | ||||||
|  |             ("Name", "Name", null, 40), | ||||||
|  |             ("GivenName", "Vorname", null, 40), | ||||||
|  |             ("Address", "Adresse", null, 60), | ||||||
|  |             ("Plz", "PLZ", null, 10), | ||||||
|  |             ("Locality", "Ort", null, 60), | ||||||
|  |             ("SortIds", "Sorte", null, 12), | ||||||
|  |             ("AttrIds", "Attribut", null, 16), | ||||||
|  |             ("Weights", "Geliefert", "kg", 22), | ||||||
|  |             ("Areas", "Fläche", "m²", 22), | ||||||
|  |             ("Yields", "Ertrag", "kg/ha", 22), | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |         public MemberDeliveryPerVariantData(IEnumerable<MemberDeliveryPerVariantRow> rows, int year) : | ||||||
|  |             base($"Liefermengen", $"Liefermengen pro Mitglied, Sorte und Attribut {year}", rows, FieldNames) { | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static async Task<MemberDeliveryPerVariantData> ForSeason(DbSet<MemberDeliveryPerVariantRowSingle> table, int year) { | ||||||
|  |             return new MemberDeliveryPerVariantData( | ||||||
|  |                (await FromDbSet(table, year)).GroupBy( | ||||||
|  |                    r => r.MgNr, | ||||||
|  |                    (k, g) => new MemberDeliveryPerVariantRow(g) | ||||||
|  |              ), year); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static async Task<IEnumerable<MemberDeliveryPerVariantRowSingle>> FromDbSet(DbSet<MemberDeliveryPerVariantRowSingle> table, int year) { | ||||||
|  |             return await table.FromSqlRaw($""" | ||||||
|  |                     SELECT m.mgnr, m.family_name, m.given_name, p.plz, o.name AS ort, m.address, | ||||||
|  |                            v.bucket, v.weight, v.area | ||||||
|  |                     FROM ( | ||||||
|  |                             SELECT c.year AS year, | ||||||
|  |                                    c.mgnr AS mgnr, | ||||||
|  |                                    c.bucket AS bucket, | ||||||
|  |                                    COALESCE(d.weight, 0) AS weight, | ||||||
|  |                                    COALESCE(c.area, 0) AS area | ||||||
|  |                             FROM v_area_commitment_bucket_strict c | ||||||
|  |                                 LEFT JOIN v_delivery_bucket_strict d ON (d.year, d.mgnr, d.bucket) = (c.year, c.mgnr, c.bucket) | ||||||
|  |                             WHERE c.year = {year} | ||||||
|  |                             UNION | ||||||
|  |                             SELECT d.year, | ||||||
|  |                                    d.mgnr, | ||||||
|  |                                    d.bucket, | ||||||
|  |                                    COALESCE(d.weight, 0), | ||||||
|  |                                    COALESCE(c.area, 0) | ||||||
|  |                             FROM v_delivery_bucket_strict d | ||||||
|  |                                 LEFT JOIN v_area_commitment_bucket_strict c ON (c.year, c.mgnr, c.bucket) = (d.year, d.mgnr, d.bucket) | ||||||
|  |                             WHERE d.year = {year} | ||||||
|  |                         ) v | ||||||
|  |                         LEFT JOIN member m ON m.mgnr = v.mgnr | ||||||
|  |                         LEFT JOIN AT_plz_dest p ON p.id = m.postal_dest | ||||||
|  |                         LEFT JOIN AT_ort o ON o.okz = p.okz | ||||||
|  |                     ORDER BY m.mgnr, v.bucket | ||||||
|  |                     """).ToListAsync(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public class MemberDeliveryPerVariantRow { | ||||||
|  |         public int MgNr; | ||||||
|  |         public string Name; | ||||||
|  |         public string GivenName; | ||||||
|  |         public string Address; | ||||||
|  |         public int Plz; | ||||||
|  |         public string Locality; | ||||||
|  |         public string[] SortIds; | ||||||
|  |         public string[] AttrIds; | ||||||
|  |         public int[] Areas; | ||||||
|  |         public int[] Weights; | ||||||
|  |         public int?[] Yields => Weights.Zip(Areas).Select(i => i.Second > 0 ? (int?)i.First * 10_000 / i.Second : null).ToArray(); | ||||||
|  |  | ||||||
|  |         public MemberDeliveryPerVariantRow(IEnumerable<MemberDeliveryPerVariantRowSingle> rows) { | ||||||
|  |             var f = rows.First(); | ||||||
|  |             MgNr = f.MgNr; | ||||||
|  |             Name = f.Name; | ||||||
|  |             GivenName = f.GivenName; | ||||||
|  |             Address = f.Address; | ||||||
|  |             Plz = f.Plz; | ||||||
|  |             Locality = f.Locality.Split(",")[0]; | ||||||
|  |             SortIds = rows.Select(r => r.VtrgId[..2]).ToArray(); | ||||||
|  |             AttrIds = rows.Select(r => r.VtrgId[2..]).ToArray(); | ||||||
|  |             Areas = rows.Select(r => r.Area).ToArray(); | ||||||
|  |             Weights = rows.Select(r => r.Weight).ToArray(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     [Keyless] | ||||||
|  |     public class MemberDeliveryPerVariantRowSingle { | ||||||
|  |         [Column("mgnr")] | ||||||
|  |         public int MgNr { get; set; } | ||||||
|  |         [Column("family_name")] | ||||||
|  |         public string Name { get; set; } | ||||||
|  |         [Column("given_name")] | ||||||
|  |         public string GivenName { get; set; } | ||||||
|  |         [Column("address")] | ||||||
|  |         public string Address { get; set; } | ||||||
|  |         [Column("plz")] | ||||||
|  |         public int Plz { get; set; } | ||||||
|  |         [Column("ort")] | ||||||
|  |         public string Locality { get; set; } | ||||||
|  |         [Column("bucket")] | ||||||
|  |         public string VtrgId { get; set; } | ||||||
|  |         [Column("area")] | ||||||
|  |         public int Area { get; set; } | ||||||
|  |         [Column("weight")] | ||||||
|  |         public int Weight { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										81
									
								
								Elwig/Models/Dtos/OverUnderDeliveryData.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								Elwig/Models/Dtos/OverUnderDeliveryData.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | |||||||
|  | using Microsoft.EntityFrameworkCore; | ||||||
|  | using System; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.ComponentModel.DataAnnotations.Schema; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  |  | ||||||
|  | namespace Elwig.Models.Dtos { | ||||||
|  |     public class OverUnderDeliveryData : DataTable<OverUnderDeliveryRow> { | ||||||
|  |  | ||||||
|  |         private static readonly (string, string, string?, int)[] FieldNames = new[] { | ||||||
|  |             ("MgNr", "MgNr.", null, 12), | ||||||
|  |             ("Name", "Name", null, 40), | ||||||
|  |             ("GivenName", "Vorname", null, 40), | ||||||
|  |             ("Address", "Adresse", null, 60), | ||||||
|  |             ("Plz", "PLZ", null, 10), | ||||||
|  |             ("Locality", "Ort", null, 60), | ||||||
|  |             ("BusinessShares", "GA", null, 10), | ||||||
|  |             ("DeliveryObligation", "Lieferpflicht", "kg", 22), | ||||||
|  |             ("DeliveryRight", "Lieferrecht", "kg", 22), | ||||||
|  |             ("Weight", "Geliefert", "kg", 22), | ||||||
|  |             ("OverUnderDelivery", "Über-/Unterliefert", "kg", 35), | ||||||
|  |             ("Percent", "Prozent", "%", 16), | ||||||
|  |         }; | ||||||
|  |  | ||||||
|  |         public OverUnderDeliveryData(IEnumerable<OverUnderDeliveryRow> rows, int year) : | ||||||
|  |             base($"Über-Unterlieferungen", $"Über- und Unterlieferungen laut gezeichneten Geschäftsanteilen {year}", rows, FieldNames) { | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static async Task<OverUnderDeliveryData> ForSeason(DbSet<OverUnderDeliveryRow> table, int year) { | ||||||
|  |             var rows = await table.FromSqlRaw($""" | ||||||
|  |                 SELECT m.mgnr, m.family_name, m.given_name, p.plz, o.name AS ort, m.address, m.business_shares, | ||||||
|  |                        m.business_shares * s.min_kg_per_bs AS min_kg, | ||||||
|  |                        m.business_shares * s.max_kg_per_bs AS max_kg, | ||||||
|  |                        COALESCE(SUM(d.weight), 0) AS sum | ||||||
|  |                 FROM member m | ||||||
|  |                     LEFT JOIN AT_plz_dest p ON p.id = m.postal_dest | ||||||
|  |                     LEFT JOIN AT_ort o ON o.okz = p.okz | ||||||
|  |                     LEFT JOIN season s ON s.year = {year} | ||||||
|  |                     LEFT JOIN v_delivery d ON d.mgnr = m.mgnr AND d.year = s.year | ||||||
|  |                 WHERE m.active = 1 | ||||||
|  |                 GROUP BY d.year, m.mgnr | ||||||
|  |                 ORDER BY 100.0 * sum / max_kg, m.mgnr; | ||||||
|  |                 """).ToListAsync(); | ||||||
|  |             return new OverUnderDeliveryData(rows, year); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     [Keyless] | ||||||
|  |     public class OverUnderDeliveryRow { | ||||||
|  |         [Column("mgnr")] | ||||||
|  |         public int MgNr { get; set; } | ||||||
|  |         [Column("family_name")] | ||||||
|  |         public string Name { get; set; } | ||||||
|  |         [Column("given_name")] | ||||||
|  |         public string GivenName { get; set; } | ||||||
|  |         [Column("address")] | ||||||
|  |         public string Address { get; set; } | ||||||
|  |         [Column("plz")] | ||||||
|  |         public int Plz { get; set; } | ||||||
|  |         [Column("ort")] | ||||||
|  |         public string LocalityFull { get; set; } | ||||||
|  |         [NotMapped] | ||||||
|  |         public string Locality => LocalityFull.Split(",")[0]; | ||||||
|  |         [Column("business_shares")] | ||||||
|  |         public int BusinessShares { get; set; } | ||||||
|  |         [Column("min_kg")] | ||||||
|  |         public int DeliveryObligation { get; set; } | ||||||
|  |         [Column("max_kg")] | ||||||
|  |         public int DeliveryRight { get; set; } | ||||||
|  |         [Column("sum")] | ||||||
|  |         public int Weight { get; set; } | ||||||
|  |         [NotMapped] | ||||||
|  |         public int? OverUnderDelivery => | ||||||
|  |             Weight < DeliveryObligation ? Weight - DeliveryObligation : | ||||||
|  |             Weight > DeliveryRight ? Weight - DeliveryRight : null; | ||||||
|  |         [NotMapped] | ||||||
|  |         public double? Percent => | ||||||
|  |             Weight < DeliveryObligation ? Weight * 100.0 / DeliveryObligation - 100.0 : | ||||||
|  |             Weight > DeliveryRight ? Weight * 100.0 / DeliveryRight - 100 : null; | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore; | |||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("AT_gem"), PrimaryKey("Gkz")] |     [Table("AT_gem"), PrimaryKey("Gkz")] | ||||||
|     public class AT_Gem { |     public class AT_Gem { | ||||||
|         [Column("gkz")] |         [Column("gkz")] | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("AT_kg"), PrimaryKey("KgNr")] |     [Table("AT_kg"), PrimaryKey("KgNr")] | ||||||
|     public class AT_Kg { |     public class AT_Kg { | ||||||
|         [Column("kgnr")] |         [Column("kgnr")] | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("AT_ort"), PrimaryKey("Okz")] |     [Table("AT_ort"), PrimaryKey("Okz")] | ||||||
|     public class AT_Ort { |     public class AT_Ort { | ||||||
|         [Column("okz")] |         [Column("okz")] | ||||||
| @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore; | |||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("AT_plz"), PrimaryKey("Plz")] |     [Table("AT_plz"), PrimaryKey("Plz")] | ||||||
|     public class AT_Plz { |     public class AT_Plz { | ||||||
|         [Column("plz")] |         [Column("plz")] | ||||||
| @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore; | |||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| using IndexAttribute = Microsoft.EntityFrameworkCore.IndexAttribute; | using IndexAttribute = Microsoft.EntityFrameworkCore.IndexAttribute; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("AT_plz_dest"), PrimaryKey("Id"), Index("Plz", "Okz", IsUnique = true)] |     [Table("AT_plz_dest"), PrimaryKey("Id"), Index("Plz", "Okz", IsUnique = true)] | ||||||
|     public class AT_PlzDest { |     public class AT_PlzDest { | ||||||
|         [Column("plz")] |         [Column("plz")] | ||||||
| @@ -1,11 +1,10 @@ | |||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.Collections; |  | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("area_commitment"), PrimaryKey("FbNr")] |     [Table("area_commitment"), PrimaryKey("FbNr")] | ||||||
|     public class AreaCom { |     public class AreaCom { | ||||||
|         [Column("fbnr")] |         [Column("fbnr")] | ||||||
| @@ -3,7 +3,7 @@ using Microsoft.EntityFrameworkCore; | |||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| using IndexAttribute = Microsoft.EntityFrameworkCore.IndexAttribute; | using IndexAttribute = Microsoft.EntityFrameworkCore.IndexAttribute; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("area_commitment_type"), PrimaryKey("VtrgId"), Index("SortId", "AttrId", "Discriminator", IsUnique = true)] |     [Table("area_commitment_type"), PrimaryKey("VtrgId"), Index("SortId", "AttrId", "Discriminator", IsUnique = true)] | ||||||
|     public class AreaComType { |     public class AreaComType { | ||||||
|         [Column("vtrgid")] |         [Column("vtrgid")] | ||||||
| @@ -2,7 +2,7 @@ using Elwig.Helpers; | |||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("member_billing_address"), PrimaryKey("MgNr")] |     [Table("member_billing_address"), PrimaryKey("MgNr")] | ||||||
|     public class BillingAddr : IAddress { |     public class BillingAddr : IAddress { | ||||||
|         [Column("mgnr")] |         [Column("mgnr")] | ||||||
| @@ -3,7 +3,7 @@ using System.Collections.Generic; | |||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| using IndexAttribute = Microsoft.EntityFrameworkCore.IndexAttribute; | using IndexAttribute = Microsoft.EntityFrameworkCore.IndexAttribute; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("branch"), PrimaryKey("ZwstId"), Index("Name", IsUnique = true)] |     [Table("branch"), PrimaryKey("ZwstId"), Index("Name", IsUnique = true)] | ||||||
|     public class Branch { |     public class Branch { | ||||||
|         [Column("zwstid")] |         [Column("zwstid")] | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("client_parameter"), PrimaryKey("Param")] |     [Table("client_parameter"), PrimaryKey("Param")] | ||||||
|     public class ClientParam { |     public class ClientParam { | ||||||
|         [Column("param")] |         [Column("param")] | ||||||
| @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore; | |||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| using IndexAttribute = Microsoft.EntityFrameworkCore.IndexAttribute; | using IndexAttribute = Microsoft.EntityFrameworkCore.IndexAttribute; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("country"), PrimaryKey("Num"), Index("Alpha2", IsUnique = true), Index("Alpha3", IsUnique = true)] |     [Table("country"), PrimaryKey("Num"), Index("Alpha2", IsUnique = true), Index("Alpha3", IsUnique = true)] | ||||||
|     public class Country { |     public class Country { | ||||||
|         [Column("num")] |         [Column("num")] | ||||||
| @@ -4,7 +4,7 @@ using System; | |||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| using IndexAttribute = Microsoft.EntityFrameworkCore.IndexAttribute; | using IndexAttribute = Microsoft.EntityFrameworkCore.IndexAttribute; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("credit"), PrimaryKey("Year", "TgNr"), Index("Year", "AvNr", "MgNr", IsUnique = true)] |     [Table("credit"), PrimaryKey("Year", "TgNr"), Index("Year", "AvNr", "MgNr", IsUnique = true)] | ||||||
|     public class Credit { |     public class Credit { | ||||||
|         [Column("year")] |         [Column("year")] | ||||||
| @@ -2,7 +2,7 @@ using Elwig.Helpers; | |||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("currency"), PrimaryKey("Code")] |     [Table("currency"), PrimaryKey("Code")] | ||||||
|     public class Currency { |     public class Currency { | ||||||
|         [Column("code")] |         [Column("code")] | ||||||
| @@ -6,7 +6,7 @@ using System.ComponentModel.DataAnnotations.Schema; | |||||||
| using System.Linq; | using System.Linq; | ||||||
| using IndexAttribute = Microsoft.EntityFrameworkCore.IndexAttribute; | using IndexAttribute = Microsoft.EntityFrameworkCore.IndexAttribute; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("delivery"), PrimaryKey("Year", "DId"), Index("DateString", "ZwstId", "LNr", IsUnique = true), Index("LsNr", IsUnique = true)] |     [Table("delivery"), PrimaryKey("Year", "DId"), Index("DateString", "ZwstId", "LNr", IsUnique = true), Index("LsNr", IsUnique = true)] | ||||||
|     public class Delivery { |     public class Delivery { | ||||||
|         [Column("year")] |         [Column("year")] | ||||||
| @@ -4,7 +4,7 @@ using System.Collections.Generic; | |||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("delivery_part"), PrimaryKey("Year", "DId", "DPNr")] |     [Table("delivery_part"), PrimaryKey("Year", "DId", "DPNr")] | ||||||
|     public class DeliveryPart { |     public class DeliveryPart { | ||||||
|         [Column("year")] |         [Column("year")] | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("delivery_part_bucket"), PrimaryKey("Year", "DId", "DPNr", "BktNr")] |     [Table("delivery_part_bucket"), PrimaryKey("Year", "DId", "DPNr", "BktNr")] | ||||||
|     public class DeliveryPartBucket { |     public class DeliveryPartBucket { | ||||||
|         [Column("year")] |         [Column("year")] | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("delivery_part_modifier"), PrimaryKey("Year", "DId", "DPNr", "ModId")] |     [Table("delivery_part_modifier"), PrimaryKey("Year", "DId", "DPNr", "ModId")] | ||||||
|     public class DeliveryPartModifier { |     public class DeliveryPartModifier { | ||||||
|         [Column("year")] |         [Column("year")] | ||||||
| @@ -5,7 +5,7 @@ using System.Collections.Generic; | |||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("member"), PrimaryKey("MgNr")] |     [Table("member"), PrimaryKey("MgNr")] | ||||||
|     public class Member : IAddress { |     public class Member : IAddress { | ||||||
|         [Column("mgnr")] |         [Column("mgnr")] | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("member_email_address"), PrimaryKey("MgNr", "Nr")] |     [Table("member_email_address"), PrimaryKey("MgNr", "Nr")] | ||||||
|     public class MemberEmailAddr { |     public class MemberEmailAddr { | ||||||
|         [Column("mgnr")] |         [Column("mgnr")] | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("member_telephone_number"), PrimaryKey("MgNr", "Nr")] |     [Table("member_telephone_number"), PrimaryKey("MgNr", "Nr")] | ||||||
|     public class MemberTelNr { |     public class MemberTelNr { | ||||||
|         [Column("mgnr")] |         [Column("mgnr")] | ||||||
| @@ -4,7 +4,7 @@ using System; | |||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("modifier"), PrimaryKey("Year", "ModId")] |     [Table("modifier"), PrimaryKey("Year", "ModId")] | ||||||
|     public class Modifier { |     public class Modifier { | ||||||
|         [Column("year")] |         [Column("year")] | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("payment_delivery_part"), PrimaryKey("Year", "DId", "DPNr", "AvNr")] |     [Table("payment_delivery_part"), PrimaryKey("Year", "DId", "DPNr", "AvNr")] | ||||||
|     public class PaymentDeliveryPart { |     public class PaymentDeliveryPart { | ||||||
|         [Column("year")] |         [Column("year")] | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("payment_delivery_part_bucket"), PrimaryKey("Year", "DId", "DPNr", "BktNr", "AvNr")] |     [Table("payment_delivery_part_bucket"), PrimaryKey("Year", "DId", "DPNr", "BktNr", "AvNr")] | ||||||
|     public class PaymentDeliveryPartBucket { |     public class PaymentDeliveryPartBucket { | ||||||
|         [Column("year")] |         [Column("year")] | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("payment_member"), PrimaryKey("Year", "AvNr", "MgNr")] |     [Table("payment_member"), PrimaryKey("Year", "AvNr", "MgNr")] | ||||||
|     public class PaymentMember { |     public class PaymentMember { | ||||||
|         [Column("year")] |         [Column("year")] | ||||||
| @@ -2,9 +2,8 @@ using Microsoft.EntityFrameworkCore; | |||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| using System.Linq; |  | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("payment_variant"), PrimaryKey("Year", "AvNr")] |     [Table("payment_variant"), PrimaryKey("Year", "AvNr")] | ||||||
|     public class PaymentVar { |     public class PaymentVar { | ||||||
|         [Column("year")] |         [Column("year")] | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("postal_dest"), PrimaryKey("CountryNum", "Id")] |     [Table("postal_dest"), PrimaryKey("CountryNum", "Id")] | ||||||
|     public class PostalDest { |     public class PostalDest { | ||||||
|         [Column("country")] |         [Column("country")] | ||||||
| @@ -4,7 +4,7 @@ using System; | |||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("season"), PrimaryKey("Year")] |     [Table("season"), PrimaryKey("Year")] | ||||||
|     public class Season { |     public class Season { | ||||||
|         [Column("year")] |         [Column("year")] | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("wb_gem"), PrimaryKey("Gkz")] |     [Table("wb_gem"), PrimaryKey("Gkz")] | ||||||
|     public class WbGem { |     public class WbGem { | ||||||
|         [Column("gkz")] |         [Column("gkz")] | ||||||
| @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore; | |||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("wb_gl"), PrimaryKey("GlNr")] |     [Table("wb_gl"), PrimaryKey("GlNr")] | ||||||
|     public class WbGl { |     public class WbGl { | ||||||
|         [Column("glnr")] |         [Column("glnr")] | ||||||
| @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore; | |||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("wb_kg"), PrimaryKey("KgNr")] |     [Table("wb_kg"), PrimaryKey("KgNr")] | ||||||
|     public class WbKg { |     public class WbKg { | ||||||
|         [Column("kgnr")] |         [Column("kgnr")] | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("wb_rd"), PrimaryKey("KgNr", "RdNr")] |     [Table("wb_rd"), PrimaryKey("KgNr", "RdNr")] | ||||||
|     public class WbRd { |     public class WbRd { | ||||||
|         [Column("kgnr")] |         [Column("kgnr")] | ||||||
| @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore; | |||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| using IndexAttribute = Microsoft.EntityFrameworkCore.IndexAttribute; | using IndexAttribute = Microsoft.EntityFrameworkCore.IndexAttribute; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("wine_attribute"), PrimaryKey("AttrId"), Index("Name", IsUnique = true)] |     [Table("wine_attribute"), PrimaryKey("AttrId"), Index("Name", IsUnique = true)] | ||||||
|     public class WineAttr { |     public class WineAttr { | ||||||
|         [Column("attrid")] |         [Column("attrid")] | ||||||
| @@ -2,7 +2,7 @@ using Microsoft.EntityFrameworkCore; | |||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| using IndexAttribute = Microsoft.EntityFrameworkCore.IndexAttribute; | using IndexAttribute = Microsoft.EntityFrameworkCore.IndexAttribute; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("wine_cultivation"), PrimaryKey("CultId"), Index("Name", IsUnique = true)] |     [Table("wine_cultivation"), PrimaryKey("CultId"), Index("Name", IsUnique = true)] | ||||||
|     public class WineCult { |     public class WineCult { | ||||||
|         [Column("cultid")] |         [Column("cultid")] | ||||||
| @@ -5,7 +5,7 @@ using System.ComponentModel.DataAnnotations.Schema; | |||||||
| using System.Linq; | using System.Linq; | ||||||
| using IndexAttribute = Microsoft.EntityFrameworkCore.IndexAttribute; | using IndexAttribute = Microsoft.EntityFrameworkCore.IndexAttribute; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("wine_origin"), PrimaryKey("HkId"), Index("Name", IsUnique = true)] |     [Table("wine_origin"), PrimaryKey("HkId"), Index("Name", IsUnique = true)] | ||||||
|     public class WineOrigin { |     public class WineOrigin { | ||||||
|         [Column("hkid")] |         [Column("hkid")] | ||||||
| @@ -2,10 +2,8 @@ using Elwig.Helpers; | |||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System; | using System; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| using System.Configuration; |  | ||||||
| using System.Security.Cryptography.Pkcs; |  | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("wine_quality_level"), PrimaryKey("QualId")] |     [Table("wine_quality_level"), PrimaryKey("QualId")] | ||||||
|     public class WineQualLevel : IEquatable<WineQualLevel> { |     public class WineQualLevel : IEquatable<WineQualLevel> { | ||||||
|         [Column("qualid")] |         [Column("qualid")] | ||||||
| @@ -1,7 +1,7 @@ | |||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models { | namespace Elwig.Models.Entities { | ||||||
|     [Table("wine_variety"), PrimaryKey("SortId")] |     [Table("wine_variety"), PrimaryKey("SortId")] | ||||||
|     public class WineVar { |     public class WineVar { | ||||||
|         [Column("sortid")] |         [Column("sortid")] | ||||||
| @@ -1,6 +1,6 @@ | |||||||
| using Elwig.Controls; | using Elwig.Controls; | ||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
| using System; | using System; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.ComponentModel; | using System.ComponentModel; | ||||||
|   | |||||||
| @@ -3,13 +3,12 @@ using System.Linq; | |||||||
| using System.Windows; | using System.Windows; | ||||||
| using System.Windows.Controls; | using System.Windows.Controls; | ||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
| using System; | using System; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using Microsoft.EntityFrameworkCore.ChangeTracking; | using Microsoft.EntityFrameworkCore.ChangeTracking; | ||||||
| using Xceed.Wpf.Toolkit.Primitives; | using Xceed.Wpf.Toolkit.Primitives; | ||||||
| using System.Runtime.Intrinsics.Arm; |  | ||||||
|  |  | ||||||
| namespace Elwig.Windows { | namespace Elwig.Windows { | ||||||
|     public partial class AreaComAdminWindow : AdministrationWindow { |     public partial class AreaComAdminWindow : AdministrationWindow { | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Collections.ObjectModel; | using System.Collections.ObjectModel; | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Collections.ObjectModel; | using System.Collections.ObjectModel; | ||||||
| using System.Windows.Controls; | using System.Windows.Controls; | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Collections.ObjectModel; | using System.Collections.ObjectModel; | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Collections.ObjectModel; | using System.Collections.ObjectModel; | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.Collections.ObjectModel; | using System.Collections.ObjectModel; | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System; | using System; | ||||||
| using System.Linq; | using System.Linq; | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ using System.Windows.Controls; | |||||||
| using System.Windows.Input; | using System.Windows.Input; | ||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
| using Elwig.Helpers.Billing; | using Elwig.Helpers.Billing; | ||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using Microsoft.EntityFrameworkCore.ChangeTracking; | using Microsoft.EntityFrameworkCore.ChangeTracking; | ||||||
| using ScottPlot; | using ScottPlot; | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| using Elwig.Documents; | using Elwig.Documents; | ||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
| using Elwig.Helpers.Export; | using Elwig.Helpers.Export; | ||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
| using LinqKit; | using LinqKit; | ||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using Microsoft.EntityFrameworkCore.ChangeTracking; | using Microsoft.EntityFrameworkCore.ChangeTracking; | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| using Elwig.Documents; | using Elwig.Documents; | ||||||
| using Elwig.Models; | using Elwig.Models.Dtos; | ||||||
|  | using Elwig.Models.Entities; | ||||||
| using Elwig.Windows; | using Elwig.Windows; | ||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System; | using System; | ||||||
| @@ -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 | ||||||
|                 } |                 } | ||||||
|             )); |             )); | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ using System.Windows; | |||||||
| using System.Windows.Controls; | using System.Windows.Controls; | ||||||
| using System.Windows.Input; | using System.Windows.Input; | ||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
| using Elwig.Models; | using Elwig.Models.Entities; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using Microsoft.EntityFrameworkCore.ChangeTracking; | using Microsoft.EntityFrameworkCore.ChangeTracking; | ||||||
| using System.Collections.ObjectModel; | using System.Collections.ObjectModel; | ||||||
|   | |||||||
| @@ -1,10 +1,10 @@ | |||||||
| using Elwig.Dialogs; | using Elwig.Dialogs; | ||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
| using Elwig.Helpers.Billing; | using Elwig.Helpers.Billing; | ||||||
|  | using Elwig.Helpers.Export; | ||||||
|  | using Elwig.Models.Dtos; | ||||||
| using Microsoft.Win32; | using Microsoft.Win32; | ||||||
| using System; | using System; | ||||||
| using System.IO; |  | ||||||
| using System.Text; |  | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| using System.Windows; | using System.Windows; | ||||||
| using System.Windows.Input; | using System.Windows.Input; | ||||||
| @@ -59,137 +59,23 @@ namespace Elwig.Windows { | |||||||
|             if (SeasonInput.Value is not int year) |             if (SeasonInput.Value is not int year) | ||||||
|                 return; |                 return; | ||||||
|             var d = new SaveFileDialog() { |             var d = new SaveFileDialog() { | ||||||
|                 FileName = $"Über-Unterlieferungen-{year}.csv", |                 FileName = $"Über-Unterlieferungen-{year}.ods", | ||||||
|                 DefaultExt = "csv", |                 DefaultExt = "ods", | ||||||
|                 Filter = "CSV-Datei (*.csv)|*.csv", |                 Filter = "OpenDocument Format Spreadsheet (*.ods)|*.ods", | ||||||
|                 Title = $"Über-/Unterlieferungen {year} speichern unter - Elwig" |                 Title = $"Über-/Unterlieferungen {year} speichern unter - Elwig" | ||||||
|             }; |             }; | ||||||
|             if (d.ShowDialog() == false) |             if (d.ShowDialog() == false) | ||||||
|                 return; |                 return; | ||||||
|  |  | ||||||
|             Mouse.OverrideCursor = Cursors.AppStarting; |             Mouse.OverrideCursor = Cursors.AppStarting; | ||||||
|  |  | ||||||
|             try { |             try { | ||||||
|                 using var file = new StreamWriter(d.FileName, false, Encoding.Latin1); |                 using var ods = new OdsFile(d.FileName); | ||||||
|                 using var cnx = await AppDbContext.ConnectAsync(); |                 await ods.AddTable(await OverUnderDeliveryData.ForSeason(Context.OverUnderDeliveryRows, year)); | ||||||
|                 await file.WriteLineAsync($"Auswertungen {year};;;;;;;;;;;"); |                 await ods.AddTable(await AreaComUnderDeliveryData.ForSeason(Context.AreaComUnderDeliveryRows, year)); | ||||||
|  |                 await ods.AddTable(await MemberDeliveryPerVariantData.ForSeason(Context.MemberDeliveryPerVariantRows, year)); | ||||||
|                 await file.WriteLineAsync($";;;;;;;;;;;"); |  | ||||||
|                 await file.WriteLineAsync($"Über-/Unterlieferungen lt. gez. GA;;;;;;;;;;;"); |  | ||||||
|                 await file.WriteLineAsync($"MgNr;Name;Vorname;Adresse;PLZ;Ort;GA;Lieferpflicht;Lieferrecht;Geliefert;Über-/Unterliefert;Prozent"); |  | ||||||
|                 using (var cmd = cnx.CreateCommand()) { |  | ||||||
|                     cmd.CommandText = $""" |  | ||||||
|                     SELECT m.mgnr, m.family_name, m.given_name, p.plz, o.name, m.address, m.business_shares, |  | ||||||
|                            m.business_shares * s.min_kg_per_bs AS min_kg, |  | ||||||
|                            m.business_shares * s.max_kg_per_bs AS max_kg, |  | ||||||
|                            COALESCE(SUM(d.weight), 0) AS sum |  | ||||||
|                     FROM member m |  | ||||||
|                         LEFT JOIN AT_plz_dest p ON p.id = m.postal_dest |  | ||||||
|                         LEFT JOIN AT_ort o ON o.okz = p.okz |  | ||||||
|                         LEFT JOIN season s ON s.year = {year} |  | ||||||
|                         LEFT JOIN v_delivery d ON d.mgnr = m.mgnr AND d.year = s.year |  | ||||||
|                     WHERE m.active = 1 |  | ||||||
|                     GROUP BY d.year, m.mgnr |  | ||||||
|                     ORDER BY sum = 0 DESC, 100.0 * sum / max_kg, m.mgnr; |  | ||||||
|                     """; |  | ||||||
|                     using var reader = await cmd.ExecuteReaderAsync(); |  | ||||||
|                     while (await reader.ReadAsync()) { |  | ||||||
|                         var mgnr = reader.GetInt32(0); |  | ||||||
|                         var familyName = reader.GetString(1); |  | ||||||
|                         var givenName = reader.GetString(2); |  | ||||||
|                         var plz = reader.GetInt32(3); |  | ||||||
|                         var ort = reader.GetString(4).Split(',')[0]; |  | ||||||
|                         var addr = reader.GetString(5); |  | ||||||
|                         var ga = reader.GetInt32(6); |  | ||||||
|                         var minKg = reader.GetInt32(7); |  | ||||||
|                         var maxKg = reader.GetInt32(8); |  | ||||||
|                         var sum = reader.GetInt32(9); |  | ||||||
|                         var s1 = sum < minKg ? $"{sum - minKg}" : sum > maxKg ? $"{sum - maxKg}" : ""; |  | ||||||
|                         var s2 = sum < minKg ? $"{sum * 100.0 / minKg - 100.0:0.0}" : sum > maxKg ? $"{sum * 100.0 / maxKg - 100:0.0}" : ""; |  | ||||||
|                         await file.WriteLineAsync($"{mgnr};{familyName};{givenName};{addr};{plz};{ort};{ga};{minKg};{maxKg};{sum};{s1};{s2}"); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 await file.WriteLineAsync($";;;;;;;;;;;"); |  | ||||||
|                 await file.WriteLineAsync($"Unterlieferungen lt. Flächenbindungen;;;;;;;;;;;"); |  | ||||||
|                 await file.WriteLineAsync($"MgNr;Name;Vorname;Adresse;PLZ;Ort;Vertrag;Fläche;Lieferpflicht;Geliefert;Unterliefert;Prozent"); |  | ||||||
|                 using (var cmd = cnx.CreateCommand()) { |  | ||||||
|                     cmd.CommandText = $""" |  | ||||||
|                     SELECT m.mgnr, m.family_name, m.given_name, p.plz, o.name, m.address, |  | ||||||
|                            c.bucket, c.area, u.min_kg, u.weight |  | ||||||
|                     FROM member m |  | ||||||
|                         LEFT JOIN AT_plz_dest p ON p.id = m.postal_dest |  | ||||||
|                         LEFT JOIN AT_ort o ON o.okz = p.okz |  | ||||||
|                         LEFT JOIN v_area_commitment_bucket_strict c ON c.mgnr = m.mgnr AND c.year = {year} |  | ||||||
|                         JOIN v_under_delivery u ON (u.mgnr, u.bucket, u.year) = (m.mgnr, c.bucket, c.year) |  | ||||||
|                     WHERE m.active = 1 |  | ||||||
|                     ORDER BY m.mgnr, c.bucket |  | ||||||
|                     """; |  | ||||||
|                     using var reader = await cmd.ExecuteReaderAsync(); |  | ||||||
|                     while (await reader.ReadAsync()) { |  | ||||||
|                         var mgnr = reader.GetInt32(0); |  | ||||||
|                         var familyName = reader.GetString(1); |  | ||||||
|                         var givenName = reader.GetString(2); |  | ||||||
|                         var plz = reader.GetInt32(3); |  | ||||||
|                         var ort = reader.GetString(4).Split(',')[0]; |  | ||||||
|                         var addr = reader.GetString(5); |  | ||||||
|                         var id = reader.GetString(6); |  | ||||||
|                         var area = reader.GetInt32(7); |  | ||||||
|                         var minKg = reader.GetInt32(8); |  | ||||||
|                         var sum = reader.GetInt32(9); |  | ||||||
|                         await file.WriteLineAsync($"{mgnr};{familyName};{givenName};{addr};{plz};{ort};{id};{area};{minKg};{sum};{sum - minKg};{sum * 100.0 / minKg - 100.0:0.0}"); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|  |  | ||||||
|                 await file.WriteLineAsync($";;;;;;;;;;;"); |  | ||||||
|                 await file.WriteLineAsync($"Lieferungen pro Mitglied und Sorte;;;;;;;;;;;"); |  | ||||||
|                 await file.WriteLineAsync($"MgNr;Name;Vorname;Adresse;PLZ;Ort;Sorte;Attribut;Geliefert;Fläche;Ertrag"); |  | ||||||
|                 using (var cmd = cnx.CreateCommand()) { |  | ||||||
|                     cmd.CommandText = $""" |  | ||||||
|                     SELECT m.mgnr, m.family_name, m.given_name, p.plz, o.name, m.address, |  | ||||||
|                            v.bucket, v.weight, v.area |  | ||||||
|                     FROM ( |  | ||||||
|                             SELECT c.year AS year, |  | ||||||
|                                    c.mgnr AS mgnr, |  | ||||||
|                                    c.bucket AS bucket, |  | ||||||
|                                    COALESCE(d.weight, 0) AS weight, |  | ||||||
|                                    COALESCE(c.area, 0) AS area |  | ||||||
|                             FROM v_area_commitment_bucket_strict c |  | ||||||
|                                 LEFT JOIN v_delivery_bucket_strict d ON (d.year, d.mgnr, d.bucket) = (c.year, c.mgnr, c.bucket) |  | ||||||
|                             WHERE c.year = {year} |  | ||||||
|                             UNION |  | ||||||
|                             SELECT d.year, |  | ||||||
|                                    d.mgnr, |  | ||||||
|                                    d.bucket, |  | ||||||
|                                    COALESCE(d.weight, 0), |  | ||||||
|                                    COALESCE(c.area, 0) |  | ||||||
|                             FROM v_delivery_bucket_strict d |  | ||||||
|                                 LEFT JOIN v_area_commitment_bucket_strict c ON (c.year, c.mgnr, c.bucket) = (d.year, d.mgnr, d.bucket) |  | ||||||
|                             WHERE d.year = {year} |  | ||||||
|                         ) v |  | ||||||
|                         LEFT JOIN member m ON m.mgnr = v.mgnr |  | ||||||
|                         LEFT JOIN AT_plz_dest p ON p.id = m.postal_dest |  | ||||||
|                         LEFT JOIN AT_ort o ON o.okz = p.okz |  | ||||||
|                     ORDER BY m.mgnr, v.bucket |  | ||||||
|                     """; |  | ||||||
|                     using var reader = await cmd.ExecuteReaderAsync(); |  | ||||||
|                     while (await reader.ReadAsync()) { |  | ||||||
|                         var mgnr = reader.GetInt32(0); |  | ||||||
|                         var familyName = reader.GetString(1); |  | ||||||
|                         var givenName = reader.GetString(2); |  | ||||||
|                         var plz = reader.GetInt32(3); |  | ||||||
|                         var ort = reader.GetString(4).Split(',')[0]; |  | ||||||
|                         var addr = reader.GetString(5); |  | ||||||
|                         var id = reader.GetString(6); |  | ||||||
|                         var sum = reader.GetInt32(7); |  | ||||||
|                         var area = reader.GetInt32(8); |  | ||||||
|                         await file.WriteLineAsync($"{mgnr};{familyName};{givenName};{addr};{plz};{ort};{id[..2]};{id[2..]};{sum};{area};{(area > 0 ? sum * 10000 / area : "")}"); |  | ||||||
|                     } |  | ||||||
|                 } |  | ||||||
|             } catch (Exception exc) { |             } catch (Exception exc) { | ||||||
|                 MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); |                 MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             Mouse.OverrideCursor = null; |             Mouse.OverrideCursor = null; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -18,6 +18,8 @@ | |||||||
|         <TextBlock x:Name="Output" Height="20" Width="200" Margin="470,329,0,0"  HorizontalAlignment="Left" VerticalAlignment="Top"/> |         <TextBlock x:Name="Output" Height="20" Width="200" Margin="470,329,0,0"  HorizontalAlignment="Left" VerticalAlignment="Top"/> | ||||||
|         <Button x:Name="ChartButton" Content="Chart" Click="ChartButton_Click" |         <Button x:Name="ChartButton" Content="Chart" Click="ChartButton_Click" | ||||||
|                 Margin="50,240,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/> |                 Margin="50,240,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/> | ||||||
|  |         <Button x:Name="ZipButton" Content="ZIP-File" Click="ZipButton_Click" | ||||||
|  |                 Margin="50,270,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/> | ||||||
|  |  | ||||||
|         <Button x:Name="PdfDeliveryButton" Content="Lieferschein Erzeugen" Click="PdfDeliveryButton_Click" Tag="Print" IsEnabled="False" |         <Button x:Name="PdfDeliveryButton" Content="Lieferschein Erzeugen" Click="PdfDeliveryButton_Click" Tag="Print" IsEnabled="False" | ||||||
|                 Margin="260,190,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/> |                 Margin="260,190,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/> | ||||||
|   | |||||||
| @@ -1,8 +1,12 @@ | |||||||
| using Elwig.Documents; | using Elwig.Documents; | ||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
| using Elwig.Helpers.Billing; | using Elwig.Helpers.Billing; | ||||||
|  | using Elwig.Helpers.Export; | ||||||
|  | using Elwig.Models.Dtos; | ||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System; | using System; | ||||||
|  | using System.Collections; | ||||||
|  | using System.Collections.Generic; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| using System.Windows; | using System.Windows; | ||||||
| using System.Windows.Input; | using System.Windows.Input; | ||||||
| @@ -51,6 +55,12 @@ namespace Elwig.Windows { | |||||||
|             w.Show(); |             w.Show(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         private async void ZipButton_Click(object sender, RoutedEventArgs evt) { | ||||||
|  |             using var ctx = new AppDbContext(); | ||||||
|  |             using var ods = new OdsFile(@"C:\Users\Lorenz\Desktop\test.ods"); | ||||||
|  |             await ods.AddTable(await DeliveryConfirmationData.ForMember(ctx.DeliveryParts, 2023, 2948)); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         private async void PdfDeliveryButton_Click(object sender, RoutedEventArgs evt) { |         private async void PdfDeliveryButton_Click(object sender, RoutedEventArgs evt) { | ||||||
|             Mouse.OverrideCursor = Cursors.AppStarting; |             Mouse.OverrideCursor = Cursors.AppStarting; | ||||||
|             using var ctx = new AppDbContext(); |             using var ctx = new AppDbContext(); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user