* Introduced Marelli packing list
This commit is contained in:
@@ -0,0 +1,568 @@
|
||||
@page "/Warehouse/Meyle/PackList/{WzHeader:guid}"
|
||||
|
||||
@using OrdersManagement.Models
|
||||
@using Syncfusion.Blazor.Cards
|
||||
@using Syncfusion.Blazor.Grids
|
||||
@using SytelineSaAppEfDataModel.Dtos
|
||||
@using Syncfusion.Blazor.Navigations
|
||||
@using Syncfusion.Blazor.Popups
|
||||
@using Syncfusion.Blazor.Inputs
|
||||
@using FilterType = Syncfusion.Blazor.Grids.FilterType
|
||||
@using Syncfusion.Blazor.Buttons
|
||||
@using SelectionType = Syncfusion.Blazor.Grids.SelectionType
|
||||
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject WarehouseService WarehouseService
|
||||
|
||||
<div class="h-100 d-flex justify-content-center align-items-start">
|
||||
<SfCard CssClass="shadow" style="width: 100%; max-width: 1200px;">
|
||||
<CardHeader>
|
||||
<h3 class="text-primary">Packing List</h3>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<SfCard CssClass="shadow" style="width: 100%; max-width: 1200px;">
|
||||
<CardContent>
|
||||
<SfButton CssClass="e-primary" IsPrimary="true" @onclick="ChangeView">Zmień widok</SfButton>
|
||||
</CardContent>
|
||||
</SfCard>
|
||||
<SfCard CssClass="shadow" style="width: 100%; max-width: 1200px;">
|
||||
<CardContent>
|
||||
<label for="textBox" class="form-label">Adresy Email do Wysyłki raportu:</label>
|
||||
<SfTextBox ID="textBox" Placeholder="Wprowadź adresy..." @bind-Value="@EmailAddresses"
|
||||
CssClass="e-outline"/>
|
||||
</CardContent>
|
||||
</SfCard>
|
||||
<SfCard CssClass="shadow" style="width: 100%; max-width: 1200px;">
|
||||
<CardContent>
|
||||
<label for="textBox" class="form-label">Numer WZ:</label>
|
||||
<SfTextBox ID="textBox" @bind-Value=@WzNumber CssClass="e-outline"/>
|
||||
</CardContent>
|
||||
</SfCard>
|
||||
<SfCard CssClass="shadow" style="width: 100%; max-width: 1200px;">
|
||||
<CardContent>
|
||||
<label for="textBox" class="form-label">Wprowadź numer palety:</label>
|
||||
<SfTextBox ID="palletNumber" Type="InputType.Number" @bind-Value="@PalletNumber"
|
||||
CssClass="e-outline"/>
|
||||
<label for="textBox" class="form-label">Zeskanowana wartość:</label>
|
||||
<SfTextBox ID="scannedValue" ValueChange="ScanValue" @bind-Value="ScannedValue"
|
||||
CssClass="e-outline" @ref="_scanner"/>
|
||||
</CardContent>
|
||||
</SfCard>
|
||||
<SfGrid @ref="_grid"
|
||||
AllowFiltering="true"
|
||||
AllowPaging="true"
|
||||
AllowSorting="true"
|
||||
AllowSelection="true"
|
||||
TValue="WzRowMeyleDto"
|
||||
DataSource="@WzRowsMeyle"
|
||||
EnableAdaptiveUI="true">
|
||||
<SfToolbar>
|
||||
<ToolbarItems>
|
||||
<ToolbarItem Type="ItemType.Button" Text="Zapisz zmiany" Id="SaveButton"
|
||||
PrefixIcon="e-icons e-save" OnClick="SaveChanges"/>
|
||||
<ToolbarItem Type="ItemType.Button" Text="Podziel Linię" Id="SplitLineButton"
|
||||
PrefixIcon="e-icons e-split-horizontal" OnClick="ShowSplitDialog"
|
||||
Disabled="IsDisabled"/>
|
||||
<ToolbarItem Type="ItemType.Button" Id="Generuj XLS i Wyślij" PrefixIcon="e-icons e-export-xls"
|
||||
Text="Generuj XLS i Wyślij" OnClick="ExportXls"/>
|
||||
</ToolbarItems>
|
||||
</SfToolbar>
|
||||
<GridColumns>
|
||||
<GridColumn Field=@nameof(WzRowMeyleDto.ID) IsPrimaryKey="true" Visible="false" AllowEditing="false"
|
||||
TextAlign="TextAlign.Center" HeaderText="ID" Width="70"></GridColumn>
|
||||
<GridColumn Field=@nameof(WzRowMeyleDto.OrderNumber) AllowEditing="false"
|
||||
TextAlign="TextAlign.Center" HeaderText="Numer Zamówienia Meyle"
|
||||
Width="70"></GridColumn>
|
||||
<GridColumn Field=@nameof(WzRowMeyleDto.FaIndex) AllowEditing="false" AllowFiltering="true"
|
||||
TextAlign="TextAlign.Center" HeaderText="Numer Indeksu FA" Width="100"></GridColumn>
|
||||
<GridColumn Field=@nameof(WzRowMeyleDto.ItemNumber) AllowEditing="false"
|
||||
TextAlign="TextAlign.Center" HeaderText="Numer Indeksu Meyle" Width="100"></GridColumn>
|
||||
<GridColumn Field=@nameof(WzRowMeyleDto.Quantity) AllowEditing="false" TextAlign="TextAlign.Center"
|
||||
HeaderText="Ilość w Dostawie" Width="80"></GridColumn>
|
||||
<GridColumn Field=@nameof(WzRowMeyleDto.PalletNumber) AllowEditing="true"
|
||||
TextAlign="TextAlign.Center" HeaderText="Nr Palety" Width="100"></GridColumn>
|
||||
<GridColumn Field=@nameof(WzRowMeyleDto.PartNumberSl) AllowEditing="true"
|
||||
TextAlign="TextAlign.Center"
|
||||
HeaderText="Nr Partii SL" Width="80"></GridColumn>
|
||||
<GridColumn Field=@nameof(WzRowMeyleDto.PartNumber) AllowEditing="true" TextAlign="TextAlign.Center"
|
||||
HeaderText="Nr Partii Meyle" Width="80"></GridColumn>
|
||||
</GridColumns>
|
||||
<GridEditSettings AllowDeleting="false"
|
||||
AllowAdding="false"
|
||||
AllowEditing="true"
|
||||
AllowNextRowEdit="true"
|
||||
AllowEditOnDblClick="true"
|
||||
ShowConfirmDialog="false"
|
||||
Mode="EditMode.Batch">
|
||||
</GridEditSettings>
|
||||
<GridFilterSettings Type="FilterType.Excel"/>
|
||||
<GridPageSettings PageSize="10"/>
|
||||
<GridSelectionSettings Mode="SelectionMode.Row" Type="SelectionType.Single"/>
|
||||
<GridEvents RowSelected="OnRowSelected" OnBatchSave="OnBatchSave" TValue="WzRowMeyleDto"></GridEvents>
|
||||
</SfGrid>
|
||||
</CardContent>
|
||||
|
||||
<SfDialog Width="500px" Title="Informacja" IsModal="true" @bind-Visible="Visibility" AllowPrerender="true">
|
||||
<DialogTemplates>
|
||||
<Content>
|
||||
@if (_isValid)
|
||||
{
|
||||
<p>Packing List został wygenerowany i wysłany!</p>
|
||||
}
|
||||
else if (string.IsNullOrWhiteSpace(EmailAddresses))
|
||||
{
|
||||
<p>Błąd: Proszę wprowadzić przynajmniej jeden <b>ADRES EMAIL</b> do wysyłki raportu!</p>
|
||||
}
|
||||
else if (!_isValid)
|
||||
{
|
||||
<p>Błąd: Nie Wszystkie linie mają wypełniony <b>NUMER PALETY</b>.<br/>Packing List nie zostanie
|
||||
wygenerowany!</p>
|
||||
}
|
||||
</Content>
|
||||
</DialogTemplates>
|
||||
<DialogButtons>
|
||||
<DialogButton Content="OK" IsPrimary="true" OnClick="@HideModal"/>
|
||||
</DialogButtons>
|
||||
</SfDialog>
|
||||
|
||||
<SfDialog Width="500px" Title="Błąd" IsModal="true" @bind-Visible="VisibilityValidation" AllowPrerender="true">
|
||||
<DialogTemplates>
|
||||
<Content>
|
||||
<p>Błąd skanowania! Wystąpił jeden z wyjątków (Zeskanowana wartość '<b>@ScannedValue</b>'):</p>
|
||||
<ul>
|
||||
<li><p>Zeskanowano niepoprawny Numer Partii SL (nieistniejący w tabeli)</p></li>
|
||||
<li><p>Zeskanowano niepoprawny numer Partii Meyle (niezaczynający się od
|
||||
<b>@($"{DateTime.Now.Year - 2000}X")</b>)</p></li>
|
||||
<li><p>Numer Palety nie jest większy niż 0 (aktualnie wybrany numer palety:
|
||||
'<b>@PalletNumber</b>')</p></li>
|
||||
</ul>
|
||||
</Content>
|
||||
</DialogTemplates>
|
||||
<DialogButtons>
|
||||
<DialogButton Content="OK" IsPrimary="true" OnClick="@HideModal"/>
|
||||
</DialogButtons>
|
||||
</SfDialog>
|
||||
|
||||
<SfDialog Width="500px" Title="Błąd" IsModal="true" @bind-Visible="VisibilityPalletNumber"
|
||||
AllowPrerender="true">
|
||||
<DialogTemplates>
|
||||
<Content>
|
||||
<p>Błąd skanowania! <b>Wybierz NUMER PALETY większy niż 0</b> (Aktualnie '@PalletNumber'):</p>
|
||||
</Content>
|
||||
</DialogTemplates>
|
||||
<DialogButtons>
|
||||
<DialogButton Content="OK" IsPrimary="true" OnClick="@HideModal"/>
|
||||
</DialogButtons>
|
||||
</SfDialog>
|
||||
|
||||
<SfDialog Width="500px" Title="Podziel Linię" IsModal="true" @bind-Visible="VisibilityLineSplitter"
|
||||
AllowPrerender="true">
|
||||
<DialogTemplates>
|
||||
<Content>
|
||||
<label for="textBox" class="form-label">Podziel linię <b>@SelectedRow?.FaIndex</b> podając ilość
|
||||
sztuk dla nowej linii:</label>
|
||||
<SfTextBox ID="newQuantity" Type="InputType.Number" @bind-Value="@NewQuantity"
|
||||
CssClass="e-outline"/>
|
||||
</Content>
|
||||
</DialogTemplates>
|
||||
<DialogButtons>
|
||||
<DialogButton Content="Zapisz" IsPrimary="true" OnClick="@SplitLine"/>
|
||||
<DialogButton Content="Anuluj" OnClick="@HideModal"></DialogButton>
|
||||
</DialogButtons>
|
||||
</SfDialog>
|
||||
|
||||
<CardFooter>
|
||||
<small class="text-muted">FA Krosno Manager © @(DateTime.Now.Year)</small>
|
||||
</CardFooter>
|
||||
</SfCard>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter] public Guid WzHeader { get; set; }
|
||||
|
||||
private SfGrid<WzRowMeyleDto> _grid;
|
||||
private List<WzRowMeyleDto> WzRowsMeyle { get; set; } = new();
|
||||
private IDictionary<string, List<TransactionModel>> TransactionModelsByPartNumber { get; set; } = new Dictionary<string, List<TransactionModel>>();
|
||||
private List<WzRowMeyleDto> ChangedRecords = new();
|
||||
private WzHeaderDto _wzHeader;
|
||||
private SfTextBox _scanner;
|
||||
|
||||
private WzRowMeyleDto? SelectedRow { get; set; }
|
||||
private List<WzRowMeyleDto> SelectedRows { get; set; } = new();
|
||||
|
||||
private string WzNumber { get; set; } = string.Empty;
|
||||
|
||||
private bool _isValid;
|
||||
|
||||
private bool Visibility { get; set; }
|
||||
private bool VisibilityValidation { get; set; }
|
||||
private bool VisibilityLineSplitter { get; set; }
|
||||
public bool VisibilityPalletNumber { get; set; }
|
||||
|
||||
private string? EmailAddresses { get; set; } = string.Empty;
|
||||
private string PalletNumber { get; set; } = "0";
|
||||
|
||||
private string LastScannedValue { get; set; } = string.Empty;
|
||||
private string ScannedValue { get; set; } = string.Empty;
|
||||
|
||||
private string NewQuantity { get; set; } = "0";
|
||||
|
||||
private bool IsDisabled => SelectedRow == null;
|
||||
|
||||
private void HideModal()
|
||||
{
|
||||
Visibility = false;
|
||||
VisibilityValidation = false;
|
||||
VisibilityLineSplitter = false;
|
||||
VisibilityPalletNumber = false;
|
||||
|
||||
LastScannedValue = ScannedValue;
|
||||
ScannedValue = string.Empty;
|
||||
|
||||
_scanner.FocusAsync();
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
_wzHeader = await WarehouseService.GetWzHeaderByIdAsync(WzHeader);
|
||||
WzRowsMeyle = (await WarehouseService.GetWzRowsByWzHeaderId(WzHeader)).ToList();
|
||||
|
||||
TransactionModelsByPartNumber = await GetTransactionModels();
|
||||
|
||||
EmailAddresses = _wzHeader.EmailAddresses;
|
||||
|
||||
WzNumber = _wzHeader.WzNumbers ?? string.Empty;
|
||||
|
||||
await _scanner.FocusAsync();
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveChanges()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(EmailAddresses))
|
||||
{
|
||||
await WarehouseService.AddEmailsToWzHeaderAsync(WzHeader, EmailAddresses);
|
||||
}
|
||||
|
||||
if (ChangedRecords.Any())
|
||||
{
|
||||
await UpdateRows(ChangedRecords);
|
||||
}
|
||||
|
||||
await _grid.EndEditAsync();
|
||||
}
|
||||
|
||||
private async Task OnBatchSave(BeforeBatchSaveArgs<WzRowMeyleDto> obj)
|
||||
{
|
||||
var changes = obj.BatchChanges;
|
||||
List<WzRowMeyleDto> changedRecords = changes.ChangedRecords;
|
||||
|
||||
if (!changedRecords.Any()) return;
|
||||
|
||||
await UpdateRows(changedRecords);
|
||||
}
|
||||
|
||||
private async Task ExportXls()
|
||||
{
|
||||
int count = WzRowsMeyle.Count(x => x.PalletNumber == null);
|
||||
|
||||
_isValid = count == 0;
|
||||
_isValid = _isValid && !string.IsNullOrWhiteSpace(EmailAddresses);
|
||||
|
||||
if (_isValid)
|
||||
{
|
||||
await WarehouseService.AddEmailsToWzHeaderAsync(WzHeader, EmailAddresses);
|
||||
await WarehouseService.GenerateXlsForMeyleAsync(WzHeader);
|
||||
}
|
||||
|
||||
Visibility = true;
|
||||
}
|
||||
|
||||
private void ScanValue(ChangedEventArgs obj)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(obj.Value)) return;
|
||||
if (int.Parse(PalletNumber) <= 0)
|
||||
{
|
||||
VisibilityPalletNumber = true;
|
||||
return;
|
||||
}
|
||||
|
||||
ScannedValue = obj.Value.Trim();
|
||||
|
||||
StateHasChanged();
|
||||
|
||||
TransactionModelsByPartNumber.TryGetValue(obj.Value.Trim(), out List<TransactionModel>? materialTransactionsByPartNumber);
|
||||
TransactionModel? materialTransactionByPartNumber = materialTransactionsByPartNumber?.FirstOrDefault();
|
||||
|
||||
if (materialTransactionByPartNumber == null && IsValidScannedValue(obj.Value))
|
||||
{
|
||||
FillMeylePartNumber(ScannedValue);
|
||||
|
||||
LastScannedValue = ScannedValue;
|
||||
ScannedValue = string.Empty;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_grid.Query = null;
|
||||
_grid.ClearFilteringAsync();
|
||||
|
||||
if (materialTransactionByPartNumber != null)
|
||||
{
|
||||
SelectedRows.Clear();
|
||||
FillFaPartNumberAndPalletNumber(materialTransactionByPartNumber, obj.Value.Trim());
|
||||
}
|
||||
|
||||
if (materialTransactionByPartNumber == null)
|
||||
{
|
||||
ShowValidationMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
LastScannedValue = ScannedValue;
|
||||
ScannedValue = string.Empty;
|
||||
|
||||
_scanner.FocusAsync();
|
||||
}
|
||||
|
||||
private bool IsValidScannedValue(string scannedValue)
|
||||
{
|
||||
int year = DateTime.Now.Year - 2000;
|
||||
|
||||
string format = $"{year}X";
|
||||
|
||||
return scannedValue.StartsWith(format);
|
||||
}
|
||||
|
||||
private async Task FillMeylePartNumber(string scannedValue)
|
||||
{
|
||||
var rowIndex = WzRowsMeyle.FindIndex(x => x.FaIndex == SelectedRow?.FaIndex && x.Quantity == SelectedRow?.Quantity);
|
||||
|
||||
if (SelectedRow != null && !SelectedRows.Any())
|
||||
{
|
||||
SelectedRow.PartNumber = scannedValue;
|
||||
ChangedRecords.Add(SelectedRow);
|
||||
}
|
||||
|
||||
foreach (WzRowMeyleDto wzRowMeyleDto in SelectedRows)
|
||||
{
|
||||
wzRowMeyleDto.PartNumber = scannedValue;
|
||||
ChangedRecords.Add(wzRowMeyleDto);
|
||||
}
|
||||
|
||||
await SaveChanges();
|
||||
|
||||
ChangedRecords.Clear();
|
||||
SelectedRows.Clear();
|
||||
|
||||
FocusGridRow(rowIndex);
|
||||
await _scanner.FocusAsync();
|
||||
}
|
||||
|
||||
private async Task FillFaPartNumberAndPalletNumber(TransactionModel materialTransactionByPartNumber, string scannedValue)
|
||||
{
|
||||
await _grid.ClearSelectionAsync();
|
||||
await _grid.Refresh();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
|
||||
List<int> selectedIndices = new List<int>();
|
||||
int palletNumber = int.Parse(PalletNumber);
|
||||
int rowIndex = WzRowsMeyle.FindIndex(x => x.FaIndex == materialTransactionByPartNumber.ItemNumber && x.Quantity == materialTransactionByPartNumber.Quantity);
|
||||
|
||||
switch (rowIndex)
|
||||
{
|
||||
case -1:
|
||||
{
|
||||
SelectedRows = WzRowsMeyle.Where(x => x.FaIndex == materialTransactionByPartNumber.ItemNumber).ToList();
|
||||
|
||||
if (SelectedRows.Count == 0)
|
||||
{
|
||||
ShowValidationMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
rowIndex = WzRowsMeyle.FindIndex(x => x.FaIndex == SelectedRows.First().FaIndex && x.Quantity == SelectedRows.First().Quantity);
|
||||
|
||||
var validCombinations = FindCombinations(SelectedRows, (int?)materialTransactionByPartNumber.Quantity ?? 0);
|
||||
|
||||
foreach (var combination in validCombinations)
|
||||
{
|
||||
foreach (var record in combination)
|
||||
{
|
||||
record.PartNumberSl = scannedValue;
|
||||
record.PalletNumber = palletNumber;
|
||||
ChangedRecords.Add(record);
|
||||
|
||||
int index = WzRowsMeyle.IndexOf(record);
|
||||
|
||||
if (index >= 0)
|
||||
{
|
||||
selectedIndices.Add(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SelectedRows.Clear();
|
||||
SelectedRows.AddRange(ChangedRecords);
|
||||
|
||||
SelectedRow = SelectedRows.FirstOrDefault();
|
||||
|
||||
await ApplyFilter(ChangedRecords);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
SelectedRow = WzRowsMeyle[rowIndex];
|
||||
selectedIndices.Add(rowIndex);
|
||||
|
||||
SelectedRow.PartNumberSl = scannedValue;
|
||||
SelectedRow.PalletNumber = palletNumber;
|
||||
|
||||
if (ChangedRecords.All(x => x.TransactionNumber != SelectedRow.TransactionNumber))
|
||||
{
|
||||
ChangedRecords.Add(SelectedRow);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
await SaveChanges();
|
||||
ChangedRecords.Clear();
|
||||
|
||||
if (selectedIndices.Any())
|
||||
{
|
||||
await _grid.SelectRowsAsync(selectedIndices.ToArray());
|
||||
}
|
||||
|
||||
await _grid.Refresh();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
|
||||
FocusGridRow(rowIndex);
|
||||
await _scanner.FocusAsync();
|
||||
}
|
||||
|
||||
private void FocusGridRow(int rowIndex)
|
||||
{
|
||||
if (_grid.AllowPaging)
|
||||
{
|
||||
int pageSize = _grid.PageSettings.PageSize;
|
||||
int targetPage = (rowIndex / pageSize) + 1;
|
||||
_grid.GoToPageAsync(targetPage);
|
||||
|
||||
rowIndex %= pageSize;
|
||||
}
|
||||
|
||||
_grid.SelectRowAsync(rowIndex);
|
||||
_grid.ScrollIntoViewAsync(rowIndex: rowIndex);
|
||||
_grid.FocusAsync();
|
||||
}
|
||||
|
||||
private void ShowValidationMessage()
|
||||
{
|
||||
VisibilityValidation = true;
|
||||
|
||||
ChangedRecords.Clear();
|
||||
_scanner.FocusAsync();
|
||||
}
|
||||
|
||||
private async Task<IDictionary<string, List<TransactionModel>>> GetTransactionModels()
|
||||
{
|
||||
return await WarehouseService.GetTransactionsModels();
|
||||
}
|
||||
|
||||
private async Task UpdateRows(IList<WzRowMeyleDto> changedRecords)
|
||||
{
|
||||
await WarehouseService.UpdateWzRowsMeyleAsync(changedRecords);
|
||||
|
||||
WzRowsMeyle = (await WarehouseService.GetWzRowsByWzHeaderId(WzHeader)).ToList();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
await _grid.Refresh();
|
||||
}
|
||||
|
||||
private async Task SplitLine(MouseEventArgs arg)
|
||||
{
|
||||
int newQuantity = int.Parse(NewQuantity);
|
||||
|
||||
if (newQuantity > 0 && SelectedRow != null)
|
||||
{
|
||||
WzRowMeyleDto splitRow = new WzRowMeyleDto
|
||||
{
|
||||
ID = Guid.NewGuid(),
|
||||
FK_Header = SelectedRow.FK_Header,
|
||||
Quantity = newQuantity,
|
||||
FaIndex = SelectedRow.FaIndex,
|
||||
ItemNumber = SelectedRow.ItemNumber,
|
||||
OrderNumber = SelectedRow.OrderNumber,
|
||||
PalletNumber = SelectedRow.PalletNumber,
|
||||
WzNumber = SelectedRow.WzNumber,
|
||||
TransactionNumber = SelectedRow.TransactionNumber += 10000,
|
||||
PartNumberSl = SelectedRow.PartNumberSl,
|
||||
PartNumber = SelectedRow.PartNumber
|
||||
};
|
||||
|
||||
WzRowsMeyle.Add(splitRow);
|
||||
SelectedRow.Quantity -= newQuantity;
|
||||
|
||||
ChangedRecords.Add(SelectedRow);
|
||||
|
||||
await WarehouseService.CreateWzRowsMeyleAsync(new List<WzRowMeyleDto> { splitRow });
|
||||
await UpdateRows(ChangedRecords);
|
||||
}
|
||||
|
||||
VisibilityLineSplitter = false;
|
||||
}
|
||||
|
||||
private void ShowSplitDialog(ClickEventArgs obj)
|
||||
{
|
||||
VisibilityLineSplitter = true;
|
||||
NewQuantity = "0";
|
||||
}
|
||||
|
||||
private void OnRowSelected(RowSelectEventArgs<WzRowMeyleDto> obj)
|
||||
{
|
||||
SelectedRow = obj.Data;
|
||||
}
|
||||
|
||||
private List<List<WzRowMeyleDto>> FindCombinations(List<WzRowMeyleDto> records, int targetSum)
|
||||
{
|
||||
var result = new List<List<WzRowMeyleDto>>();
|
||||
var currentCombination = new List<WzRowMeyleDto>();
|
||||
|
||||
void Backtrack(int start, int currentSum)
|
||||
{
|
||||
if (currentSum == targetSum)
|
||||
{
|
||||
result.Add(new List<WzRowMeyleDto>(currentCombination));
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = start; i < records.Count; i++)
|
||||
{
|
||||
if (currentSum + records[i].Quantity <= targetSum)
|
||||
{
|
||||
currentCombination.Add(records[i]);
|
||||
Backtrack(i + 1, currentSum + records[i].Quantity ?? 0);
|
||||
currentCombination.RemoveAt(currentCombination.Count - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Backtrack(0, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
private async Task ApplyFilter(IList<WzRowMeyleDto> selectedRecords)
|
||||
{
|
||||
await _grid.FilterByColumnAsync(nameof(WzRowMeyleDto.FaIndex), "equal", selectedRecords.First().FaIndex);
|
||||
}
|
||||
|
||||
private void ChangeView()
|
||||
{
|
||||
NavigationManager.NavigateTo($"/Warehouse/Meyle/PackList/{WzHeader}/Simple");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,424 @@
|
||||
@page "/Warehouse/Meyle/PackList/{WzHeader:guid}/Simple"
|
||||
@using OrdersManagement.Models
|
||||
@using Syncfusion.Blazor.Cards
|
||||
@using Syncfusion.Blazor.Grids
|
||||
@using SytelineSaAppEfDataModel.Dtos
|
||||
@using Syncfusion.Blazor.Popups
|
||||
@using Syncfusion.Blazor.Inputs
|
||||
@using Syncfusion.Blazor.Buttons
|
||||
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject WarehouseService WarehouseService
|
||||
|
||||
<div class="h-100 d-flex justify-content-center align-items-start">
|
||||
<SfCard CssClass="shadow" style="width: 100%; max-width: 1200px;">
|
||||
<CardHeader>
|
||||
<h3 class="text-primary">Packing List</h3>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<SfCard CssClass="shadow" style="width: 100%; max-width: 1200px;" Orientation="CardOrientation.Horizontal">
|
||||
<CardContent>
|
||||
<SfButton CssClass="e-primary" IsPrimary="true" @onclick="ChangeView">Zmień widok</SfButton>
|
||||
<SfButton CssClass="e-primary" IsPrimary="true" @onclick="ExportXls">Generuj XLS i Wyślij</SfButton>
|
||||
</CardContent>
|
||||
</SfCard>
|
||||
<SfCard CssClass="shadow" style="width: 100%; max-width: 1200px;">
|
||||
<CardContent>
|
||||
<label for="textBox" class="form-label">Adresy Email do Wysyłki raportu:</label>
|
||||
<SfTextBox ID="textBox" Placeholder="Wprowadź adresy..." @bind-Value="@EmailAddresses"
|
||||
CssClass="e-outline"/>
|
||||
</CardContent>
|
||||
</SfCard>
|
||||
<SfCard CssClass="shadow" style="width: 100%; max-width: 1200px;">
|
||||
<CardContent>
|
||||
<label for="textBox" class="form-label">Numer WZ:</label>
|
||||
<SfTextBox ID="textBox" @bind-Value=@WzNumber CssClass="e-outline"/>
|
||||
</CardContent>
|
||||
</SfCard>
|
||||
<SfCard CssClass="shadow" style="width: 100%; max-width: 1200px;">
|
||||
<CardContent>
|
||||
<label for="textBox" class="form-label">Wprowadź numer palety:</label>
|
||||
<SfTextBox ID="palletNumber" Type="InputType.Number" @bind-Value="@PalletNumber"
|
||||
CssClass="e-outline"/>
|
||||
<label for="textBox" class="form-label">Zeskanowana wartość:</label>
|
||||
<SfTextBox ID="scannedValue" ValueChange="ScanValue" @bind-Value="ScannedValue"
|
||||
CssClass="e-outline" @ref="_scanner"/>
|
||||
</CardContent>
|
||||
</SfCard>
|
||||
<SfCard CssClass="shadow" style="width: 100%; max-width: 1200px;">
|
||||
<CardContent>
|
||||
<label for="textBox" class="form-label">Numer Indeksu FA:</label>
|
||||
<SfTextBox ID="itemNumber" @bind-Value="@ItemNumber"
|
||||
CssClass="e-outline" Readonly="true"/>
|
||||
<label for="textBox" class="form-label">Ilość w Dostawie:</label>
|
||||
<SfTextBox ID="qty" Type="InputType.Number" @bind-Value="@Qty"
|
||||
CssClass="e-outline" Readonly="true"/>
|
||||
<label for="textBox" class="form-label">Numer Palety:</label>
|
||||
<SfTextBox ID="palletNumberOutput" Type="InputType.Number" @bind-Value="@PalletNumberOutput"
|
||||
CssClass="e-outline" Readonly="true"/>
|
||||
<label for="textBox" class="form-label">Nr Partii SL:</label>
|
||||
<SfTextBox ID="partNumberSl" @bind-Value="@PartNumberSl"
|
||||
CssClass="e-outline" Readonly="true"/>
|
||||
<label for="textBox" class="form-label">Numer Partii Meyle:</label>
|
||||
<SfTextBox ID="partNumberMeyle" @bind-Value="@PartNumberMeyle"
|
||||
CssClass="e-outline" Readonly="true"/>
|
||||
</CardContent>
|
||||
</SfCard>
|
||||
</CardContent>
|
||||
|
||||
<SfDialog Width="500px" Title="Informacja" IsModal="true" @bind-Visible="Visibility" AllowPrerender="true">
|
||||
<DialogTemplates>
|
||||
<Content>
|
||||
@if (_isValid)
|
||||
{
|
||||
<p>Packing List został wygenerowany i wysłany!</p>
|
||||
}
|
||||
else if (string.IsNullOrWhiteSpace(EmailAddresses))
|
||||
{
|
||||
<p>Błąd: Proszę wprowadzić przynajmniej jeden <b>ADRES EMAIL</b> do wysyłki raportu!</p>
|
||||
}
|
||||
else if (!_isValid)
|
||||
{
|
||||
<p>Błąd: Nie Wszystkie linie mają wypełniony <b>NUMER PALETY</b>.<br/>Packing List nie zostanie
|
||||
wygenerowany!</p>
|
||||
}
|
||||
</Content>
|
||||
</DialogTemplates>
|
||||
<DialogButtons>
|
||||
<DialogButton Content="OK" IsPrimary="true" OnClick="@HideModal"/>
|
||||
</DialogButtons>
|
||||
</SfDialog>
|
||||
|
||||
<SfDialog Width="500px" Title="Błąd" IsModal="true" @bind-Visible="VisibilityValidation" AllowPrerender="true">
|
||||
<DialogTemplates>
|
||||
<Content>
|
||||
<p>Błąd skanowania! Wystąpił jeden z wyjątków (Zeskanowana wartość '<b>@ScannedValue</b>'):</p>
|
||||
<ul>
|
||||
<li><p>Zeskanowano niepoprawny Numer Partii SL (nieistniejący w tabeli)</p></li>
|
||||
<li><p>Zeskanowano niepoprawny numer Partii Meyle (niezaczynający się od
|
||||
<b>@($"{DateTime.Now.Year - 2000}X")</b>)</p></li>
|
||||
<li><p>Numer Palety nie jest większy niż 0 (aktualnie wybrany numer palety:
|
||||
'<b>@PalletNumber</b>')</p></li>
|
||||
</ul>
|
||||
</Content>
|
||||
</DialogTemplates>
|
||||
<DialogButtons>
|
||||
<DialogButton Content="OK" IsPrimary="true" OnClick="@HideModal"/>
|
||||
</DialogButtons>
|
||||
</SfDialog>
|
||||
|
||||
<SfDialog Width="500px" Title="Błąd" IsModal="true" @bind-Visible="VisibilityPalletNumber"
|
||||
AllowPrerender="true">
|
||||
<DialogTemplates>
|
||||
<Content>
|
||||
<p>Błąd skanowania! <b>Wybierz NUMER PALETY większy niż 0</b> (Aktualnie '@PalletNumber'):</p>
|
||||
</Content>
|
||||
</DialogTemplates>
|
||||
<DialogButtons>
|
||||
<DialogButton Content="OK" IsPrimary="true" OnClick="@HideModal"/>
|
||||
</DialogButtons>
|
||||
</SfDialog>
|
||||
|
||||
<CardFooter>
|
||||
<small class="text-muted">FA Krosno Manager © @(DateTime.Now.Year)</small>
|
||||
</CardFooter>
|
||||
</SfCard>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
[Parameter] public Guid WzHeader { get; set; }
|
||||
|
||||
private List<WzRowMeyleDto> WzRowsMeyle { get; set; } = new();
|
||||
private IDictionary<string, List<TransactionModel>> TransactionModelsByPartNumber { get; set; } = new Dictionary<string, List<TransactionModel>>();
|
||||
private List<WzRowMeyleDto> ChangedRecords = new();
|
||||
private WzHeaderDto _wzHeader;
|
||||
private SfTextBox _scanner;
|
||||
|
||||
private string ItemNumber { get; set; } = string.Empty;
|
||||
private string Qty { get; set; } = "0";
|
||||
private string PalletNumberOutput { get; set; } = "0";
|
||||
private string PartNumberSl { get; set; } = string.Empty;
|
||||
private string PartNumberMeyle { get; set; } = string.Empty;
|
||||
|
||||
private string WzNumber { get; set; } = string.Empty;
|
||||
|
||||
private WzRowMeyleDto? SelectedRow { get; set; }
|
||||
private List<WzRowMeyleDto> SelectedRows { get; set; } = new();
|
||||
|
||||
private bool _isValid;
|
||||
|
||||
private bool Visibility { get; set; }
|
||||
private bool VisibilityValidation { get; set; }
|
||||
private bool VisibilityLineSplitter { get; set; }
|
||||
public bool VisibilityPalletNumber { get; set; }
|
||||
|
||||
private string? EmailAddresses { get; set; } = string.Empty;
|
||||
private string PalletNumber { get; set; } = "0";
|
||||
|
||||
private string LastScannedValue { get; set; } = string.Empty;
|
||||
private string ScannedValue { get; set; } = string.Empty;
|
||||
|
||||
private void HideModal()
|
||||
{
|
||||
Visibility = false;
|
||||
VisibilityValidation = false;
|
||||
VisibilityLineSplitter = false;
|
||||
VisibilityPalletNumber = false;
|
||||
|
||||
LastScannedValue = ScannedValue;
|
||||
ScannedValue = string.Empty;
|
||||
|
||||
_scanner.FocusAsync();
|
||||
}
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (firstRender)
|
||||
{
|
||||
_wzHeader = await WarehouseService.GetWzHeaderByIdAsync(WzHeader);
|
||||
WzRowsMeyle = (await WarehouseService.GetWzRowsByWzHeaderId(WzHeader)).ToList();
|
||||
|
||||
TransactionModelsByPartNumber = await GetTransactionModels();
|
||||
|
||||
EmailAddresses = _wzHeader.EmailAddresses;
|
||||
|
||||
WzNumber = _wzHeader.WzNumbers ?? string.Empty;
|
||||
|
||||
await _scanner.FocusAsync();
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task SaveChanges()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(EmailAddresses))
|
||||
{
|
||||
await WarehouseService.AddEmailsToWzHeaderAsync(WzHeader, EmailAddresses);
|
||||
}
|
||||
|
||||
if (ChangedRecords.Any())
|
||||
{
|
||||
await UpdateRows(ChangedRecords);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task OnBatchSave(BeforeBatchSaveArgs<WzRowMeyleDto> obj)
|
||||
{
|
||||
var changes = obj.BatchChanges;
|
||||
List<WzRowMeyleDto> changedRecords = changes.ChangedRecords;
|
||||
|
||||
if (!changedRecords.Any()) return;
|
||||
|
||||
await UpdateRows(changedRecords);
|
||||
}
|
||||
|
||||
private async Task ExportXls()
|
||||
{
|
||||
int count = WzRowsMeyle.Count(x => x.PalletNumber == null);
|
||||
|
||||
_isValid = count == 0;
|
||||
_isValid = _isValid && !string.IsNullOrWhiteSpace(EmailAddresses);
|
||||
|
||||
if (_isValid)
|
||||
{
|
||||
await WarehouseService.AddEmailsToWzHeaderAsync(WzHeader, EmailAddresses);
|
||||
await WarehouseService.GenerateXlsForMeyleAsync(WzHeader);
|
||||
}
|
||||
|
||||
Visibility = true;
|
||||
}
|
||||
|
||||
private void ScanValue(ChangedEventArgs obj)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(obj.Value)) return;
|
||||
if (int.Parse(PalletNumber) <= 0)
|
||||
{
|
||||
VisibilityPalletNumber = true;
|
||||
return;
|
||||
}
|
||||
|
||||
ScannedValue = obj.Value.Trim();
|
||||
|
||||
StateHasChanged();
|
||||
|
||||
TransactionModelsByPartNumber.TryGetValue(obj.Value.Trim(), out List<TransactionModel>? materialTransactionsByPartNumber);
|
||||
TransactionModel? materialTransactionByPartNumber = materialTransactionsByPartNumber?.FirstOrDefault();
|
||||
|
||||
if (materialTransactionByPartNumber == null && IsValidScannedValue(obj.Value))
|
||||
{
|
||||
FillMeylePartNumber(ScannedValue);
|
||||
|
||||
LastScannedValue = ScannedValue;
|
||||
ScannedValue = string.Empty;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (materialTransactionByPartNumber != null)
|
||||
{
|
||||
FillFaPartNumberAndPalletNumber(materialTransactionByPartNumber, obj.Value.Trim());
|
||||
}
|
||||
|
||||
if (materialTransactionByPartNumber == null)
|
||||
{
|
||||
ShowValidationMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
LastScannedValue = ScannedValue;
|
||||
ScannedValue = string.Empty;
|
||||
|
||||
_scanner.FocusAsync();
|
||||
}
|
||||
|
||||
private bool IsValidScannedValue(string scannedValue)
|
||||
{
|
||||
int year = DateTime.Now.Year - 2000;
|
||||
|
||||
string format = $"{year}X";
|
||||
|
||||
return scannedValue.StartsWith(format);
|
||||
}
|
||||
|
||||
private async Task FillMeylePartNumber(string scannedValue)
|
||||
{
|
||||
if (SelectedRow != null && !SelectedRows.Any())
|
||||
{
|
||||
SelectedRow.PartNumber = scannedValue;
|
||||
ChangedRecords.Add(SelectedRow);
|
||||
|
||||
PartNumberMeyle = scannedValue;
|
||||
}
|
||||
|
||||
foreach (WzRowMeyleDto wzRowMeyleDto in SelectedRows)
|
||||
{
|
||||
wzRowMeyleDto.PartNumber = scannedValue;
|
||||
ChangedRecords.Add(wzRowMeyleDto);
|
||||
}
|
||||
|
||||
await SaveChanges();
|
||||
|
||||
ChangedRecords.Clear();
|
||||
SelectedRows.Clear();
|
||||
|
||||
await _scanner.FocusAsync();
|
||||
}
|
||||
|
||||
private async Task FillFaPartNumberAndPalletNumber(TransactionModel materialTransactionByPartNumber, string scannedValue)
|
||||
{
|
||||
await InvokeAsync(StateHasChanged);
|
||||
|
||||
int palletNumber = int.Parse(PalletNumber);
|
||||
int rowIndex = WzRowsMeyle.FindIndex(x => x.FaIndex == materialTransactionByPartNumber.ItemNumber && x.Quantity == materialTransactionByPartNumber.Quantity);
|
||||
|
||||
switch (rowIndex)
|
||||
{
|
||||
case -1:
|
||||
{
|
||||
SelectedRows = WzRowsMeyle.Where(x => x.FaIndex == materialTransactionByPartNumber.ItemNumber).ToList();
|
||||
|
||||
if (SelectedRows.Count == 0)
|
||||
{
|
||||
ShowValidationMessage();
|
||||
return;
|
||||
}
|
||||
|
||||
var validCombinations = FindCombinations(SelectedRows, (int?)materialTransactionByPartNumber.Quantity ?? 0);
|
||||
|
||||
foreach (var combination in validCombinations)
|
||||
{
|
||||
foreach (var record in combination)
|
||||
{
|
||||
record.PartNumberSl = scannedValue;
|
||||
record.PalletNumber = palletNumber;
|
||||
ChangedRecords.Add(record);
|
||||
}
|
||||
}
|
||||
|
||||
SelectedRows.Clear();
|
||||
SelectedRows.AddRange(ChangedRecords);
|
||||
|
||||
SelectedRow = SelectedRows.FirstOrDefault();
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
SelectedRow = WzRowsMeyle[rowIndex];
|
||||
|
||||
SelectedRow.PartNumberSl = scannedValue;
|
||||
SelectedRow.PalletNumber = palletNumber;
|
||||
|
||||
if (ChangedRecords.All(x => x.TransactionNumber != SelectedRow.TransactionNumber))
|
||||
{
|
||||
ChangedRecords.Add(SelectedRow);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PartNumberSl = SelectedRow?.PartNumberSl ?? string.Empty;
|
||||
PalletNumberOutput = SelectedRow?.PalletNumber.ToString() ?? "0";
|
||||
ItemNumber = SelectedRow?.FaIndex ?? string.Empty;
|
||||
Qty = SelectedRow?.Quantity.ToString() ?? "0";
|
||||
|
||||
await SaveChanges();
|
||||
ChangedRecords.Clear();
|
||||
await _scanner.FocusAsync();
|
||||
}
|
||||
|
||||
private void ShowValidationMessage()
|
||||
{
|
||||
VisibilityValidation = true;
|
||||
|
||||
ChangedRecords.Clear();
|
||||
_scanner.FocusAsync();
|
||||
}
|
||||
|
||||
private async Task<IDictionary<string, List<TransactionModel>>> GetTransactionModels()
|
||||
{
|
||||
return await WarehouseService.GetTransactionsModels();
|
||||
}
|
||||
|
||||
private async Task UpdateRows(IList<WzRowMeyleDto> changedRecords)
|
||||
{
|
||||
await WarehouseService.UpdateWzRowsMeyleAsync(changedRecords);
|
||||
|
||||
WzRowsMeyle = (await WarehouseService.GetWzRowsByWzHeaderId(WzHeader)).ToList();
|
||||
await InvokeAsync(StateHasChanged);
|
||||
}
|
||||
|
||||
private List<List<WzRowMeyleDto>> FindCombinations(List<WzRowMeyleDto> records, int targetSum)
|
||||
{
|
||||
var result = new List<List<WzRowMeyleDto>>();
|
||||
var currentCombination = new List<WzRowMeyleDto>();
|
||||
|
||||
void Backtrack(int start, int currentSum)
|
||||
{
|
||||
if (currentSum == targetSum)
|
||||
{
|
||||
result.Add(new List<WzRowMeyleDto>(currentCombination));
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = start; i < records.Count; i++)
|
||||
{
|
||||
if (currentSum + records[i].Quantity <= targetSum)
|
||||
{
|
||||
currentCombination.Add(records[i]);
|
||||
Backtrack(i + 1, currentSum + records[i].Quantity ?? 0);
|
||||
currentCombination.RemoveAt(currentCombination.Count - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Backtrack(0, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void ChangeView()
|
||||
{
|
||||
NavigationManager.NavigateTo($"/Warehouse/PackList/{WzHeader}");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user