diff --git a/App/App.csproj b/App/App.csproj
index 12d0ea7..106d50b 100644
--- a/App/App.csproj
+++ b/App/App.csproj
@@ -86,5 +86,9 @@
+
+
+
+
diff --git a/App/Config/settings.example.yaml b/App/Config/settings.example.yaml
index a7999d1..f55e85e 100644
--- a/App/Config/settings.example.yaml
+++ b/App/Config/settings.example.yaml
@@ -10,12 +10,6 @@ Logging:
Console:
LogLevel:
Default: Information
- FormatterName: json
- FormatterOptions:
- SingleLine: false
- IncludeScopes: true
- JsonWriterOptions:
- Indented: true
OpenTelemetry:
IncludeFormattedMessage: true
IncludeScopes: true
diff --git a/App/Config/settings.yaml b/App/Config/settings.yaml
index c2b9467..259222b 100644
--- a/App/Config/settings.yaml
+++ b/App/Config/settings.yaml
@@ -7,14 +7,14 @@ Kestrel:
Url: http://+:9001
Logging:
LogLevel:
- Default: None
- Console:
- LogLevel:
- Default: Information
+ Default: Information
+ # Console:
+ # LogLevel:
+ # Default: Debug
OpenTelemetry:
- IncludeFormattedMessage: true
- IncludeScopes: true
- ParseStateValues: true
+ IncludeFormattedMessage: false
+ IncludeScopes: false
+ ParseStateValues: false
# Domain
App:
Landscape: lapras
diff --git a/App/Migrations/20231123145755_InitialCreate.Designer.cs b/App/Migrations/20231123145755_InitialCreate.Designer.cs
deleted file mode 100644
index 445c508..0000000
--- a/App/Migrations/20231123145755_InitialCreate.Designer.cs
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-using App.StartUp.Database;
-using Microsoft.EntityFrameworkCore;
-using Microsoft.EntityFrameworkCore.Infrastructure;
-using Microsoft.EntityFrameworkCore.Migrations;
-using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
-using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
-
-#nullable disable
-
-namespace App.Migrations
-{
- [DbContext(typeof(MainDbContext))]
- [Migration("20231123145755_InitialCreate")]
- partial class InitialCreate
- {
- ///
- protected override void BuildTargetModel(ModelBuilder modelBuilder)
- {
-#pragma warning disable 612, 618
- modelBuilder
- .HasAnnotation("ProductVersion", "8.0.0")
- .HasAnnotation("Relational:MaxIdentifierLength", 63);
-
- NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
-
- modelBuilder.Entity("App.Modules.Users.Data.UserData", b =>
- {
- b.Property("Id")
- .HasColumnType("text");
-
- b.Property("Username")
- .IsRequired()
- .HasColumnType("text");
-
- b.HasKey("Id");
-
- b.HasIndex("Username")
- .IsUnique();
-
- b.ToTable("Users");
- });
-#pragma warning restore 612, 618
- }
- }
-}
diff --git a/App/Migrations/20231123145755_InitialCreate.cs b/App/Migrations/20231123145755_InitialCreate.cs
deleted file mode 100644
index 14cfa97..0000000
--- a/App/Migrations/20231123145755_InitialCreate.cs
+++ /dev/null
@@ -1,39 +0,0 @@
-using Microsoft.EntityFrameworkCore.Migrations;
-
-#nullable disable
-
-namespace App.Migrations
-{
- ///
- public partial class InitialCreate : Migration
- {
- ///
- protected override void Up(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.CreateTable(
- name: "Users",
- columns: table => new
- {
- Id = table.Column(type: "text", nullable: false),
- Username = table.Column(type: "text", nullable: false)
- },
- constraints: table =>
- {
- table.PrimaryKey("PK_Users", x => x.Id);
- });
-
- migrationBuilder.CreateIndex(
- name: "IX_Users_Username",
- table: "Users",
- column: "Username",
- unique: true);
- }
-
- ///
- protected override void Down(MigrationBuilder migrationBuilder)
- {
- migrationBuilder.DropTable(
- name: "Users");
- }
- }
-}
diff --git a/App/Migrations/20231202115729_InitialCreate.Designer.cs b/App/Migrations/20231202115729_InitialCreate.Designer.cs
new file mode 100644
index 0000000..4ebe725
--- /dev/null
+++ b/App/Migrations/20231202115729_InitialCreate.Designer.cs
@@ -0,0 +1,222 @@
+//
+using System;
+using App.StartUp.Database;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+namespace App.Migrations
+{
+ [DbContext(typeof(MainDbContext))]
+ [Migration("20231202115729_InitialCreate")]
+ partial class InitialCreate
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "8.0.0")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("App.Modules.Bookings.Data.BookingData", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("CompletedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CreatedAt")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasDefaultValueSql("NOW()");
+
+ b.Property("Date")
+ .HasColumnType("date");
+
+ b.Property("Status")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("smallint")
+ .HasDefaultValue((byte)0);
+
+ b.Property("Time")
+ .HasColumnType("time without time zone");
+
+ b.Property("UserId")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("Bookings");
+ });
+
+ modelBuilder.Entity("App.Modules.Passengers.Data.PassengerData", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("FullName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Gender")
+ .HasColumnType("smallint");
+
+ b.Property("PassportExpiry")
+ .HasColumnType("date");
+
+ b.Property("PassportNumber")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("UserId")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId", "PassportNumber")
+ .IsUnique();
+
+ b.ToTable("Passengers");
+ });
+
+ modelBuilder.Entity("App.Modules.Schedules.Data.ScheduleData", b =>
+ {
+ b.Property("Date")
+ .HasColumnType("date");
+
+ b.Property("Confirmed")
+ .HasColumnType("boolean");
+
+ b.Property("JToWExcluded")
+ .IsRequired()
+ .HasColumnType("time without time zone[]");
+
+ b.Property("WToJExcluded")
+ .IsRequired()
+ .HasColumnType("time without time zone[]");
+
+ b.HasKey("Date");
+
+ b.ToTable("Schedules");
+ });
+
+ modelBuilder.Entity("App.Modules.Timings.Data.TimingData", b =>
+ {
+ b.Property("Direction")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Direction"));
+
+ b.Property("Timings")
+ .IsRequired()
+ .HasColumnType("time without time zone[]");
+
+ b.HasKey("Direction");
+
+ b.ToTable("Timings");
+
+ b.HasData(
+ new
+ {
+ Direction = 1,
+ Timings = new[] { new TimeOnly(5, 0, 0), new TimeOnly(5, 30, 0), new TimeOnly(6, 0, 0), new TimeOnly(6, 30, 0), new TimeOnly(7, 0, 0), new TimeOnly(7, 30, 0), new TimeOnly(8, 45, 0), new TimeOnly(10, 0, 0), new TimeOnly(11, 30, 0), new TimeOnly(12, 45, 0), new TimeOnly(14, 0, 0), new TimeOnly(15, 15, 0), new TimeOnly(16, 30, 0), new TimeOnly(17, 45, 0), new TimeOnly(19, 0, 0), new TimeOnly(20, 15, 0), new TimeOnly(21, 30, 0), new TimeOnly(22, 45, 0) }
+ },
+ new
+ {
+ Direction = 2,
+ Timings = new[] { new TimeOnly(8, 30, 0), new TimeOnly(9, 45, 0), new TimeOnly(11, 0, 0), new TimeOnly(12, 30, 0), new TimeOnly(13, 45, 0), new TimeOnly(15, 0, 0), new TimeOnly(16, 15, 0), new TimeOnly(17, 30, 0), new TimeOnly(18, 45, 0), new TimeOnly(20, 0, 0), new TimeOnly(21, 15, 0), new TimeOnly(22, 30, 0), new TimeOnly(23, 45, 0) }
+ });
+ });
+
+ modelBuilder.Entity("App.Modules.Users.Data.UserData", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("text");
+
+ b.Property("Username")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Username")
+ .IsUnique();
+
+ b.ToTable("Users");
+ });
+
+ modelBuilder.Entity("App.Modules.Bookings.Data.BookingData", b =>
+ {
+ b.HasOne("App.Modules.Users.Data.UserData", "User")
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.OwnsMany("App.Modules.Bookings.Data.BookingPassengerData", "Passengers", b1 =>
+ {
+ b1.Property("BookingDataId")
+ .HasColumnType("uuid");
+
+ b1.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ b1.Property("FullName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b1.Property("Gender")
+ .HasColumnType("smallint");
+
+ b1.Property("PassportExpiry")
+ .HasColumnType("date");
+
+ b1.Property("PassportNumber")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b1.HasKey("BookingDataId", "Id");
+
+ b1.ToTable("Bookings");
+
+ b1.ToJson("Passengers");
+
+ b1.WithOwner()
+ .HasForeignKey("BookingDataId");
+ });
+
+ b.Navigation("Passengers");
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("App.Modules.Passengers.Data.PassengerData", b =>
+ {
+ b.HasOne("App.Modules.Users.Data.UserData", "User")
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("User");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/App/Migrations/20231202115729_InitialCreate.cs b/App/Migrations/20231202115729_InitialCreate.cs
new file mode 100644
index 0000000..c96f235
--- /dev/null
+++ b/App/Migrations/20231202115729_InitialCreate.cs
@@ -0,0 +1,148 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+
+#nullable disable
+
+#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional
+
+namespace App.Migrations
+{
+ ///
+ public partial class InitialCreate : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "Schedules",
+ columns: table => new
+ {
+ Date = table.Column(type: "date", nullable: false),
+ Confirmed = table.Column(type: "boolean", nullable: false),
+ JToWExcluded = table.Column(type: "time without time zone[]", nullable: false),
+ WToJExcluded = table.Column(type: "time without time zone[]", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Schedules", x => x.Date);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Timings",
+ columns: table => new
+ {
+ Direction = table.Column(type: "integer", nullable: false)
+ .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn),
+ Timings = table.Column(type: "time without time zone[]", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Timings", x => x.Direction);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Users",
+ columns: table => new
+ {
+ Id = table.Column(type: "text", nullable: false),
+ Username = table.Column(type: "text", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Users", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Bookings",
+ columns: table => new
+ {
+ Id = table.Column(type: "uuid", nullable: false),
+ CreatedAt = table.Column(type: "timestamp with time zone", nullable: false, defaultValueSql: "NOW()"),
+ Status = table.Column(type: "smallint", nullable: false, defaultValue: (byte)0),
+ CompletedAt = table.Column(type: "timestamp with time zone", nullable: true),
+ Date = table.Column(type: "date", nullable: false),
+ Time = table.Column(type: "time without time zone", nullable: false),
+ UserId = table.Column(type: "text", nullable: false),
+ Passengers = table.Column(type: "jsonb", nullable: true)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Bookings", x => x.Id);
+ table.ForeignKey(
+ name: "FK_Bookings_Users_UserId",
+ column: x => x.UserId,
+ principalTable: "Users",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "Passengers",
+ columns: table => new
+ {
+ Id = table.Column(type: "uuid", nullable: false),
+ FullName = table.Column(type: "text", nullable: false),
+ Gender = table.Column(type: "smallint", nullable: false),
+ PassportExpiry = table.Column(type: "date", nullable: false),
+ PassportNumber = table.Column(type: "text", nullable: false),
+ UserId = table.Column(type: "text", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_Passengers", x => x.Id);
+ table.ForeignKey(
+ name: "FK_Passengers_Users_UserId",
+ column: x => x.UserId,
+ principalTable: "Users",
+ principalColumn: "Id",
+ onDelete: ReferentialAction.Cascade);
+ });
+
+ migrationBuilder.InsertData(
+ table: "Timings",
+ columns: new[] { "Direction", "Timings" },
+ values: new object[,]
+ {
+ { 1, new[] { new TimeOnly(5, 0, 0), new TimeOnly(5, 30, 0), new TimeOnly(6, 0, 0), new TimeOnly(6, 30, 0), new TimeOnly(7, 0, 0), new TimeOnly(7, 30, 0), new TimeOnly(8, 45, 0), new TimeOnly(10, 0, 0), new TimeOnly(11, 30, 0), new TimeOnly(12, 45, 0), new TimeOnly(14, 0, 0), new TimeOnly(15, 15, 0), new TimeOnly(16, 30, 0), new TimeOnly(17, 45, 0), new TimeOnly(19, 0, 0), new TimeOnly(20, 15, 0), new TimeOnly(21, 30, 0), new TimeOnly(22, 45, 0) } },
+ { 2, new[] { new TimeOnly(8, 30, 0), new TimeOnly(9, 45, 0), new TimeOnly(11, 0, 0), new TimeOnly(12, 30, 0), new TimeOnly(13, 45, 0), new TimeOnly(15, 0, 0), new TimeOnly(16, 15, 0), new TimeOnly(17, 30, 0), new TimeOnly(18, 45, 0), new TimeOnly(20, 0, 0), new TimeOnly(21, 15, 0), new TimeOnly(22, 30, 0), new TimeOnly(23, 45, 0) } }
+ });
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Bookings_UserId",
+ table: "Bookings",
+ column: "UserId");
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Passengers_UserId_PassportNumber",
+ table: "Passengers",
+ columns: new[] { "UserId", "PassportNumber" },
+ unique: true);
+
+ migrationBuilder.CreateIndex(
+ name: "IX_Users_Username",
+ table: "Users",
+ column: "Username",
+ unique: true);
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropTable(
+ name: "Bookings");
+
+ migrationBuilder.DropTable(
+ name: "Passengers");
+
+ migrationBuilder.DropTable(
+ name: "Schedules");
+
+ migrationBuilder.DropTable(
+ name: "Timings");
+
+ migrationBuilder.DropTable(
+ name: "Users");
+ }
+ }
+}
diff --git a/App/Migrations/MainDbContextModelSnapshot.cs b/App/Migrations/MainDbContextModelSnapshot.cs
index dff5783..ddfe063 100644
--- a/App/Migrations/MainDbContextModelSnapshot.cs
+++ b/App/Migrations/MainDbContextModelSnapshot.cs
@@ -1,4 +1,5 @@
//
+using System;
using App.StartUp.Database;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
@@ -21,6 +22,124 @@ protected override void BuildModel(ModelBuilder modelBuilder)
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+ modelBuilder.Entity("App.Modules.Bookings.Data.BookingData", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("CompletedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CreatedAt")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("timestamp with time zone")
+ .HasDefaultValueSql("NOW()");
+
+ b.Property("Date")
+ .HasColumnType("date");
+
+ b.Property("Status")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("smallint")
+ .HasDefaultValue((byte)0);
+
+ b.Property("Time")
+ .HasColumnType("time without time zone");
+
+ b.Property("UserId")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId");
+
+ b.ToTable("Bookings");
+ });
+
+ modelBuilder.Entity("App.Modules.Passengers.Data.PassengerData", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("FullName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("Gender")
+ .HasColumnType("smallint");
+
+ b.Property("PassportExpiry")
+ .HasColumnType("date");
+
+ b.Property("PassportNumber")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.Property("UserId")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b.HasKey("Id");
+
+ b.HasIndex("UserId", "PassportNumber")
+ .IsUnique();
+
+ b.ToTable("Passengers");
+ });
+
+ modelBuilder.Entity("App.Modules.Schedules.Data.ScheduleData", b =>
+ {
+ b.Property("Date")
+ .HasColumnType("date");
+
+ b.Property("Confirmed")
+ .HasColumnType("boolean");
+
+ b.Property("JToWExcluded")
+ .IsRequired()
+ .HasColumnType("time without time zone[]");
+
+ b.Property("WToJExcluded")
+ .IsRequired()
+ .HasColumnType("time without time zone[]");
+
+ b.HasKey("Date");
+
+ b.ToTable("Schedules");
+ });
+
+ modelBuilder.Entity("App.Modules.Timings.Data.TimingData", b =>
+ {
+ b.Property("Direction")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Direction"));
+
+ b.Property("Timings")
+ .IsRequired()
+ .HasColumnType("time without time zone[]");
+
+ b.HasKey("Direction");
+
+ b.ToTable("Timings");
+
+ b.HasData(
+ new
+ {
+ Direction = 1,
+ Timings = new[] { new TimeOnly(5, 0, 0), new TimeOnly(5, 30, 0), new TimeOnly(6, 0, 0), new TimeOnly(6, 30, 0), new TimeOnly(7, 0, 0), new TimeOnly(7, 30, 0), new TimeOnly(8, 45, 0), new TimeOnly(10, 0, 0), new TimeOnly(11, 30, 0), new TimeOnly(12, 45, 0), new TimeOnly(14, 0, 0), new TimeOnly(15, 15, 0), new TimeOnly(16, 30, 0), new TimeOnly(17, 45, 0), new TimeOnly(19, 0, 0), new TimeOnly(20, 15, 0), new TimeOnly(21, 30, 0), new TimeOnly(22, 45, 0) }
+ },
+ new
+ {
+ Direction = 2,
+ Timings = new[] { new TimeOnly(8, 30, 0), new TimeOnly(9, 45, 0), new TimeOnly(11, 0, 0), new TimeOnly(12, 30, 0), new TimeOnly(13, 45, 0), new TimeOnly(15, 0, 0), new TimeOnly(16, 15, 0), new TimeOnly(17, 30, 0), new TimeOnly(18, 45, 0), new TimeOnly(20, 0, 0), new TimeOnly(21, 15, 0), new TimeOnly(22, 30, 0), new TimeOnly(23, 45, 0) }
+ });
+ });
+
modelBuilder.Entity("App.Modules.Users.Data.UserData", b =>
{
b.Property("Id")
@@ -37,6 +156,63 @@ protected override void BuildModel(ModelBuilder modelBuilder)
b.ToTable("Users");
});
+
+ modelBuilder.Entity("App.Modules.Bookings.Data.BookingData", b =>
+ {
+ b.HasOne("App.Modules.Users.Data.UserData", "User")
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.OwnsMany("App.Modules.Bookings.Data.BookingPassengerData", "Passengers", b1 =>
+ {
+ b1.Property("BookingDataId")
+ .HasColumnType("uuid");
+
+ b1.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("integer");
+
+ b1.Property("FullName")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b1.Property("Gender")
+ .HasColumnType("smallint");
+
+ b1.Property("PassportExpiry")
+ .HasColumnType("date");
+
+ b1.Property("PassportNumber")
+ .IsRequired()
+ .HasColumnType("text");
+
+ b1.HasKey("BookingDataId", "Id");
+
+ b1.ToTable("Bookings");
+
+ b1.ToJson("Passengers");
+
+ b1.WithOwner()
+ .HasForeignKey("BookingDataId");
+ });
+
+ b.Navigation("Passengers");
+
+ b.Navigation("User");
+ });
+
+ modelBuilder.Entity("App.Modules.Passengers.Data.PassengerData", b =>
+ {
+ b.HasOne("App.Modules.Users.Data.UserData", "User")
+ .WithMany()
+ .HasForeignKey("UserId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("User");
+ });
#pragma warning restore 612, 618
}
}
diff --git a/App/Modules/Bookings/API/V1/BookingController.cs b/App/Modules/Bookings/API/V1/BookingController.cs
index 0c4f37b..cbea8db 100644
--- a/App/Modules/Bookings/API/V1/BookingController.cs
+++ b/App/Modules/Bookings/API/V1/BookingController.cs
@@ -17,10 +17,10 @@ namespace App.Modules.Bookings.API.V1;
[Consumes(MediaTypeNames.Application.Json)]
[Route("api/v{version:apiVersion}/[controller]")]
public class BookingController(
- ITrainBookingService service,
+ IBookingService service,
CreateBookingReqValidator createBookingReqValidator,
BookingSearchQueryValidator bookingSearchQueryValidator,
- AuthHelper authHelper
+ IAuthHelper authHelper
) : AtomiControllerBase(authHelper)
{
[Authorize, HttpGet]
@@ -60,13 +60,24 @@ public async Task>> CountStatus()
return this.ReturnResult(x);
}
+ [Authorize(Policy = AuthPolicies.OnlyAdmin), HttpPost("bypass/{userId}")]
+ public async Task> Create(string userId, [FromBody] CreateBookingReq req)
+ {
+ var x = await createBookingReqValidator.ValidateAsyncResult(req, "Invalid CreateBookingReq")
+ .ThenAwait(x => service.Create(userId, x.ToRecord()))
+ .Then(x => x.ToRes(), Errors.MapAll);
+ return this.ReturnResult(x);
+ }
-
+ [Authorize(Policy = AuthPolicies.OnlyAdmin), HttpPost("cancel/bypass/{id:guid}")]
+ public async Task> Cancel(Guid id)
+ {
+ var x = await service.Cancel(id)
+ .Then(x => x?.ToRes(), Errors.MapAll);
+ return this.ReturnNullableResult(x, new EntityNotFound("Booking not found", typeof(Booking), id.ToString()));
+ }
//TODO: CANCEL
//TODO: CREATE
-
-
-
}
diff --git a/App/Modules/Bookings/Data/BookingData.cs b/App/Modules/Bookings/Data/BookingData.cs
index 5053e2c..a604539 100644
--- a/App/Modules/Bookings/Data/BookingData.cs
+++ b/App/Modules/Bookings/Data/BookingData.cs
@@ -1,9 +1,8 @@
-using System.ComponentModel.DataAnnotations.Schema;
using App.Modules.Users.Data;
namespace App.Modules.Bookings.Data;
-public record BookingPassengerData
+public class BookingPassengerData
{
public required string FullName { get; set; }
@@ -30,8 +29,7 @@ public class BookingData
public TimeOnly Time { get; set; }
- [Column(TypeName = "jsonb")]
- public BookingPassengerData[] Passengers { get; set; } = null!;
+ public List Passengers { get; set; } = null!;
// FK
diff --git a/App/Modules/Bookings/Data/BookingMapper.cs b/App/Modules/Bookings/Data/BookingMapper.cs
index 8d80188..48bf58c 100644
--- a/App/Modules/Bookings/Data/BookingMapper.cs
+++ b/App/Modules/Bookings/Data/BookingMapper.cs
@@ -59,7 +59,7 @@ public static BookingData UpdateData(this BookingData data, BookingRecord record
data.Time = record.Time;
data.Passengers = record.Passengers
.Select(passenger => passenger.ToData())
- .ToArray();
+ .ToList();
return data;
}
diff --git a/App/Modules/Bookings/Data/BookingRepository.cs b/App/Modules/Bookings/Data/BookingRepository.cs
index 11b69a7..4b1717f 100644
--- a/App/Modules/Bookings/Data/BookingRepository.cs
+++ b/App/Modules/Bookings/Data/BookingRepository.cs
@@ -8,7 +8,7 @@
namespace App.Modules.Bookings.Data;
-public class BookingRepository(MainDbContext db, ILogger logger) : ITrainBookingRepository
+public class BookingRepository(MainDbContext db, ILogger logger) : IBookingRepository
{
public async Task>> Search(BookingSearch search)
{
@@ -53,6 +53,7 @@ public async Task>> Search(BookingSearch se
&&
(userId == null || x.UserId == userId)
)
+ .Include(x => x.User)
.FirstOrDefaultAsync();
return booking?.ToDomain();
}
@@ -64,13 +65,13 @@ public async Task>> Search(BookingSearch se
}
}
- public async Task> Create(string? userId, BookingRecord record)
+ public async Task> Create(string userId, BookingRecord record)
{
try
{
logger.LogInformation("Creating Booking: {@Record}", record.ToJson());
- var data = new BookingData();
+ var data = new BookingData { UserId = userId };
data = data.UpdateData(record);
@@ -164,13 +165,13 @@ public async Task>> Count(DateOnly date, TimeOn
{
try
{
- logger.LogInformation("Get booking count");
+ logger.LogInformation("Get booking count from {Date} and {Time}...", date, time);
var polls = await db.Bookings
.Where(x =>
(x.Date > date || (x.Date == date && x.Time >= time))
&&
- x.Status != 0
+ x.Status == (int)BookStatus.Pending
)
.GroupBy(x => new { x.Date, x.Time })
.Select(group =>
diff --git a/App/Modules/Common/BaseController.cs b/App/Modules/Common/BaseController.cs
index 80af744..027e0d5 100644
--- a/App/Modules/Common/BaseController.cs
+++ b/App/Modules/Common/BaseController.cs
@@ -10,7 +10,7 @@
namespace App.Modules.Common;
-public class AtomiControllerBase(AuthHelper h) : ControllerBase
+public class AtomiControllerBase(IAuthHelper h) : ControllerBase
{
protected ActionResult Error(HttpStatusCode code, IDomainProblem problem)
{
@@ -105,6 +105,7 @@ protected Result GuardOrAll(string? target, string field, params string[]
||
h.HasAll(this.HttpContext.User, field, value)
) return new Unit().ToResult();
+ h.Logger.LogInformation("Auth Failed (All): Target: {Target}, Sub: {Sub}, Field: {Field}, Value: {@Value}, Target Pass: {TargetPass}, Field Pass: {FieldPass}", target, this.Sub(), field, value, target != null && this.Sub() == target, h.HasAny(this.HttpContext.User, field, value));
return new Unauthorized("You are not authorized to access this resource").ToException();
}
@@ -115,11 +116,14 @@ protected Task> GuardOrAllAsync(string? target, string field, param
protected Result GuardOrAny(string? target, string field, params string[] value)
{
+
if (
(target != null && this.Sub() == target)
||
h.HasAny(this.HttpContext.User, field, value)
) return new Unit().ToResult();
+
+ h.Logger.LogInformation("Auth Failed (Any): Target: {Target}, Sub: {Sub}, Field: {Field}, Value: {@Value}, Target Pass: {TargetPass}, Field Pass: {FieldPass}", target, this.Sub(), field, value, target != null && this.Sub() == target, h.HasAny(this.HttpContext.User, field, value));
return new Unauthorized("You are not authorized to access this resource").ToException();
}
diff --git a/App/Modules/DomainServices.cs b/App/Modules/DomainServices.cs
index 7444849..20ac026 100644
--- a/App/Modules/DomainServices.cs
+++ b/App/Modules/DomainServices.cs
@@ -1,8 +1,10 @@
+using App.Modules.Bookings.Data;
using App.Modules.Passengers.Data;
using App.Modules.Schedules.Data;
using App.Modules.Timings.Data;
using App.Modules.Users.Data;
using App.StartUp.Services;
+using Domain.Booking;
using Domain.Passenger;
using Domain.Schedule;
using Domain.Timings;
@@ -42,6 +44,15 @@ public static IServiceCollection AddDomainServices(this IServiceCollection s)
s.AddScoped()
.AutoTrace();
+ // Bookings
+ s.AddScoped()
+ .AutoTrace();
+
+ s.AddScoped()
+ .AutoTrace();
+
+
+
return s;
}
}
diff --git a/App/Modules/Passengers/API/V1/PassengerController.cs b/App/Modules/Passengers/API/V1/PassengerController.cs
index 0ff152e..8963aab 100644
--- a/App/Modules/Passengers/API/V1/PassengerController.cs
+++ b/App/Modules/Passengers/API/V1/PassengerController.cs
@@ -21,12 +21,14 @@ public class PassengerController(
CreatePassengerReqValidator createPassengerReqValidator,
UpdatePassengerReqValidator updatePassengerReqValidator,
PassengerSearchQueryValidator passengerSearchQueryValidator,
- AuthHelper authHelper
+ ILogger logger,
+ IAuthHelper authHelper
) : AtomiControllerBase(authHelper)
{
[Authorize, HttpGet]
public async Task>> Search([FromQuery] SearchPassengerQuery query)
{
+ logger.LogInformation("Searching for passengers, query: {@Query}", query);
var x = await this
.GuardOrAnyAsync(query.UserId, AuthRoles.Field, AuthRoles.Admin)
.ThenAwait(_ => passengerSearchQueryValidator.ValidateAsyncResult(query, "Invalid SearchPassengerQuery"))
diff --git a/App/Modules/Passengers/Data/PassengerRepository.cs b/App/Modules/Passengers/Data/PassengerRepository.cs
index 028a1f2..eadc371 100644
--- a/App/Modules/Passengers/Data/PassengerRepository.cs
+++ b/App/Modules/Passengers/Data/PassengerRepository.cs
@@ -50,6 +50,7 @@ public async Task>> Search(PassengerSearc
var user = await db
.Passengers
.Where(x => x.Id == id && (userId == null || x.UserId == userId))
+ .Include(x => x.User)
.FirstOrDefaultAsync();
return user?.ToDomain();
}
diff --git a/App/Modules/Schedules/API/V1/ScheduleController.cs b/App/Modules/Schedules/API/V1/ScheduleController.cs
index 79e8341..a1c6dd6 100644
--- a/App/Modules/Schedules/API/V1/ScheduleController.cs
+++ b/App/Modules/Schedules/API/V1/ScheduleController.cs
@@ -23,7 +23,7 @@ public class ScheduleController(
ScheduleBulkUpdateReqValidator schedulePrincipalReqValidator,
ScheduleRangeReqValidator scheduleRangeReqValidator,
ScheduleDateReqValidator scheduleDateReqValidator,
- AuthHelper authHelper
+ IAuthHelper authHelper
) : AtomiControllerBase(authHelper)
{
[Authorize(Policy = AuthPolicies.AdminOrScheduleSyncer), HttpGet("latest")]
@@ -56,13 +56,13 @@ public async Task> Get([FromRoute] ScheduleDa
}
[Authorize(Policy = AuthPolicies.AdminOrScheduleSyncer), HttpPut("{date}")]
- public async Task> Update([FromRoute] ScheduleDateReq date,
+ public async Task> Update([FromRoute] ScheduleDateReq dateReq,
[FromBody] ScheduleRecordReq record)
{
var result = await scheduleDateReqValidator
- .ValidateAsyncResult(date, "Invalid ScheduleGetReq")
+ .ValidateAsyncResult(dateReq, "Invalid ScheduleGetReq")
.ThenAwait(_ => scheduleRecordReqValidator.ValidateAsyncResult(record, "Invalid ScheduleRecordReq"))
- .ThenAwait(_ => service.Update(date.Date.ToDate(), record.ToDomain()))
+ .ThenAwait(_ => service.Update(dateReq.Date.ToDate(), record.ToDomain()))
.Then(x => x.ToRes(), Errors.MapAll);
return this.ReturnResult(result);
}
@@ -77,11 +77,11 @@ public async Task BulkUpdate([FromBody] ScheduleBulkUpdateReq sche
}
[Authorize(Policy = AuthPolicies.OnlyAdmin), HttpDelete("{date}")]
- public async Task Delete([FromRoute] ScheduleDateReq date)
+ public async Task Delete([FromRoute] ScheduleDateReq req)
{
var result = await scheduleDateReqValidator
- .ValidateAsyncResult(date, "Invalid ScheduleGetReq")
+ .ValidateAsyncResult(req, "Invalid ScheduleGetReq")
.ThenAwait(x => service.Delete(x.Date.ToDate()));
- return this.ReturnUnitNullableResult(result, new EntityNotFound("Schedule Not Found", typeof(Schedule), date.Date));
+ return this.ReturnUnitNullableResult(result, new EntityNotFound("Schedule Not Found", typeof(Schedule), req.Date));
}
}
diff --git a/App/Modules/Schedules/API/V1/ScheduleMapper.cs b/App/Modules/Schedules/API/V1/ScheduleMapper.cs
index e55c6fa..5622919 100644
--- a/App/Modules/Schedules/API/V1/ScheduleMapper.cs
+++ b/App/Modules/Schedules/API/V1/ScheduleMapper.cs
@@ -31,5 +31,9 @@ public static ScheduleRecord ToDomain(this ScheduleRecordReq record) =>
public static SchedulePrincipal ToDomain(this SchedulePrincipalReq principal) =>
- new() { Date = principal.Date.ToDate(), Record = principal.Record.ToDomain(), };
+ new()
+ {
+ Date = principal.Date.ToDate(),
+ Record = principal.Record.ToDomain(),
+ };
}
diff --git a/App/Modules/Schedules/API/V1/ScheduleModel.cs b/App/Modules/Schedules/API/V1/ScheduleModel.cs
index 932bc66..e30d86c 100644
--- a/App/Modules/Schedules/API/V1/ScheduleModel.cs
+++ b/App/Modules/Schedules/API/V1/ScheduleModel.cs
@@ -1,11 +1,12 @@
using App.Modules.Users.API.V1;
+using Microsoft.AspNetCore.Mvc;
namespace App.Modules.Schedules.API.V1;
// REQ
-public record ScheduleRangeReq(string From, string To);
+public record ScheduleRangeReq([FromRoute] string From, [FromRoute] string To);
-public record ScheduleDateReq(string Date);
+public record ScheduleDateReq([FromRoute] string Date);
public record ScheduleRecordReq(bool Confirmed, string[] JToWExcluded, string[] WToJExcluded);
diff --git a/App/Modules/Schedules/Data/ScheduleMapper.cs b/App/Modules/Schedules/Data/ScheduleMapper.cs
index 330aa75..a406a74 100644
--- a/App/Modules/Schedules/Data/ScheduleMapper.cs
+++ b/App/Modules/Schedules/Data/ScheduleMapper.cs
@@ -36,6 +36,7 @@ public static ScheduleData ToData(this SchedulePrincipal record)
return new ScheduleData
{
Date = record.Date,
+ Confirmed = record.Record.Confirmed,
JToWExcluded = record.Record.JToWExcluded.ToArray(),
WToJExcluded = record.Record.WToJExcluded.ToArray(),
};
diff --git a/App/Modules/Schedules/Data/ScheduleRepository.cs b/App/Modules/Schedules/Data/ScheduleRepository.cs
index be6a959..e1c1ac7 100644
--- a/App/Modules/Schedules/Data/ScheduleRepository.cs
+++ b/App/Modules/Schedules/Data/ScheduleRepository.cs
@@ -1,9 +1,7 @@
using App.Error.V1;
-using App.Modules.Passengers.Data;
using App.StartUp.Database;
using App.Utility;
using CSharp_Result;
-using Domain.Passenger;
using Domain.Schedule;
using EFCore.BulkExtensions;
using EntityFramework.Exceptions.Common;
@@ -114,7 +112,7 @@ public async Task> BulkUpdate(IEnumerable record
logger.LogInformation("Bulk updating Schedule, {@Records}", record.ToJson());
await db.BulkInsertOrUpdateAsync(record.Select(r => r.ToData()));
await db.BulkSaveChangesAsync();
- return new();
+ return new Unit();
}
catch (Exception e)
{
@@ -132,11 +130,15 @@ public async Task> BulkUpdate(IEnumerable record
.Where(x => x.Date == date)
.FirstOrDefaultAsync();
- if (v1 == null) return (Unit?)null;
+ if (v1 == null)
+ {
+ logger.LogInformation("Schedule on '{@Date}' does not exist.", date);
+ return (Unit?)null;
+ }
db.Schedules.Remove(v1);
await db.SaveChangesAsync();
- return new();
+ return new Unit();
}
catch (Exception e)
{
diff --git a/App/Modules/System/SystemController.cs b/App/Modules/System/SystemController.cs
index 54b7787..67e2c56 100644
--- a/App/Modules/System/SystemController.cs
+++ b/App/Modules/System/SystemController.cs
@@ -10,7 +10,7 @@ namespace App.Modules.System;
[ApiVersionNeutral]
[ApiController]
[Route("/")]
-public class SystemController(IOptionsSnapshot app, AuthHelper h) : AtomiControllerBase(h)
+public class SystemController(IOptionsSnapshot app, IAuthHelper h) : AtomiControllerBase(h)
{
[HttpGet]
public ActionResult