diff --git a/src/Geopilot.Api/Migrations/20250107090507_EnableOptionalDeliveryAttributes.Designer.cs b/src/Geopilot.Api/Migrations/20250107090507_EnableOptionalDeliveryAttributes.Designer.cs
new file mode 100644
index 00000000..3cc9708b
--- /dev/null
+++ b/src/Geopilot.Api/Migrations/20250107090507_EnableOptionalDeliveryAttributes.Designer.cs
@@ -0,0 +1,301 @@
+//
+using System;
+using Geopilot.Api;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using NetTopologySuite.Geometries;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace Geopilot.Api.Migrations
+{
+ [DbContext(typeof(Context))]
+ [Migration("20250107090507_EnableOptionalDeliveryAttributes")]
+ partial class EnableOptionalDeliveryAttributes
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "8.0.8")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis");
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("Geopilot.Api.Models.Asset", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("AssetType")
+ .IsRequired()
+ .HasColumnType("varchar(24)");
+
+ b.Property("Deleted")
+ .HasColumnType("boolean");
+
+ b.Property("DeliveryId")
+ .HasColumnType("integer");
+
+ b.Property("FileHash")
+ .IsRequired()
+ .HasColumnType("bytea");
+
+ b.Property("OriginalFilename")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("SanitizedFilename")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("DeliveryId");
+
+ b.ToTable("Assets");
+ });
+
+ modelBuilder.Entity("Geopilot.Api.Models.Delivery", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Comment")
+ .HasColumnType("text");
+
+ b.Property("Date")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("DeclaringUserId")
+ .HasColumnType("integer");
+
+ b.Property("Deleted")
+ .HasColumnType("boolean");
+
+ b.Property("JobId")
+ .HasColumnType("uuid");
+
+ b.Property("MandateId")
+ .HasColumnType("integer");
+
+ b.Property("Partial")
+ .HasColumnType("boolean");
+
+ b.Property("PrecursorDeliveryId")
+ .HasColumnType("integer");
+
+ b.HasKey("Id");
+
+ b.HasIndex("DeclaringUserId");
+
+ b.HasIndex("MandateId");
+
+ b.HasIndex("PrecursorDeliveryId");
+
+ b.ToTable("Deliveries");
+ });
+
+ modelBuilder.Entity("Geopilot.Api.Models.Mandate", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("EvaluateComment")
+ .IsRequired()
+ .HasColumnType("varchar(24)");
+
+ b.Property("EvaluatePartial")
+ .IsRequired()
+ .HasColumnType("varchar(24)");
+
+ b.Property("EvaluatePrecursorDelivery")
+ .IsRequired()
+ .HasColumnType("varchar(24)");
+
+ b.Property("FileTypes")
+ .IsRequired()
+ .HasColumnType("text[]");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("SpatialExtent")
+ .IsRequired()
+ .HasColumnType("geometry");
+
+ b.HasKey("Id");
+
+ b.ToTable("Mandates");
+ });
+
+ modelBuilder.Entity("Geopilot.Api.Models.Organisation", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.ToTable("Organisations");
+ });
+
+ modelBuilder.Entity("Geopilot.Api.Models.User", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+
+ b.Property("AuthIdentifier")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Email")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("FullName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("IsAdmin")
+ .HasColumnType("boolean");
+
+ b.HasKey("Id");
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("MandateOrganisation", b =>
+ {
+ b.Property("MandatesId")
+ .HasColumnType("integer");
+
+ b.Property("OrganisationsId")
+ .HasColumnType("integer");
+
+ b.HasKey("MandatesId", "OrganisationsId");
+
+ b.HasIndex("OrganisationsId");
+
+ b.ToTable("MandateOrganisation");
+ });
+
+ modelBuilder.Entity("OrganisationUser", b =>
+ {
+ b.Property("OrganisationsId")
+ .HasColumnType("integer");
+
+ b.Property("UsersId")
+ .HasColumnType("integer");
+
+ b.HasKey("OrganisationsId", "UsersId");
+
+ b.HasIndex("UsersId");
+
+ b.ToTable("OrganisationUser");
+ });
+
+ modelBuilder.Entity("Geopilot.Api.Models.Asset", b =>
+ {
+ b.HasOne("Geopilot.Api.Models.Delivery", "Delivery")
+ .WithMany("Assets")
+ .HasForeignKey("DeliveryId");
+
+ b.Navigation("Delivery");
+ });
+
+ modelBuilder.Entity("Geopilot.Api.Models.Delivery", b =>
+ {
+ b.HasOne("Geopilot.Api.Models.User", "DeclaringUser")
+ .WithMany("Deliveries")
+ .HasForeignKey("DeclaringUserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Geopilot.Api.Models.Mandate", "Mandate")
+ .WithMany("Deliveries")
+ .HasForeignKey("MandateId");
+
+ b.HasOne("Geopilot.Api.Models.Delivery", "PrecursorDelivery")
+ .WithMany()
+ .HasForeignKey("PrecursorDeliveryId");
+
+ b.Navigation("DeclaringUser");
+
+ b.Navigation("Mandate");
+
+ b.Navigation("PrecursorDelivery");
+ });
+
+ modelBuilder.Entity("MandateOrganisation", b =>
+ {
+ b.HasOne("Geopilot.Api.Models.Mandate", null)
+ .WithMany()
+ .HasForeignKey("MandatesId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Geopilot.Api.Models.Organisation", null)
+ .WithMany()
+ .HasForeignKey("OrganisationsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("OrganisationUser", b =>
+ {
+ b.HasOne("Geopilot.Api.Models.Organisation", null)
+ .WithMany()
+ .HasForeignKey("OrganisationsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("Geopilot.Api.Models.User", null)
+ .WithMany()
+ .HasForeignKey("UsersId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("Geopilot.Api.Models.Delivery", b =>
+ {
+ b.Navigation("Assets");
+ });
+
+ modelBuilder.Entity("Geopilot.Api.Models.Mandate", b =>
+ {
+ b.Navigation("Deliveries");
+ });
+
+ modelBuilder.Entity("Geopilot.Api.Models.User", b =>
+ {
+ b.Navigation("Deliveries");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/src/Geopilot.Api/Migrations/20250107090507_EnableOptionalDeliveryAttributes.cs b/src/Geopilot.Api/Migrations/20250107090507_EnableOptionalDeliveryAttributes.cs
new file mode 100644
index 00000000..99d83b51
--- /dev/null
+++ b/src/Geopilot.Api/Migrations/20250107090507_EnableOptionalDeliveryAttributes.cs
@@ -0,0 +1,169 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace Geopilot.Api.Migrations
+{
+ ///
+ public partial class EnableOptionalDeliveryAttributes : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropForeignKey(
+ name: "FK_Assets_Deliveries_DeliveryId",
+ table: "Assets");
+
+ migrationBuilder.DropForeignKey(
+ name: "FK_Deliveries_Mandates_MandateId",
+ table: "Deliveries");
+
+ migrationBuilder.AddColumn(
+ name: "EvaluateComment",
+ table: "Mandates",
+ type: "varchar(24)",
+ nullable: false,
+ defaultValue: "");
+
+ migrationBuilder.AddColumn(
+ name: "EvaluatePartial",
+ table: "Mandates",
+ type: "varchar(24)",
+ nullable: false,
+ defaultValue: "");
+
+ migrationBuilder.AddColumn(
+ name: "EvaluatePrecursorDelivery",
+ table: "Mandates",
+ type: "varchar(24)",
+ nullable: false,
+ defaultValue: "");
+
+ migrationBuilder.AlterColumn(
+ name: "Partial",
+ table: "Deliveries",
+ type: "boolean",
+ nullable: true,
+ oldClrType: typeof(bool),
+ oldType: "boolean");
+
+ migrationBuilder.AlterColumn(
+ name: "MandateId",
+ table: "Deliveries",
+ type: "integer",
+ nullable: true,
+ oldClrType: typeof(int),
+ oldType: "integer");
+
+ migrationBuilder.AlterColumn(
+ name: "Comment",
+ table: "Deliveries",
+ type: "text",
+ nullable: true,
+ oldClrType: typeof(string),
+ oldType: "text");
+
+ migrationBuilder.AlterColumn(
+ name: "DeliveryId",
+ table: "Assets",
+ type: "integer",
+ nullable: true,
+ oldClrType: typeof(int),
+ oldType: "integer");
+
+ migrationBuilder.AddForeignKey(
+ name: "FK_Assets_Deliveries_DeliveryId",
+ table: "Assets",
+ column: "DeliveryId",
+ principalTable: "Deliveries",
+ principalColumn: "Id");
+
+ migrationBuilder.AddForeignKey(
+ name: "FK_Deliveries_Mandates_MandateId",
+ table: "Deliveries",
+ column: "MandateId",
+ principalTable: "Mandates",
+ principalColumn: "Id");
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropForeignKey(
+ name: "FK_Assets_Deliveries_DeliveryId",
+ table: "Assets");
+
+ migrationBuilder.DropForeignKey(
+ name: "FK_Deliveries_Mandates_MandateId",
+ table: "Deliveries");
+
+ migrationBuilder.DropColumn(
+ name: "EvaluateComment",
+ table: "Mandates");
+
+ migrationBuilder.DropColumn(
+ name: "EvaluatePartial",
+ table: "Mandates");
+
+ migrationBuilder.DropColumn(
+ name: "EvaluatePrecursorDelivery",
+ table: "Mandates");
+
+ migrationBuilder.AlterColumn(
+ name: "Partial",
+ table: "Deliveries",
+ type: "boolean",
+ nullable: false,
+ defaultValue: false,
+ oldClrType: typeof(bool),
+ oldType: "boolean",
+ oldNullable: true);
+
+ migrationBuilder.AlterColumn(
+ name: "MandateId",
+ table: "Deliveries",
+ type: "integer",
+ nullable: false,
+ defaultValue: 0,
+ oldClrType: typeof(int),
+ oldType: "integer",
+ oldNullable: true);
+
+ migrationBuilder.AlterColumn(
+ name: "Comment",
+ table: "Deliveries",
+ type: "text",
+ nullable: false,
+ defaultValue: "",
+ oldClrType: typeof(string),
+ oldType: "text",
+ oldNullable: true);
+
+ migrationBuilder.AlterColumn(
+ name: "DeliveryId",
+ table: "Assets",
+ type: "integer",
+ nullable: false,
+ defaultValue: 0,
+ oldClrType: typeof(int),
+ oldType: "integer",
+ oldNullable: true);
+
+ migrationBuilder.AddForeignKey(
+ name: "FK_Assets_Deliveries_DeliveryId",
+ table: "Assets",
+ column: "DeliveryId",
+ principalTable: "Deliveries",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+
+ migrationBuilder.AddForeignKey(
+ name: "FK_Deliveries_Mandates_MandateId",
+ table: "Deliveries",
+ column: "MandateId",
+ principalTable: "Mandates",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ }
+ }
+}
diff --git a/src/Geopilot.Api/Migrations/ContextModelSnapshot.cs b/src/Geopilot.Api/Migrations/ContextModelSnapshot.cs
index b72df553..2d647220 100644
--- a/src/Geopilot.Api/Migrations/ContextModelSnapshot.cs
+++ b/src/Geopilot.Api/Migrations/ContextModelSnapshot.cs
@@ -18,7 +18,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
{
#pragma warning disable 612, 618
modelBuilder
- .HasAnnotation("ProductVersion", "7.0.11")
+ .HasAnnotation("ProductVersion", "8.0.8")
.HasAnnotation("Relational:MaxIdentifierLength", 63);
NpgsqlModelBuilderExtensions.HasPostgresExtension(modelBuilder, "postgis");
@@ -39,7 +39,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.Property("Deleted")
.HasColumnType("boolean");
- b.Property("DeliveryId")
+ b.Property("DeliveryId")
.HasColumnType("integer");
b.Property("FileHash")
@@ -70,7 +70,6 @@ protected override void BuildModel(ModelBuilder modelBuilder)
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
b.Property("Comment")
- .IsRequired()
.HasColumnType("text");
b.Property("Date")
@@ -85,10 +84,10 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.Property("JobId")
.HasColumnType("uuid");
- b.Property("MandateId")
+ b.Property("MandateId")
.HasColumnType("integer");
- b.Property("Partial")
+ b.Property("Partial")
.HasColumnType("boolean");
b.Property("PrecursorDeliveryId")
@@ -113,6 +112,18 @@ protected override void BuildModel(ModelBuilder modelBuilder)
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id"));
+ b.Property("EvaluateComment")
+ .IsRequired()
+ .HasColumnType("varchar(24)");
+
+ b.Property("EvaluatePartial")
+ .IsRequired()
+ .HasColumnType("varchar(24)");
+
+ b.Property("EvaluatePrecursorDelivery")
+ .IsRequired()
+ .HasColumnType("varchar(24)");
+
b.Property("FileTypes")
.IsRequired()
.HasColumnType("text[]");
@@ -209,9 +220,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
{
b.HasOne("Geopilot.Api.Models.Delivery", "Delivery")
.WithMany("Assets")
- .HasForeignKey("DeliveryId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
+ .HasForeignKey("DeliveryId");
b.Navigation("Delivery");
});
@@ -226,9 +235,7 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.HasOne("Geopilot.Api.Models.Mandate", "Mandate")
.WithMany("Deliveries")
- .HasForeignKey("MandateId")
- .OnDelete(DeleteBehavior.Cascade)
- .IsRequired();
+ .HasForeignKey("MandateId");
b.HasOne("Geopilot.Api.Models.Delivery", "PrecursorDelivery")
.WithMany()
diff --git a/src/Geopilot.Api/Models/Delivery.cs b/src/Geopilot.Api/Models/Delivery.cs
index f53fb189..35629fe0 100644
--- a/src/Geopilot.Api/Models/Delivery.cs
+++ b/src/Geopilot.Api/Models/Delivery.cs
@@ -38,7 +38,7 @@ public class Delivery
///
/// Indicate whether the delivery contains partial data.
///
- public bool Partial { get; set; }
+ public bool? Partial { get; set; }
///
/// The previous delivery on the same .
@@ -48,7 +48,7 @@ public class Delivery
///
/// Comment to describe the delivery.
///
- public string Comment { get; set; } = string.Empty;
+ public string? Comment { get; set; } = string.Empty;
///
/// The deletion status of the delivery.
diff --git a/src/Geopilot.Api/Models/FieldEvaluationType.cs b/src/Geopilot.Api/Models/FieldEvaluationType.cs
new file mode 100644
index 00000000..a2f17abf
--- /dev/null
+++ b/src/Geopilot.Api/Models/FieldEvaluationType.cs
@@ -0,0 +1,23 @@
+namespace Geopilot.Api.Models
+{
+ ///
+ /// Defines how fileds have to be evaluated.
+ ///
+ public enum FieldEvaluationType
+ {
+ ///
+ /// Field must not contain any value.
+ ///
+ NotEvaluated,
+
+ ///
+ /// Field may contain a value but must not.
+ ///
+ Optional,
+
+ ///
+ /// Field must contan a value.
+ ///
+ Required,
+ }
+}
diff --git a/src/Geopilot.Api/Models/Mandate.cs b/src/Geopilot.Api/Models/Mandate.cs
index 582dbfdf..7cb7e41b 100644
--- a/src/Geopilot.Api/Models/Mandate.cs
+++ b/src/Geopilot.Api/Models/Mandate.cs
@@ -1,4 +1,5 @@
-using NetTopologySuite.Geometries;
+using Microsoft.VisualBasic.FileIO;
+using NetTopologySuite.Geometries;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
@@ -40,6 +41,24 @@ public class Mandate
[NotMapped]
public List Coordinates { get; set; } = new List();
+ ///
+ /// Defines how is evaluated.
+ ///
+ [Column(TypeName = "varchar(24)")]
+ public FieldEvaluationType EvaluatePrecursorDelivery { get; set; }
+
+ ///
+ /// Defines how is evaluated.
+ ///
+ [Column(TypeName = "varchar(24)")]
+ public FieldEvaluationType EvaluatePartial { get; set; }
+
+ ///
+ /// Defines how is evaluated.
+ ///
+ [Column(TypeName = "varchar(24)")]
+ public FieldEvaluationType EvaluateComment { get; set; }
+
///
/// Organisations allowed to deliver data fulfilling the mandate.
///