Compare commits
	
		
			2 Commits
		
	
	
		
			e71d9516ec
			...
			5657a8f90a
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 5657a8f90a | |||
| 56578a0a9d | 
							
								
								
									
										100
									
								
								Elwig/Documents/DeliveryConfirmation.cshtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								Elwig/Documents/DeliveryConfirmation.cshtml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | ||||
| @using RazorLight | ||||
| @inherits TemplatePage<Elwig.Documents.DeliveryConfirmation> | ||||
| @model Elwig.Documents.DeliveryConfirmation | ||||
| @{ Layout = "BusinessDocument"; } | ||||
| <link rel="stylesheet" href="file:///@Raw(Model.DataPath)\resources\style-deliveryconfirmation.css"/> | ||||
| <main> | ||||
|     <h1>@Model.Title</h1> | ||||
|     <table class="delivery-confirmation"> | ||||
|         <colgroup> | ||||
|             <col style="width: 25mm;"/> | ||||
|             <col style="width: 5mm;"/> | ||||
|             <col style="width: 20mm;"/> | ||||
|             <col style="width: 21mm;"/> | ||||
|             <col style="width: 19mm;"/> | ||||
|             <col style="width: 10mm;"/> | ||||
|             <col style="width: 10mm;"/> | ||||
|             <col style="width: 15mm;"/> | ||||
|             <col style="width: 12mm;"/> | ||||
|             <col style="width: 14mm;"/> | ||||
|             <col style="width: 14mm;"/> | ||||
|         </colgroup> | ||||
|         <thead> | ||||
|             <tr> | ||||
|                 <th rowspan="2" style="text-align: left;">Lieferschein-Nr.</th> | ||||
|                 <th rowspan="2">Pos.</th> | ||||
|                 <th rowspan="2" style="text-align: left;">Sorte</th> | ||||
|                 <th rowspan="2" style="text-align: left;">Attribut(e)</th> | ||||
|                 <th rowspan="2" style="text-align: left;">Qualitätsstufe</th> | ||||
|                 <th colspan="2">Gradation</th> | ||||
|                 <th colspan="2">Flächenbindung</th> | ||||
|                 <th>Gewicht</th> | ||||
|                 <th>Davon<br/>abwerten</th> | ||||
|             </tr> | ||||
|             <tr> | ||||
|                 <th>[°Oe]</th> | ||||
|                 <th>[°KMW]</th> | ||||
|                 <th colspan="2">[kg]</th> | ||||
|                 <th>[kg]</th> | ||||
|                 <th>[kg]</th> | ||||
|             </tr> | ||||
|         </thead> | ||||
|         <tbody> | ||||
|             @{ | ||||
|                 var lastSortId = ""; | ||||
|             } | ||||
|             @foreach (var p in Model.Deliveries) { | ||||
|                 var bins = p.Bins.Select((b, n) => (b, n + 1)).Where(b => b.Item1 > 0).ToArray(); | ||||
|                 var rowsBins = bins.Length; | ||||
|                 var mods = p.Modifiers.Select(m => m.Name).ToArray(); | ||||
|                 var rowsMod = mods.Length + 1; | ||||
|                 var rows = Math.Max(rowsBins, rowsMod); | ||||
|                 var first = true; | ||||
|                 @for (int i = 0; i < rows; i++) { | ||||
|                     <tr class="@(first ? "first" : "") @(p.SortId != lastSortId && lastSortId != "" ? "new": "") @(rows > i + 1 ? "trailing" : "")"> | ||||
|                         @if (first) { | ||||
|                             <td rowspan="@rows">@p.Delivery.LsNr</td> | ||||
|                             <td rowspan="@rows">@p.DPNr</td> | ||||
|                             <td class="small">@p.Variant.Name</td> | ||||
|                             <td class="small">@p.AttributesString</td> | ||||
|                             <td class="small">@p.Quality.Name</td> | ||||
|                             <td rowspan="@rows" class="grad">@($"{p.Oe:N0}")</td> | ||||
|                             <td rowspan="@rows" class="grad">@($"{p.Kmw:N1}")</td> | ||||
|                         } | ||||
|                         @if (i > 0 && i <= mods.Length) { | ||||
|                             <td colspan="3" class="mod">@(mods[i - 1])</td> | ||||
|                         } else if (i > 0) { | ||||
|                             <td colspan="3"></td> | ||||
|                         } | ||||
|                         @if (i < bins.Length) { | ||||
|                             var (b, n) = bins[i]; | ||||
|                             string name = ""; | ||||
|                             switch (n) { | ||||
|                                 case 1: name = $"geb. {p.SortId}{string.Join("", p.Attributes.Order().Select(a => a.AttrId).Take(2))}"; break; | ||||
|                                 case 2: name = $"geb. {p.SortId}{p.Attributes.Select(a => a.AttrId).Order().FirstOrDefault()}"; break; | ||||
|                                 case 3: name = $"geb. {p.SortId}{p.Attributes.Select(a => a.AttrId).Order().Skip(1).FirstOrDefault()}"; break; | ||||
|                                 case 4: name = $"geb. {p.SortId}"; break; | ||||
|                                 case 5: name = "ungeb."; break; | ||||
|                             } | ||||
|                             <td class="geb">@name:</td> | ||||
|                             <td class="weight">@($"{b:N0}")</td> | ||||
|                         } else { | ||||
|                             <td colspan="2"></td> | ||||
|                         } | ||||
|                         @if (first) { | ||||
|                             <td rowspan="@rows" class="weight">@($"{p.Weight:N0}")</td> | ||||
|                             <td rowspan="@rows" class="weight"></td> | ||||
|                             first = false; | ||||
|                         } | ||||
|                     </tr> | ||||
|                     lastSortId = p.SortId; | ||||
|                 } | ||||
|             } | ||||
|             <tr class="sum"> | ||||
|                 <td colspan="8">Gesamt:</td> | ||||
|                 <td colspan="2" style="text-align: right;">@($"{Model.Deliveries.Sum(p => p.Weight):N0}")</td> | ||||
|                 <td></td> | ||||
|             </tr> | ||||
|         </tbody> | ||||
|     </table> | ||||
| </main> | ||||
							
								
								
									
										26
									
								
								Elwig/Documents/DeliveryConfirmation.cshtml.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								Elwig/Documents/DeliveryConfirmation.cshtml.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| using Elwig.Helpers; | ||||
| using Elwig.Models; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
|  | ||||
| namespace Elwig.Documents { | ||||
|     public class DeliveryConfirmation : BusinessDocument { | ||||
|  | ||||
|         public int Year; | ||||
|         public IEnumerable<DeliveryPart> Deliveries; | ||||
|  | ||||
|         public DeliveryConfirmation(AppDbContext ctx, int year, Member m) : base($"Anlieferungsbestätigung {year} – {m.Name}", m) { | ||||
|             Year = year; | ||||
|             DocumentId = $"Anl.-Best. {Year}/{m.MgNr}"; | ||||
|             Deliveries = ctx.DeliveryParts.FromSqlRaw($""" | ||||
|                 SELECT p.* | ||||
|                 FROM v_delivery v | ||||
|                     JOIN delivery_part p ON (p.year, p.did, p.dpnr) = (v.year, v.did, v.dpnr) | ||||
|                 WHERE (v.year, v.mgnr) = ({Year}, {m.MgNr}) | ||||
|                 ORDER BY v.sortid, v.abgewertet ASC, LENGTH(v.attributes) DESC, COALESCE(v.attributes, '~'), v.kmw DESC, v.lsnr, v.dpnr | ||||
|                 """) | ||||
|                 .ToList(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -100,6 +100,8 @@ namespace Elwig.Documents { | ||||
|                 name = "DeliveryJournal"; | ||||
|             } else if (this is Letterhead) { | ||||
|                 name = "Letterhead"; | ||||
|             } else if (this is DeliveryConfirmation) { | ||||
|                 name = "DeliveryConfirmation"; | ||||
|             } else { | ||||
|                 throw new InvalidOperationException("Invalid document object"); | ||||
|             } | ||||
|   | ||||
| @@ -21,6 +21,7 @@ namespace Elwig.Documents { | ||||
|             await e.CompileTemplateAsync("CreditNote"); | ||||
|             await e.CompileTemplateAsync("DeliveryJournal"); | ||||
|             await e.CompileTemplateAsync("Letterhead"); | ||||
|             await e.CompileTemplateAsync("DeliveryConfirmation"); | ||||
|  | ||||
|             Engine = e; | ||||
|             evtHandler(); | ||||
|   | ||||
							
								
								
									
										66
									
								
								Elwig/Documents/style-deliveryconfirmation.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								Elwig/Documents/style-deliveryconfirmation.css
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
|  | ||||
| table.delivery-confirmation { | ||||
|     font-size: 10pt; | ||||
| } | ||||
|  | ||||
| table.delivery-confirmation thead { | ||||
|     font-size: 8pt; | ||||
| } | ||||
|  | ||||
| table.delivery-confirmation thead th { | ||||
|     font-weight: normal; | ||||
|     font-style: italic; | ||||
| } | ||||
|  | ||||
| table.delivery-confirmation td { | ||||
|     overflow: hidden; | ||||
|     white-space: nowrap; | ||||
| } | ||||
|  | ||||
| table.delivery-confirmation td[rowspan] { | ||||
|     vertical-align: top; | ||||
| } | ||||
|  | ||||
| table.delivery-confirmation .weight { | ||||
|     text-align: right; | ||||
| } | ||||
|  | ||||
| table.delivery-confirmation .grad { | ||||
|     text-align: center; | ||||
| } | ||||
|  | ||||
| table.delivery-confirmation .geb { | ||||
|     font-size: 8pt; | ||||
| } | ||||
|  | ||||
| table.delivery-confirmation .mod { | ||||
|     font-size: 8pt; | ||||
|     padding-left: 5mm; | ||||
| } | ||||
|  | ||||
| table.delivery-confirmation .small { | ||||
|     font-size: 8pt; | ||||
| } | ||||
|  | ||||
| table.delivery-confirmation tr.new td { | ||||
|     border-top: 0.5pt solid black; | ||||
| } | ||||
|  | ||||
| table.delivery-confirmation tr:not(.first) td { | ||||
|     padding-top: 0; | ||||
| } | ||||
|  | ||||
| table.delivery-confirmation tr.trailing td { | ||||
|     padding-bottom: 0; | ||||
| } | ||||
|  | ||||
| table.delivery-confirmation tr.sum { | ||||
|     border-top: 0.5pt solid black; | ||||
|     break-before: avoid; | ||||
|     font-weight: bold; | ||||
|     font-size: 12pt; | ||||
| } | ||||
|  | ||||
| table.delivery-confirmation tr.sum td { | ||||
|     padding-top: 1mm; | ||||
| } | ||||
| @@ -100,7 +100,7 @@ namespace Elwig.Models { | ||||
|         public IEnumerable<WineAttr> Attributes => PartAttributes.Select(a => a.Attr); | ||||
|  | ||||
|         [NotMapped] | ||||
|         public string AttributesString => string.Join("/", Attributes); | ||||
|         public string AttributesString => string.Join(" / ", Attributes); | ||||
|  | ||||
|         [InverseProperty("Part")] | ||||
|         public virtual ISet<DeliveryPartModifier> PartModifiers { get; private set; } | ||||
| @@ -115,10 +115,10 @@ namespace Elwig.Models { | ||||
|         public string OriginString => Origin.OriginString + "\n" + (Kg?.Gl != null ? $" / {Kg.Gl.Name}" : "") + (Kg != null ? $" / {Kg.AtKg.Gem.Name} / KG {Kg.AtKg.Name}" : "") + (Rd != null ? $" / Ried {Rd.Name}" : ""); | ||||
|  | ||||
|         [InverseProperty("Part")] | ||||
|         public virtual DeliveryPartBin Bin { get; private set; } | ||||
|         public virtual DeliveryPartBin? Bin { get; private set; } | ||||
|  | ||||
|         [NotMapped] | ||||
|         public int[] Bins => (new int?[] { Bin.Bin1, Bin.Bin2, Bin.Bin3, Bin.Bin4, Bin.Bin5, Bin.Bin6, Bin.Bin7, Bin.Bin8, Bin.Bin9 }) | ||||
|         public int[] Bins => (new int?[] { Bin?.Bin1, Bin?.Bin2, Bin?.Bin3, Bin?.Bin4, Bin?.Bin5, Bin?.Bin6, Bin?.Bin7, Bin?.Bin8, Bin?.Bin9 }) | ||||
|             .Where(b => b != null).Select(b => b.Value).ToArray(); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -8,6 +8,8 @@ | ||||
|         Loaded="Window_Loaded"> | ||||
|     <Window.Resources> | ||||
|         <Style TargetType="Button"> | ||||
|             <Setter Property="VerticalAlignment" Value="Top"/> | ||||
|             <Setter Property="HorizontalAlignment" Value="Left"/> | ||||
|             <Setter Property="FontSize" Value="14"/> | ||||
|             <Setter Property="Padding" Value="9,3"/> | ||||
|             <Setter Property="Height" Value="32"/> | ||||
| @@ -39,19 +41,19 @@ | ||||
|         </Grid> | ||||
|  | ||||
|         <Button x:Name="MemberAdminButton" Content="Mitglieder" Click="MemberAdminButton_Click" | ||||
|                 Margin="50,160,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/> | ||||
|                 Margin="50,160,0,0"/> | ||||
|         <Button x:Name="ReceiptButton" Content="Übernahme" Click="ReceiptButton_Click" | ||||
|                 Margin="50,200,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/> | ||||
|                 Margin="50,200,0,0"/> | ||||
|         <Button x:Name="DeliveryAdminButton" Content="Lieferungen" Click="DeliveryAdminButton_Click" | ||||
|                 Margin="50,240,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/> | ||||
|         <Button x:Name="PaymentWindowButton" Content="Auszahlung" Click="PaymentWindowButton_Click" | ||||
|                 Margin="50,280,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/> | ||||
|                 Margin="50,240,0,0"/> | ||||
|         <Button x:Name="SeasonFinishButton" Content="Leseabschluss" Click="SeasonFinishButton_Click" | ||||
|                 Margin="50,280,0,0"/> | ||||
|         <Button x:Name="BaseDataButton" Content="Stammdaten" Click="BaseDataButton_Click" | ||||
|                 Margin="50,320,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/> | ||||
|                 Margin="50,320,0,0"/> | ||||
|  | ||||
|         <Button x:Name="TestWindowButton" Content="Test Fenster" Click="TestWindowButton_Click" | ||||
|                 Margin="260,280,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/> | ||||
|                 Margin="260,280,0,0"/> | ||||
|         <Button x:Name="QueryWindowButton" Content="Datenbankabfragen" Click="QueryWindowButton_Click" | ||||
|                 Margin="260,320,0,0" VerticalAlignment="Top" HorizontalAlignment="Left"/> | ||||
|                 Margin="260,320,0,0"/> | ||||
|     </Grid> | ||||
| </Window> | ||||
|   | ||||
| @@ -52,8 +52,8 @@ namespace Elwig.Windows { | ||||
|             w.Show(); | ||||
|         } | ||||
|  | ||||
|         private void PaymentWindowButton_Click(object sender, RoutedEventArgs e) { | ||||
|             var w = new ChartWindow(); | ||||
|         private void SeasonFinishButton_Click(object sender, RoutedEventArgs e) { | ||||
|             var w = new SeasonFinishWindow(); | ||||
|             w.Show(); | ||||
|         } | ||||
|     } | ||||
|   | ||||
							
								
								
									
										45
									
								
								Elwig/Windows/SeasonFinishWindow.xaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								Elwig/Windows/SeasonFinishWindow.xaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| <local:ContextWindow x:Class="Elwig.Windows.SeasonFinishWindow" | ||||
|         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" | ||||
|         xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" | ||||
|         mc:Ignorable="d" | ||||
|         Loaded="Window_Loaded" | ||||
|         Title="Leseabschluss - Elwig" Height="450" Width="800"> | ||||
|     <Window.Resources> | ||||
|         <Style TargetType="Button"> | ||||
|             <Setter Property="VerticalAlignment" Value="Top"/> | ||||
|             <Setter Property="HorizontalAlignment" Value="Left"/> | ||||
|             <Setter Property="FontSize" Value="14"/> | ||||
|             <Setter Property="Padding" Value="9,3"/> | ||||
|             <Setter Property="Height" Value="32"/> | ||||
|             <Setter Property="Width" Value="200"/> | ||||
|         </Style> | ||||
|     </Window.Resources> | ||||
|     <Grid> | ||||
|         <Label Content="Saison:" Margin="50,40,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" Padding="2,4,2,4" Height="25"/> | ||||
|         <xctk:IntegerUpDown Name="SeasonInput" Height="25" Width="56" FontSize="14" Minimum="1000" Maximum="9999" | ||||
|                             Margin="110,40,0,0" VerticalAlignment="Top" HorizontalAlignment="Left" | ||||
|                             ValueChanged="SeasonInput_ValueChanged"/> | ||||
|  | ||||
|         <Button x:Name="CalculateBinsButton" | ||||
|                 Click="CalculateBinsButton_Click" | ||||
|                 Margin="50,80,0,0" FontSize="12" Height="40"> | ||||
|             <TextBlock TextAlignment="Center">Lieferungen auf Flächen-<LineBreak/>bindungen aufteilen</TextBlock> | ||||
|         </Button> | ||||
|  | ||||
|         <Button x:Name="DeliveryConfirmationButton" Content="Anlieferungsbestätigungen" | ||||
|                 Click="DeliveryConfirmationButton_Click" | ||||
|                 Margin="50,130,0,0"/> | ||||
|  | ||||
|         <Button x:Name="OverUnderDeliveryButton" Content="Über-/Unterlieferungen" | ||||
|                 Click="OverUnderDeliveryButton_Click" | ||||
|                 Margin="50,172,0,0"/> | ||||
|  | ||||
|         <Button x:Name="PaymentButton" Content="Auszahlung" | ||||
|                 Click="PaymentButton_Click" | ||||
|                 Margin="50,214,0,0"/> | ||||
|     </Grid> | ||||
| </local:ContextWindow> | ||||
							
								
								
									
										78
									
								
								Elwig/Windows/SeasonFinishWindow.xaml.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								Elwig/Windows/SeasonFinishWindow.xaml.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| using Elwig.Documents; | ||||
| using Elwig.Helpers; | ||||
| using Elwig.Helpers.Billing; | ||||
| using Microsoft.EntityFrameworkCore; | ||||
| using System.Linq; | ||||
| using System.Threading.Tasks; | ||||
| using System.Windows; | ||||
| using System.Windows.Input; | ||||
|  | ||||
| namespace Elwig.Windows { | ||||
|     public partial class SeasonFinishWindow : ContextWindow { | ||||
|         public SeasonFinishWindow() { | ||||
|             InitializeComponent(); | ||||
|         } | ||||
|  | ||||
|         private void Window_Loaded(object sender, RoutedEventArgs evt) { | ||||
|             SeasonInput.Value = Utils.CurrentLastSeason; | ||||
|         } | ||||
|  | ||||
|         protected override async Task OnRenewContext() { | ||||
|  | ||||
|         } | ||||
|  | ||||
|         private async void SeasonInput_ValueChanged(object sender, RoutedEventArgs evt) { | ||||
|             var s = await Context.Seasons.FindAsync(SeasonInput.Value); | ||||
|             var valid = (s != null); | ||||
|             CalculateBinsButton.IsEnabled = valid; | ||||
|             DeliveryConfirmationButton.IsEnabled = valid; | ||||
|             OverUnderDeliveryButton.IsEnabled = valid; | ||||
|         } | ||||
|  | ||||
|         private async void CalculateBinsButton_Click(object sender, RoutedEventArgs evt) { | ||||
|             if (SeasonInput.Value is not int year) | ||||
|                 return; | ||||
|             Mouse.OverrideCursor = Cursors.AppStarting; | ||||
|             var b = new Billing(year); | ||||
|             await b.FinishSeason(); | ||||
|             await b.CalculateBins(); | ||||
|             Mouse.OverrideCursor = null; | ||||
|         } | ||||
|  | ||||
|         private async void DeliveryConfirmationButton_Click(object sender, RoutedEventArgs evt) { | ||||
|             if (SeasonInput.Value is not int year) | ||||
|                 return; | ||||
|             var res = MessageBox.Show( | ||||
|                 $"Sollen wirklich alle Bestätigungen gedruckt werden?", "Ausdruck Bestätigen", | ||||
|                 MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No); | ||||
|             if (res != MessageBoxResult.Yes) | ||||
|                 return; | ||||
|             Mouse.OverrideCursor = Cursors.AppStarting; | ||||
|             using var doc = await Document.Merge(Context.Members.FromSqlRaw($""" | ||||
|                 SELECT m.* | ||||
|                 FROM member m | ||||
|                     JOIN delivery d ON d.mgnr = m.mgnr | ||||
|                 WHERE m.active AND d.year = {year} | ||||
|                 GROUP BY m.mgnr | ||||
|                 ORDER BY m.mgnr | ||||
|                 """) | ||||
|                 .ToList() | ||||
|                 .Select(m => new DeliveryConfirmation(Context, year, m))); | ||||
|             await doc.Generate(); | ||||
|             Mouse.OverrideCursor = null; | ||||
|             if (App.Config.Debug) { | ||||
|                 doc.Show(); | ||||
|             } else { | ||||
|                 await doc.Print(); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         private void OverUnderDeliveryButton_Click(object sender, RoutedEventArgs evt) { | ||||
|         } | ||||
|  | ||||
|         private void PaymentButton_Click(object sender, RoutedEventArgs evt) { | ||||
|             var w = new ChartWindow(); | ||||
|             w.Show(); | ||||
|         } | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user