Exemple #1
0
        private static async Task <Booking> _saveBooking(Booking booking, ResotelContext ctx, DbContextTransaction transaction)
        {
            await ctx.SaveChangesAsync();

            transaction.Commit();
            return(booking);
        }
Exemple #2
0
        private static IQueryable <Room> _getRoomRequest(ResotelContext ctx, bool fromCtx)
        {
            IQueryable <Room> rooms = ctx.Rooms;

            if (!fromCtx)
            {
                rooms = ctx.Rooms.AsNoTracking();
            }
            IQueryable <Room> loadRoomsRequest = rooms
                                                 .Include(room => room.Options.Select(o => o.Discounts))
                                                 .Include(room => room.AvailablePacks)
                                                 .Include(room => room.Bookings.Select(b => b.OptionChoices))
                                                 .Include(room => room.Bookings
                                                          .Select(b => b.OptionChoices
                                                                  .Select(optC => optC.Option)
                                                                  .Select(o => o.Discounts
                                                                          .Select(discount => discount.Validity)
                                                                          )
                                                                  )
                                                          )
                                                 .Include(room => room.Bookings.Select(b => b.Client))
                                                 .Include(room => room.Bookings.Select(b => b.Dates))
                                                 .Include(room => room.Bookings.Select(b => b.RoomPacks.Select(appliedPack => appliedPack.Room)))
                                                 .Include(room => room.Bookings.Select(b => b.RoomPacks.Select(appliedPack => appliedPack.Room.Options)))
                                                 .Include(room => room.Bookings.Select(b => b.RoomPacks.Select(appliedPack => appliedPack.RoomPack)));

            return(loadRoomsRequest);
        }
Exemple #3
0
        private static IQueryable <Option> _getOptionRequest(ResotelContext ctx)
        {
            IQueryable <Option> optionsRequest =
                ctx.Options
                .Include(opt => opt.Rooms.Select(room => room.Options))
                .Include(opt => opt.Discounts.Select(discount => discount.Validity));

            return(optionsRequest);
        }
Exemple #4
0
        private static async Task <Client> _saveNewClient(Client client, ResotelContext ctx)
        {
            ctx.Clients.Add(client);
            await ctx.SaveChangesAsync();

            Client savedClient = client;

            return(savedClient);
        }
Exemple #5
0
        /// <summary>
        /// Gets a User by its login (as this one should be unique)
        /// </summary>
        /// <param name="login"></param>
        /// <returns></returns>
        public static async Task <User> FindByLoginAsync(string login)
        {
            using (ResotelContext ctx = new ResotelContext())
            {
                User foundUser = await ctx.Users.FirstOrDefaultAsync(u =>
                                                                     u.Login.Equals(login, StringComparison.InvariantCultureIgnoreCase)
                                                                     );

                return(foundUser);
            }
        }
Exemple #6
0
        private static async Task _fillUnavailableRooms(Booking booking, ResotelContext ctx, List <Room> unavailableRooms)
        {
            foreach (Room room in booking.Rooms)
            {
                Room freshRoom = await _getFreshRoom(ctx, room.Id);

                if (freshRoom == null)
                {
                    unavailableRooms.Add(freshRoom);
                }
            }
        }
Exemple #7
0
        /// <summary>
        /// Gets Available Options within requested DateRange.
        /// </summary>
        /// <param name="dateRange"></param>
        /// <returns></returns>
        public static async Task <List <Option> > GetAvailablesBetweenAsync(DateRange dateRange)
        {
            using (ResotelContext ctx = new ResotelContext())
            {
                List <Option> availableOptions = await ctx.Options
                                                 .Include(opt => opt.Discounts.Select(discount => discount.Validity))
                                                 .Where(Option.IsAvailableBetween(dateRange))
                                                 .ToListAsync();

                return(availableOptions);
            }
        }
Exemple #8
0
        /// <summary>
        /// Gets all available Rooms wihin requested dateRange
        /// A Room is available for a given dateRange if it has no booking including those dates save the last which may be on a booking's startDate
        /// </summary>
        /// <param name="dateRange"></param>
        /// <returns></returns>
        public static async Task <List <Room> > GetAvailablesBetweenAsync(DateRange dateRange)
        {
            using (ResotelContext ctx = new ResotelContext())
            {
                List <Room> availableRooms = await ctx.Rooms
                                             .Include(room => room.Options.Select(opt => opt.Discounts.Select(discount => discount.Validity)))
                                             .Include(room => room.AvailablePacks)
                                             .Where(Room.NotBookedDuring(dateRange))
                                             .ToListAsync();

                return(availableRooms);
            }
        }
Exemple #9
0
        /// <summary>
        /// Gets all Room with given Options available within requested dateRange
        /// </summary>
        /// <param name="options"></param>
        /// <param name="dateRange"></param>
        /// <returns></returns>
        public static async Task <List <Room> > GetMatchingRoomsBetween(IEnumerable <Option> options, DateRange dateRange)
        {
            using (ResotelContext ctx = new ResotelContext())
            {
                List <Room> matchingRooms = await ctx.Rooms
                                            .Include(room => room.Options.Select(opt => opt.Discounts.Select(discount => discount.Validity)))
                                            .Include(room => room.AvailablePacks)
                                            .Where(
                    Room.NotBookedDuring(dateRange)
                    .And(Room.WithOptions(options))
                    )
                                            .ToListAsync();

                return(matchingRooms);
            }
        }
Exemple #10
0
        private static IQueryable <Client> _getClientRequest(ResotelContext ctx)
        {
            IQueryable <Client> clientRequest = ctx.Clients
                                                .Include(cl => cl.Bookings)
                                                .Include(cl => cl.Bookings.Select(b => b.Rooms))
                                                .Include(cl => cl.Bookings.Select(b => b.Rooms.Select(r => r.Options)))
                                                .Include(cl => cl.Bookings.Select(b => b.RoomPacks.Select(appliedPack => appliedPack.Booking)))
                                                .Include(cl => cl.Bookings.Select(b => b.RoomPacks.Select(appliedPack => appliedPack.Room)))
                                                .Include(cl => cl.Bookings.Select(b => b.RoomPacks.Select(appliedPack => appliedPack.Room.Options)))
                                                .Include(cl => cl.Bookings.Select(b => b.RoomPacks.Select(appliedPack => appliedPack.RoomPack)))
                                                .Include(cl => cl.Bookings.Select(b => b.OptionChoices))
                                                .Include(cl => cl.Bookings.Select(b => b.OptionChoices.Select(optC => optC.Option)))
                                                .Include(cl => cl.Bookings.Select(b => b.OptionChoices.Select(optC => optC.Option.Rooms)))
                                                .Include(cl => cl.Bookings.Select(b => b.OptionChoices.Select(optC => optC.TakenDates)));

            return(clientRequest);
        }
Exemple #11
0
        /// <summary>
        /// Save or Update a Client
        /// </summary>
        /// <param name="client">requested client</param>
        /// <returns>The saved Client with its new id, if a new Client is passed</returns>
        public async static Task <Client> Save(Client client)
        {
            Client savedClient = null;

            using (ResotelContext ctx = new ResotelContext())
            {
                if (client.Id == 0)
                {
                    savedClient = await _saveNewClient(client, ctx);
                }
                else
                {
                    savedClient = await _editClient(client, ctx);
                }
            }
            return(savedClient);
        }
Exemple #12
0
        private static async Task <List <Room> > _replaceRooms(Booking booking, ResotelContext ctx, List <Room> unavailableRooms)
        {
            List <Room> unavailableReplacementRooms = new List <Room>();

            foreach (Room unavailableRoom in unavailableRooms)
            {
                Room replacementRoom = await _getReplacementRoom(ctx, unavailableRoom);

                if (replacementRoom != null)
                {
                    _replaceRoom(booking, unavailableRoom, replacementRoom);
                }
                else
                {
                    unavailableReplacementRooms.Add(unavailableRoom);
                }
            }
            return(unavailableReplacementRooms);
        }
Exemple #13
0
        private static async Task <Client> _editClient(Client client, ResotelContext ctx)
        {
            Client editedClient = await ctx.Clients.FirstOrDefaultAsync(cl => cl.Id == client.Id);

            // a client only has bookings as reference type properties, and none of them will get changed while we edit the client.
            // so lets make sur entity knows this
            foreach (Booking booking in client.Bookings)
            {
                Booking trackedBooking = await ctx.Bookings
                                         .Include(b => b.Dates)
                                         .FirstOrDefaultAsync(b => b.Id == booking.Id);

                ctx.Entry(trackedBooking).State = EntityState.Unchanged;
            }

            // update all non reference properties
            ctx.Entry(editedClient).State = EntityState.Modified;
            ctx.Entry(editedClient).CurrentValues.SetValues(client);
            await ctx.SaveChangesAsync();

            return(editedClient);
        }
Exemple #14
0
        /// <summary>
        /// Gets all clients and their entities (booking, optionchoices, appliedpacks, rooms, ...)
        /// </summary>
        /// <returns>a fully loaded Client</returns>
        public async static Task <List <Client> > GetAllClients()
        {
            using (ResotelContext ctx = new ResotelContext())
            {
                List <Client> clientEntities = await ctx.Clients
                                               .Include(client => client.Bookings)
                                               .Include(client => client.Bookings.Select(booking => booking.Dates))
                                               .Include(client => client.Bookings.Select(booking => booking.RoomPacks))
                                               .Include(client => client.Bookings.Select(booking => booking.RoomPacks.Select(appliedPack => appliedPack.Booking)))
                                               .Include(client => client.Bookings.Select(booking => booking.RoomPacks.Select(appliedPack => appliedPack.Room)))
                                               .Include(client => client.Bookings.Select(booking => booking.RoomPacks.Select(appliedPack => appliedPack.RoomPack)))
                                               .Include(client => client.Bookings.Select(booking => booking.Rooms))
                                               .Include(client => client.Bookings.Select(booking => booking.Rooms.Select(r => r.AvailablePacks)))
                                               .Include(client => client.Bookings.Select(booking => booking.OptionChoices))
                                               .Include(client => client.Bookings.Select(booking => booking.OptionChoices.Select(optC => optC.TakenDates)))
                                               .Include(client => client.Bookings.Select(booking => booking.OptionChoices.Select(optC => optC.Option)))
                                               .Include(client => client.Bookings.Select(booking => booking.OptionChoices.Select(optC => optC.Option.Discounts)))
                                               .ToListAsync();

                return(clientEntities);
            }
        }
Exemple #15
0
        private static async Task <OptionChoice> _getTrackedOptionChoice(OptionChoice optChoice, ResotelContext ctx)
        {
            OptionChoice trackedOptChoice = await ctx.Set <OptionChoice>()
                                            .Include(optC => optC.Option)
                                            .Include(optC => optC.Option.Discounts)
                                            .Include(optC => optC.Option.Rooms)
                                            .Include(optC => optC.TakenDates)
                                            .FirstOrDefaultAsync(optC => optC.Id == optChoice.Id);

            if (trackedOptChoice == null)
            {
                trackedOptChoice = ctx.Set <OptionChoice>().Add(optChoice);
            }

            return(trackedOptChoice);
        }
Exemple #16
0
        private static async Task <DateRange> _getTrackedBookingDates(DateRange newBookingDates, ResotelContext ctx)
        {
            DateRange trackedBookingDates = await ctx.Set <DateRange>().FirstOrDefaultAsync(dr => dr.Id == newBookingDates.Id);

            if (trackedBookingDates == null)
            {
                trackedBookingDates = ctx.Set <DateRange>().Attach(newBookingDates);
            }
            else
            {
                // check
                ctx.Entry(trackedBookingDates).CurrentValues.SetValues(newBookingDates);
            }
            return(trackedBookingDates);
        }
Exemple #17
0
        private static async Task _updateRoomPacks(Booking trackedBooking, IList <AppliedPack> trackedRoomPacks, IList <AppliedPack> newRoomPacks, ResotelContext ctx)
        {
            trackedRoomPacks.Clear();
            foreach (AppliedPack appliedPack in newRoomPacks)
            {
                AppliedPack trackedAppliedPack = await ctx.Set <AppliedPack>().FirstOrDefaultAsync(ap => ap.Id == appliedPack.Id);

                if (trackedAppliedPack == null)
                {
                    trackedAppliedPack = ctx.Set <AppliedPack>().Add(appliedPack);
                }

                Room trackedRoom = await ctx.Rooms.FirstOrDefaultAsync(r => r.Id == appliedPack.Room.Id);

                Pack trackedPack = await ctx.Set <Pack>().FirstOrDefaultAsync(p => p.Id == appliedPack.RoomPack.Id);

                trackedAppliedPack.Room     = trackedRoom;
                trackedAppliedPack.RoomPack = trackedPack;
                trackedAppliedPack.Booking  = trackedBooking;
            }
        }
Exemple #18
0
 private static void _updateTrackedBookingState(Booking trackedBooking, BookingState newBookingState, ResotelContext ctx)
 {
     ctx.Entry(trackedBooking).Property(b => b.State).EntityEntry.State = EntityState.Modified;
     ctx.Entry(trackedBooking).Property(b => b.State).EntityEntry.CurrentValues.SetValues(newBookingState);
 }
Exemple #19
0
 private async static Task <Room> _getFreshRoom(ResotelContext ctx, int roomId)
 {
     return(await ctx.Rooms.AsNoTracking()
            .Where(r => r.Id == roomId)
            .FirstOrDefaultAsync());
 }
Exemple #20
0
        private static async Task _updateBookingRooms(Booking trackedBooking, IList <Room> newRooms, ResotelContext ctx)
        {
            ctx.Entry(trackedBooking).Collection(b => b.Rooms).EntityEntry.State = EntityState.Modified;
            trackedBooking.Rooms.Clear();
            foreach (Room room in newRooms)
            {
                Room trackedRoom = await ctx.Rooms.FirstOrDefaultAsync(r => r.Id == room.Id);

                trackedBooking.Rooms.Add(trackedRoom);
            }
        }
Exemple #21
0
        /// <summary>
        /// SaveOrUpdate given Booking
        /// </summary>
        /// <param name="booking"></param>
        /// <returns>The saved booking, with its new id, if a new booking (which was never saved) is passed</returns>
        public async static Task <Booking> Save(Booking booking)
        {
            using (ResotelContext ctx = new ResotelContext())
            {
                Booking savedBooking = null;

                List <Room> rooms = await _getRoomRequest(ctx, true)
                                    .ToListAsync();

                List <Option> options = await _getOptionRequest(ctx)
                                        .ToListAsync();

                Client client = await _getClientRequest(ctx).FirstOrDefaultAsync(
                    cl => cl.Id == booking.Client.Id
                    );

                _assignCtxRooms(booking, rooms);
                _assignCtxOptions(booking, options);

                if (client != null)
                {
                    booking.Client = client;
                }

                if (booking.Id == 0)
                {
                    ctx.Entry(booking).State = EntityState.Added;
                }
                else
                {
                    Booking trackedBooking = await ctx.Bookings.FirstOrDefaultAsync(b => b.Id == booking.Id);

                    _updateTrackedBooking(trackedBooking, booking, ctx);
                    await _updateOptionChoices(trackedBooking.OptionChoices, booking.OptionChoices, ctx);
                    await _updateBookingRooms(trackedBooking, booking.Rooms, ctx);
                    await _updateRoomPacks(trackedBooking, trackedBooking.RoomPacks, booking.RoomPacks, ctx);

                    _updateTrackedBookingState(trackedBooking, booking.State, ctx);

                    DateRange trackedBookingDates = await _getTrackedBookingDates(booking.Dates, ctx);

                    trackedBooking.Dates = trackedBookingDates;
                }



                List <Room> unavailableRooms = new List <Room>();

                using (DbContextTransaction transaction = ctx.Database.BeginTransaction())
                {
                    try
                    {
                        await _fillUnavailableRooms(booking, ctx, unavailableRooms);

                        if (unavailableRooms.Count == 0)
                        {
                            savedBooking = await _saveBooking(booking, ctx, transaction);
                        }
                        else
                        {
                            List <Room> unavailableReplacementRooms = await _replaceRooms(booking, ctx, unavailableRooms);

                            if (unavailableReplacementRooms.Count > 0)
                            {
                                HashSet <RoomKind> unreplaceableRoomKinds = new HashSet <RoomKind>(unavailableReplacementRooms.ConvertAll(room => room.Kind));
                                transaction.Rollback();
                                throw new InvalidOperationException(
                                          $"Impossible de sauvegarder la réservation : nous n'avons plus assez de chambres des types {string.Join(",", unreplaceableRoomKinds)}");
                            }
                            else
                            {
                                savedBooking = await _saveBooking(booking, ctx, transaction);
                            }
                        }

                        return(savedBooking);
                    }
                    catch (Exception)
                    {
                        transaction.Rollback();
                        throw;
                    }
                }
            }
        }
Exemple #22
0
        private static async Task _updateOptionChoices(IList <OptionChoice> trackedOptionChoices, IList <OptionChoice> newOptionsChoices, ResotelContext ctx)
        {
            // Deletion ain't no small thing in EF, that thing holds memory dear,
            // so once you delete something, all aggregated entities are set to null, fun, isn't it
            // db do have transactions to test and try things before committing, but EF does not ..
            // cancelling a deletion imply a new db request, how sweet
            List <OptionChoice> optionChoicesToRemove = trackedOptionChoices.
                                                        Where(trackedOptC => !newOptionsChoices.Any(newOptC => newOptC.Id == trackedOptC.Id)).ToList();

            _removeExistingOptionChoices(optionChoicesToRemove, ctx);

            foreach (OptionChoice optChoice in newOptionsChoices)
            {
                OptionChoice trackedOptChoice = await _getTrackedOptionChoice(optChoice, ctx);
                await _getTrackedOption(optChoice, ctx);

                DateRange trackedOptDates = await _getTrackedOptionDates(optChoice, ctx);


                _updateTrackedOptionDates(trackedOptDates, optChoice.TakenDates, ctx);
                _updateTrackedOptionChoice(trackedOptChoice, optChoice, ctx);

                trackedOptionChoices.Add(trackedOptChoice);
            }
        }
Exemple #23
0
 private static void _updateTrackedOptionChoice(OptionChoice trackedOptChoice, OptionChoice newOptChoice, ResotelContext ctx)
 {
     ctx.Entry(trackedOptChoice).CurrentValues.SetValues(newOptChoice);
 }
Exemple #24
0
 private static async Task <Room> _getReplacementRoom(ResotelContext ctx, Room unavailableRoom)
 {
     return(await _getRoomRequest(ctx, false)
            .FirstOrDefaultAsync(room => room.Kind == unavailableRoom.Kind));
 }
Exemple #25
0
 private static void _updateTrackedOptionDates(DateRange trackedOptDates, DateRange newDateRange, ResotelContext ctx)
 {
     ctx.Entry(trackedOptDates).CurrentValues.SetValues(newDateRange);
 }
Exemple #26
0
        private static async Task <DateRange> _getTrackedOptionDates(OptionChoice optChoice, ResotelContext ctx)
        {
            DateRange trackedOptDates = await ctx.Set <DateRange>().FirstOrDefaultAsync(dr => dr.Id == optChoice.TakenDates.Id);

            if (trackedOptDates == null)
            {
                trackedOptDates = ctx.Set <DateRange>().Add(optChoice.TakenDates);
            }

            return(trackedOptDates);
        }
Exemple #27
0
 private static async Task _getTrackedOption(OptionChoice optChoice, ResotelContext ctx)
 {
     Option trackedOpt = await ctx.Options.FirstOrDefaultAsync(opt => opt.Id == optChoice.Id);
 }
Exemple #28
0
 private static void _updateTrackedBooking(Booking trackedBooking, Booking booking, ResotelContext ctx)
 {
     ctx.Entry(trackedBooking).State = EntityState.Modified;
     ctx.Entry(trackedBooking).CurrentValues.SetValues(booking);
 }
Exemple #29
0
 private static void _removeExistingOptionChoices(IList <OptionChoice> trackedOptionChoices, ResotelContext ctx)
 {
     for (int i = trackedOptionChoices.Count - 1; i >= 0; i--)
     {
         OptionChoice trackedOptChoice = trackedOptionChoices[i];
         ctx.Entry(trackedOptChoice).State = EntityState.Deleted;
     }
 }