Compare commits
	
		
			23 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| c6cd9d7c73 | |||
| 1b28752f4c | |||
| e0bdbee2ae | |||
| ff3bd5cea5 | |||
| 116d88d3d6 | |||
| 6bcb2fb406 | |||
| 8665c93702 | |||
| 62496a0770 | |||
| 8678a02318 | |||
| 9de7fad139 | |||
| 85c8783f7e | |||
| 75e02751f0 | |||
| ef1c3b25cf | |||
| 255953a658 | |||
| 9470b26aec | |||
| 3a2bf81bd9 | |||
| d3aca196dd | |||
| 519e903d1c | |||
| dd568b81e8 | |||
| 31b0ae245d | |||
| 46498ce337 | |||
| 0fff698a5d | |||
| a71c6685f0 | 
| @@ -119,6 +119,11 @@ main h1 { | |||||||
|     font-size: 10pt; |     font-size: 10pt; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | .main-wrapper p.custom { | ||||||
|  |     white-space: pre-wrap; | ||||||
|  |     break-inside: avoid; | ||||||
|  | } | ||||||
|  |  | ||||||
| .main-wrapper .hidden { | .main-wrapper .hidden { | ||||||
|     break-before: avoid; |     break-before: avoid; | ||||||
| } | } | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ namespace Elwig.Documents { | |||||||
|  |  | ||||||
|         public PaymentMember? Payment; |         public PaymentMember? Payment; | ||||||
|         public Credit? Credit; |         public Credit? Credit; | ||||||
|         public CreditNoteData Data; |         public CreditNoteDeliveryData Data; | ||||||
|         public string? Text; |         public string? Text; | ||||||
|         public string CurrencySymbol; |         public string CurrencySymbol; | ||||||
|         public int Precision; |         public int Precision; | ||||||
| @@ -20,7 +20,7 @@ namespace Elwig.Documents { | |||||||
|         public decimal MemberTotalUnderDelivery; |         public decimal MemberTotalUnderDelivery; | ||||||
|         public decimal MemberAutoBusinessShares; |         public decimal MemberAutoBusinessShares; | ||||||
|  |  | ||||||
|         public CreditNote(AppDbContext ctx, PaymentMember p, CreditNoteData data, Dictionary<string, UnderDelivery>? underDeliveries = null) : |         public CreditNote(AppDbContext ctx, PaymentMember p, CreditNoteDeliveryData data, Dictionary<string, UnderDelivery>? underDeliveries = null) : | ||||||
|             base($"{Name} {(p.Credit != null ? $"Nr. {p.Credit.Year}/{p.Credit.TgNr:000}" : p.Member.Name)} – {p.Variant.Name}", p.Member) { |             base($"{Name} {(p.Credit != null ? $"Nr. {p.Credit.Year}/{p.Credit.TgNr:000}" : p.Member.Name)} – {p.Variant.Name}", p.Member) { | ||||||
|             UseBillingAddress = true; |             UseBillingAddress = true; | ||||||
|             ShowDateAndLocation = true; |             ShowDateAndLocation = true; | ||||||
| @@ -50,18 +50,18 @@ namespace Elwig.Documents { | |||||||
|                 $"<tr><th>Überw. am</th><td>{p.Variant.TransferDate:dd.MM.yyyy}</td></tr>" + |                 $"<tr><th>Überw. am</th><td>{p.Variant.TransferDate:dd.MM.yyyy}</td></tr>" + | ||||||
|                 $"<tr><th>Datum/Zeit</th><td>{p.Credit?.ModifiedTimestamp:dd.MM.yyyy} / {p.Credit?.ModifiedTimestamp:HH:mm}</td></tr>" + |                 $"<tr><th>Datum/Zeit</th><td>{p.Credit?.ModifiedTimestamp:dd.MM.yyyy} / {p.Credit?.ModifiedTimestamp:HH:mm}</td></tr>" + | ||||||
|                 $"</tbody></table>"; |                 $"</tbody></table>"; | ||||||
|             Text = App.Client.TextDeliveryNote; |             Text = App.Client.TextCreditNote; | ||||||
|             DocumentId = $"Tr.-Gutschr. " + (p.Credit != null ? $"{p.Credit.Year}/{p.Credit.TgNr:000}" : p.MgNr); |             DocumentId = $"Tr.-Gutschr. " + (p.Credit != null ? $"{p.Credit.Year}/{p.Credit.TgNr:000}" : p.MgNr); | ||||||
|             CurrencySymbol = season.Currency.Symbol ?? season.Currency.Code; |             CurrencySymbol = season.Currency.Symbol ?? season.Currency.Code; | ||||||
|             Precision = season.Precision; |             Precision = season.Precision; | ||||||
|  |  | ||||||
|             var variants = ctx.WineVarieties.ToDictionary(v => v.SortId, v => v); |             var varieties = ctx.WineVarieties.ToDictionary(v => v.SortId, v => v); | ||||||
|             var attributes = ctx.WineAttributes.ToDictionary(a => a.AttrId, a => a); |             var attributes = ctx.WineAttributes.ToDictionary(a => a.AttrId, a => a); | ||||||
|             var comTypes = ctx.AreaCommitmentTypes.ToDictionary(t => t.VtrgId, t => t); |             var comTypes = ctx.AreaCommitmentTypes.ToDictionary(t => t.VtrgId, t => t); | ||||||
|             MemberUnderDeliveries = underDeliveries? |             MemberUnderDeliveries = underDeliveries? | ||||||
|                 .OrderBy(u => u.Key) |                 .OrderBy(u => u.Key) | ||||||
|                 .Select(u => ( |                 .Select(u => ( | ||||||
|                     variants[u.Key[..2]].Name + (u.Key.Length > 2 ? " " + attributes[u.Key[2..]].Name : ""), |                     varieties[u.Key[..2]].Name + (u.Key.Length > 2 ? " " + attributes[u.Key[2..]].Name : ""), | ||||||
|                     u.Value.Diff, |                     u.Value.Diff, | ||||||
|                     u.Value.Diff * (comTypes[u.Key].PenaltyPerKg ?? 0) |                     u.Value.Diff * (comTypes[u.Key].PenaltyPerKg ?? 0) | ||||||
|                       - (comTypes[u.Key].PenaltyAmount ?? 0) |                       - (comTypes[u.Key].PenaltyAmount ?? 0) | ||||||
|   | |||||||
| @@ -49,7 +49,7 @@ | |||||||
|                         @if (i == 0) { |                         @if (i == 0) { | ||||||
|                             <td rowspan="@rows">@p.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</td> |                             <td class="small">@p.Variety</td> | ||||||
|                             <td class="small">@p.Attribute</td> |                             <td class="small">@p.Attribute</td> | ||||||
|                             <td rowspan="@rows" class="center">@($"{p.Gradation.Oe:N0}")</td> |                             <td rowspan="@rows" class="center">@($"{p.Gradation.Oe:N0}")</td> | ||||||
|                             <td rowspan="@rows" class="center">@($"{p.Gradation.Kmw:N1}")</td> |                             <td rowspan="@rows" class="center">@($"{p.Gradation.Kmw:N1}")</td> | ||||||
| @@ -158,4 +158,10 @@ | |||||||
|             } |             } | ||||||
|         </tbody> |         </tbody> | ||||||
|     </table> |     </table> | ||||||
|  |     <p>Überweisung erfolgt auf Konto @(Elwig.Helpers.Utils.FormatIban(Model.Member.Iban ?? "-")).</p> | ||||||
|  |     <div style="margin-top: 1em;"> | ||||||
|  |         @if (Model.Text != null) { | ||||||
|  |             <p class="custom">@Model.Text</p> | ||||||
|  |         } | ||||||
|  |     </div> | ||||||
| </main> | </main> | ||||||
|   | |||||||
| @@ -10,11 +10,11 @@ namespace Elwig.Documents { | |||||||
|         public new static string Name => "Anlieferungsbestätigung"; |         public new static string Name => "Anlieferungsbestätigung"; | ||||||
|  |  | ||||||
|         public Season Season; |         public Season Season; | ||||||
|         public DeliveryConfirmationData Data; |         public DeliveryConfirmationDeliveryData Data; | ||||||
|         public string? Text = App.Client.TextDeliveryConfirmation; |         public string? Text = App.Client.TextDeliveryConfirmation; | ||||||
|         public Dictionary<string, MemberBucket> MemberBuckets; |         public Dictionary<string, MemberBucket> MemberBuckets; | ||||||
|  |  | ||||||
|         public DeliveryConfirmation(AppDbContext ctx, int year, Member m, DeliveryConfirmationData data) : |         public DeliveryConfirmation(AppDbContext ctx, int year, Member m, DeliveryConfirmationDeliveryData data) : | ||||||
|             base($"{Name} {year}", m) { |             base($"{Name} {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; | ||||||
|   | |||||||
| @@ -42,17 +42,17 @@ | |||||||
|         </thead> |         </thead> | ||||||
|         <tbody> |         <tbody> | ||||||
|             @{ |             @{ | ||||||
|                 var lastVariant = ""; |                 var lastVariety = ""; | ||||||
|             } |             } | ||||||
|             @foreach (var p in Model.Data.Rows) { |             @foreach (var p in Model.Data.Rows) { | ||||||
|                 var rows = Math.Max(p.Buckets.Length, p.Modifiers.Length + 1); |                 var rows = Math.Max(p.Buckets.Length, p.Modifiers.Length + 1); | ||||||
|                 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.Variant != lastVariant && lastVariant != "" ? "new": "") @(rows > i + 1 ? "last" : "")"> |                     <tr class="@(first ? "first" : "") @(p.Variety != lastVariety && lastVariety != "" ? "new": "") @(rows > i + 1 ? "last" : "")"> | ||||||
|                         @if (first) { |                         @if (first) { | ||||||
|                             <td rowspan="@rows">@p.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</td> |                             <td class="small">@p.Variety</td> | ||||||
|                             <td class="small">@p.Attribute</td> |                             <td class="small">@p.Attribute</td> | ||||||
|                             <td class="small">@p.QualityLevel</td> |                             <td class="small">@p.QualityLevel</td> | ||||||
|                             <td rowspan="@rows" class="center">@($"{p.Gradation.Oe:N0}")</td> |                             <td rowspan="@rows" class="center">@($"{p.Gradation.Oe:N0}")</td> | ||||||
| @@ -80,7 +80,7 @@ | |||||||
|                             first = false; |                             first = false; | ||||||
|                         } |                         } | ||||||
|                     </tr> |                     </tr> | ||||||
|                     lastVariant = p.Variant; |                     lastVariety = p.Variety; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             <tr class="sum bold"> |             <tr class="sum bold"> | ||||||
| @@ -92,9 +92,9 @@ | |||||||
|     </table> |     </table> | ||||||
|     @Raw(BusinessDocument.PrintSortenaufteilung(Model.MemberBuckets)) |     @Raw(BusinessDocument.PrintSortenaufteilung(Model.MemberBuckets)) | ||||||
|     @Raw(Model.PrintBucketTable(Model.Season, Model.MemberBuckets, includePayment: true)) |     @Raw(Model.PrintBucketTable(Model.Season, Model.MemberBuckets, includePayment: true)) | ||||||
|     <div class="text" style="margin-top: 2em;"> |     <div style="margin-top: 2em;"> | ||||||
|         @if (Model.Text != null) { |         @if (Model.Text != null) { | ||||||
|             <p class="comment" style="white-space: pre-wrap; break-inside: avoid;">@Model.Text</p> |             <p class="custom comment">@Model.Text</p> | ||||||
|         } |         } | ||||||
|     </div> |     </div> | ||||||
| </main> | </main> | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ namespace Elwig.Documents { | |||||||
|         public DeliveryJournal(string filter, IQueryable<DeliveryPart> deliveries) : |         public DeliveryJournal(string filter, IQueryable<DeliveryPart> deliveries) : | ||||||
|             this(filter, deliveries |             this(filter, deliveries | ||||||
|                 .Include(p => p.Delivery).ThenInclude(d => d.Member) |                 .Include(p => p.Delivery).ThenInclude(d => d.Member) | ||||||
|                 .Include(p => p.Variant) |                 .Include(p => p.Variety) | ||||||
|                 .ToList()) { } |                 .ToList()) { } | ||||||
|  |  | ||||||
|         public DeliveryJournal(AppDbContext ctx, DateOnly date) : |         public DeliveryJournal(AppDbContext ctx, DateOnly date) : | ||||||
|   | |||||||
| @@ -45,7 +45,7 @@ | |||||||
|                     <td class="small">@($"{p.Delivery.Time:HH:mm}")</td> |                     <td class="small">@($"{p.Delivery.Time:HH:mm}")</td> | ||||||
|                     <td class="number">@p.Delivery.Member.MgNr</td> |                     <td class="number">@p.Delivery.Member.MgNr</td> | ||||||
|                     <td class="small">@p.Delivery.Member.AdministrativeName</td> |                     <td class="small">@p.Delivery.Member.AdministrativeName</td> | ||||||
|                     <td class="small">@p.Variant.Name</td> |                     <td class="small">@p.Variety.Name</td> | ||||||
|                     <td class="center">@($"{p.Oe:N0}")</td> |                     <td class="center">@($"{p.Oe:N0}")</td> | ||||||
|                     <td class="center">@($"{p.Kmw:N1}")</td> |                     <td class="center">@($"{p.Kmw:N1}")</td> | ||||||
|                     <td class="number">@($"{p.Weight:N0}")</td> |                     <td class="number">@($"{p.Weight:N0}")</td> | ||||||
|   | |||||||
| @@ -36,7 +36,7 @@ | |||||||
|         @foreach (var part in Model.Delivery.Parts.OrderBy(p => p.DPNr)) { |         @foreach (var part in Model.Delivery.Parts.OrderBy(p => p.DPNr)) { | ||||||
|             <tr class="main"> |             <tr class="main"> | ||||||
|                 <td class="center">@part.DPNr</td> |                 <td class="center">@part.DPNr</td> | ||||||
|                 <td colspan="2">@part.Variant.Name</td> |                 <td colspan="2">@part.Variety.Name</td> | ||||||
|                 <td colspan="2">@part.Attribute?.Name</td> |                 <td colspan="2">@part.Attribute?.Name</td> | ||||||
|                 <td>@part.Quality.Name</td> |                 <td>@part.Quality.Name</td> | ||||||
|                 <td class="center">@($"{part.Oe:N0}")</td> |                 <td class="center">@($"{part.Oe:N0}")</td> | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
|     <UseWPF>true</UseWPF> |     <UseWPF>true</UseWPF> | ||||||
|     <PreserveCompilationContext>true</PreserveCompilationContext> |     <PreserveCompilationContext>true</PreserveCompilationContext> | ||||||
|     <ApplicationIcon>Resources\Images\Elwig.ico</ApplicationIcon> |     <ApplicationIcon>Resources\Images\Elwig.ico</ApplicationIcon> | ||||||
|     <Version>0.6.1</Version> |     <Version>0.6.3</Version> | ||||||
|     <SatelliteResourceLanguages>de-AT</SatelliteResourceLanguages> |     <SatelliteResourceLanguages>de-AT</SatelliteResourceLanguages> | ||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|  |  | ||||||
|   | |||||||
| @@ -58,6 +58,7 @@ namespace Elwig.Helpers { | |||||||
|         public DbSet<OverUnderDeliveryRow> OverUnderDeliveryRows { get; private set; } |         public DbSet<OverUnderDeliveryRow> OverUnderDeliveryRows { get; private set; } | ||||||
|         public DbSet<AreaComUnderDeliveryRowSingle> AreaComUnderDeliveryRows { get; private set; } |         public DbSet<AreaComUnderDeliveryRowSingle> AreaComUnderDeliveryRows { get; private set; } | ||||||
|         public DbSet<MemberDeliveryPerVariantRowSingle> MemberDeliveryPerVariantRows { get; private set; } |         public DbSet<MemberDeliveryPerVariantRowSingle> MemberDeliveryPerVariantRows { get; private set; } | ||||||
|  |         public DbSet<CreditNoteDeliveryRowSingle> CreditNoteDeliveryRows { get; private set; } | ||||||
|         public DbSet<CreditNoteRowSingle> CreditNoteRows { get; private set; } |         public DbSet<CreditNoteRowSingle> CreditNoteRows { get; private set; } | ||||||
|  |  | ||||||
|         private readonly StreamWriter? LogFile = null; |         private readonly StreamWriter? LogFile = null; | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ namespace Elwig.Helpers { | |||||||
|     public static class AppDbUpdater { |     public static class AppDbUpdater { | ||||||
|  |  | ||||||
|         // Don't forget to update value in Tests/fetch-resources.bat! |         // Don't forget to update value in Tests/fetch-resources.bat! | ||||||
|         public static readonly int RequiredSchemaVersion = 13; |         public static readonly int RequiredSchemaVersion = 14; | ||||||
|  |  | ||||||
|         private static int VersionOffset = 0; |         private static int VersionOffset = 0; | ||||||
|  |  | ||||||
|   | |||||||
| @@ -150,31 +150,31 @@ namespace Elwig.Helpers.Billing { | |||||||
|             return dict; |             return dict; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         protected static Dictionary<string, JsonValue> GetSelection(JsonNode value, IEnumerable<string> attributeVariants) { |         protected static Dictionary<string, JsonValue> GetSelection(JsonNode value, IEnumerable<string> vaributes) { | ||||||
|             if (value is JsonValue flatRate) { |             if (value is JsonValue flatRate) { | ||||||
|                 return attributeVariants.ToDictionary(e => e, _ => flatRate); |                 return vaributes.ToDictionary(e => e, _ => flatRate); | ||||||
|             } if (value is not JsonObject data) { |             } if (value is not JsonObject data) { | ||||||
|                 throw new InvalidOperationException(); |                 throw new InvalidOperationException(); | ||||||
|             } |             } | ||||||
|             Dictionary<string, JsonValue> dict; |             Dictionary<string, JsonValue> dict; | ||||||
|             if (data["default"] is JsonValue def) { |             if (data["default"] is JsonValue def) { | ||||||
|                 dict = attributeVariants.ToDictionary(e => e, _ => def); |                 dict = vaributes.ToDictionary(e => e, _ => def); | ||||||
|             } else { |             } else { | ||||||
|                 dict = []; |                 dict = []; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             var variants = data.Where(p => !p.Key.StartsWith('/') && p.Key.Length == 2); |             var varieties = data.Where(p => !p.Key.StartsWith('/') && p.Key.Length == 2); | ||||||
|             var attributes = data.Where(p => p.Key.StartsWith('/')); |             var attributes = data.Where(p => p.Key.StartsWith('/')); | ||||||
|             var others = data.Where(p => !p.Key.StartsWith('/') && p.Key.Length > 2 && p.Key != "default"); |             var others = data.Where(p => !p.Key.StartsWith('/') && p.Key.Length > 2 && p.Key != "default"); | ||||||
|             foreach (var (idx, v) in variants) { |             foreach (var (idx, v) in varieties) { | ||||||
|                 var curve = v?.AsValue() ?? throw new InvalidOperationException(); |                 var curve = v?.AsValue() ?? throw new InvalidOperationException(); | ||||||
|                 foreach (var i in attributeVariants.Where(e => e.StartsWith(idx[..^1]))) { |                 foreach (var i in vaributes.Where(e => e.StartsWith(idx[..^1]))) { | ||||||
|                     dict[i] = curve; |                     dict[i] = curve; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             foreach (var (idx, v) in attributes) { |             foreach (var (idx, v) in attributes) { | ||||||
|                 var curve = v?.AsValue() ?? throw new InvalidOperationException(); |                 var curve = v?.AsValue() ?? throw new InvalidOperationException(); | ||||||
|                 foreach (var i in attributeVariants.Where(e => e[2..] == idx[1..])) { |                 foreach (var i in vaributes.Where(e => e[2..] == idx[1..])) { | ||||||
|                     dict[i] = curve; |                     dict[i] = curve; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
| @@ -257,7 +257,7 @@ namespace Elwig.Helpers.Billing { | |||||||
|             return curve; |             return curve; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         protected static void CollapsePaymentData(JsonObject data, IEnumerable<string> attributeVariants) { |         protected static void CollapsePaymentData(JsonObject data, IEnumerable<string> vaributes, bool useDefault = true) { | ||||||
|             Dictionary<string, List<string>> rev1 = []; |             Dictionary<string, List<string>> rev1 = []; | ||||||
|             Dictionary<decimal, List<string>> rev2 = []; |             Dictionary<decimal, List<string>> rev2 = []; | ||||||
|             foreach (var (k, v) in data) { |             foreach (var (k, v) in data) { | ||||||
| @@ -273,18 +273,18 @@ namespace Elwig.Helpers.Billing { | |||||||
|             } |             } | ||||||
|             if (!data.ContainsKey("default")) { |             if (!data.ContainsKey("default")) { | ||||||
|                 foreach (var (v, ks) in rev1) { |                 foreach (var (v, ks) in rev1) { | ||||||
|                     if (ks.Count >= attributeVariants.Count() / 2.0) { |                     if ((ks.Count >= vaributes.Count() * 0.5 && useDefault) || ks.Count == vaributes.Count()) { | ||||||
|                         foreach (var k in ks) data.Remove(k); |                         foreach (var k in ks) data.Remove(k); | ||||||
|                         data["default"] = v; |                         data["default"] = v; | ||||||
|                         CollapsePaymentData(data, attributeVariants); |                         CollapsePaymentData(data, vaributes, useDefault); | ||||||
|                         return; |                         return; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 foreach (var (v, ks) in rev2) { |                 foreach (var (v, ks) in rev2) { | ||||||
|                     if (ks.Count >= attributeVariants.Count() / 2.0) { |                     if ((ks.Count >= vaributes.Count() * 0.5 && useDefault) || ks.Count == vaributes.Count()) { | ||||||
|                         foreach (var k in ks) data.Remove(k); |                         foreach (var k in ks) data.Remove(k); | ||||||
|                         data["default"] = v; |                         data["default"] = v; | ||||||
|                         CollapsePaymentData(data, attributeVariants); |                         CollapsePaymentData(data, vaributes, useDefault); | ||||||
|                         return; |                         return; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
| @@ -296,17 +296,17 @@ namespace Elwig.Helpers.Billing { | |||||||
|                 .Distinct() |                 .Distinct() | ||||||
|                 .ToList(); |                 .ToList(); | ||||||
|             foreach (var idx in attributes) { |             foreach (var idx in attributes) { | ||||||
|                 var len = attributeVariants.Count(e => e.EndsWith(idx)); |                 var len = vaributes.Count(e => e.EndsWith(idx)); | ||||||
|                 foreach (var (v, ks) in rev1) { |                 foreach (var (v, ks) in rev1) { | ||||||
|                     var myKs = ks.Where(k => k.EndsWith(idx)).ToList(); |                     var myKs = ks.Where(k => k.EndsWith(idx)).ToList(); | ||||||
|                     if (myKs.Count > 1 && myKs.Count >= len / 2.0) { |                     if (myKs.Count > 1 && ((myKs.Count >= len * 0.5 && useDefault) || myKs.Count == len)) { | ||||||
|                         foreach (var k in myKs) data.Remove(k); |                         foreach (var k in myKs) data.Remove(k); | ||||||
|                         data[idx] = v; |                         data[idx] = v; | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 foreach (var (v, ks) in rev2) { |                 foreach (var (v, ks) in rev2) { | ||||||
|                     var myKs = ks.Where(k => k.EndsWith(idx)).ToList(); |                     var myKs = ks.Where(k => k.EndsWith(idx)).ToList(); | ||||||
|                     if (myKs.Count > 1 && myKs.Count >= len / 2.0) { |                     if (myKs.Count > 1 && ((myKs.Count >= len * 0.5 && useDefault) || myKs.Count == len)) { | ||||||
|                         foreach (var k in myKs) data.Remove(k); |                         foreach (var k in myKs) data.Remove(k); | ||||||
|                         data[idx] = v; |                         data[idx] = v; | ||||||
|                     } |                     } | ||||||
| @@ -314,7 +314,13 @@ namespace Elwig.Helpers.Billing { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public static JsonObject FromGraphEntries(IEnumerable<GraphEntry> graphEntries, BillingData? origData = null, IEnumerable<string>? attributeVariants = null) { |         public static JsonObject FromGraphEntries( | ||||||
|  |             IEnumerable<GraphEntry> graphEntries, | ||||||
|  |             BillingData? origData = null, | ||||||
|  |             IEnumerable<string>? vaributes = null, | ||||||
|  |             bool useDefaultPayment = true, | ||||||
|  |             bool useDefaultQuality = true | ||||||
|  |         ) { | ||||||
|             var payment = new JsonObject(); |             var payment = new JsonObject(); | ||||||
|             var qualityWei = new JsonObject(); |             var qualityWei = new JsonObject(); | ||||||
|             var curves = new JsonArray(); |             var curves = new JsonArray(); | ||||||
| @@ -331,7 +337,7 @@ namespace Elwig.Helpers.Billing { | |||||||
|                 } else { |                 } else { | ||||||
|                     continue; |                     continue; | ||||||
|                 } |                 } | ||||||
|                 foreach (var c in entry.Contracts) { |                 foreach (var c in entry.Vaributes) { | ||||||
|                     if (entry.Abgewertet) { |                     if (entry.Abgewertet) { | ||||||
|                         qualityWei[$"{c.Variety?.SortId}/{c.Attribute?.AttrId}"] = node.DeepClone(); |                         qualityWei[$"{c.Variety?.SortId}/{c.Attribute?.AttrId}"] = node.DeepClone(); | ||||||
|                     } else { |                     } else { | ||||||
| @@ -340,8 +346,8 @@ namespace Elwig.Helpers.Billing { | |||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             CollapsePaymentData(payment, attributeVariants ?? payment.Select(e => e.Key).ToList()); |             CollapsePaymentData(payment, vaributes ?? payment.Select(e => e.Key).ToList(), useDefaultPayment); | ||||||
|             CollapsePaymentData(qualityWei, attributeVariants ?? qualityWei.Select(e => e.Key).ToList()); |             CollapsePaymentData(qualityWei, vaributes ?? qualityWei.Select(e => e.Key).ToList(), useDefaultQuality); | ||||||
|  |  | ||||||
|             var data = new JsonObject { |             var data = new JsonObject { | ||||||
|                 ["mode"] = "elwig", |                 ["mode"] = "elwig", | ||||||
| @@ -359,16 +365,16 @@ namespace Elwig.Helpers.Billing { | |||||||
|  |  | ||||||
|             if (payment.Count == 0) { |             if (payment.Count == 0) { | ||||||
|                 data["payment"] = 0; |                 data["payment"] = 0; | ||||||
|             } else if (payment.Count == 1) { |             } else if (payment.Count == 1 && payment.First().Key == "default") { | ||||||
|                 data["payment"] = payment.Single().Value?.DeepClone(); |                 data["payment"] = payment.Single().Value?.DeepClone(); | ||||||
|             } else { |             } else { | ||||||
|                 data["payment"] = payment; |                 data["payment"] = payment; | ||||||
|             } |             } | ||||||
|             if (qualityWei.Count == 1) { |             if (qualityWei.Count == 1 && qualityWei.First().Key == "default") { | ||||||
|                 data["quality"] = new JsonObject() { |                 data["quality"] = new JsonObject() { | ||||||
|                     ["WEI"] = qualityWei.Single().Value?.DeepClone() |                     ["WEI"] = qualityWei.Single().Value?.DeepClone() | ||||||
|                 }; |                 }; | ||||||
|             } else if (qualityWei.Count > 1) { |             } else if (qualityWei.Count >= 1) { | ||||||
|                 data["quality"] = new JsonObject() { |                 data["quality"] = new JsonObject() { | ||||||
|                     ["WEI"] = qualityWei |                     ["WEI"] = qualityWei | ||||||
|                 }; |                 }; | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ namespace Elwig.Helpers.Billing { | |||||||
|         public BillingVariant(int year, int avnr) : base(year) { |         public BillingVariant(int year, int avnr) : base(year) { | ||||||
|             AvNr = avnr; |             AvNr = avnr; | ||||||
|             PaymentVariant = Context.PaymentVariants.Find(Year, AvNr) ?? throw new ArgumentException("PaymentVar not found"); |             PaymentVariant = Context.PaymentVariants.Find(Year, AvNr) ?? throw new ArgumentException("PaymentVar not found"); | ||||||
|             Data = PaymentBillingData.FromJson(PaymentVariant.Data, Utils.GetAttributeVarieties(Context, Year)); |             Data = PaymentBillingData.FromJson(PaymentVariant.Data, Utils.GetVaributes(Context, Year, onlyDelivered: false)); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public async Task Calculate() { |         public async Task Calculate() { | ||||||
| @@ -24,9 +24,10 @@ namespace Elwig.Helpers.Billing { | |||||||
|             await DeleteInDb(cnx); |             await DeleteInDb(cnx); | ||||||
|             await SetCalcTime(cnx); |             await SetCalcTime(cnx); | ||||||
|             await CalculatePrices(cnx); |             await CalculatePrices(cnx); | ||||||
|             if (Data.ConsiderDelieryModifiers) |             if (Data.ConsiderDelieryModifiers) { | ||||||
|                 await CalculateDeliveryModifiers(cnx); |                 await CalculateDeliveryModifiers(cnx); | ||||||
|             await CalculateMemberModifiers(cnx); |                 await CalculateMemberModifiers(cnx); | ||||||
|  |             } | ||||||
|             await tx.CommitAsync(); |             await tx.CommitAsync(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -42,11 +43,10 @@ namespace Elwig.Helpers.Billing { | |||||||
|                            ROUND(p.amount / POW(10, s.precision - 2)) AS net_amount, |                            ROUND(p.amount / POW(10, s.precision - 2)) AS net_amount, | ||||||
|                            ROUND(lp.amount / POW(10, s.precision - 2)) AS prev_amount, |                            ROUND(lp.amount / POW(10, s.precision - 2)) AS prev_amount, | ||||||
|                            IIF(m.buchführend, s.vat_normal, s.vat_flatrate) AS vat, |                            IIF(m.buchführend, s.vat_normal, s.vat_flatrate) AS vat, | ||||||
|                            ROUND( |                            ROUND(IIF({Data.ConsiderContractPenalties}, COALESCE(u.total_penalty, 0), 0) / POW(10, 4 - 2)) + | ||||||
|                                IIF({Data.ConsiderContractPenalties}, COALESCE(u.total_penalty, 0) / POW(10, 4 - 2), 0) + |                            ROUND(IIF({Data.ConsiderTotalPenalty}, COALESCE(b.total_penalty, 0), 0) / POW(10, s.precision - 2)) + | ||||||
|                                IIF({Data.ConsiderTotalPenalty}, COALESCE(b.total_penalty, 0), 0) + |                            ROUND(IIF({Data.ConsiderAutoBusinessShares}, -COALESCE(a.total_amount, 0), 0) / POW(10, s.precision - 2)) | ||||||
|                                IIF({Data.ConsiderAutoBusinessShares}, -COALESCE(a.business_shares * s.bs_value, 0), 0) / POW(10, s.precision - 2) |                            AS modifiers, | ||||||
|                            ) AS modifiers, |  | ||||||
|                            lc.modifiers AS prev_modifiers |                            lc.modifiers AS prev_modifiers | ||||||
|                     FROM season s |                     FROM season s | ||||||
|                         JOIN payment_variant v ON v.year = s.year |                         JOIN payment_variant v ON v.year = s.year | ||||||
| @@ -62,26 +62,9 @@ namespace Elwig.Helpers.Billing { | |||||||
|                         LEFT JOIN payment_member lp ON (lp.year, lp.avnr, lp.mgnr) = (l.year, l.avnr, m.mgnr) |                         LEFT JOIN payment_member lp ON (lp.year, lp.avnr, lp.mgnr) = (l.year, l.avnr, m.mgnr) | ||||||
|                         LEFT JOIN payment_member p ON (p.year, p.avnr, p.mgnr) = (v.year, v.avnr, m.mgnr) |                         LEFT JOIN payment_member p ON (p.year, p.avnr, p.mgnr) = (v.year, v.avnr, m.mgnr) | ||||||
|                         LEFT JOIN credit lc ON (lc.year, lc.avnr, lc.mgnr) = (l.year, l.avnr, m.mgnr) |                         LEFT JOIN credit lc ON (lc.year, lc.avnr, lc.mgnr) = (l.year, l.avnr, m.mgnr) | ||||||
|                         LEFT JOIN (SELECT year, mgnr, |                         LEFT JOIN v_penalty_area_commitments u ON (u.year, u.mgnr) = (s.year, m.mgnr) | ||||||
|                                           SUM(COALESCE(IIF(u.weight = 0, -t.penalty_none, 0), 0) + |                         LEFT JOIN v_penalty_business_shares b ON (b.year, b.mgnr) = (s.year, m.mgnr) | ||||||
|                                               COALESCE(IIF(u.diff < 0, -t.penalty_amount, 0), 0) + |                         LEFT JOIN v_auto_business_shares a ON (a.year, a.mgnr) = (s.year, m.mgnr) | ||||||
|                                               COALESCE(u.diff * t.penalty_per_kg, 0)) AS total_penalty |  | ||||||
|                                    FROM v_under_delivery u |  | ||||||
|                                        JOIN area_commitment_type t ON t.vtrgid = u.bucket |  | ||||||
|                                    GROUP BY year, mgnr) u ON (u.year, u.mgnr) = (s.year, m.mgnr) |  | ||||||
|                         LEFT JOIN (SELECT s.year, u.mgnr, |  | ||||||
|                                           (COALESCE(IIF(u.weight = 0, -s.penalty_none, 0), 0) + |  | ||||||
|                                            COALESCE(IIF(u.diff < 0, -s.penalty_amount, 0), 0) + |  | ||||||
|                                            COALESCE(u.diff * s.penalty_per_kg, 0) |  | ||||||
|                                            ) / POW(10, s.precision - 2) AS total_penalty |  | ||||||
|                                    FROM v_total_under_delivery u |  | ||||||
|                                        JOIN season s ON s.year = u.year |  | ||||||
|                                    WHERE u.diff < 0) b ON (b.year, b.mgnr) = (s.year, m.mgnr) |  | ||||||
|                         LEFT JOIN (SELECT h.mgnr, h.business_shares |  | ||||||
|                                    FROM member_history h |  | ||||||
|                                    WHERE type = 'auto' AND |  | ||||||
|                                          date >= '{Year}-06-01' AND |  | ||||||
|                                          date < '{Year + 1}-06-01') a ON a.mgnr = m.mgnr |  | ||||||
|                     WHERE s.year = {Year} AND v.avnr = {AvNr}; |                     WHERE s.year = {Year} AND v.avnr = {AvNr}; | ||||||
|  |  | ||||||
|                     UPDATE payment_variant SET test_variant = FALSE WHERE (year, avnr) = ({Year}, {AvNr}); |                     UPDATE payment_variant SET test_variant = FALSE WHERE (year, avnr) = ({Year}, {AvNr}); | ||||||
|   | |||||||
| @@ -7,15 +7,15 @@ using System.Text.Json.Nodes; | |||||||
| namespace Elwig.Helpers.Billing { | namespace Elwig.Helpers.Billing { | ||||||
|     public class EditBillingData : BillingData { |     public class EditBillingData : BillingData { | ||||||
|  |  | ||||||
|         protected readonly IEnumerable<string> AttributeVariants; |         protected readonly IEnumerable<string> Vaributes; | ||||||
|  |  | ||||||
|         public EditBillingData(JsonObject data, IEnumerable<string> attributeVariants) : |         public EditBillingData(JsonObject data, IEnumerable<string> vaributes) : | ||||||
|             base(data) { |             base(data) { | ||||||
|             AttributeVariants = attributeVariants; |             Vaributes = vaributes; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public static EditBillingData FromJson(string json, IEnumerable<string> attributeVariants) { |         public static EditBillingData FromJson(string json, IEnumerable<string> vaributes) { | ||||||
|             return new(ParseJson(json), attributeVariants); |             return new(ParseJson(json), vaributes); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private (Dictionary<int, Curve>, Dictionary<int, List<string>>) GetGraphEntries(JsonNode root) { |         private (Dictionary<int, Curve>, Dictionary<int, List<string>>) GetGraphEntries(JsonNode root) { | ||||||
| @@ -56,7 +56,7 @@ namespace Elwig.Helpers.Billing { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             Dictionary<int, List<string>> dict3 = curves.ToDictionary(c => c.Key, _ => new List<string>()); |             Dictionary<int, List<string>> dict3 = curves.ToDictionary(c => c.Key, _ => new List<string>()); | ||||||
|             foreach (var (selector, value) in GetSelection(root, AttributeVariants)) { |             foreach (var (selector, value) in GetSelection(root, Vaributes)) { | ||||||
|                 int? idx = null; |                 int? idx = null; | ||||||
|                 if (value.TryGetValue<decimal>(out var val)) { |                 if (value.TryGetValue<decimal>(out var val)) { | ||||||
|                     idx = Array.IndexOf(virtCurves, val) + virtOffset; |                     idx = Array.IndexOf(virtCurves, val) + virtOffset; | ||||||
| @@ -70,12 +70,16 @@ namespace Elwig.Helpers.Billing { | |||||||
|             return (curves, dict3); |             return (curves, dict3); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private static List<GraphEntry> CreateGraphEntries(AppDbContext ctx, int precision, Dictionary<int, Curve> curves, Dictionary<int, List<string>> entries) { |         private static List<GraphEntry> CreateGraphEntries( | ||||||
|  |             AppDbContext ctx, int precision, | ||||||
|  |             Dictionary<int, Curve> curves, | ||||||
|  |             Dictionary<int, List<string>> entries | ||||||
|  |         ) { | ||||||
|             var vars = ctx.WineVarieties.ToDictionary(v => v.SortId, v => v); |             var vars = ctx.WineVarieties.ToDictionary(v => v.SortId, v => v); | ||||||
|             var attrs = ctx.WineAttributes.ToDictionary(a => a.AttrId, a => a); |             var attrs = ctx.WineAttributes.ToDictionary(a => a.AttrId, a => a); | ||||||
|             return entries |             return entries | ||||||
|                 .Select(e => new GraphEntry(e.Key, precision, curves[e.Key], e.Value |                 .Select(e => new GraphEntry(e.Key, precision, curves[e.Key], e.Value | ||||||
|                     .Select(s => new ContractSelection(vars[s[..2]], s.Length > 2 ? attrs[s[2..]] : null)) |                     .Select(s => new Varibute(vars[s[..2]], s.Length > 2 ? attrs[s[2..]] : null)) | ||||||
|                     .ToList())) |                     .ToList())) | ||||||
|                 .ToList(); |                 .ToList(); | ||||||
|         } |         } | ||||||
| @@ -83,7 +87,7 @@ namespace Elwig.Helpers.Billing { | |||||||
|         public IEnumerable<GraphEntry> GetPaymentGraphEntries(AppDbContext ctx, Season season) { |         public IEnumerable<GraphEntry> GetPaymentGraphEntries(AppDbContext ctx, Season season) { | ||||||
|             var root = GetPaymentEntry(); |             var root = GetPaymentEntry(); | ||||||
|             var (curves, entries) = GetGraphEntries(root); |             var (curves, entries) = GetGraphEntries(root); | ||||||
|             return CreateGraphEntries(ctx, season.Precision, curves, entries).Where(e => e.Contracts.Count > 0); |             return CreateGraphEntries(ctx, season.Precision, curves, entries).Where(e => e.Vaributes.Count > 0); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public IEnumerable<GraphEntry> GetQualityGraphEntries(AppDbContext ctx, Season season, int idOffset = 0) { |         public IEnumerable<GraphEntry> GetQualityGraphEntries(AppDbContext ctx, Season season, int idOffset = 0) { | ||||||
| @@ -91,7 +95,7 @@ namespace Elwig.Helpers.Billing { | |||||||
|             if (root == null || root["WEI"] is not JsonNode qualityWei) |             if (root == null || root["WEI"] is not JsonNode qualityWei) | ||||||
|                 return []; |                 return []; | ||||||
|             var (curves, entries) = GetGraphEntries(qualityWei); |             var (curves, entries) = GetGraphEntries(qualityWei); | ||||||
|             var list = CreateGraphEntries(ctx, season.Precision, curves, entries).Where(e => e.Contracts.Count > 0); |             var list = CreateGraphEntries(ctx, season.Precision, curves, entries).Where(e => e.Vaributes.Count > 0); | ||||||
|             foreach (var e in list) { |             foreach (var e in list) { | ||||||
|                 e.Id += idOffset; |                 e.Id += idOffset; | ||||||
|                 e.Abgewertet = true; |                 e.Abgewertet = true; | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ namespace Elwig.Helpers.Billing { | |||||||
|  |  | ||||||
|         public const int MinX = 50; |         public const int MinX = 50; | ||||||
|         public const int MinXGeb = 73; |         public const int MinXGeb = 73; | ||||||
|         public const int MaxX = 140; |         public const int MaxX = 120; | ||||||
|  |  | ||||||
|         public int Id { get; set; } |         public int Id { get; set; } | ||||||
|         public BillingData.CurveMode Mode { get; set; } |         public BillingData.CurveMode Mode { get; set; } | ||||||
| @@ -36,10 +36,10 @@ namespace Elwig.Helpers.Billing { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public List<ContractSelection> Contracts { get; set; } |         public List<Varibute> Vaributes { get; set; } | ||||||
|         public string ContractsStringSimple => (Abgewertet ? "Abgew.: " : "") + (Contracts.Count != 0 ? (Contracts.Count >= 25 ? "Restliche Sorten" : string.Join(", ", Contracts.Select(c => c.Listing))) : "-"); |         public string VaributeStringSimple => (Abgewertet ? "Abgew.: " : "") + (Vaributes.Count != 0 ? (Vaributes.Count >= 25 ? "Restliche Sorten" : string.Join(", ", Vaributes.Select(c => c.Listing))) : "-"); | ||||||
|         public string ContractsString => Contracts.Count != 0 ? string.Join("\n", Contracts.Select(c => c.FullName)) : "-"; |         public string VaributeString => Vaributes.Count != 0 ? string.Join("\n", Vaributes.Select(c => c.FullName)) : "-"; | ||||||
|         public string ContractsStringChange => (Abgewertet ? "A." : "") + string.Join(",", Contracts.Select(c => c.Listing)); |         public string VaributeStringChange => (Abgewertet ? "A." : "") + string.Join(",", Vaributes.Select(c => c.Listing)); | ||||||
|         private readonly int Precision; |         private readonly int Precision; | ||||||
|  |  | ||||||
|         public GraphEntry(int id, int precision, BillingData.CurveMode mode) { |         public GraphEntry(int id, int precision, BillingData.CurveMode mode) { | ||||||
| @@ -47,7 +47,7 @@ namespace Elwig.Helpers.Billing { | |||||||
|             Precision = precision; |             Precision = precision; | ||||||
|             Mode = mode; |             Mode = mode; | ||||||
|             DataGraph = new Graph(precision, MinX, MaxX); ; |             DataGraph = new Graph(precision, MinX, MaxX); ; | ||||||
|             Contracts = []; |             Vaributes = []; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public GraphEntry(int id, int precision, BillingData.CurveMode mode, Dictionary<double, decimal> data, Dictionary<double, decimal>? gebunden) : |         public GraphEntry(int id, int precision, BillingData.CurveMode mode, Dictionary<double, decimal> data, Dictionary<double, decimal>? gebunden) : | ||||||
| @@ -56,21 +56,21 @@ namespace Elwig.Helpers.Billing { | |||||||
|             if (gebunden != null) GebundenGraph = new Graph(gebunden, precision, MinXGeb, MaxX); |             if (gebunden != null) GebundenGraph = new Graph(gebunden, precision, MinXGeb, MaxX); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public GraphEntry(int id, int precision, BillingData.Curve curve, List<ContractSelection> contracts) : |         public GraphEntry(int id, int precision, BillingData.Curve curve, List<Varibute> vaributes) : | ||||||
|             this(id, precision, curve.Mode) { |             this(id, precision, curve.Mode) { | ||||||
|             DataGraph = new Graph(curve.Normal, precision, MinX, MaxX); |             DataGraph = new Graph(curve.Normal, precision, MinX, MaxX); | ||||||
|             if (curve.Gebunden != null) |             if (curve.Gebunden != null) | ||||||
|                 GebundenGraph = new Graph(curve.Gebunden, precision, MinXGeb, MaxX); |                 GebundenGraph = new Graph(curve.Gebunden, precision, MinXGeb, MaxX); | ||||||
|             Contracts = contracts; |             Vaributes = vaributes; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private GraphEntry(int id, int precision, BillingData.CurveMode mode, Graph dataGraph, Graph? gebundenGraph, List<ContractSelection> contracts) { |         private GraphEntry(int id, int precision, BillingData.CurveMode mode, Graph dataGraph, Graph? gebundenGraph, List<Varibute> vaributes) { | ||||||
|             Id = id; |             Id = id; | ||||||
|             Precision = precision; |             Precision = precision; | ||||||
|             Mode = mode; |             Mode = mode; | ||||||
|             DataGraph = dataGraph; |             DataGraph = dataGraph; | ||||||
|             GebundenGraph = gebundenGraph; |             GebundenGraph = gebundenGraph; | ||||||
|             Contracts = contracts; |             Vaributes = vaributes; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public void AddGebundenGraph() { |         public void AddGebundenGraph() { | ||||||
|   | |||||||
| @@ -9,24 +9,24 @@ namespace Elwig.Helpers.Billing { | |||||||
|         protected readonly Dictionary<int, Curve> Curves; |         protected readonly Dictionary<int, Curve> Curves; | ||||||
|         protected readonly Dictionary<string, Curve> PaymentData; |         protected readonly Dictionary<string, Curve> PaymentData; | ||||||
|         protected readonly Dictionary<string, Curve> QualityData; |         protected readonly Dictionary<string, Curve> QualityData; | ||||||
|         protected readonly IEnumerable<string> AttributeVariants; |         protected readonly IEnumerable<string> Vaributes; | ||||||
|  |  | ||||||
|         public PaymentBillingData(JsonObject data, IEnumerable<string> attributeVariants) : |         public PaymentBillingData(JsonObject data, IEnumerable<string> vaributes) : | ||||||
|             base(data) { |             base(data) { | ||||||
|             if (attributeVariants.Any(e => e.Any(c => c < 'A' || c > 'Z'))) |             if (vaributes.Any(e => e.Any(c => c < 'A' || c > 'Z'))) | ||||||
|                 throw new ArgumentException("Invalid attributeVariants"); |                 throw new ArgumentException("Invalid vaributes"); | ||||||
|             AttributeVariants = attributeVariants; |             Vaributes = vaributes; | ||||||
|             Curves = GetCurves(); |             Curves = GetCurves(); | ||||||
|             PaymentData = GetPaymentData(); |             PaymentData = GetPaymentData(); | ||||||
|             QualityData = GetQualityData(); |             QualityData = GetQualityData(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public static PaymentBillingData FromJson(string json, IEnumerable<string> attributeVariants) { |         public static PaymentBillingData FromJson(string json, IEnumerable<string> vaributes) { | ||||||
|             return new(ParseJson(json), attributeVariants); |             return new(ParseJson(json), vaributes); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private Dictionary<string, Curve> GetData(JsonNode data) { |         private Dictionary<string, Curve> GetData(JsonNode data) { | ||||||
|             return GetSelection(data, AttributeVariants).ToDictionary(e => e.Key, e => LookupCurve(e.Value)); |             return GetSelection(data, Vaributes).ToDictionary(e => e.Key, e => LookupCurve(e.Value)); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         protected Dictionary<string, Curve> GetPaymentData() { |         protected Dictionary<string, Curve> GetPaymentData() { | ||||||
|   | |||||||
| @@ -2,14 +2,17 @@ | |||||||
| using System; | using System; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Helpers.Billing { | namespace Elwig.Helpers.Billing { | ||||||
|     public class ContractSelection : IComparable<ContractSelection> { |     public class Varibute : IComparable<Varibute> { | ||||||
| 
 | 
 | ||||||
|         public WineVar? Variety { get; } |         public WineVar? Variety { get; } | ||||||
|         public WineAttr? Attribute { get; } |         public WineAttr? Attribute { get; } | ||||||
|  |         public int? AssignedGraphId { get; set; } | ||||||
|  |         public int? AssignedAbgewGraphId { get; set; } | ||||||
|  | 
 | ||||||
|         public string Listing => $"{Variety?.SortId}{Attribute?.AttrId}"; |         public string Listing => $"{Variety?.SortId}{Attribute?.AttrId}"; | ||||||
|         public string FullName => $"{Variety?.Name}" + (Variety != null && Attribute != null ? " " : "") + $"{Attribute?.Name}"; |         public string FullName => $"{Variety?.Name}" + (Variety != null && Attribute != null ? " " : "") + $"{Attribute?.Name}"; | ||||||
| 
 | 
 | ||||||
|         public ContractSelection(WineVar? var, WineAttr? attr) { |         public Varibute(WineVar? var, WineAttr? attr) { | ||||||
|             Variety = var; |             Variety = var; | ||||||
|             Attribute = attr; |             Attribute = attr; | ||||||
|         } |         } | ||||||
| @@ -18,7 +21,7 @@ namespace Elwig.Helpers.Billing { | |||||||
|             return Listing; |             return Listing; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public int CompareTo(ContractSelection? other) { |         public int CompareTo(Varibute? other) { | ||||||
|             return Listing.CompareTo(other?.Listing); |             return Listing.CompareTo(other?.Listing); | ||||||
|         }  |         }  | ||||||
|     } |     } | ||||||
| @@ -60,6 +60,7 @@ namespace Elwig.Helpers { | |||||||
|  |  | ||||||
|         public string? TextDeliveryNote; |         public string? TextDeliveryNote; | ||||||
|         public string? TextDeliveryConfirmation; |         public string? TextDeliveryConfirmation; | ||||||
|  |         public string? TextCreditNote; | ||||||
|  |  | ||||||
|         public ClientParameters(AppDbContext ctx) : this(ctx.ClientParameters.ToDictionary(e => e.Param, e => e.Value)) { } |         public ClientParameters(AppDbContext ctx) : this(ctx.ClientParameters.ToDictionary(e => e.Param, e => e.Value)) { } | ||||||
|  |  | ||||||
| @@ -99,6 +100,8 @@ namespace Elwig.Helpers { | |||||||
|                 if (TextDeliveryNote == "") TextDeliveryNote = null; |                 if (TextDeliveryNote == "") TextDeliveryNote = null; | ||||||
|                 TextDeliveryConfirmation = parameters.GetValueOrDefault("TEXT_DELIVERYCONFIRMATION"); |                 TextDeliveryConfirmation = parameters.GetValueOrDefault("TEXT_DELIVERYCONFIRMATION"); | ||||||
|                 if (TextDeliveryConfirmation == "") TextDeliveryConfirmation = null; |                 if (TextDeliveryConfirmation == "") TextDeliveryConfirmation = null; | ||||||
|  |                 TextCreditNote = parameters.GetValueOrDefault("TEXT_CREDITNOTE"); | ||||||
|  |                 if (TextCreditNote == "") TextCreditNote = null; | ||||||
|             } catch { |             } catch { | ||||||
|                 throw new KeyNotFoundException(); |                 throw new KeyNotFoundException(); | ||||||
|             } |             } | ||||||
| @@ -133,6 +136,7 @@ namespace Elwig.Helpers { | |||||||
|                 ("DOCUMENT_SENDER", Sender2), |                 ("DOCUMENT_SENDER", Sender2), | ||||||
|                 ("TEXT_DELIVERYNOTE", TextDeliveryNote), |                 ("TEXT_DELIVERYNOTE", TextDeliveryNote), | ||||||
|                 ("TEXT_DELIVERYCONFIRMATION", TextDeliveryConfirmation), |                 ("TEXT_DELIVERYCONFIRMATION", TextDeliveryConfirmation), | ||||||
|  |                 ("TEXT_CREDITNOTE", TextCreditNote), | ||||||
|             }; |             }; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -108,19 +108,19 @@ namespace Elwig.Helpers.Export { | |||||||
|                    <style:paragraph-properties fo:text-align="center"/> |                    <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:text-properties fo:font-weight="bold" style:font-weight-asian="bold" style:font-weight-complex="bold"/> | ||||||
|                   </style:style> |                   </style:style> | ||||||
|                   <number:number-style style:name="NN0"><number:number number:decimal-places="0" number:min-decimal-places="0" number:min-integer-digits="1"/></number:number-style> |                   <number:number-style style:name="NN0"><number:number number:decimal-places="0" number:min-decimal-places="0" number:min-integer-digits="1" number:grouping="true"/></number:number-style> | ||||||
|                   <style:style style:name="N0" style:family="table-cell" style:parent-style-name="default" style:data-style-name="NN0"/> |                   <style:style style:name="N0" style:family="table-cell" style:parent-style-name="default" style:data-style-name="NN0"/> | ||||||
|                   <number:number-style style:name="NN1"><number:number number:decimal-places="1" number:min-decimal-places="1" number:min-integer-digits="1"/></number:number-style> |                   <number:number-style style:name="NN1"><number:number number:decimal-places="1" number:min-decimal-places="1" number:min-integer-digits="1" number:grouping="true"/></number:number-style> | ||||||
|                   <style:style style:name="N1" style:family="table-cell" style:parent-style-name="default" style:data-style-name="NN1"/> |                   <style:style style:name="N1" style:family="table-cell" style:parent-style-name="default" style:data-style-name="NN1"/> | ||||||
|                   <number:number-style style:name="NN2"><number:number number:decimal-places="2" number:min-decimal-places="2" number:min-integer-digits="1"/></number:number-style> |                   <number:number-style style:name="NN2"><number:number number:decimal-places="2" number:min-decimal-places="2" number:min-integer-digits="1" number:grouping="true"/></number:number-style> | ||||||
|                   <style:style style:name="N2" style:family="table-cell" style:parent-style-name="default" style:data-style-name="NN2"/> |                   <style:style style:name="N2" style:family="table-cell" style:parent-style-name="default" style:data-style-name="NN2"/> | ||||||
|                   <number:number-style style:name="NN3"><number:number number:decimal-places="3" number:min-decimal-places="3" number:min-integer-digits="1"/></number:number-style> |                   <number:number-style style:name="NN3"><number:number number:decimal-places="3" number:min-decimal-places="3" number:min-integer-digits="1" number:grouping="true"/></number:number-style> | ||||||
|                   <style:style style:name="N3" style:family="table-cell" style:parent-style-name="default" style:data-style-name="NN3"/> |                   <style:style style:name="N3" style:family="table-cell" style:parent-style-name="default" style:data-style-name="NN3"/> | ||||||
|                   <number:number-style style:name="NN4"><number:number number:decimal-places="4" number:min-decimal-places="4" number:min-integer-digits="1"/></number:number-style> |                   <number:number-style style:name="NN4"><number:number number:decimal-places="4" number:min-decimal-places="4" number:min-integer-digits="1" number:grouping="true"/></number:number-style> | ||||||
|                   <style:style style:name="N4" style:family="table-cell" style:parent-style-name="default" style:data-style-name="NN4"/> |                   <style:style style:name="N4" style:family="table-cell" style:parent-style-name="default" style:data-style-name="NN4"/> | ||||||
|                   <number:number-style style:name="NN5"><number:number number:decimal-places="5" number:min-decimal-places="5" number:min-integer-digits="1"/></number:number-style> |                   <number:number-style style:name="NN5"><number:number number:decimal-places="5" number:min-decimal-places="5" number:min-integer-digits="1" number:grouping="true"/></number:number-style> | ||||||
|                   <style:style style:name="N5" style:family="table-cell" style:parent-style-name="default" style:data-style-name="NN5"/> |                   <style:style style:name="N5" style:family="table-cell" style:parent-style-name="default" style:data-style-name="NN5"/> | ||||||
|                   <number:number-style style:name="NN6"><number:number number:decimal-places="6" number:min-decimal-places="6" number:min-integer-digits="1"/></number:number-style> |                   <number:number-style style:name="NN6"><number:number number:decimal-places="6" number:min-decimal-places="6" number:min-integer-digits="1" number:grouping="true"/></number:number-style> | ||||||
|                   <style:style style:name="N6" style:family="table-cell" style:parent-style-name="default" style:data-style-name="NN6"/> |                   <style:style style:name="N6" style:family="table-cell" style:parent-style-name="default" style:data-style-name="NN6"/> | ||||||
|                  </office:automatic-styles> |                  </office:automatic-styles> | ||||||
|                  <office:body> |                  <office:body> | ||||||
| @@ -262,13 +262,14 @@ namespace Elwig.Helpers.Export { | |||||||
|             string c; |             string c; | ||||||
|             if (data == null) { |             if (data == null) { | ||||||
|                 c = $"<{ct}{add}/>"; |                 c = $"<{ct}{add}/>"; | ||||||
|             } else if (data is float || data is double || data is byte || data is char || |             } else if (data is decimal || 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) { |                        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");  // use default culture for ToString and Parse()! |                 double v = double.Parse(data?.ToString() ?? "0");  // use default culture for ToString and Parse()! | ||||||
|                 if (units != null && units.Length > 0) { |                 if (units != null && units.Length > 0) { | ||||||
|                     int n = -1; |                     int n = -1; | ||||||
|                     switch (units[0]) { |                     switch (units[0]) { | ||||||
|                         case "%": n = 1; data = $"{v:N1}"; break; |                         case "%": n = 1; data = $"{v:N1}"; break; | ||||||
|  |                         case "€": n = 2; data = $"{v:N2}"; break; | ||||||
|                         case "°KMW": n = 1; data = $"{v:N1}"; break; |                         case "°KMW": n = 1; data = $"{v:N1}"; break; | ||||||
|                         case "°Oe": n = 0; data = $"{v:N0}"; break; |                         case "°Oe": n = 0; data = $"{v:N0}"; break; | ||||||
|                     } |                     } | ||||||
|   | |||||||
| @@ -74,12 +74,16 @@ namespace Elwig.Helpers.Printing { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         public static async Task Print(string path, int copies = 1) { |         public static async Task Print(string path, int copies = 1) { | ||||||
|             var p = new Process() { StartInfo = new() { FileName = PdfToPrinter } }; |             try { | ||||||
|             p.StartInfo.ArgumentList.Add(path); |                 var p = new Process() { StartInfo = new() { FileName = PdfToPrinter } }; | ||||||
|             p.StartInfo.ArgumentList.Add("/s"); |                 p.StartInfo.ArgumentList.Add(path); | ||||||
|             p.StartInfo.ArgumentList.Add($"copies={copies}"); |                 p.StartInfo.ArgumentList.Add("/s"); | ||||||
|             p.Start(); |                 p.StartInfo.ArgumentList.Add($"copies={copies}"); | ||||||
|             await p.WaitForExitAsync(); |                 p.Start(); | ||||||
|  |                 await p.WaitForExitAsync(); | ||||||
|  |             } catch (Exception e) { | ||||||
|  |                 MessageBox.Show("Beim Drucken ist ein Fehler aufgetreten:\n\n" + e.Message, "Fehler beim Drucken"); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -163,7 +163,7 @@ namespace Elwig.Helpers { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         public static string FormatIban(string iban) { |         public static string FormatIban(string iban) { | ||||||
|             return Regex.Replace(iban, ".{4}", "$0 "); |             return Regex.Replace(iban.Trim(), ".{4}", "$0 ").Trim(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public static void RunBackground(string title, Func<Task> a) { |         public static void RunBackground(string title, Func<Task> a) { | ||||||
| @@ -362,25 +362,21 @@ namespace Elwig.Helpers { | |||||||
|             return output.OrderByDescending(l => l.Count()); |             return output.OrderByDescending(l => l.Count()); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public static List<string> GetAttributeVarieties(AppDbContext ctx, int year, bool withSlash = false) { |         public static List<string> GetVaributes(AppDbContext ctx, int year, bool withSlash = false, bool onlyDelivered = true) { | ||||||
|             return ctx.DeliveryParts |             var varieties = ctx.WineVarieties.Select(v => v.SortId).ToList(); | ||||||
|  |             var delivered = ctx.DeliveryParts | ||||||
|                .Where(d => d.Year == year) |                .Where(d => d.Year == year) | ||||||
|                .Select(d => $"{d.SortId}{(withSlash ? "/" : "")}{d.AttrId}") |                .Select(d => $"{d.SortId}{(withSlash ? "/" : "")}{d.AttrId}") | ||||||
|                .Distinct() |                .Distinct() | ||||||
|                .ToList() |  | ||||||
|                .Union(ctx.WineVarieties.Select(v => v.SortId)) |  | ||||||
|                .ToList(); |                .ToList(); | ||||||
|  |             return [.. (onlyDelivered ? delivered : delivered.Union(varieties)).Order()]; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public static List<ContractSelection> GetContractsForYear(AppDbContext ctx, int year) { |         public static List<Varibute> GetVaributeList(AppDbContext ctx, int year, bool onlyDelivered = true) { | ||||||
|             return ctx.DeliveryParts |             var varieties = ctx.WineVarieties.ToDictionary(v => v.SortId, v => v); | ||||||
|                 .Where(p => p.Year == year) |             var attributes = ctx.WineAttributes.ToDictionary(a => a.AttrId, a => a); | ||||||
|                 .Select(d => new ContractSelection(d.Variant, d.Attribute)) |             return GetVaributes(ctx, year, false, onlyDelivered) | ||||||
|                 .Distinct() |                 .Select(s => new Varibute(varieties[s[..2]], s.Length > 2 ? attributes[s[2..]] : null)) | ||||||
|                 .ToList() |  | ||||||
|                 .Union(ctx.WineVarieties.Select(v => new ContractSelection(v, null))) |  | ||||||
|                 .DistinctBy(c => c.Listing) |  | ||||||
|                 .Order() |  | ||||||
|                 .ToList(); |                 .ToList(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|   | |||||||
| @@ -1,5 +1,4 @@ | |||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System; |  | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| @@ -8,7 +7,7 @@ using System.Threading.Tasks; | |||||||
| namespace Elwig.Models.Dtos { | namespace Elwig.Models.Dtos { | ||||||
|     public class AreaComUnderDeliveryData : DataTable<AreaComUnderDeliveryRow> { |     public class AreaComUnderDeliveryData : DataTable<AreaComUnderDeliveryRow> { | ||||||
|  |  | ||||||
|         private static readonly (string, string, string?, int)[] FieldNames = new[] { |         private static readonly (string, string, string?, int)[] FieldNames = [ | ||||||
|             ("MgNr", "MgNr.", null, 12), |             ("MgNr", "MgNr.", null, 12), | ||||||
|             ("Name", "Name", null, 40), |             ("Name", "Name", null, 40), | ||||||
|             ("GivenName", "Vorname", null, 40), |             ("GivenName", "Vorname", null, 40), | ||||||
| @@ -20,7 +19,7 @@ namespace Elwig.Models.Dtos { | |||||||
|             ("DeliveryObligations", "Lieferpflicht", "kg", 22), |             ("DeliveryObligations", "Lieferpflicht", "kg", 22), | ||||||
|             ("Weights", "Geliefert", "kg", 22), |             ("Weights", "Geliefert", "kg", 22), | ||||||
|             ("UnderDeliveries", "Unterliefert", "kg|%", 34), |             ("UnderDeliveries", "Unterliefert", "kg|%", 34), | ||||||
|         }; |         ]; | ||||||
|  |  | ||||||
|         public AreaComUnderDeliveryData(IEnumerable<AreaComUnderDeliveryRow> rows, int year) : |         public AreaComUnderDeliveryData(IEnumerable<AreaComUnderDeliveryRow> rows, int year) : | ||||||
|             base($"Unterlieferungen FB", $"Unterlieferungen laut Flächenbindungen {year}", rows, FieldNames) { |             base($"Unterlieferungen FB", $"Unterlieferungen laut Flächenbindungen {year}", rows, FieldNames) { | ||||||
|   | |||||||
| @@ -1,162 +1,180 @@ | |||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
| using Elwig.Helpers.Billing; | using Elwig.Helpers.Billing; | ||||||
| using Elwig.Models.Entities; |  | ||||||
| using Microsoft.EntityFrameworkCore; | using Microsoft.EntityFrameworkCore; | ||||||
| using System; |  | ||||||
| using System.Collections.Generic; | using System.Collections.Generic; | ||||||
| using System.ComponentModel.DataAnnotations.Schema; | using System.ComponentModel.DataAnnotations.Schema; | ||||||
|  | using System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder; | ||||||
| using System.Linq; | using System.Linq; | ||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
|  |  | ||||||
| namespace Elwig.Models.Dtos { | namespace Elwig.Models.Dtos { | ||||||
|     public class CreditNoteData : DataTable<CreditNoteRow> { |     public class CreditNoteData : DataTable<CreditNoteRow> { | ||||||
|  |  | ||||||
|         private static readonly (string, string, string?)[] FieldNames = new[] { |         private static readonly (string, string, string?, int)[] FieldNames = [ | ||||||
|             ("", "", (string?)null), // TODO |             ("MgNr", "MgNr.", null, 12), | ||||||
|         }; |             ("Name", "Name", null, 40), | ||||||
|  |             ("GivenName", "Vorname", null, 40), | ||||||
|  |             ("Address", "Adresse", null, 60), | ||||||
|  |             ("Plz", "PLZ", null, 10), | ||||||
|  |             ("Locality", "Ort", null, 60), | ||||||
|  |             ("Iban", "IBAN", null, 45), | ||||||
|  |             ("TgNr", "TG-Nr.", null, 20), | ||||||
|  |             ("Sum", "Zwischens.", "€", 20), | ||||||
|  |             ("Surcharge", "Zuschlag", "€", 20), | ||||||
|  |             ("Total", "Gesamt", "€", 20), | ||||||
|  |             ("ConsideredSum", "Berückstgt.", "€", 20), | ||||||
|  |             ("Net", "Netto", "€", 20), | ||||||
|  |             ("Vat1", "10% MwSt.", "€", 20), | ||||||
|  |             ("Vat2", "13% MwSt.", "€", 20), | ||||||
|  |             ("Gross", "Brutto", "€", 20), | ||||||
|  |             ("Penalties", "Pönalen FB", "€", 20), | ||||||
|  |             ("Penalty", "Unterl. GA", "€", 20), | ||||||
|  |             ("AutoBs", "GA Nachz.", "€", 20), | ||||||
|  |             ("Others", "Sonstige", "€", 20), | ||||||
|  |             ("Considered", "Berückstgt.", "€", 20), | ||||||
|  |             ("Amount", "Betrag", "€", 20), | ||||||
|  |         ]; | ||||||
|  |  | ||||||
|         private readonly int Year; |         public CreditNoteData(IEnumerable<CreditNoteRow> rows, int year, string name) : | ||||||
|         private readonly int? TgNr; |             base($"Buchungsliste", $"Buchungsliste {name} {year}", rows, FieldNames) { | ||||||
|         private readonly int? AvNr; |  | ||||||
|         private readonly int? MgNr; |  | ||||||
|  |  | ||||||
|         private CreditNoteData(IEnumerable<CreditNoteRow> rows, int year, int? tgnr, int? avnr = null, int? mgnr = null) : |  | ||||||
|             base($"Traubengutschrift {year}/{tgnr}", rows, FieldNames) { |  | ||||||
|             Year = year; |  | ||||||
|             TgNr = tgnr; |  | ||||||
|             AvNr = avnr; |  | ||||||
|             MgNr = mgnr; |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         public static async Task<IDictionary<int, CreditNoteData>> ForPaymentVariant(DbSet<CreditNoteRowSingle> table, DbSet<Season> seasons, int year, int avnr) { |         public static async Task<CreditNoteData> ForPaymentVariant(AppDbContext ctx, int year, int avnr) { | ||||||
|             return (await FromDbSet(table, year, avnr)) |             var variant = await ctx.PaymentVariants.FindAsync(year, avnr); | ||||||
|                 .GroupBy( |             var name = variant!.Name; | ||||||
|                     r => new { r.Year, r.AvNr, r.MgNr, r.TgNr, r.DId, r.DPNr }, |             var data = BillingData.FromJson(variant!.Data); | ||||||
|                     (k, g) => new CreditNoteRow(g, seasons)) |             var rows = (await FromDbSet(ctx.CreditNoteRows, year, avnr)).Select(r => new CreditNoteRow(r, data)).ToList(); | ||||||
|                 .GroupBy( |             return new CreditNoteData(rows, year, name); | ||||||
|                     r => new { r.Year, r.AvNr, r.MgNr, r.TgNr }, |  | ||||||
|                     (k, g) => new CreditNoteData(g, k.Year, k.TgNr, mgnr: k.MgNr)) |  | ||||||
|                 .ToDictionary(d => d.MgNr ?? 0); |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private static async Task<IEnumerable<CreditNoteRowSingle>> FromDbSet(DbSet<CreditNoteRowSingle> table, int? year = null, int? avnr = null, int? mgnr = null) { |         private static async Task<IEnumerable<CreditNoteRowSingle>> FromDbSet(DbSet<CreditNoteRowSingle> table, int year, int avnr) { | ||||||
|             var y = year?.ToString() ?? "NULL"; |             return await table.FromSql($""" | ||||||
|             var v = avnr?.ToString() ?? "NULL"; |                 SELECT m.mgnr, m.family_name, m.given_name, p.plz, o.name AS ort, m.address, m.iban, c.tgnr, s.year, s.precision, | ||||||
|             var m = mgnr?.ToString() ?? "NULL"; |                        p.amount - p.net_amount AS surcharge, | ||||||
|             return await table.FromSqlRaw($""" |                        c.net_amount, c.prev_net_amount, c.vat, c.vat_amount, c.gross_amount, c.modifiers, c.prev_modifiers, c.amount, | ||||||
|                 SELECT d.year, c.tgnr, v.avnr, d.mgnr, d.did, d.lsnr, d.dpnr, d.weight, d.modifiers, |                        ROUND(COALESCE(u.total_penalty, 0) / POW(10, 4 - 2)) AS fb_penalty, | ||||||
|                        b.bktnr, d.sortid, b.discr, b.value, pb.price, pb.amount, p.net_amount, p.amount AS total_amount, |                        ROUND(COALESCE(b.total_penalty, 0) / POW(10, s.precision - 2)) AS bs_penalty, | ||||||
|                        s.name AS variant, a.name AS attribute, q.name AS quality_level, d.oe, d.kmw |                        ROUND(COALESCE(a.total_amount, 0) / POW(10, s.precision - 2)) AS auto_bs | ||||||
|                 FROM v_delivery d |                 FROM credit c | ||||||
|                     JOIN wine_variety s ON s.sortid = d.sortid |                     LEFT JOIN member m ON m.mgnr = c.mgnr | ||||||
|                     LEFT JOIN wine_attribute a ON a.attrid = d.attrid |                     LEFT JOIN payment_member p ON (p.year, p.avnr, p.mgnr) = (c.year, c.avnr, c.mgnr)  | ||||||
|                     JOIN wine_quality_level q ON q.qualid = d.qualid |                     LEFT JOIN AT_plz_dest p ON p.id = m.postal_dest | ||||||
|                     LEFT JOIN delivery_part_bucket b ON (b.year, b.did, b.dpnr) = (d.year, d.did, d.dpnr) |                     LEFT JOIN AT_ort o ON o.okz = p.okz | ||||||
|                     LEFT JOIN payment_variant v ON v.year = d.year |                     LEFT JOIN season s ON s.year = c.year | ||||||
|                     LEFT JOIN payment_delivery_part p ON (p.year, p.did, p.dpnr, p.avnr) = (d.year, d.did, d.dpnr, v.avnr) |                     LEFT JOIN v_penalty_area_commitments u ON (u.year, u.mgnr) = (s.year, m.mgnr) | ||||||
|                     LEFT JOIN payment_delivery_part_bucket pb ON (pb.year, pb.did, pb.dpnr, pb.bktnr, pb.avnr) = (b.year, b.did, b.dpnr, b.bktnr, v.avnr) |                     LEFT JOIN v_penalty_business_shares b ON (b.year, b.mgnr) = (s.year, m.mgnr) | ||||||
|                     LEFT JOIN credit c ON (c.year, c.avnr, c.mgnr) = (d.year, v.avnr, d.mgnr) |                     LEFT JOIN v_auto_business_shares a ON (a.year, a.mgnr) = (s.year, m.mgnr) | ||||||
|                 WHERE b.value > 0 AND (d.year = {y} OR {y} IS NULL) AND (v.avnr = {v} OR {v} IS NULL) AND (d.mgnr = {m} OR {m} IS NULL) |                 WHERE c.year = {year} AND c.avnr = {avnr} | ||||||
|                 ORDER BY d.year, v.avnr, d.mgnr, d.lsnr, d.dpnr |                 ORDER BY m.mgnr | ||||||
|                 """).ToListAsync(); |                 """).ToListAsync(); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     public class CreditNoteRow { |     public class CreditNoteRow { | ||||||
|  |  | ||||||
|         public int Year; |  | ||||||
|         public int? TgNr; |  | ||||||
|         public int AvNr; |  | ||||||
|         public int MgNr; |         public int MgNr; | ||||||
|  |         public string Name; | ||||||
|  |         public string GivenName; | ||||||
|  |         public string Address; | ||||||
|  |         public int Plz; | ||||||
|  |         public string Locality; | ||||||
|  |         public string Iban; | ||||||
|  |         public string TgNr; | ||||||
|  |         public decimal Sum; | ||||||
|  |         public decimal? Surcharge; | ||||||
|  |         public decimal Total; | ||||||
|  |         public decimal? ConsideredSum; | ||||||
|  |         public decimal Net; | ||||||
|  |         public decimal? Vat1, Vat2; | ||||||
|  |         public decimal Gross; | ||||||
|  |         public decimal? Penalties; | ||||||
|  |         public decimal? Penalty; | ||||||
|  |         public decimal? AutoBs; | ||||||
|  |         public decimal? Others; | ||||||
|  |         public decimal? Considered; | ||||||
|  |         public decimal Amount; | ||||||
|  |  | ||||||
|         public string LsNr; |         public CreditNoteRow(CreditNoteRowSingle row, BillingData data) { | ||||||
|         public int DPNr; |             byte prec1 = 2, prec2 = row.Precision; | ||||||
|         public string Variant; |             MgNr = row.MgNr; | ||||||
|         public string? Attribute; |             Name = row.Name; | ||||||
|         public string[] Modifiers; |             GivenName = row.GivenName; | ||||||
|         public string QualityLevel; |             Address = row.Address; | ||||||
|         public (double Oe, double Kmw) Gradation; |             Plz = row.Plz; | ||||||
|         public (string Name, int Value, decimal? Price, decimal? Amount)[] Buckets; |             Locality = row.Locality; | ||||||
|         public decimal? TotalModifiers; |             Iban = Utils.FormatIban(row.Iban); | ||||||
|         public decimal? Amount; |             TgNr = $"{row.Year}/{row.TgNr}"; | ||||||
|  |             Total = Utils.DecFromDb(row.NetAmount, prec1); | ||||||
|         public CreditNoteRow(IEnumerable<CreditNoteRowSingle> rows, DbSet<Season> seasons) { |             Surcharge = (row.Surcharge == null || row.Surcharge == 0) ? null : Utils.DecFromDb((long)row.Surcharge, prec2); | ||||||
|             var f = rows.First(); |             Sum = Total - (Surcharge ?? 0); | ||||||
|             Year = f.Year; |             ConsideredSum = (row.PrevNetAmount == null ||row.PrevNetAmount == 0) ? null : -Utils.DecFromDb((long)row.PrevNetAmount, prec1); | ||||||
|             TgNr = f.TgNr; |             Net = Total + (ConsideredSum ?? 0); | ||||||
|             MgNr = f.MgNr; |             if (row.Vat == 0.10) { | ||||||
|             var season = seasons.Find(Year); |                 Vat1 = Utils.DecFromDb(row.VatAmount, prec1); | ||||||
|  |             } else if (row.Vat == 0.13) { | ||||||
|             LsNr = f.LsNr; |                 Vat2 = Utils.DecFromDb(row.VatAmount, prec1); | ||||||
|             DPNr = f.DPNr; |             } | ||||||
|             Variant = f.Variant; |             decimal mod = (row.Modifiers == null) ? 0 : Utils.DecFromDb((long)row.Modifiers, prec1); | ||||||
|             Attribute = f.Attribute; |             if (data.ConsiderContractPenalties) | ||||||
|             var modifiers = (IEnumerable<Modifier>)(f.Modifiers ?? "").Split(',') |                 Penalties = (row.FbPenalty == null || row.FbPenalty == 0) ? null : Utils.DecFromDb((long)row.FbPenalty, prec1); | ||||||
|                 .Select(m => season?.Modifiers.FirstOrDefault(s => s.ModId == m)) |             if (data.ConsiderTotalPenalty) | ||||||
|                 .Where(m => m != null) |                 Penalty = (row.BsPealty == null || row.BsPealty == 0) ? null : Utils.DecFromDb((long)row.BsPealty, prec1); | ||||||
|                 .OrderBy(m => m.Ordering) |             if (data.ConsiderAutoBusinessShares) | ||||||
|                 .ToList(); |                 AutoBs = (row.AutoBs == null || row.AutoBs == 0) ? null : -Utils.DecFromDb((long)row.AutoBs, prec1); | ||||||
|             Modifiers = modifiers.Select(m => m.Name).ToArray(); |             mod -= (Penalties ?? 0) + (Penalty ?? 0) + (AutoBs ?? 0); | ||||||
|             QualityLevel = f.QualityLevel; |             Others = (mod == 0) ? null : mod; | ||||||
|             Gradation = (f.Oe, f.Kmw); |             Gross = Utils.DecFromDb(row.GrossAmount, prec1); | ||||||
|             Buckets = rows |             Considered = (row.PrevModifiers == null || row.PrevModifiers == 0) ? null : -Utils.DecFromDb((long)row.PrevModifiers, prec1); | ||||||
|                 .Where(b => b.Value > 0) |             Amount = Utils.DecFromDb(row.Amount, prec1); | ||||||
|                 .OrderByDescending(b => b.BktNr) |  | ||||||
|                 .Select(b => (b.Discr == "_" ? "ungeb." : $"geb. {f.SortId}{b.Discr}", b.Value, |  | ||||||
|                               b.Price != null ? season?.DecFromDb((long)b.Price) : null, |  | ||||||
|                               b.Amount != null ? season?.DecFromDb((long)b.Amount) : null)) |  | ||||||
|                 .ToArray(); |  | ||||||
|             Amount = f.TotalAmount != null ? season?.DecFromDb((long)f.TotalAmount) : null; |  | ||||||
|             var netAmount = f.NetAmount != null ? season?.DecFromDb((long)f.NetAmount) : null; |  | ||||||
|             TotalModifiers = Amount - netAmount; |  | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     [Keyless] |     [Keyless] | ||||||
|     public class CreditNoteRowSingle { |     public class CreditNoteRowSingle { | ||||||
|         [Column("year")] |  | ||||||
|         public int Year { get; set; } |  | ||||||
|         [Column("tgnr")] |  | ||||||
|         public int? TgNr { get; set; } |  | ||||||
|         [Column("avnr")] |  | ||||||
|         public int? AvNr { get; set; } |  | ||||||
|         [Column("mgnr")] |         [Column("mgnr")] | ||||||
|         public int MgNr { get; set; } |         public int MgNr { get; set; } | ||||||
|         [Column("did")] |         [Column("family_name")] | ||||||
|         public int DId { get; set; } |         public string Name { get; set; } | ||||||
|         [Column("lsnr")] |         [Column("given_name")] | ||||||
|         public string LsNr { get; set; } |         public string GivenName { get; set; } | ||||||
|         [Column("dpnr")] |         [Column("address")] | ||||||
|         public int DPNr { get; set; } |         public string Address { get; set; } | ||||||
|         [Column("weight")] |         [Column("plz")] | ||||||
|         public int Weight { get; set; } |         public int Plz { get; set; } | ||||||
|         [Column("modifiers")] |         [Column("ort")] | ||||||
|         public string? Modifiers { get; set; } |         public string LocalityFull { get; set; } | ||||||
|         [Column("bktnr")] |         [NotMapped] | ||||||
|         public int BktNr { get; set; } |         public string Locality => LocalityFull.Split(",")[0]; | ||||||
|         [Column("sortid")] |         [Column("iban")] | ||||||
|         public string SortId { get; set; } |         public string Iban { get; set; } | ||||||
|         [Column("discr")] |         [Column("year")] | ||||||
|         public string Discr { get; set; } |         public int Year { get; set; } | ||||||
|         [Column("value")] |         [Column("precision")] | ||||||
|         public int Value { get; set; } |         public byte Precision { get; set; } | ||||||
|         [Column("price")] |         [Column("tgnr")] | ||||||
|         public long? Price { get; set; } |         public string TgNr { get; set; } | ||||||
|         [Column("amount")] |         [Column("surcharge")] | ||||||
|         public long? Amount { get; set; } |         public long? Surcharge { get; set; } | ||||||
|         [Column("net_amount")] |         [Column("net_amount")] | ||||||
|         public long? NetAmount { get; set; } |         public long NetAmount { get; set; } | ||||||
|         [Column("total_amount")] |         [Column("prev_net_amount")] | ||||||
|         public long? TotalAmount { get; set; } |         public long? PrevNetAmount { get; set; } | ||||||
|         [Column("variant")] |         [Column("vat")] | ||||||
|         public string Variant { get; set; } |         public double Vat { get; set; } | ||||||
|         [Column("attribute")] |         [Column("vat_amount")] | ||||||
|         public string? Attribute { get; set; } |         public long VatAmount { get; set; } | ||||||
|         [Column("quality_level")] |         [Column("gross_amount")] | ||||||
|         public string QualityLevel { get; set; } |         public long GrossAmount { get; set; } | ||||||
|         [Column("oe")] |         [Column("modifiers")] | ||||||
|         public double Oe { get; set; } |         public long? Modifiers { get; set; } | ||||||
|         [Column("kmw")] |         [Column("prev_modifiers")] | ||||||
|         public double Kmw { get; set; } |         public long? PrevModifiers { get; set; } | ||||||
|  |         [Column("amount")] | ||||||
|  |         public long Amount { get; set; } | ||||||
|  |         [Column("fb_penalty")] | ||||||
|  |         public long? FbPenalty { get; set; } | ||||||
|  |         [Column("bs_penalty")] | ||||||
|  |         public long? BsPealty { get; set; } | ||||||
|  |         [Column("auto_bs")] | ||||||
|  |         public long? AutoBs { get; set; } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										159
									
								
								Elwig/Models/Dtos/CreditNoteDeliveryData.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										159
									
								
								Elwig/Models/Dtos/CreditNoteDeliveryData.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,159 @@ | |||||||
|  | using Elwig.Models.Entities; | ||||||
|  | using Microsoft.EntityFrameworkCore; | ||||||
|  | using System.Collections.Generic; | ||||||
|  | using System.ComponentModel.DataAnnotations.Schema; | ||||||
|  | using System.Linq; | ||||||
|  | using System.Threading.Tasks; | ||||||
|  |  | ||||||
|  | namespace Elwig.Models.Dtos { | ||||||
|  |     public class CreditNoteDeliveryData : DataTable<CreditNoteDeliveryRow> { | ||||||
|  |  | ||||||
|  |         private static readonly (string, string, string?)[] FieldNames = [ | ||||||
|  |             ("", "", null), // TODO | ||||||
|  |         ]; | ||||||
|  |  | ||||||
|  |         private readonly int Year; | ||||||
|  |         private readonly int? TgNr; | ||||||
|  |         private readonly int? AvNr; | ||||||
|  |         private readonly int? MgNr; | ||||||
|  |  | ||||||
|  |         private CreditNoteDeliveryData(IEnumerable<CreditNoteDeliveryRow> rows, int year, int? tgnr, int? avnr = null, int? mgnr = null) : | ||||||
|  |             base($"Traubengutschrift {year}/{tgnr}", rows, FieldNames) { | ||||||
|  |             Year = year; | ||||||
|  |             TgNr = tgnr; | ||||||
|  |             AvNr = avnr; | ||||||
|  |             MgNr = mgnr; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         public static async Task<IDictionary<int, CreditNoteDeliveryData>> ForPaymentVariant(DbSet<CreditNoteDeliveryRowSingle> table, DbSet<Season> seasons, int year, int avnr) { | ||||||
|  |             return (await FromDbSet(table, year, avnr)) | ||||||
|  |                 .GroupBy( | ||||||
|  |                     r => new { r.Year, r.AvNr, r.MgNr, r.TgNr, r.DId, r.DPNr }, | ||||||
|  |                     (k, g) => new CreditNoteDeliveryRow(g, seasons)) | ||||||
|  |                 .GroupBy( | ||||||
|  |                     r => new { r.Year, r.AvNr, r.MgNr, r.TgNr }, | ||||||
|  |                     (k, g) => new CreditNoteDeliveryData(g, k.Year, k.TgNr, mgnr: k.MgNr)) | ||||||
|  |                 .ToDictionary(d => d.MgNr ?? 0); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private static async Task<IEnumerable<CreditNoteDeliveryRowSingle>> FromDbSet(DbSet<CreditNoteDeliveryRowSingle> table, int? year = null, int? avnr = null, int? mgnr = null) { | ||||||
|  |             var y = year?.ToString() ?? "NULL"; | ||||||
|  |             var v = avnr?.ToString() ?? "NULL"; | ||||||
|  |             var m = mgnr?.ToString() ?? "NULL"; | ||||||
|  |             return await table.FromSqlRaw($""" | ||||||
|  |                 SELECT d.year, c.tgnr, v.avnr, d.mgnr, d.did, d.lsnr, d.dpnr, d.weight, d.modifiers, | ||||||
|  |                        b.bktnr, d.sortid, b.discr, b.value, pb.price, pb.amount, p.net_amount, p.amount AS total_amount, | ||||||
|  |                        s.name AS variety, a.name AS attribute, q.name AS quality_level, d.oe, d.kmw | ||||||
|  |                 FROM v_delivery d | ||||||
|  |                     JOIN wine_variety s ON s.sortid = d.sortid | ||||||
|  |                     LEFT JOIN wine_attribute a ON a.attrid = d.attrid | ||||||
|  |                     JOIN wine_quality_level q ON q.qualid = d.qualid | ||||||
|  |                     LEFT JOIN delivery_part_bucket b ON (b.year, b.did, b.dpnr) = (d.year, d.did, d.dpnr) | ||||||
|  |                     LEFT JOIN payment_variant v ON v.year = d.year | ||||||
|  |                     LEFT JOIN payment_delivery_part p ON (p.year, p.did, p.dpnr, p.avnr) = (d.year, d.did, d.dpnr, v.avnr) | ||||||
|  |                     LEFT JOIN payment_delivery_part_bucket pb ON (pb.year, pb.did, pb.dpnr, pb.bktnr, pb.avnr) = (b.year, b.did, b.dpnr, b.bktnr, v.avnr) | ||||||
|  |                     LEFT JOIN credit c ON (c.year, c.avnr, c.mgnr) = (d.year, v.avnr, d.mgnr) | ||||||
|  |                 WHERE b.value > 0 AND (d.year = {y} OR {y} IS NULL) AND (v.avnr = {v} OR {v} IS NULL) AND (d.mgnr = {m} OR {m} IS NULL) | ||||||
|  |                 ORDER BY d.year, v.avnr, d.mgnr, d.lsnr, d.dpnr | ||||||
|  |                 """).ToListAsync(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public class CreditNoteDeliveryRow { | ||||||
|  |  | ||||||
|  |         public int Year; | ||||||
|  |         public int? TgNr; | ||||||
|  |         public int AvNr; | ||||||
|  |         public int MgNr; | ||||||
|  |  | ||||||
|  |         public string LsNr; | ||||||
|  |         public int DPNr; | ||||||
|  |         public string Variety; | ||||||
|  |         public string? Attribute; | ||||||
|  |         public string[] Modifiers; | ||||||
|  |         public string QualityLevel; | ||||||
|  |         public (double Oe, double Kmw) Gradation; | ||||||
|  |         public (string Name, int Value, decimal? Price, decimal? Amount)[] Buckets; | ||||||
|  |         public decimal? TotalModifiers; | ||||||
|  |         public decimal? Amount; | ||||||
|  |  | ||||||
|  |         public CreditNoteDeliveryRow(IEnumerable<CreditNoteDeliveryRowSingle> rows, DbSet<Season> seasons) { | ||||||
|  |             var f = rows.First(); | ||||||
|  |             Year = f.Year; | ||||||
|  |             TgNr = f.TgNr; | ||||||
|  |             MgNr = f.MgNr; | ||||||
|  |             var season = seasons.Find(Year); | ||||||
|  |  | ||||||
|  |             LsNr = f.LsNr; | ||||||
|  |             DPNr = f.DPNr; | ||||||
|  |             Variety = f.Variety; | ||||||
|  |             Attribute = f.Attribute; | ||||||
|  |             var modifiers = (IEnumerable<Modifier>)(f.Modifiers ?? "").Split(',') | ||||||
|  |                 .Select(m => season?.Modifiers.FirstOrDefault(s => s.ModId == m)) | ||||||
|  |                 .Where(m => m != null) | ||||||
|  |                 .OrderBy(m => m.Ordering) | ||||||
|  |                 .ToList(); | ||||||
|  |             Modifiers = modifiers.Select(m => m.Name).ToArray(); | ||||||
|  |             QualityLevel = f.QualityLevel; | ||||||
|  |             Gradation = (f.Oe, f.Kmw); | ||||||
|  |             Buckets = rows | ||||||
|  |                 .Where(b => b.Value > 0) | ||||||
|  |                 .OrderByDescending(b => b.BktNr) | ||||||
|  |                 .Select(b => (b.Discr == "_" ? "ungeb." : $"geb. {f.SortId}{b.Discr}", b.Value, | ||||||
|  |                               b.Price != null ? season?.DecFromDb((long)b.Price) : null, | ||||||
|  |                               b.Amount != null ? season?.DecFromDb((long)b.Amount) : null)) | ||||||
|  |                 .ToArray(); | ||||||
|  |             Amount = f.TotalAmount != null ? season?.DecFromDb((long)f.TotalAmount) : null; | ||||||
|  |             var netAmount = f.NetAmount != null ? season?.DecFromDb((long)f.NetAmount) : null; | ||||||
|  |             TotalModifiers = Amount - netAmount; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     [Keyless] | ||||||
|  |     public class CreditNoteDeliveryRowSingle { | ||||||
|  |         [Column("year")] | ||||||
|  |         public int Year { get; set; } | ||||||
|  |         [Column("tgnr")] | ||||||
|  |         public int? TgNr { get; set; } | ||||||
|  |         [Column("avnr")] | ||||||
|  |         public int? AvNr { get; set; } | ||||||
|  |         [Column("mgnr")] | ||||||
|  |         public int MgNr { get; set; } | ||||||
|  |         [Column("did")] | ||||||
|  |         public int DId { get; set; } | ||||||
|  |         [Column("lsnr")] | ||||||
|  |         public string LsNr { get; set; } | ||||||
|  |         [Column("dpnr")] | ||||||
|  |         public int DPNr { get; set; } | ||||||
|  |         [Column("weight")] | ||||||
|  |         public int Weight { get; set; } | ||||||
|  |         [Column("modifiers")] | ||||||
|  |         public string? Modifiers { get; set; } | ||||||
|  |         [Column("bktnr")] | ||||||
|  |         public int BktNr { get; set; } | ||||||
|  |         [Column("sortid")] | ||||||
|  |         public string SortId { get; set; } | ||||||
|  |         [Column("discr")] | ||||||
|  |         public string Discr { get; set; } | ||||||
|  |         [Column("value")] | ||||||
|  |         public int Value { get; set; } | ||||||
|  |         [Column("price")] | ||||||
|  |         public long? Price { get; set; } | ||||||
|  |         [Column("amount")] | ||||||
|  |         public long? Amount { get; set; } | ||||||
|  |         [Column("net_amount")] | ||||||
|  |         public long? NetAmount { get; set; } | ||||||
|  |         [Column("total_amount")] | ||||||
|  |         public long? TotalAmount { get; set; } | ||||||
|  |         [Column("variety")] | ||||||
|  |         public string Variety { get; set; } | ||||||
|  |         [Column("attribute")] | ||||||
|  |         public string? Attribute { get; set; } | ||||||
|  |         [Column("quality_level")] | ||||||
|  |         public string QualityLevel { get; set; } | ||||||
|  |         [Column("oe")] | ||||||
|  |         public double Oe { get; set; } | ||||||
|  |         [Column("kmw")] | ||||||
|  |         public double Kmw { get; set; } | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -5,42 +5,42 @@ using System.Linq; | |||||||
| using System.Threading.Tasks; | using System.Threading.Tasks; | ||||||
| 
 | 
 | ||||||
| namespace Elwig.Models.Dtos { | namespace Elwig.Models.Dtos { | ||||||
|     public class DeliveryConfirmationData : DataTable<DeliveryConfirmationRow> { |     public class DeliveryConfirmationDeliveryData : DataTable<DeliveryConfirmationDeliveryRow> { | ||||||
| 
 | 
 | ||||||
|         private static readonly (string, string, string?, int)[] FieldNames = new[] { |         private static readonly (string, string, string?, int)[] FieldNames = [ | ||||||
|             ("LsNr", "LsNr.", null, 26), |             ("LsNr", "LsNr.", null, 26), | ||||||
|             ("DPNr", "Pos.", null, 8), |             ("DPNr", "Pos.", null, 8), | ||||||
|             ("Variant", "Sorte", null, 40), |             ("Variety", "Sorte", null, 40), | ||||||
|             ("Attribute", "Attribut", null, 20), |             ("Attribute", "Attribut", null, 20), | ||||||
|             ("Modifiers", "Zu-/Abschläge", null, 30), |             ("Modifiers", "Zu-/Abschläge", null, 30), | ||||||
|             ("QualityLevel", "Qualitätsstufe", null, 25), |             ("QualityLevel", "Qualitätsstufe", null, 25), | ||||||
|             ("Gradation", "Gradation", "°Oe|°KMW", 32), |             ("Gradation", "Gradation", "°Oe|°KMW", 32), | ||||||
|             ("Buckets", "Flächenbindung", "|kg", 36), |             ("Buckets", "Flächenbindung", "|kg", 36), | ||||||
|             ("Weight", "Gewicht", "kg", 16), |             ("Weight", "Gewicht", "kg", 16), | ||||||
|         }; |         ]; | ||||||
| 
 | 
 | ||||||
|         private readonly int MgNr; |         private readonly int MgNr; | ||||||
| 
 | 
 | ||||||
|         private DeliveryConfirmationData(IEnumerable<DeliveryConfirmationRow> rows, int year, Member m) : |         private DeliveryConfirmationDeliveryData(IEnumerable<DeliveryConfirmationDeliveryRow> rows, int year, Member m) : | ||||||
|             base($"Anlieferungsbestätigung", $"Anlieferungsbestätigung {year} – {m.AdministrativeName}", rows, FieldNames) { |             base($"Anlieferungsbestätigung", $"Anlieferungsbestätigung {year} – {m.AdministrativeName}", rows, FieldNames) { | ||||||
|             MgNr = m.MgNr; |             MgNr = m.MgNr; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public static DeliveryConfirmationData CreateEmpty(int year, Member m) { |         public static DeliveryConfirmationDeliveryData CreateEmpty(int year, Member m) { | ||||||
|             return new([], year, m); |             return new([], year, m); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public static async Task<IDictionary<int, DeliveryConfirmationData>> ForSeason(DbSet<DeliveryPart> table, int year) { |         public static async Task<IDictionary<int, DeliveryConfirmationDeliveryData>> ForSeason(DbSet<DeliveryPart> table, int year) { | ||||||
|             return (await FromDbSet(table, year)) |             return (await FromDbSet(table, year)) | ||||||
|                 .GroupBy( |                 .GroupBy( | ||||||
|                     p => p.Delivery.Member, |                     p => p.Delivery.Member, | ||||||
|                     p => new DeliveryConfirmationRow(p), |                     p => new DeliveryConfirmationDeliveryRow(p), | ||||||
|                     (k, g) => new DeliveryConfirmationData(g, year, k) |                     (k, g) => new DeliveryConfirmationDeliveryData(g, year, k) | ||||||
|                 ).ToDictionary(d => d.MgNr, d => d); |                 ).ToDictionary(d => d.MgNr, d => d); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         public static async Task<DeliveryConfirmationData> ForMember(DbSet<DeliveryPart> table, int year, Member m) { |         public static async Task<DeliveryConfirmationDeliveryData> ForMember(DbSet<DeliveryPart> table, int year, Member m) { | ||||||
|             return new DeliveryConfirmationData((await FromDbSet(table, year, m.MgNr)).Select(p => new DeliveryConfirmationRow(p)), year, m); |             return new DeliveryConfirmationDeliveryData((await FromDbSet(table, year, m.MgNr)).Select(p => new DeliveryConfirmationDeliveryRow(p)), year, m); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         private static async Task<IEnumerable<DeliveryPart>> FromDbSet(DbSet<DeliveryPart> table, int? year = null, int? mgnr = null) { |         private static async Task<IEnumerable<DeliveryPart>> FromDbSet(DbSet<DeliveryPart> table, int? year = null, int? mgnr = null) { | ||||||
| @@ -51,7 +51,7 @@ namespace Elwig.Models.Dtos { | |||||||
|             if (mgnr != null) q = q.Where(p => p.Delivery.MgNr == mgnr); |             if (mgnr != null) q = q.Where(p => p.Delivery.MgNr == mgnr); | ||||||
|             await q |             await q | ||||||
|                  .Include(p => p.Delivery) |                  .Include(p => p.Delivery) | ||||||
|                  .Include(p => p.Variant) |                  .Include(p => p.Variety) | ||||||
|                  .Include(p => p.Attribute) |                  .Include(p => p.Attribute) | ||||||
|                  .Include(p => p.Quality) |                  .Include(p => p.Quality) | ||||||
|                  .Include(p => p.Buckets) |                  .Include(p => p.Buckets) | ||||||
| @@ -68,10 +68,10 @@ namespace Elwig.Models.Dtos { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public class DeliveryConfirmationRow { |     public class DeliveryConfirmationDeliveryRow { | ||||||
|         public string LsNr; |         public string LsNr; | ||||||
|         public int DPNr; |         public int DPNr; | ||||||
|         public string Variant; |         public string Variety; | ||||||
|         public string? Attribute; |         public string? Attribute; | ||||||
|         public string QualityLevel; |         public string QualityLevel; | ||||||
|         public (double Oe, double Kmw) Gradation; |         public (double Oe, double Kmw) Gradation; | ||||||
| @@ -79,11 +79,11 @@ namespace Elwig.Models.Dtos { | |||||||
|         public int Weight; |         public int Weight; | ||||||
|         public (string Name, int Value)[] Buckets; |         public (string Name, int Value)[] Buckets; | ||||||
| 
 | 
 | ||||||
|         public DeliveryConfirmationRow(DeliveryPart p) { |         public DeliveryConfirmationDeliveryRow(DeliveryPart p) { | ||||||
|             var d = p.Delivery; |             var d = p.Delivery; | ||||||
|             LsNr = d.LsNr; |             LsNr = d.LsNr; | ||||||
|             DPNr = p.DPNr; |             DPNr = p.DPNr; | ||||||
|             Variant = p.Variant.Name; |             Variety = p.Variety.Name; | ||||||
|             Attribute = p.Attribute?.Name; |             Attribute = p.Attribute?.Name; | ||||||
|             QualityLevel = p.Quality.Name; |             QualityLevel = p.Quality.Name; | ||||||
|             Gradation = (p.Oe, p.Kmw); |             Gradation = (p.Oe, p.Kmw); | ||||||
| @@ -8,7 +8,7 @@ using System.Threading.Tasks; | |||||||
| namespace Elwig.Models.Dtos { | namespace Elwig.Models.Dtos { | ||||||
|     public class MemberDeliveryPerVariantData : DataTable<MemberDeliveryPerVariantRow> { |     public class MemberDeliveryPerVariantData : DataTable<MemberDeliveryPerVariantRow> { | ||||||
|  |  | ||||||
|         private static readonly (string, string, string?, int)[] FieldNames = new[] { |         private static readonly (string, string, string?, int)[] FieldNames = [ | ||||||
|             ("MgNr", "MgNr.", null, 12), |             ("MgNr", "MgNr.", null, 12), | ||||||
|             ("Name", "Name", null, 40), |             ("Name", "Name", null, 40), | ||||||
|             ("GivenName", "Vorname", null, 40), |             ("GivenName", "Vorname", null, 40), | ||||||
| @@ -20,7 +20,7 @@ namespace Elwig.Models.Dtos { | |||||||
|             ("Weights", "Geliefert", "kg", 22), |             ("Weights", "Geliefert", "kg", 22), | ||||||
|             ("Areas", "Fläche", "m²", 22), |             ("Areas", "Fläche", "m²", 22), | ||||||
|             ("Yields", "Ertrag", "kg/ha", 22), |             ("Yields", "Ertrag", "kg/ha", 22), | ||||||
|         }; |         ]; | ||||||
|  |  | ||||||
|  |  | ||||||
|         public MemberDeliveryPerVariantData(IEnumerable<MemberDeliveryPerVariantRow> rows, int year) : |         public MemberDeliveryPerVariantData(IEnumerable<MemberDeliveryPerVariantRow> rows, int year) : | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ using System.Threading.Tasks; | |||||||
| namespace Elwig.Models.Dtos { | namespace Elwig.Models.Dtos { | ||||||
|     public class OverUnderDeliveryData : DataTable<OverUnderDeliveryRow> { |     public class OverUnderDeliveryData : DataTable<OverUnderDeliveryRow> { | ||||||
|  |  | ||||||
|         private static readonly (string, string, string?, int)[] FieldNames = new[] { |         private static readonly (string, string, string?, int)[] FieldNames = [ | ||||||
|             ("MgNr", "MgNr.", null, 12), |             ("MgNr", "MgNr.", null, 12), | ||||||
|             ("Name", "Name", null, 40), |             ("Name", "Name", null, 40), | ||||||
|             ("GivenName", "Vorname", null, 40), |             ("GivenName", "Vorname", null, 40), | ||||||
| @@ -19,7 +19,7 @@ namespace Elwig.Models.Dtos { | |||||||
|             ("DeliveryRight", "Lieferrecht", "kg", 22), |             ("DeliveryRight", "Lieferrecht", "kg", 22), | ||||||
|             ("Weight", "Geliefert", "kg", 22), |             ("Weight", "Geliefert", "kg", 22), | ||||||
|             ("OverUnderDelivery", "Über-/Unterliefert", "kg|%", 34), |             ("OverUnderDelivery", "Über-/Unterliefert", "kg|%", 34), | ||||||
|         }; |         ]; | ||||||
|  |  | ||||||
|         public OverUnderDeliveryData(IEnumerable<OverUnderDeliveryRow> rows, int year) : |         public OverUnderDeliveryData(IEnumerable<OverUnderDeliveryRow> rows, int year) : | ||||||
|             base($"Über-Unterlieferungen", $"Über- und Unterlieferungen laut gezeichneten Geschäftsanteilen {year}", rows, FieldNames) { |             base($"Über-Unterlieferungen", $"Über- und Unterlieferungen laut gezeichneten Geschäftsanteilen {year}", rows, FieldNames) { | ||||||
|   | |||||||
| @@ -23,7 +23,7 @@ namespace Elwig.Models.Entities { | |||||||
|         public string SortId { get; set; } |         public string SortId { get; set; } | ||||||
|  |  | ||||||
|         [ForeignKey("SortId")] |         [ForeignKey("SortId")] | ||||||
|         public virtual WineVar Variant { get; private set; } |         public virtual WineVar Variety { get; private set; } | ||||||
|  |  | ||||||
|         [Column("attrid")] |         [Column("attrid")] | ||||||
|         public string? AttrId { get; set; } |         public string? AttrId { get; set; } | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| -- schema version 11 to 12 | -- schema version 12 to 13 | ||||||
|  |  | ||||||
| ALTER TABLE season ADD COLUMN bs_value INTEGER; | ALTER TABLE season ADD COLUMN bs_value INTEGER; | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										33
									
								
								Elwig/Resources/Sql/13-14.sql
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								Elwig/Resources/Sql/13-14.sql
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | |||||||
|  | -- schema version 13 to 14 | ||||||
|  |  | ||||||
|  | CREATE VIEW v_penalty_area_commitments AS | ||||||
|  | SELECT year, mgnr, | ||||||
|  |       SUM(COALESCE(IIF(u.weight = 0, -t.penalty_none, 0), 0) + | ||||||
|  |           COALESCE(IIF(u.diff < 0, -t.penalty_amount, 0), 0) + | ||||||
|  |           COALESCE(u.diff * t.penalty_per_kg, 0) | ||||||
|  |       ) AS total_penalty | ||||||
|  | FROM v_under_delivery u | ||||||
|  |    JOIN area_commitment_type t ON t.vtrgid = u.bucket | ||||||
|  | GROUP BY year, mgnr | ||||||
|  | HAVING total_penalty < 0 | ||||||
|  | ORDER BY year, mgnr; | ||||||
|  |  | ||||||
|  | CREATE VIEW v_penalty_business_shares AS | ||||||
|  | SELECT s.year, u.mgnr, | ||||||
|  |        (COALESCE(IIF(u.weight = 0, -s.penalty_none, 0), 0) + | ||||||
|  |         COALESCE(IIF(u.diff < 0, -s.penalty_amount, 0), 0) + | ||||||
|  |         COALESCE(u.diff * s.penalty_per_kg, 0) | ||||||
|  |        ) AS total_penalty | ||||||
|  | FROM v_total_under_delivery u | ||||||
|  |    JOIN season s ON s.year = u.year | ||||||
|  | WHERE u.diff < 0 AND total_penalty < 0 | ||||||
|  | ORDER BY s.year, u.mgnr; | ||||||
|  |  | ||||||
|  | CREATE VIEW v_auto_business_shares AS | ||||||
|  | SELECT s.year, h.mgnr, | ||||||
|  |        SUM(h.business_shares) AS business_shares, | ||||||
|  |        SUM(h.business_shares) * s.bs_value AS total_amount | ||||||
|  | FROM member_history h, season s | ||||||
|  | WHERE h.type = 'auto' AND h.date >= s.year || '-01-01' AND h.date <= s.year || '-12-31' | ||||||
|  | GROUP BY s.year, h.mgnr | ||||||
|  | ORDER BY s.year, h.mgnr; | ||||||
| @@ -535,15 +535,18 @@ | |||||||
|                         </GroupBox> |                         </GroupBox> | ||||||
|                         <GroupBox Header="Anlieferungsbestätigung" Margin="10,10,10,10" Height="250"> |                         <GroupBox Header="Anlieferungsbestätigung" Margin="10,10,10,10" Height="250"> | ||||||
|                             <Grid> |                             <Grid> | ||||||
|                                 <Grid.ColumnDefinitions> |  | ||||||
|                                     <ColumnDefinition Width="*"/> |  | ||||||
|                                 </Grid.ColumnDefinitions> |  | ||||||
|  |  | ||||||
|                                 <TextBox x:Name="TextElementDeliveryConfirmation" TextWrapping="Wrap" VerticalScrollBarVisibility="Visible" AcceptsReturn="True" |                                 <TextBox x:Name="TextElementDeliveryConfirmation" TextWrapping="Wrap" VerticalScrollBarVisibility="Visible" AcceptsReturn="True" | ||||||
|                                          HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="10,10,10,10" Height="Auto" |                                          HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="10,10,10,10" Height="Auto" | ||||||
|                                          TextChanged="TextBox_TextChanged"/> |                                          TextChanged="TextBox_TextChanged"/> | ||||||
|                             </Grid> |                             </Grid> | ||||||
|                         </GroupBox> |                         </GroupBox> | ||||||
|  |                         <GroupBox Header="Traubengutschrift" Margin="10,10,10,10" Height="250"> | ||||||
|  |                             <Grid> | ||||||
|  |                                 <TextBox x:Name="TextElementCreditNote" TextWrapping="Wrap" VerticalScrollBarVisibility="Visible" AcceptsReturn="True" | ||||||
|  |                                          HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="10,10,10,10" Height="Auto" | ||||||
|  |                                          TextChanged="TextBox_TextChanged"/> | ||||||
|  |                             </Grid> | ||||||
|  |                         </GroupBox> | ||||||
|                     </StackPanel> |                     </StackPanel> | ||||||
|                 </ScrollViewer> |                 </ScrollViewer> | ||||||
|             </TabItem> |             </TabItem> | ||||||
|   | |||||||
| @@ -12,11 +12,11 @@ namespace Elwig.Windows { | |||||||
|  |  | ||||||
|         public BaseDataWindow() { |         public BaseDataWindow() { | ||||||
|             InitializeComponent(); |             InitializeComponent(); | ||||||
|             RequiredInputs = new Control[] { |             RequiredInputs = [ | ||||||
|                 ClientNameInput, ClientNameTypeInput, ClientNameTokenInput, ClientNameShortInput, |                 ClientNameInput, ClientNameTypeInput, ClientNameTokenInput, ClientNameShortInput, | ||||||
|                 ClientAddressInput, ClientPlzInput, ClientOrtInput, |                 ClientAddressInput, ClientPlzInput, ClientOrtInput, | ||||||
|             }; |             ]; | ||||||
|             ExemptInputs = new Control[] { |             ExemptInputs = [ | ||||||
|                 ClientNameFull, |                 ClientNameFull, | ||||||
|                 BranchIdInput, BranchNameInput, BranchPlzInput, BranchOrtInput, |                 BranchIdInput, BranchNameInput, BranchPlzInput, BranchOrtInput, | ||||||
|                 BranchAddressInput, BranchPhoneNrInput, BranchFaxNrInput, BranchMobileNrInput, |                 BranchAddressInput, BranchPhoneNrInput, BranchFaxNrInput, BranchMobileNrInput, | ||||||
| @@ -30,7 +30,7 @@ namespace Elwig.Windows { | |||||||
|                 SeasonMinKgPerBsInput.TextBox, SeasonMaxKgPerBsInput.TextBox, SeasonBsValueInput.TextBox, |                 SeasonMinKgPerBsInput.TextBox, SeasonMaxKgPerBsInput.TextBox, SeasonBsValueInput.TextBox, | ||||||
|                 SeasonPenaltyPerKgInput.TextBox, SeasonPenaltyInput.TextBox, SeasonPenaltyNoneInput.TextBox, |                 SeasonPenaltyPerKgInput.TextBox, SeasonPenaltyInput.TextBox, SeasonPenaltyNoneInput.TextBox, | ||||||
|                 SeasonModifierIdInput, SeasonModifierNameInput, SeasonModifierRelInput.TextBox, SeasonModifierAbsInput.TextBox, |                 SeasonModifierIdInput, SeasonModifierNameInput, SeasonModifierRelInput.TextBox, SeasonModifierAbsInput.TextBox, | ||||||
|             }; |             ]; | ||||||
|             WineAttributeFillLowerInput.Visibility = Visibility.Hidden; |             WineAttributeFillLowerInput.Visibility = Visibility.Hidden; | ||||||
|             WineAttributeFillLowerLabel.Visibility = Visibility.Hidden; |             WineAttributeFillLowerLabel.Visibility = Visibility.Hidden; | ||||||
|         } |         } | ||||||
| @@ -297,6 +297,7 @@ namespace Elwig.Windows { | |||||||
|                 case 3: ModeDeliveryNoteFull.IsChecked = true; break; |                 case 3: ModeDeliveryNoteFull.IsChecked = true; break; | ||||||
|             } |             } | ||||||
|             TextElementDeliveryConfirmation.Text = p.TextDeliveryConfirmation; |             TextElementDeliveryConfirmation.Text = p.TextDeliveryConfirmation; | ||||||
|  |             TextElementCreditNote.Text = p.TextCreditNote; | ||||||
|  |  | ||||||
|             FinishInputFilling(); |             FinishInputFilling(); | ||||||
|         } |         } | ||||||
| @@ -322,6 +323,7 @@ namespace Elwig.Windows { | |||||||
|             p.TextDeliveryNote = TextElementDeliveryNote.Text.Length > 0 ? TextElementDeliveryNote.Text : null; |             p.TextDeliveryNote = TextElementDeliveryNote.Text.Length > 0 ? TextElementDeliveryNote.Text : null; | ||||||
|             p.ModeDeliveryNoteStats = (ModeDeliveryNoteNone.IsChecked == true) ? 0 : (ModeDeliveryNoteGaOnly.IsChecked == true) ? 1 : (ModeDeliveryNoteShort.IsChecked == true) ? 2 : (ModeDeliveryNoteFull.IsChecked == true) ? 3 : 2; |             p.ModeDeliveryNoteStats = (ModeDeliveryNoteNone.IsChecked == true) ? 0 : (ModeDeliveryNoteGaOnly.IsChecked == true) ? 1 : (ModeDeliveryNoteShort.IsChecked == true) ? 2 : (ModeDeliveryNoteFull.IsChecked == true) ? 3 : 2; | ||||||
|             p.TextDeliveryConfirmation = TextElementDeliveryConfirmation.Text.Length > 0 ? TextElementDeliveryConfirmation.Text : null; |             p.TextDeliveryConfirmation = TextElementDeliveryConfirmation.Text.Length > 0 ? TextElementDeliveryConfirmation.Text : null; | ||||||
|  |             p.TextCreditNote = TextElementCreditNote.Text.Length > 0 ? TextElementCreditNote.Text : null; | ||||||
|  |  | ||||||
|             await p.UpdateValues(); |             await p.UpdateValues(); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -61,14 +61,17 @@ | |||||||
|             </Grid.ColumnDefinitions> |             </Grid.ColumnDefinitions> | ||||||
|  |  | ||||||
|             <Label Content="Für:" Margin="10,-2,0,0" FontSize="14" Grid.Column="0" VerticalAlignment="Center"/> |             <Label Content="Für:" Margin="10,-2,0,0" FontSize="14" Grid.Column="0" VerticalAlignment="Center"/> | ||||||
|             <xctk:CheckComboBox x:Name="ContractInput" Margin="50,0,0,0" Grid.Column="0" |             <xctk:CheckComboBox x:Name="VaributeInput" Margin="50,0,0,0" Grid.Column="0" Width="500" Height="25" HorizontalAlignment="Left" | ||||||
|                                 Delimiter=", " AllItemsSelectedContent="Alle" IsEnabled="False" ItemSelectionChanged="ContractInput_Changed" |                                 IsSelectAllActive="True" SelectAllContent="Alle Sorten" Delimiter=", " AllItemsSelectedContent="Alle Sorten" | ||||||
|                                 Width="500" Height="25" HorizontalAlignment="Left"> |                                 IsEnabled="False" ItemSelectionChanged="VaributeInput_Changed"> | ||||||
|                 <xctk:CheckComboBox.ItemTemplate> |                 <xctk:CheckComboBox.ItemTemplate> | ||||||
|                     <DataTemplate> |                     <DataTemplate> | ||||||
|                         <StackPanel Orientation="Horizontal"> |                         <StackPanel Orientation="Horizontal"> | ||||||
|                             <TextBlock Text="{Binding Variety.Name}" Width="150"/> |                             <TextBlock Text="{Binding Variety.Name}" Width="150"/> | ||||||
|                             <TextBlock Text="{Binding Attribute.Name}"/> |                             <TextBlock Text="{Binding Variety.Type}" Width="30"/> | ||||||
|  |                             <TextBlock Text="{Binding Attribute.Name}" Width="120"/> | ||||||
|  |                             <TextBlock Text="{Binding AssignedGraphId}" Width="30"/> | ||||||
|  |                             <TextBlock Text="{Binding AssignedAbgewGraphId}" Width="30"/> | ||||||
|                         </StackPanel> |                         </StackPanel> | ||||||
|                     </DataTemplate> |                     </DataTemplate> | ||||||
|                 </xctk:CheckComboBox.ItemTemplate> |                 </xctk:CheckComboBox.ItemTemplate> | ||||||
| @@ -83,7 +86,7 @@ | |||||||
|                 <DataTemplate> |                 <DataTemplate> | ||||||
|                     <StackPanel Orientation="Horizontal"> |                     <StackPanel Orientation="Horizontal"> | ||||||
|                         <TextBlock Text="{Binding Id}" Width="30"/> |                         <TextBlock Text="{Binding Id}" Width="30"/> | ||||||
|                         <TextBlock Text="{Binding ContractsStringSimple}" ToolTip="{Binding ContractsString}"/> |                         <TextBlock Text="{Binding VaributeStringSimple}" ToolTip="{Binding VaributeString}"/> | ||||||
|                     </StackPanel> |                     </StackPanel> | ||||||
|                 </DataTemplate> |                 </DataTemplate> | ||||||
|             </ListBox.ItemTemplate> |             </ListBox.ItemTemplate> | ||||||
|   | |||||||
| @@ -33,14 +33,28 @@ namespace Elwig.Windows { | |||||||
|         private Marker PrimaryMarkedPointPlot; |         private Marker PrimaryMarkedPointPlot; | ||||||
|         private Marker SecondaryMarkedPointPlot; |         private Marker SecondaryMarkedPointPlot; | ||||||
|         private Text TooltipPlot; |         private Text TooltipPlot; | ||||||
|         private LegendItem UngebundenLegend; |  | ||||||
|         private LegendItem GebundenLegend; |  | ||||||
|         private LegendItem LDWLegend; |  | ||||||
|         private LegendItem QUWLegend; |  | ||||||
|         private LegendItem KABLegend; |  | ||||||
|  |  | ||||||
|         private (Graph? graph, int index) LastHighlighted = (null, -1); |         private static readonly LegendItem | ||||||
|         private (Graph? graph, int index) Highlighted = (null, -1); |             UngebundenLegend = new() { | ||||||
|  |                 Label = "Ungebunden", LineWidth = 1, LineColor = ColorUngebunden, | ||||||
|  |                 Marker = new(MarkerShape.FilledCircle, 5, ColorUngebunden) | ||||||
|  |             }, | ||||||
|  |             GebundenLegend = new() { | ||||||
|  |                 Label = "Gebunden", LineWidth = 1, LineColor = ColorGebunden, | ||||||
|  |                 Marker = new(MarkerShape.FilledCircle, 5, ColorGebunden) | ||||||
|  |             }, | ||||||
|  |             LdwLegend = new() { | ||||||
|  |                 Label = "68 °Oe (LDW)", LineWidth = 2, LineColor = Colors.Red, Marker = MarkerStyle.None | ||||||
|  |             }, | ||||||
|  |             QuwLegend = new() { | ||||||
|  |                 Label = "73 °Oe (QUW)", LineWidth = 2, LineColor = Colors.Orange, Marker = MarkerStyle.None | ||||||
|  |             }, | ||||||
|  |             KabLegend = new() { | ||||||
|  |                 Label = "84 °Oe (KAB)", LineWidth = 2, LineColor = Colors.Green, Marker = MarkerStyle.None | ||||||
|  |             }; | ||||||
|  |  | ||||||
|  |         private (Graph? Graph, int Index) LastHighlighted = (null, -1); | ||||||
|  |         private (Graph? Graph, int Index) Highlighted = (null, -1); | ||||||
|         private Graph? ActiveGraph = null; |         private Graph? ActiveGraph = null; | ||||||
|         private int PrimaryMarkedPoint = -1; |         private int PrimaryMarkedPoint = -1; | ||||||
|         private int SecondaryMarkedPoint = -1; |         private int SecondaryMarkedPoint = -1; | ||||||
| @@ -50,6 +64,9 @@ namespace Elwig.Windows { | |||||||
|  |  | ||||||
|         private List<GraphEntry> GraphEntries = []; |         private List<GraphEntry> GraphEntries = []; | ||||||
|         private GraphEntry? SelectedGraphEntry => (GraphEntry)GraphList.SelectedItem; |         private GraphEntry? SelectedGraphEntry => (GraphEntry)GraphList.SelectedItem; | ||||||
|  |         private List<Varibute> Vaributes = []; | ||||||
|  |         private bool AllVaributesAssigned => Vaributes.All(v => v.AssignedGraphId != null); | ||||||
|  |         private bool AllVaributesAssignedAbgew => Vaributes.All(v => v.AssignedAbgewGraphId != null); | ||||||
|  |  | ||||||
|         public ChartWindow(int year, int avnr) { |         public ChartWindow(int year, int avnr) { | ||||||
|             InitializeComponent(); |             InitializeComponent(); | ||||||
| @@ -84,18 +101,29 @@ namespace Elwig.Windows { | |||||||
|             PaymentVar = await Context.PaymentVariants.FindAsync(Year, AvNr) ?? throw new ArgumentException("PaymentVar not found"); |             PaymentVar = await Context.PaymentVariants.FindAsync(Year, AvNr) ?? throw new ArgumentException("PaymentVar not found"); | ||||||
|             Season = await Context.Seasons.FindAsync(Year) ?? throw new ArgumentException("Season not found"); |             Season = await Context.Seasons.FindAsync(Year) ?? throw new ArgumentException("Season not found"); | ||||||
|  |  | ||||||
|             var data = EditBillingData.FromJson(PaymentVar.Data, Utils.GetAttributeVarieties(Context, Year)); |             var data = EditBillingData.FromJson(PaymentVar.Data, Utils.GetVaributes(Context, Year)); | ||||||
|             var paymentEntries = data.GetPaymentGraphEntries(Context, Season); |             var paymentEntries = data.GetPaymentGraphEntries(Context, Season); | ||||||
|             GraphEntries = [ |             GraphEntries = [ | ||||||
|                 ..paymentEntries, |                 ..paymentEntries, | ||||||
|                 ..data.GetQualityGraphEntries(Context, Season, paymentEntries.Max(e => e.Id)) |                 ..data.GetQualityGraphEntries(Context, Season, paymentEntries.Any() ? paymentEntries.Max(e => e.Id) : 0) | ||||||
|             ]; |             ]; | ||||||
|  |             Vaributes = Utils.GetVaributeList(Context, Year); | ||||||
|  |             GraphEntries.ForEach(e => { | ||||||
|  |                 e.Vaributes.ForEach(v => { | ||||||
|  |                     var found = Vaributes.Find(a => a.Attribute?.AttrId == v.Attribute?.AttrId && a.Variety?.SortId == v.Variety?.SortId); | ||||||
|  |                     if (found == null) return; | ||||||
|  |                     if (e.Abgewertet) { | ||||||
|  |                         found.AssignedAbgewGraphId = e.Id; | ||||||
|  |                     } else { | ||||||
|  |                         found.AssignedGraphId = e.Id; | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|  |             }); | ||||||
|  |  | ||||||
|             var contracts = Utils.GetContractsForYear(Context, Year); |  | ||||||
|             FillingInputs = true; |             FillingInputs = true; | ||||||
|             ControlUtils.RenewItemsSource(ContractInput, contracts, g => (g as ContractSelection)?.Listing); |             ControlUtils.RenewItemsSource(VaributeInput, Vaributes, v => (v as Varibute)?.Listing); | ||||||
|             FillingInputs = false; |             FillingInputs = false; | ||||||
|             ControlUtils.RenewItemsSource(GraphList, GraphEntries, g => (g as GraphEntry)?.ContractsStringChange, GraphList_SelectionChanged, ControlUtils.RenewSourceDefault.First); |             ControlUtils.RenewItemsSource(GraphList, GraphEntries, g => (g as GraphEntry)?.VaributeStringChange, GraphList_SelectionChanged, ControlUtils.RenewSourceDefault.First); | ||||||
|  |  | ||||||
|             RefreshInputs(); |             RefreshInputs(); | ||||||
|         } |         } | ||||||
| @@ -108,7 +136,7 @@ namespace Elwig.Windows { | |||||||
|                 GebundenTypeFixed.IsEnabled = true; |                 GebundenTypeFixed.IsEnabled = true; | ||||||
|                 GebundenTypeGraph.IsEnabled = true; |                 GebundenTypeGraph.IsEnabled = true; | ||||||
|                 GebundenTypeNone.IsEnabled = true; |                 GebundenTypeNone.IsEnabled = true; | ||||||
|                 ContractInput.IsEnabled = true; |                 VaributeInput.IsEnabled = true; | ||||||
|                 AbgewertetInput.IsEnabled = true; |                 AbgewertetInput.IsEnabled = true; | ||||||
|                 EnableOptionButtons(); |                 EnableOptionButtons(); | ||||||
|                 FillInputs(); |                 FillInputs(); | ||||||
| @@ -127,7 +155,7 @@ namespace Elwig.Windows { | |||||||
|                 GebundenTypeFixed.IsEnabled = false; |                 GebundenTypeFixed.IsEnabled = false; | ||||||
|                 GebundenTypeGraph.IsEnabled = false; |                 GebundenTypeGraph.IsEnabled = false; | ||||||
|                 GebundenTypeNone.IsEnabled = false; |                 GebundenTypeNone.IsEnabled = false; | ||||||
|                 ContractInput.IsEnabled = false; |                 VaributeInput.IsEnabled = false; | ||||||
|                 AbgewertetInput.IsEnabled = false; |                 AbgewertetInput.IsEnabled = false; | ||||||
|             } |             } | ||||||
|             GC.Collect(); |             GC.Collect(); | ||||||
| @@ -148,7 +176,7 @@ namespace Elwig.Windows { | |||||||
|                 GebundenFlatBonus.Text = ""; |                 GebundenFlatBonus.Text = ""; | ||||||
|             } |             } | ||||||
|  |  | ||||||
|             ControlUtils.SelectCheckComboBoxItems(ContractInput, SelectedGraphEntry?.Contracts ?? [], i => (i as ContractSelection)?.Listing); |             ControlUtils.SelectCheckComboBoxItems(VaributeInput, SelectedGraphEntry?.Vaributes ?? [], i => (i as Varibute)?.Listing); | ||||||
|  |  | ||||||
|             InitPlot(); |             InitPlot(); | ||||||
|             OechslePricePlot.IsEnabled = true; |             OechslePricePlot.IsEnabled = true; | ||||||
| @@ -160,41 +188,6 @@ namespace Elwig.Windows { | |||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void InitPlot() { |         private void InitPlot() { | ||||||
|             UngebundenLegend = new LegendItem() { |  | ||||||
|                 Label = "Ungebunden", |  | ||||||
|                 LineWidth = 1, |  | ||||||
|                 LineColor = ColorUngebunden, |  | ||||||
|                 Marker = new MarkerStyle(MarkerShape.FilledCircle, 5, ColorUngebunden) |  | ||||||
|             }; |  | ||||||
|  |  | ||||||
|             GebundenLegend = new LegendItem() { |  | ||||||
|                 Label = "Gebunden", |  | ||||||
|                 LineWidth = 1, |  | ||||||
|                 LineColor = ColorGebunden, |  | ||||||
|                 Marker = new MarkerStyle(MarkerShape.FilledCircle, 5, ColorGebunden) |  | ||||||
|             }; |  | ||||||
|  |  | ||||||
|             LDWLegend = new LegendItem() { |  | ||||||
|                 Label = "68 °Oe (LDW)", |  | ||||||
|                 LineWidth = 2, |  | ||||||
|                 LineColor = Colors.Red, |  | ||||||
|                 Marker = MarkerStyle.None |  | ||||||
|             }; |  | ||||||
|  |  | ||||||
|             QUWLegend = new LegendItem() { |  | ||||||
|                 Label = "73 °Oe (QUW)", |  | ||||||
|                 LineWidth = 2, |  | ||||||
|                 LineColor = Colors.Orange, |  | ||||||
|                 Marker = MarkerStyle.None |  | ||||||
|             }; |  | ||||||
|  |  | ||||||
|             KABLegend = new LegendItem() { |  | ||||||
|                 Label = "84 °Oe (KAB)", |  | ||||||
|                 LineWidth = 2, |  | ||||||
|                 LineColor = Colors.Green, |  | ||||||
|                 Marker = MarkerStyle.None |  | ||||||
|             }; |  | ||||||
|  |  | ||||||
|             RefreshGradationLines(); |             RefreshGradationLines(); | ||||||
|  |  | ||||||
|             if (SelectedGraphEntry?.GebundenGraph != null) { |             if (SelectedGraphEntry?.GebundenGraph != null) { | ||||||
| @@ -230,7 +223,7 @@ namespace Elwig.Windows { | |||||||
|  |  | ||||||
|             //OechslePricePlot.Plot.XAxis.ManualTickSpacing(1); |             //OechslePricePlot.Plot.XAxis.ManualTickSpacing(1); | ||||||
|             //OechslePricePlot.Plot.YAxis.ManualTickSpacing(0.1); |             //OechslePricePlot.Plot.YAxis.ManualTickSpacing(0.1); | ||||||
|             OechslePricePlot.Plot.Axes.SetLimits(Math.Min(GraphEntry.MinX, GraphEntry.MinXGeb) - 1, GraphEntry.MaxX + 1, -0.1, 2); |             OechslePricePlot.Plot.Axes.SetLimits(Math.Min(GraphEntry.MinX, GraphEntry.MinXGeb) - 1, GraphEntry.MaxX + 1, -0.1, 1.5); | ||||||
|  |  | ||||||
|             //OechslePricePlot.Plot.Layout(padding: 0); |             //OechslePricePlot.Plot.Layout(padding: 0); | ||||||
|             //OechslePricePlot.Plot.XAxis2.Layout(padding: 0); |             //OechslePricePlot.Plot.XAxis2.Layout(padding: 0); | ||||||
| @@ -317,7 +310,7 @@ namespace Elwig.Windows { | |||||||
|             OechslePricePlot.Plot.Axes.Rules.Clear(); |             OechslePricePlot.Plot.Axes.Rules.Clear(); | ||||||
|             OechslePricePlot.Plot.Axes.Rules.Add(BoundaryRule); |             OechslePricePlot.Plot.Axes.Rules.Add(BoundaryRule); | ||||||
|             OechslePricePlot.Plot.Axes.Rules.Add(SpanRule); |             OechslePricePlot.Plot.Axes.Rules.Add(SpanRule); | ||||||
|             OechslePricePlot.Plot.Axes.SetLimits(GraphEntry.MinX - 1, GraphEntry.MaxX + 1, -0.1, 2); |             OechslePricePlot.Plot.Axes.SetLimits(GraphEntry.MinX - 1, GraphEntry.MaxX + 1, -0.1, 1.5); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void UnlockZoom() { |         private void UnlockZoom() { | ||||||
| @@ -372,9 +365,9 @@ namespace Elwig.Windows { | |||||||
|             OechslePricePlot.Plot.Legend.Location = Alignment.UpperLeft; |             OechslePricePlot.Plot.Legend.Location = Alignment.UpperLeft; | ||||||
|             OechslePricePlot.Plot.Legend.IsVisible = true; |             OechslePricePlot.Plot.Legend.IsVisible = true; | ||||||
|  |  | ||||||
|             OechslePricePlot.Plot.Legend.ManualItems.Add(LDWLegend); |             OechslePricePlot.Plot.Legend.ManualItems.Add(LdwLegend); | ||||||
|             OechslePricePlot.Plot.Legend.ManualItems.Add(QUWLegend); |             OechslePricePlot.Plot.Legend.ManualItems.Add(QuwLegend); | ||||||
|             OechslePricePlot.Plot.Legend.ManualItems.Add(KABLegend); |             OechslePricePlot.Plot.Legend.ManualItems.Add(KabLegend); | ||||||
|             OechslePricePlot.Plot.Legend.ManualItems.Add(UngebundenLegend); |             OechslePricePlot.Plot.Legend.ManualItems.Add(UngebundenLegend); | ||||||
|             if (SelectedGraphEntry?.GebundenGraph != null) OechslePricePlot.Plot.Legend.ManualItems.Add(GebundenLegend); |             if (SelectedGraphEntry?.GebundenGraph != null) OechslePricePlot.Plot.Legend.ManualItems.Add(GebundenLegend); | ||||||
|         } |         } | ||||||
| @@ -481,10 +474,10 @@ namespace Elwig.Windows { | |||||||
|  |  | ||||||
|             if (HoverActive) { |             if (HoverActive) { | ||||||
|                 if (PaymentVar.TestVariant && Keyboard.IsKeyDown(System.Windows.Input.Key.LeftCtrl)) { |                 if (PaymentVar.TestVariant && Keyboard.IsKeyDown(System.Windows.Input.Key.LeftCtrl)) { | ||||||
|                     if (PrimaryMarkedPoint == -1 || ActiveGraph == null || ActiveGraph != Highlighted.graph) { |                     if (PrimaryMarkedPoint == -1 || ActiveGraph == null || ActiveGraph != Highlighted.Graph) { | ||||||
|                         return; |                         return; | ||||||
|                     } |                     } | ||||||
|                     SecondaryMarkedPoint = Highlighted.index; |                     SecondaryMarkedPoint = Highlighted.Index; | ||||||
|  |  | ||||||
|                     ChangeMarker(SecondaryMarkedPointPlot, true, ActiveGraph.GetOechsleAt(SecondaryMarkedPoint), ActiveGraph.GetPriceAt(SecondaryMarkedPoint)); |                     ChangeMarker(SecondaryMarkedPointPlot, true, ActiveGraph.GetOechsleAt(SecondaryMarkedPoint), ActiveGraph.GetPriceAt(SecondaryMarkedPoint)); | ||||||
|  |  | ||||||
| @@ -493,13 +486,13 @@ namespace Elwig.Windows { | |||||||
|                     return; |                     return; | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 PrimaryMarkedPoint = Highlighted.index; |                 PrimaryMarkedPoint = Highlighted.Index; | ||||||
|                 if (ActiveGraph != Highlighted.graph) ChangeActiveGraph(Highlighted.graph); |                 if (ActiveGraph != Highlighted.Graph) ChangeActiveGraph(Highlighted.Graph); | ||||||
|  |  | ||||||
|                 ChangeMarker(PrimaryMarkedPointPlot, true, ActiveGraph.GetOechsleAt(PrimaryMarkedPoint), ActiveGraph.GetPriceAt(PrimaryMarkedPoint)); |                 ChangeMarker(PrimaryMarkedPointPlot, true, ActiveGraph.GetOechsleAt(PrimaryMarkedPoint), ActiveGraph.GetPriceAt(PrimaryMarkedPoint)); | ||||||
|  |  | ||||||
|                 OechsleInput.Text = Highlighted.graph.GetOechsleAt(Highlighted.index).ToString(); |                 OechsleInput.Text = Highlighted.Graph.GetOechsleAt(Highlighted.Index).ToString(); | ||||||
|                 PriceInput.Text = Highlighted.graph.GetPriceAt(Highlighted.index).ToString(); |                 PriceInput.Text = Highlighted.Graph.GetPriceAt(Highlighted.Index).ToString(); | ||||||
|  |  | ||||||
|                 EnableActionButtons(); |                 EnableActionButtons(); | ||||||
|             } else { |             } else { | ||||||
| @@ -622,8 +615,8 @@ namespace Elwig.Windows { | |||||||
|             if (SelectedGraphEntry == null) return; |             if (SelectedGraphEntry == null) return; | ||||||
|  |  | ||||||
|             var r = MessageBox.Show( |             var r = MessageBox.Show( | ||||||
|                 $"Soll der Graph {SelectedGraphEntry.Id} (verwendet in folgenden Verträgen: {SelectedGraphEntry.ContractsStringSimple}) wirklich gelöscht werden?", |                 $"Soll die Kurve {SelectedGraphEntry.Id} (verwendet in folgenden Verträgen: {SelectedGraphEntry.VaributeStringSimple}) wirklich gelöscht werden?", | ||||||
|                 "Graph löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No); |                 "Kurve löschen", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No); | ||||||
|  |  | ||||||
|             if (r == MessageBoxResult.Yes) { |             if (r == MessageBoxResult.Yes) { | ||||||
|                 GraphEntries.Remove(SelectedGraphEntry); |                 GraphEntries.Remove(SelectedGraphEntry); | ||||||
| @@ -635,7 +628,8 @@ namespace Elwig.Windows { | |||||||
|  |  | ||||||
|         private async void SaveButton_Click(object sender, RoutedEventArgs e) { |         private async void SaveButton_Click(object sender, RoutedEventArgs e) { | ||||||
|             var origData = BillingData.FromJson(PaymentVar.Data); |             var origData = BillingData.FromJson(PaymentVar.Data); | ||||||
|             var data = BillingData.FromGraphEntries(GraphEntries, origData, Utils.GetAttributeVarieties(Context, Year, true)); |             var data = BillingData.FromGraphEntries(GraphEntries, origData, Utils.GetVaributes(Context, Year, withSlash: true), | ||||||
|  |                 AllVaributesAssigned, AllVaributesAssignedAbgew); | ||||||
|  |  | ||||||
|             EntityEntry<PaymentVar>? tr = null; |             EntityEntry<PaymentVar>? tr = null; | ||||||
|             try { |             try { | ||||||
| @@ -715,32 +709,45 @@ namespace Elwig.Windows { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void ContractInput_Changed(object sender, ItemSelectionChangedEventArgs e) { |         private void VaributeInput_Changed(object sender, ItemSelectionChangedEventArgs e) { | ||||||
|             if (FillingInputs) return; |             if (FillingInputs || e.Item is not Varibute v) return; | ||||||
|             if (e.IsSelected == true) { |             var isOpen = VaributeInput.IsDropDownOpen; | ||||||
|                 bool success = RemoveContractFromOtherGraphEntries(e.Item.ToString()); |             if (e.IsSelected) { | ||||||
|                 if (!success) { |                 if (RemoveVaributeFromOthers(e.Item.ToString())) { | ||||||
|                     ContractInput.SelectedItems.Remove(e.Item); |                     if (AbgewertetInput.IsChecked == true) { | ||||||
|  |                         v.AssignedAbgewGraphId = SelectedGraphEntry?.Id; | ||||||
|  |                     } else { | ||||||
|  |                         v.AssignedGraphId = SelectedGraphEntry?.Id; | ||||||
|  |                     } | ||||||
|  |                 } else { | ||||||
|  |                     VaributeInput.SelectedItems.Remove(e.Item); | ||||||
|  |                 } | ||||||
|  |             } else { | ||||||
|  |                 if (AbgewertetInput.IsChecked == true) { | ||||||
|  |                     v.AssignedAbgewGraphId = null; | ||||||
|  |                 } else { | ||||||
|  |                     v.AssignedGraphId = null; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             var r = ContractInput.SelectedItems.Cast<ContractSelection>(); |             SelectedGraphEntry!.Vaributes = VaributeInput.SelectedItems.Cast<Varibute>().ToList(); | ||||||
|             SelectedGraphEntry!.Contracts = r.ToList(); |  | ||||||
|             SetHasChanged(); |             SetHasChanged(); | ||||||
|             GraphList.Items.Refresh(); |             GraphList.Items.Refresh(); | ||||||
|  |             VaributeInput.Items.Refresh(); | ||||||
|  |             VaributeInput.IsDropDownOpen = isOpen; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private bool RemoveContractFromOtherGraphEntries(string? contract) { |         private bool RemoveVaributeFromOthers(string? varibute) { | ||||||
|             if (contract == null) return true; |             if (varibute == null) return true; | ||||||
|             foreach (var ge in GraphEntries) { |             foreach (var ge in GraphEntries) { | ||||||
|                 if (ge != SelectedGraphEntry && ge.Abgewertet == SelectedGraphEntry?.Abgewertet) { |                 if (ge != SelectedGraphEntry && ge.Abgewertet == SelectedGraphEntry?.Abgewertet) { | ||||||
|                     var toRemove = ge.Contracts.Where(c => c.Listing.Equals(contract)).ToList(); |                     var toRemove = ge.Vaributes.Where(c => c.Listing.Equals(varibute)).ToList(); | ||||||
|                     if (toRemove.Count == 0) continue; |                     if (toRemove.Count == 0) continue; | ||||||
|                     var r = MessageBox.Show($"Achtung: {string.Join(", ", toRemove)} ist bereits in Graph {ge.Id} in Verwendung!\nSoll die Zuweisung dort entfernt werden?", "Entfernen bestätigen", |                     var r = MessageBox.Show($"Achtung: {string.Join(", ", toRemove)} ist bereits in Kurve {ge.Id} in Verwendung!\nSoll die Zuweisung dort entfernt werden?", "Entfernen bestätigen", | ||||||
|                         MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No); |                         MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No); | ||||||
|                     if (r != MessageBoxResult.Yes) { |                     if (r != MessageBoxResult.Yes) { | ||||||
|                         return false; |                         return false; | ||||||
|                     } |                     } | ||||||
|                     ge.Contracts.RemoveAll(c => c.Listing.Equals(contract)); |                     ge.Vaributes.RemoveAll(c => c.Listing.Equals(varibute)); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             return true; |             return true; | ||||||
|   | |||||||
| @@ -101,12 +101,12 @@ | |||||||
|                         Filtern nach:<LineBreak/> |                         Filtern nach:<LineBreak/> | ||||||
|                         <Bold>Sorte</Bold>: z.B. GV, ZW, rr, sa, !gv (ausgenommen GV), ...<LineBreak/> |                         <Bold>Sorte</Bold>: z.B. GV, ZW, rr, sa, !gv (ausgenommen GV), ...<LineBreak/> | ||||||
|                         <Bold>Rot/Weiß</Bold>: z.B. r, Rot, w, weiß, ...<LineBreak/> |                         <Bold>Rot/Weiß</Bold>: z.B. r, Rot, w, weiß, ...<LineBreak/> | ||||||
|                         <Bold>Qualitätsstufe</Bold>: z.B. QUW, kab, !ldw (ausgenommen LDW), ...<LineBreak/> |                         <Bold>Qualitätsstufe</Bold>: z.B. QUW, kab, !ldw (ausgenommen LDW), abgew[ertet], ...<LineBreak/> | ||||||
|                         <Bold>Gradation</Bold>: z.B. >73, <15, 17-18, 15-, >17,5, 62-75, ...<LineBreak/> |                         <Bold>Gradation</Bold>: z.B. >73, <15, 17-18, 15-, >17,5, 62-75, ...<LineBreak/> | ||||||
|                         <Bold>Mitglied</Bold>: z.B. 1234, 987, ...<LineBreak/> |                         <Bold>Mitglied</Bold>: z.B. 1234, 987, ...<LineBreak/> | ||||||
|                         <Bold>Saison</Bold>: z.B. 2020, >2015, 2017-2019, <2005, 2019-, ...<LineBreak/> |                         <Bold>Saison</Bold>: z.B. 2020, >2015, 2017-2019, <2005, 2019-, ...<LineBreak/> | ||||||
|                         <Bold>Zweigstelle</Bold>: z.B. musterort, ...<LineBreak/> |                         <Bold>Zweigstelle</Bold>: z.B. musterort, ...<LineBreak/> | ||||||
|                         <Bold>Attribute</Bold>: z.B. kabinett, !kabinett (alle außer kabinett), ...<LineBreak/> |                         <Bold>Attribut</Bold>: z.B. kabinett, !kabinett (alle außer kabinett), ...<LineBreak/> | ||||||
|                         <Bold>Datum</Bold>: z.B. 1.9., 15.9.-10.10., -15.10.2020, ...<LineBreak/> |                         <Bold>Datum</Bold>: z.B. 1.9., 15.9.-10.10., -15.10.2020, ...<LineBreak/> | ||||||
|                         <Bold>Uhrzeit</Bold>: z.B. 06:00-08:00, 18:00-, ...<LineBreak/> |                         <Bold>Uhrzeit</Bold>: z.B. 06:00-08:00, 18:00-, ...<LineBreak/> | ||||||
|                         <Bold>Freitext</Bold>: z.B. Lieferscheinnummern, Anmerkung, "quw" (sucht nach dem Text "quw") |                         <Bold>Freitext</Bold>: z.B. Lieferscheinnummern, Anmerkung, "quw" (sucht nach dem Text "quw") | ||||||
|   | |||||||
| @@ -365,13 +365,23 @@ namespace Elwig.Windows { | |||||||
|                         filter.RemoveAt(i--); |                         filter.RemoveAt(i--); | ||||||
|                         filterNames.Add("außer " + var[e[1..].ToUpper()].Name); |                         filterNames.Add("außer " + var[e[1..].ToUpper()].Name); | ||||||
|                     } else if (e.Length == 3 && qual.ContainsKey(e.ToUpper())) { |                     } else if (e.Length == 3 && qual.ContainsKey(e.ToUpper())) { | ||||||
|                         filterQual.Add(e.ToUpper()); |                         var qualId = e.ToUpper(); | ||||||
|  |                         filterQual.Add(qualId); | ||||||
|                         filter.RemoveAt(i--); |                         filter.RemoveAt(i--); | ||||||
|                         filterNames.Add(qual[e.ToUpper()].Name); |                         filterNames.Add(qualId == "WEI" ? "abgewertet" : qual[e.ToUpper()].Name); | ||||||
|                     } else if (e[0] == '!' && qual.ContainsKey(e[1..].ToUpper())) { |                     } else if (e[0] == '!' && qual.ContainsKey(e[1..].ToUpper())) { | ||||||
|                         filterNotQual.Add(e[1..].ToUpper()); |                         var qualId = e[1..].ToUpper(); | ||||||
|  |                         filterNotQual.Add(qualId); | ||||||
|                         filter.RemoveAt(i--); |                         filter.RemoveAt(i--); | ||||||
|                         filterNames.Add("außer " + qual[e[1..].ToUpper()].Name); |                         filterNames.Add(qualId == "WEI" ? "nicht abgewertet" : "außer " + qual[e[1..].ToUpper()].Name); | ||||||
|  |                     } else if (e.Length >= 5 && e.Length <= 10 && "abgewertet".StartsWith(e, StringComparison.CurrentCultureIgnoreCase)) { | ||||||
|  |                         filterQual.Add("WEI"); | ||||||
|  |                         filter.RemoveAt(i--); | ||||||
|  |                         filterNames.Add("abgewertet"); | ||||||
|  |                     } else if (e.Length >= 6 && e.Length <= 11 && "!abgewertet".StartsWith(e, StringComparison.CurrentCultureIgnoreCase)) { | ||||||
|  |                         filterNotQual.Add("WEI"); | ||||||
|  |                         filter.RemoveAt(i--); | ||||||
|  |                         filterNames.Add("nicht abgewertet"); | ||||||
|                     } else if (e.All(char.IsAsciiDigit) && mgnr.TryGetValue(e, out var member)) { |                     } else if (e.All(char.IsAsciiDigit) && mgnr.TryGetValue(e, out var member)) { | ||||||
|                         filterMgNr.Add(int.Parse(e)); |                         filterMgNr.Add(int.Parse(e)); | ||||||
|                         filter.RemoveAt(i--); |                         filter.RemoveAt(i--); | ||||||
|   | |||||||
| @@ -74,9 +74,9 @@ namespace Elwig.Dialogs { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             IEnumerable<Member> list = await members.ToListAsync(); |             IEnumerable<Member> list = await members.ToListAsync(); | ||||||
|             var data = await DeliveryConfirmationData.ForSeason(Context.DeliveryParts, Year); |             var data = await DeliveryConfirmationDeliveryData.ForSeason(Context.DeliveryParts, Year); | ||||||
|             using var doc = Document.Merge(list.Select(m => |             using var doc = Document.Merge(list.Select(m => | ||||||
|                 new DeliveryConfirmation(Context, Year, m, data.TryGetValue(m.MgNr, out var d) ? d : DeliveryConfirmationData.CreateEmpty(Year, m)) { |                 new DeliveryConfirmation(Context, Year, m, data.TryGetValue(m.MgNr, out var d) ? d : DeliveryConfirmationDeliveryData.CreateEmpty(Year, m)) { | ||||||
|                     //DoubleSided = true |                     //DoubleSided = true | ||||||
|                 } |                 } | ||||||
|             )); |             )); | ||||||
|   | |||||||
| @@ -27,11 +27,6 @@ namespace Elwig.Windows { | |||||||
|             w.Show(); |             w.Show(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void MemberListButton_Click(object sender, RoutedEventArgs evt) { |  | ||||||
|             var w = new MemberListWindow(); |  | ||||||
|             w.Show(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         private void ReceiptButton_Click(object sender, RoutedEventArgs evt) { |         private void ReceiptButton_Click(object sender, RoutedEventArgs evt) { | ||||||
|             App.FocusReceipt(); |             App.FocusReceipt(); | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -2,8 +2,6 @@ | |||||||
|         x:Class="Elwig.Windows.MemberAdminWindow" |         x:Class="Elwig.Windows.MemberAdminWindow" | ||||||
|         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||||||
|         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||||||
|         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |  | ||||||
|         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |  | ||||||
|         xmlns:local="clr-namespace:Elwig.Windows" |         xmlns:local="clr-namespace:Elwig.Windows" | ||||||
|         Title="Mitglieder - Elwig" Height="700" Width="1250" MinHeight="650" MinWidth="1150" |         Title="Mitglieder - Elwig" Height="700" Width="1250" MinHeight="650" MinWidth="1150" | ||||||
|         Loaded="Window_Loaded"> |         Loaded="Window_Loaded"> | ||||||
| @@ -239,14 +237,42 @@ | |||||||
|                         <ColumnDefinition Width="2*"/> |                         <ColumnDefinition Width="2*"/> | ||||||
|                     </Grid.ColumnDefinitions> |                     </Grid.ColumnDefinitions> | ||||||
|  |  | ||||||
|                     <Label Content="E-Mail-Adresse (1):" Margin="10,10,0,0" Grid.Column="0"/> |                     <Label x:Name="EmailAddress1Label" Content="E-Mail-Adresse:" Margin="10,10,0,0" Grid.Column="0"/> | ||||||
|                     <TextBox x:Name="EmailAddress1Input" Margin="0,10,10,0" Grid.Column="1" Grid.ColumnSpan="2" |                     <TextBox x:Name="EmailAddress1Input" Margin="0,10,10,0" Grid.Column="1" Grid.ColumnSpan="2" | ||||||
|                              TextChanged="EmailAddressInput_TextChanged" LostFocus="EmailAddressInput_LostFocus"/> |                              TextChanged="EmailAddressInput_TextChanged" LostFocus="EmailAddressInput_LostFocus"/> | ||||||
|  |  | ||||||
|                     <Label Content="E-Mail-Adresse (2):" Margin="10,40,0,0" Grid.Column="0"/> |                     <Label x:Name="EmailAddress2Label" Content="E-Mail-Adresse:" Margin="10,40,0,0" Grid.Column="0"/> | ||||||
|                     <TextBox x:Name="EmailAddress2Input" Margin="0,40,10,0" Grid.Column="1" Grid.ColumnSpan="2" |                     <TextBox x:Name="EmailAddress2Input" Margin="0,40,10,0" Grid.Column="1" Grid.ColumnSpan="2" | ||||||
|                              TextChanged="EmailAddressInput_TextChanged" LostFocus="EmailAddressInput_LostFocus"/> |                              TextChanged="EmailAddressInput_TextChanged" LostFocus="EmailAddressInput_LostFocus"/> | ||||||
|  |  | ||||||
|  |                     <Label x:Name="EmailAddress3Label" Content="E-Mail-Adresse:" Margin="10,70,0,0" Grid.Column="0"/> | ||||||
|  |                     <TextBox x:Name="EmailAddress3Input" Margin="0,70,10,0" Grid.Column="1" Grid.ColumnSpan="2" | ||||||
|  |                              TextChanged="EmailAddressInput_TextChanged" LostFocus="EmailAddressInput_LostFocus"/> | ||||||
|  |  | ||||||
|  |                     <Label x:Name="EmailAddress4Label" Content="E-Mail-Adresse:" Margin="10,100,0,0" Grid.Column="0"/> | ||||||
|  |                     <TextBox x:Name="EmailAddress4Input" Margin="0,100,10,0" Grid.Column="1" Grid.ColumnSpan="2" | ||||||
|  |                              TextChanged="EmailAddressInput_TextChanged" LostFocus="EmailAddressInput_LostFocus"/> | ||||||
|  |  | ||||||
|  |                     <Label x:Name="EmailAddress5Label" Content="E-Mail-Adresse:" Margin="10,130,0,0" Grid.Column="0"/> | ||||||
|  |                     <TextBox x:Name="EmailAddress5Input" Margin="0,130,10,0" Grid.Column="1" Grid.ColumnSpan="2" | ||||||
|  |                              TextChanged="EmailAddressInput_TextChanged" LostFocus="EmailAddressInput_LostFocus"/> | ||||||
|  |  | ||||||
|  |                     <Label x:Name="EmailAddress6Label" Content="E-Mail-Adresse:" Margin="10,160,0,0" Grid.Column="0"/> | ||||||
|  |                     <TextBox x:Name="EmailAddress6Input" Margin="0,160,10,0" Grid.Column="1" Grid.ColumnSpan="2" | ||||||
|  |                              TextChanged="EmailAddressInput_TextChanged" LostFocus="EmailAddressInput_LostFocus"/> | ||||||
|  |  | ||||||
|  |                     <Label x:Name="EmailAddress7Label" Content="E-Mail-Adresse:" Margin="10,190,0,0" Grid.Column="0"/> | ||||||
|  |                     <TextBox x:Name="EmailAddress7Input" Margin="0,190,10,0" Grid.Column="1" Grid.ColumnSpan="2" | ||||||
|  |                              TextChanged="EmailAddressInput_TextChanged" LostFocus="EmailAddressInput_LostFocus"/> | ||||||
|  |  | ||||||
|  |                     <Label x:Name="EmailAddress8Label" Content="E-Mail-Adresse:" Margin="10,210,0,0" Grid.Column="0"/> | ||||||
|  |                     <TextBox x:Name="EmailAddress8Input" Margin="0,210,10,0" Grid.Column="1" Grid.ColumnSpan="2" | ||||||
|  |                              TextChanged="EmailAddressInput_TextChanged" LostFocus="EmailAddressInput_LostFocus"/> | ||||||
|  |  | ||||||
|  |                     <Label x:Name="EmailAddress9Label" Content="E-Mail-Adresse:" Margin="10,250,0,0" Grid.Column="0"/> | ||||||
|  |                     <TextBox x:Name="EmailAddress9Input" Margin="0,250,10,0" Grid.Column="1" Grid.ColumnSpan="2" | ||||||
|  |                              TextChanged="EmailAddressInput_TextChanged" LostFocus="EmailAddressInput_LostFocus"/> | ||||||
|  |  | ||||||
|                     <ComboBox x:Name="PhoneNr1TypeInput" DisplayMemberPath="Value" Margin="6,70,5,0" FontSize="12" Padding="6,4,4,4"/> |                     <ComboBox x:Name="PhoneNr1TypeInput" DisplayMemberPath="Value" Margin="6,70,5,0" FontSize="12" Padding="6,4,4,4"/> | ||||||
|                     <TextBox x:Name="PhoneNr1Input" Margin="0,70,5,0" Grid.Column="1" |                     <TextBox x:Name="PhoneNr1Input" Margin="0,70,5,0" Grid.Column="1" | ||||||
|                              TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> |                              TextChanged="PhoneNrInput_TextChanged" LostFocus="PhoneNrInput_LostFocus"/> | ||||||
|   | |||||||
| @@ -17,7 +17,8 @@ namespace Elwig.Windows { | |||||||
|     public partial class MemberAdminWindow : AdministrationWindow { |     public partial class MemberAdminWindow : AdministrationWindow { | ||||||
|  |  | ||||||
|         private List<string> TextFilter = []; |         private List<string> TextFilter = []; | ||||||
|         private readonly (ComboBox, TextBox, TextBox)[] PhoneNrInputs; |         private readonly (ComboBox Type, TextBox Number, TextBox Comment)[] PhoneNrInputs; | ||||||
|  |         private readonly (Label Label, TextBox Address)[] EmailAddressInputs; | ||||||
|  |  | ||||||
|         private readonly RoutedCommand CtrlF = new("CtrlF", typeof(MemberAdminWindow), [new KeyGesture(Key.F, ModifierKeys.Control)]); |         private readonly RoutedCommand CtrlF = new("CtrlF", typeof(MemberAdminWindow), [new KeyGesture(Key.F, ModifierKeys.Control)]); | ||||||
|         private readonly RoutedCommand CtrlP = new("CtrlP", typeof(MemberAdminWindow), [new KeyGesture(Key.P, ModifierKeys.Control)]); |         private readonly RoutedCommand CtrlP = new("CtrlP", typeof(MemberAdminWindow), [new KeyGesture(Key.P, ModifierKeys.Control)]); | ||||||
| @@ -38,6 +39,17 @@ namespace Elwig.Windows { | |||||||
|                 AddressInput, PlzInput, OrtInput, BillingOrtInput, |                 AddressInput, PlzInput, OrtInput, BillingOrtInput, | ||||||
|                 BusinessSharesInput, BranchInput, DefaultKgInput |                 BusinessSharesInput, BranchInput, DefaultKgInput | ||||||
|             ]; |             ]; | ||||||
|  |             EmailAddressInputs = [ | ||||||
|  |                 (EmailAddress1Label, EmailAddress1Input), | ||||||
|  |                 (EmailAddress2Label, EmailAddress2Input), | ||||||
|  |                 (EmailAddress3Label, EmailAddress3Input), | ||||||
|  |                 (EmailAddress4Label, EmailAddress4Input), | ||||||
|  |                 (EmailAddress5Label, EmailAddress5Input), | ||||||
|  |                 (EmailAddress6Label, EmailAddress6Input), | ||||||
|  |                 (EmailAddress7Label, EmailAddress7Input), | ||||||
|  |                 (EmailAddress8Label, EmailAddress8Input), | ||||||
|  |                 (EmailAddress9Label, EmailAddress9Input), | ||||||
|  |             ]; | ||||||
|             PhoneNrInputs = [ |             PhoneNrInputs = [ | ||||||
|                 (PhoneNr1TypeInput, PhoneNr1Input, PhoneNr1CommentInput), |                 (PhoneNr1TypeInput, PhoneNr1Input, PhoneNr1CommentInput), | ||||||
|                 (PhoneNr2TypeInput, PhoneNr2Input, PhoneNr2CommentInput), |                 (PhoneNr2TypeInput, PhoneNr2Input, PhoneNr2CommentInput), | ||||||
| @@ -63,7 +75,7 @@ namespace Elwig.Windows { | |||||||
|             Menu_Print_MemberDataSheet.IsEnabled = App.IsPrintingReady; |             Menu_Print_MemberDataSheet.IsEnabled = App.IsPrintingReady; | ||||||
|  |  | ||||||
|             ActiveMemberInput.IsChecked = true; |             ActiveMemberInput.IsChecked = true; | ||||||
|             UpdatePhoneNrInputVisibility(); |             UpdateContactInfoVisibility(); | ||||||
|             LockInputs(); |             LockInputs(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -236,27 +248,55 @@ namespace Elwig.Windows { | |||||||
|  |  | ||||||
|         private void SetPhoneNrInput(int nr, string? type, string? number, string? comment) { |         private void SetPhoneNrInput(int nr, string? type, string? number, string? comment) { | ||||||
|             var inputs = PhoneNrInputs[nr]; |             var inputs = PhoneNrInputs[nr]; | ||||||
|             inputs.Item1.SelectedItem = (type == null) ? null : inputs.Item1.ItemsSource.Cast<KeyValuePair<string, string>>().FirstOrDefault(p => p.Key == type); |             inputs.Type.SelectedItem = (type == null) ? null : inputs.Type.ItemsSource.Cast<KeyValuePair<string, string>>().FirstOrDefault(p => p.Key == type); | ||||||
|             inputs.Item2.Text = number; |             inputs.Number.Text = number; | ||||||
|             inputs.Item3.Text = comment; |             inputs.Comment.Text = comment; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private void SetEmailAddressInput(int nr, string? address) { | ||||||
|  |             var inputs = EmailAddressInputs[nr]; | ||||||
|  |             inputs.Address.Text = address; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private (string, string, string?)? GetPhoneNrInput(int nr) { |         private (string, string, string?)? GetPhoneNrInput(int nr) { | ||||||
|             var inputs = PhoneNrInputs[nr]; |             var inputs = PhoneNrInputs[nr]; | ||||||
|             var number = inputs.Item2.Text; |             var number = inputs.Number.Text; | ||||||
|             if (string.IsNullOrEmpty(number)) |             if (string.IsNullOrEmpty(number)) | ||||||
|                 return null; |                 return null; | ||||||
|             var type = (inputs.Item1.SelectedItem as KeyValuePair<string, string>?)?.Key ?? (number.StartsWith("+43 ") && number[4] == '6' ? "mobile" : "landline"); |             var type = (inputs.Type.SelectedItem as KeyValuePair<string, string>?)?.Key ?? (number.StartsWith("+43 ") && number[4] == '6' ? "mobile" : "landline"); | ||||||
|             var comment = inputs.Item3.Text; |             var comment = inputs.Comment.Text; | ||||||
|             return (type, number, comment == "" ? null : comment); |             return (type, number, comment == "" ? null : comment); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void SetPhoneNrInputVisible(int nr, bool visible) { |         private string? GetEmailAddressInput(int nr) { | ||||||
|  |             var inputs = EmailAddressInputs[nr]; | ||||||
|  |             return inputs.Address.Text == "" ? null : inputs.Address.Text; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private void SetPhoneNrInputVisible(int nr, bool visible, int? position = null) { | ||||||
|             var inputs = PhoneNrInputs[nr]; |             var inputs = PhoneNrInputs[nr]; | ||||||
|  |             if (position is int p) { | ||||||
|  |                 var mt = 10 + p * 30; | ||||||
|  |                 inputs.Type.Margin = new(6, mt, 5, 0); | ||||||
|  |                 inputs.Number.Margin = new(0, mt, 5, 0); | ||||||
|  |                 inputs.Comment.Margin = new(0, mt, 10, 0); | ||||||
|  |             } | ||||||
|             var vis = visible ? Visibility.Visible : Visibility.Hidden; |             var vis = visible ? Visibility.Visible : Visibility.Hidden; | ||||||
|             inputs.Item1.Visibility = vis; |             inputs.Type.Visibility = vis; | ||||||
|             inputs.Item2.Visibility = vis; |             inputs.Number.Visibility = vis; | ||||||
|             inputs.Item3.Visibility = vis; |             inputs.Comment.Visibility = vis; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private void SetEmailAddressInputVisible(int nr, bool visible, int? position = null) { | ||||||
|  |             var inputs = EmailAddressInputs[nr]; | ||||||
|  |             if (position is int p) { | ||||||
|  |                 var mt = 10 + p * 30; | ||||||
|  |                 inputs.Label.Margin = new(10, mt, 0, 0); | ||||||
|  |                 inputs.Address.Margin = new(0, mt, 10, 0); | ||||||
|  |             } | ||||||
|  |             var vis = visible ? Visibility.Visible : Visibility.Hidden; | ||||||
|  |             inputs.Label.Visibility = vis; | ||||||
|  |             inputs.Address.Visibility = vis; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void MemberList_SelectionChanged(object sender, RoutedEventArgs evt) { |         private void MemberList_SelectionChanged(object sender, RoutedEventArgs evt) { | ||||||
| @@ -274,7 +314,7 @@ namespace Elwig.Windows { | |||||||
|             HideNewEditDeleteButtons(); |             HideNewEditDeleteButtons(); | ||||||
|             ShowSaveResetCancelButtons(); |             ShowSaveResetCancelButtons(); | ||||||
|             UnlockInputs(); |             UnlockInputs(); | ||||||
|             UpdatePhoneNrInputVisibility(true); |             UpdateContactInfoVisibility(true); | ||||||
|             InitInputs(); |             InitInputs(); | ||||||
|             LockSearchInputs(); |             LockSearchInputs(); | ||||||
|         } |         } | ||||||
| @@ -289,7 +329,7 @@ namespace Elwig.Windows { | |||||||
|             HideNewEditDeleteButtons(); |             HideNewEditDeleteButtons(); | ||||||
|             ShowSaveResetCancelButtons(); |             ShowSaveResetCancelButtons(); | ||||||
|             UnlockInputs(); |             UnlockInputs(); | ||||||
|             UpdatePhoneNrInputVisibility(true); |             UpdateContactInfoVisibility(true); | ||||||
|             LockSearchInputs(); |             LockSearchInputs(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -315,7 +355,7 @@ namespace Elwig.Windows { | |||||||
|             HideSaveResetCancelButtons(); |             HideSaveResetCancelButtons(); | ||||||
|             ShowNewEditDeleteButtons(); |             ShowNewEditDeleteButtons(); | ||||||
|             LockInputs(); |             LockInputs(); | ||||||
|             UpdatePhoneNrInputVisibility(); |             UpdateContactInfoVisibility(); | ||||||
|             UnlockSearchInputs(); |             UnlockSearchInputs(); | ||||||
|             FinishInputFilling(); |             FinishInputFilling(); | ||||||
|             await RefreshMemberList(); |             await RefreshMemberList(); | ||||||
| @@ -342,7 +382,7 @@ namespace Elwig.Windows { | |||||||
|             ShowNewEditDeleteButtons(); |             ShowNewEditDeleteButtons(); | ||||||
|             RefreshInputs(); |             RefreshInputs(); | ||||||
|             LockInputs(); |             LockInputs(); | ||||||
|             UpdatePhoneNrInputVisibility(); |             UpdateContactInfoVisibility(); | ||||||
|             UnlockSearchInputs(); |             UnlockSearchInputs(); | ||||||
|         } |         } | ||||||
|  |  | ||||||
| @@ -504,13 +544,24 @@ namespace Elwig.Windows { | |||||||
|             ActiveMemberInput.IsEnabled = true; |             ActiveMemberInput.IsEnabled = true; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void UpdatePhoneNrInputVisibility(bool extra = false) { |         private void UpdateContactInfoVisibility(bool extra = false) { | ||||||
|             bool lastVisible = true; |             var m = MemberList.SelectedItem as Member; | ||||||
|             var m = (Member)MemberList.SelectedItem; |             bool lastVisible; | ||||||
|  |             int num = 0; | ||||||
|  |             lastVisible = true; | ||||||
|  |             for (int i = 0; i < EmailAddressInputs.Length; i++) { | ||||||
|  |                 var input = EmailAddressInputs[i]; | ||||||
|  |                 var vis = !string.IsNullOrEmpty(input.Address.Text) || (m?.EmailAddresses.Any(a => a.Nr - 1 == i) ?? false); | ||||||
|  |                 var cVis = vis || (extra && lastVisible); | ||||||
|  |                 SetEmailAddressInputVisible(i, cVis, cVis ? num++ : null); | ||||||
|  |                 lastVisible = vis; | ||||||
|  |             } | ||||||
|  |             lastVisible = true; | ||||||
|             for (int i = 0; i < PhoneNrInputs.Length; i++) { |             for (int i = 0; i < PhoneNrInputs.Length; i++) { | ||||||
|                 var input = PhoneNrInputs[i]; |                 var input = PhoneNrInputs[i]; | ||||||
|                 var vis = !string.IsNullOrEmpty(input.Item2.Text) || (m?.TelephoneNumbers.Any(p => p.Nr - 1 == i) ?? false); |                 var vis = !string.IsNullOrEmpty(input.Number.Text) || (m?.TelephoneNumbers.Any(n => n.Nr - 1 == i) ?? false); | ||||||
|                 SetPhoneNrInputVisible(i, vis || (extra && lastVisible)); |                 var cVis = vis || (extra && lastVisible); | ||||||
|  |                 SetPhoneNrInputVisible(i, cVis, cVis ? num++ : null); | ||||||
|                 lastVisible = vis; |                 lastVisible = vis; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @@ -605,17 +656,17 @@ namespace Elwig.Windows { | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|                 for (int i = 0; i < 2; i++) { |                 for (int i = 0; i < EmailAddressInputs.Length; i++) { | ||||||
|                     var input = i == 0 ? EmailAddress1Input : EmailAddress2Input; |                     var input = GetEmailAddressInput(i); | ||||||
|                     var emailAddr = m.EmailAddresses.FirstOrDefault(a => a.Nr - 1 == i); |                     var emailAddr = m.EmailAddresses.FirstOrDefault(a => a.Nr - 1 == i); | ||||||
|                     if (input.Text == "") { |                     if (input == null || input == "") { | ||||||
|                         if (emailAddr != null) { |                         if (emailAddr != null) { | ||||||
|                             Context.Remove(emailAddr); |                             Context.Remove(emailAddr); | ||||||
|                         } |                         } | ||||||
|                     } else { |                     } else { | ||||||
|                         MemberEmailAddr a = emailAddr ?? Context.CreateProxy<MemberEmailAddr>(); |                         MemberEmailAddr a = emailAddr ?? Context.CreateProxy<MemberEmailAddr>(); | ||||||
|                         a.Nr = i + 1; |                         a.Nr = i + 1; | ||||||
|                         a.Address = input.Text; |                         a.Address = input ?? ""; | ||||||
|                         a.Comment = null; |                         a.Comment = null; | ||||||
|                         if (emailAddr == null) { |                         if (emailAddr == null) { | ||||||
|                             a.MgNr = newMgNr; |                             a.MgNr = newMgNr; | ||||||
| @@ -678,8 +729,14 @@ namespace Elwig.Windows { | |||||||
|             } |             } | ||||||
|  |  | ||||||
|             var emailAddrs = m.EmailAddresses.OrderBy(a => a.Nr).ToList(); |             var emailAddrs = m.EmailAddresses.OrderBy(a => a.Nr).ToList(); | ||||||
|             EmailAddress1Input.Text = emailAddrs.Count > 0 ? emailAddrs[0].Address : ""; |             for (int i = 0; i< EmailAddressInputs.Length; i++) { | ||||||
|             EmailAddress2Input.Text = emailAddrs.Count > 1 ? emailAddrs[1].Address : ""; |                 if (i < emailAddrs.Count) { | ||||||
|  |                     var emailAddr = emailAddrs[i]; | ||||||
|  |                     SetEmailAddressInput(i, emailAddr.Address); | ||||||
|  |                 } else { | ||||||
|  |                     SetEmailAddressInput(i, null); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |  | ||||||
|             var phoneNrs = m.TelephoneNumbers.OrderBy(p => p.Nr).ToList(); |             var phoneNrs = m.TelephoneNumbers.OrderBy(p => p.Nr).ToList(); | ||||||
|             for (int i = 0; i < PhoneNrInputs.Length; i++) { |             for (int i = 0; i < PhoneNrInputs.Length; i++) { | ||||||
| @@ -690,7 +747,7 @@ namespace Elwig.Windows { | |||||||
|                     SetPhoneNrInput(i, null, null, null); |                     SetPhoneNrInput(i, null, null, null); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             UpdatePhoneNrInputVisibility(IsEditing || IsCreating); |             UpdateContactInfoVisibility(IsEditing || IsCreating); | ||||||
|  |  | ||||||
|             IbanInput.Text = m.Iban; |             IbanInput.Text = m.Iban; | ||||||
|             BicInput.Text = m.Bic; |             BicInput.Text = m.Bic; | ||||||
| @@ -786,9 +843,14 @@ namespace Elwig.Windows { | |||||||
|             InputLostFocus((TextBox)sender, Validator.CheckPredecessorMgNr); |             InputLostFocus((TextBox)sender, Validator.CheckPredecessorMgNr); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         private new void EmailAddressInput_TextChanged(object sender, TextChangedEventArgs evt) { | ||||||
|  |             base.EmailAddressInput_TextChanged(sender, evt); | ||||||
|  |             UpdateContactInfoVisibility(IsEditing || IsCreating); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         private new void PhoneNrInput_TextChanged(object sender, TextChangedEventArgs evt) { |         private new void PhoneNrInput_TextChanged(object sender, TextChangedEventArgs evt) { | ||||||
|             base.PhoneNrInput_TextChanged(sender, evt); |             base.PhoneNrInput_TextChanged(sender, evt); | ||||||
|             UpdatePhoneNrInputVisibility(IsEditing || IsCreating); |             UpdateContactInfoVisibility(IsEditing || IsCreating); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private void KgDetailsButton_Click(object sender, RoutedEventArgs evt) { |         private void KgDetailsButton_Click(object sender, RoutedEventArgs evt) { | ||||||
|   | |||||||
| @@ -1,22 +0,0 @@ | |||||||
| <Window x:Class="Elwig.Windows.MemberListWindow" |  | ||||||
|         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |  | ||||||
|         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |  | ||||||
|         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" |  | ||||||
|         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |  | ||||||
|         xmlns:local="clr-namespace:Elwig.Windows" |  | ||||||
|         mc:Ignorable="d" |  | ||||||
|         Title="Mitgliederliste - Elwig" Height="450" Width="800"> |  | ||||||
|     <Grid> |  | ||||||
|         <DataGrid x:Name="MemberList" AutoGenerateColumns="False" HeadersVisibility="Column" IsReadOnly="True" GridLinesVisibility="None" SelectionMode="Single" |  | ||||||
|                   CanUserDeleteRows="False" CanUserResizeRows="False" CanUserAddRows="False" FontSize="14"> |  | ||||||
|             <DataGrid.Columns> |  | ||||||
|                 <DataGridTextColumn Header="MgNr."          Binding="{Binding MgNr}"        Width="70"/> |  | ||||||
|                 <DataGridTextColumn Header="Präfix"         Binding="{Binding Prefix}"      Width="100"/> |  | ||||||
|                 <DataGridTextColumn Header="Vorname"        Binding="{Binding GivenName}"   Width="100"/> |  | ||||||
|                 <DataGridTextColumn Header="Weitere Namen"  Binding="{Binding MiddleName}"  Width="100"/> |  | ||||||
|                 <DataGridTextColumn Header="Nachname"       Binding="{Binding FamilyName}"  Width="100"/> |  | ||||||
|                 <DataGridTextColumn Header="Suffix"         Binding="{Binding Suffix}"      Width="100"/> |  | ||||||
|             </DataGrid.Columns> |  | ||||||
|         </DataGrid> |  | ||||||
|     </Grid> |  | ||||||
| </Window> |  | ||||||
| @@ -1,27 +0,0 @@ | |||||||
| using Elwig.Helpers; |  | ||||||
| using System; |  | ||||||
| using System.Collections.Generic; |  | ||||||
| using System.Linq; |  | ||||||
| using System.Text; |  | ||||||
| using System.Threading.Tasks; |  | ||||||
| using System.Windows; |  | ||||||
| using System.Windows.Controls; |  | ||||||
| using System.Windows.Data; |  | ||||||
| using System.Windows.Documents; |  | ||||||
| using System.Windows.Input; |  | ||||||
| using System.Windows.Media; |  | ||||||
| using System.Windows.Media.Imaging; |  | ||||||
| using System.Windows.Shapes; |  | ||||||
|  |  | ||||||
| namespace Elwig.Windows { |  | ||||||
|     public partial class MemberListWindow : Window { |  | ||||||
|         private readonly AppDbContext Context = new(); |  | ||||||
|  |  | ||||||
|         public MemberListWindow() { |  | ||||||
|             InitializeComponent(); |  | ||||||
|             MemberList.ItemsSource = Context.Members.ToList(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| @@ -6,7 +6,7 @@ | |||||||
|         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" |         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||||||
|         xmlns:local="clr-namespace:Elwig.Windows" |         xmlns:local="clr-namespace:Elwig.Windows" | ||||||
|         mc:Ignorable="d" |         mc:Ignorable="d" | ||||||
|         Title="Auszahlungsvarianten - Elwig" Height="500" Width="820" MinHeight="500" MinWidth="820"> |         Title="Auszahlungsvarianten - Elwig" Height="510" Width="820" MinHeight="500" MinWidth="820"> | ||||||
|     <Window.Resources> |     <Window.Resources> | ||||||
|         <Style TargetType="Label"> |         <Style TargetType="Label"> | ||||||
|             <Setter Property="HorizontalAlignment" Value="Left"/> |             <Setter Property="HorizontalAlignment" Value="Left"/> | ||||||
| @@ -42,7 +42,7 @@ | |||||||
|         </Grid.ColumnDefinitions> |         </Grid.ColumnDefinitions> | ||||||
|         <Grid.RowDefinitions> |         <Grid.RowDefinitions> | ||||||
|             <RowDefinition Height="*"/> |             <RowDefinition Height="*"/> | ||||||
|             <RowDefinition Height="200"/> |             <RowDefinition Height="220"/> | ||||||
|         </Grid.RowDefinitions> |         </Grid.RowDefinitions> | ||||||
|  |  | ||||||
|         <ListBox x:Name="PaymentVariantList" Margin="10,10,35,10" Grid.RowSpan="2" SelectionChanged="PaymentVariantList_SelectionChanged"> |         <ListBox x:Name="PaymentVariantList" Margin="10,10,35,10" Grid.RowSpan="2" SelectionChanged="PaymentVariantList_SelectionChanged"> | ||||||
| @@ -163,6 +163,9 @@ | |||||||
|                     <Button x:Name="ExportButton" Content="Exportieren" FontSize="14" Width="180" Margin="10,10,10,10" Height="27" IsEnabled="False" |                     <Button x:Name="ExportButton" Content="Exportieren" FontSize="14" Width="180" Margin="10,10,10,10" Height="27" IsEnabled="False" | ||||||
|                             Click="ExportButton_Click" |                             Click="ExportButton_Click" | ||||||
|                             VerticalAlignment="Top" HorizontalAlignment="Left"/> |                             VerticalAlignment="Top" HorizontalAlignment="Left"/> | ||||||
|  |                     <Button x:Name="TransactionButton" Content="Buchungsliste" FontSize="14" Width="180" Margin="10,42,10,10" Height="27" IsEnabled="False" | ||||||
|  |                             Click="TransactionButton_Click" | ||||||
|  |                             VerticalAlignment="Top" HorizontalAlignment="Left"/> | ||||||
|  |  | ||||||
|                     <ProgressBar x:Name="ProgressBar" Margin="10,10,10,74" Height="27" Width="180" |                     <ProgressBar x:Name="ProgressBar" Margin="10,10,10,74" Height="27" Width="180" | ||||||
|                                  VerticalAlignment="Bottom" HorizontalAlignment="Left"/> |                                  VerticalAlignment="Bottom" HorizontalAlignment="Left"/> | ||||||
|   | |||||||
| @@ -57,6 +57,7 @@ namespace Elwig.Windows { | |||||||
|                 ShowButton.IsEnabled = true; |                 ShowButton.IsEnabled = true; | ||||||
|                 PrintButton.IsEnabled = true; |                 PrintButton.IsEnabled = true; | ||||||
|                 ExportButton.IsEnabled = locked; |                 ExportButton.IsEnabled = locked; | ||||||
|  |                 TransactionButton.IsEnabled = locked; | ||||||
|  |  | ||||||
|                 NameInput.Text = v.Name; |                 NameInput.Text = v.Name; | ||||||
|                 NameInput.IsReadOnly = false; |                 NameInput.IsReadOnly = false; | ||||||
| @@ -101,6 +102,7 @@ namespace Elwig.Windows { | |||||||
|                 ShowButton.IsEnabled = false; |                 ShowButton.IsEnabled = false; | ||||||
|                 PrintButton.IsEnabled = false; |                 PrintButton.IsEnabled = false; | ||||||
|                 ExportButton.IsEnabled = false; |                 ExportButton.IsEnabled = false; | ||||||
|  |                 TransactionButton.IsEnabled = false; | ||||||
|  |  | ||||||
|                 BillingData = null; |                 BillingData = null; | ||||||
|                 NameInput.Text = ""; |                 NameInput.Text = ""; | ||||||
| @@ -173,7 +175,7 @@ namespace Elwig.Windows { | |||||||
|                 v.Name = "Neue Auszahlungsvariante"; |                 v.Name = "Neue Auszahlungsvariante"; | ||||||
|                 v.TestVariant = true; |                 v.TestVariant = true; | ||||||
|                 v.DateString = $"{DateTime.Today:yyyy-MM-dd}"; |                 v.DateString = $"{DateTime.Today:yyyy-MM-dd}"; | ||||||
|                 v.Data = "{\"mode\": \"elwig\", \"version\": 1, \"payment\": 1.0, \"quality\": {\"WEI\": 0}, \"curves\": []}"; |                 v.Data = "{\"mode\": \"elwig\", \"version\": 1, \"payment\": {}, \"curves\": []}"; | ||||||
|  |  | ||||||
|                 await Context.AddAsync(v); |                 await Context.AddAsync(v); | ||||||
|                 await Context.SaveChangesAsync(); |                 await Context.SaveChangesAsync(); | ||||||
| @@ -311,6 +313,31 @@ namespace Elwig.Windows { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         private async void TransactionButton_Click(object sender, RoutedEventArgs evt) { | ||||||
|  |             if (PaymentVariantList.SelectedValue is not PaymentVar v) { | ||||||
|  |                 return; | ||||||
|  |             } | ||||||
|  |             var d = new SaveFileDialog() { | ||||||
|  |                 FileName = $"{App.Client.NameToken}-Buchungsliste-{v.Year}-{v.Name.Trim().Replace(' ', '-')}.ods", | ||||||
|  |                 DefaultExt = "ods", | ||||||
|  |                 Filter = "OpenDocument Format Spreadsheet (*.ods)|*.ods", | ||||||
|  |                 Title = $"Buchungsliste speichern unter - Elwig" | ||||||
|  |             }; | ||||||
|  |             if (d.ShowDialog() == true) { | ||||||
|  |                 TransactionButton.IsEnabled = false; | ||||||
|  |                 Mouse.OverrideCursor = Cursors.AppStarting; | ||||||
|  |                 try { | ||||||
|  |                     var tbl = await CreditNoteData.ForPaymentVariant(Context, v.Year, v.AvNr); | ||||||
|  |                     using var ods = new OdsFile(d.FileName); | ||||||
|  |                     await ods.AddTable(tbl); | ||||||
|  |                 } catch (Exception exc) { | ||||||
|  |                     MessageBox.Show(exc.Message, "Fehler", MessageBoxButton.OK, MessageBoxImage.Error); | ||||||
|  |                 } | ||||||
|  |                 Mouse.OverrideCursor = null; | ||||||
|  |                 TransactionButton.IsEnabled = true; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |  | ||||||
|         private async void SaveButton_Click(object sender, RoutedEventArgs evt) { |         private async void SaveButton_Click(object sender, RoutedEventArgs evt) { | ||||||
|             if (PaymentVariantList.SelectedItem is not PaymentVar v || BillingData == null) return; |             if (PaymentVariantList.SelectedItem is not PaymentVar v || BillingData == null) return; | ||||||
|             try { |             try { | ||||||
| @@ -488,7 +515,7 @@ namespace Elwig.Windows { | |||||||
|             members = members.OrderBy(m => m.MgNr); |             members = members.OrderBy(m => m.MgNr); | ||||||
|  |  | ||||||
|             IEnumerable<Member> list = await members.ToListAsync(); |             IEnumerable<Member> list = await members.ToListAsync(); | ||||||
|             var data = await CreditNoteData.ForPaymentVariant(Context.CreditNoteRows, Context.Seasons, v.Year, v.AvNr); |             var data = await CreditNoteDeliveryData.ForPaymentVariant(Context.CreditNoteDeliveryRows, Context.Seasons, v.Year, v.AvNr); | ||||||
|             var payments = await Context.MemberPayments.Where(p => p.Year == v.Year && p.AvNr == v.AvNr).ToDictionaryAsync(c => c.MgNr); |             var payments = await Context.MemberPayments.Where(p => p.Year == v.Year && p.AvNr == v.AvNr).ToDictionaryAsync(c => c.MgNr); | ||||||
|             await Context.GetMemberAreaCommitmentBuckets(Year, 0); |             await Context.GetMemberAreaCommitmentBuckets(Year, 0); | ||||||
|             using var doc = Document.Merge(list.Select(m => |             using var doc = Document.Merge(list.Select(m => | ||||||
|   | |||||||
| @@ -48,7 +48,7 @@ namespace Elwig.Windows { | |||||||
|         private async void ZipButton_Click(object sender, RoutedEventArgs evt) { |         private async void ZipButton_Click(object sender, RoutedEventArgs evt) { | ||||||
|             using var ctx = new AppDbContext(); |             using var ctx = new AppDbContext(); | ||||||
|             using var ods = new OdsFile(@"C:\Users\Lorenz\Desktop\test.ods"); |             using var ods = new OdsFile(@"C:\Users\Lorenz\Desktop\test.ods"); | ||||||
|             await ods.AddTable(await DeliveryConfirmationData.ForMember(ctx.DeliveryParts, 2023, ctx.Members.Find(2948))); |             await ods.AddTable(await DeliveryConfirmationDeliveryData.ForMember(ctx.DeliveryParts, 2023, ctx.Members.Find(2948))); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| ::mkdir "C:\Program Files\Elwig" | ::mkdir "C:\Program Files\Elwig" | ||||||
| ::curl -s "http://www.columbia.edu/~em36/PDFtoPrinter.exe" -z "C:\Program Files\Elwig\PDFtoPrinter.exe" -o "C:\Program Files\Elwig\PDFtoPrinter.exe" | ::curl -s -L "http://www.columbia.edu/~em36/PDFtoPrinter.exe" -z "C:\Program Files\Elwig\PDFtoPrinter.exe" -o "C:\Program Files\Elwig\PDFtoPrinter.exe" | ||||||
| mkdir "C:\ProgramData\Elwig\resources" | mkdir "C:\ProgramData\Elwig\resources" | ||||||
| copy /b /y Documents\*.css "C:\ProgramData\Elwig\resources" | copy /b /y Documents\*.css "C:\ProgramData\Elwig\resources" | ||||||
| copy /b /y Documents\*.cshtml "C:\ProgramData\Elwig\resources" | copy /b /y Documents\*.cshtml "C:\ProgramData\Elwig\resources" | ||||||
|   | |||||||
| @@ -25,7 +25,7 @@ | |||||||
|     </Task> |     </Task> | ||||||
|   </UsingTask> |   </UsingTask> | ||||||
|   <Target Name="CustomBeforeBuild" BeforeTargets="BeforeBuild"> |   <Target Name="CustomBeforeBuild" BeforeTargets="BeforeBuild"> | ||||||
|     <Exec Command="curl -s "http://www.columbia.edu/~em36/PDFtoPrinter.exe" -z "$(TargetDir)PDFtoPrinter.exe" -o "$(TargetDir)PDFtoPrinter.exe"" /> |     <Exec Command="curl -s -L "http://www.columbia.edu/~em36/PDFtoPrinter.exe" -z "$(TargetDir)PDFtoPrinter.exe" -o "$(TargetDir)PDFtoPrinter.exe"" /> | ||||||
|     <Exec Command="dotnet publish "$(SolutionDir)Elwig\Elwig.csproj" "/p:PublishProfile=$(SolutionDir)\Elwig\Properties\PublishProfiles\FolderProfile.pubxml"" /> |     <Exec Command="dotnet publish "$(SolutionDir)Elwig\Elwig.csproj" "/p:PublishProfile=$(SolutionDir)\Elwig\Properties\PublishProfiles\FolderProfile.pubxml"" /> | ||||||
|     <GetFileVersion AssemblyPath="..\Elwig\bin\Publish\Elwig.exe"> |     <GetFileVersion AssemblyPath="..\Elwig\bin\Publish\Elwig.exe"> | ||||||
|       <Output TaskParameter="Version" PropertyName="ElwigFileVersion" /> |       <Output TaskParameter="Version" PropertyName="ElwigFileVersion" /> | ||||||
|   | |||||||
| @@ -5,8 +5,8 @@ | |||||||
|     <Cultures>de-AT</Cultures> |     <Cultures>de-AT</Cultures> | ||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|   <Target Name="CustomBeforeBuild" BeforeTargets="BeforeBuild"> |   <Target Name="CustomBeforeBuild" BeforeTargets="BeforeBuild"> | ||||||
|     <Exec Command='curl -L -s "https://go.microsoft.com/fwlink/p/?LinkId=2124703" -z "$(TargetDir)MicrosoftEdgeWebview2Setup.exe" -o "$(TargetDir)MicrosoftEdgeWebview2Setup.exe"' /> |     <Exec Command='curl -s -L "https://go.microsoft.com/fwlink/p/?LinkId=2124703" -z "$(TargetDir)MicrosoftEdgeWebview2Setup.exe" -o "$(TargetDir)MicrosoftEdgeWebview2Setup.exe"' /> | ||||||
|     <Exec Command='curl -L -s "https://aka.ms/vs/17/release/vc_redist.x86.exe" -z "$(TargetDir)VC_redist.x86.exe" -o "$(TargetDir)VC_redist.x86.exe"' /> |     <Exec Command='curl -s -L "https://aka.ms/vs/17/release/vc_redist.x86.exe" -z "$(TargetDir)VC_redist.x86.exe" -o "$(TargetDir)VC_redist.x86.exe"' /> | ||||||
|     <PropertyGroup> |     <PropertyGroup> | ||||||
|       <DefineConstants>ElwigProjectDir=..\Elwig</DefineConstants> |       <DefineConstants>ElwigProjectDir=..\Elwig</DefineConstants> | ||||||
|     </PropertyGroup> |     </PropertyGroup> | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
|  | using Elwig.Helpers.Billing; | ||||||
| using Microsoft.Data.Sqlite; | using Microsoft.Data.Sqlite; | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| @@ -16,6 +17,11 @@ namespace Tests { | |||||||
|             await AppDbContext.ExecuteEmbeddedScript(Connection, Assembly.GetExecutingAssembly(), "Tests.Resources.Insert.sql"); |             await AppDbContext.ExecuteEmbeddedScript(Connection, Assembly.GetExecutingAssembly(), "Tests.Resources.Insert.sql"); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         [OneTimeSetUp] | ||||||
|  |         public async Task SetupBillingData() { | ||||||
|  |             await BillingData.Init(); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         [OneTimeTearDown] |         [OneTimeTearDown] | ||||||
|         public async Task TeardownDatabase() { |         public async Task TeardownDatabase() { | ||||||
|             AppDbContext.ConnectionStringOverride = null; |             AppDbContext.ConnectionStringOverride = null; | ||||||
|   | |||||||
| @@ -8,12 +8,7 @@ namespace Tests.HelperTests { | |||||||
|     public class BillingDataTest { |     public class BillingDataTest { | ||||||
|  |  | ||||||
|         private static readonly JsonSerializerOptions JsonOpts = new() { WriteIndented = true }; |         private static readonly JsonSerializerOptions JsonOpts = new() { WriteIndented = true }; | ||||||
|         private static readonly string[] AttributeVariants = ["GV", "GVD", "GVK", "GVS", "GVZ", "WR", "WRS", "ZW", "ZWS", "ZWZ"]; |         private static readonly string[] Vaributes = ["GV", "GVD", "GVK", "GVS", "GVZ", "WR", "WRS", "ZW", "ZWS", "ZWZ"]; | ||||||
|  |  | ||||||
|         [OneTimeSetUp] |  | ||||||
|         public async Task SetupBilling() { |  | ||||||
|             await BillingData.Init(); |  | ||||||
|         } |  | ||||||
|  |  | ||||||
|         private static (string, string?) GetSortIdAttrId(string bucket) { |         private static (string, string?) GetSortIdAttrId(string bucket) { | ||||||
|             return (bucket[..2], bucket.Length > 2 ? bucket[2..] : null); |             return (bucket[..2], bucket.Length > 2 ? bucket[2..] : null); | ||||||
| @@ -52,7 +47,7 @@ namespace Tests.HelperTests { | |||||||
|                   "payment": 0.5, |                   "payment": 0.5, | ||||||
|                   "curves": [] |                   "curves": [] | ||||||
|                 } |                 } | ||||||
|                 """, AttributeVariants); |                 """, Vaributes); | ||||||
|             Assert.Multiple(() => { |             Assert.Multiple(() => { | ||||||
|                 TestCalcOe(data, "GV",  73, 0.5m); |                 TestCalcOe(data, "GV",  73, 0.5m); | ||||||
|                 TestCalcOe(data, "WRS", 74, 0.5m); |                 TestCalcOe(data, "WRS", 74, 0.5m); | ||||||
| @@ -77,7 +72,7 @@ namespace Tests.HelperTests { | |||||||
|                     "geb": 0.10 |                     "geb": 0.10 | ||||||
|                   }] |                   }] | ||||||
|                 } |                 } | ||||||
|                 """, AttributeVariants); |                 """, Vaributes); | ||||||
|             Assert.Multiple(() => { |             Assert.Multiple(() => { | ||||||
|                 TestCalcOe(data, "GV", 70, 0.25m); |                 TestCalcOe(data, "GV", 70, 0.25m); | ||||||
|                 TestCalcOe(data, "GV", 72, 0.25m); |                 TestCalcOe(data, "GV", 72, 0.25m); | ||||||
| @@ -114,7 +109,7 @@ namespace Tests.HelperTests { | |||||||
|                     } |                     } | ||||||
|                   }] |                   }] | ||||||
|                 } |                 } | ||||||
|                 """, AttributeVariants); |                 """, Vaributes); | ||||||
|             Assert.Multiple(() => { |             Assert.Multiple(() => { | ||||||
|                 TestCalcKmw(data, "GV", 13.00, 0.10m); |                 TestCalcKmw(data, "GV", 13.00, 0.10m); | ||||||
|                 TestCalcKmw(data, "GV", 13.50, 0.10m); |                 TestCalcKmw(data, "GV", 13.50, 0.10m); | ||||||
| @@ -148,7 +143,7 @@ namespace Tests.HelperTests { | |||||||
|                   }, |                   }, | ||||||
|                   "curves": [] |                   "curves": [] | ||||||
|                 } |                 } | ||||||
|                 """, AttributeVariants); |                 """, Vaributes); | ||||||
|             Assert.Multiple(() => { |             Assert.Multiple(() => { | ||||||
|                 TestCalcOe(data, "WR",  73, 0.10m); |                 TestCalcOe(data, "WR",  73, 0.10m); | ||||||
|                 TestCalcOe(data, "WRS", 73, 0.15m); |                 TestCalcOe(data, "WRS", 73, 0.15m); | ||||||
| @@ -179,7 +174,7 @@ namespace Tests.HelperTests { | |||||||
|                   }, |                   }, | ||||||
|                   "curves": [] |                   "curves": [] | ||||||
|                 } |                 } | ||||||
|                 """, AttributeVariants); |                 """, Vaributes); | ||||||
|             Assert.Multiple(() => { |             Assert.Multiple(() => { | ||||||
|                 TestCalcOe(data, "GV",  75, 0.30m, qualid: "WEI"); |                 TestCalcOe(data, "GV",  75, 0.30m, qualid: "WEI"); | ||||||
|                 TestCalcOe(data, "ZW",  76, 0.25m, qualid: "WEI"); |                 TestCalcOe(data, "ZW",  76, 0.25m, qualid: "WEI"); | ||||||
| @@ -221,7 +216,7 @@ namespace Tests.HelperTests { | |||||||
|                     } |                     } | ||||||
|                   }] |                   }] | ||||||
|                 } |                 } | ||||||
|                 """, AttributeVariants); |                 """, Vaributes); | ||||||
|             Assert.Multiple(() => { |             Assert.Multiple(() => { | ||||||
|                 TestCalcKmw(data, "GV", 15.0, 2.0m); |                 TestCalcKmw(data, "GV", 15.0, 2.0m); | ||||||
|                 TestCalcKmw(data, "GV", 15.5, 2.272727m); |                 TestCalcKmw(data, "GV", 15.5, 2.272727m); | ||||||
| @@ -281,7 +276,7 @@ namespace Tests.HelperTests { | |||||||
|                     } |                     } | ||||||
|                   }] |                   }] | ||||||
|                 } |                 } | ||||||
|                 """, AttributeVariants); |                 """, Vaributes); | ||||||
|             Assert.Multiple(() => { |             Assert.Multiple(() => { | ||||||
|                 TestCalcKmw(data, "GV",  15.0, 0.75m); |                 TestCalcKmw(data, "GV",  15.0, 0.75m); | ||||||
|                 TestCalcKmw(data, "GVS", 15.0, 0.50m); |                 TestCalcKmw(data, "GVS", 15.0, 0.50m); | ||||||
| @@ -340,7 +335,7 @@ namespace Tests.HelperTests { | |||||||
|                     } |                     } | ||||||
|                   }] |                   }] | ||||||
|                 } |                 } | ||||||
|                 """, AttributeVariants); |                 """, Vaributes); | ||||||
|             Assert.Multiple(() => { |             Assert.Multiple(() => { | ||||||
|                 TestCalcOe(data, "GVK", 73, 0.032m); |                 TestCalcOe(data, "GVK", 73, 0.032m); | ||||||
|                 TestCalcOe(data, "ZWS", 74, 0.033m); |                 TestCalcOe(data, "ZWS", 74, 0.033m); | ||||||
| @@ -349,11 +344,11 @@ namespace Tests.HelperTests { | |||||||
|             }); |             }); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         private static List<ContractSelection> GetSelection(IEnumerable<string> attVars) { |         private static List<Varibute> GetSelection(IEnumerable<string> attVars) { | ||||||
|             return attVars.Select(s => { |             return attVars.Select(s => { | ||||||
|                 var sortid = s[..2]; |                 var sortid = s[..2]; | ||||||
|                 var attrid = s.Length > 2 ? s[2..] : null; |                 var attrid = s.Length > 2 ? s[2..] : null; | ||||||
|                 return new ContractSelection( |                 return new Varibute( | ||||||
|                     new WineVar(sortid, sortid), |                     new WineVar(sortid, sortid), | ||||||
|                     attrid == null ? null : new WineAttr(attrid, attrid) |                     attrid == null ? null : new WineAttr(attrid, attrid) | ||||||
|                 ); |                 ); | ||||||
|   | |||||||
| @@ -1,4 +1,5 @@ | |||||||
| using Elwig.Helpers; | using Elwig.Helpers; | ||||||
|  | using Elwig.Helpers.Billing; | ||||||
| using Microsoft.Data.Sqlite; | using Microsoft.Data.Sqlite; | ||||||
| using System.Reflection; | using System.Reflection; | ||||||
|  |  | ||||||
| @@ -6,6 +7,9 @@ namespace Tests.HelperTests { | |||||||
|     [TestFixture] |     [TestFixture] | ||||||
|     public class BillingTest { |     public class BillingTest { | ||||||
|  |  | ||||||
|  |         private const int Year1 = 2020, Year2 = 2020; | ||||||
|  |         private const int MgNr1 = 101, MgNr2 = 102, MgNr3 = 103, MgNr4 = 104; | ||||||
|  |  | ||||||
|         private SqliteConnection? Connection; |         private SqliteConnection? Connection; | ||||||
|  |  | ||||||
|         [OneTimeSetUp] |         [OneTimeSetUp] | ||||||
| @@ -22,9 +26,120 @@ namespace Tests.HelperTests { | |||||||
|             Connection = null; |             Connection = null; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         [TearDown] | ||||||
|  |         public async Task CleanupDatabasePayment() { | ||||||
|  |             if (Connection == null) return; | ||||||
|  |             await AppDbContext.ExecuteBatch(Connection, """ | ||||||
|  |                 DELETE FROM credit; | ||||||
|  |                 DELETE FROM delivery_part_bucket; | ||||||
|  |                 DELETE FROM payment_variant; | ||||||
|  |                 """); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private Task<Dictionary<string, AreaComBucket>> GetMemberAreaCommitmentBuckets(int year, int mgnr) { | ||||||
|  |             var ctx = new AppDbContext(); | ||||||
|  |             return ctx.GetMemberAreaCommitmentBuckets(year, mgnr, Connection); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private Task<Dictionary<string, int>> GetMemberDeliveryBuckets(int year, int mgnr) { | ||||||
|  |             var ctx = new AppDbContext(); | ||||||
|  |             return ctx.GetMemberDeliveryBuckets(year, mgnr, Connection); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private Task<Dictionary<string, int>> GetMemberPaymentBuckets(int year, int mgnr) { | ||||||
|  |             var ctx = new AppDbContext(); | ||||||
|  |             return ctx.GetMemberPaymentBuckets(year, mgnr, Connection); | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private async Task<Dictionary<(string, string), int>> GetMemberDeliveryPrices(int year, int mgnr) { | ||||||
|  |             var buckets = new Dictionary<(string, string), int>(); | ||||||
|  |             using (var cmd = Connection!.CreateCommand()) { | ||||||
|  |                 cmd.CommandText = $""" | ||||||
|  |                     SELECT lsnr || '/' ||  d.dpnr, d.sortid || b.discr, price | ||||||
|  |                     FROM v_delivery d | ||||||
|  |                         LEFT JOIN payment_delivery_part_bucket p ON (p.year, p.did, p.dpnr) = (d.year, d.did, d.dpnr) | ||||||
|  |                         LEFT JOIN delivery_part_bucket b ON (b.year, b.did, b.dpnr, b.bktnr) = (p.year, p.did, p.dpnr, p.bktnr) | ||||||
|  |                     WHERE d.year = {year} AND mgnr = {mgnr} | ||||||
|  |                     """; | ||||||
|  |                 using var reader = await cmd.ExecuteReaderAsync(); | ||||||
|  |                 while (await reader.ReadAsync()) { | ||||||
|  |                     var lsnr = reader.GetString(0); | ||||||
|  |                     var bucket = reader.GetString(1); | ||||||
|  |                     buckets[(lsnr, bucket)] = reader.GetInt32(2); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             return buckets; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         private Task InsertPaymentVariant(int year, int avnr, string data) { | ||||||
|  |             return AppDbContext.ExecuteBatch(Connection!, $""" | ||||||
|  |                 INSERT INTO payment_variant (year, avnr, name, date, transfer_date, test_variant, calc_time, data) | ||||||
|  |                 VALUES ({year}, {avnr}, 'Test', '2021-01-15', NULL, TRUE, NULL, '{data}'); | ||||||
|  |                 """); | ||||||
|  |         } | ||||||
|  |  | ||||||
|         [Test] |         [Test] | ||||||
|         public void Test() { |         public async Task Test_01_NoActiveAreaCommitments() { | ||||||
|             // TODO |             int mgnr = MgNr1, year = Year1; | ||||||
|  |             await InsertPaymentVariant(year, 1, """ | ||||||
|  |                 { | ||||||
|  |                   "mode": "elwig", | ||||||
|  |                   "version": 1, | ||||||
|  |                   "payment": { | ||||||
|  |                     "GV/": "curve:0", | ||||||
|  |                     "GV/B": "curve:1", | ||||||
|  |                     "GV/K": "curve:2" | ||||||
|  |                   }, | ||||||
|  |                   "quality": {"WEI": 0.1}, | ||||||
|  |                   "curves": [{ | ||||||
|  |                     "id": 0, | ||||||
|  |                     "mode": "oe", | ||||||
|  |                     "data": {"15kmw": 0.5}, | ||||||
|  |                     "geb": 0.1 | ||||||
|  |                   }, { | ||||||
|  |                     "id": 1, | ||||||
|  |                     "mode": "oe", | ||||||
|  |                     "data": {"15kmw": 0.54}, | ||||||
|  |                     "geb": 0.1 | ||||||
|  |                   }, { | ||||||
|  |                     "id": 2, | ||||||
|  |                     "mode": "oe", | ||||||
|  |                     "data": {"15kmw": 0.61}, | ||||||
|  |                     "geb": 0.1 | ||||||
|  |                   }] | ||||||
|  |                 } | ||||||
|  |                 """); | ||||||
|  |  | ||||||
|  |             var areaCom = await GetMemberAreaCommitmentBuckets(year, mgnr); | ||||||
|  |             Assert.That(areaCom, Is.Empty); | ||||||
|  |             var delivery = await GetMemberDeliveryBuckets(year, mgnr); | ||||||
|  |             Assert.Multiple(() => { | ||||||
|  |                 Assert.That(delivery, Has.Count.EqualTo(4)); | ||||||
|  |                 Assert.That(delivery["GV"],  Is.EqualTo(16_000)); | ||||||
|  |                 Assert.That(delivery["GV_"], Is.EqualTo( 1_000)); | ||||||
|  |                 Assert.That(delivery["GVB"], Is.EqualTo( 8_000)); | ||||||
|  |                 Assert.That(delivery["GVK"], Is.EqualTo( 4_000)); | ||||||
|  |             }); | ||||||
|  |  | ||||||
|  |             BillingVariant b = new(year, 1); | ||||||
|  |             await b.CalculateBuckets(false, false, false); | ||||||
|  |             var payment = await GetMemberPaymentBuckets(year, mgnr); | ||||||
|  |             Assert.Multiple(() => { | ||||||
|  |                 Assert.That(payment, Has.Count.EqualTo(1)); | ||||||
|  |                 Assert.That(payment["GV_"], Is.EqualTo(17_000)); | ||||||
|  |             }); | ||||||
|  |  | ||||||
|  |             await b.Calculate(); | ||||||
|  |             var prices = await GetMemberDeliveryPrices(year, mgnr); | ||||||
|  |             Assert.Multiple(() => { | ||||||
|  |                 Assert.That(prices, Has.Count.EqualTo(6)); | ||||||
|  |                 Assert.That(prices[("20201001X001/1", "GV_")], Is.EqualTo(0_6100)); | ||||||
|  |                 Assert.That(prices[("20201001X001/2", "GV_")], Is.EqualTo(0_5000)); | ||||||
|  |                 Assert.That(prices[("20201001X002/1", "GV_")], Is.EqualTo(0_5400)); | ||||||
|  |                 Assert.That(prices[("20201001X002/2", "GV_")], Is.EqualTo(0_5400)); | ||||||
|  |                 Assert.That(prices[("20201001X003/1", "GV_")], Is.EqualTo(0_1000)); | ||||||
|  |                 Assert.That(prices[("20201001X003/2", "GV_")], Is.EqualTo(0_5000)); | ||||||
|  |             }); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1 +1,11 @@ | |||||||
| -- deletes for HelpersBillingTest | -- deletes for HelperTests.BillingTest | ||||||
|  |  | ||||||
|  | DELETE FROM credit; | ||||||
|  | DELETE FROM payment_variant | ||||||
|  | DELETE FROM delivery; | ||||||
|  | DELETE FROM area_commitment; | ||||||
|  | DELETE FROM area_commitment_type; | ||||||
|  | DELETE FROM season; | ||||||
|  | DELETE FROM member; | ||||||
|  | DELETE FROM wine_attribute; | ||||||
|  | DELETE FROM wine_cultivation; | ||||||
|   | |||||||
| @@ -1 +1,59 @@ | |||||||
| -- inserts for HelpersBillingTest | -- inserts for HelperTests.BillingTest | ||||||
|  |  | ||||||
|  | INSERT INTO wine_cultivation (cultid, name, description) VALUES | ||||||
|  | ('N', 'Normal', NULL), | ||||||
|  | ('K', 'KIP', 'Kontrollierte Integrierte Produktion'), | ||||||
|  | ('B', 'Org. Biologisch', 'Organisch Biologisch'); | ||||||
|  |  | ||||||
|  | INSERT INTO wine_attribute (attrid, name, active, max_kg_per_ha, strict, fill_lower) VALUES | ||||||
|  | ('B', 'Bio',       TRUE, NULL, FALSE, 0), | ||||||
|  | ('K', 'Kabinett',  TRUE, NULL, FALSE, 0), | ||||||
|  | ('D', 'DAC',       TRUE, 7500, FALSE, 0), | ||||||
|  | ('S', 'Saft',      TRUE, NULL, FALSE, 0), | ||||||
|  | ('Z', 'Sekt',      TRUE, NULL, FALSE, 0), | ||||||
|  | ('P', 'Vertrag P', TRUE, NULL, TRUE,  0), | ||||||
|  | ('Q', 'Vertrag Q', TRUE, NULL, TRUE,  1), | ||||||
|  | ('R', 'Vertrag R', TRUE, NULL, TRUE,  2); | ||||||
|  |  | ||||||
|  | INSERT INTO area_commitment_type (vtrgid, sortid, attrid, disc, min_kg_per_ha, penalty_per_kg, penalty_amount, penalty_none) VALUES | ||||||
|  | ('ZW', 'ZW', NULL, NULL, 2500,  600, NULL, NULL), | ||||||
|  | ('GV', 'GV', NULL, NULL, 5000,  500, NULL, NULL), | ||||||
|  | ('GVK', 'GV', 'K', NULL, 5000,  500, NULL, NULL), | ||||||
|  | ('GVD', 'GV', 'D', NULL, 5000, 1000, NULL, NULL), | ||||||
|  | ('GVP', 'GV', 'P', NULL, 5000, 1000, 1000000, NULL), | ||||||
|  | ('GVQ', 'GV', 'Q', NULL, 5000, 1000, 1000000, NULL), | ||||||
|  | ('GVR', 'GV', 'R', NULL, 5000, 1000, 1000000, NULL); | ||||||
|  |  | ||||||
|  | INSERT INTO member (mgnr, given_name, family_name, zwstid, volllieferant, buchführend, country, postal_dest, address, default_kgnr) VALUES | ||||||
|  | (101, 'Max',       'Mustermann',  'X', FALSE, FALSE, 40, 222303524, 'Winzerstraße 1', 06109), | ||||||
|  | (102, 'Wernhardt', 'Weinbauer',   'X', FALSE, FALSE, 40, 222303524, 'Winzerstraße 2', 06109), | ||||||
|  | (103, 'Matthäus',  'Musterbauer', 'X', FALSE, FALSE, 40, 212005138, 'Brünner Straße 10', 15224), | ||||||
|  | (104, 'Waltraud',  'Winzer',      'X', FALSE, FALSE, 40, 212005138, 'Wiener Straße 15', 15224); | ||||||
|  |  | ||||||
|  | INSERT INTO area_commitment (fbnr, mgnr, vtrgid, cultid, area, kgnr, gstnr, rdnr, year_from, year_to) VALUES | ||||||
|  | ( 1, 101, 'GV',  'K', 10000, 06109, '123/4', NULL, 2000, 2019), | ||||||
|  | ( 2, 101, 'GV',  'B', 10000, 06109, '123/5', NULL, 2025, 2030); | ||||||
|  |  | ||||||
|  | INSERT INTO season (year, currency, min_kg_per_bs, max_kg_per_bs, penalty_per_kg, penalty_amount, penalty_none, start_date, end_date) VALUES | ||||||
|  | (2020, 'EUR', 1000, 2000, NULL, NULL, NULL, NULL, NULL), | ||||||
|  | (2021, 'EUR', 2000, 4000, NULL, NULL, NULL, NULL, NULL); | ||||||
|  |  | ||||||
|  | INSERT INTO modifier (year, modid, ordering, name, abs, rel, standard, quick_select) VALUES | ||||||
|  | (2020, 'S', 0, 'Geschädigte Trauben', NULL, -0.1, FALSE, FALSE), | ||||||
|  | (2020, 'A', 0, 'Keine Voranmeldung', -1000, NULL, FALSE, FALSE); | ||||||
|  |  | ||||||
|  | INSERT INTO delivery (mgnr, year, did, date, time, zwstid, lnr) VALUES | ||||||
|  | (101, 2020, 1, '2020-10-01', NULL, 'X', 1), | ||||||
|  | (101, 2020, 2, '2020-10-01', NULL, 'X', 2), | ||||||
|  | (101, 2020, 3, '2020-10-01', NULL, 'X', 3); | ||||||
|  |  | ||||||
|  | INSERT INTO delivery_part (year, did, dpnr, sortid, attrid, weight, kmw, qualid, hkid, kgnr, gerebelt, manual_weighing, spl_check, scale_id, weighing_id, weighing_reason) VALUES | ||||||
|  | (2020, 1, 1, 'GV',  'K', 4000, 17, 'KAB', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL), | ||||||
|  | (2020, 1, 2, 'GV', NULL, 4000, 16, 'QUW', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL), | ||||||
|  | (2020, 2, 1, 'GV',  'B', 4000, 15, 'QUW', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL), | ||||||
|  | (2020, 2, 2, 'GV',  'B', 4000, 16, 'QUW', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL), | ||||||
|  | (2020, 3, 1, 'GV', NULL,  500, 15, 'WEI', 'OEST', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL), | ||||||
|  | (2020, 3, 2, 'GV', NULL,  500, 14, 'LDW', 'WLXX', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL); | ||||||
|  |  | ||||||
|  | INSERT INTO delivery_part_modifier (year, did, dpnr, modid) VALUES | ||||||
|  | (2020, 1, 2, 'S'); | ||||||
|   | |||||||
| @@ -1 +1 @@ | |||||||
| curl -s "https://www.necronda.net/elwig/files/create.sql?v=13" -u "elwig:ganzGeheim123!" -o "Resources\Create.sql" | curl -s -L "https://www.necronda.net/elwig/files/create.sql?v=13" -u "elwig:ganzGeheim123!" -o "Resources\Create.sql" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user