Add MeasurementOwnerId; RevisorId generic attributes to Order; improvements, fixes, etc..

This commit is contained in:
Loretta 2025-10-20 16:46:40 +02:00
parent e54612f923
commit 35e71cb75c
16 changed files with 414 additions and 198 deletions

View File

@ -2,8 +2,10 @@
using AyCode.Utils.Extensions;
using FruitBank.Common.Entities;
using FruitBank.Common.Interfaces;
using FruitBank.Common.Models;
using LinqToDB.Mapping;
using Mango.Nop.Core.Dtos;
using Mango.Nop.Core.Extensions;
using Mango.Nop.Core.Interfaces;
using Newtonsoft.Json;
using Nop.Core;
@ -13,7 +15,6 @@ using Nop.Core.Domain.Orders;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Linq.Expressions;
using Mango.Nop.Core.Extensions;
namespace FruitBank.Common.Dtos;
@ -42,7 +43,21 @@ public class OrderDto : MgOrderDto<OrderItemDto, ProductDto>, IOrderDto
}
[NotColumn, JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
public string TimeOfReceiptText => $"{DateOfReceiptOrCreated:H:mm} - {Customer.Company}";
public string TimeOfReceiptText
{
get
{
var resultText = string.Empty;
if (IsComplete) resultText = "[AUDITED]";
else if (IsMeasured) resultText = "[KÉSZ]";
else if (MeasurementOwnerId > 0) resultText = "[FOLYAMATBAN]";
//else if (MeasurementOwnerId == ??) resultText = "[SAJÁT MÉRÉS]";
//else if (MeasurementOwnerId > 0) resultText = "[MÁSOK MÉRIK]";
return $"{resultText} {DateOfReceiptOrCreated:H:mm} - {Customer.Company}";
}
}
[NotColumn, JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
public DateTime DateOfReceiptOrCreated => DateOfReceipt ?? CreatedOnUtc;
@ -50,6 +65,12 @@ public class OrderDto : MgOrderDto<OrderItemDto, ProductDto>, IOrderDto
[NotColumn, JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
public DateTime? DateOfReceipt => GenericAttributes.GetValueOrNull<DateTime>(nameof(IOrderDto.DateOfReceipt));
[NotColumn, JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
public int RevisorId => GenericAttributes.GetValueOrDefault(nameof(IOrderDto.RevisorId), 0);
[NotColumn, JsonIgnore, System.Text.Json.Serialization.JsonIgnore]
public int MeasurementOwnerId => GenericAttributes.GetValueOrDefault(nameof(IOrderDto.MeasurementOwnerId), 0);
//if (GenericAttributes.TryGetValue<DateTime>(nameof(IOrderDto.DateOfReceipt), out var value)) return value;
//var dateOfReceipt = GenericAttributes.SingleOrDefault(x => x.Key == nameof(IOrderDto.DateOfReceipt))?.Value ?? string.Empty;
//return dateOfReceipt.IsNullOrWhiteSpace() ? null : CommonHelper.To<DateTime>(dateOfReceipt);
@ -60,7 +81,15 @@ public class OrderDto : MgOrderDto<OrderItemDto, ProductDto>, IOrderDto
public OrderDto(Order order) : base(order)
{ }
public bool IsComplete => OrderStatus == OrderStatus.Complete;
public bool HasMeasuringAccess(int? customerId, bool isRevisorUser = false)
=> isRevisorUser || (customerId.HasValue && OrderStatus != OrderStatus.Complete && (customerId.Value == MeasurementOwnerId || MeasurementOwnerId == 0));
public bool IsMeasuredAndValid() => Id > 0 && OrderItemDtos.Count > 0 && OrderItemDtos.All(x => x.IsMeasured);
public bool IsValidMeasuringValues() => OrderItemDtos.Count > 0 && OrderItemDtos.All(x => x.IsValidMeasuringValues());
public bool IsOtherMeasuringInProgress(int? customerId)
=> customerId.GetValueOrDefault(0) != 0 && OrderItemDtos.Any(oi => oi.IsOtherMeasuringInProgress(customerId));
}

View File

@ -108,4 +108,7 @@ public class OrderItemDto : MgOrderItemDto<ProductDto>, IOrderItemDto
public bool IsMeasuredAndValid() => Id > 0 && IsValidMeasuringValues() && OrderItemPallets.All(oip => oip.IsMeasuredAndValid(IsMeasurable));
public bool IsValidMeasuringValues() => OrderItemPallets.Count > 0 && (!IsMeasurable || NetWeight > 0) && TrayQuantity == Quantity;
public bool IsOtherMeasuringInProgress(int? customerId)
=> customerId.GetValueOrDefault(0) != 0 && OrderItemPallets.Any(oip => oip.Id > 0 && oip.CreatorId.GetValueOrDefault(0) != customerId);
}

View File

@ -11,5 +11,7 @@ public interface ICustomOrderSignalREndpointCommon
Task<List<OrderDto>?> GetAllOrderDtoByIds(int[] orderIds);
Task<OrderDto?> GetOrderDtoById(int orderId);
Task<OrderItemPallet?> AddOrUpdateMeasuredOrderItemPallet(OrderItemPallet orderItemPallet);
Task<OrderDto?> SetOrderStatusToComplete(int orderId);
Task<OrderDto?> StartMeasuring(int orderId, int userId);
Task<OrderDto?> SetOrderStatusToComplete(int orderId, int revisorId);
}

View File

@ -10,4 +10,12 @@ public interface IOrderDto : IMgOrderDto<OrderItemDto, ProductDto>, IMeasured, I
DateTime DateOfReceiptOrCreated { get; }
string TimeOfReceiptText { get; }
int RevisorId { get; }
int MeasurementOwnerId { get; }
bool IsComplete { get; }
bool HasMeasuringAccess(int? customerId, bool isRevisorUser = false);
bool IsOtherMeasuringInProgress(int? customerId);
}

View File

@ -8,7 +8,9 @@ namespace FruitBank.Common.Interfaces;
public interface IOrderItemDto : IMgOrderItemDto<ProductDto>, IMeasuringValues, IMeasured, IMeasurable
{
public OrderDto OrderDto { get; set; }
public List<OrderItemPallet> OrderItemPallets { get; set; }
public void InitializeOrderItemPallets(List<OrderItemPallet> orderItemPallets);
OrderDto OrderDto { get; set; }
List<OrderItemPallet> OrderItemPallets { get; set; }
bool IsOtherMeasuringInProgress(int? customerId);
void InitializeOrderItemPallets(List<OrderItemPallet> orderItemPallets);
}

View File

@ -8,10 +8,12 @@ namespace FruitBank.Common.Models;
public class LoggedInModel
{
public bool IsLoggedIn => CustomerDto != null;
public bool IsRevisor => IsLoggedIn && CustomerRoles.Any(x => x.SystemName.ToLowerInvariant() == "measuringrevisor");
public CustomerDto? CustomerDto { get; private set; }
public List<CustomerRole> CustomerRoles { get; private set; } = [];
public List<CustomerDto> MeasuringUsers { get; set; } = [];
public LoggedInModel()
{
}

View File

@ -49,8 +49,9 @@ public class SignalRTags : AcSignalRTags
public const int GetOrderDtoById = 112;
public const int GetAllOrderDtoByIds = 114;
public const int GetPendingOrderDtos = 115;
public const int SetOrderStatusToComplete = 116;
public const int StartMeasuring = 116;
public const int SetOrderStatusToComplete = 117;
public const int AddOrderItemPallet = 131;
public const int UpdateOrderItemPallet = 132;
public const int AddOrUpdateMeasuredOrderItemPallet = 133;

View File

@ -484,24 +484,33 @@ namespace FruitBankHybrid.Shared.Tests
#endregion Product
#region OrderItem
//[return: NotNull]
//public async Task<ShippingItem> GetOrderDtoByIdAsync(int orderId)
//{
// var orderDto = await _signalRClient.GetOrderDtoById(orderId);
// Assert.IsNotNull(orderDto, $"orderDto: {orderId}");
[DataTestMethod]
[DataRow(1)]
public async Task GetOrderDtoByIdTest(int orderId) => await GetOrderDtoByIdAsync(orderId);
// if (orderDto.IsMeasurable) Assert.IsNotNull(orderDto.Pallet, $"orderDto.Pallet == null; orderDto.PalletId: {orderDto.PalletId}");
[return: NotNull]
public async Task<OrderDto> GetOrderDtoByIdAsync(int orderId)
{
var orderDto = await _signalRClient.GetOrderDtoById(orderId);
// Assert.IsNotNull(orderDto.ProductDto, $"orderDto.Product == null; orderDto.ProductId: {orderDto.ProductId}");
// Assert.IsTrue(orderDto.Id == orderId);
ValidateOrderDto(orderId, orderDto);
// Assert.IsTrue(orderDto.QuantityOnDocument > 0, "QuantityOnDocument == 0");
// Assert.IsTrue(orderDto.NetWeightOnDocument > 0, "NetWeightOnDocument == 0");
// Assert.IsTrue(orderDto.GrossWeightOnDocument > 0, "GrossWeightOnDocument == 0");
return orderDto!;
}
// return orderDto;
//}
private static bool ValidateOrderDto(int orderId, [NotNullWhen(true)] OrderDto? orderDto)
{
Assert.IsNotNull(orderDto, $"orderId: {orderId}");
Assert.IsNotNull(orderDto.Customer);
Assert.IsTrue(orderDto.Id == orderId);
Assert.IsTrue(orderDto.OrderItemDtos.Count > 0);
Assert.IsTrue(orderDto.OrderItemDtos.All(oi => oi.ProductDto != null));
return true;
}
//[DataTestMethod]
//[DataRow(1, -1, -2.137563300001, -333.75238200001, 2.12545)]
@ -611,7 +620,7 @@ namespace FruitBankHybrid.Shared.Tests
// }
// Assert.IsTrue(shippingItem.MeasuredQuantity == originalShippingItem.MeasuredQuantity + incQuantity);
// Assert.IsTrue(shippingItem.ShippingItemPallets!.All(x => x.IsValidSafeMeasuringValues()));
// Assert.IsTrue(shippingItem.ShippingItemPallets!.All(x => x.IsValidMeasuringValues(shippingItem.IsMeasurable)));

View File

@ -19,7 +19,7 @@
<DxFormLayoutItem Context="ctxFromLayoutItemPallet" CaptionCssClass="@(GetOrderItemPalletsCssClassNames(nameof(IMeasuringItemPalletBase.PalletWeight)))"
Field="@nameof(ShippingItemPallet.PalletWeight)"
Enabled="@(IsMeasurable && ProductId > 0)"
Caption="Rakl.súly(kg)" ColSpanMd="2"@ref="_weightFormLayoutItem" />
Caption="Rakl.súly(kg)" ColSpanMd="2" />
<DxFormLayoutItem Context="ctxFromLayoutItemPallet" CaptionCssClass="@(GetOrderItemPalletsCssClassNames(nameof(IMeasuringItemPalletBase.TareWeight)))"
Field="@nameof(ShippingItemPallet.TareWeight)"
@ -43,7 +43,7 @@
</DxFormLayoutItem>
<DxFormLayoutItem Context="ctxFromLayoutItemPallet" ColSpanMd="1">
<DxButton Enabled="@_btnSaveEnabled" Text="@(PalletItem.Id == 0 ? "Mentés" : "Módosítás")" Click="() => PalletItemSaveClick()" CssClass="w-100" />
<DxButton Enabled="@BtnSaveEnabled" Text="@(PalletItem.Id == 0 ? "Mentés" : "Módosítás")" Click="() => PalletItemSaveClick()" CssClass="w-100" />
</DxFormLayoutItem>
</DxFormLayout>
@ -55,6 +55,8 @@
[Parameter] public required int MeasuringIndex { get; set; }
[Parameter] public int? AddOrUpdateSignalRTag { get; set; } = null;
[Parameter] public int? MaxTrayQuantity { get; set; } = null;
//[Parameter] public EventCallback OnPalletItemSaveClick { get; set; }
[Parameter] public Func<TPalletItem?, Task>? OnPalletItemSaved { get; set; }
[Parameter] public Func<TPalletItem, Task>? OnPalletItemValueChanged { get; set; }
@ -63,12 +65,15 @@
[Inject] public required FruitBankSignalRClient FruitBankSignalRClient { get; set; }
[Inject] public required LoggedInModel LoggedInModel { get; set; }
private DxFormLayoutItem _weightFormLayoutItem;
public bool _btnSaveEnabled { get; set; }
//public bool LoadingPanelVisible { get; set; } = false;
public bool BtnSaveEnabled { get; set; }
private bool GetBtnSaveEnabled()
=> PalletItem.IsValidMeasuringValues(IsMeasurable) && !PalletItem.IsMeasured && (!MaxTrayQuantity.HasValue || PalletItem.TrayQuantity <= MaxTrayQuantity.Value);
protected override async Task OnInitializedAsync()
{
_btnSaveEnabled = PalletItem.IsValidMeasuringValues(IsMeasurable) && !PalletItem.IsMeasured;
BtnSaveEnabled = GetBtnSaveEnabled();// PalletItem.IsValidMeasuringValues(IsMeasurable) && !PalletItem.IsMeasured;
//((DxSpinEdit<double>)_weightFormLayoutItem.Template.Target).DisplayFormat = "N3";
await base.OnInitializedAsync();
@ -80,7 +85,8 @@
private async Task PalletItemSaveClick()
{
_btnSaveEnabled = false;
BtnSaveEnabled = false;
//LoadingPanelVisible = true;
if (AddOrUpdateSignalRTag == null) throw new Exception($"PalletItemComponent->PalletItemSaveClick(); AddOrUpdateSignalRTag == null");
@ -91,29 +97,38 @@
//else _logger.Error($"Sikertelen volt a raklap adatainak mentése!");
if (OnPalletItemSaved != null) await OnPalletItemSaved.Invoke(responseShippingItemPallet);
//LoadingPanelVisible = false;
}
protected async Task OnItemUpdating(string fieldName, object newValue, TPalletItem palletItem)
{
_btnSaveEnabled = false;
BtnSaveEnabled = false;
// if (SelectedOrderItem == null) return;
switch (fieldName)
{
case nameof(IMeasuringItemPalletBase.PalletWeight):
palletItem.PalletWeight = (double)newValue;
if (palletItem.PalletWeight < 0) palletItem.PalletWeight = 0;
break;
case nameof(IMeasuringItemPalletBase.TareWeight):
palletItem.TareWeight = (double)newValue;
break;
if (palletItem.TareWeight < 0) palletItem.TareWeight = 0;
break;
case nameof(IMeasuringItemPalletBase.TrayQuantity):
palletItem.TrayQuantity = (int)newValue;
break;
if (palletItem.TrayQuantity < 0) palletItem.TrayQuantity = 0;
//else if (MaxTrayQuantity.HasValue && palletItem.TrayQuantity > MaxTrayQuantity.Value) palletItem.TrayQuantity = MaxTrayQuantity.Value;
break;
case nameof(IMeasuringItemPalletBase.GrossWeight):
palletItem.GrossWeight = (double)newValue;
if (palletItem.GrossWeight < 0) palletItem.GrossWeight = 0;
break;
}
@ -121,7 +136,7 @@
//MeasuringValuesHelper.SetShippingItemTotalMeasuringValues(palletItem);
//BtnSaveEnabled = SelectedShippingItem.IsValidMeasuringValues() && shippingItemPallet.IsValidMeasuringValues(SelectedShippingItem.IsMeasurable);
_btnSaveEnabled = palletItem.IsValidMeasuringValues(IsMeasurable) && !palletItem.IsMeasured;
BtnSaveEnabled = GetBtnSaveEnabled();// palletItem.IsValidMeasuringValues(IsMeasurable) && !palletItem.IsMeasured && (MaxTrayQuantity.HasValue && palletItem.TrayQuantity <= MaxTrayQuantity.Value);
if (OnPalletItemValueChanged != null) await OnPalletItemValueChanged.Invoke(palletItem);
}

View File

@ -0,0 +1,20 @@
using DevExpress.Blazor;
using DevExpress.Blazor.Internal;
namespace FruitBankHybrid.Shared.Extensions;
public static class DevextremeComponentExtension
{
public static async Task ShowMessageBoxAsync(this IDialogService messageBox, string title, string text, MessageBoxRenderStyle messageBoxRenderStyle, MessageBoxType messageBoxType = MessageBoxType.Alert)
{
var messageBoxOptions = new MessageBoxOptions
{
Title = title,
Text = text,
RenderStyle = messageBoxRenderStyle,
};
if (messageBoxType == MessageBoxType.Alert) await messageBox.AlertAsync(messageBoxOptions);
else await messageBox.ConfirmAsync(messageBoxOptions);
}
}

View File

@ -8,7 +8,7 @@
{
<DxFormLayout CaptionPosition="CaptionPosition.Vertical" CssClass="w-500">
<DxFormLayoutItem Caption="Válasszon felhasználót:" ColSpanMd="6">
<DxComboBox Data="@Users"
<DxComboBox Data="@LoggedInModel.MeasuringUsers"
@bind-Value="@SelectedUser"
Text="Select Employee"
ValueFieldName="@nameof(CustomerDto.Id)"

View File

@ -21,7 +21,7 @@ public partial class Login : ComponentBase
[Inject] public required LoggedInModel LoggedInModel { get; set; }
private ILogger _logger = null!;
private List<CustomerDto> Users { get; set; }
//private List<CustomerDto> Users { get; set; }
private CustomerDto? SelectedUser { get; set; }
private string PasswordValue { get; set; } = string.Empty;
@ -37,8 +37,8 @@ public partial class Login : ComponentBase
if (!LoggedInModel.IsLoggedIn)
{
Users = await FruitBankSignalRClient.GetMeasuringUsers() ?? [];
SelectedUser = Users.FirstOrDefault();
LoggedInModel.MeasuringUsers = await FruitBankSignalRClient.GetMeasuringUsers() ?? [];
SelectedUser = LoggedInModel.MeasuringUsers.FirstOrDefault();
}
else _rolesText = string.Join("; ", LoggedInModel.CustomerRoles.Select(x => x.Name));

View File

@ -9,158 +9,198 @@
@using Nop.Core.Domain.Orders
<h3>Kimenő mérés</h3>
<DxDialogProvider />
<div style="margin-top: 50px;">
<DxFormLayout CaptionPosition="CaptionPosition.Vertical" CssClass="w-100">
<DxFormLayoutItem Caption="Átvétel dátuma" ColSpanMd="2"
CaptionCssClass="@(SelectedOrder != null && _measuringDates.Where(x => MeasuringService.DaysEqual(x.DateTime, SelectedOrder.DateOfReceiptOrCreated)).All(x => x.IsMeasured) ? "text-success" : "")">
<DxDateEdit CssClass="cw-320"
DisplayFormat="m"
Format="m"
Context="ctxOrderDate"
Date="@(SelectedOrder?.DateOfReceiptOrCreated.Date ?? DateTime.Now.Date)"
CustomDisabledDate="@OnCustomDisabledMeasuringDate"
DateChanged="@((DateTime newValue) => OnMeasuringDateChanged(newValue))"
InputId="deDisabledDates">
<DayCellTemplate>
@{
var cssClass = GetMeasuringDateCssClassNames(ctxOrderDate);
if (!cssClass.IsNullOrWhiteSpace())
{
<a class="@GetMeasuringDateCssClassNames(ctxOrderDate)">@ctxOrderDate.Day.ToString()</a>
}
else
{
<a>@ctxOrderDate.Day.ToString()</a>
}
}
<DxLoadingPanel @bind-Visible="LoadingPanelVisible"
IsContentBlocked="true"
ApplyBackgroundShading="true"
IndicatorAreaVisible="true"
IsContentVisible="true"
IndicatorAnimationType="WaitIndicatorAnimationType.Spin"
Text="Adatok betöltése...">
</DayCellTemplate>
</DxDateEdit>
</DxFormLayoutItem>
<DxFormLayoutItem Caption="Átvétel időpontja:" ColSpanMd="3" CaptionCssClass="@(SelectedOrder?.IsMeasured == true ? "text-success" : "")">
<DxComboBox Data="@SelectedDayOrders"
@bind-Value="@SelectedOrder"
Text="Válasszon időpontot..."
ValueFieldName="@nameof(OrderDto.Id)"
TextFieldName="@nameof(OrderDto.TimeOfReceiptText)"
CssClass="cw-480"
Context="ctxOrder"
DropDownBodyCssClass="dd-body-class"
SelectedDataItemChanged="@((SelectedDataItemChangedEventArgs<OrderDto> args) => OnSelectedOrderChanged(args))"
InputId="cbOrders">
<ItemDisplayTemplate>
<span class="@(ctxOrder.DataItem.IsMeasured ? "text-success" : "")">@ctxOrder.DisplayText</span>
</ItemDisplayTemplate>
</DxComboBox>
</DxFormLayoutItem>
<DxFormLayoutItem ColSpanMd="1"></DxFormLayoutItem>
@if (SelectedOrder != null && LoggedInModel.IsLoggedIn && LoggedInModel.CustomerRoles.Any(x => x.SystemName.ToLowerInvariant() == "measuringrevisor"))
{
var isCompleteOrder = SelectedOrder.OrderStatus == OrderStatus.Complete;
<DxFormLayoutItem Caption="Revizor:" ColSpanMd="3" CaptionCssClass="@(isCompleteOrder ? "text-success" : "")">
<DxButton Text="@(isCompleteOrder ? "Jóváhagyva" : "Mérés jóváhagyása")" Enabled="@(!isCompleteOrder && SelectedOrder.IsMeasured)" CssClass="w-100"
Click="() => OnMeasuringAuditorClick()"/>
</DxFormLayoutItem>
}
</DxFormLayout>
<div style="margin-top: 50px;">
<DxAccordion Data="@SelectedOrder?.OrderItemDtos"
ExpandMode="AccordionExpandMode.SingleOrNone"
ExpandCollapseAction="AccordionExpandCollapseAction.ExpandButtonClick"
AnimationType="LayoutAnimationType.Slide">
<DataMappings>
<DxAccordionDataMapping Text="ProductName"></DxAccordionDataMapping>
@* <DxAccordionDataMapping Text="OrderItemId" Level="1"></DxAccordionDataMapping> *@
</DataMappings>
<ItemHeaderTextTemplate>
@{
if (context.Level == 0)
{
var cssClass = "text-danger";
var selectedOrderItemDto = (OrderItemDto)(context.DataItem);
var trayQuantity = selectedOrderItemDto.TrayQuantity; //selectedOrderItemDto.OrderItemPallets.Where(x => x.IsMeasured).Sum(x => x.TrayQuantity);
var isValid = selectedOrderItemDto.IsValidMeasuringValues();
var isValidAndMeasured = isValid && selectedOrderItemDto.IsMeasuredAndValid();// && selectedOrderItemDto.;
if (isValidAndMeasured) cssClass = "text-success";
else if (isValid) cssClass = string.Empty;
<h5 class="@cssClass">@($"{selectedOrderItemDto.ProductName} - {trayQuantity}/{selectedOrderItemDto.Quantity} rekesz, {(selectedOrderItemDto.IsMeasurable ? "net súly: " + selectedOrderItemDto.NetWeight + "kg." : "nem mérendő!")}")</h5>
}
}
</ItemHeaderTextTemplate>
<ItemContentTemplate>
@{
if (context.Level == 0)
{
//var orderItemPallet = ((OrderItemPallet)(context.DataItem));
//text = ((OrderItemPallet)(context.DataItem)).OrderItemId.ToString() + " dfgdfsg";
//var selectedOrderItemDto = SelectedOrder!.OrderItemDtos.First(x => x.Id == orderItemPallet.OrderItemId);
var selectedOrderItemDto = (OrderItemDto)(context.DataItem);
<DxFormLayout Context="ctxFormLayout" Data="@selectedOrderItemDto" CaptionPosition="CaptionPosition.Vertical" CssClass="w-100">
<DxFormLayoutItem Context="ctxFormLayoutItem" ColSpanMd="12">
@for (var index = 0; index < (selectedOrderItemDto?.OrderItemPallets?.Count ?? 0); index++)
{
var localI = index + 1;
var currentOrderItemPallet = selectedOrderItemDto!.OrderItemPallets![index];
<PalletItemComponent IsMeasurable="@selectedOrderItemDto.IsMeasurable"
MeasuringIndex="@localI"
PalletItem="@currentOrderItemPallet"
ProductId="@selectedOrderItemDto.ProductId"
AddOrUpdateSignalRTag="SignalRTags.AddOrUpdateMeasuredOrderItemPallet"
OnPalletItemSaved="pallet => OnOrderItemPalletSaved(pallet, selectedOrderItemDto)"
OnPalletItemValueChanged="pallet => OnOrderItemPalletValueChanged(pallet, selectedOrderItemDto)">
</PalletItemComponent>
}
</DxFormLayoutItem>
<DxFormLayoutItem Context="ctxFromLayoutNewPallet" ColSpanMd="2" BeginRow="true">
<DxButton Text="Új mérés" Click="() => AddNewPalletItemClick(selectedOrderItemDto)" CssClass="w-100"
Enabled="@(selectedOrderItemDto.OrderItemPallets[^1].Id > 0)" />
</DxFormLayoutItem>
<DxFormLayoutItem Context="ctxFromLayoutNewPallet" ColSpanMd="2">
<DxButton Text="Utolsó mérés törlése" Click="() => LastPalletItemDeleteClick(selectedOrderItemDto)" CssClass="w-100"
Enabled="@(selectedOrderItemDto.OrderItemPallets.Count > 1 && selectedOrderItemDto.OrderItemPallets[^1].Id <= 0)" />
</DxFormLayoutItem>
<DxFormLayoutItem Context="ctxFromLayoutNewPallet" ColSpanMd="6" />
<DxFormLayoutItem Context="vfdfgfd" ColSpanMd="12" BeginRow="true">
<DxFormLayout CssClass="w-100" Context="dfcadsc">
<DxFormLayoutItem Context="dfcadsc2" ColSpanMd="1" BeginRow="false"><strong>TOTAL:</strong></DxFormLayoutItem>
<DxFormLayoutItem Context="dfcadsc2" ColSpanMd="2" BeginRow="false" />
<DxFormLayoutItem Context="dfcadsc2" ColSpanMd="2" BeginRow="false" />
<DxFormLayoutItem Context="dfcadsc2" ColSpanMd="1" BeginRow="false" />
<DxFormLayoutItem Context="dfcadsc2" ColSpanMd="2" BeginRow="false"><strong>@(selectedOrderItemDto.TrayQuantity) db</strong></DxFormLayoutItem>
<DxFormLayoutItem Context="dfcadsc2" ColSpanMd="2" BeginRow="false"><strong>@(selectedOrderItemDto.GrossWeight) kg</strong></DxFormLayoutItem>
<DxFormLayoutItem Context="dfcadsc2" ColSpanMd="1" BeginRow="false"><strong>@(selectedOrderItemDto.NetWeight) kg</strong></DxFormLayoutItem>
<DxFormLayoutItem Context="dfcadsc2" ColSpanMd="1" BeginRow="false" />
</DxFormLayout>
</DxFormLayoutItem>
@if (!_errorText.IsNullOrWhiteSpace())
<DxFormLayout CaptionPosition="CaptionPosition.Vertical" CssClass="w-100">
<DxFormLayoutItem Caption="Átvétel dátuma" ColSpanMd="2"
CaptionCssClass="@(SelectedOrder != null && _measuringDates.Where(x => MeasuringService.DaysEqual(x.DateTime, SelectedOrder.DateOfReceiptOrCreated)).All(x => x.IsMeasured) ? "text-success" : "")">
<DxDateEdit CssClass="cw-320"
DisplayFormat="m"
Format="m"
Context="ctxOrderDate"
Date="@(SelectedOrder?.DateOfReceiptOrCreated.Date ?? DateTime.Now.Date)"
CustomDisabledDate="@OnCustomDisabledMeasuringDate"
DateChanged="@((DateTime newValue) => OnMeasuringDateChanged(newValue))"
InputId="deDisabledDates">
<DayCellTemplate>
@{
var cssClass = GetMeasuringDateCssClassNames(ctxOrderDate);
if (!cssClass.IsNullOrWhiteSpace())
{
<DxFormLayoutItem Context="ctxFromLayoutItemError" ColSpanMd="12" BeginRow="true">
<text>HIBA! @_errorText</text>
</DxFormLayoutItem>
//_errorText = string.Empty;
<a class="@GetMeasuringDateCssClassNames(ctxOrderDate)">@ctxOrderDate.Day.ToString()</a>
}
</DxFormLayout>
<div style="margin-bottom: 20px;"></div>
}
}
</ItemContentTemplate>
</DxAccordion>
</div>
else
{
<a>@ctxOrderDate.Day.ToString()</a>
}
}
</DayCellTemplate>
</DxDateEdit>
</DxFormLayoutItem>
<DxFormLayoutItem Caption="Átvétel időpontja:" ColSpanMd="3" CaptionCssClass="@(SelectedOrder?.IsMeasured == true ? "text-success" : "")">
<DxComboBox Data="@SelectedDayOrders"
@bind-Value="@SelectedOrder"
Text="Válasszon időpontot..."
ValueFieldName="@nameof(OrderDto.Id)"
TextFieldName="@nameof(OrderDto.TimeOfReceiptText)"
CssClass="cw-480"
Context="ctxOrder"
DropDownBodyCssClass="dd-body-class"
SelectedDataItemChanged="@((SelectedDataItemChangedEventArgs<OrderDto> args) => OnSelectedOrderChanged(args))"
InputId="cbOrders">
<ItemDisplayTemplate>
<span class="@(ctxOrder.DataItem.IsMeasured ? "text-success" : "")">@ctxOrder.DisplayText</span>
</ItemDisplayTemplate>
<Buttons>
<DxEditorButton IconCssClass="editor-icon editor-icon-add" Text="R" Tooltip="Adatok frissítése..."
Click="() => OnOrdersRefreshClick()" />
</Buttons>
</DxComboBox>
</DxFormLayoutItem>
<DxFormLayoutItem ColSpanMd="2">
<DxButton Enabled="@(HasMeasuringAccess && SelectedOrder?.MeasurementOwnerId == 0)" Visible="@(SelectedOrder != null)" CssClass="w-100"
Text="@(HasMeasuringAccess && SelectedOrder?.MeasurementOwnerId == 0 ? "Mérés indítása" : "Mérés folyamatban...")"
Click="() => OnStartMeasuringClick()" />
</DxFormLayoutItem>
<DxFormLayoutItem ColSpanMd="1"></DxFormLayoutItem>
@if (SelectedOrder != null && LoggedInModel.IsRevisor)
{
var isCompleteOrder = SelectedOrder.IsComplete;
<DxFormLayoutItem Caption="Revizor:" ColSpanMd="2" CaptionCssClass="@(isCompleteOrder ? "text-success" : "")">
<DxButton Text="@(isCompleteOrder ? "Jóváhagyva" : "Mérés jóváhagyása")" Enabled="@(!isCompleteOrder && SelectedOrder.IsMeasured)" CssClass="w-100"
Click="() => OnMeasuringAuditorClick()" />
</DxFormLayoutItem>
}
</DxFormLayout>
@if (SelectedOrder == null)
{
}
else if (!HasMeasuringAccess)
{
@* var userIds = @SelectedOrder.OrderItemDtos.SelectMany(oi => oi.OrderItemPallets.Where(x => x.Id > 0 && x.CreatorId.HasValue).Select(x => x.CreatorId!.Value)).ToHashSet();
var a = string.Join("; ", LoggedInModel.MeasuringUsers.Where(x => userIds.Contains(x.Id)).Select(x => x.Email));
<span style="margin-top: 20px;">Mérést végzi: @a</span> *@
<span style="margin-top: 20px;">Mások végzik a mérést! Mérést végzi: @(LoggedInModel.MeasuringUsers.FirstOrDefault(x => x.Id == SelectedOrder.MeasurementOwnerId)?.Email)</span>
}
else
{
@* var userIds = @SelectedOrder.OrderItemDtos.SelectMany(oi => oi.OrderItemPallets.Where(x => x.Id > 0 && x.CreatorId.HasValue).Select(x => x.CreatorId!.Value)).ToHashSet();
var a = string.Join("; ", LoggedInModel.MeasuringUsers.Where(x => userIds.Contains(x.Id)).Select(x => x.Email));
<span style="margin-top: 20px;">Mérést végzi: @a</span> *@
<span style="margin-top: 20px;">Mérést végzi: @(LoggedInModel.MeasuringUsers.FirstOrDefault(x => x.Id == SelectedOrder.MeasurementOwnerId)?.Email)</span>
<div style="margin-top: 50px;">
<DxAccordion Data="@SelectedOrder?.OrderItemDtos" Enabled="@(HasMeasuringAccess && SelectedOrder?.MeasurementOwnerId > 0)"
ExpandMode="AccordionExpandMode.SingleOrNone"
ExpandCollapseAction="AccordionExpandCollapseAction.ExpandButtonClick"
AnimationType="LayoutAnimationType.Slide">
<DataMappings>
<DxAccordionDataMapping Text="ProductName"></DxAccordionDataMapping>
@* <DxAccordionDataMapping Text="OrderItemId" Level="1"></DxAccordionDataMapping> *@
</DataMappings>
<ItemHeaderTextTemplate>
@{
if (context.Level == 0)
{
var cssClass = "text-danger";
var selectedOrderItemDto = (OrderItemDto)(context.DataItem);
var trayQuantity = selectedOrderItemDto.TrayQuantity; //selectedOrderItemDto.OrderItemPallets.Where(x => x.IsMeasured).Sum(x => x.TrayQuantity);
var isValid = selectedOrderItemDto.IsValidMeasuringValues();
var isValidAndMeasured = isValid && selectedOrderItemDto.IsMeasuredAndValid(); // && selectedOrderItemDto.;
if (isValidAndMeasured) cssClass = "text-success";
else if (isValid) cssClass = string.Empty;
<h5 class="@cssClass">@($"{selectedOrderItemDto.ProductName} - {trayQuantity}/{selectedOrderItemDto.Quantity} rekesz, {(selectedOrderItemDto.IsMeasurable ? "net súly: " + selectedOrderItemDto.NetWeight + "kg." : "nem mérendő!")}")</h5>
}
}
</ItemHeaderTextTemplate>
<ItemContentTemplate>
@{
if (context.Level == 0)
{
//var orderItemPallet = ((OrderItemPallet)(context.DataItem));
//text = ((OrderItemPallet)(context.DataItem)).OrderItemId.ToString() + " dfgdfsg";
//var selectedOrderItemDto = SelectedOrder!.OrderItemDtos.First(x => x.Id == orderItemPallet.OrderItemId);
var selectedOrderItemDto = (OrderItemDto)(context.DataItem);
<DxFormLayout Context="ctxFormLayout" Data="@selectedOrderItemDto" CaptionPosition="CaptionPosition.Vertical" CssClass="w-100">
<DxFormLayoutItem Context="ctxFormLayoutItem" ColSpanMd="12">
@for (var index = 0; index < (selectedOrderItemDto?.OrderItemPallets?.Count ?? 0); index++)
{
var localI = index + 1;
var currentOrderItemPallet = selectedOrderItemDto!.OrderItemPallets![index];
<PalletItemComponent IsMeasurable="@selectedOrderItemDto.IsMeasurable"
MeasuringIndex="@localI"
PalletItem="@currentOrderItemPallet"
ProductId="@selectedOrderItemDto.ProductId"
MaxTrayQuantity="@selectedOrderItemDto.Quantity"
AddOrUpdateSignalRTag="SignalRTags.AddOrUpdateMeasuredOrderItemPallet"
OnPalletItemSaved="pallet => OnOrderItemPalletSaved(pallet, selectedOrderItemDto)"
OnPalletItemValueChanged="pallet => OnOrderItemPalletValueChanged(pallet, selectedOrderItemDto)">
</PalletItemComponent>
}
</DxFormLayoutItem>
<DxFormLayoutItem Context="ctxFromLayoutNewPallet" ColSpanMd="2" BeginRow="true">
<DxButton Text="Új mérés" Click="() => AddNewPalletItemClick(selectedOrderItemDto)" CssClass="w-100"
Enabled="@(selectedOrderItemDto.OrderItemPallets[^1].Id > 0)" />
</DxFormLayoutItem>
<DxFormLayoutItem Context="ctxFromLayoutNewPallet" ColSpanMd="2">
<DxButton Text="Utolsó mérés törlése" Click="() => LastPalletItemDeleteClick(selectedOrderItemDto)" CssClass="w-100"
Enabled="@(selectedOrderItemDto.OrderItemPallets.Count > 1 && selectedOrderItemDto.OrderItemPallets[^1].Id <= 0)" />
</DxFormLayoutItem>
<DxFormLayoutItem Context="ctxFromLayoutNewPallet" ColSpanMd="6" />
<DxFormLayoutItem Context="vfdfgfd" ColSpanMd="12" BeginRow="true">
<DxFormLayout CssClass="w-100" Context="dfcadsc">
<DxFormLayoutItem Context="dfcadsc2" ColSpanMd="1" BeginRow="false"><strong>TOTAL:</strong></DxFormLayoutItem>
<DxFormLayoutItem Context="dfcadsc2" ColSpanMd="2" BeginRow="false" />
<DxFormLayoutItem Context="dfcadsc2" ColSpanMd="2" BeginRow="false" />
<DxFormLayoutItem Context="dfcadsc2" ColSpanMd="1" BeginRow="false" />
<DxFormLayoutItem Context="dfcadsc2" ColSpanMd="2" BeginRow="false"><strong>@(selectedOrderItemDto.TrayQuantity) db</strong></DxFormLayoutItem>
<DxFormLayoutItem Context="dfcadsc2" ColSpanMd="2" BeginRow="false"><strong>@(selectedOrderItemDto.GrossWeight) kg</strong></DxFormLayoutItem>
<DxFormLayoutItem Context="dfcadsc2" ColSpanMd="1" BeginRow="false"><strong>@(selectedOrderItemDto.NetWeight) kg</strong></DxFormLayoutItem>
<DxFormLayoutItem Context="dfcadsc2" ColSpanMd="1" BeginRow="false" />
</DxFormLayout>
</DxFormLayoutItem>
@if (!_errorText.IsNullOrWhiteSpace())
{
<DxFormLayoutItem Context="ctxFromLayoutItemError" ColSpanMd="12" BeginRow="true">
<text>HIBA! @_errorText</text>
</DxFormLayoutItem>
//_errorText = string.Empty;
}
</DxFormLayout>
<div style="margin-bottom: 20px;"></div>
}
}
</ItemContentTemplate>
</DxAccordion>
</div>
}
</DxLoadingPanel>
</div>
@code {
}

View File

@ -17,6 +17,8 @@ using System.Threading.Tasks;
using FruitBank.Common.Helpers;
using FruitBank.Common.Interfaces;
using AyCode.Core.Extensions;
using FruitBankHybrid.Shared.Extensions;
using Mango.Nop.Core.Extensions;
using Nop.Core.Domain.Orders;
namespace FruitBankHybrid.Shared.Pages
@ -25,11 +27,16 @@ namespace FruitBankHybrid.Shared.Pages
{
[Inject] public required IEnumerable<IAcLogWriterClientBase> LogWriters { get; set; }
[Inject] public required FruitBankSignalRClient FruitBankSignalRClient { get; set; }
[Inject] private IDialogService DialogService { get; set; } = null!;
[Inject] public required LoggedInModel LoggedInModel { get; set; }
private ILogger _logger = null!;
private string _errorText;
public bool HasMeasuringAccess;
public bool LoadingPanelVisible { get; set; } = true;
private List<OrderDto> SelectedDayOrders { get; set; } = null!;
private OrderDto? SelectedOrder { get; set; }
private OrderItemDto? SelectedOrderItem { get; set; }
@ -38,6 +45,7 @@ namespace FruitBankHybrid.Shared.Pages
protected override async Task OnInitializedAsync()
{
LoadingPanelVisible = true;
_logger = new LoggerClient<MeasuringOut>(LogWriters.ToArray());
_logger.Info("OnInitializedAsync");
@ -47,17 +55,21 @@ namespace FruitBankHybrid.Shared.Pages
private async Task RefreshOrdersFromDb(DateTime dateTime)
{
var orders = await FruitBankSignalRClient.GetPendingOrderDtos() ?? [];
LoadingPanelVisible = true;
var orders = (await FruitBankSignalRClient.GetPendingOrderDtos() ?? []).Where(o => o.HasMeasuringAccess(LoggedInModel.CustomerDto?.Id, LoggedInModel.IsRevisor)).ToList();
_measuringDates = orders.Select(order => new MeasuringDateSelectorModel(order.Id, order.DateOfReceiptOrCreated, order.IsMeasured)).ToList();
SelectedDayOrders = orders.Where(order => MeasuringService.DaysEqual(order.DateOfReceiptOrCreated, dateTime)).ToList();
SelectedOrder = SelectedDayOrders.FirstOrDefault();
foreach (var orderItem in SelectedDayOrders.SelectMany(order => order.OrderItemDtos.Where(orderItem => orderItem.OrderItemPallets.Count == 0)))
{
orderItem.OrderItemPallets.Add(MeasuringService.CreateNewOrderItemPallet(orderItem, LoggedInModel.CustomerDto));
}
foreach (var orderDto in SelectedDayOrders) PrepareOrderDto(orderDto);
SelectedOrder = LoggedInModel.IsRevisor
? SelectedDayOrders.FirstOrDefault(o => o is { IsComplete: false, IsMeasured: true })
: SelectedDayOrders.FirstOrDefault(o => o.MeasurementOwnerId == 0 || (o.MeasurementOwnerId == (LoggedInModel.CustomerDto?.Id ?? 0) && !o.IsMeasured));
SelectedOrder ??= SelectedDayOrders.FirstOrDefault();
LoadingPanelVisible = false;
}
private async Task OnMeasuringDateChanged(DateTime selectedDateTime)
@ -75,9 +87,36 @@ namespace FruitBankHybrid.Shared.Pages
private bool IsOrderItemPalletMeasuredAndValid(OrderItemPallet orderItemPallet)
=> MeasuringService.IsCustomItemPalletMeasuredAndValid(orderItemPallet, orderItemPallet.OrderItemDto!.IsMeasurable);
private void OnSelectedOrderChanged(SelectedDataItemChangedEventArgs<OrderDto> eventArgs)
private async Task OnSelectedOrderChanged(SelectedDataItemChangedEventArgs<OrderDto> eventArgs)
{
//SelectedOrderItem = eventArgs.DataItem?.OrderItemDtos?.FirstOrDefault();
//var orderDtosFromDb = await FruitBankSignalRClient.GetPendingOrderDtos();
//if (orderDtosFromDb != null) RefreshOrderGenericAttributes(orderDtosFromDb, SelectedDayOrders);
//else MessageBox.ShowMessageBox("Hiba", "Az adatok letöltése sikertelen!", MessageBoxRenderStyle.Danger);
var orderDto = eventArgs.DataItem;
if (orderDto != null)
{
var orderFromDb = await FruitBankSignalRClient.GetOrderDtoById(orderDto.Id);
if (orderFromDb != null)
{
orderDto.OrderStatus = orderFromDb.OrderStatus;
orderDto.GenericAttributes.UpdateBaseEntityCollection(orderFromDb.GenericAttributes, false);
if (LoggedInModel.IsRevisor)
{
var orderItemPalletsByOrderId = orderFromDb.OrderItemDtos.Where(o => o.OrderItemPallets.Count > 0).ToDictionary(k => k.Id, v => v.OrderItemPallets);
foreach (var orderItemDto in orderDto.OrderItemDtos)
{
if (orderItemPalletsByOrderId.TryGetValue(orderDto.Id, out var orderItemPallets))
orderItemDto.OrderItemPallets.UpdateCollection(orderItemPallets, false);
}
}
}
}
HasMeasuringAccess = orderDto?.HasMeasuringAccess(LoggedInModel.CustomerDto?.Id, LoggedInModel.IsRevisor) ?? false;
if (!HasMeasuringAccess) await DialogService.ShowMessageBoxAsync("Információ", "A mérés már folyamatban, válasszon másik rendelést", MessageBoxRenderStyle.Info);
}
private Task OnOrderItemPalletValueChanged(OrderItemPallet orderItemPallet, OrderItemDto selectedOrderItemDto)
@ -123,13 +162,36 @@ namespace FruitBankHybrid.Shared.Pages
return Task.CompletedTask;
}
private async Task OnMeasuringAuditorClick()
private async Task OnOrdersRefreshClick()
=> await RefreshOrdersFromDb(SelectedDayOrders.FirstOrDefault()?.DateOfReceiptOrCreated ?? DateTime.Now);
private async Task OnStartMeasuringClick()
{
if (SelectedOrder != null && SelectedOrder.IsMeasured && SelectedOrder.OrderStatus != OrderStatus.Complete)
if (SelectedOrder != null && LoggedInModel.IsLoggedIn && SelectedOrder.MeasurementOwnerId == 0)
{
var responseOrderDto = await FruitBankSignalRClient.SetOrderStatusToComplete(SelectedOrder.Id);
var responseOrderDto = await FruitBankSignalRClient.StartMeasuring(SelectedOrder.Id, LoggedInModel.CustomerDto!.Id);
if (responseOrderDto != null)
{
PrepareOrderDto(responseOrderDto);
//SelectedOrder.GenericAttributes.UpdateBaseEntityCollection(responseOrderDto.GenericAttributes, false);
SelectedDayOrders.UpdateCollection(responseOrderDto, false);
SelectedOrder = responseOrderDto;
}
StateHasChanged();
}
}
private async Task OnMeasuringAuditorClick()
{
if (SelectedOrder != null && LoggedInModel.IsRevisor && SelectedOrder.IsMeasured && SelectedOrder.OrderStatus != OrderStatus.Complete)
{
var responseOrderDto = await FruitBankSignalRClient.SetOrderStatusToComplete(SelectedOrder.Id, LoggedInModel.CustomerDto!.Id);
if (responseOrderDto != null)
{
PrepareOrderDto(responseOrderDto);
SelectedDayOrders.UpdateCollection(responseOrderDto, false);
SelectedOrder = responseOrderDto;
}
@ -138,5 +200,23 @@ namespace FruitBankHybrid.Shared.Pages
}
}
private void PrepareOrderDto(OrderDto orderDto)
{
foreach (var orderItemDto in orderDto.OrderItemDtos.Where(orderItem => orderItem.OrderItemPallets.Count == 0))
{
orderItemDto.OrderItemPallets.Add(MeasuringService.CreateNewOrderItemPallet(orderItemDto, LoggedInModel.CustomerDto));
}
}
private static void RefreshOrderGenericAttributes(List<OrderDto> srcOrderDtos, List<OrderDto> destOrderDtos)
{
var orderAttributesByOrderId = srcOrderDtos.Where(o => o.GenericAttributes.Count > 0).ToDictionary(k => k.Id, v => v.GenericAttributes);
foreach (var orderDto in destOrderDtos)
{
if (orderAttributesByOrderId.TryGetValue(orderDto.Id, out var genericAttributes))
orderDto.GenericAttributes.UpdateBaseEntityCollection(genericAttributes, false);
}
}
}
}

View File

@ -17,11 +17,13 @@ public class MeasuringService
public static bool DaysEqual(DateTime date1, DateTime date2)
=> (date1.Year == date2.Year && date1.DayOfYear == date2.DayOfYear);
public static void OnCustomDisabledDate(CalendarCustomDisabledDateEventArgs args, List<MeasuringDateSelectorModel> measuringDates)
public static void OnCustomDisabledDate(CalendarCustomDisabledDateEventArgs args, List<MeasuringDateSelectorModel>? measuringDates)
=> args.IsDisabled = measuringDates == null || !measuringDates.Exists(shippingDateModel => DaysEqual(shippingDateModel.DateTime, args.Date));
public static string GetShippingDateCssClassNames(DateTime date, List<MeasuringDateSelectorModel> measuringDates)
public static string GetShippingDateCssClassNames(DateTime date, List<MeasuringDateSelectorModel>? measuringDates)
{
if (measuringDates == null) return string.Empty;
if (measuringDates.Exists(shipping => !shipping.IsMeasured && shipping.DateTime.Date <= DateTime.Now.Date && DaysEqual(shipping.DateTime, date)))
return "fw-bold text-danger";

View File

@ -143,8 +143,11 @@ namespace FruitBankHybrid.Shared.Services.SignalRs
public Task<OrderItemPallet?> AddOrUpdateMeasuredOrderItemPallet(OrderItemPallet orderItemPallet)
=> PostDataAsync(SignalRTags.AddOrUpdateMeasuredOrderItemPallet, orderItemPallet);
public Task<OrderDto?> SetOrderStatusToComplete(int orderId)
=> GetByIdAsync<OrderDto>(SignalRTags.SetOrderStatusToComplete, orderId);
public Task<OrderDto?> StartMeasuring(int orderId, int userId)
=> GetByIdAsync<OrderDto>(SignalRTags.StartMeasuring, [orderId, userId]);
public Task<OrderDto?> SetOrderStatusToComplete(int orderId, int revisorId)
=> GetByIdAsync<OrderDto>(SignalRTags.SetOrderStatusToComplete, [orderId, revisorId]);
#endregion Orders
}