From 78f2c48415d614c168f380095de9a7dca552888a Mon Sep 17 00:00:00 2001 From: Magnus Gule Date: Tue, 17 Oct 2023 11:51:38 +0200 Subject: [PATCH 01/26] Re-implement Organization entity model back to db --- .../Api/Consultants/ConsultantController.cs | 1 + backend/Api/Consultants/ConsultantService.cs | 9 +- backend/Core/DomainModels/Absence.cs | 1 + backend/Core/DomainModels/Customer.cs | 1 + backend/Core/DomainModels/Department.cs | 1 + backend/Core/DomainModels/Organization.cs | 19 + backend/Core/DomainModels/Project.cs | 1 + .../DatabaseContext/ApplicationContext.cs | 26 + ...94309_AddOrganizationBackAgain.Designer.cs | 531 ++++++++++++++++++ ...20231017094309_AddOrganizationBackAgain.cs | 178 ++++++ .../ApplicationContextModelSnapshot.cs | 120 +++- 11 files changed, 883 insertions(+), 5 deletions(-) create mode 100644 backend/Core/DomainModels/Organization.cs create mode 100644 backend/Database/Migrations/20231017094309_AddOrganizationBackAgain.Designer.cs create mode 100644 backend/Database/Migrations/20231017094309_AddOrganizationBackAgain.cs diff --git a/backend/Api/Consultants/ConsultantController.cs b/backend/Api/Consultants/ConsultantController.cs index 525194fc..c11a33e1 100644 --- a/backend/Api/Consultants/ConsultantController.cs +++ b/backend/Api/Consultants/ConsultantController.cs @@ -119,6 +119,7 @@ private List LoadConsultantAvailability(int numberOfWeeks) (pa.Year <= yearA && minWeekA <= pa.WeekNumber && pa.WeekNumber <= maxWeekA) || (yearB <= pa.Year && minWeekB <= pa.WeekNumber && pa.WeekNumber <= maxWeekB))) .Include(c => c.Department) + .ThenInclude(d => d.Organization) .Include(c => c.Staffings.Where(s => (s.Year <= yearA && minWeekA <= s.Week && s.Week <= maxWeekA) || (yearB <= s.Year && minWeekB <= s.Week && s.Week <= maxWeekB))) diff --git a/backend/Api/Consultants/ConsultantService.cs b/backend/Api/Consultants/ConsultantService.cs index 0b62667f..03c9696a 100644 --- a/backend/Api/Consultants/ConsultantService.cs +++ b/backend/Api/Consultants/ConsultantService.cs @@ -21,7 +21,7 @@ public ConsultantReadModel MapConsultantToReadModel(Consultant consultant, int w const double tolerance = 0.1; var bookedHours = GetBookedHoursForWeeks(consultant, weeks); - var isOccupied = bookedHours.All(b => b.BookedHours >= GetHoursPrWeek() - tolerance); + var isOccupied = bookedHours.All(b => b.BookedHours >= GetHoursPrWeek(consultant) - tolerance); return new ConsultantReadModel( consultant.Id, @@ -36,7 +36,8 @@ public ConsultantReadModel MapConsultantToReadModel(Consultant consultant, int w public double GetBookedHours(Consultant consultant, int year, int week) { - var hoursPrWorkDay = _organizationOptions.HoursPerWorkday; + var hoursPrWorkDay = consultant.Department.Organization.HoursPerWorkday; + // var hoursPrWorkDay = _organizationOptions.HoursPerWorkday; var holidayHours = _holidayService.GetTotalHolidaysOfWeek(year, week) * hoursPrWorkDay; var vacationHours = consultant.Vacations.Count(v => DateService.DateIsInWeek(v.Date, year, week)) * @@ -73,8 +74,8 @@ public List GetBookedHoursForWeeks(Consultant consultant, in .ToList(); } - public double GetHoursPrWeek() + public double GetHoursPrWeek(Consultant consultant) { - return _organizationOptions.HoursPerWorkday * 5; + return consultant.Department.Organization.HoursPerWorkday * 5; } } \ No newline at end of file diff --git a/backend/Core/DomainModels/Absence.cs b/backend/Core/DomainModels/Absence.cs index 42f36a2f..ef3610b9 100644 --- a/backend/Core/DomainModels/Absence.cs +++ b/backend/Core/DomainModels/Absence.cs @@ -9,4 +9,5 @@ public class Absence public required string Name { get; set; } public required bool ExcludeFromBillRate { get; set; } = false; + public required Organization Organization { get; set; } } \ No newline at end of file diff --git a/backend/Core/DomainModels/Customer.cs b/backend/Core/DomainModels/Customer.cs index b0666ff2..9de19b5f 100644 --- a/backend/Core/DomainModels/Customer.cs +++ b/backend/Core/DomainModels/Customer.cs @@ -8,5 +8,6 @@ public class Customer public int Id { get; set; } public required string Name { get; set; } + public required Organization Organization { get; set; } public required List Projects { get; set; } } \ No newline at end of file diff --git a/backend/Core/DomainModels/Department.cs b/backend/Core/DomainModels/Department.cs index 97d7a5c8..62e3b7c2 100644 --- a/backend/Core/DomainModels/Department.cs +++ b/backend/Core/DomainModels/Department.cs @@ -8,5 +8,6 @@ public class Department [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public required string Id { get; set; } public required string Name { get; set; } + public required Organization Organization { get; set; } [JsonIgnore] public required List Consultants { get; set; } } \ No newline at end of file diff --git a/backend/Core/DomainModels/Organization.cs b/backend/Core/DomainModels/Organization.cs new file mode 100644 index 00000000..f9fd7f32 --- /dev/null +++ b/backend/Core/DomainModels/Organization.cs @@ -0,0 +1,19 @@ +using System.Text.Json.Serialization; +namespace Core.DomainModels; + +public class Organization +{ + public required string Id { get; set; } // guid ? Decide What to set here first => + public required string Name { get; set; } + public required string TagName { get; set; } // "variant-as", "variant-sverige" + public required string Country { get; set; } + public required int NumberOfVacationDaysInYear { get; set; } + public required bool HasVacationInChristmas { get; set; } + public required double HoursPerWorkday { get; set; } + + [JsonIgnore] public List Departments { get; set; } + + public required List Customers { get; set; } + + public List AbsenceTypes { get; set; } +} diff --git a/backend/Core/DomainModels/Project.cs b/backend/Core/DomainModels/Project.cs index 9e974f3f..7d73da8c 100644 --- a/backend/Core/DomainModels/Project.cs +++ b/backend/Core/DomainModels/Project.cs @@ -8,6 +8,7 @@ public class Project public required int Id { get; set; } public required Customer Customer { get; set; } + public required Organization Organization { get; set; } public required ProjectState State { get; set; } diff --git a/backend/Database/DatabaseContext/ApplicationContext.cs b/backend/Database/DatabaseContext/ApplicationContext.cs index 98159c0a..de097a4d 100644 --- a/backend/Database/DatabaseContext/ApplicationContext.cs +++ b/backend/Database/DatabaseContext/ApplicationContext.cs @@ -13,6 +13,7 @@ public ApplicationContext(DbContextOptions options) : base(options) public DbSet Consultant { get; set; } = null!; public DbSet Competence { get; set; } = null!; public DbSet Department { get; set; } = null!; + public DbSet Organization { get; set; } = null!; public DbSet PlannedAbsence { get; set; } = null!; public DbSet Vacation { get; set; } = null!; public DbSet Customer { get; set; } = null!; @@ -29,6 +30,19 @@ protected override void ConfigureConventions(ModelConfigurationBuilder configura protected override void OnModelCreating(ModelBuilder modelBuilder) { + modelBuilder.Entity() + .HasMany(org => org.Departments) + .WithOne(dept => dept.Organization); + + modelBuilder.Entity() + .HasMany(organization => organization.AbsenceTypes) + .WithOne(absence => absence.Organization); + + modelBuilder.Entity() + .HasMany(organization => organization.Customers) + .WithOne(customer => customer.Organization); + + modelBuilder.Entity() .HasMany(customer => customer.Projects) .WithOne(project => project.Customer); @@ -100,6 +114,18 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) new() { Id = "project-mgmt", Name = "Project Management" } }); + modelBuilder.Entity() + .HasData(new + { + Id = "variant-as", + Name = "Variant AS", + TagName = "variant-as", + Country = "norway", + HoursPerWorkday = 7.5, + HasVacationInChristmas = true, + NumberOfVacationDaysInYear = 25 + }); + modelBuilder.Entity() .HasData(new { Id = "trondheim", Name = "Trondheim", OrganizationId = "variant-as" }); diff --git a/backend/Database/Migrations/20231017094309_AddOrganizationBackAgain.Designer.cs b/backend/Database/Migrations/20231017094309_AddOrganizationBackAgain.Designer.cs new file mode 100644 index 00000000..de3f22d8 --- /dev/null +++ b/backend/Database/Migrations/20231017094309_AddOrganizationBackAgain.Designer.cs @@ -0,0 +1,531 @@ +// +using System; +using Database.DatabaseContext; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace backend.Migrations +{ + [DbContext(typeof(ApplicationContext))] + [Migration("20231017094309_AddOrganizationBackAgain")] + partial class AddOrganizationBackAgain + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("CompetenceConsultant", b => + { + b.Property("CompetencesId") + .HasColumnType("nvarchar(450)"); + + b.Property("ConsultantId") + .HasColumnType("int"); + + b.HasKey("CompetencesId", "ConsultantId"); + + b.HasIndex("ConsultantId"); + + b.ToTable("CompetenceConsultant"); + }); + + modelBuilder.Entity("Core.DomainModels.Absence", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ExcludeFromBillRate") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Absence"); + }); + + modelBuilder.Entity("Core.DomainModels.Competence", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Competence"); + + b.HasData( + new + { + Id = "frontend", + Name = "Frontend" + }, + new + { + Id = "backend", + Name = "Backend" + }, + new + { + Id = "design", + Name = "Design" + }, + new + { + Id = "project-mgmt", + Name = "Project Management" + }); + }); + + modelBuilder.Entity("Core.DomainModels.Consultant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Degree") + .HasColumnType("nvarchar(max)"); + + b.Property("DepartmentId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("GraduationYear") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("DepartmentId"); + + b.ToTable("Consultant"); + + b.HasData( + new + { + Id = 1, + Degree = "Master", + DepartmentId = "trondheim", + Email = "j@variant.no", + GraduationYear = 2019, + Name = "Jonas", + StartDate = new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Core.DomainModels.Customer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Customer"); + }); + + modelBuilder.Entity("Core.DomainModels.Department", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Department"); + + b.HasData( + new + { + Id = "trondheim", + Name = "Trondheim", + OrganizationId = "variant-as" + }); + }); + + modelBuilder.Entity("Core.DomainModels.Organization", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Country") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("HasVacationInChristmas") + .HasColumnType("bit"); + + b.Property("HoursPerWorkday") + .HasColumnType("float"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("NumberOfVacationDaysInYear") + .HasColumnType("int"); + + b.Property("TagName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Organization"); + + b.HasData( + new + { + Id = "variant-as", + Country = "norway", + HasVacationInChristmas = true, + HoursPerWorkday = 7.5, + Name = "Variant AS", + NumberOfVacationDaysInYear = 25, + TagName = "variant-as" + }); + }); + + modelBuilder.Entity("Core.DomainModels.PlannedAbsence", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AbsenceId") + .HasColumnType("int"); + + b.Property("ConsultantId") + .HasColumnType("int"); + + b.Property("Hours") + .HasColumnType("float"); + + b.Property("WeekNumber") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("AbsenceId"); + + b.HasIndex("ConsultantId"); + + b.ToTable("PlannedAbsence"); + }); + + modelBuilder.Entity("Core.DomainModels.Project", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CustomerId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("State") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("CustomerId"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Project"); + }); + + modelBuilder.Entity("Core.DomainModels.Staffing", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ConsultantId") + .HasColumnType("int"); + + b.Property("Hours") + .HasColumnType("float"); + + b.Property("ProjectId") + .HasColumnType("int"); + + b.Property("Week") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ConsultantId"); + + b.HasIndex("ProjectId"); + + b.ToTable("Staffing"); + }); + + modelBuilder.Entity("Core.DomainModels.Vacation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ConsultantId") + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("ConsultantId"); + + b.ToTable("Vacation"); + }); + + modelBuilder.Entity("CompetenceConsultant", b => + { + b.HasOne("Core.DomainModels.Competence", null) + .WithMany() + .HasForeignKey("CompetencesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Core.DomainModels.Consultant", null) + .WithMany() + .HasForeignKey("ConsultantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Core.DomainModels.Absence", b => + { + b.HasOne("Core.DomainModels.Organization", "Organization") + .WithMany("AbsenceTypes") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Core.DomainModels.Consultant", b => + { + b.HasOne("Core.DomainModels.Department", "Department") + .WithMany("Consultants") + .HasForeignKey("DepartmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Department"); + }); + + modelBuilder.Entity("Core.DomainModels.Customer", b => + { + b.HasOne("Core.DomainModels.Organization", "Organization") + .WithMany("Customers") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Core.DomainModels.Department", b => + { + b.HasOne("Core.DomainModels.Organization", "Organization") + .WithMany("Departments") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Core.DomainModels.PlannedAbsence", b => + { + b.HasOne("Core.DomainModels.Absence", "Absence") + .WithMany() + .HasForeignKey("AbsenceId") + .OnDelete(DeleteBehavior.ClientCascade) + .IsRequired(); + + b.HasOne("Core.DomainModels.Consultant", "Consultant") + .WithMany("PlannedAbsences") + .HasForeignKey("ConsultantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Absence"); + + b.Navigation("Consultant"); + }); + + modelBuilder.Entity("Core.DomainModels.Project", b => + { + b.HasOne("Core.DomainModels.Customer", "Customer") + .WithMany("Projects") + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Core.DomainModels.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Customer"); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Core.DomainModels.Staffing", b => + { + b.HasOne("Core.DomainModels.Consultant", "Consultant") + .WithMany("Staffings") + .HasForeignKey("ConsultantId") + .OnDelete(DeleteBehavior.ClientCascade) + .IsRequired(); + + b.HasOne("Core.DomainModels.Project", "Project") + .WithMany("Staffings") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Consultant"); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("Core.DomainModels.Vacation", b => + { + b.HasOne("Core.DomainModels.Consultant", "Consultant") + .WithMany("Vacations") + .HasForeignKey("ConsultantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Consultant"); + }); + + modelBuilder.Entity("Core.DomainModels.Consultant", b => + { + b.Navigation("PlannedAbsences"); + + b.Navigation("Staffings"); + + b.Navigation("Vacations"); + }); + + modelBuilder.Entity("Core.DomainModels.Customer", b => + { + b.Navigation("Projects"); + }); + + modelBuilder.Entity("Core.DomainModels.Department", b => + { + b.Navigation("Consultants"); + }); + + modelBuilder.Entity("Core.DomainModels.Organization", b => + { + b.Navigation("AbsenceTypes"); + + b.Navigation("Customers"); + + b.Navigation("Departments"); + }); + + modelBuilder.Entity("Core.DomainModels.Project", b => + { + b.Navigation("Staffings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/backend/Database/Migrations/20231017094309_AddOrganizationBackAgain.cs b/backend/Database/Migrations/20231017094309_AddOrganizationBackAgain.cs new file mode 100644 index 00000000..e0653fd3 --- /dev/null +++ b/backend/Database/Migrations/20231017094309_AddOrganizationBackAgain.cs @@ -0,0 +1,178 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace backend.Migrations +{ + /// + public partial class AddOrganizationBackAgain : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "OrganizationId", + table: "Project", + type: "nvarchar(450)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "OrganizationId", + table: "Department", + type: "nvarchar(450)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "OrganizationId", + table: "Customer", + type: "nvarchar(450)", + nullable: false, + defaultValue: ""); + + migrationBuilder.AddColumn( + name: "OrganizationId", + table: "Absence", + type: "nvarchar(450)", + nullable: false, + defaultValue: ""); + + migrationBuilder.CreateTable( + name: "Organization", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(max)", nullable: false), + TagName = table.Column(type: "nvarchar(max)", nullable: false), + Country = table.Column(type: "nvarchar(max)", nullable: false), + NumberOfVacationDaysInYear = table.Column(type: "int", nullable: false), + HasVacationInChristmas = table.Column(type: "bit", nullable: false), + HoursPerWorkday = table.Column(type: "float", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Organization", x => x.Id); + }); + + migrationBuilder.UpdateData( + table: "Department", + keyColumn: "Id", + keyValue: "trondheim", + column: "OrganizationId", + value: "variant-as"); + + migrationBuilder.InsertData( + table: "Organization", + columns: new[] { "Id", "Country", "HasVacationInChristmas", "HoursPerWorkday", "Name", "NumberOfVacationDaysInYear", "TagName" }, + values: new object[] { "variant-as", "norway", true, 7.5, "Variant AS", 25, "variant-as" }); + + migrationBuilder.CreateIndex( + name: "IX_Project_OrganizationId", + table: "Project", + column: "OrganizationId"); + + migrationBuilder.CreateIndex( + name: "IX_Department_OrganizationId", + table: "Department", + column: "OrganizationId"); + + migrationBuilder.CreateIndex( + name: "IX_Customer_OrganizationId", + table: "Customer", + column: "OrganizationId"); + + migrationBuilder.CreateIndex( + name: "IX_Absence_OrganizationId", + table: "Absence", + column: "OrganizationId"); + + migrationBuilder.AddForeignKey( + name: "FK_Absence_Organization_OrganizationId", + table: "Absence", + column: "OrganizationId", + principalTable: "Organization", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_Customer_Organization_OrganizationId", + table: "Customer", + column: "OrganizationId", + principalTable: "Organization", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_Department_Organization_OrganizationId", + table: "Department", + column: "OrganizationId", + principalTable: "Organization", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + + migrationBuilder.AddForeignKey( + name: "FK_Project_Organization_OrganizationId", + table: "Project", + column: "OrganizationId", + principalTable: "Organization", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Absence_Organization_OrganizationId", + table: "Absence"); + + migrationBuilder.DropForeignKey( + name: "FK_Customer_Organization_OrganizationId", + table: "Customer"); + + migrationBuilder.DropForeignKey( + name: "FK_Department_Organization_OrganizationId", + table: "Department"); + + migrationBuilder.DropForeignKey( + name: "FK_Project_Organization_OrganizationId", + table: "Project"); + + migrationBuilder.DropTable( + name: "Organization"); + + migrationBuilder.DropIndex( + name: "IX_Project_OrganizationId", + table: "Project"); + + migrationBuilder.DropIndex( + name: "IX_Department_OrganizationId", + table: "Department"); + + migrationBuilder.DropIndex( + name: "IX_Customer_OrganizationId", + table: "Customer"); + + migrationBuilder.DropIndex( + name: "IX_Absence_OrganizationId", + table: "Absence"); + + migrationBuilder.DropColumn( + name: "OrganizationId", + table: "Project"); + + migrationBuilder.DropColumn( + name: "OrganizationId", + table: "Department"); + + migrationBuilder.DropColumn( + name: "OrganizationId", + table: "Customer"); + + migrationBuilder.DropColumn( + name: "OrganizationId", + table: "Absence"); + } + } +} diff --git a/backend/Database/Migrations/ApplicationContextModelSnapshot.cs b/backend/Database/Migrations/ApplicationContextModelSnapshot.cs index 946bfb53..5f314aef 100644 --- a/backend/Database/Migrations/ApplicationContextModelSnapshot.cs +++ b/backend/Database/Migrations/ApplicationContextModelSnapshot.cs @@ -52,8 +52,14 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("nvarchar(max)"); + b.Property("OrganizationId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + b.HasKey("Id"); + b.HasIndex("OrganizationId"); + b.ToTable("Absence"); }); @@ -157,8 +163,14 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("nvarchar(max)"); + b.Property("OrganizationId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + b.HasKey("Id"); + b.HasIndex("OrganizationId"); + b.ToTable("Customer"); }); @@ -172,15 +184,65 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("nvarchar(max)"); + b.Property("OrganizationId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + b.HasKey("Id"); + b.HasIndex("OrganizationId"); + b.ToTable("Department"); b.HasData( new { Id = "trondheim", - Name = "Trondheim" + Name = "Trondheim", + OrganizationId = "variant-as" + }); + }); + + modelBuilder.Entity("Core.DomainModels.Organization", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Country") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("HasVacationInChristmas") + .HasColumnType("bit"); + + b.Property("HoursPerWorkday") + .HasColumnType("float"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("NumberOfVacationDaysInYear") + .HasColumnType("int"); + + b.Property("TagName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Organization"); + + b.HasData( + new + { + Id = "variant-as", + Country = "norway", + HasVacationInChristmas = true, + HoursPerWorkday = 7.5, + Name = "Variant AS", + NumberOfVacationDaysInYear = 25, + TagName = "variant-as" }); }); @@ -231,6 +293,10 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired() .HasColumnType("nvarchar(max)"); + b.Property("OrganizationId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + b.Property("State") .IsRequired() .HasColumnType("nvarchar(max)"); @@ -239,6 +305,8 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("CustomerId"); + b.HasIndex("OrganizationId"); + b.ToTable("Project"); }); @@ -310,6 +378,17 @@ protected override void BuildModel(ModelBuilder modelBuilder) .IsRequired(); }); + modelBuilder.Entity("Core.DomainModels.Absence", b => + { + b.HasOne("Core.DomainModels.Organization", "Organization") + .WithMany("AbsenceTypes") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + modelBuilder.Entity("Core.DomainModels.Consultant", b => { b.HasOne("Core.DomainModels.Department", "Department") @@ -321,6 +400,28 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Department"); }); + modelBuilder.Entity("Core.DomainModels.Customer", b => + { + b.HasOne("Core.DomainModels.Organization", "Organization") + .WithMany("Customers") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Core.DomainModels.Department", b => + { + b.HasOne("Core.DomainModels.Organization", "Organization") + .WithMany("Departments") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + modelBuilder.Entity("Core.DomainModels.PlannedAbsence", b => { b.HasOne("Core.DomainModels.Absence", "Absence") @@ -348,7 +449,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Cascade) .IsRequired(); + b.HasOne("Core.DomainModels.Organization", "Organization") + .WithMany() + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + b.Navigation("Customer"); + + b.Navigation("Organization"); }); modelBuilder.Entity("Core.DomainModels.Staffing", b => @@ -400,6 +509,15 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Navigation("Consultants"); }); + modelBuilder.Entity("Core.DomainModels.Organization", b => + { + b.Navigation("AbsenceTypes"); + + b.Navigation("Customers"); + + b.Navigation("Departments"); + }); + modelBuilder.Entity("Core.DomainModels.Project", b => { b.Navigation("Staffings"); From 1274654891ca838201058a1e1ab1b602eda45223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B8ralt?= Date: Tue, 17 Oct 2023 12:55:05 +0200 Subject: [PATCH 02/26] begone, migrations! --- backend/Database/Database.csproj | 4 + .../20230915072931_InitialCreate.Designer.cs | 235 -------- .../20230915072931_InitialCreate.cs | 170 ------ ...30919085422_VacationAndAbsence.Designer.cs | 318 ----------- .../20230919085422_VacationAndAbsence.cs | 79 --- ...20230926080554_StaffingAbsence.Designer.cs | 500 ----------------- .../20230926080554_StaffingAbsence.cs | 196 ------- ...ayModelAndFloatToDoubleCastFix.Designer.cs | 500 ----------------- ...ddedHolidayModelAndFloatToDoubleCastFix.cs | 48 -- ...1004195542_RemovedOrganization.Designer.cs | 413 -------------- .../20231004195542_RemovedOrganization.cs | 142 ----- ...94309_AddOrganizationBackAgain.Designer.cs | 531 ------------------ ...20231017094309_AddOrganizationBackAgain.cs | 178 ------ .../ApplicationContextModelSnapshot.cs | 528 ----------------- 14 files changed, 4 insertions(+), 3838 deletions(-) delete mode 100644 backend/Database/Migrations/20230915072931_InitialCreate.Designer.cs delete mode 100644 backend/Database/Migrations/20230915072931_InitialCreate.cs delete mode 100644 backend/Database/Migrations/20230919085422_VacationAndAbsence.Designer.cs delete mode 100644 backend/Database/Migrations/20230919085422_VacationAndAbsence.cs delete mode 100644 backend/Database/Migrations/20230926080554_StaffingAbsence.Designer.cs delete mode 100644 backend/Database/Migrations/20230926080554_StaffingAbsence.cs delete mode 100644 backend/Database/Migrations/20230927080712_AddedHolidayModelAndFloatToDoubleCastFix.Designer.cs delete mode 100644 backend/Database/Migrations/20230927080712_AddedHolidayModelAndFloatToDoubleCastFix.cs delete mode 100644 backend/Database/Migrations/20231004195542_RemovedOrganization.Designer.cs delete mode 100644 backend/Database/Migrations/20231004195542_RemovedOrganization.cs delete mode 100644 backend/Database/Migrations/20231017094309_AddOrganizationBackAgain.Designer.cs delete mode 100644 backend/Database/Migrations/20231017094309_AddOrganizationBackAgain.cs delete mode 100644 backend/Database/Migrations/ApplicationContextModelSnapshot.cs diff --git a/backend/Database/Database.csproj b/backend/Database/Database.csproj index 5e9f8a9e..a864ecc1 100644 --- a/backend/Database/Database.csproj +++ b/backend/Database/Database.csproj @@ -25,4 +25,8 @@ + + + + diff --git a/backend/Database/Migrations/20230915072931_InitialCreate.Designer.cs b/backend/Database/Migrations/20230915072931_InitialCreate.Designer.cs deleted file mode 100644 index 1f19a123..00000000 --- a/backend/Database/Migrations/20230915072931_InitialCreate.Designer.cs +++ /dev/null @@ -1,235 +0,0 @@ -// -using System; -using Database.DatabaseContext; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace backend.Migrations -{ - [DbContext(typeof(ApplicationContext))] - [Migration("20230915072931_InitialCreate")] - partial class InitialCreate - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.10") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("CompetenceConsultant", b => - { - b.Property("CompetencesId") - .HasColumnType("nvarchar(450)"); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.HasKey("CompetencesId", "ConsultantId"); - - b.HasIndex("ConsultantId"); - - b.ToTable("CompetenceConsultant"); - }); - - modelBuilder.Entity("backend.DomainModels.Competence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Competence"); - - b.HasData( - new - { - Id = "frontend", - Name = "Frontend" - }, - new - { - Id = "backend", - Name = "Backend" - }, - new - { - Id = "design", - Name = "Design" - }, - new - { - Id = "project-mgmt", - Name = "Project Management" - }); - }); - - modelBuilder.Entity("backend.DomainModels.Consultant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Degree") - .HasColumnType("nvarchar(max)"); - - b.Property("DepartmentId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Email") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("EndDate") - .HasColumnType("datetime2"); - - b.Property("GraduationYear") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StartDate") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("DepartmentId"); - - b.ToTable("Consultant"); - - b.HasData( - new - { - Id = 1, - Degree = "Master", - DepartmentId = "trondheim", - Email = "j@variant.no", - GraduationYear = 2019, - Name = "Jonas", - StartDate = new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) - }); - }); - - modelBuilder.Entity("backend.DomainModels.Department", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Department"); - - b.HasData( - new - { - Id = "trondheim", - Name = "Trondheim", - OrganizationId = "variant-as" - }); - }); - - modelBuilder.Entity("backend.DomainModels.Organization", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("HoursPerWorkday") - .HasColumnType("real"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Organization"); - - b.HasData( - new - { - Id = "variant-as", - HoursPerWorkday = 7.5f, - Name = "Variant AS" - }); - }); - - modelBuilder.Entity("CompetenceConsultant", b => - { - b.HasOne("backend.DomainModels.Competence", null) - .WithMany() - .HasForeignKey("CompetencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("backend.DomainModels.Consultant", null) - .WithMany() - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("backend.DomainModels.Consultant", b => - { - b.HasOne("backend.DomainModels.Department", "Department") - .WithMany("Consultants") - .HasForeignKey("DepartmentId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Department"); - }); - - modelBuilder.Entity("backend.DomainModels.Department", b => - { - b.HasOne("backend.DomainModels.Organization", "Organization") - .WithMany("Departments") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("backend.DomainModels.Department", b => - { - b.Navigation("Consultants"); - }); - - modelBuilder.Entity("backend.DomainModels.Organization", b => - { - b.Navigation("Departments"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/backend/Database/Migrations/20230915072931_InitialCreate.cs b/backend/Database/Migrations/20230915072931_InitialCreate.cs deleted file mode 100644 index 0d69b902..00000000 --- a/backend/Database/Migrations/20230915072931_InitialCreate.cs +++ /dev/null @@ -1,170 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional - -namespace backend.Migrations -{ - /// - public partial class InitialCreate : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "Competence", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - Name = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Competence", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Organization", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - Name = table.Column(type: "nvarchar(max)", nullable: false), - HoursPerWorkday = table.Column(type: "real", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Organization", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Department", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - OrganizationId = table.Column(type: "nvarchar(450)", nullable: false), - Name = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Department", x => x.Id); - table.ForeignKey( - name: "FK_Department_Organization_OrganizationId", - column: x => x.OrganizationId, - principalTable: "Organization", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Consultant", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: false), - Email = table.Column(type: "nvarchar(max)", nullable: false), - StartDate = table.Column(type: "datetime2", nullable: true), - EndDate = table.Column(type: "datetime2", nullable: true), - DepartmentId = table.Column(type: "nvarchar(450)", nullable: false), - Degree = table.Column(type: "nvarchar(max)", nullable: true), - GraduationYear = table.Column(type: "int", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Consultant", x => x.Id); - table.ForeignKey( - name: "FK_Consultant_Department_DepartmentId", - column: x => x.DepartmentId, - principalTable: "Department", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "CompetenceConsultant", - columns: table => new - { - CompetencesId = table.Column(type: "nvarchar(450)", nullable: false), - ConsultantId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_CompetenceConsultant", x => new { x.CompetencesId, x.ConsultantId }); - table.ForeignKey( - name: "FK_CompetenceConsultant_Competence_CompetencesId", - column: x => x.CompetencesId, - principalTable: "Competence", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_CompetenceConsultant_Consultant_ConsultantId", - column: x => x.ConsultantId, - principalTable: "Consultant", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.InsertData( - table: "Competence", - columns: new[] { "Id", "Name" }, - values: new object[,] - { - { "backend", "Backend" }, - { "design", "Design" }, - { "frontend", "Frontend" }, - { "project-mgmt", "Project Management" } - }); - - migrationBuilder.InsertData( - table: "Organization", - columns: new[] { "Id", "HoursPerWorkday", "Name" }, - values: new object[] { "variant-as", 7.5f, "Variant AS" }); - - migrationBuilder.InsertData( - table: "Department", - columns: new[] { "Id", "Name", "OrganizationId" }, - values: new object[] { "trondheim", "Trondheim", "variant-as" }); - - migrationBuilder.InsertData( - table: "Consultant", - columns: new[] { "Id", "Degree", "DepartmentId", "Email", "EndDate", "GraduationYear", "Name", "StartDate" }, - values: new object[] { 1, "Master", "trondheim", "j@variant.no", null, 2019, "Jonas", new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) }); - - migrationBuilder.CreateIndex( - name: "IX_CompetenceConsultant_ConsultantId", - table: "CompetenceConsultant", - column: "ConsultantId"); - - migrationBuilder.CreateIndex( - name: "IX_Consultant_DepartmentId", - table: "Consultant", - column: "DepartmentId"); - - migrationBuilder.CreateIndex( - name: "IX_Department_OrganizationId", - table: "Department", - column: "OrganizationId"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "CompetenceConsultant"); - - migrationBuilder.DropTable( - name: "Competence"); - - migrationBuilder.DropTable( - name: "Consultant"); - - migrationBuilder.DropTable( - name: "Department"); - - migrationBuilder.DropTable( - name: "Organization"); - } - } -} diff --git a/backend/Database/Migrations/20230919085422_VacationAndAbsence.Designer.cs b/backend/Database/Migrations/20230919085422_VacationAndAbsence.Designer.cs deleted file mode 100644 index 92896494..00000000 --- a/backend/Database/Migrations/20230919085422_VacationAndAbsence.Designer.cs +++ /dev/null @@ -1,318 +0,0 @@ -// -using System; -using Database.DatabaseContext; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace backend.Migrations -{ - [DbContext(typeof(ApplicationContext))] - [Migration("20230919085422_VacationAndAbsence")] - partial class VacationAndAbsence - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.10") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("CompetenceConsultant", b => - { - b.Property("CompetencesId") - .HasColumnType("nvarchar(450)"); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.HasKey("CompetencesId", "ConsultantId"); - - b.HasIndex("ConsultantId"); - - b.ToTable("CompetenceConsultant"); - }); - - modelBuilder.Entity("backend.ApplicationCore.DomainModels.Competence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Competence"); - - b.HasData( - new - { - Id = "frontend", - Name = "Frontend" - }, - new - { - Id = "backend", - Name = "Backend" - }, - new - { - Id = "design", - Name = "Design" - }, - new - { - Id = "project-mgmt", - Name = "Project Management" - }); - }); - - modelBuilder.Entity("backend.ApplicationCore.DomainModels.Consultant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Degree") - .HasColumnType("nvarchar(max)"); - - b.Property("DepartmentId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Email") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("EndDate") - .HasColumnType("datetime2"); - - b.Property("GraduationYear") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StartDate") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("DepartmentId"); - - b.ToTable("Consultant"); - - b.HasData( - new - { - Id = 1, - Degree = "Master", - DepartmentId = "trondheim", - Email = "j@variant.no", - GraduationYear = 2019, - Name = "Jonas", - StartDate = new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) - }); - }); - - modelBuilder.Entity("backend.ApplicationCore.DomainModels.Department", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Department"); - - b.HasData( - new - { - Id = "trondheim", - Name = "Trondheim", - OrganizationId = "variant-as" - }); - }); - - modelBuilder.Entity("backend.ApplicationCore.DomainModels.Organization", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("HoursPerWorkday") - .HasColumnType("real"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Organization"); - - b.HasData( - new - { - Id = "variant-as", - HoursPerWorkday = 7.5f, - Name = "Variant AS" - }); - }); - - modelBuilder.Entity("backend.ApplicationCore.DomainModels.PlannedAbsence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ApplicableDays") - .HasColumnType("int"); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Fraction") - .HasColumnType("float"); - - b.Property("Type") - .HasColumnType("int"); - - b.Property("WeekNumber") - .HasColumnType("int"); - - b.Property("Year") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ConsultantId"); - - b.ToTable("PlannedAbsence"); - }); - - modelBuilder.Entity("backend.ApplicationCore.DomainModels.Vacation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Date") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("ConsultantId"); - - b.ToTable("Vacation"); - }); - - modelBuilder.Entity("CompetenceConsultant", b => - { - b.HasOne("backend.ApplicationCore.DomainModels.Competence", null) - .WithMany() - .HasForeignKey("CompetencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("backend.ApplicationCore.DomainModels.Consultant", null) - .WithMany() - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("backend.ApplicationCore.DomainModels.Consultant", b => - { - b.HasOne("backend.ApplicationCore.DomainModels.Department", "Department") - .WithMany("Consultants") - .HasForeignKey("DepartmentId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Department"); - }); - - modelBuilder.Entity("backend.ApplicationCore.DomainModels.Department", b => - { - b.HasOne("backend.ApplicationCore.DomainModels.Organization", "Organization") - .WithMany("Departments") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("backend.ApplicationCore.DomainModels.PlannedAbsence", b => - { - b.HasOne("backend.ApplicationCore.DomainModels.Consultant", "Consultant") - .WithMany("PlannedAbsences") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Consultant"); - }); - - modelBuilder.Entity("backend.ApplicationCore.DomainModels.Vacation", b => - { - b.HasOne("backend.ApplicationCore.DomainModels.Consultant", "Consultant") - .WithMany("Vacations") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Consultant"); - }); - - modelBuilder.Entity("backend.ApplicationCore.DomainModels.Consultant", b => - { - b.Navigation("PlannedAbsences"); - - b.Navigation("Vacations"); - }); - - modelBuilder.Entity("backend.ApplicationCore.DomainModels.Department", b => - { - b.Navigation("Consultants"); - }); - - modelBuilder.Entity("backend.ApplicationCore.DomainModels.Organization", b => - { - b.Navigation("Departments"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/backend/Database/Migrations/20230919085422_VacationAndAbsence.cs b/backend/Database/Migrations/20230919085422_VacationAndAbsence.cs deleted file mode 100644 index c3e886e5..00000000 --- a/backend/Database/Migrations/20230919085422_VacationAndAbsence.cs +++ /dev/null @@ -1,79 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace backend.Migrations -{ - /// - public partial class VacationAndAbsence : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "PlannedAbsence", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ConsultantId = table.Column(type: "int", nullable: false), - Type = table.Column(type: "int", nullable: false), - Year = table.Column(type: "int", nullable: false), - WeekNumber = table.Column(type: "int", nullable: false), - ApplicableDays = table.Column(type: "int", nullable: false), - Fraction = table.Column(type: "float", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_PlannedAbsence", x => x.Id); - table.ForeignKey( - name: "FK_PlannedAbsence_Consultant_ConsultantId", - column: x => x.ConsultantId, - principalTable: "Consultant", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Vacation", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ConsultantId = table.Column(type: "int", nullable: false), - Date = table.Column(type: "datetime2", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Vacation", x => x.Id); - table.ForeignKey( - name: "FK_Vacation_Consultant_ConsultantId", - column: x => x.ConsultantId, - principalTable: "Consultant", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_PlannedAbsence_ConsultantId", - table: "PlannedAbsence", - column: "ConsultantId"); - - migrationBuilder.CreateIndex( - name: "IX_Vacation_ConsultantId", - table: "Vacation", - column: "ConsultantId"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "PlannedAbsence"); - - migrationBuilder.DropTable( - name: "Vacation"); - } - } -} diff --git a/backend/Database/Migrations/20230926080554_StaffingAbsence.Designer.cs b/backend/Database/Migrations/20230926080554_StaffingAbsence.Designer.cs deleted file mode 100644 index bc600c1e..00000000 --- a/backend/Database/Migrations/20230926080554_StaffingAbsence.Designer.cs +++ /dev/null @@ -1,500 +0,0 @@ -// -using System; -using Database.DatabaseContext; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace backend.Migrations -{ - [DbContext(typeof(ApplicationContext))] - [Migration("20230926080554_StaffingAbsence")] - partial class StaffingAbsence - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.10") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("CompetenceConsultant", b => - { - b.Property("CompetencesId") - .HasColumnType("nvarchar(450)"); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.HasKey("CompetencesId", "ConsultantId"); - - b.HasIndex("ConsultantId"); - - b.ToTable("CompetenceConsultant"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Absence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ExcludeFromBillRate") - .HasColumnType("bit"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Absence"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Competence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Competence"); - - b.HasData( - new - { - Id = "frontend", - Name = "Frontend" - }, - new - { - Id = "backend", - Name = "Backend" - }, - new - { - Id = "design", - Name = "Design" - }, - new - { - Id = "project-mgmt", - Name = "Project Management" - }); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Consultant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Degree") - .HasColumnType("nvarchar(max)"); - - b.Property("DepartmentId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Email") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("EndDate") - .HasColumnType("datetime2"); - - b.Property("GraduationYear") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StartDate") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("DepartmentId"); - - b.ToTable("Consultant"); - - b.HasData( - new - { - Id = 1, - Degree = "Master", - DepartmentId = "trondheim", - Email = "j@variant.no", - GraduationYear = 2019, - Name = "Jonas", - StartDate = new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) - }); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Customer", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Customer"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Department", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Department"); - - b.HasData( - new - { - Id = "trondheim", - Name = "Trondheim", - OrganizationId = "variant-as" - }); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Organization", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("HoursPerWorkday") - .HasColumnType("real"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Organization"); - - b.HasData( - new - { - Id = "variant-as", - HoursPerWorkday = 7.5f, - Name = "Variant AS" - }); - }); - - modelBuilder.Entity("backend.Core.DomainModels.PlannedAbsence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("AbsenceId") - .HasColumnType("int"); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Hours") - .HasColumnType("float"); - - b.Property("WeekNumber") - .HasColumnType("int"); - - b.Property("Year") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("AbsenceId"); - - b.HasIndex("ConsultantId"); - - b.ToTable("PlannedAbsence"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Project", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("CustomerId") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("State") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("CustomerId"); - - b.ToTable("Project"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Staffing", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Hours") - .HasColumnType("float"); - - b.Property("ProjectId") - .HasColumnType("int"); - - b.Property("Week") - .HasColumnType("int"); - - b.Property("Year") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ConsultantId"); - - b.HasIndex("ProjectId"); - - b.ToTable("Staffing"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Vacation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Date") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("ConsultantId"); - - b.ToTable("Vacation"); - }); - - modelBuilder.Entity("CompetenceConsultant", b => - { - b.HasOne("backend.Core.DomainModels.Competence", null) - .WithMany() - .HasForeignKey("CompetencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("backend.Core.DomainModels.Consultant", null) - .WithMany() - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Absence", b => - { - b.HasOne("backend.Core.DomainModels.Organization", "Organization") - .WithMany("AbsenceTypes") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Consultant", b => - { - b.HasOne("backend.Core.DomainModels.Department", "Department") - .WithMany("Consultants") - .HasForeignKey("DepartmentId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Department"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Customer", b => - { - b.HasOne("backend.Core.DomainModels.Organization", "Organization") - .WithMany("Customers") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Department", b => - { - b.HasOne("backend.Core.DomainModels.Organization", "Organization") - .WithMany("Departments") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.PlannedAbsence", b => - { - b.HasOne("backend.Core.DomainModels.Absence", "Absence") - .WithMany() - .HasForeignKey("AbsenceId") - .OnDelete(DeleteBehavior.ClientCascade) - .IsRequired(); - - b.HasOne("backend.Core.DomainModels.Consultant", "Consultant") - .WithMany("PlannedAbsences") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Absence"); - - b.Navigation("Consultant"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Project", b => - { - b.HasOne("backend.Core.DomainModels.Customer", "Customer") - .WithMany("Projects") - .HasForeignKey("CustomerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Customer"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Staffing", b => - { - b.HasOne("backend.Core.DomainModels.Consultant", "Consultant") - .WithMany("Staffings") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.ClientCascade) - .IsRequired(); - - b.HasOne("backend.Core.DomainModels.Project", "Project") - .WithMany("Staffings") - .HasForeignKey("ProjectId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Consultant"); - - b.Navigation("Project"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Vacation", b => - { - b.HasOne("backend.Core.DomainModels.Consultant", "Consultant") - .WithMany("Vacations") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Consultant"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Consultant", b => - { - b.Navigation("PlannedAbsences"); - - b.Navigation("Staffings"); - - b.Navigation("Vacations"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Customer", b => - { - b.Navigation("Projects"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Department", b => - { - b.Navigation("Consultants"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Organization", b => - { - b.Navigation("AbsenceTypes"); - - b.Navigation("Customers"); - - b.Navigation("Departments"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Project", b => - { - b.Navigation("Staffings"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/backend/Database/Migrations/20230926080554_StaffingAbsence.cs b/backend/Database/Migrations/20230926080554_StaffingAbsence.cs deleted file mode 100644 index 67e4a49e..00000000 --- a/backend/Database/Migrations/20230926080554_StaffingAbsence.cs +++ /dev/null @@ -1,196 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace backend.Migrations -{ - /// - public partial class StaffingAbsence : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropColumn( - name: "ApplicableDays", - table: "PlannedAbsence"); - - migrationBuilder.RenameColumn( - name: "Type", - table: "PlannedAbsence", - newName: "AbsenceId"); - - migrationBuilder.RenameColumn( - name: "Fraction", - table: "PlannedAbsence", - newName: "Hours"); - - migrationBuilder.CreateTable( - name: "Absence", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: false), - ExcludeFromBillRate = table.Column(type: "bit", nullable: false), - OrganizationId = table.Column(type: "nvarchar(450)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Absence", x => x.Id); - table.ForeignKey( - name: "FK_Absence_Organization_OrganizationId", - column: x => x.OrganizationId, - principalTable: "Organization", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Customer", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: false), - OrganizationId = table.Column(type: "nvarchar(450)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Customer", x => x.Id); - table.ForeignKey( - name: "FK_Customer_Organization_OrganizationId", - column: x => x.OrganizationId, - principalTable: "Organization", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Project", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - CustomerId = table.Column(type: "int", nullable: false), - State = table.Column(type: "nvarchar(max)", nullable: false), - Name = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Project", x => x.Id); - table.ForeignKey( - name: "FK_Project_Customer_CustomerId", - column: x => x.CustomerId, - principalTable: "Customer", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Staffing", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ProjectId = table.Column(type: "int", nullable: false), - ConsultantId = table.Column(type: "int", nullable: false), - Year = table.Column(type: "int", nullable: false), - Week = table.Column(type: "int", nullable: false), - Hours = table.Column(type: "float", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Staffing", x => x.Id); - table.ForeignKey( - name: "FK_Staffing_Consultant_ConsultantId", - column: x => x.ConsultantId, - principalTable: "Consultant", - principalColumn: "Id"); - table.ForeignKey( - name: "FK_Staffing_Project_ProjectId", - column: x => x.ProjectId, - principalTable: "Project", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateIndex( - name: "IX_PlannedAbsence_AbsenceId", - table: "PlannedAbsence", - column: "AbsenceId"); - - migrationBuilder.CreateIndex( - name: "IX_Absence_OrganizationId", - table: "Absence", - column: "OrganizationId"); - - migrationBuilder.CreateIndex( - name: "IX_Customer_OrganizationId", - table: "Customer", - column: "OrganizationId"); - - migrationBuilder.CreateIndex( - name: "IX_Project_CustomerId", - table: "Project", - column: "CustomerId"); - - migrationBuilder.CreateIndex( - name: "IX_Staffing_ConsultantId", - table: "Staffing", - column: "ConsultantId"); - - migrationBuilder.CreateIndex( - name: "IX_Staffing_ProjectId", - table: "Staffing", - column: "ProjectId"); - - migrationBuilder.AddForeignKey( - name: "FK_PlannedAbsence_Absence_AbsenceId", - table: "PlannedAbsence", - column: "AbsenceId", - principalTable: "Absence", - principalColumn: "Id"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_PlannedAbsence_Absence_AbsenceId", - table: "PlannedAbsence"); - - migrationBuilder.DropTable( - name: "Absence"); - - migrationBuilder.DropTable( - name: "Staffing"); - - migrationBuilder.DropTable( - name: "Project"); - - migrationBuilder.DropTable( - name: "Customer"); - - migrationBuilder.DropIndex( - name: "IX_PlannedAbsence_AbsenceId", - table: "PlannedAbsence"); - - migrationBuilder.RenameColumn( - name: "Hours", - table: "PlannedAbsence", - newName: "Fraction"); - - migrationBuilder.RenameColumn( - name: "AbsenceId", - table: "PlannedAbsence", - newName: "Type"); - - migrationBuilder.AddColumn( - name: "ApplicableDays", - table: "PlannedAbsence", - type: "int", - nullable: false, - defaultValue: 0); - } - } -} diff --git a/backend/Database/Migrations/20230927080712_AddedHolidayModelAndFloatToDoubleCastFix.Designer.cs b/backend/Database/Migrations/20230927080712_AddedHolidayModelAndFloatToDoubleCastFix.Designer.cs deleted file mode 100644 index 50b3dbc6..00000000 --- a/backend/Database/Migrations/20230927080712_AddedHolidayModelAndFloatToDoubleCastFix.Designer.cs +++ /dev/null @@ -1,500 +0,0 @@ -// -using System; -using Database.DatabaseContext; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace backend.Migrations -{ - [DbContext(typeof(ApplicationContext))] - [Migration("20230927080712_AddedHolidayModelAndFloatToDoubleCastFix")] - partial class AddedHolidayModelAndFloatToDoubleCastFix - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.10") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("CompetenceConsultant", b => - { - b.Property("CompetencesId") - .HasColumnType("nvarchar(450)"); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.HasKey("CompetencesId", "ConsultantId"); - - b.HasIndex("ConsultantId"); - - b.ToTable("CompetenceConsultant"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Absence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ExcludeFromBillRate") - .HasColumnType("bit"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Absence"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Competence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Competence"); - - b.HasData( - new - { - Id = "frontend", - Name = "Frontend" - }, - new - { - Id = "backend", - Name = "Backend" - }, - new - { - Id = "design", - Name = "Design" - }, - new - { - Id = "project-mgmt", - Name = "Project Management" - }); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Consultant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Degree") - .HasColumnType("nvarchar(max)"); - - b.Property("DepartmentId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Email") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("EndDate") - .HasColumnType("datetime2"); - - b.Property("GraduationYear") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StartDate") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("DepartmentId"); - - b.ToTable("Consultant"); - - b.HasData( - new - { - Id = 1, - Degree = "Master", - DepartmentId = "trondheim", - Email = "j@variant.no", - GraduationYear = 2019, - Name = "Jonas", - StartDate = new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) - }); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Customer", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Customer"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Department", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Department"); - - b.HasData( - new - { - Id = "trondheim", - Name = "Trondheim", - OrganizationId = "variant-as" - }); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Organization", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("HoursPerWorkday") - .HasColumnType("float"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Organization"); - - b.HasData( - new - { - Id = "variant-as", - HoursPerWorkday = 7.5, - Name = "Variant AS" - }); - }); - - modelBuilder.Entity("backend.Core.DomainModels.PlannedAbsence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("AbsenceId") - .HasColumnType("int"); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Hours") - .HasColumnType("float"); - - b.Property("WeekNumber") - .HasColumnType("int"); - - b.Property("Year") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("AbsenceId"); - - b.HasIndex("ConsultantId"); - - b.ToTable("PlannedAbsence"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Project", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("CustomerId") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("State") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("CustomerId"); - - b.ToTable("Project"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Staffing", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Hours") - .HasColumnType("float"); - - b.Property("ProjectId") - .HasColumnType("int"); - - b.Property("Week") - .HasColumnType("int"); - - b.Property("Year") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ConsultantId"); - - b.HasIndex("ProjectId"); - - b.ToTable("Staffing"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Vacation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Date") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("ConsultantId"); - - b.ToTable("Vacation"); - }); - - modelBuilder.Entity("CompetenceConsultant", b => - { - b.HasOne("backend.Core.DomainModels.Competence", null) - .WithMany() - .HasForeignKey("CompetencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("backend.Core.DomainModels.Consultant", null) - .WithMany() - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Absence", b => - { - b.HasOne("backend.Core.DomainModels.Organization", "Organization") - .WithMany("AbsenceTypes") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Consultant", b => - { - b.HasOne("backend.Core.DomainModels.Department", "Department") - .WithMany("Consultants") - .HasForeignKey("DepartmentId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Department"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Customer", b => - { - b.HasOne("backend.Core.DomainModels.Organization", "Organization") - .WithMany("Customers") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Department", b => - { - b.HasOne("backend.Core.DomainModels.Organization", "Organization") - .WithMany("Departments") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.PlannedAbsence", b => - { - b.HasOne("backend.Core.DomainModels.Absence", "Absence") - .WithMany() - .HasForeignKey("AbsenceId") - .OnDelete(DeleteBehavior.ClientCascade) - .IsRequired(); - - b.HasOne("backend.Core.DomainModels.Consultant", "Consultant") - .WithMany("PlannedAbsences") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Absence"); - - b.Navigation("Consultant"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Project", b => - { - b.HasOne("backend.Core.DomainModels.Customer", "Customer") - .WithMany("Projects") - .HasForeignKey("CustomerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Customer"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Staffing", b => - { - b.HasOne("backend.Core.DomainModels.Consultant", "Consultant") - .WithMany("Staffings") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.ClientCascade) - .IsRequired(); - - b.HasOne("backend.Core.DomainModels.Project", "Project") - .WithMany("Staffings") - .HasForeignKey("ProjectId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Consultant"); - - b.Navigation("Project"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Vacation", b => - { - b.HasOne("backend.Core.DomainModels.Consultant", "Consultant") - .WithMany("Vacations") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Consultant"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Consultant", b => - { - b.Navigation("PlannedAbsences"); - - b.Navigation("Staffings"); - - b.Navigation("Vacations"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Customer", b => - { - b.Navigation("Projects"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Department", b => - { - b.Navigation("Consultants"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Organization", b => - { - b.Navigation("AbsenceTypes"); - - b.Navigation("Customers"); - - b.Navigation("Departments"); - }); - - modelBuilder.Entity("backend.Core.DomainModels.Project", b => - { - b.Navigation("Staffings"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/backend/Database/Migrations/20230927080712_AddedHolidayModelAndFloatToDoubleCastFix.cs b/backend/Database/Migrations/20230927080712_AddedHolidayModelAndFloatToDoubleCastFix.cs deleted file mode 100644 index c8a542ae..00000000 --- a/backend/Database/Migrations/20230927080712_AddedHolidayModelAndFloatToDoubleCastFix.cs +++ /dev/null @@ -1,48 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace backend.Migrations -{ - /// - public partial class AddedHolidayModelAndFloatToDoubleCastFix : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "HoursPerWorkday", - table: "Organization", - type: "float", - nullable: false, - oldClrType: typeof(float), - oldType: "real"); - - migrationBuilder.UpdateData( - table: "Organization", - keyColumn: "Id", - keyValue: "variant-as", - column: "HoursPerWorkday", - value: 7.5); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AlterColumn( - name: "HoursPerWorkday", - table: "Organization", - type: "real", - nullable: false, - oldClrType: typeof(double), - oldType: "float"); - - migrationBuilder.UpdateData( - table: "Organization", - keyColumn: "Id", - keyValue: "variant-as", - column: "HoursPerWorkday", - value: 7.5f); - } - } -} diff --git a/backend/Database/Migrations/20231004195542_RemovedOrganization.Designer.cs b/backend/Database/Migrations/20231004195542_RemovedOrganization.Designer.cs deleted file mode 100644 index 162c4307..00000000 --- a/backend/Database/Migrations/20231004195542_RemovedOrganization.Designer.cs +++ /dev/null @@ -1,413 +0,0 @@ -// -using System; -using Database.DatabaseContext; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace backend.Migrations -{ - [DbContext(typeof(ApplicationContext))] - [Migration("20231004195542_RemovedOrganization")] - partial class RemovedOrganization - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.10") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("CompetenceConsultant", b => - { - b.Property("CompetencesId") - .HasColumnType("nvarchar(450)"); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.HasKey("CompetencesId", "ConsultantId"); - - b.HasIndex("ConsultantId"); - - b.ToTable("CompetenceConsultant"); - }); - - modelBuilder.Entity("Core.DomainModels.Absence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ExcludeFromBillRate") - .HasColumnType("bit"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Absence"); - }); - - modelBuilder.Entity("Core.DomainModels.Competence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Competence"); - - b.HasData( - new - { - Id = "frontend", - Name = "Frontend" - }, - new - { - Id = "backend", - Name = "Backend" - }, - new - { - Id = "design", - Name = "Design" - }, - new - { - Id = "project-mgmt", - Name = "Project Management" - }); - }); - - modelBuilder.Entity("Core.DomainModels.Consultant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Degree") - .HasColumnType("nvarchar(max)"); - - b.Property("DepartmentId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Email") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("EndDate") - .HasColumnType("datetime2"); - - b.Property("GraduationYear") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StartDate") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("DepartmentId"); - - b.ToTable("Consultant"); - - b.HasData( - new - { - Id = 1, - Degree = "Master", - DepartmentId = "trondheim", - Email = "j@variant.no", - GraduationYear = 2019, - Name = "Jonas", - StartDate = new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) - }); - }); - - modelBuilder.Entity("Core.DomainModels.Customer", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Customer"); - }); - - modelBuilder.Entity("Core.DomainModels.Department", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Department"); - - b.HasData( - new - { - Id = "trondheim", - Name = "Trondheim" - }); - }); - - modelBuilder.Entity("Core.DomainModels.PlannedAbsence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("AbsenceId") - .HasColumnType("int"); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Hours") - .HasColumnType("float"); - - b.Property("WeekNumber") - .HasColumnType("int"); - - b.Property("Year") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("AbsenceId"); - - b.HasIndex("ConsultantId"); - - b.ToTable("PlannedAbsence"); - }); - - modelBuilder.Entity("Core.DomainModels.Project", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("CustomerId") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("State") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("CustomerId"); - - b.ToTable("Project"); - }); - - modelBuilder.Entity("Core.DomainModels.Staffing", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Hours") - .HasColumnType("float"); - - b.Property("ProjectId") - .HasColumnType("int"); - - b.Property("Week") - .HasColumnType("int"); - - b.Property("Year") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ConsultantId"); - - b.HasIndex("ProjectId"); - - b.ToTable("Staffing"); - }); - - modelBuilder.Entity("Core.DomainModels.Vacation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Date") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("ConsultantId"); - - b.ToTable("Vacation"); - }); - - modelBuilder.Entity("CompetenceConsultant", b => - { - b.HasOne("Core.DomainModels.Competence", null) - .WithMany() - .HasForeignKey("CompetencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Core.DomainModels.Consultant", null) - .WithMany() - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Core.DomainModels.Consultant", b => - { - b.HasOne("Core.DomainModels.Department", "Department") - .WithMany("Consultants") - .HasForeignKey("DepartmentId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Department"); - }); - - modelBuilder.Entity("Core.DomainModels.PlannedAbsence", b => - { - b.HasOne("Core.DomainModels.Absence", "Absence") - .WithMany() - .HasForeignKey("AbsenceId") - .OnDelete(DeleteBehavior.ClientCascade) - .IsRequired(); - - b.HasOne("Core.DomainModels.Consultant", "Consultant") - .WithMany("PlannedAbsences") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Absence"); - - b.Navigation("Consultant"); - }); - - modelBuilder.Entity("Core.DomainModels.Project", b => - { - b.HasOne("Core.DomainModels.Customer", "Customer") - .WithMany("Projects") - .HasForeignKey("CustomerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Customer"); - }); - - modelBuilder.Entity("Core.DomainModels.Staffing", b => - { - b.HasOne("Core.DomainModels.Consultant", "Consultant") - .WithMany("Staffings") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.ClientCascade) - .IsRequired(); - - b.HasOne("Core.DomainModels.Project", "Project") - .WithMany("Staffings") - .HasForeignKey("ProjectId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Consultant"); - - b.Navigation("Project"); - }); - - modelBuilder.Entity("Core.DomainModels.Vacation", b => - { - b.HasOne("Core.DomainModels.Consultant", "Consultant") - .WithMany("Vacations") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Consultant"); - }); - - modelBuilder.Entity("Core.DomainModels.Consultant", b => - { - b.Navigation("PlannedAbsences"); - - b.Navigation("Staffings"); - - b.Navigation("Vacations"); - }); - - modelBuilder.Entity("Core.DomainModels.Customer", b => - { - b.Navigation("Projects"); - }); - - modelBuilder.Entity("Core.DomainModels.Department", b => - { - b.Navigation("Consultants"); - }); - - modelBuilder.Entity("Core.DomainModels.Project", b => - { - b.Navigation("Staffings"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/backend/Database/Migrations/20231004195542_RemovedOrganization.cs b/backend/Database/Migrations/20231004195542_RemovedOrganization.cs deleted file mode 100644 index dcdeb30d..00000000 --- a/backend/Database/Migrations/20231004195542_RemovedOrganization.cs +++ /dev/null @@ -1,142 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace backend.Migrations -{ - /// - public partial class RemovedOrganization : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_Absence_Organization_OrganizationId", - table: "Absence"); - - migrationBuilder.DropForeignKey( - name: "FK_Customer_Organization_OrganizationId", - table: "Customer"); - - migrationBuilder.DropForeignKey( - name: "FK_Department_Organization_OrganizationId", - table: "Department"); - - migrationBuilder.DropTable( - name: "Organization"); - - migrationBuilder.DropIndex( - name: "IX_Department_OrganizationId", - table: "Department"); - - migrationBuilder.DropIndex( - name: "IX_Customer_OrganizationId", - table: "Customer"); - - migrationBuilder.DropIndex( - name: "IX_Absence_OrganizationId", - table: "Absence"); - - migrationBuilder.DropColumn( - name: "OrganizationId", - table: "Department"); - - migrationBuilder.DropColumn( - name: "OrganizationId", - table: "Customer"); - - migrationBuilder.DropColumn( - name: "OrganizationId", - table: "Absence"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "OrganizationId", - table: "Department", - type: "nvarchar(450)", - nullable: false, - defaultValue: ""); - - migrationBuilder.AddColumn( - name: "OrganizationId", - table: "Customer", - type: "nvarchar(450)", - nullable: false, - defaultValue: ""); - - migrationBuilder.AddColumn( - name: "OrganizationId", - table: "Absence", - type: "nvarchar(450)", - nullable: false, - defaultValue: ""); - - migrationBuilder.CreateTable( - name: "Organization", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - HoursPerWorkday = table.Column(type: "float", nullable: false), - Name = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Organization", x => x.Id); - }); - - migrationBuilder.UpdateData( - table: "Department", - keyColumn: "Id", - keyValue: "trondheim", - column: "OrganizationId", - value: "variant-as"); - - migrationBuilder.InsertData( - table: "Organization", - columns: new[] { "Id", "HoursPerWorkday", "Name" }, - values: new object[] { "variant-as", 7.5, "Variant AS" }); - - migrationBuilder.CreateIndex( - name: "IX_Department_OrganizationId", - table: "Department", - column: "OrganizationId"); - - migrationBuilder.CreateIndex( - name: "IX_Customer_OrganizationId", - table: "Customer", - column: "OrganizationId"); - - migrationBuilder.CreateIndex( - name: "IX_Absence_OrganizationId", - table: "Absence", - column: "OrganizationId"); - - migrationBuilder.AddForeignKey( - name: "FK_Absence_Organization_OrganizationId", - table: "Absence", - column: "OrganizationId", - principalTable: "Organization", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_Customer_Organization_OrganizationId", - table: "Customer", - column: "OrganizationId", - principalTable: "Organization", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_Department_Organization_OrganizationId", - table: "Department", - column: "OrganizationId", - principalTable: "Organization", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - } - } -} diff --git a/backend/Database/Migrations/20231017094309_AddOrganizationBackAgain.Designer.cs b/backend/Database/Migrations/20231017094309_AddOrganizationBackAgain.Designer.cs deleted file mode 100644 index de3f22d8..00000000 --- a/backend/Database/Migrations/20231017094309_AddOrganizationBackAgain.Designer.cs +++ /dev/null @@ -1,531 +0,0 @@ -// -using System; -using Database.DatabaseContext; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace backend.Migrations -{ - [DbContext(typeof(ApplicationContext))] - [Migration("20231017094309_AddOrganizationBackAgain")] - partial class AddOrganizationBackAgain - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.10") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("CompetenceConsultant", b => - { - b.Property("CompetencesId") - .HasColumnType("nvarchar(450)"); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.HasKey("CompetencesId", "ConsultantId"); - - b.HasIndex("ConsultantId"); - - b.ToTable("CompetenceConsultant"); - }); - - modelBuilder.Entity("Core.DomainModels.Absence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ExcludeFromBillRate") - .HasColumnType("bit"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Absence"); - }); - - modelBuilder.Entity("Core.DomainModels.Competence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Competence"); - - b.HasData( - new - { - Id = "frontend", - Name = "Frontend" - }, - new - { - Id = "backend", - Name = "Backend" - }, - new - { - Id = "design", - Name = "Design" - }, - new - { - Id = "project-mgmt", - Name = "Project Management" - }); - }); - - modelBuilder.Entity("Core.DomainModels.Consultant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Degree") - .HasColumnType("nvarchar(max)"); - - b.Property("DepartmentId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Email") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("EndDate") - .HasColumnType("datetime2"); - - b.Property("GraduationYear") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StartDate") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("DepartmentId"); - - b.ToTable("Consultant"); - - b.HasData( - new - { - Id = 1, - Degree = "Master", - DepartmentId = "trondheim", - Email = "j@variant.no", - GraduationYear = 2019, - Name = "Jonas", - StartDate = new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) - }); - }); - - modelBuilder.Entity("Core.DomainModels.Customer", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Customer"); - }); - - modelBuilder.Entity("Core.DomainModels.Department", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Department"); - - b.HasData( - new - { - Id = "trondheim", - Name = "Trondheim", - OrganizationId = "variant-as" - }); - }); - - modelBuilder.Entity("Core.DomainModels.Organization", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("Country") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("HasVacationInChristmas") - .HasColumnType("bit"); - - b.Property("HoursPerWorkday") - .HasColumnType("float"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("NumberOfVacationDaysInYear") - .HasColumnType("int"); - - b.Property("TagName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Organization"); - - b.HasData( - new - { - Id = "variant-as", - Country = "norway", - HasVacationInChristmas = true, - HoursPerWorkday = 7.5, - Name = "Variant AS", - NumberOfVacationDaysInYear = 25, - TagName = "variant-as" - }); - }); - - modelBuilder.Entity("Core.DomainModels.PlannedAbsence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("AbsenceId") - .HasColumnType("int"); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Hours") - .HasColumnType("float"); - - b.Property("WeekNumber") - .HasColumnType("int"); - - b.Property("Year") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("AbsenceId"); - - b.HasIndex("ConsultantId"); - - b.ToTable("PlannedAbsence"); - }); - - modelBuilder.Entity("Core.DomainModels.Project", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("CustomerId") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("State") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("CustomerId"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Project"); - }); - - modelBuilder.Entity("Core.DomainModels.Staffing", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Hours") - .HasColumnType("float"); - - b.Property("ProjectId") - .HasColumnType("int"); - - b.Property("Week") - .HasColumnType("int"); - - b.Property("Year") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ConsultantId"); - - b.HasIndex("ProjectId"); - - b.ToTable("Staffing"); - }); - - modelBuilder.Entity("Core.DomainModels.Vacation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Date") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("ConsultantId"); - - b.ToTable("Vacation"); - }); - - modelBuilder.Entity("CompetenceConsultant", b => - { - b.HasOne("Core.DomainModels.Competence", null) - .WithMany() - .HasForeignKey("CompetencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Core.DomainModels.Consultant", null) - .WithMany() - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Core.DomainModels.Absence", b => - { - b.HasOne("Core.DomainModels.Organization", "Organization") - .WithMany("AbsenceTypes") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("Core.DomainModels.Consultant", b => - { - b.HasOne("Core.DomainModels.Department", "Department") - .WithMany("Consultants") - .HasForeignKey("DepartmentId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Department"); - }); - - modelBuilder.Entity("Core.DomainModels.Customer", b => - { - b.HasOne("Core.DomainModels.Organization", "Organization") - .WithMany("Customers") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("Core.DomainModels.Department", b => - { - b.HasOne("Core.DomainModels.Organization", "Organization") - .WithMany("Departments") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("Core.DomainModels.PlannedAbsence", b => - { - b.HasOne("Core.DomainModels.Absence", "Absence") - .WithMany() - .HasForeignKey("AbsenceId") - .OnDelete(DeleteBehavior.ClientCascade) - .IsRequired(); - - b.HasOne("Core.DomainModels.Consultant", "Consultant") - .WithMany("PlannedAbsences") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Absence"); - - b.Navigation("Consultant"); - }); - - modelBuilder.Entity("Core.DomainModels.Project", b => - { - b.HasOne("Core.DomainModels.Customer", "Customer") - .WithMany("Projects") - .HasForeignKey("CustomerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Core.DomainModels.Organization", "Organization") - .WithMany() - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Customer"); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("Core.DomainModels.Staffing", b => - { - b.HasOne("Core.DomainModels.Consultant", "Consultant") - .WithMany("Staffings") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.ClientCascade) - .IsRequired(); - - b.HasOne("Core.DomainModels.Project", "Project") - .WithMany("Staffings") - .HasForeignKey("ProjectId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Consultant"); - - b.Navigation("Project"); - }); - - modelBuilder.Entity("Core.DomainModels.Vacation", b => - { - b.HasOne("Core.DomainModels.Consultant", "Consultant") - .WithMany("Vacations") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Consultant"); - }); - - modelBuilder.Entity("Core.DomainModels.Consultant", b => - { - b.Navigation("PlannedAbsences"); - - b.Navigation("Staffings"); - - b.Navigation("Vacations"); - }); - - modelBuilder.Entity("Core.DomainModels.Customer", b => - { - b.Navigation("Projects"); - }); - - modelBuilder.Entity("Core.DomainModels.Department", b => - { - b.Navigation("Consultants"); - }); - - modelBuilder.Entity("Core.DomainModels.Organization", b => - { - b.Navigation("AbsenceTypes"); - - b.Navigation("Customers"); - - b.Navigation("Departments"); - }); - - modelBuilder.Entity("Core.DomainModels.Project", b => - { - b.Navigation("Staffings"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/backend/Database/Migrations/20231017094309_AddOrganizationBackAgain.cs b/backend/Database/Migrations/20231017094309_AddOrganizationBackAgain.cs deleted file mode 100644 index e0653fd3..00000000 --- a/backend/Database/Migrations/20231017094309_AddOrganizationBackAgain.cs +++ /dev/null @@ -1,178 +0,0 @@ -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -namespace backend.Migrations -{ - /// - public partial class AddOrganizationBackAgain : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.AddColumn( - name: "OrganizationId", - table: "Project", - type: "nvarchar(450)", - nullable: false, - defaultValue: ""); - - migrationBuilder.AddColumn( - name: "OrganizationId", - table: "Department", - type: "nvarchar(450)", - nullable: false, - defaultValue: ""); - - migrationBuilder.AddColumn( - name: "OrganizationId", - table: "Customer", - type: "nvarchar(450)", - nullable: false, - defaultValue: ""); - - migrationBuilder.AddColumn( - name: "OrganizationId", - table: "Absence", - type: "nvarchar(450)", - nullable: false, - defaultValue: ""); - - migrationBuilder.CreateTable( - name: "Organization", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - Name = table.Column(type: "nvarchar(max)", nullable: false), - TagName = table.Column(type: "nvarchar(max)", nullable: false), - Country = table.Column(type: "nvarchar(max)", nullable: false), - NumberOfVacationDaysInYear = table.Column(type: "int", nullable: false), - HasVacationInChristmas = table.Column(type: "bit", nullable: false), - HoursPerWorkday = table.Column(type: "float", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Organization", x => x.Id); - }); - - migrationBuilder.UpdateData( - table: "Department", - keyColumn: "Id", - keyValue: "trondheim", - column: "OrganizationId", - value: "variant-as"); - - migrationBuilder.InsertData( - table: "Organization", - columns: new[] { "Id", "Country", "HasVacationInChristmas", "HoursPerWorkday", "Name", "NumberOfVacationDaysInYear", "TagName" }, - values: new object[] { "variant-as", "norway", true, 7.5, "Variant AS", 25, "variant-as" }); - - migrationBuilder.CreateIndex( - name: "IX_Project_OrganizationId", - table: "Project", - column: "OrganizationId"); - - migrationBuilder.CreateIndex( - name: "IX_Department_OrganizationId", - table: "Department", - column: "OrganizationId"); - - migrationBuilder.CreateIndex( - name: "IX_Customer_OrganizationId", - table: "Customer", - column: "OrganizationId"); - - migrationBuilder.CreateIndex( - name: "IX_Absence_OrganizationId", - table: "Absence", - column: "OrganizationId"); - - migrationBuilder.AddForeignKey( - name: "FK_Absence_Organization_OrganizationId", - table: "Absence", - column: "OrganizationId", - principalTable: "Organization", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_Customer_Organization_OrganizationId", - table: "Customer", - column: "OrganizationId", - principalTable: "Organization", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_Department_Organization_OrganizationId", - table: "Department", - column: "OrganizationId", - principalTable: "Organization", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - - migrationBuilder.AddForeignKey( - name: "FK_Project_Organization_OrganizationId", - table: "Project", - column: "OrganizationId", - principalTable: "Organization", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropForeignKey( - name: "FK_Absence_Organization_OrganizationId", - table: "Absence"); - - migrationBuilder.DropForeignKey( - name: "FK_Customer_Organization_OrganizationId", - table: "Customer"); - - migrationBuilder.DropForeignKey( - name: "FK_Department_Organization_OrganizationId", - table: "Department"); - - migrationBuilder.DropForeignKey( - name: "FK_Project_Organization_OrganizationId", - table: "Project"); - - migrationBuilder.DropTable( - name: "Organization"); - - migrationBuilder.DropIndex( - name: "IX_Project_OrganizationId", - table: "Project"); - - migrationBuilder.DropIndex( - name: "IX_Department_OrganizationId", - table: "Department"); - - migrationBuilder.DropIndex( - name: "IX_Customer_OrganizationId", - table: "Customer"); - - migrationBuilder.DropIndex( - name: "IX_Absence_OrganizationId", - table: "Absence"); - - migrationBuilder.DropColumn( - name: "OrganizationId", - table: "Project"); - - migrationBuilder.DropColumn( - name: "OrganizationId", - table: "Department"); - - migrationBuilder.DropColumn( - name: "OrganizationId", - table: "Customer"); - - migrationBuilder.DropColumn( - name: "OrganizationId", - table: "Absence"); - } - } -} diff --git a/backend/Database/Migrations/ApplicationContextModelSnapshot.cs b/backend/Database/Migrations/ApplicationContextModelSnapshot.cs deleted file mode 100644 index 5f314aef..00000000 --- a/backend/Database/Migrations/ApplicationContextModelSnapshot.cs +++ /dev/null @@ -1,528 +0,0 @@ -// -using System; -using Database.DatabaseContext; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace backend.Migrations -{ - [DbContext(typeof(ApplicationContext))] - partial class ApplicationContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.10") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("CompetenceConsultant", b => - { - b.Property("CompetencesId") - .HasColumnType("nvarchar(450)"); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.HasKey("CompetencesId", "ConsultantId"); - - b.HasIndex("ConsultantId"); - - b.ToTable("CompetenceConsultant"); - }); - - modelBuilder.Entity("Core.DomainModels.Absence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ExcludeFromBillRate") - .HasColumnType("bit"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Absence"); - }); - - modelBuilder.Entity("Core.DomainModels.Competence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Competence"); - - b.HasData( - new - { - Id = "frontend", - Name = "Frontend" - }, - new - { - Id = "backend", - Name = "Backend" - }, - new - { - Id = "design", - Name = "Design" - }, - new - { - Id = "project-mgmt", - Name = "Project Management" - }); - }); - - modelBuilder.Entity("Core.DomainModels.Consultant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Degree") - .HasColumnType("nvarchar(max)"); - - b.Property("DepartmentId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Email") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("EndDate") - .HasColumnType("datetime2"); - - b.Property("GraduationYear") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StartDate") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("DepartmentId"); - - b.ToTable("Consultant"); - - b.HasData( - new - { - Id = 1, - Degree = "Master", - DepartmentId = "trondheim", - Email = "j@variant.no", - GraduationYear = 2019, - Name = "Jonas", - StartDate = new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) - }); - }); - - modelBuilder.Entity("Core.DomainModels.Customer", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Customer"); - }); - - modelBuilder.Entity("Core.DomainModels.Department", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Department"); - - b.HasData( - new - { - Id = "trondheim", - Name = "Trondheim", - OrganizationId = "variant-as" - }); - }); - - modelBuilder.Entity("Core.DomainModels.Organization", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("Country") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("HasVacationInChristmas") - .HasColumnType("bit"); - - b.Property("HoursPerWorkday") - .HasColumnType("float"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("NumberOfVacationDaysInYear") - .HasColumnType("int"); - - b.Property("TagName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Organization"); - - b.HasData( - new - { - Id = "variant-as", - Country = "norway", - HasVacationInChristmas = true, - HoursPerWorkday = 7.5, - Name = "Variant AS", - NumberOfVacationDaysInYear = 25, - TagName = "variant-as" - }); - }); - - modelBuilder.Entity("Core.DomainModels.PlannedAbsence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("AbsenceId") - .HasColumnType("int"); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Hours") - .HasColumnType("float"); - - b.Property("WeekNumber") - .HasColumnType("int"); - - b.Property("Year") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("AbsenceId"); - - b.HasIndex("ConsultantId"); - - b.ToTable("PlannedAbsence"); - }); - - modelBuilder.Entity("Core.DomainModels.Project", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("CustomerId") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("State") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("CustomerId"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Project"); - }); - - modelBuilder.Entity("Core.DomainModels.Staffing", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Hours") - .HasColumnType("float"); - - b.Property("ProjectId") - .HasColumnType("int"); - - b.Property("Week") - .HasColumnType("int"); - - b.Property("Year") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ConsultantId"); - - b.HasIndex("ProjectId"); - - b.ToTable("Staffing"); - }); - - modelBuilder.Entity("Core.DomainModels.Vacation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Date") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("ConsultantId"); - - b.ToTable("Vacation"); - }); - - modelBuilder.Entity("CompetenceConsultant", b => - { - b.HasOne("Core.DomainModels.Competence", null) - .WithMany() - .HasForeignKey("CompetencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Core.DomainModels.Consultant", null) - .WithMany() - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Core.DomainModels.Absence", b => - { - b.HasOne("Core.DomainModels.Organization", "Organization") - .WithMany("AbsenceTypes") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("Core.DomainModels.Consultant", b => - { - b.HasOne("Core.DomainModels.Department", "Department") - .WithMany("Consultants") - .HasForeignKey("DepartmentId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Department"); - }); - - modelBuilder.Entity("Core.DomainModels.Customer", b => - { - b.HasOne("Core.DomainModels.Organization", "Organization") - .WithMany("Customers") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("Core.DomainModels.Department", b => - { - b.HasOne("Core.DomainModels.Organization", "Organization") - .WithMany("Departments") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("Core.DomainModels.PlannedAbsence", b => - { - b.HasOne("Core.DomainModels.Absence", "Absence") - .WithMany() - .HasForeignKey("AbsenceId") - .OnDelete(DeleteBehavior.ClientCascade) - .IsRequired(); - - b.HasOne("Core.DomainModels.Consultant", "Consultant") - .WithMany("PlannedAbsences") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Absence"); - - b.Navigation("Consultant"); - }); - - modelBuilder.Entity("Core.DomainModels.Project", b => - { - b.HasOne("Core.DomainModels.Customer", "Customer") - .WithMany("Projects") - .HasForeignKey("CustomerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Core.DomainModels.Organization", "Organization") - .WithMany() - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Customer"); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("Core.DomainModels.Staffing", b => - { - b.HasOne("Core.DomainModels.Consultant", "Consultant") - .WithMany("Staffings") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.ClientCascade) - .IsRequired(); - - b.HasOne("Core.DomainModels.Project", "Project") - .WithMany("Staffings") - .HasForeignKey("ProjectId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Consultant"); - - b.Navigation("Project"); - }); - - modelBuilder.Entity("Core.DomainModels.Vacation", b => - { - b.HasOne("Core.DomainModels.Consultant", "Consultant") - .WithMany("Vacations") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Consultant"); - }); - - modelBuilder.Entity("Core.DomainModels.Consultant", b => - { - b.Navigation("PlannedAbsences"); - - b.Navigation("Staffings"); - - b.Navigation("Vacations"); - }); - - modelBuilder.Entity("Core.DomainModels.Customer", b => - { - b.Navigation("Projects"); - }); - - modelBuilder.Entity("Core.DomainModels.Department", b => - { - b.Navigation("Consultants"); - }); - - modelBuilder.Entity("Core.DomainModels.Organization", b => - { - b.Navigation("AbsenceTypes"); - - b.Navigation("Customers"); - - b.Navigation("Departments"); - }); - - modelBuilder.Entity("Core.DomainModels.Project", b => - { - b.Navigation("Staffings"); - }); -#pragma warning restore 612, 618 - } - } -} From df365bac165c8cf768ed24f7727b10dab5ca4621 Mon Sep 17 00:00:00 2001 From: Magnus Gule Date: Tue, 17 Oct 2023 13:05:03 +0200 Subject: [PATCH 03/26] Adding HotKey optional to Department. Used frontend to keybindings. --- backend/Core/DomainModels/Department.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/Core/DomainModels/Department.cs b/backend/Core/DomainModels/Department.cs index 62e3b7c2..660ae9dc 100644 --- a/backend/Core/DomainModels/Department.cs +++ b/backend/Core/DomainModels/Department.cs @@ -8,6 +8,7 @@ public class Department [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public required string Id { get; set; } public required string Name { get; set; } + public int Hotkey { get; set; } public required Organization Organization { get; set; } [JsonIgnore] public required List Consultants { get; set; } } \ No newline at end of file From 1d19804c32b6a3d6be7a3dc0875919042188a80f Mon Sep 17 00:00:00 2001 From: Magnus Gule Date: Tue, 17 Oct 2023 13:08:02 +0200 Subject: [PATCH 04/26] Adding Hotkey to be optional --- backend/Core/DomainModels/Department.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/Core/DomainModels/Department.cs b/backend/Core/DomainModels/Department.cs index 660ae9dc..2cb0d46f 100644 --- a/backend/Core/DomainModels/Department.cs +++ b/backend/Core/DomainModels/Department.cs @@ -8,7 +8,7 @@ public class Department [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public required string Id { get; set; } public required string Name { get; set; } - public int Hotkey { get; set; } + public int? Hotkey { get; set; } public required Organization Organization { get; set; } [JsonIgnore] public required List Consultants { get; set; } } \ No newline at end of file From c0d5b00abd5185708f5e4ecb596d5135d368ae27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B8ralt?= Date: Tue, 17 Oct 2023 13:23:19 +0200 Subject: [PATCH 05/26] remove org from project --- backend/Core/DomainModels/Project.cs | 1 - backend/Database/DatabaseContext/ApplicationContext.cs | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/backend/Core/DomainModels/Project.cs b/backend/Core/DomainModels/Project.cs index 7d73da8c..9e974f3f 100644 --- a/backend/Core/DomainModels/Project.cs +++ b/backend/Core/DomainModels/Project.cs @@ -8,7 +8,6 @@ public class Project public required int Id { get; set; } public required Customer Customer { get; set; } - public required Organization Organization { get; set; } public required ProjectState State { get; set; } diff --git a/backend/Database/DatabaseContext/ApplicationContext.cs b/backend/Database/DatabaseContext/ApplicationContext.cs index de097a4d..d42ae353 100644 --- a/backend/Database/DatabaseContext/ApplicationContext.cs +++ b/backend/Database/DatabaseContext/ApplicationContext.cs @@ -55,10 +55,10 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) .HasMany(p => p.Consultants) .WithMany(c => c.Projects) .UsingEntity( - r => r.HasOne(s => s.Consultant) + staffing => staffing.HasOne(s => s.Consultant) .WithMany(c => c.Staffings) .OnDelete(DeleteBehavior.ClientCascade), - l => l + staffing => staffing .HasOne(s => s.Project) .WithMany(c => c.Staffings) .OnDelete(DeleteBehavior.Cascade) From 612f02ffb293c967ab758c29bb1a5a4ba5c6eca9 Mon Sep 17 00:00:00 2001 From: Magnus Gule Date: Tue, 17 Oct 2023 13:26:01 +0200 Subject: [PATCH 06/26] Initial migrations on new org-based db-schema --- .../20231017112509_InitialCreate.Designer.cs | 520 ++++++++++++++++++ .../20231017112509_InitialCreate.cs | 371 +++++++++++++ .../ApplicationContextModelSnapshot.cs | 517 +++++++++++++++++ 3 files changed, 1408 insertions(+) create mode 100644 backend/Database/Migrations/20231017112509_InitialCreate.Designer.cs create mode 100644 backend/Database/Migrations/20231017112509_InitialCreate.cs create mode 100644 backend/Database/Migrations/ApplicationContextModelSnapshot.cs diff --git a/backend/Database/Migrations/20231017112509_InitialCreate.Designer.cs b/backend/Database/Migrations/20231017112509_InitialCreate.Designer.cs new file mode 100644 index 00000000..d6fff5b6 --- /dev/null +++ b/backend/Database/Migrations/20231017112509_InitialCreate.Designer.cs @@ -0,0 +1,520 @@ +// +using System; +using Database.DatabaseContext; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Database.Migrations +{ + [DbContext(typeof(ApplicationContext))] + [Migration("20231017112509_InitialCreate")] + partial class InitialCreate + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("CompetenceConsultant", b => + { + b.Property("CompetencesId") + .HasColumnType("nvarchar(450)"); + + b.Property("ConsultantId") + .HasColumnType("int"); + + b.HasKey("CompetencesId", "ConsultantId"); + + b.HasIndex("ConsultantId"); + + b.ToTable("CompetenceConsultant"); + }); + + modelBuilder.Entity("Core.DomainModels.Absence", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ExcludeFromBillRate") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Absence"); + }); + + modelBuilder.Entity("Core.DomainModels.Competence", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Competence"); + + b.HasData( + new + { + Id = "frontend", + Name = "Frontend" + }, + new + { + Id = "backend", + Name = "Backend" + }, + new + { + Id = "design", + Name = "Design" + }, + new + { + Id = "project-mgmt", + Name = "Project Management" + }); + }); + + modelBuilder.Entity("Core.DomainModels.Consultant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Degree") + .HasColumnType("nvarchar(max)"); + + b.Property("DepartmentId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("GraduationYear") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("DepartmentId"); + + b.ToTable("Consultant"); + + b.HasData( + new + { + Id = 1, + Degree = "Master", + DepartmentId = "trondheim", + Email = "j@variant.no", + GraduationYear = 2019, + Name = "Jonas", + StartDate = new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Core.DomainModels.Customer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Customer"); + }); + + modelBuilder.Entity("Core.DomainModels.Department", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("Hotkey") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Department"); + + b.HasData( + new + { + Id = "trondheim", + Name = "Trondheim", + OrganizationId = "variant-as" + }); + }); + + modelBuilder.Entity("Core.DomainModels.Organization", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Country") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("HasVacationInChristmas") + .HasColumnType("bit"); + + b.Property("HoursPerWorkday") + .HasColumnType("float"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("NumberOfVacationDaysInYear") + .HasColumnType("int"); + + b.Property("TagName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Organization"); + + b.HasData( + new + { + Id = "variant-as", + Country = "norway", + HasVacationInChristmas = true, + HoursPerWorkday = 7.5, + Name = "Variant AS", + NumberOfVacationDaysInYear = 25, + TagName = "variant-as" + }); + }); + + modelBuilder.Entity("Core.DomainModels.PlannedAbsence", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AbsenceId") + .HasColumnType("int"); + + b.Property("ConsultantId") + .HasColumnType("int"); + + b.Property("Hours") + .HasColumnType("float"); + + b.Property("WeekNumber") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("AbsenceId"); + + b.HasIndex("ConsultantId"); + + b.ToTable("PlannedAbsence"); + }); + + modelBuilder.Entity("Core.DomainModels.Project", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CustomerId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("State") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("CustomerId"); + + b.ToTable("Project"); + }); + + modelBuilder.Entity("Core.DomainModels.Staffing", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ConsultantId") + .HasColumnType("int"); + + b.Property("Hours") + .HasColumnType("float"); + + b.Property("ProjectId") + .HasColumnType("int"); + + b.Property("Week") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ConsultantId"); + + b.HasIndex("ProjectId"); + + b.ToTable("Staffing"); + }); + + modelBuilder.Entity("Core.DomainModels.Vacation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ConsultantId") + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("ConsultantId"); + + b.ToTable("Vacation"); + }); + + modelBuilder.Entity("CompetenceConsultant", b => + { + b.HasOne("Core.DomainModels.Competence", null) + .WithMany() + .HasForeignKey("CompetencesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Core.DomainModels.Consultant", null) + .WithMany() + .HasForeignKey("ConsultantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Core.DomainModels.Absence", b => + { + b.HasOne("Core.DomainModels.Organization", "Organization") + .WithMany("AbsenceTypes") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Core.DomainModels.Consultant", b => + { + b.HasOne("Core.DomainModels.Department", "Department") + .WithMany("Consultants") + .HasForeignKey("DepartmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Department"); + }); + + modelBuilder.Entity("Core.DomainModels.Customer", b => + { + b.HasOne("Core.DomainModels.Organization", "Organization") + .WithMany("Customers") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Core.DomainModels.Department", b => + { + b.HasOne("Core.DomainModels.Organization", "Organization") + .WithMany("Departments") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Core.DomainModels.PlannedAbsence", b => + { + b.HasOne("Core.DomainModels.Absence", "Absence") + .WithMany() + .HasForeignKey("AbsenceId") + .OnDelete(DeleteBehavior.ClientCascade) + .IsRequired(); + + b.HasOne("Core.DomainModels.Consultant", "Consultant") + .WithMany("PlannedAbsences") + .HasForeignKey("ConsultantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Absence"); + + b.Navigation("Consultant"); + }); + + modelBuilder.Entity("Core.DomainModels.Project", b => + { + b.HasOne("Core.DomainModels.Customer", "Customer") + .WithMany("Projects") + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Customer"); + }); + + modelBuilder.Entity("Core.DomainModels.Staffing", b => + { + b.HasOne("Core.DomainModels.Consultant", "Consultant") + .WithMany("Staffings") + .HasForeignKey("ConsultantId") + .OnDelete(DeleteBehavior.ClientCascade) + .IsRequired(); + + b.HasOne("Core.DomainModels.Project", "Project") + .WithMany("Staffings") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Consultant"); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("Core.DomainModels.Vacation", b => + { + b.HasOne("Core.DomainModels.Consultant", "Consultant") + .WithMany("Vacations") + .HasForeignKey("ConsultantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Consultant"); + }); + + modelBuilder.Entity("Core.DomainModels.Consultant", b => + { + b.Navigation("PlannedAbsences"); + + b.Navigation("Staffings"); + + b.Navigation("Vacations"); + }); + + modelBuilder.Entity("Core.DomainModels.Customer", b => + { + b.Navigation("Projects"); + }); + + modelBuilder.Entity("Core.DomainModels.Department", b => + { + b.Navigation("Consultants"); + }); + + modelBuilder.Entity("Core.DomainModels.Organization", b => + { + b.Navigation("AbsenceTypes"); + + b.Navigation("Customers"); + + b.Navigation("Departments"); + }); + + modelBuilder.Entity("Core.DomainModels.Project", b => + { + b.Navigation("Staffings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/backend/Database/Migrations/20231017112509_InitialCreate.cs b/backend/Database/Migrations/20231017112509_InitialCreate.cs new file mode 100644 index 00000000..4cae1586 --- /dev/null +++ b/backend/Database/Migrations/20231017112509_InitialCreate.cs @@ -0,0 +1,371 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace Database.Migrations +{ + /// + public partial class InitialCreate : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Competence", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(max)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Competence", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Organization", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(max)", nullable: false), + TagName = table.Column(type: "nvarchar(max)", nullable: false), + Country = table.Column(type: "nvarchar(max)", nullable: false), + NumberOfVacationDaysInYear = table.Column(type: "int", nullable: false), + HasVacationInChristmas = table.Column(type: "bit", nullable: false), + HoursPerWorkday = table.Column(type: "float", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Organization", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Absence", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Name = table.Column(type: "nvarchar(max)", nullable: false), + ExcludeFromBillRate = table.Column(type: "bit", nullable: false), + OrganizationId = table.Column(type: "nvarchar(450)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Absence", x => x.Id); + table.ForeignKey( + name: "FK_Absence_Organization_OrganizationId", + column: x => x.OrganizationId, + principalTable: "Organization", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Customer", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Name = table.Column(type: "nvarchar(max)", nullable: false), + OrganizationId = table.Column(type: "nvarchar(450)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Customer", x => x.Id); + table.ForeignKey( + name: "FK_Customer_Organization_OrganizationId", + column: x => x.OrganizationId, + principalTable: "Organization", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Department", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(max)", nullable: false), + Hotkey = table.Column(type: "int", nullable: true), + OrganizationId = table.Column(type: "nvarchar(450)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Department", x => x.Id); + table.ForeignKey( + name: "FK_Department_Organization_OrganizationId", + column: x => x.OrganizationId, + principalTable: "Organization", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Project", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + CustomerId = table.Column(type: "int", nullable: false), + State = table.Column(type: "nvarchar(max)", nullable: false), + Name = table.Column(type: "nvarchar(max)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Project", x => x.Id); + table.ForeignKey( + name: "FK_Project_Customer_CustomerId", + column: x => x.CustomerId, + principalTable: "Customer", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Consultant", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Name = table.Column(type: "nvarchar(max)", nullable: false), + Email = table.Column(type: "nvarchar(max)", nullable: false), + StartDate = table.Column(type: "datetime2", nullable: true), + EndDate = table.Column(type: "datetime2", nullable: true), + DepartmentId = table.Column(type: "nvarchar(450)", nullable: false), + Degree = table.Column(type: "nvarchar(max)", nullable: true), + GraduationYear = table.Column(type: "int", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Consultant", x => x.Id); + table.ForeignKey( + name: "FK_Consultant_Department_DepartmentId", + column: x => x.DepartmentId, + principalTable: "Department", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "CompetenceConsultant", + columns: table => new + { + CompetencesId = table.Column(type: "nvarchar(450)", nullable: false), + ConsultantId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_CompetenceConsultant", x => new { x.CompetencesId, x.ConsultantId }); + table.ForeignKey( + name: "FK_CompetenceConsultant_Competence_CompetencesId", + column: x => x.CompetencesId, + principalTable: "Competence", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_CompetenceConsultant_Consultant_ConsultantId", + column: x => x.ConsultantId, + principalTable: "Consultant", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PlannedAbsence", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + AbsenceId = table.Column(type: "int", nullable: false), + ConsultantId = table.Column(type: "int", nullable: false), + Year = table.Column(type: "int", nullable: false), + WeekNumber = table.Column(type: "int", nullable: false), + Hours = table.Column(type: "float", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PlannedAbsence", x => x.Id); + table.ForeignKey( + name: "FK_PlannedAbsence_Absence_AbsenceId", + column: x => x.AbsenceId, + principalTable: "Absence", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_PlannedAbsence_Consultant_ConsultantId", + column: x => x.ConsultantId, + principalTable: "Consultant", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Staffing", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ProjectId = table.Column(type: "int", nullable: false), + ConsultantId = table.Column(type: "int", nullable: false), + Year = table.Column(type: "int", nullable: false), + Week = table.Column(type: "int", nullable: false), + Hours = table.Column(type: "float", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Staffing", x => x.Id); + table.ForeignKey( + name: "FK_Staffing_Consultant_ConsultantId", + column: x => x.ConsultantId, + principalTable: "Consultant", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_Staffing_Project_ProjectId", + column: x => x.ProjectId, + principalTable: "Project", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Vacation", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ConsultantId = table.Column(type: "int", nullable: false), + Date = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Vacation", x => x.Id); + table.ForeignKey( + name: "FK_Vacation_Consultant_ConsultantId", + column: x => x.ConsultantId, + principalTable: "Consultant", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.InsertData( + table: "Competence", + columns: new[] { "Id", "Name" }, + values: new object[,] + { + { "backend", "Backend" }, + { "design", "Design" }, + { "frontend", "Frontend" }, + { "project-mgmt", "Project Management" } + }); + + migrationBuilder.InsertData( + table: "Organization", + columns: new[] { "Id", "Country", "HasVacationInChristmas", "HoursPerWorkday", "Name", "NumberOfVacationDaysInYear", "TagName" }, + values: new object[] { "variant-as", "norway", true, 7.5, "Variant AS", 25, "variant-as" }); + + migrationBuilder.InsertData( + table: "Department", + columns: new[] { "Id", "Hotkey", "Name", "OrganizationId" }, + values: new object[] { "trondheim", null, "Trondheim", "variant-as" }); + + migrationBuilder.InsertData( + table: "Consultant", + columns: new[] { "Id", "Degree", "DepartmentId", "Email", "EndDate", "GraduationYear", "Name", "StartDate" }, + values: new object[] { 1, "Master", "trondheim", "j@variant.no", null, 2019, "Jonas", new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) }); + + migrationBuilder.CreateIndex( + name: "IX_Absence_OrganizationId", + table: "Absence", + column: "OrganizationId"); + + migrationBuilder.CreateIndex( + name: "IX_CompetenceConsultant_ConsultantId", + table: "CompetenceConsultant", + column: "ConsultantId"); + + migrationBuilder.CreateIndex( + name: "IX_Consultant_DepartmentId", + table: "Consultant", + column: "DepartmentId"); + + migrationBuilder.CreateIndex( + name: "IX_Customer_OrganizationId", + table: "Customer", + column: "OrganizationId"); + + migrationBuilder.CreateIndex( + name: "IX_Department_OrganizationId", + table: "Department", + column: "OrganizationId"); + + migrationBuilder.CreateIndex( + name: "IX_PlannedAbsence_AbsenceId", + table: "PlannedAbsence", + column: "AbsenceId"); + + migrationBuilder.CreateIndex( + name: "IX_PlannedAbsence_ConsultantId", + table: "PlannedAbsence", + column: "ConsultantId"); + + migrationBuilder.CreateIndex( + name: "IX_Project_CustomerId", + table: "Project", + column: "CustomerId"); + + migrationBuilder.CreateIndex( + name: "IX_Staffing_ConsultantId", + table: "Staffing", + column: "ConsultantId"); + + migrationBuilder.CreateIndex( + name: "IX_Staffing_ProjectId", + table: "Staffing", + column: "ProjectId"); + + migrationBuilder.CreateIndex( + name: "IX_Vacation_ConsultantId", + table: "Vacation", + column: "ConsultantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "CompetenceConsultant"); + + migrationBuilder.DropTable( + name: "PlannedAbsence"); + + migrationBuilder.DropTable( + name: "Staffing"); + + migrationBuilder.DropTable( + name: "Vacation"); + + migrationBuilder.DropTable( + name: "Competence"); + + migrationBuilder.DropTable( + name: "Absence"); + + migrationBuilder.DropTable( + name: "Project"); + + migrationBuilder.DropTable( + name: "Consultant"); + + migrationBuilder.DropTable( + name: "Customer"); + + migrationBuilder.DropTable( + name: "Department"); + + migrationBuilder.DropTable( + name: "Organization"); + } + } +} diff --git a/backend/Database/Migrations/ApplicationContextModelSnapshot.cs b/backend/Database/Migrations/ApplicationContextModelSnapshot.cs new file mode 100644 index 00000000..dca67932 --- /dev/null +++ b/backend/Database/Migrations/ApplicationContextModelSnapshot.cs @@ -0,0 +1,517 @@ +// +using System; +using Database.DatabaseContext; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Database.Migrations +{ + [DbContext(typeof(ApplicationContext))] + partial class ApplicationContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("CompetenceConsultant", b => + { + b.Property("CompetencesId") + .HasColumnType("nvarchar(450)"); + + b.Property("ConsultantId") + .HasColumnType("int"); + + b.HasKey("CompetencesId", "ConsultantId"); + + b.HasIndex("ConsultantId"); + + b.ToTable("CompetenceConsultant"); + }); + + modelBuilder.Entity("Core.DomainModels.Absence", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ExcludeFromBillRate") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Absence"); + }); + + modelBuilder.Entity("Core.DomainModels.Competence", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Competence"); + + b.HasData( + new + { + Id = "frontend", + Name = "Frontend" + }, + new + { + Id = "backend", + Name = "Backend" + }, + new + { + Id = "design", + Name = "Design" + }, + new + { + Id = "project-mgmt", + Name = "Project Management" + }); + }); + + modelBuilder.Entity("Core.DomainModels.Consultant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Degree") + .HasColumnType("nvarchar(max)"); + + b.Property("DepartmentId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("GraduationYear") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("DepartmentId"); + + b.ToTable("Consultant"); + + b.HasData( + new + { + Id = 1, + Degree = "Master", + DepartmentId = "trondheim", + Email = "j@variant.no", + GraduationYear = 2019, + Name = "Jonas", + StartDate = new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Core.DomainModels.Customer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Customer"); + }); + + modelBuilder.Entity("Core.DomainModels.Department", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("Hotkey") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Department"); + + b.HasData( + new + { + Id = "trondheim", + Name = "Trondheim", + OrganizationId = "variant-as" + }); + }); + + modelBuilder.Entity("Core.DomainModels.Organization", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Country") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("HasVacationInChristmas") + .HasColumnType("bit"); + + b.Property("HoursPerWorkday") + .HasColumnType("float"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("NumberOfVacationDaysInYear") + .HasColumnType("int"); + + b.Property("TagName") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Organization"); + + b.HasData( + new + { + Id = "variant-as", + Country = "norway", + HasVacationInChristmas = true, + HoursPerWorkday = 7.5, + Name = "Variant AS", + NumberOfVacationDaysInYear = 25, + TagName = "variant-as" + }); + }); + + modelBuilder.Entity("Core.DomainModels.PlannedAbsence", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AbsenceId") + .HasColumnType("int"); + + b.Property("ConsultantId") + .HasColumnType("int"); + + b.Property("Hours") + .HasColumnType("float"); + + b.Property("WeekNumber") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("AbsenceId"); + + b.HasIndex("ConsultantId"); + + b.ToTable("PlannedAbsence"); + }); + + modelBuilder.Entity("Core.DomainModels.Project", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CustomerId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("State") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("CustomerId"); + + b.ToTable("Project"); + }); + + modelBuilder.Entity("Core.DomainModels.Staffing", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ConsultantId") + .HasColumnType("int"); + + b.Property("Hours") + .HasColumnType("float"); + + b.Property("ProjectId") + .HasColumnType("int"); + + b.Property("Week") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ConsultantId"); + + b.HasIndex("ProjectId"); + + b.ToTable("Staffing"); + }); + + modelBuilder.Entity("Core.DomainModels.Vacation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ConsultantId") + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("ConsultantId"); + + b.ToTable("Vacation"); + }); + + modelBuilder.Entity("CompetenceConsultant", b => + { + b.HasOne("Core.DomainModels.Competence", null) + .WithMany() + .HasForeignKey("CompetencesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Core.DomainModels.Consultant", null) + .WithMany() + .HasForeignKey("ConsultantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Core.DomainModels.Absence", b => + { + b.HasOne("Core.DomainModels.Organization", "Organization") + .WithMany("AbsenceTypes") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Core.DomainModels.Consultant", b => + { + b.HasOne("Core.DomainModels.Department", "Department") + .WithMany("Consultants") + .HasForeignKey("DepartmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Department"); + }); + + modelBuilder.Entity("Core.DomainModels.Customer", b => + { + b.HasOne("Core.DomainModels.Organization", "Organization") + .WithMany("Customers") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Core.DomainModels.Department", b => + { + b.HasOne("Core.DomainModels.Organization", "Organization") + .WithMany("Departments") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Core.DomainModels.PlannedAbsence", b => + { + b.HasOne("Core.DomainModels.Absence", "Absence") + .WithMany() + .HasForeignKey("AbsenceId") + .OnDelete(DeleteBehavior.ClientCascade) + .IsRequired(); + + b.HasOne("Core.DomainModels.Consultant", "Consultant") + .WithMany("PlannedAbsences") + .HasForeignKey("ConsultantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Absence"); + + b.Navigation("Consultant"); + }); + + modelBuilder.Entity("Core.DomainModels.Project", b => + { + b.HasOne("Core.DomainModels.Customer", "Customer") + .WithMany("Projects") + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Customer"); + }); + + modelBuilder.Entity("Core.DomainModels.Staffing", b => + { + b.HasOne("Core.DomainModels.Consultant", "Consultant") + .WithMany("Staffings") + .HasForeignKey("ConsultantId") + .OnDelete(DeleteBehavior.ClientCascade) + .IsRequired(); + + b.HasOne("Core.DomainModels.Project", "Project") + .WithMany("Staffings") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Consultant"); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("Core.DomainModels.Vacation", b => + { + b.HasOne("Core.DomainModels.Consultant", "Consultant") + .WithMany("Vacations") + .HasForeignKey("ConsultantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Consultant"); + }); + + modelBuilder.Entity("Core.DomainModels.Consultant", b => + { + b.Navigation("PlannedAbsences"); + + b.Navigation("Staffings"); + + b.Navigation("Vacations"); + }); + + modelBuilder.Entity("Core.DomainModels.Customer", b => + { + b.Navigation("Projects"); + }); + + modelBuilder.Entity("Core.DomainModels.Department", b => + { + b.Navigation("Consultants"); + }); + + modelBuilder.Entity("Core.DomainModels.Organization", b => + { + b.Navigation("AbsenceTypes"); + + b.Navigation("Customers"); + + b.Navigation("Departments"); + }); + + modelBuilder.Entity("Core.DomainModels.Project", b => + { + b.Navigation("Staffings"); + }); +#pragma warning restore 612, 618 + } + } +} From 75e4cf47e7992ab1926c3a44b5e6d2d5d8751a69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B8ralt?= Date: Tue, 17 Oct 2023 14:59:21 +0200 Subject: [PATCH 07/26] redo migrations, add auth service wip --- .../Authorization/AuthorizationController.cs | 27 + backend/Core/DomainModels/Organization.cs | 9 +- .../DatabaseContext/ApplicationContext.cs | 8 +- .../20231017112509_InitialCreate.Designer.cs | 520 ------------------ .../20231017112509_InitialCreate.cs | 371 ------------- .../ApplicationContextModelSnapshot.cs | 517 ----------------- 6 files changed, 36 insertions(+), 1416 deletions(-) create mode 100644 backend/Api/Authorization/AuthorizationController.cs delete mode 100644 backend/Database/Migrations/20231017112509_InitialCreate.Designer.cs delete mode 100644 backend/Database/Migrations/20231017112509_InitialCreate.cs delete mode 100644 backend/Database/Migrations/ApplicationContextModelSnapshot.cs diff --git a/backend/Api/Authorization/AuthorizationController.cs b/backend/Api/Authorization/AuthorizationController.cs new file mode 100644 index 00000000..66e54fcf --- /dev/null +++ b/backend/Api/Authorization/AuthorizationController.cs @@ -0,0 +1,27 @@ +using Database.DatabaseContext; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace Api.Authorization; + +[Route("v0/authorization")] +[ApiController] +public class AuthorizationController : ControllerBase +{ + [HttpGet] + public ActionResult> Get(ApplicationContext context) + { + var uname = HttpContext.User.Claims.Single(c => c.Type == "preferred_username").Value; + + var orgs = context.Organization + .Include(org => org.Departments) + .ThenInclude(dept => dept.Consultants) + .Where(org => org.Departments + .Count(dept => dept.Consultants.Select(c => c.Email).Contains(uname)) > 0) + .Select(organization => + new OrganizationReadModel(organization.Id, organization.UrlKey, organization.Name)) + .ToList(); + + return Ok(orgs); + } +} \ No newline at end of file diff --git a/backend/Core/DomainModels/Organization.cs b/backend/Core/DomainModels/Organization.cs index f9fd7f32..8b7de43b 100644 --- a/backend/Core/DomainModels/Organization.cs +++ b/backend/Core/DomainModels/Organization.cs @@ -1,19 +1,20 @@ using System.Text.Json.Serialization; + namespace Core.DomainModels; public class Organization { public required string Id { get; set; } // guid ? Decide What to set here first => public required string Name { get; set; } - public required string TagName { get; set; } // "variant-as", "variant-sverige" + public required string UrlKey { get; set; } // "variant-as", "variant-sverige" public required string Country { get; set; } public required int NumberOfVacationDaysInYear { get; set; } public required bool HasVacationInChristmas { get; set; } public required double HoursPerWorkday { get; set; } - + [JsonIgnore] public List Departments { get; set; } - + public required List Customers { get; set; } public List AbsenceTypes { get; set; } -} +} \ No newline at end of file diff --git a/backend/Database/DatabaseContext/ApplicationContext.cs b/backend/Database/DatabaseContext/ApplicationContext.cs index d42ae353..b730a378 100644 --- a/backend/Database/DatabaseContext/ApplicationContext.cs +++ b/backend/Database/DatabaseContext/ApplicationContext.cs @@ -117,11 +117,11 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity() .HasData(new { - Id = "variant-as", - Name = "Variant AS", - TagName = "variant-as", + Id = "variant-as", + Name = "Variant AS", + UrlKey = "variant-as", Country = "norway", - HoursPerWorkday = 7.5, + HoursPerWorkday = 7.5, HasVacationInChristmas = true, NumberOfVacationDaysInYear = 25 }); diff --git a/backend/Database/Migrations/20231017112509_InitialCreate.Designer.cs b/backend/Database/Migrations/20231017112509_InitialCreate.Designer.cs deleted file mode 100644 index d6fff5b6..00000000 --- a/backend/Database/Migrations/20231017112509_InitialCreate.Designer.cs +++ /dev/null @@ -1,520 +0,0 @@ -// -using System; -using Database.DatabaseContext; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Migrations; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Database.Migrations -{ - [DbContext(typeof(ApplicationContext))] - [Migration("20231017112509_InitialCreate")] - partial class InitialCreate - { - /// - protected override void BuildTargetModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.10") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("CompetenceConsultant", b => - { - b.Property("CompetencesId") - .HasColumnType("nvarchar(450)"); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.HasKey("CompetencesId", "ConsultantId"); - - b.HasIndex("ConsultantId"); - - b.ToTable("CompetenceConsultant"); - }); - - modelBuilder.Entity("Core.DomainModels.Absence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ExcludeFromBillRate") - .HasColumnType("bit"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Absence"); - }); - - modelBuilder.Entity("Core.DomainModels.Competence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Competence"); - - b.HasData( - new - { - Id = "frontend", - Name = "Frontend" - }, - new - { - Id = "backend", - Name = "Backend" - }, - new - { - Id = "design", - Name = "Design" - }, - new - { - Id = "project-mgmt", - Name = "Project Management" - }); - }); - - modelBuilder.Entity("Core.DomainModels.Consultant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Degree") - .HasColumnType("nvarchar(max)"); - - b.Property("DepartmentId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Email") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("EndDate") - .HasColumnType("datetime2"); - - b.Property("GraduationYear") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StartDate") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("DepartmentId"); - - b.ToTable("Consultant"); - - b.HasData( - new - { - Id = 1, - Degree = "Master", - DepartmentId = "trondheim", - Email = "j@variant.no", - GraduationYear = 2019, - Name = "Jonas", - StartDate = new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) - }); - }); - - modelBuilder.Entity("Core.DomainModels.Customer", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Customer"); - }); - - modelBuilder.Entity("Core.DomainModels.Department", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("Hotkey") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Department"); - - b.HasData( - new - { - Id = "trondheim", - Name = "Trondheim", - OrganizationId = "variant-as" - }); - }); - - modelBuilder.Entity("Core.DomainModels.Organization", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("Country") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("HasVacationInChristmas") - .HasColumnType("bit"); - - b.Property("HoursPerWorkday") - .HasColumnType("float"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("NumberOfVacationDaysInYear") - .HasColumnType("int"); - - b.Property("TagName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Organization"); - - b.HasData( - new - { - Id = "variant-as", - Country = "norway", - HasVacationInChristmas = true, - HoursPerWorkday = 7.5, - Name = "Variant AS", - NumberOfVacationDaysInYear = 25, - TagName = "variant-as" - }); - }); - - modelBuilder.Entity("Core.DomainModels.PlannedAbsence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("AbsenceId") - .HasColumnType("int"); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Hours") - .HasColumnType("float"); - - b.Property("WeekNumber") - .HasColumnType("int"); - - b.Property("Year") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("AbsenceId"); - - b.HasIndex("ConsultantId"); - - b.ToTable("PlannedAbsence"); - }); - - modelBuilder.Entity("Core.DomainModels.Project", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("CustomerId") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("State") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("CustomerId"); - - b.ToTable("Project"); - }); - - modelBuilder.Entity("Core.DomainModels.Staffing", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Hours") - .HasColumnType("float"); - - b.Property("ProjectId") - .HasColumnType("int"); - - b.Property("Week") - .HasColumnType("int"); - - b.Property("Year") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ConsultantId"); - - b.HasIndex("ProjectId"); - - b.ToTable("Staffing"); - }); - - modelBuilder.Entity("Core.DomainModels.Vacation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Date") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("ConsultantId"); - - b.ToTable("Vacation"); - }); - - modelBuilder.Entity("CompetenceConsultant", b => - { - b.HasOne("Core.DomainModels.Competence", null) - .WithMany() - .HasForeignKey("CompetencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Core.DomainModels.Consultant", null) - .WithMany() - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Core.DomainModels.Absence", b => - { - b.HasOne("Core.DomainModels.Organization", "Organization") - .WithMany("AbsenceTypes") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("Core.DomainModels.Consultant", b => - { - b.HasOne("Core.DomainModels.Department", "Department") - .WithMany("Consultants") - .HasForeignKey("DepartmentId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Department"); - }); - - modelBuilder.Entity("Core.DomainModels.Customer", b => - { - b.HasOne("Core.DomainModels.Organization", "Organization") - .WithMany("Customers") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("Core.DomainModels.Department", b => - { - b.HasOne("Core.DomainModels.Organization", "Organization") - .WithMany("Departments") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("Core.DomainModels.PlannedAbsence", b => - { - b.HasOne("Core.DomainModels.Absence", "Absence") - .WithMany() - .HasForeignKey("AbsenceId") - .OnDelete(DeleteBehavior.ClientCascade) - .IsRequired(); - - b.HasOne("Core.DomainModels.Consultant", "Consultant") - .WithMany("PlannedAbsences") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Absence"); - - b.Navigation("Consultant"); - }); - - modelBuilder.Entity("Core.DomainModels.Project", b => - { - b.HasOne("Core.DomainModels.Customer", "Customer") - .WithMany("Projects") - .HasForeignKey("CustomerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Customer"); - }); - - modelBuilder.Entity("Core.DomainModels.Staffing", b => - { - b.HasOne("Core.DomainModels.Consultant", "Consultant") - .WithMany("Staffings") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.ClientCascade) - .IsRequired(); - - b.HasOne("Core.DomainModels.Project", "Project") - .WithMany("Staffings") - .HasForeignKey("ProjectId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Consultant"); - - b.Navigation("Project"); - }); - - modelBuilder.Entity("Core.DomainModels.Vacation", b => - { - b.HasOne("Core.DomainModels.Consultant", "Consultant") - .WithMany("Vacations") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Consultant"); - }); - - modelBuilder.Entity("Core.DomainModels.Consultant", b => - { - b.Navigation("PlannedAbsences"); - - b.Navigation("Staffings"); - - b.Navigation("Vacations"); - }); - - modelBuilder.Entity("Core.DomainModels.Customer", b => - { - b.Navigation("Projects"); - }); - - modelBuilder.Entity("Core.DomainModels.Department", b => - { - b.Navigation("Consultants"); - }); - - modelBuilder.Entity("Core.DomainModels.Organization", b => - { - b.Navigation("AbsenceTypes"); - - b.Navigation("Customers"); - - b.Navigation("Departments"); - }); - - modelBuilder.Entity("Core.DomainModels.Project", b => - { - b.Navigation("Staffings"); - }); -#pragma warning restore 612, 618 - } - } -} diff --git a/backend/Database/Migrations/20231017112509_InitialCreate.cs b/backend/Database/Migrations/20231017112509_InitialCreate.cs deleted file mode 100644 index 4cae1586..00000000 --- a/backend/Database/Migrations/20231017112509_InitialCreate.cs +++ /dev/null @@ -1,371 +0,0 @@ -using System; -using Microsoft.EntityFrameworkCore.Migrations; - -#nullable disable - -#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional - -namespace Database.Migrations -{ - /// - public partial class InitialCreate : Migration - { - /// - protected override void Up(MigrationBuilder migrationBuilder) - { - migrationBuilder.CreateTable( - name: "Competence", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - Name = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Competence", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Organization", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - Name = table.Column(type: "nvarchar(max)", nullable: false), - TagName = table.Column(type: "nvarchar(max)", nullable: false), - Country = table.Column(type: "nvarchar(max)", nullable: false), - NumberOfVacationDaysInYear = table.Column(type: "int", nullable: false), - HasVacationInChristmas = table.Column(type: "bit", nullable: false), - HoursPerWorkday = table.Column(type: "float", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Organization", x => x.Id); - }); - - migrationBuilder.CreateTable( - name: "Absence", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: false), - ExcludeFromBillRate = table.Column(type: "bit", nullable: false), - OrganizationId = table.Column(type: "nvarchar(450)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Absence", x => x.Id); - table.ForeignKey( - name: "FK_Absence_Organization_OrganizationId", - column: x => x.OrganizationId, - principalTable: "Organization", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Customer", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: false), - OrganizationId = table.Column(type: "nvarchar(450)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Customer", x => x.Id); - table.ForeignKey( - name: "FK_Customer_Organization_OrganizationId", - column: x => x.OrganizationId, - principalTable: "Organization", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Department", - columns: table => new - { - Id = table.Column(type: "nvarchar(450)", nullable: false), - Name = table.Column(type: "nvarchar(max)", nullable: false), - Hotkey = table.Column(type: "int", nullable: true), - OrganizationId = table.Column(type: "nvarchar(450)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Department", x => x.Id); - table.ForeignKey( - name: "FK_Department_Organization_OrganizationId", - column: x => x.OrganizationId, - principalTable: "Organization", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Project", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - CustomerId = table.Column(type: "int", nullable: false), - State = table.Column(type: "nvarchar(max)", nullable: false), - Name = table.Column(type: "nvarchar(max)", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Project", x => x.Id); - table.ForeignKey( - name: "FK_Project_Customer_CustomerId", - column: x => x.CustomerId, - principalTable: "Customer", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Consultant", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - Name = table.Column(type: "nvarchar(max)", nullable: false), - Email = table.Column(type: "nvarchar(max)", nullable: false), - StartDate = table.Column(type: "datetime2", nullable: true), - EndDate = table.Column(type: "datetime2", nullable: true), - DepartmentId = table.Column(type: "nvarchar(450)", nullable: false), - Degree = table.Column(type: "nvarchar(max)", nullable: true), - GraduationYear = table.Column(type: "int", nullable: true) - }, - constraints: table => - { - table.PrimaryKey("PK_Consultant", x => x.Id); - table.ForeignKey( - name: "FK_Consultant_Department_DepartmentId", - column: x => x.DepartmentId, - principalTable: "Department", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "CompetenceConsultant", - columns: table => new - { - CompetencesId = table.Column(type: "nvarchar(450)", nullable: false), - ConsultantId = table.Column(type: "int", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_CompetenceConsultant", x => new { x.CompetencesId, x.ConsultantId }); - table.ForeignKey( - name: "FK_CompetenceConsultant_Competence_CompetencesId", - column: x => x.CompetencesId, - principalTable: "Competence", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - table.ForeignKey( - name: "FK_CompetenceConsultant_Consultant_ConsultantId", - column: x => x.ConsultantId, - principalTable: "Consultant", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "PlannedAbsence", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - AbsenceId = table.Column(type: "int", nullable: false), - ConsultantId = table.Column(type: "int", nullable: false), - Year = table.Column(type: "int", nullable: false), - WeekNumber = table.Column(type: "int", nullable: false), - Hours = table.Column(type: "float", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_PlannedAbsence", x => x.Id); - table.ForeignKey( - name: "FK_PlannedAbsence_Absence_AbsenceId", - column: x => x.AbsenceId, - principalTable: "Absence", - principalColumn: "Id"); - table.ForeignKey( - name: "FK_PlannedAbsence_Consultant_ConsultantId", - column: x => x.ConsultantId, - principalTable: "Consultant", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Staffing", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ProjectId = table.Column(type: "int", nullable: false), - ConsultantId = table.Column(type: "int", nullable: false), - Year = table.Column(type: "int", nullable: false), - Week = table.Column(type: "int", nullable: false), - Hours = table.Column(type: "float", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Staffing", x => x.Id); - table.ForeignKey( - name: "FK_Staffing_Consultant_ConsultantId", - column: x => x.ConsultantId, - principalTable: "Consultant", - principalColumn: "Id"); - table.ForeignKey( - name: "FK_Staffing_Project_ProjectId", - column: x => x.ProjectId, - principalTable: "Project", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.CreateTable( - name: "Vacation", - columns: table => new - { - Id = table.Column(type: "int", nullable: false) - .Annotation("SqlServer:Identity", "1, 1"), - ConsultantId = table.Column(type: "int", nullable: false), - Date = table.Column(type: "datetime2", nullable: false) - }, - constraints: table => - { - table.PrimaryKey("PK_Vacation", x => x.Id); - table.ForeignKey( - name: "FK_Vacation_Consultant_ConsultantId", - column: x => x.ConsultantId, - principalTable: "Consultant", - principalColumn: "Id", - onDelete: ReferentialAction.Cascade); - }); - - migrationBuilder.InsertData( - table: "Competence", - columns: new[] { "Id", "Name" }, - values: new object[,] - { - { "backend", "Backend" }, - { "design", "Design" }, - { "frontend", "Frontend" }, - { "project-mgmt", "Project Management" } - }); - - migrationBuilder.InsertData( - table: "Organization", - columns: new[] { "Id", "Country", "HasVacationInChristmas", "HoursPerWorkday", "Name", "NumberOfVacationDaysInYear", "TagName" }, - values: new object[] { "variant-as", "norway", true, 7.5, "Variant AS", 25, "variant-as" }); - - migrationBuilder.InsertData( - table: "Department", - columns: new[] { "Id", "Hotkey", "Name", "OrganizationId" }, - values: new object[] { "trondheim", null, "Trondheim", "variant-as" }); - - migrationBuilder.InsertData( - table: "Consultant", - columns: new[] { "Id", "Degree", "DepartmentId", "Email", "EndDate", "GraduationYear", "Name", "StartDate" }, - values: new object[] { 1, "Master", "trondheim", "j@variant.no", null, 2019, "Jonas", new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) }); - - migrationBuilder.CreateIndex( - name: "IX_Absence_OrganizationId", - table: "Absence", - column: "OrganizationId"); - - migrationBuilder.CreateIndex( - name: "IX_CompetenceConsultant_ConsultantId", - table: "CompetenceConsultant", - column: "ConsultantId"); - - migrationBuilder.CreateIndex( - name: "IX_Consultant_DepartmentId", - table: "Consultant", - column: "DepartmentId"); - - migrationBuilder.CreateIndex( - name: "IX_Customer_OrganizationId", - table: "Customer", - column: "OrganizationId"); - - migrationBuilder.CreateIndex( - name: "IX_Department_OrganizationId", - table: "Department", - column: "OrganizationId"); - - migrationBuilder.CreateIndex( - name: "IX_PlannedAbsence_AbsenceId", - table: "PlannedAbsence", - column: "AbsenceId"); - - migrationBuilder.CreateIndex( - name: "IX_PlannedAbsence_ConsultantId", - table: "PlannedAbsence", - column: "ConsultantId"); - - migrationBuilder.CreateIndex( - name: "IX_Project_CustomerId", - table: "Project", - column: "CustomerId"); - - migrationBuilder.CreateIndex( - name: "IX_Staffing_ConsultantId", - table: "Staffing", - column: "ConsultantId"); - - migrationBuilder.CreateIndex( - name: "IX_Staffing_ProjectId", - table: "Staffing", - column: "ProjectId"); - - migrationBuilder.CreateIndex( - name: "IX_Vacation_ConsultantId", - table: "Vacation", - column: "ConsultantId"); - } - - /// - protected override void Down(MigrationBuilder migrationBuilder) - { - migrationBuilder.DropTable( - name: "CompetenceConsultant"); - - migrationBuilder.DropTable( - name: "PlannedAbsence"); - - migrationBuilder.DropTable( - name: "Staffing"); - - migrationBuilder.DropTable( - name: "Vacation"); - - migrationBuilder.DropTable( - name: "Competence"); - - migrationBuilder.DropTable( - name: "Absence"); - - migrationBuilder.DropTable( - name: "Project"); - - migrationBuilder.DropTable( - name: "Consultant"); - - migrationBuilder.DropTable( - name: "Customer"); - - migrationBuilder.DropTable( - name: "Department"); - - migrationBuilder.DropTable( - name: "Organization"); - } - } -} diff --git a/backend/Database/Migrations/ApplicationContextModelSnapshot.cs b/backend/Database/Migrations/ApplicationContextModelSnapshot.cs deleted file mode 100644 index dca67932..00000000 --- a/backend/Database/Migrations/ApplicationContextModelSnapshot.cs +++ /dev/null @@ -1,517 +0,0 @@ -// -using System; -using Database.DatabaseContext; -using Microsoft.EntityFrameworkCore; -using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Storage.ValueConversion; - -#nullable disable - -namespace Database.Migrations -{ - [DbContext(typeof(ApplicationContext))] - partial class ApplicationContextModelSnapshot : ModelSnapshot - { - protected override void BuildModel(ModelBuilder modelBuilder) - { -#pragma warning disable 612, 618 - modelBuilder - .HasAnnotation("ProductVersion", "7.0.10") - .HasAnnotation("Relational:MaxIdentifierLength", 128); - - SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); - - modelBuilder.Entity("CompetenceConsultant", b => - { - b.Property("CompetencesId") - .HasColumnType("nvarchar(450)"); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.HasKey("CompetencesId", "ConsultantId"); - - b.HasIndex("ConsultantId"); - - b.ToTable("CompetenceConsultant"); - }); - - modelBuilder.Entity("Core.DomainModels.Absence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ExcludeFromBillRate") - .HasColumnType("bit"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Absence"); - }); - - modelBuilder.Entity("Core.DomainModels.Competence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Competence"); - - b.HasData( - new - { - Id = "frontend", - Name = "Frontend" - }, - new - { - Id = "backend", - Name = "Backend" - }, - new - { - Id = "design", - Name = "Design" - }, - new - { - Id = "project-mgmt", - Name = "Project Management" - }); - }); - - modelBuilder.Entity("Core.DomainModels.Consultant", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Degree") - .HasColumnType("nvarchar(max)"); - - b.Property("DepartmentId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.Property("Email") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("EndDate") - .HasColumnType("datetime2"); - - b.Property("GraduationYear") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("StartDate") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("DepartmentId"); - - b.ToTable("Consultant"); - - b.HasData( - new - { - Id = 1, - Degree = "Master", - DepartmentId = "trondheim", - Email = "j@variant.no", - GraduationYear = 2019, - Name = "Jonas", - StartDate = new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) - }); - }); - - modelBuilder.Entity("Core.DomainModels.Customer", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Customer"); - }); - - modelBuilder.Entity("Core.DomainModels.Department", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("nvarchar(450)"); - - b.Property("Hotkey") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("OrganizationId") - .IsRequired() - .HasColumnType("nvarchar(450)"); - - b.HasKey("Id"); - - b.HasIndex("OrganizationId"); - - b.ToTable("Department"); - - b.HasData( - new - { - Id = "trondheim", - Name = "Trondheim", - OrganizationId = "variant-as" - }); - }); - - modelBuilder.Entity("Core.DomainModels.Organization", b => - { - b.Property("Id") - .HasColumnType("nvarchar(450)"); - - b.Property("Country") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("HasVacationInChristmas") - .HasColumnType("bit"); - - b.Property("HoursPerWorkday") - .HasColumnType("float"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("NumberOfVacationDaysInYear") - .HasColumnType("int"); - - b.Property("TagName") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.ToTable("Organization"); - - b.HasData( - new - { - Id = "variant-as", - Country = "norway", - HasVacationInChristmas = true, - HoursPerWorkday = 7.5, - Name = "Variant AS", - NumberOfVacationDaysInYear = 25, - TagName = "variant-as" - }); - }); - - modelBuilder.Entity("Core.DomainModels.PlannedAbsence", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("AbsenceId") - .HasColumnType("int"); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Hours") - .HasColumnType("float"); - - b.Property("WeekNumber") - .HasColumnType("int"); - - b.Property("Year") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("AbsenceId"); - - b.HasIndex("ConsultantId"); - - b.ToTable("PlannedAbsence"); - }); - - modelBuilder.Entity("Core.DomainModels.Project", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("CustomerId") - .HasColumnType("int"); - - b.Property("Name") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.Property("State") - .IsRequired() - .HasColumnType("nvarchar(max)"); - - b.HasKey("Id"); - - b.HasIndex("CustomerId"); - - b.ToTable("Project"); - }); - - modelBuilder.Entity("Core.DomainModels.Staffing", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Hours") - .HasColumnType("float"); - - b.Property("ProjectId") - .HasColumnType("int"); - - b.Property("Week") - .HasColumnType("int"); - - b.Property("Year") - .HasColumnType("int"); - - b.HasKey("Id"); - - b.HasIndex("ConsultantId"); - - b.HasIndex("ProjectId"); - - b.ToTable("Staffing"); - }); - - modelBuilder.Entity("Core.DomainModels.Vacation", b => - { - b.Property("Id") - .ValueGeneratedOnAdd() - .HasColumnType("int"); - - SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); - - b.Property("ConsultantId") - .HasColumnType("int"); - - b.Property("Date") - .HasColumnType("datetime2"); - - b.HasKey("Id"); - - b.HasIndex("ConsultantId"); - - b.ToTable("Vacation"); - }); - - modelBuilder.Entity("CompetenceConsultant", b => - { - b.HasOne("Core.DomainModels.Competence", null) - .WithMany() - .HasForeignKey("CompetencesId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.HasOne("Core.DomainModels.Consultant", null) - .WithMany() - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); - - modelBuilder.Entity("Core.DomainModels.Absence", b => - { - b.HasOne("Core.DomainModels.Organization", "Organization") - .WithMany("AbsenceTypes") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("Core.DomainModels.Consultant", b => - { - b.HasOne("Core.DomainModels.Department", "Department") - .WithMany("Consultants") - .HasForeignKey("DepartmentId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Department"); - }); - - modelBuilder.Entity("Core.DomainModels.Customer", b => - { - b.HasOne("Core.DomainModels.Organization", "Organization") - .WithMany("Customers") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("Core.DomainModels.Department", b => - { - b.HasOne("Core.DomainModels.Organization", "Organization") - .WithMany("Departments") - .HasForeignKey("OrganizationId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Organization"); - }); - - modelBuilder.Entity("Core.DomainModels.PlannedAbsence", b => - { - b.HasOne("Core.DomainModels.Absence", "Absence") - .WithMany() - .HasForeignKey("AbsenceId") - .OnDelete(DeleteBehavior.ClientCascade) - .IsRequired(); - - b.HasOne("Core.DomainModels.Consultant", "Consultant") - .WithMany("PlannedAbsences") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Absence"); - - b.Navigation("Consultant"); - }); - - modelBuilder.Entity("Core.DomainModels.Project", b => - { - b.HasOne("Core.DomainModels.Customer", "Customer") - .WithMany("Projects") - .HasForeignKey("CustomerId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Customer"); - }); - - modelBuilder.Entity("Core.DomainModels.Staffing", b => - { - b.HasOne("Core.DomainModels.Consultant", "Consultant") - .WithMany("Staffings") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.ClientCascade) - .IsRequired(); - - b.HasOne("Core.DomainModels.Project", "Project") - .WithMany("Staffings") - .HasForeignKey("ProjectId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Consultant"); - - b.Navigation("Project"); - }); - - modelBuilder.Entity("Core.DomainModels.Vacation", b => - { - b.HasOne("Core.DomainModels.Consultant", "Consultant") - .WithMany("Vacations") - .HasForeignKey("ConsultantId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - - b.Navigation("Consultant"); - }); - - modelBuilder.Entity("Core.DomainModels.Consultant", b => - { - b.Navigation("PlannedAbsences"); - - b.Navigation("Staffings"); - - b.Navigation("Vacations"); - }); - - modelBuilder.Entity("Core.DomainModels.Customer", b => - { - b.Navigation("Projects"); - }); - - modelBuilder.Entity("Core.DomainModels.Department", b => - { - b.Navigation("Consultants"); - }); - - modelBuilder.Entity("Core.DomainModels.Organization", b => - { - b.Navigation("AbsenceTypes"); - - b.Navigation("Customers"); - - b.Navigation("Departments"); - }); - - modelBuilder.Entity("Core.DomainModels.Project", b => - { - b.Navigation("Staffings"); - }); -#pragma warning restore 612, 618 - } - } -} From b4f8dead92f0008d2c488451073877e122b244e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B8ralt?= Date: Tue, 17 Oct 2023 15:07:01 +0200 Subject: [PATCH 08/26] unnskyld sigrid --- .../Api/Authorization/AuthorizationService.cs | 20 +++++++++++++++++++ .../Authorization/OrganisationReadModel.cs | 3 +++ 2 files changed, 23 insertions(+) create mode 100644 backend/Api/Authorization/AuthorizationService.cs create mode 100644 backend/Api/Authorization/OrganisationReadModel.cs diff --git a/backend/Api/Authorization/AuthorizationService.cs b/backend/Api/Authorization/AuthorizationService.cs new file mode 100644 index 00000000..4e8ab68b --- /dev/null +++ b/backend/Api/Authorization/AuthorizationService.cs @@ -0,0 +1,20 @@ +using Core.DomainModels; +using Database.DatabaseContext; +using Microsoft.EntityFrameworkCore; + +namespace Api.Authorization; + +public static class AuthorizationService +{ + public static List GetAuthorizedOrganizations(ApplicationContext dbContext, HttpContext httpContext) + { + var uname = httpContext.User.Claims.Single(c => c.Type == "preferred_username").Value; + + return dbContext.Organization + .Include(org => org.Departments) + .ThenInclude(dept => dept.Consultants) + .Where(org => org.Departments + .Count(dept => dept.Consultants.Select(c => c.Email).Contains(uname)) > 0) + .ToList(); + } +} \ No newline at end of file diff --git a/backend/Api/Authorization/OrganisationReadModel.cs b/backend/Api/Authorization/OrganisationReadModel.cs new file mode 100644 index 00000000..2e0f5277 --- /dev/null +++ b/backend/Api/Authorization/OrganisationReadModel.cs @@ -0,0 +1,3 @@ +namespace Api.Authorization; + +public record OrganizationReadModel(string Id, string UrlKey, string Name); \ No newline at end of file From 0e8990e3c943eb865630e6ea8656ac81e18ba733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B8ralt?= Date: Tue, 17 Oct 2023 15:07:14 +0200 Subject: [PATCH 09/26] new migrations too --- .../20231017124126_Initial.Designer.cs | 520 ++++++++++++++++++ .../Migrations/20231017124126_Initial.cs | 371 +++++++++++++ .../ApplicationContextModelSnapshot.cs | 517 +++++++++++++++++ 3 files changed, 1408 insertions(+) create mode 100644 backend/Database/Migrations/20231017124126_Initial.Designer.cs create mode 100644 backend/Database/Migrations/20231017124126_Initial.cs create mode 100644 backend/Database/Migrations/ApplicationContextModelSnapshot.cs diff --git a/backend/Database/Migrations/20231017124126_Initial.Designer.cs b/backend/Database/Migrations/20231017124126_Initial.Designer.cs new file mode 100644 index 00000000..9d0a175f --- /dev/null +++ b/backend/Database/Migrations/20231017124126_Initial.Designer.cs @@ -0,0 +1,520 @@ +// +using System; +using Database.DatabaseContext; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Database.Migrations +{ + [DbContext(typeof(ApplicationContext))] + [Migration("20231017124126_Initial")] + partial class Initial + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("CompetenceConsultant", b => + { + b.Property("CompetencesId") + .HasColumnType("nvarchar(450)"); + + b.Property("ConsultantId") + .HasColumnType("int"); + + b.HasKey("CompetencesId", "ConsultantId"); + + b.HasIndex("ConsultantId"); + + b.ToTable("CompetenceConsultant"); + }); + + modelBuilder.Entity("Core.DomainModels.Absence", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ExcludeFromBillRate") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Absence"); + }); + + modelBuilder.Entity("Core.DomainModels.Competence", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Competence"); + + b.HasData( + new + { + Id = "frontend", + Name = "Frontend" + }, + new + { + Id = "backend", + Name = "Backend" + }, + new + { + Id = "design", + Name = "Design" + }, + new + { + Id = "project-mgmt", + Name = "Project Management" + }); + }); + + modelBuilder.Entity("Core.DomainModels.Consultant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Degree") + .HasColumnType("nvarchar(max)"); + + b.Property("DepartmentId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("GraduationYear") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("DepartmentId"); + + b.ToTable("Consultant"); + + b.HasData( + new + { + Id = 1, + Degree = "Master", + DepartmentId = "trondheim", + Email = "j@variant.no", + GraduationYear = 2019, + Name = "Jonas", + StartDate = new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Core.DomainModels.Customer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Customer"); + }); + + modelBuilder.Entity("Core.DomainModels.Department", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("Hotkey") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Department"); + + b.HasData( + new + { + Id = "trondheim", + Name = "Trondheim", + OrganizationId = "variant-as" + }); + }); + + modelBuilder.Entity("Core.DomainModels.Organization", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Country") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("HasVacationInChristmas") + .HasColumnType("bit"); + + b.Property("HoursPerWorkday") + .HasColumnType("float"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("NumberOfVacationDaysInYear") + .HasColumnType("int"); + + b.Property("UrlKey") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Organization"); + + b.HasData( + new + { + Id = "variant-as", + Country = "norway", + HasVacationInChristmas = true, + HoursPerWorkday = 7.5, + Name = "Variant AS", + NumberOfVacationDaysInYear = 25, + UrlKey = "variant-as" + }); + }); + + modelBuilder.Entity("Core.DomainModels.PlannedAbsence", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AbsenceId") + .HasColumnType("int"); + + b.Property("ConsultantId") + .HasColumnType("int"); + + b.Property("Hours") + .HasColumnType("float"); + + b.Property("WeekNumber") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("AbsenceId"); + + b.HasIndex("ConsultantId"); + + b.ToTable("PlannedAbsence"); + }); + + modelBuilder.Entity("Core.DomainModels.Project", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CustomerId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("State") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("CustomerId"); + + b.ToTable("Project"); + }); + + modelBuilder.Entity("Core.DomainModels.Staffing", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ConsultantId") + .HasColumnType("int"); + + b.Property("Hours") + .HasColumnType("float"); + + b.Property("ProjectId") + .HasColumnType("int"); + + b.Property("Week") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ConsultantId"); + + b.HasIndex("ProjectId"); + + b.ToTable("Staffing"); + }); + + modelBuilder.Entity("Core.DomainModels.Vacation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ConsultantId") + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("ConsultantId"); + + b.ToTable("Vacation"); + }); + + modelBuilder.Entity("CompetenceConsultant", b => + { + b.HasOne("Core.DomainModels.Competence", null) + .WithMany() + .HasForeignKey("CompetencesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Core.DomainModels.Consultant", null) + .WithMany() + .HasForeignKey("ConsultantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Core.DomainModels.Absence", b => + { + b.HasOne("Core.DomainModels.Organization", "Organization") + .WithMany("AbsenceTypes") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Core.DomainModels.Consultant", b => + { + b.HasOne("Core.DomainModels.Department", "Department") + .WithMany("Consultants") + .HasForeignKey("DepartmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Department"); + }); + + modelBuilder.Entity("Core.DomainModels.Customer", b => + { + b.HasOne("Core.DomainModels.Organization", "Organization") + .WithMany("Customers") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Core.DomainModels.Department", b => + { + b.HasOne("Core.DomainModels.Organization", "Organization") + .WithMany("Departments") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Core.DomainModels.PlannedAbsence", b => + { + b.HasOne("Core.DomainModels.Absence", "Absence") + .WithMany() + .HasForeignKey("AbsenceId") + .OnDelete(DeleteBehavior.ClientCascade) + .IsRequired(); + + b.HasOne("Core.DomainModels.Consultant", "Consultant") + .WithMany("PlannedAbsences") + .HasForeignKey("ConsultantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Absence"); + + b.Navigation("Consultant"); + }); + + modelBuilder.Entity("Core.DomainModels.Project", b => + { + b.HasOne("Core.DomainModels.Customer", "Customer") + .WithMany("Projects") + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Customer"); + }); + + modelBuilder.Entity("Core.DomainModels.Staffing", b => + { + b.HasOne("Core.DomainModels.Consultant", "Consultant") + .WithMany("Staffings") + .HasForeignKey("ConsultantId") + .OnDelete(DeleteBehavior.ClientCascade) + .IsRequired(); + + b.HasOne("Core.DomainModels.Project", "Project") + .WithMany("Staffings") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Consultant"); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("Core.DomainModels.Vacation", b => + { + b.HasOne("Core.DomainModels.Consultant", "Consultant") + .WithMany("Vacations") + .HasForeignKey("ConsultantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Consultant"); + }); + + modelBuilder.Entity("Core.DomainModels.Consultant", b => + { + b.Navigation("PlannedAbsences"); + + b.Navigation("Staffings"); + + b.Navigation("Vacations"); + }); + + modelBuilder.Entity("Core.DomainModels.Customer", b => + { + b.Navigation("Projects"); + }); + + modelBuilder.Entity("Core.DomainModels.Department", b => + { + b.Navigation("Consultants"); + }); + + modelBuilder.Entity("Core.DomainModels.Organization", b => + { + b.Navigation("AbsenceTypes"); + + b.Navigation("Customers"); + + b.Navigation("Departments"); + }); + + modelBuilder.Entity("Core.DomainModels.Project", b => + { + b.Navigation("Staffings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/backend/Database/Migrations/20231017124126_Initial.cs b/backend/Database/Migrations/20231017124126_Initial.cs new file mode 100644 index 00000000..3f3da3f1 --- /dev/null +++ b/backend/Database/Migrations/20231017124126_Initial.cs @@ -0,0 +1,371 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace Database.Migrations +{ + /// + public partial class Initial : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "Competence", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(max)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Competence", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Organization", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(max)", nullable: false), + UrlKey = table.Column(type: "nvarchar(max)", nullable: false), + Country = table.Column(type: "nvarchar(max)", nullable: false), + NumberOfVacationDaysInYear = table.Column(type: "int", nullable: false), + HasVacationInChristmas = table.Column(type: "bit", nullable: false), + HoursPerWorkday = table.Column(type: "float", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Organization", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "Absence", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Name = table.Column(type: "nvarchar(max)", nullable: false), + ExcludeFromBillRate = table.Column(type: "bit", nullable: false), + OrganizationId = table.Column(type: "nvarchar(450)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Absence", x => x.Id); + table.ForeignKey( + name: "FK_Absence_Organization_OrganizationId", + column: x => x.OrganizationId, + principalTable: "Organization", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Customer", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Name = table.Column(type: "nvarchar(max)", nullable: false), + OrganizationId = table.Column(type: "nvarchar(450)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Customer", x => x.Id); + table.ForeignKey( + name: "FK_Customer_Organization_OrganizationId", + column: x => x.OrganizationId, + principalTable: "Organization", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Department", + columns: table => new + { + Id = table.Column(type: "nvarchar(450)", nullable: false), + Name = table.Column(type: "nvarchar(max)", nullable: false), + Hotkey = table.Column(type: "int", nullable: true), + OrganizationId = table.Column(type: "nvarchar(450)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Department", x => x.Id); + table.ForeignKey( + name: "FK_Department_Organization_OrganizationId", + column: x => x.OrganizationId, + principalTable: "Organization", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Project", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + CustomerId = table.Column(type: "int", nullable: false), + State = table.Column(type: "nvarchar(max)", nullable: false), + Name = table.Column(type: "nvarchar(max)", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Project", x => x.Id); + table.ForeignKey( + name: "FK_Project_Customer_CustomerId", + column: x => x.CustomerId, + principalTable: "Customer", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Consultant", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + Name = table.Column(type: "nvarchar(max)", nullable: false), + Email = table.Column(type: "nvarchar(max)", nullable: false), + StartDate = table.Column(type: "datetime2", nullable: true), + EndDate = table.Column(type: "datetime2", nullable: true), + DepartmentId = table.Column(type: "nvarchar(450)", nullable: false), + Degree = table.Column(type: "nvarchar(max)", nullable: true), + GraduationYear = table.Column(type: "int", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Consultant", x => x.Id); + table.ForeignKey( + name: "FK_Consultant_Department_DepartmentId", + column: x => x.DepartmentId, + principalTable: "Department", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "CompetenceConsultant", + columns: table => new + { + CompetencesId = table.Column(type: "nvarchar(450)", nullable: false), + ConsultantId = table.Column(type: "int", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_CompetenceConsultant", x => new { x.CompetencesId, x.ConsultantId }); + table.ForeignKey( + name: "FK_CompetenceConsultant_Competence_CompetencesId", + column: x => x.CompetencesId, + principalTable: "Competence", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + table.ForeignKey( + name: "FK_CompetenceConsultant_Consultant_ConsultantId", + column: x => x.ConsultantId, + principalTable: "Consultant", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "PlannedAbsence", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + AbsenceId = table.Column(type: "int", nullable: false), + ConsultantId = table.Column(type: "int", nullable: false), + Year = table.Column(type: "int", nullable: false), + WeekNumber = table.Column(type: "int", nullable: false), + Hours = table.Column(type: "float", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_PlannedAbsence", x => x.Id); + table.ForeignKey( + name: "FK_PlannedAbsence_Absence_AbsenceId", + column: x => x.AbsenceId, + principalTable: "Absence", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_PlannedAbsence_Consultant_ConsultantId", + column: x => x.ConsultantId, + principalTable: "Consultant", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Staffing", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ProjectId = table.Column(type: "int", nullable: false), + ConsultantId = table.Column(type: "int", nullable: false), + Year = table.Column(type: "int", nullable: false), + Week = table.Column(type: "int", nullable: false), + Hours = table.Column(type: "float", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Staffing", x => x.Id); + table.ForeignKey( + name: "FK_Staffing_Consultant_ConsultantId", + column: x => x.ConsultantId, + principalTable: "Consultant", + principalColumn: "Id"); + table.ForeignKey( + name: "FK_Staffing_Project_ProjectId", + column: x => x.ProjectId, + principalTable: "Project", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.CreateTable( + name: "Vacation", + columns: table => new + { + Id = table.Column(type: "int", nullable: false) + .Annotation("SqlServer:Identity", "1, 1"), + ConsultantId = table.Column(type: "int", nullable: false), + Date = table.Column(type: "datetime2", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_Vacation", x => x.Id); + table.ForeignKey( + name: "FK_Vacation_Consultant_ConsultantId", + column: x => x.ConsultantId, + principalTable: "Consultant", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + }); + + migrationBuilder.InsertData( + table: "Competence", + columns: new[] { "Id", "Name" }, + values: new object[,] + { + { "backend", "Backend" }, + { "design", "Design" }, + { "frontend", "Frontend" }, + { "project-mgmt", "Project Management" } + }); + + migrationBuilder.InsertData( + table: "Organization", + columns: new[] { "Id", "Country", "HasVacationInChristmas", "HoursPerWorkday", "Name", "NumberOfVacationDaysInYear", "UrlKey" }, + values: new object[] { "variant-as", "norway", true, 7.5, "Variant AS", 25, "variant-as" }); + + migrationBuilder.InsertData( + table: "Department", + columns: new[] { "Id", "Hotkey", "Name", "OrganizationId" }, + values: new object[] { "trondheim", null, "Trondheim", "variant-as" }); + + migrationBuilder.InsertData( + table: "Consultant", + columns: new[] { "Id", "Degree", "DepartmentId", "Email", "EndDate", "GraduationYear", "Name", "StartDate" }, + values: new object[] { 1, "Master", "trondheim", "j@variant.no", null, 2019, "Jonas", new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) }); + + migrationBuilder.CreateIndex( + name: "IX_Absence_OrganizationId", + table: "Absence", + column: "OrganizationId"); + + migrationBuilder.CreateIndex( + name: "IX_CompetenceConsultant_ConsultantId", + table: "CompetenceConsultant", + column: "ConsultantId"); + + migrationBuilder.CreateIndex( + name: "IX_Consultant_DepartmentId", + table: "Consultant", + column: "DepartmentId"); + + migrationBuilder.CreateIndex( + name: "IX_Customer_OrganizationId", + table: "Customer", + column: "OrganizationId"); + + migrationBuilder.CreateIndex( + name: "IX_Department_OrganizationId", + table: "Department", + column: "OrganizationId"); + + migrationBuilder.CreateIndex( + name: "IX_PlannedAbsence_AbsenceId", + table: "PlannedAbsence", + column: "AbsenceId"); + + migrationBuilder.CreateIndex( + name: "IX_PlannedAbsence_ConsultantId", + table: "PlannedAbsence", + column: "ConsultantId"); + + migrationBuilder.CreateIndex( + name: "IX_Project_CustomerId", + table: "Project", + column: "CustomerId"); + + migrationBuilder.CreateIndex( + name: "IX_Staffing_ConsultantId", + table: "Staffing", + column: "ConsultantId"); + + migrationBuilder.CreateIndex( + name: "IX_Staffing_ProjectId", + table: "Staffing", + column: "ProjectId"); + + migrationBuilder.CreateIndex( + name: "IX_Vacation_ConsultantId", + table: "Vacation", + column: "ConsultantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "CompetenceConsultant"); + + migrationBuilder.DropTable( + name: "PlannedAbsence"); + + migrationBuilder.DropTable( + name: "Staffing"); + + migrationBuilder.DropTable( + name: "Vacation"); + + migrationBuilder.DropTable( + name: "Competence"); + + migrationBuilder.DropTable( + name: "Absence"); + + migrationBuilder.DropTable( + name: "Project"); + + migrationBuilder.DropTable( + name: "Consultant"); + + migrationBuilder.DropTable( + name: "Customer"); + + migrationBuilder.DropTable( + name: "Department"); + + migrationBuilder.DropTable( + name: "Organization"); + } + } +} diff --git a/backend/Database/Migrations/ApplicationContextModelSnapshot.cs b/backend/Database/Migrations/ApplicationContextModelSnapshot.cs new file mode 100644 index 00000000..439ece9c --- /dev/null +++ b/backend/Database/Migrations/ApplicationContextModelSnapshot.cs @@ -0,0 +1,517 @@ +// +using System; +using Database.DatabaseContext; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Database.Migrations +{ + [DbContext(typeof(ApplicationContext))] + partial class ApplicationContextModelSnapshot : ModelSnapshot + { + protected override void BuildModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.10") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("CompetenceConsultant", b => + { + b.Property("CompetencesId") + .HasColumnType("nvarchar(450)"); + + b.Property("ConsultantId") + .HasColumnType("int"); + + b.HasKey("CompetencesId", "ConsultantId"); + + b.HasIndex("ConsultantId"); + + b.ToTable("CompetenceConsultant"); + }); + + modelBuilder.Entity("Core.DomainModels.Absence", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ExcludeFromBillRate") + .HasColumnType("bit"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Absence"); + }); + + modelBuilder.Entity("Core.DomainModels.Competence", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Competence"); + + b.HasData( + new + { + Id = "frontend", + Name = "Frontend" + }, + new + { + Id = "backend", + Name = "Backend" + }, + new + { + Id = "design", + Name = "Design" + }, + new + { + Id = "project-mgmt", + Name = "Project Management" + }); + }); + + modelBuilder.Entity("Core.DomainModels.Consultant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Degree") + .HasColumnType("nvarchar(max)"); + + b.Property("DepartmentId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("Email") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("EndDate") + .HasColumnType("datetime2"); + + b.Property("GraduationYear") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("StartDate") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("DepartmentId"); + + b.ToTable("Consultant"); + + b.HasData( + new + { + Id = 1, + Degree = "Master", + DepartmentId = "trondheim", + Email = "j@variant.no", + GraduationYear = 2019, + Name = "Jonas", + StartDate = new DateTime(2020, 1, 1, 0, 0, 0, 0, DateTimeKind.Unspecified) + }); + }); + + modelBuilder.Entity("Core.DomainModels.Customer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Customer"); + }); + + modelBuilder.Entity("Core.DomainModels.Department", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(450)"); + + b.Property("Hotkey") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("OrganizationId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.HasKey("Id"); + + b.HasIndex("OrganizationId"); + + b.ToTable("Department"); + + b.HasData( + new + { + Id = "trondheim", + Name = "Trondheim", + OrganizationId = "variant-as" + }); + }); + + modelBuilder.Entity("Core.DomainModels.Organization", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Country") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("HasVacationInChristmas") + .HasColumnType("bit"); + + b.Property("HoursPerWorkday") + .HasColumnType("float"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("NumberOfVacationDaysInYear") + .HasColumnType("int"); + + b.Property("UrlKey") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Organization"); + + b.HasData( + new + { + Id = "variant-as", + Country = "norway", + HasVacationInChristmas = true, + HoursPerWorkday = 7.5, + Name = "Variant AS", + NumberOfVacationDaysInYear = 25, + UrlKey = "variant-as" + }); + }); + + modelBuilder.Entity("Core.DomainModels.PlannedAbsence", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AbsenceId") + .HasColumnType("int"); + + b.Property("ConsultantId") + .HasColumnType("int"); + + b.Property("Hours") + .HasColumnType("float"); + + b.Property("WeekNumber") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("AbsenceId"); + + b.HasIndex("ConsultantId"); + + b.ToTable("PlannedAbsence"); + }); + + modelBuilder.Entity("Core.DomainModels.Project", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CustomerId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("State") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("CustomerId"); + + b.ToTable("Project"); + }); + + modelBuilder.Entity("Core.DomainModels.Staffing", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ConsultantId") + .HasColumnType("int"); + + b.Property("Hours") + .HasColumnType("float"); + + b.Property("ProjectId") + .HasColumnType("int"); + + b.Property("Week") + .HasColumnType("int"); + + b.Property("Year") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ConsultantId"); + + b.HasIndex("ProjectId"); + + b.ToTable("Staffing"); + }); + + modelBuilder.Entity("Core.DomainModels.Vacation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ConsultantId") + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("ConsultantId"); + + b.ToTable("Vacation"); + }); + + modelBuilder.Entity("CompetenceConsultant", b => + { + b.HasOne("Core.DomainModels.Competence", null) + .WithMany() + .HasForeignKey("CompetencesId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Core.DomainModels.Consultant", null) + .WithMany() + .HasForeignKey("ConsultantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Core.DomainModels.Absence", b => + { + b.HasOne("Core.DomainModels.Organization", "Organization") + .WithMany("AbsenceTypes") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Core.DomainModels.Consultant", b => + { + b.HasOne("Core.DomainModels.Department", "Department") + .WithMany("Consultants") + .HasForeignKey("DepartmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Department"); + }); + + modelBuilder.Entity("Core.DomainModels.Customer", b => + { + b.HasOne("Core.DomainModels.Organization", "Organization") + .WithMany("Customers") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Core.DomainModels.Department", b => + { + b.HasOne("Core.DomainModels.Organization", "Organization") + .WithMany("Departments") + .HasForeignKey("OrganizationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Organization"); + }); + + modelBuilder.Entity("Core.DomainModels.PlannedAbsence", b => + { + b.HasOne("Core.DomainModels.Absence", "Absence") + .WithMany() + .HasForeignKey("AbsenceId") + .OnDelete(DeleteBehavior.ClientCascade) + .IsRequired(); + + b.HasOne("Core.DomainModels.Consultant", "Consultant") + .WithMany("PlannedAbsences") + .HasForeignKey("ConsultantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Absence"); + + b.Navigation("Consultant"); + }); + + modelBuilder.Entity("Core.DomainModels.Project", b => + { + b.HasOne("Core.DomainModels.Customer", "Customer") + .WithMany("Projects") + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Customer"); + }); + + modelBuilder.Entity("Core.DomainModels.Staffing", b => + { + b.HasOne("Core.DomainModels.Consultant", "Consultant") + .WithMany("Staffings") + .HasForeignKey("ConsultantId") + .OnDelete(DeleteBehavior.ClientCascade) + .IsRequired(); + + b.HasOne("Core.DomainModels.Project", "Project") + .WithMany("Staffings") + .HasForeignKey("ProjectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Consultant"); + + b.Navigation("Project"); + }); + + modelBuilder.Entity("Core.DomainModels.Vacation", b => + { + b.HasOne("Core.DomainModels.Consultant", "Consultant") + .WithMany("Vacations") + .HasForeignKey("ConsultantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Consultant"); + }); + + modelBuilder.Entity("Core.DomainModels.Consultant", b => + { + b.Navigation("PlannedAbsences"); + + b.Navigation("Staffings"); + + b.Navigation("Vacations"); + }); + + modelBuilder.Entity("Core.DomainModels.Customer", b => + { + b.Navigation("Projects"); + }); + + modelBuilder.Entity("Core.DomainModels.Department", b => + { + b.Navigation("Consultants"); + }); + + modelBuilder.Entity("Core.DomainModels.Organization", b => + { + b.Navigation("AbsenceTypes"); + + b.Navigation("Customers"); + + b.Navigation("Departments"); + }); + + modelBuilder.Entity("Core.DomainModels.Project", b => + { + b.Navigation("Staffings"); + }); +#pragma warning restore 612, 618 + } + } +} From bc12d202252c8c2ca1dfacf856cd609ba9625051 Mon Sep 17 00:00:00 2001 From: Sigrid Elnan Date: Tue, 17 Oct 2023 16:03:42 +0200 Subject: [PATCH 10/26] Add organisationId chek to api calls --- .../Api/Authorization/AuthorizationService.cs | 23 +++++++++++---- .../OrganisationPolicyHandler.cs | 28 +++++++++++++++++++ .../Authorization/OrganisationRequirement.cs | 5 ++++ .../Api/Consultants/ConsultantController.cs | 5 +++- backend/Api/Program.cs | 10 ++++++- 5 files changed, 64 insertions(+), 7 deletions(-) create mode 100644 backend/Api/Authorization/OrganisationPolicyHandler.cs create mode 100644 backend/Api/Authorization/OrganisationRequirement.cs diff --git a/backend/Api/Authorization/AuthorizationService.cs b/backend/Api/Authorization/AuthorizationService.cs index 4e8ab68b..14f31cb8 100644 --- a/backend/Api/Authorization/AuthorizationService.cs +++ b/backend/Api/Authorization/AuthorizationService.cs @@ -1,20 +1,33 @@ using Core.DomainModels; using Database.DatabaseContext; using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Caching.Memory; namespace Api.Authorization; -public static class AuthorizationService +public class AuthorizationService { - public static List GetAuthorizedOrganizations(ApplicationContext dbContext, HttpContext httpContext) + private IMemoryCache _cache; + private ApplicationContext _context; + + public AuthorizationService(IMemoryCache cache, ApplicationContext context) + { + _cache = cache; + _context = context; + } + + public List GetAuthorizedOrganizations(string userEmail) { - var uname = httpContext.User.Claims.Single(c => c.Type == "preferred_username").Value; - return dbContext.Organization + return _context.Organization .Include(org => org.Departments) .ThenInclude(dept => dept.Consultants) .Where(org => org.Departments - .Count(dept => dept.Consultants.Select(c => c.Email).Contains(uname)) > 0) + .Count(dept => dept.Consultants.Select(c => c.Email).Contains(userEmail)) > 0) .ToList(); } + + public bool IsInOrganisation(string userEmail, string orgId){ + return GetAuthorizedOrganizations(userEmail).Any(org => org.Id == orgId); + } } \ No newline at end of file diff --git a/backend/Api/Authorization/OrganisationPolicyHandler.cs b/backend/Api/Authorization/OrganisationPolicyHandler.cs new file mode 100644 index 00000000..7a29415a --- /dev/null +++ b/backend/Api/Authorization/OrganisationPolicyHandler.cs @@ -0,0 +1,28 @@ +using Api.Authorization; +using Microsoft.AspNetCore.Authorization; + +public class OrganisationPolicyHandler : AuthorizationHandler +{ + private AuthorizationService _authorizationService; + + public OrganisationPolicyHandler(AuthorizationService authorizationService) + { + _authorizationService = authorizationService; + } + + protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, OrganisationRequirement requirement) + { + string userEmail = context.User.Claims.Single(c => c.Type == "preferred_username").Value; + + ((DefaultHttpContext) context.Resource).Request.RouteValues.TryGetValue("orgId", out var orgId); + if(orgId is null) { + context.Fail(); + return Task.CompletedTask; + } + if(_authorizationService.IsInOrganisation(userEmail, orgId.ToString())){ + context.Succeed(requirement); + } + + return Task.CompletedTask; + } +} \ No newline at end of file diff --git a/backend/Api/Authorization/OrganisationRequirement.cs b/backend/Api/Authorization/OrganisationRequirement.cs new file mode 100644 index 00000000..9a6933ab --- /dev/null +++ b/backend/Api/Authorization/OrganisationRequirement.cs @@ -0,0 +1,5 @@ +using Microsoft.AspNetCore.Authorization; + +public class OrganisationRequirement : IAuthorizationRequirement{ + +} \ No newline at end of file diff --git a/backend/Api/Consultants/ConsultantController.cs b/backend/Api/Consultants/ConsultantController.cs index c11a33e1..c4ff271a 100644 --- a/backend/Api/Consultants/ConsultantController.cs +++ b/backend/Api/Consultants/ConsultantController.cs @@ -2,6 +2,7 @@ using Core.DomainModels; using Core.Services; using Database.DatabaseContext; +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http.HttpResults; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; @@ -9,7 +10,7 @@ namespace Api.Consultants; -[Route("v0/consultants")] +[Route("v0/{orgId}/consultants")] [ApiController] public class ConsultantController : ControllerBase { @@ -24,8 +25,10 @@ public ConsultantController(ApplicationContext context, IMemoryCache cache, Cons _consultantService = consultantService; } + [Authorize(Policy = "Organisation")] [HttpGet] public ActionResult> Get( + [FromRoute] string orgId, [FromQuery(Name = "weeks")] int numberOfWeeks = 8, [FromQuery(Name = "includeOccupied")] bool includeOccupied = true) { diff --git a/backend/Api/Program.cs b/backend/Api/Program.cs index 78ad8d80..1aa629d3 100644 --- a/backend/Api/Program.cs +++ b/backend/Api/Program.cs @@ -1,8 +1,11 @@ +using Api.Authorization; using Api.BuildHelpers; using Api.Consultants; using Api.Options; using Database.DatabaseContext; +using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.JwtBearer; +using Microsoft.AspNetCore.Authorization; using Microsoft.EntityFrameworkCore; using Microsoft.Identity.Web; using Microsoft.OpenApi.Models; @@ -15,7 +18,10 @@ builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(builder.Configuration); -builder.Services.AddAuthorization(opt => opt.FallbackPolicy = opt.DefaultPolicy); +builder.Services.AddAuthorization(opt => { + opt.FallbackPolicy = opt.DefaultPolicy; + opt.AddPolicy("Organisation", policy=>policy.Requirements.Add(new OrganisationRequirement())); + }); builder.Services.AddDbContext(options => options.UseSqlServer(connection)); @@ -25,6 +31,8 @@ builder.Services.Configure(builder.Configuration.GetSection("OrganizationSettings")); builder.Services.AddSingleton(); builder.Services.AddSingleton(); +builder.Services.AddSingleton(); +builder.Services.AddTransient(); builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); From 0fa93a67b6761664967a4151d9ffa56ff4cf51ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B8ralt?= Date: Tue, 17 Oct 2023 21:44:07 +0200 Subject: [PATCH 11/26] some cleanup, add caching --- .../Authorization/AuthorizationPolicies.cs | 6 ++++ .../Api/Authorization/AuthorizationService.cs | 28 +++++++++++++------ backend/Api/Cache/CacheKeys.cs | 3 +- backend/Api/Program.cs | 11 ++++---- 4 files changed, 33 insertions(+), 15 deletions(-) create mode 100644 backend/Api/Authorization/AuthorizationPolicies.cs diff --git a/backend/Api/Authorization/AuthorizationPolicies.cs b/backend/Api/Authorization/AuthorizationPolicies.cs new file mode 100644 index 00000000..20096724 --- /dev/null +++ b/backend/Api/Authorization/AuthorizationPolicies.cs @@ -0,0 +1,6 @@ +namespace Api.Authorization; + +public static class AuthorizationPolicies +{ + public const string ConsultantInOrganisation = "ConsultantInOrganisation"; +} \ No newline at end of file diff --git a/backend/Api/Authorization/AuthorizationService.cs b/backend/Api/Authorization/AuthorizationService.cs index 14f31cb8..ee0c8893 100644 --- a/backend/Api/Authorization/AuthorizationService.cs +++ b/backend/Api/Authorization/AuthorizationService.cs @@ -1,3 +1,4 @@ +using Api.Cache; using Core.DomainModels; using Database.DatabaseContext; using Microsoft.EntityFrameworkCore; @@ -7,8 +8,8 @@ namespace Api.Authorization; public class AuthorizationService { - private IMemoryCache _cache; - private ApplicationContext _context; + private readonly IMemoryCache _cache; + private readonly ApplicationContext _context; public AuthorizationService(IMemoryCache cache, ApplicationContext context) { @@ -18,16 +19,25 @@ public AuthorizationService(IMemoryCache cache, ApplicationContext context) public List GetAuthorizedOrganizations(string userEmail) { + var foundCache = _cache.TryGetValue>>( + CacheKeys.ConsulantsPrOrganisation, + out var consultantOrgMap); - return _context.Organization - .Include(org => org.Departments) - .ThenInclude(dept => dept.Consultants) - .Where(org => org.Departments - .Count(dept => dept.Consultants.Select(c => c.Email).Contains(userEmail)) > 0) - .ToList(); + if (!foundCache || consultantOrgMap is null) + consultantOrgMap = _context.Consultant + .Include(c => c.Department) + .ThenInclude(d => d.Organization) + .ToDictionary(c => c.Email, consultant => new List + { + consultant.Department.Organization + }); + + _cache.Set(CacheKeys.ConsulantsPrOrganisation, consultantOrgMap); + return consultantOrgMap.TryGetValue(userEmail, out var orgList) ? orgList : new List(); } - public bool IsInOrganisation(string userEmail, string orgId){ + public bool IsInOrganisation(string userEmail, string orgId) + { return GetAuthorizedOrganizations(userEmail).Any(org => org.Id == orgId); } } \ No newline at end of file diff --git a/backend/Api/Cache/CacheKeys.cs b/backend/Api/Cache/CacheKeys.cs index 5bd0e341..1c076bcf 100644 --- a/backend/Api/Cache/CacheKeys.cs +++ b/backend/Api/Cache/CacheKeys.cs @@ -2,5 +2,6 @@ namespace Api.Cache; public enum CacheKeys { - ConsultantAvailability8Weeks + ConsultantAvailability8Weeks, + ConsulantsPrOrganisation } \ No newline at end of file diff --git a/backend/Api/Program.cs b/backend/Api/Program.cs index 1aa629d3..783671d9 100644 --- a/backend/Api/Program.cs +++ b/backend/Api/Program.cs @@ -3,7 +3,6 @@ using Api.Consultants; using Api.Options; using Database.DatabaseContext; -using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.AspNetCore.Authorization; using Microsoft.EntityFrameworkCore; @@ -18,10 +17,12 @@ builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(builder.Configuration); -builder.Services.AddAuthorization(opt => { - opt.FallbackPolicy = opt.DefaultPolicy; - opt.AddPolicy("Organisation", policy=>policy.Requirements.Add(new OrganisationRequirement())); - }); +builder.Services.AddAuthorization(opt => +{ + opt.FallbackPolicy = opt.DefaultPolicy; + opt.AddPolicy(AuthorizationPolicies.ConsultantInOrganisation, + policy => policy.Requirements.Add(new OrganisationRequirement())); +}); builder.Services.AddDbContext(options => options.UseSqlServer(connection)); From afe997da823cbccc4caba33e9b03c531da20899d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B8ralt?= Date: Wed, 18 Oct 2023 08:31:48 +0200 Subject: [PATCH 12/26] more cleanup --- .../Authorization/AuthorizationController.cs | 19 ++++--------------- .../Api/Consultants/ConsultantController.cs | 5 +++-- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/backend/Api/Authorization/AuthorizationController.cs b/backend/Api/Authorization/AuthorizationController.cs index 66e54fcf..72d43aa0 100644 --- a/backend/Api/Authorization/AuthorizationController.cs +++ b/backend/Api/Authorization/AuthorizationController.cs @@ -1,6 +1,4 @@ -using Database.DatabaseContext; using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; namespace Api.Authorization; @@ -9,19 +7,10 @@ namespace Api.Authorization; public class AuthorizationController : ControllerBase { [HttpGet] - public ActionResult> Get(ApplicationContext context) + public ActionResult> Get(AuthorizationService authorizationService) { - var uname = HttpContext.User.Claims.Single(c => c.Type == "preferred_username").Value; - - var orgs = context.Organization - .Include(org => org.Departments) - .ThenInclude(dept => dept.Consultants) - .Where(org => org.Departments - .Count(dept => dept.Consultants.Select(c => c.Email).Contains(uname)) > 0) - .Select(organization => - new OrganizationReadModel(organization.Id, organization.UrlKey, organization.Name)) - .ToList(); - - return Ok(orgs); + var email = HttpContext.User.Claims.Single(c => c.Type == "preferred_username").Value; + return Ok(authorizationService.GetAuthorizedOrganizations(email) + .Select(org => new OrganizationReadModel(org.Id, org.UrlKey, org.Name))); } } \ No newline at end of file diff --git a/backend/Api/Consultants/ConsultantController.cs b/backend/Api/Consultants/ConsultantController.cs index c4ff271a..d2fb6187 100644 --- a/backend/Api/Consultants/ConsultantController.cs +++ b/backend/Api/Consultants/ConsultantController.cs @@ -1,3 +1,4 @@ +using Api.Authorization; using Api.Cache; using Core.DomainModels; using Core.Services; @@ -10,7 +11,8 @@ namespace Api.Consultants; -[Route("v0/{orgId}/consultants")] +[Authorize(Policy = AuthorizationPolicies.ConsultantInOrganisation)] +[Route("/v0/{orgId}/consultants")] [ApiController] public class ConsultantController : ControllerBase { @@ -25,7 +27,6 @@ public ConsultantController(ApplicationContext context, IMemoryCache cache, Cons _consultantService = consultantService; } - [Authorize(Policy = "Organisation")] [HttpGet] public ActionResult> Get( [FromRoute] string orgId, From a3fec33a583b061ad3e64319ce81fedc6b44e318 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B8ralt?= Date: Wed, 18 Oct 2023 08:45:13 +0200 Subject: [PATCH 13/26] rename cache key --- backend/Api/Authorization/AuthorizationService.cs | 15 +++++++++------ backend/Api/Cache/CacheKeys.cs | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/backend/Api/Authorization/AuthorizationService.cs b/backend/Api/Authorization/AuthorizationService.cs index ee0c8893..66638b3f 100644 --- a/backend/Api/Authorization/AuthorizationService.cs +++ b/backend/Api/Authorization/AuthorizationService.cs @@ -20,19 +20,22 @@ public AuthorizationService(IMemoryCache cache, ApplicationContext context) public List GetAuthorizedOrganizations(string userEmail) { var foundCache = _cache.TryGetValue>>( - CacheKeys.ConsulantsPrOrganisation, + CacheKeys.OrganisationsPrConsultant, out var consultantOrgMap); if (!foundCache || consultantOrgMap is null) consultantOrgMap = _context.Consultant .Include(c => c.Department) .ThenInclude(d => d.Organization) - .ToDictionary(c => c.Email, consultant => new List - { - consultant.Department.Organization - }); + .ToDictionary( + c => c.Email, + consultant => new List + { + consultant.Department.Organization + } + ); - _cache.Set(CacheKeys.ConsulantsPrOrganisation, consultantOrgMap); + _cache.Set(CacheKeys.OrganisationsPrConsultant, consultantOrgMap); return consultantOrgMap.TryGetValue(userEmail, out var orgList) ? orgList : new List(); } diff --git a/backend/Api/Cache/CacheKeys.cs b/backend/Api/Cache/CacheKeys.cs index 1c076bcf..981e7f90 100644 --- a/backend/Api/Cache/CacheKeys.cs +++ b/backend/Api/Cache/CacheKeys.cs @@ -3,5 +3,5 @@ namespace Api.Cache; public enum CacheKeys { ConsultantAvailability8Weeks, - ConsulantsPrOrganisation + OrganisationsPrConsultant } \ No newline at end of file From 0275e5b3de7cb22377bb0929b5f7093a895a1f22 Mon Sep 17 00:00:00 2001 From: Magnus Gule Date: Wed, 18 Oct 2023 08:54:12 +0200 Subject: [PATCH 14/26] Correcting namespacing --- backend/Api/Authorization/OrganisationPolicyHandler.cs | 3 ++- backend/Api/Authorization/OrganisationRequirement.cs | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/backend/Api/Authorization/OrganisationPolicyHandler.cs b/backend/Api/Authorization/OrganisationPolicyHandler.cs index 7a29415a..6541a514 100644 --- a/backend/Api/Authorization/OrganisationPolicyHandler.cs +++ b/backend/Api/Authorization/OrganisationPolicyHandler.cs @@ -1,6 +1,7 @@ -using Api.Authorization; using Microsoft.AspNetCore.Authorization; +namespace Api.Authorization; + public class OrganisationPolicyHandler : AuthorizationHandler { private AuthorizationService _authorizationService; diff --git a/backend/Api/Authorization/OrganisationRequirement.cs b/backend/Api/Authorization/OrganisationRequirement.cs index 9a6933ab..b6d5be36 100644 --- a/backend/Api/Authorization/OrganisationRequirement.cs +++ b/backend/Api/Authorization/OrganisationRequirement.cs @@ -1,5 +1,7 @@ using Microsoft.AspNetCore.Authorization; +namespace Api.Authorization; + public class OrganisationRequirement : IAuthorizationRequirement{ } \ No newline at end of file From 890f169644b34c80766afa766dc2fb6e26a3b4dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B8ralt?= Date: Wed, 18 Oct 2023 16:17:20 +0200 Subject: [PATCH 15/26] simplify auth ny postponing tenant-id --- .../Authorization/AuthorizationController.cs | 16 ------- .../Authorization/AuthorizationPolicies.cs | 6 --- .../Api/Authorization/AuthorizationService.cs | 46 ------------------- .../OrganisationPolicyHandler.cs | 29 ------------ .../Authorization/OrganisationReadModel.cs | 3 -- .../Authorization/OrganisationRequirement.cs | 7 --- .../Api/Consultants/ConsultantController.cs | 6 +-- .../Api/Departments/DeparmentController.cs | 16 ------- .../Api/Organisation/DeparmentController.cs | 42 +++++++++++++++++ backend/Api/Program.cs | 10 +--- 10 files changed, 45 insertions(+), 136 deletions(-) delete mode 100644 backend/Api/Authorization/AuthorizationController.cs delete mode 100644 backend/Api/Authorization/AuthorizationPolicies.cs delete mode 100644 backend/Api/Authorization/AuthorizationService.cs delete mode 100644 backend/Api/Authorization/OrganisationPolicyHandler.cs delete mode 100644 backend/Api/Authorization/OrganisationReadModel.cs delete mode 100644 backend/Api/Authorization/OrganisationRequirement.cs delete mode 100644 backend/Api/Departments/DeparmentController.cs create mode 100644 backend/Api/Organisation/DeparmentController.cs diff --git a/backend/Api/Authorization/AuthorizationController.cs b/backend/Api/Authorization/AuthorizationController.cs deleted file mode 100644 index 72d43aa0..00000000 --- a/backend/Api/Authorization/AuthorizationController.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Microsoft.AspNetCore.Mvc; - -namespace Api.Authorization; - -[Route("v0/authorization")] -[ApiController] -public class AuthorizationController : ControllerBase -{ - [HttpGet] - public ActionResult> Get(AuthorizationService authorizationService) - { - var email = HttpContext.User.Claims.Single(c => c.Type == "preferred_username").Value; - return Ok(authorizationService.GetAuthorizedOrganizations(email) - .Select(org => new OrganizationReadModel(org.Id, org.UrlKey, org.Name))); - } -} \ No newline at end of file diff --git a/backend/Api/Authorization/AuthorizationPolicies.cs b/backend/Api/Authorization/AuthorizationPolicies.cs deleted file mode 100644 index 20096724..00000000 --- a/backend/Api/Authorization/AuthorizationPolicies.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace Api.Authorization; - -public static class AuthorizationPolicies -{ - public const string ConsultantInOrganisation = "ConsultantInOrganisation"; -} \ No newline at end of file diff --git a/backend/Api/Authorization/AuthorizationService.cs b/backend/Api/Authorization/AuthorizationService.cs deleted file mode 100644 index 66638b3f..00000000 --- a/backend/Api/Authorization/AuthorizationService.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Api.Cache; -using Core.DomainModels; -using Database.DatabaseContext; -using Microsoft.EntityFrameworkCore; -using Microsoft.Extensions.Caching.Memory; - -namespace Api.Authorization; - -public class AuthorizationService -{ - private readonly IMemoryCache _cache; - private readonly ApplicationContext _context; - - public AuthorizationService(IMemoryCache cache, ApplicationContext context) - { - _cache = cache; - _context = context; - } - - public List GetAuthorizedOrganizations(string userEmail) - { - var foundCache = _cache.TryGetValue>>( - CacheKeys.OrganisationsPrConsultant, - out var consultantOrgMap); - - if (!foundCache || consultantOrgMap is null) - consultantOrgMap = _context.Consultant - .Include(c => c.Department) - .ThenInclude(d => d.Organization) - .ToDictionary( - c => c.Email, - consultant => new List - { - consultant.Department.Organization - } - ); - - _cache.Set(CacheKeys.OrganisationsPrConsultant, consultantOrgMap); - return consultantOrgMap.TryGetValue(userEmail, out var orgList) ? orgList : new List(); - } - - public bool IsInOrganisation(string userEmail, string orgId) - { - return GetAuthorizedOrganizations(userEmail).Any(org => org.Id == orgId); - } -} \ No newline at end of file diff --git a/backend/Api/Authorization/OrganisationPolicyHandler.cs b/backend/Api/Authorization/OrganisationPolicyHandler.cs deleted file mode 100644 index 6541a514..00000000 --- a/backend/Api/Authorization/OrganisationPolicyHandler.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Microsoft.AspNetCore.Authorization; - -namespace Api.Authorization; - -public class OrganisationPolicyHandler : AuthorizationHandler -{ - private AuthorizationService _authorizationService; - - public OrganisationPolicyHandler(AuthorizationService authorizationService) - { - _authorizationService = authorizationService; - } - - protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, OrganisationRequirement requirement) - { - string userEmail = context.User.Claims.Single(c => c.Type == "preferred_username").Value; - - ((DefaultHttpContext) context.Resource).Request.RouteValues.TryGetValue("orgId", out var orgId); - if(orgId is null) { - context.Fail(); - return Task.CompletedTask; - } - if(_authorizationService.IsInOrganisation(userEmail, orgId.ToString())){ - context.Succeed(requirement); - } - - return Task.CompletedTask; - } -} \ No newline at end of file diff --git a/backend/Api/Authorization/OrganisationReadModel.cs b/backend/Api/Authorization/OrganisationReadModel.cs deleted file mode 100644 index 2e0f5277..00000000 --- a/backend/Api/Authorization/OrganisationReadModel.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace Api.Authorization; - -public record OrganizationReadModel(string Id, string UrlKey, string Name); \ No newline at end of file diff --git a/backend/Api/Authorization/OrganisationRequirement.cs b/backend/Api/Authorization/OrganisationRequirement.cs deleted file mode 100644 index b6d5be36..00000000 --- a/backend/Api/Authorization/OrganisationRequirement.cs +++ /dev/null @@ -1,7 +0,0 @@ -using Microsoft.AspNetCore.Authorization; - -namespace Api.Authorization; - -public class OrganisationRequirement : IAuthorizationRequirement{ - -} \ No newline at end of file diff --git a/backend/Api/Consultants/ConsultantController.cs b/backend/Api/Consultants/ConsultantController.cs index d2fb6187..f1f1563f 100644 --- a/backend/Api/Consultants/ConsultantController.cs +++ b/backend/Api/Consultants/ConsultantController.cs @@ -1,4 +1,3 @@ -using Api.Authorization; using Api.Cache; using Core.DomainModels; using Core.Services; @@ -11,8 +10,8 @@ namespace Api.Consultants; -[Authorize(Policy = AuthorizationPolicies.ConsultantInOrganisation)] -[Route("/v0/{orgId}/consultants")] +[Authorize] +[Route("/v0/consultants")] [ApiController] public class ConsultantController : ControllerBase { @@ -29,7 +28,6 @@ public ConsultantController(ApplicationContext context, IMemoryCache cache, Cons [HttpGet] public ActionResult> Get( - [FromRoute] string orgId, [FromQuery(Name = "weeks")] int numberOfWeeks = 8, [FromQuery(Name = "includeOccupied")] bool includeOccupied = true) { diff --git a/backend/Api/Departments/DeparmentController.cs b/backend/Api/Departments/DeparmentController.cs deleted file mode 100644 index 76405de6..00000000 --- a/backend/Api/Departments/DeparmentController.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Database.DatabaseContext; -using Microsoft.AspNetCore.Mvc; - -[Route("/v0/departments")] -[ApiController] -public class DepartmentController : ControllerBase { - - [HttpGet] - public ActionResult> Get(ApplicationContext applicationContext){ - - return applicationContext.Department.Select(d => new DepartmentReadModel(d.Id, d.Name)).ToList(); - - } -} - -public record DepartmentReadModel(string Id, string Name); diff --git a/backend/Api/Organisation/DeparmentController.cs b/backend/Api/Organisation/DeparmentController.cs new file mode 100644 index 00000000..bb4d620d --- /dev/null +++ b/backend/Api/Organisation/DeparmentController.cs @@ -0,0 +1,42 @@ +using Database.DatabaseContext; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; + +namespace Api.Organisation; + +[Route("/v0/organisations")] +[ApiController] +public class OrganisationController : ControllerBase +{ + private readonly ApplicationContext _applicationContext; + + public OrganisationController(ApplicationContext applicationContext) + { + _applicationContext = applicationContext; + } + + [HttpGet] + public ActionResult> Get() + { + return _applicationContext.Organization + .Select(organization => new OrganisationReadModel(organization.Name, organization.UrlKey)) + .ToList(); + } + + + [HttpGet] + [Route("{orgUrlKey}/departments")] + public ActionResult> GetDepartment([FromRoute] string orgUrlKey) + { + return _applicationContext.Organization + .Include(o => o.Departments) + .Single(o => o.UrlKey == orgUrlKey) + .Departments + .Select(d => new DepartmentReadModel(d.Id, d.Name)) + .ToList(); + } +} + +public record DepartmentReadModel(string Id, string Name); + +public record OrganisationReadModel(string Name, string UrlKey); \ No newline at end of file diff --git a/backend/Api/Program.cs b/backend/Api/Program.cs index 783671d9..ee59d56c 100644 --- a/backend/Api/Program.cs +++ b/backend/Api/Program.cs @@ -1,4 +1,3 @@ -using Api.Authorization; using Api.BuildHelpers; using Api.Consultants; using Api.Options; @@ -17,12 +16,7 @@ builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(builder.Configuration); -builder.Services.AddAuthorization(opt => -{ - opt.FallbackPolicy = opt.DefaultPolicy; - opt.AddPolicy(AuthorizationPolicies.ConsultantInOrganisation, - policy => policy.Requirements.Add(new OrganisationRequirement())); -}); +builder.Services.AddAuthorization(opt => { opt.FallbackPolicy = opt.DefaultPolicy; }); builder.Services.AddDbContext(options => options.UseSqlServer(connection)); @@ -32,8 +26,6 @@ builder.Services.Configure(builder.Configuration.GetSection("OrganizationSettings")); builder.Services.AddSingleton(); builder.Services.AddSingleton(); -builder.Services.AddSingleton(); -builder.Services.AddTransient(); builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); From 1c5af9f87f37a5160dd4c73a3c4c6e41f3a2d484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B8ralt?= Date: Wed, 18 Oct 2023 17:03:09 +0200 Subject: [PATCH 16/26] wip: some redirect logic frontend --- .../app/{ => [organisation]}/bemanning/layout.tsx | 0 .../app/{ => [organisation]}/bemanning/page.tsx | 4 ++-- frontend/src/app/page.tsx | 11 +++++++++-- frontend/src/components/DepartmentFilter.tsx | 2 +- frontend/src/types.ts | 15 +++++++++++++++ 5 files changed, 27 insertions(+), 5 deletions(-) rename frontend/src/app/{ => [organisation]}/bemanning/layout.tsx (100%) rename frontend/src/app/{ => [organisation]}/bemanning/page.tsx (61%) diff --git a/frontend/src/app/bemanning/layout.tsx b/frontend/src/app/[organisation]/bemanning/layout.tsx similarity index 100% rename from frontend/src/app/bemanning/layout.tsx rename to frontend/src/app/[organisation]/bemanning/layout.tsx diff --git a/frontend/src/app/bemanning/page.tsx b/frontend/src/app/[organisation]/bemanning/page.tsx similarity index 61% rename from frontend/src/app/bemanning/page.tsx rename to frontend/src/app/[organisation]/bemanning/page.tsx index 2901efb0..5e49c8da 100644 --- a/frontend/src/app/bemanning/page.tsx +++ b/frontend/src/app/[organisation]/bemanning/page.tsx @@ -2,8 +2,8 @@ import FilteredConsultantsList from "@/components/FilteredConsultantsList"; import { fetchWithToken } from "@/data/fetchWithToken"; import { Consultant } from "@/types"; -export default async function Bemanning() { - const consultants = (await fetchWithToken("consultants")) ?? []; +export default async function Bemanning({params}: {params: {organisation: string}}) { + const consultants = (await fetchWithToken(`${params.organisation}/consultants`)) ?? []; return (
diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx index 1e343bfb..8ec7bd2c 100644 --- a/frontend/src/app/page.tsx +++ b/frontend/src/app/page.tsx @@ -1,5 +1,12 @@ import { redirect } from "next/navigation"; +import { fetchWithToken } from "@/data/fetchWithToken"; +import { Consultant, Organisation } from "@/types"; +import Link from "next/link"; -export default function Root() { - redirect("/bemanning"); +export default async function Root() { + const orgs = await fetchWithToken('organisations') ?? [] + return
    + {orgs.map(o =>
  • {o.name}
  • )} +
+ //redirect("/bemanning"); } diff --git a/frontend/src/components/DepartmentFilter.tsx b/frontend/src/components/DepartmentFilter.tsx index 5485bd09..2dda4275 100644 --- a/frontend/src/components/DepartmentFilter.tsx +++ b/frontend/src/components/DepartmentFilter.tsx @@ -3,7 +3,7 @@ import { fetchWithToken } from "@/data/fetchWithToken"; import { Department } from "@/types"; export default async function DepartmentFilter() { - const departments = (await fetchWithToken("departments")) ?? []; + const departments = (await fetchWithToken("organisations/variant-norge/departments")) ?? []; if (departments.length > 0) { return ( diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 5492e420..468a2696 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -1,3 +1,5 @@ +import { PopoverVirtualElement } from "@mui/material"; + export type Consultant = { id: string; name: string; @@ -17,3 +19,16 @@ export type Department = { id: string; name: string; }; + +export type Organisation = { + name: string, + urlKey: string +} + +export type AnchorProp = + | Element + | (() => Element) + | PopoverVirtualElement + | (() => PopoverVirtualElement) + | null + | undefined; From bb05fcf0b5774c19b1891dfc50c6ab1d47378b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B8ralt?= Date: Wed, 18 Oct 2023 22:10:09 +0200 Subject: [PATCH 17/26] fix frontend redirect --- backend/Api/Consultants/ConsultantController.cs | 15 +++++++++------ frontend/src/components/SearchBarComponent.tsx | 7 ++++--- frontend/src/components/VibesNavBar.tsx | 0 3 files changed, 13 insertions(+), 9 deletions(-) create mode 100644 frontend/src/components/VibesNavBar.tsx diff --git a/backend/Api/Consultants/ConsultantController.cs b/backend/Api/Consultants/ConsultantController.cs index f1f1563f..abb7655c 100644 --- a/backend/Api/Consultants/ConsultantController.cs +++ b/backend/Api/Consultants/ConsultantController.cs @@ -11,7 +11,7 @@ namespace Api.Consultants; [Authorize] -[Route("/v0/consultants")] +[Route("/v0/{orgUrlKey}/consultants")] [ApiController] public class ConsultantController : ControllerBase { @@ -28,10 +28,11 @@ public ConsultantController(ApplicationContext context, IMemoryCache cache, Cons [HttpGet] public ActionResult> Get( + [FromRoute] string orgUrlKey, [FromQuery(Name = "weeks")] int numberOfWeeks = 8, [FromQuery(Name = "includeOccupied")] bool includeOccupied = true) { - var consultants = GetConsultantsWithAvailability(numberOfWeeks) + var consultants = GetConsultantsWithAvailability(orgUrlKey, numberOfWeeks) .Where(c => includeOccupied || c.IsOccupied @@ -69,16 +70,17 @@ public async Task, ProblemHttpResult, Vali } } - private List GetConsultantsWithAvailability(int numberOfWeeks) + private List GetConsultantsWithAvailability(string orgUrlKey, int numberOfWeeks) { if (numberOfWeeks == 8) { - _cache.TryGetValue(CacheKeys.ConsultantAvailability8Weeks, + _cache.TryGetValue( + $"{orgUrlKey}/{CacheKeys.ConsultantAvailability8Weeks}", out List? cachedConsultants); if (cachedConsultants != null) return cachedConsultants; } - var consultants = LoadConsultantAvailability(numberOfWeeks) + var consultants = LoadConsultantAvailability(orgUrlKey, numberOfWeeks) .Select(c => _consultantService.MapConsultantToReadModel(c, numberOfWeeks)).ToList(); @@ -86,7 +88,7 @@ private List GetConsultantsWithAvailability(int numberOfWee return consultants; } - private List LoadConsultantAvailability(int numberOfWeeks) + private List LoadConsultantAvailability(string orgUrlKey, int numberOfWeeks) { var applicableWeeks = DateService.GetNextWeeks(numberOfWeeks); var firstDayOfCurrentWeek = DateService.GetFirstDayOfWeekContainingDate(DateTime.Now); @@ -122,6 +124,7 @@ private List LoadConsultantAvailability(int numberOfWeeks) || (yearB <= pa.Year && minWeekB <= pa.WeekNumber && pa.WeekNumber <= maxWeekB))) .Include(c => c.Department) .ThenInclude(d => d.Organization) + .Where(c => c.Department.Organization.UrlKey == orgUrlKey) .Include(c => c.Staffings.Where(s => (s.Year <= yearA && minWeekA <= s.Week && s.Week <= maxWeekA) || (yearB <= s.Year && minWeekB <= s.Week && s.Week <= maxWeekB))) diff --git a/frontend/src/components/SearchBarComponent.tsx b/frontend/src/components/SearchBarComponent.tsx index f056babb..80c485a8 100644 --- a/frontend/src/components/SearchBarComponent.tsx +++ b/frontend/src/components/SearchBarComponent.tsx @@ -1,11 +1,12 @@ "use client"; -import { useRouter, useSearchParams } from "next/navigation"; +import { usePathname, useRouter, useSearchParams } from "next/navigation"; import { useEffect, useRef, useState } from "react"; import { Search } from "react-feather"; export default function SearchBarComponent() { const router = useRouter(); const searchParams = useSearchParams(); + const pathname = usePathname(); const [searchText, setSearchText] = useState( searchParams.get("search") || "", ); @@ -13,8 +14,8 @@ export default function SearchBarComponent() { useEffect(() => { const currentFilter = searchParams.get("filter") || ""; - router.push(`/bemanning?search=${searchText}&filter=${currentFilter}`); - }, [searchText, searchParams, router]); + router.push(`${pathname}?search=${searchText}&filter=${currentFilter}`); + }, [searchText, searchParams, router, pathname]); useEffect(() => { function keyDownHandler(e: { code: string }) { diff --git a/frontend/src/components/VibesNavBar.tsx b/frontend/src/components/VibesNavBar.tsx new file mode 100644 index 00000000..e69de29b From ae41b28c9467f4802c576957be861d9395c5fd0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B8ralt?= Date: Thu, 19 Oct 2023 10:47:09 +0200 Subject: [PATCH 18/26] Fix dept filter --- frontend/src/components/FilterButton.tsx | 5 +++-- frontend/src/data/fetchWithToken.ts | 9 +++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/FilterButton.tsx b/frontend/src/components/FilterButton.tsx index 054ba132..6fa99edc 100644 --- a/frontend/src/components/FilterButton.tsx +++ b/frontend/src/components/FilterButton.tsx @@ -1,9 +1,10 @@ "use client"; -import { useRouter, useSearchParams } from "next/navigation"; +import { usePathname, useRouter, useSearchParams } from "next/navigation"; import { useState } from "react"; export default function FilterButton({ filterName }: { filterName: string }) { const router = useRouter(); + const pathname = usePathname(); const searchParams = useSearchParams(); const [isButtonActive, setIsButtonActive] = useState(checkFilterInUrl); @@ -21,7 +22,7 @@ export default function FilterButton({ filterName }: { filterName: string }) { newFilters.splice(filterIndex, 1); } const newFilterString = newFilters.join(",").replace(/^,/, ""); - router.push(`/bemanning?search=${currentSearch}&filter=${newFilterString}`); + router.push(`${pathname}?search=${currentSearch}&filter=${newFilterString}`); } function checkFilterInUrl() { diff --git a/frontend/src/data/fetchWithToken.ts b/frontend/src/data/fetchWithToken.ts index 55fb36f6..f574410f 100644 --- a/frontend/src/data/fetchWithToken.ts +++ b/frontend/src/data/fetchWithToken.ts @@ -26,8 +26,13 @@ export async function fetchWithToken(path: string): Promise { method: "GET", headers: headers, }; - const response = await fetch(`${apiBackendUrl}/${path}`, options); - return (await response.json()) as T; + try{ + const response = await fetch(`${apiBackendUrl}/${path}`, options); + return (await response.json()) as T; + } catch (e) { + console.log(`${apiBackendUrl}/${path}`) + console.error(e) + } } function mockedCall(path: string): Promise { From a8d7e1009b547157b055a104ae6b057669029d12 Mon Sep 17 00:00:00 2001 From: Magnus Gule Date: Thu, 19 Oct 2023 11:18:58 +0200 Subject: [PATCH 19/26] added timer to test fetchWithToken --- frontend/src/data/fetchWithToken.ts | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/frontend/src/data/fetchWithToken.ts b/frontend/src/data/fetchWithToken.ts index f574410f..89818431 100644 --- a/frontend/src/data/fetchWithToken.ts +++ b/frontend/src/data/fetchWithToken.ts @@ -6,6 +6,7 @@ import { } from "@/app/api/auth/[...nextauth]/route"; export async function fetchWithToken(path: string): Promise { + console.time(path); if (process.env.NEXT_PUBLIC_NO_AUTH) { return mockedCall(path); } @@ -26,12 +27,13 @@ export async function fetchWithToken(path: string): Promise { method: "GET", headers: headers, }; - try{ + try { const response = await fetch(`${apiBackendUrl}/${path}`, options); + console.timeEnd(path); return (await response.json()) as T; } catch (e) { - console.log(`${apiBackendUrl}/${path}`) - console.error(e) + console.log(`${apiBackendUrl}/${path}`); + console.error(e); } } From 7bdf395d3f8f5d9e74dd51dc3e6fa788b0d93f88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B8ralt?= Date: Thu, 19 Oct 2023 11:20:06 +0200 Subject: [PATCH 20/26] Fix caching --- backend/Api/Consultants/ConsultantController.cs | 9 ++++----- frontend/src/components/NavBar/NavBar.tsx | 4 ++-- frontend/src/components/VibesNavBar.tsx | 0 3 files changed, 6 insertions(+), 7 deletions(-) delete mode 100644 frontend/src/components/VibesNavBar.tsx diff --git a/backend/Api/Consultants/ConsultantController.cs b/backend/Api/Consultants/ConsultantController.cs index abb7655c..22cc5b71 100644 --- a/backend/Api/Consultants/ConsultantController.cs +++ b/backend/Api/Consultants/ConsultantController.cs @@ -59,7 +59,7 @@ public async Task, ProblemHttpResult, Vali var newConsultant = CreateConsultantFromModel(basicConsultant, selectedDepartment); await AddConsultantToDatabaseAsync(_context, newConsultant); - ClearConsultantCache(); + ClearConsultantCache(selectedDepartment.Organization.UrlKey); return TypedResults.Created($"/consultant/{newConsultant.Id}", basicConsultant); } @@ -83,8 +83,7 @@ private List GetConsultantsWithAvailability(string orgUrlKe var consultants = LoadConsultantAvailability(orgUrlKey, numberOfWeeks) .Select(c => _consultantService.MapConsultantToReadModel(c, numberOfWeeks)).ToList(); - - _cache.Set(CacheKeys.ConsultantAvailability8Weeks, consultants); + _cache.Set($"{orgUrlKey}/{CacheKeys.ConsultantAvailability8Weeks}", consultants); return consultants; } @@ -160,9 +159,9 @@ private static async Task AddConsultantToDatabaseAsync(ApplicationContext db, Co await db.SaveChangesAsync(); } - private void ClearConsultantCache() + private void ClearConsultantCache(string orgUrlKey) { - _cache.Remove(CacheKeys.ConsultantAvailability8Weeks); + _cache.Remove($"{orgUrlKey}/{CacheKeys.ConsultantAvailability8Weeks}"); } diff --git a/frontend/src/components/NavBar/NavBar.tsx b/frontend/src/components/NavBar/NavBar.tsx index e8559595..a8c58963 100644 --- a/frontend/src/components/NavBar/NavBar.tsx +++ b/frontend/src/components/NavBar/NavBar.tsx @@ -6,13 +6,13 @@ export default function NavBar() { return (
- +
Variant logo diff --git a/frontend/src/components/VibesNavBar.tsx b/frontend/src/components/VibesNavBar.tsx deleted file mode 100644 index e69de29b..00000000 From a6fee69d88d2da969a4bc1a16ec2375974e5ec61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B8ralt?= Date: Thu, 19 Oct 2023 11:22:58 +0200 Subject: [PATCH 21/26] Remove timer --- frontend/src/data/fetchWithToken.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/frontend/src/data/fetchWithToken.ts b/frontend/src/data/fetchWithToken.ts index 89818431..16466fef 100644 --- a/frontend/src/data/fetchWithToken.ts +++ b/frontend/src/data/fetchWithToken.ts @@ -6,7 +6,6 @@ import { } from "@/app/api/auth/[...nextauth]/route"; export async function fetchWithToken(path: string): Promise { - console.time(path); if (process.env.NEXT_PUBLIC_NO_AUTH) { return mockedCall(path); } @@ -29,10 +28,8 @@ export async function fetchWithToken(path: string): Promise { }; try { const response = await fetch(`${apiBackendUrl}/${path}`, options); - console.timeEnd(path); return (await response.json()) as T; } catch (e) { - console.log(`${apiBackendUrl}/${path}`); console.error(e); } } From c460c2a1d1f6094d4b474938dc5c390884cb0c88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B8ralt?= Date: Thu, 19 Oct 2023 11:23:48 +0200 Subject: [PATCH 22/26] prettier --- frontend/src/app/[organisation]/bemanning/page.tsx | 11 +++++++++-- frontend/src/app/page.tsx | 14 ++++++++++---- frontend/src/components/DepartmentFilter.tsx | 5 ++++- frontend/src/components/FilterButton.tsx | 4 +++- frontend/src/types.ts | 6 +++--- 5 files changed, 29 insertions(+), 11 deletions(-) diff --git a/frontend/src/app/[organisation]/bemanning/page.tsx b/frontend/src/app/[organisation]/bemanning/page.tsx index 5e49c8da..9939cc9b 100644 --- a/frontend/src/app/[organisation]/bemanning/page.tsx +++ b/frontend/src/app/[organisation]/bemanning/page.tsx @@ -2,8 +2,15 @@ import FilteredConsultantsList from "@/components/FilteredConsultantsList"; import { fetchWithToken } from "@/data/fetchWithToken"; import { Consultant } from "@/types"; -export default async function Bemanning({params}: {params: {organisation: string}}) { - const consultants = (await fetchWithToken(`${params.organisation}/consultants`)) ?? []; +export default async function Bemanning({ + params, +}: { + params: { organisation: string }; +}) { + const consultants = + (await fetchWithToken( + `${params.organisation}/consultants`, + )) ?? []; return (
diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx index 8ec7bd2c..5a4a5881 100644 --- a/frontend/src/app/page.tsx +++ b/frontend/src/app/page.tsx @@ -4,9 +4,15 @@ import { Consultant, Organisation } from "@/types"; import Link from "next/link"; export default async function Root() { - const orgs = await fetchWithToken('organisations') ?? [] - return
    - {orgs.map(o =>
  • {o.name}
  • )} -
+ const orgs = (await fetchWithToken("organisations")) ?? []; + return ( +
    + {orgs.map((o) => ( +
  • + {o.name} +
  • + ))} +
+ ); //redirect("/bemanning"); } diff --git a/frontend/src/components/DepartmentFilter.tsx b/frontend/src/components/DepartmentFilter.tsx index 2dda4275..c2d2916f 100644 --- a/frontend/src/components/DepartmentFilter.tsx +++ b/frontend/src/components/DepartmentFilter.tsx @@ -3,7 +3,10 @@ import { fetchWithToken } from "@/data/fetchWithToken"; import { Department } from "@/types"; export default async function DepartmentFilter() { - const departments = (await fetchWithToken("organisations/variant-norge/departments")) ?? []; + const departments = + (await fetchWithToken( + "organisations/variant-norge/departments", + )) ?? []; if (departments.length > 0) { return ( diff --git a/frontend/src/components/FilterButton.tsx b/frontend/src/components/FilterButton.tsx index 6fa99edc..a6b9ab63 100644 --- a/frontend/src/components/FilterButton.tsx +++ b/frontend/src/components/FilterButton.tsx @@ -22,7 +22,9 @@ export default function FilterButton({ filterName }: { filterName: string }) { newFilters.splice(filterIndex, 1); } const newFilterString = newFilters.join(",").replace(/^,/, ""); - router.push(`${pathname}?search=${currentSearch}&filter=${newFilterString}`); + router.push( + `${pathname}?search=${currentSearch}&filter=${newFilterString}`, + ); } function checkFilterInUrl() { diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 468a2696..c2f323c3 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -21,9 +21,9 @@ export type Department = { }; export type Organisation = { - name: string, - urlKey: string -} + name: string; + urlKey: string; +}; export type AnchorProp = | Element From 8246f1f855861a8611537165564562d220c5ba50 Mon Sep 17 00:00:00 2001 From: Magnus Gule Date: Thu, 19 Oct 2023 11:37:36 +0200 Subject: [PATCH 23/26] Removing MUI breadcrumbs.... --- STYLEGUIDE.md | 9 --------- frontend/README.md | 13 ------------- frontend/next.config.js | 5 ----- frontend/src/types.ts | 16 +++------------- 4 files changed, 3 insertions(+), 40 deletions(-) delete mode 100644 STYLEGUIDE.md diff --git a/STYLEGUIDE.md b/STYLEGUIDE.md deleted file mode 100644 index 67f2fde5..00000000 --- a/STYLEGUIDE.md +++ /dev/null @@ -1,9 +0,0 @@ -# Styleguide in project - - -## Frontend -### Overriding of MUI components -Follow the guide on https://mui.com/material-ui/customization/how-to-customize/ - -For implementaion examples using @mui/material/styled, see component: -[VibesNavBarTabs.tsx](/frontend/src/app/components/VibesNavBarTabs.tsx) diff --git a/frontend/README.md b/frontend/README.md index 8bd0ae5c..b7d1ae19 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -41,16 +41,3 @@ You can check out [the Next.js GitHub repository](https://github.com/vercel/next ## Deployment See [project root README](../README.md). - -## Issues - -This seem to be a bug in the MUI package. It is only triggered when importing styled from `@mui/material`: - -```ts -import { styled } from "@mui/material"; - -// As a workaround, I recommend importing { styled } from styles instead: -import { styled } from "@mui/material/styles"; -``` - -https://github.com/vercel/next.js/issues/55663 diff --git a/frontend/next.config.js b/frontend/next.config.js index 3a48579c..d8d5f63e 100644 --- a/frontend/next.config.js +++ b/frontend/next.config.js @@ -4,11 +4,6 @@ const nextConfig = { distDir: "build", swcMinify: true, - modularizeImports: { - "@mui/icons-material": { - transform: "@mui/icons-material/{{member}}", - }, - }, }; module.exports = nextConfig; diff --git a/frontend/src/types.ts b/frontend/src/types.ts index c2f323c3..583da473 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -1,5 +1,3 @@ -import { PopoverVirtualElement } from "@mui/material"; - export type Consultant = { id: string; name: string; @@ -21,14 +19,6 @@ export type Department = { }; export type Organisation = { - name: string; - urlKey: string; -}; - -export type AnchorProp = - | Element - | (() => Element) - | PopoverVirtualElement - | (() => PopoverVirtualElement) - | null - | undefined; + name: string, + urlKey: string +} From 46474432c79f276b1c7039aaa3bab8e750f91b41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B8ralt?= Date: Thu, 19 Oct 2023 11:42:36 +0200 Subject: [PATCH 24/26] fix tests --- frontend/mockdata/mockConsultants.ts | 12 ------------ frontend/mockdata/mockData.ts | 26 ++++++++++++++++++++++++++ frontend/mockdata/mockDepartments.ts | 8 -------- frontend/src/data/fetchWithToken.ts | 10 ++++++++-- frontend/src/types.ts | 6 +++--- frontend/tests/consultant-list.spec.ts | 5 ++++- 6 files changed, 41 insertions(+), 26 deletions(-) delete mode 100644 frontend/mockdata/mockConsultants.ts create mode 100644 frontend/mockdata/mockData.ts delete mode 100644 frontend/mockdata/mockDepartments.ts diff --git a/frontend/mockdata/mockConsultants.ts b/frontend/mockdata/mockConsultants.ts deleted file mode 100644 index 1a7a52d0..00000000 --- a/frontend/mockdata/mockConsultants.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { Consultant } from "@/types"; - -export const MockConsultants: Consultant[] = [ - { - id: "id", - name: "Test Consultant", - email: "test@company.io", - competences: ["Frontend"], - department: "My Department", - bookings: [{ year: 2023, weekNumber: 10, bookedHours: 10 }], - }, -]; diff --git a/frontend/mockdata/mockData.ts b/frontend/mockdata/mockData.ts new file mode 100644 index 00000000..f2f98df3 --- /dev/null +++ b/frontend/mockdata/mockData.ts @@ -0,0 +1,26 @@ +import { Consultant, Department, Organisation } from "@/types"; + +export const MockConsultants: Consultant[] = [ + { + id: "id", + name: "Test Consultant", + email: "test@company.io", + competences: ["Frontend"], + department: "My Department", + bookings: [{ year: 2023, weekNumber: 10, bookedHours: 10 }], + }, +]; + +export const MockDepartments: Department[] = [ + { + id: "myDepartment", + name: "My Department", + }, +]; + +export const MockOrganisations: Organisation[] = [ + { + name: "My Organisation", + urlKey: "my-org", + }, +]; diff --git a/frontend/mockdata/mockDepartments.ts b/frontend/mockdata/mockDepartments.ts deleted file mode 100644 index aa2d3db0..00000000 --- a/frontend/mockdata/mockDepartments.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Department, Consultant } from "@/types"; - -export const MockDepartments: Department[] = [ - { - id: "myDepartment", - name: "My Department", - }, -]; diff --git a/frontend/src/data/fetchWithToken.ts b/frontend/src/data/fetchWithToken.ts index 16466fef..6e680f9b 100644 --- a/frontend/src/data/fetchWithToken.ts +++ b/frontend/src/data/fetchWithToken.ts @@ -1,9 +1,12 @@ -import { MockConsultants } from "../../mockdata/mockConsultants"; -import { MockDepartments } from "../../mockdata/mockDepartments"; import { authOptions, getCustomServerSession, } from "@/app/api/auth/[...nextauth]/route"; +import { + MockConsultants, + MockDepartments, + MockOrganisations, +} from "../../mockdata/mockData"; export async function fetchWithToken(path: string): Promise { if (process.env.NEXT_PUBLIC_NO_AUTH) { @@ -42,5 +45,8 @@ function mockedCall(path: string): Promise { if (path.includes("departments")) { resolve(MockDepartments as T); } + if (path.includes("organisations")) { + resolve(MockOrganisations as T); + } }); } diff --git a/frontend/src/types.ts b/frontend/src/types.ts index 583da473..65dffa48 100644 --- a/frontend/src/types.ts +++ b/frontend/src/types.ts @@ -19,6 +19,6 @@ export type Department = { }; export type Organisation = { - name: string, - urlKey: string -} + name: string; + urlKey: string; +}; diff --git a/frontend/tests/consultant-list.spec.ts b/frontend/tests/consultant-list.spec.ts index 7b3401b7..35595b61 100644 --- a/frontend/tests/consultant-list.spec.ts +++ b/frontend/tests/consultant-list.spec.ts @@ -1,7 +1,10 @@ import { test, expect } from "@playwright/test"; -test("has title", async ({ page }) => { +test("Has organisation index page", async ({ page }) => { await page.goto("/"); + const orgLink = page.getByText("My Organisation"); + await orgLink.click(); + const consultantName = page.getByText("Test Consultant"); await expect(consultantName).toBeVisible(); From 2ac458a427de20f0fa49fcc667342fd655b6d29c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B8ralt?= Date: Thu, 19 Oct 2023 11:43:09 +0200 Subject: [PATCH 25/26] fix import --- frontend/src/data/fetchWithToken.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/frontend/src/data/fetchWithToken.ts b/frontend/src/data/fetchWithToken.ts index 6e680f9b..1c3bc36c 100644 --- a/frontend/src/data/fetchWithToken.ts +++ b/frontend/src/data/fetchWithToken.ts @@ -2,11 +2,8 @@ import { authOptions, getCustomServerSession, } from "@/app/api/auth/[...nextauth]/route"; -import { - MockConsultants, - MockDepartments, - MockOrganisations, -} from "../../mockdata/mockData"; +import { MockConsultants, MockDepartments, MockOrganisations } from "../../mockdata/mockData"; + export async function fetchWithToken(path: string): Promise { if (process.env.NEXT_PUBLIC_NO_AUTH) { From 563535df788bb40733bb6edd55ac902a6a7df3f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20Bj=C3=B8ralt?= Date: Thu, 19 Oct 2023 12:19:44 +0200 Subject: [PATCH 26/26] prettier --- frontend/src/data/fetchWithToken.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/frontend/src/data/fetchWithToken.ts b/frontend/src/data/fetchWithToken.ts index 1c3bc36c..6e680f9b 100644 --- a/frontend/src/data/fetchWithToken.ts +++ b/frontend/src/data/fetchWithToken.ts @@ -2,8 +2,11 @@ import { authOptions, getCustomServerSession, } from "@/app/api/auth/[...nextauth]/route"; -import { MockConsultants, MockDepartments, MockOrganisations } from "../../mockdata/mockData"; - +import { + MockConsultants, + MockDepartments, + MockOrganisations, +} from "../../mockdata/mockData"; export async function fetchWithToken(path: string): Promise { if (process.env.NEXT_PUBLIC_NO_AUTH) {