[#34] First step of not using Bio as Attribute

This commit is contained in:
2024-02-19 22:14:47 +01:00
parent 092c5788a4
commit abbb5a12a6
19 changed files with 219 additions and 59 deletions

View File

@ -40,19 +40,19 @@ namespace Elwig.Documents {
return "<colgroup>\n" + string.Join("\n", cols.Select(g => $"<col style=\"width: {g.ToString(CultureInfo.InvariantCulture)}mm;\"/>")) + "\n</colgroup>\n"; return "<colgroup>\n" + string.Join("\n", cols.Select(g => $"<col style=\"width: {g.ToString(CultureInfo.InvariantCulture)}mm;\"/>")) + "\n</colgroup>\n";
} }
public static string PrintSortenaufteilung(Dictionary<string, MemberBucket> buckets) { public static string PrintSortenaufteilung(List<MemberStat> stats) {
List<string> attributes = ["_", ""]; List<string> discrs = [""];
List<string> names = ["kein Qual.Wein", "ohne Attribut"]; List<string> names = ["ohne Attr./Bewirt."];
List<(string, string)> bucketAttrs = [ List<string> bucketAttrs = [
.. buckets .. stats
.Where(b => b.Key.Length > 2 && b.Key[2] != '_' && b.Value.DeliveryStrict > 0) .Select(s => s.Discr)
.Select(b => (b.Key[2..], b.Value.Name.Split("(")[1][..^1]))
.Distinct() .Distinct()
.OrderBy(v => v.Item1) .Where(s => s.Length > 0)
.Order()
]; ];
names.AddRange(bucketAttrs.Select(b => b.Item2)); names.AddRange(bucketAttrs);
names.Add("Gesamt"); names.Add("Gesamt");
attributes.AddRange(bucketAttrs.Select(b => b.Item1)); discrs.AddRange(bucketAttrs);
List<double> cols = [40]; List<double> cols = [40];
cols.AddRange(names.Select(_ => 125.0 / names.Count)); cols.AddRange(names.Select(_ => 125.0 / names.Count));
@ -62,19 +62,18 @@ namespace Elwig.Documents {
string.Join("", names.Select(c => $"<th>{c}</th>")) + string.Join("", names.Select(c => $"<th>{c}</th>")) +
"</tr></thead>"; "</tr></thead>";
tbl += string.Join("\n", buckets tbl += string.Join("\n", stats
.GroupBy(b => (b.Key[..2], b.Value.Name.Split("(")[0].Trim())) .GroupBy(b => b.Variety)
.Where(g => g.Sum(a => a.Value.DeliveryStrict) > 0) .OrderBy(b => b.Key)
.OrderBy(g => g.Key.Item1)
.Select(g => { .Select(g => {
var dict = g.ToDictionary(a => a.Key[2..], a => a.Value); var dict = g.ToDictionary(a => a.Discr, a => a.Weight);
var vals = attributes.Select(a => dict.TryGetValue(a, out MemberBucket value) ? value.DeliveryStrict : 0).ToList(); var vals = discrs.Select(a => dict.GetValueOrDefault(a, 0)).ToList();
return $"<tr><th>{g.Key.Item2}</th>" + string.Join("", vals.Select(v => "<td class=\"number\">" + (v == 0 ? "-" : $"{v:N0}") + "</td>")) + return $"<tr><th>{g.Key}</th>" + string.Join("", vals.Select(v => "<td class=\"number\">" + (v == 0 ? "-" : $"{v:N0}") + "</td>")) +
$"<td class=\"number\">{dict.Values.Select(v => v.DeliveryStrict).Sum():N0}</td></tr>"; $"<td class=\"number\">{dict.Values.Sum():N0}</td></tr>";
}) })
); );
var totalDict = buckets.GroupBy(b => b.Key[2..]).ToDictionary(g => g.Key, g => g.Sum(a => a.Value.DeliveryStrict)); var totalDict = stats.GroupBy(s => s.Discr).ToDictionary(g => g.Key, g => g.Sum(a => a.Weight));
var totals = attributes.Select(a => totalDict.TryGetValue(a, out int value) ? value : 0); var totals = discrs.Select(a => totalDict.TryGetValue(a, out int value) ? value : 0);
tbl += "<tr class=\"sum bold\"><td></td>" + string.Join("", totals.Select(v => $"<td class=\"number\">{v:N0}</td>")) + tbl += "<tr class=\"sum bold\"><td></td>" + string.Join("", totals.Select(v => $"<td class=\"number\">{v:N0}</td>")) +
$"<td class=\"number\">{totalDict.Values.Sum():N0}</td></tr>"; $"<td class=\"number\">{totalDict.Values.Sum():N0}</td></tr>";

View File

@ -10,8 +10,8 @@
<colgroup> <colgroup>
<col style="width: 25mm;"/> <col style="width: 25mm;"/>
<col style="width: 5mm;"/> <col style="width: 5mm;"/>
<col style="width: 20mm;"/> <col style="width: 24mm;"/>
<col style="width: 20mm;"/> <col style="width: 16mm;"/>
<col style="width: 10mm;"/> <col style="width: 10mm;"/>
<col style="width: 10mm;"/> <col style="width: 10mm;"/>
<col style="width: 15mm;"/> <col style="width: 15mm;"/>
@ -25,7 +25,7 @@
<th rowspan="2" style="text-align: left;">Lieferschein-Nr.</th> <th rowspan="2" style="text-align: left;">Lieferschein-Nr.</th>
<th rowspan="2" class="narrow">Pos.</th> <th rowspan="2" class="narrow">Pos.</th>
<th rowspan="2" style="text-align: left;">Sorte</th> <th rowspan="2" style="text-align: left;">Sorte</th>
<th rowspan="2" style="text-align: left;">Attribut</th> <th rowspan="2" style="text-align: left;">Attr./Bewirt.</th>
<th colspan="2">Gradation</th> <th colspan="2">Gradation</th>
<th colspan="2">Flächenbindung</th> <th colspan="2">Flächenbindung</th>
<th>Preis</th> <th>Preis</th>
@ -50,7 +50,7 @@
<td rowspan="@rows">@p.LsNr</td> <td rowspan="@rows">@p.LsNr</td>
<td rowspan="@rows">@p.DPNr</td> <td rowspan="@rows">@p.DPNr</td>
<td class="small">@p.Variety</td> <td class="small">@p.Variety</td>
<td class="small">@p.Attribute</td> <td class="small">@p.Attribute@(p.Attribute != null && p.Cultivation != null ? " / " : "")@p.Cultivation</td>
<td rowspan="@rows" class="center">@($"{p.Gradation.Oe:N0}")</td> <td rowspan="@rows" class="center">@($"{p.Gradation.Oe:N0}")</td>
<td rowspan="@rows" class="center">@($"{p.Gradation.Kmw:N1}")</td> <td rowspan="@rows" class="center">@($"{p.Gradation.Kmw:N1}")</td>
} }

View File

@ -13,6 +13,7 @@ namespace Elwig.Documents {
public DeliveryConfirmationDeliveryData Data; public DeliveryConfirmationDeliveryData Data;
public string? Text = App.Client.TextDeliveryConfirmation; public string? Text = App.Client.TextDeliveryConfirmation;
public Dictionary<string, MemberBucket> MemberBuckets; public Dictionary<string, MemberBucket> MemberBuckets;
public List<MemberStat> MemberStats;
public DeliveryConfirmation(AppDbContext ctx, int year, Member m, DeliveryConfirmationDeliveryData data) : public DeliveryConfirmation(AppDbContext ctx, int year, Member m, DeliveryConfirmationDeliveryData data) :
base($"{Name} {year}", m) { base($"{Name} {year}", m) {
@ -23,6 +24,7 @@ namespace Elwig.Documents {
DocumentId = $"Anl.-Best. {Season.Year}/{m.MgNr}"; DocumentId = $"Anl.-Best. {Season.Year}/{m.MgNr}";
Data = data; Data = data;
MemberBuckets = ctx.GetMemberBuckets(Season.Year, m.MgNr).GetAwaiter().GetResult(); MemberBuckets = ctx.GetMemberBuckets(Season.Year, m.MgNr).GetAwaiter().GetResult();
MemberStats = AppDbContext.GetMemberStats(Season.Year, m.MgNr).GetAwaiter().GetResult();
} }
} }
} }

View File

@ -10,8 +10,8 @@
<colgroup> <colgroup>
<col style="width: 25mm;"/> <col style="width: 25mm;"/>
<col style="width: 5mm;"/> <col style="width: 5mm;"/>
<col style="width: 20mm;"/> <col style="width: 24mm;"/>
<col style="width: 21mm;"/> <col style="width: 17mm;"/>
<col style="width: 19mm;"/> <col style="width: 19mm;"/>
<col style="width: 10mm;"/> <col style="width: 10mm;"/>
<col style="width: 10mm;"/> <col style="width: 10mm;"/>
@ -25,7 +25,7 @@
<th rowspan="2" style="text-align: left;">Lieferschein-Nr.</th> <th rowspan="2" style="text-align: left;">Lieferschein-Nr.</th>
<th rowspan="2" class="narrow">Pos.</th> <th rowspan="2" class="narrow">Pos.</th>
<th rowspan="2" style="text-align: left;">Sorte</th> <th rowspan="2" style="text-align: left;">Sorte</th>
<th rowspan="2" style="text-align: left;">Attribut</th> <th rowspan="2" style="text-align: left;">Attr./Bewirt.</th>
<th rowspan="2" style="text-align: left;">Qualitätsstufe</th> <th rowspan="2" style="text-align: left;">Qualitätsstufe</th>
<th colspan="2">Gradation</th> <th colspan="2">Gradation</th>
<th colspan="2">Flächenbindung</th> <th colspan="2">Flächenbindung</th>
@ -53,7 +53,7 @@
<td rowspan="@rows">@p.LsNr</td> <td rowspan="@rows">@p.LsNr</td>
<td rowspan="@rows">@p.DPNr</td> <td rowspan="@rows">@p.DPNr</td>
<td class="small">@p.Variety</td> <td class="small">@p.Variety</td>
<td class="small">@p.Attribute</td> <td class="small">@p.Attribute@(p.Attribute != null && p.Cultivation != null ? " / " : "")@p.Cultivation</td>
<td class="small">@p.QualityLevel</td> <td class="small">@p.QualityLevel</td>
<td rowspan="@rows" class="center">@($"{p.Gradation.Oe:N0}")</td> <td rowspan="@rows" class="center">@($"{p.Gradation.Oe:N0}")</td>
<td rowspan="@rows" class="center">@($"{p.Gradation.Kmw:N1}")</td> <td rowspan="@rows" class="center">@($"{p.Gradation.Kmw:N1}")</td>
@ -90,7 +90,7 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
@Raw(BusinessDocument.PrintSortenaufteilung(Model.MemberBuckets)) @Raw(BusinessDocument.PrintSortenaufteilung(Model.MemberStats))
@Raw(Model.PrintBucketTable(Model.Season, Model.MemberBuckets, includePayment: true)) @Raw(Model.PrintBucketTable(Model.Season, Model.MemberBuckets, includePayment: true))
<div style="margin-top: 2em;"> <div style="margin-top: 2em;">
@if (Model.Text != null) { @if (Model.Text != null) {

View File

@ -43,6 +43,14 @@
<td class="center">@($"{part.Kmw:N1}")</td> <td class="center">@($"{part.Kmw:N1}")</td>
<td class="number">@($"{part.Weight:N0}")</td> <td class="number">@($"{part.Weight:N0}")</td>
</tr> </tr>
@if (part.Cultivation != null) {
<tr><td></td><td><i>Bewirtschaftung:</i></td><td colspan="4"><b>
@part.Cultivation.Name
@if(part.Cultivation.Description != null) {
@("(")@part.Cultivation.Description@(")")
}
</b></td></tr>
}
<tr><td></td><td colspan="5" style="white-space: pre;"><i>Herkunft:</i> @part.OriginString</td></tr> <tr><td></td><td colspan="5" style="white-space: pre;"><i>Herkunft:</i> @part.OriginString</td></tr>
@if (part.Modifiers.Count() > 0) { @if (part.Modifiers.Count() > 0) {
var first = true; var first = true;
@ -52,8 +60,8 @@
} }
} }
<tr><td></td><td colspan="5"> <tr><td></td><td colspan="5">
@Raw(part.ManualWeighing ? "<i>Handwiegung</i>" : $"<i>Waage:</i> {part.ScaleId ?? "?"}, <i>ID:</i> {part.WeighingId ?? "?"}") @Raw(part.IsManualWeighing ? "<i>Handwiegung</i>" : $"<i>Waage:</i> {part.ScaleId ?? "?"}, <i>ID:</i> {part.WeighingId ?? "?"}")
(@(part.IsGerebelt ? "gerebelt gewogen" : "nicht gerebelt gewogen"))@Raw(part.WeighingReason != null ? $", <i>Begründung:</i>" : "") @part.WeighingReason (@(part.IsNetWeight ? "gerebelt gewogen" : "nicht gerebelt gewogen"))@Raw(part.WeighingReason != null ? $", <i>Begründung:</i>" : "") @part.WeighingReason
</td></tr> </td></tr>
@if (part.Comment != null) { @if (part.Comment != null) {
<tr><td></td><td colspan="5"><i>Anmerkung:</i> @part.Comment</td></tr> <tr><td></td><td colspan="5"><i>Anmerkung:</i> @part.Comment</td></tr>

View File

@ -17,6 +17,7 @@ namespace Elwig.Helpers {
public record struct AreaComBucket(int Area, int Obligation, int Right); public record struct AreaComBucket(int Area, int Obligation, int Right);
public record struct UnderDelivery(int Weight, int Diff); 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 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 { public class AppDbContext : DbContext {
@ -159,6 +160,10 @@ namespace Elwig.Helpers {
return await WineAttributes.FindAsync(attrId) != null; return await WineAttributes.FindAsync(attrId) != null;
} }
public async Task<bool> CultIdExists(string cultId) {
return await WineCultivations.FindAsync(cultId) != null;
}
public async Task<int> NextMgNr() { public async Task<int> NextMgNr() {
int c = 0; int c = 0;
(await Members.OrderBy(m => m.MgNr).Select(m => m.MgNr).ToListAsync()) (await Members.OrderBy(m => m.MgNr).Select(m => m.MgNr).ToListAsync())
@ -384,5 +389,31 @@ namespace Elwig.Helpers {
} }
return buckets; return buckets;
} }
public static async Task<List<MemberStat>> GetMemberStats(int year, int mgnr, SqliteConnection? cnx = null) {
var ownCnx = cnx == null;
cnx ??= await ConnectAsync();
var list = new List<MemberStat>();
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;
}
} }
} }

View File

@ -9,7 +9,7 @@ namespace Elwig.Helpers {
public static class AppDbUpdater { public static class AppDbUpdater {
// Don't forget to update value in Tests/fetch-resources.bat! // Don't forget to update value in Tests/fetch-resources.bat!
public static readonly int RequiredSchemaVersion = 17; public static readonly int RequiredSchemaVersion = 18;
private static int VersionOffset = 0; private static int VersionOffset = 0;

View File

@ -454,9 +454,9 @@ namespace Elwig.Helpers {
if (input.Text.Length < 2 || !ctx.SortIdExists(input.Text[0..2]).GetAwaiter().GetResult()) { if (input.Text.Length < 2 || !ctx.SortIdExists(input.Text[0..2]).GetAwaiter().GetResult()) {
return new(false, "Ungültige Sorte"); return new(false, "Ungültige Sorte");
} else if (input.Text.Length >= 3) { } else if (input.Text.Length >= 3) {
var attr = input.Text[2..]; var disc = input.Text[2..];
if (!ctx.AttrIdExists(attr).GetAwaiter().GetResult()) { if (!ctx.AttrIdExists(disc).GetAwaiter().GetResult() && !ctx.CultIdExists(disc).GetAwaiter().GetResult()) {
return new(false, "Ungültiges Attribut"); return new(false, "Ungültiges Attribut/Bewirt.");
} }
} }

View File

@ -43,10 +43,11 @@ namespace Elwig.Models.Dtos {
return await table.FromSqlRaw($""" return await table.FromSqlRaw($"""
SELECT d.year, c.tgnr, v.avnr, d.mgnr, d.did, d.lsnr, d.dpnr, d.weight, d.modifiers, 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, 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 FROM v_delivery d
JOIN wine_variety s ON s.sortid = d.sortid JOIN wine_variety s ON s.sortid = d.sortid
LEFT JOIN wine_attribute a ON a.attrid = d.attrid 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 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 delivery_part_bucket b ON (b.year, b.did, b.dpnr) = (d.year, d.did, d.dpnr)
LEFT JOIN payment_variant v ON v.year = d.year LEFT JOIN payment_variant v ON v.year = d.year
@ -70,6 +71,7 @@ namespace Elwig.Models.Dtos {
public int DPNr; public int DPNr;
public string Variety; public string Variety;
public string? Attribute; public string? Attribute;
public string? Cultivation;
public string[] Modifiers; public string[] Modifiers;
public string QualityLevel; public string QualityLevel;
public (double Oe, double Kmw) Gradation; public (double Oe, double Kmw) Gradation;
@ -88,6 +90,7 @@ namespace Elwig.Models.Dtos {
DPNr = f.DPNr; DPNr = f.DPNr;
Variety = f.Variety; Variety = f.Variety;
Attribute = f.Attribute; Attribute = f.Attribute;
Cultivation = f.Cultivation;
var modifiers = (IEnumerable<Modifier>)(f.Modifiers ?? "").Split(',') var modifiers = (IEnumerable<Modifier>)(f.Modifiers ?? "").Split(',')
.Select(m => season?.Modifiers.FirstOrDefault(s => s.ModId == m)) .Select(m => season?.Modifiers.FirstOrDefault(s => s.ModId == m))
.Where(m => m != null) .Where(m => m != null)
@ -149,6 +152,8 @@ namespace Elwig.Models.Dtos {
public string Variety { get; set; } public string Variety { get; set; }
[Column("attribute")] [Column("attribute")]
public string? Attribute { get; set; } public string? Attribute { get; set; }
[Column("cultivation")]
public string? Cultivation { get; set; }
[Column("quality_level")] [Column("quality_level")]
public string QualityLevel { get; set; } public string QualityLevel { get; set; }
[Column("oe")] [Column("oe")]

View File

@ -73,6 +73,7 @@ namespace Elwig.Models.Dtos {
public int DPNr; public int DPNr;
public string Variety; public string Variety;
public string? Attribute; public string? Attribute;
public string? Cultivation;
public string QualityLevel; public string QualityLevel;
public (double Oe, double Kmw) Gradation; public (double Oe, double Kmw) Gradation;
public string[] Modifiers; public string[] Modifiers;
@ -85,6 +86,7 @@ namespace Elwig.Models.Dtos {
DPNr = p.DPNr; DPNr = p.DPNr;
Variety = p.Variety.Name; Variety = p.Variety.Name;
Attribute = p.Attribute?.Name; Attribute = p.Attribute?.Name;
Cultivation = p.Cultivation?.Name;
QualityLevel = p.Quality.Name; QualityLevel = p.Quality.Name;
Gradation = (p.Oe, p.Kmw); Gradation = (p.Oe, p.Kmw);
Modifiers = p.Modifiers Modifiers = p.Modifiers

View File

@ -17,7 +17,7 @@ namespace Elwig.Models.Entities {
public string VtrgId { get; set; } public string VtrgId { get; set; }
[Column("cultid")] [Column("cultid")]
public string CultId { get; set; } public string? CultId { get; set; }
[Column("area")] [Column("area")]
public int Area { get; set; } public int Area { get; set; }
@ -47,7 +47,7 @@ namespace Elwig.Models.Entities {
public virtual AreaComType AreaComType { get; private set; } public virtual AreaComType AreaComType { get; private set; }
[ForeignKey("CultId")] [ForeignKey("CultId")]
public virtual WineCult WineCult { get; private set; } public virtual WineCult? WineCult { get; private set; }
[ForeignKey("KgNr")] [ForeignKey("KgNr")]
public virtual WbKg Kg { get; private set; } public virtual WbKg Kg { get; private set; }
@ -57,7 +57,7 @@ namespace Elwig.Models.Entities {
public int SearchScore(IEnumerable<string> keywords) { public int SearchScore(IEnumerable<string> keywords) {
var list = new string?[] { var list = new string?[] {
WineCult.Name, Kg.AtKg.Name, Rd.Name, GstNr, Comment, WineCult?.Name, Kg.AtKg.Name, Rd.Name, GstNr, Comment,
}.ToList(); }.ToList();
return Utils.GetSearchScore(list, keywords); return Utils.GetSearchScore(list, keywords);
} }

View File

@ -31,6 +31,12 @@ namespace Elwig.Models.Entities {
[ForeignKey("AttrId")] [ForeignKey("AttrId")]
public virtual WineAttr? Attribute { get; private set; } 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")] [Column("weight")]
public int Weight { get; set; } public int Weight { get; set; }
@ -66,14 +72,14 @@ namespace Elwig.Models.Entities {
[ForeignKey("KgNr, RdNr")] [ForeignKey("KgNr, RdNr")]
public virtual WbRd? Rd { get; private set; } public virtual WbRd? Rd { get; private set; }
[Column("gerebelt")] [Column("net_weight")]
public bool IsGerebelt { get; set; } public bool IsNetWeight { get; set; }
[Column("manual_weighing")] [Column("manual_weighing")]
public bool ManualWeighing { get; set; } public bool IsManualWeighing { get; set; }
[Column("spl_check")] [Column("spl_check")]
public bool SplCheck { get; set; } public bool IsSplCheck { get; set; }
[Column("hand_picked")] [Column("hand_picked")]
public bool? IsHandPicked { get; set; } public bool? IsHandPicked { get; set; }

View File

@ -43,7 +43,7 @@
} }
}, },
"patternProperties": { "patternProperties": {
"^([A-Z]{2})?(\/[A-Z]*)?$": { "^([A-Z]{2})?(\/[A-Z]*)?(-[A-Z][A-Z0-9]*)?$": {
"type": ["number", "string"], "type": ["number", "string"],
"pattern": "^curve:[0-9]+$" "pattern": "^curve:[0-9]+$"
} }
@ -64,7 +64,7 @@
} }
}, },
"patternProperties": { "patternProperties": {
"^([A-Z]{2})?(\/[A-Z]*)?$": { "^([A-Z]{2})?(\/[A-Z]*)?(-[A-Z][A-Z0-9]*)?$": {
"type": ["number", "string"], "type": ["number", "string"],
"pattern": "^curve:[0-9]+$" "pattern": "^curve:[0-9]+$"
} }

View File

@ -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"');

View File

@ -280,21 +280,25 @@
<GroupBox Header="Sorte" Grid.Column="1" Grid.Row="0" Margin="5,5,5,5"> <GroupBox Header="Sorte" Grid.Column="1" Grid.Row="0" Margin="5,5,5,5">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="70"/> <ColumnDefinition Width="80"/>
<ColumnDefinition/>
<ColumnDefinition/> <ColumnDefinition/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<Label Content="Sorte:" Margin="10,10,0,0" Grid.Column="0"/> <Label Content="Sorte:" Margin="10,10,0,0" Grid.Column="0"/>
<TextBox x:Name="SortIdInput" Width="36" Grid.Row="1" Grid.Column="1" Margin="0,10,0,0" HorizontalAlignment="Left" <TextBox x:Name="SortIdInput" Width="36" Grid.Row="1" Grid.Column="1" Margin="0,10,0,0" HorizontalAlignment="Left"
TextChanged="SortIdInput_TextChanged" LostFocus="SortIdInput_LostFocus" KeyUp="Input_KeyUp"/> TextChanged="SortIdInput_TextChanged" LostFocus="SortIdInput_LostFocus" KeyUp="Input_KeyUp"/>
<ComboBox x:Name="WineVarietyInput" Grid.Row="1" Grid.Column="1" Margin="41,10,10,10" <ComboBox x:Name="WineVarietyInput" Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="2" Margin="41,10,10,10"
ItemTemplate="{StaticResource WineVarietyTemplate}" TextSearch.TextPath="Name" ItemTemplate="{StaticResource WineVarietyTemplate}" TextSearch.TextPath="Name"
SelectionChanged="WineVarietyInput_SelectionChanged" KeyUp="Input_KeyUp"/> SelectionChanged="WineVarietyInput_SelectionChanged" KeyUp="Input_KeyUp"/>
<Label Content="Attribut:" Margin="10,40,0,0" Grid.Column="0"/> <Label Content="Attr./Bewirt.:" Margin="10,40,0,0" Grid.Column="0"/>
<ComboBox x:Name="AttributeInput" Grid.Row="1" Grid.Column="1" Margin="0,40,10,10" <ComboBox x:Name="AttributeInput" Grid.Row="1" Grid.Column="1" Margin="0,40,5,10"
DisplayMemberPath="Name" DisplayMemberPath="Name"
SelectionChanged="AttributeInput_SelectionChanged" KeyUp="Input_KeyUp"/> SelectionChanged="AttributeInput_SelectionChanged" KeyUp="Input_KeyUp"/>
<ComboBox x:Name="CultivationInput" Grid.Row="1" Grid.Column="2" Margin="0,40,10,10"
DisplayMemberPath="Name"
SelectionChanged="CultivationInput_SelectionChanged" KeyUp="Input_KeyUp"/>
</Grid> </Grid>
</GroupBox> </GroupBox>

View File

@ -292,7 +292,7 @@ namespace Elwig.Windows {
if (ctrl == MgNrInput || ctrl == MemberInput) { if (ctrl == MgNrInput || ctrl == MemberInput) {
SortIdInput.Focus(); SortIdInput.Focus();
SortIdInput.SelectAll(); SortIdInput.SelectAll();
} else if (ctrl == SortIdInput || ctrl == WineVarietyInput || ctrl == AttributeInput) { } else if (ctrl == SortIdInput || ctrl == WineVarietyInput || ctrl == AttributeInput || ctrl == CultivationInput) {
GradationOeInput.Focus(); GradationOeInput.Focus();
GradationOeInput.TextBox.SelectAll(); GradationOeInput.TextBox.SelectAll();
} else if (ctrl == GradationKmwInput || ctrl == GradationOeInput || ctrl == WineQualityLevelInput) { } 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<object>().ToListAsync(); var attrList = await Context.WineAttributes.Where(a => !IsCreating || a.IsActive).OrderBy(a => a.Name).Cast<object>().ToListAsync();
attrList.Insert(0, new NullItem("")); attrList.Insert(0, new NullItem(""));
ControlUtils.RenewItemsSource(AttributeInput, attrList, i => (i as WineAttr)?.AttrId, null, ControlUtils.RenewSourceDefault.First); ControlUtils.RenewItemsSource(AttributeInput, attrList, i => (i as WineAttr)?.AttrId, null, ControlUtils.RenewSourceDefault.First);
var cultList = await Context.WineCultivations.OrderBy(a => a.Name).Cast<object>().ToListAsync();
cultList.Insert(0, new NullItem(""));
ControlUtils.RenewItemsSource(CultivationInput, cultList, i => (i as WineCult)?.CultId, null, ControlUtils.RenewSourceDefault.First);
ControlUtils.RenewItemsSource(WineQualityLevelInput, await Context.WineQualityLevels.ToListAsync(), i => (i as WineQualLevel)?.QualId); ControlUtils.RenewItemsSource(WineQualityLevelInput, await Context.WineQualityLevels.ToListAsync(), i => (i as WineQualLevel)?.QualId);
ControlUtils.RenewItemsSource(ModifiersInput, await Context.Modifiers.Where(m => m.Year == y).OrderBy(m => m.Ordering).ToListAsync(), i => (i as Modifier)?.ModId); ControlUtils.RenewItemsSource(ModifiersInput, await Context.Modifiers.Where(m => m.Year == y).OrderBy(m => m.Ordering).ToListAsync(), i => (i as Modifier)?.ModId);
ControlUtils.RenewItemsSource(WineOriginInput, (await Context.WineOrigins.ToListAsync()).OrderByDescending(o => o.SortKey).ThenBy(o => o.HkId), i => (i as WineOrigin)?.HkId); ControlUtils.RenewItemsSource(WineOriginInput, (await Context.WineOrigins.ToListAsync()).OrderByDescending(o => o.SortKey).ThenBy(o => o.HkId), i => (i as WineOrigin)?.HkId);
@ -836,14 +839,15 @@ namespace Elwig.Windows {
SortIdInput.Text = p?.SortId ?? ""; SortIdInput.Text = p?.SortId ?? "";
ControlUtils.SelectComboBoxItem(AttributeInput, p?.Attribute, i => (i as WineAttr)?.AttrId); ControlUtils.SelectComboBoxItem(AttributeInput, p?.Attribute, i => (i as WineAttr)?.AttrId);
ControlUtils.SelectComboBoxItem(CultivationInput, p?.Cultivation, i => (i as WineCult)?.CultId);
GradationKmwInput.Text = (p != null) ? $"{p.Kmw:N1}" : ""; GradationKmwInput.Text = (p != null) ? $"{p.Kmw:N1}" : "";
ControlUtils.SelectComboBoxItem(WineQualityLevelInput, q => (q as WineQualLevel)?.QualId, p?.QualId); ControlUtils.SelectComboBoxItem(WineQualityLevelInput, q => (q as WineQualLevel)?.QualId, p?.QualId);
ControlUtils.SelectComboBoxItem(WineKgInput, k => (k as AT_Kg)?.KgNr, p?.KgNr); ControlUtils.SelectComboBoxItem(WineKgInput, k => (k as AT_Kg)?.KgNr, p?.KgNr);
ControlUtils.SelectComboBoxItem(WineRdInput, r => (r as WbRd)?.RdNr, p?.RdNr); ControlUtils.SelectComboBoxItem(WineRdInput, r => (r as WbRd)?.RdNr, p?.RdNr);
ControlUtils.SelectComboBoxItem(WineOriginInput, r => (r as WineOrigin)?.HkId, p?.HkId); ControlUtils.SelectComboBoxItem(WineOriginInput, r => (r as WineOrigin)?.HkId, p?.HkId);
WeightInput.Text = (p != null) ? $"{p.Weight:N0}" : ""; WeightInput.Text = (p != null) ? $"{p.Weight:N0}" : "";
ManualWeighingInput.IsChecked = p?.ManualWeighing ?? false; ManualWeighingInput.IsChecked = p?.IsManualWeighing ?? false;
GerebeltGewogenInput.IsChecked = p?.IsGerebelt ?? false; GerebeltGewogenInput.IsChecked = p?.IsNetWeight ?? false;
ControlUtils.SelectCheckComboBoxItems(ModifiersInput, p?.Modifiers, i => (i as Modifier)?.ModId); ControlUtils.SelectCheckComboBoxItems(ModifiersInput, p?.Modifiers, i => (i as Modifier)?.ModId);
PartCommentInput.Text = p?.Comment ?? ""; PartCommentInput.Text = p?.Comment ?? "";
TemperatureInput.Text = (p != null && p.Temperature != null) ? $"{p.Temperature:N1}" : ""; TemperatureInput.Text = (p != null && p.Temperature != null) ? $"{p.Temperature:N1}" : "";
@ -900,13 +904,14 @@ namespace Elwig.Windows {
p.SortId = (WineVarietyInput.SelectedItem as WineVar)?.SortId; p.SortId = (WineVarietyInput.SelectedItem as WineVar)?.SortId;
p.AttrId = (AttributeInput.SelectedItem as WineAttr)?.AttrId; p.AttrId = (AttributeInput.SelectedItem as WineAttr)?.AttrId;
p.CultId = (CultivationInput.SelectedItem as WineCult)?.CultId;
p.Kmw = double.Parse(GradationKmwInput.Text); p.Kmw = double.Parse(GradationKmwInput.Text);
p.QualId = (WineQualityLevelInput.SelectedItem as WineQualLevel)?.QualId; p.QualId = (WineQualityLevelInput.SelectedItem as WineQualLevel)?.QualId;
p.HkId = (WineOriginInput.SelectedItem as WineOrigin)?.HkId; p.HkId = (WineOriginInput.SelectedItem as WineOrigin)?.HkId;
p.KgNr = (WineKgInput.SelectedItem as AT_Kg)?.KgNr; p.KgNr = (WineKgInput.SelectedItem as AT_Kg)?.KgNr;
p.RdNr = (WineRdInput.SelectedItem as WbRd)?.RdNr; p.RdNr = (WineRdInput.SelectedItem as WbRd)?.RdNr;
p.IsGerebelt = GerebeltGewogenInput.IsChecked ?? false; p.IsNetWeight = GerebeltGewogenInput.IsChecked ?? false;
p.IsHandPicked = HandPickedInput.IsChecked; p.IsHandPicked = HandPickedInput.IsChecked;
p.IsLesewagen = LesewagenInput.IsChecked; p.IsLesewagen = LesewagenInput.IsChecked;
p.IsGebunden = GebundenInput.IsChecked; p.IsGebunden = GebundenInput.IsChecked;
@ -915,7 +920,7 @@ namespace Elwig.Windows {
p.Comment = (PartCommentInput.Text == "") ? null : PartCommentInput.Text; p.Comment = (PartCommentInput.Text == "") ? null : PartCommentInput.Text;
p.Weight = int.Parse(WeightInput.Text.Replace(Utils.GroupSeparator, "")); p.Weight = int.Parse(WeightInput.Text.Replace(Utils.GroupSeparator, ""));
p.ManualWeighing = ManualWeighingInput.IsChecked ?? false; p.IsManualWeighing = ManualWeighingInput.IsChecked ?? false;
p.ScaleId = ScaleId; p.ScaleId = ScaleId;
p.WeighingId = WeighingId; p.WeighingId = WeighingId;
p.WeighingReason = ManualWeighingReason; p.WeighingReason = ManualWeighingReason;
@ -1563,11 +1568,13 @@ namespace Elwig.Windows {
WineVarietyInput.SelectedItem = Context.WineVarieties.Find(text[0..2]); WineVarietyInput.SelectedItem = Context.WineVarieties.Find(text[0..2]);
if (text.Length >= 3) { if (text.Length >= 3) {
ControlUtils.SelectComboBoxItem(AttributeInput, Context.WineAttributes.Find(text[2..]), a => (a as WineAttr)?.AttrId); ControlUtils.SelectComboBoxItem(AttributeInput, Context.WineAttributes.Find(text[2..]), a => (a as WineAttr)?.AttrId);
ControlUtils.SelectComboBoxItem(CultivationInput, Context.WineCultivations.Find(text[2..]), i => (i as WineCult)?.CultId);
SortIdInput.Text = text[0..2]; SortIdInput.Text = text[0..2];
} }
} else { } else {
WineVarietyInput.SelectedItem = null; WineVarietyInput.SelectedItem = null;
AttributeInput.SelectedIndex = 0; AttributeInput.SelectedIndex = 0;
CultivationInput.SelectedIndex = 0;
} }
} }
@ -1648,6 +1655,10 @@ namespace Elwig.Windows {
} }
private void CultivationInput_SelectionChanged(object sender, SelectionChangedEventArgs evt) {
}
private void ModifiersInput_SelectionChanged(object sender, ItemSelectionChangedEventArgs evt) { private void ModifiersInput_SelectionChanged(object sender, ItemSelectionChangedEventArgs evt) {
if (!IsEditing && !IsCreating) return; if (!IsEditing && !IsCreating) return;
var mod = ModifiersInput.SelectedItems.Cast<Modifier>(); var mod = ModifiersInput.SelectedItems.Cast<Modifier>();

View File

@ -42,7 +42,7 @@ INSERT INTO delivery (mgnr, year, did, date, time, zwstid, lnr) VALUES
(101, 2020, 1, '2020-10-01', NULL, 'X', 1), (101, 2020, 1, '2020-10-01', NULL, 'X', 1),
(101, 2020, 2, '2020-10-01', NULL, 'X', 2), (101, 2020, 2, '2020-10-01', NULL, 'X', 2),
(101, 2020, 3, '2020-10-01', NULL, 'X', 3); (101, 2020, 3, '2020-10-01', NULL, 'X', 3);
INSERT INTO delivery_part (year, did, dpnr, sortid, attrid, weight, kmw, qualid, hkid, kgnr, gerebelt, manual_weighing, spl_check, scale_id, weighing_id, weighing_reason) VALUES INSERT INTO delivery_part (year, did, dpnr, sortid, attrid, weight, kmw, qualid, hkid, kgnr, net_weight, manual_weighing, spl_check, scale_id, weighing_id, weighing_reason) VALUES
(2020, 1, 1, 'GV', 'K', 4000, 17, 'KAB', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL), (2020, 1, 1, 'GV', 'K', 4000, 17, 'KAB', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 1, 2, 'GV', NULL, 4000, 16, 'QUW', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL), (2020, 1, 2, 'GV', NULL, 4000, 16, 'QUW', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2020, 2, 1, 'GV', 'B', 4000, 15, 'QUW', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL), (2020, 2, 1, 'GV', 'B', 4000, 15, 'QUW', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL),
@ -57,7 +57,7 @@ INSERT INTO delivery (mgnr, year, did, date, time, zwstid, lnr) VALUES
(101, 2021, 1, '2021-10-01', NULL, 'X', 1), (101, 2021, 1, '2021-10-01', NULL, 'X', 1),
(101, 2021, 2, '2021-10-01', NULL, 'X', 2), (101, 2021, 2, '2021-10-01', NULL, 'X', 2),
(101, 2021, 3, '2021-10-01', NULL, 'X', 3); (101, 2021, 3, '2021-10-01', NULL, 'X', 3);
INSERT INTO delivery_part (year, did, dpnr, sortid, attrid, weight, kmw, qualid, hkid, kgnr, gebunden, gerebelt, manual_weighing, spl_check, scale_id, weighing_id, weighing_reason) VALUES INSERT INTO delivery_part (year, did, dpnr, sortid, attrid, weight, kmw, qualid, hkid, kgnr, gebunden, net_weight, manual_weighing, spl_check, scale_id, weighing_id, weighing_reason) VALUES
(2021, 1, 1, 'GV', 'K', 4000, 17, 'KAB', 'WLNO', 06109, TRUE, TRUE, FALSE, FALSE, NULL, NULL, NULL), (2021, 1, 1, 'GV', 'K', 4000, 17, 'KAB', 'WLNO', 06109, TRUE, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2021, 1, 2, 'GV', NULL, 4000, 16, 'QUW', 'WLNO', 06109, FALSE, TRUE, FALSE, FALSE, NULL, NULL, NULL), (2021, 1, 2, 'GV', NULL, 4000, 16, 'QUW', 'WLNO', 06109, FALSE, TRUE, FALSE, FALSE, NULL, NULL, NULL),
(2021, 2, 1, 'GV', 'B', 4000, 15, 'QUW', 'WLNO', 06109, TRUE, TRUE, FALSE, FALSE, NULL, NULL, NULL), (2021, 2, 1, 'GV', 'B', 4000, 15, 'QUW', 'WLNO', 06109, TRUE, TRUE, FALSE, FALSE, NULL, NULL, NULL),

View File

@ -16,5 +16,5 @@ INSERT INTO delivery (mgnr, year, did, date, time, zwstid, lnr) VALUES
(101, 2020, 2, '2020-10-01', NULL, 'X', 2), (101, 2020, 2, '2020-10-01', NULL, 'X', 2),
(101, 2020, 3, '2020-10-01', NULL, 'X', 3); (101, 2020, 3, '2020-10-01', NULL, 'X', 3);
INSERT INTO delivery_part (year, did, dpnr, sortid, attrid, weight, kmw, qualid, hkid, kgnr, gerebelt, manual_weighing, spl_check, scale_id, weighing_id, weighing_reason) VALUES INSERT INTO delivery_part (year, did, dpnr, sortid, attrid, weight, kmw, qualid, hkid, kgnr, net_weight, manual_weighing, spl_check, scale_id, weighing_id, weighing_reason) VALUES
(2020, 1, 1, 'GV', NULL, 4000, 17, 'KAB', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL); (2020, 1, 1, 'GV', NULL, 4000, 17, 'KAB', 'WLNO', 06109, TRUE, FALSE, FALSE, NULL, NULL, NULL);

View File

@ -1 +1 @@
curl -s -L "https://www.necronda.net/elwig/files/create.sql?v=17" -u "elwig:ganzGeheim123!" -o "Resources\Sql\Create.sql" curl -s -L "https://www.necronda.net/elwig/files/create.sql?v=18" -u "elwig:ganzGeheim123!" -o "Resources\Sql\Create.sql"