From 93c1879d23a49a1f078dec2a8c66d62d6255c256 Mon Sep 17 00:00:00 2001 From: sipakov Date: Wed, 14 Jun 2023 13:46:22 +0300 Subject: [PATCH] #23 added api to update reservation from lower status to contract --- .../AlgoTecture.Data.Persistence.Ef.csproj | 12 + .../ApplicationDbContext.cs | 8 +- ...0230614093857_InitialMigration.Designer.cs | 606 +++++++++++++++++ .../20230614093857_InitialMigration.cs | 400 ++++++++++++ ...AddReservationUniqueIdentifier.Designer.cs | 609 ++++++++++++++++++ ...14093945_AddReservationUniqueIdentifier.cs | 25 + .../ApplicationDbContextModelSnapshot.cs | 607 +++++++++++++++++ AlgoTecture.Data.Persistence.Ef/Provider.cs | 5 +- .../Enum/ReservationStatusType.cs | 3 +- .../Models/RepositoryModels/Reservation.cs | 2 + .../UpdateReservationStatusTests.cs | 52 ++ .../IReservationService.cs | 3 +- .../Models/UpdateReservationStatusModel.cs | 8 + .../ReservationService.cs | 20 + AlgoTecture.WebApi/AlgoTecture.WebApi.csproj | 1 + .../Controllers/ReservationController.cs | 28 + AlgoTecture.WebApi/Program.cs | 6 +- AlgoTecture.sln.DotSettings.user | 1 + 18 files changed, 2385 insertions(+), 11 deletions(-) create mode 100644 AlgoTecture.Data.Persistence.Ef/Migrations/20230614093857_InitialMigration.Designer.cs create mode 100644 AlgoTecture.Data.Persistence.Ef/Migrations/20230614093857_InitialMigration.cs create mode 100644 AlgoTecture.Data.Persistence.Ef/Migrations/20230614093945_AddReservationUniqueIdentifier.Designer.cs create mode 100644 AlgoTecture.Data.Persistence.Ef/Migrations/20230614093945_AddReservationUniqueIdentifier.cs create mode 100644 AlgoTecture.Data.Persistence.Ef/Migrations/ApplicationDbContextModelSnapshot.cs create mode 100644 AlgoTecture.Libraries.Reservations.Tests/UpdateReservationStatusTests.cs create mode 100644 AlgoTecture.Libraries.Reservations/Models/UpdateReservationStatusModel.cs create mode 100644 AlgoTecture.WebApi/Controllers/ReservationController.cs diff --git a/AlgoTecture.Data.Persistence.Ef/AlgoTecture.Data.Persistence.Ef.csproj b/AlgoTecture.Data.Persistence.Ef/AlgoTecture.Data.Persistence.Ef.csproj index 615752b..4d2ae86 100644 --- a/AlgoTecture.Data.Persistence.Ef/AlgoTecture.Data.Persistence.Ef.csproj +++ b/AlgoTecture.Data.Persistence.Ef/AlgoTecture.Data.Persistence.Ef.csproj @@ -14,10 +14,22 @@ + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + true + PreserveNewest + Always + + + diff --git a/AlgoTecture.Data.Persistence.Ef/ApplicationDbContext.cs b/AlgoTecture.Data.Persistence.Ef/ApplicationDbContext.cs index 3e0e39b..dc6cb86 100644 --- a/AlgoTecture.Data.Persistence.Ef/ApplicationDbContext.cs +++ b/AlgoTecture.Data.Persistence.Ef/ApplicationDbContext.cs @@ -26,9 +26,10 @@ public class ApplicationDbContext : DbContext public virtual DbSet PriceSpecifications { get; set; } - private Provider _provider; - public ApplicationDbContext() {} - + private Provider _provider = Provider.NpgSql; + + public ApplicationDbContext() { } + public ApplicationDbContext(Provider provider = Provider.NpgSql) { _provider = provider; @@ -45,6 +46,7 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) } var appConnectionString = Configurator.GetConfiguration().GetConnectionString("Algotecture-Demo"); + if (string.IsNullOrEmpty(appConnectionString)) return; if (optionsBuilder.IsConfigured) diff --git a/AlgoTecture.Data.Persistence.Ef/Migrations/20230614093857_InitialMigration.Designer.cs b/AlgoTecture.Data.Persistence.Ef/Migrations/20230614093857_InitialMigration.Designer.cs new file mode 100644 index 0000000..271d772 --- /dev/null +++ b/AlgoTecture.Data.Persistence.Ef/Migrations/20230614093857_InitialMigration.Designer.cs @@ -0,0 +1,606 @@ +// +using System; +using AlgoTecture.Data.Persistence.Ef; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace AlgoTecture.Data.Persistence.Ef.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20230614093857_InitialMigration")] + partial class InitialMigration + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.Contract", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ContractDateTimeUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("ContractFromUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("ContractToUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("DeclarationDateTime") + .HasColumnType("timestamp with time zone"); + + b.Property("OwnerUserId") + .HasColumnType("bigint"); + + b.Property("PriceCurrency") + .IsRequired() + .HasColumnType("text"); + + b.Property("PriceSpecificationId") + .HasColumnType("bigint"); + + b.Property("ReservationId") + .HasColumnType("bigint"); + + b.Property("SpaceId") + .HasColumnType("bigint"); + + b.Property("SubSpaceId") + .HasColumnType("uuid"); + + b.Property("TenantUserId") + .HasColumnType("bigint"); + + b.Property("TotalPrice") + .IsRequired() + .HasColumnType("text"); + + b.Property("UtilizationTypeId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("OwnerUserId"); + + b.HasIndex("PriceSpecificationId"); + + b.HasIndex("ReservationId"); + + b.HasIndex("SpaceId"); + + b.HasIndex("SubSpaceId"); + + b.HasIndex("TenantUserId"); + + b.HasIndex("UtilizationTypeId"); + + b.ToTable("Contracts"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.PriceSpecification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PriceCurrency") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("PricePerTime") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SpaceId") + .HasColumnType("bigint"); + + b.Property("SubSpaceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("UnitOfTime") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ValidFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("ValidThrough") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("SpaceId"); + + b.ToTable("PriceSpecifications"); + + b.HasData( + new + { + Id = 1L, + PriceCurrency = "Usd", + PricePerTime = "50", + SpaceId = 1L, + UnitOfTime = "Hour" + }, + new + { + Id = 2L, + PriceCurrency = "Usd", + PricePerTime = "45", + SpaceId = 2L, + UnitOfTime = "Hour" + }, + new + { + Id = 3L, + PriceCurrency = "Usd", + PricePerTime = "60", + SpaceId = 3L, + UnitOfTime = "Hour" + }); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.Reservation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("PriceSpecificationId") + .HasColumnType("bigint"); + + b.Property("ReservationDateTimeUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("ReservationFromUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("ReservationStatus") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ReservationToUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("SpaceId") + .HasColumnType("bigint"); + + b.Property("SubSpaceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("TenantUserId") + .HasColumnType("bigint"); + + b.Property("TotalPrice") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.HasIndex("PriceSpecificationId"); + + b.HasIndex("SpaceId"); + + b.HasIndex("TenantUserId"); + + b.ToTable("Reservations"); + + b.HasData( + new + { + Id = 1L, + PriceSpecificationId = 1L, + ReservationDateTimeUtc = new DateTime(2023, 3, 16, 12, 0, 0, 0, DateTimeKind.Utc), + ReservationFromUtc = new DateTime(2023, 3, 17, 12, 0, 0, 0, DateTimeKind.Utc), + ReservationStatus = "Confirmed", + ReservationToUtc = new DateTime(2023, 3, 17, 14, 0, 0, 0, DateTimeKind.Utc), + SpaceId = 1L, + TenantUserId = 2L, + TotalPrice = "100" + }, + new + { + Id = 2L, + PriceSpecificationId = 1L, + ReservationDateTimeUtc = new DateTime(2023, 3, 17, 12, 0, 0, 0, DateTimeKind.Utc), + ReservationFromUtc = new DateTime(2023, 3, 18, 12, 0, 0, 0, DateTimeKind.Utc), + ReservationStatus = "Confirmed", + ReservationToUtc = new DateTime(2023, 3, 18, 15, 0, 0, 0, DateTimeKind.Utc), + SpaceId = 1L, + TenantUserId = 3L, + TotalPrice = "100" + }); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.Space", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Latitude") + .HasColumnType("double precision"); + + b.Property("Longitude") + .HasColumnType("double precision"); + + b.Property("SpaceAddress") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("SpaceProperty") + .IsRequired() + .HasColumnType("text"); + + b.Property("UtilizationTypeId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("Latitude"); + + b.HasIndex("Longitude"); + + b.HasIndex("UtilizationTypeId"); + + b.ToTable("Spaces"); + + b.HasData( + new + { + Id = 1L, + Latitude = 47.361812591552734, + Longitude = 8.5370702743530273, + SpaceAddress = "Mythenquai 7, 8002 Zürich", + SpaceProperty = "{\"SpacePropertyId\":\"4c4f455c-bc98-47da-9f4b-9dcc25a17fe5\",\"Name\":\"Santa María\",\"Description\":\"best boat in the world\",\"Properties\":null,\"OwnerId\":0,\"ContractId\":0,\"SubSpaces\":null}", + UtilizationTypeId = 12 + }, + new + { + Id = 2L, + Latitude = 47.361648559570312, + Longitude = 8.5366735458374023, + SpaceAddress = "Mythenquai 9, 8002 Zürich", + SpaceProperty = "{\"SpacePropertyId\":\"7d2dc2f3-4f52-4244-8ade-73eba2772a51\",\"Name\":\"Niña\",\"Description\":\"best boat in the world\",\"Properties\":null,\"OwnerId\":0,\"ContractId\":0,\"SubSpaces\":null}", + UtilizationTypeId = 12 + }, + new + { + Id = 3L, + Latitude = 47.361316680908203, + Longitude = 8.5362958908081055, + SpaceAddress = "Mythenquai 25, 8002 Zürich", + SpaceProperty = "{\"SpacePropertyId\":\"a5f8e388-0c2f-491c-82ff-d4c92da97aaa\",\"Name\":\"Pinta\",\"Description\":\"best boat in the world\",\"Properties\":null,\"OwnerId\":0,\"ContractId\":0,\"SubSpaces\":null}", + UtilizationTypeId = 12 + }); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.TelegramUserInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("TelegramChatId") + .HasColumnType("bigint"); + + b.Property("TelegramUserFullName") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("TelegramUserId") + .HasColumnType("bigint"); + + b.Property("TelegramUserName") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.HasKey("Id"); + + b.ToTable("TelegramUserInfos"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreateDateTimeUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Phone") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("TelegramUserInfoId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("TelegramUserInfoId"); + + b.ToTable("Users"); + + b.HasData( + new + { + Id = 1L, + CreateDateTimeUtc = new DateTime(2023, 2, 20, 21, 0, 0, 0, DateTimeKind.Utc) + }, + new + { + Id = 2L, + CreateDateTimeUtc = new DateTime(2023, 3, 13, 21, 0, 0, 0, DateTimeKind.Utc) + }, + new + { + Id = 3L, + CreateDateTimeUtc = new DateTime(2023, 3, 13, 21, 0, 0, 0, DateTimeKind.Utc) + }, + new + { + Id = 4L, + CreateDateTimeUtc = new DateTime(2023, 3, 15, 21, 0, 0, 0, DateTimeKind.Utc) + }); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.UserAuthentication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("HashedPassword") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserAuthentications"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.UtilizationType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.HasKey("Id"); + + b.ToTable("UtilizationTypes"); + + b.HasData( + new + { + Id = 1, + Name = "Residential" + }, + new + { + Id = 2, + Name = "Сommercial" + }, + new + { + Id = 3, + Name = "Production" + }, + new + { + Id = 4, + Name = "Warehouse" + }, + new + { + Id = 5, + Name = "Public catering" + }, + new + { + Id = 6, + Name = "Utility" + }, + new + { + Id = 7, + Name = "Office space" + }, + new + { + Id = 8, + Name = "Education" + }, + new + { + Id = 9, + Name = "Sports" + }, + new + { + Id = 10, + Name = "Free target" + }, + new + { + Id = 11, + Name = "Parking" + }, + new + { + Id = 12, + Name = "Boat" + }); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.Contract", b => + { + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.User", "OwnerUser") + .WithMany() + .HasForeignKey("OwnerUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.PriceSpecification", "PriceSpecification") + .WithMany() + .HasForeignKey("PriceSpecificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.Reservation", "Reservation") + .WithMany() + .HasForeignKey("ReservationId"); + + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.Space", "Space") + .WithMany() + .HasForeignKey("SpaceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.User", "TenantUser") + .WithMany() + .HasForeignKey("TenantUserId"); + + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.UtilizationType", "UtilizationType") + .WithMany() + .HasForeignKey("UtilizationTypeId"); + + b.Navigation("OwnerUser"); + + b.Navigation("PriceSpecification"); + + b.Navigation("Reservation"); + + b.Navigation("Space"); + + b.Navigation("TenantUser"); + + b.Navigation("UtilizationType"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.PriceSpecification", b => + { + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.Space", "Space") + .WithMany() + .HasForeignKey("SpaceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Space"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.Reservation", b => + { + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.PriceSpecification", "PriceSpecification") + .WithMany() + .HasForeignKey("PriceSpecificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.Space", "Space") + .WithMany() + .HasForeignKey("SpaceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.User", "TenantUser") + .WithMany() + .HasForeignKey("TenantUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PriceSpecification"); + + b.Navigation("Space"); + + b.Navigation("TenantUser"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.Space", b => + { + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.UtilizationType", "UtilizationType") + .WithMany() + .HasForeignKey("UtilizationTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("UtilizationType"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.User", b => + { + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.TelegramUserInfo", "TelegramUserInfo") + .WithMany() + .HasForeignKey("TelegramUserInfoId"); + + b.Navigation("TelegramUserInfo"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.UserAuthentication", b => + { + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/AlgoTecture.Data.Persistence.Ef/Migrations/20230614093857_InitialMigration.cs b/AlgoTecture.Data.Persistence.Ef/Migrations/20230614093857_InitialMigration.cs new file mode 100644 index 0000000..c9fe560 --- /dev/null +++ b/AlgoTecture.Data.Persistence.Ef/Migrations/20230614093857_InitialMigration.cs @@ -0,0 +1,400 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace AlgoTecture.Data.Persistence.Ef.Migrations +{ + public partial class InitialMigration : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "TelegramUserInfos", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + TelegramUserId = table.Column(type: "bigint", nullable: true), + TelegramChatId = table.Column(type: "bigint", nullable: true), + TelegramUserName = table.Column(type: "character varying(500)", maxLength: 500, nullable: true), + TelegramUserFullName = table.Column(type: "character varying(500)", maxLength: 500, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_TelegramUserInfos", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "UtilizationTypes", + columns: table => new + { + Id = table.Column(type: "integer", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Name = table.Column(type: "character varying(500)", maxLength: 500, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UtilizationTypes", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Users", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Phone = table.Column(type: "character varying(500)", maxLength: 500, nullable: true), + Email = table.Column(type: "character varying(500)", maxLength: 500, nullable: true), + TelegramUserInfoId = table.Column(type: "bigint", nullable: true), + CreateDateTimeUtc = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Users", x => x.Id); + table.ForeignKey( + name: "FK_Users_TelegramUserInfos_TelegramUserInfoId", + column: x => x.TelegramUserInfoId, + principalTable: "TelegramUserInfos", + principalColumn: "Id"); + }); + + migrationBuilder.CreateTable( + name: "Spaces", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + UtilizationTypeId = table.Column(type: "integer", nullable: false), + SpaceAddress = table.Column(type: "character varying(500)", maxLength: 500, nullable: false), + Latitude = table.Column(type: "double precision", nullable: false), + Longitude = table.Column(type: "double precision", nullable: false), + SpaceProperty = table.Column(type: "text", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Spaces", x => x.Id); + table.ForeignKey( + name: "FK_Spaces_UtilizationTypes_UtilizationTypeId", + column: x => x.UtilizationTypeId, + principalTable: "UtilizationTypes", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "UserAuthentications", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + UserId = table.Column(type: "bigint", nullable: false), + HashedPassword = table.Column(type: "character varying(500)", maxLength: 500, nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_UserAuthentications", x => x.Id); + table.ForeignKey( + name: "FK_UserAuthentications_Users_UserId", + column: x => x.UserId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PriceSpecifications", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + SpaceId = table.Column(type: "bigint", nullable: false), + SubSpaceId = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + PricePerTime = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + PriceCurrency = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + UnitOfTime = table.Column(type: "character varying(100)", maxLength: 100, nullable: false), + ValidFrom = table.Column(type: "timestamp with time zone", nullable: true), + ValidThrough = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_PriceSpecifications", x => x.Id); + table.ForeignKey( + name: "FK_PriceSpecifications_Spaces_SpaceId", + column: x => x.SpaceId, + principalTable: "Spaces", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Reservations", + columns: table => new + { + Id = table.Column(type: "bigint", nullable: false) + .Annotation("Npgsql:ValueGenerationStrategy", NpgsqlValueGenerationStrategy.IdentityByDefaultColumn), + Description = table.Column(type: "character varying(500)", maxLength: 500, nullable: true), + TenantUserId = table.Column(type: "bigint", nullable: false), + SpaceId = table.Column(type: "bigint", nullable: false), + SubSpaceId = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + TotalPrice = table.Column(type: "character varying(100)", maxLength: 100, nullable: true), + PriceSpecificationId = table.Column(type: "bigint", nullable: false), + ReservationDateTimeUtc = table.Column(type: "timestamp with time zone", nullable: true), + ReservationFromUtc = table.Column(type: "timestamp with time zone", nullable: true), + ReservationToUtc = table.Column(type: "timestamp with time zone", nullable: true), + ReservationStatus = table.Column(type: "character varying(100)", maxLength: 100, nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Reservations", x => x.Id); + table.ForeignKey( + name: "FK_Reservations_PriceSpecifications_PriceSpecificationId", + column: x => x.PriceSpecificationId, + principalTable: "PriceSpecifications", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Reservations_Spaces_SpaceId", + column: x => x.SpaceId, + principalTable: "Spaces", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Reservations_Users_TenantUserId", + column: x => x.TenantUserId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Contracts", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + OwnerUserId = table.Column(type: "bigint", nullable: false), + TenantUserId = table.Column(type: "bigint", nullable: true), + SpaceId = table.Column(type: "bigint", nullable: false), + SubSpaceId = table.Column(type: "uuid", nullable: false), + PriceCurrency = table.Column(type: "text", nullable: false), + TotalPrice = table.Column(type: "text", nullable: false), + PriceSpecificationId = table.Column(type: "bigint", nullable: false), + UtilizationTypeId = table.Column(type: "integer", nullable: true), + ReservationId = table.Column(type: "bigint", nullable: true), + DeclarationDateTime = table.Column(type: "timestamp with time zone", nullable: true), + ContractFromUtc = table.Column(type: "timestamp with time zone", nullable: true), + ContractToUtc = table.Column(type: "timestamp with time zone", nullable: true), + ContractDateTimeUtc = table.Column(type: "timestamp with time zone", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Contracts", x => x.Id); + table.ForeignKey( + name: "FK_Contracts_PriceSpecifications_PriceSpecificationId", + column: x => x.PriceSpecificationId, + principalTable: "PriceSpecifications", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Contracts_Reservations_ReservationId", + column: x => x.ReservationId, + principalTable: "Reservations", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_Contracts_Spaces_SpaceId", + column: x => x.SpaceId, + principalTable: "Spaces", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Contracts_Users_OwnerUserId", + column: x => x.OwnerUserId, + principalTable: "Users", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_Contracts_Users_TenantUserId", + column: x => x.TenantUserId, + principalTable: "Users", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_Contracts_UtilizationTypes_UtilizationTypeId", + column: x => x.UtilizationTypeId, + principalTable: "UtilizationTypes", + principalColumn: "Id"); + }); + + migrationBuilder.InsertData( + table: "Users", + columns: new[] { "Id", "CreateDateTimeUtc", "Email", "Phone", "TelegramUserInfoId" }, + values: new object[,] + { + { 1L, new DateTime(2023, 2, 20, 21, 0, 0, 0, DateTimeKind.Utc), null, null, null }, + { 2L, new DateTime(2023, 3, 13, 21, 0, 0, 0, DateTimeKind.Utc), null, null, null }, + { 3L, new DateTime(2023, 3, 13, 21, 0, 0, 0, DateTimeKind.Utc), null, null, null }, + { 4L, new DateTime(2023, 3, 15, 21, 0, 0, 0, DateTimeKind.Utc), null, null, null } + }); + + migrationBuilder.InsertData( + table: "UtilizationTypes", + columns: new[] { "Id", "Name" }, + values: new object[,] + { + { 1, "Residential" }, + { 2, "Сommercial" }, + { 3, "Production" }, + { 4, "Warehouse" }, + { 5, "Public catering" }, + { 6, "Utility" }, + { 7, "Office space" }, + { 8, "Education" }, + { 9, "Sports" }, + { 10, "Free target" }, + { 11, "Parking" }, + { 12, "Boat" } + }); + + migrationBuilder.InsertData( + table: "Spaces", + columns: new[] { "Id", "Latitude", "Longitude", "SpaceAddress", "SpaceProperty", "UtilizationTypeId" }, + values: new object[,] + { + { 1L, 47.361812591552734, 8.5370702743530273, "Mythenquai 7, 8002 Zürich", "{\"SpacePropertyId\":\"4c4f455c-bc98-47da-9f4b-9dcc25a17fe5\",\"Name\":\"Santa María\",\"Description\":\"best boat in the world\",\"Properties\":null,\"OwnerId\":0,\"ContractId\":0,\"SubSpaces\":null}", 12 }, + { 2L, 47.361648559570312, 8.5366735458374023, "Mythenquai 9, 8002 Zürich", "{\"SpacePropertyId\":\"7d2dc2f3-4f52-4244-8ade-73eba2772a51\",\"Name\":\"Niña\",\"Description\":\"best boat in the world\",\"Properties\":null,\"OwnerId\":0,\"ContractId\":0,\"SubSpaces\":null}", 12 }, + { 3L, 47.361316680908203, 8.5362958908081055, "Mythenquai 25, 8002 Zürich", "{\"SpacePropertyId\":\"a5f8e388-0c2f-491c-82ff-d4c92da97aaa\",\"Name\":\"Pinta\",\"Description\":\"best boat in the world\",\"Properties\":null,\"OwnerId\":0,\"ContractId\":0,\"SubSpaces\":null}", 12 } + }); + + migrationBuilder.InsertData( + table: "PriceSpecifications", + columns: new[] { "Id", "PriceCurrency", "PricePerTime", "SpaceId", "SubSpaceId", "UnitOfTime", "ValidFrom", "ValidThrough" }, + values: new object[,] + { + { 1L, "Usd", "50", 1L, null, "Hour", null, null }, + { 2L, "Usd", "45", 2L, null, "Hour", null, null }, + { 3L, "Usd", "60", 3L, null, "Hour", null, null } + }); + + migrationBuilder.InsertData( + table: "Reservations", + columns: new[] { "Id", "Description", "PriceSpecificationId", "ReservationDateTimeUtc", "ReservationFromUtc", "ReservationStatus", "ReservationToUtc", "SpaceId", "SubSpaceId", "TenantUserId", "TotalPrice" }, + values: new object[,] + { + { 1L, null, 1L, new DateTime(2023, 3, 16, 12, 0, 0, 0, DateTimeKind.Utc), new DateTime(2023, 3, 17, 12, 0, 0, 0, DateTimeKind.Utc), "Confirmed", new DateTime(2023, 3, 17, 14, 0, 0, 0, DateTimeKind.Utc), 1L, null, 2L, "100" }, + { 2L, null, 1L, new DateTime(2023, 3, 17, 12, 0, 0, 0, DateTimeKind.Utc), new DateTime(2023, 3, 18, 12, 0, 0, 0, DateTimeKind.Utc), "Confirmed", new DateTime(2023, 3, 18, 15, 0, 0, 0, DateTimeKind.Utc), 1L, null, 3L, "100" } + }); + + migrationBuilder.CreateIndex( + name: "IX_Contracts_OwnerUserId", + table: "Contracts", + column: "OwnerUserId"); + + migrationBuilder.CreateIndex( + name: "IX_Contracts_PriceSpecificationId", + table: "Contracts", + column: "PriceSpecificationId"); + + migrationBuilder.CreateIndex( + name: "IX_Contracts_ReservationId", + table: "Contracts", + column: "ReservationId"); + + migrationBuilder.CreateIndex( + name: "IX_Contracts_SpaceId", + table: "Contracts", + column: "SpaceId"); + + migrationBuilder.CreateIndex( + name: "IX_Contracts_SubSpaceId", + table: "Contracts", + column: "SubSpaceId"); + + migrationBuilder.CreateIndex( + name: "IX_Contracts_TenantUserId", + table: "Contracts", + column: "TenantUserId"); + + migrationBuilder.CreateIndex( + name: "IX_Contracts_UtilizationTypeId", + table: "Contracts", + column: "UtilizationTypeId"); + + migrationBuilder.CreateIndex( + name: "IX_PriceSpecifications_SpaceId", + table: "PriceSpecifications", + column: "SpaceId"); + + migrationBuilder.CreateIndex( + name: "IX_Reservations_PriceSpecificationId", + table: "Reservations", + column: "PriceSpecificationId"); + + migrationBuilder.CreateIndex( + name: "IX_Reservations_SpaceId", + table: "Reservations", + column: "SpaceId"); + + migrationBuilder.CreateIndex( + name: "IX_Reservations_TenantUserId", + table: "Reservations", + column: "TenantUserId"); + + migrationBuilder.CreateIndex( + name: "IX_Spaces_Latitude", + table: "Spaces", + column: "Latitude"); + + migrationBuilder.CreateIndex( + name: "IX_Spaces_Longitude", + table: "Spaces", + column: "Longitude"); + + migrationBuilder.CreateIndex( + name: "IX_Spaces_UtilizationTypeId", + table: "Spaces", + column: "UtilizationTypeId"); + + migrationBuilder.CreateIndex( + name: "IX_UserAuthentications_UserId", + table: "UserAuthentications", + column: "UserId"); + + migrationBuilder.CreateIndex( + name: "IX_Users_Email", + table: "Users", + column: "Email"); + + migrationBuilder.CreateIndex( + name: "IX_Users_TelegramUserInfoId", + table: "Users", + column: "TelegramUserInfoId"); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "Contracts"); + + migrationBuilder.DropTable( + name: "UserAuthentications"); + + migrationBuilder.DropTable( + name: "Reservations"); + + migrationBuilder.DropTable( + name: "PriceSpecifications"); + + migrationBuilder.DropTable( + name: "Users"); + + migrationBuilder.DropTable( + name: "Spaces"); + + migrationBuilder.DropTable( + name: "TelegramUserInfos"); + + migrationBuilder.DropTable( + name: "UtilizationTypes"); + } + } +} diff --git a/AlgoTecture.Data.Persistence.Ef/Migrations/20230614093945_AddReservationUniqueIdentifier.Designer.cs b/AlgoTecture.Data.Persistence.Ef/Migrations/20230614093945_AddReservationUniqueIdentifier.Designer.cs new file mode 100644 index 0000000..336ef84 --- /dev/null +++ b/AlgoTecture.Data.Persistence.Ef/Migrations/20230614093945_AddReservationUniqueIdentifier.Designer.cs @@ -0,0 +1,609 @@ +// +using System; +using AlgoTecture.Data.Persistence.Ef; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace AlgoTecture.Data.Persistence.Ef.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + [Migration("20230614093945_AddReservationUniqueIdentifier")] + partial class AddReservationUniqueIdentifier + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.Contract", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ContractDateTimeUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("ContractFromUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("ContractToUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("DeclarationDateTime") + .HasColumnType("timestamp with time zone"); + + b.Property("OwnerUserId") + .HasColumnType("bigint"); + + b.Property("PriceCurrency") + .IsRequired() + .HasColumnType("text"); + + b.Property("PriceSpecificationId") + .HasColumnType("bigint"); + + b.Property("ReservationId") + .HasColumnType("bigint"); + + b.Property("SpaceId") + .HasColumnType("bigint"); + + b.Property("SubSpaceId") + .HasColumnType("uuid"); + + b.Property("TenantUserId") + .HasColumnType("bigint"); + + b.Property("TotalPrice") + .IsRequired() + .HasColumnType("text"); + + b.Property("UtilizationTypeId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("OwnerUserId"); + + b.HasIndex("PriceSpecificationId"); + + b.HasIndex("ReservationId"); + + b.HasIndex("SpaceId"); + + b.HasIndex("SubSpaceId"); + + b.HasIndex("TenantUserId"); + + b.HasIndex("UtilizationTypeId"); + + b.ToTable("Contracts"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.PriceSpecification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PriceCurrency") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("PricePerTime") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SpaceId") + .HasColumnType("bigint"); + + b.Property("SubSpaceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("UnitOfTime") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ValidFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("ValidThrough") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("SpaceId"); + + b.ToTable("PriceSpecifications"); + + b.HasData( + new + { + Id = 1L, + PriceCurrency = "Usd", + PricePerTime = "50", + SpaceId = 1L, + UnitOfTime = "Hour" + }, + new + { + Id = 2L, + PriceCurrency = "Usd", + PricePerTime = "45", + SpaceId = 2L, + UnitOfTime = "Hour" + }, + new + { + Id = 3L, + PriceCurrency = "Usd", + PricePerTime = "60", + SpaceId = 3L, + UnitOfTime = "Hour" + }); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.Reservation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("PriceSpecificationId") + .HasColumnType("bigint"); + + b.Property("ReservationDateTimeUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("ReservationFromUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("ReservationStatus") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ReservationToUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("ReservationUniqueIdentifier") + .HasColumnType("text"); + + b.Property("SpaceId") + .HasColumnType("bigint"); + + b.Property("SubSpaceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("TenantUserId") + .HasColumnType("bigint"); + + b.Property("TotalPrice") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.HasIndex("PriceSpecificationId"); + + b.HasIndex("SpaceId"); + + b.HasIndex("TenantUserId"); + + b.ToTable("Reservations"); + + b.HasData( + new + { + Id = 1L, + PriceSpecificationId = 1L, + ReservationDateTimeUtc = new DateTime(2023, 3, 16, 12, 0, 0, 0, DateTimeKind.Utc), + ReservationFromUtc = new DateTime(2023, 3, 17, 12, 0, 0, 0, DateTimeKind.Utc), + ReservationStatus = "Confirmed", + ReservationToUtc = new DateTime(2023, 3, 17, 14, 0, 0, 0, DateTimeKind.Utc), + SpaceId = 1L, + TenantUserId = 2L, + TotalPrice = "100" + }, + new + { + Id = 2L, + PriceSpecificationId = 1L, + ReservationDateTimeUtc = new DateTime(2023, 3, 17, 12, 0, 0, 0, DateTimeKind.Utc), + ReservationFromUtc = new DateTime(2023, 3, 18, 12, 0, 0, 0, DateTimeKind.Utc), + ReservationStatus = "Confirmed", + ReservationToUtc = new DateTime(2023, 3, 18, 15, 0, 0, 0, DateTimeKind.Utc), + SpaceId = 1L, + TenantUserId = 3L, + TotalPrice = "100" + }); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.Space", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Latitude") + .HasColumnType("double precision"); + + b.Property("Longitude") + .HasColumnType("double precision"); + + b.Property("SpaceAddress") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("SpaceProperty") + .IsRequired() + .HasColumnType("text"); + + b.Property("UtilizationTypeId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("Latitude"); + + b.HasIndex("Longitude"); + + b.HasIndex("UtilizationTypeId"); + + b.ToTable("Spaces"); + + b.HasData( + new + { + Id = 1L, + Latitude = 47.361812591552734, + Longitude = 8.5370702743530273, + SpaceAddress = "Mythenquai 7, 8002 Zürich", + SpaceProperty = "{\"SpacePropertyId\":\"4c4f455c-bc98-47da-9f4b-9dcc25a17fe5\",\"Name\":\"Santa María\",\"Description\":\"best boat in the world\",\"Properties\":null,\"OwnerId\":0,\"ContractId\":0,\"SubSpaces\":null}", + UtilizationTypeId = 12 + }, + new + { + Id = 2L, + Latitude = 47.361648559570312, + Longitude = 8.5366735458374023, + SpaceAddress = "Mythenquai 9, 8002 Zürich", + SpaceProperty = "{\"SpacePropertyId\":\"7d2dc2f3-4f52-4244-8ade-73eba2772a51\",\"Name\":\"Niña\",\"Description\":\"best boat in the world\",\"Properties\":null,\"OwnerId\":0,\"ContractId\":0,\"SubSpaces\":null}", + UtilizationTypeId = 12 + }, + new + { + Id = 3L, + Latitude = 47.361316680908203, + Longitude = 8.5362958908081055, + SpaceAddress = "Mythenquai 25, 8002 Zürich", + SpaceProperty = "{\"SpacePropertyId\":\"a5f8e388-0c2f-491c-82ff-d4c92da97aaa\",\"Name\":\"Pinta\",\"Description\":\"best boat in the world\",\"Properties\":null,\"OwnerId\":0,\"ContractId\":0,\"SubSpaces\":null}", + UtilizationTypeId = 12 + }); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.TelegramUserInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("TelegramChatId") + .HasColumnType("bigint"); + + b.Property("TelegramUserFullName") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("TelegramUserId") + .HasColumnType("bigint"); + + b.Property("TelegramUserName") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.HasKey("Id"); + + b.ToTable("TelegramUserInfos"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreateDateTimeUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Phone") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("TelegramUserInfoId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("TelegramUserInfoId"); + + b.ToTable("Users"); + + b.HasData( + new + { + Id = 1L, + CreateDateTimeUtc = new DateTime(2023, 2, 20, 21, 0, 0, 0, DateTimeKind.Utc) + }, + new + { + Id = 2L, + CreateDateTimeUtc = new DateTime(2023, 3, 13, 21, 0, 0, 0, DateTimeKind.Utc) + }, + new + { + Id = 3L, + CreateDateTimeUtc = new DateTime(2023, 3, 13, 21, 0, 0, 0, DateTimeKind.Utc) + }, + new + { + Id = 4L, + CreateDateTimeUtc = new DateTime(2023, 3, 15, 21, 0, 0, 0, DateTimeKind.Utc) + }); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.UserAuthentication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("HashedPassword") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserAuthentications"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.UtilizationType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.HasKey("Id"); + + b.ToTable("UtilizationTypes"); + + b.HasData( + new + { + Id = 1, + Name = "Residential" + }, + new + { + Id = 2, + Name = "Сommercial" + }, + new + { + Id = 3, + Name = "Production" + }, + new + { + Id = 4, + Name = "Warehouse" + }, + new + { + Id = 5, + Name = "Public catering" + }, + new + { + Id = 6, + Name = "Utility" + }, + new + { + Id = 7, + Name = "Office space" + }, + new + { + Id = 8, + Name = "Education" + }, + new + { + Id = 9, + Name = "Sports" + }, + new + { + Id = 10, + Name = "Free target" + }, + new + { + Id = 11, + Name = "Parking" + }, + new + { + Id = 12, + Name = "Boat" + }); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.Contract", b => + { + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.User", "OwnerUser") + .WithMany() + .HasForeignKey("OwnerUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.PriceSpecification", "PriceSpecification") + .WithMany() + .HasForeignKey("PriceSpecificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.Reservation", "Reservation") + .WithMany() + .HasForeignKey("ReservationId"); + + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.Space", "Space") + .WithMany() + .HasForeignKey("SpaceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.User", "TenantUser") + .WithMany() + .HasForeignKey("TenantUserId"); + + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.UtilizationType", "UtilizationType") + .WithMany() + .HasForeignKey("UtilizationTypeId"); + + b.Navigation("OwnerUser"); + + b.Navigation("PriceSpecification"); + + b.Navigation("Reservation"); + + b.Navigation("Space"); + + b.Navigation("TenantUser"); + + b.Navigation("UtilizationType"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.PriceSpecification", b => + { + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.Space", "Space") + .WithMany() + .HasForeignKey("SpaceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Space"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.Reservation", b => + { + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.PriceSpecification", "PriceSpecification") + .WithMany() + .HasForeignKey("PriceSpecificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.Space", "Space") + .WithMany() + .HasForeignKey("SpaceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.User", "TenantUser") + .WithMany() + .HasForeignKey("TenantUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PriceSpecification"); + + b.Navigation("Space"); + + b.Navigation("TenantUser"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.Space", b => + { + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.UtilizationType", "UtilizationType") + .WithMany() + .HasForeignKey("UtilizationTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("UtilizationType"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.User", b => + { + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.TelegramUserInfo", "TelegramUserInfo") + .WithMany() + .HasForeignKey("TelegramUserInfoId"); + + b.Navigation("TelegramUserInfo"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.UserAuthentication", b => + { + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/AlgoTecture.Data.Persistence.Ef/Migrations/20230614093945_AddReservationUniqueIdentifier.cs b/AlgoTecture.Data.Persistence.Ef/Migrations/20230614093945_AddReservationUniqueIdentifier.cs new file mode 100644 index 0000000..75c31d5 --- /dev/null +++ b/AlgoTecture.Data.Persistence.Ef/Migrations/20230614093945_AddReservationUniqueIdentifier.cs @@ -0,0 +1,25 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace AlgoTecture.Data.Persistence.Ef.Migrations +{ + public partial class AddReservationUniqueIdentifier : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "ReservationUniqueIdentifier", + table: "Reservations", + type: "text", + nullable: true); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "ReservationUniqueIdentifier", + table: "Reservations"); + } + } +} diff --git a/AlgoTecture.Data.Persistence.Ef/Migrations/ApplicationDbContextModelSnapshot.cs b/AlgoTecture.Data.Persistence.Ef/Migrations/ApplicationDbContextModelSnapshot.cs new file mode 100644 index 0000000..bce364b --- /dev/null +++ b/AlgoTecture.Data.Persistence.Ef/Migrations/ApplicationDbContextModelSnapshot.cs @@ -0,0 +1,607 @@ +// +using System; +using AlgoTecture.Data.Persistence.Ef; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace AlgoTecture.Data.Persistence.Ef.Migrations +{ + [DbContext(typeof(ApplicationDbContext))] + partial class ApplicationDbContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.3") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.Contract", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ContractDateTimeUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("ContractFromUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("ContractToUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("DeclarationDateTime") + .HasColumnType("timestamp with time zone"); + + b.Property("OwnerUserId") + .HasColumnType("bigint"); + + b.Property("PriceCurrency") + .IsRequired() + .HasColumnType("text"); + + b.Property("PriceSpecificationId") + .HasColumnType("bigint"); + + b.Property("ReservationId") + .HasColumnType("bigint"); + + b.Property("SpaceId") + .HasColumnType("bigint"); + + b.Property("SubSpaceId") + .HasColumnType("uuid"); + + b.Property("TenantUserId") + .HasColumnType("bigint"); + + b.Property("TotalPrice") + .IsRequired() + .HasColumnType("text"); + + b.Property("UtilizationTypeId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("OwnerUserId"); + + b.HasIndex("PriceSpecificationId"); + + b.HasIndex("ReservationId"); + + b.HasIndex("SpaceId"); + + b.HasIndex("SubSpaceId"); + + b.HasIndex("TenantUserId"); + + b.HasIndex("UtilizationTypeId"); + + b.ToTable("Contracts"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.PriceSpecification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("PriceCurrency") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("PricePerTime") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("SpaceId") + .HasColumnType("bigint"); + + b.Property("SubSpaceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("UnitOfTime") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ValidFrom") + .HasColumnType("timestamp with time zone"); + + b.Property("ValidThrough") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("SpaceId"); + + b.ToTable("PriceSpecifications"); + + b.HasData( + new + { + Id = 1L, + PriceCurrency = "Usd", + PricePerTime = "50", + SpaceId = 1L, + UnitOfTime = "Hour" + }, + new + { + Id = 2L, + PriceCurrency = "Usd", + PricePerTime = "45", + SpaceId = 2L, + UnitOfTime = "Hour" + }, + new + { + Id = 3L, + PriceCurrency = "Usd", + PricePerTime = "60", + SpaceId = 3L, + UnitOfTime = "Hour" + }); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.Reservation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("PriceSpecificationId") + .HasColumnType("bigint"); + + b.Property("ReservationDateTimeUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("ReservationFromUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("ReservationStatus") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("ReservationToUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("ReservationUniqueIdentifier") + .HasColumnType("text"); + + b.Property("SpaceId") + .HasColumnType("bigint"); + + b.Property("SubSpaceId") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.Property("TenantUserId") + .HasColumnType("bigint"); + + b.Property("TotalPrice") + .HasMaxLength(100) + .HasColumnType("character varying(100)"); + + b.HasKey("Id"); + + b.HasIndex("PriceSpecificationId"); + + b.HasIndex("SpaceId"); + + b.HasIndex("TenantUserId"); + + b.ToTable("Reservations"); + + b.HasData( + new + { + Id = 1L, + PriceSpecificationId = 1L, + ReservationDateTimeUtc = new DateTime(2023, 3, 16, 12, 0, 0, 0, DateTimeKind.Utc), + ReservationFromUtc = new DateTime(2023, 3, 17, 12, 0, 0, 0, DateTimeKind.Utc), + ReservationStatus = "Confirmed", + ReservationToUtc = new DateTime(2023, 3, 17, 14, 0, 0, 0, DateTimeKind.Utc), + SpaceId = 1L, + TenantUserId = 2L, + TotalPrice = "100" + }, + new + { + Id = 2L, + PriceSpecificationId = 1L, + ReservationDateTimeUtc = new DateTime(2023, 3, 17, 12, 0, 0, 0, DateTimeKind.Utc), + ReservationFromUtc = new DateTime(2023, 3, 18, 12, 0, 0, 0, DateTimeKind.Utc), + ReservationStatus = "Confirmed", + ReservationToUtc = new DateTime(2023, 3, 18, 15, 0, 0, 0, DateTimeKind.Utc), + SpaceId = 1L, + TenantUserId = 3L, + TotalPrice = "100" + }); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.Space", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Latitude") + .HasColumnType("double precision"); + + b.Property("Longitude") + .HasColumnType("double precision"); + + b.Property("SpaceAddress") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("SpaceProperty") + .IsRequired() + .HasColumnType("text"); + + b.Property("UtilizationTypeId") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("Latitude"); + + b.HasIndex("Longitude"); + + b.HasIndex("UtilizationTypeId"); + + b.ToTable("Spaces"); + + b.HasData( + new + { + Id = 1L, + Latitude = 47.361812591552734, + Longitude = 8.5370702743530273, + SpaceAddress = "Mythenquai 7, 8002 Zürich", + SpaceProperty = "{\"SpacePropertyId\":\"4c4f455c-bc98-47da-9f4b-9dcc25a17fe5\",\"Name\":\"Santa María\",\"Description\":\"best boat in the world\",\"Properties\":null,\"OwnerId\":0,\"ContractId\":0,\"SubSpaces\":null}", + UtilizationTypeId = 12 + }, + new + { + Id = 2L, + Latitude = 47.361648559570312, + Longitude = 8.5366735458374023, + SpaceAddress = "Mythenquai 9, 8002 Zürich", + SpaceProperty = "{\"SpacePropertyId\":\"7d2dc2f3-4f52-4244-8ade-73eba2772a51\",\"Name\":\"Niña\",\"Description\":\"best boat in the world\",\"Properties\":null,\"OwnerId\":0,\"ContractId\":0,\"SubSpaces\":null}", + UtilizationTypeId = 12 + }, + new + { + Id = 3L, + Latitude = 47.361316680908203, + Longitude = 8.5362958908081055, + SpaceAddress = "Mythenquai 25, 8002 Zürich", + SpaceProperty = "{\"SpacePropertyId\":\"a5f8e388-0c2f-491c-82ff-d4c92da97aaa\",\"Name\":\"Pinta\",\"Description\":\"best boat in the world\",\"Properties\":null,\"OwnerId\":0,\"ContractId\":0,\"SubSpaces\":null}", + UtilizationTypeId = 12 + }); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.TelegramUserInfo", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("TelegramChatId") + .HasColumnType("bigint"); + + b.Property("TelegramUserFullName") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("TelegramUserId") + .HasColumnType("bigint"); + + b.Property("TelegramUserName") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.HasKey("Id"); + + b.ToTable("TelegramUserInfos"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("CreateDateTimeUtc") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("Phone") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("TelegramUserInfoId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("Email"); + + b.HasIndex("TelegramUserInfoId"); + + b.ToTable("Users"); + + b.HasData( + new + { + Id = 1L, + CreateDateTimeUtc = new DateTime(2023, 2, 20, 21, 0, 0, 0, DateTimeKind.Utc) + }, + new + { + Id = 2L, + CreateDateTimeUtc = new DateTime(2023, 3, 13, 21, 0, 0, 0, DateTimeKind.Utc) + }, + new + { + Id = 3L, + CreateDateTimeUtc = new DateTime(2023, 3, 13, 21, 0, 0, 0, DateTimeKind.Utc) + }, + new + { + Id = 4L, + CreateDateTimeUtc = new DateTime(2023, 3, 15, 21, 0, 0, 0, DateTimeKind.Utc) + }); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.UserAuthentication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("HashedPassword") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("UserId") + .HasColumnType("bigint"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("UserAuthentications"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.UtilizationType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.HasKey("Id"); + + b.ToTable("UtilizationTypes"); + + b.HasData( + new + { + Id = 1, + Name = "Residential" + }, + new + { + Id = 2, + Name = "Сommercial" + }, + new + { + Id = 3, + Name = "Production" + }, + new + { + Id = 4, + Name = "Warehouse" + }, + new + { + Id = 5, + Name = "Public catering" + }, + new + { + Id = 6, + Name = "Utility" + }, + new + { + Id = 7, + Name = "Office space" + }, + new + { + Id = 8, + Name = "Education" + }, + new + { + Id = 9, + Name = "Sports" + }, + new + { + Id = 10, + Name = "Free target" + }, + new + { + Id = 11, + Name = "Parking" + }, + new + { + Id = 12, + Name = "Boat" + }); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.Contract", b => + { + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.User", "OwnerUser") + .WithMany() + .HasForeignKey("OwnerUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.PriceSpecification", "PriceSpecification") + .WithMany() + .HasForeignKey("PriceSpecificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.Reservation", "Reservation") + .WithMany() + .HasForeignKey("ReservationId"); + + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.Space", "Space") + .WithMany() + .HasForeignKey("SpaceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.User", "TenantUser") + .WithMany() + .HasForeignKey("TenantUserId"); + + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.UtilizationType", "UtilizationType") + .WithMany() + .HasForeignKey("UtilizationTypeId"); + + b.Navigation("OwnerUser"); + + b.Navigation("PriceSpecification"); + + b.Navigation("Reservation"); + + b.Navigation("Space"); + + b.Navigation("TenantUser"); + + b.Navigation("UtilizationType"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.PriceSpecification", b => + { + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.Space", "Space") + .WithMany() + .HasForeignKey("SpaceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Space"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.Reservation", b => + { + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.PriceSpecification", "PriceSpecification") + .WithMany() + .HasForeignKey("PriceSpecificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.Space", "Space") + .WithMany() + .HasForeignKey("SpaceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.User", "TenantUser") + .WithMany() + .HasForeignKey("TenantUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("PriceSpecification"); + + b.Navigation("Space"); + + b.Navigation("TenantUser"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.Space", b => + { + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.UtilizationType", "UtilizationType") + .WithMany() + .HasForeignKey("UtilizationTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("UtilizationType"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.User", b => + { + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.TelegramUserInfo", "TelegramUserInfo") + .WithMany() + .HasForeignKey("TelegramUserInfoId"); + + b.Navigation("TelegramUserInfo"); + }); + + modelBuilder.Entity("AlgoTecture.Domain.Models.RepositoryModels.UserAuthentication", b => + { + b.HasOne("AlgoTecture.Domain.Models.RepositoryModels.User", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("User"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/AlgoTecture.Data.Persistence.Ef/Provider.cs b/AlgoTecture.Data.Persistence.Ef/Provider.cs index 21c8f76..f67527a 100644 --- a/AlgoTecture.Data.Persistence.Ef/Provider.cs +++ b/AlgoTecture.Data.Persistence.Ef/Provider.cs @@ -2,6 +2,7 @@ public enum Provider { - InMemory = 0, - NpgSql = 1 + None = 0, + InMemory = 1, + NpgSql = 2 } \ No newline at end of file diff --git a/AlgoTecture.Domain/Enum/ReservationStatusType.cs b/AlgoTecture.Domain/Enum/ReservationStatusType.cs index e557b08..ae338cd 100644 --- a/AlgoTecture.Domain/Enum/ReservationStatusType.cs +++ b/AlgoTecture.Domain/Enum/ReservationStatusType.cs @@ -5,5 +5,6 @@ public enum ReservationStatusType Pending = 0, Hold = 1, Confirmed = 2, - Cancelled = 3 + Cancelled = 3, + Contract = 4 } \ No newline at end of file diff --git a/AlgoTecture.Domain/Models/RepositoryModels/Reservation.cs b/AlgoTecture.Domain/Models/RepositoryModels/Reservation.cs index ae25d4c..f0bed63 100644 --- a/AlgoTecture.Domain/Models/RepositoryModels/Reservation.cs +++ b/AlgoTecture.Domain/Models/RepositoryModels/Reservation.cs @@ -29,4 +29,6 @@ public class Reservation public DateTime? ReservationToUtc { get; set; } public string? ReservationStatus { get; set; } + + public string? ReservationUniqueIdentifier { get; set; } } \ No newline at end of file diff --git a/AlgoTecture.Libraries.Reservations.Tests/UpdateReservationStatusTests.cs b/AlgoTecture.Libraries.Reservations.Tests/UpdateReservationStatusTests.cs new file mode 100644 index 0000000..8b012f5 --- /dev/null +++ b/AlgoTecture.Libraries.Reservations.Tests/UpdateReservationStatusTests.cs @@ -0,0 +1,52 @@ +using AlgoTecture.Data.Persistence.Core.Interfaces; +using AlgoTecture.Data.Persistence.Data; +using AlgoTecture.Data.Persistence.Ef; +using AlgoTecture.Domain.Models.RepositoryModels; +using AlgoTecture.Libraries.Reservations.Models; +using NUnit.Framework; + +namespace AlgoTecture.Libraries.Reservations.Tests; + +public class UpdateReservationStatusTests +{ + private IUnitOfWork _unitOfWork; + + [SetUp] + public void SetUp() + { + _unitOfWork = new UnitOfWork(new ApplicationDbContext(Provider.InMemory), null); + } + + [Test] + public void Returned_Confirmed_Status() + { + var reservationService = new ReservationService(_unitOfWork); + + var addOrUpdateReservationModelDataSeedingOne = new Reservation() + { + Id = 1, + ReservationFromUtc = DateTime.Parse("2023-03-17 15:00"), + ReservationToUtc = DateTime.Parse("2023-03-17 17:00"), + ReservationStatus = "Confirmed", + TotalPrice = "150", + SpaceId = 1, + SubSpaceId = null, + TenantUserId = 1, + ReservationDateTimeUtc = DateTime.Parse("2023-03-16 14:00"), + PriceSpecificationId = 1 + }; + + var reservation = _unitOfWork.Reservations.Add(addOrUpdateReservationModelDataSeedingOne).Result; + _unitOfWork.CompleteAsync(); + + var updateReservationStatusModel = new UpdateReservationStatusModel() + { + ReservationId = 1, + ReservationStatus = "Contract" + }; + + var updatedReservation = reservationService.UpdateReservationStatus(updateReservationStatusModel.ReservationStatus, updateReservationStatusModel.ReservationId).Result; + + Assert.AreEqual("Contract", updatedReservation?.ReservationStatus); + } +} \ No newline at end of file diff --git a/AlgoTecture.Libraries.Reservations/IReservationService.cs b/AlgoTecture.Libraries.Reservations/IReservationService.cs index f7c0457..840818a 100644 --- a/AlgoTecture.Libraries.Reservations/IReservationService.cs +++ b/AlgoTecture.Libraries.Reservations/IReservationService.cs @@ -1,6 +1,5 @@ using AlgoTecture.Domain.Models.RepositoryModels; using AlgoTecture.Libraries.Reservations.Models; -using JetBrains.Annotations; namespace AlgoTecture.Libraries.Reservations; @@ -13,4 +12,6 @@ public interface IReservationService Task UpdateReservation(AddOrUpdateReservationModel addOrUpdateReservationModel); Task> GetReservationsBySpaceId(long spaceId); + + Task UpdateReservationStatus(string reservationStatus, long reservationId); } \ No newline at end of file diff --git a/AlgoTecture.Libraries.Reservations/Models/UpdateReservationStatusModel.cs b/AlgoTecture.Libraries.Reservations/Models/UpdateReservationStatusModel.cs new file mode 100644 index 0000000..3529038 --- /dev/null +++ b/AlgoTecture.Libraries.Reservations/Models/UpdateReservationStatusModel.cs @@ -0,0 +1,8 @@ +namespace AlgoTecture.Libraries.Reservations.Models; + +public class UpdateReservationStatusModel +{ + public long ReservationId { get; set; } + + public string ReservationStatus { get; set; } +} \ No newline at end of file diff --git a/AlgoTecture.Libraries.Reservations/ReservationService.cs b/AlgoTecture.Libraries.Reservations/ReservationService.cs index cf01408..44cd667 100644 --- a/AlgoTecture.Libraries.Reservations/ReservationService.cs +++ b/AlgoTecture.Libraries.Reservations/ReservationService.cs @@ -1,4 +1,5 @@ using AlgoTecture.Data.Persistence.Core.Interfaces; +using AlgoTecture.Domain.Enum; using AlgoTecture.Domain.Models.RepositoryModels; using AlgoTecture.Libraries.Reservations.Models; @@ -90,4 +91,23 @@ public async Task> GetReservationsBySpaceId(long spaceI { return await _unitOfWork.Reservations.GetReservationsBySpaceId(spaceId); } + + public async Task UpdateReservationStatus(string reservationStatus, long reservationId) + { + if (string.IsNullOrEmpty(reservationStatus)) throw new ArgumentException("Value cannot be null or empty.", nameof(reservationStatus)); + + var isValidReservationStatus = Enum.IsDefined(typeof(ReservationStatusType), reservationStatus); + + if (!isValidReservationStatus) throw new InvalidCastException($"{reservationStatus} is not valid"); + + var reservation = await _unitOfWork.Reservations.GetById(reservationId); + + if (reservation == null) throw new ArgumentNullException($"Reservation with id {reservationId} not exist"); + + reservation.ReservationStatus = reservationStatus; + + var updatedReservation = await _unitOfWork.Reservations.Upsert(reservation); + + return updatedReservation; + } } \ No newline at end of file diff --git a/AlgoTecture.WebApi/AlgoTecture.WebApi.csproj b/AlgoTecture.WebApi/AlgoTecture.WebApi.csproj index 53d6920..d0839ae 100644 --- a/AlgoTecture.WebApi/AlgoTecture.WebApi.csproj +++ b/AlgoTecture.WebApi/AlgoTecture.WebApi.csproj @@ -31,6 +31,7 @@ + diff --git a/AlgoTecture.WebApi/Controllers/ReservationController.cs b/AlgoTecture.WebApi/Controllers/ReservationController.cs new file mode 100644 index 0000000..e4117ac --- /dev/null +++ b/AlgoTecture.WebApi/Controllers/ReservationController.cs @@ -0,0 +1,28 @@ +using System.Threading.Tasks; +using AlgoTecture.Libraries.Reservations; +using AlgoTecture.Libraries.Reservations.Models; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; + +namespace AlgoTecture.WebApi.Controllers; + +[Route("[controller]")] +public class ReservationController : Controller +{ + private readonly IReservationService _reservationService; + + public ReservationController(IReservationService reservationService) + { + _reservationService = reservationService; + } + + [HttpPost("UpdateReservationStatus")] + public async Task> UpdateReservationStatus([FromBody] UpdateReservationStatusModel updateReservationStatusModel) + { + if (!ModelState.IsValid) return BadRequest(); + + _ = await _reservationService.UpdateReservationStatus(updateReservationStatusModel.ReservationStatus, updateReservationStatusModel.ReservationId); + + return Ok(); + } +} \ No newline at end of file diff --git a/AlgoTecture.WebApi/Program.cs b/AlgoTecture.WebApi/Program.cs index 2aceb5c..dfc1f38 100644 --- a/AlgoTecture.WebApi/Program.cs +++ b/AlgoTecture.WebApi/Program.cs @@ -1,22 +1,19 @@ using System; using System.IO; -using System.Linq; using System.Threading.Tasks; using AlgoTecture.Common; using AlgoTecture.Data.Persistence; using AlgoTecture.Libraries.GeoAdminSearch; +using AlgoTecture.Libraries.Reservations; using AlgoTecture.Libraries.Spaces; -using AlgoTecture.Libraries.Users.Models; using AlgoTecture.Libraries.Users.Models.AppsettingsModels; using AlgoTecture.WebApi.Implementations; using AlgoTecture.WebApi.Interfaces; using AlgoTecture.WebApi.Middleware.CustomExceptionMiddleware; -using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection.Extensions; using Microsoft.Extensions.Hosting; -using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; using Serilog; using Swashbuckle.AspNetCore.SwaggerGen; @@ -77,6 +74,7 @@ public static async Task Main(string[] args) webAppBuilder.Services.UseSpaceLibrary(); webAppBuilder.Services.UsePersistenceLibrary(); webAppBuilder.Services.UseGeoAdminSearchLibrary(); + webAppBuilder.Services.UseReservationLibrary(); var app = webAppBuilder.Build(); diff --git a/AlgoTecture.sln.DotSettings.user b/AlgoTecture.sln.DotSettings.user index b695f2b..c9b9ec4 100644 --- a/AlgoTecture.sln.DotSettings.user +++ b/AlgoTecture.sln.DotSettings.user @@ -4,6 +4,7 @@ <TestId>NUnit3x::1EC8134E-12A2-4EEB-83F7-A128164E15E7::net6.0::AlgoTecture.Libraries.Reservations.Tests.ReservationTests</TestId> <TestId>NUnit3x::1EC8134E-12A2-4EEB-83F7-A128164E15E7::net6.0::AlgoTecture.Libraries.Reservations.Tests.Serialization.ClassToJsonSerializationTests.ConversationClassToJsonSimpleTest</TestId> <TestId>NUnit3x::998D3762-0AF4-4ABF-807A-ED210BB6D1DF::net6.0::AlgoTecture.Libraries.Spaces.Tests.Serialization.ClassToJsonSerializationTests.ConversationClassToJsonSimpleTest</TestId> + <TestId>NUnit3x::1EC8134E-12A2-4EEB-83F7-A128164E15E7::net6.0::AlgoTecture.Libraries.Reservations.Tests.UpdateReservationStatusTests.Returned_Confirmed_Status</TestId> </TestAncestor> </SessionState>