GuestDocument Versions - Part 1:

- Changed GuestDocument PK from `DocumentType`+`DocumentNumber` to to `ID`+`Version` for future versioning.
- Added DB field "IsLastVersion" to simplify queries where only last/current version is allowed.
- Updated GuestDocument DB fields type for `CreateTime` & `UpdateTime` to add precision.
- Updated usages of GuestDocument PK to new PK.
- Limit delete of a GuestDocument when it's currently used in a StayEntry.

Note: DB changes require recreating db tables, so all data is lost and migration "rollback" is not allowed.
This commit is contained in:
2026-09-01 15:04:38 +02:00
parent a01eed82e1
commit 887c3d787a
21 changed files with 525 additions and 93 deletions
@@ -14,7 +14,7 @@
<PageTitle>Somnia - Guest Docs - Details</PageTitle>
<MudStack Row="true" Class="my-4">
<MudText Typo="Typo.h4" GutterBottom="true">Guest Document - "@docId"</MudText>
<MudText Typo="Typo.h4" GutterBottom="true">Guest Document: @docId - @documentModel?.FullDocument</MudText>
<MudSpacer />
<MudButton Variant="Variant.Filled" Color="Color.Success" Size="Size.Small" StartIcon="@Icons.Material.Filled.Edit"
OnClick="() => BtnEdit()" Disabled>
@@ -77,7 +77,7 @@
@code {
[Parameter]
public string? docId { get; set; }
public long docId { get; set; }
GuestDocForm _form = null!;
@@ -90,23 +90,8 @@
protected override async Task OnInitializedAsync()
{
if (docId is null)
{
userMessage.ShowMessage("No GuestDocument provided!!", MessageKind.Error);
Navigation.NotFound();
return;
}
GuestDocIdDTO? docIdModel = GuestDocIdDTO.DecodeFromString(docId);
if (docIdModel is null)
{
userMessage.ShowMessage($"Provided GuestDocId can't be decoded: '{docId}'", MessageKind.Error);
Navigation.NotFound();
return;
}
//Get model from db.
documentModel = await guestDocService.GetDtoByIdAsync(docIdModel.DocumentType, docIdModel.DocumentNum);
documentModel = await guestDocService.GetLastVersionDtoByIdAsync(docId);
if (documentModel is null)
{
userMessage.ShowMessage($"GuestDocument not found with ID: '{docId}'", MessageKind.Error);
@@ -123,13 +108,13 @@
return;
}
if (documentModel is null || documentModel.DocumentType is null || documentModel.DocumentNum is null)
if (documentModel is null || documentModel.Id is null || documentModel.Version is null)
{
throw new InvalidOperationException();
}
guestStaysLoading = true;
guestStayList = await stayService.GetStaysWithGuest(documentModel.DocumentType, documentModel.DocumentNum);
guestStayList = await stayService.GetStaysWithGuest(documentModel.Id.Value);
guestStaysLoading = false;
}
@@ -43,6 +43,8 @@
</MudStack>
</ToolBarContent>
<Columns>
<PropertyColumn Property="x => x.Id" Title="@LanguageLocale.dto_GuestDocument_Id" />
<PropertyColumn Property="x => x.Version" Title="@LanguageLocale.dto_GuestDocument_Version" />
<PropertyColumn Title="@LanguageLocale.dto_GuestDocument_DocumentType"
Property="x => dataListService.GetLocalizedValue(GuestConsts.DataList_DocumentTypes, x.DocumentType)"
Hideable="false" />
@@ -50,6 +52,7 @@
Title="@LanguageLocale.dto_GuestDocument_DocumentNum" />
<PropertyColumn Property="x => x.Name" Title="@LanguageLocale.dto_GuestDocument_Name" />
<PropertyColumn Property="x => x.Surname" Title="@LanguageLocale.dto_GuestDocument_Surname" />
<PropertyColumn Property="x => x.Surname2" Title="@LanguageLocale.dto_GuestDocument_Surname2" />
<PropertyColumn Title="@LanguageLocale.dto_GuestDocument_Nationality"
Property="x => dataListService.GetLocalizedValue(GuestConsts.DataList_CountryCodes, x.Nationality)" />
<PropertyColumn Property="x => x.UpdateTime" Title="@LanguageLocale.dto_GuestDocument_UpdateTime" />
@@ -126,10 +129,9 @@
private async Task BtnViewDetails(GuestDocumentDTO item)
{
GuestDocIdDTO idDto = GuestDocIdDTO.BuildFromDto(item) ?? throw new InvalidOperationException();
string strId = item.Id?.ToString() ?? throw new InvalidOperationException();
string itemId = GuestDocIdDTO.EncodeAsString(idDto);
string uri = GuestConsts.Page_GuestDocs_Detail.Replace(GuestConsts.Page_GuestDocs_Detail_Param_DocId, itemId);
string uri = GuestConsts.Page_GuestDocs_Detail.Replace(GuestConsts.Page_GuestDocs_Detail_Param_DocId, strId);
Navigation.NavigateTo(uri);
}
@@ -151,7 +153,7 @@
}
userMessage.ShowMessage($"Document {item.DocumentType}-{item.DocumentNum} deleted!", MessageKind.Success);
await LoadDataAsync();
await LoadDataAsync(showMsg: false);
}
private void BtnNewGuest()
@@ -82,6 +82,7 @@
ePageMode currentPageMode = ePageMode.selectDocId;
GuestDocIdDTO currentDocId = new() { DocumentNum = "", DocumentType = "" };
long? alreadyExistDocId = null;
GuestDocumentDTO newDocumentModel = new();
bool loadingDocId = false;
@@ -100,7 +101,8 @@
}
loadingDocId = true;
GuestDocumentDTO? dto = await guestDocService.GetDtoByIdAsync(currentDocId.DocumentType, currentDocId.DocumentNum);
GuestDocumentDTO? dto =
await guestDocService.GetLastVersionDtoByDocumentAsync(currentDocId.DocumentType, currentDocId.DocumentNum);
loadingDocId = false;
if (dto is null)
@@ -117,6 +119,7 @@
//GuestDoc already exists!
currentPageMode = ePageMode.alreadyExistDoc;
alreadyExistDocId = dto.Id;
}
private void BtnReturn()
@@ -153,14 +156,15 @@
private void BtnGoToDocument()
{
if (currentPageMode != ePageMode.alreadyExistDoc)
if (currentPageMode != ePageMode.alreadyExistDoc || alreadyExistDocId is null)
{
userMessage.ShowMessage("Invalid operation!", MessageKind.Error);
return;
}
string docId = GuestDocIdDTO.EncodeAsString(currentDocId);
string uri = GuestConsts.Page_GuestDocs_Detail.Replace("{docId}", docId);
string strId = alreadyExistDocId.Value.ToString();
string uri = GuestConsts.Page_GuestDocs_Detail.Replace(GuestConsts.Page_GuestDocs_Detail_Param_DocId, strId);
Navigation.NavigateTo(uri);
}