-
-
+
+
@@ -25,7 +25,7 @@
Lieferschein-Nr. |
Pos. |
Sorte |
- Attribut |
+ Attr./Bewirt. |
Qualitätsstufe |
Gradation |
Flächenbindung |
@@ -53,7 +53,7 @@
@p.LsNr |
@p.DPNr |
@p.Variety |
- @p.Attribute |
+ @p.Attribute@(p.Attribute != null && p.Cultivation != null ? " / " : "")@p.Cultivation |
@p.QualityLevel |
@($"{p.Gradation.Oe:N0}") |
@($"{p.Gradation.Kmw:N1}") |
@@ -90,7 +90,7 @@
- @Raw(BusinessDocument.PrintSortenaufteilung(Model.MemberBuckets))
+ @Raw(BusinessDocument.PrintSortenaufteilung(Model.MemberStats))
@Raw(Model.PrintBucketTable(Model.Season, Model.MemberBuckets, includePayment: true))
@if (Model.Text != null) {
diff --git a/Elwig/Documents/DeliveryNote.cshtml b/Elwig/Documents/DeliveryNote.cshtml
index ec5cda5..d5b9c43 100644
--- a/Elwig/Documents/DeliveryNote.cshtml
+++ b/Elwig/Documents/DeliveryNote.cshtml
@@ -43,6 +43,14 @@
@($"{part.Kmw:N1}") |
@($"{part.Weight:N0}") |
+ @if (part.Cultivation != null) {
+ | Bewirtschaftung: |
+ @part.Cultivation.Name
+ @if(part.Cultivation.Description != null) {
+ @("(")@part.Cultivation.Description@(")")
+ }
+ |
+ }
| Herkunft: @part.OriginString |
@if (part.Modifiers.Count() > 0) {
var first = true;
@@ -52,8 +60,8 @@
}
}
|
- @Raw(part.ManualWeighing ? "Handwiegung" : $"Waage: {part.ScaleId ?? "?"}, ID: {part.WeighingId ?? "?"}")
- (@(part.IsGerebelt ? "gerebelt gewogen" : "nicht gerebelt gewogen"))@Raw(part.WeighingReason != null ? $", Begründung:" : "") @part.WeighingReason
+ @Raw(part.IsManualWeighing ? "Handwiegung" : $"Waage: {part.ScaleId ?? "?"}, ID: {part.WeighingId ?? "?"}")
+ (@(part.IsNetWeight ? "gerebelt gewogen" : "nicht gerebelt gewogen"))@Raw(part.WeighingReason != null ? $", Begründung:" : "") @part.WeighingReason
|
@if (part.Comment != null) {
| Anmerkung: @part.Comment |
diff --git a/Elwig/Helpers/AppDbContext.cs b/Elwig/Helpers/AppDbContext.cs
index 72efe3d..e06fa77 100644
--- a/Elwig/Helpers/AppDbContext.cs
+++ b/Elwig/Helpers/AppDbContext.cs
@@ -17,6 +17,7 @@ namespace Elwig.Helpers {
public record struct AreaComBucket(int Area, int Obligation, int Right);
public record struct UnderDelivery(int Weight, int Diff);
public record struct MemberBucket(string Name, int Area, int Obligation, int Right, int Delivery, int DeliveryStrict, int Payment);
+ public record struct MemberStat(string Variety, string Discr, int Weight);
public class AppDbContext : DbContext {
@@ -159,6 +160,10 @@ namespace Elwig.Helpers {
return await WineAttributes.FindAsync(attrId) != null;
}
+ public async Task CultIdExists(string cultId) {
+ return await WineCultivations.FindAsync(cultId) != null;
+ }
+
public async Task NextMgNr() {
int c = 0;
(await Members.OrderBy(m => m.MgNr).Select(m => m.MgNr).ToListAsync())
@@ -384,5 +389,31 @@ namespace Elwig.Helpers {
}
return buckets;
}
+
+ public static async Task> GetMemberStats(int year, int mgnr, SqliteConnection? cnx = null) {
+ var ownCnx = cnx == null;
+ cnx ??= await ConnectAsync();
+ var list = new List();
+ using (var cmd = cnx.CreateCommand()) {
+ cmd.CommandText = $"""
+ SELECT v.name AS variety,
+ COALESCE(a.name, '') || IIF(a.name IS NOT NULL AND c.name IS NOT NULL, ' / ', '') || COALESCE(c.name, '') AS disc,
+ SUM(weight) AS weight
+ FROM v_delivery d
+ LEFT JOIN wine_variety v ON v.sortid = d.sortid
+ LEFT JOIN wine_attribute a ON a.attrid = d.attrid
+ LEFT JOIN wine_cultivation c ON c.cultid = d.cultid
+ WHERE d.year = {year} AND d.mgnr = {mgnr}
+ GROUP BY d.sortid, d.attrid, d.cultid
+ ORDER BY variety, disc;
+ """;
+ using var reader = await cmd.ExecuteReaderAsync();
+ while (await reader.ReadAsync()) {
+ list.Add(new(reader.GetString(0), reader.GetString(1), reader.GetInt32(2)));
+ }
+ }
+ if (ownCnx) await cnx.DisposeAsync();
+ return list;
+ }
}
}
diff --git a/Elwig/Helpers/AppDbUpdater.cs b/Elwig/Helpers/AppDbUpdater.cs
index ace01f5..0a3c6ca 100644
--- a/Elwig/Helpers/AppDbUpdater.cs
+++ b/Elwig/Helpers/AppDbUpdater.cs
@@ -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 = 17;
+ public static readonly int RequiredSchemaVersion = 18;
private static int VersionOffset = 0;
diff --git a/Elwig/Helpers/Validator.cs b/Elwig/Helpers/Validator.cs
index 68c9422..5a6054b 100644
--- a/Elwig/Helpers/Validator.cs
+++ b/Elwig/Helpers/Validator.cs
@@ -454,9 +454,9 @@ namespace Elwig.Helpers {
if (input.Text.Length < 2 || !ctx.SortIdExists(input.Text[0..2]).GetAwaiter().GetResult()) {
return new(false, "Ungültige Sorte");
} else if (input.Text.Length >= 3) {
- var attr = input.Text[2..];
- if (!ctx.AttrIdExists(attr).GetAwaiter().GetResult()) {
- return new(false, "Ungültiges Attribut");
+ var disc = input.Text[2..];
+ if (!ctx.AttrIdExists(disc).GetAwaiter().GetResult() && !ctx.CultIdExists(disc).GetAwaiter().GetResult()) {
+ return new(false, "Ungültiges Attribut/Bewirt.");
}
}
diff --git a/Elwig/Models/Dtos/CreditNoteDeliveryData.cs b/Elwig/Models/Dtos/CreditNoteDeliveryData.cs
index 0b2be48..05e7c36 100644
--- a/Elwig/Models/Dtos/CreditNoteDeliveryData.cs
+++ b/Elwig/Models/Dtos/CreditNoteDeliveryData.cs
@@ -43,10 +43,11 @@ namespace Elwig.Models.Dtos {
return await table.FromSqlRaw($"""
SELECT d.year, c.tgnr, v.avnr, d.mgnr, d.did, d.lsnr, d.dpnr, d.weight, d.modifiers,
b.bktnr, d.sortid, b.discr, b.value, pb.price, pb.amount, p.net_amount, p.amount AS total_amount,
- s.name AS variety, a.name AS attribute, q.name AS quality_level, d.oe, d.kmw
+ s.name AS variety, a.name AS attribute, c.name AS cultivation, q.name AS quality_level, d.oe, d.kmw
FROM v_delivery d
JOIN wine_variety s ON s.sortid = d.sortid
LEFT JOIN wine_attribute a ON a.attrid = d.attrid
+ LEFT JOIN wine_cultivation c ON c.cultid = d.cultid
JOIN wine_quality_level q ON q.qualid = d.qualid
LEFT JOIN delivery_part_bucket b ON (b.year, b.did, b.dpnr) = (d.year, d.did, d.dpnr)
LEFT JOIN payment_variant v ON v.year = d.year
@@ -70,6 +71,7 @@ namespace Elwig.Models.Dtos {
public int DPNr;
public string Variety;
public string? Attribute;
+ public string? Cultivation;
public string[] Modifiers;
public string QualityLevel;
public (double Oe, double Kmw) Gradation;
@@ -88,6 +90,7 @@ namespace Elwig.Models.Dtos {
DPNr = f.DPNr;
Variety = f.Variety;
Attribute = f.Attribute;
+ Cultivation = f.Cultivation;
var modifiers = (IEnumerable)(f.Modifiers ?? "").Split(',')
.Select(m => season?.Modifiers.FirstOrDefault(s => s.ModId == m))
.Where(m => m != null)
@@ -149,6 +152,8 @@ namespace Elwig.Models.Dtos {
public string Variety { get; set; }
[Column("attribute")]
public string? Attribute { get; set; }
+ [Column("cultivation")]
+ public string? Cultivation { get; set; }
[Column("quality_level")]
public string QualityLevel { get; set; }
[Column("oe")]
diff --git a/Elwig/Models/Dtos/DeliveryConfirmationDeliveryData.cs b/Elwig/Models/Dtos/DeliveryConfirmationDeliveryData.cs
index e8a11b5..0be2155 100644
--- a/Elwig/Models/Dtos/DeliveryConfirmationDeliveryData.cs
+++ b/Elwig/Models/Dtos/DeliveryConfirmationDeliveryData.cs
@@ -73,6 +73,7 @@ namespace Elwig.Models.Dtos {
public int DPNr;
public string Variety;
public string? Attribute;
+ public string? Cultivation;
public string QualityLevel;
public (double Oe, double Kmw) Gradation;
public string[] Modifiers;
@@ -85,6 +86,7 @@ namespace Elwig.Models.Dtos {
DPNr = p.DPNr;
Variety = p.Variety.Name;
Attribute = p.Attribute?.Name;
+ Cultivation = p.Cultivation?.Name;
QualityLevel = p.Quality.Name;
Gradation = (p.Oe, p.Kmw);
Modifiers = p.Modifiers
diff --git a/Elwig/Models/Entities/AreaCom.cs b/Elwig/Models/Entities/AreaCom.cs
index a358b97..4878f9d 100644
--- a/Elwig/Models/Entities/AreaCom.cs
+++ b/Elwig/Models/Entities/AreaCom.cs
@@ -17,7 +17,7 @@ namespace Elwig.Models.Entities {
public string VtrgId { get; set; }
[Column("cultid")]
- public string CultId { get; set; }
+ public string? CultId { get; set; }
[Column("area")]
public int Area { get; set; }
@@ -47,7 +47,7 @@ namespace Elwig.Models.Entities {
public virtual AreaComType AreaComType { get; private set; }
[ForeignKey("CultId")]
- public virtual WineCult WineCult { get; private set; }
+ public virtual WineCult? WineCult { get; private set; }
[ForeignKey("KgNr")]
public virtual WbKg Kg { get; private set; }
@@ -57,7 +57,7 @@ namespace Elwig.Models.Entities {
public int SearchScore(IEnumerable keywords) {
var list = new string?[] {
- WineCult.Name, Kg.AtKg.Name, Rd.Name, GstNr, Comment,
+ WineCult?.Name, Kg.AtKg.Name, Rd.Name, GstNr, Comment,
}.ToList();
return Utils.GetSearchScore(list, keywords);
}
diff --git a/Elwig/Models/Entities/DeliveryPart.cs b/Elwig/Models/Entities/DeliveryPart.cs
index 5ae5f95..4c15525 100644
--- a/Elwig/Models/Entities/DeliveryPart.cs
+++ b/Elwig/Models/Entities/DeliveryPart.cs
@@ -31,6 +31,12 @@ namespace Elwig.Models.Entities {
[ForeignKey("AttrId")]
public virtual WineAttr? Attribute { get; private set; }
+ [Column("cultid")]
+ public string? CultId { get; set; }
+
+ [ForeignKey("CultId")]
+ public virtual WineCult? Cultivation { get; private set; }
+
[Column("weight")]
public int Weight { get; set; }
@@ -66,14 +72,14 @@ namespace Elwig.Models.Entities {
[ForeignKey("KgNr, RdNr")]
public virtual WbRd? Rd { get; private set; }
- [Column("gerebelt")]
- public bool IsGerebelt { get; set; }
+ [Column("net_weight")]
+ public bool IsNetWeight { get; set; }
[Column("manual_weighing")]
- public bool ManualWeighing { get; set; }
+ public bool IsManualWeighing { get; set; }
[Column("spl_check")]
- public bool SplCheck { get; set; }
+ public bool IsSplCheck { get; set; }
[Column("hand_picked")]
public bool? IsHandPicked { get; set; }
diff --git a/Elwig/Resources/Schemas/PaymentVariantData.json b/Elwig/Resources/Schemas/PaymentVariantData.json
index 8cc658d..8844061 100644
--- a/Elwig/Resources/Schemas/PaymentVariantData.json
+++ b/Elwig/Resources/Schemas/PaymentVariantData.json
@@ -43,7 +43,7 @@
}
},
"patternProperties": {
- "^([A-Z]{2})?(\/[A-Z]*)?$": {
+ "^([A-Z]{2})?(\/[A-Z]*)?(-[A-Z][A-Z0-9]*)?$": {
"type": ["number", "string"],
"pattern": "^curve:[0-9]+$"
}
@@ -64,7 +64,7 @@
}
},
"patternProperties": {
- "^([A-Z]{2})?(\/[A-Z]*)?$": {
+ "^([A-Z]{2})?(\/[A-Z]*)?(-[A-Z][A-Z0-9]*)?$": {
"type": ["number", "string"],
"pattern": "^curve:[0-9]+$"
}
diff --git a/Elwig/Resources/Sql/17-18.sql b/Elwig/Resources/Sql/17-18.sql
new file mode 100644
index 0000000..d8a7551
--- /dev/null
+++ b/Elwig/Resources/Sql/17-18.sql
@@ -0,0 +1,92 @@
+-- schema version 17 to 18
+
+ALTER TABLE delivery_part ADD COLUMN cultid TEXT DEFAULT NULL;
+
+PRAGMA writable_schema = ON;
+UPDATE sqlite_schema SET sql = REPLACE(sql, CHAR(10) ||
+ ') STRICT',
+ ',' || CHAR(10) ||
+ ' CONSTRAINT fk_delivery_part_wine_cultivation FOREIGN KEY (cultid) REFERENCES wine_cultivation (cultid)' || CHAR(10) ||
+ ' ON UPDATE CASCADE' || CHAR(10) ||
+ ' ON DELETE RESTRICT' || CHAR(10) ||
+ ') STRICT')
+WHERE type = 'table' AND name = 'delivery_part';
+UPDATE sqlite_schema SET sql = REPLACE(sql, 'gerebelt ', 'net_weight')
+WHERE type = 'table' AND name = 'delivery_part';
+
+UPDATE sqlite_schema SET sql = REPLACE(sql, 'CHECK (cultid REGEXP ''^[A-Z]+$'')', 'CHECK (cultid REGEXP ''^[A-Z][A-Z0-9]*$'')')
+WHERE type = 'table' AND name = 'wine_cultivation';
+
+UPDATE sqlite_schema SET sql = REPLACE(sql, 'cultid TEXT NOT NULL', 'cultid TEXT DEFAULT NULL')
+WHERE type = 'table' AND name = 'area_commitment';
+
+DROP VIEW v_delivery;
+CREATE VIEW v_delivery AS
+SELECT p.year, p.did, p.dpnr,
+ d.date, d.time, d.zwstid, d.lnr, d.lsnr,
+ m.mgnr, m.family_name, m.given_name,
+ p.sortid, a.attrid, p.cultid,
+ p.weight, p.kmw, ROUND(p.kmw * (4.54 + 0.022 * p.kmw), 0) AS oe, p.qualid,
+ p.hkid, p.kgnr, p.rdnr,
+ p.net_weight, p.gebunden,
+ p.qualid IN (SELECT l.qualid FROM wine_quality_level l WHERE NOT l.predicate AND (p.kmw >= l.min_kmw OR l.min_kmw IS NULL) ORDER BY l.min_kmw DESC LIMIT 1,100) AS abgewertet,
+ p.qualid NOT IN ('WEI', 'RSW', 'LDW') AS min_quw,
+ IIF(a.strict, COALESCE(a.fill_lower, 0), 0) AS attribute_prio,
+ GROUP_CONCAT(o.modid) AS modifiers,
+ d.comment, p.comment AS part_comment
+FROM delivery_part p
+ JOIN delivery d ON (d.year, d.did) = (p.year, p.did)
+ JOIN member m ON m.mgnr = d.mgnr
+ LEFT JOIN wine_attribute a ON a.attrid = p.attrid
+ LEFT JOIN delivery_part_modifier o ON (o.year, o.did, o.dpnr) = (p.year, p.did, p.dpnr)
+GROUP BY p.year, p.did, p.dpnr
+ORDER BY p.year, p.did, p.dpnr, o.modid;
+
+CREATE VIEW v_wine_attribute AS
+SELECT a.attrid, name, active, max_kg_per_ha, strict, fill_lower,
+ COUNT(t.attrid) > 0 AS area_com
+FROM wine_attribute a
+ LEFT JOIN area_commitment_type t ON t.attrid = a.attrid
+GROUP BY a.attrid;
+
+DROP VIEW v_delivery_bucket_strict;
+CREATE VIEW v_delivery_bucket_strict AS
+SELECT year, mgnr,
+ sortid || IIF(min_quw OR NOT COALESCE(area_com, TRUE), COALESCE(a.attrid, ''), '_') AS bucket,
+ sortid, IIF(min_quw OR NOT COALESCE(area_com, TRUE), a.attrid, NULL) AS attrid,
+ SUM(weight) AS weight,
+ min_quw OR NOT COALESCE(area_com, TRUE) AS valid
+FROM v_delivery d
+ LEFT JOIN v_wine_attribute a ON a.attrid = d.attrid
+GROUP BY year, mgnr, bucket
+ORDER BY year, mgnr, bucket;
+
+DROP VIEW v_delivery_bucket;
+CREATE VIEW v_delivery_bucket AS
+SELECT year, mgnr, bucket, weight
+FROM v_delivery_bucket_strict
+WHERE attrid IS NOT NULL OR NOT valid
+UNION ALL
+SELECT b.year, b.mgnr, b.sortid,
+ SUM(b.weight) AS weight
+FROM v_delivery_bucket_strict b
+ LEFT JOIN wine_attribute a ON a.attrid = b.attrid
+WHERE valid AND (a.strict IS NULL OR a.strict = FALSE)
+GROUP BY b.year, b.mgnr, b.sortid
+ORDER BY year, mgnr, bucket;
+
+PRAGMA schema_version = 1701;
+PRAGMA writable_schame = OFF;
+
+----------------------------------------------------------------
+
+UPDATE area_commitment SET cultid = NULL WHERE cultid = 'N';
+DELETE FROM wine_cultivation WHERE cultid = 'N';
+UPDATE wine_cultivation SET cultid = 'B', name = 'Bio', description = 'AT-BIO-302' WHERE cultid = 'BIO';
+
+UPDATE area_commitment SET cultid = 'B', vtrgid = SUBSTR(vtrgid, 0, 2) WHERE vtrgid LIKE '__B';
+DELETE FROM area_commitment_type WHERE attrid = 'B';
+UPDATE delivery_part SET cultid = 'B', attrid = NULL WHERE attrid = 'B';
+DELETE FROM wine_attribute WHERE attrid = 'B';
+
+UPDATE payment_variant SET data = REPLACE(REPLACE(data, '/B', '/-B'), '"/-B"', '"-B"');
diff --git a/Elwig/Windows/DeliveryAdminWindow.xaml b/Elwig/Windows/DeliveryAdminWindow.xaml
index fe6bfb3..913faa5 100644
--- a/Elwig/Windows/DeliveryAdminWindow.xaml
+++ b/Elwig/Windows/DeliveryAdminWindow.xaml
@@ -277,24 +277,28 @@
-
+
-
+
+
-
-
-
+
+
diff --git a/Elwig/Windows/DeliveryAdminWindow.xaml.cs b/Elwig/Windows/DeliveryAdminWindow.xaml.cs
index 38e8f51..2d611ea 100644
--- a/Elwig/Windows/DeliveryAdminWindow.xaml.cs
+++ b/Elwig/Windows/DeliveryAdminWindow.xaml.cs
@@ -292,7 +292,7 @@ namespace Elwig.Windows {
if (ctrl == MgNrInput || ctrl == MemberInput) {
SortIdInput.Focus();
SortIdInput.SelectAll();
- } else if (ctrl == SortIdInput || ctrl == WineVarietyInput || ctrl == AttributeInput) {
+ } else if (ctrl == SortIdInput || ctrl == WineVarietyInput || ctrl == AttributeInput || ctrl == CultivationInput) {
GradationOeInput.Focus();
GradationOeInput.TextBox.SelectAll();
} else if (ctrl == GradationKmwInput || ctrl == GradationOeInput || ctrl == WineQualityLevelInput) {
@@ -762,6 +762,9 @@ namespace Elwig.Windows {
var attrList = await Context.WineAttributes.Where(a => !IsCreating || a.IsActive).OrderBy(a => a.Name).Cast