SHA256
- Added new entity "StayEntry" to log stays of guests. - Added pages for StayEntry management (List and creation). - New DataList for PaymentMethods. - Other general changes and improvements.
162 lines
5.5 KiB
C#
162 lines
5.5 KiB
C#
using FluentValidation;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Somnia.GuestLog.Infrastructure;
|
|
using Somnia.GuestLog.Models;
|
|
using Somnia.GuestLog.Models.DTOs;
|
|
using Somnia.GuestLog.Models.Entities;
|
|
|
|
namespace Somnia.GuestLog.Services;
|
|
|
|
public class StayEntryService(
|
|
ILogger<StayEntryService> logger,
|
|
IDbContextFactory<GuestLogContext> contextFactory,
|
|
IValidator<StayEntryDTO> dtoValidator
|
|
) : IStayEntryService
|
|
{
|
|
public async Task<bool> CreateEntryAsync(StayEntryDTO dto)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(dto);
|
|
|
|
var valResult = await dtoValidator.ValidateAsync(dto);
|
|
if (!valResult.IsValid)
|
|
{
|
|
logger.LogWarning("StayEntryService - CreateEntryAsync: Dto validation failed. Fix the errors: {errorList}", valResult.Errors);
|
|
return false;
|
|
}
|
|
|
|
DateTime createTime = DateTime.UtcNow;
|
|
StayEntry dbStay = new()
|
|
{
|
|
DateIn = dto.DateIn!.Value.ToUniversalTime(),
|
|
DateOut = dto.DateOut!.Value.ToUniversalTime(),
|
|
RoomCount = dto.RoomCount!.Value,
|
|
RoomNumber = dto.RoomNumber,
|
|
PaymentMethod = dto.PaymentMethod!,
|
|
CreateTime = createTime,
|
|
UpdateTime = createTime,
|
|
};
|
|
|
|
try
|
|
{
|
|
using var dbContext = contextFactory.CreateDbContext();
|
|
|
|
//Check and add GuestDocuments
|
|
foreach (GuestDocumentDTO guestDto in dto.GuestDocuments)
|
|
{
|
|
//Get it from db.
|
|
GuestDocument? dbGuest = await dbContext.GuestDocuments.FindAsync(guestDto.DocumentType, guestDto.DocumentNum)
|
|
?? throw new InvalidOperationException($"GuestDocument not found! Id: '{guestDto.FullKey}'");
|
|
|
|
//Check if Guest is already in other stay during the same period.
|
|
bool isInOtherStay = await this.IsGuestInStayInPeriod(dbGuest.DocumentType, dbGuest.DocumentNum, dbStay.DateIn, dbStay.DateOut);
|
|
if (isInOtherStay)
|
|
{
|
|
throw new InvalidOperationException($"Guest ('{dbGuest.GetFullKey()}') is already in a stay during the period: {dbStay.DateIn}-{dbStay.DateOut}");
|
|
}
|
|
|
|
//Add dbGuest to dbStay.
|
|
dbStay.GuestDocuments.Add(dbGuest);
|
|
}
|
|
|
|
await dbContext.AddAsync(dbStay);
|
|
await dbContext.SaveChangesAsync();
|
|
|
|
logger.LogInformation("StayEntryService - CreateEntryAsync: StayEntry Created: '{id}'", dbStay.GetFullKey());
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logger.LogError(ex, "StayEntryService - CreateEntryAsync: Error creating StayEntry");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public Task<bool> UpdateEntryAsync(StayEntryDTO updatedDto)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
|
|
public Task<bool> DeleteEntryAsync(StayEntryDTO dto)
|
|
{
|
|
if (dto.Id is null)
|
|
{
|
|
throw new InvalidOperationException("StayEntryService - DeleteEntry: A DTO without key can't be deleted!");
|
|
}
|
|
|
|
return DeleteEntryAsync(dto.Id.Value);
|
|
}
|
|
|
|
public async Task<bool> DeleteEntryAsync(long id)
|
|
{
|
|
using var dbContext = contextFactory.CreateDbContext();
|
|
StayEntry? dbItem = await dbContext.StayEntries.FindAsync(id);
|
|
if (dbItem is null)
|
|
{
|
|
logger.LogWarning("StayEntryService - DeleteEntry: Error deleting StayEntry. Entity not found with key: '{key}'", id);
|
|
return false;
|
|
}
|
|
|
|
try
|
|
{
|
|
dbContext.StayEntries.Remove(dbItem);
|
|
await dbContext.SaveChangesAsync();
|
|
|
|
logger.LogInformation("StayEntryService - DeleteEntry: StayEntry deleted: '{id}'", dbItem.GetFullKey());
|
|
return true;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
logger.LogError(ex, "StayEntryService - DeleteEntry: Error deleting StayEntry: '{id}'", dbItem.GetFullKey());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public async Task<StayEntryDTO?> GetDtoByIdAsync(long id)
|
|
{
|
|
using var dbContext = contextFactory.CreateDbContext();
|
|
StayEntry? dbItem = await dbContext.StayEntries.FindAsync(id);
|
|
return dbItem is not null ? GetDtoFromDb(dbItem) : null;
|
|
}
|
|
|
|
public async Task<IEnumerable<StayEntryDTO>> GetDtoListAsync()
|
|
{
|
|
using var dbContext = contextFactory.CreateDbContext();
|
|
var dbList = await dbContext.StayEntries
|
|
.OrderByDescending(e => e.UpdateTime)
|
|
.ToListAsync();
|
|
|
|
return dbList.Select(GetDtoFromDb);
|
|
}
|
|
|
|
|
|
public async Task<bool> IsGuestInStayInPeriod(string docType, string docNum, DateTime startTime, DateTime endTime)
|
|
{
|
|
using var dbContext = contextFactory.CreateDbContext();
|
|
|
|
bool rs = await dbContext.StayEntries.AnyAsync(
|
|
s => s.DateIn < endTime && s.DateOut > startTime
|
|
&& s.GuestDocuments.Any(g => g.DocumentType == docType && g.DocumentNum == docNum));
|
|
|
|
return rs;
|
|
}
|
|
|
|
public async Task<IEnumerable<StayEntryDTO>> GetStaysWithGuest(string docType, string docNum)
|
|
{
|
|
using var dbContext = contextFactory.CreateDbContext();
|
|
|
|
var rs = await dbContext.StayEntries.Where(
|
|
s => s.GuestDocuments.Any(g => g.DocumentType == docType && g.DocumentNum == docNum))
|
|
.ToListAsync();
|
|
|
|
return rs.Select(GetDtoFromDb);
|
|
}
|
|
|
|
#region Internal Methods
|
|
|
|
private static StayEntryDTO GetDtoFromDb(StayEntry dbItem)
|
|
{
|
|
return EntityMapping.MapStayEntryEntityToDTO(dbItem);
|
|
}
|
|
|
|
#endregion
|
|
} |