SHA256
GuestLog - StayEntry - Initial Implementation
- 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.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
using FluentValidation;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Somnia.GuestLog.Infrastructure;
|
||||
using Somnia.GuestLog.Models;
|
||||
using Somnia.GuestLog.Models.DTOs;
|
||||
using Somnia.GuestLog.Models.Entities;
|
||||
using Somnia.GuestLog.Utils;
|
||||
@@ -35,6 +36,7 @@ public class GuestDocumentService(
|
||||
ZipCode = dto.ZipCode,
|
||||
};
|
||||
|
||||
DateTime createTime = DateTime.UtcNow;
|
||||
GuestDocument dbItem = new()
|
||||
{
|
||||
DocumentType = dto.DocumentType!,
|
||||
@@ -50,8 +52,8 @@ public class GuestDocumentService(
|
||||
PhoneNumber = dto.PhoneNumber,
|
||||
EmailAddress = dto.EmailAddress,
|
||||
AddressDetails = addressItem,
|
||||
CreateTime = DateTime.UtcNow,
|
||||
UpdateTime = DateTime.UtcNow,
|
||||
CreateTime = createTime,
|
||||
UpdateTime = createTime,
|
||||
};
|
||||
|
||||
try
|
||||
@@ -125,7 +127,7 @@ public class GuestDocumentService(
|
||||
.OrderByDescending(e => e.UpdateTime)
|
||||
.ToListAsync();
|
||||
|
||||
return dbList.Select(x => GetDtoFromDb(x));
|
||||
return dbList.Select(GetDtoFromDb);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -163,30 +165,13 @@ public class GuestDocumentService(
|
||||
return dbList.Select(x => GetDtoFromDb(x));
|
||||
}
|
||||
|
||||
public GuestDocumentDTO GetDtoFromDb(GuestDocument dbItem)
|
||||
|
||||
#region Internal Methods
|
||||
|
||||
private static GuestDocumentDTO GetDtoFromDb(GuestDocument dbItem)
|
||||
{
|
||||
return new()
|
||||
{
|
||||
DocumentType = dbItem.DocumentType,
|
||||
DocumentNum = dbItem.DocumentNum,
|
||||
IssueDate = dbItem.IssueDate.ToDateTime(TimeOnly.MinValue),
|
||||
SupportNum = dbItem.SupportNum,
|
||||
Nationality = dbItem.Nationality,
|
||||
Name = dbItem.Name,
|
||||
Surname = dbItem.Surname,
|
||||
Surname2 = dbItem.Surname2,
|
||||
BirthDate = dbItem.BirthDate.ToDateTime(TimeOnly.MinValue),
|
||||
Gender = dbItem.Gender,
|
||||
PhoneNumber = dbItem.PhoneNumber,
|
||||
EmailAddress = dbItem.EmailAddress,
|
||||
Address = dbItem.AddressDetails?.Address ?? "",
|
||||
AddressCity = dbItem.AddressDetails?.AddressCity ?? "",
|
||||
AddressProvince = dbItem.AddressDetails?.AddressProvince ?? "",
|
||||
AddressState = dbItem.AddressDetails?.AddressState ?? "",
|
||||
AddressCountry = dbItem.AddressDetails?.AddressCountry! ?? "",
|
||||
ZipCode = dbItem.AddressDetails?.ZipCode ?? "",
|
||||
CreateTime = dbItem.CreateTime,
|
||||
UpdateTime = dbItem.UpdateTime,
|
||||
};
|
||||
return EntityMapping.MapGuestDocumentEntityToDTO(dbItem);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using Somnia.GuestLog.Models.DTOs;
|
||||
|
||||
namespace Somnia.GuestLog.Services;
|
||||
|
||||
public interface IStayEntryService
|
||||
{
|
||||
public Task<bool> CreateEntryAsync(StayEntryDTO dto);
|
||||
public Task<bool> UpdateEntryAsync(StayEntryDTO updatedDto);
|
||||
public Task<bool> DeleteEntryAsync(StayEntryDTO dto);
|
||||
public Task<bool> DeleteEntryAsync(long id);
|
||||
|
||||
public Task<StayEntryDTO?> GetDtoByIdAsync(long id);
|
||||
public Task<IEnumerable<StayEntryDTO>> GetDtoListAsync();
|
||||
|
||||
|
||||
public Task<bool> IsGuestInStayInPeriod(string docType, string docNum, DateTime startTime, DateTime endTime);
|
||||
public Task<IEnumerable<StayEntryDTO>> GetStaysWithGuest(string docType, string docNum);
|
||||
|
||||
}
|
||||
@@ -20,6 +20,7 @@ public class StaticDataListService(
|
||||
new KeyValuePair<string, HashSet<string>>(GuestConsts.DataList_DocumentTypes, _documentTypeSet),
|
||||
new KeyValuePair<string, HashSet<string>>(GuestConsts.DataList_GenderOptions, _genderOptionSet),
|
||||
new KeyValuePair<string, HashSet<string>>(GuestConsts.DataList_CountryCodes, _countryCodeSet),
|
||||
new KeyValuePair<string, HashSet<string>>(GuestConsts.DataList_PaymentMethods, _paymentMethodSet),
|
||||
]);
|
||||
|
||||
public List<string> GetAvailableLists()
|
||||
@@ -92,6 +93,14 @@ public class StaticDataListService(
|
||||
"VIR","VNM","VUT","WLF","WSM","YEM","ZAF","ZMB","ZWE",
|
||||
];
|
||||
|
||||
private static readonly HashSet<string> _paymentMethodSet = [
|
||||
"EFECT",
|
||||
"TARJT",
|
||||
"TRANS",
|
||||
"MOVIL",
|
||||
"OTRO",
|
||||
];
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user