Warehouses #1

Merged
trent merged 159 commits from Warehouses into master 2026-01-10 20:24:17 +00:00
10 changed files with 160 additions and 54 deletions
Showing only changes of commit ad641560ea - Show all commits

View File

@@ -89,7 +89,7 @@ public class ExcelGeneratorController(IWzHeaderService wzHeaderService, IMateria
workbook.SaveAs(stream); workbook.SaveAs(stream);
stream.Position = 0; stream.Position = 0;
SendEmail(stream); SendEmail(stream, wzHeader);
} }
private static string GetColumnLetter(int columnIndex) private static string GetColumnLetter(int columnIndex)
@@ -104,7 +104,7 @@ public class ExcelGeneratorController(IWzHeaderService wzHeaderService, IMateria
return columnName; return columnName;
} }
private void SendEmail(MemoryStream stream) private void SendEmail(MemoryStream stream, WzHeaderDto wzHeader)
{ {
IConfigurationSection smtpSettings = configuration.GetSection("EmailSettings"); IConfigurationSection smtpSettings = configuration.GetSection("EmailSettings");
string smtpHost = smtpSettings["SmtpServer"] ?? string.Empty; string smtpHost = smtpSettings["SmtpServer"] ?? string.Empty;
@@ -112,7 +112,8 @@ public class ExcelGeneratorController(IWzHeaderService wzHeaderService, IMateria
string smtpUsername = smtpSettings["SenderEmail"] ?? string.Empty; string smtpUsername = smtpSettings["SenderEmail"] ?? string.Empty;
string smtpPassword = smtpSettings["SenderPassword"] ?? string.Empty; string smtpPassword = smtpSettings["SenderPassword"] ?? string.Empty;
string fromEmail = smtpSettings["SenderEmail"] ?? string.Empty; string fromEmail = smtpSettings["SenderEmail"] ?? string.Empty;
List<string> toEmail = (smtpSettings["RecipientEmail"] ?? string.Empty).Split(',').ToList(); List<string> toEmail = wzHeader.EmailAddresses?.Split(',')?.ToList() ??
(smtpSettings["RecipientEmail"] ?? string.Empty).Split(',').ToList();
string subject = "MEYLE: Packing List"; string subject = "MEYLE: Packing List";
string body = string body =
$"W załączeniu znajduje się Packing List dla klienta MEYLE wygenerowany {DateTime.Now:dd.MM.yyyy HH:mm:ss}"; $"W załączeniu znajduje się Packing List dla klienta MEYLE wygenerowany {DateTime.Now:dd.MM.yyyy HH:mm:ss}";

View File

@@ -52,4 +52,16 @@ public class WzHeaderController(IWzHeaderService service, IMaterialTransactionSe
WzHeaderDto? wzHeader = await service.GetById(id); WzHeaderDto? wzHeader = await service.GetById(id);
return wzHeader != null ? Ok(wzHeader) : NotFound(); return wzHeader != null ? Ok(wzHeader) : NotFound();
} }
[HttpPost("add-emails")]
public async Task<IActionResult> AddEmailsToWzHeader([FromQuery] Guid id, [FromBody] string emailAddresses)
{
if (string.IsNullOrWhiteSpace(emailAddresses))
{
return BadRequest("Email addresses cannot be empty.");
}
await service.AddEmailsToWzHeader(id, emailAddresses);
return NoContent();
}
} }

View File

@@ -8,6 +8,7 @@
@using FilterType = Syncfusion.Blazor.Grids.FilterType @using FilterType = Syncfusion.Blazor.Grids.FilterType
@using SelectionMode = Syncfusion.Blazor.Grids.SelectionMode @using SelectionMode = Syncfusion.Blazor.Grids.SelectionMode
@using Syncfusion.Blazor.Navigations @using Syncfusion.Blazor.Navigations
@using Syncfusion.Blazor.Popups
@inject WarehouseService WarehouseService @inject WarehouseService WarehouseService
@inject NavigationManager NavigationManager @inject NavigationManager NavigationManager
@@ -61,8 +62,7 @@
<h5 class="text-primary mb-3">Packling Listy</h5> <h5 class="text-primary mb-3">Packling Listy</h5>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<SfGrid @ref="_wzHeadersGrid" <SfGrid AllowFiltering="true"
AllowFiltering="true"
AllowPaging="true" AllowPaging="true"
AllowSorting="true" AllowSorting="true"
AllowSelection="true" AllowSelection="true"
@@ -71,6 +71,7 @@
EnableAdaptiveUI="true"> EnableAdaptiveUI="true">
<GridColumns> <GridColumns>
<GridColumn Field=@nameof(WzHeaderDto.ID) HeaderText="ID" TextAlign="TextAlign.Center" Width="110"></GridColumn> <GridColumn Field=@nameof(WzHeaderDto.ID) HeaderText="ID" TextAlign="TextAlign.Center" Width="110"></GridColumn>
<GridColumn Field=@nameof(WzHeaderDto.WzNumbers) HeaderText="Numery WZ" TextAlign="TextAlign.Center" Width="100"></GridColumn>
<GridColumn Field=@nameof(WzHeaderDto.CreatedDate) HeaderText="Data utworzenia" TextAlign="TextAlign.Center" Width="100"></GridColumn> <GridColumn Field=@nameof(WzHeaderDto.CreatedDate) HeaderText="Data utworzenia" TextAlign="TextAlign.Center" Width="100"></GridColumn>
</GridColumns> </GridColumns>
<GridFilterSettings Type="FilterType.Excel"/> <GridFilterSettings Type="FilterType.Excel"/>
@@ -82,6 +83,18 @@
</SfCard> </SfCard>
} }
</CardContent> </CardContent>
<SfDialog Width="500px" Title="Informacja" IsModal="true" @bind-Visible="Visibility" AllowPrerender="true">
<DialogTemplates>
<Content>
<p>Błąd: Zaznacz przynajmniej jeden rekord, żeby wygenerowac Pack List!</p>
</Content>
</DialogTemplates>
<DialogButtons>
<DialogButton Content="OK" IsPrimary="true" OnClick="@HideModal"/>
</DialogButtons>
</SfDialog>
<CardFooter> <CardFooter>
<small class="text-muted">FA Krosno Manager © @(DateTime.Now.Year)</small> <small class="text-muted">FA Krosno Manager © @(DateTime.Now.Year)</small>
</CardFooter> </CardFooter>
@@ -90,7 +103,6 @@
@code { @code {
private SfGrid<MaterialTransactionDto> _grid; private SfGrid<MaterialTransactionDto> _grid;
private SfGrid<WzHeaderDto> _wzHeadersGrid;
private IEnumerable<WzClientDto> _clients = new List<WzClientDto>(); private IEnumerable<WzClientDto> _clients = new List<WzClientDto>();
private IEnumerable<MaterialTransactionDto> _materialTransactions = new List<MaterialTransactionDto>(); private IEnumerable<MaterialTransactionDto> _materialTransactions = new List<MaterialTransactionDto>();
private IEnumerable<MaterialTransactionDto> _dataSource = new List<MaterialTransactionDto>(); private IEnumerable<MaterialTransactionDto> _dataSource = new List<MaterialTransactionDto>();
@@ -102,6 +114,8 @@
private SfDropDownList<Guid?, WzClientDto> _dropdown; private SfDropDownList<Guid?, WzClientDto> _dropdown;
private bool _isVisible; private bool _isVisible;
private bool Visibility { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender) protected override async Task OnAfterRenderAsync(bool firstRender)
{ {
if (firstRender) if (firstRender)
@@ -109,14 +123,15 @@
_clients = await WarehouseService.GetAllClientsAsync(); _clients = await WarehouseService.GetAllClientsAsync();
_clients = _clients.Where(x => x.Name.Equals("MEYLE", StringComparison.OrdinalIgnoreCase)); _clients = _clients.Where(x => x.Name.Equals("MEYLE", StringComparison.OrdinalIgnoreCase));
StateHasChanged();
var savedClientId = await LocalStorage.GetItemAsync<Guid?>("SelectedClientId"); var savedClientId = await LocalStorage.GetItemAsync<Guid?>("SelectedClientId");
if (savedClientId != null && _clients.FirstOrDefault(c => c.ID == savedClientId) is {} savedClient) if (savedClientId != null && _clients.FirstOrDefault(c => c.ID == savedClientId) is {} savedClient)
{ {
await OnValueChange(new ChangeEventArgs<Guid?, WzClientDto>() { Value = savedClient.ID }); await OnValueChange(new ChangeEventArgs<Guid?, WzClientDto>() { Value = savedClient.ID });
StateHasChanged();
} }
StateHasChanged();
} }
} }
@@ -156,43 +171,54 @@
private async Task CreatePackingList() private async Task CreatePackingList()
{ {
var selectedRecords = await _grid.GetSelectedRecordsAsync(); var selectedRecords = await _grid.GetSelectedRecordsAsync();
if (selectedRecords.Any())
if (!selectedRecords.Any())
{ {
WzHeaderDto wzHeader = new WzHeaderDto Visibility = true;
{ return;
ID = Guid.NewGuid(),
FK_Client = _selectedClient?.ID
};
await WarehouseService.CreateWzHeaderAsync(wzHeader);
switch (_selectedClient?.Name.ToUpper())
{
case "MEYLE":
IList<WzRowMeyleDto> rows = new List<WzRowMeyleDto>();
IList<MaterialTransactionDto> materialTransactions = _materialTransactions.Where(x => selectedRecords.Any(y => y.MTGroupNum == x.MTGroupNum)).ToList();
foreach (MaterialTransactionDto materialTransactionDto in materialTransactions)
{
CustomerOrderDto customerOrder = await WarehouseService.GetCustomerOrder(materialTransactionDto.RefNum ?? string.Empty);
ItemCustDto item = await WarehouseService.GetItem(materialTransactionDto.Item ?? string.Empty, customerOrder.CustNum);
rows.Add(new WzRowMeyleDto
{
ID = Guid.NewGuid(),
Quantity = Math.Abs((int?)materialTransactionDto.Qty ?? 0),
ItemNumber = item.CustItem,
OrderNumber = customerOrder.CustPo,
WzNumber = materialTransactionDto.MTGroupNum ?? string.Empty,
FK_Header = wzHeader.ID
});
}
await WarehouseService.CreateWzRowsMeyleAsync(rows);
break;
}
NavigationManager.NavigateTo("/Warehouse/PackList/" + wzHeader.ID);
} }
WzHeaderDto wzHeader = new WzHeaderDto
{
ID = Guid.NewGuid(),
FK_Client = _selectedClient?.ID,
CreatedDate = DateTime.Now,
WzNumbers = string.Join(", ",selectedRecords.Select(x => x.MTGroupNum).Distinct())
};
await WarehouseService.CreateWzHeaderAsync(wzHeader);
switch (_selectedClient?.Name.ToUpper())
{
case "MEYLE":
IList<WzRowMeyleDto> rows = new List<WzRowMeyleDto>();
IList<MaterialTransactionDto> materialTransactions = _materialTransactions.Where(x => selectedRecords.Any(y => y.MTGroupNum == x.MTGroupNum)).ToList();
foreach (MaterialTransactionDto materialTransactionDto in materialTransactions)
{
CustomerOrderDto customerOrder = await WarehouseService.GetCustomerOrder(materialTransactionDto.RefNum ?? string.Empty);
ItemCustDto item = await WarehouseService.GetItem(materialTransactionDto.Item ?? string.Empty, customerOrder.CustNum);
rows.Add(new WzRowMeyleDto
{
ID = Guid.NewGuid(),
Quantity = Math.Abs((int?)materialTransactionDto.Qty ?? 0),
ItemNumber = item.CustItem,
OrderNumber = customerOrder.CustPo,
WzNumber = materialTransactionDto.MTGroupNum ?? string.Empty,
FK_Header = wzHeader.ID
});
}
await WarehouseService.CreateWzRowsMeyleAsync(rows);
break;
}
NavigationManager.NavigateTo("/Warehouse/PackList/" + wzHeader.ID);
}
private void HideModal()
{
Visibility = false;
} }
} }

View File

@@ -4,6 +4,7 @@
@using SytelineSaAppEfDataModel.Dtos @using SytelineSaAppEfDataModel.Dtos
@using Syncfusion.Blazor.Navigations @using Syncfusion.Blazor.Navigations
@using Syncfusion.Blazor.Popups @using Syncfusion.Blazor.Popups
@using Syncfusion.Blazor.Inputs
@inject WarehouseService WarehouseService @inject WarehouseService WarehouseService
@@ -13,6 +14,12 @@
<h3 class="text-primary">Packing List</h3> <h3 class="text-primary">Packing List</h3>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<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>
<SfGrid @ref="_grid" <SfGrid @ref="_grid"
AllowFiltering="true" AllowFiltering="true"
AllowPaging="true" AllowPaging="true"
@@ -23,10 +30,10 @@
EnableAdaptiveUI="true"> EnableAdaptiveUI="true">
<SfToolbar> <SfToolbar>
<ToolbarItems> <ToolbarItems>
<ToolbarItem Type="ItemType.Button" Text="Zapisz" Id="SaveButton" <ToolbarItem Type="ItemType.Button" Text="Zapisz zmiany" Id="SaveButton"
PrefixIcon="e-icons e-save" OnClick="SaveChanges"/> PrefixIcon="e-icons e-save" OnClick="SaveChanges"/>
<ToolbarItem Type="ItemType.Button" Id="Generuj XLS" PrefixIcon="e-icons e-export-xls" <ToolbarItem Type="ItemType.Button" Id="Generuj XLS i Wyślij" PrefixIcon="e-icons e-export-xls"
Text="Generuj XLS" OnClick="ExportXls"/> Text="Generuj XLS i Wyślij" OnClick="ExportXls"/>
</ToolbarItems> </ToolbarItems>
</SfToolbar> </SfToolbar>
<GridColumns> <GridColumns>
@@ -68,7 +75,11 @@
{ {
<p>Packing List został wygenerowany i wysłany!</p> <p>Packing List został wygenerowany i wysłany!</p>
} }
else 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> <p>Błąd: Nie Wszystkie linie mają wypełniony <b>NUMER PALETY</b>.<br/>Packing List nie zostanie wygenerowany!</p>
} }
@@ -90,11 +101,14 @@
private SfGrid<WzRowMeyleDto> _grid; private SfGrid<WzRowMeyleDto> _grid;
private IEnumerable<WzRowMeyleDto> _wzRowsMeyle { get; set; } = new List<WzRowMeyleDto>(); private IEnumerable<WzRowMeyleDto> _wzRowsMeyle { get; set; } = new List<WzRowMeyleDto>();
private WzHeaderDto _wzHeader;
private bool _isValid; private bool _isValid;
private bool Visibility { get; set; } private bool Visibility { get; set; }
private string EmailAddresses { get; set; } = string.Empty;
private void HideModal() private void HideModal()
{ {
Visibility = false; Visibility = false;
@@ -104,13 +118,18 @@
{ {
if (firstRender) if (firstRender)
{ {
_wzHeader = await WarehouseService.GetWzHeaderByIdAsync(WzHeader);
_wzRowsMeyle = await WarehouseService.GetWzRowsByWzHeaderId(WzHeader); _wzRowsMeyle = await WarehouseService.GetWzRowsByWzHeaderId(WzHeader);
EmailAddresses = _wzHeader.EmailAddresses;
StateHasChanged(); StateHasChanged();
} }
} }
private async Task SaveChanges() private async Task SaveChanges()
{ {
await WarehouseService.AddEmailsToWzHeaderAsync(WzHeader, EmailAddresses);
await _grid.EndEditAsync(); await _grid.EndEditAsync();
} }
@@ -119,6 +138,8 @@
var changes = obj.BatchChanges; var changes = obj.BatchChanges;
var changedRecords = changes.ChangedRecords; var changedRecords = changes.ChangedRecords;
if (!changedRecords.Any()) return;
await WarehouseService.UpdateWzRowsMeyleAsync(changedRecords); await WarehouseService.UpdateWzRowsMeyleAsync(changedRecords);
_wzRowsMeyle = await WarehouseService.GetWzRowsByWzHeaderId(WzHeader); _wzRowsMeyle = await WarehouseService.GetWzRowsByWzHeaderId(WzHeader);
@@ -131,9 +152,11 @@
int count = _wzRowsMeyle.Count(x => x.PalletNumber == null); int count = _wzRowsMeyle.Count(x => x.PalletNumber == null);
_isValid = count == 0; _isValid = count == 0;
_isValid = _isValid && !string.IsNullOrWhiteSpace(EmailAddresses);
if (_isValid) if (_isValid)
{ {
await WarehouseService.AddEmailsToWzHeaderAsync(WzHeader, EmailAddresses);
await WarehouseService.GenerateXlsForMeyleAsync(WzHeader); await WarehouseService.GenerateXlsForMeyleAsync(WzHeader);
} }

View File

@@ -6,6 +6,13 @@ public class WarehouseService(IHttpClientFactory httpClientFactory)
{ {
private readonly HttpClient _httpClient = httpClientFactory.CreateClient("FaKrosnoApi"); private readonly HttpClient _httpClient = httpClientFactory.CreateClient("FaKrosnoApi");
public async Task<WzHeaderDto> GetWzHeaderByIdAsync(Guid wzHeaderId)
{
var response = await _httpClient.GetAsync($"api/WzHeader/by-id?id={wzHeaderId}");
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<WzHeaderDto>();
}
public async Task<IEnumerable<WzClientDto>> GetAllClientsAsync() public async Task<IEnumerable<WzClientDto>> GetAllClientsAsync()
{ {
var response = await _httpClient.GetAsync($"api/WzClient"); var response = await _httpClient.GetAsync($"api/WzClient");
@@ -98,4 +105,13 @@ public class WarehouseService(IHttpClientFactory httpClientFactory)
throw new Exception("Failed to generate XLS for Mayle"); throw new Exception("Failed to generate XLS for Mayle");
} }
} }
public async Task AddEmailsToWzHeaderAsync(Guid wzHeaderId, string emailAddresses)
{
var response = await _httpClient.PostAsJsonAsync(
$"api/WzHeader/add-emails?id={wzHeaderId}",
emailAddresses);
response.EnsureSuccessStatusCode();
}
} }

View File

@@ -5,6 +5,7 @@ public class WzHeaderDto
public Guid ID { get; set; } public Guid ID { get; set; }
public Guid? FK_Client { get; set; } public Guid? FK_Client { get; set; }
public DateTime CreatedDate { get; set; } public DateTime CreatedDate { get; set; }
public string? EmailAddresses { get; set; }
public string? WzNumbers { get; set; }
public IEnumerable<WzRowMeyleDto> WzRowsMeyle { get; set; } = new List<WzRowMeyleDto>(); public IEnumerable<WzRowMeyleDto> WzRowsMeyle { get; set; } = new List<WzRowMeyleDto>();
} }

View File

@@ -5,6 +5,8 @@ public class WzHeader
public Guid ID { get; set; } public Guid ID { get; set; }
public Guid? FK_Client { get; set; } public Guid? FK_Client { get; set; }
public DateTime CreatedDate { get; set; } public DateTime CreatedDate { get; set; }
public string? EmailAddresses { get; set; }
public string? WzNumbers { get; set; }
// Navigation property // Navigation property
public WzClient Client { get; set; } public WzClient Client { get; set; }

View File

@@ -8,4 +8,5 @@ public interface IWzHeaderService
Task<IEnumerable<WzHeaderDto>> GetByCustomerNumber(string customerNumber, int customerSequence); Task<IEnumerable<WzHeaderDto>> GetByCustomerNumber(string customerNumber, int customerSequence);
Task CreateHeader(WzHeaderDto wzHeader); Task CreateHeader(WzHeaderDto wzHeader);
Task<WzHeaderDto> GetById(Guid id); Task<WzHeaderDto> GetById(Guid id);
Task AddEmailsToWzHeader(Guid id, string emailAddresses);
} }

View File

@@ -37,4 +37,18 @@ public class WzHeaderService(SytelineSaAppDbContext context, IMapper mapper) : I
return wzHeader; return wzHeader;
} }
public async Task AddEmailsToWzHeader(Guid id, string emailAddresses)
{
var entity = await context.WzHeaders.FindAsync(id);
if (entity == null)
{
throw new KeyNotFoundException($"WzHeader with ID {id} not found.");
}
entity.EmailAddresses = emailAddresses;
context.WzHeaders.Update(entity);
await context.SaveChangesAsync();
}
} }

View File

@@ -902,6 +902,16 @@ namespace SytelineSaAppEfDataModel
.HasColumnType("DateTime") .HasColumnType("DateTime")
.IsRowVersion(); .IsRowVersion();
entity.Property(e => e.EmailAddresses)
.HasColumnName("EmailAddresses")
.HasMaxLength(1000)
.IsRequired(false);
entity.Property(e => e.WzNumbers)
.HasColumnName("WzNumbers")
.HasMaxLength(500)
.IsRequired(false);
// Relationship // Relationship
entity.HasOne(e => e.Client) entity.HasOne(e => e.Client)
.WithMany() .WithMany()