working new models for product detail view and refactor to fit

This commit is contained in:
Frede Hundewadt 2023-08-04 13:34:46 +02:00
parent 14d6175c24
commit ec971c0b00
22 changed files with 174 additions and 124 deletions

View file

@ -84,7 +84,10 @@
</div>
</div>
<div class="col-sm-2">
@product.Description
<div class="d-grid mx-auto">
<a class="btn btn-outline-secondary" href="/catalog/item/@product.SalesItemId" >Produkt Info @product.Description</a>
</div>
</div>
<div class="col-sm-2 text-sm-start">
<a class="btn btn-outline-secondary" href="@(_config.AssetUrl)/Home/DownloadLabelNumber?filename=@(product.VendorItemNo).lbx">

View file

@ -36,16 +36,10 @@
onerror="this.onerror=null;this.src='@(_config.AssetUrl)/images/no-image.png?height=100'"
alt="@salesItem.Name"/>
</td>
<td class="align-middle">
@salesItem.Name
</td>
<td class="align-middle">@salesItem.Name</td>
<td class="align-middle">@salesItem.ShortName</td>
<td class="align-middle">
@salesItem.Sku
</td>
<td class="align-middle">
@salesItem.BoxSize
</td>
<td class="align-middle">@salesItem.Sku</td>
<td class="align-middle">@salesItem.BoxSize</td>
<td class="align-middle">
<ul class="list-group">
@foreach (var rate in salesItem.Rates)

View file

@ -24,10 +24,16 @@ namespace Wonky.Client.Components;
public partial class ProductPriceListComponent
{
[Parameter] public List<SalesItemView> ItemList { get; set; } = new();
[Inject] public IToastService ToastService { get; set; }
// ##############################################################
[Inject] private IOptions<ApiConfig> Config { get; set; }
// ##############################################################
[Parameter] public List<SalesItemView> ItemList { get; set; } = new();
// ##############################################################
private ApiConfig _config = new();
protected override void OnInitialized()
{
_config = Config.Value;

View file

@ -48,6 +48,20 @@ public class CountryCatalogRepository : ICountryCatalogRepository
_api = configuration.Value;
}
/// <summary>
/// Complete catalog for print country
/// </summary>
/// <param name="countryCode"></param>
/// <returns></returns>
public async Task<List<SalesItemView>> GetPriceList(string countryCode)
{
var result = await _client.GetFromJsonAsync<List<SalesItemView>>(
$"{_api.Catalog}/{countryCode}", _options);
return result ?? new List<SalesItemView>();
}
/// <summary>
/// Get a paged sales item list
/// </summary>
@ -89,19 +103,6 @@ public class CountryCatalogRepository : ICountryCatalogRepository
}
/// <summary>
/// Get sales item by id
/// </summary>
/// <param name="countryCode"></param>
/// <param name="salesItemId"></param>
/// <returns></returns>
public async Task<SalesItemView> GetSalesItemId(string countryCode, string salesItemId)
{
var salesItem = await _client
.GetFromJsonAsync<SalesItemView>($"{_api.Catalog}/{countryCode}/{salesItemId}");
return salesItem ?? new SalesItemView();
}
/// <summary>
/// Overload Get sales item by sku and country code
/// </summary>
@ -114,28 +115,29 @@ public class CountryCatalogRepository : ICountryCatalogRepository
return salesItem ?? new SalesItemView();
}
/// <summary>
/// Get sales item by id
/// </summary>
/// <param name="salesItemId"></param>
/// <returns></returns>
public async Task<ProductDetailView> GetProductDetailView(string salesItemId)
{
var detailView = await _client
.GetFromJsonAsync<ProductDetailView>($"{_api.Catalog}/{salesItemId}");
return detailView ?? new ProductDetailView();
}
/// <summary>
/// Get sales item by variant id
/// </summary>
/// <param name="countryCode"></param>
/// <param name="variantId"></param>
/// <returns></returns>
public async Task<SalesItemView> GetSalesVariantId(string countryCode, string variantId)
public async Task<ProductDetailView> GetVariantDetailView(string variantId)
{
var salesItem = await _client
.GetFromJsonAsync<SalesItemView>($"{_api.Catalog}/{countryCode}/variant/{variantId}");
return salesItem ?? new SalesItemView();
}
/// <summary>
/// Complete catalog for print country
/// </summary>
/// <param name="countryCode"></param>
/// <returns></returns>
public async Task<List<SalesItemView>> GetPriceList(string countryCode)
{
var result = await _client.GetFromJsonAsync<List<SalesItemView>>(
$"{_api.Catalog}/{countryCode}", _options);
return result ?? new List<SalesItemView>();
var detailView = await _client
.GetFromJsonAsync<ProductDetailView>($"{_api.Catalog}/variant/{variantId}");
return detailView ?? new ProductDetailView();
}
}

View file

@ -24,6 +24,14 @@ namespace Wonky.Client.HttpRepository;
/// </summary>
public interface ICountryCatalogRepository
{
/// <summary>
/// Complete catalog for print country
/// </summary>
/// <param name="countryCode"></param>
/// <returns></returns>
Task<List<SalesItemView>> GetPriceList(string countryCode);
/// <summary>
/// Get a paged sales item list
/// </summary>
@ -32,14 +40,7 @@ public interface ICountryCatalogRepository
/// <returns></returns>
Task<PagingResponse<SalesItemView>> GetSalesItemsPaged(string countryCode, CatalogPager pager);
/// <summary>
/// Get sales item by id
/// </summary>
/// <param name="countryCode"></param>
/// <param name="salesItemId"></param>
/// <returns></returns>
Task<SalesItemView> GetSalesItemId(string countryCode, string salesItemId);
/// <summary>
/// Overload Get sales item by sku and country code
/// </summary>
@ -48,18 +49,19 @@ public interface ICountryCatalogRepository
/// <returns></returns>
Task<SalesItemView> GetSalesItemSku(string countryCode, string sku);
/// <summary>
/// Get sales item by id
/// </summary>
/// <param name="salesItemId"></param>
/// <returns></returns>
Task<ProductDetailView> GetProductDetailView(string salesItemId);
/// <summary>
/// Get sales item by variant id
/// </summary>
/// <param name="countryCode"></param>
/// <param name="variantId"></param>
/// <returns></returns>
Task<SalesItemView> GetSalesVariantId(string countryCode, string variantId);
/// <summary>
/// Complete catalog for print country
/// </summary>
/// <param name="countryCode"></param>
/// <returns></returns>
Task<List<SalesItemView>> GetPriceList(string countryCode);
Task<ProductDetailView> GetVariantDetailView(string variantId);
}

View file

@ -7,10 +7,11 @@ namespace Wonky.Client.Local.Services;
public class CabinetDrawerService : ICabinetDrawerService
{
private readonly JsonSerializerOptions _options = new ()
private readonly JsonSerializerOptions _options = new()
{
PropertyNameCaseInsensitive = true
};
private readonly ILogger<CabinetDrawerService> _logger;
private readonly ILocalStorageService _asyncStorageService;
private readonly IAdvisorActivityRepository _activityRepo;
@ -30,9 +31,9 @@ public class CabinetDrawerService : ICabinetDrawerService
public CabinetDrawerService(
ILogger<CabinetDrawerService> logger,
ILocalStorageService asyncStorageService,
ICountryCatalogRepository catalogRepo,
IAdvisorCustomerHistoryRepository historyRepo,
IAdvisorCustomerRepository customerRepo,
ICountryCatalogRepository catalogRepo,
IAdvisorCustomerHistoryRepository historyRepo,
IAdvisorCustomerRepository customerRepo,
IAdvisorActivityRepository activityRepo)
{
_logger = logger;
@ -65,7 +66,7 @@ public class CabinetDrawerService : ICabinetDrawerService
return drawer ?? new ActivityDrawer();
}
/// <summary>
/// Sales Catalog
/// </summary>
@ -76,7 +77,7 @@ public class CabinetDrawerService : ICabinetDrawerService
{
var drawer = await _asyncStorageService
.GetItemAsync<CatalogDrawer>($"{countryCode}.{CatalogDrawer.Label}");
if (drawer == null) force = true;
if (!force) return drawer ?? new CatalogDrawer();
var result = await _catalogRepo.GetPriceList(countryCode);
@ -89,7 +90,7 @@ public class CabinetDrawerService : ICabinetDrawerService
return drawer ?? new CatalogDrawer();
}
/// <summary>
/// Company Info
/// </summary>
@ -100,7 +101,7 @@ public class CabinetDrawerService : ICabinetDrawerService
{
var drawer = await _asyncStorageService
.GetItemAsync<InfoDrawer>($"{companyId}.{InfoDrawer.Label}");
if (drawer == null) force = true;
if (!force) return drawer ?? new InfoDrawer();
var result = await _customerRepo.GetCompanyById(companyId);
@ -112,7 +113,7 @@ public class CabinetDrawerService : ICabinetDrawerService
await StoreInfoDrawerAsync(companyId, drawer);
return drawer ?? new InfoDrawer();
}
/// <summary>
/// Inventory
@ -124,7 +125,7 @@ public class CabinetDrawerService : ICabinetDrawerService
{
var drawer = await _asyncStorageService
.GetItemAsync<InventoryDrawer>($"{companyId}.{InventoryDrawer.Label}");
if (drawer == null) force = true;
if (!force) return drawer ?? new InventoryDrawer();
var result = await _historyRepo.GetInventory(companyId);
@ -136,7 +137,7 @@ public class CabinetDrawerService : ICabinetDrawerService
await StoreInventoryDrawerAsync(companyId, drawer);
return drawer ?? new InventoryDrawer();
}
/// <summary>
/// Invoices
@ -159,8 +160,8 @@ public class CabinetDrawerService : ICabinetDrawerService
await StoreInvoiceDrawerAsync(companyId, drawer);
return drawer ?? new InvoiceDrawer();
}
/// <summary>
/// Statistic (invoice lines)
/// </summary>
@ -171,7 +172,7 @@ public class CabinetDrawerService : ICabinetDrawerService
{
var drawer = await _asyncStorageService
.GetItemAsync<StatisticDrawer>($"{companyId}.{StatisticDrawer.Label}");
if (drawer == null) force = true;
if (!force) return drawer ?? new StatisticDrawer();
var result = await _historyRepo.GetProductInvoiceLines(companyId);
@ -205,10 +206,11 @@ public class CabinetDrawerService : ICabinetDrawerService
{
drawer.Content = drawer.Content.OrderByDescending(x => x.OrderDate).ToList();
}
await _asyncStorageService.SetItemAsync($"{companyId}.{ActivityDrawer.Label}", drawer);
}
/// <summary>
/// Store Sales Catalog
/// </summary>
@ -218,8 +220,8 @@ public class CabinetDrawerService : ICabinetDrawerService
{
await _asyncStorageService.SetItemAsync($"{countryCode}.{CatalogDrawer.Label}", drawer);
}
/// <summary>
/// Store Company Info
/// </summary>
@ -229,8 +231,8 @@ public class CabinetDrawerService : ICabinetDrawerService
{
await _asyncStorageService.SetItemAsync($"{companyId}.{InfoDrawer.Label}", drawer);
}
/// <summary>
/// Store Inventory
/// </summary>
@ -242,10 +244,11 @@ public class CabinetDrawerService : ICabinetDrawerService
{
drawer.Content = drawer.Content.OrderByDescending(x => x.LastInvoiceDate).ToList();
}
await _asyncStorageService.SetItemAsync($"{companyId}.{InventoryDrawer.Label}", drawer);
}
/// <summary>
/// Store Invoices
/// </summary>
@ -257,10 +260,11 @@ public class CabinetDrawerService : ICabinetDrawerService
{
drawer.Content = drawer.Content.OrderByDescending(x => x.DocumentDate).ToList();
}
await _asyncStorageService.SetItemAsync($"{companyId}.{InvoiceDrawer.Label}", drawer);
}
/// <summary>
/// Store statistic (invoice lines)
/// </summary>
@ -272,6 +276,7 @@ public class CabinetDrawerService : ICabinetDrawerService
{
drawer.Content = drawer.Content.OrderByDescending(x => x.DeliveryDate).ToList();
}
await _asyncStorageService.SetItemAsync($"{companyId}.{StatisticDrawer.Label}", drawer);
}
}

View file

@ -16,12 +16,12 @@
namespace Wonky.Client.Models;
public class SelectedSku
public class ItemSelect
{
/// <summary>
/// ItemId
/// ItemNo
/// </summary>
public string ItemId { get; set; } = "";
public string ItemNo { get; set; } = "";
/// <summary>
/// Quantity

View file

@ -20,7 +20,7 @@
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title">@CompanyName - Produktoversigt</h3>
<button type="button" class="btn btn-danger" @onclick="@Hide" data-bs-dismiss="modal" aria-label="Luk"><i class="bi-x-lg"></i></button>
<button type="button" class="btn btn-outline-secondary" @onclick="OnReload"><i class="bi-repeat"></i></button> <button type="button" class="btn btn-danger" @onclick="@Hide" data-bs-dismiss="modal" aria-label="Luk"><i class="bi-x-lg"></i></button>
</div>
<div class="modal-body">
<CustomerInventoryListComponent OnReorderSelected="OnReorderCallback" CompanyId="@CompanyId" Inventory="@Inventory"/>
@ -33,4 +33,4 @@
<div class="modal-backdrop fade show"></div>
}
<CustomerInventoryReorderOverlay CompanyId="@CompanyId" SalesItem="SalesItem" OnSelected="OnSelected" @ref="@ReorderOverlay" />
<CustomerInventoryReorderOverlay CompanyId="@CompanyId" SalesItemView="SalesItem" OnSelected="OnSelected" @ref="@ReorderOverlay" />

View file

@ -39,6 +39,7 @@ public partial class CustomerInventoryListOverlay : IDisposable
[Parameter] public string CountryCode { get; set; } = "";
[Parameter] public List<ProductInventoryItemView> Inventory { get; set; } = new();
[Parameter] public EventCallback<DraftItem> OnSelected { get; set; }
[Parameter] public EventCallback OnReload { get; set; }
/*
* Private Variables
*/
@ -72,7 +73,7 @@ public partial class CustomerInventoryListOverlay : IDisposable
Interceptor.RegisterBeforeSendEvent();
StateHasChanged();
}
/// <summary>
/// Inventory Reorder Overlay Callback

View file

@ -20,11 +20,11 @@
<div class="modal-dialog modal-dialog-scrollable modal-fullscreen">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">@SalesItem.Name @SalesItem.Sku (@SalesItem.BoxSize stk/colli)</h4>
<h4 class="modal-title">@SalesItemView.Name @SalesItemView.Sku (@SalesItemView.BoxSize stk/colli)</h4>
<button type="button" class="btn btn-danger" @onclick="@Hide" data-bs-dismiss="modal" aria-label="Luk"><i class="bi-x-lg"></i></button>
</div>
<div class="modal-body">
@if (SalesItem.Discontinued)
@if (SalesItemView.Discontinued)
{
<h3>Udgået produkt</h3>
}
@ -73,7 +73,7 @@
@* end draft line ------------------------------------------------- *@
@* price list item ------------------------------------------------ *@
<div class="row align-middle">
@foreach (var rate in SalesItem.Rates)
@foreach (var rate in SalesItemView.Rates)
{
<div class="col">
<a type="button" class="btn btn-primary btn-sm" data-bs-dismiss="modal" @onclick="@(() => SelectPrice(rate.Quantity, rate.Rate))">
@ -105,7 +105,7 @@
<td class="align-middle">@entry.Discount</td>
<td class="align-middle">@entry.Price</td>
<td class="align-middle">
@if (!SalesItem.Discontinued)
@if (!SalesItemView.Discontinued)
{
<button type="button" class="btn btn-primary btn-sm" data-bs-dismiss="modal" @onclick="@(() => SelectHistory(entry))">
<i class="bi-plus"></i> VÆLG

View file

@ -31,7 +31,7 @@ public partial class CustomerInventoryReorderOverlay
// ##############################################################
[Parameter] public EventCallback<DraftItem> OnSelected { get; set; }
[Parameter] public string CompanyId { get; set; } = "";
[Parameter] public SalesItemView SalesItem { get; set; } = new();
[Parameter] public SalesItemView SalesItemView { get; set; } = new();
// ##############################################################
private List<ProductHistoryView>? History { get; set; } = new();
@ -47,17 +47,17 @@ public partial class CustomerInventoryReorderOverlay
/// </summary>
protected override async Task OnParametersSetAsync()
{
if (string.IsNullOrWhiteSpace(SalesItem.Sku))
if (string.IsNullOrWhiteSpace(SalesItemView.Sku))
return;
History = await HistoryRepo.GetProductInvoiceLines(CompanyId, SalesItem.Sku);
History = await HistoryRepo.GetProductInvoiceLines(CompanyId, SalesItemView.Sku);
if (!History.Any())
await Task.Delay(1000);
SelectedItem.Item = SalesItem;
SelectedItem.Item = SalesItemView;
SelectedItem.Discount = 0;
SelectedItem.Quantity = 1;
if(SalesItem.Rates.Any())
SelectedItem.Price = decimal.Parse(SalesItem.Rates[0].Rate, CultureInfo.InvariantCulture);
if(SalesItemView.Rates.Any())
SelectedItem.Price = decimal.Parse(SalesItemView.Rates[0].Rate, CultureInfo.InvariantCulture);
}

View file

@ -79,7 +79,8 @@
<div class="text-sm-end me-1">@rate.Quantity</div>
<div class="text-sm-end me-1">@rate.Rate</div>
<div>
<a class="btn btn-primary btn-sm" data-bs-dismiss="modal" @onclick="@(() => SelectItem(item.SalesItemId, rate.Quantity, rate.Rate))">
<a class="btn btn-primary btn-sm" data-bs-dismiss="modal"
@onclick="@(() => SelectItem(item.Sku, rate.Quantity, rate.Rate))">
<i class="bi-plus-lg"></i>
</a>
</div>

View file

@ -37,7 +37,7 @@ public partial class CatalogPagedOverlay : IDisposable
// ##############################################################
[Parameter] public string CountryCode { get; set; } = "";
[Parameter] public EventCallback<SelectedSku> OnSelected { get; set; }
[Parameter] public EventCallback<ItemSelect> OnSelected { get; set; }
// ##############################################################
private string _modalDisplay = "";
@ -65,16 +65,14 @@ public partial class CatalogPagedOverlay : IDisposable
private async Task GetSalesItems()
{
var pagingResponse = await CatalogRepo.GetSalesItemsPaged(CountryCode, _pager);
if (pagingResponse == null)
Task.Delay(250);
Items = pagingResponse.Items!;
PageData = pagingResponse.MetaData;
Logger.LogDebug("PriceCatalogOverlay => Items <= {}", JsonSerializer.Serialize(Items));
}
private void SelectItem(string itemId, string quantity, string rate)
private void SelectItem(string itemNo, string quantity, string rate)
{
OnSelected.InvokeAsync(new SelectedSku { Quantity = quantity, Rate = rate, ItemId = itemId });
OnSelected.InvokeAsync(new ItemSelect { Quantity = quantity, Rate = rate, ItemNo = itemNo });
Hide();
}

View file

@ -449,7 +449,7 @@ else
Activities="_activityDrawer.Content" @ref="ActivityListOverlay"/>
<CustomerInventoryListOverlay CompanyName="@_company.Name" CompanyId="@CompanyId" CountryCode="@_company.CountryCode"
Inventory="_inventoryDrawer.Content"
OnReload="@(() => ReloadHistory(true))" Inventory="_inventoryDrawer.Content"
OnSelected="InventoryOverlayCallback" @ref="InventoryListOverlay"/>
<CustomerInvoiceListOverlay Company="_company"

View file

@ -336,18 +336,18 @@ public partial class AdvisorActivityCreatePage : IDisposable
/// <summary>
/// Price Catalog Overlay Callback
/// </summary>
/// <param name="sku"></param>
private async Task PriceCatalogOverlayCallback(SelectedSku sku)
/// <param name="selectedItem"></param>
private async Task PriceCatalogOverlayCallback(ItemSelect selectedItem)
{
// get selected item
if (string.IsNullOrWhiteSpace(sku.ItemId))
if (string.IsNullOrWhiteSpace(selectedItem.ItemNo))
{
return;
}
_selectedItem = await CatalogRepo.GetSalesItemId(_salesRep.CountryCode.ToLower(), sku.ItemId);
_selectedItem = await CatalogRepo.GetSalesItemSku(_company.CountryCode, selectedItem.ItemNo);
ShowItem = true;
Price = sku.Rate;
Quantity = sku.Quantity;
Price = selectedItem.Rate;
Quantity = selectedItem.Quantity;
StateHasChanged();
}

View file

@ -37,7 +37,7 @@
</div>
<CustomerInventoryListComponent OnReorderSelected="@OnReorderCallback" CompanyId="@CompanyId" Inventory="@Inventory"/>
<CustomerInventoryReorderOverlay OnSelected="@OnSelectedItem" CompanyId="@CompanyId" SalesItem="@SalesItem" @ref="@ReorderOverlay"/>
<CustomerInventoryReorderOverlay OnSelected="@OnSelectedItem" CompanyId="@CompanyId" SalesItemView="@SalesItem" @ref="@ReorderOverlay"/>
@if (Working)
{

View file

@ -1,6 +1,6 @@
@using Wonky.Client.Components
@using System.Text.Json
@page "/catalog/{CountryCode}/{sku}"
@page "/catalog/item/{SalesItemId}"
<h3>CatalogCountryProductPage</h3>

View file

@ -15,11 +15,10 @@ public partial class CatalogCountryProductPage
[Inject] public ICountryCatalogRepository Catalog { get; set; }
// ##############################################################
[Parameter] public string CountryCode { get; set; } = "";
[Parameter] public string Sku { get; set; } = "";
[Parameter] public string SalesItemId { get; set; } = "";
// ##############################################################
private SalesItemView _item = new();
private ProductDetailView _item = new();
private bool _working = true;
protected override async Task OnInitializedAsync()
@ -27,7 +26,7 @@ public partial class CatalogCountryProductPage
Interceptor.RegisterEvent();
Interceptor.RegisterBeforeSendEvent();
_item = await Catalog.GetSalesItemSku(CountryCode, Sku);
_item = await Catalog.GetProductDetailView(SalesItemId);
_working = false;
}
}

View file

@ -205,15 +205,15 @@ public partial class OfficeOrderCreatePage : IDisposable
}
private async Task PriceListCallback(SelectedSku sku)
private async Task PriceListCallback(ItemSelect selectedItem)
{
// get selected item
if (string.IsNullOrWhiteSpace(sku.ItemId))
if (string.IsNullOrWhiteSpace(selectedItem.ItemNo))
return;
SelectedItem = await Catalog.GetSalesItemId(CountryCode, sku.ItemId);
SelectedItem = await Catalog.GetSalesItemSku(CountryCode, selectedItem.ItemNo);
ShowItem = true;
Price = sku.Rate;
Quantity = sku.Quantity;
Price = selectedItem.Rate;
Quantity = selectedItem.Quantity;
StateHasChanged();
}

View file

@ -1,7 +1,7 @@
{
"appInfo": {
"name": "Wonky Online",
"version": "203.0",
"version": "205.0",
"rc": true,
"sandBox": true,
"image": "grumpy-coder.png",

View file

@ -0,0 +1,38 @@
// Copyright (C) 2022 FCS Frede's Computer Services.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
//
using System.Collections.Generic;
namespace Wonky.Entity.Views;
public class ProductDetailView
{
public string Name { get; set; } = "";
public string Sku { get; set; } = "";
public string VendorItemNo { get; set; } = "";
public string ShortName { get; set; } = "";
public string PictureLink { get; set; } = "";
public string ProductGroup { get; set; } = "";
public bool Discontinued { get; set; }
public int BoxSize { get; set; }
public List<DocumentView> Documents { get; set; } = new();
}
public class DocumentView
{
public string Name { get; set; } = "";
public string Description { get; set; } = "";
public string DocumentTypeEnum { get; set; } = "";
}

View file

@ -29,4 +29,5 @@ public class ProductInventoryItemView
public string LastInvoiceDate { get; set; } = "";
public string Sku { get; set; } = "";
public string VendorItemNo { get; set; } = "";
public string SalesItemId { get; set; } = "";
}