Compare commits
10 Commits
ff3bd5cea5
...
v0.6.4
| Author | SHA1 | Date | |
|---|---|---|---|
| b063b201e3 | |||
| 60b624b009 | |||
| 71a234ca60 | |||
| 38abfb0edd | |||
| 05a037db70 | |||
| b9287f8260 | |||
| 50ac757067 | |||
| c6cd9d7c73 | |||
| 1b28752f4c | |||
| e0bdbee2ae |
@@ -20,7 +20,15 @@ namespace Elwig.Documents {
|
||||
public decimal MemberTotalUnderDelivery;
|
||||
public decimal MemberAutoBusinessShares;
|
||||
|
||||
public CreditNote(AppDbContext ctx, PaymentMember p, CreditNoteDeliveryData data, Dictionary<string, UnderDelivery>? underDeliveries = null) :
|
||||
public CreditNote(
|
||||
AppDbContext ctx,
|
||||
PaymentMember p,
|
||||
CreditNoteDeliveryData data,
|
||||
bool considerContractPenalties,
|
||||
bool considerTotalPenalty,
|
||||
bool considerAutoBusinessShares,
|
||||
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) {
|
||||
UseBillingAddress = true;
|
||||
ShowDateAndLocation = true;
|
||||
@@ -34,16 +42,6 @@ namespace Elwig.Documents {
|
||||
} else {
|
||||
MemberModifier = "Sonstige Zu-/Abschläge";
|
||||
}
|
||||
var total = data.Rows.SelectMany(r => r.Buckets).Sum(b => b.Value);
|
||||
var totalUnderDelivery = total - p.Member.BusinessShares * season.MinKgPerBusinessShare;
|
||||
MemberTotalUnderDelivery = totalUnderDelivery < 0 ? totalUnderDelivery * (season.PenaltyPerKg ?? 0) - (season.PenaltyAmount ?? 0) : 0;
|
||||
var fromDate = $"{season.Year}-06-01";
|
||||
var toDate = $"{season.Year + 1}-06-01";
|
||||
MemberAutoBusinessShares = ctx.MemberHistory
|
||||
.Where(h => h.MgNr == p.Member.MgNr && h.Type == "auto")
|
||||
.Where(h => h.DateString.CompareTo(fromDate) >= 0 && h.DateString.CompareTo(toDate) < 0)
|
||||
.Sum(h => h.BusinessShares) * (-season.BusinessShareValue ?? 0);
|
||||
if (total == 0) MemberTotalUnderDelivery -= (season.PenaltyNone ?? 0);
|
||||
Aside = Aside.Replace("</table>", "") +
|
||||
$"<thead><tr><th colspan='2'>Gutschrift</th></tr></thead><tbody>" +
|
||||
$"<tr><th>TG-Nr.</th><td>{(p.Credit != null ? $"{p.Credit.Year}/{p.Credit.TgNr:000}" : "-")}</td></tr>" +
|
||||
@@ -55,18 +53,35 @@ namespace Elwig.Documents {
|
||||
CurrencySymbol = season.Currency.Symbol ?? season.Currency.Code;
|
||||
Precision = season.Precision;
|
||||
|
||||
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?
|
||||
.OrderBy(u => u.Key)
|
||||
.Select(u => (
|
||||
varieties[u.Key[..2]].Name + (u.Key.Length > 2 ? " " + attributes[u.Key[2..]].Name : ""),
|
||||
u.Value.Diff,
|
||||
u.Value.Diff * (comTypes[u.Key].PenaltyPerKg ?? 0)
|
||||
- (comTypes[u.Key].PenaltyAmount ?? 0)
|
||||
- ((u.Value.Weight == 0 ? comTypes[u.Key].PenaltyNone : null) ?? 0)))
|
||||
.Where(u => u.Item3 != 0)
|
||||
.ToList();
|
||||
if (considerTotalPenalty) {
|
||||
var total = data.Rows.SelectMany(r => r.Buckets).Sum(b => b.Value);
|
||||
var totalUnderDelivery = total - p.Member.BusinessShares * season.MinKgPerBusinessShare;
|
||||
MemberTotalUnderDelivery = totalUnderDelivery < 0 ? totalUnderDelivery * (season.PenaltyPerKg ?? 0) - (season.PenaltyAmount ?? 0) : 0;
|
||||
if (total == 0)
|
||||
MemberTotalUnderDelivery -= (season.PenaltyNone ?? 0);
|
||||
}
|
||||
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")
|
||||
.Where(h => h.DateString.CompareTo(fromDate) >= 0 && h.DateString.CompareTo(toDate) <= 0)
|
||||
.Sum(h => h.BusinessShares) * (-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?
|
||||
.OrderBy(u => u.Key)
|
||||
.Select(u => (
|
||||
varieties[u.Key[..2]].Name + (u.Key.Length > 2 ? " " + attributes[u.Key[2..]].Name : ""),
|
||||
u.Value.Diff,
|
||||
u.Value.Diff * (comTypes[u.Key].PenaltyPerKg ?? 0)
|
||||
- (comTypes[u.Key].PenaltyAmount ?? 0)
|
||||
- ((u.Value.Weight == 0 ? comTypes[u.Key].PenaltyNone : null) ?? 0)))
|
||||
.Where(u => u.Item3 != 0)
|
||||
.ToList();
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
@@ -81,15 +81,20 @@
|
||||
</table>
|
||||
<div class="hint">
|
||||
Hinweis:<br/>
|
||||
Die Summe der Lieferungen und die Summe der anfallenden Pönalen werden mit
|
||||
@Model.Payment?.Variant.Season.Precision Nachkommastellen berechnent,
|
||||
erst das Ergebnis wird kaufmännisch auf 2 Nachkommastellen gerundet.
|
||||
Die Summe der Lieferungen und die Summe der anfal­lenden Pönalen werden mit
|
||||
@Model.Payment?.Variant.Season.Precision Nach­komma­stellen berechnent,
|
||||
erst das Ergebnis wird kauf­männisch auf 2 Nach­komma­stellen gerundet.
|
||||
</div>
|
||||
<table class="credit-sum">
|
||||
<colgroup>
|
||||
<col style="width: auto;"/>
|
||||
<col style="width: 5mm;"/>
|
||||
<col style="width: 30mm;"/>
|
||||
</colgroup>
|
||||
@{
|
||||
string FormatRow(string name, decimal? value, bool add = false, bool bold = false, bool subCat = false, bool noTopBorder = false) {
|
||||
return $"<tr class=\"{(!add && !noTopBorder ? "sum" : !add ? "large" : "")} {(bold ? "large bold" : "")}\">"
|
||||
+ $"<td class=\"{(subCat ? "small" : "")}\" style=\"overflow: visible;\">{name}:</td>"
|
||||
+ $"<td class=\"{(subCat ? "small" : "")}\">{name}:</td>"
|
||||
+ $"<td class=\"number {(subCat ? "small" : "large")}\">{(value < 0 ? "–" : (add ? "+" : ""))}</td>"
|
||||
+ $"<td class=\"number {(subCat ? "small" : "large")}\">"
|
||||
+ $"<span class=\"fleft\">{Model.CurrencySymbol}</span>{Math.Abs(value ?? 0):N2}</td>"
|
||||
@@ -148,8 +153,9 @@
|
||||
@if (Model.Credit == null) {
|
||||
@Raw(FormatRow("Auszahlungsbetrag", (Model.Payment?.Amount + penalty) ?? (sum + penalty), bold: true))
|
||||
} else {
|
||||
if (Model.Credit.Modifiers - penalty != 0) {
|
||||
@Raw(FormatRow("Weitere Abzüge", Model.Credit.Modifiers - penalty, add: true))
|
||||
var diff = Model.Credit.Modifiers - penalty;
|
||||
if (diff != 0) {
|
||||
@Raw(FormatRow(diff < 0 ? "Weitere Abzüge" : "Weitere Zuschläge", diff, add: true))
|
||||
}
|
||||
if (Model.Credit.PrevModifiers != null && Model.Credit.PrevModifiers != 0) {
|
||||
@Raw(FormatRow("Bereits berücksichtigte Abzüge", -Model.Credit.PrevModifiers, add: true))
|
||||
|
||||
@@ -24,8 +24,8 @@ table.credit tr.last td {
|
||||
}
|
||||
|
||||
table.credit-sum {
|
||||
width: 50%;
|
||||
margin-left: 50%;
|
||||
width: 60%;
|
||||
margin-left: 40%;
|
||||
}
|
||||
|
||||
table.credit-sum tr.sum,
|
||||
@@ -41,7 +41,7 @@ table.credit-sum td.sum {
|
||||
.hint {
|
||||
font-style: italic;
|
||||
font-size: 8pt;
|
||||
width: 74mm;
|
||||
width: 56mm;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
margin: 2mm 4mm;
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@
|
||||
<UseWPF>true</UseWPF>
|
||||
<PreserveCompilationContext>true</PreserveCompilationContext>
|
||||
<ApplicationIcon>Resources\Images\Elwig.ico</ApplicationIcon>
|
||||
<Version>0.6.1</Version>
|
||||
<Version>0.6.4</Version>
|
||||
<SatelliteResourceLanguages>de-AT</SatelliteResourceLanguages>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ namespace Elwig.Helpers {
|
||||
public DbSet<OverUnderDeliveryRow> OverUnderDeliveryRows { get; private set; }
|
||||
public DbSet<AreaComUnderDeliveryRowSingle> AreaComUnderDeliveryRows { get; private set; }
|
||||
public DbSet<MemberDeliveryPerVariantRowSingle> MemberDeliveryPerVariantRows { get; private set; }
|
||||
public DbSet<CreditNoteDeliveryRowSingle> CreditNoteDeliveryRows { get; private set; }
|
||||
public DbSet<CreditNoteRowSingle> CreditNoteRows { get; private set; }
|
||||
|
||||
private readonly StreamWriter? LogFile = null;
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Elwig.Helpers {
|
||||
public static class AppDbUpdater {
|
||||
|
||||
// Don't forget to update value in Tests/fetch-resources.bat!
|
||||
public static readonly int RequiredSchemaVersion = 13;
|
||||
public static readonly int RequiredSchemaVersion = 15;
|
||||
|
||||
private static int VersionOffset = 0;
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using Elwig.Models.Entities;
|
||||
using Microsoft.Data.Sqlite;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -8,6 +10,7 @@ namespace Elwig.Helpers.Billing {
|
||||
|
||||
protected readonly int Year;
|
||||
protected readonly AppDbContext Context;
|
||||
protected readonly Season Season;
|
||||
protected readonly Dictionary<string, string> Attributes;
|
||||
protected readonly Dictionary<string, (decimal?, decimal?)> Modifiers;
|
||||
protected readonly Dictionary<string, (string, string?, string?, int?, decimal?)> AreaComTypes;
|
||||
@@ -15,6 +18,7 @@ namespace Elwig.Helpers.Billing {
|
||||
public Billing(int year) {
|
||||
Year = year;
|
||||
Context = new AppDbContext();
|
||||
Season = Context.Seasons.Find(Year)!;
|
||||
Attributes = Context.WineAttributes.ToDictionary(a => a.AttrId, a => a.Name);
|
||||
Modifiers = Context.Modifiers.Where(m => m.Year == Year).ToDictionary(m => m.ModId, m => (m.Abs, m.Rel));
|
||||
AreaComTypes = Context.AreaCommitmentTypes.ToDictionary(v => v.VtrgId, v => (v.SortId, v.AttrId, v.Discriminator, v.MinKgPerHa, v.PenaltyAmount));
|
||||
@@ -26,8 +30,6 @@ namespace Elwig.Helpers.Billing {
|
||||
UPDATE season
|
||||
SET (start_date, end_date) = (SELECT MIN(date), MAX(date) FROM delivery WHERE year = {Year})
|
||||
WHERE year = {Year};
|
||||
|
||||
DELETE FROM delivery_part_bucket WHERE year = {Year};
|
||||
""");
|
||||
}
|
||||
|
||||
@@ -43,10 +45,11 @@ namespace Elwig.Helpers.Billing {
|
||||
""");
|
||||
}
|
||||
|
||||
public async Task CalculateBuckets(bool allowAttrsIntoLower, bool avoidUnderDeliveries, bool honorGebunden) {
|
||||
public async Task CalculateBuckets(bool allowAttrsIntoLower, bool avoidUnderDeliveries, bool honorGebunden, SqliteConnection? cnx = null) {
|
||||
var attrVals = Context.WineAttributes.ToDictionary(a => a.AttrId, a => (a.IsStrict, a.FillLower));
|
||||
var attrForced = attrVals.Where(a => a.Value.IsStrict && a.Value.FillLower == 0).Select(a => a.Key).ToArray();
|
||||
using var cnx = await AppDbContext.ConnectAsync();
|
||||
var ownCnx = cnx == null;
|
||||
cnx ??= await AppDbContext.ConnectAsync();
|
||||
await Context.GetMemberAreaCommitmentBuckets(Year, 0, cnx);
|
||||
var inserts = new List<(int, int, int, string, int)>();
|
||||
|
||||
@@ -65,7 +68,7 @@ namespace Elwig.Helpers.Billing {
|
||||
reader.GetInt32(0), reader.GetInt32(1), reader.GetInt32(2), reader.GetString(3), reader.GetInt32(4),
|
||||
reader.GetDouble(5), reader.GetString(6),
|
||||
reader.IsDBNull(7) ? null : reader.GetString(7),
|
||||
reader.IsDBNull(8) ? Array.Empty<string>() : reader.GetString(8).Split(",").Order().ToArray(),
|
||||
reader.IsDBNull(8) ? [] : reader.GetString(8).Split(",").Order().ToArray(),
|
||||
reader.IsDBNull(9) ? null : reader.GetBoolean(9)
|
||||
));
|
||||
}
|
||||
@@ -73,11 +76,11 @@ namespace Elwig.Helpers.Billing {
|
||||
|
||||
int lastMgNr = 0;
|
||||
Dictionary<string, AreaComBucket>? rightsAndObligations = null;
|
||||
Dictionary<string, int> used = new();
|
||||
Dictionary<string, int> used = [];
|
||||
foreach (var (mgnr, did, dpnr, sortid, weight, kmw, qualid, attrid, modifiers, gebunden) in deliveries) {
|
||||
if (lastMgNr != mgnr) {
|
||||
rightsAndObligations = await Context.GetMemberAreaCommitmentBuckets(Year, mgnr);
|
||||
used = new();
|
||||
used = [];
|
||||
}
|
||||
if ((honorGebunden && gebunden == false) ||
|
||||
rightsAndObligations == null || rightsAndObligations.Count == 0 ||
|
||||
@@ -92,16 +95,16 @@ namespace Elwig.Helpers.Billing {
|
||||
}
|
||||
|
||||
int w = weight;
|
||||
var attributes = attrid == null ? Array.Empty<string>() : new string[] { attrid };
|
||||
var attributes = attrid == null ? [] : new string[] { attrid };
|
||||
var isStrict = attrid != null && attrVals[attrid].IsStrict;
|
||||
foreach (var p in Utils.Permutate(attributes, attributes.Intersect(attrForced))) {
|
||||
var c = p.Count();
|
||||
var key = sortid + string.Join("", p);
|
||||
if (rightsAndObligations.ContainsKey(key)) {
|
||||
if (rightsAndObligations.TryGetValue(key, out AreaComBucket value)) {
|
||||
int i = (c == 0) ? 1 : 2;
|
||||
var u = used.GetValueOrDefault(key, 0);
|
||||
var vr = Math.Max(0, Math.Min(rightsAndObligations[key].Right - u, w));
|
||||
var vo = Math.Max(0, Math.Min(rightsAndObligations[key].Obligation - u, w));
|
||||
var vr = Math.Max(0, Math.Min(value.Right - u, w));
|
||||
var vo = Math.Max(0, Math.Min(value.Obligation - u, w));
|
||||
var v = (attributes.Length == c || attributes.Select(a => !attrVals[a].IsStrict ? 2 : attrVals[a].FillLower).Min() == 2) ? vr : vo;
|
||||
used[key] = u + v;
|
||||
if (key.Length > 2 && !isStrict) used[key[..2]] = used.GetValueOrDefault(key[..2], 0) + v;
|
||||
@@ -115,14 +118,17 @@ namespace Elwig.Helpers.Billing {
|
||||
}
|
||||
|
||||
await AppDbContext.ExecuteBatch(cnx, $"""
|
||||
UPDATE delivery_part_bucket SET value = 0 WHERE year = {Year};
|
||||
INSERT INTO delivery_part_bucket (year, did, dpnr, bktnr, discr, value)
|
||||
VALUES {string.Join(",\n ", inserts.Select(i => $"({Year}, {i.Item1}, {i.Item2}, {i.Item3}, '{i.Item4}', {i.Item5})"))}
|
||||
ON CONFLICT DO UPDATE
|
||||
SET discr = excluded.discr, value = value + excluded.value;
|
||||
""");
|
||||
|
||||
if (!avoidUnderDeliveries)
|
||||
if (!avoidUnderDeliveries) {
|
||||
if (ownCnx) await cnx.DisposeAsync();
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME avoidUnderDelivery-calculations not always right!
|
||||
|
||||
@@ -200,6 +206,8 @@ namespace Elwig.Helpers.Billing {
|
||||
ON CONFLICT DO UPDATE
|
||||
SET value = excluded.value;
|
||||
""");
|
||||
|
||||
if (ownCnx) await cnx.DisposeAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,11 @@ namespace Elwig.Helpers.Billing {
|
||||
public async Task Calculate() {
|
||||
using var cnx = await AppDbContext.ConnectAsync();
|
||||
using var tx = await cnx.BeginTransactionAsync();
|
||||
await CalculateBuckets(
|
||||
Season.Billing_AllowAttrsIntoLower,
|
||||
Season.Billing_AvoidUnderDeliveries,
|
||||
Season.Billing_HonorGebunden,
|
||||
cnx);
|
||||
await DeleteInDb(cnx);
|
||||
await SetCalcTime(cnx);
|
||||
await CalculatePrices(cnx);
|
||||
@@ -43,11 +48,10 @@ namespace Elwig.Helpers.Billing {
|
||||
ROUND(p.amount / POW(10, s.precision - 2)) AS net_amount,
|
||||
ROUND(lp.amount / POW(10, s.precision - 2)) AS prev_amount,
|
||||
IIF(m.buchführend, s.vat_normal, s.vat_flatrate) AS vat,
|
||||
ROUND(
|
||||
IIF({Data.ConsiderContractPenalties}, COALESCE(u.total_penalty, 0) / POW(10, 4 - 2), 0) +
|
||||
IIF({Data.ConsiderTotalPenalty}, COALESCE(b.total_penalty, 0), 0) +
|
||||
IIF({Data.ConsiderAutoBusinessShares}, -COALESCE(a.business_shares * s.bs_value, 0), 0) / POW(10, s.precision - 2)
|
||||
) AS modifiers,
|
||||
ROUND(IIF({Data.ConsiderContractPenalties}, COALESCE(u.total_penalty, 0), 0) / POW(10, 4 - 2)) +
|
||||
ROUND(IIF({Data.ConsiderTotalPenalty}, COALESCE(b.total_penalty, 0), 0) / POW(10, s.precision - 2)) +
|
||||
ROUND(IIF({Data.ConsiderAutoBusinessShares}, -COALESCE(a.total_amount, 0), 0) / POW(10, s.precision - 2))
|
||||
AS modifiers,
|
||||
lc.modifiers AS prev_modifiers
|
||||
FROM season s
|
||||
JOIN payment_variant v ON v.year = s.year
|
||||
@@ -63,26 +67,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 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 (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) 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
|
||||
LEFT JOIN v_penalty_area_commitments u ON (u.year, u.mgnr) = (s.year, m.mgnr)
|
||||
LEFT JOIN v_penalty_business_shares b ON (b.year, b.mgnr) = (s.year, m.mgnr)
|
||||
LEFT JOIN v_auto_business_shares a ON (a.year, a.mgnr) = (s.year, m.mgnr)
|
||||
WHERE s.year = {Year} AND v.avnr = {AvNr};
|
||||
|
||||
UPDATE payment_variant SET test_variant = FALSE WHERE (year, avnr) = ({Year}, {AvNr});
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Linq;
|
||||
@@ -8,7 +7,7 @@ using System.Threading.Tasks;
|
||||
namespace Elwig.Models.Dtos {
|
||||
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),
|
||||
("Name", "Name", null, 40),
|
||||
("GivenName", "Vorname", null, 40),
|
||||
@@ -20,7 +19,7 @@ namespace Elwig.Models.Dtos {
|
||||
("DeliveryObligations", "Lieferpflicht", "kg", 22),
|
||||
("Weights", "Geliefert", "kg", 22),
|
||||
("UnderDeliveries", "Unterliefert", "kg|%", 34),
|
||||
};
|
||||
];
|
||||
|
||||
public AreaComUnderDeliveryData(IEnumerable<AreaComUnderDeliveryRow> rows, int year) :
|
||||
base($"Unterlieferungen FB", $"Unterlieferungen laut Flächenbindungen {year}", rows, FieldNames) {
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
using Elwig.Helpers;
|
||||
using Elwig.Helpers.Billing;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Data.Entity.Core.Common.CommandTrees.ExpressionBuilder;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Elwig.Models.Dtos {
|
||||
public class CreditNoteData : DataTable<CreditNoteRow> {
|
||||
|
||||
private static readonly (string, string, string?, int)[] FieldNames = [
|
||||
("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),
|
||||
];
|
||||
|
||||
public CreditNoteData(IEnumerable<CreditNoteRow> rows, int year, string name) :
|
||||
base($"Buchungsliste", $"Buchungsliste {name} {year}", rows, FieldNames) {
|
||||
}
|
||||
|
||||
public static async Task<CreditNoteData> ForPaymentVariant(AppDbContext ctx, int year, int avnr) {
|
||||
var variant = await ctx.PaymentVariants.FindAsync(year, avnr);
|
||||
var name = variant!.Name;
|
||||
var data = BillingData.FromJson(variant!.Data);
|
||||
var rows = (await FromDbSet(ctx.CreditNoteRows, year, avnr)).Select(r => new CreditNoteRow(r, data)).ToList();
|
||||
return new CreditNoteData(rows, year, name);
|
||||
}
|
||||
|
||||
private static async Task<IEnumerable<CreditNoteRowSingle>> FromDbSet(DbSet<CreditNoteRowSingle> table, int year, int avnr) {
|
||||
return await table.FromSql($"""
|
||||
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,
|
||||
p.amount - p.net_amount AS surcharge,
|
||||
c.net_amount, c.prev_net_amount, c.vat, c.vat_amount, c.gross_amount, c.modifiers, c.prev_modifiers, c.amount,
|
||||
ROUND(COALESCE(u.total_penalty, 0) / POW(10, 4 - 2)) AS fb_penalty,
|
||||
ROUND(COALESCE(b.total_penalty, 0) / POW(10, s.precision - 2)) AS bs_penalty,
|
||||
ROUND(COALESCE(a.total_amount, 0) / POW(10, s.precision - 2)) AS auto_bs
|
||||
FROM credit c
|
||||
LEFT JOIN member m ON m.mgnr = c.mgnr
|
||||
LEFT JOIN payment_member p ON (p.year, p.avnr, p.mgnr) = (c.year, c.avnr, c.mgnr)
|
||||
LEFT JOIN AT_plz_dest p ON p.id = m.postal_dest
|
||||
LEFT JOIN AT_ort o ON o.okz = p.okz
|
||||
LEFT JOIN season s ON s.year = c.year
|
||||
LEFT JOIN v_penalty_area_commitments u ON (u.year, u.mgnr) = (s.year, m.mgnr)
|
||||
LEFT JOIN v_penalty_business_shares b ON (b.year, b.mgnr) = (s.year, m.mgnr)
|
||||
LEFT JOIN v_auto_business_shares a ON (a.year, a.mgnr) = (s.year, m.mgnr)
|
||||
WHERE c.year = {year} AND c.avnr = {avnr}
|
||||
ORDER BY m.mgnr
|
||||
""").ToListAsync();
|
||||
}
|
||||
}
|
||||
|
||||
public class CreditNoteRow {
|
||||
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 CreditNoteRow(CreditNoteRowSingle row, BillingData data) {
|
||||
byte prec1 = 2, prec2 = row.Precision;
|
||||
MgNr = row.MgNr;
|
||||
Name = row.Name;
|
||||
GivenName = row.GivenName;
|
||||
Address = row.Address;
|
||||
Plz = row.Plz;
|
||||
Locality = row.Locality;
|
||||
Iban = Utils.FormatIban(row.Iban);
|
||||
TgNr = $"{row.Year}/{row.TgNr}";
|
||||
Total = Utils.DecFromDb(row.NetAmount, prec1);
|
||||
Surcharge = (row.Surcharge == null || row.Surcharge == 0) ? null : Utils.DecFromDb((long)row.Surcharge, prec2);
|
||||
Sum = Total - (Surcharge ?? 0);
|
||||
ConsideredSum = (row.PrevNetAmount == null ||row.PrevNetAmount == 0) ? null : -Utils.DecFromDb((long)row.PrevNetAmount, prec1);
|
||||
Net = Total + (ConsideredSum ?? 0);
|
||||
if (row.Vat == 0.10) {
|
||||
Vat1 = Utils.DecFromDb(row.VatAmount, prec1);
|
||||
} else if (row.Vat == 0.13) {
|
||||
Vat2 = Utils.DecFromDb(row.VatAmount, prec1);
|
||||
}
|
||||
decimal mod = (row.Modifiers == null) ? 0 : Utils.DecFromDb((long)row.Modifiers, prec1);
|
||||
if (data.ConsiderContractPenalties)
|
||||
Penalties = (row.FbPenalty == null || row.FbPenalty == 0) ? null : Utils.DecFromDb((long)row.FbPenalty, prec1);
|
||||
if (data.ConsiderTotalPenalty)
|
||||
Penalty = (row.BsPealty == null || row.BsPealty == 0) ? null : Utils.DecFromDb((long)row.BsPealty, prec1);
|
||||
if (data.ConsiderAutoBusinessShares)
|
||||
AutoBs = (row.AutoBs == null || row.AutoBs == 0) ? null : -Utils.DecFromDb((long)row.AutoBs, prec1);
|
||||
mod -= (Penalties ?? 0) + (Penalty ?? 0) + (AutoBs ?? 0);
|
||||
Others = (mod == 0) ? null : mod;
|
||||
Gross = Utils.DecFromDb(row.GrossAmount, prec1);
|
||||
Considered = (row.PrevModifiers == null || row.PrevModifiers == 0) ? null : -Utils.DecFromDb((long)row.PrevModifiers, prec1);
|
||||
Amount = Utils.DecFromDb(row.Amount, prec1);
|
||||
}
|
||||
}
|
||||
|
||||
[Keyless]
|
||||
public class CreditNoteRowSingle {
|
||||
[Column("mgnr")]
|
||||
public int MgNr { get; set; }
|
||||
[Column("family_name")]
|
||||
public string Name { get; set; }
|
||||
[Column("given_name")]
|
||||
public string GivenName { get; set; }
|
||||
[Column("address")]
|
||||
public string Address { get; set; }
|
||||
[Column("plz")]
|
||||
public int Plz { get; set; }
|
||||
[Column("ort")]
|
||||
public string LocalityFull { get; set; }
|
||||
[NotMapped]
|
||||
public string Locality => LocalityFull.Split(",")[0];
|
||||
[Column("iban")]
|
||||
public string Iban { get; set; }
|
||||
[Column("year")]
|
||||
public int Year { get; set; }
|
||||
[Column("precision")]
|
||||
public byte Precision { get; set; }
|
||||
[Column("tgnr")]
|
||||
public string TgNr { get; set; }
|
||||
[Column("surcharge")]
|
||||
public long? Surcharge { get; set; }
|
||||
[Column("net_amount")]
|
||||
public long NetAmount { get; set; }
|
||||
[Column("prev_net_amount")]
|
||||
public long? PrevNetAmount { get; set; }
|
||||
[Column("vat")]
|
||||
public double Vat { get; set; }
|
||||
[Column("vat_amount")]
|
||||
public long VatAmount { get; set; }
|
||||
[Column("gross_amount")]
|
||||
public long GrossAmount { get; set; }
|
||||
[Column("modifiers")]
|
||||
public long? Modifiers { get; set; }
|
||||
[Column("prev_modifiers")]
|
||||
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; }
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,9 @@ using System.Threading.Tasks;
|
||||
namespace Elwig.Models.Dtos {
|
||||
public class CreditNoteDeliveryData : DataTable<CreditNoteDeliveryRow> {
|
||||
|
||||
private static readonly (string, string, string?)[] FieldNames = new[] {
|
||||
("", "", (string?)null), // TODO
|
||||
};
|
||||
private static readonly (string, string, string?)[] FieldNames = [
|
||||
("", "", null), // TODO
|
||||
];
|
||||
|
||||
private readonly int Year;
|
||||
private readonly int? TgNr;
|
||||
@@ -25,7 +25,7 @@ namespace Elwig.Models.Dtos {
|
||||
MgNr = mgnr;
|
||||
}
|
||||
|
||||
public static async Task<IDictionary<int, CreditNoteDeliveryData>> ForPaymentVariant(DbSet<CreditNoteRowSingle> table, DbSet<Season> seasons, int year, int avnr) {
|
||||
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 },
|
||||
@@ -36,7 +36,7 @@ namespace Elwig.Models.Dtos {
|
||||
.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<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";
|
||||
@@ -77,7 +77,7 @@ namespace Elwig.Models.Dtos {
|
||||
public decimal? TotalModifiers;
|
||||
public decimal? Amount;
|
||||
|
||||
public CreditNoteDeliveryRow(IEnumerable<CreditNoteRowSingle> rows, DbSet<Season> seasons) {
|
||||
public CreditNoteDeliveryRow(IEnumerable<CreditNoteDeliveryRowSingle> rows, DbSet<Season> seasons) {
|
||||
var f = rows.First();
|
||||
Year = f.Year;
|
||||
TgNr = f.TgNr;
|
||||
@@ -110,7 +110,7 @@ namespace Elwig.Models.Dtos {
|
||||
}
|
||||
|
||||
[Keyless]
|
||||
public class CreditNoteRowSingle {
|
||||
public class CreditNoteDeliveryRowSingle {
|
||||
[Column("year")]
|
||||
public int Year { get; set; }
|
||||
[Column("tgnr")]
|
||||
|
||||
@@ -65,7 +65,6 @@ namespace Elwig.Models.Entities {
|
||||
|
||||
[Column("start_date")]
|
||||
public string? StartDateString { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public DateOnly? StartDate {
|
||||
get => StartDateString != null ? DateOnly.ParseExact(StartDateString, "yyyy-MM-dd") : null;
|
||||
@@ -74,13 +73,30 @@ namespace Elwig.Models.Entities {
|
||||
|
||||
[Column("end_date")]
|
||||
public string? EndDateString { get; set; }
|
||||
|
||||
[NotMapped]
|
||||
public DateOnly? EndDate {
|
||||
get => EndDateString != null ? DateOnly.ParseExact(EndDateString, "yyyy-MM-dd") : null;
|
||||
set => EndDateString = value?.ToString("yyyy-MM-dd");
|
||||
}
|
||||
|
||||
[Column("calc_mode")]
|
||||
public int CalcMode { get; set; }
|
||||
[NotMapped]
|
||||
public bool Billing_HonorGebunden {
|
||||
get => (CalcMode & 0x1) != 0;
|
||||
set => CalcMode = value ? CalcMode | 0x1 : CalcMode & ~0x1;
|
||||
}
|
||||
[NotMapped]
|
||||
public bool Billing_AllowAttrsIntoLower {
|
||||
get => (CalcMode & 0x4) != 0;
|
||||
set => CalcMode = value ? CalcMode | 0x4 : CalcMode & ~0x4;
|
||||
}
|
||||
[NotMapped]
|
||||
public bool Billing_AvoidUnderDeliveries {
|
||||
get => (CalcMode & 0x2) != 0;
|
||||
set => CalcMode = value ? CalcMode | 0x2 : CalcMode & ~0x2;
|
||||
}
|
||||
|
||||
[ForeignKey("CurrencyCode")]
|
||||
public virtual Currency Currency { get; private set; }
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
-- schema version 11 to 12
|
||||
-- schema version 12 to 13
|
||||
|
||||
ALTER TABLE season ADD COLUMN bs_value INTEGER;
|
||||
|
||||
|
||||
@@ -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;
|
||||
@@ -0,0 +1,18 @@
|
||||
-- schema version 14 to 15
|
||||
|
||||
ALTER TABLE season ADD COLUMN calc_mode INTEGER NOT NULL DEFAULT 0;
|
||||
|
||||
DROP TRIGGER t_payment_delivery_part_u;
|
||||
|
||||
CREATE TRIGGER t_payment_delivery_part_u
|
||||
AFTER UPDATE ON payment_delivery_part FOR EACH ROW
|
||||
BEGIN
|
||||
UPDATE payment_member
|
||||
SET net_amount = net_amount - OLD.amount
|
||||
WHERE (year, avnr, mgnr) IN (SELECT year, OLD.avnr, mgnr FROM delivery WHERE (year, did) = (OLD.year, OLD.did));
|
||||
INSERT INTO payment_member (year, avnr, mgnr, net_amount)
|
||||
SELECT d.year, v.avnr, d.mgnr, NEW.amount
|
||||
FROM delivery d, payment_variant v
|
||||
WHERE (d.year, d.did) = (NEW.year, NEW.did) AND (v.year, v.avnr) = (NEW.year, NEW.avnr)
|
||||
ON CONFLICT DO UPDATE SET net_amount = net_amount + excluded.net_amount;
|
||||
END;
|
||||
@@ -6,7 +6,7 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:Elwig.Windows"
|
||||
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>
|
||||
<Style TargetType="Label">
|
||||
<Setter Property="HorizontalAlignment" Value="Left"/>
|
||||
@@ -42,7 +42,7 @@
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="200"/>
|
||||
<RowDefinition Height="220"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<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"
|
||||
Click="ExportButton_Click"
|
||||
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"
|
||||
VerticalAlignment="Bottom" HorizontalAlignment="Left"/>
|
||||
|
||||
@@ -57,6 +57,7 @@ namespace Elwig.Windows {
|
||||
ShowButton.IsEnabled = true;
|
||||
PrintButton.IsEnabled = true;
|
||||
ExportButton.IsEnabled = locked;
|
||||
TransactionButton.IsEnabled = locked;
|
||||
|
||||
NameInput.Text = v.Name;
|
||||
NameInput.IsReadOnly = false;
|
||||
@@ -101,6 +102,7 @@ namespace Elwig.Windows {
|
||||
ShowButton.IsEnabled = false;
|
||||
PrintButton.IsEnabled = false;
|
||||
ExportButton.IsEnabled = false;
|
||||
TransactionButton.IsEnabled = false;
|
||||
|
||||
BillingData = null;
|
||||
NameInput.Text = "";
|
||||
@@ -135,6 +137,7 @@ namespace Elwig.Windows {
|
||||
(ConsiderPenaltyInput.IsChecked != BillingData?.ConsiderTotalPenalty) ||
|
||||
(ConsiderAutoInput.IsChecked != BillingData?.ConsiderAutoBusinessShares));
|
||||
CalculateButton.IsEnabled = !SaveButton.IsEnabled && PaymentVariantList.SelectedItem is PaymentVar { TestVariant: true };
|
||||
CommitButton.IsEnabled = CalculateButton.IsEnabled;
|
||||
}
|
||||
|
||||
private void UpdateSums() {
|
||||
@@ -283,9 +286,9 @@ namespace Elwig.Windows {
|
||||
Mouse.OverrideCursor = Cursors.AppStarting;
|
||||
var b = new BillingVariant(v.Year, v.AvNr);
|
||||
await b.Revert();
|
||||
await App.HintContextChange();
|
||||
Mouse.OverrideCursor = null;
|
||||
CommitButton.IsEnabled = true;
|
||||
await App.HintContextChange();
|
||||
}
|
||||
|
||||
private async void ExportButton_Click(object sender, RoutedEventArgs evt) {
|
||||
@@ -311,6 +314,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) {
|
||||
if (PaymentVariantList.SelectedItem is not PaymentVar v || BillingData == null) return;
|
||||
try {
|
||||
@@ -488,11 +516,19 @@ namespace Elwig.Windows {
|
||||
members = members.OrderBy(m => m.MgNr);
|
||||
|
||||
IEnumerable<Member> list = await members.ToListAsync();
|
||||
var data = await CreditNoteDeliveryData.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);
|
||||
await Context.GetMemberAreaCommitmentBuckets(Year, 0);
|
||||
using var doc = Document.Merge(list.Select(m =>
|
||||
new CreditNote(Context, payments[m.MgNr], data[m.MgNr], Context.GetMemberUnderDelivery(Year, m.MgNr).GetAwaiter().GetResult())
|
||||
new CreditNote(
|
||||
Context,
|
||||
payments[m.MgNr],
|
||||
data[m.MgNr],
|
||||
BillingData?.ConsiderContractPenalties ?? false,
|
||||
BillingData?.ConsiderTotalPenalty ?? false,
|
||||
BillingData?.ConsiderAutoBusinessShares ?? false,
|
||||
Context.GetMemberUnderDelivery(Year, m.MgNr).GetAwaiter().GetResult()
|
||||
)
|
||||
));
|
||||
await doc.Generate(new Progress<double>(v => {
|
||||
ProgressBar.Value = v;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using Elwig.Dialogs;
|
||||
using Elwig.Helpers;
|
||||
using Elwig.Helpers.Billing;
|
||||
using Elwig.Helpers.Export;
|
||||
using Elwig.Models.Dtos;
|
||||
using Elwig.Models.Entities;
|
||||
using Microsoft.Win32;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
@@ -33,19 +33,34 @@ namespace Elwig.Windows {
|
||||
OverUnderDeliveryButton.IsEnabled = valid;
|
||||
AutoBusinessSharesButton.IsEnabled = valid;
|
||||
PaymentButton.IsEnabled = valid;
|
||||
AllowAttrIntoLowerInput.IsEnabled = valid && last;
|
||||
AvoidUnderDeliveriesInput.IsEnabled = valid && last;
|
||||
HonorGebundenInput.IsEnabled = valid && last;
|
||||
AllowAttrIntoLowerInput.IsChecked = s0?.Billing_AllowAttrsIntoLower;
|
||||
AvoidUnderDeliveriesInput.IsChecked = s0?.Billing_AvoidUnderDeliveries;
|
||||
HonorGebundenInput.IsChecked = s0?.Billing_HonorGebunden;
|
||||
}
|
||||
|
||||
private async void CalculateBucketsButton_Click(object sender, RoutedEventArgs evt) {
|
||||
if (SeasonInput.Value is not int year)
|
||||
if (SeasonInput.Value is not int year || await Context.Seasons.FindAsync(year) is not Season s)
|
||||
return;
|
||||
CalculateBucketsButton.IsEnabled = false;
|
||||
Mouse.OverrideCursor = Cursors.AppStarting;
|
||||
|
||||
try {
|
||||
s.Billing_AllowAttrsIntoLower = AllowAttrIntoLowerInput.IsChecked ?? false;
|
||||
s.Billing_AvoidUnderDeliveries = AvoidUnderDeliveriesInput.IsChecked ?? false;
|
||||
s.Billing_HonorGebunden = HonorGebundenInput.IsChecked ?? false;
|
||||
Context.Update(s);
|
||||
await Context.SaveChangesAsync();
|
||||
} catch { }
|
||||
|
||||
var b = new Billing(year);
|
||||
await b.FinishSeason();
|
||||
await b.CalculateBuckets(
|
||||
AllowAttrIntoLowerInput.IsChecked ?? false,
|
||||
AvoidUnderDeliveriesInput.IsChecked ?? false,
|
||||
HonorGebundenInput.IsChecked ?? false);
|
||||
s.Billing_AllowAttrsIntoLower,
|
||||
s.Billing_AvoidUnderDeliveries,
|
||||
s.Billing_HonorGebunden);
|
||||
Mouse.OverrideCursor = null;
|
||||
CalculateBucketsButton.IsEnabled = true;
|
||||
}
|
||||
|
||||
@@ -31,8 +31,8 @@ namespace Tests.HelperTests {
|
||||
if (Connection == null) return;
|
||||
await AppDbContext.ExecuteBatch(Connection, """
|
||||
DELETE FROM credit;
|
||||
DELETE FROM delivery_part_bucket;
|
||||
DELETE FROM payment_variant;
|
||||
DELETE FROM delivery_part_bucket;
|
||||
""");
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace Tests.HelperTests {
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_01_NoActiveAreaCommitments() {
|
||||
public async Task Test_01_NoActiveAreaComs() {
|
||||
int mgnr = MgNr1, year = Year1;
|
||||
await InsertPaymentVariant(year, 1, """
|
||||
{
|
||||
@@ -141,5 +141,86 @@ namespace Tests.HelperTests {
|
||||
Assert.That(prices[("20201001X003/2", "GV_")], Is.EqualTo(0_5000));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_02_SimpleNotStrictAreaComs() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_03_SimpleNotStrictAreaComs_HonorGebunden() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_04_ComplexNotStrictAreaComs() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_05_ComplexNotStrictAreaComs_HonorGebunden() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_06_StrictAreaComs_NoFillLower_NotAllowed() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_07_StrictAreaComs_NoFillLower_Allowed() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_08_StrictAreaComs_NoFillLower_Allowed_AvoidUnderDeliveries() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_09_StrictAreaComs_FillLowerUntilObligation_NotAllowed() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_10_StrictAreaComs_FillLowerUntilObligation_Allowed() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_11_StrictAreaComs_FillLowerUntilObligation_Allowed_AvoidUnderDeliveries() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
[Test]
|
||||
public async Task Test_12_StrictAreaComs_FillLowerUntilObligation_NotAllowed() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_13_StrictAreaComs_FillLowerUntilObligation_Allowed() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_14_StrictAreaComs_FillLowerUntilObligation_Allowed_AvoidUnderDeliveries() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_15_StrictAreaComs_FillLowerUntilRight_NotAllowed() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_16_StrictAreaComs_FillLowerUntilRight_Allowed() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task Test_17_StrictAreaComs_FillLowerUntilRight_Allowed_AvoidUnderDeliveries() {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
curl -s -L "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=15" -u "elwig:ganzGeheim123!" -o "Resources\Create.sql"
|
||||
|
||||
Reference in New Issue
Block a user