├── Helpdesk ├── src │ └── GalaxyHotel.HelpDesk │ │ ├── Views │ │ ├── _ViewStart.cshtml │ │ ├── _ViewImports.cshtml │ │ ├── Shared │ │ │ ├── _ValidationScriptsPartial.cshtml │ │ │ ├── Error.cshtml │ │ │ └── _Layout.cshtml │ │ └── Home │ │ │ ├── Cancel.cshtml │ │ │ ├── Index.cshtml │ │ │ └── Reservations.cshtml │ │ ├── wwwroot │ │ ├── favicon.ico │ │ ├── js │ │ │ └── site.js │ │ ├── lib │ │ │ ├── jquery-validation-unobtrusive │ │ │ │ ├── LICENSE.txt │ │ │ │ └── jquery.validate.unobtrusive.min.js │ │ │ ├── jquery-validation │ │ │ │ └── LICENSE.md │ │ │ ├── bootstrap │ │ │ │ ├── LICENSE │ │ │ │ └── dist │ │ │ │ │ └── css │ │ │ │ │ ├── bootstrap-reboot.min.css │ │ │ │ │ └── bootstrap-reboot.css │ │ │ └── jquery │ │ │ │ └── LICENSE.txt │ │ └── css │ │ │ └── site.css │ │ ├── appsettings.Development.json │ │ ├── Models │ │ ├── ErrorViewModel.cs │ │ ├── RoomViewModel.cs │ │ └── ReservationViewModel.cs │ │ ├── appsettings.json │ │ ├── Program.cs │ │ ├── GalaxyHotel.HelpDesk.csproj │ │ ├── Controllers │ │ └── HomeController.cs │ │ ├── Startup.cs │ │ └── Migrations │ │ ├── 20200829211346_SeedGalaxyHotelDb.cs │ │ ├── GalaxyHotelContextModelSnapshot.cs │ │ └── 20200829211346_SeedGalaxyHotelDb.Designer.cs └── GalaxyHotel.HelpDesk.sln ├── Website ├── src │ └── GalaxyHotel.Website │ │ ├── Views │ │ ├── _ViewStart.cshtml │ │ ├── _ViewImports.cshtml │ │ ├── Shared │ │ │ ├── _ValidationScriptsPartial.cshtml │ │ │ ├── Error.cshtml │ │ │ ├── _LoginPartial.cshtml │ │ │ └── _Layout.cshtml │ │ └── Home │ │ │ ├── Booking.cshtml │ │ │ └── Index.cshtml │ │ ├── Areas │ │ └── Identity │ │ │ └── Pages │ │ │ └── _ViewStart.cshtml │ │ ├── wwwroot │ │ ├── favicon.ico │ │ ├── js │ │ │ └── site.js │ │ ├── lib │ │ │ ├── jquery-validation-unobtrusive │ │ │ │ ├── LICENSE.txt │ │ │ │ └── jquery.validate.unobtrusive.min.js │ │ │ ├── jquery-validation │ │ │ │ └── LICENSE.md │ │ │ ├── bootstrap │ │ │ │ ├── LICENSE │ │ │ │ └── dist │ │ │ │ │ └── css │ │ │ │ │ ├── bootstrap-reboot.min.css │ │ │ │ │ └── bootstrap-reboot.css │ │ │ └── jquery │ │ │ │ └── LICENSE.txt │ │ └── css │ │ │ └── site.css │ │ ├── Properties │ │ ├── serviceDependencies.json │ │ ├── serviceDependencies.local.json │ │ └── launchSettings.json │ │ ├── appsettings.Development.json │ │ ├── Models │ │ ├── ErrorViewModel.cs │ │ └── RoomViewModel.cs │ │ ├── appsettings.Staging.json │ │ ├── appsettings.Production.json │ │ ├── appsettings.json │ │ ├── Data │ │ ├── ApplicationDbContext.cs │ │ └── Migrations │ │ │ ├── 00000000000000_SeedGalaxyHotelDb.cs │ │ │ ├── 00000000000000_SeedGalaxyHotelDb.Designer.cs │ │ │ ├── 00000000000000_CreateIdentitySchema.cs │ │ │ └── ApplicationDbContextModelSnapshot.cs │ │ ├── Program.cs │ │ ├── GalaxyHotel.Website.csproj │ │ ├── Controllers │ │ └── HomeController.cs │ │ └── Startup.cs ├── tests │ └── GalaxyHotel.UITests │ │ ├── GalaxyHotelTests.runsettings │ │ ├── GalaxyHotel.UITests.csproj │ │ └── BookingTests.cs ├── build-website.yml ├── GalaxyHotel.Website.sln ├── db │ └── SeedGalaxyHotelDbScript.sql └── azure-pipelines.yml ├── cover.png ├── Libraries ├── GitVersion.yml ├── src │ ├── GalaxyHotel.Core │ │ ├── Interfaces │ │ │ ├── IAggregateRoot.cs │ │ │ ├── IRoomService.cs │ │ │ ├── IIncludeQuery.cs │ │ │ ├── IReservationService.cs │ │ │ ├── ISpecification.cs │ │ │ └── IAsyncRepository.cs │ │ ├── Models │ │ │ ├── BaseEntity.cs │ │ │ ├── PaymentMethod.cs │ │ │ ├── Address.cs │ │ │ ├── Room.cs │ │ │ ├── Reservation.cs │ │ │ └── Guest.cs │ │ ├── Entities │ │ │ ├── BaseEntity.cs │ │ │ ├── GuestAggregate │ │ │ │ ├── PaymentMethod.cs │ │ │ │ ├── Address.cs │ │ │ │ └── Guest.cs │ │ │ ├── RoomAggregate │ │ │ │ ├── RoomType.cs │ │ │ │ └── Room.cs │ │ │ └── ReservationAggregate │ │ │ │ └── Reservation.cs │ │ ├── Exceptions │ │ │ └── NotExistingReservationException.cs │ │ ├── Extensions │ │ │ └── ReservationExtensions.cs │ │ ├── Specification │ │ │ ├── GuestReservationSpecification.cs │ │ │ ├── ReservationWithDetailsSpecification.cs │ │ │ └── BaseSpecifition.cs │ │ ├── Helpers │ │ │ └── Query │ │ │ │ ├── IncludeVisitor.cs │ │ │ │ ├── IncludeQuery.cs │ │ │ │ ├── IncludeAggregator.cs │ │ │ │ └── IncludeQueryExtensions.cs │ │ ├── GalaxyHotel.Core.csproj │ │ ├── Services │ │ │ ├── RoomService.cs │ │ │ └── ReservationService.cs │ │ └── Mapping │ │ │ └── GalaxyHotelMapping.cs │ ├── GalaxyHotel.Dto │ │ ├── GalaxyHotel.Dto.csproj │ │ ├── RoomDto.cs │ │ └── ReservationDto.cs │ └── GalaxyHotel.Infrastructure │ │ ├── Data │ │ ├── ReservationRepository.cs │ │ ├── GalaxyHotelContext.cs │ │ ├── SpecificationEvaluator.cs │ │ ├── ModelBuilderExtensions.cs │ │ └── Repository.cs │ │ └── GalaxyHotel.Infrastructure.csproj ├── tests │ ├── GalaxyHotel.Core.Services.Tests │ │ ├── GalaxyHotel.Core.Services.Tests.csproj │ │ └── ReservationServiceTests.cs │ └── GalaxyHotel.Infrastructure.IntegrationTests │ │ ├── GalaxyHotel.Infrastructure.IntegrationTests.csproj │ │ ├── Data │ │ └── ReservationRepositoryTests.cs │ │ └── SetUp │ │ └── TestGalaxyHotelContext.cs ├── azure-pipelines.yml └── GalaxyHotel.Libraries.sln ├── README.md └── LICENSE /Helpdesk/src/GalaxyHotel.HelpDesk/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Views/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "_Layout"; 3 | } 4 | -------------------------------------------------------------------------------- /cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SyncfusionSuccinctlyE-Books/Azure-Pipelines-Succinctly/HEAD/cover.png -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Areas/Identity/Pages/_ViewStart.cshtml: -------------------------------------------------------------------------------- 1 | @{ 2 | Layout = "/Views/Shared/_Layout.cshtml"; 3 | } 4 | -------------------------------------------------------------------------------- /Libraries/GitVersion.yml: -------------------------------------------------------------------------------- 1 | mode: ContinuousDelivery 2 | branches: 3 | release: 4 | tag: rc 5 | ignore: 6 | sha: [] 7 | merge-message-formats: {} 8 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Interfaces/IAggregateRoot.cs: -------------------------------------------------------------------------------- 1 | namespace GalaxyHotel.Core.Interfaces 2 | { 3 | public interface IAggregateRoot 4 | { 5 | 6 | } 7 | } -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using GalaxyHotel.Website 2 | @using GalaxyHotel.Website.Models 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/Views/_ViewImports.cshtml: -------------------------------------------------------------------------------- 1 | @using GalaxyHotel.HelpDesk 2 | @using GalaxyHotel.HelpDesk.Models 3 | @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers 4 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Models/BaseEntity.cs: -------------------------------------------------------------------------------- 1 | namespace GalaxyHotel.Core.Models 2 | { 3 | public class BaseEntity 4 | { 5 | public int Id { get; set; } 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SyncfusionSuccinctlyE-Books/Azure-Pipelines-Succinctly/HEAD/Website/src/GalaxyHotel.Website/wwwroot/favicon.ico -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/wwwroot/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SyncfusionSuccinctlyE-Books/Azure-Pipelines-Succinctly/HEAD/Helpdesk/src/GalaxyHotel.HelpDesk/wwwroot/favicon.ico -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Properties/serviceDependencies.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "mssql1": { 4 | "type": "mssql", 5 | "connectionId": "DefaultConnection" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Dto/GalaxyHotel.Dto.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Entities/BaseEntity.cs: -------------------------------------------------------------------------------- 1 | namespace GalaxyHotel.Core.Entities 2 | { 3 | public abstract class BaseEntity 4 | { 5 | public virtual int Id { get; protected set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Properties/serviceDependencies.local.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "mssql1": { 4 | "type": "mssql.local", 5 | "connectionId": "DefaultConnection" 6 | } 7 | } 8 | } -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/Views/Shared/_ValidationScriptsPartial.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Views/Shared/_ValidationScriptsPartial.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /Website/tests/GalaxyHotel.UITests/GalaxyHotelTests.runsettings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/Views/Home/Cancel.cshtml: -------------------------------------------------------------------------------- 1 | @model RoomViewModel 2 | 3 | @{ 4 | ViewData["Title"] = "Cancel Reservation"; 5 | } 6 | 7 |
8 |

Reservation canceled!

9 |
10 | -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Views/Home/Booking.cshtml: -------------------------------------------------------------------------------- 1 | @model List 2 | 3 | @{ 4 | ViewData["Title"] = "Booking Page"; 5 | } 6 | 7 |
8 |

Room booked!

9 |
10 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/appsettings.Development.json: -------------------------------------------------------------------------------- 1 | { 2 | "Logging": { 3 | "LogLevel": { 4 | "Default": "Information", 5 | "Microsoft": "Warning", 6 | "Microsoft.Hosting.Lifetime": "Information" 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/wwwroot/js/site.js: -------------------------------------------------------------------------------- 1 | // Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification 2 | // for details on configuring this project to bundle and minify static web assets. 3 | 4 | // Write your JavaScript code. 5 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/wwwroot/js/site.js: -------------------------------------------------------------------------------- 1 | // Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification 2 | // for details on configuring this project to bundle and minify static web assets. 3 | 4 | // Write your JavaScript code. 5 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Dto/RoomDto.cs: -------------------------------------------------------------------------------- 1 | namespace GalaxyHotel.Dto 2 | { 3 | public class RoomDto 4 | { 5 | public int Id { get; set; } 6 | public string Name { get; set; } 7 | public int Floor { get; set; } 8 | public decimal PricePerNight { get; set; } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/Models/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GalaxyHotel.HelpDesk.Models 4 | { 5 | public class ErrorViewModel 6 | { 7 | public string RequestId { get; set; } 8 | 9 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Models/ErrorViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GalaxyHotel.Website.Models 4 | { 5 | public class ErrorViewModel 6 | { 7 | public string RequestId { get; set; } 8 | 9 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Entities/GuestAggregate/PaymentMethod.cs: -------------------------------------------------------------------------------- 1 | namespace GalaxyHotel.Core.Entities.GuestAggregate 2 | { 3 | public class PaymentMethod : BaseEntity 4 | { 5 | public string Alias { get; private set; } 6 | public string CardId { get; private set; } 7 | public string Last4 { get; private set; } 8 | } 9 | } -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Interfaces/IRoomService.cs: -------------------------------------------------------------------------------- 1 | using GalaxyHotel.Core.Models; 2 | using GalaxyHotel.Dto; 3 | using System.Collections.Generic; 4 | using System.Threading.Tasks; 5 | 6 | namespace GalaxyHotel.Core.Interfaces 7 | { 8 | public interface IRoomService 9 | { 10 | Task> GetAll(); 11 | } 12 | } -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Exceptions/NotExistingReservationException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GalaxyHotel.Core.Exceptions 4 | { 5 | public class NotExistingReservationException : Exception 6 | { 7 | public NotExistingReservationException() 8 | : base("Reservation was not found!") 9 | { 10 | 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Infrastructure/Data/ReservationRepository.cs: -------------------------------------------------------------------------------- 1 | using GalaxyHotel.Core.Models; 2 | 3 | namespace GalaxyHotel.Infrastructure.Data 4 | { 5 | public class ReservationRepository : Repository 6 | { 7 | public ReservationRepository(GalaxyHotelContext dbContext) : 8 | base(dbContext) 9 | { 10 | } 11 | } 12 | } -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Models/PaymentMethod.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GalaxyHotel.Core.Models 4 | { 5 | public class PaymentMethod : BaseEntity 6 | { 7 | public string Alias { get; set; } 8 | public string CardNumber { get; set; } 9 | public DateTimeOffset DueDate { get; set; } 10 | public Guest Guest { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/Models/RoomViewModel.cs: -------------------------------------------------------------------------------- 1 | using GalaxyHotel.Dto; 2 | using System.Collections.Generic; 3 | 4 | namespace GalaxyHotel.HelpDesk.Models 5 | { 6 | public class RoomViewModel 7 | { 8 | public RoomViewModel(IEnumerable rooms) 9 | { 10 | this.Rooms = rooms; 11 | } 12 | 13 | public IEnumerable Rooms { get; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Models/RoomViewModel.cs: -------------------------------------------------------------------------------- 1 | using GalaxyHotel.Dto; 2 | using System.Collections.Generic; 3 | 4 | namespace GalaxyHotel.Website.Models 5 | { 6 | public class RoomViewModel 7 | { 8 | public RoomViewModel(IEnumerable rooms) 9 | { 10 | this.Rooms = rooms; 11 | } 12 | 13 | public IEnumerable Rooms { get; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/appsettings.Staging.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=GalaxyHotel-Staging;Trusted_Connection=True;MultipleActiveResultSets=true" 4 | }, 5 | "Logging": { 6 | "LogLevel": { 7 | "Default": "Information", 8 | "Microsoft": "Warning", 9 | "Microsoft.Hosting.Lifetime": "Information" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Models/Address.cs: -------------------------------------------------------------------------------- 1 | namespace GalaxyHotel.Core.Models 2 | { 3 | public class Address : BaseEntity 4 | { 5 | public string Street { get; set; } 6 | public string City { get; set; } 7 | public string State { get; set; } 8 | public string Country { get; set; } 9 | public string ZipCode { get; set; } 10 | public Guest Guest { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Models/Room.cs: -------------------------------------------------------------------------------- 1 | using System.Collections; 2 | using System.Collections.Generic; 3 | 4 | namespace GalaxyHotel.Core.Models 5 | { 6 | public class Room : BaseEntity 7 | { 8 | public string Name { get; set; } 9 | public int Floor { get; set; } 10 | public decimal PricePerNight { get; set; } 11 | public IEnumerable Reservations { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/appsettings.Production.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=GalaxyHotel-Production;Trusted_Connection=True;MultipleActiveResultSets=true" 4 | }, 5 | "Logging": { 6 | "LogLevel": { 7 | "Default": "Information", 8 | "Microsoft": "Warning", 9 | "Microsoft.Hosting.Lifetime": "Information" 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=GalaxyHotel-Dev;Trusted_Connection=True;MultipleActiveResultSets=true" 4 | }, 5 | "Logging": { 6 | "LogLevel": { 7 | "Default": "Information", 8 | "Microsoft": "Warning", 9 | "Microsoft.Hosting.Lifetime": "Information" 10 | } 11 | }, 12 | "AllowedHosts": "*" 13 | } 14 | -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/appsettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "ConnectionStrings": { 3 | "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=GalaxyHotelHelpDesk-Dev;Trusted_Connection=True;MultipleActiveResultSets=true" 4 | }, 5 | "Logging": { 6 | "LogLevel": { 7 | "Default": "Information", 8 | "Microsoft": "Warning", 9 | "Microsoft.Hosting.Lifetime": "Information" 10 | } 11 | }, 12 | "AllowedHosts": "*" 13 | } 14 | -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/Models/ReservationViewModel.cs: -------------------------------------------------------------------------------- 1 | using GalaxyHotel.Dto; 2 | using System.Collections.Generic; 3 | 4 | namespace GalaxyHotel.HelpDesk.Models 5 | { 6 | public class ReservationViewModel 7 | { 8 | public ReservationViewModel(IEnumerable reservations) 9 | { 10 | this.Reservations = reservations; 11 | } 12 | 13 | public IEnumerable Reservations { get; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Dto/ReservationDto.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GalaxyHotel.Dto 4 | { 5 | public class ReservationDto 6 | { 7 | public DateTimeOffset CheckIn { get; set; } 8 | public DateTimeOffset CheckOut { get; set; } 9 | public int GuestId { get; set; } 10 | public string GuestName { get; set; } 11 | public int RoomId { get; set; } 12 | public string RoomName { get; set; } 13 | public decimal TotalPrice { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Data/ApplicationDbContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using Microsoft.AspNetCore.Identity.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore; 6 | 7 | namespace GalaxyHotel.Website.Data 8 | { 9 | public class ApplicationDbContext : IdentityDbContext 10 | { 11 | public ApplicationDbContext(DbContextOptions options) 12 | : base(options) 13 | { 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Entities/RoomAggregate/RoomType.cs: -------------------------------------------------------------------------------- 1 | using Ardalis.GuardClauses; 2 | 3 | namespace GalaxyHotel.Core.Entities.RoomAggregate 4 | { 5 | public class RoomType : BaseEntity 6 | { 7 | public string Type { get; private set; } 8 | 9 | public RoomType() 10 | { 11 | 12 | } 13 | 14 | public RoomType(string type) 15 | { 16 | Guard.Against.NullOrEmpty(type, nameof(type)); 17 | 18 | Type = type; 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Models/Reservation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace GalaxyHotel.Core.Models 4 | { 5 | public class Reservation : BaseEntity 6 | { 7 | public DateTimeOffset CheckIn { get; set; } 8 | public DateTimeOffset CheckOut { get; set; } 9 | public decimal TotalPrice { get; set; } 10 | public int GuestId { get; set; } 11 | public Guest Guest { get; set; } 12 | public int RoomId { get; set; } 13 | public virtual Room Room { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Azure Pipelines Succinctly 2 | 3 | This is the companion repo for [*Azure Pipelines Succinctly*](https://www.syncfusion.com/ebooks/) by Antonio Liccardi. Published by Syncfusion. 4 | 5 | [![cover](https://github.com/SyncfusionSuccinctlyE-Books/Azure-Pipelines-Succinctly/blob/main/cover.png)](https://www.syncfusion.com/ebooks) 6 | 7 | ## Looking for more _Succinctly_ titles? 8 | 9 | Check out the entire library of more than 190 _Succinctly_ ebooks at [https://www.syncfusion.com/ebooks](https://www.syncfusion.com/ebooks). 10 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Extensions/ReservationExtensions.cs: -------------------------------------------------------------------------------- 1 | using Ardalis.GuardClauses; 2 | using GalaxyHotel.Core.Exceptions; 3 | using GalaxyHotel.Core.Models; 4 | 5 | namespace GalaxyHotel.Core.Extensions 6 | { 7 | public static class ReservationExtensions 8 | { 9 | public static void NotExistingReservation(this IGuardClause guardClause, Reservation reservation) 10 | { 11 | if (reservation == null) 12 | throw new NotExistingReservationException(); 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Specification/GuestReservationSpecification.cs: -------------------------------------------------------------------------------- 1 | using GalaxyHotel.Core.Helpers.Query; 2 | using GalaxyHotel.Core.Models; 3 | 4 | namespace GalaxyHotel.Core.Specification 5 | { 6 | public class GuestReservationSpecification : BaseSpecification 7 | { 8 | public GuestReservationSpecification(int guestId) 9 | : base(o => o.GuestId == guestId) 10 | { 11 | AddIncludes(query => query.Include(o => o.Guest).Include(o => o.Room)); 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Interfaces/IIncludeQuery.cs: -------------------------------------------------------------------------------- 1 | using GalaxyHotel.Core.Helpers.Query; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace GalaxyHotel.Core.Interfaces 7 | { 8 | public interface IIncludeQuery 9 | { 10 | Dictionary PathMap { get; } 11 | IncludeVisitor Visitor { get; } 12 | HashSet Paths { get; } 13 | } 14 | 15 | public interface IIncludeQuery : IIncludeQuery 16 | { 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Helpers/Query/IncludeVisitor.cs: -------------------------------------------------------------------------------- 1 | using System.Linq.Expressions; 2 | 3 | namespace GalaxyHotel.Core.Helpers.Query 4 | { 5 | public class IncludeVisitor : ExpressionVisitor 6 | { 7 | public string Path { get; private set; } = string.Empty; 8 | 9 | protected override Expression VisitMember(MemberExpression node) 10 | { 11 | Path = string.IsNullOrEmpty(Path) ? node.Member.Name : $"{node.Member.Name}.{Path}"; 12 | 13 | return base.VisitMember(node); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Specification/ReservationWithDetailsSpecification.cs: -------------------------------------------------------------------------------- 1 | using GalaxyHotel.Core.Helpers.Query; 2 | using GalaxyHotel.Core.Models; 3 | 4 | namespace GalaxyHotel.Core.Specification 5 | { 6 | public class ReservationWithDetailsSpecification : BaseSpecification 7 | { 8 | public ReservationWithDetailsSpecification() 9 | : base() 10 | { 11 | AddIncludes(query => query 12 | .Include(o => o.Room) 13 | .Include(o => o.Guest)); 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Models/Guest.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace GalaxyHotel.Core.Models 4 | { 5 | public class Guest : BaseEntity 6 | { 7 | public string FirstName { get; set; } 8 | public string LastName { get; set; } 9 | public int AddressId { get; set; } 10 | public Address Address { get; set; } 11 | public int PaymentMethodId { get; set; } 12 | public PaymentMethod PaymentMethod { get; set; } 13 | public IEnumerable Reservations { get; set; } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Interfaces/IReservationService.cs: -------------------------------------------------------------------------------- 1 | using GalaxyHotel.Dto; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Threading.Tasks; 5 | 6 | namespace GalaxyHotel.Core.Interfaces 7 | { 8 | public interface IReservationService 9 | { 10 | Task> GetAll(); 11 | Task GetByIdAsync(int reservationId); 12 | Task CreateReservationAsync(DateTimeOffset checkIn, DateTimeOffset checkOut, int guestId, int roomId); 13 | Task CancelReservationAsync(int reservationId); 14 | } 15 | } -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | 4 | namespace GalaxyHotel.HelpDesk 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IHostBuilder CreateHostBuilder(string[] args) => 14 | Host.CreateDefaultBuilder(args) 15 | .ConfigureWebHostDefaults(webBuilder => 16 | { 17 | webBuilder.UseStartup(); 18 | }); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Program.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.AspNetCore.Hosting; 2 | using Microsoft.Extensions.Hosting; 3 | 4 | namespace GalaxyHotel.Website 5 | { 6 | public class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | CreateHostBuilder(args).Build().Run(); 11 | } 12 | 13 | public static IHostBuilder CreateHostBuilder(string[] args) => 14 | Host.CreateDefaultBuilder(args) 15 | .ConfigureWebHostDefaults(webBuilder => 16 | { 17 | webBuilder.UseStartup(); 18 | }); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Interfaces/ISpecification.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq.Expressions; 4 | 5 | namespace GalaxyHotel.Core.Interfaces 6 | { 7 | public interface ISpecification 8 | { 9 | Expression> Criteria { get; } 10 | List>> Includes { get; } 11 | List IncludeStrings { get; } 12 | Expression> OrderBy { get; } 13 | Expression> OrderByDescending { get; } 14 | int Take { get; } 15 | int Skip { get; } 16 | bool IsPagingEnabled { get; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/GalaxyHotel.HelpDesk.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) .NET Foundation. All rights reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use 4 | these files except in compliance with the License. You may obtain a copy of the 5 | License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software distributed 10 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 11 | CONDITIONS OF ANY KIND, either express or implied. See the License for the 12 | specific language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/GalaxyHotel.Core.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.1 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/wwwroot/lib/jquery-validation-unobtrusive/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) .NET Foundation. All rights reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use 4 | these files except in compliance with the License. You may obtain a copy of the 5 | License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software distributed 10 | under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 11 | CONDITIONS OF ANY KIND, either express or implied. See the License for the 12 | specific language governing permissions and limitations under the License. 13 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Helpers/Query/IncludeQuery.cs: -------------------------------------------------------------------------------- 1 | using GalaxyHotel.Core.Interfaces; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace GalaxyHotel.Core.Helpers.Query 6 | { 7 | public class IncludeQuery : IIncludeQuery 8 | { 9 | public Dictionary PathMap { get; } = new Dictionary(); 10 | public IncludeVisitor Visitor { get; } = new IncludeVisitor(); 11 | 12 | public IncludeQuery(Dictionary pathMap) 13 | { 14 | PathMap = pathMap; 15 | } 16 | 17 | public HashSet Paths => PathMap.Select(x => x.Value).ToHashSet(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Interfaces/IAsyncRepository.cs: -------------------------------------------------------------------------------- 1 | using GalaxyHotel.Core.Models; 2 | using System.Collections.Generic; 3 | using System.Threading.Tasks; 4 | 5 | namespace GalaxyHotel.Core.Interfaces 6 | { 7 | public interface IAsyncRepository where T : BaseEntity//, IAggregateRoot 8 | { 9 | Task GetByIdAsync(int id); 10 | Task> ListAllAsync(); 11 | Task> ListAsync(ISpecification spec); 12 | Task AddAsync(T entity); 13 | Task UpdateAsync(T entity); 14 | Task DeleteAsync(T entity); 15 | Task CountAsync(ISpecification spec); 16 | Task FirstAsync(ISpecification spec); 17 | Task FirstOrDefaultAsync(ISpecification spec); 18 | } 19 | } -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Entities/GuestAggregate/Address.cs: -------------------------------------------------------------------------------- 1 | namespace GalaxyHotel.Core.Entities.GuestAggregate 2 | { 3 | public class Address : BaseEntity 4 | { 5 | public string Street { get; private set; } 6 | public string City { get; private set; } 7 | public string State { get; private set; } 8 | public string Country { get; private set; } 9 | public string ZipCode { get; private set; } 10 | 11 | private Address() { } 12 | 13 | public Address(string street, string city, string state, string country, string zipcode) 14 | { 15 | Street = street; 16 | City = city; 17 | State = state; 18 | Country = country; 19 | ZipCode = zipcode; 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Properties/launchSettings.json: -------------------------------------------------------------------------------- 1 | { 2 | "iisSettings": { 3 | "windowsAuthentication": false, 4 | "anonymousAuthentication": true, 5 | "iisExpress": { 6 | "applicationUrl": "http://localhost:51294", 7 | "sslPort": 44380 8 | } 9 | }, 10 | "profiles": { 11 | "IIS Express": { 12 | "commandName": "IISExpress", 13 | "launchBrowser": true, 14 | "environmentVariables": { 15 | "ASPNETCORE_ENVIRONMENT": "Development" 16 | } 17 | }, 18 | "GalaxyHotel.Website": { 19 | "commandName": "Project", 20 | "launchBrowser": true, 21 | "applicationUrl": "https://localhost:5001;http://localhost:5000", 22 | "environmentVariables": { 23 | "ASPNETCORE_ENVIRONMENT": "Development" 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Infrastructure/GalaxyHotel.Infrastructure.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.1 5 | 6 | 7 | 8 | 9 | runtime; build; native; contentfiles; analyzers; buildtransitive 10 | all 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /Libraries/tests/GalaxyHotel.Core.Services.Tests/GalaxyHotel.Core.Services.Tests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model RoomViewModel 2 | 3 | @{ 4 | ViewData["Title"] = "Home Page"; 5 | } 6 | 7 |
8 |

Welcome to the Galaxy Hotel!

9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | @foreach (var room in Model.Rooms) 19 | { 20 | 21 | 22 | 23 | 24 | 25 | 26 | } 27 | 28 |
Room NameRoom FloorRoom Price
@room.Name @room.Floor @room.PricePerNight @Html.ActionLink("Book", "Booking")
29 |
30 | -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/Views/Home/Index.cshtml: -------------------------------------------------------------------------------- 1 | @model RoomViewModel 2 | 3 | @{ 4 | ViewData["Title"] = "Home Page"; 5 | } 6 | 7 |
8 |

Welcome to the Galaxy Hotel HelpDesk

9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | @foreach (var room in Model.Rooms) 19 | { 20 | 21 | 22 | 23 | 24 | 25 | 26 | } 27 | 28 |
Room NameRoom FloorRoom Price
@room.Name @room.Floor @room.PricePerNight @Html.ActionLink("Book", "Reserve")
29 |
30 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Helpers/Query/IncludeAggregator.cs: -------------------------------------------------------------------------------- 1 | using GalaxyHotel.Core.Interfaces; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq.Expressions; 5 | 6 | namespace GalaxyHotel.Core.Helpers.Query 7 | { 8 | public class IncludeAggregator 9 | { 10 | public IncludeQuery Include(Expression> selector) 11 | { 12 | var visitor = new IncludeVisitor(); 13 | visitor.Visit(selector); 14 | 15 | var pathMap = new Dictionary(); 16 | var query = new IncludeQuery(pathMap); 17 | 18 | if (!string.IsNullOrEmpty(visitor.Path)) 19 | { 20 | pathMap[query] = visitor.Path; 21 | } 22 | 23 | return query; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /Libraries/tests/GalaxyHotel.Infrastructure.IntegrationTests/GalaxyHotel.Infrastructure.IntegrationTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Infrastructure/Data/GalaxyHotelContext.cs: -------------------------------------------------------------------------------- 1 | using GalaxyHotel.Core.Models; 2 | using Microsoft.EntityFrameworkCore; 3 | 4 | namespace GalaxyHotel.Infrastructure.Data 5 | { 6 | public class GalaxyHotelContext : DbContext 7 | { 8 | public GalaxyHotelContext(DbContextOptions options) 9 | : base(options) 10 | { } 11 | 12 | public DbSet
Addresses { get; set; } 13 | public DbSet Guests { get; set; } 14 | public DbSet PaymentMethods { get; set; } 15 | public DbSet Reservations { get; set; } 16 | public DbSet Rooms { get; set; } 17 | 18 | 19 | protected override void OnModelCreating(ModelBuilder builder) 20 | { 21 | base.OnModelCreating(builder); 22 | builder.CreateSchema(); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Services/RoomService.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using GalaxyHotel.Core.Interfaces; 3 | using GalaxyHotel.Core.Models; 4 | using GalaxyHotel.Dto; 5 | using System.Collections.Generic; 6 | using System.Threading.Tasks; 7 | 8 | namespace GalaxyHotel.Core.Services 9 | { 10 | public class RoomService : IRoomService 11 | { 12 | private readonly IAsyncRepository roomRepository; 13 | private readonly IMapper mapper; 14 | 15 | public RoomService(IAsyncRepository roomRepository, IMapper mapper) 16 | { 17 | this.roomRepository = roomRepository; 18 | this.mapper = mapper; 19 | } 20 | 21 | public async Task> GetAll() 22 | { 23 | var rooms = await roomRepository.ListAllAsync(); 24 | return mapper.Map>(rooms); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model ErrorViewModel 2 | @{ 3 | ViewData["Title"] = "Error"; 4 | } 5 | 6 |

Error.

7 |

An error occurred while processing your request.

8 | 9 | @if (Model.ShowRequestId) 10 | { 11 |

12 | Request ID: @Model.RequestId 13 |

14 | } 15 | 16 |

Development Mode

17 |

18 | Swapping to Development environment will display more detailed information about the error that occurred. 19 |

20 |

21 | The Development environment shouldn't be enabled for deployed applications. 22 | It can result in displaying sensitive information from exceptions to end users. 23 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 24 | and restarting the app. 25 |

26 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Views/Shared/Error.cshtml: -------------------------------------------------------------------------------- 1 | @model ErrorViewModel 2 | @{ 3 | ViewData["Title"] = "Error"; 4 | } 5 | 6 |

Error.

7 |

An error occurred while processing your request.

8 | 9 | @if (Model.ShowRequestId) 10 | { 11 |

12 | Request ID: @Model.RequestId 13 |

14 | } 15 | 16 |

Development Mode

17 |

18 | Swapping to Development environment will display more detailed information about the error that occurred. 19 |

20 |

21 | The Development environment shouldn't be enabled for deployed applications. 22 | It can result in displaying sensitive information from exceptions to end users. 23 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development 24 | and restarting the app. 25 |

26 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Mapping/GalaxyHotelMapping.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using GalaxyHotel.Core.Models; 3 | using GalaxyHotel.Dto; 4 | 5 | namespace GalaxyHotel.Core.Mapping 6 | { 7 | public class GalaxyHotelProfile : Profile 8 | { 9 | public GalaxyHotelProfile() 10 | { 11 | CreateMap() 12 | .ForMember(dest => dest.RoomName, opts => opts.MapFrom(src => src.Room.Name)) 13 | .ForMember(dest => dest.GuestName, opts => opts.MapFrom(src => $"{src.Guest.FirstName} {src.Guest.LastName}")); 14 | 15 | CreateMap() 16 | .ForMember(dest => dest.Id, opts => opts.MapFrom(src => src.Id)) 17 | .ForMember(dest => dest.Name, opts => opts.MapFrom(src => src.Name)) 18 | .ForMember(dest => dest.Floor, opts => opts.MapFrom(src => src.Floor)) 19 | .ForMember(dest => dest.PricePerNight, opts => opts.MapFrom(src => src.PricePerNight)); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Entities/RoomAggregate/Room.cs: -------------------------------------------------------------------------------- 1 | using Ardalis.GuardClauses; 2 | using GalaxyHotel.Core.Interfaces; 3 | 4 | namespace GalaxyHotel.Core.Entities.RoomAggregate 5 | { 6 | public class Room : BaseEntity, IAggregateRoot 7 | { 8 | public string Name { get; private set; } 9 | public int Floor { get; private set; } 10 | public int RoomTypeId { get; private set; } 11 | public decimal PricePerNight { get; private set; } 12 | 13 | public Room() { } 14 | 15 | public Room(string name, int floor, int roomTypeId, decimal pricePerNight) 16 | { 17 | Guard.Against.NullOrEmpty(name, nameof(name)); 18 | Guard.Against.NegativeOrZero(floor, nameof(floor)); 19 | Guard.Against.NegativeOrZero(roomTypeId, nameof(roomTypeId)); 20 | Guard.Against.NegativeOrZero(pricePerNight, nameof(pricePerNight)); 21 | 22 | Name = name; 23 | Floor = floor; 24 | RoomTypeId = roomTypeId; 25 | PricePerNight = pricePerNight; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /Website/tests/GalaxyHotel.UITests/GalaxyHotel.UITests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | 6 | false 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Views/Shared/_LoginPartial.cshtml: -------------------------------------------------------------------------------- 1 | @using Microsoft.AspNetCore.Identity 2 | @inject SignInManager SignInManager 3 | @inject UserManager UserManager 4 | 5 | 27 | -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/Views/Home/Reservations.cshtml: -------------------------------------------------------------------------------- 1 | @model ReservationViewModel 2 | 3 | @{ 4 | ViewData["Title"] = "Home Page"; 5 | } 6 | 7 |
8 |

Reservations

9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | @foreach (var reservation in Model.Reservations) 21 | { 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | } 31 | 32 |
Check InCheck OutGuestRoomPrice
@reservation.CheckIn.ToString("d") @reservation.CheckOut.ToString("d") @reservation.GuestName @reservation.RoomName @reservation.TotalPrice @Html.ActionLink("Cancel", "Cancel")
33 |
34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Syncfusion Succinctly E-Books 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Libraries/azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | - develop 3 | - master 4 | 5 | variables: 6 | buildConfiguration: 'Release' 7 | 8 | steps: 9 | - task: gitversion/setup@0 10 | displayName: Install GitVersion 11 | inputs: 12 | versionSpec: '5.x' 13 | 14 | - task: gitversion/execute@0 15 | displayName: Generate a new version number 16 | inputs: 17 | useConfigFile: true 18 | configFilePath: 'GitVersion.yml' 19 | 20 | - task: DotNetCoreCLI@2 21 | displayName: Build libraries 22 | inputs: 23 | command: 'build' 24 | 25 | - task: DotNetCoreCLI@2 26 | displayName: Test libraries 27 | inputs: 28 | command: 'test' 29 | 30 | - task: DotNetCoreCLI@2 31 | displayName: Pack libraries 32 | inputs: 33 | command: 'pack' 34 | packagesToPack: '**/*.csproj' 35 | versioningScheme: 'byEnvVar' 36 | versionEnvVar: 'GitVersion.NugetVersion' 37 | 38 | - task: DotNetCoreCLI@2 39 | displayName: Push libraries 40 | inputs: 41 | command: 'push' 42 | packagesToPush: '$(Build.ArtifactStagingDirectory)/*.nupkg' 43 | nuGetFeedType: 'internal' 44 | publishVstsFeed: 'cd43281b-c764-45ca-a804-974d979b8d0b/b4b93fc7-3bd6-45a6-a7bb-2c07e846463e' 45 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Entities/GuestAggregate/Guest.cs: -------------------------------------------------------------------------------- 1 | using Ardalis.GuardClauses; 2 | using GalaxyHotel.Core.Interfaces; 3 | using System.Collections.Generic; 4 | 5 | namespace GalaxyHotel.Core.Entities.GuestAggregate 6 | { 7 | public class Guest : BaseEntity, IAggregateRoot 8 | { 9 | private List paymentMethods = new List(); 10 | public IEnumerable PaymentMethods => paymentMethods.AsReadOnly(); 11 | 12 | public string FirstName { get; private set; } 13 | public string LastName { get; private set; } 14 | public Address Address { get; private set; } 15 | 16 | public Guest() 17 | { 18 | 19 | } 20 | 21 | public Guest(string firstName, string lastName, Address address) 22 | { 23 | Guard.Against.NullOrEmpty(firstName, nameof(firstName)); 24 | Guard.Against.NullOrEmpty(lastName, nameof(lastName)); 25 | Guard.Against.Null(address, nameof(address)); 26 | 27 | this.FirstName = firstName; 28 | this.LastName = lastName; 29 | this.Address = address; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/wwwroot/lib/jquery-validation/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright Jörn Zaefferer 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/wwwroot/lib/jquery-validation/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | ===================== 3 | 4 | Copyright Jörn Zaefferer 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Website/build-website.yml: -------------------------------------------------------------------------------- 1 | parameters: 2 | - name: librariesFeed 3 | displayName: 'Restore from Libraries NuGet feed' 4 | type: boolean 5 | default: true 6 | - name: enablePublish 7 | displayName: 'Enable publish' 8 | type: boolean 9 | default: true 10 | - name: publishArgs 11 | displayName: 'Publish Arguments' 12 | type: string 13 | default: '' 14 | 15 | steps: 16 | - ${{ if eq(parameters.librariesFeed, true) }}: 17 | - task: DotNetCoreCLI@2 18 | displayName: Restore packages 19 | inputs: 20 | command: 'restore' 21 | feedsToUse: 'select' 22 | vstsFeed: '834230a0-50c2-4971-954a-75eb9e3d47dd/dcb14a3c-e6ab-48df-ac52-3ae79a5055f7' 23 | 24 | - task: DotNetCoreCLI@2 25 | displayName: Build the website 26 | inputs: 27 | command: 'build' 28 | projects: '**/*.csproj' 29 | 30 | - task: DotNetCoreCLI@2 31 | displayName: Run tests 32 | inputs: 33 | command: 'test' 34 | projects: 'tests/**/*.csproj;!tests/**/*UITests*.csproj' 35 | 36 | - ${{ if eq(parameters.enablePublish, true) }}: 37 | - task: DotNetCoreCLI@2 38 | displayName: Publish the website 39 | inputs: 40 | command: 'publish' 41 | publishWebProjects: true 42 | arguments: ${{ parameters.publishArgs }} -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/wwwroot/lib/bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2018 Twitter, Inc. 4 | Copyright (c) 2011-2018 The Bootstrap Authors 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/wwwroot/lib/bootstrap/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2018 Twitter, Inc. 4 | Copyright (c) 2011-2018 The Bootstrap Authors 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /Website/tests/GalaxyHotel.UITests/BookingTests.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.VisualStudio.TestTools.UnitTesting; 2 | using OpenQA.Selenium; 3 | using OpenQA.Selenium.Chrome; 4 | 5 | namespace GalaxyHotel.UITests 6 | { 7 | [TestClass] 8 | public class BookingTests 9 | { 10 | private IWebDriver webDriver; 11 | private string baseUrl; 12 | 13 | public TestContext TestContext { get; set; } 14 | 15 | [TestMethod] 16 | [TestCategory("Chrome")] 17 | public void BookARoomAndCheckForConfirmationTest() 18 | { 19 | webDriver.Navigate().GoToUrl(baseUrl); 20 | webDriver.FindElement(By.LinkText("Book")).Click(); 21 | 22 | var bookingConfirmationText = webDriver.FindElement(By.XPath("//h1")).Text; 23 | 24 | Assert.AreEqual("Room booked!", bookingConfirmationText); 25 | } 26 | 27 | [TestInitialize()] 28 | public void SetupTest() 29 | { 30 | baseUrl = TestContext.Properties["baseUrl"].ToString(); 31 | webDriver = new ChromeDriver(); 32 | } 33 | 34 | [TestCleanup] 35 | public void TeardownTest() 36 | { 37 | webDriver.Quit(); 38 | webDriver.Dispose(); 39 | webDriver = null; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/GalaxyHotel.Website.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netcoreapp3.1 5 | aspnet-GalaxyHotel.Website-F4CD36CD-E24A-49DF-B7F9-29E514408D94 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | all 20 | runtime; build; native; contentfiles; analyzers; buildtransitive 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /Helpdesk/GalaxyHotel.HelpDesk.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30204.135 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GalaxyHotel.HelpDesk", "src\GalaxyHotel.HelpDesk\GalaxyHotel.HelpDesk.csproj", "{AD5E5C66-3AE0-4691-B4AF-9FDD8BAE6350}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{971F35C2-5B69-4D7B-9454-10D5C50B41C2}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {AD5E5C66-3AE0-4691-B4AF-9FDD8BAE6350}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {AD5E5C66-3AE0-4691-B4AF-9FDD8BAE6350}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {AD5E5C66-3AE0-4691-B4AF-9FDD8BAE6350}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {AD5E5C66-3AE0-4691-B4AF-9FDD8BAE6350}.Release|Any CPU.Build.0 = Release|Any CPU 20 | EndGlobalSection 21 | GlobalSection(SolutionProperties) = preSolution 22 | HideSolutionNode = FALSE 23 | EndGlobalSection 24 | GlobalSection(NestedProjects) = preSolution 25 | {AD5E5C66-3AE0-4691-B4AF-9FDD8BAE6350} = {971F35C2-5B69-4D7B-9454-10D5C50B41C2} 26 | EndGlobalSection 27 | GlobalSection(ExtensibilityGlobals) = postSolution 28 | SolutionGuid = {C85C9E2D-4FC7-4457-B37B-69F3A3CE0209} 29 | EndGlobalSection 30 | EndGlobal 31 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Infrastructure/Data/SpecificationEvaluator.cs: -------------------------------------------------------------------------------- 1 | using GalaxyHotel.Core.Interfaces; 2 | using GalaxyHotel.Core.Models; 3 | using Microsoft.EntityFrameworkCore; 4 | using System.Linq; 5 | 6 | namespace GalaxyHotel.Infrastructure.Data 7 | { 8 | public class SpecificationEvaluator where T : BaseEntity 9 | { 10 | public static IQueryable GetQuery(IQueryable inputQuery, ISpecification specification) 11 | { 12 | var query = inputQuery; 13 | 14 | if (specification.Criteria != null) 15 | { 16 | query = query.Where(specification.Criteria); 17 | } 18 | 19 | query = specification.Includes.Aggregate(query, 20 | (current, include) => current.Include(include)); 21 | 22 | query = specification.IncludeStrings.Aggregate(query, 23 | (current, include) => current.Include(include)); 24 | 25 | if (specification.OrderBy != null) 26 | { 27 | query = query.OrderBy(specification.OrderBy); 28 | } 29 | else if (specification.OrderByDescending != null) 30 | { 31 | query = query.OrderByDescending(specification.OrderByDescending); 32 | } 33 | 34 | if (specification.IsPagingEnabled) 35 | { 36 | query = query.Skip(specification.Skip) 37 | .Take(specification.Take); 38 | } 39 | 40 | return query; 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using AutoMapper.Mappers; 3 | using GalaxyHotel.Core.Models; 4 | using GalaxyHotel.Core.Services; 5 | using GalaxyHotel.Infrastructure.Data; 6 | using GalaxyHotel.Website.Models; 7 | using Microsoft.AspNetCore.Mvc; 8 | using Microsoft.Extensions.Logging; 9 | using System.Diagnostics; 10 | using System.Threading.Tasks; 11 | 12 | namespace GalaxyHotel.Website.Controllers 13 | { 14 | public class HomeController : Controller 15 | { 16 | private readonly ILogger _logger; 17 | private readonly GalaxyHotelContext _context; 18 | private readonly IMapper _mapper; 19 | 20 | public HomeController(ILogger logger, GalaxyHotelContext context, IMapper mapper) 21 | { 22 | _logger = logger; 23 | _context = context; 24 | _mapper = mapper; 25 | } 26 | 27 | public async Task Index() 28 | { 29 | var roomService = new RoomService(new Repository(_context), _mapper); 30 | var rooms = await roomService.GetAll(); 31 | 32 | return View(new RoomViewModel(rooms)); 33 | } 34 | 35 | public IActionResult Booking() 36 | { 37 | return View(); 38 | } 39 | 40 | [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] 41 | public IActionResult Error() 42 | { 43 | return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Entities/ReservationAggregate/Reservation.cs: -------------------------------------------------------------------------------- 1 | using Ardalis.GuardClauses; 2 | using GalaxyHotel.Core.Interfaces; 3 | using System; 4 | 5 | namespace GalaxyHotel.Core.Entities.ReservationAggregate 6 | { 7 | public class Reservation : BaseEntity, IAggregateRoot 8 | { 9 | public DateTimeOffset CheckIn { get; private set; } 10 | public DateTimeOffset CheckOut { get; private set; } 11 | public int GuestId { get; private set; } 12 | public int RoomId { get; private set; } 13 | public decimal PricePerNight { get; private set; } 14 | 15 | public Reservation() { } 16 | 17 | public Reservation(DateTimeOffset checkIn, DateTimeOffset checkOut, int guestId, int roomId, decimal pricePerNight) 18 | { 19 | Guard.Against.NegativeOrZero(guestId, nameof(guestId)); 20 | Guard.Against.NegativeOrZero(roomId, nameof(roomId)); 21 | Guard.Against.NegativeOrZero(pricePerNight, nameof(pricePerNight)); 22 | 23 | CheckIn = checkIn; 24 | CheckOut = checkOut; 25 | GuestId = guestId; 26 | RoomId = roomId; 27 | PricePerNight = pricePerNight; 28 | } 29 | 30 | public void UpdatePricePerNight(decimal pricePerNight) 31 | { 32 | PricePerNight = pricePerNight; 33 | } 34 | 35 | public void UpdateCheckOutDate(DateTimeOffset newCheckOutDate) 36 | { 37 | CheckOut = newCheckOutDate; 38 | } 39 | 40 | public decimal TotalPrice() 41 | { 42 | return PricePerNight * (decimal)(CheckOut.Subtract(CheckIn).TotalDays); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Infrastructure/Data/ModelBuilderExtensions.cs: -------------------------------------------------------------------------------- 1 | using GalaxyHotel.Core.Models; 2 | using Microsoft.EntityFrameworkCore; 3 | 4 | namespace GalaxyHotel.Infrastructure.Data 5 | { 6 | public static class ModelBuilderExtensions 7 | { 8 | public static void CreateSchema(this ModelBuilder modelBuilder) 9 | { 10 | modelBuilder.Entity() 11 | .HasOne(r => r.Guest) 12 | .WithMany(r => r.Reservations) 13 | .OnDelete(DeleteBehavior.Cascade); 14 | 15 | modelBuilder.Entity() 16 | .HasOne(r => r.Room) 17 | .WithMany(r => r.Reservations) 18 | .OnDelete(DeleteBehavior.Cascade); 19 | 20 | modelBuilder.Entity() 21 | .HasMany(g => g.Reservations) 22 | .WithOne(g => g.Guest) 23 | .OnDelete(DeleteBehavior.Cascade); 24 | 25 | modelBuilder.Entity() 26 | .HasOne(g => g.Address) 27 | .WithOne(g => g.Guest) 28 | .OnDelete(DeleteBehavior.Cascade); 29 | 30 | modelBuilder.Entity() 31 | .HasOne(g => g.PaymentMethod) 32 | .WithOne(g => g.Guest) 33 | .OnDelete(DeleteBehavior.Cascade); 34 | 35 | modelBuilder.Entity
() 36 | .HasOne(g => g.Guest) 37 | .WithOne(g => g.Address) 38 | .OnDelete(DeleteBehavior.Cascade); 39 | 40 | modelBuilder.Entity() 41 | .HasOne(g => g.Guest) 42 | .WithOne(g => g.PaymentMethod) 43 | .OnDelete(DeleteBehavior.Cascade); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/wwwroot/lib/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright JS Foundation and other contributors, https://js.foundation/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals. For exact contribution history, see the revision history 5 | available at https://github.com/jquery/jquery 6 | 7 | The following license applies to all parts of this software except as 8 | documented below: 9 | 10 | ==== 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | ==== 32 | 33 | All files located in the node_modules and external directories are 34 | externally maintained libraries used by this software which have their 35 | own licenses; we recommend you read them, as their terms may differ from 36 | the terms above. 37 | -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/wwwroot/lib/jquery/LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright JS Foundation and other contributors, https://js.foundation/ 2 | 3 | This software consists of voluntary contributions made by many 4 | individuals. For exact contribution history, see the revision history 5 | available at https://github.com/jquery/jquery 6 | 7 | The following license applies to all parts of this software except as 8 | documented below: 9 | 10 | ==== 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining 13 | a copy of this software and associated documentation files (the 14 | "Software"), to deal in the Software without restriction, including 15 | without limitation the rights to use, copy, modify, merge, publish, 16 | distribute, sublicense, and/or sell copies of the Software, and to 17 | permit persons to whom the Software is furnished to do so, subject to 18 | the following conditions: 19 | 20 | The above copyright notice and this permission notice shall be 21 | included in all copies or substantial portions of the Software. 22 | 23 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 27 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 28 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 30 | 31 | ==== 32 | 33 | All files located in the node_modules and external directories are 34 | externally maintained libraries used by this software which have their 35 | own licenses; we recommend you read them, as their terms may differ from 36 | the terms above. 37 | -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | /* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification 2 | for details on configuring this project to bundle and minify static web assets. */ 3 | 4 | a.navbar-brand { 5 | white-space: normal; 6 | text-align: center; 7 | word-break: break-all; 8 | } 9 | 10 | /* Provide sufficient contrast against white background */ 11 | a { 12 | color: #0366d6; 13 | } 14 | 15 | .btn-primary { 16 | color: #fff; 17 | background-color: #1b6ec2; 18 | border-color: #1861ac; 19 | } 20 | 21 | .nav-pills .nav-link.active, .nav-pills .show > .nav-link { 22 | color: #fff; 23 | background-color: #1b6ec2; 24 | border-color: #1861ac; 25 | } 26 | 27 | /* Sticky footer styles 28 | -------------------------------------------------- */ 29 | html { 30 | font-size: 14px; 31 | } 32 | @media (min-width: 768px) { 33 | html { 34 | font-size: 16px; 35 | } 36 | } 37 | 38 | .border-top { 39 | border-top: 1px solid #e5e5e5; 40 | } 41 | .border-bottom { 42 | border-bottom: 1px solid #e5e5e5; 43 | } 44 | 45 | .box-shadow { 46 | box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05); 47 | } 48 | 49 | button.accept-policy { 50 | font-size: 1rem; 51 | line-height: inherit; 52 | } 53 | 54 | /* Sticky footer styles 55 | -------------------------------------------------- */ 56 | html { 57 | position: relative; 58 | min-height: 100%; 59 | } 60 | 61 | body { 62 | /* Margin bottom by footer height */ 63 | margin-bottom: 60px; 64 | } 65 | .footer { 66 | position: absolute; 67 | bottom: 0; 68 | width: 100%; 69 | white-space: nowrap; 70 | line-height: 60px; /* Vertically center the text there */ 71 | } 72 | 73 | table { 74 | width: 80%; 75 | font-size: 20pt; 76 | text-align: center; 77 | margin-top: 200px; 78 | margin-left: auto; 79 | margin-right: auto; 80 | } 81 | 82 | tr { 83 | width: 200px; 84 | } 85 | 86 | td { 87 | width: 200px; 88 | } -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/Controllers/HomeController.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using GalaxyHotel.Core.Models; 3 | using GalaxyHotel.Core.Services; 4 | using GalaxyHotel.HelpDesk.Models; 5 | using GalaxyHotel.Infrastructure.Data; 6 | using Microsoft.AspNetCore.Mvc; 7 | using Microsoft.Extensions.Logging; 8 | using System.Diagnostics; 9 | using System.Threading.Tasks; 10 | 11 | namespace GalaxyHotel.HelpDesk.Controllers 12 | { 13 | public class HomeController : Controller 14 | { 15 | private readonly ILogger _logger; 16 | private readonly GalaxyHotelContext _context; 17 | private readonly IMapper _mapper; 18 | 19 | public HomeController(ILogger logger, GalaxyHotelContext context, IMapper mapper) 20 | { 21 | _logger = logger; 22 | _context = context; 23 | _mapper = mapper; 24 | } 25 | 26 | public async Task Index() 27 | { 28 | var roomService = new RoomService(new Repository(_context), _mapper); 29 | var rooms = await roomService.GetAll(); 30 | 31 | return View(new RoomViewModel(rooms)); 32 | } 33 | 34 | public async Task Reservations() 35 | { 36 | var reservationService = new ReservationService(new ReservationRepository(_context), new Repository(_context), _mapper); 37 | var reservations = await reservationService.GetAll(); 38 | 39 | return View(new ReservationViewModel(reservations)); 40 | } 41 | 42 | public IActionResult Cancel() 43 | { 44 | return View(); 45 | } 46 | 47 | [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)] 48 | public IActionResult Error() 49 | { 50 | return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier }); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/wwwroot/css/site.css: -------------------------------------------------------------------------------- 1 | /* Please see documentation at https://docs.microsoft.com/aspnet/core/client-side/bundling-and-minification 2 | for details on configuring this project to bundle and minify static web assets. */ 3 | 4 | a.navbar-brand { 5 | white-space: normal; 6 | text-align: center; 7 | word-break: break-all; 8 | } 9 | 10 | /* Provide sufficient contrast against white background */ 11 | a { 12 | color: #0366d6; 13 | } 14 | 15 | .btn-primary { 16 | color: #fff; 17 | background-color: #1b6ec2; 18 | border-color: #1861ac; 19 | } 20 | 21 | .nav-pills .nav-link.active, .nav-pills .show > .nav-link { 22 | color: #fff; 23 | background-color: #1b6ec2; 24 | border-color: #1861ac; 25 | } 26 | 27 | /* Sticky footer styles 28 | -------------------------------------------------- */ 29 | html { 30 | font-size: 14px; 31 | } 32 | 33 | @media (min-width: 768px) { 34 | html { 35 | font-size: 16px; 36 | } 37 | } 38 | 39 | .border-top { 40 | border-top: 1px solid #e5e5e5; 41 | } 42 | 43 | .border-bottom { 44 | border-bottom: 1px solid #e5e5e5; 45 | } 46 | 47 | .box-shadow { 48 | box-shadow: 0 .25rem .75rem rgba(0, 0, 0, .05); 49 | } 50 | 51 | button.accept-policy { 52 | font-size: 1rem; 53 | line-height: inherit; 54 | } 55 | 56 | /* Sticky footer styles 57 | -------------------------------------------------- */ 58 | html { 59 | position: relative; 60 | min-height: 100%; 61 | } 62 | 63 | body { 64 | /* Margin bottom by footer height */ 65 | margin-bottom: 60px; 66 | } 67 | 68 | .footer { 69 | position: absolute; 70 | bottom: 0; 71 | width: 100%; 72 | white-space: nowrap; 73 | line-height: 60px; /* Vertically center the text there */ 74 | } 75 | 76 | table { 77 | width: 80%; 78 | font-size: 20pt; 79 | text-align: center; 80 | margin-top: 200px; 81 | margin-left: auto; 82 | margin-right: auto; 83 | } 84 | 85 | tr { 86 | width: 200px; 87 | } 88 | 89 | td { 90 | width: 200px; 91 | } 92 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | @ViewData["Title"] - GalaxyHotel.Website 7 | 8 | 9 | 10 | 11 |
12 | 29 |
30 |
31 |
32 | @RenderBody() 33 |
34 |
35 | 36 |
37 |
38 | © 2020 - GalaxyHotel.Website - Privacy 39 |
40 |
41 | 42 | 43 | 44 | @RenderSection("Scripts", required: false) 45 | 46 | 47 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Specification/BaseSpecifition.cs: -------------------------------------------------------------------------------- 1 | using GalaxyHotel.Core.Helpers.Query; 2 | using GalaxyHotel.Core.Interfaces; 3 | using System; 4 | using System.Collections.Generic; 5 | using System.Linq.Expressions; 6 | 7 | namespace GalaxyHotel.Core.Specification 8 | { 9 | public abstract class BaseSpecification : ISpecification 10 | { 11 | protected BaseSpecification() { } 12 | 13 | protected BaseSpecification(Expression> criteria) 14 | { 15 | Criteria = criteria; 16 | } 17 | 18 | public Expression> Criteria { get; } 19 | public List>> Includes { get; } = new List>>(); 20 | public List IncludeStrings { get; } = new List(); 21 | public Expression> OrderBy { get; private set; } 22 | public Expression> OrderByDescending { get; private set; } 23 | 24 | public int Take { get; private set; } 25 | public int Skip { get; private set; } 26 | public bool IsPagingEnabled { get; private set; } = false; 27 | 28 | protected virtual void AddInclude(Expression> includeExpression) 29 | { 30 | Includes.Add(includeExpression); 31 | } 32 | 33 | protected virtual void AddIncludes(Func, IIncludeQuery> includeGenerator) 34 | { 35 | var includeQuery = includeGenerator(new IncludeAggregator()); 36 | IncludeStrings.AddRange(includeQuery.Paths); 37 | } 38 | 39 | protected virtual void AddInclude(string includeString) 40 | { 41 | IncludeStrings.Add(includeString); 42 | } 43 | 44 | protected virtual void ApplyPaging(int skip, int take) 45 | { 46 | Skip = skip; 47 | Take = take; 48 | IsPagingEnabled = true; 49 | } 50 | 51 | protected virtual void ApplyOrderBy(Expression> orderByExpression) 52 | { 53 | OrderBy = orderByExpression; 54 | } 55 | 56 | protected virtual void ApplyOrderByDescending(Expression> orderByDescendingExpression) 57 | { 58 | OrderByDescending = orderByDescendingExpression; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/Views/Shared/_Layout.cshtml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | @ViewData["Title"] - GalaxyHotel.HelpDesk 7 | 8 | 9 | 10 | 11 |
12 | 31 |
32 |
33 |
34 | @RenderBody() 35 |
36 |
37 | 38 |
39 |
40 | © 2020 - GalaxyHotel.HelpDesk - Privacy 41 |
42 |
43 | 44 | 45 | 46 | @RenderSection("Scripts", required: false) 47 | 48 | 49 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Infrastructure/Data/Repository.cs: -------------------------------------------------------------------------------- 1 | using GalaxyHotel.Core.Interfaces; 2 | using GalaxyHotel.Core.Models; 3 | using Microsoft.EntityFrameworkCore; 4 | using System.Collections.Generic; 5 | using System.Linq; 6 | using System.Threading.Tasks; 7 | 8 | namespace GalaxyHotel.Infrastructure.Data 9 | { 10 | public class Repository : IAsyncRepository where T : BaseEntity//, IAggregateRoot 11 | { 12 | protected readonly GalaxyHotelContext dbContext; 13 | 14 | public Repository(GalaxyHotelContext dbContext) 15 | { 16 | this.dbContext = dbContext; 17 | } 18 | 19 | public virtual async Task GetByIdAsync(int id) 20 | { 21 | return await dbContext.Set().FindAsync(id); 22 | } 23 | 24 | public virtual async Task> ListAllAsync() 25 | { 26 | return await dbContext.Set().ToListAsync(); 27 | } 28 | 29 | public async Task> ListAsync(ISpecification spec) 30 | { 31 | return await ApplySpecification(spec).ToListAsync(); 32 | } 33 | 34 | public async Task CountAsync(ISpecification spec) 35 | { 36 | return await ApplySpecification(spec).CountAsync(); 37 | } 38 | 39 | public async Task AddAsync(T entity) 40 | { 41 | await dbContext.Set().AddAsync(entity); 42 | await dbContext.SaveChangesAsync(); 43 | 44 | return entity; 45 | } 46 | 47 | public async Task UpdateAsync(T entity) 48 | { 49 | dbContext.Entry(entity).State = EntityState.Modified; 50 | await dbContext.SaveChangesAsync(); 51 | } 52 | 53 | public async Task DeleteAsync(T entity) 54 | { 55 | dbContext.Set().Remove(entity); 56 | await dbContext.SaveChangesAsync(); 57 | } 58 | 59 | public async Task FirstAsync(ISpecification spec) 60 | { 61 | return await ApplySpecification(spec).FirstAsync(); 62 | } 63 | 64 | public async Task FirstOrDefaultAsync(ISpecification spec) 65 | { 66 | return await ApplySpecification(spec).FirstOrDefaultAsync(); 67 | } 68 | 69 | private IQueryable ApplySpecification(ISpecification spec) 70 | { 71 | return SpecificationEvaluator.GetQuery(dbContext.Set().AsQueryable(), spec); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /Website/GalaxyHotel.Website.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30204.135 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EC94B521-83F2-49FF-AD14-4B978CD271B3}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{D8F2C080-3D9D-4D9F-BF1D-B6F6FCCC6877}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GalaxyHotel.Website", "src\GalaxyHotel.Website\GalaxyHotel.Website.csproj", "{DA0F1A87-71D4-4047-A994-15E934ADB858}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GalaxyHotel.UITests", "tests\GalaxyHotel.UITests\GalaxyHotel.UITests.csproj", "{B623DDD1-C43E-46AD-8094-D26851D3E35D}" 13 | EndProject 14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "db", "db", "{23FFBAD7-12B9-442D-A59A-5FD851B3EDF4}" 15 | ProjectSection(SolutionItems) = preProject 16 | db\SeedGalaxyHotelDbScript.sql = db\SeedGalaxyHotelDbScript.sql 17 | EndProjectSection 18 | EndProject 19 | Global 20 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 21 | Debug|Any CPU = Debug|Any CPU 22 | Release|Any CPU = Release|Any CPU 23 | EndGlobalSection 24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 25 | {DA0F1A87-71D4-4047-A994-15E934ADB858}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 26 | {DA0F1A87-71D4-4047-A994-15E934ADB858}.Debug|Any CPU.Build.0 = Debug|Any CPU 27 | {DA0F1A87-71D4-4047-A994-15E934ADB858}.Release|Any CPU.ActiveCfg = Release|Any CPU 28 | {DA0F1A87-71D4-4047-A994-15E934ADB858}.Release|Any CPU.Build.0 = Release|Any CPU 29 | {B623DDD1-C43E-46AD-8094-D26851D3E35D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 30 | {B623DDD1-C43E-46AD-8094-D26851D3E35D}.Debug|Any CPU.Build.0 = Debug|Any CPU 31 | {B623DDD1-C43E-46AD-8094-D26851D3E35D}.Release|Any CPU.ActiveCfg = Release|Any CPU 32 | {B623DDD1-C43E-46AD-8094-D26851D3E35D}.Release|Any CPU.Build.0 = Release|Any CPU 33 | EndGlobalSection 34 | GlobalSection(SolutionProperties) = preSolution 35 | HideSolutionNode = FALSE 36 | EndGlobalSection 37 | GlobalSection(NestedProjects) = preSolution 38 | {DA0F1A87-71D4-4047-A994-15E934ADB858} = {EC94B521-83F2-49FF-AD14-4B978CD271B3} 39 | {B623DDD1-C43E-46AD-8094-D26851D3E35D} = {D8F2C080-3D9D-4D9F-BF1D-B6F6FCCC6877} 40 | EndGlobalSection 41 | GlobalSection(ExtensibilityGlobals) = postSolution 42 | SolutionGuid = {3F2CA0D0-68C8-42E2-BE75-EB4DFD8A3E81} 43 | EndGlobalSection 44 | EndGlobal 45 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Services/ReservationService.cs: -------------------------------------------------------------------------------- 1 | using Ardalis.GuardClauses; 2 | using AutoMapper; 3 | using GalaxyHotel.Core.Extensions; 4 | using GalaxyHotel.Core.Interfaces; 5 | using GalaxyHotel.Core.Models; 6 | using GalaxyHotel.Core.Specification; 7 | using GalaxyHotel.Dto; 8 | using System; 9 | using System.Collections.Generic; 10 | using System.Threading.Tasks; 11 | 12 | namespace GalaxyHotel.Core.Services 13 | { 14 | public class ReservationService : IReservationService 15 | { 16 | private readonly IAsyncRepository reservationRepository; 17 | private readonly IAsyncRepository roomRepository; 18 | private readonly IMapper mapper; 19 | 20 | public ReservationService(IAsyncRepository reservationRepository, IAsyncRepository roomRepository, 21 | IMapper mapper) 22 | { 23 | this.reservationRepository = reservationRepository; 24 | this.roomRepository = roomRepository; 25 | this.mapper = mapper; 26 | } 27 | 28 | public async Task CancelReservationAsync(int reservationId) 29 | { 30 | var reservation = await reservationRepository.GetByIdAsync(reservationId); 31 | Guard.Against.NotExistingReservation(reservation); 32 | 33 | await reservationRepository.DeleteAsync(reservation); 34 | } 35 | 36 | public async Task CreateReservationAsync(DateTimeOffset checkIn, DateTimeOffset checkOut, int guestId, int roomId) 37 | { 38 | var room = await roomRepository.GetByIdAsync(roomId); 39 | Guard.Against.Null(room, nameof(room)); 40 | 41 | var reservation = new Reservation 42 | { 43 | CheckIn = checkIn, 44 | CheckOut = checkOut, 45 | GuestId = guestId, 46 | RoomId = roomId, 47 | TotalPrice = room.PricePerNight 48 | }; 49 | 50 | await reservationRepository.AddAsync(reservation); 51 | } 52 | 53 | public async Task> GetAll() 54 | { 55 | var specification = new ReservationWithDetailsSpecification(); 56 | var reservations = await reservationRepository.ListAsync(specification); 57 | return mapper.Map>(reservations); 58 | } 59 | 60 | public async Task GetByIdAsync(int reservationId) 61 | { 62 | var reservation = await reservationRepository.GetByIdAsync(reservationId); 63 | return mapper.Map(reservation); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/Startup.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using GalaxyHotel.Core.Mapping; 3 | using GalaxyHotel.Infrastructure.Data; 4 | using Microsoft.AspNetCore.Builder; 5 | using Microsoft.AspNetCore.Hosting; 6 | using Microsoft.EntityFrameworkCore; 7 | using Microsoft.Extensions.Configuration; 8 | using Microsoft.Extensions.DependencyInjection; 9 | using Microsoft.Extensions.Hosting; 10 | 11 | namespace GalaxyHotel.HelpDesk 12 | { 13 | public class Startup 14 | { 15 | public Startup(IConfiguration configuration) 16 | { 17 | Configuration = configuration; 18 | } 19 | 20 | public IConfiguration Configuration { get; } 21 | 22 | // This method gets called by the runtime. Use this method to add services to the container. 23 | public void ConfigureServices(IServiceCollection services) 24 | { 25 | services.AddDbContext(options => 26 | options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), 27 | b => b.MigrationsAssembly("GalaxyHotel.HelpDesk"))); 28 | services.AddAutoMapper(typeof(Startup), typeof(GalaxyHotelProfile)); 29 | services.AddControllersWithViews(); 30 | } 31 | 32 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 33 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 34 | { 35 | using (var serviceScope = app.ApplicationServices.GetService().CreateScope()) 36 | { 37 | var galaxyHotelContext = serviceScope.ServiceProvider.GetRequiredService(); 38 | galaxyHotelContext.Database.EnsureCreated(); 39 | if (env.IsDevelopment()) galaxyHotelContext.Database.Migrate(); 40 | } 41 | 42 | if (env.IsDevelopment()) 43 | { 44 | app.UseDeveloperExceptionPage(); 45 | } 46 | else 47 | { 48 | app.UseExceptionHandler("/Home/Error"); 49 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 50 | app.UseHsts(); 51 | } 52 | app.UseHttpsRedirection(); 53 | app.UseStaticFiles(); 54 | 55 | app.UseRouting(); 56 | 57 | app.UseAuthorization(); 58 | 59 | app.UseEndpoints(endpoints => 60 | { 61 | endpoints.MapControllerRoute( 62 | name: "default", 63 | pattern: "{controller=Home}/{action=Index}/{id?}"); 64 | }); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /Libraries/src/GalaxyHotel.Core/Helpers/Query/IncludeQueryExtensions.cs: -------------------------------------------------------------------------------- 1 | using GalaxyHotel.Core.Interfaces; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq.Expressions; 5 | 6 | namespace GalaxyHotel.Core.Helpers.Query 7 | { 8 | public static class IncludeQueryExtensions 9 | { 10 | public static IIncludeQuery Include( 11 | this IIncludeQuery query, 12 | Expression> selector) 13 | { 14 | query.Visitor.Visit(selector); 15 | 16 | var includeQuery = new IncludeQuery(query.PathMap); 17 | query.PathMap[includeQuery] = query.Visitor.Path; 18 | 19 | return includeQuery; 20 | } 21 | 22 | public static IIncludeQuery ThenInclude( 23 | this IIncludeQuery query, 24 | Expression> selector) 25 | { 26 | query.Visitor.Visit(selector); 27 | 28 | // If the visitor did not generated a path, return a new IncludeQuery with an unmodified PathMap. 29 | if (string.IsNullOrEmpty(query.Visitor.Path)) 30 | { 31 | return new IncludeQuery(query.PathMap); 32 | } 33 | 34 | var pathMap = query.PathMap; 35 | var existingPath = pathMap[query]; 36 | pathMap.Remove(query); 37 | 38 | var includeQuery = new IncludeQuery(query.PathMap); 39 | pathMap[includeQuery] = $"{existingPath}.{query.Visitor.Path}"; 40 | 41 | return includeQuery; 42 | } 43 | 44 | public static IIncludeQuery ThenInclude( 45 | this IIncludeQuery> query, 46 | Expression> selector) 47 | { 48 | query.Visitor.Visit(selector); 49 | 50 | // If the visitor did not generated a path, return a new IncludeQuery with an unmodified PathMap. 51 | if (string.IsNullOrEmpty(query.Visitor.Path)) 52 | { 53 | return new IncludeQuery(query.PathMap); 54 | } 55 | 56 | var pathMap = query.PathMap; 57 | var existingPath = pathMap[query]; 58 | pathMap.Remove(query); 59 | 60 | var includeQuery = new IncludeQuery(query.PathMap); 61 | pathMap[includeQuery] = $"{existingPath}.{query.Visitor.Path}"; 62 | 63 | return includeQuery; 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Startup.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using GalaxyHotel.Core.Mapping; 3 | using GalaxyHotel.Infrastructure.Data; 4 | using GalaxyHotel.Website.Data; 5 | using Microsoft.AspNetCore.Builder; 6 | using Microsoft.AspNetCore.Hosting; 7 | using Microsoft.AspNetCore.Identity; 8 | using Microsoft.EntityFrameworkCore; 9 | using Microsoft.Extensions.Configuration; 10 | using Microsoft.Extensions.DependencyInjection; 11 | using Microsoft.Extensions.Hosting; 12 | 13 | namespace GalaxyHotel.Website 14 | { 15 | public class Startup 16 | { 17 | public Startup(IConfiguration configuration) 18 | { 19 | Configuration = configuration; 20 | } 21 | 22 | public IConfiguration Configuration { get; } 23 | 24 | // This method gets called by the runtime. Use this method to add services to the container. 25 | public void ConfigureServices(IServiceCollection services) 26 | { 27 | services.AddDbContext(options => 28 | options.UseSqlServer( 29 | Configuration.GetConnectionString("DefaultConnection"))); 30 | services.AddDefaultIdentity(options => options.SignIn.RequireConfirmedAccount = true) 31 | .AddEntityFrameworkStores(); 32 | services.AddDbContext(options => 33 | options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"), 34 | b => b.MigrationsAssembly("GalaxyHotel.Website"))); 35 | services.AddAutoMapper(typeof(Startup), typeof(GalaxyHotelProfile)); 36 | services.AddControllersWithViews(); 37 | services.AddRazorPages(); 38 | } 39 | 40 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. 41 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env) 42 | { 43 | using (var serviceScope = app.ApplicationServices.GetService().CreateScope()) 44 | { 45 | var galaxyHotelContext = serviceScope.ServiceProvider.GetRequiredService(); 46 | galaxyHotelContext.Database.EnsureCreated(); 47 | if (env.IsDevelopment()) galaxyHotelContext.Database.Migrate(); 48 | 49 | var identityContext = serviceScope.ServiceProvider.GetRequiredService(); 50 | identityContext.Database.Migrate(); 51 | } 52 | 53 | if (env.IsDevelopment()) 54 | { 55 | app.UseDeveloperExceptionPage(); 56 | app.UseDatabaseErrorPage(); 57 | } 58 | else 59 | { 60 | app.UseExceptionHandler("/Home/Error"); 61 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. 62 | app.UseHsts(); 63 | } 64 | app.UseHttpsRedirection(); 65 | app.UseStaticFiles(); 66 | 67 | app.UseRouting(); 68 | 69 | app.UseAuthentication(); 70 | app.UseAuthorization(); 71 | 72 | app.UseEndpoints(endpoints => 73 | { 74 | endpoints.MapControllerRoute( 75 | name: "default", 76 | pattern: "{controller=Home}/{action=Index}/{id?}"); 77 | endpoints.MapRazorPages(); 78 | }); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/) 3 | * Copyright 2011-2019 The Bootstrap Authors 4 | * Copyright 2011-2019 Twitter, Inc. 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) 7 | */*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important} 8 | /*# sourceMappingURL=bootstrap-reboot.min.css.map */ -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/) 3 | * Copyright 2011-2019 The Bootstrap Authors 4 | * Copyright 2011-2019 Twitter, Inc. 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) 7 | */*,::after,::before{box-sizing:border-box}html{font-family:sans-serif;line-height:1.15;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}article,aside,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}body{margin:0;font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;text-align:left;background-color:#fff}[tabindex="-1"]:focus{outline:0!important}hr{box-sizing:content-box;height:0;overflow:visible}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem}p{margin-top:0;margin-bottom:1rem}abbr[data-original-title],abbr[title]{text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;border-bottom:0;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:80%}sub,sup{position:relative;font-size:75%;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#007bff;text-decoration:none;background-color:transparent}a:hover{color:#0056b3;text-decoration:underline}a:not([href]):not([tabindex]){color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus,a:not([href]):not([tabindex]):hover{color:inherit;text-decoration:none}a:not([href]):not([tabindex]):focus{outline:0}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em}pre{margin-top:0;margin-bottom:1rem;overflow:auto}figure{margin:0 0 1rem}img{vertical-align:middle;border-style:none}svg{overflow:hidden;vertical-align:middle}table{border-collapse:collapse}caption{padding-top:.75rem;padding-bottom:.75rem;color:#6c757d;text-align:left;caption-side:bottom}th{text-align:inherit}label{display:inline-block;margin-bottom:.5rem}button{border-radius:0}button:focus{outline:1px dotted;outline:5px auto -webkit-focus-ring-color}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,input{overflow:visible}button,select{text-transform:none}select{word-wrap:normal}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{padding:0;border-style:none}input[type=checkbox],input[type=radio]{box-sizing:border-box;padding:0}input[type=date],input[type=datetime-local],input[type=month],input[type=time]{-webkit-appearance:listbox}textarea{overflow:auto;resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{display:block;width:100%;max-width:100%;padding:0;margin-bottom:.5rem;font-size:1.5rem;line-height:inherit;color:inherit;white-space:normal}progress{vertical-align:baseline}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:none}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}summary{display:list-item;cursor:pointer}template{display:none}[hidden]{display:none!important} 8 | /*# sourceMappingURL=bootstrap-reboot.min.css.map */ -------------------------------------------------------------------------------- /Website/db/SeedGalaxyHotelDbScript.sql: -------------------------------------------------------------------------------- 1 | DELETE FROM [dbo].[Reservations] 2 | GO 3 | DELETE FROM [dbo].[Guests] 4 | GO 5 | DELETE FROM [dbo].[Rooms] 6 | GO 7 | DELETE FROM [dbo].[PaymentMethods] 8 | GO 9 | DELETE FROM [dbo].[Addresses] 10 | GO 11 | 12 | SET IDENTITY_INSERT [dbo].[Addresses] ON 13 | GO 14 | INSERT [dbo].[Addresses] ([Id], [Street], [City], [State], [Country], [ZipCode]) VALUES (1, N'13th Space Road, Brooklyn', N'New York', N'New York', N'United States of America', N'13021') 15 | GO 16 | INSERT [dbo].[Addresses] ([Id], [Street], [City], [State], [Country], [ZipCode]) VALUES (2, N'12th Hollywood road, Hollywood', N'Los Angeles', N'New York', N'United States of America', N'33024') 17 | GO 18 | INSERT [dbo].[Addresses] ([Id], [Street], [City], [State], [Country], [ZipCode]) VALUES (3, N'Piazza Plebiscito 1, Naples', N'Naples', N'', N'Italy', N'80100') 19 | GO 20 | INSERT [dbo].[Addresses] ([Id], [Street], [City], [State], [Country], [ZipCode]) VALUES (4, N'14th Valley Road', N'London', N'New York', N'United States of America', N'WC2N 5DU') 21 | GO 22 | SET IDENTITY_INSERT [dbo].[Addresses] OFF 23 | GO 24 | SET IDENTITY_INSERT [dbo].[PaymentMethods] ON 25 | GO 26 | INSERT [dbo].[PaymentMethods] ([Id], [Alias], [CardNumber], [DueDate]) VALUES (1, N'Private Credit Card 1', N'123412349876598765', CAST(N'2021-08-28T10:25:09.4799091+02:00' AS DateTimeOffset)) 27 | GO 28 | INSERT [dbo].[PaymentMethods] ([Id], [Alias], [CardNumber], [DueDate]) VALUES (2, N'Private Credit Card 2', N'123412349876598766', CAST(N'2021-08-28T10:25:09.4871490+02:00' AS DateTimeOffset)) 29 | GO 30 | INSERT [dbo].[PaymentMethods] ([Id], [Alias], [CardNumber], [DueDate]) VALUES (3, N'Private Credit Card 3', N'123412349876598767', CAST(N'2021-08-28T10:25:09.4871614+02:00' AS DateTimeOffset)) 31 | GO 32 | INSERT [dbo].[PaymentMethods] ([Id], [Alias], [CardNumber], [DueDate]) VALUES (4, N'Private Credit Card 4', N'123412349876598768', CAST(N'2021-08-28T10:25:09.4871635+02:00' AS DateTimeOffset)) 33 | GO 34 | SET IDENTITY_INSERT [dbo].[PaymentMethods] OFF 35 | GO 36 | SET IDENTITY_INSERT [dbo].[Guests] ON 37 | GO 38 | INSERT [dbo].[Guests] ([Id], [FirstName], [LastName], [AddressId], [PaymentMethodId]) VALUES (1, N'John', N'Doe', 1, 1) 39 | GO 40 | INSERT [dbo].[Guests] ([Id], [FirstName], [LastName], [AddressId], [PaymentMethodId]) VALUES (2, N'Alex', N'Harvey', 2, 2) 41 | GO 42 | INSERT [dbo].[Guests] ([Id], [FirstName], [LastName], [AddressId], [PaymentMethodId]) VALUES (3, N'Antonio', N'Esposito', 3, 3) 43 | GO 44 | INSERT [dbo].[Guests] ([Id], [FirstName], [LastName], [AddressId], [PaymentMethodId]) VALUES (4, N'Mark', N'River', 4, 4) 45 | GO 46 | SET IDENTITY_INSERT [dbo].[Guests] OFF 47 | GO 48 | SET IDENTITY_INSERT [dbo].[Rooms] ON 49 | GO 50 | INSERT [dbo].[Rooms] ([Id], [Name], [Floor], [PricePerNight]) VALUES (1, N'Andromeda', 1, CAST(200.00 AS Decimal(18, 2))) 51 | GO 52 | INSERT [dbo].[Rooms] ([Id], [Name], [Floor], [PricePerNight]) VALUES (2, N'Whirpool', 1, CAST(150.00 AS Decimal(18, 2))) 53 | GO 54 | INSERT [dbo].[Rooms] ([Id], [Name], [Floor], [PricePerNight]) VALUES (3, N'Sombrero', 1, CAST(100.00 AS Decimal(18, 2))) 55 | GO 56 | SET IDENTITY_INSERT [dbo].[Rooms] OFF 57 | GO 58 | SET IDENTITY_INSERT [dbo].[Reservations] ON 59 | GO 60 | INSERT [dbo].[Reservations] ([Id], [CheckIn], [CheckOut], [TotalPrice], [GuestId], [RoomId]) VALUES (1, CAST(N'2020-08-28T10:25:09.4921003+02:00' AS DateTimeOffset), CAST(N'2020-08-29T10:25:09.4921050+02:00' AS DateTimeOffset), CAST(200.00 AS Decimal(18, 2)), 1, 1) 61 | GO 62 | INSERT [dbo].[Reservations] ([Id], [CheckIn], [CheckOut], [TotalPrice], [GuestId], [RoomId]) VALUES (2, CAST(N'2020-08-28T10:25:09.4921003+02:00' AS DateTimeOffset), CAST(N'2020-08-29T10:25:09.4921050+02:00' AS DateTimeOffset), CAST(150.00 AS Decimal(18, 2)), 2, 2) 63 | GO 64 | INSERT [dbo].[Reservations] ([Id], [CheckIn], [CheckOut], [TotalPrice], [GuestId], [RoomId]) VALUES (3, CAST(N'2020-08-28T10:25:09.4921003+02:00' AS DateTimeOffset), CAST(N'2020-08-29T10:25:09.4921050+02:00' AS DateTimeOffset), CAST(100.00 AS Decimal(18, 2)), 3, 3) 65 | GO 66 | SET IDENTITY_INSERT [dbo].[Reservations] OFF 67 | GO 68 | -------------------------------------------------------------------------------- /Libraries/GalaxyHotel.Libraries.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30204.135 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GalaxyHotel.Core", "src\GalaxyHotel.Core\GalaxyHotel.Core.csproj", "{B359C0F4-02C6-4776-AA6F-8855B23EA978}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{048E1DA2-519E-4B47-864A-9F9A96C54C07}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GalaxyHotel.Dto", "src\GalaxyHotel.Dto\GalaxyHotel.Dto.csproj", "{85AE3219-9A17-4C8B-922D-076177312114}" 11 | EndProject 12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GalaxyHotel.Infrastructure", "src\GalaxyHotel.Infrastructure\GalaxyHotel.Infrastructure.csproj", "{F1A30111-6929-4F0B-ADCD-5F01A2158A71}" 13 | EndProject 14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{3A549608-93C5-45F3-BE4B-84105FCE9B9E}" 15 | EndProject 16 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GalaxyHotel.Core.Services.Tests", "tests\GalaxyHotel.Core.Services.Tests\GalaxyHotel.Core.Services.Tests.csproj", "{1C1CB7D0-49AD-401F-BCFD-962F07ED9F81}" 17 | EndProject 18 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GalaxyHotel.Infrastructure.IntegrationTests", "tests\GalaxyHotel.Infrastructure.IntegrationTests\GalaxyHotel.Infrastructure.IntegrationTests.csproj", "{CA831A3B-17EA-4678-B41C-A9D973FE6CE5}" 19 | EndProject 20 | Global 21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 22 | Debug|Any CPU = Debug|Any CPU 23 | Release|Any CPU = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 26 | {B359C0F4-02C6-4776-AA6F-8855B23EA978}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {B359C0F4-02C6-4776-AA6F-8855B23EA978}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {B359C0F4-02C6-4776-AA6F-8855B23EA978}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {B359C0F4-02C6-4776-AA6F-8855B23EA978}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {85AE3219-9A17-4C8B-922D-076177312114}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {85AE3219-9A17-4C8B-922D-076177312114}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {85AE3219-9A17-4C8B-922D-076177312114}.Release|Any CPU.ActiveCfg = Release|Any CPU 33 | {85AE3219-9A17-4C8B-922D-076177312114}.Release|Any CPU.Build.0 = Release|Any CPU 34 | {F1A30111-6929-4F0B-ADCD-5F01A2158A71}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 35 | {F1A30111-6929-4F0B-ADCD-5F01A2158A71}.Debug|Any CPU.Build.0 = Debug|Any CPU 36 | {F1A30111-6929-4F0B-ADCD-5F01A2158A71}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {F1A30111-6929-4F0B-ADCD-5F01A2158A71}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {1C1CB7D0-49AD-401F-BCFD-962F07ED9F81}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 39 | {1C1CB7D0-49AD-401F-BCFD-962F07ED9F81}.Debug|Any CPU.Build.0 = Debug|Any CPU 40 | {1C1CB7D0-49AD-401F-BCFD-962F07ED9F81}.Release|Any CPU.ActiveCfg = Release|Any CPU 41 | {1C1CB7D0-49AD-401F-BCFD-962F07ED9F81}.Release|Any CPU.Build.0 = Release|Any CPU 42 | {CA831A3B-17EA-4678-B41C-A9D973FE6CE5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 43 | {CA831A3B-17EA-4678-B41C-A9D973FE6CE5}.Debug|Any CPU.Build.0 = Debug|Any CPU 44 | {CA831A3B-17EA-4678-B41C-A9D973FE6CE5}.Release|Any CPU.ActiveCfg = Release|Any CPU 45 | {CA831A3B-17EA-4678-B41C-A9D973FE6CE5}.Release|Any CPU.Build.0 = Release|Any CPU 46 | EndGlobalSection 47 | GlobalSection(SolutionProperties) = preSolution 48 | HideSolutionNode = FALSE 49 | EndGlobalSection 50 | GlobalSection(NestedProjects) = preSolution 51 | {B359C0F4-02C6-4776-AA6F-8855B23EA978} = {048E1DA2-519E-4B47-864A-9F9A96C54C07} 52 | {85AE3219-9A17-4C8B-922D-076177312114} = {048E1DA2-519E-4B47-864A-9F9A96C54C07} 53 | {F1A30111-6929-4F0B-ADCD-5F01A2158A71} = {048E1DA2-519E-4B47-864A-9F9A96C54C07} 54 | {1C1CB7D0-49AD-401F-BCFD-962F07ED9F81} = {3A549608-93C5-45F3-BE4B-84105FCE9B9E} 55 | {CA831A3B-17EA-4678-B41C-A9D973FE6CE5} = {3A549608-93C5-45F3-BE4B-84105FCE9B9E} 56 | EndGlobalSection 57 | GlobalSection(ExtensibilityGlobals) = postSolution 58 | SolutionGuid = {63F36747-965C-4623-AEEF-E4F2C635819F} 59 | EndGlobalSection 60 | EndGlobal 61 | -------------------------------------------------------------------------------- /Website/azure-pipelines.yml: -------------------------------------------------------------------------------- 1 | trigger: 2 | - master 3 | 4 | pool: 5 | vmImage: 'windows-latest' 6 | 7 | variables: 8 | buildConfiguration: 'Release' 9 | 10 | stages: 11 | - stage: build 12 | displayName: Build 13 | jobs: 14 | - job: Build 15 | steps: 16 | - template: build-website.yml 17 | parameters: 18 | publishArgs: '--output $(Build.ArtifactStagingDirectory)' 19 | - task: PublishPipelineArtifact@1 20 | displayName: Publish UI Tests artifacts 21 | inputs: 22 | targetPath: '$(Build.Repository.LocalPath)/tests/GalaxyHotel.UITests' 23 | artifact: 'UITests' 24 | publishLocation: 'pipeline' 25 | - task: PublishPipelineArtifact@1 26 | displayName: Publish db artifacts 27 | inputs: 28 | targetPath: '$(Build.Repository.LocalPath)/db' 29 | artifact: 'db' 30 | publishLocation: 'pipeline' 31 | - task: PublishPipelineArtifact@1 32 | displayName: Publish web artifacts 33 | inputs: 34 | targetPath: '$(Build.ArtifactStagingDirectory)' 35 | artifact: 'web' 36 | publishLocation: 'pipeline' 37 | 38 | - stage: deployDev 39 | displayName: Deploy to Dev 40 | jobs: 41 | - deployment: deployDev 42 | displayName: Deploy To Dev 43 | environment: 'GalaxyHotel-Dev' 44 | strategy: 45 | runOnce: 46 | deploy: 47 | steps: 48 | - task: AzureRmWebAppDeployment@4 49 | inputs: 50 | ConnectionType: 'AzureRM' 51 | azureSubscription: 'Microsoft Azure Sponsorship' 52 | appType: 'webApp' 53 | WebAppName: 'galaxyhotel-dev' 54 | packageForLinux: '$(Pipeline.Workspace)/web/**/*.zip' 55 | 56 | - stage: deployQA 57 | displayName: Deploy to QA 58 | jobs: 59 | - deployment: deployQAWebsite 60 | displayName: Deploy Website to QA 61 | environment: 'GalaxyHotel-QA' 62 | strategy: 63 | runOnce: 64 | deploy: 65 | steps: 66 | - task: SqlAzureDacpacDeployment@1 67 | displayName: Prepare the database 68 | inputs: 69 | azureSubscription: 'Microsoft Azure Sponsorship' 70 | AuthenticationType: 'server' 71 | ServerName: 'succintly.database.windows.net' 72 | DatabaseName: 'galaxyhotel-qa' 73 | SqlUsername: '$(sqlAdmin)' 74 | SqlPassword: '$(sqlPassword)' 75 | deployType: 'SqlTask' 76 | SqlFile: '$(Pipeline.Workspace)/db/SeedGalaxyHotelDbScript.sql' 77 | IpDetectionMethod: 'AutoDetect' 78 | - task: AzureRmWebAppDeployment@4 79 | displayName: Deploy website 80 | inputs: 81 | ConnectionType: 'AzureRM' 82 | azureSubscription: 'Microsoft Azure Sponsorship' 83 | appType: 'webApp' 84 | WebAppName: 'galaxyhotel-qa' 85 | packageForLinux: '$(Pipeline.Workspace)/web/**/*.zip' 86 | - deployment: runQATests 87 | displayName: Run QA Tests 88 | dependsOn: deployQAWebsite 89 | environment: 90 | name: 'GalaxyHotel-QA' 91 | resourceType: VirtualMachine 92 | tags: qa 93 | strategy: 94 | runOnce: 95 | deploy: 96 | steps: 97 | - download: none 98 | - task: DownloadPipelineArtifact@2 99 | displayName: Download UITests artifact 100 | inputs: 101 | buildType: 'current' 102 | artifactName: 'UITests' 103 | targetPath: '$(Pipeline.Workspace)/UITests' 104 | - task: PowerShell@2 105 | displayName: Override TestRunParameters 106 | inputs: 107 | targetType: 'inline' 108 | script: | 109 | [xml]$doc = Get-Content $(Pipeline.Workspace)/UITests/GalaxyHotelTests.runsettings 110 | $doc.RunSettings.TestRunParameters.ChildNodes.Item(0).value = '$(qaBaseUrl)' 111 | $doc.Save("$(Pipeline.Workspace)/UITests/GalaxyHotelTests.runsettings") 112 | - task: DotNetCoreCLI@2 113 | displayName: Execute UI Tests with Selenium 114 | inputs: 115 | command: 'test' 116 | projects: '$(Pipeline.Workspace)/UITests/**/*.csproj' 117 | arguments: '--settings $(Pipeline.Workspace)/UITests/GalaxyHotelTests.runsettings' 118 | 119 | - stage: deployProd 120 | displayName: Deploy to Production 121 | jobs: 122 | - deployment: deployProd 123 | displayName: Deploy To Production 124 | environment: 'GalaxyHotel-Prod' 125 | strategy: 126 | runOnce: 127 | deploy: 128 | steps: 129 | - task: AzureRmWebAppDeployment@4 130 | inputs: 131 | ConnectionType: 'AzureRM' 132 | azureSubscription: 'Microsoft Azure Sponsorship' 133 | appType: 'webApp' 134 | WebAppName: 'galaxyhotel' 135 | packageForLinux: '$(Pipeline.Workspace)/web/**/*.zip' -------------------------------------------------------------------------------- /Libraries/tests/GalaxyHotel.Core.Services.Tests/ReservationServiceTests.cs: -------------------------------------------------------------------------------- 1 | using AutoMapper; 2 | using GalaxyHotel.Core.Exceptions; 3 | using GalaxyHotel.Core.Interfaces; 4 | using GalaxyHotel.Core.Models; 5 | using Moq; 6 | using NUnit.Framework; 7 | using System; 8 | using System.Threading.Tasks; 9 | 10 | namespace GalaxyHotel.Core.Services.Tests 11 | { 12 | public class ReservationServiceTests 13 | { 14 | private Mock> reservationRepositoryMock; 15 | private Mock> roomRepositoryMock; 16 | private Mock mapperMock; 17 | private ReservationService reservationService; 18 | private readonly DateTimeOffset checkInDate = DateTimeOffset.Now; 19 | private readonly DateTimeOffset checkOutDate = DateTimeOffset.Now.AddDays(1); 20 | private const int reservationId = 1; 21 | private const int notExistingReservationId = 2; 22 | private const int guestId = 1; 23 | private const int roomId = 1; 24 | private const int notExistingRoomId = 2; 25 | private const string roomName = "Andromeda"; 26 | private const int roomFloor = 1; 27 | private const int roomTypeId = 1; 28 | private const decimal pricePerNight = 50; 29 | 30 | [SetUp] 31 | public void Setup() 32 | { 33 | reservationRepositoryMock = new Mock>(); 34 | roomRepositoryMock = new Mock>(); 35 | mapperMock = new Mock(); 36 | 37 | var room = new Room { Name = roomName, Floor = roomFloor, PricePerNight = pricePerNight }; 38 | Room notExistingRoom = null; 39 | roomRepositoryMock.Setup(r => r.GetByIdAsync(roomId)).ReturnsAsync(room); 40 | roomRepositoryMock.Setup(r => r.GetByIdAsync(notExistingRoomId)).ReturnsAsync(notExistingRoom); 41 | 42 | Reservation notExistingReservation = null; 43 | Reservation reservation = new Reservation 44 | { 45 | Id = 1, 46 | CheckIn = checkInDate, 47 | CheckOut = checkOutDate, 48 | GuestId = guestId, 49 | RoomId = roomId, 50 | TotalPrice = pricePerNight 51 | }; 52 | reservationRepositoryMock.Setup(r => r.AddAsync(It.IsAny())).Verifiable(); 53 | reservationRepositoryMock.Setup(r => r.GetByIdAsync(reservationId)).ReturnsAsync(reservation).Verifiable(); 54 | reservationRepositoryMock.Setup(r => r.ListAllAsync()).Verifiable(); 55 | reservationRepositoryMock.Setup(r => r.GetByIdAsync(notExistingReservationId)).ReturnsAsync(notExistingReservation); 56 | reservationRepositoryMock.Setup(r => r.DeleteAsync(It.IsAny())).Verifiable(); 57 | 58 | reservationService = new ReservationService(reservationRepositoryMock.Object, roomRepositoryMock.Object, mapperMock.Object); 59 | } 60 | 61 | [Test] 62 | public async Task CreateReservation_RoomAvailable_ReservationCreated() 63 | { 64 | await reservationService.CreateReservationAsync(checkInDate, checkOutDate, guestId, roomId); 65 | 66 | reservationRepositoryMock.Verify(m => m.AddAsync(It.IsAny()), Times.Once); 67 | } 68 | 69 | [Test] 70 | public void CreateReservation_RoomNotExisting_ExceptionThrown() 71 | { 72 | Assert.That(() => reservationService.CreateReservationAsync(checkInDate, checkOutDate, guestId, notExistingRoomId), 73 | Throws.ArgumentNullException); 74 | } 75 | 76 | [Test] 77 | public async Task GetReservationById_ReservationExisting_ReservationReturned() 78 | { 79 | await reservationService.GetByIdAsync(reservationId); 80 | 81 | reservationRepositoryMock.Verify(m => m.GetByIdAsync(reservationId), Times.Once); 82 | } 83 | 84 | [Test] 85 | public async Task GetReservations_ReservationsExisting_ReservationsReturned() 86 | { 87 | await reservationService.GetAll(); 88 | 89 | reservationRepositoryMock.Verify(m => m.ListAsync(It.IsAny>()), Times.Once); 90 | } 91 | 92 | [Test] 93 | public async Task CancelReservation_ReservationExisting_ReservationCanceled() 94 | { 95 | await reservationService.CancelReservationAsync(reservationId); 96 | 97 | reservationRepositoryMock.Verify(m => m.GetByIdAsync(reservationId), Times.Once); 98 | reservationRepositoryMock.Verify(m => m.DeleteAsync(It.IsAny()), Times.Once); 99 | } 100 | 101 | [Test] 102 | public void CancelReservation_ReservationNotExisting_ExceptionThrown() 103 | { 104 | Assert.That(() => reservationService.CancelReservationAsync(notExistingReservationId), 105 | Throws.TypeOf()); 106 | } 107 | } 108 | } -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/Migrations/20200829211346_SeedGalaxyHotelDb.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.EntityFrameworkCore.Migrations; 2 | 3 | namespace GalaxyHotel.HelpDesk.Migrations 4 | { 5 | public partial class SeedGalaxyHotelDb : Migration 6 | { 7 | protected override void Up(MigrationBuilder migrationBuilder) 8 | { 9 | migrationBuilder.Sql( 10 | @"SET IDENTITY_INSERT [dbo].[Addresses] ON 11 | GO 12 | INSERT [dbo].[Addresses] ([Id], [Street], [City], [State], [Country], [ZipCode]) VALUES (1, N'13th Space Road, Brooklyn', N'New York', N'New York', N'United States of America', N'13021') 13 | GO 14 | INSERT [dbo].[Addresses] ([Id], [Street], [City], [State], [Country], [ZipCode]) VALUES (2, N'12th Hollywood road, Hollywood', N'Los Angeles', N'New York', N'United States of America', N'33024') 15 | GO 16 | INSERT [dbo].[Addresses] ([Id], [Street], [City], [State], [Country], [ZipCode]) VALUES (3, N'Piazza Plebiscito 1, Naples', N'Naples', N'', N'Italy', N'80100') 17 | GO 18 | INSERT [dbo].[Addresses] ([Id], [Street], [City], [State], [Country], [ZipCode]) VALUES (4, N'14th Valley Road', N'London', N'New York', N'United States of America', N'WC2N 5DU') 19 | GO 20 | SET IDENTITY_INSERT [dbo].[Addresses] OFF 21 | GO 22 | SET IDENTITY_INSERT [dbo].[PaymentMethods] ON 23 | GO 24 | INSERT [dbo].[PaymentMethods] ([Id], [Alias], [CardNumber], [DueDate]) VALUES (1, N'Private Credit Card 1', N'123412349876598765', CAST(N'2021-08-28T10:25:09.4799091+02:00' AS DateTimeOffset)) 25 | GO 26 | INSERT [dbo].[PaymentMethods] ([Id], [Alias], [CardNumber], [DueDate]) VALUES (2, N'Private Credit Card 2', N'123412349876598766', CAST(N'2021-08-28T10:25:09.4871490+02:00' AS DateTimeOffset)) 27 | GO 28 | INSERT [dbo].[PaymentMethods] ([Id], [Alias], [CardNumber], [DueDate]) VALUES (3, N'Private Credit Card 3', N'123412349876598767', CAST(N'2021-08-28T10:25:09.4871614+02:00' AS DateTimeOffset)) 29 | GO 30 | INSERT [dbo].[PaymentMethods] ([Id], [Alias], [CardNumber], [DueDate]) VALUES (4, N'Private Credit Card 4', N'123412349876598768', CAST(N'2021-08-28T10:25:09.4871635+02:00' AS DateTimeOffset)) 31 | GO 32 | SET IDENTITY_INSERT [dbo].[PaymentMethods] OFF 33 | GO 34 | SET IDENTITY_INSERT [dbo].[Guests] ON 35 | GO 36 | INSERT [dbo].[Guests] ([Id], [FirstName], [LastName], [AddressId], [PaymentMethodId]) VALUES (1, N'John', N'Doe', 1, 1) 37 | GO 38 | INSERT [dbo].[Guests] ([Id], [FirstName], [LastName], [AddressId], [PaymentMethodId]) VALUES (2, N'Alex', N'Harvey', 2, 2) 39 | GO 40 | INSERT [dbo].[Guests] ([Id], [FirstName], [LastName], [AddressId], [PaymentMethodId]) VALUES (3, N'Antonio', N'Esposito', 3, 3) 41 | GO 42 | INSERT [dbo].[Guests] ([Id], [FirstName], [LastName], [AddressId], [PaymentMethodId]) VALUES (4, N'Mark', N'River', 4, 4) 43 | GO 44 | SET IDENTITY_INSERT [dbo].[Guests] OFF 45 | GO 46 | SET IDENTITY_INSERT [dbo].[Rooms] ON 47 | GO 48 | INSERT [dbo].[Rooms] ([Id], [Name], [Floor], [PricePerNight]) VALUES (1, N'Andromeda', 1, CAST(200.00 AS Decimal(18, 2))) 49 | GO 50 | INSERT [dbo].[Rooms] ([Id], [Name], [Floor], [PricePerNight]) VALUES (2, N'Whirpool', 1, CAST(150.00 AS Decimal(18, 2))) 51 | GO 52 | INSERT [dbo].[Rooms] ([Id], [Name], [Floor], [PricePerNight]) VALUES (3, N'Sombrero', 1, CAST(100.00 AS Decimal(18, 2))) 53 | GO 54 | SET IDENTITY_INSERT [dbo].[Rooms] OFF 55 | GO 56 | SET IDENTITY_INSERT [dbo].[Reservations] ON 57 | GO 58 | INSERT [dbo].[Reservations] ([Id], [CheckIn], [CheckOut], [TotalPrice], [GuestId], [RoomId]) VALUES (1, CAST(N'2020-08-28T10:25:09.4921003+02:00' AS DateTimeOffset), CAST(N'2020-08-29T10:25:09.4921050+02:00' AS DateTimeOffset), CAST(200.00 AS Decimal(18, 2)), 1, 1) 59 | GO 60 | INSERT [dbo].[Reservations] ([Id], [CheckIn], [CheckOut], [TotalPrice], [GuestId], [RoomId]) VALUES (2, CAST(N'2020-08-28T10:25:09.4921003+02:00' AS DateTimeOffset), CAST(N'2020-08-29T10:25:09.4921050+02:00' AS DateTimeOffset), CAST(150.00 AS Decimal(18, 2)), 2, 2) 61 | GO 62 | INSERT [dbo].[Reservations] ([Id], [CheckIn], [CheckOut], [TotalPrice], [GuestId], [RoomId]) VALUES (3, CAST(N'2020-08-28T10:25:09.4921003+02:00' AS DateTimeOffset), CAST(N'2020-08-29T10:25:09.4921050+02:00' AS DateTimeOffset), CAST(100.00 AS Decimal(18, 2)), 3, 3) 63 | GO 64 | SET IDENTITY_INSERT [dbo].[Reservations] OFF 65 | GO 66 | "); 67 | } 68 | 69 | protected override void Down(MigrationBuilder migrationBuilder) 70 | { 71 | 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Data/Migrations/00000000000000_SeedGalaxyHotelDb.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Migrations; 3 | 4 | namespace GalaxyHotel.Website.Migrations 5 | { 6 | public partial class SeedGalaxyHotelDb : Migration 7 | { 8 | protected override void Up(MigrationBuilder migrationBuilder) 9 | { 10 | migrationBuilder.Sql( 11 | @"SET IDENTITY_INSERT [dbo].[Addresses] ON 12 | GO 13 | INSERT [dbo].[Addresses] ([Id], [Street], [City], [State], [Country], [ZipCode]) VALUES (1, N'13th Space Road, Brooklyn', N'New York', N'New York', N'United States of America', N'13021') 14 | GO 15 | INSERT [dbo].[Addresses] ([Id], [Street], [City], [State], [Country], [ZipCode]) VALUES (2, N'12th Hollywood road, Hollywood', N'Los Angeles', N'New York', N'United States of America', N'33024') 16 | GO 17 | INSERT [dbo].[Addresses] ([Id], [Street], [City], [State], [Country], [ZipCode]) VALUES (3, N'Piazza Plebiscito 1, Naples', N'Naples', N'', N'Italy', N'80100') 18 | GO 19 | INSERT [dbo].[Addresses] ([Id], [Street], [City], [State], [Country], [ZipCode]) VALUES (4, N'14th Valley Road', N'London', N'New York', N'United States of America', N'WC2N 5DU') 20 | GO 21 | SET IDENTITY_INSERT [dbo].[Addresses] OFF 22 | GO 23 | SET IDENTITY_INSERT [dbo].[PaymentMethods] ON 24 | GO 25 | INSERT [dbo].[PaymentMethods] ([Id], [Alias], [CardNumber], [DueDate]) VALUES (1, N'Private Credit Card 1', N'123412349876598765', CAST(N'2021-08-28T10:25:09.4799091+02:00' AS DateTimeOffset)) 26 | GO 27 | INSERT [dbo].[PaymentMethods] ([Id], [Alias], [CardNumber], [DueDate]) VALUES (2, N'Private Credit Card 2', N'123412349876598766', CAST(N'2021-08-28T10:25:09.4871490+02:00' AS DateTimeOffset)) 28 | GO 29 | INSERT [dbo].[PaymentMethods] ([Id], [Alias], [CardNumber], [DueDate]) VALUES (3, N'Private Credit Card 3', N'123412349876598767', CAST(N'2021-08-28T10:25:09.4871614+02:00' AS DateTimeOffset)) 30 | GO 31 | INSERT [dbo].[PaymentMethods] ([Id], [Alias], [CardNumber], [DueDate]) VALUES (4, N'Private Credit Card 4', N'123412349876598768', CAST(N'2021-08-28T10:25:09.4871635+02:00' AS DateTimeOffset)) 32 | GO 33 | SET IDENTITY_INSERT [dbo].[PaymentMethods] OFF 34 | GO 35 | SET IDENTITY_INSERT [dbo].[Guests] ON 36 | GO 37 | INSERT [dbo].[Guests] ([Id], [FirstName], [LastName], [AddressId], [PaymentMethodId]) VALUES (1, N'John', N'Doe', 1, 1) 38 | GO 39 | INSERT [dbo].[Guests] ([Id], [FirstName], [LastName], [AddressId], [PaymentMethodId]) VALUES (2, N'Alex', N'Harvey', 2, 2) 40 | GO 41 | INSERT [dbo].[Guests] ([Id], [FirstName], [LastName], [AddressId], [PaymentMethodId]) VALUES (3, N'Antonio', N'Esposito', 3, 3) 42 | GO 43 | INSERT [dbo].[Guests] ([Id], [FirstName], [LastName], [AddressId], [PaymentMethodId]) VALUES (4, N'Mark', N'River', 4, 4) 44 | GO 45 | SET IDENTITY_INSERT [dbo].[Guests] OFF 46 | GO 47 | SET IDENTITY_INSERT [dbo].[Rooms] ON 48 | GO 49 | INSERT [dbo].[Rooms] ([Id], [Name], [Floor], [PricePerNight]) VALUES (1, N'Andromeda', 1, CAST(200.00 AS Decimal(18, 2))) 50 | GO 51 | INSERT [dbo].[Rooms] ([Id], [Name], [Floor], [PricePerNight]) VALUES (2, N'Whirpool', 1, CAST(150.00 AS Decimal(18, 2))) 52 | GO 53 | INSERT [dbo].[Rooms] ([Id], [Name], [Floor], [PricePerNight]) VALUES (3, N'Sombrero', 1, CAST(100.00 AS Decimal(18, 2))) 54 | GO 55 | SET IDENTITY_INSERT [dbo].[Rooms] OFF 56 | GO 57 | SET IDENTITY_INSERT [dbo].[Reservations] ON 58 | GO 59 | INSERT [dbo].[Reservations] ([Id], [CheckIn], [CheckOut], [TotalPrice], [GuestId], [RoomId]) VALUES (1, CAST(N'2020-08-28T10:25:09.4921003+02:00' AS DateTimeOffset), CAST(N'2020-08-29T10:25:09.4921050+02:00' AS DateTimeOffset), CAST(200.00 AS Decimal(18, 2)), 1, 1) 60 | GO 61 | INSERT [dbo].[Reservations] ([Id], [CheckIn], [CheckOut], [TotalPrice], [GuestId], [RoomId]) VALUES (2, CAST(N'2020-08-28T10:25:09.4921003+02:00' AS DateTimeOffset), CAST(N'2020-08-29T10:25:09.4921050+02:00' AS DateTimeOffset), CAST(150.00 AS Decimal(18, 2)), 2, 2) 62 | GO 63 | INSERT [dbo].[Reservations] ([Id], [CheckIn], [CheckOut], [TotalPrice], [GuestId], [RoomId]) VALUES (3, CAST(N'2020-08-28T10:25:09.4921003+02:00' AS DateTimeOffset), CAST(N'2020-08-29T10:25:09.4921050+02:00' AS DateTimeOffset), CAST(100.00 AS Decimal(18, 2)), 3, 3) 64 | GO 65 | SET IDENTITY_INSERT [dbo].[Reservations] OFF 66 | GO 67 | "); 68 | } 69 | 70 | protected override void Down(MigrationBuilder migrationBuilder) 71 | { 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js: -------------------------------------------------------------------------------- 1 | // Unobtrusive validation support library for jQuery and jQuery Validate 2 | // Copyright (c) .NET Foundation. All rights reserved. 3 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 4 | // @version v3.2.11 5 | !function(a){"function"==typeof define&&define.amd?define("jquery.validate.unobtrusive",["jquery-validation"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery-validation")):jQuery.validator.unobtrusive=a(jQuery)}(function(a){function e(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function n(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function t(a){return a.replace(/([!"#$%&'()*+,.\/:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function r(a){return a.substr(0,a.lastIndexOf(".")+1)}function i(a,e){return 0===a.indexOf("*.")&&(a=a.replace("*.",e)),a}function o(e,n){var r=a(this).find("[data-valmsg-for='"+t(n[0].name)+"']"),i=r.attr("data-valmsg-replace"),o=i?a.parseJSON(i)!==!1:null;r.removeClass("field-validation-valid").addClass("field-validation-error"),e.data("unobtrusiveContainer",r),o?(r.empty(),e.removeClass("input-validation-error").appendTo(r)):e.hide()}function d(e,n){var t=a(this).find("[data-valmsg-summary=true]"),r=t.find("ul");r&&r.length&&n.errorList.length&&(r.empty(),t.addClass("validation-summary-errors").removeClass("validation-summary-valid"),a.each(n.errorList,function(){a("
  • ").html(this.message).appendTo(r)}))}function s(e){var n=e.data("unobtrusiveContainer");if(n){var t=n.attr("data-valmsg-replace"),r=t?a.parseJSON(t):null;n.addClass("field-validation-valid").removeClass("field-validation-error"),e.removeData("unobtrusiveContainer"),r&&n.empty()}}function l(e){var n=a(this),t="__jquery_unobtrusive_validation_form_reset";if(!n.data(t)){n.data(t,!0);try{n.data("validator").resetForm()}finally{n.removeData(t)}n.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),n.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function u(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=f.unobtrusive.options||{},u=function(n,t){var r=i[n];r&&a.isFunction(r)&&r.apply(e,t)};return t||(t={options:{errorClass:i.errorClass||"input-validation-error",errorElement:i.errorElement||"span",errorPlacement:function(){o.apply(e,arguments),u("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),u("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),u("success",arguments)}},attachValidation:function(){n.off("reset."+v,r).on("reset."+v,r).validate(this.options)},validate:function(){return n.validate(),n.valid()}},n.data(v,t)),t}var m,f=a.validator,v="unobtrusiveValidation";return f.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=u(d),t.options.rules[e.name]=r={},t.options.messages[e.name]=i={},a.each(this.adapters,function(){var n="data-val-"+this.name,t=o.attr(n),s={};void 0!==t&&(n+="-",a.each(this.params,function(){s[this]=o.attr(n+this)}),this.adapt({element:e,form:d,message:t,params:s,rules:r,messages:i}))}),a.extend(r,{__dummy__:!0}),n||t.attachValidation())},parse:function(e){var n=a(e),t=n.parents().addBack().filter("form").add(n.find("form")).has("[data-val=true]");n.find("[data-val=true]").each(function(){f.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=u(this);a&&a.attachValidation()})}},m=f.unobtrusive.adapters,m.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},m.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},m.addMinMax=function(a,n,t,r,i,o){return this.add(a,[i||"min",o||"max"],function(a){var i=a.params.min,o=a.params.max;i&&o?e(a,r,[i,o]):i?e(a,n,i):o&&e(a,t,o)})},m.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},f.addMethod("__dummy__",function(a,e,n){return!0}),f.addMethod("regex",function(a,e,n){var t;return!!this.optional(e)||(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),f.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),f.methods.extension?(m.addSingleVal("accept","mimtype"),m.addSingleVal("extension","extension")):m.addSingleVal("extension","extension","accept"),m.addSingleVal("regex","pattern"),m.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),m.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),m.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),m.add("equalto",["other"],function(n){var o=r(n.element.name),d=n.params.other,s=i(d,o),l=a(n.form).find(":input").filter("[name='"+t(s)+"']")[0];e(n,"equalTo",l)}),m.add("required",function(a){"INPUT"===a.element.tagName.toUpperCase()&&"CHECKBOX"===a.element.type.toUpperCase()||e(a,"required",!0)}),m.add("remote",["url","type","additionalfields"],function(o){var d={url:o.params.url,type:o.params.type||"GET",data:{}},s=r(o.element.name);a.each(n(o.params.additionalfields||o.element.name),function(e,n){var r=i(n,s);d.data[r]=function(){var e=a(o.form).find(":input").filter("[name='"+t(r)+"']");return e.is(":checkbox")?e.filter(":checked").val()||e.filter(":hidden").val()||"":e.is(":radio")?e.filter(":checked").val()||"":e.val()}}),e(o,"remote",d)}),m.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&e(a,"minlength",a.params.min),a.params.nonalphamin&&e(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&e(a,"regex",a.params.regex)}),m.add("fileextensions",["extensions"],function(a){e(a,"extension",a.params.extensions)}),a(function(){f.unobtrusive.parse(document)}),f.unobtrusive}); -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js: -------------------------------------------------------------------------------- 1 | // Unobtrusive validation support library for jQuery and jQuery Validate 2 | // Copyright (c) .NET Foundation. All rights reserved. 3 | // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. 4 | // @version v3.2.11 5 | !function(a){"function"==typeof define&&define.amd?define("jquery.validate.unobtrusive",["jquery-validation"],a):"object"==typeof module&&module.exports?module.exports=a(require("jquery-validation")):jQuery.validator.unobtrusive=a(jQuery)}(function(a){function e(a,e,n){a.rules[e]=n,a.message&&(a.messages[e]=a.message)}function n(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function t(a){return a.replace(/([!"#$%&'()*+,.\/:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function r(a){return a.substr(0,a.lastIndexOf(".")+1)}function i(a,e){return 0===a.indexOf("*.")&&(a=a.replace("*.",e)),a}function o(e,n){var r=a(this).find("[data-valmsg-for='"+t(n[0].name)+"']"),i=r.attr("data-valmsg-replace"),o=i?a.parseJSON(i)!==!1:null;r.removeClass("field-validation-valid").addClass("field-validation-error"),e.data("unobtrusiveContainer",r),o?(r.empty(),e.removeClass("input-validation-error").appendTo(r)):e.hide()}function d(e,n){var t=a(this).find("[data-valmsg-summary=true]"),r=t.find("ul");r&&r.length&&n.errorList.length&&(r.empty(),t.addClass("validation-summary-errors").removeClass("validation-summary-valid"),a.each(n.errorList,function(){a("
  • ").html(this.message).appendTo(r)}))}function s(e){var n=e.data("unobtrusiveContainer");if(n){var t=n.attr("data-valmsg-replace"),r=t?a.parseJSON(t):null;n.addClass("field-validation-valid").removeClass("field-validation-error"),e.removeData("unobtrusiveContainer"),r&&n.empty()}}function l(e){var n=a(this),t="__jquery_unobtrusive_validation_form_reset";if(!n.data(t)){n.data(t,!0);try{n.data("validator").resetForm()}finally{n.removeData(t)}n.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors"),n.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}}function u(e){var n=a(e),t=n.data(v),r=a.proxy(l,e),i=f.unobtrusive.options||{},u=function(n,t){var r=i[n];r&&a.isFunction(r)&&r.apply(e,t)};return t||(t={options:{errorClass:i.errorClass||"input-validation-error",errorElement:i.errorElement||"span",errorPlacement:function(){o.apply(e,arguments),u("errorPlacement",arguments)},invalidHandler:function(){d.apply(e,arguments),u("invalidHandler",arguments)},messages:{},rules:{},success:function(){s.apply(e,arguments),u("success",arguments)}},attachValidation:function(){n.off("reset."+v,r).on("reset."+v,r).validate(this.options)},validate:function(){return n.validate(),n.valid()}},n.data(v,t)),t}var m,f=a.validator,v="unobtrusiveValidation";return f.unobtrusive={adapters:[],parseElement:function(e,n){var t,r,i,o=a(e),d=o.parents("form")[0];d&&(t=u(d),t.options.rules[e.name]=r={},t.options.messages[e.name]=i={},a.each(this.adapters,function(){var n="data-val-"+this.name,t=o.attr(n),s={};void 0!==t&&(n+="-",a.each(this.params,function(){s[this]=o.attr(n+this)}),this.adapt({element:e,form:d,message:t,params:s,rules:r,messages:i}))}),a.extend(r,{__dummy__:!0}),n||t.attachValidation())},parse:function(e){var n=a(e),t=n.parents().addBack().filter("form").add(n.find("form")).has("[data-val=true]");n.find("[data-val=true]").each(function(){f.unobtrusive.parseElement(this,!0)}),t.each(function(){var a=u(this);a&&a.attachValidation()})}},m=f.unobtrusive.adapters,m.add=function(a,e,n){return n||(n=e,e=[]),this.push({name:a,params:e,adapt:n}),this},m.addBool=function(a,n){return this.add(a,function(t){e(t,n||a,!0)})},m.addMinMax=function(a,n,t,r,i,o){return this.add(a,[i||"min",o||"max"],function(a){var i=a.params.min,o=a.params.max;i&&o?e(a,r,[i,o]):i?e(a,n,i):o&&e(a,t,o)})},m.addSingleVal=function(a,n,t){return this.add(a,[n||"val"],function(r){e(r,t||a,r.params[n])})},f.addMethod("__dummy__",function(a,e,n){return!0}),f.addMethod("regex",function(a,e,n){var t;return!!this.optional(e)||(t=new RegExp(n).exec(a),t&&0===t.index&&t[0].length===a.length)}),f.addMethod("nonalphamin",function(a,e,n){var t;return n&&(t=a.match(/\W/g),t=t&&t.length>=n),t}),f.methods.extension?(m.addSingleVal("accept","mimtype"),m.addSingleVal("extension","extension")):m.addSingleVal("extension","extension","accept"),m.addSingleVal("regex","pattern"),m.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url"),m.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range"),m.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength"),m.add("equalto",["other"],function(n){var o=r(n.element.name),d=n.params.other,s=i(d,o),l=a(n.form).find(":input").filter("[name='"+t(s)+"']")[0];e(n,"equalTo",l)}),m.add("required",function(a){"INPUT"===a.element.tagName.toUpperCase()&&"CHECKBOX"===a.element.type.toUpperCase()||e(a,"required",!0)}),m.add("remote",["url","type","additionalfields"],function(o){var d={url:o.params.url,type:o.params.type||"GET",data:{}},s=r(o.element.name);a.each(n(o.params.additionalfields||o.element.name),function(e,n){var r=i(n,s);d.data[r]=function(){var e=a(o.form).find(":input").filter("[name='"+t(r)+"']");return e.is(":checkbox")?e.filter(":checked").val()||e.filter(":hidden").val()||"":e.is(":radio")?e.filter(":checked").val()||"":e.val()}}),e(o,"remote",d)}),m.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&e(a,"minlength",a.params.min),a.params.nonalphamin&&e(a,"nonalphamin",a.params.nonalphamin),a.params.regex&&e(a,"regex",a.params.regex)}),m.add("fileextensions",["extensions"],function(a){e(a,"extension",a.params.extensions)}),a(function(){f.unobtrusive.parse(document)}),f.unobtrusive}); -------------------------------------------------------------------------------- /Libraries/tests/GalaxyHotel.Infrastructure.IntegrationTests/Data/ReservationRepositoryTests.cs: -------------------------------------------------------------------------------- 1 | using GalaxyHotel.Core.Models; 2 | using GalaxyHotel.Core.Specification; 3 | using GalaxyHotel.Infrastructure.Data; 4 | using GalaxyHotel.Infrastructure.IntegrationTests.SetUp; 5 | using Microsoft.Data.Sqlite; 6 | using Microsoft.EntityFrameworkCore; 7 | using NUnit.Framework; 8 | using System; 9 | using System.Linq; 10 | using System.Threading.Tasks; 11 | 12 | namespace GalaxyHotel.Infrastructure.IntegrationTests 13 | { 14 | public class ReservationRepositoryTests 15 | { 16 | private SqliteConnection connection; 17 | private TestGalaxyHotelContext galaxyHotelContext; 18 | private ReservationRepository reservationRepository; 19 | private readonly DateTimeOffset checkInDate = DateTimeOffset.Now; 20 | private readonly DateTimeOffset checkOutDate = DateTimeOffset.Now.AddDays(1); 21 | private readonly int firstGuest = 1; 22 | private readonly int secondGuest = 2; 23 | private readonly int thirdGuest = 3; 24 | private readonly int secondRoom = 2; 25 | private readonly decimal pricePerNight = 10; 26 | 27 | [SetUp] 28 | public void Setup() 29 | { 30 | connection = new SqliteConnection("DataSource=:memory:;Foreign Keys=False"); 31 | connection.Open(); 32 | 33 | var options = new DbContextOptionsBuilder().UseSqlite(connection).Options; 34 | galaxyHotelContext = new TestGalaxyHotelContext(options); 35 | galaxyHotelContext.Database.EnsureCreated(); 36 | 37 | reservationRepository = new ReservationRepository(galaxyHotelContext); 38 | } 39 | 40 | [TearDown] 41 | public void TearDown() 42 | { 43 | galaxyHotelContext.Dispose(); 44 | connection.Close(); 45 | } 46 | 47 | [Test] 48 | public async Task GetReservations_ReservationsExisting_ReservationsReturned() 49 | { 50 | var reservations = await reservationRepository.ListAllAsync(); 51 | 52 | Assert.That(reservations.Count, Is.EqualTo(3)); 53 | } 54 | 55 | [Test] 56 | public async Task CountReservations_ReservationsExisting_ReservationsNumberReturned() 57 | { 58 | var reservationCount = await reservationRepository 59 | .CountAsync(new GuestReservationSpecification(firstGuest)); 60 | 61 | Assert.That(reservationCount, Is.EqualTo(1)); 62 | } 63 | 64 | [Test] 65 | public async Task GetReservationById_ReservationExisting_ReservationReturned() 66 | { 67 | var reservations = await reservationRepository 68 | .ListAllAsync(); 69 | 70 | var reservation = await reservationRepository 71 | .GetByIdAsync(reservations.First().Id); 72 | 73 | Assert.That(reservation, Is.Not.Null); 74 | } 75 | 76 | [Test] 77 | public async Task GetReservationByGuestId_ReservationExisting_ReservationReturned() 78 | { 79 | var reservations = await reservationRepository 80 | .ListAsync(new GuestReservationSpecification(firstGuest)); 81 | 82 | Assert.That(reservations.Count, Is.EqualTo(1)); 83 | } 84 | 85 | [Test] 86 | public async Task AddReservation_RoomAvailable_ReservationCreated() 87 | { 88 | var reservation = new Reservation 89 | { 90 | Id = 10, 91 | CheckIn = checkInDate, 92 | CheckOut = checkOutDate, 93 | GuestId = secondGuest, 94 | RoomId = secondRoom, 95 | TotalPrice = pricePerNight 96 | }; 97 | 98 | await reservationRepository.AddAsync(reservation); 99 | 100 | var reservationCount = await reservationRepository 101 | .CountAsync(new GuestReservationSpecification(secondGuest)); 102 | Assert.That(reservationCount, Is.EqualTo(2)); 103 | } 104 | 105 | [Test] 106 | public async Task DeleteReservation_ReservationExisting_ReservationDeleted() 107 | { 108 | var reservation = new Reservation 109 | { 110 | Id = 11, 111 | CheckIn = checkInDate, 112 | CheckOut = checkOutDate, 113 | GuestId = thirdGuest, 114 | RoomId = secondRoom, 115 | TotalPrice = pricePerNight 116 | }; 117 | 118 | await reservationRepository.AddAsync(reservation); 119 | 120 | await reservationRepository.DeleteAsync(reservation); 121 | 122 | var reservationCount = await reservationRepository 123 | .CountAsync(new GuestReservationSpecification(thirdGuest)); 124 | Assert.That(reservationCount, Is.EqualTo(1)); 125 | } 126 | 127 | [Test, Ignore("ignore")] 128 | public async Task UpdateReservation_ReservationExisting_ReservationUpdated() 129 | { 130 | var newPricePerNight = 50; 131 | var guestId = 1; 132 | var reservation = await reservationRepository 133 | .FirstAsync(new GuestReservationSpecification(guestId)); 134 | 135 | await reservationRepository.UpdateAsync(reservation); 136 | 137 | reservation = await reservationRepository 138 | .FirstAsync(new GuestReservationSpecification(guestId)); 139 | 140 | Assert.That(reservation.TotalPrice, Is.EqualTo(newPricePerNight)); 141 | } 142 | 143 | [Test] 144 | public async Task GetReservationByGuestId_GuestNotExisting_NoReservationReturned() 145 | { 146 | var notExistingGuest = 5; 147 | 148 | var reservation = await reservationRepository 149 | .FirstOrDefaultAsync(new GuestReservationSpecification(notExistingGuest)); 150 | 151 | Assert.That(reservation, Is.Null); 152 | } 153 | } 154 | } -------------------------------------------------------------------------------- /Libraries/tests/GalaxyHotel.Infrastructure.IntegrationTests/SetUp/TestGalaxyHotelContext.cs: -------------------------------------------------------------------------------- 1 | using GalaxyHotel.Core.Models; 2 | using GalaxyHotel.Infrastructure.Data; 3 | using Microsoft.EntityFrameworkCore; 4 | using System; 5 | 6 | namespace GalaxyHotel.Infrastructure.IntegrationTests.SetUp 7 | { 8 | public class TestGalaxyHotelContext : GalaxyHotelContext 9 | { 10 | private static DateTimeOffset checkInDate = DateTimeOffset.Now; 11 | private static DateTimeOffset checkOutDate = DateTimeOffset.Now.AddDays(1); 12 | 13 | public TestGalaxyHotelContext(DbContextOptions options) 14 | : base(options) 15 | { } 16 | 17 | protected override void OnModelCreating(ModelBuilder modelBuilder) 18 | { 19 | base.OnModelCreating(modelBuilder); 20 | 21 | modelBuilder.Entity() 22 | .HasOne(r => r.Guest) 23 | .WithMany(r => r.Reservations) 24 | .OnDelete(DeleteBehavior.Cascade); 25 | 26 | modelBuilder.Entity() 27 | .HasOne(r => r.Room) 28 | .WithMany(r => r.Reservations) 29 | .OnDelete(DeleteBehavior.Cascade); 30 | 31 | modelBuilder.Entity() 32 | .HasMany(g => g.Reservations) 33 | .WithOne(g => g.Guest) 34 | .OnDelete(DeleteBehavior.Cascade); 35 | 36 | modelBuilder.Entity() 37 | .HasOne(g => g.Address) 38 | .WithOne(g => g.Guest) 39 | .OnDelete(DeleteBehavior.Cascade); 40 | 41 | modelBuilder.Entity() 42 | .HasOne(g => g.PaymentMethod) 43 | .WithOne(g => g.Guest) 44 | .OnDelete(DeleteBehavior.Cascade); 45 | 46 | modelBuilder.Entity
    () 47 | .HasOne(g => g.Guest) 48 | .WithOne(g => g.Address) 49 | .OnDelete(DeleteBehavior.Cascade); 50 | 51 | modelBuilder.Entity() 52 | .HasOne(g => g.Guest) 53 | .WithOne(g => g.PaymentMethod) 54 | .OnDelete(DeleteBehavior.Cascade); 55 | 56 | modelBuilder.Entity().HasData( 57 | new PaymentMethod { Id = 1, Alias = "Private Credit Card 1", CardNumber = "123412349876598765", DueDate = DateTimeOffset.Now.AddYears(1) }, 58 | new PaymentMethod { Id = 2, Alias = "Private Credit Card 2", CardNumber = "123412349876598766", DueDate = DateTimeOffset.Now.AddYears(1) }, 59 | new PaymentMethod { Id = 3, Alias = "Private Credit Card 3", CardNumber = "123412349876598767", DueDate = DateTimeOffset.Now.AddYears(1) }, 60 | new PaymentMethod { Id = 4, Alias = "Private Credit Card 4", CardNumber = "123412349876598768", DueDate = DateTimeOffset.Now.AddYears(1) }); 61 | 62 | modelBuilder.Entity
    ().HasData( 63 | new Address { Id = 1, City = "New York", Street = "13th Space Road, Brooklyn", Country = "United States of America", State = "New York", ZipCode = "13021" }, 64 | new Address { Id = 2, City = "Los Angeles", Street = "12th Hollywood road, Hollywood", Country = "United States of America", State = "New York", ZipCode = "33024" }, 65 | new Address { Id = 3, City = "Naples", Street = "Piazza Plebiscito 1, Naples", Country = "Italy", State = "", ZipCode = "80100" }, 66 | new Address { Id = 4, City = "London", Street = "14th Valley Road", Country = "United States of America", State = "New York", ZipCode = "WC2N 5DU" }); 67 | 68 | modelBuilder.Entity().HasData( 69 | new Guest { Id = 1, FirstName = "John", LastName = "Doe", AddressId = 1, PaymentMethodId = 1 }, 70 | new Guest { Id = 2, FirstName = "Alex", LastName = "Harvey", AddressId = 2, PaymentMethodId = 2 }, 71 | new Guest { Id = 3, FirstName = "Antonio", LastName = "Esposito", AddressId = 3, PaymentMethodId = 3 }, 72 | new Guest { Id = 4, FirstName = "Mark", LastName = "River", AddressId = 4, PaymentMethodId = 4 }); 73 | 74 | modelBuilder.Entity().HasData( 75 | new Room 76 | { 77 | Id = 1, 78 | Floor = 1, 79 | Name = "Andromeda", 80 | PricePerNight = 200 81 | }, 82 | new Room 83 | { 84 | Id = 2, 85 | Floor = 1, 86 | Name = "Whirpool", 87 | PricePerNight = 150 88 | }, 89 | new Room 90 | { 91 | Id = 3, 92 | Floor = 1, 93 | Name = "Sombrero", 94 | PricePerNight = 100 95 | }); 96 | 97 | modelBuilder.Entity().HasData( 98 | new Reservation 99 | { 100 | Id = 1, 101 | CheckIn = checkInDate, 102 | CheckOut = checkOutDate, 103 | GuestId = 1, 104 | RoomId = 1, 105 | TotalPrice = 200 106 | }, 107 | new Reservation 108 | { 109 | Id = 2, 110 | CheckIn = checkInDate, 111 | CheckOut = checkOutDate, 112 | GuestId = 2, 113 | RoomId = 2, 114 | TotalPrice = 150 115 | }, 116 | new Reservation 117 | { 118 | Id = 3, 119 | CheckIn = checkInDate, 120 | CheckOut = checkOutDate, 121 | GuestId = 3, 122 | RoomId = 3, 123 | TotalPrice = 100 124 | 125 | }); 126 | } 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/) 3 | * Copyright 2011-2019 The Bootstrap Authors 4 | * Copyright 2011-2019 Twitter, Inc. 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) 7 | */ 8 | *, 9 | *::before, 10 | *::after { 11 | box-sizing: border-box; 12 | } 13 | 14 | html { 15 | font-family: sans-serif; 16 | line-height: 1.15; 17 | -webkit-text-size-adjust: 100%; 18 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 19 | } 20 | 21 | article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { 22 | display: block; 23 | } 24 | 25 | body { 26 | margin: 0; 27 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; 28 | font-size: 1rem; 29 | font-weight: 400; 30 | line-height: 1.5; 31 | color: #212529; 32 | text-align: left; 33 | background-color: #fff; 34 | } 35 | 36 | [tabindex="-1"]:focus { 37 | outline: 0 !important; 38 | } 39 | 40 | hr { 41 | box-sizing: content-box; 42 | height: 0; 43 | overflow: visible; 44 | } 45 | 46 | h1, h2, h3, h4, h5, h6 { 47 | margin-top: 0; 48 | margin-bottom: 0.5rem; 49 | } 50 | 51 | p { 52 | margin-top: 0; 53 | margin-bottom: 1rem; 54 | } 55 | 56 | abbr[title], 57 | abbr[data-original-title] { 58 | text-decoration: underline; 59 | -webkit-text-decoration: underline dotted; 60 | text-decoration: underline dotted; 61 | cursor: help; 62 | border-bottom: 0; 63 | -webkit-text-decoration-skip-ink: none; 64 | text-decoration-skip-ink: none; 65 | } 66 | 67 | address { 68 | margin-bottom: 1rem; 69 | font-style: normal; 70 | line-height: inherit; 71 | } 72 | 73 | ol, 74 | ul, 75 | dl { 76 | margin-top: 0; 77 | margin-bottom: 1rem; 78 | } 79 | 80 | ol ol, 81 | ul ul, 82 | ol ul, 83 | ul ol { 84 | margin-bottom: 0; 85 | } 86 | 87 | dt { 88 | font-weight: 700; 89 | } 90 | 91 | dd { 92 | margin-bottom: .5rem; 93 | margin-left: 0; 94 | } 95 | 96 | blockquote { 97 | margin: 0 0 1rem; 98 | } 99 | 100 | b, 101 | strong { 102 | font-weight: bolder; 103 | } 104 | 105 | small { 106 | font-size: 80%; 107 | } 108 | 109 | sub, 110 | sup { 111 | position: relative; 112 | font-size: 75%; 113 | line-height: 0; 114 | vertical-align: baseline; 115 | } 116 | 117 | sub { 118 | bottom: -.25em; 119 | } 120 | 121 | sup { 122 | top: -.5em; 123 | } 124 | 125 | a { 126 | color: #007bff; 127 | text-decoration: none; 128 | background-color: transparent; 129 | } 130 | 131 | a:hover { 132 | color: #0056b3; 133 | text-decoration: underline; 134 | } 135 | 136 | a:not([href]):not([tabindex]) { 137 | color: inherit; 138 | text-decoration: none; 139 | } 140 | 141 | a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus { 142 | color: inherit; 143 | text-decoration: none; 144 | } 145 | 146 | a:not([href]):not([tabindex]):focus { 147 | outline: 0; 148 | } 149 | 150 | pre, 151 | code, 152 | kbd, 153 | samp { 154 | font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; 155 | font-size: 1em; 156 | } 157 | 158 | pre { 159 | margin-top: 0; 160 | margin-bottom: 1rem; 161 | overflow: auto; 162 | } 163 | 164 | figure { 165 | margin: 0 0 1rem; 166 | } 167 | 168 | img { 169 | vertical-align: middle; 170 | border-style: none; 171 | } 172 | 173 | svg { 174 | overflow: hidden; 175 | vertical-align: middle; 176 | } 177 | 178 | table { 179 | border-collapse: collapse; 180 | } 181 | 182 | caption { 183 | padding-top: 0.75rem; 184 | padding-bottom: 0.75rem; 185 | color: #6c757d; 186 | text-align: left; 187 | caption-side: bottom; 188 | } 189 | 190 | th { 191 | text-align: inherit; 192 | } 193 | 194 | label { 195 | display: inline-block; 196 | margin-bottom: 0.5rem; 197 | } 198 | 199 | button { 200 | border-radius: 0; 201 | } 202 | 203 | button:focus { 204 | outline: 1px dotted; 205 | outline: 5px auto -webkit-focus-ring-color; 206 | } 207 | 208 | input, 209 | button, 210 | select, 211 | optgroup, 212 | textarea { 213 | margin: 0; 214 | font-family: inherit; 215 | font-size: inherit; 216 | line-height: inherit; 217 | } 218 | 219 | button, 220 | input { 221 | overflow: visible; 222 | } 223 | 224 | button, 225 | select { 226 | text-transform: none; 227 | } 228 | 229 | select { 230 | word-wrap: normal; 231 | } 232 | 233 | button, 234 | [type="button"], 235 | [type="reset"], 236 | [type="submit"] { 237 | -webkit-appearance: button; 238 | } 239 | 240 | button:not(:disabled), 241 | [type="button"]:not(:disabled), 242 | [type="reset"]:not(:disabled), 243 | [type="submit"]:not(:disabled) { 244 | cursor: pointer; 245 | } 246 | 247 | button::-moz-focus-inner, 248 | [type="button"]::-moz-focus-inner, 249 | [type="reset"]::-moz-focus-inner, 250 | [type="submit"]::-moz-focus-inner { 251 | padding: 0; 252 | border-style: none; 253 | } 254 | 255 | input[type="radio"], 256 | input[type="checkbox"] { 257 | box-sizing: border-box; 258 | padding: 0; 259 | } 260 | 261 | input[type="date"], 262 | input[type="time"], 263 | input[type="datetime-local"], 264 | input[type="month"] { 265 | -webkit-appearance: listbox; 266 | } 267 | 268 | textarea { 269 | overflow: auto; 270 | resize: vertical; 271 | } 272 | 273 | fieldset { 274 | min-width: 0; 275 | padding: 0; 276 | margin: 0; 277 | border: 0; 278 | } 279 | 280 | legend { 281 | display: block; 282 | width: 100%; 283 | max-width: 100%; 284 | padding: 0; 285 | margin-bottom: .5rem; 286 | font-size: 1.5rem; 287 | line-height: inherit; 288 | color: inherit; 289 | white-space: normal; 290 | } 291 | 292 | progress { 293 | vertical-align: baseline; 294 | } 295 | 296 | [type="number"]::-webkit-inner-spin-button, 297 | [type="number"]::-webkit-outer-spin-button { 298 | height: auto; 299 | } 300 | 301 | [type="search"] { 302 | outline-offset: -2px; 303 | -webkit-appearance: none; 304 | } 305 | 306 | [type="search"]::-webkit-search-decoration { 307 | -webkit-appearance: none; 308 | } 309 | 310 | ::-webkit-file-upload-button { 311 | font: inherit; 312 | -webkit-appearance: button; 313 | } 314 | 315 | output { 316 | display: inline-block; 317 | } 318 | 319 | summary { 320 | display: list-item; 321 | cursor: pointer; 322 | } 323 | 324 | template { 325 | display: none; 326 | } 327 | 328 | [hidden] { 329 | display: none !important; 330 | } 331 | /*# sourceMappingURL=bootstrap-reboot.css.map */ -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap Reboot v4.3.1 (https://getbootstrap.com/) 3 | * Copyright 2011-2019 The Bootstrap Authors 4 | * Copyright 2011-2019 Twitter, Inc. 5 | * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) 6 | * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) 7 | */ 8 | *, 9 | *::before, 10 | *::after { 11 | box-sizing: border-box; 12 | } 13 | 14 | html { 15 | font-family: sans-serif; 16 | line-height: 1.15; 17 | -webkit-text-size-adjust: 100%; 18 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0); 19 | } 20 | 21 | article, aside, figcaption, figure, footer, header, hgroup, main, nav, section { 22 | display: block; 23 | } 24 | 25 | body { 26 | margin: 0; 27 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; 28 | font-size: 1rem; 29 | font-weight: 400; 30 | line-height: 1.5; 31 | color: #212529; 32 | text-align: left; 33 | background-color: #fff; 34 | } 35 | 36 | [tabindex="-1"]:focus { 37 | outline: 0 !important; 38 | } 39 | 40 | hr { 41 | box-sizing: content-box; 42 | height: 0; 43 | overflow: visible; 44 | } 45 | 46 | h1, h2, h3, h4, h5, h6 { 47 | margin-top: 0; 48 | margin-bottom: 0.5rem; 49 | } 50 | 51 | p { 52 | margin-top: 0; 53 | margin-bottom: 1rem; 54 | } 55 | 56 | abbr[title], 57 | abbr[data-original-title] { 58 | text-decoration: underline; 59 | -webkit-text-decoration: underline dotted; 60 | text-decoration: underline dotted; 61 | cursor: help; 62 | border-bottom: 0; 63 | -webkit-text-decoration-skip-ink: none; 64 | text-decoration-skip-ink: none; 65 | } 66 | 67 | address { 68 | margin-bottom: 1rem; 69 | font-style: normal; 70 | line-height: inherit; 71 | } 72 | 73 | ol, 74 | ul, 75 | dl { 76 | margin-top: 0; 77 | margin-bottom: 1rem; 78 | } 79 | 80 | ol ol, 81 | ul ul, 82 | ol ul, 83 | ul ol { 84 | margin-bottom: 0; 85 | } 86 | 87 | dt { 88 | font-weight: 700; 89 | } 90 | 91 | dd { 92 | margin-bottom: .5rem; 93 | margin-left: 0; 94 | } 95 | 96 | blockquote { 97 | margin: 0 0 1rem; 98 | } 99 | 100 | b, 101 | strong { 102 | font-weight: bolder; 103 | } 104 | 105 | small { 106 | font-size: 80%; 107 | } 108 | 109 | sub, 110 | sup { 111 | position: relative; 112 | font-size: 75%; 113 | line-height: 0; 114 | vertical-align: baseline; 115 | } 116 | 117 | sub { 118 | bottom: -.25em; 119 | } 120 | 121 | sup { 122 | top: -.5em; 123 | } 124 | 125 | a { 126 | color: #007bff; 127 | text-decoration: none; 128 | background-color: transparent; 129 | } 130 | 131 | a:hover { 132 | color: #0056b3; 133 | text-decoration: underline; 134 | } 135 | 136 | a:not([href]):not([tabindex]) { 137 | color: inherit; 138 | text-decoration: none; 139 | } 140 | 141 | a:not([href]):not([tabindex]):hover, a:not([href]):not([tabindex]):focus { 142 | color: inherit; 143 | text-decoration: none; 144 | } 145 | 146 | a:not([href]):not([tabindex]):focus { 147 | outline: 0; 148 | } 149 | 150 | pre, 151 | code, 152 | kbd, 153 | samp { 154 | font-family: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; 155 | font-size: 1em; 156 | } 157 | 158 | pre { 159 | margin-top: 0; 160 | margin-bottom: 1rem; 161 | overflow: auto; 162 | } 163 | 164 | figure { 165 | margin: 0 0 1rem; 166 | } 167 | 168 | img { 169 | vertical-align: middle; 170 | border-style: none; 171 | } 172 | 173 | svg { 174 | overflow: hidden; 175 | vertical-align: middle; 176 | } 177 | 178 | table { 179 | border-collapse: collapse; 180 | } 181 | 182 | caption { 183 | padding-top: 0.75rem; 184 | padding-bottom: 0.75rem; 185 | color: #6c757d; 186 | text-align: left; 187 | caption-side: bottom; 188 | } 189 | 190 | th { 191 | text-align: inherit; 192 | } 193 | 194 | label { 195 | display: inline-block; 196 | margin-bottom: 0.5rem; 197 | } 198 | 199 | button { 200 | border-radius: 0; 201 | } 202 | 203 | button:focus { 204 | outline: 1px dotted; 205 | outline: 5px auto -webkit-focus-ring-color; 206 | } 207 | 208 | input, 209 | button, 210 | select, 211 | optgroup, 212 | textarea { 213 | margin: 0; 214 | font-family: inherit; 215 | font-size: inherit; 216 | line-height: inherit; 217 | } 218 | 219 | button, 220 | input { 221 | overflow: visible; 222 | } 223 | 224 | button, 225 | select { 226 | text-transform: none; 227 | } 228 | 229 | select { 230 | word-wrap: normal; 231 | } 232 | 233 | button, 234 | [type="button"], 235 | [type="reset"], 236 | [type="submit"] { 237 | -webkit-appearance: button; 238 | } 239 | 240 | button:not(:disabled), 241 | [type="button"]:not(:disabled), 242 | [type="reset"]:not(:disabled), 243 | [type="submit"]:not(:disabled) { 244 | cursor: pointer; 245 | } 246 | 247 | button::-moz-focus-inner, 248 | [type="button"]::-moz-focus-inner, 249 | [type="reset"]::-moz-focus-inner, 250 | [type="submit"]::-moz-focus-inner { 251 | padding: 0; 252 | border-style: none; 253 | } 254 | 255 | input[type="radio"], 256 | input[type="checkbox"] { 257 | box-sizing: border-box; 258 | padding: 0; 259 | } 260 | 261 | input[type="date"], 262 | input[type="time"], 263 | input[type="datetime-local"], 264 | input[type="month"] { 265 | -webkit-appearance: listbox; 266 | } 267 | 268 | textarea { 269 | overflow: auto; 270 | resize: vertical; 271 | } 272 | 273 | fieldset { 274 | min-width: 0; 275 | padding: 0; 276 | margin: 0; 277 | border: 0; 278 | } 279 | 280 | legend { 281 | display: block; 282 | width: 100%; 283 | max-width: 100%; 284 | padding: 0; 285 | margin-bottom: .5rem; 286 | font-size: 1.5rem; 287 | line-height: inherit; 288 | color: inherit; 289 | white-space: normal; 290 | } 291 | 292 | progress { 293 | vertical-align: baseline; 294 | } 295 | 296 | [type="number"]::-webkit-inner-spin-button, 297 | [type="number"]::-webkit-outer-spin-button { 298 | height: auto; 299 | } 300 | 301 | [type="search"] { 302 | outline-offset: -2px; 303 | -webkit-appearance: none; 304 | } 305 | 306 | [type="search"]::-webkit-search-decoration { 307 | -webkit-appearance: none; 308 | } 309 | 310 | ::-webkit-file-upload-button { 311 | font: inherit; 312 | -webkit-appearance: button; 313 | } 314 | 315 | output { 316 | display: inline-block; 317 | } 318 | 319 | summary { 320 | display: list-item; 321 | cursor: pointer; 322 | } 323 | 324 | template { 325 | display: none; 326 | } 327 | 328 | [hidden] { 329 | display: none !important; 330 | } 331 | /*# sourceMappingURL=bootstrap-reboot.css.map */ -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/Migrations/GalaxyHotelContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using GalaxyHotel.Infrastructure.Data; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | 9 | namespace GalaxyHotel.HelpDesk.Migrations 10 | { 11 | [DbContext(typeof(GalaxyHotelContext))] 12 | partial class GalaxyHotelContextModelSnapshot : ModelSnapshot 13 | { 14 | protected override void BuildModel(ModelBuilder modelBuilder) 15 | { 16 | #pragma warning disable 612, 618 17 | modelBuilder 18 | .HasAnnotation("ProductVersion", "3.1.5") 19 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 20 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 21 | 22 | modelBuilder.Entity("GalaxyHotel.Core.Models.Address", b => 23 | { 24 | b.Property("Id") 25 | .ValueGeneratedOnAdd() 26 | .HasColumnType("int") 27 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 28 | 29 | b.Property("City") 30 | .HasColumnType("nvarchar(max)"); 31 | 32 | b.Property("Country") 33 | .HasColumnType("nvarchar(max)"); 34 | 35 | b.Property("State") 36 | .HasColumnType("nvarchar(max)"); 37 | 38 | b.Property("Street") 39 | .HasColumnType("nvarchar(max)"); 40 | 41 | b.Property("ZipCode") 42 | .HasColumnType("nvarchar(max)"); 43 | 44 | b.HasKey("Id"); 45 | 46 | b.ToTable("Addresses"); 47 | }); 48 | 49 | modelBuilder.Entity("GalaxyHotel.Core.Models.Guest", b => 50 | { 51 | b.Property("Id") 52 | .ValueGeneratedOnAdd() 53 | .HasColumnType("int") 54 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 55 | 56 | b.Property("AddressId") 57 | .HasColumnType("int"); 58 | 59 | b.Property("FirstName") 60 | .HasColumnType("nvarchar(max)"); 61 | 62 | b.Property("LastName") 63 | .HasColumnType("nvarchar(max)"); 64 | 65 | b.Property("PaymentMethodId") 66 | .HasColumnType("int"); 67 | 68 | b.HasKey("Id"); 69 | 70 | b.HasIndex("AddressId") 71 | .IsUnique(); 72 | 73 | b.HasIndex("PaymentMethodId") 74 | .IsUnique(); 75 | 76 | b.ToTable("Guests"); 77 | }); 78 | 79 | modelBuilder.Entity("GalaxyHotel.Core.Models.PaymentMethod", b => 80 | { 81 | b.Property("Id") 82 | .ValueGeneratedOnAdd() 83 | .HasColumnType("int") 84 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 85 | 86 | b.Property("Alias") 87 | .HasColumnType("nvarchar(max)"); 88 | 89 | b.Property("CardNumber") 90 | .HasColumnType("nvarchar(max)"); 91 | 92 | b.Property("DueDate") 93 | .HasColumnType("datetimeoffset"); 94 | 95 | b.HasKey("Id"); 96 | 97 | b.ToTable("PaymentMethods"); 98 | }); 99 | 100 | modelBuilder.Entity("GalaxyHotel.Core.Models.Reservation", b => 101 | { 102 | b.Property("Id") 103 | .ValueGeneratedOnAdd() 104 | .HasColumnType("int") 105 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 106 | 107 | b.Property("CheckIn") 108 | .HasColumnType("datetimeoffset"); 109 | 110 | b.Property("CheckOut") 111 | .HasColumnType("datetimeoffset"); 112 | 113 | b.Property("GuestId") 114 | .HasColumnType("int"); 115 | 116 | b.Property("RoomId") 117 | .HasColumnType("int"); 118 | 119 | b.Property("TotalPrice") 120 | .HasColumnType("decimal(18,2)"); 121 | 122 | b.HasKey("Id"); 123 | 124 | b.HasIndex("GuestId"); 125 | 126 | b.HasIndex("RoomId"); 127 | 128 | b.ToTable("Reservations"); 129 | }); 130 | 131 | modelBuilder.Entity("GalaxyHotel.Core.Models.Room", b => 132 | { 133 | b.Property("Id") 134 | .ValueGeneratedOnAdd() 135 | .HasColumnType("int") 136 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 137 | 138 | b.Property("Floor") 139 | .HasColumnType("int"); 140 | 141 | b.Property("Name") 142 | .HasColumnType("nvarchar(max)"); 143 | 144 | b.Property("PricePerNight") 145 | .HasColumnType("decimal(18,2)"); 146 | 147 | b.HasKey("Id"); 148 | 149 | b.ToTable("Rooms"); 150 | }); 151 | 152 | modelBuilder.Entity("GalaxyHotel.Core.Models.Guest", b => 153 | { 154 | b.HasOne("GalaxyHotel.Core.Models.Address", "Address") 155 | .WithOne("Guest") 156 | .HasForeignKey("GalaxyHotel.Core.Models.Guest", "AddressId") 157 | .OnDelete(DeleteBehavior.Cascade) 158 | .IsRequired(); 159 | 160 | b.HasOne("GalaxyHotel.Core.Models.PaymentMethod", "PaymentMethod") 161 | .WithOne("Guest") 162 | .HasForeignKey("GalaxyHotel.Core.Models.Guest", "PaymentMethodId") 163 | .OnDelete(DeleteBehavior.Cascade) 164 | .IsRequired(); 165 | }); 166 | 167 | modelBuilder.Entity("GalaxyHotel.Core.Models.Reservation", b => 168 | { 169 | b.HasOne("GalaxyHotel.Core.Models.Guest", "Guest") 170 | .WithMany("Reservations") 171 | .HasForeignKey("GuestId") 172 | .OnDelete(DeleteBehavior.Cascade) 173 | .IsRequired(); 174 | 175 | b.HasOne("GalaxyHotel.Core.Models.Room", "Room") 176 | .WithMany("Reservations") 177 | .HasForeignKey("RoomId") 178 | .OnDelete(DeleteBehavior.Cascade) 179 | .IsRequired(); 180 | }); 181 | #pragma warning restore 612, 618 182 | } 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /Helpdesk/src/GalaxyHotel.HelpDesk/Migrations/20200829211346_SeedGalaxyHotelDb.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using GalaxyHotel.Infrastructure.Data; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Migrations; 8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 9 | 10 | namespace GalaxyHotel.HelpDesk.Migrations 11 | { 12 | [DbContext(typeof(GalaxyHotelContext))] 13 | [Migration("20200829211346_SeedGalaxyHotelDb")] 14 | partial class SeedGalaxyHotelDb 15 | { 16 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 17 | { 18 | #pragma warning disable 612, 618 19 | modelBuilder 20 | .HasAnnotation("ProductVersion", "3.1.5") 21 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 22 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 23 | 24 | modelBuilder.Entity("GalaxyHotel.Core.Models.Address", b => 25 | { 26 | b.Property("Id") 27 | .ValueGeneratedOnAdd() 28 | .HasColumnType("int") 29 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 30 | 31 | b.Property("City") 32 | .HasColumnType("nvarchar(max)"); 33 | 34 | b.Property("Country") 35 | .HasColumnType("nvarchar(max)"); 36 | 37 | b.Property("State") 38 | .HasColumnType("nvarchar(max)"); 39 | 40 | b.Property("Street") 41 | .HasColumnType("nvarchar(max)"); 42 | 43 | b.Property("ZipCode") 44 | .HasColumnType("nvarchar(max)"); 45 | 46 | b.HasKey("Id"); 47 | 48 | b.ToTable("Addresses"); 49 | }); 50 | 51 | modelBuilder.Entity("GalaxyHotel.Core.Models.Guest", b => 52 | { 53 | b.Property("Id") 54 | .ValueGeneratedOnAdd() 55 | .HasColumnType("int") 56 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 57 | 58 | b.Property("AddressId") 59 | .HasColumnType("int"); 60 | 61 | b.Property("FirstName") 62 | .HasColumnType("nvarchar(max)"); 63 | 64 | b.Property("LastName") 65 | .HasColumnType("nvarchar(max)"); 66 | 67 | b.Property("PaymentMethodId") 68 | .HasColumnType("int"); 69 | 70 | b.HasKey("Id"); 71 | 72 | b.HasIndex("AddressId") 73 | .IsUnique(); 74 | 75 | b.HasIndex("PaymentMethodId") 76 | .IsUnique(); 77 | 78 | b.ToTable("Guests"); 79 | }); 80 | 81 | modelBuilder.Entity("GalaxyHotel.Core.Models.PaymentMethod", b => 82 | { 83 | b.Property("Id") 84 | .ValueGeneratedOnAdd() 85 | .HasColumnType("int") 86 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 87 | 88 | b.Property("Alias") 89 | .HasColumnType("nvarchar(max)"); 90 | 91 | b.Property("CardNumber") 92 | .HasColumnType("nvarchar(max)"); 93 | 94 | b.Property("DueDate") 95 | .HasColumnType("datetimeoffset"); 96 | 97 | b.HasKey("Id"); 98 | 99 | b.ToTable("PaymentMethods"); 100 | }); 101 | 102 | modelBuilder.Entity("GalaxyHotel.Core.Models.Reservation", b => 103 | { 104 | b.Property("Id") 105 | .ValueGeneratedOnAdd() 106 | .HasColumnType("int") 107 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 108 | 109 | b.Property("CheckIn") 110 | .HasColumnType("datetimeoffset"); 111 | 112 | b.Property("CheckOut") 113 | .HasColumnType("datetimeoffset"); 114 | 115 | b.Property("GuestId") 116 | .HasColumnType("int"); 117 | 118 | b.Property("RoomId") 119 | .HasColumnType("int"); 120 | 121 | b.Property("TotalPrice") 122 | .HasColumnType("decimal(18,2)"); 123 | 124 | b.HasKey("Id"); 125 | 126 | b.HasIndex("GuestId"); 127 | 128 | b.HasIndex("RoomId"); 129 | 130 | b.ToTable("Reservations"); 131 | }); 132 | 133 | modelBuilder.Entity("GalaxyHotel.Core.Models.Room", b => 134 | { 135 | b.Property("Id") 136 | .ValueGeneratedOnAdd() 137 | .HasColumnType("int") 138 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 139 | 140 | b.Property("Floor") 141 | .HasColumnType("int"); 142 | 143 | b.Property("Name") 144 | .HasColumnType("nvarchar(max)"); 145 | 146 | b.Property("PricePerNight") 147 | .HasColumnType("decimal(18,2)"); 148 | 149 | b.HasKey("Id"); 150 | 151 | b.ToTable("Rooms"); 152 | }); 153 | 154 | modelBuilder.Entity("GalaxyHotel.Core.Models.Guest", b => 155 | { 156 | b.HasOne("GalaxyHotel.Core.Models.Address", "Address") 157 | .WithOne("Guest") 158 | .HasForeignKey("GalaxyHotel.Core.Models.Guest", "AddressId") 159 | .OnDelete(DeleteBehavior.Cascade) 160 | .IsRequired(); 161 | 162 | b.HasOne("GalaxyHotel.Core.Models.PaymentMethod", "PaymentMethod") 163 | .WithOne("Guest") 164 | .HasForeignKey("GalaxyHotel.Core.Models.Guest", "PaymentMethodId") 165 | .OnDelete(DeleteBehavior.Cascade) 166 | .IsRequired(); 167 | }); 168 | 169 | modelBuilder.Entity("GalaxyHotel.Core.Models.Reservation", b => 170 | { 171 | b.HasOne("GalaxyHotel.Core.Models.Guest", "Guest") 172 | .WithMany("Reservations") 173 | .HasForeignKey("GuestId") 174 | .OnDelete(DeleteBehavior.Cascade) 175 | .IsRequired(); 176 | 177 | b.HasOne("GalaxyHotel.Core.Models.Room", "Room") 178 | .WithMany("Reservations") 179 | .HasForeignKey("RoomId") 180 | .OnDelete(DeleteBehavior.Cascade) 181 | .IsRequired(); 182 | }); 183 | #pragma warning restore 612, 618 184 | } 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Data/Migrations/00000000000000_SeedGalaxyHotelDb.Designer.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using GalaxyHotel.Infrastructure.Data; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Migrations; 8 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 9 | 10 | namespace GalaxyHotel.Website.Migrations 11 | { 12 | [DbContext(typeof(GalaxyHotelContext))] 13 | [Migration("20200828091845_SeedGalaxyHotelDb")] 14 | partial class SeedGalaxyHotelDb 15 | { 16 | protected override void BuildTargetModel(ModelBuilder modelBuilder) 17 | { 18 | #pragma warning disable 612, 618 19 | modelBuilder 20 | .HasAnnotation("ProductVersion", "3.1.6") 21 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 22 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 23 | 24 | modelBuilder.Entity("GalaxyHotel.Core.Models.Address", b => 25 | { 26 | b.Property("Id") 27 | .ValueGeneratedOnAdd() 28 | .HasColumnType("int") 29 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 30 | 31 | b.Property("City") 32 | .HasColumnType("nvarchar(max)"); 33 | 34 | b.Property("Country") 35 | .HasColumnType("nvarchar(max)"); 36 | 37 | b.Property("State") 38 | .HasColumnType("nvarchar(max)"); 39 | 40 | b.Property("Street") 41 | .HasColumnType("nvarchar(max)"); 42 | 43 | b.Property("ZipCode") 44 | .HasColumnType("nvarchar(max)"); 45 | 46 | b.HasKey("Id"); 47 | 48 | b.ToTable("Addresses"); 49 | }); 50 | 51 | modelBuilder.Entity("GalaxyHotel.Core.Models.Guest", b => 52 | { 53 | b.Property("Id") 54 | .ValueGeneratedOnAdd() 55 | .HasColumnType("int") 56 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 57 | 58 | b.Property("AddressId") 59 | .HasColumnType("int"); 60 | 61 | b.Property("FirstName") 62 | .HasColumnType("nvarchar(max)"); 63 | 64 | b.Property("LastName") 65 | .HasColumnType("nvarchar(max)"); 66 | 67 | b.Property("PaymentMethodId") 68 | .HasColumnType("int"); 69 | 70 | b.HasKey("Id"); 71 | 72 | b.HasIndex("AddressId") 73 | .IsUnique(); 74 | 75 | b.HasIndex("PaymentMethodId") 76 | .IsUnique(); 77 | 78 | b.ToTable("Guests"); 79 | }); 80 | 81 | modelBuilder.Entity("GalaxyHotel.Core.Models.PaymentMethod", b => 82 | { 83 | b.Property("Id") 84 | .ValueGeneratedOnAdd() 85 | .HasColumnType("int") 86 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 87 | 88 | b.Property("Alias") 89 | .HasColumnType("nvarchar(max)"); 90 | 91 | b.Property("CardNumber") 92 | .HasColumnType("nvarchar(max)"); 93 | 94 | b.Property("DueDate") 95 | .HasColumnType("datetimeoffset"); 96 | 97 | b.HasKey("Id"); 98 | 99 | b.ToTable("PaymentMethods"); 100 | }); 101 | 102 | modelBuilder.Entity("GalaxyHotel.Core.Models.Reservation", b => 103 | { 104 | b.Property("Id") 105 | .ValueGeneratedOnAdd() 106 | .HasColumnType("int") 107 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 108 | 109 | b.Property("CheckIn") 110 | .HasColumnType("datetimeoffset"); 111 | 112 | b.Property("CheckOut") 113 | .HasColumnType("datetimeoffset"); 114 | 115 | b.Property("GuestId") 116 | .HasColumnType("int"); 117 | 118 | b.Property("RoomId") 119 | .HasColumnType("int"); 120 | 121 | b.Property("TotalPrice") 122 | .HasColumnType("decimal(18,2)"); 123 | 124 | b.HasKey("Id"); 125 | 126 | b.HasIndex("GuestId"); 127 | 128 | b.HasIndex("RoomId"); 129 | 130 | b.ToTable("Reservations"); 131 | }); 132 | 133 | modelBuilder.Entity("GalaxyHotel.Core.Models.Room", b => 134 | { 135 | b.Property("Id") 136 | .ValueGeneratedOnAdd() 137 | .HasColumnType("int") 138 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 139 | 140 | b.Property("Floor") 141 | .HasColumnType("int"); 142 | 143 | b.Property("Name") 144 | .HasColumnType("nvarchar(max)"); 145 | 146 | b.Property("PricePerNight") 147 | .HasColumnType("decimal(18,2)"); 148 | 149 | b.HasKey("Id"); 150 | 151 | b.ToTable("Rooms"); 152 | }); 153 | 154 | modelBuilder.Entity("GalaxyHotel.Core.Models.Guest", b => 155 | { 156 | b.HasOne("GalaxyHotel.Core.Models.Address", "Address") 157 | .WithOne("Guest") 158 | .HasForeignKey("GalaxyHotel.Core.Models.Guest", "AddressId") 159 | .OnDelete(DeleteBehavior.Cascade) 160 | .IsRequired(); 161 | 162 | b.HasOne("GalaxyHotel.Core.Models.PaymentMethod", "PaymentMethod") 163 | .WithOne("Guest") 164 | .HasForeignKey("GalaxyHotel.Core.Models.Guest", "PaymentMethodId") 165 | .OnDelete(DeleteBehavior.Cascade) 166 | .IsRequired(); 167 | }); 168 | 169 | modelBuilder.Entity("GalaxyHotel.Core.Models.Reservation", b => 170 | { 171 | b.HasOne("GalaxyHotel.Core.Models.Guest", "Guest") 172 | .WithMany("Reservations") 173 | .HasForeignKey("GuestId") 174 | .OnDelete(DeleteBehavior.Cascade) 175 | .IsRequired(); 176 | 177 | b.HasOne("GalaxyHotel.Core.Models.Room", "Room") 178 | .WithMany("Reservations") 179 | .HasForeignKey("RoomId") 180 | .OnDelete(DeleteBehavior.Cascade) 181 | .IsRequired(); 182 | }); 183 | #pragma warning restore 612, 618 184 | } 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Data/Migrations/00000000000000_CreateIdentitySchema.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Microsoft.EntityFrameworkCore.Metadata; 3 | using Microsoft.EntityFrameworkCore.Migrations; 4 | 5 | namespace GalaxyHotel.Website.Data.Migrations 6 | { 7 | public partial class CreateIdentitySchema : Migration 8 | { 9 | protected override void Up(MigrationBuilder migrationBuilder) 10 | { 11 | migrationBuilder.CreateTable( 12 | name: "AspNetRoles", 13 | columns: table => new 14 | { 15 | Id = table.Column(nullable: false), 16 | Name = table.Column(maxLength: 256, nullable: true), 17 | NormalizedName = table.Column(maxLength: 256, nullable: true), 18 | ConcurrencyStamp = table.Column(nullable: true) 19 | }, 20 | constraints: table => 21 | { 22 | table.PrimaryKey("PK_AspNetRoles", x => x.Id); 23 | }); 24 | 25 | migrationBuilder.CreateTable( 26 | name: "AspNetUsers", 27 | columns: table => new 28 | { 29 | Id = table.Column(nullable: false), 30 | UserName = table.Column(maxLength: 256, nullable: true), 31 | NormalizedUserName = table.Column(maxLength: 256, nullable: true), 32 | Email = table.Column(maxLength: 256, nullable: true), 33 | NormalizedEmail = table.Column(maxLength: 256, nullable: true), 34 | EmailConfirmed = table.Column(nullable: false), 35 | PasswordHash = table.Column(nullable: true), 36 | SecurityStamp = table.Column(nullable: true), 37 | ConcurrencyStamp = table.Column(nullable: true), 38 | PhoneNumber = table.Column(nullable: true), 39 | PhoneNumberConfirmed = table.Column(nullable: false), 40 | TwoFactorEnabled = table.Column(nullable: false), 41 | LockoutEnd = table.Column(nullable: true), 42 | LockoutEnabled = table.Column(nullable: false), 43 | AccessFailedCount = table.Column(nullable: false) 44 | }, 45 | constraints: table => 46 | { 47 | table.PrimaryKey("PK_AspNetUsers", x => x.Id); 48 | }); 49 | 50 | migrationBuilder.CreateTable( 51 | name: "AspNetRoleClaims", 52 | columns: table => new 53 | { 54 | Id = table.Column(nullable: false) 55 | .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 56 | RoleId = table.Column(nullable: false), 57 | ClaimType = table.Column(nullable: true), 58 | ClaimValue = table.Column(nullable: true) 59 | }, 60 | constraints: table => 61 | { 62 | table.PrimaryKey("PK_AspNetRoleClaims", x => x.Id); 63 | table.ForeignKey( 64 | name: "FK_AspNetRoleClaims_AspNetRoles_RoleId", 65 | column: x => x.RoleId, 66 | principalTable: "AspNetRoles", 67 | principalColumn: "Id", 68 | onDelete: ReferentialAction.Cascade); 69 | }); 70 | 71 | migrationBuilder.CreateTable( 72 | name: "AspNetUserClaims", 73 | columns: table => new 74 | { 75 | Id = table.Column(nullable: false) 76 | .Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn), 77 | UserId = table.Column(nullable: false), 78 | ClaimType = table.Column(nullable: true), 79 | ClaimValue = table.Column(nullable: true) 80 | }, 81 | constraints: table => 82 | { 83 | table.PrimaryKey("PK_AspNetUserClaims", x => x.Id); 84 | table.ForeignKey( 85 | name: "FK_AspNetUserClaims_AspNetUsers_UserId", 86 | column: x => x.UserId, 87 | principalTable: "AspNetUsers", 88 | principalColumn: "Id", 89 | onDelete: ReferentialAction.Cascade); 90 | }); 91 | 92 | migrationBuilder.CreateTable( 93 | name: "AspNetUserLogins", 94 | columns: table => new 95 | { 96 | LoginProvider = table.Column(maxLength: 128, nullable: false), 97 | ProviderKey = table.Column(maxLength: 128, nullable: false), 98 | ProviderDisplayName = table.Column(nullable: true), 99 | UserId = table.Column(nullable: false) 100 | }, 101 | constraints: table => 102 | { 103 | table.PrimaryKey("PK_AspNetUserLogins", x => new { x.LoginProvider, x.ProviderKey }); 104 | table.ForeignKey( 105 | name: "FK_AspNetUserLogins_AspNetUsers_UserId", 106 | column: x => x.UserId, 107 | principalTable: "AspNetUsers", 108 | principalColumn: "Id", 109 | onDelete: ReferentialAction.Cascade); 110 | }); 111 | 112 | migrationBuilder.CreateTable( 113 | name: "AspNetUserRoles", 114 | columns: table => new 115 | { 116 | UserId = table.Column(nullable: false), 117 | RoleId = table.Column(nullable: false) 118 | }, 119 | constraints: table => 120 | { 121 | table.PrimaryKey("PK_AspNetUserRoles", x => new { x.UserId, x.RoleId }); 122 | table.ForeignKey( 123 | name: "FK_AspNetUserRoles_AspNetRoles_RoleId", 124 | column: x => x.RoleId, 125 | principalTable: "AspNetRoles", 126 | principalColumn: "Id", 127 | onDelete: ReferentialAction.Cascade); 128 | table.ForeignKey( 129 | name: "FK_AspNetUserRoles_AspNetUsers_UserId", 130 | column: x => x.UserId, 131 | principalTable: "AspNetUsers", 132 | principalColumn: "Id", 133 | onDelete: ReferentialAction.Cascade); 134 | }); 135 | 136 | migrationBuilder.CreateTable( 137 | name: "AspNetUserTokens", 138 | columns: table => new 139 | { 140 | UserId = table.Column(nullable: false), 141 | LoginProvider = table.Column(maxLength: 128, nullable: false), 142 | Name = table.Column(maxLength: 128, nullable: false), 143 | Value = table.Column(nullable: true) 144 | }, 145 | constraints: table => 146 | { 147 | table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); 148 | table.ForeignKey( 149 | name: "FK_AspNetUserTokens_AspNetUsers_UserId", 150 | column: x => x.UserId, 151 | principalTable: "AspNetUsers", 152 | principalColumn: "Id", 153 | onDelete: ReferentialAction.Cascade); 154 | }); 155 | 156 | migrationBuilder.CreateIndex( 157 | name: "IX_AspNetRoleClaims_RoleId", 158 | table: "AspNetRoleClaims", 159 | column: "RoleId"); 160 | 161 | migrationBuilder.CreateIndex( 162 | name: "RoleNameIndex", 163 | table: "AspNetRoles", 164 | column: "NormalizedName", 165 | unique: true, 166 | filter: "[NormalizedName] IS NOT NULL"); 167 | 168 | migrationBuilder.CreateIndex( 169 | name: "IX_AspNetUserClaims_UserId", 170 | table: "AspNetUserClaims", 171 | column: "UserId"); 172 | 173 | migrationBuilder.CreateIndex( 174 | name: "IX_AspNetUserLogins_UserId", 175 | table: "AspNetUserLogins", 176 | column: "UserId"); 177 | 178 | migrationBuilder.CreateIndex( 179 | name: "IX_AspNetUserRoles_RoleId", 180 | table: "AspNetUserRoles", 181 | column: "RoleId"); 182 | 183 | migrationBuilder.CreateIndex( 184 | name: "EmailIndex", 185 | table: "AspNetUsers", 186 | column: "NormalizedEmail"); 187 | 188 | migrationBuilder.CreateIndex( 189 | name: "UserNameIndex", 190 | table: "AspNetUsers", 191 | column: "NormalizedUserName", 192 | unique: true, 193 | filter: "[NormalizedUserName] IS NOT NULL"); 194 | } 195 | 196 | protected override void Down(MigrationBuilder migrationBuilder) 197 | { 198 | migrationBuilder.DropTable( 199 | name: "AspNetRoleClaims"); 200 | 201 | migrationBuilder.DropTable( 202 | name: "AspNetUserClaims"); 203 | 204 | migrationBuilder.DropTable( 205 | name: "AspNetUserLogins"); 206 | 207 | migrationBuilder.DropTable( 208 | name: "AspNetUserRoles"); 209 | 210 | migrationBuilder.DropTable( 211 | name: "AspNetUserTokens"); 212 | 213 | migrationBuilder.DropTable( 214 | name: "AspNetRoles"); 215 | 216 | migrationBuilder.DropTable( 217 | name: "AspNetUsers"); 218 | } 219 | } 220 | } 221 | -------------------------------------------------------------------------------- /Website/src/GalaxyHotel.Website/Data/Migrations/ApplicationDbContextModelSnapshot.cs: -------------------------------------------------------------------------------- 1 | // 2 | using System; 3 | using GalaxyHotel.Website.Data; 4 | using Microsoft.EntityFrameworkCore; 5 | using Microsoft.EntityFrameworkCore.Infrastructure; 6 | using Microsoft.EntityFrameworkCore.Metadata; 7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion; 8 | 9 | namespace GalaxyHotel.Website.Data.Migrations 10 | { 11 | [DbContext(typeof(ApplicationDbContext))] 12 | partial class ApplicationDbContextModelSnapshot : ModelSnapshot 13 | { 14 | protected override void BuildModel(ModelBuilder modelBuilder) 15 | { 16 | #pragma warning disable 612, 618 17 | modelBuilder 18 | .HasAnnotation("ProductVersion", "3.0.0") 19 | .HasAnnotation("Relational:MaxIdentifierLength", 128) 20 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 21 | 22 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => 23 | { 24 | b.Property("Id") 25 | .HasColumnType("nvarchar(450)"); 26 | 27 | b.Property("ConcurrencyStamp") 28 | .IsConcurrencyToken() 29 | .HasColumnType("nvarchar(max)"); 30 | 31 | b.Property("Name") 32 | .HasColumnType("nvarchar(256)") 33 | .HasMaxLength(256); 34 | 35 | b.Property("NormalizedName") 36 | .HasColumnType("nvarchar(256)") 37 | .HasMaxLength(256); 38 | 39 | b.HasKey("Id"); 40 | 41 | b.HasIndex("NormalizedName") 42 | .IsUnique() 43 | .HasName("RoleNameIndex") 44 | .HasFilter("[NormalizedName] IS NOT NULL"); 45 | 46 | b.ToTable("AspNetRoles"); 47 | }); 48 | 49 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 50 | { 51 | b.Property("Id") 52 | .ValueGeneratedOnAdd() 53 | .HasColumnType("int") 54 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 55 | 56 | b.Property("ClaimType") 57 | .HasColumnType("nvarchar(max)"); 58 | 59 | b.Property("ClaimValue") 60 | .HasColumnType("nvarchar(max)"); 61 | 62 | b.Property("RoleId") 63 | .IsRequired() 64 | .HasColumnType("nvarchar(450)"); 65 | 66 | b.HasKey("Id"); 67 | 68 | b.HasIndex("RoleId"); 69 | 70 | b.ToTable("AspNetRoleClaims"); 71 | }); 72 | 73 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUser", b => 74 | { 75 | b.Property("Id") 76 | .HasColumnType("nvarchar(450)"); 77 | 78 | b.Property("AccessFailedCount") 79 | .HasColumnType("int"); 80 | 81 | b.Property("ConcurrencyStamp") 82 | .IsConcurrencyToken() 83 | .HasColumnType("nvarchar(max)"); 84 | 85 | b.Property("Email") 86 | .HasColumnType("nvarchar(256)") 87 | .HasMaxLength(256); 88 | 89 | b.Property("EmailConfirmed") 90 | .HasColumnType("bit"); 91 | 92 | b.Property("LockoutEnabled") 93 | .HasColumnType("bit"); 94 | 95 | b.Property("LockoutEnd") 96 | .HasColumnType("datetimeoffset"); 97 | 98 | b.Property("NormalizedEmail") 99 | .HasColumnType("nvarchar(256)") 100 | .HasMaxLength(256); 101 | 102 | b.Property("NormalizedUserName") 103 | .HasColumnType("nvarchar(256)") 104 | .HasMaxLength(256); 105 | 106 | b.Property("PasswordHash") 107 | .HasColumnType("nvarchar(max)"); 108 | 109 | b.Property("PhoneNumber") 110 | .HasColumnType("nvarchar(max)"); 111 | 112 | b.Property("PhoneNumberConfirmed") 113 | .HasColumnType("bit"); 114 | 115 | b.Property("SecurityStamp") 116 | .HasColumnType("nvarchar(max)"); 117 | 118 | b.Property("TwoFactorEnabled") 119 | .HasColumnType("bit"); 120 | 121 | b.Property("UserName") 122 | .HasColumnType("nvarchar(256)") 123 | .HasMaxLength(256); 124 | 125 | b.HasKey("Id"); 126 | 127 | b.HasIndex("NormalizedEmail") 128 | .HasName("EmailIndex"); 129 | 130 | b.HasIndex("NormalizedUserName") 131 | .IsUnique() 132 | .HasName("UserNameIndex") 133 | .HasFilter("[NormalizedUserName] IS NOT NULL"); 134 | 135 | b.ToTable("AspNetUsers"); 136 | }); 137 | 138 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 139 | { 140 | b.Property("Id") 141 | .ValueGeneratedOnAdd() 142 | .HasColumnType("int") 143 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); 144 | 145 | b.Property("ClaimType") 146 | .HasColumnType("nvarchar(max)"); 147 | 148 | b.Property("ClaimValue") 149 | .HasColumnType("nvarchar(max)"); 150 | 151 | b.Property("UserId") 152 | .IsRequired() 153 | .HasColumnType("nvarchar(450)"); 154 | 155 | b.HasKey("Id"); 156 | 157 | b.HasIndex("UserId"); 158 | 159 | b.ToTable("AspNetUserClaims"); 160 | }); 161 | 162 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 163 | { 164 | b.Property("LoginProvider") 165 | .HasColumnType("nvarchar(128)") 166 | .HasMaxLength(128); 167 | 168 | b.Property("ProviderKey") 169 | .HasColumnType("nvarchar(128)") 170 | .HasMaxLength(128); 171 | 172 | b.Property("ProviderDisplayName") 173 | .HasColumnType("nvarchar(max)"); 174 | 175 | b.Property("UserId") 176 | .IsRequired() 177 | .HasColumnType("nvarchar(450)"); 178 | 179 | b.HasKey("LoginProvider", "ProviderKey"); 180 | 181 | b.HasIndex("UserId"); 182 | 183 | b.ToTable("AspNetUserLogins"); 184 | }); 185 | 186 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 187 | { 188 | b.Property("UserId") 189 | .HasColumnType("nvarchar(450)"); 190 | 191 | b.Property("RoleId") 192 | .HasColumnType("nvarchar(450)"); 193 | 194 | b.HasKey("UserId", "RoleId"); 195 | 196 | b.HasIndex("RoleId"); 197 | 198 | b.ToTable("AspNetUserRoles"); 199 | }); 200 | 201 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 202 | { 203 | b.Property("UserId") 204 | .HasColumnType("nvarchar(450)"); 205 | 206 | b.Property("LoginProvider") 207 | .HasColumnType("nvarchar(128)") 208 | .HasMaxLength(128); 209 | 210 | b.Property("Name") 211 | .HasColumnType("nvarchar(128)") 212 | .HasMaxLength(128); 213 | 214 | b.Property("Value") 215 | .HasColumnType("nvarchar(max)"); 216 | 217 | b.HasKey("UserId", "LoginProvider", "Name"); 218 | 219 | b.ToTable("AspNetUserTokens"); 220 | }); 221 | 222 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => 223 | { 224 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 225 | .WithMany() 226 | .HasForeignKey("RoleId") 227 | .OnDelete(DeleteBehavior.Cascade) 228 | .IsRequired(); 229 | }); 230 | 231 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => 232 | { 233 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 234 | .WithMany() 235 | .HasForeignKey("UserId") 236 | .OnDelete(DeleteBehavior.Cascade) 237 | .IsRequired(); 238 | }); 239 | 240 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => 241 | { 242 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 243 | .WithMany() 244 | .HasForeignKey("UserId") 245 | .OnDelete(DeleteBehavior.Cascade) 246 | .IsRequired(); 247 | }); 248 | 249 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => 250 | { 251 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) 252 | .WithMany() 253 | .HasForeignKey("RoleId") 254 | .OnDelete(DeleteBehavior.Cascade) 255 | .IsRequired(); 256 | 257 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 258 | .WithMany() 259 | .HasForeignKey("UserId") 260 | .OnDelete(DeleteBehavior.Cascade) 261 | .IsRequired(); 262 | }); 263 | 264 | modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => 265 | { 266 | b.HasOne("Microsoft.AspNetCore.Identity.IdentityUser", null) 267 | .WithMany() 268 | .HasForeignKey("UserId") 269 | .OnDelete(DeleteBehavior.Cascade) 270 | .IsRequired(); 271 | }); 272 | #pragma warning restore 612, 618 273 | } 274 | } 275 | } 276 | --------------------------------------------------------------------------------