From 2d737e27801f290924df8a216885a67ce6c246a5 Mon Sep 17 00:00:00 2001 From: Lorenz Stechauner Date: Fri, 2 Aug 2024 21:14:08 +0200 Subject: [PATCH] [#14] Models: Add DeliveryAncmt --- Elwig/Helpers/AppDbContext.cs | 3 + Elwig/Helpers/AppDbUpdater.cs | 2 +- Elwig/Models/Entities/AreaCom.cs | 11 +++ Elwig/Models/Entities/Credit.cs | 6 +- Elwig/Models/Entities/Delivery.cs | 12 ++- Elwig/Models/Entities/DeliveryAncmt.cs | 56 ++++++++++++ Elwig/Models/Entities/DeliveryPart.cs | 10 ++ Elwig/Models/Entities/DeliverySchedule.cs | 63 +++++++++++++ .../Entities/DeliveryScheduleWineVar.cs | 26 ++++++ Elwig/Models/Entities/Member.cs | 14 ++- Elwig/Models/Entities/PaymentVar.cs | 14 ++- Elwig/Resources/Sql/25-26.sql | 91 +++++++++++++++++++ Tests/fetch-resources.bat | 2 +- 13 files changed, 297 insertions(+), 13 deletions(-) create mode 100644 Elwig/Models/Entities/DeliveryAncmt.cs create mode 100644 Elwig/Models/Entities/DeliverySchedule.cs create mode 100644 Elwig/Models/Entities/DeliveryScheduleWineVar.cs create mode 100644 Elwig/Resources/Sql/25-26.sql diff --git a/Elwig/Helpers/AppDbContext.cs b/Elwig/Helpers/AppDbContext.cs index 217ab76..e1c9847 100644 --- a/Elwig/Helpers/AppDbContext.cs +++ b/Elwig/Helpers/AppDbContext.cs @@ -51,6 +51,9 @@ namespace Elwig.Helpers { public DbSet MemberHistory { get; private set; } public DbSet AreaCommitments { get; private set; } public DbSet Seasons { get; private set; } + public DbSet DeliverySchedules { get; private set; } + public DbSet DeliveryScheduleWineVarieties { get; private set; } + public DbSet DeliveryAnnouncements { get; private set; } public DbSet Modifiers { get; private set; } public DbSet Deliveries { get; private set; } public DbSet DeliveryParts { get; private set; } diff --git a/Elwig/Helpers/AppDbUpdater.cs b/Elwig/Helpers/AppDbUpdater.cs index aa239bb..631ba88 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 = 25; + public static readonly int RequiredSchemaVersion = 26; private static int VersionOffset = 0; diff --git a/Elwig/Models/Entities/AreaCom.cs b/Elwig/Models/Entities/AreaCom.cs index 07278b1..e238f97 100644 --- a/Elwig/Models/Entities/AreaCom.cs +++ b/Elwig/Models/Entities/AreaCom.cs @@ -1,5 +1,6 @@ using Elwig.Helpers; using Microsoft.EntityFrameworkCore; +using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations.Schema; @@ -39,6 +40,16 @@ namespace Elwig.Models.Entities { [Column("comment")] public string? Comment { get; set; } + [Column("ctime"), DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public long CTime { get; private set; } + [NotMapped] + public DateTime CreatedTimestamp => DateTimeOffset.FromUnixTimeSeconds(CTime).LocalDateTime; + + [Column("mtime"), DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public long MTime { get; private set; } + [NotMapped] + public DateTime ModifiedTimestamp => DateTimeOffset.FromUnixTimeSeconds(MTime).LocalDateTime; + [ForeignKey("MgNr")] public virtual Member Member { get; private set; } = null!; diff --git a/Elwig/Models/Entities/Credit.cs b/Elwig/Models/Entities/Credit.cs index e75ed9a..d257363 100644 --- a/Elwig/Models/Entities/Credit.cs +++ b/Elwig/Models/Entities/Credit.cs @@ -83,15 +83,15 @@ namespace Elwig.Models.Entities { get => Utils.DecFromDb(AmountValue, 2); } - [Column("ctime")] + [Column("ctime"), DatabaseGenerated(DatabaseGeneratedOption.Computed)] public long CTime { get; private set; } [NotMapped] public DateTime CreatedTimestamp => DateTimeOffset.FromUnixTimeSeconds(CTime).LocalDateTime; - [Column("mtime")] + [Column("mtime"), DatabaseGenerated(DatabaseGeneratedOption.Computed)] public long MTime { get; private set; } [NotMapped] - public DateTime ModifiedTimestamp => DateTimeOffset.FromUnixTimeSeconds(CTime).LocalDateTime; + public DateTime ModifiedTimestamp => DateTimeOffset.FromUnixTimeSeconds(MTime).LocalDateTime; [ForeignKey("Year, AvNr, MgNr")] public virtual PaymentMember Payment { get; private set; } = null!; diff --git a/Elwig/Models/Entities/Delivery.cs b/Elwig/Models/Entities/Delivery.cs index f3ad394..2979a31 100644 --- a/Elwig/Models/Entities/Delivery.cs +++ b/Elwig/Models/Entities/Delivery.cs @@ -17,7 +17,6 @@ namespace Elwig.Models.Entities { [Column("date")] public required string DateString { get; set; } - [NotMapped] public DateOnly Date { get => DateOnly.ParseExact(DateString, "yyyy-MM-dd"); @@ -26,7 +25,6 @@ namespace Elwig.Models.Entities { [Column("time")] public string? TimeString { get; set; } - [NotMapped] public TimeOnly? Time { get => (TimeString == null) ? null : TimeOnly.ParseExact(TimeString, "HH:mm:ss"); @@ -63,6 +61,16 @@ namespace Elwig.Models.Entities { [Column("comment")] public string? Comment { get; set; } + [Column("ctime"), DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public long CTime { get; private set; } + [NotMapped] + public DateTime CreatedTimestamp => DateTimeOffset.FromUnixTimeSeconds(CTime).LocalDateTime; + + [Column("mtime"), DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public long MTime { get; private set; } + [NotMapped] + public DateTime ModifiedTimestamp => DateTimeOffset.FromUnixTimeSeconds(MTime).LocalDateTime; + [ForeignKey("Year")] public virtual Season Season { get; private set; } = null!; diff --git a/Elwig/Models/Entities/DeliveryAncmt.cs b/Elwig/Models/Entities/DeliveryAncmt.cs new file mode 100644 index 0000000..ac4dbcd --- /dev/null +++ b/Elwig/Models/Entities/DeliveryAncmt.cs @@ -0,0 +1,56 @@ +using Elwig.Helpers; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Elwig.Models.Entities { + [Table("delivery_announcement"), PrimaryKey("Year", "DsNr", "MgNr", "SortId")] + public class DeliveryAncmt { + + [Column("year")] + public int Year { get; set; } + + [Column("dsnr")] + public int DsNr { get; set; } + + [Column("mgnr")] + public int MgNr { get; set; } + + [Column("sortid")] + public required string SortId { get; set; } + + [Column("weight")] + public int Weight { get; set; } + + [Column("type")] + public required string Type { get; set; } + + [Column("ctime"), DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public long CTime { get; private set; } + [NotMapped] + public DateTime CreatedTimestamp => DateTimeOffset.FromUnixTimeSeconds(CTime).LocalDateTime; + + [Column("mtime"), DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public long MTime { get; private set; } + [NotMapped] + public DateTime ModifiedTimestamp => DateTimeOffset.FromUnixTimeSeconds(MTime).LocalDateTime; + + [ForeignKey("Year, DsNr")] + public virtual DeliverySchedule Schedule { get; private set; } = null!; + + [ForeignKey("MgNr")] + public virtual Member Member { get; private set; } = null!; + + [ForeignKey("SortId")] + public virtual WineVar Variety { get; private set; } = null!; + + public int SearchScore(IEnumerable keywords) { + return Utils.GetSearchScore([ + Schedule.Description, + Member.FamilyName, Member.MiddleName, Member.GivenName, + Member.BillingAddress?.Name, + ], keywords); + } + } +} diff --git a/Elwig/Models/Entities/DeliveryPart.cs b/Elwig/Models/Entities/DeliveryPart.cs index 4368991..2fd2834 100644 --- a/Elwig/Models/Entities/DeliveryPart.cs +++ b/Elwig/Models/Entities/DeliveryPart.cs @@ -128,6 +128,16 @@ namespace Elwig.Models.Entities { [Column("comment")] public string? Comment { get; set; } + [Column("ctime"), DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public long CTime { get; private set; } + [NotMapped] + public DateTime CreatedTimestamp => DateTimeOffset.FromUnixTimeSeconds(CTime).LocalDateTime; + + [Column("mtime"), DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public long MTime { get; private set; } + [NotMapped] + public DateTime ModifiedTimestamp => DateTimeOffset.FromUnixTimeSeconds(MTime).LocalDateTime; + [InverseProperty(nameof(DeliveryPartModifier.Part))] public virtual ICollection PartModifiers { get; private set; } = null!; diff --git a/Elwig/Models/Entities/DeliverySchedule.cs b/Elwig/Models/Entities/DeliverySchedule.cs new file mode 100644 index 0000000..43ce315 --- /dev/null +++ b/Elwig/Models/Entities/DeliverySchedule.cs @@ -0,0 +1,63 @@ +using Elwig.Helpers; +using Microsoft.EntityFrameworkCore; +using System; +using System.Collections.Generic; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Elwig.Models.Entities { + [Table("delivery_schedule"), PrimaryKey("Year", "DsNr")] + public class DeliverySchedule { + + [Column("year")] + public int Year { get; set; } + + [Column("dsnr")] + public int DsNr { get; set; } + + [Column("date")] + public required string DateString { get; set; } + [NotMapped] + public DateOnly Date { + get => DateOnly.ParseExact(DateString, "yyyy-MM-dd"); + set => DateString = value.ToString("yyyy-MM-dd"); + } + + [Column("zwstid")] + public required string ZwstId { get; set; } + + [Column("description")] + public required string Description { get; set; } + + [Column("max_weight")] + public int? MaxWeight { get; set; } + + [Column("ancmt_from")] + public long? AncmtFromUnix { get; set; } + [NotMapped] + public DateTime? AncmtFrom { + get => AncmtFromUnix != null ? DateTimeOffset.FromUnixTimeSeconds(AncmtFromUnix.Value).LocalDateTime : null; + set => AncmtFromUnix = value != null ? new DateTimeOffset(value.Value).ToUnixTimeSeconds() : null; + } + + [Column("ancmt_to")] + public long? AncmtToUnix { get; set; } + [NotMapped] + public DateTime? AncmtTo { + get => AncmtToUnix != null ? DateTimeOffset.FromUnixTimeSeconds(AncmtToUnix.Value).LocalDateTime : null; + set => AncmtToUnix = value != null ? new DateTimeOffset(value.Value).ToUnixTimeSeconds() : null; + } + + [ForeignKey("Year")] + public virtual Season Season { get; private set; } = null!; + + [ForeignKey("ZwstId")] + public virtual Branch Branch { get; private set; } = null!; + + [InverseProperty(nameof(DeliveryScheduleWineVar.Schedule))] + public virtual ICollection Varieties { get; private set; } = null!; + + public int SearchScore(IEnumerable keywords) { + return Utils.GetSearchScore([Description], keywords); + } + } +} diff --git a/Elwig/Models/Entities/DeliveryScheduleWineVar.cs b/Elwig/Models/Entities/DeliveryScheduleWineVar.cs new file mode 100644 index 0000000..8a85eb7 --- /dev/null +++ b/Elwig/Models/Entities/DeliveryScheduleWineVar.cs @@ -0,0 +1,26 @@ +using Microsoft.EntityFrameworkCore; +using System.ComponentModel.DataAnnotations.Schema; + +namespace Elwig.Models.Entities { + [Table("delivery_schedule_wine_variety"), PrimaryKey("Year", "DsNr", "SortId")] + public class DeliveryScheduleWineVar { + + [Column("year")] + public int Year { get; set; } + + [Column("dsnr")] + public int DsNr { get; set; } + + [Column("sortid")] + public required string SortId { get; set; } + + [Column("priority")] + public int Priority { get; set; } + + [ForeignKey("Year, DsNr")] + public virtual DeliverySchedule Schedule { get; private set; } = null!; + + [ForeignKey("SortId")] + public virtual WineVar Variety { get; private set; } = null!; + } +} diff --git a/Elwig/Models/Entities/Member.cs b/Elwig/Models/Entities/Member.cs index af70440..71667d9 100644 --- a/Elwig/Models/Entities/Member.cs +++ b/Elwig/Models/Entities/Member.cs @@ -22,7 +22,6 @@ namespace Elwig.Models.Entities { [Column("middle_names")] public string? MiddleName { get; set; } - [NotMapped] public string[] MiddleNames { get => (MiddleName != null) ? MiddleName.Split(" ") : []; @@ -59,7 +58,6 @@ namespace Elwig.Models.Entities { [Column("entry_date")] public string? EntryDateString { get; set; } - [NotMapped] public DateOnly? EntryDate { get => EntryDateString != null ? DateOnly.ParseExact(EntryDateString, "yyyy-MM-dd") : null; @@ -68,7 +66,6 @@ namespace Elwig.Models.Entities { [Column("exit_date")] public string? ExitDateString { get; set; } - [NotMapped] public DateOnly? ExitDate { get => ExitDateString != null ? DateOnly.ParseExact(ExitDateString, "yyyy-MM-dd") : null; @@ -146,10 +143,19 @@ namespace Elwig.Models.Entities { [ForeignKey("DefaultKgNr")] public virtual WbKg? DefaultWbKg { get; private set; } - [NotMapped] public AT_Kg? DefaultKg => DefaultWbKg?.AtKg; + [Column("ctime"), DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public long CTime { get; private set; } + [NotMapped] + public DateTime CreatedTimestamp => DateTimeOffset.FromUnixTimeSeconds(CTime).LocalDateTime; + + [Column("mtime"), DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public long MTime { get; private set; } + [NotMapped] + public DateTime ModifiedTimestamp => DateTimeOffset.FromUnixTimeSeconds(MTime).LocalDateTime; + [ForeignKey("ZwstId")] public virtual Branch? Branch { get; private set; } diff --git a/Elwig/Models/Entities/PaymentVar.cs b/Elwig/Models/Entities/PaymentVar.cs index 33abe52..616a616 100644 --- a/Elwig/Models/Entities/PaymentVar.cs +++ b/Elwig/Models/Entities/PaymentVar.cs @@ -35,9 +35,9 @@ namespace Elwig.Models.Entities { public bool TestVariant { get; set; } [Column("calc_time")] - public int? CalcTimeUnix { get; set; } + public long? CalcTimeUnix { get; set; } [NotMapped] - public DateTime? CalcTime => CalcTimeUnix != null ? DateTimeOffset.FromUnixTimeSeconds((long)CalcTimeUnix).UtcDateTime.ToLocalTime() : null; + public DateTime? CalcTime => CalcTimeUnix != null ? DateTimeOffset.FromUnixTimeSeconds(CalcTimeUnix.Value).LocalDateTime : null; [Column("comment")] public string? Comment { get; set; } @@ -45,6 +45,16 @@ namespace Elwig.Models.Entities { [Column("data")] public required string Data { get; set; } + [Column("ctime"), DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public long CTime { get; private set; } + [NotMapped] + public DateTime CreatedTimestamp => DateTimeOffset.FromUnixTimeSeconds(CTime).LocalDateTime; + + [Column("mtime"), DatabaseGenerated(DatabaseGeneratedOption.Computed)] + public long MTime { get; private set; } + [NotMapped] + public DateTime ModifiedTimestamp => DateTimeOffset.FromUnixTimeSeconds(MTime).LocalDateTime; + [ForeignKey("Year")] public virtual Season Season { get; private set; } = null!; diff --git a/Elwig/Resources/Sql/25-26.sql b/Elwig/Resources/Sql/25-26.sql new file mode 100644 index 0000000..fa06c51 --- /dev/null +++ b/Elwig/Resources/Sql/25-26.sql @@ -0,0 +1,91 @@ +-- schema version 24 to 25 + +CREATE TABLE delivery_schedule ( + year INTEGER NOT NULL, + dsnr INTEGER NOT NULL, + + date TEXT NOT NULL CHECK (date LIKE year || '-%' AND date REGEXP '^[1-9][0-9]{3}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$'), + zwstid TEXT NOT NULL, + description TEXT NOT NULL, + max_weight INTEGER, + + ancmt_from INTEGER, + ancmt_to INTEGER, + + CONSTRAINT pk_delivery_schedule PRIMARY KEY (year, dsnr), + CONSTRAINT fk_delivery_schedule_season FOREIGN KEY (year) REFERENCES season (year) + ON UPDATE CASCADE + ON DELETE RESTRICT, + CONSTRAINT fk_delivery_schedule_branch FOREIGN KEY (zwstid) REFERENCES branch (zwstid) + ON UPDATE CASCADE + ON DELETE RESTRICT +) STRICT; + +CREATE TABLE delivery_schedule_wine_variety ( + year INTEGER NOT NULL, + dsnr INTEGER NOT NULL, + sortid TEXT NOT NULL, + + priority INTEGER NOT NULL DEFAULT 1, + + CONSTRAINT pk_delivery_schedule_wine_variety PRIMARY KEY (year, dsnr, sortid), + CONSTRAINT fk_delivery_schedule_wine_variety_delivery_schedule FOREIGN KEY (year, dsnr) REFERENCES delivery_schedule (year, dsnr) + ON UPDATE CASCADE + ON DELETE CASCADE, + CONSTRAINT fk_delivery_schedule_wine_variety_wine_variety FOREIGN KEY (sortid) REFERENCES wine_variety (sortid) + ON UPDATE CASCADE + ON DELETE RESTRICT +) STRICT; + +CREATE TABLE delivery_announcement ( + year INTEGER NOT NULL, + dsnr INTEGER NOT NULL, + mgnr INTEGER NOT NULL, + sortid TEXT NOT NULL, + + weight INTEGER NOT NULL, + + type TEXT NOT NULL, + ctime INTEGER NOT NULL DEFAULT (UNIXEPOCH()), + mtime INTEGER NOT NULL DEFAULT (UNIXEPOCH()), + + CONSTRAINT pk_delivery_announcement PRIMARY KEY (year, dsnr, mgnr, sortid), + CONSTRAINT fk_delivery_announcement_delivery_schedule FOREIGN KEY (year, dsnr) REFERENCES delivery_schedule (year, dsnr) + ON UPDATE CASCADE + ON DELETE CASCADE, + CONSTRAINT fk_delivery_announcement_member FOREIGN KEY (mgnr) REFERENCES member (mgnr) + ON UPDATE CASCADE + ON DELETE CASCADE, + CONSTRAINT fk_delivery_announcement_wine_variety FOREIGN KEY (sortid) REFERENCES wine_variety (sortid) + ON UPDATE CASCADE + ON DELETE RESTRICT +) STRICT; + + +CREATE TRIGGER t_delivery_announcement_i_ctime + AFTER INSERT ON delivery_announcement FOR EACH ROW + WHEN NEW.ctime != UNIXEPOCH() +BEGIN + UPDATE delivery_announcement SET ctime = UNIXEPOCH() WHERE (year, dsnr, mgnr, sortid) = (NEW.year, NEW.dsnr, NEW.mgnr, NEW.sortid); +END; + +CREATE TRIGGER t_delivery_announcement_u_ctime + BEFORE UPDATE ON delivery_announcement FOR EACH ROW + WHEN OLD.ctime != NEW.ctime +BEGIN + SELECT RAISE(ABORT, 'It is not allowed to change ctime'); +END; + +CREATE TRIGGER t_delivery_announcement_i_mtime + AFTER INSERT ON delivery_announcement FOR EACH ROW + WHEN NEW.mtime != UNIXEPOCH() +BEGIN + UPDATE delivery_announcement SET mtime = UNIXEPOCH() WHERE (year, dsnr, mgnr, sortid) = (NEW.year, NEW.dsnr, NEW.mgnr, NEW.sortid); +END; + +CREATE TRIGGER t_delivery_announcement_u_mtime + AFTER UPDATE ON delivery_announcement FOR EACH ROW + WHEN NEW.mtime != UNIXEPOCH() +BEGIN + UPDATE delivery_announcement SET mtime = UNIXEPOCH() WHERE (year, dsnr, mgnr, sortid) = (NEW.year, NEW.dsnr, NEW.mgnr, NEW.sortid); +END; diff --git a/Tests/fetch-resources.bat b/Tests/fetch-resources.bat index 0363416..d6977f8 100644 --- a/Tests/fetch-resources.bat +++ b/Tests/fetch-resources.bat @@ -1 +1 @@ -curl --fail -s -L "https://elwig.at/files/create.sql?v=25" -u "elwig:ganzGeheim123!" -o "Resources\Sql\Create.sql" +curl --fail -s -L "https://elwig.at/files/create.sql?v=26" -u "elwig:ganzGeheim123!" -o "Resources\Sql\Create.sql"