[#79] Entities: Remove EF proxies
This commit is contained in:
@@ -261,7 +261,7 @@ namespace Elwig.Documents {
|
||||
}
|
||||
|
||||
protected Table NewBucketTable(
|
||||
Season season, Dictionary<string, MemberBucket> buckets,
|
||||
Season season, Dictionary<string, MemberBucket> buckets, int deliveredWeight,
|
||||
bool includeDelivery = true, bool includePayment = false,
|
||||
bool isTiny = false, IEnumerable<string>? filter = null
|
||||
) {
|
||||
@@ -315,10 +315,8 @@ namespace Elwig.Documents {
|
||||
.OrderBy(b => b.Value.Name);
|
||||
|
||||
tbl.AddCell(NewBucketTh("Gesamtlieferung lt. gez. GA", isTiny: isTiny));
|
||||
tbl.AddCells(FormatRow(Member.BusinessShares * season.MinKgPerBusinessShare,
|
||||
Member.BusinessShares * season.MaxKgPerBusinessShare,
|
||||
season.Deliveries.Where(d => d.MgNr == Member.MgNr).Sum(d => d.Weight),
|
||||
isGa: true, showPayment: includePayment, showArea: !includeDelivery, isTiny: isTiny));
|
||||
tbl.AddCells(FormatRow(Member.BusinessShares * season.MinKgPerBusinessShare, Member.BusinessShares * season.MaxKgPerBusinessShare,
|
||||
deliveredWeight, isGa: true, showPayment: includePayment, showArea: !includeDelivery, isTiny: isTiny));
|
||||
|
||||
if (fbs.Any()) {
|
||||
tbl.AddCell(NewBucketSubHdr("Flächenbindungen" + (vtr.Any() ? " (inkl. Verträge)" : "") + ":", includePayment ? 8 : 7, isTiny: isTiny));
|
||||
|
||||
@@ -1,55 +1,82 @@
|
||||
using Elwig.Helpers;
|
||||
using Elwig.Helpers.Billing;
|
||||
using Elwig.Models.Dtos;
|
||||
using Elwig.Models.Entities;
|
||||
using iText.Kernel.Pdf;
|
||||
using iText.Layout.Borders;
|
||||
using iText.Layout.Element;
|
||||
using iText.Layout.Properties;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Elwig.Documents {
|
||||
public class CreditNote : BusinessDocument {
|
||||
|
||||
public new static string Name => "Traubengutschrift";
|
||||
|
||||
public PaymentMember? Payment;
|
||||
public PaymentMember Payment;
|
||||
public Credit? Credit;
|
||||
public CreditNoteDeliveryData Data;
|
||||
public string? Text;
|
||||
public string CurrencySymbol;
|
||||
public int Precision;
|
||||
public string MemberModifier;
|
||||
public string? MemberModifier;
|
||||
public List<(string Name, int Kg, decimal Amount)>? MemberUnderDeliveries;
|
||||
public decimal MemberTotalUnderDelivery;
|
||||
public int MemberAutoBusinessShares;
|
||||
public decimal MemberAutoBusinessSharesAmount;
|
||||
public PaymentCustom? CustomPayment;
|
||||
|
||||
public CreditNote(
|
||||
AppDbContext ctx,
|
||||
PaymentMember p,
|
||||
CreditNoteDeliveryData data,
|
||||
bool considerContractPenalties,
|
||||
bool considerTotalPenalty,
|
||||
bool considerAutoBusinessShares,
|
||||
bool considerCustomModifiers,
|
||||
Dictionary<string, UnderDelivery>? underDeliveries = null
|
||||
) :
|
||||
protected bool ConsiderContractPenalties;
|
||||
protected bool ConsiderTotalPenalty;
|
||||
protected bool ConsiderAutoBusinessShares;
|
||||
protected bool ConsiderCustomModifiers;
|
||||
|
||||
private CreditNoteDeliveryData? _data;
|
||||
private Dictionary<string, UnderDelivery>? _underDeliveries;
|
||||
|
||||
public CreditNote(PaymentMember p, BillingData? billingData = null, CreditNoteDeliveryData? data = null, Dictionary<string, UnderDelivery>? underDeliveries = null) :
|
||||
base($"{Name} {(p.Credit != null ? $"Nr. {p.Credit.Year}/{p.Credit.TgNr:000}" : p.Member.FullName)} – {p.Variant.Name}", p.Member) {
|
||||
UseBillingAddress = true;
|
||||
ShowDateAndLocation = true;
|
||||
Data = data;
|
||||
Payment = p;
|
||||
Credit = p.Credit;
|
||||
IsPreview = Payment == null || Credit == null;
|
||||
var season = p.Variant.Season;
|
||||
if (considerCustomModifiers) {
|
||||
CustomPayment = ctx.CustomPayments.Find(p.Year, p.MgNr);
|
||||
Text = App.Client.TextCreditNote;
|
||||
DocumentId = $"Tr.-Gutschr. " + (Credit != null ? $"{Credit.Year}/{Credit.TgNr:000}" : Payment.MgNr);
|
||||
IsPreview = Credit == null;
|
||||
_data = data;
|
||||
_underDeliveries = underDeliveries;
|
||||
CurrencySymbol = Payment.Variant.Season.Currency.Symbol ?? Payment.Variant.Season.Currency.Code;
|
||||
Precision = Payment.Variant.Season.Precision;
|
||||
|
||||
billingData ??= BillingData.FromJson(Payment.Variant.Data);
|
||||
ConsiderContractPenalties = billingData.ConsiderContractPenalties;
|
||||
ConsiderTotalPenalty = billingData.ConsiderTotalPenalty;
|
||||
ConsiderAutoBusinessShares = billingData.ConsiderAutoBusinessShares;
|
||||
ConsiderCustomModifiers = billingData.ConsiderCustomModifiers;
|
||||
}
|
||||
|
||||
public static async Task<CreditNote> Initialize(int year, int avnr, int mgnr, BillingData? billingData = null, CreditNoteDeliveryData? data = null, Dictionary<string, UnderDelivery>? underDeliveries = null) {
|
||||
using var ctx = new AppDbContext();
|
||||
var p = await ctx.MemberPayments
|
||||
.Where(p => p.Year == year && p.AvNr == avnr && p.MgNr == mgnr)
|
||||
.SingleAsync();
|
||||
return new CreditNote(p, billingData, data, underDeliveries);
|
||||
}
|
||||
|
||||
protected override async Task LoadData(AppDbContext ctx) {
|
||||
await base.LoadData(ctx);
|
||||
var season = Payment.Variant.Season;
|
||||
if (ConsiderCustomModifiers) {
|
||||
CustomPayment = await ctx.CustomPayments.FindAsync(Payment.Year, Payment.MgNr);
|
||||
}
|
||||
|
||||
var mod = App.Client.IsMatzen ? ctx.Modifiers.Where(m => m.Year == season.Year && m.Name.StartsWith("Treue")).FirstOrDefault() : null;
|
||||
_data ??= (await CreditNoteDeliveryData.ForPaymentVariant(ctx.CreditNoteDeliveryRows, ctx.PaymentVariants, Payment.Year, Payment.AvNr))[Member.MgNr];
|
||||
_underDeliveries ??= await ctx.GetMemberUnderDelivery(Payment.Year, Member.MgNr);
|
||||
|
||||
var mod = App.Client.IsMatzen ? await ctx.Modifiers.Where(m => m.Year == season.Year && m.Name.StartsWith("Treue")).FirstOrDefaultAsync() : null;
|
||||
if (CustomPayment?.ModComment != null) {
|
||||
MemberModifier = CustomPayment.ModComment;
|
||||
} else if (mod != null) {
|
||||
@@ -57,32 +84,28 @@ namespace Elwig.Documents {
|
||||
} else {
|
||||
MemberModifier = "Sonstige Zu-/Abschläge";
|
||||
}
|
||||
Text = App.Client.TextCreditNote;
|
||||
DocumentId = $"Tr.-Gutschr. " + (p.Credit != null ? $"{p.Credit.Year}/{p.Credit.TgNr:000}" : p.MgNr);
|
||||
CurrencySymbol = season.Currency.Symbol ?? season.Currency.Code;
|
||||
Precision = season.Precision;
|
||||
|
||||
if (considerTotalPenalty) {
|
||||
var total = data.Rows.SelectMany(r => r.Buckets).Sum(b => b.Value);
|
||||
var totalUnderDelivery = total - p.Member.BusinessShares * season.MinKgPerBusinessShare;
|
||||
if (ConsiderTotalPenalty) {
|
||||
var total = _data.Rows.SelectMany(r => r.Buckets).Sum(b => b.Value);
|
||||
var totalUnderDelivery = total - Member.BusinessShares * season.MinKgPerBusinessShare;
|
||||
MemberTotalUnderDelivery = totalUnderDelivery < 0 ? totalUnderDelivery * (season.PenaltyPerKg ?? 0) - (season.PenaltyAmount ?? 0) - (season.PenaltyPerBsAmount * Math.Floor(-(decimal)totalUnderDelivery / season.MinKgPerBusinessShare) ?? 0) : 0;
|
||||
if (total == 0)
|
||||
MemberTotalUnderDelivery -= (season.PenaltyNone ?? 0) + (season.PenaltyPerBsNone * p.Member.BusinessShares ?? 0);
|
||||
MemberTotalUnderDelivery -= (season.PenaltyNone ?? 0) + (season.PenaltyPerBsNone * Member.BusinessShares ?? 0);
|
||||
}
|
||||
if (considerAutoBusinessShares) {
|
||||
if (ConsiderAutoBusinessShares) {
|
||||
var fromDate = $"{season.Year}-01-01";
|
||||
var toDate = $"{season.Year}-12-31";
|
||||
MemberAutoBusinessShares = ctx.MemberHistory
|
||||
.Where(h => h.MgNr == p.Member.MgNr && h.Type == "auto")
|
||||
MemberAutoBusinessShares = await ctx.MemberHistory
|
||||
.Where(h => h.MgNr == Member.MgNr && h.Type == "auto")
|
||||
.Where(h => h.DateString.CompareTo(fromDate) >= 0 && h.DateString.CompareTo(toDate) <= 0)
|
||||
.Sum(h => h.BusinessShares);
|
||||
.SumAsync(h => h.BusinessShares);
|
||||
MemberAutoBusinessSharesAmount = MemberAutoBusinessShares * (-season.BusinessShareValue ?? 0);
|
||||
}
|
||||
if (considerContractPenalties) {
|
||||
var varieties = ctx.WineVarieties.ToDictionary(v => v.SortId, v => v);
|
||||
var attributes = ctx.WineAttributes.ToDictionary(a => a.AttrId, a => a);
|
||||
var comTypes = ctx.AreaCommitmentTypes.ToDictionary(t => t.VtrgId, t => t);
|
||||
MemberUnderDeliveries = underDeliveries?
|
||||
if (ConsiderContractPenalties) {
|
||||
var varieties = await ctx.WineVarieties.ToDictionaryAsync(v => v.SortId, v => v);
|
||||
var attributes = await ctx.WineAttributes.ToDictionaryAsync(a => a.AttrId, a => a);
|
||||
var comTypes = await ctx.AreaCommitmentTypes.ToDictionaryAsync(t => t.VtrgId, t => t);
|
||||
MemberUnderDeliveries = _underDeliveries?
|
||||
.OrderBy(u => u.Key)
|
||||
.Select(u => (
|
||||
varieties[u.Key[..2]].Name + (u.Key.Length > 2 ? " " + attributes[u.Key[2..]].Name : ""),
|
||||
@@ -104,8 +127,9 @@ namespace Elwig.Documents {
|
||||
}
|
||||
|
||||
protected override void RenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
||||
if (_data == null) throw new Exception("Call LoadData before RenderBody");
|
||||
base.RenderBody(doc, pdf);
|
||||
doc.Add(NewCreditTable(Data));
|
||||
doc.Add(NewCreditTable(_data));
|
||||
|
||||
var div = new Table(ColsMM(60, 105))
|
||||
.SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout()
|
||||
@@ -131,7 +155,7 @@ namespace Elwig.Documents {
|
||||
.SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE)
|
||||
.SetKeepTogether(true);
|
||||
|
||||
var sum = Data.Rows.Sum(p => p.Amount);
|
||||
var sum = _data.Rows.Sum(p => p.Amount);
|
||||
if (Payment == null) {
|
||||
tbl1.AddCells(FormatRow("Gesamt", sum, bold: true, noTopBorder: true));
|
||||
} else {
|
||||
@@ -139,7 +163,7 @@ namespace Elwig.Documents {
|
||||
if (Payment.NetAmount != Payment.Amount) {
|
||||
tbl1.AddCells(FormatRow("Zwischensumme", Payment.NetAmount, noTopBorder: noBorder));
|
||||
noBorder = false;
|
||||
tbl1.AddCells(FormatRow(MemberModifier, Payment.Amount - Payment.NetAmount, add: true));
|
||||
tbl1.AddCells(FormatRow(MemberModifier ?? "", Payment.Amount - Payment.NetAmount, add: true));
|
||||
}
|
||||
if (Credit == null) {
|
||||
tbl1.AddCells(FormatRow("Gesamtbetrag", Payment.Amount, bold: true, noTopBorder: noBorder));
|
||||
|
||||
@@ -5,33 +5,48 @@ using iText.Kernel.Pdf;
|
||||
using iText.Layout.Borders;
|
||||
using iText.Layout.Element;
|
||||
using iText.Layout.Properties;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Elwig.Documents {
|
||||
public class DeliveryConfirmation : BusinessDocument {
|
||||
|
||||
public new static string Name => "Anlieferungsbestätigung";
|
||||
|
||||
public Season Season;
|
||||
public DeliveryConfirmationDeliveryData Data;
|
||||
private readonly int _year;
|
||||
public Season? Season;
|
||||
public int MemberDeliveredWeight;
|
||||
public DeliveryConfirmationDeliveryData? Data;
|
||||
public string? Text = App.Client.TextDeliveryConfirmation;
|
||||
public Dictionary<string, MemberBucket> MemberBuckets;
|
||||
public List<MemberStat> MemberStats;
|
||||
public Dictionary<string, MemberBucket> MemberBuckets = [];
|
||||
public List<MemberStat> MemberStats = [];
|
||||
|
||||
public DeliveryConfirmation(AppDbContext ctx, int year, Member m, DeliveryConfirmationDeliveryData data) :
|
||||
public DeliveryConfirmation(int year, Member m, DeliveryConfirmationDeliveryData? data = null) :
|
||||
base($"{Name} {year}", m) {
|
||||
Season = ctx.Seasons.Find(year) ?? throw new ArgumentException("invalid season");
|
||||
_year = year;
|
||||
ShowDateAndLocation = true;
|
||||
UseBillingAddress = true;
|
||||
DocumentId = $"Anl.-Best. {Season.Year}/{m.MgNr}";
|
||||
DocumentId = $"Anl.-Best. {_year}/{m.MgNr}";
|
||||
Data = data;
|
||||
MemberBuckets = ctx.GetMemberBuckets(Season.Year, m.MgNr).GetAwaiter().GetResult();
|
||||
MemberStats = AppDbContext.GetMemberStats(Season.Year, m.MgNr).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
protected override async Task LoadData(AppDbContext ctx) {
|
||||
await base.LoadData(ctx);
|
||||
Season = ctx.Seasons.Find(_year) ?? throw new ArgumentException("invalid season");
|
||||
MemberDeliveredWeight = await ctx.Deliveries
|
||||
.Where(d => d.Year == Season.Year && d.MgNr == Member.MgNr)
|
||||
.SelectMany(d => d.Parts)
|
||||
.SumAsync(p => p.Weight);
|
||||
MemberBuckets = await ctx.GetMemberBuckets(Season.Year, Member.MgNr);
|
||||
MemberStats = await AppDbContext.GetMemberStats(Season.Year, Member.MgNr);
|
||||
Data ??= await DeliveryConfirmationDeliveryData.ForMember(ctx.DeliveryParts, Season.Year, Member);
|
||||
}
|
||||
|
||||
protected override void BeforeRenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
||||
if (Data == null) throw new Exception("Call LoadData before BeforeRenderBody");
|
||||
base.BeforeRenderBody(doc, pdf);
|
||||
var firstDay = Data.Rows.MinBy(r => r.Date)?.Date;
|
||||
var lastDay = Data.Rows.MaxBy(r => r.Date)?.Date;
|
||||
@@ -42,12 +57,13 @@ namespace Elwig.Documents {
|
||||
}
|
||||
|
||||
protected override void RenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
||||
if (Season == null || Data == null) throw new Exception("Call LoadData before RenderBody");
|
||||
base.RenderBody(doc, pdf);
|
||||
|
||||
doc.Add(NewDeliveryListTable(Data));
|
||||
doc.Add(NewWeightsTable(MemberStats)
|
||||
.SetMarginTopMM(10).SetKeepTogether(true));
|
||||
doc.Add(NewBucketTable(Season, MemberBuckets, includePayment: true)
|
||||
doc.Add(NewBucketTable(Season, MemberBuckets, MemberDeliveredWeight, includePayment: true)
|
||||
.SetMarginTopMM(10).SetKeepTogether(true));
|
||||
|
||||
if (Text != null) {
|
||||
|
||||
@@ -5,10 +5,12 @@ using iText.Layout.Borders;
|
||||
using iText.Layout.Element;
|
||||
using iText.Layout.Layout;
|
||||
using iText.Layout.Properties;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Elwig.Documents {
|
||||
public class DeliveryNote : BusinessDocument {
|
||||
@@ -17,7 +19,8 @@ namespace Elwig.Documents {
|
||||
|
||||
public Delivery Delivery;
|
||||
public string? Text;
|
||||
public Dictionary<string, MemberBucket> MemberBuckets;
|
||||
public int MemberDeliveredWeight;
|
||||
public Dictionary<string, MemberBucket> MemberBuckets = [];
|
||||
|
||||
// 0 - none
|
||||
// 1 - GA only
|
||||
@@ -25,7 +28,7 @@ namespace Elwig.Documents {
|
||||
// 3 - full
|
||||
public int DisplayStats = App.Client.ModeDeliveryNoteStats;
|
||||
|
||||
public DeliveryNote(Delivery d, AppDbContext? ctx = null) :
|
||||
public DeliveryNote(Delivery d) :
|
||||
base($"{Name} Nr. {d.LsNr}", d.Member) {
|
||||
UseBillingAddress = true;
|
||||
ShowDateAndLocation = true;
|
||||
@@ -34,7 +37,34 @@ namespace Elwig.Documents {
|
||||
DocumentId = d.LsNr;
|
||||
Date = DateOnly.FromDateTime(d.ModifiedAt);
|
||||
IsDoublePaged = true;
|
||||
MemberBuckets = ctx?.GetMemberBuckets(d.Year, d.Member.MgNr).GetAwaiter().GetResult() ?? [];
|
||||
}
|
||||
|
||||
public static async Task<DeliveryNote> Initialize(int year, int did) {
|
||||
using var ctx = new AppDbContext();
|
||||
await ctx.WineOrigins.LoadAsync();
|
||||
var d = await ctx.Deliveries
|
||||
.Where(d => d.Year == year && d.DId == did)
|
||||
.Include(d => d.Parts).ThenInclude(p => p.PartModifiers)
|
||||
.SingleAsync();
|
||||
return new DeliveryNote(d);
|
||||
}
|
||||
|
||||
public static async Task<DeliveryNote> Initialize(string lsnr) {
|
||||
using var ctx = new AppDbContext();
|
||||
await ctx.WineOrigins.LoadAsync();
|
||||
var d = await ctx.Deliveries
|
||||
.Where(d => d.LsNr == lsnr)
|
||||
.Include(d => d.Parts).ThenInclude(p => p.PartModifiers)
|
||||
.SingleAsync();
|
||||
return new DeliveryNote(d);
|
||||
}
|
||||
|
||||
protected override async Task LoadData(AppDbContext ctx) {
|
||||
await base.LoadData(ctx);
|
||||
MemberDeliveredWeight = await ctx.DeliveryParts
|
||||
.Where(d => d.Year == Delivery.Year && d.Delivery.MgNr == Member.MgNr)
|
||||
.SumAsync(p => p.Weight);
|
||||
MemberBuckets = await ctx.GetMemberBuckets(Delivery.Year, Member.MgNr) ?? [];
|
||||
}
|
||||
|
||||
protected override void BeforeRenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
||||
@@ -53,7 +83,7 @@ namespace Elwig.Documents {
|
||||
doc.Add(new KernedParagraph($"Anmerkung zur Lieferung: {Delivery.Comment}", 10).SetMarginsMM(5, 0, 0, 0));
|
||||
}
|
||||
if (DisplayStats > 0) {
|
||||
doc.Add(NewBucketTable(Delivery.Season, MemberBuckets, isTiny: true,
|
||||
doc.Add(NewBucketTable(Delivery.Season, MemberBuckets, MemberDeliveredWeight, isTiny: true,
|
||||
filter: DisplayStats > 2 ? null : DisplayStats == 1 ? [] : Delivery.Parts.Select(p => p.SortId).Distinct().ToList())
|
||||
.SetKeepTogether(true)
|
||||
.SetMarginsMM(5, 0, 0, 0));
|
||||
|
||||
@@ -128,6 +128,8 @@ namespace Elwig.Documents {
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual async Task LoadData(AppDbContext ctx) { }
|
||||
|
||||
protected virtual void BeforeRenderBody(iText.Layout.Document doc, PdfDocument pdf) { }
|
||||
|
||||
protected virtual void RenderBody(iText.Layout.Document doc, PdfDocument pdf) { }
|
||||
@@ -136,7 +138,7 @@ namespace Elwig.Documents {
|
||||
return new KernedParagraph(App.Client.NameFull, 10);
|
||||
}
|
||||
|
||||
public async Task Generate(CancellationToken? cancelToken = null, IProgress<double>? progress = null) {
|
||||
public async Task Generate(AppDbContext ctx, CancellationToken? cancelToken = null, IProgress<double>? progress = null) {
|
||||
if (_pdfFile != null)
|
||||
return;
|
||||
progress?.Report(0.0);
|
||||
@@ -181,6 +183,7 @@ namespace Elwig.Documents {
|
||||
merger.Merge(src, 1, src.GetNumberOfPages());
|
||||
p += src.GetNumberOfPages();
|
||||
} else {
|
||||
await doc.LoadData(ctx);
|
||||
int pageNum = doc.Render(tmpPdf.FilePath);
|
||||
if (IsDoublePaged && doc is Letterhead) {
|
||||
using var reader = new PdfReader(tmpPdf.FilePath);
|
||||
@@ -233,6 +236,7 @@ namespace Elwig.Documents {
|
||||
throw new OperationCanceledException("Dokumentenerzeugung abgebrochen!");
|
||||
var pdf = new TempFile("pdf");
|
||||
try {
|
||||
await LoadData(ctx);
|
||||
TotalPages = Render(pdf.FilePath);
|
||||
} catch {
|
||||
pdf.Dispose();
|
||||
|
||||
@@ -5,32 +5,55 @@ using iText.Kernel.Pdf;
|
||||
using iText.Layout.Borders;
|
||||
using iText.Layout.Element;
|
||||
using iText.Layout.Properties;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Elwig.Documents {
|
||||
public class MemberDataSheet : BusinessDocument {
|
||||
|
||||
public new static string Name => "Stammdatenblatt";
|
||||
|
||||
public Season Season;
|
||||
public Dictionary<string, MemberBucket> MemberBuckets;
|
||||
public List<AreaCom> ActiveAreaCommitments;
|
||||
public Season? Season;
|
||||
public int MemberDeliveredWeight;
|
||||
public Dictionary<string, MemberBucket> MemberBuckets = [];
|
||||
public List<AreaCom> ActiveAreaCommitments = [];
|
||||
|
||||
public MemberDataSheet(Member m, AppDbContext ctx) :
|
||||
public MemberDataSheet(Member m) :
|
||||
base($"{Name} {m.AdministrativeName}", m) {
|
||||
DocumentId = $"{Name} {m.MgNr}";
|
||||
Season = ctx.Seasons.ToList().MaxBy(s => s.Year) ?? throw new ArgumentException("invalid season");
|
||||
MemberBuckets = ctx.GetMemberBuckets(Utils.CurrentYear, m.MgNr).GetAwaiter().GetResult();
|
||||
ActiveAreaCommitments = [.. m.ActiveAreaCommitments(ctx)];
|
||||
}
|
||||
|
||||
public static async Task<MemberDataSheet> Initialize(int mgnr) {
|
||||
using var ctx = new AppDbContext();
|
||||
return new MemberDataSheet(await ctx.Members
|
||||
.Include(m => m.EmailAddresses)
|
||||
.Include(m => m.TelephoneNumbers)
|
||||
.Where(m => m.MgNr == mgnr)
|
||||
.SingleAsync());
|
||||
}
|
||||
|
||||
protected override async Task LoadData(AppDbContext ctx) {
|
||||
await base.LoadData(ctx);
|
||||
Season = await ctx.Seasons.OrderBy(s => s.Year).LastOrDefaultAsync() ?? throw new ArgumentException("invalid season");
|
||||
MemberBuckets = await ctx.GetMemberBuckets(Utils.CurrentYear, Member.MgNr);
|
||||
ActiveAreaCommitments = await Member.ActiveAreaCommitments(ctx)
|
||||
.Include(c => c.Contract).ThenInclude(c => c.Revisions)
|
||||
.ToListAsync();
|
||||
MemberDeliveredWeight = await ctx.Deliveries
|
||||
.Where(d => d.Year == Season.Year && d.MgNr == Member.MgNr)
|
||||
.SelectMany(d => d.Parts)
|
||||
.SumAsync(p => p.Weight);
|
||||
}
|
||||
|
||||
protected override void RenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
||||
if (Season == null) throw new Exception("Call LoadData before RenderBody");
|
||||
base.RenderBody(doc, pdf);
|
||||
doc.Add(NewMemberData().SetMarginBottomMM(5));
|
||||
doc.Add(NewBucketTable(Season, MemberBuckets, includeDelivery: false));
|
||||
doc.Add(NewMemberData(Season).SetMarginBottomMM(5));
|
||||
doc.Add(NewBucketTable(Season, MemberBuckets, MemberDeliveredWeight, includeDelivery: false));
|
||||
if (ActiveAreaCommitments.Count != 0) {
|
||||
bool firstOnPage = false;
|
||||
if (pdf.GetNumberOfPages() == 1) {
|
||||
@@ -38,7 +61,7 @@ namespace Elwig.Documents {
|
||||
firstOnPage = true;
|
||||
}
|
||||
doc.Add(new KernedParagraph(12).Add(Bold($"Flächenbindungen per {Date:dd.MM.yyyy}")).SetMargins(firstOnPage ? 0 : 24, 0, 12, 0));
|
||||
doc.Add(NewAreaComTable());
|
||||
doc.Add(NewAreaComTable(ActiveAreaCommitments));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +75,7 @@ namespace Elwig.Documents {
|
||||
.SetPaddingRightMM(0);
|
||||
}
|
||||
|
||||
protected Table NewMemberData() {
|
||||
protected Table NewMemberData(Season season) {
|
||||
var tbl = new Table(ColsMM(30.0, 51.5, 20.0, 12.0, 18.0, 31.5))
|
||||
.SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout()
|
||||
.SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE)
|
||||
@@ -117,7 +140,7 @@ namespace Elwig.Documents {
|
||||
.AddCell(NewDataTh("UID:", colspan: 2)).AddCell(NewTd(Member.UstIdNr, colspan: 2))
|
||||
.AddCell(NewDataTh("Stammgemeinde:")).AddCell(NewTd(Member.DefaultKg?.Name))
|
||||
.AddCell(NewDataTh("Buchführend:", colspan: 2)).AddCell(NewTd(new KernedParagraph(Member.IsBuchführend ? "Ja " : "Nein ", 10)
|
||||
.Add(Normal($"({(Member.IsBuchführend ? Season.VatNormal : Season.VatFlatrate) * 100:N0}% USt.)", 8)), colspan: 2))
|
||||
.Add(Normal($"({(Member.IsBuchführend ? season.VatNormal : season.VatFlatrate) * 100:N0}% USt.)", 8)), colspan: 2))
|
||||
.AddCell(NewDataTh("(Katastralgemeinde mit dem größten Anteil an Weinbauflächen)", 8, colspan: 2))
|
||||
.AddCell(NewDataTh("Bio:", colspan: 2)).AddCell(NewTd(Member.IsOrganic ? "Ja" : "Nein", colspan: 2))
|
||||
.AddCell(NewDataHdr("Genossenschaft", colspan: 6))
|
||||
@@ -134,8 +157,8 @@ namespace Elwig.Documents {
|
||||
return tbl;
|
||||
}
|
||||
|
||||
protected Table NewAreaComTable() {
|
||||
var areaComs = ActiveAreaCommitments.GroupBy(a => a.AreaComType).Select(group => new {
|
||||
protected Table NewAreaComTable(IEnumerable<AreaCom> activeAreaComs) {
|
||||
var areaComs = activeAreaComs.GroupBy(a => a.AreaComType).Select(group => new {
|
||||
Type = group.Key,
|
||||
AreaComs = group.OrderBy(c => c.Contract.Kg.AtKg.Name).ToList(),
|
||||
Size = group.Sum(c => c.Area)
|
||||
@@ -177,7 +200,7 @@ namespace Elwig.Documents {
|
||||
}
|
||||
|
||||
tbl.AddCell(NewTd("Gesamt:", 12, colspan: 2, bold: true, borderTop: true).SetPaddingsMM(1, 1, 1, 1));
|
||||
tbl.AddCell(NewTd($"{ActiveAreaCommitments.Sum(a => a.Area):N0}", 12, colspan: 2, right: true, bold: true, borderTop: true).SetPaddingsMM(1, 1, 1, 1));
|
||||
tbl.AddCell(NewTd($"{activeAreaComs.Sum(a => a.Area):N0}", 12, colspan: 2, right: true, bold: true, borderTop: true).SetPaddingsMM(1, 1, 1, 1));
|
||||
tbl.AddCell(NewTd(colspan: 2, borderTop: true).SetPaddingsMM(1, 1, 1, 1));
|
||||
|
||||
return tbl;
|
||||
|
||||
@@ -7,40 +7,60 @@ using iText.Kernel.Pdf;
|
||||
using iText.Layout.Borders;
|
||||
using iText.Layout.Element;
|
||||
using iText.Layout.Properties;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Elwig.Documents {
|
||||
public class PaymentVariantSummary : Document {
|
||||
|
||||
public new static string Name => "Auszahlungsvariante";
|
||||
|
||||
public PaymentVariantSummaryData Data;
|
||||
public PaymentVariantSummaryData? Data;
|
||||
public PaymentVar Variant;
|
||||
public BillingData BillingData;
|
||||
public string CurrencySymbol;
|
||||
public int MemberNum;
|
||||
public int DeliveryNum;
|
||||
public int DeliveryPartNum;
|
||||
public List<ModifierStat> ModifierStat;
|
||||
public Dictionary<string, Modifier> Modifiers;
|
||||
public List<ModifierStat>? ModifierStat;
|
||||
public Dictionary<string, Modifier>? Modifiers;
|
||||
|
||||
public PaymentVariantSummary(PaymentVar v, PaymentVariantSummaryData data) :
|
||||
private List<Credit> _credits = [];
|
||||
private List<PaymentDeliveryPart> _parts = [];
|
||||
|
||||
public PaymentVariantSummary(PaymentVar v, PaymentVariantSummaryData? data = null) :
|
||||
base($"{Name} {v.Year} - {v.Name}") {
|
||||
Variant = v;
|
||||
BillingData = BillingData.FromJson(v.Data);
|
||||
Data = data;
|
||||
CurrencySymbol = v.Season.Currency.Symbol ?? v.Season.Currency.Code;
|
||||
MemberNum = v.Credits.Count;
|
||||
}
|
||||
|
||||
public static async Task<PaymentVariantSummary> Initialize(int year, int avnr, PaymentVariantSummaryData? data = null) {
|
||||
using var ctx = new AppDbContext();
|
||||
var v = await ctx.PaymentVariants
|
||||
.Where(v => v.Year == year && v.AvNr == avnr)
|
||||
.SingleAsync();
|
||||
return new PaymentVariantSummary(v, data);
|
||||
}
|
||||
|
||||
protected override async Task LoadData(AppDbContext ctx) {
|
||||
_credits = await ctx.Credits.Where(c => c.Year == Variant.Year && c.AvNr == Variant.AvNr).ToListAsync();
|
||||
_parts = await ctx.PaymentDeliveryParts.Where(p => p.Year == Variant.Year && p.AvNr == Variant.AvNr).ToListAsync();
|
||||
MemberNum = _credits.Count;
|
||||
IsPreview = MemberNum == 0;
|
||||
DeliveryNum = v.DeliveryPartPayments.DistinctBy(p => p.DeliveryPart.Delivery).Count();
|
||||
DeliveryPartNum = v.DeliveryPartPayments.Count;
|
||||
ModifierStat = AppDbContext.GetModifierStats(v.Year, v.AvNr).GetAwaiter().GetResult();
|
||||
Modifiers = v.Season.Modifiers.ToDictionary(m => m.ModId);
|
||||
DeliveryNum = await ctx.Deliveries.Where(d => d.Year == Variant.Year).CountAsync();
|
||||
DeliveryPartNum = await ctx.DeliveryParts.Where(d => d.Year == Variant.Year).CountAsync();
|
||||
Data ??= await PaymentVariantSummaryData.ForPaymentVariant(Variant, ctx.PaymentVariantSummaryRows);
|
||||
ModifierStat = await AppDbContext.GetModifierStats(Variant.Year, Variant.AvNr);
|
||||
Modifiers = await ctx.Modifiers.Where(m => m.Year == Variant.Year).ToDictionaryAsync(m => m.ModId);
|
||||
}
|
||||
|
||||
protected override void RenderBody(iText.Layout.Document doc, PdfDocument pdf) {
|
||||
if (Data == null || Modifiers == null || ModifierStat == null) throw new Exception("Call LoadData before RenderBody");
|
||||
base.RenderBody(doc, pdf);
|
||||
doc.Add(new KernedParagraph($"{Name} Lese {Variant.Year}", 24)
|
||||
.SetTextAlignment(TextAlignment.CENTER).SetFont(BF)
|
||||
@@ -48,10 +68,10 @@ namespace Elwig.Documents {
|
||||
doc.Add(new KernedParagraph(Variant.Name, 14)
|
||||
.SetTextAlignment(TextAlignment.CENTER).SetFont(BF)
|
||||
.SetMarginsMM(0, 0, 10, 0));
|
||||
doc.Add(NewVariantStatTable().SetMarginBottomMM(10));
|
||||
doc.Add(NewModifierStatTable());
|
||||
doc.Add(NewVariantStatTable(Data).SetMarginBottomMM(10));
|
||||
doc.Add(NewModifierStatTable(Modifiers, ModifierStat));
|
||||
doc.Add(new AreaBreak(AreaBreakType.NEXT_PAGE));
|
||||
doc.Add(NewPriceTable());
|
||||
doc.Add(NewPriceTable(Data));
|
||||
}
|
||||
|
||||
protected Cell NewSectionHdr(string text, int colspan = 1, bool borderLeft = false) {
|
||||
@@ -67,33 +87,33 @@ namespace Elwig.Documents {
|
||||
.SetBorderLeft(borderLeft ? new SolidBorder(BorderThickness) : Border.NO_BORDER);
|
||||
}
|
||||
|
||||
protected Table NewVariantStatTable() {
|
||||
protected Table NewVariantStatTable(PaymentVariantSummaryData data) {
|
||||
var tbl = new Table(ColsMM(20, 30, 4.5, 4.5, 23.5, 47.5, 15, 20))
|
||||
.SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout()
|
||||
.SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE)
|
||||
.SetBorder(new SolidBorder(BorderThickness));
|
||||
|
||||
//var sum1 = Variant.DeliveryPartPayments.Sum(p => p.NetAmount);
|
||||
//var sum2 = Variant.Credits.Sum(p => p.); //Variant.MemberPayments.Sum(p => p.Amount);
|
||||
var deliveryModifiers = Variant.DeliveryPartPayments.Sum(p => p.Amount - p.NetAmount);
|
||||
var memberModifiers = Variant.Credits.Sum(c => c.Payment.Amount - c.Payment.NetAmount);
|
||||
var sum2 = Variant.Credits.Sum(p => p.NetAmount);
|
||||
//var sum1 = _parts.Sum(p => p.NetAmount);
|
||||
//var sum2 = _credits.Sum(p => p.); //Variant.MemberPayments.Sum(p => p.Amount);
|
||||
var deliveryModifiers = _parts.Sum(p => p.Amount - p.NetAmount);
|
||||
var memberModifiers = _credits.Sum(c => c.Payment.Amount - c.Payment.NetAmount);
|
||||
var sum2 = _credits.Sum(p => p.NetAmount);
|
||||
var sum1 = sum2 - deliveryModifiers - memberModifiers;
|
||||
var payed = -Variant.Credits.Sum(p => p.PrevNetAmount ?? 0m);
|
||||
var netSum = Variant.Credits.Sum(p => p.NetAmount) - Variant.Credits.Sum(p => p.PrevNetAmount ?? 0m);
|
||||
var vat = Variant.Credits.Sum(p => p.VatAmount);
|
||||
var grossSum = Variant.Credits.Sum(p => p.GrossAmount);
|
||||
var totalMods = Variant.Credits.Sum(p => p.Modifiers ?? 0m);
|
||||
var considered = -Variant.Credits.Sum(p => p.PrevModifiers ?? 0m);
|
||||
var totalSum = Variant.Credits.Sum(p => p.Amount);
|
||||
var payed = -_credits.Sum(p => p.PrevNetAmount ?? 0m);
|
||||
var netSum = _credits.Sum(p => p.NetAmount) - _credits.Sum(p => p.PrevNetAmount ?? 0m);
|
||||
var vat = _credits.Sum(p => p.VatAmount);
|
||||
var grossSum = _credits.Sum(p => p.GrossAmount);
|
||||
var totalMods = _credits.Sum(p => p.Modifiers ?? 0m);
|
||||
var considered = -_credits.Sum(p => p.PrevModifiers ?? 0m);
|
||||
var totalSum = _credits.Sum(p => p.Amount);
|
||||
|
||||
var weiRows = Data.Rows.Where(r => r.QualityLevel == "Wein");
|
||||
var weiRows = data.Rows.Where(r => r.QualityLevel == "Wein");
|
||||
var minWei = weiRows.Min(r => r.Ungeb.MinPrice);
|
||||
var maxWei = weiRows.Max(r => r.Ungeb.MaxPrice);
|
||||
var quwRows = Data.Rows.Where(r => r.QualityLevel != "Wein");
|
||||
var quwRows = data.Rows.Where(r => r.QualityLevel != "Wein");
|
||||
var minPrice = quwRows.Min(r => r.Ungeb.MinPrice);
|
||||
var maxPrice = quwRows.Max(r => r.Ungeb.MaxPrice);
|
||||
var gebRows = Data.Rows
|
||||
var gebRows = data.Rows
|
||||
.Where(r => r.Geb.MaxPrice != null && r.Ungeb.MinPrice != null)
|
||||
.Select(r => r.Geb.MaxPrice - r.Ungeb.MinPrice);
|
||||
var minGeb = gebRows.Min();
|
||||
@@ -191,26 +211,26 @@ namespace Elwig.Documents {
|
||||
.AddCell(NewTd(CurrencySymbol))
|
||||
.AddCell(NewTd($"{Math.Abs(totalMods):N2}", right: true))
|
||||
.AddCell(NewSectionTh("Menge (ungebunden):", borderLeft: true, borderTop: true))
|
||||
.AddCell(NewTd($"{Data.Rows.Sum(r => r.Ungeb.Weight):N0} kg", colspan: 2, right: true, borderTop: true))
|
||||
.AddCell(NewTd($"{data.Rows.Sum(r => r.Ungeb.Weight):N0} kg", colspan: 2, right: true, borderTop: true))
|
||||
|
||||
.AddCell(NewSectionTh("Bereits berücksichtigte Abzüge:", colspan: 2))
|
||||
.AddCell(NewTd(Utils.GetSign(considered)))
|
||||
.AddCell(NewTd(CurrencySymbol))
|
||||
.AddCell(NewTd($"{Math.Abs(considered):N2}", right: true))
|
||||
.AddCell(NewSectionTh("Menge (gebunden):", borderLeft: true))
|
||||
.AddCell(NewTd($"{Data.Rows.Sum(r => r.Geb.Weight + r.LowGeb.Weight):N0} kg", colspan: 2, right: true))
|
||||
.AddCell(NewTd($"{data.Rows.Sum(r => r.Geb.Weight + r.LowGeb.Weight):N0} kg", colspan: 2, right: true))
|
||||
|
||||
.AddCell(NewSectionTh("Auszahlungsbetrag:", colspan: 2))
|
||||
.AddCell(NewTd(borderTop: true))
|
||||
.AddCell(NewTd(CurrencySymbol, borderTop: true))
|
||||
.AddCell(NewTd($"{totalSum:N2}", right: true, borderTop: true))
|
||||
.AddCell(NewSectionTh("Gesamtmenge:", borderLeft: true))
|
||||
.AddCell(NewTd($"{Data.Rows.Sum(r => r.Ungeb.Weight + r.LowGeb.Weight + r.Geb.Weight):N0} kg", colspan: 2, right: true, borderTop: true));
|
||||
.AddCell(NewTd($"{data.Rows.Sum(r => r.Ungeb.Weight + r.LowGeb.Weight + r.Geb.Weight):N0} kg", colspan: 2, right: true, borderTop: true));
|
||||
|
||||
return tbl;
|
||||
}
|
||||
|
||||
protected Table NewModifierStatTable() {
|
||||
protected Table NewModifierStatTable(Dictionary<string, Modifier> modifiers, IEnumerable<ModifierStat> modStat) {
|
||||
var tbl = new Table(ColsMM(35, 30, 25, 25, 25, 25))
|
||||
.SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout()
|
||||
.SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE)
|
||||
@@ -228,8 +248,8 @@ namespace Elwig.Documents {
|
||||
.AddCell(NewTh($"[{CurrencySymbol}]"))
|
||||
.AddCell(NewTh($"[{CurrencySymbol}]"));
|
||||
|
||||
foreach (var m in ModifierStat) {
|
||||
var mod = Modifiers[m.ModId];
|
||||
foreach (var m in modStat) {
|
||||
var mod = modifiers[m.ModId];
|
||||
tbl.AddCell(NewTd(mod.Name, italic: true))
|
||||
.AddCell(NewTd(mod.ValueStr, right: true))
|
||||
.AddCell(NewTd($"{m.Count:N0}", right: true))
|
||||
@@ -241,7 +261,7 @@ namespace Elwig.Documents {
|
||||
return tbl;
|
||||
}
|
||||
|
||||
protected Table NewPriceTable() {
|
||||
protected Table NewPriceTable(PaymentVariantSummaryData data) {
|
||||
var tbl = new Table(ColsMM(25, 19, 18, 15, 18, 15, 18, 15, 22))
|
||||
.SetWidth(UnitValue.CreatePercentValue(100)).SetFixedLayout()
|
||||
.SetBorderCollapse(BorderCollapsePropertyValue.COLLAPSE);
|
||||
@@ -262,10 +282,10 @@ namespace Elwig.Documents {
|
||||
.AddHeaderCell(NewTh($"[{CurrencySymbol}]"));
|
||||
|
||||
string? lastHdr = null;
|
||||
foreach (var row in Data.Rows) {
|
||||
foreach (var row in data.Rows) {
|
||||
var hdr = $"{row.Variety}{(row.Attribute != null ? " / " : "")}{row.Attribute}{(row.Cultivation != null ? " / " : "")}{row.Cultivation}";
|
||||
if (lastHdr != hdr) {
|
||||
var rows = Data.Rows
|
||||
var rows = data.Rows
|
||||
.Where(r => r.Variety == row.Variety && r.Attribute == row.Attribute && r.Cultivation == row.Cultivation)
|
||||
.ToList();
|
||||
var border = lastHdr != null;
|
||||
|
||||
Reference in New Issue
Block a user