From 80d5ea5d9670fdba75a076d00c1a4320c01adf2f Mon Sep 17 00:00:00 2001 From: Paul Frank Date: Sun, 19 Nov 2023 23:52:47 +0100 Subject: [PATCH 1/8] bookings crud WORKING --- .../Repositories/BookingRepository.cs | 4 +- .../Repositories/GenericRepository.cs | 19 +- .../Dtos/BookingDtos/BookingDto.cs | 4 +- .../Dtos/BookingDtos/CreateBookingDto.cs | 5 +- .../Dtos/BookingDtos/UpdateBookingDto.cs | 2 +- ...21110_AmountOfPeopleInBookings.Designer.cs | 279 ++++++++++++++++++ ...20231119221110_AmountOfPeopleInBookings.cs | 26 ++ .../TableBookingContextModelSnapshot.cs | 13 +- .../TableBooking.Model/Models/Booking.cs | 2 +- .../TableBooking.Model/Models/Table.cs | 2 +- .../Controllers/BookingController.cs | 7 +- .../Interfaces/IBookingService.cs | 2 +- .../TableBooking/Services/BookingService.cs | 32 +- 13 files changed, 369 insertions(+), 28 deletions(-) create mode 100644 TableBookingAPI/TableBooking.Model/Migrations/20231119221110_AmountOfPeopleInBookings.Designer.cs create mode 100644 TableBookingAPI/TableBooking.Model/Migrations/20231119221110_AmountOfPeopleInBookings.cs diff --git a/TableBookingAPI/TableBooking.Logic/Repositories/BookingRepository.cs b/TableBookingAPI/TableBooking.Logic/Repositories/BookingRepository.cs index 816f627..accfd88 100644 --- a/TableBookingAPI/TableBooking.Logic/Repositories/BookingRepository.cs +++ b/TableBookingAPI/TableBooking.Logic/Repositories/BookingRepository.cs @@ -13,12 +13,12 @@ public BookingRepository(TableBookingContext context) : base(context) public async Task> GetAllBookingsForSpecificUserAsync(Guid userId) { - return await _objectSet.Where(x => x.Id.Equals(userId)).ToListAsync(); + return await _objectSet.Where(x => x.AppUserId.Equals(userId)).ToListAsync(); } public async Task GetBookingByIdForSpecificUserAsync(Guid bookingId, Guid userId) { - return await _objectSet.FirstOrDefaultAsync(x => x.Id.Equals(bookingId) && x.Id.Equals(userId)); + return await _objectSet.FirstOrDefaultAsync(x => x.Id.Equals(bookingId) && x.AppUserId.Equals(userId)); } } } diff --git a/TableBookingAPI/TableBooking.Logic/Repositories/GenericRepository.cs b/TableBookingAPI/TableBooking.Logic/Repositories/GenericRepository.cs index 765cf03..b0e30c3 100644 --- a/TableBookingAPI/TableBooking.Logic/Repositories/GenericRepository.cs +++ b/TableBookingAPI/TableBooking.Logic/Repositories/GenericRepository.cs @@ -35,10 +35,23 @@ public async Task Delete(object id) _objectSet.Remove(objectToDelete); } - public async virtual Task Update(T entity) + public async Task Update(T entity) { - await Update(entity); - } + var existingEntity = await _objectSet.FindAsync(GetKeyValues(entity)); + + if (existingEntity != null) + { + _context.Entry(existingEntity).State = EntityState.Detached; + } + _objectSet.Update(entity); + await _context.SaveChangesAsync(); + } + + private object[] GetKeyValues(T entity) + { + var keyProperties = _context.Model.FindEntityType(typeof(T)).FindPrimaryKey().Properties; + return keyProperties.Select(prop => prop.PropertyInfo.GetValue(entity)).ToArray(); + } } } diff --git a/TableBookingAPI/TableBooking.Model/Dtos/BookingDtos/BookingDto.cs b/TableBookingAPI/TableBooking.Model/Dtos/BookingDtos/BookingDto.cs index 10d7a02..e915bf4 100644 --- a/TableBookingAPI/TableBooking.Model/Dtos/BookingDtos/BookingDto.cs +++ b/TableBookingAPI/TableBooking.Model/Dtos/BookingDtos/BookingDto.cs @@ -7,7 +7,7 @@ public class BookingDto public Guid Id { get; set; } public DateTime Date { get; set; } public int DurationInMinutes { get; set; } - public TableDto TableDto { get; set; } - public Guid UserId { get; set; } + public int AmountOfPeople { get; set; } + public Guid AppUserId { get; set; } } } diff --git a/TableBookingAPI/TableBooking.Model/Dtos/BookingDtos/CreateBookingDto.cs b/TableBookingAPI/TableBooking.Model/Dtos/BookingDtos/CreateBookingDto.cs index 29a3186..b617ff3 100644 --- a/TableBookingAPI/TableBooking.Model/Dtos/BookingDtos/CreateBookingDto.cs +++ b/TableBookingAPI/TableBooking.Model/Dtos/BookingDtos/CreateBookingDto.cs @@ -1,9 +1,12 @@ -namespace TableBooking.Model.Dtos.BookingDtos +using TableBooking.Model.Models; + +namespace TableBooking.Model.Dtos.BookingDtos { public class CreateBookingDto { public DateTime Date { get; set; } public int DurationInMinutes { get; set; } + public int AmountOfPeople { get; set; } public Guid TableId { get; set; } } } \ No newline at end of file diff --git a/TableBookingAPI/TableBooking.Model/Dtos/BookingDtos/UpdateBookingDto.cs b/TableBookingAPI/TableBooking.Model/Dtos/BookingDtos/UpdateBookingDto.cs index ab13ae7..c9b5f86 100644 --- a/TableBookingAPI/TableBooking.Model/Dtos/BookingDtos/UpdateBookingDto.cs +++ b/TableBookingAPI/TableBooking.Model/Dtos/BookingDtos/UpdateBookingDto.cs @@ -4,6 +4,6 @@ public class UpdateBookingDto { public DateTime Date { get; set; } public int DurationInMinutes { get; set; } - public Guid TableId { get; set; } + public int AmountOfPeople { get; set; } } } diff --git a/TableBookingAPI/TableBooking.Model/Migrations/20231119221110_AmountOfPeopleInBookings.Designer.cs b/TableBookingAPI/TableBooking.Model/Migrations/20231119221110_AmountOfPeopleInBookings.Designer.cs new file mode 100644 index 0000000..d2f737f --- /dev/null +++ b/TableBookingAPI/TableBooking.Model/Migrations/20231119221110_AmountOfPeopleInBookings.Designer.cs @@ -0,0 +1,279 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using TableBooking.Model; + +#nullable disable + +namespace TableBooking.Model.Migrations +{ + [DbContext(typeof(TableBookingContext))] + [Migration("20231119221110_AmountOfPeopleInBookings")] + partial class AmountOfPeopleInBookings + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.15") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("TableBooking.Model.Models.AppUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .HasColumnType("text"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NormalizedEmail") + .HasColumnType("text"); + + b.Property("NormalizedUserName") + .HasColumnType("text"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("RefreshToken") + .HasColumnType("text"); + + b.Property("RefreshTokenExpiryTime") + .HasColumnType("timestamp with time zone"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("TableBooking.Model.Models.Booking", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AmountOfPeople") + .HasColumnType("integer"); + + b.Property("AppUserId") + .HasColumnType("uuid"); + + b.Property("Date") + .HasColumnType("timestamp with time zone"); + + b.Property("DurationInMinutes") + .HasColumnType("integer"); + + b.Property("TableId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AppUserId"); + + b.HasIndex("TableId"); + + b.ToTable("Bookings"); + }); + + modelBuilder.Entity("TableBooking.Model.Models.Rating", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AppUserId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("DateOfRating") + .HasColumnType("timestamp with time zone"); + + b.Property("NumberOfLikes") + .HasColumnType("integer"); + + b.Property("RatingStars") + .HasColumnType("integer"); + + b.Property("RestaurantId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AppUserId"); + + b.HasIndex("RestaurantId"); + + b.ToTable("Ratings"); + }); + + modelBuilder.Entity("TableBooking.Model.Models.Restaurant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CloseTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Location") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OpenTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Phone") + .IsRequired() + .HasColumnType("text"); + + b.Property("Price") + .HasColumnType("integer"); + + b.Property("PrimaryImageURL") + .HasColumnType("text"); + + b.Property("Rating") + .HasColumnType("real"); + + b.Property("SecondaryImageURL") + .HasColumnType("text"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Restaurants"); + }); + + modelBuilder.Entity("TableBooking.Model.Models.Table", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("NumberOfSeats") + .HasColumnType("integer"); + + b.Property("RestaurantId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("RestaurantId"); + + b.ToTable("Tables"); + }); + + modelBuilder.Entity("TableBooking.Model.Models.Booking", b => + { + b.HasOne("TableBooking.Model.Models.AppUser", null) + .WithMany("Bookings") + .HasForeignKey("AppUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("TableBooking.Model.Models.Table", "Table") + .WithMany("Bookings") + .HasForeignKey("TableId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Table"); + }); + + modelBuilder.Entity("TableBooking.Model.Models.Rating", b => + { + b.HasOne("TableBooking.Model.Models.AppUser", "AppUser") + .WithMany() + .HasForeignKey("AppUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("TableBooking.Model.Models.Restaurant", "Restaurant") + .WithMany() + .HasForeignKey("RestaurantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AppUser"); + + b.Navigation("Restaurant"); + }); + + modelBuilder.Entity("TableBooking.Model.Models.Table", b => + { + b.HasOne("TableBooking.Model.Models.Restaurant", null) + .WithMany("Tables") + .HasForeignKey("RestaurantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("TableBooking.Model.Models.AppUser", b => + { + b.Navigation("Bookings"); + }); + + modelBuilder.Entity("TableBooking.Model.Models.Restaurant", b => + { + b.Navigation("Tables"); + }); + + modelBuilder.Entity("TableBooking.Model.Models.Table", b => + { + b.Navigation("Bookings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/TableBookingAPI/TableBooking.Model/Migrations/20231119221110_AmountOfPeopleInBookings.cs b/TableBookingAPI/TableBooking.Model/Migrations/20231119221110_AmountOfPeopleInBookings.cs new file mode 100644 index 0000000..a92a1f1 --- /dev/null +++ b/TableBookingAPI/TableBooking.Model/Migrations/20231119221110_AmountOfPeopleInBookings.cs @@ -0,0 +1,26 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace TableBooking.Model.Migrations +{ + public partial class AmountOfPeopleInBookings : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "AmountOfPeople", + table: "Bookings", + type: "integer", + nullable: false, + defaultValue: 0); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "AmountOfPeople", + table: "Bookings"); + } + } +} diff --git a/TableBookingAPI/TableBooking.Model/Migrations/TableBookingContextModelSnapshot.cs b/TableBookingAPI/TableBooking.Model/Migrations/TableBookingContextModelSnapshot.cs index e277a52..04780a0 100644 --- a/TableBookingAPI/TableBooking.Model/Migrations/TableBookingContextModelSnapshot.cs +++ b/TableBookingAPI/TableBooking.Model/Migrations/TableBookingContextModelSnapshot.cs @@ -78,7 +78,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("Id"); - b.ToTable("Users"); + b.ToTable("Users", (string)null); }); modelBuilder.Entity("TableBooking.Model.Models.Booking", b => @@ -87,6 +87,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) .ValueGeneratedOnAdd() .HasColumnType("uuid"); + b.Property("AmountOfPeople") + .HasColumnType("integer"); + b.Property("AppUserId") .HasColumnType("uuid"); @@ -105,7 +108,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("TableId"); - b.ToTable("Bookings"); + b.ToTable("Bookings", (string)null); }); modelBuilder.Entity("TableBooking.Model.Models.Rating", b => @@ -139,7 +142,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("RestaurantId"); - b.ToTable("Ratings"); + b.ToTable("Ratings", (string)null); }); modelBuilder.Entity("TableBooking.Model.Models.Restaurant", b => @@ -187,7 +190,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("Id"); - b.ToTable("Restaurants"); + b.ToTable("Restaurants", (string)null); }); modelBuilder.Entity("TableBooking.Model.Models.Table", b => @@ -206,7 +209,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("RestaurantId"); - b.ToTable("Tables"); + b.ToTable("Tables", (string)null); }); modelBuilder.Entity("TableBooking.Model.Models.Booking", b => diff --git a/TableBookingAPI/TableBooking.Model/Models/Booking.cs b/TableBookingAPI/TableBooking.Model/Models/Booking.cs index 9fed1aa..5188adf 100644 --- a/TableBookingAPI/TableBooking.Model/Models/Booking.cs +++ b/TableBookingAPI/TableBooking.Model/Models/Booking.cs @@ -4,7 +4,7 @@ public class Booking : Entity { public DateTime Date { get; set; } public int DurationInMinutes { get; set; } - public Table Table { get; set; } + public int AmountOfPeople { get; set; } public Guid AppUserId { get; set; } public Guid TableId { get; set; } } diff --git a/TableBookingAPI/TableBooking.Model/Models/Table.cs b/TableBookingAPI/TableBooking.Model/Models/Table.cs index 9fa2ec6..9f27d05 100644 --- a/TableBookingAPI/TableBooking.Model/Models/Table.cs +++ b/TableBookingAPI/TableBooking.Model/Models/Table.cs @@ -4,6 +4,6 @@ public class Table : Entity { public int NumberOfSeats { get; set; } public Guid RestaurantId { get; set; } - public IEnumerable Bookings { get; set; } + public IEnumerable? Bookings { get; set; } } } diff --git a/TableBookingAPI/TableBooking/Controllers/BookingController.cs b/TableBookingAPI/TableBooking/Controllers/BookingController.cs index 908093b..e233306 100644 --- a/TableBookingAPI/TableBooking/Controllers/BookingController.cs +++ b/TableBookingAPI/TableBooking/Controllers/BookingController.cs @@ -60,14 +60,15 @@ public async Task DeleteUserBooking(Guid id) public async Task CreateUserBooking([FromBody] CreateBookingDto bookingToCreateDto) { var userId = Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)); + return await _bookingService.CreateBookingAsync(bookingToCreateDto, userId); } - [HttpPut("UpdateBooking/{id}")] - public async Task UpdateUserBooking([FromBody] UpdateBookingDto updateBookignDto, Guid tableId) + [HttpPut("UpdateBooking/{bookingId}")] + public async Task UpdateUserBooking([FromBody] UpdateBookingDto updateBookingDto, Guid bookingId) { var userId = Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)); - return await _bookingService.UpdateBookingAsync(updateBookignDto, userId); + return await _bookingService.UpdateBookingAsync(updateBookingDto, userId, bookingId); } } diff --git a/TableBookingAPI/TableBooking/Interfaces/IBookingService.cs b/TableBookingAPI/TableBooking/Interfaces/IBookingService.cs index 5fe65fb..e930ad2 100644 --- a/TableBookingAPI/TableBooking/Interfaces/IBookingService.cs +++ b/TableBookingAPI/TableBooking/Interfaces/IBookingService.cs @@ -8,7 +8,7 @@ public interface IBookingService public Task GetAllBookings(Guid userId); public Task GetBookingByIdAsync(Guid bookingId, Guid userId); public Task CreateBookingAsync(CreateBookingDto createBookingDto, Guid userId); - public Task UpdateBookingAsync(UpdateBookingDto updateBookingDto, Guid userId); + public Task UpdateBookingAsync(UpdateBookingDto updateBookingDto, Guid userId, Guid bookingId); public Task DeleteBookingAsync(Guid bookingId, Guid userId); } } diff --git a/TableBookingAPI/TableBooking/Services/BookingService.cs b/TableBookingAPI/TableBooking/Services/BookingService.cs index 83cd89b..787346b 100644 --- a/TableBookingAPI/TableBooking/Services/BookingService.cs +++ b/TableBookingAPI/TableBooking/Services/BookingService.cs @@ -30,7 +30,7 @@ public async Task CreateBookingAsync(CreateBookingDto request, Gu DurationInMinutes = request.DurationInMinutes, TableId = request.TableId, AppUserId = userId, - Table = table + AmountOfPeople = request.AmountOfPeople }; await _unitOfWork.BookingRepository.InsertAsync(newBooking); @@ -41,8 +41,8 @@ public async Task CreateBookingAsync(CreateBookingDto request, Gu Id = newBooking.Id, Date = newBooking.Date, DurationInMinutes = newBooking.DurationInMinutes, - TableDto = _tableConverter.TableToTableDto(newBooking.Table), - UserId = userId + AmountOfPeople = newBooking.AmountOfPeople, + AppUserId = userId }; return new CreatedResult(String.Empty, bookingDto); } @@ -53,7 +53,7 @@ public async Task DeleteBookingAsync(Guid bookingId, Guid userId) if (booking == null) return new BadRequestObjectResult("Bad request"); - await _unitOfWork.BookingRepository.Delete(booking); + await _unitOfWork.BookingRepository.Delete(booking.Id); await _unitOfWork.SaveChangesAsync(); return new NoContentResult(); } @@ -71,8 +71,8 @@ public async Task GetBookingByIdAsync(Guid bookingId, Guid userId Id = booking.Id, Date = booking.Date, DurationInMinutes = booking.DurationInMinutes, - TableDto = _tableConverter.TableToTableDto(booking.Table), - UserId = userId + AmountOfPeople = booking.AmountOfPeople, + AppUserId = userId }; return new OkObjectResult(bookingDto); } @@ -86,9 +86,25 @@ public async Task GetAllBookings(Guid userId) return new OkObjectResult(bookings); } - public async Task UpdateBookingAsync(UpdateBookingDto updateBookingDto, Guid userId) + public async Task UpdateBookingAsync(UpdateBookingDto updateBookingDto, Guid userId, Guid bookingId) { - return new OkObjectResult("XD"); + var booking = await _unitOfWork.BookingRepository.GetBookingByIdForSpecificUserAsync(bookingId, userId); + if (booking == null) + return new BadRequestObjectResult($"Booking with id {bookingId} doesn't exist."); + + var newBooking = new Booking + { + Id = booking.Id, + Date = updateBookingDto.Date, + DurationInMinutes = updateBookingDto.DurationInMinutes, + AmountOfPeople = updateBookingDto.AmountOfPeople, + TableId = booking.TableId, + AppUserId = userId + }; + + await _unitOfWork.BookingRepository.Update(newBooking); + + return new OkObjectResult(newBooking); } } } From 901a74bacbecb05e05a020ccc3dc244fc8a47560 Mon Sep 17 00:00:00 2001 From: Paul Frank Date: Mon, 20 Nov 2023 17:50:02 +0100 Subject: [PATCH 2/8] resolved Thomas comments --- .../TableBooking.Logic/Repositories/GenericRepository.cs | 1 - TableBookingAPI/TableBooking/Services/BookingService.cs | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/TableBookingAPI/TableBooking.Logic/Repositories/GenericRepository.cs b/TableBookingAPI/TableBooking.Logic/Repositories/GenericRepository.cs index b0e30c3..438fc49 100644 --- a/TableBookingAPI/TableBooking.Logic/Repositories/GenericRepository.cs +++ b/TableBookingAPI/TableBooking.Logic/Repositories/GenericRepository.cs @@ -45,7 +45,6 @@ public async Task Update(T entity) } _objectSet.Update(entity); - await _context.SaveChangesAsync(); } private object[] GetKeyValues(T entity) diff --git a/TableBookingAPI/TableBooking/Services/BookingService.cs b/TableBookingAPI/TableBooking/Services/BookingService.cs index 787346b..40721b3 100644 --- a/TableBookingAPI/TableBooking/Services/BookingService.cs +++ b/TableBookingAPI/TableBooking/Services/BookingService.cs @@ -103,7 +103,8 @@ public async Task UpdateBookingAsync(UpdateBookingDto updateBooki }; await _unitOfWork.BookingRepository.Update(newBooking); - + await _unitOfWork.SaveChangesAsync(); + return new OkObjectResult(newBooking); } } From 5914b2f9a9ebaad5c161c753267bf9b266cb7afc Mon Sep 17 00:00:00 2001 From: Paul Frank Date: Mon, 27 Nov 2023 19:22:38 +0100 Subject: [PATCH 3/8] =?UTF-8?q?Delete=20tableId=20when=20creating=20bookin?= =?UTF-8?q?g=20=F0=9F=A4=A6=E2=80=8D=E2=99=82=EF=B8=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TableBooking.Model/Dtos/BookingDtos/CreateBookingDto.cs | 1 - TableBookingAPI/TableBooking/Services/BookingService.cs | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/TableBookingAPI/TableBooking.Model/Dtos/BookingDtos/CreateBookingDto.cs b/TableBookingAPI/TableBooking.Model/Dtos/BookingDtos/CreateBookingDto.cs index b617ff3..05986a5 100644 --- a/TableBookingAPI/TableBooking.Model/Dtos/BookingDtos/CreateBookingDto.cs +++ b/TableBookingAPI/TableBooking.Model/Dtos/BookingDtos/CreateBookingDto.cs @@ -7,6 +7,5 @@ public class CreateBookingDto public DateTime Date { get; set; } public int DurationInMinutes { get; set; } public int AmountOfPeople { get; set; } - public Guid TableId { get; set; } } } \ No newline at end of file diff --git a/TableBookingAPI/TableBooking/Services/BookingService.cs b/TableBookingAPI/TableBooking/Services/BookingService.cs index 40721b3..e09b987 100644 --- a/TableBookingAPI/TableBooking/Services/BookingService.cs +++ b/TableBookingAPI/TableBooking/Services/BookingService.cs @@ -22,13 +22,11 @@ public BookingService(IUnitOfWork unitOfWork, ITableConverter tableConverter, IT } public async Task CreateBookingAsync(CreateBookingDto request, Guid userId) { - var table = await _tableService.GetTableObjectByIdAsync(request.TableId); - var newBooking = new Booking { Date = request.Date, DurationInMinutes = request.DurationInMinutes, - TableId = request.TableId, + TableId = Guid.NewGuid(), AppUserId = userId, AmountOfPeople = request.AmountOfPeople }; From 86b899e3513ba1c1cdf8055fa020d9aa32650d73 Mon Sep 17 00:00:00 2001 From: Tomo2433 Date: Fri, 1 Dec 2023 22:18:12 +0100 Subject: [PATCH 4/8] restaurant avarage rating added --- TableBookingAPI/TableBooking/Program.cs | 1 + .../TableBooking/Services/RatingService.cs | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/TableBookingAPI/TableBooking/Program.cs b/TableBookingAPI/TableBooking/Program.cs index 3c38987..78004a9 100644 --- a/TableBookingAPI/TableBooking/Program.cs +++ b/TableBookingAPI/TableBooking/Program.cs @@ -142,6 +142,7 @@ app.UseSwagger(); app.UseSwaggerUI(); } +AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true); app.UseSerilogRequestLogging(); app.MapHealthChecks("/healthz"); //.RequireHost("*:5001").RequireAuthorization(); diff --git a/TableBookingAPI/TableBooking/Services/RatingService.cs b/TableBookingAPI/TableBooking/Services/RatingService.cs index fa72769..6c1ebde 100644 --- a/TableBookingAPI/TableBooking/Services/RatingService.cs +++ b/TableBookingAPI/TableBooking/Services/RatingService.cs @@ -34,6 +34,18 @@ public async Task CreateRatingAsync(CreateRatingDto dto) await _unitOfWork.RatingRepository.InsertAsync(rating); await _unitOfWork.SaveChangesAsync(); + var ratings = await _unitOfWork.RatingRepository.GetRatingsAsync(dto.RestaurantId) ; + var numberOfRaitings = ratings.Count(); + var result = 0d; + + if (numberOfRaitings > 0 && numberOfRaitings % 5 == 0) + { + result = ratings.Select(x => x.RatingStars).Average(); + restaurant.Rating = (float)result; + await _unitOfWork.RestaurantRepository.Update(restaurant); + await _unitOfWork.SaveChangesAsync(); + } + return new OkObjectResult(_ratingConverter.RatingToRatingDto(rating)); } From 74b66eddc67e7f62b4942d9cf2582783c39e9172 Mon Sep 17 00:00:00 2001 From: Tomo2433 Date: Sat, 2 Dec 2023 18:25:12 +0100 Subject: [PATCH 5/8] app roles added --- ..._restaurant_rating_and_approle.Designer.cs | 314 ++++++++++++++++++ ...202144812_restaurant_rating_and_approle.cs | 85 +++++ .../TableBookingContextModelSnapshot.cs | 55 ++- .../TableBooking.Model/Models/AppRole.cs | 7 - .../TableBooking.Model/Models/AppUser.cs | 2 + .../TableBooking.Model/Models/Restaurant.cs | 7 +- .../TableBooking.Model/Seed/seed.sql | 44 ++- .../TableBooking.Model/TableBookingContext.cs | 1 + .../Controllers/RestaurantController.cs | 1 + TableBookingAPI/TableBooking/Program.cs | 1 + .../TableBooking/Services/RatingService.cs | 2 +- .../TableBooking/Services/UserService.cs | 16 +- 12 files changed, 502 insertions(+), 33 deletions(-) create mode 100644 TableBookingAPI/TableBooking.Model/Migrations/20231202144812_restaurant_rating_and_approle.Designer.cs create mode 100644 TableBookingAPI/TableBooking.Model/Migrations/20231202144812_restaurant_rating_and_approle.cs diff --git a/TableBookingAPI/TableBooking.Model/Migrations/20231202144812_restaurant_rating_and_approle.Designer.cs b/TableBookingAPI/TableBooking.Model/Migrations/20231202144812_restaurant_rating_and_approle.Designer.cs new file mode 100644 index 0000000..f19146e --- /dev/null +++ b/TableBookingAPI/TableBooking.Model/Migrations/20231202144812_restaurant_rating_and_approle.Designer.cs @@ -0,0 +1,314 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; +using TableBooking.Model; + +#nullable disable + +namespace TableBooking.Model.Migrations +{ + [DbContext(typeof(TableBookingContext))] + [Migration("20231202144812_restaurant_rating_and_approle")] + partial class restaurant_rating_and_approle + { + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "6.0.15") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("TableBooking.Model.Models.AppRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("NormalizedName") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Roles"); + }); + + modelBuilder.Entity("TableBooking.Model.Models.AppUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("AppRoleId") + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .HasColumnType("text"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("NormalizedEmail") + .HasColumnType("text"); + + b.Property("NormalizedUserName") + .HasColumnType("text"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("RefreshToken") + .HasColumnType("text"); + + b.Property("RefreshTokenExpiryTime") + .HasColumnType("timestamp with time zone"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("AppRoleId"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("TableBooking.Model.Models.Booking", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AmountOfPeople") + .HasColumnType("integer"); + + b.Property("AppUserId") + .HasColumnType("uuid"); + + b.Property("Date") + .HasColumnType("timestamp with time zone"); + + b.Property("DurationInMinutes") + .HasColumnType("integer"); + + b.Property("TableId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AppUserId"); + + b.HasIndex("TableId"); + + b.ToTable("Bookings"); + }); + + modelBuilder.Entity("TableBooking.Model.Models.Rating", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AppUserId") + .HasColumnType("uuid"); + + b.Property("Comment") + .IsRequired() + .HasColumnType("text"); + + b.Property("DateOfRating") + .HasColumnType("timestamp with time zone"); + + b.Property("NumberOfLikes") + .HasColumnType("integer"); + + b.Property("RatingStars") + .HasColumnType("integer"); + + b.Property("RestaurantId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("AppUserId"); + + b.HasIndex("RestaurantId"); + + b.ToTable("Ratings"); + }); + + modelBuilder.Entity("TableBooking.Model.Models.Restaurant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CloseTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Location") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("OpenTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Phone") + .IsRequired() + .HasColumnType("text"); + + b.Property("Price") + .HasColumnType("integer"); + + b.Property("PrimaryImageURL") + .HasColumnType("text"); + + b.Property("Rating") + .HasPrecision(1, 1) + .HasColumnType("double precision"); + + b.Property("SecondaryImageURL") + .HasColumnType("text"); + + b.Property("Type") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Restaurants"); + }); + + modelBuilder.Entity("TableBooking.Model.Models.Table", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("NumberOfSeats") + .HasColumnType("integer"); + + b.Property("RestaurantId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("RestaurantId"); + + b.ToTable("Tables"); + }); + + modelBuilder.Entity("TableBooking.Model.Models.AppUser", b => + { + b.HasOne("TableBooking.Model.Models.AppRole", "AppRole") + .WithMany() + .HasForeignKey("AppRoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AppRole"); + }); + + modelBuilder.Entity("TableBooking.Model.Models.Booking", b => + { + b.HasOne("TableBooking.Model.Models.AppUser", null) + .WithMany("Bookings") + .HasForeignKey("AppUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("TableBooking.Model.Models.Table", null) + .WithMany("Bookings") + .HasForeignKey("TableId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("TableBooking.Model.Models.Rating", b => + { + b.HasOne("TableBooking.Model.Models.AppUser", "AppUser") + .WithMany() + .HasForeignKey("AppUserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("TableBooking.Model.Models.Restaurant", "Restaurant") + .WithMany() + .HasForeignKey("RestaurantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AppUser"); + + b.Navigation("Restaurant"); + }); + + modelBuilder.Entity("TableBooking.Model.Models.Table", b => + { + b.HasOne("TableBooking.Model.Models.Restaurant", null) + .WithMany("Tables") + .HasForeignKey("RestaurantId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("TableBooking.Model.Models.AppUser", b => + { + b.Navigation("Bookings"); + }); + + modelBuilder.Entity("TableBooking.Model.Models.Restaurant", b => + { + b.Navigation("Tables"); + }); + + modelBuilder.Entity("TableBooking.Model.Models.Table", b => + { + b.Navigation("Bookings"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/TableBookingAPI/TableBooking.Model/Migrations/20231202144812_restaurant_rating_and_approle.cs b/TableBookingAPI/TableBooking.Model/Migrations/20231202144812_restaurant_rating_and_approle.cs new file mode 100644 index 0000000..bd6d328 --- /dev/null +++ b/TableBookingAPI/TableBooking.Model/Migrations/20231202144812_restaurant_rating_and_approle.cs @@ -0,0 +1,85 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace TableBooking.Model.Migrations +{ + public partial class restaurant_rating_and_approle : Migration + { + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "AppRoleId", + table: "Users", + type: "uuid", + nullable: false, + defaultValue: new Guid("00000000-0000-0000-0000-000000000000")); + + migrationBuilder.AlterColumn( + name: "Rating", + table: "Restaurants", + type: "double precision", + precision: 1, + scale: 1, + nullable: false, + oldClrType: typeof(float), + oldType: "real"); + + migrationBuilder.CreateTable( + name: "Roles", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + Name = table.Column(type: "text", nullable: true), + NormalizedName = table.Column(type: "text", nullable: true), + ConcurrencyStamp = table.Column(type: "text", nullable: true) + }, + constraints: table => + { + table.PrimaryKey("PK_Roles", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_Users_AppRoleId", + table: "Users", + column: "AppRoleId"); + + migrationBuilder.AddForeignKey( + name: "FK_Users_Roles_AppRoleId", + table: "Users", + column: "AppRoleId", + principalTable: "Roles", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); + } + + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropForeignKey( + name: "FK_Users_Roles_AppRoleId", + table: "Users"); + + migrationBuilder.DropTable( + name: "Roles"); + + migrationBuilder.DropIndex( + name: "IX_Users_AppRoleId", + table: "Users"); + + migrationBuilder.DropColumn( + name: "AppRoleId", + table: "Users"); + + migrationBuilder.AlterColumn( + name: "Rating", + table: "Restaurants", + type: "real", + nullable: false, + oldClrType: typeof(double), + oldType: "double precision", + oldPrecision: 1, + oldScale: 1); + } + } +} diff --git a/TableBookingAPI/TableBooking.Model/Migrations/TableBookingContextModelSnapshot.cs b/TableBookingAPI/TableBooking.Model/Migrations/TableBookingContextModelSnapshot.cs index 04780a0..e2676ef 100644 --- a/TableBookingAPI/TableBooking.Model/Migrations/TableBookingContextModelSnapshot.cs +++ b/TableBookingAPI/TableBooking.Model/Migrations/TableBookingContextModelSnapshot.cs @@ -22,6 +22,26 @@ protected override void BuildModel(ModelBuilder modelBuilder) NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + modelBuilder.Entity("TableBooking.Model.Models.AppRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("NormalizedName") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Roles"); + }); + modelBuilder.Entity("TableBooking.Model.Models.AppUser", b => { b.Property("Id") @@ -31,6 +51,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("AccessFailedCount") .HasColumnType("integer"); + b.Property("AppRoleId") + .HasColumnType("uuid"); + b.Property("ConcurrencyStamp") .HasColumnType("text"); @@ -78,7 +101,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("Id"); - b.ToTable("Users", (string)null); + b.HasIndex("AppRoleId"); + + b.ToTable("Users"); }); modelBuilder.Entity("TableBooking.Model.Models.Booking", b => @@ -108,7 +133,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("TableId"); - b.ToTable("Bookings", (string)null); + b.ToTable("Bookings"); }); modelBuilder.Entity("TableBooking.Model.Models.Rating", b => @@ -142,7 +167,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("RestaurantId"); - b.ToTable("Ratings", (string)null); + b.ToTable("Ratings"); }); modelBuilder.Entity("TableBooking.Model.Models.Restaurant", b => @@ -178,8 +203,9 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.Property("PrimaryImageURL") .HasColumnType("text"); - b.Property("Rating") - .HasColumnType("real"); + b.Property("Rating") + .HasPrecision(1, 1) + .HasColumnType("double precision"); b.Property("SecondaryImageURL") .HasColumnType("text"); @@ -190,7 +216,7 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasKey("Id"); - b.ToTable("Restaurants", (string)null); + b.ToTable("Restaurants"); }); modelBuilder.Entity("TableBooking.Model.Models.Table", b => @@ -209,7 +235,18 @@ protected override void BuildModel(ModelBuilder modelBuilder) b.HasIndex("RestaurantId"); - b.ToTable("Tables", (string)null); + b.ToTable("Tables"); + }); + + modelBuilder.Entity("TableBooking.Model.Models.AppUser", b => + { + b.HasOne("TableBooking.Model.Models.AppRole", "AppRole") + .WithMany() + .HasForeignKey("AppRoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AppRole"); }); modelBuilder.Entity("TableBooking.Model.Models.Booking", b => @@ -220,13 +257,11 @@ protected override void BuildModel(ModelBuilder modelBuilder) .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - b.HasOne("TableBooking.Model.Models.Table", "Table") + b.HasOne("TableBooking.Model.Models.Table", null) .WithMany("Bookings") .HasForeignKey("TableId") .OnDelete(DeleteBehavior.Cascade) .IsRequired(); - - b.Navigation("Table"); }); modelBuilder.Entity("TableBooking.Model.Models.Rating", b => diff --git a/TableBookingAPI/TableBooking.Model/Models/AppRole.cs b/TableBookingAPI/TableBooking.Model/Models/AppRole.cs index ec53207..b3f471d 100644 --- a/TableBookingAPI/TableBooking.Model/Models/AppRole.cs +++ b/TableBookingAPI/TableBooking.Model/Models/AppRole.cs @@ -4,12 +4,5 @@ namespace TableBooking.Model.Models { public class AppRole : IdentityRole { - public AppRole() - { - } - public AppRole(string roleName) - { - Name = roleName; - } } } \ No newline at end of file diff --git a/TableBookingAPI/TableBooking.Model/Models/AppUser.cs b/TableBookingAPI/TableBooking.Model/Models/AppUser.cs index d863b2f..8a3c101 100644 --- a/TableBookingAPI/TableBooking.Model/Models/AppUser.cs +++ b/TableBookingAPI/TableBooking.Model/Models/AppUser.cs @@ -7,5 +7,7 @@ public class AppUser : IdentityUser public string? RefreshToken { get; set; } public DateTime? RefreshTokenExpiryTime { get; set; } public IEnumerable Bookings { get; set; } + public Guid AppRoleId { get; set; } + public AppRole AppRole { get; set; } } } \ No newline at end of file diff --git a/TableBookingAPI/TableBooking.Model/Models/Restaurant.cs b/TableBookingAPI/TableBooking.Model/Models/Restaurant.cs index b1906e4..aa3ae99 100644 --- a/TableBookingAPI/TableBooking.Model/Models/Restaurant.cs +++ b/TableBookingAPI/TableBooking.Model/Models/Restaurant.cs @@ -1,4 +1,6 @@ -namespace TableBooking.Model.Models +using Microsoft.EntityFrameworkCore; + +namespace TableBooking.Model.Models { public enum Price { @@ -15,7 +17,8 @@ public class Restaurant : Entity public string Phone { get; set; } public string? PrimaryImageURL { get; set; } public string? SecondaryImageURL { get; set; } - public float Rating { get; set; } + [Precision(1,1)] + public double Rating { get; set; } public Price Price { get; set; } public DateTime OpenTime { get; set; } public DateTime CloseTime { get; set; } diff --git a/TableBookingAPI/TableBooking.Model/Seed/seed.sql b/TableBookingAPI/TableBooking.Model/Seed/seed.sql index e254139..4e20519 100644 --- a/TableBookingAPI/TableBooking.Model/Seed/seed.sql +++ b/TableBookingAPI/TableBooking.Model/Seed/seed.sql @@ -12,7 +12,7 @@ CREATE TABLE IF NOT EXISTS "Restaurants" ( "PrimaryImageURL" TEXT, "SecondaryImageURL" TEXT, "Price" INT, - "Rating" INT, + "Rating" DOUBLE PRECISION, "Phone" VARCHAR(20) ); @@ -23,6 +23,14 @@ CREATE TABLE IF NOT EXISTS "Tables" ( "RestaurantId" UUID REFERENCES "Restaurants"("Id") ); +-- Create Role table +CREATE TABLE IF NOT EXISTS "Roles" ( + "Id" UUID PRIMARY KEY, + "Name" VARCHAR(30), + "NormalizedName" VARCHAR(255), + "ConcurrencyStamp" VARCHAR(255) +); + -- Create Users table CREATE TABLE IF NOT EXISTS "Users" ( "Id" UUID PRIMARY KEY, @@ -41,7 +49,8 @@ CREATE TABLE IF NOT EXISTS "Users" ( "TwoFactorEnabled" BOOLEAN, "LockoutEnd" TIMESTAMPTZ, "LockoutEnabled" BOOLEAN, - "AccessFailedCount" INT + "AccessFailedCount" INT, + "AppRoleId" UUID REFERENCES "Roles"("Id") ); -- Create Bookings table @@ -88,6 +97,17 @@ INSERT INTO "Tables" ("Id","NumberOfSeats", "RestaurantId") VALUES ('423d89b6-1d INSERT INTO "Tables" ("Id","NumberOfSeats", "RestaurantId") VALUES ('840fffa7-ba45-4f44-a139-d794dcc4c647',4, 'a7f7be1c-adae-40df-b315-f772857936d5'); INSERT INTO "Tables" ("Id","NumberOfSeats", "RestaurantId") VALUES ('d3f5aa07-4803-4008-8fed-7fa6a4de5fe6',8, 'a7f7be1c-adae-40df-b315-f772857936d5'); +--Seed Roles records +INSERT INTO "Roles"( + "Id", "Name", "NormalizedName", "ConcurrencyStamp") + VALUES ('65329b28-837c-46cb-8f3c-e2ce20a81cac', 'Admin', 'admin', 'xd1'); +INSERT INTO "Roles"( + "Id", "Name", "NormalizedName", "ConcurrencyStamp") + VALUES ('5ad1268f-f61f-4b1c-b690-cbf8c3d35019', 'User', 'user', 'xd2'); +INSERT INTO "Roles"( + "Id", "Name", "NormalizedName", "ConcurrencyStamp") + VALUES ('6e380994-fb58-4364-aeaa-83f7a06e1cc2', 'Restaurant', 'restaurant', 'xd3'); + -- seed Users records INSERT INTO "Users" ( "Id", @@ -106,7 +126,8 @@ INSERT INTO "Users" ( "TwoFactorEnabled", "LockoutEnd", "LockoutEnabled", - "AccessFailedCount" + "AccessFailedCount", + "AppRoleId" ) VALUES ( 'abc663f0-08b1-4c52-afe4-1d446b11017f', 'refreshtoken1', @@ -124,7 +145,8 @@ INSERT INTO "Users" ( FALSE, '2023-10-12 14:30:00+00'::timestamptz, TRUE, - 0 + 0, + '65329b28-837c-46cb-8f3c-e2ce20a81cac' ); INSERT INTO "Users" ( @@ -144,7 +166,8 @@ INSERT INTO "Users" ( "TwoFactorEnabled", "LockoutEnd", "LockoutEnabled", - "AccessFailedCount" + "AccessFailedCount", + "AppRoleId" ) VALUES ( '123663f0-08b1-4c52-afe4-1d446b11017f', 'refreshtoken2', @@ -162,7 +185,8 @@ INSERT INTO "Users" ( TRUE, '2023-10-12 14:30:00+00'::timestamptz, TRUE, - 2 + 2, + '5ad1268f-f61f-4b1c-b690-cbf8c3d35019' ); -- seed Bookings records @@ -170,11 +194,11 @@ INSERT INTO "Bookings" ("Id", "Date", "DurationInMinutes", "UserId", "TableId") INSERT INTO "Bookings" ("Id", "Date", "DurationInMinutes", "UserId", "TableId") VALUES ('c4c4a1c0-3cb4-445e-ba81-311a6b939b4a','2050-05-07 20:15:00+00', 3, '123663f0-08b1-4c52-afe4-1d446b11017f', '3eb2eb68-a47e-47cd-8a22-06c20197a0b3'); -- Seed Users records -INSERT INTO "Users" ("Id", "RefreshToken", "RefreshTokenExpiryTime", "UserName", "NormalizedUserName", "Email", "NormalizedEmail", "EmailConfirmed", "PasswordHash", "SecurityStamp", "ConcurrencyStamp", "PhoneNumber", "PhoneNumberConfirmed", "TwoFactorEnabled", "LockoutEnd", "LockoutEnabled", "AccessFailedCount") -VALUES ('e8213e4a-c336-4345-b93e-26231379acda', 'refreshtoken1', '2023-11-12 00:00:00+00', 'user uno', 'normalized user uno name', 'email1', 'normalized_email1', FALSE, 'hashpasswd1', 'securitystamp1', 'concurrencystamp1', '123-456-789', FALSE, TRUE, '2023-10-12 14:30:00+00', TRUE, 0); +INSERT INTO "Users" ("Id", "RefreshToken", "RefreshTokenExpiryTime", "UserName", "NormalizedUserName", "Email", "NormalizedEmail", "EmailConfirmed", "PasswordHash", "SecurityStamp", "ConcurrencyStamp", "PhoneNumber", "PhoneNumberConfirmed", "TwoFactorEnabled", "LockoutEnd", "LockoutEnabled", "AccessFailedCount", "AppRoleId") +VALUES ('e8213e4a-c336-4345-b93e-26231379acda', 'refreshtoken1', '2023-11-12 00:00:00+00', 'user uno', 'normalized user uno name', 'email1', 'normalized_email1', FALSE, 'hashpasswd1', 'securitystamp1', 'concurrencystamp1', '123-456-789', FALSE, TRUE, '2023-10-12 14:30:00+00', TRUE, 0, '5ad1268f-f61f-4b1c-b690-cbf8c3d35019'); -INSERT INTO "Users" ("Id", "RefreshToken", "RefreshTokenExpiryTime", "UserName", "NormalizedUserName", "Email", "NormalizedEmail", "EmailConfirmed", "PasswordHash", "SecurityStamp", "ConcurrencyStamp", "PhoneNumber", "PhoneNumberConfirmed", "TwoFactorEnabled", "LockoutEnd", "LockoutEnabled", "AccessFailedCount") -VALUES ('c52fd4e3-1e46-4c38-84cc-d686800b425c', 'refreshtoken2', '2023-11-12 00:00:00+00', 'user nienazarty', 'normalized user nienazarty name', 'email2', 'normalized_email2', TRUE, 'hashpasswd2', 'securitystamp2', 'concurrencystamp2', '123-333-789', TRUE, FALSE, '2023-10-12 14:30:00+00', TRUE, 2); +INSERT INTO "Users" ("Id", "RefreshToken", "RefreshTokenExpiryTime", "UserName", "NormalizedUserName", "Email", "NormalizedEmail", "EmailConfirmed", "PasswordHash", "SecurityStamp", "ConcurrencyStamp", "PhoneNumber", "PhoneNumberConfirmed", "TwoFactorEnabled", "LockoutEnd", "LockoutEnabled", "AccessFailedCount", "AppRoleId") +VALUES ('c52fd4e3-1e46-4c38-84cc-d686800b425c', 'refreshtoken2', '2023-11-12 00:00:00+00', 'user nienazarty', 'normalized user nienazarty name', 'email2', 'normalized_email2', TRUE, 'hashpasswd2', 'securitystamp2', 'concurrencystamp2', '123-333-789', TRUE, FALSE, '2023-10-12 14:30:00+00', TRUE, 2, '6e380994-fb58-4364-aeaa-83f7a06e1cc2'); -- seed Ratings records INSERT INTO "Ratings"( diff --git a/TableBookingAPI/TableBooking.Model/TableBookingContext.cs b/TableBookingAPI/TableBooking.Model/TableBookingContext.cs index 68ce0ab..ec51b0e 100644 --- a/TableBookingAPI/TableBooking.Model/TableBookingContext.cs +++ b/TableBookingAPI/TableBooking.Model/TableBookingContext.cs @@ -29,6 +29,7 @@ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) public DbSet Tables { get; set; } public DbSet Ratings { get; set; } public DbSet Users { get; set; } + public DbSet Roles { get; set; } } } \ No newline at end of file diff --git a/TableBookingAPI/TableBooking/Controllers/RestaurantController.cs b/TableBookingAPI/TableBooking/Controllers/RestaurantController.cs index 314a9d8..b64f9e2 100644 --- a/TableBookingAPI/TableBooking/Controllers/RestaurantController.cs +++ b/TableBookingAPI/TableBooking/Controllers/RestaurantController.cs @@ -1,3 +1,4 @@ +using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using TableBooking.Api.Interfaces; using TableBooking.Model.Dtos.RestaurantDtos; diff --git a/TableBookingAPI/TableBooking/Program.cs b/TableBookingAPI/TableBooking/Program.cs index 78004a9..b686004 100644 --- a/TableBookingAPI/TableBooking/Program.cs +++ b/TableBookingAPI/TableBooking/Program.cs @@ -121,6 +121,7 @@ { options.User.RequireUniqueEmail = true; options.ClaimsIdentity.UserIdClaimType = ClaimTypes.NameIdentifier; + options.ClaimsIdentity.RoleClaimType = ClaimTypes.Role; }); builder.Services.AddScoped(); diff --git a/TableBookingAPI/TableBooking/Services/RatingService.cs b/TableBookingAPI/TableBooking/Services/RatingService.cs index 6c1ebde..153ba9c 100644 --- a/TableBookingAPI/TableBooking/Services/RatingService.cs +++ b/TableBookingAPI/TableBooking/Services/RatingService.cs @@ -41,7 +41,7 @@ public async Task CreateRatingAsync(CreateRatingDto dto) if (numberOfRaitings > 0 && numberOfRaitings % 5 == 0) { result = ratings.Select(x => x.RatingStars).Average(); - restaurant.Rating = (float)result; + restaurant.Rating = result; await _unitOfWork.RestaurantRepository.Update(restaurant); await _unitOfWork.SaveChangesAsync(); } diff --git a/TableBookingAPI/TableBooking/Services/UserService.cs b/TableBookingAPI/TableBooking/Services/UserService.cs index 1e66196..6f3d220 100644 --- a/TableBookingAPI/TableBooking/Services/UserService.cs +++ b/TableBookingAPI/TableBooking/Services/UserService.cs @@ -17,6 +17,7 @@ public class UserService : IUserService private readonly UserManager _userManager; private readonly RoleManager _roleManager; private readonly IConfiguration _configuration; + private readonly string userRoleId = "5ad1268f-f61f-4b1c-b690-cbf8c3d35019"; public UserService( UserManager userManager, @@ -35,31 +36,40 @@ public async Task Register(UserRegisterDto dto) if (userExists != null) return new BadRequestObjectResult("Bad request: Registration failed"); + var appUserRole = await _roleManager.FindByIdAsync(userRoleId); + if (appUserRole == null) + return new BadRequestObjectResult("Bad request: Registration failed"); + var user = new AppUser() { Email = dto.Email, SecurityStamp = Guid.NewGuid().ToString(), - UserName = dto.Username + UserName = dto.Username, + AppRoleId = appUserRole.Id }; + var result = await _userManager.CreateAsync(user, dto.Password); if (!result.Succeeded) - return new BadRequestObjectResult("Invalid password lenght"); + return new BadRequestObjectResult("Invalid password lenght Or Bad Email"); return new OkObjectResult(new ResultDto { Status = "Success", Message = "User created successfully!" }); } public async Task Login(UserLoginDto dto) { - var user = await _userManager.FindByNameAsync(dto.Username); + var user = await _userManager.FindByNameAsync(dto.Username) ; if (user == null || !await _userManager.CheckPasswordAsync(user, dto.Password)) { return new UnauthorizedResult(); } + var role = await _roleManager.FindByIdAsync(user.AppRoleId.ToString()); + if (role == null) return new BadRequestObjectResult("Bad request"); var authClaims = new List { new Claim(ClaimTypes.Name, user.UserName), new Claim(ClaimTypes.NameIdentifier, user.Id.ToString()), + new Claim(ClaimTypes.Role, role.Name), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) }; From 6fb8184affb55195e8a4469b2b5790f29e8f0a63 Mon Sep 17 00:00:00 2001 From: Tomo2433 Date: Wed, 10 Jan 2024 19:21:29 +0100 Subject: [PATCH 6/8] needed changes in seeder --- TableBookingAPI/TableBooking.Model/Seed/seed.sql | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/TableBookingAPI/TableBooking.Model/Seed/seed.sql b/TableBookingAPI/TableBooking.Model/Seed/seed.sql index 4e20519..dfbc74b 100644 --- a/TableBookingAPI/TableBooking.Model/Seed/seed.sql +++ b/TableBookingAPI/TableBooking.Model/Seed/seed.sql @@ -1,5 +1,4 @@ ALTER ROLE "TableBookingUser" SET search_path = public; - -- Create Restaurants table CREATE TABLE IF NOT EXISTS "Restaurants" ( "Id" UUID PRIMARY KEY, @@ -57,8 +56,9 @@ CREATE TABLE IF NOT EXISTS "Users" ( CREATE TABLE IF NOT EXISTS "Bookings" ( "Id" UUID PRIMARY KEY, "Date" TIMESTAMPTZ, + "AmountOfPeople" INT, "DurationInMinutes" INT, - "UserId" UUID REFERENCES "Users"("Id"), + "AppUserId" UUID REFERENCES "Users"("Id"), "TableId" UUID REFERENCES "Tables"("Id") ); @@ -190,8 +190,8 @@ INSERT INTO "Users" ( ); -- seed Bookings records -INSERT INTO "Bookings" ("Id", "Date", "DurationInMinutes", "UserId", "TableId") VALUES ('fc9663f0-08b1-4c52-afe4-1d446b11017f','2030-01-01 14:30:00+00', 5, 'abc663f0-08b1-4c52-afe4-1d446b11017f', '123e1a20-6801-4a5e-a327-ecc5cb2bd906'); -INSERT INTO "Bookings" ("Id", "Date", "DurationInMinutes", "UserId", "TableId") VALUES ('c4c4a1c0-3cb4-445e-ba81-311a6b939b4a','2050-05-07 20:15:00+00', 3, '123663f0-08b1-4c52-afe4-1d446b11017f', '3eb2eb68-a47e-47cd-8a22-06c20197a0b3'); +INSERT INTO "Bookings" ("Id", "Date","AmountOfPeople", "DurationInMinutes", "AppUserId", "TableId") VALUES ('fc9663f0-08b1-4c52-afe4-1d446b11017f','2030-01-01 14:30:00+00', 1, 5, 'abc663f0-08b1-4c52-afe4-1d446b11017f', '123e1a20-6801-4a5e-a327-ecc5cb2bd906'); +INSERT INTO "Bookings" ("Id", "Date","AmountOfPeople", "DurationInMinutes", "AppUserId", "TableId") VALUES ('c4c4a1c0-3cb4-445e-ba81-311a6b939b4a','2050-05-07 20:15:00+00', 2, 3, '123663f0-08b1-4c52-afe4-1d446b11017f', '3eb2eb68-a47e-47cd-8a22-06c20197a0b3'); -- Seed Users records INSERT INTO "Users" ("Id", "RefreshToken", "RefreshTokenExpiryTime", "UserName", "NormalizedUserName", "Email", "NormalizedEmail", "EmailConfirmed", "PasswordHash", "SecurityStamp", "ConcurrencyStamp", "PhoneNumber", "PhoneNumberConfirmed", "TwoFactorEnabled", "LockoutEnd", "LockoutEnabled", "AccessFailedCount", "AppRoleId") From b698fdc140b54735825735829a6d3ecd47ec6805 Mon Sep 17 00:00:00 2001 From: Tomo2433 Date: Thu, 11 Jan 2024 22:24:27 +0100 Subject: [PATCH 7/8] not working endpoints repaired --- .../TableConverters/TableToGetConverter.cs | 3 +- .../Repositories/TableRepository.cs | 2 +- .../RestaurantDtos/RestaurantShortInfoDto.cs | 1 + .../Dtos/TableDtos/GetTablesDto.cs | 5 ++- .../Dtos/TableDtos/TableDto.cs | 2 +- .../TableBooking.Model/Models/Table.cs | 1 + .../Controllers/BookingController.cs | 6 ++-- .../Controllers/RestaurantController.cs | 8 ++--- .../Controllers/TableController.cs | 8 ++--- .../Interfaces/IBookingService.cs | 2 +- .../Interfaces/IRestaurantService.cs | 2 +- .../TableBooking/Interfaces/ITableService.cs | 2 +- .../TableBooking/Services/BookingService.cs | 6 ++-- .../Services/RestaurantService.cs | 32 +++++++++++++++++-- .../TableBooking/Services/TableService.cs | 18 +++++++---- 15 files changed, 69 insertions(+), 29 deletions(-) diff --git a/TableBookingAPI/TableBooking.Logic/Converters/TableConverters/TableToGetConverter.cs b/TableBookingAPI/TableBooking.Logic/Converters/TableConverters/TableToGetConverter.cs index ec97484..89951d5 100644 --- a/TableBookingAPI/TableBooking.Logic/Converters/TableConverters/TableToGetConverter.cs +++ b/TableBookingAPI/TableBooking.Logic/Converters/TableConverters/TableToGetConverter.cs @@ -21,7 +21,8 @@ public GetTablesDto TableToTableDto(Table table) { Id = table.Id, RestaurantId = table.RestaurantId, - NumberOfSeats = table.NumberOfSeats + NumberOfSeats = table.NumberOfSeats, + Bookings = table.Bookings }; } } diff --git a/TableBookingAPI/TableBooking.Logic/Repositories/TableRepository.cs b/TableBookingAPI/TableBooking.Logic/Repositories/TableRepository.cs index 6471c9d..cb58f54 100644 --- a/TableBookingAPI/TableBooking.Logic/Repositories/TableRepository.cs +++ b/TableBookingAPI/TableBooking.Logic/Repositories/TableRepository.cs @@ -13,7 +13,7 @@ public TableRepository(TableBookingContext context) : base(context) public async Task> GetTablesByRestaurantIdAsync(Guid restaurantId) { return await _objectSet - .Include(x => x.RestaurantId) + .Include(x => x.Restaurant) .Where(x => x.RestaurantId.Equals(restaurantId)) .ToListAsync(); } diff --git a/TableBookingAPI/TableBooking.Model/Dtos/RestaurantDtos/RestaurantShortInfoDto.cs b/TableBookingAPI/TableBooking.Model/Dtos/RestaurantDtos/RestaurantShortInfoDto.cs index 53aa2a2..e190689 100644 --- a/TableBookingAPI/TableBooking.Model/Dtos/RestaurantDtos/RestaurantShortInfoDto.cs +++ b/TableBookingAPI/TableBooking.Model/Dtos/RestaurantDtos/RestaurantShortInfoDto.cs @@ -7,6 +7,7 @@ public class RestaurantShortInfoDto public string Name { get; set; } public string Type { get; set; } public string Description { get; set; } + public string Phone { get; set; } public string Location { get; set; } public string ImageURL { get; set; } public int Rating { get; set; } diff --git a/TableBookingAPI/TableBooking.Model/Dtos/TableDtos/GetTablesDto.cs b/TableBookingAPI/TableBooking.Model/Dtos/TableDtos/GetTablesDto.cs index a04f491..68eb2b5 100644 --- a/TableBookingAPI/TableBooking.Model/Dtos/TableDtos/GetTablesDto.cs +++ b/TableBookingAPI/TableBooking.Model/Dtos/TableDtos/GetTablesDto.cs @@ -1,9 +1,12 @@ -namespace TableBooking.Model.Dtos.TableDtos +using TableBooking.Model.Models; + +namespace TableBooking.Model.Dtos.TableDtos { public class GetTablesDto { public Guid Id { get; set; } public int NumberOfSeats { get; set; } public Guid RestaurantId { get; set; } + public IEnumerable? Bookings { get; set; } } } diff --git a/TableBookingAPI/TableBooking.Model/Dtos/TableDtos/TableDto.cs b/TableBookingAPI/TableBooking.Model/Dtos/TableDtos/TableDto.cs index c3ecee8..fe62546 100644 --- a/TableBookingAPI/TableBooking.Model/Dtos/TableDtos/TableDto.cs +++ b/TableBookingAPI/TableBooking.Model/Dtos/TableDtos/TableDto.cs @@ -2,7 +2,7 @@ namespace TableBooking.Model.Dtos.TableDtos { - public class TableDto : Entity + public class TableDto { public int NumberOfSeats { get; set; } public Guid RestaurantId { get; set; } diff --git a/TableBookingAPI/TableBooking.Model/Models/Table.cs b/TableBookingAPI/TableBooking.Model/Models/Table.cs index 9f27d05..51db151 100644 --- a/TableBookingAPI/TableBooking.Model/Models/Table.cs +++ b/TableBookingAPI/TableBooking.Model/Models/Table.cs @@ -5,5 +5,6 @@ public class Table : Entity public int NumberOfSeats { get; set; } public Guid RestaurantId { get; set; } public IEnumerable? Bookings { get; set; } + public Restaurant Restaurant { get; set; } } } diff --git a/TableBookingAPI/TableBooking/Controllers/BookingController.cs b/TableBookingAPI/TableBooking/Controllers/BookingController.cs index e233306..5783f93 100644 --- a/TableBookingAPI/TableBooking/Controllers/BookingController.cs +++ b/TableBookingAPI/TableBooking/Controllers/BookingController.cs @@ -56,12 +56,12 @@ public async Task DeleteUserBooking(Guid id) return await _bookingService.DeleteBookingAsync(id, userId); } - [HttpPost("CreateBooking")] - public async Task CreateUserBooking([FromBody] CreateBookingDto bookingToCreateDto) + [HttpPost("CreateBooking/{restaurantId}")] + public async Task CreateUserBooking([FromBody] CreateBookingDto bookingToCreateDto, Guid restaurantId) { var userId = Guid.Parse(User.FindFirstValue(ClaimTypes.NameIdentifier)); - return await _bookingService.CreateBookingAsync(bookingToCreateDto, userId); + return await _bookingService.CreateBookingAsync(bookingToCreateDto, userId, restaurantId); } [HttpPut("UpdateBooking/{bookingId}")] diff --git a/TableBookingAPI/TableBooking/Controllers/RestaurantController.cs b/TableBookingAPI/TableBooking/Controllers/RestaurantController.cs index b64f9e2..cbddf1c 100644 --- a/TableBookingAPI/TableBooking/Controllers/RestaurantController.cs +++ b/TableBookingAPI/TableBooking/Controllers/RestaurantController.cs @@ -35,16 +35,16 @@ public async Task CreateRestaurant([FromBody] RestaurantShortInfo return await _restaurantService.CreateRestaurantAsync(restaurantShortInfoDto); } - [HttpDelete("DeleteRestaurant/{id:int}")] + [HttpDelete("DeleteRestaurant/{id:Guid}")] public async Task DeleteRestaurant(Guid id) { return await _restaurantService.DeleteRestaurantAsync(id); } - [HttpPut("UpdateRestaurant")] - public async Task UpdateRestaurant() + [HttpPut("UpdateRestaurant/{restaurantId}")] + public async Task UpdateRestaurant([FromBody] RestaurantShortInfoDto restaurantShortInfoDto, Guid restaurantId) { - return Ok(); + return await _restaurantService.UpdateRestaurantAsync(restaurantShortInfoDto, restaurantId); } diff --git a/TableBookingAPI/TableBooking/Controllers/TableController.cs b/TableBookingAPI/TableBooking/Controllers/TableController.cs index 1158b1f..d1450e6 100644 --- a/TableBookingAPI/TableBooking/Controllers/TableController.cs +++ b/TableBookingAPI/TableBooking/Controllers/TableController.cs @@ -39,13 +39,13 @@ public async Task CreateTable([FromBody] TableDto tableDto) return await _tableService.CreateTableAsync(tableDto); } - [HttpPut("UpdateTable")] - public async Task UpdateTable([FromBody] TableDto tableDto) + [HttpPut("UpdateTable/{tableId}")] + public async Task UpdateTable([FromBody] TableDto tableDto, Guid tableId) { - return await _tableService.UpdateTableAsync(tableDto); + return await _tableService.UpdateTableAsync(tableDto, tableId); } - [HttpDelete("DeleteTable/{id:int}")] + [HttpDelete("DeleteTable/{id:Guid}")] public async Task DeleteTable(Guid id) { return await _tableService.DeleteTableAsync(id); diff --git a/TableBookingAPI/TableBooking/Interfaces/IBookingService.cs b/TableBookingAPI/TableBooking/Interfaces/IBookingService.cs index e930ad2..995bd27 100644 --- a/TableBookingAPI/TableBooking/Interfaces/IBookingService.cs +++ b/TableBookingAPI/TableBooking/Interfaces/IBookingService.cs @@ -7,7 +7,7 @@ public interface IBookingService { public Task GetAllBookings(Guid userId); public Task GetBookingByIdAsync(Guid bookingId, Guid userId); - public Task CreateBookingAsync(CreateBookingDto createBookingDto, Guid userId); + public Task CreateBookingAsync(CreateBookingDto createBookingDto, Guid userId, Guid restaurantId); public Task UpdateBookingAsync(UpdateBookingDto updateBookingDto, Guid userId, Guid bookingId); public Task DeleteBookingAsync(Guid bookingId, Guid userId); } diff --git a/TableBookingAPI/TableBooking/Interfaces/IRestaurantService.cs b/TableBookingAPI/TableBooking/Interfaces/IRestaurantService.cs index 0011980..e94c135 100644 --- a/TableBookingAPI/TableBooking/Interfaces/IRestaurantService.cs +++ b/TableBookingAPI/TableBooking/Interfaces/IRestaurantService.cs @@ -9,7 +9,7 @@ public interface IRestaurantService public Task GetAllRestaurantsAsync(string? restaurantName, Price? price); public Task GetRestaurantByIdAsync(Guid restaurantId); public Task CreateRestaurantAsync(RestaurantShortInfoDto dto); - public Task UpdateRestaurantAsync(RestaurantShortInfoDto dto); + public Task UpdateRestaurantAsync(RestaurantShortInfoDto dto, Guid restaurantId); public Task DeleteRestaurantAsync(Guid restaurantId); } diff --git a/TableBookingAPI/TableBooking/Interfaces/ITableService.cs b/TableBookingAPI/TableBooking/Interfaces/ITableService.cs index e4cbbf1..fa6a8a7 100644 --- a/TableBookingAPI/TableBooking/Interfaces/ITableService.cs +++ b/TableBookingAPI/TableBooking/Interfaces/ITableService.cs @@ -10,7 +10,7 @@ public interface ITableService public Task GetTableByIdAsync(Guid tableId); public Task GetTableByRestaurantAsync(Guid restaurantId); public Task CreateTableAsync(TableDto dto); - public Task UpdateTableAsync(TableDto dto); + public Task UpdateTableAsync(TableDto dto, Guid tableId); public Task DeleteTableAsync(Guid tableId); public Task
GetTableObjectByIdAsync(Guid tableId); } diff --git a/TableBookingAPI/TableBooking/Services/BookingService.cs b/TableBookingAPI/TableBooking/Services/BookingService.cs index e09b987..69130fb 100644 --- a/TableBookingAPI/TableBooking/Services/BookingService.cs +++ b/TableBookingAPI/TableBooking/Services/BookingService.cs @@ -20,13 +20,15 @@ public BookingService(IUnitOfWork unitOfWork, ITableConverter tableConverter, IT _tableConverter = tableConverter; _tableService = tableService; } - public async Task CreateBookingAsync(CreateBookingDto request, Guid userId) + public async Task CreateBookingAsync(CreateBookingDto request, Guid userId, Guid restaurantId) { + var restaurantTables = await _unitOfWork.TableRepository.GetTablesByRestaurantIdAsync(restaurantId); + var table = restaurantTables.FirstOrDefault(x => x.Bookings == null); var newBooking = new Booking { Date = request.Date, DurationInMinutes = request.DurationInMinutes, - TableId = Guid.NewGuid(), + TableId = table.Id, AppUserId = userId, AmountOfPeople = request.AmountOfPeople }; diff --git a/TableBookingAPI/TableBooking/Services/RestaurantService.cs b/TableBookingAPI/TableBooking/Services/RestaurantService.cs index fb79757..6d0e57f 100644 --- a/TableBookingAPI/TableBooking/Services/RestaurantService.cs +++ b/TableBookingAPI/TableBooking/Services/RestaurantService.cs @@ -3,6 +3,7 @@ using TableBooking.Logic.Interfaces; using TableBooking.Model.Models; using TableBooking.Api.Interfaces; +using TableBooking.Model.Dtos.BookingDtos; namespace TableBooking.Api.Services { @@ -21,6 +22,7 @@ public async Task CreateRestaurantAsync(RestaurantShortInfoDto dt Name = dto.Name, CloseTime = dto.CloseTime, Description = dto.Description, + Phone = dto.Phone, Location = dto.Location, Rating = 0, Price = dto.Price, @@ -37,7 +39,7 @@ public async Task DeleteRestaurantAsync(Guid restaurantId) var restaurantToDelete = await _unitOfWork.RestaurantRepository.GetByIdAsync(restaurantId); if (restaurantToDelete == null) return new NotFoundObjectResult($"Restaurant with Id = {restaurantId} not found"); - await _unitOfWork.RestaurantRepository.Delete(restaurantToDelete); + await _unitOfWork.RestaurantRepository.Delete(restaurantToDelete.Id); await _unitOfWork.SaveChangesAsync(); return new OkObjectResult(restaurantToDelete); } @@ -57,9 +59,33 @@ public async Task GetRestaurantByIdAsync(Guid restaurantId) return new OkObjectResult(restaurant); } - public Task UpdateRestaurantAsync(RestaurantShortInfoDto dto) + public async Task UpdateRestaurantAsync(RestaurantShortInfoDto dto, Guid restaurantId) { - throw new NotImplementedException(); + var restaurant = await _unitOfWork.RestaurantRepository.GetByIdAsync(restaurantId); + if (restaurant == null) + return new BadRequestObjectResult($"Booking with id {restaurantId} doesn't exist."); + + var newRestaurant = new Restaurant + { + Id = restaurant.Id, + Description = dto.Description, + Location = dto.Location, + Name = dto.Name, + Phone = dto.Phone, + Price = dto.Price, + PrimaryImageURL = dto.ImageURL, + SecondaryImageURL = dto.ImageURL, + Tables = restaurant.Tables, + Type = dto.Type, + Rating = restaurant.Rating, + CloseTime = dto.CloseTime, + OpenTime = dto.OpenTime + }; + + await _unitOfWork.RestaurantRepository.Update(newRestaurant); + await _unitOfWork.SaveChangesAsync(); + + return new OkObjectResult(newRestaurant); } } } diff --git a/TableBookingAPI/TableBooking/Services/TableService.cs b/TableBookingAPI/TableBooking/Services/TableService.cs index fd078d2..6fa34de 100644 --- a/TableBookingAPI/TableBooking/Services/TableService.cs +++ b/TableBookingAPI/TableBooking/Services/TableService.cs @@ -22,7 +22,7 @@ public async Task CreateTableAsync(TableDto dto) var table = new Table { NumberOfSeats = dto.NumberOfSeats, - + RestaurantId = dto.RestaurantId }; await _unitOfWork.TableRepository.InsertAsync(table); await _unitOfWork.SaveChangesAsync(); @@ -34,7 +34,7 @@ public async Task DeleteTableAsync(Guid tableId) var tableToDelete = await _unitOfWork.TableRepository.GetByIdAsync(tableId); if (tableToDelete == null) return new NotFoundObjectResult($"Restaurant with Id = {tableId} not found"); - await _unitOfWork.TableRepository.Delete(tableToDelete); + await _unitOfWork.TableRepository.Delete(tableToDelete.Id); await _unitOfWork.SaveChangesAsync(); return new OkObjectResult(tableToDelete); } @@ -43,7 +43,7 @@ public async Task GetAllTablesAsync() { var tables = await _unitOfWork.TableRepository.GetAllAsync(); if (tables == null) return new BadRequestObjectResult("No tables found"); - return new OkObjectResult(tables); + return new OkObjectResult(_tableConverter.TablesToTableDtos(tables)); } public async Task GetTableByIdAsync(Guid tableId) @@ -51,7 +51,7 @@ public async Task GetTableByIdAsync(Guid tableId) var table = await _unitOfWork.TableRepository.GetByIdAsync(tableId); if (table == null) return new BadRequestObjectResult($"Can't find table with {tableId}"); - return new OkObjectResult(table); + return new OkObjectResult(_tableConverter.TableToTableDto(table)); } public async Task
GetTableObjectByIdAsync(Guid tableId) @@ -69,11 +69,17 @@ public async Task GetTableByRestaurantAsync(Guid restaurantId) return new OkObjectResult(_tableConverter.TablesToTableDtos(tables)); } - public async Task UpdateTableAsync(TableDto dto) + public async Task UpdateTableAsync(TableDto dto, Guid tableId) { + var updateTable = await _unitOfWork.TableRepository.GetByIdAsync(tableId); + if (updateTable == null) + return new BadRequestObjectResult($"Booking with id {tableId} doesn't exist."); + var table = new Table { - NumberOfSeats = dto.NumberOfSeats + Id = updateTable.Id, + NumberOfSeats = dto.NumberOfSeats, + RestaurantId = dto.RestaurantId }; await _unitOfWork.TableRepository.Update(table); await _unitOfWork.SaveChangesAsync(); From f971b8995090de5ed8db2fcea2d41de198c3f366 Mon Sep 17 00:00:00 2001 From: Paul Frank Date: Sat, 21 Dec 2024 12:09:37 +0100 Subject: [PATCH 8/8] fix dockerfile --- TableBookingAPI/TableBooking/Dockerfile | 8 ++++---- TableBookingAPI/docker-compose.yml | 22 ++++++++++------------ 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/TableBookingAPI/TableBooking/Dockerfile b/TableBookingAPI/TableBooking/Dockerfile index d85ad82..a9987e3 100644 --- a/TableBookingAPI/TableBooking/Dockerfile +++ b/TableBookingAPI/TableBooking/Dockerfile @@ -7,14 +7,14 @@ EXPOSE 443 FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build WORKDIR /src -COPY ["TableBooking/TableBooking.csproj", "TableBooking/"] -RUN dotnet restore "TableBooking/TableBooking.csproj" +COPY ["TableBooking/TableBooking.Api.csproj", "TableBooking/"] +RUN dotnet restore "TableBooking/TableBooking.Api.csproj" COPY . . WORKDIR "/src/TableBooking" -RUN dotnet build "TableBooking.csproj" -c Release -o /app/build +RUN dotnet build "TableBooking.Api.csproj" -c Release -o /app/build FROM build AS publish -RUN dotnet publish "TableBooking.csproj" -c Release -o /app/publish /p:UseAppHost=false +RUN dotnet publish "TableBooking.Api.csproj" -c Release -o /app/publish /p:UseAppHost=false FROM base AS final WORKDIR /app diff --git a/TableBookingAPI/docker-compose.yml b/TableBookingAPI/docker-compose.yml index 79467ee..9ebb0f8 100644 --- a/TableBookingAPI/docker-compose.yml +++ b/TableBookingAPI/docker-compose.yml @@ -16,18 +16,16 @@ services: volumes: - ./TableBooking.Model/Seed/seed.sql:/docker-entrypoint-initdb.d/seed.sql - # api: - # build: - # context: . - # dockerfile: ./TableBooking/Dockerfile - # ports: - # - "7012:7012" - # depends_on: - # - db - # # condition: service_healthy - # # command: ["python", "app.py"] - # networks: - # - table_booking_network + api: + build: + context: . + dockerfile: ./TableBooking/Dockerfile + ports: + - "7012:7012" + depends_on: + - db + networks: + - table_booking_network networks: table_booking_network: