Merge pull request #1 from trencik91/Syncfusion_changes

Syncfusion changes
This commit is contained in:
2025-04-15 20:12:45 +02:00
committed by GitHub
125 changed files with 68445 additions and 1203 deletions

View File

@@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FaKrosnoEfDataModel", "FaKr
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SytelineSaAppEfDataModel", "SytelineSaAppEfDataModel\SytelineSaAppEfDataModel.csproj", "{02B7F642-62C1-4BA2-87B0-0B9214319095}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OrdersManagementDataModel", "OrdersManagementDataModel\OrdersManagementDataModel.csproj", "{5971D564-5108-4777-8273-DDE90BF39879}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -35,6 +37,10 @@ Global
{02B7F642-62C1-4BA2-87B0-0B9214319095}.Debug|Any CPU.Build.0 = Debug|Any CPU
{02B7F642-62C1-4BA2-87B0-0B9214319095}.Release|Any CPU.ActiveCfg = Release|Any CPU
{02B7F642-62C1-4BA2-87B0-0B9214319095}.Release|Any CPU.Build.0 = Release|Any CPU
{5971D564-5108-4777-8273-DDE90BF39879}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5971D564-5108-4777-8273-DDE90BF39879}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5971D564-5108-4777-8273-DDE90BF39879}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5971D564-5108-4777-8273-DDE90BF39879}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -42,5 +48,6 @@ Global
GlobalSection(NestedProjects) = preSolution
{4671E3B6-4D11-4521-A927-DC3B1072FC4A} = {6607ACC9-71B9-4095-9A81-B6FBB0AAAF17}
{02B7F642-62C1-4BA2-87B0-0B9214319095} = {6607ACC9-71B9-4095-9A81-B6FBB0AAAF17}
{5971D564-5108-4777-8273-DDE90BF39879} = {6607ACC9-71B9-4095-9A81-B6FBB0AAAF17}
EndGlobalSection
EndGlobal

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SytelineSaAppEfDataModel.Dtos;
using SytelineSaAppEfDataModel.Services;

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SytelineSaAppEfDataModel.Dtos;
using SytelineSaAppEfDataModel.Services;

View File

@@ -0,0 +1,24 @@
using Microsoft.AspNetCore.Mvc;
using SytelineSaAppEfDataModel.Dtos;
using SytelineSaAppEfDataModel.Services;
namespace FaKrosnoApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class EdiCustomerOrdersTranslationsController(IEdiCustomerOrderTranslateService service) : Controller
{
[HttpGet]
public async Task<ActionResult<IEnumerable<EdiCustomerOrderTranslateDto>>> GetAll()
{
IEnumerable<EdiCustomerOrderTranslateDto?> ediCustomerOrdersTranlations = await service.GetAll();
return Ok(ediCustomerOrdersTranlations);
}
[HttpDelete]
public async Task<IActionResult> Delete([FromQuery] int id)
{
await service.Delete(id);
return NoContent();
}
}

View File

@@ -1,4 +1,5 @@
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using SytelineSaAppEfDataModel.Dtos;
using SytelineSaAppEfDataModel.Services;

View File

@@ -0,0 +1,52 @@
using Microsoft.AspNetCore.Mvc;
using OrdersManagementDataModel.Dtos;
using OrdersManagementDataModel.Services;
namespace FaKrosnoApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class FunctionsController(IFunctionService service) : Controller
{
[HttpGet]
public async Task<ActionResult<IEnumerable<FunctionDto>>> GetAll()
{
IEnumerable<FunctionDto?> functions = await service.GetAll();
return Ok(functions);
}
[HttpGet("by-id")]
public async Task<ActionResult<FunctionDto?>> GetById([FromQuery] Guid id)
{
FunctionDto? function = await service.GetById(id);
return function != null ? Ok(function) : NotFound();
}
[HttpGet("by-name")]
public async Task<ActionResult<FunctionDto?>> GetByName([FromQuery] string name)
{
FunctionDto? function = await service.GetByName(name);
return function != null ? Ok(function) : NotFound();
}
[HttpPost]
public async Task<ActionResult<FunctionDto>> Add([FromBody] FunctionDto function)
{
await service.Add(function);
return Ok(function);
}
[HttpPut]
public async Task<ActionResult<FunctionDto>> Update([FromBody] FunctionDto function)
{
await service.Update(function);
return Ok(function);
}
[HttpDelete]
public async Task<ActionResult<FunctionDto>> Delete([FromQuery] Guid id)
{
await service.Delete(id);
return Ok();
}
}

View File

@@ -0,0 +1,170 @@
using System.Diagnostics;
using FaKrosnoApi.Models;
using Hangfire;
using Hangfire.Storage;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using OrdersManagementDataModel.Dtos;
using OrdersManagementDataModel.Services;
namespace FaKrosnoApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class HangfireJobsController(
JobStorage jobStorage,
IRecurringJobManager recurringJobManager,
ITaskSchedulerService service) : Controller
{
[HttpGet("GetJobsToRun")]
public async Task<ActionResult<IEnumerable<JobModel>>> GetJobsToRun()
{
IList<JobModel> jobsToRun = new List<JobModel>();
using (IStorageConnection? connection = jobStorage.GetConnection())
{
IList<RecurringJobDto>? recurringJobs = connection.GetRecurringJobs();
IList<TaskSchedulerDto>? taskSchedulers = (await service.GetTaskSchedulers()).ToList();
foreach (var recurringJob in recurringJobs)
{
TaskSchedulerDto? taskScheduler = taskSchedulers?.FirstOrDefault(ts => ts.Name == recurringJob.Id);
if (taskScheduler != null)
{
jobsToRun.Add(new JobModel(recurringJob.Id, recurringJob.Cron, taskScheduler.Path,
recurringJob.LastExecution, recurringJob.NextExecution, recurringJob.Job));
}
}
}
return Ok(jobsToRun);
}
[HttpPost("run")]
public async Task<IActionResult> RunJobs()
{
var jobsToRun = (await GetJobsToRun()).Value?.ToList();
if (jobsToRun == null || jobsToRun.Count == 0)
{
return BadRequest("Nie udało się pobrać zadań do uruchomienia.");
}
foreach (var job in jobsToRun)
{
if (!string.IsNullOrEmpty(job.Path))
{
recurringJobManager.AddOrUpdate(job.JobId, () => RunConsoleApplication(job.Path), job.Cron,
new RecurringJobOptions { TimeZone = TimeZoneInfo.Local });
}
}
return Ok("Zadania zostały zaplanowane do uruchamiania zgodnie z ich CRON.");
}
[HttpPost("add")]
public async Task<IActionResult> AddTask([FromBody] TaskSchedulerDto taskSchedulerDto)
{
var taskScheduler = new OrdersManagementDataModel.Entities.TaskScheduler
{
Name = taskSchedulerDto.Name,
Path = taskSchedulerDto.Path,
CronOptions = taskSchedulerDto.CronOptions,
CreateDate = DateTime.UtcNow
};
int result = await service.AddTaskScheduler(taskSchedulerDto);
if (result == 0)
{
return BadRequest("Nie udało się dodać zadania.");
}
recurringJobManager.AddOrUpdate(taskScheduler.Name, () => RunConsoleApplication(taskScheduler.Path),
taskScheduler.CronOptions, new RecurringJobOptions { TimeZone = TimeZoneInfo.Local });
return Ok("Zadanie zostało dodane.");
}
[HttpPost("delete")]
public async Task<IActionResult> DeleteTask([FromBody] TaskSchedulerDto taskSchedulerDto)
{
int result = await service.DeleteTaskScheduler(taskSchedulerDto.RowPointer);
if (result == 0)
{
return BadRequest("Nie udało się usunąć zadania.");
}
recurringJobManager.RemoveIfExists(taskSchedulerDto.Name);
return Ok("Zadanie zostało usunięte.");
}
[HttpGet]
public async Task<ActionResult<IEnumerable<TaskSchedulerDto>>> GetTasks()
{
var tasks = await service.GetTaskSchedulers();
foreach (TaskSchedulerDto taskSchedulerDto in tasks)
{
var job = GetJob(taskSchedulerDto.Name);
taskSchedulerDto.LastExecution = job?.LastExecution;
taskSchedulerDto.NextExecution = job?.NextExecution;
}
return Ok(tasks);
}
[HttpGet("by-name")]
public async Task<ActionResult<TaskSchedulerDto>> GetTaskSchedulerByTaskName([FromQuery] string name)
{
var taskSchedulerDto = await service.GetTaskSchedulerByTaskName(name);
if (taskSchedulerDto == null) return NotFound();
var job = GetJob(taskSchedulerDto.Name);
taskSchedulerDto.LastExecution = job?.LastExecution;
taskSchedulerDto.NextExecution = job?.NextExecution;
return Ok(taskSchedulerDto);
}
private RecurringJobDto? GetJob(string jobId)
{
using IStorageConnection? connection = jobStorage.GetConnection();
IList<RecurringJobDto>? recurringJobs = connection.GetRecurringJobs();
return recurringJobs.FirstOrDefault(x => x.Id == jobId);
}
public void RunConsoleApplication(string pathToApp)
{
try
{
var process = new Process
{
StartInfo = new ProcessStartInfo
{
FileName = pathToApp,
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true,
CreateNoWindow = true,
WorkingDirectory = Path.GetDirectoryName(pathToApp)
}
};
process.Start();
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
process.WaitForExit();
Console.WriteLine($"Output: {output}");
Console.WriteLine($"Error: {error}");
}
catch (Exception ex)
{
Console.WriteLine($"Error executing console application: {ex.Message}");
}
}
}

View File

@@ -0,0 +1,31 @@
using FaKrosnoEfDataModel.Dtos;
using FaKrosnoEfDataModel.Services;
using Microsoft.AspNetCore.Mvc;
namespace FaKrosnoApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class ProductController(IProductService service) : Controller
{
[HttpGet]
public async Task<ActionResult<IEnumerable<ProductDto>>> GetAll()
{
IEnumerable<ProductDto?> products = await service.GetEntities();
return Ok(products);
}
[HttpGet("by-index")]
public async Task<ActionResult<IEnumerable<ProductDto>>> GetByIndex([FromQuery] string indexName)
{
IEnumerable<ProductDto?> products = await service.GetEntitiesToFix(indexName);
return Ok(products);
}
[HttpPut]
public async Task<ActionResult> Update([FromBody] ProductDto product)
{
await service.UpdateEntity(product);
return Ok();
}
}

View File

@@ -0,0 +1,45 @@
using Microsoft.AspNetCore.Mvc;
using OrdersManagementDataModel.Dtos;
using OrdersManagementDataModel.Services;
namespace FaKrosnoApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class RolesController(IRoleService service) : Controller
{
[HttpGet]
public async Task<ActionResult<IEnumerable<RoleDto>>> GetAll()
{
IEnumerable<RoleDto?> roles = await service.GetAll();
return Ok(roles);
}
[HttpGet("by-id")]
public async Task<ActionResult<RoleDto?>> GetById([FromQuery] Guid id)
{
RoleDto? role = await service.GetById(id);
return role != null ? Ok(role) : NotFound();
}
[HttpGet("by-name")]
public async Task<ActionResult<RoleDto?>> GetByName([FromQuery] string name)
{
RoleDto? role = await service.GetByName(name);
return role != null ? Ok(role) : NotFound();
}
[HttpPost]
public async Task<ActionResult<RoleDto>> Add([FromBody] RoleDto role)
{
await service.Add(role);
return Ok(role);
}
[HttpDelete]
public async Task<ActionResult<RoleDto>> Delete([FromQuery] Guid id)
{
await service.Delete(id);
return Ok();
}
}

View File

@@ -0,0 +1,18 @@
using FaKrosnoApi.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace FaKrosnoApi.Controllers;
[ApiController]
[Route("[controller]")]
public class ScheduleJobController(IScheduleJobService scheduledJob) : ControllerBase
{
[HttpPost("start")]
public IActionResult StartJob()
{
scheduledJob.ExecuteAsync();
return Ok("Job started");
}
}

View File

@@ -1,18 +0,0 @@
using FaKrosnoEfDataModel.Dtos;
using FaKrosnoEfDataModel.Services;
using Microsoft.AspNetCore.Mvc;
namespace FaKrosnoApi.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class ScheduleOrderDetailsController(IScheduleOrderDetailsService service) : Controller
{
[HttpGet("order/{scheduleOrderId:int}")]
public async Task<ActionResult<IEnumerable<ScheduleOrderDto>>> GetByScheduleOrderId(int scheduleOrderId)
{
IEnumerable<ScheduleOrderDetailDto>? scheduleOrderDetails = await service.GetScheduleOrderDetailsAsync(scheduleOrderId);
return Ok(scheduleOrderDetails);
}
}
}

View File

@@ -1,6 +1,4 @@
using AutoMapper;
using FaKrosnoEfDataModel;
using FaKrosnoEfDataModel.Dtos;
using FaKrosnoEfDataModel.Dtos;
using FaKrosnoEfDataModel.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
@@ -9,7 +7,6 @@ namespace FaKrosnoApi.Controllers
{
[ApiController]
[Route("api/[controller]")]
//[Authorize]
public class ScheduleOrdersController(IScheduleOrderService service) : Controller
{
[HttpGet]

View File

@@ -0,0 +1,45 @@
using Microsoft.AspNetCore.Mvc;
using OrdersManagementDataModel.Dtos;
using OrdersManagementDataModel.Services;
namespace FaKrosnoApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class UserRolesController(IUserRoleService service) : Controller
{
[HttpGet]
public async Task<ActionResult<IEnumerable<UserRoleDto>>> GetAll()
{
IEnumerable<UserRoleDto?> userRoles = await service.GetAll();
return Ok(userRoles);
}
[HttpGet("by-id")]
public async Task<ActionResult<UserRoleDto?>> GetById([FromQuery] Guid id)
{
UserRoleDto? userRole = await service.GetById(id);
return userRole != null ? Ok(userRole) : NotFound();
}
[HttpPost]
public async Task<ActionResult<UserRoleDto>> Add([FromBody] UserRoleDto userRole)
{
await service.Add(userRole);
return Ok(userRole);
}
[HttpPut]
public async Task<ActionResult<UserRoleDto>> Update([FromBody] UserRoleDto userRole)
{
await service.Update(userRole);
return Ok(userRole);
}
[HttpDelete]
public async Task<ActionResult<UserRoleDto>> Delete([FromQuery] Guid id)
{
await service.Delete(id);
return Ok();
}
}

View File

@@ -0,0 +1,91 @@
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using FaKrosnoApi.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.IdentityModel.Tokens;
using OrdersManagementDataModel.Dtos;
using OrdersManagementDataModel.Services;
namespace FaKrosnoApi.Controllers;
[ApiController]
[Route("api/[controller]")]
public class UsersController(IUserService service, IConfiguration configuration) : Controller
{
[HttpGet]
public async Task<ActionResult<IEnumerable<UserDto>>> GetAll()
{
IEnumerable<UserDto?> users = await service.GetAll();
return Ok(users);
}
[HttpGet("by-id")]
public async Task<ActionResult<UserDto?>> GetById([FromQuery] Guid id)
{
UserDto? user = await service.GetById(id);
return user != null ? Ok(user) : NotFound();
}
[HttpGet("by-username")]
public async Task<ActionResult<UserDto?>> GetByUsername([FromQuery] string username)
{
UserDto? user = await service.GetByUsername(username);
return user != null ? Ok(user) : NotFound();
}
[HttpPost("login")]
public async Task<IActionResult> Login([FromBody] AuthenticateRequestModel loginDto)
{
var user = await service.GetByUsername(loginDto.Login);
if(user == null || !BCrypt.Net.BCrypt.Verify(loginDto.Password, user.PasswordHash))
{
return Unauthorized("Nieprawidłowa nazwa użytkownika lub hasło.");
}
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, user.Login),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["Jwt:Key"]));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(
issuer: configuration["Jwt:Issuer"],
audience: configuration["Jwt:Audience"],
claims: claims,
expires: DateTime.Now.AddHours(1),
signingCredentials: credentials);
return Ok(new
{
token = new JwtSecurityTokenHandler().WriteToken(token),
expires = token.ValidTo
});
}
[HttpPost]
public async Task<ActionResult<UserDto>> Add([FromBody] UserDto user)
{
await service.Add(user);
return Ok(user);
}
[HttpPut]
public async Task<ActionResult<UserDto>> Update([FromBody] UserDto user)
{
await service.Update(user);
return Ok(user);
}
[HttpDelete]
public async Task<ActionResult<UserDto>> Delete([FromQuery] Guid id)
{
await service.Delete(id);
return Ok();
}
}

View File

@@ -7,8 +7,11 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BCrypt.Net-Core" Version="1.6.0" />
<PackageReference Include="Hangfire" Version="1.8.17" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.11" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="8.0.11" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
@@ -20,6 +23,7 @@
<ItemGroup>
<ProjectReference Include="..\FaKrosnoEfDataModel\FaKrosnoEfDataModel.csproj" />
<ProjectReference Include="..\OrdersManagementDataModel\OrdersManagementDataModel.csproj" />
<ProjectReference Include="..\SytelineSaAppEfDataModel\SytelineSaAppEfDataModel.csproj" />
</ItemGroup>

View File

@@ -0,0 +1,7 @@
namespace FaKrosnoApi.Models;
public class AuthenticateRequestModel
{
public string Login { get; set; }
public string Password { get; set; }
}

View File

@@ -0,0 +1,11 @@
namespace FaKrosnoApi.Models;
public class EmailSettingsModel
{
public string SmtpServer { get; set; }
public int Port { get; set; }
public string SenderEmail { get; set; }
public string SenderPassword { get; set; }
public string RecipientEmail { get; set; }
public bool UseSsl { get; set; }
}

View File

@@ -0,0 +1,19 @@
using Hangfire.Common;
namespace FaKrosnoApi.Models;
public class JobModel(
string jobId,
string cron,
string path,
DateTime? lastExecution,
DateTime? nextExecution,
Job jobDetails)
{
public string JobId { get; set; } = jobId;
public string Cron { get; set; } = cron;
public string Path { get; set; } = path;
public DateTime? LastExecution { get; set; } = lastExecution;
public DateTime? NextExecution { get; set; } = nextExecution;
public Job JobDetails { get; set; } = jobDetails;
}

View File

@@ -0,0 +1,6 @@
namespace FaKrosnoApi.Models;
public class JobSettingsModel
{
public int QueryIntervalMinutes { get; set; }
}

View File

@@ -1,69 +1,112 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using FaKrosnoApi.Models;
using FaKrosnoApi.Services;
using FaKrosnoEfDataModel;
using FaKrosnoEfDataModel.Services;
using Hangfire;
using Hangfire.SqlServer;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using OrdersManagementDataModel;
using OrdersManagementDataModel.Services;
using SytelineSaAppEfDataModel;
using SytelineSaAppEfDataModel.Services;
using NSwag;
using NSwag.Generation.Processors.Security;
using FaKrosnoMappingProfile = FaKrosnoEfDataModel.MappingProfile;
using SytelineSaAppMappingProfile = SytelineSaAppEfDataModel.MappingProfile;
using OrdersManagementMappingProfile = OrdersManagementDataModel.MappingProfile;
var builder = WebApplication.CreateBuilder(args);
var configuration = builder.Configuration;
// Add services to the container.
builder.Services.AddDbContext<FaKrosnoDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("FaKrosnoConnection")));
builder.Services.AddDbContext<SytelineSaAppDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("SytelineSaAppConnection")));
builder.Services.AddDbContext<OrdersManagementDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("OrdersManagementConnection")));
builder.WebHost.UseUrls("http://*:5555");
builder.Services.Configure<EmailSettingsModel>(builder.Configuration.GetSection("EmailSettings"));
builder.Services.Configure<JobSettingsModel>(builder.Configuration.GetSection("JobSettings"));
builder.WebHost.UseUrls("http://*:5001");
// builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
// .AddJwtBearer(options =>
// {
// options.TokenValidationParameters = new TokenValidationParameters
// {
// ValidateIssuer = true,
// ValidateAudience = true,
// ValidateLifetime = true,
// ValidateIssuerSigningKey = true,
// ValidIssuer = builder.Configuration["Jwt:Issuer"],
// ValidAudience = builder.Configuration["Jwt:Audience"],
// IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"] ?? string.Empty)),
// NameClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"
// };
// });
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddOpenApiDocument(config =>
{
config.Title = "FaKrosnoApi";
config.Version = "v1";
config.AddSecurity("Bearer", new OpenApiSecurityScheme
{
Name = "Authorization",
Type = OpenApiSecuritySchemeType.Http,
Scheme = "Bearer",
BearerFormat = "JWT",
In = OpenApiSecurityApiKeyLocation.Header,
Description = "Wprowadź token JWT w formacie: Bearer {token}"
});
// Configure AutoMapper
builder.Services.AddAutoMapper(typeof(FaKrosnoMappingProfile), typeof(SytelineSaAppMappingProfile));
// Configure JWT Authentication
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
};
config.OperationProcessors.Add(new OperationSecurityScopeProcessor("Bearer"));
});
builder.Services.AddHangfire(config => config
.SetDataCompatibilityLevel(CompatibilityLevel.Version_170)
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseSqlServerStorage(builder.Configuration.GetConnectionString("OrdersManagementConnection"), new SqlServerStorageOptions
{
CommandBatchMaxTimeout = TimeSpan.FromMinutes(5),
SlidingInvisibilityTimeout = TimeSpan.FromMinutes(5),
QueuePollInterval = TimeSpan.Zero,
UseRecommendedIsolationLevel = true,
DisableGlobalLocks = true
}));
builder.Services.AddHangfireServer();
builder.Services.AddAutoMapper(typeof(FaKrosnoMappingProfile), typeof(SytelineSaAppMappingProfile),
typeof(OrdersManagementMappingProfile));
builder.Services.AddScoped<IScheduleOrderService, ScheduleOrderService>();
builder.Services.AddScoped<IScheduleOrderDetailsService, ScheduleOrderDetailsService>();
builder.Services.AddScoped<IEdiCustomerOrderService, EdiCustomerOrderService>();
builder.Services.AddScoped<IEdiCustomerOrderTranslateService, EdiCustomerOrderTranslateService>();
builder.Services.AddScoped<IErrorLogService, ErrorLogService>();
builder.Services.AddScoped<ICustomerOrderService, CustomerOrderService>();
builder.Services.AddScoped<IEmailService, EmailService>();
builder.Services.AddScoped<IScheduleJobService, ScheduleJobService>();
builder.Services.AddScoped<ITaskSchedulerService, TaskSchedulerService>();
builder.Services.AddScoped<IUserService, UserService>();
builder.Services.AddScoped<IRoleService, RoleService>();
builder.Services.AddScoped<IFunctionService, FunctionService>();
builder.Services.AddScoped<IUserRoleService, UserRoleService>();
builder.Services.AddScoped<IProductService, ProductService>();
builder.Services.AddHostedService<TimedHostedService>();
var app = builder.Build();
// Configure the HTTP request pipeline.
//if (app.Environment.IsDevelopment())
//{
app.UseOpenApi(); // Serwuje dokument OpenAPI
app.UseSwaggerUi(); // Dodaje interfejs u<>ytkownika Swagger
//}
app.UseOpenApi();
app.UseSwaggerUi();
app.UseHttpsRedirection();
@@ -72,4 +115,6 @@ app.UseAuthorization();
app.MapControllers();
app.UseHangfireDashboard();
app.Run();

View File

@@ -0,0 +1,30 @@
using System.Net;
using System.Net.Mail;
using FaKrosnoApi.Models;
using Microsoft.Extensions.Options;
namespace FaKrosnoApi.Services;
public class EmailService(IOptions<EmailSettingsModel> emailSettings) : IEmailService
{
private readonly EmailSettingsModel _emailSettings = emailSettings.Value;
public void SendEmail(string subject, string body)
{
using var smtpClient = new SmtpClient(_emailSettings.SmtpServer, _emailSettings.Port);
smtpClient.EnableSsl = true;
smtpClient.UseDefaultCredentials = false;
smtpClient.Credentials = new NetworkCredential(_emailSettings.SenderEmail, _emailSettings.SenderPassword);
var mailMessage = new MailMessage
{
From = new MailAddress(_emailSettings.SenderEmail),
Subject = subject,
Body = body
};
mailMessage.To.Add(_emailSettings.RecipientEmail);
smtpClient.Send(mailMessage);
}
}

View File

@@ -0,0 +1,6 @@
namespace FaKrosnoApi.Services;
public interface IEmailService
{
void SendEmail(string subject, string body);
}

View File

@@ -0,0 +1,6 @@
namespace FaKrosnoApi.Services;
public interface IScheduleJobService
{
Task ExecuteAsync();
}

View File

@@ -0,0 +1,29 @@
using System.Text;
using SytelineSaAppEfDataModel.Dtos;
using SytelineSaAppEfDataModel.Services;
namespace FaKrosnoApi.Services;
public class ScheduleJobService(IEmailService emailService, IServiceScopeFactory scopeFactory) : IScheduleJobService
{
public async Task ExecuteAsync()
{
using var scope = scopeFactory.CreateScope();
IEdiCustomerOrderService ediCustomerOrderService = scope.ServiceProvider.GetRequiredService<IEdiCustomerOrderService>();
IEnumerable<EdiCustomerOrderTranslateDto> missingOrders =
(await ediCustomerOrderService.FindMissingOrders(DateTime.Now.AddDays(-1))).ToList();
if (missingOrders.Any())
{
StringBuilder result = new StringBuilder();
result.AppendLine("Znaleziono brakujące zamówienia w bazie 'edi_co':");
foreach (EdiCustomerOrderTranslateDto missingOrder in missingOrders)
{
result.AppendLine($"- {missingOrder.EdiCoCoNum}");
}
emailService.SendEmail("Znaleziono brakujące zamówienia!", result.ToString());
}
}
}

View File

@@ -0,0 +1,32 @@
using SytelineSaAppEfDataModel.Services;
namespace FaKrosnoApi.Services;
public class TimedHostedService(IServiceScopeFactory scopeFactory) : IHostedService, IDisposable
{
private Timer? _timer;
public Task StartAsync(CancellationToken cancellationToken)
{
_timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromMinutes(30));
return Task.CompletedTask;
}
private void DoWork(object? state)
{
using var scope = scopeFactory.CreateScope();
var scheduledJob = scope.ServiceProvider.GetRequiredService<IScheduleJobService>();
scheduledJob.ExecuteAsync();
}
public Task StopAsync(CancellationToken cancellationToken)
{
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
_timer?.Dispose();
}
}

View File

@@ -1,7 +1,8 @@
{
"ConnectionStrings": {
"FaKrosnoConnection": "Server=192.168.0.7;Database=fakrosnotest;User Id=sa;Password=Tetum#2021!;TrustServerCertificate=true",
"SytelineSaAppConnection": "Server=192.168.0.7;Database=SL_PRODTEST_SA_APP;User Id=sa;Password=Tetum#2021!;TrustServerCertificate=true"
"FaKrosnoConnection": "Server=192.168.0.7;Database=fakrosno;User Id=sa;Password=Tetum#2021!;TrustServerCertificate=true",
"SytelineSaAppConnection": "Server=192.168.0.7;Database=SL_PROD_SA_APP;User Id=sa;Password=Tetum#2021!;TrustServerCertificate=true",
"OrdersManagementConnection": "Server=192.168.0.7;Database=OrdersManagement;User Id=sa;Password=Tetum#2021!;TrustServerCertificate=true"
},
"Logging": {
"LogLevel": {
@@ -10,11 +11,22 @@
}
},
"Jwt": {
"Key": "ThisIsASecretKeyForJwt",
"Key": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6A7B8C9D0E1F",
"Issuer": "FaKrosnoApi",
"Audience": "FaKrosnoClient"
},
"Host": {
"Urls": "http://0.0.0.0:5555"
"Urls": "http://0.0.0.0:5001"
},
"EmailSettings": {
"SmtpServer": "poczta.fakrosno.pl",
"Port": 587,
"SenderEmail": "edi@fakrosno.pl",
"SenderPassword": "F@Krosno2014",
"RecipientEmail": "piotr.kus@fakrosno.pl",
"UseSsl": false
},
"JobSettings": {
"QueryIntervalMinutes": 30
}
}

View File

@@ -0,0 +1,9 @@
namespace FaKrosnoEfDataModel.Dtos;
public class ProductDto : DtoBase
{
public int ID { get; set; }
public int RecipientID { get; set; }
public string RecipientIdx { get; set; }
public string FaIdx { get; set; }
}

View File

@@ -20,6 +20,6 @@ namespace FaKrosnoEfDataModel.Dtos
public DateTime? ShipDate { get; set; }
public DateTime LastUpdateDate { get; set; }
public IList<ScheduleOrderDetailDetailMiscDto> ScheduleOrderDetailDetailMiscs { get; set; }
public IList<ScheduleOrderDetailDetailMiscDto>? ScheduleOrderDetailDetailMiscs { get; set; }
}
}

View File

@@ -13,5 +13,7 @@ namespace FaKrosnoEfDataModel.Dtos
public string Value { get; set; }
public string? Label { get; set; }
public bool Display { get; set; }
public string Text => $"{Label}:\t{Value}";
}
}

View File

@@ -13,7 +13,11 @@ namespace FaKrosnoEfDataModel.Dtos
public string Sh_productCode { get; set; }
public int? Price { get; set; }
public string? OrderNumber {get; set;}
public string? RecipientName {get; set;}
public string? RecipientCode {get; set;}
public string? PurchaserName {get; set;}
public IList<ScheduleOrderDetailDetailDto> ScheduleOrderDetailDetails { get; set; }
public IList<ScheduleOrderDetailMiscDto> ScheduleOrderDetailMiscs { get; set; }
public IList<ScheduleOrderDetailMiscDto>? ScheduleOrderDetailMiscs { get; set; }
}
}

View File

@@ -13,5 +13,7 @@ namespace FaKrosnoEfDataModel.Dtos
public string Value { get; set; }
public string? Label { get; set; }
public bool Display { get; set; }
public string Text => $"{Label}:\t{Value}";
}
}

View File

@@ -15,8 +15,10 @@ namespace FaKrosnoEfDataModel.Dtos
public int DocNumber { get; set; }
public string? DocType { get; set; }
public string? RecipientCode => Recipient.RecipientCode;
public string RecipientCode => Recipient.RecipientCode;
public string? PurchaserCode => Recipient.Purchaser?.PurchaserCode;
public string RecipientName => Recipient.RecipientDesc;
public string? PurchaserName => Recipient.Purchaser?.PurchaserDesc;
public RecipientDto Recipient { get; set; }
public IList<ScheduleOrderDetailDto> ScheduleOrderDetails { get; set; }

View File

@@ -13,5 +13,7 @@ namespace FaKrosnoEfDataModel.Dtos
public string Value { get; set; }
public string? Label { get; set; }
public bool Display { get; set; }
public string Text => $"{Label}:\t{Value}";
}
}

View File

@@ -0,0 +1,9 @@
namespace FaKrosnoEfDataModel.Entities;
public class Product : EntityBase
{
public int ID { get; set; }
public int RecipientID { get; set; }
public string RecipientIdx { get; set; }
public string FaIdx { get; set; }
}

View File

@@ -21,6 +21,7 @@ namespace FaKrosnoEfDataModel
public DbSet<ScheduleOrderDetailDetailMisc> ScheduleOrderDetailDetailMiscs { get; set; }
public DbSet<ScheduleOrderDetailMisc> ScheduleOrderDetailMiscs { get; set; }
public DbSet<ScheduleOrderMisc> ScheduleOrderMiscs { get; set; }
public DbSet<Product> Products { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
@@ -85,6 +86,36 @@ namespace FaKrosnoEfDataModel
entity.Property(x => x.QtyDesc).IsRequired(false);
entity.Property(x => x.ShipDate).IsRequired(false);
});
modelBuilder.Entity<Product>(entity =>
{
entity.ToTable("product");
entity.HasKey(e => e.ID);
entity.Property(e => e.ID)
.HasColumnName("ID")
.ValueGeneratedOnAdd();
entity.Property(e => e.RecipientID)
.HasColumnName("recipientID")
.IsRequired();
entity.Property(e => e.RecipientIdx)
.HasColumnName("recipientIdx")
.HasMaxLength(50)
.IsRequired();
entity.Property(e => e.FaIdx)
.HasColumnName("faIdx")
.HasMaxLength(50)
.IsRequired();
// Define the unique constraint for recipientID and recipientIdx
entity.HasIndex(e => new { e.RecipientID, e.RecipientIdx })
.HasDatabaseName("IX_product")
.IsUnique();
});
}
}
}

View File

@@ -20,6 +20,7 @@ namespace FaKrosnoEfDataModel
CreateMap<ScheduleOrderDetailMisc, ScheduleOrderDetailMiscDto>().IncludeBase<EntityBase, DtoBase>()
.ReverseMap();
CreateMap<ScheduleOrderMisc, ScheduleOrderMiscDto>().IncludeBase<EntityBase, DtoBase>().ReverseMap();
CreateMap<Product, ProductDto>().IncludeBase<EntityBase, DtoBase>().ReverseMap();
}
}
}

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FaKrosnoEfDataModel.Entities;
using FaKrosnoEfDataModel.Entities;
using Microsoft.EntityFrameworkCore;
namespace FaKrosnoEfDataModel.Queries
@@ -16,6 +11,11 @@ namespace FaKrosnoEfDataModel.Queries
.Include(x => x.ScheduleOrderDetails).ThenInclude(x => x.ScheduleOrderDetailDetails)
.ThenInclude(x => x.ScheduleOrderDetailDetailMiscs).Include(x => x.ScheduleOrderMiscs));
public static readonly Func<FaKrosnoDbContext, int, IEnumerable<ScheduleOrder?>> GetEntitiesByPurchaser =
EF.CompileQuery((FaKrosnoDbContext context, int purchaser) => context.ScheduleOrders
.Include(x => x.Recipient).ThenInclude(x => x.Purchaser).Include(x => x.ScheduleOrderDetails)
.ThenInclude(x => x.ScheduleOrderDetailMiscs).Where(x => x.Recipient.Purchaser.ID == purchaser));
public static readonly Func<FaKrosnoDbContext, DateTime, IEnumerable<ScheduleOrder?>> GetEntitiesByDate =
EF.CompileQuery((FaKrosnoDbContext context, DateTime fromDate) => context.ScheduleOrders
.Include(x => x.Recipient).ThenInclude(x => x.Purchaser).Include(x => x.ScheduleOrderDetails)

View File

@@ -0,0 +1,10 @@
using FaKrosnoEfDataModel.Dtos;
namespace FaKrosnoEfDataModel.Services;
public interface IProductService
{
Task<IEnumerable<ProductDto?>> GetEntities();
Task<IEnumerable<ProductDto?>> GetEntitiesToFix(string indexName);
Task UpdateEntity(ProductDto entity);
}

View File

@@ -10,5 +10,8 @@ namespace FaKrosnoEfDataModel.Services
public interface IScheduleOrderDetailsService
{
Task<IEnumerable<ScheduleOrderDetailDto>?> GetScheduleOrderDetailsAsync(int scheduleOrderId);
Task<IEnumerable<ScheduleOrderDetailDetailDto>> GetScheduleOrderDetailsDetailsByIdAsync(
int scheduleOrderDetailId);
}
}

View File

@@ -12,6 +12,7 @@ namespace FaKrosnoEfDataModel.Services
Task<IEnumerable<ScheduleOrderDto?>> GetEntities();
Task<ScheduleOrderDto?> GetById(int id);
Task<IEnumerable<ScheduleOrderDto?>> GetByRecipientId(int recipientId);
Task<IEnumerable<ScheduleOrderDto>> GetByPurchaserId(int purchaserId);
Task<IEnumerable<ScheduleOrderDto?>> GetEntitiesByLastUpdateDate(DateTime date);
Task<IEnumerable<ScheduleOrderDto?>> GetByRecipientAndLastUpdateDate(int recipientId, DateTime date);
}

View File

@@ -0,0 +1,39 @@
using AutoMapper;
using FaKrosnoEfDataModel.Dtos;
using FaKrosnoEfDataModel.Entities;
using Microsoft.EntityFrameworkCore;
namespace FaKrosnoEfDataModel.Services;
public class ProductService : ServiceBase<ProductDto>, IProductService
{
public ProductService(FaKrosnoDbContext context, IMapper mapper) : base(context, mapper)
{
}
public async Task<IEnumerable<ProductDto?>> GetEntities()
{
IList<ProductDto> products = (await GetAll()).ToList();
return products;
}
public async Task<IEnumerable<ProductDto?>> GetEntitiesToFix(string indexName)
{
IList<ProductDto> products = (await GetAll()).ToList();
return products.Where(x => x?.FaIdx == indexName);
}
public async Task UpdateEntity(ProductDto entity)
{
Product? product = await Context.Products.FirstOrDefaultAsync(x => x.ID == entity.ID);
if (product != null)
{
product.FaIdx = entity.FaIdx;
Context.Products.Update(product);
await Context.SaveChangesAsync();
}
}
}

View File

@@ -1,9 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using AutoMapper;
using AutoMapper;
using AutoMapper.QueryableExtensions;
using FaKrosnoEfDataModel.Dtos;
using Microsoft.EntityFrameworkCore;
@@ -21,5 +16,11 @@ namespace FaKrosnoEfDataModel.Services
return await Context.ScheduleOrderDetails.Where(x => x.ScheduleOrderID == scheduleOrderId)
.ProjectTo<ScheduleOrderDetailDto>(Mapper.ConfigurationProvider).ToListAsync();
}
public async Task<IEnumerable<ScheduleOrderDetailDetailDto>> GetScheduleOrderDetailsDetailsByIdAsync(int scheduleOrderDetailId)
{
return await Context.ScheduleOrderDetailDetails.Where(x => x.ScheduleOrderDetailID == scheduleOrderDetailId)
.ProjectTo<ScheduleOrderDetailDetailDto>(Mapper.ConfigurationProvider).ToListAsync();
}
}
}

View File

@@ -26,6 +26,14 @@ namespace FaKrosnoEfDataModel.Services
return scheduleOrders.Where(x => x?.RecipientID == recipientId);
}
public async Task<IEnumerable<ScheduleOrderDto>> GetByPurchaserId(int purchaserId)
{
IEnumerable<ScheduleOrder?> scheduleOrders =
(await Task.FromResult(ScheduleOrderQueries.GetEntitiesByPurchaser(Context, purchaserId))).ToList();
return scheduleOrders.Select(x => Mapper.Map<ScheduleOrderDto>(x));
}
public async Task<IEnumerable<ScheduleOrderDto?>> GetByRecipientAndLastUpdateDate(int recipientId, DateTime date)
{
IList<ScheduleOrderDto?> scheduleOrders = (await GetEntitiesByLastUpdateDate(date)).ToList();
@@ -35,7 +43,7 @@ namespace FaKrosnoEfDataModel.Services
public async Task<IEnumerable<ScheduleOrderDto?>> GetEntities()
{
IList<ScheduleOrder> scheduleOrders = await Context.ScheduleOrders.Include(x => x.Recipient)
IList<ScheduleOrder> scheduleOrders = await Context.ScheduleOrders.Include(x => x.ScheduleOrderDetails).Include(x => x.Recipient)
.ThenInclude(x => x.Purchaser).ToListAsync();
return Mapper.Map<IEnumerable<ScheduleOrderDto>>(scheduleOrders);

View File

@@ -1,4 +1,6 @@
<!DOCTYPE html>
@using Microsoft.AspNetCore.Components.Authorization
@using OrdersManagement.Components.Layout
<!DOCTYPE html>
<html lang="en">
<head>
@@ -8,8 +10,11 @@
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous" />
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.3/font/bootstrap-icons.css" rel="stylesheet" />
<link href="_content/Blazor.Bootstrap/blazor.bootstrap.css" rel="stylesheet" />
<link href="_content/Syncfusion.Blazor.Themes/bootstrap5.css" rel="stylesheet" />
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/css/all.min.css" integrity="sha512-Fo3rlrZj/k7ujTnHg4CGR2D7kSs0v4LLanw2qksYuRlEzO+tcaEPQogQ0KaoGN26/zrn20ImR1DfuLWnOo7aBA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<link rel="stylesheet" href="app.css" />
<link rel="stylesheet" href="OrdersManagement.styles.css" />
<link href="material.css" rel="stylesheet"/>
<HeadOutlet @rendermode="@InteractiveServer" />
</head>
@@ -17,12 +22,11 @@
<Routes @rendermode="@InteractiveServer" />
<script src="_framework/blazor.web.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
<!-- Add chart.js reference if chart components are used in your application. -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.0.1/chart.umd.js" integrity="sha512-gQhCDsnnnUfaRzD8k1L5llCCV6O9HN09zClIzzeJ8OJ9MpGmIlCxm+pdCkqTwqJ4JcjbojFr79rl2F1mzcoLMQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<!-- Add chartjs-plugin-datalabels.min.js reference if chart components with data label feature is used in your application. -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/chartjs-plugin-datalabels/2.2.0/chartjs-plugin-datalabels.min.js" integrity="sha512-JPcRR8yFa8mmCsfrw4TNte1ZvF1e3+1SdGMslZvmrzDYxS69J7J49vkFL8u6u8PlPJK+H3voElBtUCzaXj+6ig==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.jsdelivr.net/npm/sortablejs@latest/Sortable.min.js"></script>
<script src="_content/Blazor.Bootstrap/blazor.bootstrap.js"></script>
<script src="_content/Syncfusion.Blazor.Core/scripts/syncfusion-blazor.min.js" type="text/javascript"></script>
</body>
</html>

View File

@@ -1,49 +1,91 @@
@using BlazorBootstrap
@inherits LayoutComponentBase
@inherits LayoutComponentBase
<div class="bb-page">
@using System.Security.Claims
@using Microsoft.AspNetCore.Components.Authorization
@using Syncfusion.Blazor.Navigations
@using static Syncfusion.Blazor.Navigations.Orientation
@using Syncfusion.Blazor.Buttons
@inject NavigationManager NavigationManager
@inject CustomAuthenticationStateProvider AuthenticationStateProvider
<Sidebar @ref="_sidebar"
IconName="IconName.App"
Title="FA Krosno Manager"
DataProvider="SidebarDataProvider" />
<main>
<div class="bb-top-row px-4 d-flex justify-content-end">
<a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
<div class="page h-100 d-flex flex-column">
<main class="container-fluid d-flex flex-column h-100">
<div class="bb-top-row px-4 d-flex justify-content-between align-items-center mb-3 shadow-sm"
style="background-color: #f8f9fa;">
<div class="d-flex align-items-center" style="margin: 10px">
<img src="logo.svg" class="me-2" width="35" height="35" alt="Icon">
<h3 class="text-primary m-0">FA Krosno Manager</h3>
</div>
<article class="content px-4">
<div class="py-2">@Body</div>
@* <div class="d-flex align-items-center"> *@
@* @if (IsAuthenticated) *@
@* { *@
@* <span class="me-2">Jesteś zalogowany jako <strong>@UserName</strong></span> *@
@* <SfButton CssClass="e-primary" IsPrimary="true" @onclick="Logout">Wyloguj</SfButton> *@
@* } *@
@* else *@
@* { *@
@* <a href="/login" class="text-muted">Zaloguj</a> *@
@* } *@
@* </div> *@
</div>
<div class="row gx-1 flex-grow-1">
<div class="col-auto custom-menu-width">
<SfMenu TValue="MenuItem" HamburgerMode="true" Orientation="Vertical" Title="Menu">
<MenuItems>
<MenuItem Text="Zamówienia DELFOR" Url="/" IconCss="fa-solid fa-landmark"></MenuItem>
<MenuItem Text="Zarządzanie Indeksami" Url="/Products" IconCss="fa-solid fa-basket-shopping"></MenuItem>
@* <MenuItem Text="Zamówienia klienta EDI" Url="/EdiCustomerOrders" IconCss="fa-solid fa-list-check"></MenuItem> *@
@* <MenuItem Text="Zamówienia klienta" Url="/CustomerOrders" IconCss="fa-solid fa-database"></MenuItem> *@
@if (UserName == "pkus")
{
<MenuItem Text="Admin" IconCss="fa-solid fa-screwdriver-wrench">
<MenuItems>
<MenuItem Text = "Użytkownicy" Url = "/Admin/UsersManager" IconCss="fa-solid fa-user-tie"></MenuItem>
<MenuItem Text= "Scheduler" Url = "/Admin/Scheduler" IconCss="fa-solid fa-calendar-week"></MenuItem>
</MenuItems>
</MenuItem>
}
</MenuItems>
<MenuAnimationSettings Effect="MenuEffect.SlideDown" Duration="800"></MenuAnimationSettings>
</SfMenu>
</div>
<article class="content col d-flex flex-column">
<div class="py-2 flex-grow-1">@Body</div>
<footer class="text-center text-muted py-2">
<small>FA Krosno Manager © @(DateTime.Now.Year)</small>
</footer>
</article>
</div>
</main>
</div>
@code {
Sidebar? _sidebar;
IEnumerable<NavItem>? _navItems;
private bool IsAuthenticated { get; set; }
private string UserName { get; set; } = string.Empty;
private async Task<SidebarDataProviderResult> SidebarDataProvider(SidebarDataProviderRequest request)
protected override void OnInitialized()
{
_navItems ??= GetNavItems();
return await Task.FromResult(request.ApplyTo(_navItems));
// ClaimsPrincipal currentUser = AuthenticationStateProvider.GetCurrentUser();
// IsAuthenticated = currentUser.Identity?.IsAuthenticated == true;
// UserName = currentUser.Identity?.Name ?? "Nieznany użytkownik";
//
// AuthenticationStateProvider.AuthenticationStateChanged += OnAuthenticationStateChanged;
}
private IEnumerable<NavItem>? GetNavItems()
private async void OnAuthenticationStateChanged(Task<AuthenticationState> task)
{
_navItems = new List<NavItem>
{
new NavItem { Id = "1", Href = "/", IconName = IconName.HouseDoorFill, Text = "Zamówienia DELFOR", Match=NavLinkMatch.All},
new NavItem { Id = "2", Href = "/EdiCustomerOrders", IconName = IconName.Database, Text = "Zamówienia klienta EDI"},
new NavItem { Id = "3", Href = "/CustomerOrders", IconName = IconName.Database, Text = "Zamówienia klienta"}
};
return _navItems;
}
var authState = await task;
IsAuthenticated = authState.User.Identity?.IsAuthenticated ?? false;
UserName = IsAuthenticated ? authState.User.Identity?.Name ?? "Nieznany użytkownik" : string.Empty;
StateHasChanged();
}
private void Logout()
{
NavigationManager.NavigateTo("/");
}
}
<div id="blazor-error-ui">
An unhandled error has occurred.

View File

@@ -1,30 +0,0 @@
<div class="top-row ps-3 navbar navbar-dark">
<div class="container-fluid">
<a class="navbar-brand" href="">OrdersManagement</a>
</div>
</div>
<input type="checkbox" title="Navigation menu" class="navbar-toggler" />
<div class="nav-scrollable" onclick="document.querySelector('.navbar-toggler').click()">
<nav class="flex-column">
<div class="nav-item px-3">
<NavLink class="nav-link" href="" Match="NavLinkMatch.All">
<span class="bi bi-house-door-fill-nav-menu" aria-hidden="true"></span> Home
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="counter">
<span class="bi bi-plus-square-fill-nav-menu" aria-hidden="true"></span> Counter
</NavLink>
</div>
<div class="nav-item px-3">
<NavLink class="nav-link" href="weather">
<span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Weather
</NavLink>
</div>
</nav>
</div>

View File

@@ -1,105 +0,0 @@
.navbar-toggler {
appearance: none;
cursor: pointer;
width: 3.5rem;
height: 2.5rem;
color: white;
position: absolute;
top: 0.5rem;
right: 1rem;
border: 1px solid rgba(255, 255, 255, 0.1);
background: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 30 30'%3e%3cpath stroke='rgba%28255, 255, 255, 0.55%29' stroke-linecap='round' stroke-miterlimit='10' stroke-width='2' d='M4 7h22M4 15h22M4 23h22'/%3e%3c/svg%3e") no-repeat center/1.75rem rgba(255, 255, 255, 0.1);
}
.navbar-toggler:checked {
background-color: rgba(255, 255, 255, 0.5);
}
.top-row {
height: 3.5rem;
background-color: rgba(0,0,0,0.4);
}
.navbar-brand {
font-size: 1.1rem;
}
.bi {
display: inline-block;
position: relative;
width: 1.25rem;
height: 1.25rem;
margin-right: 0.75rem;
top: -1px;
background-size: cover;
}
.bi-house-door-fill-nav-menu {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-house-door-fill' viewBox='0 0 16 16'%3E%3Cpath d='M6.5 14.5v-3.505c0-.245.25-.495.5-.495h2c.25 0 .5.25.5.5v3.5a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5v-7a.5.5 0 0 0-.146-.354L13 5.793V2.5a.5.5 0 0 0-.5-.5h-1a.5.5 0 0 0-.5.5v1.293L8.354 1.146a.5.5 0 0 0-.708 0l-6 6A.5.5 0 0 0 1.5 7.5v7a.5.5 0 0 0 .5.5h4a.5.5 0 0 0 .5-.5Z'/%3E%3C/svg%3E");
}
.bi-plus-square-fill-nav-menu {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-plus-square-fill' viewBox='0 0 16 16'%3E%3Cpath d='M2 0a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V2a2 2 0 0 0-2-2H2zm6.5 4.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3a.5.5 0 0 1 1 0z'/%3E%3C/svg%3E");
}
.bi-list-nested-nav-menu {
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='white' class='bi bi-list-nested' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.5 11.5A.5.5 0 0 1 5 11h10a.5.5 0 0 1 0 1H5a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 3 7h10a.5.5 0 0 1 0 1H3a.5.5 0 0 1-.5-.5zm-2-4A.5.5 0 0 1 1 3h10a.5.5 0 0 1 0 1H1a.5.5 0 0 1-.5-.5z'/%3E%3C/svg%3E");
}
.nav-item {
font-size: 0.9rem;
padding-bottom: 0.5rem;
}
.nav-item:first-of-type {
padding-top: 1rem;
}
.nav-item:last-of-type {
padding-bottom: 1rem;
}
.nav-item ::deep .nav-link {
color: #d7d7d7;
background: none;
border: none;
border-radius: 4px;
height: 3rem;
display: flex;
align-items: center;
line-height: 3rem;
width: 100%;
}
.nav-item ::deep a.active {
background-color: rgba(255,255,255,0.37);
color: white;
}
.nav-item ::deep .nav-link:hover {
background-color: rgba(255,255,255,0.1);
color: white;
}
.nav-scrollable {
display: none;
}
.navbar-toggler:checked ~ .nav-scrollable {
display: block;
}
@media (min-width: 641px) {
.navbar-toggler {
display: none;
}
.nav-scrollable {
/* Never collapse the sidebar for wide screens */
display: block;
/* Allow sidebar to scroll for tall menus */
height: calc(100vh - 3.5rem);
overflow-y: auto;
}
}

View File

@@ -0,0 +1,114 @@
@page "/Admin/Scheduler"
@using System.Security.Claims
@using Microsoft.AspNetCore.Authorization
@using OrdersManagementDataModel.Dtos
@using Syncfusion.Blazor.Grids
@using Action = Syncfusion.Blazor.Grids.Action
@using Syncfusion.Blazor.Cards
@inject HangfireService HangfireService
@inject NavigationManager NavigationManager
@inject CustomAuthenticationStateProvider CustomAuthenticationStateProvider
<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">Zarządzanie Zadaniami</h3>
</CardHeader>
<CardContent>
<SfGrid DataSource="@Tasks"
AllowPaging="true"
ShowColumnMenu="true"
Toolbar="@(new List<string> { "Add", "Edit", "Delete", "Cancel", "Update" })">
<GridColumns>
<GridColumn Field=@nameof(TaskSchedulerDto.RowPointer) AllowEditing="false" IsPrimaryKey="true" HeaderText="Id"
Width="100"></GridColumn>
<GridColumn Field=@nameof(TaskSchedulerDto.Name) HeaderText="Nazwa" Width="150"></GridColumn>
<GridColumn Field=@nameof(TaskSchedulerDto.Path) HeaderText="Ścieżka" Width="200"></GridColumn>
<GridColumn Field=@nameof(TaskSchedulerDto.CronOptions) HeaderText="CRON" Width="120"></GridColumn>
<GridColumn Field=@nameof(TaskSchedulerDto.LastExecution) AllowEditing="false" HeaderText="Ostatnie Uruchomienie"
Width="150"></GridColumn>
<GridColumn Field=@nameof(TaskSchedulerDto.NextExecution) AllowEditing="false" HeaderText="Następne Uruchomienie"
Width="150"></GridColumn>
</GridColumns>
<GridEditSettings AllowDeleting="true"
ShowDeleteConfirmDialog="true"
AllowAdding="true"
NewRowPosition="NewRowPosition.Bottom"
AllowEditing="true">
</GridEditSettings>
<GridEvents OnActionBegin="OnActionBegin"
OnActionComplete="OnActionComplete"
TValue="TaskSchedulerDto">
</GridEvents>
<GridPageSettings PageSize="10"></GridPageSettings>
</SfGrid>
</CardContent>
<CardFooter>
<small class="text-muted">FA Krosno Manager © @(DateTime.Now.Year)</small>
</CardFooter>
</SfCard>
</div>
@code {
private List<TaskSchedulerDto> Tasks { get; set; } = new();
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
// ClaimsPrincipal currentUser = CustomAuthenticationStateProvider.GetCurrentUser();
//
// if (currentUser.Identity?.IsAuthenticated == false || currentUser.Identity?.Name != "pkus")
// {
// NavigationManager.NavigateTo("/Unauthorized");
// }
// else
// {
await LoadTasks();
StateHasChanged();
// }
}
}
public async Task OnActionBegin(ActionEventArgs<TaskSchedulerDto> args)
{
if (args.RequestType.Equals(Action.Delete))
{
await HangfireService.DeleteTaskSchedulerAsync(args.Data);
}
else if (args.RequestType.Equals(Action.Add))
{
args.Data.RowPointer = Guid.NewGuid();
}
}
private async Task AddTask(TaskSchedulerDto taskSchedulerDto)
{
var response = await HangfireService.AddTaskSchedulerAsync(taskSchedulerDto);
if (response == 1)
{
await LoadTasks();
}
}
private async Task LoadTasks()
{
Tasks = (await HangfireService.GetTaskSchedulersAsync() ?? Array.Empty<TaskSchedulerDto>()).ToList();
}
private async Task OnActionComplete(ActionEventArgs<TaskSchedulerDto> args)
{
switch (args.RequestType)
{
case Action.Delete:
await LoadTasks();
break;
case Action.Save when args.Data.Id == 0:
await AddTask(args.Data);
break;
}
}
}

View File

@@ -0,0 +1,296 @@
@page "/admin/UsersManager"
@using System.Security.Claims
@using Microsoft.AspNetCore.Authorization
@using OrdersManagementDataModel.Dtos
@using Syncfusion.Blazor.Grids
@using Action = Syncfusion.Blazor.Grids.Action
@using UserService = OrdersManagement.Services.UserService
@using Syncfusion.Blazor.Cards
@using Syncfusion.Blazor.Popups
@using Syncfusion.Blazor.Buttons
@inject UserService UserService
@inject RoleService RoleService
@inject FunctionService FunctionService
@inject NavigationManager NavigationManager
@inject CustomAuthenticationStateProvider CustomAuthenticationStateProvider
<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">Zarządzanie Użytkownikami i Rolami</h3>
</CardHeader>
<CardContent>
<h5 class="text-primary mb-3">Użytkownicy</h5>
<SfGrid DataSource="@UserList"
AllowPaging="true"
ShowColumnMenu="true"
Toolbar="@(new List<string> { "Add", "Edit", "Delete", "Cancel", "Update" })">
<GridColumns>
<GridColumn Field="@nameof(UserDto.RowPointer)" AllowEditing="false" IsPrimaryKey="true" HeaderText="ID" Width="70"></GridColumn>
<GridColumn Field="@nameof(UserDto.Login)" HeaderText="Login" Width="100"></GridColumn>
<GridColumn Field="@nameof(UserDto.Email)" HeaderText="Email" Width="150"></GridColumn>
<GridColumn Field="@nameof(UserDto.FirstName)" HeaderText="Imię" Width="100"></GridColumn>
<GridColumn Field="@nameof(UserDto.LastName)" HeaderText="Nazwisko" Width="100"></GridColumn>
<GridColumn Field="@nameof(UserDto.IsActive)" HeaderText="Aktywny" Width="80"></GridColumn>
<GridColumn Field="@nameof(UserDto.CreatedDate)" AllowEditing="false" HeaderText="Utworzono" Format="d" Width="120"></GridColumn>
<GridColumn HeaderText="" Width="100">
<Template>
@{
var user = (context as UserDto);
<SfButton CssClass="e-small e-primary" @onclick="() => ResetPassword(user)">Zresetuj haslo</SfButton>
}
</Template>
</GridColumn>
</GridColumns>
<GridEditSettings AllowDeleting="true"
ShowDeleteConfirmDialog="true"
AllowAdding="true"
NewRowPosition="NewRowPosition.Bottom"
AllowEditing="true">
</GridEditSettings>
<GridEvents OnActionBegin="UserActionBegin"
OnActionComplete="UserActionComplete"
TValue="UserDto">
</GridEvents>
<GridPageSettings PageSize="10"></GridPageSettings>
</SfGrid>
<h5 class="text-primary mb-3 mt-4">Role</h5>
<SfGrid DataSource="@Roles"
AllowPaging="true"
ShowColumnMenu="true"
Toolbar="@(new List<string> { "Add", "Edit", "Delete", "Cancel", "Update" })">
<GridColumns>
<GridColumn Field="@nameof(RoleDto.Id)" IsPrimaryKey="true" HeaderText="ID" Width="70"></GridColumn>
<GridColumn Field="@nameof(RoleDto.Name)" HeaderText="Nazwa" Width="150"></GridColumn>
</GridColumns>
<GridEditSettings AllowDeleting="true"
ShowDeleteConfirmDialog="true"
AllowAdding="true"
AllowEditing="true"
Mode="EditMode.Normal">
</GridEditSettings>
<GridEvents OnActionBegin="RoleActionBegin"
OnActionComplete="RoleActionComplete"
TValue="RoleDto">
</GridEvents>
<GridPageSettings PageSize="10"></GridPageSettings>
</SfGrid>
<h5 class="text-primary mb-3 mt-4">Funkcje</h5>
<SfGrid DataSource="@Functions"
AllowPaging="true"
ShowColumnMenu="true"
Toolbar="@(new List<string> { "Add", "Edit", "Delete", "Cancel", "Update" })">
<GridColumns>
<GridColumn Field="@nameof(FunctionDto.Id)" IsPrimaryKey="true" HeaderText="ID" Width="70"></GridColumn>
<GridColumn Field="@nameof(FunctionDto.RoleId)" HeaderText="ID Roli" Width="70"></GridColumn>
<GridColumn Field="@nameof(FunctionDto.Name)" HeaderText="Nazwa Funkcji" Width="200"></GridColumn>
</GridColumns>
<GridEditSettings AllowDeleting="true"
ShowDeleteConfirmDialog="true"
AllowAdding="true"
AllowEditing="true"
Mode="EditMode.Normal">
</GridEditSettings>
<GridEvents OnActionBegin="FunctionActionBegin"
OnActionComplete="FunctionActionComplete"
TValue="FunctionDto">
</GridEvents>
<GridPageSettings PageSize="10"></GridPageSettings>
</SfGrid>
<SfDialog Width="500px" Title="Dodano użytkownika!" IsModal="true" @bind-Visible="Visibility" AllowPrerender="true">
<DialogTemplates>
<Content>
<p>Użytkownik <strong>@Login</strong> został dodany pomyślnie!</p>
<p>Hasło tymczasowe: <strong>@TempPassword</strong></p>
</Content>
</DialogTemplates>
<DialogButtons>
<DialogButton Content="OK" IsPrimary="true" OnClick="@HideModal"/>
</DialogButtons>
</SfDialog>
</CardContent>
<CardFooter>
<small class="text-muted">FA Krosno Manager © @(DateTime.Now.Year)</small>
</CardFooter>
</SfCard>
</div>
@code {
private List<UserDto> UserList { get; set; } = new();
private List<RoleDto> Roles { get; set; } = new();
private List<FunctionDto> Functions { get; set; } = new();
private bool Visibility { get; set; }
private string Login { get; set; } = string.Empty;
private string TempPassword { get; set; } = string.Empty;
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
Visibility = false;
// ClaimsPrincipal currentUser = CustomAuthenticationStateProvider.GetCurrentUser();
//
// if (currentUser.Identity?.IsAuthenticated == false || currentUser.Identity?.Name != "pkus")
// {
// NavigationManager.NavigateTo("/Unauthorized");
// }
// else
// {
await LoadUsers();
await LoadRoles();
//await LoadFunctions();
StateHasChanged();
// }
}
}
private async Task LoadUsers()
{
UserList = (await UserService.GetUsersAsync() ?? Array.Empty<UserDto>()).ToList();
}
private async Task LoadRoles()
{
Roles = (await RoleService.GetRolesAsync() ?? Array.Empty<RoleDto>()).ToList();
}
private async Task LoadFunctions()
{
Functions = (await FunctionService.GetFunctionsAsync() ?? Array.Empty<FunctionDto>()).ToList();
}
public async Task ResetPassword(UserDto? user)
{
if(user == null) return;
TempPassword = Guid.NewGuid().ToString().Substring(0, 8);
Login = user.Login;
string passwordHash = BCrypt.Net.BCrypt.HashPassword(TempPassword);
user.PasswordHash = passwordHash;
user.IsTemporaryPassword = true;
await UserService.UpdateUserAsync(user);
await LoadUsers();
Visibility = true;
}
private async Task UserActionBegin(ActionEventArgs<UserDto> args)
{
switch (args.RequestType)
{
case Action.Delete:
await UserService.DeleteUserAsync(args.Data.RowPointer);
break;
case Action.Add:
args.Data.RowPointer = Guid.NewGuid();
args.Data.CreatedDate = DateTime.Now;
args.Data.IsActive = true;
break;
}
}
private async Task UserActionComplete(ActionEventArgs<UserDto> args)
{
switch (args.RequestType)
{
case Action.Delete:
await LoadUsers();
break;
case Action.Save when args.Data.Id == 0:
UserDto? user = args.Data;
TempPassword = Guid.NewGuid().ToString().Substring(0, 8);
Login = user.Login;
string? passwordHash = BCrypt.Net.BCrypt.HashPassword(TempPassword);
user.PasswordHash = passwordHash;
user.IsTemporaryPassword = true;
user.ActiveFrom = DateTime.Now;
user.CreatedDate = DateTime.Now;
await UserService.AddUserAsync(user);
await LoadUsers();
Visibility = true;
break;
case Action.Save when args.Data.Id != 0:
await UserService.UpdateUserAsync(args.Data);
await LoadUsers();
break;
}
}
private async Task RoleActionBegin(ActionEventArgs<RoleDto> args)
{
if (args.RequestType.Equals(Action.Delete))
{
await RoleService.DeleteRoleAsync(args.Data.RowPointer);
}
else if (args.RequestType.Equals(Action.Add))
{
args.Data.RowPointer = Guid.NewGuid();
}
}
private async Task RoleActionComplete(ActionEventArgs<RoleDto> args)
{
switch (args.RequestType)
{
case Action.Delete:
await LoadRoles();
break;
case Action.Save when args.Data.Id == 0:
await RoleService.AddRoleAsync(args.Data);
await LoadUsers();
break;
case Action.Save when args.Data.Id != 0:
await RoleService.UpdateRoleAsync(args.Data);
await LoadRoles();
break;
}
}
private async Task FunctionActionBegin(ActionEventArgs<FunctionDto> args)
{
if (args.RequestType.Equals(Action.Delete))
{
await FunctionService.DeleteFunctionAsync(args.Data.RowPointer);
}
else if (args.RequestType.Equals(Action.Add))
{
args.Data.RowPointer = Guid.NewGuid();
}
}
private async Task FunctionActionComplete(ActionEventArgs<FunctionDto> args)
{
switch (args.RequestType)
{
case Action.Delete:
await LoadFunctions();
break;
case Action.Save when args.Data.Id == 0:
await FunctionService.AddFunctionAsync(args.Data);
await LoadFunctions();
break;
case Action.Save when args.Data.Id != 0:
await FunctionService.UpdateFunctionAsync(args.Data);
await LoadFunctions();
break;
}
}
private void HideModal()
{
Visibility = false;
}
}

View File

@@ -2,262 +2,218 @@
@inject CustomerOrderService CustomerOrderService
@inject ScheduleOrderService ScheduleOrderService
@inject NavigationManager NavigationManager
@inject CustomAuthenticationStateProvider CustomAuthenticationStateProvider
@using System.Security.Claims
@using Microsoft.AspNetCore.Authorization
@using SytelineSaAppEfDataModel.Dtos
@using OrdersManagement.Components.Pages.Shared
@using Syncfusion.Blazor.Grids
@using Syncfusion.Blazor.Cards
@using Syncfusion.Blazor.Buttons
@using SelectionType = Syncfusion.Blazor.Grids.SelectionType
@inherits LayoutComponentBase
<h3>Zamówienie klienta nr @CustomerOrders.FirstOrDefault()?.CoNum</h3>
<br/>
<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">Zamówienie klienta nr @(CustomerOrderDto?.CoNum ?? "Brak numeru")</h3>
</CardHeader>
<CardContent>
<SfCard CssClass="mb-4">
<CardContent>
<div class="row">
<div class="col">
<SortableList TItem="CustomerOrderDto" Data="CustomerOrders" Class="bg-light">
<ItemTemplate>
<u>Numer Zamówienia:</u> <b>@context.CoNum</b><br/>
<u>Numer Zamówienia Klienta:</u> <b>@context.CustPo</b><br/>
<u>Klient:</u> <b>@context.CustNum</b><br/>
<u>Numer Odbiorcy:</u> <b>@context.CustSeq</b><br/>
<u>Kontakt:</u> <b>@context.Contact</b><br/>
<u>Telefon:</u> <b>@context.Phone</b><br/>
<u>Data Zamówienia:</u> <b>@context.OrderDate.ToString("yyyy-MM-dd HH:mm:ss")</b><br/>
<u>Warunki:</u> <b>@context.TermsCode</b><br/>
<u>Wartość Brutto:</u> <b>@(context.Price?.ToString("F2") ?? "N/A")</b><br/>
<u>Status:</u> <b>@context.TranslatedStatus</b><br/>
</ItemTemplate>
</SortableList>
<u>Numer Zamówienia:</u> <b>@CustomerOrderDto?.CoNum</b><br/>
<u>Numer Zamówienia Klienta:</u> <b>@CustomerOrderDto?.CustPo</b><br/>
<u>Klient:</u> <b>@CustomerOrderDto?.CustNum</b><br/>
<u>Numer Odbiorcy:</u> <b>@CustomerOrderDto?.CustSeq</b><br/>
<u>Kontakt:</u> <b>@CustomerOrderDto?.Contact</b><br/>
<u>Telefon:</u> <b>@CustomerOrderDto?.Phone</b><br/>
<u>Data Zamówienia:</u> <b>@CustomerOrderDto?.OrderDate.ToString("yyyy-MM-dd HH:mm:ss")</b><br/>
<u>Warunki:</u> <b>@CustomerOrderDto?.TermsCode</b><br/>
<u>Wartość Brutto:</u> <b>@(CustomerOrderDto?.Price?.ToString("F2") ?? "N/A")</b><br/>
<u>Status:</u> <b>@CustomerOrderDto?.TranslatedStatus</b><br/>
</div>
<div class="col">
<SortableList TItem="CustomerOrderDto" Data="CustomerOrders" Class="bg-light">
<ItemTemplate>
<u>Magazyn:</u> <b>@context.Whse</b><br/>
<u>VAT:</u> <b>@context.FrtTaxCode1</b><br/>
<u>Typ Odbiorcy:</u> <b>@context.EndUserType</b><br/>
<u>Kurs Wymiany:</u> <b>@(context.ExchRate?.ToString("F4") ?? "N/A")</b><br/>
<u>Gate:</u> <b>@context.Uf_FKR_EDI_Gate</b><br/>
<u>RecipientCode:</u> <b>@context.Uf_FKR_EDI_RecipientCode</b><br/>
<u>SelletCode:</u> <b>@context.Uf_FKR_EDI_SellerCode</b><br/>
<u>SenderCode:</u> <b>@context.Uf_FKR_EDI_SenderCode</b><br/>
<u>BuyerCode:</u> <b>@context.Uf_FKR_EDI_BuyerCode</b><br/>
<u>Typ Dokumentu:</u> <b>@context.Uf_DocType</b><br/>
</ItemTemplate>
</SortableList>
<u>Magazyn:</u> <b>@CustomerOrderDto?.Whse</b><br/>
<u>VAT:</u> <b>@CustomerOrderDto?.FrtTaxCode1</b><br/>
<u>Typ Odbiorcy:</u> <b>@CustomerOrderDto?.EndUserType</b><br/>
<u>Kurs Wymiany:</u> <b>@(CustomerOrderDto?.ExchRate?.ToString("F4") ?? "N/A")</b><br/>
<u>Gate:</u> <b>@CustomerOrderDto?.Uf_FKR_EDI_Gate</b><br/>
<u>RecipientCode:</u> <b>@CustomerOrderDto?.Uf_FKR_EDI_RecipientCode</b><br/>
<u>SellerCode:</u> <b>@CustomerOrderDto?.Uf_FKR_EDI_SellerCode</b><br/>
<u>SenderCode:</u> <b>@CustomerOrderDto?.Uf_FKR_EDI_SenderCode</b><br/>
<u>BuyerCode:</u> <b>@CustomerOrderDto?.Uf_FKR_EDI_BuyerCode</b><br/>
<u>Typ Dokumentu:</u> <b>@CustomerOrderDto?.Uf_DocType</b><br/>
</div>
</div>
<br/>
<div class="row">
</CardContent>
</SfCard>
<div class="row mb-4">
<div class="col-md-12">
<Button Color="ButtonColor.Primary" @onclick="ShowLastDelfors">@_text</Button>
<SfButton CssClass="e-primary" IsPrimary="true" @onclick="ShowLastDelfors">@_text</SfButton>
</div>
</div>
<br/>
@if (_isVisible)
{
<div class="row">
<h3>Zamówienie DELFOR do zamówienia @CustomerOrders.FirstOrDefault()?.CoNum</h3>
</div>
<br/>
<div class="row">
<ScheduleOrdersGrid PageSize="5" PassGridRef="SetGridRef" DataProvider="ScheduleOrdersDataProvider"></ScheduleOrdersGrid>
</div>
<br/>
<h5 class="text-primary mb-3">Zamówienie DELFOR do zamówienia @(CustomerOrderDto?.CoNum ?? "Brak numeru")</h5>
<ScheduleOrdersGrid PageSize="5" PassGridRef="SetGridRef" GridData="_scheduleOrders" />
}
<div class="row">
<h3>Indeksy</h3>
</div>
<div class="row">
<Grid @ref="_customerOrderLinesGrid"
TItem="CustomerOrderLineDto"
Class="table table-hover table-bordered table-striped"
Data="_customerOrderLines"
<h5 class="text-primary mb-3 pt-5">Indeksy</h5>
<SfGrid @ref="_customerOrderLinesGrid"
AllowFiltering="true"
Responsive="true"
AllowPaging="true"
PageSize="10"
AllowSorting="true"
AllowSelection="true"
AllowRowClick="true"
SelectionMode="GridSelectionMode.Single"
SelectedItemsChanged="SelectedCustomerOrderLineChanged">
<GridColumns>
<GridColumn TItem="CustomerOrderLineDto" HeaderText="Linia" PropertyName="CoLine">
@context.CoLine
</GridColumn>
<GridColumn TItem="CustomerOrderLineDto" HeaderText="Pozycja" PropertyName="Item">
@context.Item
</GridColumn>
<GridColumn TItem="CustomerOrderLineDto" HeaderText="Pozycja Klienta" PropertyName="CustItem">
@context.CustItem
</GridColumn>
<GridColumn TItem="CustomerOrderLineDto" HeaderText="Opis" PropertyName="Description">
@context.Description
</GridColumn>
<GridColumn TItem="CustomerOrderLineDto" HeaderText="Ilość" TextAlignment="Alignment.End"
PropertyName="BlanketQty">
@context.BlanketQty
</GridColumn>
<GridColumn TItem="CustomerOrderLineDto" HeaderText="J/M" PropertyName="UM">
@context.UM
</GridColumn>
<GridColumn TItem="CustomerOrderLineDto" HeaderText="Cena" PropertyName="ContPrice">
@context.ContPrice
</GridColumn>
<GridColumn TItem="CustomerOrderLineDto" HeaderText="Status" PropertyName="TranslatedStatus">
@context.TranslatedStatus
</GridColumn>
</GridColumns>
</Grid>
TValue="CustomerOrderLineDto"
DataSource="@_customerOrderLines"
EnableAdaptiveUI="true">
<GridTemplates>
<DetailTemplate>
@{
var order = context as CustomerOrderLineDto;
<SfCard>
<CardContent>
<div class="row">
<h6>Szczegóły</h6>
<div class="col">
<u>Numer zamówienia:</u><b>@order?.CoNum</b><br/>
<u>Linia:</u><b>@order?.CoLine</b><br/>
<u>Pozycja:</u><b>@order?.Item</b><br/>
<u>Pozycja Klienta:</u><b>@order?.CustItem</b><br/>
<u>Opis:</u><b>@order?.Description</b><br/>
<u>Łączna Ilość:</u><b>@order?.BlanketQty.ToString("F2")</b><br/>
<u>Status:</u><b>@order?.TranslatedStatus</b><br/>
</div>
<div class="col">
<u>Cena:</u><b>@(order?.ContPrice?.ToString("F2") ?? "N/A")</b><br/>
<u>Ważne Od:</u><b>@(order?.EffDate?.ToString("dd.MM.yyyy") ?? "N/A")</b><br/>
<u>J/M:</u><b>@order?.UM</b><br/>
<u>BoxType:</u><b>@order?.Uf_FKR_EDI_BLN_BoxType</b><br/>
<u>Address:</u><b>@order?.Uf_FKR_EDI_BLN_Address</b><br/>
<u>FinalDestination:</u><b>@order?.Uf_FKR_EDI_BLN_FinalDestination</b><br/>
<u>QtyPerBox:</u><b>@(order?.Uf_FKR_EDI_BLN_QtyPerBox?.ToString() ?? "N/A")</b>
</div>
</div>
</CardContent>
</SfCard>
}
</DetailTemplate>
</GridTemplates>
<GridColumns>
<GridColumn Field=@nameof(CustomerOrderLineDto.CoLine) HeaderText="Linia" Width="70"></GridColumn>
<GridColumn Field=@nameof(CustomerOrderLineDto.Item) HeaderText="Pozycja" Width="100"></GridColumn>
<GridColumn Field=@nameof(CustomerOrderLineDto.CustItem) HeaderText="Pozycja Klienta" Width="120"></GridColumn>
<GridColumn Field=@nameof(CustomerOrderLineDto.Description) HeaderText="Opis" Width="200"></GridColumn>
<GridColumn Field=@nameof(CustomerOrderLineDto.BlanketQty) HeaderText="Ilość" TextAlign="TextAlign.Right" Width="100"></GridColumn>
<GridColumn Field=@nameof(CustomerOrderLineDto.UM) HeaderText="J/M" Width="50"></GridColumn>
<GridColumn Field=@nameof(CustomerOrderLineDto.ContPrice) HeaderText="Cena" Width="100"></GridColumn>
<GridColumn Field=@nameof(CustomerOrderLineDto.TranslatedStatus) HeaderText="Status" Width="100"></GridColumn>
</GridColumns>
<GridFilterSettings Type="FilterType.Excel"/>
<GridPageSettings PageSize="10"/>
<GridSelectionSettings Mode="SelectionMode.Row" Type="SelectionType.Single"/>
<GridEvents TValue="CustomerOrderLineDto" RowSelected="OnSelectedLineRow"></GridEvents>
</SfGrid>
@if (_isVisibleCustomerOrderLine)
{
<div class="row">
<h3>Szczegóły</h3>
</div>
<div class="row">
<div class="col">
<SortableList TItem="CustomerOrderLineDto" Data="_selectedCustomerOrderLine">
<ItemTemplate>
<u>Numer zamówienia:</u>&emsp;<b>@context.CoNum</b><br/>
<u>Linia:</u>&emsp;<b>@context.CoLine</b><br/>
<u>Pozycja:</u>&emsp;<b>@context.Item</b><br/>
<u>Pozycja Klienta:</u>&emsp;<b>@context.CustItem</b><br/>
<u>Opis:</u>&emsp;<b>@context.Description</b><br/>
<u>Łączna Ilość:</u>&emsp;<b>@context.BlanketQty.ToString("F2")</b><br/>
<u>Status:</u>&emsp;<b>@context.TranslatedStatus</b><br/>
</ItemTemplate>
</SortableList>
</div>
<div class="col">
<SortableList TItem="CustomerOrderLineDto" Data="_selectedCustomerOrderLine">
<ItemTemplate>
<u>Cena:</u>&emsp;<b>@(context.ContPrice?.ToString("F2") ?? "N/A")</b><br/>
<u>Ważne Od:</u>&emsp;<b>@(context.EffDate?.ToString("dd.MM.yyyy") ?? "N/A")</b><br/>
<u>J/M:</u>&emsp;<b>@context.UM</b><br/>
<u>BoxType:</u>&emsp;<b>@context.Uf_FKR_EDI_BLN_BoxType</b><br/>
<u>Address:</u>&emsp;<b>@context.Uf_FKR_EDI_BLN_Address</b><br/>
<u>FinalDestination:</u>&emsp;<b>@context.Uf_FKR_EDI_BLN_FinalDestination</b><br/>
<u>QtyPerBox:</u>&emsp;<b>@(context.Uf_FKR_EDI_BLN_QtyPerBox?.ToString() ?? "N/A")</b>
</ItemTemplate>
</SortableList>
</div>
</div>
<br/>
<h3>Harmonogramy</h3>
<div class="row">
<Grid @ref="_customerOrderLineItemsGrid"
TItem="CustomerOrderLineItemDto"
Class="table table-hover table-bordered table-striped"
Data="_customerOrderLineItems"
<h5 class="text-primary mb-3 mt-4">Harmonogramy</h5>
<SfGrid @ref="_customerOrderLineItemsGrid"
TValue="CustomerOrderLineItemDto"
DataSource="@_customerOrderLineItems"
AllowFiltering="true"
Responsive="true"
AllowPaging="true"
PageSize="10"
AllowSelection="true"
AllowRowClick="true"
SelectionMode="GridSelectionMode.Single"
AllowSorting="true"
SelectionMode="Syncfusion.Blazor.Grids.SelectionMode.Single"
SelectedItemsChanged="SelectedCustomerOrderLineItemChanged">
<GridColumns>
<GridColumn TItem="CustomerOrderLineItemDto" HeaderText="Linia" PropertyName="CustomerOrderLine">
@context.CoLine
</GridColumn>
<GridColumn TItem="CustomerOrderLineItemDto" HeaderText="Zwolnienie"
PropertyName="CustomerOrderRelease">
@context.CoRelease
</GridColumn>
<GridColumn TItem="CustomerOrderLineItemDto" HeaderText="Pozycja" PropertyName="Item">
@context.Item
</GridColumn>
<GridColumn TItem="CustomerOrderLineItemDto" HeaderText="Pozycja" PropertyName="CustomerItem">
@context.CustItem
</GridColumn>
<GridColumn TItem="CustomerOrderLineItemDto" HeaderText="Łączna Ilość" TextAlignment="Alignment.End"
PropertyName="QtyOrdered">
@context.QtyOrdered
</GridColumn>
<GridColumn TItem="CustomerOrderLineItemDto" HeaderText="Data Wykonania" PropertyName="DueDate">
@context.DueDate?.ToString("dd.MM.yyyy")
</GridColumn>
<GridColumn TItem="CustomerOrderLineItemDto" HeaderText="Status" PropertyName="TranslatedStatus">
@context.TranslatedStatus
</GridColumn>
</GridColumns>
</Grid>
</div>
@if (_isVisibleCustomerOrderLineItem)
{
<div class="row">
<h3>Szczegóły</h3>
</div>
<GridTemplates>
<DetailTemplate>
@{
var detailLineItem = context as CustomerOrderLineItemDto;
<SfCard>
<CardContent>
<div class="row">
<h6>Szczegóły</h6>
<div class="col">
<SortableList TItem="CustomerOrderLineItemDto" Data="_selectedCustomerOrderLineItem">
<ItemTemplate>
<u>Numer Zamówienia:</u>&emsp;<b>@context.CoNum</b><br/>
<u>Linia:</u>&emsp;<b>@context.CoLine</b><br/>
<u>Zwolnienie:</u>&emsp;<b>@context.CoRelease</b><br/>
<u>Pozycja:</u>&emsp;<b>@context.Item</b><br/>
<u>Pozycja Klienta:</u>&emsp;<b>@context.CustItem</b><br/>
<u>Łączna Ilość Sztuk:</u>&emsp;<b>@(context.QtyOrdered.ToString("F2") ?? "N/A")</b><br/>
<u>Cena:</u>&emsp;<b>@(context.Price.ToString("F2") ?? "N/A")</b><br/>
<u>Data Wykonania:</u>&emsp;<b>@(context.DueDate?.ToString("dd.MM.yyyy") ?? "N/A")</b><br/>
<u>Data
Rejestracji:</u>&emsp;<b>@(context.ReleaseDate?.ToString("dd.MM.yyyy") ?? "N/A")</b><br/>
<u>Magazyn:</u>&emsp;<b>@context.Whse</b><br/>
<u>Typ Documentu:</u>&emsp;<b>@context.Uf_FKR_EDI_ITEM_DocumentType</b><br/>
</ItemTemplate>
</SortableList>
<u>Numer Zamówienia:</u><b>@detailLineItem?.CoNum</b><br/>
<u>Linia:</u><b>@detailLineItem?.CoLine</b><br/>
<u>Zwolnienie:</u><b>@detailLineItem?.CoRelease</b><br/>
<u>Pozycja:</u><b>@detailLineItem?.Item</b><br/>
<u>Pozycja Klienta:</u><b>@detailLineItem?.CustItem</b><br/>
<u>Łączna Ilość Sztuk:</u><b>@(detailLineItem?.QtyOrdered.ToString("F2") ?? "N/A")</b><br/>
<u>Cena:</u><b>@(detailLineItem?.Price.ToString("F2") ?? "N/A")</b><br/>
<u>Data Wykonania:</u><b>@(detailLineItem?.DueDate?.ToString("dd.MM.yyyy") ?? "N/A")</b><br/>
<u>Data Rejestracji:</u><b>@(detailLineItem?.ReleaseDate?.ToString("dd.MM.yyyy") ?? "N/A")</b><br/>
<u>Magazyn:</u><b>@detailLineItem?.Whse</b><br/>
<u>Typ Documentu:</u><b>@detailLineItem?.Uf_FKR_EDI_ITEM_DocumentType</b><br/>
</div>
<div class="col">
<SortableList TItem="CustomerOrderLineItemDto" Data="_selectedCustomerOrderLineItem">
<ItemTemplate>
<u>Kod VAT:</u>&emsp;<b>@context.TaxCode1</b><br/>
<u>J/M:</u>&emsp;<b>@context.UM</b><br/>
<u>Numer Klienta:</u>&emsp;<b>@context.CoCustNum</b><br/>
<u>Opis:</u>&emsp;<b>@context.Description</b><br/>
<u>Status:</u>&emsp;<b>@context.TranslatedStatus</b><br/>
<u>RoutingCode:</u>&emsp;<b>@context.Uf_FKR_EDI_ITEM_RoutingCode</b><br/>
<u>DeliveryCallNumber:</u>&emsp;<b>@context.Uf_FKR_EDI_ITEM_DeliveryCallNum</b><br/>
<u>UnloadingPoint:</u>&emsp;<b>@context.Uf_LOC_11_UnloadingPoint</b><br/>
<u>DestinationPoint:</u>&emsp;<b>@context.Uf_LOC_159_DestinationPoint</b><br/>
<u>PalletCode:</u>&emsp;<b>@context.Uf_FKR_EDI_ITEM_PalletCode</b><br/>
</ItemTemplate>
</SortableList>
<u>Kod VAT:</u><b>@detailLineItem?.TaxCode1</b><br/>
<u>J/M:</u><b>@detailLineItem?.UM</b><br/>
<u>Numer Klienta:</u><b>@detailLineItem?.CoCustNum</b><br/>
<u>Opis:</u><b>@detailLineItem?.Description</b><br/>
<u>Status:</u><b>@detailLineItem?.TranslatedStatus</b><br/>
<u>RoutingCode:</u><b>@detailLineItem?.Uf_FKR_EDI_ITEM_RoutingCode</b><br/>
<u>DeliveryCallNumber:</u><b>@detailLineItem?.Uf_FKR_EDI_ITEM_DeliveryCallNum</b><br/>
<u>UnloadingPoint:</u><b>@detailLineItem?.Uf_LOC_11_UnloadingPoint</b><br/>
<u>DestinationPoint:</u><b>@detailLineItem?.Uf_LOC_159_DestinationPoint</b><br/>
<u>PalletCode:</u><b>@detailLineItem?.Uf_FKR_EDI_ITEM_PalletCode</b><br/>
</div>
</div>
</CardContent>
</SfCard>
}
</DetailTemplate>
</GridTemplates>
<Syncfusion.Blazor.Grids.GridColumns>
<Syncfusion.Blazor.Grids.GridColumn Field=@nameof(CustomerOrderLineItemDto.CoLine) HeaderText="Linia" Width="70"/>
<Syncfusion.Blazor.Grids.GridColumn Field=@nameof(CustomerOrderLineItemDto.CoRelease) HeaderText="Zwolnienie" Width="70"/>
<Syncfusion.Blazor.Grids.GridColumn Field=@nameof(CustomerOrderLineItemDto.Item) HeaderText="Pozycja" Width="100"></Syncfusion.Blazor.Grids.GridColumn>
<Syncfusion.Blazor.Grids.GridColumn Field=@nameof(CustomerOrderLineItemDto.CustItem) HeaderText="Pozycja" Width="100"></Syncfusion.Blazor.Grids.GridColumn>
<Syncfusion.Blazor.Grids.GridColumn Field=@nameof(CustomerOrderLineItemDto.QtyOrdered) HeaderText="Łączna Ilość" TextAlign="TextAlign.Right" Width="120"></Syncfusion.Blazor.Grids.GridColumn>
<Syncfusion.Blazor.Grids.GridColumn Field=@nameof(CustomerOrderLineItemDto.DueDate) HeaderText="Data Wykonania" Width="100"/>
<Syncfusion.Blazor.Grids.GridColumn Field=@nameof(CustomerOrderLineItemDto.TranslatedStatus) HeaderText="Status" Width="100"></Syncfusion.Blazor.Grids.GridColumn>
</Syncfusion.Blazor.Grids.GridColumns>
<GridFilterSettings Type="FilterType.Excel"/>
<GridPageSettings PageSize="10"/>
<GridSelectionSettings Mode="SelectionMode.Row" Type="SelectionType.Single"/>
</SfGrid>
}
</CardContent>
<CardFooter>
<small class="text-muted">FA Krosno Manager © @(DateTime.Now.Year)</small>
</CardFooter>
</SfCard>
</div>
@code {
[Parameter] public Guid CustomerOrderId { get; set; }
private List<CustomerOrderDto> CustomerOrders { get; set; } = [];
private CustomerOrderDto CustomerOrderDto { get; set; }
private List<CustomerOrderLineDto> _customerOrderLines = [];
private List<CustomerOrderLineItemDto> _customerOrderLineItems = [];
private IEnumerable<ScheduleOrderDto>? _scheduleOrders;
private List<CustomerOrderLineDto?> _selectedCustomerOrderLine = [];
private List<CustomerOrderLineItemDto?> _selectedCustomerOrderLineItem = [];
CustomerOrderLineDto? _selectedCustomerOrderLine;
private Grid<CustomerOrderLineDto>? _customerOrderLinesGrid;
private Grid<CustomerOrderLineItemDto>? _customerOrderLineItemsGrid;
private SfGrid<CustomerOrderLineDto>? _customerOrderLinesGrid;
private SfGrid<CustomerOrderLineItemDto>? _customerOrderLineItemsGrid;
private bool _isVisibleCustomerOrderLine;
private bool _isVisibleCustomerOrderLineItem;
private Grid<ScheduleOrderDto> _gridRef = new();
private SfGrid<ScheduleOrderDto> _gridRef = new();
private bool _isVisible = true;
private string _text = "Pokaż powiązane zamówienia DELFOR";
protected override async Task OnInitializedAsync()
{
CustomerOrderDto? customerOrder = await CustomerOrderService.GetCustomerOrderAsync(CustomerOrderId);
if (customerOrder != null)
{
CustomerOrders = [customerOrder];
_customerOrderLines = customerOrder.CustomerOrderLines.ToList() ?? [];
}
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
@@ -265,20 +221,26 @@
await SetGridRef(_gridRef);
StateHasChanged();
_isVisible = false;
}
// ClaimsPrincipal currentUser = CustomAuthenticationStateProvider.GetCurrentUser();
//
// if (currentUser.Identity?.IsAuthenticated == false)
// {
// NavigationManager.NavigateTo("/Unauthorized");
// }
// else
// {
CustomerOrderDto? customerOrder = await CustomerOrderService.GetCustomerOrderAsync(CustomerOrderId);
if (customerOrder != null)
{
CustomerOrderDto = customerOrder;
_customerOrderLines = CustomerOrderDto.CustomerOrderLines.ToList() ?? [];
}
private void SelectedCustomerOrderLineChanged(HashSet<CustomerOrderLineDto> obj)
{
_isVisibleCustomerOrderLine = obj.Any();
_selectedCustomerOrderLine = [obj.FirstOrDefault()];
_customerOrderLineItems = obj.FirstOrDefault()?.CustomerOrderLineItems.ToList() ?? [];
StateHasChanged();
// }
}
private void SelectedCustomerOrderLineItemChanged(HashSet<CustomerOrderLineItemDto> obj)
{
_isVisibleCustomerOrderLineItem = obj.Any();
_selectedCustomerOrderLineItem = [obj.FirstOrDefault()];
}
private async Task ShowLastDelfors()
@@ -291,23 +253,23 @@
}
else
{
await _gridRef.RefreshDataAsync();
_scheduleOrders = await FetchScheduleOrdersAsync();
await _gridRef.Refresh();
StateHasChanged();
_isVisible = true;
_text = "Ukryj";
}
}
private async Task SetGridRef(Grid<ScheduleOrderDto> grid)
private async Task SetGridRef(SfGrid<ScheduleOrderDto> grid)
{
_gridRef = grid;
}
private async Task<GridDataProviderResult<ScheduleOrderDto>> ScheduleOrdersDataProvider(GridDataProviderRequest<ScheduleOrderDto> request)
private async Task<IEnumerable<ScheduleOrderDto>> FetchScheduleOrdersAsync()
{
_scheduleOrders = [];
IList<int> scheduleOrderDetails = CustomerOrders?.FirstOrDefault()?.EdiCustomerOrderTranslates?.Select(x => x.ScheduleOrderId).Distinct().ToList() ?? [];
IList<int> scheduleOrderDetails = CustomerOrderDto?.EdiCustomerOrderTranslates?.Select(x => x.ScheduleOrderId).Distinct().ToList() ?? [];
if (scheduleOrderDetails.Any())
{
@@ -315,6 +277,14 @@
_scheduleOrders = _scheduleOrders.Where(x => scheduleOrderDetails.Contains(x.ID)).OrderByDescending(x => x.LastUpdateDate).ToList();
}
return await Task.FromResult(request.ApplyTo(_scheduleOrders));
return _scheduleOrders;
}
private void OnSelectedLineRow<TValue>(RowSelectEventArgs<TValue> obj)
{
_selectedCustomerOrderLine = obj.Data as CustomerOrderLineDto;
_isVisibleCustomerOrderLine = _selectedCustomerOrderLine != null;
_customerOrderLineItems = _selectedCustomerOrderLine?.CustomerOrderLineItems.ToList() ?? [];
}
}

View File

@@ -1,75 +1,115 @@
@page "/CustomerOrders"
@inject CustomerOrderService CustomerOrderService
@inject NavigationManager NavigationManager
@inject CustomAuthenticationStateProvider CustomAuthenticationStateProvider
@using System.Security.Claims
@using Microsoft.AspNetCore.Authorization
@using SytelineSaAppEfDataModel.Dtos
@using Syncfusion.Blazor.Grids
@using Syncfusion.Blazor.Cards
@inherits LayoutComponentBase
<div class="row">
<h3>Zamówienia Klienta</h3>
</div>
<br />
<div class="row">
<Grid @ref="_grid"
TItem="CustomerOrderDto"
Class="table table-hover table-bordered table-striped"
DataProvider="CustomerOrdersDataProvider"
AllowFiltering="true"
Responsive="true"
<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">Zamówienia Klienta</h3>
</CardHeader>
<CardContent>
<SfGrid AllowFiltering="true"
AllowPaging="true"
PageSize="20"
AllowSorting="true"
AllowSelection="true"
AllowRowClick="true"
OnRowDoubleClick="OnRowDoubleClick"
SelectedItemsChanged="SelectedItemsChanged">
TValue="CustomerOrderDto"
DataSource="@_customerOrders"
EnableAdaptiveUI="true">
<GridTemplates>
<DetailTemplate>
@{
var order = context as CustomerOrderDto;
<SfCard>
<CardContent>
<div class="row">
<div class="col">
<u>Numer Zamówienia:</u> <b>@order?.CoNum</b><br/>
<u>Numer Zamówienia Klienta:</u> <b>@order?.CustPo</b><br/>
<u>Klient:</u> <b>@order?.CustNum</b><br/>
<u>Numer Odbiorcy:</u> <b>@order?.CustSeq</b><br/>
<u>Kontakt:</u> <b>@order?.Contact</b><br/>
<u>Telefon:</u> <b>@order?.Phone</b><br/>
<u>Data Zamówienia:</u>
<b>@order?.OrderDate.ToString("yyyy-MM-dd HH:mm:ss")</b><br/>
<u>Warunki:</u> <b>@order?.TermsCode</b><br/>
<u>Wartość Brutto:</u> <b>@(order?.Price?.ToString("F2") ?? "N/A")</b><br/>
<u>Status:</u> <b>@order?.TranslatedStatus</b><br/>
</div>
<div class="col">
<u>Magazyn:</u> <b>@order?.Whse</b><br/>
<u>VAT:</u> <b>@order?.FrtTaxCode1</b><br/>
<u>Typ Odbiorcy:</u> <b>@order?.EndUserType</b><br/>
<u>Kurs Wymiany:</u> <b>@(order?.ExchRate?.ToString("F4") ?? "N/A")</b><br/>
<u>Gate:</u> <b>@order?.Uf_FKR_EDI_Gate</b><br/>
<u>RecipientCode:</u> <b>@order?.Uf_FKR_EDI_RecipientCode</b><br/>
<u>SellerCode:</u> <b>@order?.Uf_FKR_EDI_SellerCode</b><br/>
<u>SenderCode:</u> <b>@order?.Uf_FKR_EDI_SenderCode</b><br/>
<u>BuyerCode:</u> <b>@order?.Uf_FKR_EDI_BuyerCode</b><br/>
<u>Typ Dokumentu:</u> <b>@order?.Uf_DocType</b><br/>
</div>
</div>
</CardContent>
</SfCard>
}
</DetailTemplate>
</GridTemplates>
<GridColumns>
<GridColumn TItem="CustomerOrderDto" HeaderText="Numer Zamówienia" PropertyName="CoNum">
@context.CoNum
</GridColumn>
<GridColumn TItem="CustomerOrderDto" HeaderText="Zamówienie Klienta" PropertyName="CustNum">
@context.CustPo
</GridColumn>
<GridColumn TItem="CustomerOrderDto" HeaderText="Numer Klienta" PropertyName="CustNum">
@context.CustNum
</GridColumn>
<GridColumn TItem="CustomerOrderDto" HeaderText="Odbiorca" PropertyName="CustSeq">
@context.CustSeq
</GridColumn>
<GridColumn TItem="CustomerOrderDto" HeaderText="Data zamówienia" PropertyName="CreateDate">
@context.CreateDate
</GridColumn>
<GridColumn TItem="CustomerOrderDto" HeaderText="Status" PropertyName="Stat">
@context.TranslatedStatus
</GridColumn>
<GridColumn Field=@nameof(CustomerOrderDto.CoNum) HeaderText="Numer Zamówienia" Width="110"></GridColumn>
<GridColumn Field=@nameof(CustomerOrderDto.CustPo) HeaderText="Zamówienie Klienta" Width="100"></GridColumn>
<GridColumn Field=@nameof(CustomerOrderDto.CustNum) HeaderText="Numer Klienta" Width="90"></GridColumn>
<GridColumn Field=@nameof(CustomerOrderDto.CustSeq) HeaderText="Odbiorca" Width="80"></GridColumn>
<GridColumn Field=@nameof(CustomerOrderDto.CreateDate) HeaderText="Data zamówienia" TextAlign="TextAlign.Right" Width="110"></GridColumn>
<GridColumn Field=@nameof(CustomerOrderDto.TranslatedStatus) HeaderText="Status" Width="100"></GridColumn>
</GridColumns>
</Grid>
<GridFilterSettings Type="FilterType.Excel"/>
<GridPageSettings PageSize="10"/>
<GridSelectionSettings Mode="SelectionMode.Row" Type="SelectionType.Single"/>
<GridEvents TValue="CustomerOrderDto" OnRecordDoubleClick="OnRowDoubleClick"/>
</SfGrid>
</CardContent>
<CardFooter>
<small class="text-muted">FA Krosno Manager © @(DateTime.Now.Year)</small>
</CardFooter>
</SfCard>
</div>
@code {
Grid<CustomerOrderDto>? _grid;
private IEnumerable<CustomerOrderDto>? _customerOrders;
private CustomerOrderDto? _selectedCustomerOrder;
private async Task<GridDataProviderResult<CustomerOrderDto>> CustomerOrdersDataProvider(GridDataProviderRequest<CustomerOrderDto> request)
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
// ClaimsPrincipal currentUser = CustomAuthenticationStateProvider.GetCurrentUser();
//
// if (currentUser.Identity?.IsAuthenticated == false)
// {
// NavigationManager.NavigateTo("/Unauthorized");
// }
// else
// {
_customerOrders = await CustomerOrderService.GetCustomerOrdersAsync() ?? new List<CustomerOrderDto>();
_customerOrders = _customerOrders.OrderByDescending(x => x.CreateDate).ToList();
StateHasChanged();
return await Task.FromResult(request.ApplyTo(_customerOrders));
// }
}
}
private void OnRowDoubleClick(GridRowEventArgs<CustomerOrderDto> obj)
private void OnRowDoubleClick(RecordDoubleClickEventArgs<CustomerOrderDto> obj)
{
Guid customerOrderId = obj.Item.RowPointer;
Guid customerOrderId = obj.RowData.RowPointer;
NavigationManager.NavigateTo($"/CustomerOrder/{customerOrderId}");
}
private void SelectedItemsChanged(HashSet<CustomerOrderDto> obj)
{
_selectedCustomerOrder = obj.FirstOrDefault() ?? null;
}
}

View File

@@ -0,0 +1,96 @@
@page "/CustomerOrdersTranslations"
@using SytelineSaAppEfDataModel.Dtos
@using Syncfusion.Blazor.Cards
@using Syncfusion.Blazor.Grids
@using Action = Syncfusion.Blazor.Grids.Action
@inject EdiCustomerOrderTranslateService EdiCustomerOrderTranslateService
<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">Zarządzanie powiązaniami zamówień z DELFORami</h3>
</CardHeader>
<CardContent>
<SfGrid DataSource="@OrderTranslations"
AllowFiltering="true"
AllowPaging="true"
AllowSorting="true"
AllowSelection="true"
EnableAdaptiveUI="true"
EnablePersistence="true"
AdaptiveUIMode="AdaptiveMode.Both"
Toolbar="@(new List<string> { "Edit", "Delete", "Cancel", "Update" })">
<GridColumns>
<GridColumn Field=@nameof(EdiCustomerOrderTranslateDto.Id) AllowEditing="false" IsPrimaryKey="true" Visible="false" HeaderText="Id"
Width="100"></GridColumn>
<GridColumn Field=@nameof(EdiCustomerOrderTranslateDto.ScheduleOrderId) HeaderText="DELFOR Id" Width="150"></GridColumn>
<GridColumn Field=@nameof(EdiCustomerOrderTranslateDto.EdiCoCoNum) HeaderText="Numer zamówienia EDI" Width="150"></GridColumn>
<GridColumn Field=@nameof(EdiCustomerOrderTranslateDto.CoCoNum) HeaderText="Numer zamówienia SL" Width="200"></GridColumn>
<GridColumn Field=@nameof(EdiCustomerOrderTranslateDto.CreatedDate) AllowEditing="false" HeaderText="Data utworzenia"
Width="150"></GridColumn>
</GridColumns>
<GridEditSettings AllowDeleting="true"
ShowDeleteConfirmDialog="true"
AllowEditing="true">
</GridEditSettings>
<GridEvents OnActionBegin="OnActionBegin"
OnActionComplete="OnActionComplete"
TValue="EdiCustomerOrderTranslateDto">
</GridEvents>
<GridPageSettings PageSize="10"></GridPageSettings>
<GridFilterSettings Type="FilterType.Excel"/>
</SfGrid>
</CardContent>
<CardFooter>
<small class="text-muted">FA Krosno Manager © @(DateTime.Now.Year)</small>
</CardFooter>
</SfCard>
</div>
@code {
private List<EdiCustomerOrderTranslateDto> OrderTranslations { get; set; } = new();
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
// ClaimsPrincipal currentUser = CustomAuthenticationStateProvider.GetCurrentUser();
//
// if (currentUser.Identity?.IsAuthenticated == false || currentUser.Identity?.Name != "pkus")
// {
// NavigationManager.NavigateTo("/Unauthorized");
// }
// else
// {
await LoadTranslations();
StateHasChanged();
// }
}
}
public async Task OnActionBegin(ActionEventArgs<EdiCustomerOrderTranslateDto> args)
{
if (args.RequestType.Equals(Action.Delete))
{
await EdiCustomerOrderTranslateService.DeleteEdiCustomerOrderTranslateAsync(args.Data);
}
}
private async Task LoadTranslations()
{
OrderTranslations = (await EdiCustomerOrderTranslateService.GetEdiCustomerOrdersTranslationsAsync() ?? Array.Empty<EdiCustomerOrderTranslateDto>()).OrderByDescending(x => x.CreatedDate).ToList();
}
private async Task OnActionComplete(ActionEventArgs<EdiCustomerOrderTranslateDto> args)
{
switch (args.RequestType)
{
case Action.Delete:
await LoadTranslations();
break;
}
}
}

View File

@@ -1,240 +1,228 @@
@page "/EdiCustomerOrder/{CustomerOrderId:guid}"
@inject EdiCustomerOrderService EdiCustomerOrderService
@inject NavigationManager NavigationManager
@inject CustomAuthenticationStateProvider CustomAuthenticationStateProvider
@using System.Security.Claims
@using Microsoft.AspNetCore.Authorization
@using SytelineSaAppEfDataModel.Dtos
@using Syncfusion.Blazor.Grids
@using Syncfusion.Blazor.Cards
@inherits LayoutComponentBase
<div class="row">
<h3>Zamówienie Klienta EDI</h3>
</div>
<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">Zamówienie klienta EDI nr @(EdiCustomerOrderDto?.CustomerOrderNumber ?? "Brak numeru")</h3>
</CardHeader>
<CardContent>
<SfCard CssClass="mb-4">
<CardContent>
<div class="row">
<div class="col">
<SortableList TItem="EdiCustomerOrderDto" Data="_ediCustomerOrder">
<ItemTemplate>
<u>Numer zamówienia EDI:</u>&emsp;<b>@context.CustomerOrderNumber</b><br />
<u>Numer zamówienia Klienta:</u>&emsp;<b>@context.CustomerPoNumber</b><br />
<u>Numer klienta:</u>&emsp;<b>@context.CustomerNumber</b><br />
<u>Klient:</u>&emsp;<b>@context.CustomerName</b><br />
<u>Numer odbiorcy:</u>&emsp;<b>@(context.CustomerSequence?.ToString() ?? "N/A")</b><br />
<u>Data otrzymania:</u>&emsp;<b>@(context.RecivedDate?.ToString("dd.MM.yyyy") ?? "N/A")</b><br />
<u>Wysłano do Syteline?:</u>&emsp;<b>@((context.Posted?.ToString() ?? "0") == "0" ? "NIE" : "TAK")</b><br />
<u>Data wysyłki do Syteline:</u>&emsp;<b>@(context.PostedDate?.ToString("dd.MM.yyyy") ?? "N/A")</b><br />
<u>Data zamówienia:</u>&emsp;<b>@(context.OrderDate?.ToString("dd.MM.yyyy") ?? "N/A")</b><br />
</ItemTemplate>
</SortableList>
<u>Numer zamówienia EDI:</u> <b>@EdiCustomerOrderDto?.CustomerOrderNumber</b><br/>
<u>Numer zamówienia Klienta:</u> <b>@EdiCustomerOrderDto?.CustomerPoNumber</b><br/>
<u>Numer klienta:</u> <b>@EdiCustomerOrderDto?.CustomerNumber</b><br/>
<u>Klient:</u> <b>@EdiCustomerOrderDto?.CustomerName</b><br/>
<u>Numer odbiorcy:</u> <b>@(EdiCustomerOrderDto?.CustomerSequence?.ToString() ?? "N/A")</b><br/>
<u>Data otrzymania:</u> <b>@(EdiCustomerOrderDto?.RecivedDate?.ToString("dd.MM.yyyy") ?? "N/A")</b><br/>
<u>Wysłano do Syteline?:</u> <b>@((EdiCustomerOrderDto?.Posted?.ToString() ?? "0") == "0" ? "NIE" : "TAK")</b><br/>
<u>Data wysyłki do Syteline:</u> <b>@(EdiCustomerOrderDto?.PostedDate?.ToString("dd.MM.yyyy") ?? "N/A")</b><br/>
<u>Data zamówienia:</u> <b>@(EdiCustomerOrderDto?.OrderDate?.ToString("dd.MM.yyyy") ?? "N/A")</b><br/>
</div>
<div class="col">
<SortableList TItem="EdiCustomerOrderDto" Data="_ediCustomerOrder" Class="bg-light">
<ItemTemplate>
<u>Cena:</u>&emsp;<b>@(context.Price?.ToString("F2") ?? "N/A")</b><br />
<u>Waga:</u>&emsp;<b>@(context.Weight?.ToString("F2") ?? "N/A")</b><br />
<u>Magazyn:</u>&emsp;<b>@context.Warehouse</b><br />
<u>Gate:</u>&emsp;<b>@context.Gate</b><br />
<u>Kod odbiorcy:</u>&emsp;<b>@context.RecipientCode</b><br />
<u>Kod wysyłającego:</u>&emsp;<b>@context.SenderCode</b><br />
<u>Kod sprzedawcy:</u>&emsp;<b>@context.SellerCode</b><br />
<u>Kod kupującego:</u>&emsp;<b>@context.BuyerCode</b><br />
<u>Typ dokumentu:</u>&emsp;<b>@context.DocType</b><br />
</ItemTemplate>
</SortableList>
<u>Cena:</u> <b>@(EdiCustomerOrderDto?.Price?.ToString("F2") ?? "N/A")</b><br/>
<u>Waga:</u> <b>@(EdiCustomerOrderDto?.Weight?.ToString("F2") ?? "N/A")</b><br/>
<u>Magazyn:</u> <b>@EdiCustomerOrderDto?.Warehouse</b><br/>
<u>Gate:</u> <b>@EdiCustomerOrderDto?.Gate</b><br/>
<u>Kod odbiorcy:</u> <b>@EdiCustomerOrderDto?.RecipientCode</b><br/>
<u>Kod wysyłającego:</u> <b>@EdiCustomerOrderDto?.SenderCode</b><br/>
<u>Kod sprzedawcy:</u> <b>@EdiCustomerOrderDto?.SellerCode</b><br/>
<u>Kod kupującego:</u> <b>@EdiCustomerOrderDto?.BuyerCode</b><br/>
<u>Typ dokumentu:</u> <b>@EdiCustomerOrderDto?.DocType</b><br/>
</div>
</div>
<br/>
<div class="row">
<h3>Indeksy</h3>
</div>
<div class="row">
<Grid @ref="_ediCustomerOrderLinesGrid"
TItem="EdiCustomerOrderLineDto"
Class="table table-hover table-bordered table-striped"
Data="_ediCustomerOrderLines"
</CardContent>
</SfCard>
<h5 class="text-primary mb-3">Indeksy</h5>
<SfGrid @ref="_ediCustomerOrderLinesGrid"
AllowFiltering="true"
Responsive="true"
AllowPaging="true"
PageSize="10"
AllowSorting="true"
AllowSelection="true"
AllowRowClick="true"
SelectionMode="GridSelectionMode.Single"
SelectedItemsChanged="SelectedEdiCustomerOrderLineChanged">
<GridColumns>
<GridColumn TItem="EdiCustomerOrderLineDto" HeaderText="Linia" PropertyName="CustomerOrderLine">
@context.CustomerOrderLine
</GridColumn>
<GridColumn TItem="EdiCustomerOrderLineDto" HeaderText="Pozycja" PropertyName="Item">
@context.Item
</GridColumn>
<GridColumn TItem="EdiCustomerOrderLineDto" HeaderText="Pozycja Klienta" PropertyName="CustomerItemNumber">
@context.CustomerItemNumber
</GridColumn>
<GridColumn TItem="EdiCustomerOrderLineDto" HeaderText="Opis" PropertyName="Description">
@context.Description
</GridColumn>
<GridColumn TItem="EdiCustomerOrderLineDto" HeaderText="Ilość" TextAlignment="Alignment.End" PropertyName="BlanketQty">
@context.BlanketQty
</GridColumn>
<GridColumn TItem="EdiCustomerOrderLineDto" HeaderText="J/M" PropertyName="Uom">
@context.Uom
</GridColumn>
<GridColumn TItem="EdiCustomerOrderLineDto" HeaderText="Cena" PropertyName="ContPrice">
@context.ContPrice
</GridColumn>
<GridColumn TItem="EdiCustomerOrderLineDto" HeaderText="Status" PropertyName="TranslatedStatus">
@context.TranslatedStatus
</GridColumn>
</GridColumns>
</Grid>
TValue="EdiCustomerOrderLineDto"
DataSource="@_ediCustomerOrderLines"
EnableAdaptiveUI="true">
<GridTemplates>
<DetailTemplate>
@{
var order = context as EdiCustomerOrderLineDto;
<SfCard CssClass="mb-4">
<CardContent>
<div class="row">
<h6>Szczegóły</h6>
<div class="col">
<u>Numer zamówienia EDI:</u> <b>@order?.CustomerOrderNumber</b><br/>
<u>Linia:</u> <b>@order?.CustomerOrderLine</b><br/>
<u>Pozycja:</u> <b>@order?.Item</b><br/>
<u>Pozycja Klienta:</u> <b>@order?.CustomerItemNumber</b><br/>
<u>Opis:</u> <b>@order?.Description</b><br/>
<u>Łączna Ilość:</u> <b>@(order?.BlanketQty?.ToString("F2") ?? "N/A")</b><br/>
<u>Status:</u> <b>@order?.TranslatedStatus</b><br/>
</div>
<div class="col">
<u>Cena:</u> <b>@(order?.ContPrice?.ToString("F2") ?? "N/A")</b><br/>
<u>Ważne Od:</u> <b>@(order?.EffectiveDate?.ToString("dd.MM.yyyy") ?? "N/A")</b><br/>
<u>J/M:</u> <b>@order?.Uom</b><br/>
<u>BoxType:</u> <b>@order?.BoxType</b><br/>
<u>Address:</u> <b>@order?.Address</b><br/>
<u>FinalDestination:</u> <b>@order?.FinalDestination</b><br/>
<u>QtyPerBox:</u> <b>@(order?.QtyPerBox?.ToString() ?? "N/A")</b>
</div>
</div>
</CardContent>
</SfCard>
}
</DetailTemplate>
</GridTemplates>
<GridColumns>
<GridColumn Field=@nameof(EdiCustomerOrderLineDto.CustomerOrderLine) HeaderText="Linia" Width="70"></GridColumn>
<GridColumn Field=@nameof(EdiCustomerOrderLineDto.Item) HeaderText="Pozycja" Width="100"></GridColumn>
<GridColumn Field=@nameof(EdiCustomerOrderLineDto.CustomerItemNumber) HeaderText="Pozycja Klienta" Width="120"></GridColumn>
<GridColumn Field=@nameof(EdiCustomerOrderLineDto.Description) HeaderText="Opis" Width="200"></GridColumn>
<GridColumn Field=@nameof(EdiCustomerOrderLineDto.BlanketQty) HeaderText="Ilość" TextAlign="TextAlign.Right" Width="100"></GridColumn>
<GridColumn Field=@nameof(EdiCustomerOrderLineDto.Uom) HeaderText="J/M" Width="50"></GridColumn>
<GridColumn Field=@nameof(EdiCustomerOrderLineDto.ContPrice) HeaderText="Cena" Width="100"></GridColumn>
<GridColumn Field=@nameof(EdiCustomerOrderLineDto.TranslatedStatus) HeaderText="Status" Width="100"></GridColumn>
</GridColumns>
<GridFilterSettings Type="FilterType.Excel"/>
<GridPageSettings PageSize="10"/>
<GridSelectionSettings Mode="SelectionMode.Row" Type="SelectionType.Single"/>
<GridEvents TValue="EdiCustomerOrderLineDto" RowSelected="OnSelectedLineRow"></GridEvents>
</SfGrid>
@if (_isVisibleEdiCustomerOrderLine)
{
<div class="row">
<h3>Szczegóły</h3>
</div>
<div class="row">
<div class="col">
<SortableList TItem="EdiCustomerOrderLineDto" Data="_selectedEdiCustomerOrderLine">
<ItemTemplate>
<u>Numer zamówienia EDI:</u>&emsp;<b>@context.CustomerOrderNumber</b><br />
<u>Linia:</u>&emsp;<b>@context.CustomerOrderLine</b><br />
<u>Pozycja:</u>&emsp;<b>@context.Item</b><br />
<u>Pozycja Klienta:</u>&emsp;<b>@context.CustomerItemNumber</b><br />
<u>Opis:</u>&emsp;<b>@context.Description</b><br />
<u>Łączna Ilość:</u>&emsp;<b>@(context.BlanketQty?.ToString("F2") ?? "N/A")</b><br />
<u>Status:</u>&emsp;<b>@context.TranslatedStatus</b><br />
</ItemTemplate>
</SortableList>
</div>
<div class="col">
<SortableList TItem="EdiCustomerOrderLineDto" Data="_selectedEdiCustomerOrderLine">
<ItemTemplate>
<u>Cena:</u>&emsp;<b>@(context.ContPrice?.ToString("F2") ?? "N/A")</b><br />
<u>Ważne Od:</u>&emsp;<b>@(context.EffectiveDate?.ToString("dd.MM.yyyy") ?? "N/A")</b><br />
<u>J/M:</u>&emsp;<b>@context.Uom</b><br />
<u>BoxType:</u>&emsp;<b>@context.BoxType</b><br/>
<u>Address:</u>&emsp;<b>@context.Address</b><br/>
<u>FinalDestination:</u>&emsp;<b>@context.FinalDestination</b><br/>
<u>QtyPerBox:</u>&emsp;<b>@(context.QtyPerBox?.ToString() ?? "N/A")</b>
</ItemTemplate>
</SortableList>
</div>
</div>
<br />
<h3>Harmonogramy</h3>
<div class="row">
<Grid @ref="_ediCustomerOrderLineItemsGrid"
TItem="EdiCustomerOrderLineItemDto"
Class="table table-hover table-bordered table-striped"
Data="_ediCustomerOrderLineItems"
<h5 class="text-primary mb-3 mt-4">Harmonogramy</h5>
<SfGrid @ref="_ediCustomerOrderLineItemsGrid"
TValue="EdiCustomerOrderLineItemDto"
DataSource="@_ediCustomerOrderLineItems"
AllowFiltering="true"
Responsive="true"
AllowPaging="true"
PageSize="10"
AllowSelection="true"
AllowRowClick="true"
SelectionMode="GridSelectionMode.Single"
SelectedItemsChanged="SelectedEdiCustomerOrderLineItemChanged">
<GridColumns>
<GridColumn TItem="EdiCustomerOrderLineItemDto" HeaderText="Linia" PropertyName="CustomerOrderLine">
@context.CustomerOrderLine
</GridColumn>
<GridColumn TItem="EdiCustomerOrderLineItemDto" HeaderText="Zwolnienie" PropertyName="CustomerOrderRelease">
@context.CustomerOrderRelease
</GridColumn>
<GridColumn TItem="EdiCustomerOrderLineItemDto" HeaderText="Pozycja" PropertyName="Item">
@context.Item
</GridColumn>
<GridColumn TItem="EdiCustomerOrderLineItemDto" HeaderText="Pozycja" PropertyName="CustomerItem">
@context.CustomerItem
</GridColumn>
<GridColumn TItem="EdiCustomerOrderLineItemDto" HeaderText="Łączna Ilość" TextAlignment="Alignment.End" PropertyName="QtyOrdered">
@context.QtyOrdered
</GridColumn>
<GridColumn TItem="EdiCustomerOrderLineItemDto" HeaderText="Data Wykonania" PropertyName="DueDate">
@context.DueDate?.ToString("dd.MM.yyyy")
</GridColumn>
<GridColumn TItem="EdiCustomerOrderLineItemDto" HeaderText="Status" PropertyName="TranslatedStatus">
@context.TranslatedStatus
</GridColumn>
</GridColumns>
</Grid>
</div>
}@if (_isVisibleEdiCustomerOrderLineItem)
{
<div class="row">
<h3>Szczegóły</h3>
</div>
AllowSorting="true"
SelectionMode="Syncfusion.Blazor.Grids.SelectionMode.Single"
SelectedItemsChanged="SelectedCustomerOrderLineItemChanged">
<GridTemplates>
<DetailTemplate>
@{
var detailLineItem = context as EdiCustomerOrderLineItemDto;
<SfCard CssClass="mb-4">
<CardContent>
<div class="row">
<h6>Szczegóły</h6>
<div class="col">
<SortableList TItem="EdiCustomerOrderLineItemDto" Data="_selectedEdiCustomerOrderLineItem">
<ItemTemplate>
<u>Numer Zamówienia:</u>&emsp;<b>@context.CustomerOrderNumber</b><br />
<u>Linia:</u>&emsp;<b>@context.CustomerOrderLine</b><br />
<u>Zwolnienie:</u>&emsp;<b>@context.CustomerOrderRelease</b><br />
<u>Pozycja:</u>&emsp;<b>@context.Item</b><br />
<u>Pozycja Klienta:</u>&emsp;<b>@context.CustomerItem</b><br />
<u>Łączna Ilość Sztuk:</u>&emsp;<b>@(context.QtyOrdered?.ToString("F2") ?? "N/A")</b><br />
<u>Cena:</u>&emsp;<b>@(context.Price?.ToString("F2") ?? "N/A")</b><br />
<u>Data Wykonania:</u>&emsp;<b>@(context.DueDate?.ToString("dd.MM.yyyy") ?? "N/A")</b><br />
<u>Data Rejestracji:</u>&emsp;<b>@(context.ReleaseDate?.ToString("dd.MM.yyyy") ?? "N/A")</b><br />
<u>Magazyn:</u>&emsp;<b>@context.Warehouse</b><br />
<u>Typ Documentu:</u>&emsp;<b>@context.DocumentType</b><br />
</ItemTemplate>
</SortableList>
<u>Numer Zamówienia:</u> <b>@detailLineItem?.CustomerOrderNumber</b><br/>
<u>Linia:</u> <b>@detailLineItem?.CustomerOrderLine</b><br/>
<u>Zwolnienie:</u> <b>@detailLineItem?.CustomerOrderRelease</b><br/>
<u>Pozycja:</u> <b>@detailLineItem?.Item</b><br/>
<u>Pozycja Klienta:</u> <b>@detailLineItem?.CustomerItem</b><br/>
<u>Łączna Ilość Sztuk:</u> <b>@(detailLineItem?.QtyOrdered?.ToString("F2") ?? "N/A")</b><br/>
<u>Cena:</u> <b>@(detailLineItem?.Price?.ToString("F2") ?? "N/A")</b><br/>
<u>Data Wykonania:</u> <b>@(detailLineItem?.DueDate?.ToString("dd.MM.yyyy") ?? "N/A")</b><br/>
<u>Data Rejestracji:</u> <b>@(detailLineItem?.ReleaseDate?.ToString("dd.MM.yyyy") ?? "N/A")</b><br/>
<u>Magazyn:</u> <b>@detailLineItem?.Warehouse</b><br/>
<u>Typ Dokumentu:</u> <b>@detailLineItem?.DocumentType</b><br/>
</div>
<div class="col">
<SortableList TItem="EdiCustomerOrderLineItemDto" Data="_selectedEdiCustomerOrderLineItem">
<ItemTemplate>
<u>Kod VAT:</u>&emsp;<b>@context.TaxCodeOne</b><br />
<u>J/M:</u>&emsp;<b>@context.Uom</b><br />
<u>Numer Klienta:</u>&emsp;<b>@context.CustomerOrderCustomerNumber</b><br />
<u>Opis:</u>&emsp;<b>@context.Description</b><br />
<u>Status:</u>&emsp;<b>@context.TranslatedStatus</b><br />
<u>RoutingCode:</u>&emsp;<b>@context.RoutingCode</b><br />
<u>DeliveryCallNumber:</u>&emsp;<b>@context.DeliveryCallNumber</b><br />
<u>UnloadingPoint:</u>&emsp;<b>@context.UnloadingPoint</b><br />
<u>DestinationPoint:</u>&emsp;<b>@context.DestinationPoint</b><br />
<u>PalletCode:</u>&emsp;<b>@context.PalletCode</b><br />
<u>PalletNumber:</u>&emsp;<b>@context.PalletNumber</b>
</ItemTemplate>
</SortableList>
<u>Kod VAT:</u> <b>@detailLineItem?.TaxCodeOne</b><br/>
<u>J/M:</u> <b>@detailLineItem?.Uom</b><br/>
<u>Numer Klienta:</u> <b>@detailLineItem?.CustomerOrderCustomerNumber</b><br/>
<u>Opis:</u> <b>@detailLineItem?.Description</b><br/>
<u>Status:</u> <b>@detailLineItem?.TranslatedStatus</b><br/>
<u>RoutingCode:</u> <b>@detailLineItem?.RoutingCode</b><br/>
<u>DeliveryCallNumber:</u> <b>@detailLineItem?.DeliveryCallNumber</b><br/>
<u>UnloadingPoint:</u> <b>@detailLineItem?.UnloadingPoint</b><br/>
<u>DestinationPoint:</u> <b>@detailLineItem?.DestinationPoint</b><br/>
<u>PalletCode:</u> <b>@detailLineItem?.PalletCode</b><br/>
<u>PalletNumber:</u> <b>@detailLineItem?.PalletNumber</b>
</div>
</div>
</CardContent>
</SfCard>
}
</DetailTemplate>
</GridTemplates>
<Syncfusion.Blazor.Grids.GridColumns>
<Syncfusion.Blazor.Grids.GridColumn Field=@nameof(EdiCustomerOrderLineItemDto.CustomerOrderLine) HeaderText="Linia" Width="70"/>
<Syncfusion.Blazor.Grids.GridColumn Field=@nameof(EdiCustomerOrderLineItemDto.CustomerOrderRelease) HeaderText="Zwolnienie" Width="70"/>
<Syncfusion.Blazor.Grids.GridColumn Field=@nameof(EdiCustomerOrderLineItemDto.Item) HeaderText="Pozycja" Width="100"></Syncfusion.Blazor.Grids.GridColumn>
<Syncfusion.Blazor.Grids.GridColumn Field=@nameof(EdiCustomerOrderLineItemDto.CustomerItem) HeaderText="Pozycja Klienta" Width="100"></Syncfusion.Blazor.Grids.GridColumn>
<Syncfusion.Blazor.Grids.GridColumn Field=@nameof(EdiCustomerOrderLineItemDto.QtyOrdered) HeaderText="Łączna Ilość" TextAlign="TextAlign.Right" Width="120"></Syncfusion.Blazor.Grids.GridColumn>
<Syncfusion.Blazor.Grids.GridColumn Field=@nameof(EdiCustomerOrderLineItemDto.DueDate) HeaderText="Data Wykonania" Width="100"/>
<Syncfusion.Blazor.Grids.GridColumn Field=@nameof(EdiCustomerOrderLineItemDto.TranslatedStatus) HeaderText="Status" Width="100"></Syncfusion.Blazor.Grids.GridColumn>
</Syncfusion.Blazor.Grids.GridColumns>
<GridFilterSettings Type="FilterType.Excel"/>
<GridPageSettings PageSize="10"/>
<GridSelectionSettings Mode="SelectionMode.Row" Type="SelectionType.Single"/>
</SfGrid>
}
</CardContent>
<CardFooter>
<small class="text-muted">FA Krosno Manager © @(DateTime.Now.Year)</small>
</CardFooter>
</SfCard>
</div>
@code {
[Parameter] public Guid CustomerOrderId { get; set; }
[Parameter]
public Guid CustomerOrderId { get; set; }
private EdiCustomerOrderDto? EdiCustomerOrderDto { get; set; }
private List<EdiCustomerOrderLineDto> _ediCustomerOrderLines = [];
private List<EdiCustomerOrderLineItemDto> _ediCustomerOrderLineItems = [];
List<EdiCustomerOrderDto?>? _ediCustomerOrder;
List<EdiCustomerOrderLineDto> _ediCustomerOrderLines = [];
List<EdiCustomerOrderLineItemDto> _ediCustomerOrderLineItems = [];
EdiCustomerOrderLineDto? _selectedEdiCustomerOrderLine;
List<EdiCustomerOrderLineDto?> _selectedEdiCustomerOrderLine = [];
List<EdiCustomerOrderLineItemDto?> _selectedEdiCustomerOrderLineItem = [];
Grid<EdiCustomerOrderLineDto>? _ediCustomerOrderLinesGrid;
Grid<EdiCustomerOrderLineItemDto>? _ediCustomerOrderLineItemsGrid;
SfGrid<EdiCustomerOrderLineDto>? _ediCustomerOrderLinesGrid;
SfGrid<EdiCustomerOrderLineItemDto>? _ediCustomerOrderLineItemsGrid;
private bool _isVisibleEdiCustomerOrderLine;
private bool _isVisibleEdiCustomerOrderLineItem;
protected override async Task OnInitializedAsync()
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
// ClaimsPrincipal currentUser = CustomAuthenticationStateProvider.GetCurrentUser();
//
// if (currentUser.Identity?.IsAuthenticated == false)
// {
// NavigationManager.NavigateTo("/Unauthorized");
// }
// else
// {
EdiCustomerOrderDto? ediCustomerOrder = await EdiCustomerOrderService.GetEdiCustomerOrderAsync(CustomerOrderId);
_ediCustomerOrder = [ediCustomerOrder];
EdiCustomerOrderDto = ediCustomerOrder;
_ediCustomerOrderLines = ediCustomerOrder?.EdiCustomerOrderLines.ToList() ?? [];
StateHasChanged();
// }
}
}
private void SelectedEdiCustomerOrderLineChanged(HashSet<EdiCustomerOrderLineDto> obj)
private void OnSelectedLineRow<TValue>(RowSelectEventArgs<TValue> obj)
{
_isVisibleEdiCustomerOrderLine = obj.Any();
_selectedEdiCustomerOrderLine = [obj.FirstOrDefault()];
_ediCustomerOrderLineItems = obj.FirstOrDefault()?.EdiCustomerOrderLineItems.ToList() ?? [];
_isVisibleEdiCustomerOrderLine = obj.Data is not null;
_selectedEdiCustomerOrderLine = obj.Data as EdiCustomerOrderLineDto;
_ediCustomerOrderLineItems = _selectedEdiCustomerOrderLine?.EdiCustomerOrderLineItems.ToList() ?? [];
}
private void SelectedEdiCustomerOrderLineItemChanged(HashSet<EdiCustomerOrderLineItemDto> obj)
{
_isVisibleEdiCustomerOrderLineItem = obj.Any();
_selectedEdiCustomerOrderLineItem = [obj.FirstOrDefault()];
}
}

View File

@@ -2,127 +2,164 @@
@inject EdiCustomerOrderService EdiCustomerOrderService
@inject NavigationManager NavigationManager
@using OrdersManagement.Dtos
@inject CustomAuthenticationStateProvider CustomAuthenticationStateProvider
@using System.Security.Claims
@using Microsoft.AspNetCore.Authorization
@using OrdersManagement.Models
@using SytelineSaAppEfDataModel.Dtos
@using Syncfusion.Blazor.Grids
@using Syncfusion.Blazor.Cards
@using Syncfusion.Blazor.Popups
@using Syncfusion.Blazor.Buttons
@using SelectionType = Syncfusion.Blazor.Grids.SelectionType
@inherits LayoutComponentBase
<div class="row">
<h3>Zamówienia Klienta EDI</h3>
</div>
<br />
<div class="row">
<div class="col-md-12">
<Switch ValueExpression="() => _filter" ValueChanged="FilterChanged" Label="Pokaż wszystkie" />
<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">Zamówienia Klienta EDI</h3>
</CardHeader>
<CardContent>
<div class="row mb-4">
<div class="col-md-12 d-flex align-items-center">
<label for="checked" style="padding: 10px 10px 10px 0">Pokaż wszystkie</label>
<SfSwitch @bind-Checked="_filter" ValueChange="FilterChanged" TChecked="bool?"
OnLabel="Pokaż tylko Wysłane do SL" OffLabel="Pokaż wszystkie"/>
</div>
</div>
<br />
@if (_isVisible)
{
<div class="row">
<div class="row mb-4">
<div class="col-md-12">
<Button Color="ButtonColor.Primary" @onclick="SendOrderToSyteLine">@_text</Button>
<SfButton CssClass="e-primary" IsPrimary="true" @onclick="SendOrderToSyteLine">@_text</SfButton>
</div>
</div>
}
<br />
<div class="row">
<Grid @ref="_grid"
TItem="EdiCustomerOrderDto"
Class="table table-hover table-bordered table-striped"
DataProvider="EdiCustomerOrdersDataProvider"
<SfGrid @ref="_grid"
AllowFiltering="true"
Responsive="true"
AllowPaging="true"
PageSize="10"
AllowSorting="true"
AllowSelection="true"
AllowRowClick="true"
SelectionMode="GridSelectionMode.Multiple"
OnRowDoubleClick="OnRowDoubleClick"
SelectedItemsChanged="SelectedItemsChanged">
<GridColumns>
<GridColumn TItem="EdiCustomerOrderDto" HeaderText="Numer Zamówienia" PropertyName="CustomerOrderNumber">
@context.CustomerOrderNumber
</GridColumn>
<GridColumn TItem="EdiCustomerOrderDto" HeaderText="Zamówienie Klienta" PropertyName="CustomerPoNumber">
@context.CustomerPoNumber
</GridColumn>
<GridColumn TItem="EdiCustomerOrderDto" HeaderText="Numer Klienta" PropertyName="CustomerNumber">
@context.CustomerNumber
</GridColumn>
<GridColumn TItem="EdiCustomerOrderDto" HeaderText="Klient" PropertyName="CustomerName">
@context.CustomerName
</GridColumn>
<GridColumn TItem="EdiCustomerOrderDto" HeaderText="Odbiorca" PropertyName="CustomerSequence">
@context.CustomerSequence
</GridColumn>
<GridColumn TItem="EdiCustomerOrderDto" HeaderText="Data Otrzymania" PropertyName="CreateDate">
@context.CreateDate
</GridColumn>
<GridColumn TItem="EdiCustomerOrderDto" HeaderText="Zamówienie SL" PropertyName="SlOrderNumber">
@context.SlOrderNumber
</GridColumn>
<GridColumn TItem="EdiCustomerOrderDto" HeaderText="Wysłane do SL" PropertyName="SentToSl">
@context.SentToSl
</GridColumn>
</GridColumns>
</Grid>
TValue="EdiCustomerOrderDto"
DataSource="@_ediCustomerOrders"
EnableAdaptiveUI="true">
<GridTemplates>
<DetailTemplate>
@{
var order = context as EdiCustomerOrderDto;
<SfCard CssClass="mb-4">
<CardContent>
<div class="row">
<div class="col">
<u>Numer zamówienia EDI:</u> <b>@order?.CustomerOrderNumber</b><br/>
<u>Numer zamówienia Klienta:</u> <b>@order?.CustomerPoNumber</b><br/>
<u>Numer klienta:</u> <b>@order?.CustomerNumber</b><br/>
<u>Klient:</u> <b>@order?.CustomerName</b><br/>
<u>Numer odbiorcy:</u> <b>@(order?.CustomerSequence?.ToString() ?? "N/A")</b><br/>
<u>Data otrzymania:</u> <b>@(order?.RecivedDate?.ToString("dd.MM.yyyy") ?? "N/A")</b><br/>
<u>Wysłano do Syteline?:</u> <b>@((order?.Posted?.ToString() ?? "0") == "0" ? "NIE" : "TAK")</b><br/>
<u>Data wysyłki do Syteline:</u> <b>@(order?.PostedDate?.ToString("dd.MM.yyyy") ?? "N/A")</b><br/>
<u>Data zamówienia:</u> <b>@(order?.OrderDate?.ToString("dd.MM.yyyy") ?? "N/A")</b><br/>
</div>
<div class="col">
<u>Cena:</u> <b>@(order?.Price?.ToString("F2") ?? "N/A")</b><br/>
<u>Waga:</u> <b>@(order?.Weight?.ToString("F2") ?? "N/A")</b><br/>
<u>Magazyn:</u> <b>@order?.Warehouse</b><br/>
<u>Gate:</u> <b>@order?.Gate</b><br/>
<u>Kod odbiorcy:</u> <b>@order?.RecipientCode</b><br/>
<u>Kod wysyłającego:</u> <b>@order?.SenderCode</b><br/>
<u>Kod sprzedawcy:</u> <b>@order?.SellerCode</b><br/>
<u>Kod kupującego:</u> <b>@order?.BuyerCode</b><br/>
<u>Typ dokumentu:</u> <b>@order?.DocType</b><br/>
</div>
</div>
</CardContent>
</SfCard>
}
</DetailTemplate>
</GridTemplates>
<GridColumns>
<GridColumn Field=@nameof(EdiCustomerOrderDto.CustomerOrderNumber) HeaderText="Numer Zamówienia" Width="110"></GridColumn>
<GridColumn Field=@nameof(EdiCustomerOrderDto.CustomerPoNumber) HeaderText="Zamówienie Klienta" Width="100"></GridColumn>
<GridColumn Field=@nameof(EdiCustomerOrderDto.CustomerNumber) HeaderText="Numer Klienta" Width="90"></GridColumn>
<GridColumn Field=@nameof(EdiCustomerOrderDto.CustomerSequence) HeaderText="Odbiorca" Width="80"></GridColumn>
<GridColumn Field=@nameof(EdiCustomerOrderDto.CreateDate) HeaderText="Data Otrzymania" TextAlign="TextAlign.Center" Width="110"></GridColumn>
<GridColumn Field=@nameof(EdiCustomerOrderDto.SlOrderNumber) HeaderText="Zamówienie SL" Width="100"></GridColumn>
<GridColumn Field=@nameof(EdiCustomerOrderDto.SentToSl) HeaderText="Wysłane do SL" TextAlign="TextAlign.Center" Width="80"></GridColumn>
</GridColumns>
<GridFilterSettings Type="FilterType.Excel"/>
<GridPageSettings PageSize="10"/>
<GridSelectionSettings Mode="SelectionMode.Row" Type="SelectionType.Multiple"/>
<GridEvents TValue="EdiCustomerOrderDto" OnRecordDoubleClick="OnRowDoubleClick" RowSelected="RowSelected"/>
</SfGrid>
<Modal @ref="_modal" Title="@_text">
<BodyTemplate>
<SfDialog Width="500px" Title="@_text" IsModal="true" @bind-Visible="Visibility" AllowPrerender="true">
<DialogTemplates>
<Content>
@if (_responses.Any(x => x.Status == 1))
{
foreach (ResponseDto response in _responses.Where(x => x.Status == 1))
foreach (ResponseModel? response in _responses.Where(x => x.Status == 1))
{
<p>Zamówienie EDI @response.Identifier zostało poprawnie zaksięgowane w Zamówieniach klienta pod numerem '@response.ExternalIdentifier'</p>
}
}
@if (_responses.Any(x => x.Status == 0))
{
foreach (ResponseDto response in _responses.Where(x => x.Status == 0))
foreach (ResponseModel? response in _responses.Where(x => x.Status == 0))
{
<p>Błąd: Zamówienie EDI @response.Identifier nie zostało poprawnie zaksięgowane w Zamówieniach klienta.<br/>Lista błędów:<br/>@response.Message</p>
}
}
</BodyTemplate>
<FooterTemplate>
<Button Color="ButtonColor.Primary" @onclick="OnHideModalClick">OK</Button>
</FooterTemplate>
</Modal>
</Content>
</DialogTemplates>
<DialogButtons>
<DialogButton Content="OK" IsPrimary="true" OnClick="@HideModal"/>
</DialogButtons>
</SfDialog>
</CardContent>
<CardFooter>
<small class="text-muted">FA Krosno Manager © @(DateTime.Now.Year)</small>
</CardFooter>
</SfCard>
</div>
@code {
Grid<EdiCustomerOrderDto>? _grid;
private List<EdiCustomerOrderDto> _ediCustomerOrders = new();
private bool Visibility { get; set; }
private SfGrid<EdiCustomerOrderDto>? _grid;
private IEnumerable<EdiCustomerOrderDto> _ediCustomerOrders = [];
private List<EdiCustomerOrderDto> _selectedEdiCustomerOrders = new();
private List<ResponseDto> _responses = new();
private Modal _modal = null!;
private List<ResponseModel?> _responses = new();
private bool _isVisible;
private bool _filter;
private bool? _filter = false;
private string _text = "Księguj bieżący";
private async Task<GridDataProviderResult<EdiCustomerOrderDto>> EdiCustomerOrdersDataProvider(GridDataProviderRequest<EdiCustomerOrderDto> request)
protected override async Task OnAfterRenderAsync(bool firstRender)
{
_ediCustomerOrders = (await EdiCustomerOrderService.GetEdiCustomerOrdersAsync() ?? new List<EdiCustomerOrderDto>()).ToList();
_ediCustomerOrders = _ediCustomerOrders.OrderByDescending(x => x.CreateDate).ToList();
if (!_filter)
if (firstRender)
{
_ediCustomerOrders = _ediCustomerOrders.Where(x => x.Posted == 0).ToList();
// ClaimsPrincipal currentUser = CustomAuthenticationStateProvider.GetCurrentUser();
//
// if (currentUser.Identity?.IsAuthenticated == false)
// {
// NavigationManager.NavigateTo("/Unauthorized");
// }
// else
// {
await LoadData();
// }
}
}
StateHasChanged();
return await Task.FromResult(request.ApplyTo(_ediCustomerOrders));
}
private void OnRowDoubleClick(GridRowEventArgs<EdiCustomerOrderDto> obj)
private void OnRowDoubleClick(RecordDoubleClickEventArgs<EdiCustomerOrderDto> obj)
{
Guid customerOrderId = obj.Item.RowPointer;
Guid customerOrderId = obj.RowData.RowPointer;
NavigationManager.NavigateTo($"/EdiCustomerOrder/{customerOrderId}");
}
@@ -131,11 +168,11 @@
{
if (!_selectedEdiCustomerOrders.Any()) return false;
_responses = new List<ResponseDto>();
_responses = new List<ResponseModel?>();
foreach (EdiCustomerOrderDto selectedEdiCustomerOrder in _selectedEdiCustomerOrders)
{
ResponseDto response = await EdiCustomerOrderService.SendOrderToSyteline(selectedEdiCustomerOrder.RowPointer, selectedEdiCustomerOrder.CustomerOrderNumber);
ResponseModel? response = await EdiCustomerOrderService.SendOrderToSyteline(selectedEdiCustomerOrder.RowPointer, selectedEdiCustomerOrder.CustomerOrderNumber);
if (response.Status == 1)
{
@@ -145,31 +182,54 @@
_responses.Add(response);
}
await _modal.ShowAsync();
_grid?.RefreshDataAsync();
Visibility = true;
await LoadData();
_grid?.Refresh();
_isVisible = false;
return true;
}
private void SelectedItemsChanged(HashSet<EdiCustomerOrderDto> obj)
private void HideModal()
{
Visibility = false;
}
private async Task RowSelected(RowSelectEventArgs<EdiCustomerOrderDto> obj)
{
List<EdiCustomerOrderDto> selectedRecords = await _grid.GetSelectedRecordsAsync();
_isVisible = false;
if (!obj.Any()) return;
if (!selectedRecords.Any()) return;
_selectedEdiCustomerOrders = obj.ToList();
_selectedEdiCustomerOrders = selectedRecords;
_isVisible = _selectedEdiCustomerOrders.Any(x => x.Posted == 0);
_text = obj.Count > 1 ? "Księguj zaznaczone" : "Księguj bieżący";
_text = selectedRecords.Count > 1 ? "Księguj zaznaczone" : "Księguj bieżący";
}
private async Task OnHideModalClick()
private async Task FilterChanged(ChangeEventArgs<bool?> obj)
{
await _modal.HideAsync();
_filter = obj.Checked;
await LoadData();
_grid?.Refresh();
}
private void FilterChanged(bool obj)
private async Task LoadData()
{
_filter = obj;
_grid?.RefreshDataAsync();
_ediCustomerOrders = await EdiCustomerOrderService.GetEdiCustomerOrdersAsync() ?? new List<EdiCustomerOrderDto>();
if (_filter == false)
{
_ediCustomerOrders = _ediCustomerOrders.Where(x => x.Posted == 0).ToList();
}
_ediCustomerOrders = _ediCustomerOrders.OrderByDescending(x => x.CreateDate).ToList();
StateHasChanged();
}
}

View File

@@ -0,0 +1,163 @@
@page "/login"
@using Microsoft.AspNetCore.Authorization
@using OrdersManagement.Models
@using Syncfusion.Blazor.Inputs
@using Syncfusion.Blazor.Buttons
@using Syncfusion.Blazor.Cards
@inject UserService UserService
@inject NavigationManager NavigationManager
<div class="h-100 d-flex justify-content-center align-items-start">
<SfCard CssClass="text-center shadow" style="max-width: 500px;">
<CardHeader>
<h3 class="text-primary">Logowanie</h3>
</CardHeader>
<CardContent>
@if (!string.IsNullOrEmpty(TempPassword))
{
<div class="alert alert-info mb-3">
Twoje tymczasowe hasło to: <strong>@TempPassword</strong>. Użyj go do pierwszego logowania.
</div>
}
<EditForm Model="@LoginModel" FormName="LoginForm" OnValidSubmit="@HandleLogin">
<DataAnnotationsValidator/>
<ValidationSummary class="text-danger mb-3"/>
<div class="form-group mb-3">
<label for="login" class="d-block text-start">Login</label>
<SfTextBox ID="login" @bind-Value="LoginModel.Login" Placeholder="Wprowadź login" CssClass="e-outline"/>
<ValidationMessage For="@(() => LoginModel.Login)" ClassName="text-danger"/>
</div>
<div class="form-group mb-3">
<label for="password" class="d-block text-start">Hasło</label>
<SfTextBox ID="password" Type="InputType.Password" @bind-Value="LoginModel.Password"
Placeholder="Wprowadź hasło" CssClass="e-outline"/>
<ValidationMessage For="@(() => LoginModel.Password)" ClassName="text-danger"/>
</div>
<div class="form-group mt-3">
<SfButton CssClass="e-primary" IsPrimary="true" Type="submit">Zaloguj</SfButton>
</div>
@if (!string.IsNullOrEmpty(ErrorMessage))
{
<div class="alert alert-danger mt-3">@ErrorMessage</div>
}
</EditForm>
@if (ShowChangePassword)
{
<hr class="my-4"/>
<h5 class="text-success mb-3">Zmień hasło</h5>
<EditForm Model="@ChangePasswordModel" FormName="ChangePasswordForm" OnValidSubmit="@HandleChangePassword">
<DataAnnotationsValidator/>
<ValidationSummary class="text-danger mb-3"/>
<div class="form-group mb-3">
<label for="newPassword" class="d-block text-start">Nowe hasło</label>
<SfTextBox ID="newPassword" Type="InputType.Password" @bind-Value="ChangePasswordModel.NewPassword"
Placeholder="Wprowadź nowe hasło" CssClass="e-outline"/>
<ValidationMessage For="@(() => ChangePasswordModel.NewPassword)" ClassName="text-danger"/>
</div>
<div class="form-group mb-3">
<label for="confirmPassword" class="d-block text-start">Potwierdź hasło</label>
<SfTextBox ID="confirmPassword" Type="InputType.Password" @bind-Value="ChangePasswordModel.ConfirmPassword"
Placeholder="Potwierdź nowe hasło" CssClass="e-outline"/>
<ValidationMessage For="@(() => ChangePasswordModel.ConfirmPassword)" ClassName="text-danger"/>
</div>
<div class="form-group mt-3">
<SfButton CssClass="e-success" IsPrimary="true" Type="submit">Zmień hasło</SfButton>
</div>
</EditForm>
}
</CardContent>
<CardFooter>
<small class="text-muted">FA Krosno Manager © @(DateTime.Now.Year)</small>
</CardFooter>
</SfCard>
</div>
@code {
private LoginModel LoginModel { get; set; } = new();
private ChangePasswordModel ChangePasswordModel { get; set; } = new();
private bool ShowChangePassword { get; set; }
private string TempPassword { get; set; }
private string ErrorMessage { get; set; }
protected override void OnInitialized()
{
TempPassword = NavigationManager.Uri.Split('?').Length > 1 ? Uri.UnescapeDataString(NavigationManager.Uri.Split('=')[1]) : null;
}
private async Task HandleLogin()
{
try
{
Console.WriteLine($"Próba logowania dla: {LoginModel.Login}");
var user = await UserService.AuthenticateUserAsync(LoginModel.Login, LoginModel.Password);
if (user != null)
{
Console.WriteLine($"Użytkownik {user.Login} znaleziony.");
if (user.IsTemporaryPassword)
{
ShowChangePassword = true;
StateHasChanged();
}
else
{
NavigationManager.NavigateTo("/ScheduleOrders");
}
}
else
{
ErrorMessage = "Nieprawidłowy login lub hasło";
Console.WriteLine(ErrorMessage);
StateHasChanged();
}
}
catch (Exception ex)
{
ErrorMessage = $"Błąd logowania: {ex.Message}";
Console.WriteLine(ErrorMessage);
StateHasChanged();
}
}
private async Task HandleChangePassword()
{
try
{
if (ChangePasswordModel.NewPassword == ChangePasswordModel.ConfirmPassword)
{
var user = await UserService.GetUserByUsernameAsync(LoginModel.Login);
if (user != null)
{
user.PasswordHash = BCrypt.Net.BCrypt.HashPassword(ChangePasswordModel.NewPassword);
user.IsTemporaryPassword = false;
await UserService.UpdateUserAsync(user);
ShowChangePassword = false;
LoginModel = new LoginModel();
StateHasChanged();
NavigationManager.NavigateTo("/login");
}
}
else
{
ErrorMessage = "Hasła nie są zgodne";
StateHasChanged();
}
}
catch (Exception ex)
{
ErrorMessage = $"Błąd zmiany hasła: {ex.Message}";
StateHasChanged();
}
}
}

View File

@@ -0,0 +1,19 @@
@page "/Main"
@using Microsoft.AspNetCore.Authorization
@inject CustomAuthenticationStateProvider CustomAuthenticationStateProvider
@inject NavigationManager NavigationManager
@code {
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
await CustomAuthenticationStateProvider.MarkUserAsLoggedOut();
NavigationManager.NavigateTo("/login");
}
}
}

View File

@@ -0,0 +1,76 @@
@page "/Products"
@using Syncfusion.Blazor.Grids
@using Syncfusion.Blazor.Cards
@using Action = Syncfusion.Blazor.Grids.Action
@inject ProductService ProductService
@inject CustomAuthenticationStateProvider CustomAuthenticationStateProvider
<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">Zarządzanie Indeksami</h3>
</CardHeader>
<CardContent>
<SfGrid DataSource="@_products"
AllowPaging="true"
ShowColumnMenu="true"
Toolbar="@(new List<string> { "Update" })">
<GridColumns>
<GridColumn Field="@nameof(ProductDto.ID)" AllowEditing="false" IsPrimaryKey="true" HeaderText="ID" Width="70"></GridColumn>
<GridColumn Field="@nameof(ProductDto.RecipientID)" AllowEditing="false" HeaderText="Odbiorca" Width="100"></GridColumn>
<GridColumn Field="@nameof(ProductDto.RecipientIdx)" AllowEditing="false" HeaderText="Indeks odbiorcy" Width="100"></GridColumn>
<GridColumn Field="@nameof(ProductDto.FaIdx)" HeaderText="Kod FA" Width="100"></GridColumn>
</GridColumns>
<GridEditSettings AllowEditing="true">
</GridEditSettings>
<GridEvents OnActionComplete="UserActionComplete"
TValue="ProductDto">
</GridEvents>
<GridPageSettings PageSize="10"></GridPageSettings>
</SfGrid>
</CardContent>
<CardFooter>
<small class="text-muted">FA Krosno Manager © @(DateTime.Now.Year)</small>
</CardFooter>
</SfCard>
</div>
@code {
private IEnumerable<ProductDto>? _products { get; set; }
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
// ClaimsPrincipal currentUser = CustomAuthenticationStateProvider.GetCurrentUser();
//
// if (currentUser.Identity?.IsAuthenticated == false)
// {
// NavigationManager.NavigateTo("/Unauthorized");
// }
// else
// {
await GetProducts();
// }
}
}
private async Task UserActionComplete(ActionEventArgs<ProductDto> args)
{
switch (args.RequestType)
{
case Action.Save:
await ProductService.UpdateProductAsync(args.Data);
await GetProducts();
break;
}
}
private async Task GetProducts()
{
_products = await ProductService.GetProductsByIndexAsync("Uzupelnij") ?? new List<ProductDto>();
StateHasChanged();
}
}

View File

@@ -0,0 +1,87 @@
@page "/register"
@using OrdersManagement.Models
@using OrdersManagementDataModel.Dtos
@using Syncfusion.Blazor.Inputs
@using Syncfusion.Blazor.Buttons
@using Syncfusion.Blazor.Cards
@inject UserService UserService
@inject NavigationManager NavigationManager
<div class="h-100 d-flex flex-column">
<h5>Rejestracja</h5>
<br/>
<SfCard>
<CardHeader Title="Zarejestruj się"/>
<CardContent>
<EditForm Model="@RegisterModel" OnValidSubmit="HandleRegister">
<DataAnnotationsValidator/>
<ValidationSummary/>
<div class="form-group">
<label for="login">Login</label>
<SfTextBox ID="login" @bind-Value="RegisterModel.Login" Placeholder="Wprowadź login"
CssClass="e-outline"/>
<ValidationMessage For="@(() => RegisterModel.Login)"/>
</div>
<div class="form-group">
<label for="email">Email</label>
<SfTextBox ID="email" @bind-Value="RegisterModel.Email" Placeholder="Wprowadź email"
CssClass="e-outline"/>
<ValidationMessage For="@(() => RegisterModel.Email)"/>
</div>
<div class="form-group">
<label for="firstName">Imię</label>
<SfTextBox ID="firstName" @bind-Value="RegisterModel.FirstName" Placeholder="Wprowadź imię"
CssClass="e-outline"/>
<ValidationMessage For="@(() => RegisterModel.FirstName)"/>
</div>
<div class="form-group">
<label for="lastName">Nazwisko</label>
<SfTextBox ID="lastName" @bind-Value="RegisterModel.LastName" Placeholder="Wprowadź nazwisko"
CssClass="e-outline"/>
<ValidationMessage For="@(() => RegisterModel.LastName)"/>
</div>
<div class="form-group mt-3">
<SfButton CssClass="e-primary" IsPrimary="true" Type="submit">Zarejestruj</SfButton>
</div>
</EditForm>
</CardContent>
</SfCard>
</div>
@code {
private RegisterModel RegisterModel { get; set; } = new();
private async Task HandleRegister()
{
var temporaryPassword = Guid.NewGuid().ToString().Substring(0, 8);
var passwordHash = BCrypt.Net.BCrypt.HashPassword(temporaryPassword);
var user = new UserDto
{
Login = RegisterModel.Login,
PasswordHash = passwordHash,
IsTemporaryPassword = true,
IsActive = true,
ActiveFrom = DateTime.Now,
Email = RegisterModel.Email,
FirstName = RegisterModel.FirstName,
LastName = RegisterModel.LastName,
CreatedDate = DateTime.Now,
RowPointer = Guid.NewGuid()
};
var result = await UserService.AddUserAsync(user);
if (result.IsSuccessStatusCode)
{
NavigationManager.NavigateTo($"/login?tempPassword={Uri.EscapeDataString(temporaryPassword)}");
}
}
}

View File

@@ -1,137 +1,166 @@
@page "/ScheduleOrder/{ScheduleOrderId:int}"
@inject ScheduleOrderDetailsService ScheduleOrderDetailsService
@using System.Security.Claims
@using Microsoft.AspNetCore.Authorization
@using Syncfusion.Blazor.Grids
@using Syncfusion.Blazor.Lists
@using Syncfusion.Blazor.Cards
@inject ScheduleOrderService ScheduleOrderService
@inject NavigationManager NavigationManager
@inject CustomAuthenticationStateProvider CustomAuthenticationStateProvider
<div class="row">
<h3>Indeksy</h3>
</div>
<div class="row">
<Grid @ref="_grid"
TItem="ScheduleOrderDetailDto"
Class="table table-hover table-bordered table-striped"
DataProvider="ScheduleOrderDetailsDataProvider"
AllowFiltering="true"
Responsive="true"
AllowPaging="true"
PageSize="20"
AllowSelection="true"
AllowRowClick="true"
SelectionMode="GridSelectionMode.Single"
SelectedItemsChanged="SelectedItemChanged">
<GridColumns>
<GridColumn TItem="ScheduleOrderDetailDto" HeaderText="Pozycja"
PropertyName="SalesChannelProductCode">
@context.Sc_productCode
</GridColumn>
<GridColumn TItem="ScheduleOrderDetailDto" HeaderText="Pozycja Klienta"
PropertyName="ShipperProductCode">
@context.Sh_productCode
</GridColumn>
<GridColumn TItem="ScheduleOrderDetailDto" HeaderText="Cena" PropertyName="Price">
@context.Price
</GridColumn>
</GridColumns>
</Grid>
</div>
@if (_isVisible)
{
<div class="row">
<h2>Dodatkowe informacje</h2>
</div>
<div class="row">
<SortableList TItem="ScheduleOrderDetailMiscDto" Data="_scheduleOrderDetailMiscs">
<ItemTemplate>
<u>@context.Label:</u>&emsp;<b>@context.Value</b>
</ItemTemplate>
</SortableList>
</div>
<br/>
<div class="row">
<h3>Harmonogramy</h3>
</div>
<div class="row">
<Grid @ref="_detailDetailsGrid"
TItem="ScheduleOrderDetailDetailDto"
Data="_scheduleOrderDetailsDetails"
Class="table table-hover table-bordered table-striped"
AllowFiltering="true"
Responsive="true"
AllowPaging="true"
PageSize="20"
AllowSelection="true"
SelectionMode="GridSelectionMode.Single"
SelectedItemsChanged="SelectedDetailDetailChanged">
<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">Zamówienie DELFOR nr @(ScheduleOrderDto?.PONum ?? "Brak numeru")</h3>
</CardHeader>
<CardContent>
<SfListView Id="ScheduleOrderMiscs"
DataSource="@ScheduleOrderDto?.ScheduleOrderMiscs"
ShowHeader="false"
CssClass="e-list-template mb-4">
<ListViewFieldSettings TValue="ScheduleOrderMiscDto" Id="ScheduleOrderMiscListId" Text="Text"></ListViewFieldSettings>
<ListViewTemplates Context="item" TValue="ScheduleOrderMiscDto">
<Template>
<span class="e-list-content"><b>@item.Label:</b>@item.Value</span>
</Template>
</ListViewTemplates>
</SfListView>
<h5 class="text-primary mb-3">Indeksy</h5>
<SfGrid AllowFiltering="true"
AllowPaging="true"
AllowSorting="true"
AllowSelection="true"
TValue="ScheduleOrderDetailDto"
DataSource="@_scheduleOrderDetails"
EnableAdaptiveUI="true">
<GridTemplates>
<DetailTemplate>
@{
IList<ScheduleOrderDetailMiscDto>? scheduleOrderDetailMiscs = (@context as ScheduleOrderDetailDto)?.ScheduleOrderDetailMiscs;
IList<ScheduleOrderDetailDetailDto>? scheduleOrderDetailDetails = (@context as ScheduleOrderDetailDto)?.ScheduleOrderDetailDetails;
<SfListView Id="ScheduleOrderDetailMiscs"
DataSource="@scheduleOrderDetailMiscs"
ShowHeader="false"
CssClass="e-list-template mb-4">
<ListViewFieldSettings TValue="ScheduleOrderDetailMiscDto" Id="ScheduleOrderDetailMiscListId" Text="Text"></ListViewFieldSettings>
<ListViewTemplates Context="item" TValue="ScheduleOrderDetailMiscDto">
<Template>
<span class="e-list-content"><b>@item.Label:</b>@item.Value</span>
</Template>
</ListViewTemplates>
</SfListView>
<h5 class="text-primary mb-3">Harmonogramy</h5>
<SfGrid AllowFiltering="true"
AllowPaging="true"
AllowSorting="true"
AllowSelection="true"
TValue="ScheduleOrderDetailDetailDto"
DataSource="@scheduleOrderDetailDetails"
EnableAdaptiveUI="true"
AdaptiveUIMode="AdaptiveMode.Both">
<GridEvents TValue="ScheduleOrderDetailDetailDto" RowDataBound="OnRowDataBound"/>
<GridTemplates Context="detailDetail">
<DetailTemplate>
@{
IList<ScheduleOrderDetailDetailMiscDto>? scheduleOrderDetailDetailMiscs = (@detailDetail as ScheduleOrderDetailDetailDto)?.ScheduleOrderDetailDetailMiscs;
<SfListView Id="ScheduleOrderDetailDetailMiscs"
DataSource="@scheduleOrderDetailDetailMiscs"
ShowHeader="false"
CssClass="e-list-template mb-4">
<ListViewFieldSettings TValue="ScheduleOrderDetailDetailMiscDto" Id="ScheduleOrderDetailDetailMiscListId" Text="Text"></ListViewFieldSettings>
<ListViewTemplates Context="item" TValue="ScheduleOrderDetailDetailMiscDto">
<Template>
<span class="e-list-content"><b>@item.Label:</b>@item.Value</span>
</Template>
</ListViewTemplates>
</SfListView>
}
</DetailTemplate>
</GridTemplates>
<GridColumns>
<GridColumn TItem="ScheduleOrderDetailDetailDto" HeaderText="Id" PropertyName="Id">
@context.ID
</GridColumn>
<GridColumn TItem="ScheduleOrderDetailDetailDto" HeaderText="Data Od" PropertyName="DateFrom">
@context.DateFrom.ToString("dd.MM.yyyy")
</GridColumn>
<GridColumn TItem="ScheduleOrderDetailDetailDto" HeaderText="Data Do" PropertyName="DateTo">
@context.DateTo.ToString("dd.MM.yyyy")
</GridColumn>
<GridColumn TItem="ScheduleOrderDetailDetailDto" HeaderText="Ilość Sztuk" PropertyName="Qty">
@context.Qty
</GridColumn>
<GridColumn TItem="ScheduleOrderDetailDetailDto" HeaderText="Typ Qty" PropertyName="QtyType">
@context.QtyType
</GridColumn>
<GridColumn TItem="ScheduleOrderDetailDetailDto" HeaderText="Opis Typu" PropertyName="QtyDesc">
@context.QtyDesc
</GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDetailDetailDto.DateFrom) HeaderText="Data Od" Width="100"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDetailDetailDto.DateTo) HeaderText="Data Do" Width="100"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDetailDetailDto.Qty) TextAlign="TextAlign.Right" HeaderText="Ilość Sztuk" Width="50"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDetailDetailDto.QtyType) TextAlign="TextAlign.Right" HeaderText="Typ Qty" Width="50"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDetailDetailDto.QtyDesc) HeaderText="Opis Typu" Width="100"></GridColumn>
</GridColumns>
</Grid>
</div>
<GridFilterSettings Type="FilterType.Excel"/>
<GridPageSettings PageSize="10"/>
<GridSelectionSettings Mode="SelectionMode.Row" Type="SelectionType.Single"/>
</SfGrid>
}
@if (_isVisibleDetailDetail)
{
<div class="row">
<h2>Dodatkowe informacje</h2>
</DetailTemplate>
</GridTemplates>
<GridColumns>
<GridColumn Field=@nameof(ScheduleOrderDetailDto.OrderNumber) HeaderText="Numer Zamówienia" Width="100"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDetailDto.PurchaserName) HeaderText="Klient" Width="100"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDetailDto.RecipientName) HeaderText="Odbiorca" Width="100"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDetailDto.RecipientCode) HeaderText="Kod odbiorcy" Width="100" AllowFiltering="true"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDetailDto.Sh_productCode) HeaderText="Pozycja" Width="100"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDetailDto.Sc_productCode) HeaderText="Pozycja Klienta" Width="100"></GridColumn>
</GridColumns>
<GridFilterSettings Type="FilterType.Excel"/>
<GridPageSettings PageSize="10"/>
<GridSelectionSettings Mode="SelectionMode.Row" Type="SelectionType.Single"/>
</SfGrid>
</CardContent>
<CardFooter>
<small class="text-muted">FA Krosno Manager © @(DateTime.Now.Year)</small>
</CardFooter>
</SfCard>
</div>
<div class="row">
<SortableList TItem="ScheduleOrderDetailDetailMiscDto" Data="_scheduleOrderDetailDetailMiscs">
<ItemTemplate>
<u>@context.Label:</u>&emsp;<b>@context.Value</b>
</ItemTemplate>
</SortableList>
</div>
}
@code {
[Parameter] public int ScheduleOrderId { get; set; }
private bool _isVisible;
private bool _isVisibleDetailDetail;
Grid<ScheduleOrderDetailDto>? _grid;
Grid<ScheduleOrderDetailDetailDto>? _detailDetailsGrid;
private IEnumerable<ScheduleOrderDetailDto>? _scheduleOrderDetails;
private IEnumerable<ScheduleOrderDetailDetailDto>? _scheduleOrderDetailsDetails;
private List<ScheduleOrderDetailMiscDto>? _scheduleOrderDetailMiscs;
private List<ScheduleOrderDetailDetailMiscDto>? _scheduleOrderDetailDetailMiscs;
private ScheduleOrderDto? ScheduleOrderDto { get; set; }
private async Task<GridDataProviderResult<ScheduleOrderDetailDto>> ScheduleOrderDetailsDataProvider(GridDataProviderRequest<ScheduleOrderDetailDto> request)
protected override async Task OnAfterRenderAsync(bool firstRender)
{
_scheduleOrderDetails = await ScheduleOrderDetailsService.GetScheduleOrderDetails(ScheduleOrderId) ?? new List<ScheduleOrderDetailDto>();
if (firstRender)
{
// ClaimsPrincipal currentUser = CustomAuthenticationStateProvider.GetCurrentUser();
//
// if (currentUser.Identity?.IsAuthenticated == false)
// {
// NavigationManager.NavigateTo("/Unauthorized");
// }
// else
// {
ScheduleOrderDto = await ScheduleOrderService.GetScheduleOrderAsync(ScheduleOrderId);
_scheduleOrderDetails = ScheduleOrderDto?.ScheduleOrderDetails;
if (ScheduleOrderDto is not null && _scheduleOrderDetails is not null)
{
foreach (ScheduleOrderDetailDto scheduleOrderDetailDto in _scheduleOrderDetails)
{
scheduleOrderDetailDto.OrderNumber = ScheduleOrderDto?.PONum;
scheduleOrderDetailDto.RecipientCode = ScheduleOrderDto?.RecipientCode;
scheduleOrderDetailDto.RecipientName = ScheduleOrderDto?.RecipientName;
scheduleOrderDetailDto.PurchaserName = ScheduleOrderDto?.PurchaserCode;
}
// }
StateHasChanged();
return await Task.FromResult(request.ApplyTo(_scheduleOrderDetails));
}
}
}
private void SelectedItemChanged(HashSet<ScheduleOrderDetailDto> obj)
private void OnRowDataBound(RowDataBoundEventArgs<ScheduleOrderDetailDetailDto> args)
{
_isVisible = obj.Any();
_scheduleOrderDetailMiscs = obj.FirstOrDefault()?.ScheduleOrderDetailMiscs.ToList();
_scheduleOrderDetailsDetails = obj.FirstOrDefault()?.ScheduleOrderDetailDetails.ToList();
}
private void SelectedDetailDetailChanged(HashSet<ScheduleOrderDetailDetailDto> obj)
if (args.Data.QtyType == "83" || args.Data.QtyType == "84")
{
_isVisibleDetailDetail = obj.Any();
_scheduleOrderDetailDetailMiscs = obj.FirstOrDefault()?.ScheduleOrderDetailDetailMiscs.ToList();
args.Row.AddClass(["highlight-red"]);
}
}
}

View File

@@ -1,30 +1,54 @@
@page "/"
@using System.Security.Claims
@using Microsoft.AspNetCore.Authorization
@using OrdersManagement.Components.Pages.Shared
@inject ScheduleOrderService ScheduleOrderService
@inherits LayoutComponentBase
@using Syncfusion.Blazor.Grids
<div class="row">
<h3>Zamówienia DELFOR </h3>
</div>
<br />
<ScheduleOrdersGrid PageSize="20" PassGridRef="SetGridRef" DataProvider="ScheduleOrdersDataProvider"></ScheduleOrdersGrid>
@inject ScheduleOrderService ScheduleOrderService
@inject CustomAuthenticationStateProvider CustomAuthenticationStateProvider
@inject NavigationManager NavigationManager;
<ScheduleOrdersGrid PageSize="20" @ref="_grid" PassGridRef="SetGridRef" GridData="_scheduleOrders" />
@code {
private IEnumerable<ScheduleOrderDto>? _scheduleOrders;
private IEnumerable<ScheduleOrderDto> _scheduleOrders = [];
private Grid<ScheduleOrderDto> _gridRef;
private ScheduleOrdersGrid _grid { get; set; }
private async Task<GridDataProviderResult<ScheduleOrderDto>> ScheduleOrdersDataProvider(GridDataProviderRequest<ScheduleOrderDto> request)
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
// ClaimsPrincipal currentUser = CustomAuthenticationStateProvider.GetCurrentUser();
//
// if (currentUser.Identity?.IsAuthenticated == false)
// {
// NavigationManager.NavigateTo("/Unauthorized");
// }
// else
// {
_scheduleOrders = await FetchScheduleOrdersAsync();
StateHasChanged();
//
// }
}
else
{
await _grid.RestoreFilterFromLocalStorage();
}
}
private async Task<IEnumerable<ScheduleOrderDto>> FetchScheduleOrdersAsync()
{
_scheduleOrders = await ScheduleOrderService.GetScheduleOrdersAsync() ?? new List<ScheduleOrderDto>();
_scheduleOrders = _scheduleOrders.OrderByDescending(x => x.LastUpdateDate).ToList();
StateHasChanged();
return await Task.FromResult(request.ApplyTo(_scheduleOrders));
return _scheduleOrders;
}
private async Task SetGridRef(Grid<ScheduleOrderDto> grid)
private SfGrid<ScheduleOrderDto> _gridRef;
private async Task SetGridRef(SfGrid<ScheduleOrderDto> grid)
{
_gridRef = grid;
}

View File

@@ -1,71 +1,286 @@
@inject NavigationManager NavigationManager
@using System.Text.Json
@using Syncfusion.Blazor.Grids
@using Syncfusion.Blazor.Cards
@using Syncfusion.Blazor.Data
@using FilterType = Syncfusion.Blazor.Grids.FilterType
@using Syncfusion.Blazor.Navigations
@inherits LayoutComponentBase
<div class="row">
<Grid @ref="_grid"
TItem="ScheduleOrderDto"
Class="table table-hover table-bordered table-striped"
AllowFiltering="true"
Responsive="true"
AllowPaging="true"
PageSize="@PageSize"
AllowSelection="true"
AllowRowClick="true"
DataProvider="LoadData"
OnRowDoubleClick="OnRowDoubleClick">
@inject ScheduleOrderService ScheduleOrderService
@inject IJSRuntime JSRuntime
<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">Zamówienia DELFOR</h3>
</CardHeader>
<CardContent>
<SfGrid @ref="Grid"
TValue="ScheduleOrderDto"
AllowFiltering="true"
AllowPaging="true"
AllowSorting="true"
AllowSelection="true"
DataSource="@_dataSource"
EnableAdaptiveUI="true"
EnablePersistence="true"
AdaptiveUIMode="AdaptiveMode.Both"
AllowRowClick="true"
SelectionMode="GridSelectionMode.Single"
QueryCellInfo="OnQueryCellInfo"
RowSelected="OnRowSelected">
<SfToolbar>
<ToolbarItems>
<ToolbarItem Type="ItemType.Button" Text="Zapisz Filtry" Id="SaveButton"
PrefixIcon="e-icons e-save" OnClick="SaveFilters"/>
<ToolbarItem Type="ItemType.Button" Id="DeleteButton" PrefixIcon="e-icons e-delete"
Text="Usuń Zapisane Filtry" OnClick="DeleteFilters"/>
</ToolbarItems>
</SfToolbar>
<GridColumns>
<GridColumn TItem="ScheduleOrderDto" HeaderText="Zamówienie" PropertyName="OrderID">
@context.OrderID
</GridColumn>
<GridColumn TItem="ScheduleOrderDto" HeaderText="Zamówienie Klienta" PropertyName="PONum">
@context.PONum
</GridColumn>
<GridColumn TItem="ScheduleOrderDto" HeaderText="Odbiorca" PropertyName="RecipientCode">
@context.RecipientCode
</GridColumn>
<GridColumn TItem="ScheduleOrderDto" HeaderText="Klient" PropertyName="PurchaserCode">
@context.PurchaserCode
</GridColumn>
<GridColumn TItem="ScheduleOrderDto" HeaderText="Data Utworzenia" PropertyName="LastUpdateDate">
@context.LastUpdateDate
</GridColumn>
<GridColumn TItem="ScheduleOrderDto" HeaderText="Typ Dokumentu" PropertyName="DocType">
@context.DocType
</GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDto.PONum) HeaderText="Zamówienie Klienta" Width="150"
AllowFiltering="true"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDto.PurchaserCode) HeaderText="Klient" Width="100"
AllowFiltering="true"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDto.RecipientName) HeaderText="Odbiorca" Width="100"
AllowFiltering="true"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDto.RecipientCode) HeaderText="Kod odbiorcy" Width="100"
AllowFiltering="true"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDto.LastUpdateDate) HeaderText="Data Utworzenia" Format="d"
Type="ColumnType.Date" Width="130" AllowFiltering="true"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDto.DocType) HeaderText="Typ Dokumentu" Width="100"
AllowFiltering="true"></GridColumn>
</GridColumns>
</Grid>
<GridTemplates>
<DetailTemplate>
@{
IList<ScheduleOrderDetailDto>? scheduleOrderDetails = (@context as ScheduleOrderDto)?.ScheduleOrderDetails;
<SfGrid AllowFiltering="true"
AllowPaging="true"
AllowSorting="true"
AllowSelection="true"
TValue="ScheduleOrderDetailDto"
DataSource="@scheduleOrderDetails"
EnablePersistence="true"
EnableAdaptiveUI="true"
AdaptiveUIMode="AdaptiveMode.Both">
<GridColumns>
<GridColumn Field=@nameof(ScheduleOrderDetailDto.OrderNumber)
HeaderText="Numer Zamówienia" Width="100"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDetailDto.PurchaserName) HeaderText="Klient"
Width="100"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDetailDto.RecipientName)
HeaderText="Odbiorca" Width="100"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDetailDto.RecipientCode)
HeaderText="Kod odbiorcy" Width="100"
AllowFiltering="true"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDetailDto.Sc_productCode)
HeaderText="Pozycja" Width="100"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDetailDto.Sh_productCode)
HeaderText="Pozycja Klienta" Width="100"></GridColumn>
</GridColumns>
<GridTemplates>
<DetailTemplate Context="detail">
@{
IList<ScheduleOrderDetailDetailDto>? scheduleOrderDetailsDetails = (@detail as ScheduleOrderDetailDto)?.ScheduleOrderDetailDetails;
<SfGrid AllowFiltering="true"
AllowPaging="true"
AllowSorting="true"
AllowSelection="true"
TValue="ScheduleOrderDetailDetailDto"
DataSource="@scheduleOrderDetailsDetails"
EnableAdaptiveUI="true"
AdaptiveUIMode="AdaptiveMode.Both">
<GridColumns>
<GridColumn Field=@nameof(ScheduleOrderDetailDetailDto.DateFrom)
HeaderText="Data Od" Width="100"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDetailDetailDto.DateTo)
HeaderText="Data Do" Width="100"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDetailDetailDto.Qty)
TextAlign="TextAlign.Right" HeaderText="Ilość Sztuk"
Width="50"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDetailDetailDto.QtyType)
TextAlign="TextAlign.Right" HeaderText="Typ Qty"
Width="50"></GridColumn>
<GridColumn Field=@nameof(ScheduleOrderDetailDetailDto.QtyDesc)
HeaderText="Opis Typu" Width="100"></GridColumn>
</GridColumns>
<GridFilterSettings Type="FilterType.Excel"/>
<GridPageSettings PageSize="10"/>
<GridSelectionSettings Mode="SelectionMode.Row"
Type="SelectionType.Single"/>
<GridEvents TValue="ScheduleOrderDetailDetailDto"
OnRecordDoubleClick="OnScheduleOrderDetailDetailRowDoubleClick"
RowDataBound="OnRowDataBound"/>
</SfGrid>
}
</DetailTemplate>
</GridTemplates>
<GridFilterSettings Type="FilterType.Excel"/>
<GridPageSettings PageSize="10"/>
<GridSelectionSettings Mode="SelectionMode.Row" Type="SelectionType.Single"/>
<GridEvents TValue="ScheduleOrderDetailDto"
OnRecordDoubleClick="OnScheduleOrderDetailRowDoubleClick"/>
</SfGrid>
}
</DetailTemplate>
</GridTemplates>
<GridEvents TValue="ScheduleOrderDto" OnRecordDoubleClick="OnScheduleOrderRowDoubleClick" DetailsExpanding="OnDetailsExpanding"/>
<GridFilterSettings Type="FilterType.Excel"/>
<GridPageSettings PageSize="@PageSize"/>
</SfGrid>
</CardContent>
<CardFooter>
<small class="text-muted">FA Krosno Manager © @(DateTime.Now.Year)</small>
</CardFooter>
</SfCard>
</div>
@code {
[Parameter]
public required Func<GridDataProviderRequest<ScheduleOrderDto>, Task<GridDataProviderResult<ScheduleOrderDto>>> DataProvider { get; set; }
[Parameter] public required IEnumerable<ScheduleOrderDto> GridData { get; set; }
[Parameter]
public required Func<Grid<ScheduleOrderDto>, Task> PassGridRef { get; set; }
[Parameter] public required Func<SfGrid<ScheduleOrderDto>, Task> PassGridRef { get; set; }
[Parameter]
public required int PageSize { get; set; }
[Parameter] public required int PageSize { get; set; }
private Grid<ScheduleOrderDto> _grid { get; set; }
private ScheduleOrderDto? ScheduleOrderDto { get; set; }
private SfGrid<ScheduleOrderDto>? Grid { get; set; }
private IEnumerable<ScheduleOrderDto> _dataSource = [];
protected override void OnParametersSet()
{
_dataSource = GridData;
}
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
if (firstRender && Grid != null)
{
await PassGridRef(_grid);
await PassGridRef(Grid);
}
}
private async Task<GridDataProviderResult<ScheduleOrderDto>> LoadData(GridDataProviderRequest<ScheduleOrderDto> request)
private void OnScheduleOrderRowDoubleClick(RecordDoubleClickEventArgs<ScheduleOrderDto> obj)
{
return await DataProvider.Invoke(request);
int scheduleOrderId = obj.RowData.ID;
NavigationManager.NavigateTo($"/ScheduleOrder/{scheduleOrderId}");
}
private void OnRowDoubleClick(GridRowEventArgs<ScheduleOrderDto> obj)
private void OnScheduleOrderDetailRowDoubleClick(RecordDoubleClickEventArgs<ScheduleOrderDetailDto> obj)
{
int scheduleOrderId = obj.Item.ID;
int? scheduleOrderId = ScheduleOrderDto?.ID;
if (scheduleOrderId is not null)
{
NavigationManager.NavigateTo($"/ScheduleOrder/{scheduleOrderId}");
}
}
private void OnScheduleOrderDetailDetailRowDoubleClick(RecordDoubleClickEventArgs<ScheduleOrderDetailDetailDto> obj)
{
int? scheduleOrderId = ScheduleOrderDto?.ID;
if (scheduleOrderId is not null)
{
NavigationManager.NavigateTo($"/ScheduleOrder/{scheduleOrderId}");
}
}
private async Task OnDetailsExpanding(DetailsExpandingEventArgs<ScheduleOrderDto> obj)
{
ScheduleOrderDto = obj.Data;
if (ScheduleOrderDto != null)
{
ScheduleOrderDto? scheduleOrder = await ScheduleOrderService.GetScheduleOrderAsync(ScheduleOrderDto.ID);
ScheduleOrderDto.ScheduleOrderDetails = scheduleOrder?.ScheduleOrderDetails ?? [];
foreach (ScheduleOrderDetailDto scheduleOrderDetailDto in ScheduleOrderDto.ScheduleOrderDetails)
{
scheduleOrderDetailDto.OrderNumber = scheduleOrder?.PONum;
scheduleOrderDetailDto.RecipientCode = scheduleOrder?.RecipientCode;
scheduleOrderDetailDto.RecipientName = scheduleOrder?.RecipientName;
scheduleOrderDetailDto.PurchaserName = scheduleOrder?.PurchaserCode;
}
}
}
private void OnRowDataBound(RowDataBoundEventArgs<ScheduleOrderDetailDetailDto> args)
{
if (args.Data.QtyType == "83" || args.Data.QtyType == "84")
{
args.Row.AddClass(["highlight-red"]);
}
}
public async Task RestoreFilterFromLocalStorage()
{
var filterJson = await JSRuntime.InvokeAsync<string>("localStorage.getItem", "gridFilter");
if (!string.IsNullOrEmpty(filterJson))
{
var options = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true
};
var filters = JsonSerializer.Deserialize<List<WhereFilter>>(filterJson, options);
await Grid.ClearFilteringAsync();
if (filters != null && filters.Any())
{
foreach (var filter in filters.GroupBy(x => x.Field))
{
IList<object> values = filter.Select(x => GetValueFromJsonElement((JsonElement)x.value)).ToList();
await Grid.FilterByColumnAsync(filter.Key, filter.First().Operator.ToLower(), values);
}
await Grid.Refresh();
}
}
}
private object GetValueFromJsonElement(JsonElement element)
{
switch (element.ValueKind)
{
case JsonValueKind.String:
return element.GetString();
case JsonValueKind.Number:
if (element.TryGetInt32(out int intValue)) return intValue;
if (element.TryGetDouble(out double doubleValue)) return doubleValue;
break;
case JsonValueKind.True:
return true;
case JsonValueKind.False:
return false;
case JsonValueKind.Null:
return null;
default:
Console.WriteLine($"Nieobsługiwany typ JsonElement: {element.ValueKind}");
return null;
}
return null;
}
private async Task SaveFilters()
{
var filterSettings = Grid.FilterSettings.Columns;
if (filterSettings != null && filterSettings.Any())
{
string filterJson = JsonSerializer.Serialize(filterSettings);
await JSRuntime.InvokeVoidAsync("localStorage.setItem", "gridFilter", filterJson);
}
}
private async Task DeleteFilters()
{
await JSRuntime.InvokeVoidAsync("localStorage.removeItem", "gridFilter");
await Grid.ClearFilteringAsync();
}
}

View File

@@ -0,0 +1,33 @@
@page "/Unauthorized"
@using Microsoft.AspNetCore.Authorization
@using Syncfusion.Blazor.Cards
@using Syncfusion.Blazor.Buttons
@inject NavigationManager NavigationManager
<div class="h-100 d-flex justify-content-center align-items-start pt-5">
<SfCard CssClass="text-center shadow" style="max-width: 500px;">
<CardHeader>
<h3 class="text-warning">Brak autoryzacji</h3>
</CardHeader>
<CardContent>
<p class="text-muted mb-4">
Ups! Wygląda na to, że nie masz dostępu do tej strony. Aby kontynuować, zaloguj się do swojego konta.
</p>
<SfButton CssClass="e-primary" IsPrimary="true" @onclick="NavigateToLogin">
Przejdź do logowania
</SfButton>
</CardContent>
<CardFooter>
<small class="text-muted">FA Krosno Manager © @(DateTime.Now.Year)</small>
</CardFooter>
</SfCard>
</div>
@code {
private void NavigateToLogin()
{
NavigationManager.NavigateTo("/login");
}
}

View File

@@ -1,5 +1,4 @@
@using OrdersManagement.Components.Layout
<Router AppAssembly="@typeof(Program).Assembly">
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(Layout.MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />

View File

@@ -6,6 +6,5 @@
@using static Microsoft.AspNetCore.Components.Web.RenderMode
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using BlazorBootstrap;
@using FaKrosnoEfDataModel.Dtos
@using OrdersManagement.Services

View File

@@ -0,0 +1,51 @@
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components.Authorization;
namespace OrdersManagement;
public class CustomAuthenticationStateProvider(ILocalStorageService localStorage) : AuthenticationStateProvider
{
private string? _token;
private ClaimsPrincipal _currentUser = new(new ClaimsIdentity());
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
_token = await localStorage.GetItemAsync<string>("authToken");
if (string.IsNullOrEmpty(_token))
{
return await Task.FromResult(new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())));
}
var handler = new JwtSecurityTokenHandler();
var jwtToken = handler.ReadJwtToken(_token);
var identity = new ClaimsIdentity(jwtToken.Claims, "jwt", JwtRegisteredClaimNames.Sub, null);
_currentUser = new ClaimsPrincipal(identity);
return await Task.FromResult(new AuthenticationState(_currentUser));
}
public async Task MarkUserAsAuthenticated(string? token)
{
_token = token;
await localStorage.SetItemAsync("authToken", token);
var handler = new JwtSecurityTokenHandler();
var jwtToken = handler.ReadJwtToken(token);
var identity = new ClaimsIdentity(jwtToken.Claims, "jwt", JwtRegisteredClaimNames.Sub, null);
_currentUser = new ClaimsPrincipal(identity);
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(_currentUser)));
}
public async Task MarkUserAsLoggedOut()
{
_token = null;
await localStorage.RemoveItemAsync("authToken");
_currentUser = new ClaimsPrincipal(new ClaimsIdentity());
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(_currentUser)));
}
public string? GetToken() => _token;
public ClaimsPrincipal GetCurrentUser() => _currentUser;
}

View File

@@ -0,0 +1,14 @@
using System.ComponentModel.DataAnnotations;
namespace OrdersManagement.Models;
public class ChangePasswordModel
{
[Required(ErrorMessage = "Nowe hasło jest wymagane")]
[StringLength(100, MinimumLength = 6, ErrorMessage = "Hasło musi mieć od 6 do 100 znaków")]
public string NewPassword { get; set; }
[Required(ErrorMessage = "Potwierdzenie hasła jest wymagane")]
[Compare("NewPassword", ErrorMessage = "Hasła muszą się zgadzać")]
public string ConfirmPassword { get; set; }
}

View File

@@ -0,0 +1,12 @@
using System.ComponentModel.DataAnnotations;
namespace OrdersManagement.Models;
public class LoginModel
{
[Required(ErrorMessage = "Login jest wymagany")]
public string Login { get; set; }
[Required(ErrorMessage = "Hasło jest wymagane")]
public string Password { get; set; }
}

View File

@@ -0,0 +1,7 @@
namespace OrdersManagement.Models;
public class LoginResponseDto
{
public string? Token { get; set; }
public DateTime Expires { get; set; }
}

View File

@@ -0,0 +1,21 @@
using System.ComponentModel.DataAnnotations;
namespace OrdersManagement.Models;
public class RegisterModel
{
[Required(ErrorMessage = "Login jest wymagany")]
[StringLength(50, ErrorMessage = "Login może mieć maksymalnie 50 znaków")]
public string Login { get; set; }
[Required(ErrorMessage = "Email jest wymagany")]
[EmailAddress(ErrorMessage = "Nieprawidłowy format email")]
[StringLength(100, ErrorMessage = "Email może mieć maksymalnie 100 znaków")]
public string Email { get; set; }
[StringLength(50, ErrorMessage = "Imię może mieć maksymalnie 50 znaków")]
public string FirstName { get; set; }
[StringLength(50, ErrorMessage = "Nazwisko może mieć maksymalnie 50 znaków")]
public string LastName { get; set; }
}

View File

@@ -1,6 +1,6 @@
namespace OrdersManagement.Dtos
namespace OrdersManagement.Models
{
public class ResponseDto(int status, string identifier, string? message, string? externalIdentifier)
public class ResponseModel(int status, string identifier, string? message, string? externalIdentifier)
{
public int Status { get; set; } = status;
public string Identifier { get; set; } = identifier;

View File

@@ -7,11 +7,24 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Blazor.Bootstrap" Version="3.2.0" />
<PackageReference Include="BCrypt.Net-Core" Version="1.6.0" />
<PackageReference Include="Blazored.LocalStorage" Version="4.5.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.11" />
<PackageReference Include="Microsoft.IdentityModel.Protocols" Version="8.6.1" />
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="8.6.1" />
<PackageReference Include="Syncfusion.Blazor.Buttons" Version="28.2.3" />
<PackageReference Include="Syncfusion.Blazor.Cards" Version="28.2.3" />
<PackageReference Include="Syncfusion.Blazor.Core" Version="28.2.3" />
<PackageReference Include="Syncfusion.Blazor.Grid" Version="28.2.3" />
<PackageReference Include="Syncfusion.Blazor.Navigations" Version="28.2.3" />
<PackageReference Include="Syncfusion.Blazor.SplitButtons" Version="28.2.3" />
<PackageReference Include="Syncfusion.Blazor.Themes" Version="28.2.3" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.6.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FaKrosnoEfDataModel\FaKrosnoEfDataModel.csproj" />
<ProjectReference Include="..\OrdersManagementDataModel\OrdersManagementDataModel.csproj" />
<ProjectReference Include="..\SytelineSaAppEfDataModel\SytelineSaAppEfDataModel.csproj" />
</ItemGroup>

View File

@@ -1,39 +1,78 @@
using Microsoft.AspNetCore.Routing.Constraints;
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.IdentityModel.Tokens;
using OrdersManagement;
using OrdersManagement.Components;
using OrdersManagement.Services;
using Syncfusion.Blazor;
using System.Text;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddBlazorBootstrap();
string faKrosnoApiUrl = builder.Configuration["FaKrosnoApiUrl"] ?? "http://localhost:5001";
string apiUrl = builder.Configuration["ApiUrl"] ?? "http://localhost:5555"; // Ustawienie na adres twojego API
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(apiUrl) });
builder.Services.AddSyncfusionBlazor();
builder.Services.AddBlazoredLocalStorage();
// Add services to the container.
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = builder.Configuration["Jwt:Issuer"],
ValidAudience = builder.Configuration["Jwt:Audience"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"] ?? string.Empty)),
NameClaimType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"
};
});
builder.Services.AddAuthorizationCore();
builder.Services.AddScoped<CustomAuthenticationStateProvider>();
builder.Services.AddHttpClient("FaKrosnoApi", client =>
{
client.BaseAddress = new Uri(faKrosnoApiUrl);
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
});
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
builder.Services.AddScoped<ScheduleOrderService>();
builder.Services.AddScoped<ScheduleOrderDetailsService>();
builder.Services.AddScoped<EdiCustomerOrderService>();
builder.Services.AddScoped<EdiCustomerOrderTranslateService>();
builder.Services.AddScoped<CustomerOrderService>();
builder.Services.AddScoped<HangfireService>();
builder.Services.AddScoped<RoleService>();
builder.Services.AddScoped<FunctionService>();
builder.Services.AddScoped<UserService>();
builder.Services.AddScoped<ErrorLogService>();
builder.Services.AddScoped<ProductService>();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseAntiforgery();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
Syncfusion.Licensing.SyncfusionLicenseProvider.RegisterLicense("Ngo9BigBOggjHTQxAR8/V1NMaF5cXmBCf1FpRmJGdld5fUVHYVZUTXxaS00DNHVRdkdmWX1ec3VWQmNYV01wWUE=");
app.Run();

View File

@@ -1,17 +1,36 @@
using Microsoft.AspNetCore.Components.Authorization;
using SytelineSaAppEfDataModel.Dtos;
namespace OrdersManagement.Services;
public class CustomerOrderService(HttpClient httpClient)
public class CustomerOrderService(
IHttpClientFactory httpClientFactory,
CustomAuthenticationStateProvider authenticationStateProvider)
: ServiceBase<CustomerOrderDto>(httpClientFactory, authenticationStateProvider)
{
public async Task<IEnumerable<CustomerOrderDto>?> GetCustomerOrdersAsync()
{
return await httpClient.GetFromJsonAsync<IEnumerable<CustomerOrderDto>>("api/CustomerOrders");
try
{
return await GetListAsync("api/CustomerOrders");
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Błąd HTTP w GetCustomerOrdersAsync: {ex.Message}");
return null;
}
}
public async Task<CustomerOrderDto?> GetCustomerOrderAsync(Guid customerOrderNumber)
{
return await httpClient.GetFromJsonAsync<CustomerOrderDto>(
$"api/CustomerOrders/by-order-number/?customerOrderNumber={customerOrderNumber}");
try
{
return await GetEntityAsync($"api/CustomerOrders/by-order-number/?customerOrderNumber={customerOrderNumber}");
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Błąd HTTP w GetScheduleOrderAsync: {ex.Message}");
return null;
}
}
}

View File

@@ -1,41 +1,63 @@
using OrdersManagement.Dtos;
using Microsoft.AspNetCore.Components.Authorization;
using OrdersManagement.Models;
using SytelineSaAppEfDataModel.Dtos;
namespace OrdersManagement.Services
{
public class EdiCustomerOrderService(HttpClient httpClient)
public class EdiCustomerOrderService(IHttpClientFactory httpClientFactory, CustomAuthenticationStateProvider authenticationStateProvider, ErrorLogService errorLogService) : ServiceBase<EdiCustomerOrderDto>(httpClientFactory, authenticationStateProvider)
{
public async Task<IEnumerable<EdiCustomerOrderDto>?> GetEdiCustomerOrdersAsync()
{
return await httpClient.GetFromJsonAsync<IEnumerable<EdiCustomerOrderDto>>("api/EdiCustomerOrders");
try
{
return await GetListAsync("api/EdiCustomerOrders");
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Błąd HTTP w GetEdiCustomerOrdersAsync: {ex.Message}");
return null;
}
}
public async Task<EdiCustomerOrderDto?> GetEdiCustomerOrderAsync(Guid customerOrderNumber)
{
return await httpClient.GetFromJsonAsync<EdiCustomerOrderDto>(
$"api/EdiCustomerOrders/by-order-number/?customerOrderNumber={customerOrderNumber}");
try
{
return await GetEntityAsync($"api/EdiCustomerOrders/by-order-number/?customerOrderNumber={customerOrderNumber}");
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Błąd HTTP w GetEdiCustomerOrdersAsync: {ex.Message}");
return null;
}
}
public async Task<ResponseDto> SendOrderToSyteline(Guid customerOrderNumber, string orderNumber)
public async Task<ResponseModel?> SendOrderToSyteline(Guid customerOrderNumber, string orderNumber)
{
HttpResponseMessage responseMessage = await httpClient.PostAsync(
$"api/EdiCustomerOrders/send-to-syteline?customerOrderNumber={customerOrderNumber}", null);
try
{
HttpResponseMessage responseMessage = await PostAsync($"api/EdiCustomerOrders/send-to-syteline?customerOrderNumber={customerOrderNumber}");
if (responseMessage.IsSuccessStatusCode)
{
return new ResponseDto(1, orderNumber, null, null);
return new ResponseModel(1, orderNumber, null, null);
}
string? errorMessage = null;
IEnumerable<ErrorLogDto>? logs = await httpClient.GetFromJsonAsync<IEnumerable<ErrorLogDto>>(
$"api/ErrorLog/by-order-number/?customerOrderNumber={customerOrderNumber}");
IEnumerable<ErrorLogDto>? logs = await errorLogService.GetErrorLogsAsync(customerOrderNumber);
if (logs != null)
{
errorMessage = string.Join("\r\n", logs.Select(x => x.ErrMsg));
}
return new ResponseDto(0, orderNumber, errorMessage, null);
return new ResponseModel(0, orderNumber, errorMessage, null);
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Błąd HTTP w GetEdiCustomerOrdersAsync: {ex.Message}");
return null;
}
}
}
}

View File

@@ -0,0 +1,29 @@
using SytelineSaAppEfDataModel.Dtos;
namespace OrdersManagement.Services;
public class EdiCustomerOrderTranslateService(
IHttpClientFactory httpClientFactory,
CustomAuthenticationStateProvider authenticationStateProvider)
: ServiceBase<EdiCustomerOrderTranslateDto>(httpClientFactory, authenticationStateProvider)
{
public async Task<IEnumerable<EdiCustomerOrderTranslateDto>?> GetEdiCustomerOrdersTranslationsAsync()
{
try
{
return await GetListAsync("api/EdiCustomerOrdersTranslations");
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Błąd HTTP w GetEdiCustomerOrdersTranslationsAsync: {ex.Message}");
return null;
}
}
public async Task<int> DeleteEdiCustomerOrderTranslateAsync(EdiCustomerOrderTranslateDto ediCustomerOrderTranslateDto)
{
HttpResponseMessage responseMessage =
await DeleteAsync($"api/EdiCustomerOrdersTranslations/?id={ediCustomerOrderTranslateDto.Id}");
return responseMessage.IsSuccessStatusCode ? 1 : 0;
}
}

View File

@@ -0,0 +1,23 @@
using Microsoft.AspNetCore.Components.Authorization;
using SytelineSaAppEfDataModel.Dtos;
namespace OrdersManagement.Services;
public class ErrorLogService(
IHttpClientFactory httpClientFactory,
CustomAuthenticationStateProvider authenticationStateProvider)
: ServiceBase<ErrorLogDto>(httpClientFactory, authenticationStateProvider)
{
public async Task<IEnumerable<ErrorLogDto>?> GetErrorLogsAsync(Guid customerOrderNumber)
{
try
{
return await GetListAsync($"api/CustomerOrders/by-order-number/?customerOrderNumber={customerOrderNumber}");
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Błąd HTTP w GetCustomerOrdersAsync: {ex.Message}");
return null;
}
}
}

View File

@@ -0,0 +1,36 @@
using OrdersManagementDataModel.Dtos;
namespace OrdersManagement.Services;
public class FunctionService(HttpClient httpClient)
{
public async Task<IEnumerable<FunctionDto>?> GetFunctionsAsync()
{
return await httpClient.GetFromJsonAsync<IEnumerable<FunctionDto>>("api/Functions");
}
public async Task<FunctionDto?> GetFunctionAsync(Guid functionId)
{
return await httpClient.GetFromJsonAsync<FunctionDto>($"api/Functions/by-id/?id={functionId}");
}
public async Task<FunctionDto?> GetFunctionByNameAsync(string functionName)
{
return await httpClient.GetFromJsonAsync<FunctionDto>($"api/Functions/by-name/?name={functionName}");
}
public async Task AddFunctionAsync(FunctionDto function)
{
await httpClient.PostAsJsonAsync("api/Functions", function);
}
public async Task UpdateFunctionAsync(FunctionDto function)
{
await httpClient.PutAsJsonAsync("api/Functions", function);
}
public async Task DeleteFunctionAsync(Guid functionId)
{
await httpClient.DeleteAsync($"api/Functions/?id={functionId}");
}
}

View File

@@ -0,0 +1,31 @@
using OrdersManagementDataModel.Dtos;
namespace OrdersManagement.Services;
public class HangfireService(
IHttpClientFactory httpClientFactory,
CustomAuthenticationStateProvider authenticationStateProvider)
: ServiceBase<TaskSchedulerDto>(httpClientFactory, authenticationStateProvider)
{
public async Task<IEnumerable<TaskSchedulerDto>?> GetTaskSchedulersAsync()
{
return await GetListAsync("api/HangfireJobs/");
}
public async Task<TaskSchedulerDto?> GetTaskSchedulerAsync(Guid id)
{
return await GetEntityAsync($"api/HangfireJobs/{id}");
}
public async Task<int> AddTaskSchedulerAsync(TaskSchedulerDto taskSchedulerDto)
{
HttpResponseMessage responseMessage = await PostAsJsonAsync("api/HangfireJobs/add", taskSchedulerDto);
return responseMessage.IsSuccessStatusCode ? 1 : 0;
}
public async Task<int> DeleteTaskSchedulerAsync(TaskSchedulerDto taskSchedulerDto)
{
HttpResponseMessage responseMessage = await PostAsJsonAsync("api/HangfireJobs/delete", taskSchedulerDto);
return responseMessage.IsSuccessStatusCode ? 1 : 0;
}
}

View File

@@ -0,0 +1,25 @@
using FaKrosnoEfDataModel.Dtos;
namespace OrdersManagement.Services;
public class ProductService(IHttpClientFactory httpClientFactory, CustomAuthenticationStateProvider authenticationStateProvider)
: ServiceBase<ProductDto>(httpClientFactory, authenticationStateProvider)
{
public async Task<IEnumerable<ProductDto>?> GetProductsByIndexAsync(string indexName)
{
try
{
return await GetListAsync($"api/Product/by-index?indexName={indexName}");
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Błąd HTTP w GetProductsByIndexAsync: {ex.Message}");
return null;
}
}
public async Task<HttpResponseMessage> UpdateProductAsync(ProductDto product)
{
return await PutAsJsonAsync("api/Product", product);
}
}

View File

@@ -0,0 +1,39 @@
using OrdersManagementDataModel.Dtos;
namespace OrdersManagement.Services;
public class RoleService(
IHttpClientFactory httpClientFactory,
CustomAuthenticationStateProvider authenticationStateProvider)
: ServiceBase<RoleDto>(httpClientFactory, authenticationStateProvider)
{
public async Task<IEnumerable<RoleDto>?> GetRolesAsync()
{
return await GetListAsync("api/Roles");
}
public async Task<RoleDto?> GetRoleAsync(Guid roleId)
{
return await GetEntityAsync($"api/Roles/by-id/?id={roleId}");
}
public async Task<RoleDto?> GetRoleByNameAsync(string roleName)
{
return await GetEntityAsync($"api/Roles/by-name/?name={roleName}");
}
public async Task<HttpResponseMessage> AddRoleAsync(RoleDto role)
{
return await PostAsJsonAsync("api/Roles", role);
}
public async Task<HttpResponseMessage> UpdateRoleAsync(RoleDto role)
{
return await PutAsJsonAsync("api/Roles", role);
}
public async Task<HttpResponseMessage> DeleteRoleAsync(Guid roleId)
{
return await DeleteAsync($"api/Roles/?id={roleId}");
}
}

View File

@@ -1,13 +0,0 @@
using FaKrosnoEfDataModel.Dtos;
namespace OrdersManagement.Services
{
public class ScheduleOrderDetailsService(HttpClient httpClient)
{
public async Task<IEnumerable<ScheduleOrderDetailDto>?> GetScheduleOrderDetails(int scheduleOrderId)
{
return await httpClient.GetFromJsonAsync<IEnumerable<ScheduleOrderDetailDto>>(
$"api/scheduleOrderDetails/order/{scheduleOrderId}");
}
}
}

View File

@@ -1,12 +1,38 @@
using FaKrosnoEfDataModel.Dtos;
using System.Net.Http.Headers;
using Blazored.LocalStorage;
using FaKrosnoEfDataModel.Dtos;
using Microsoft.AspNetCore.Components.Authorization;
namespace OrdersManagement.Services
{
public class ScheduleOrderService(HttpClient httpClient)
namespace OrdersManagement.Services;
public class ScheduleOrderService(
IHttpClientFactory httpClientFactory,
CustomAuthenticationStateProvider authenticationStateProvider)
: ServiceBase<ScheduleOrderDto>(httpClientFactory, authenticationStateProvider)
{
public async Task<IEnumerable<ScheduleOrderDto>?> GetScheduleOrdersAsync()
{
return await httpClient.GetFromJsonAsync<IEnumerable<ScheduleOrderDto>>("api/ScheduleOrders");
try
{
return await GetListAsync("api/ScheduleOrders");
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Błąd HTTP w GetScheduleOrdersAsync: {ex.Message}");
return null;
}
}
public async Task<ScheduleOrderDto?> GetScheduleOrderAsync(int scheduleOrderId)
{
try
{
return await GetEntityAsync($"api/ScheduleOrders/{scheduleOrderId}");
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Błąd HTTP w GetScheduleOrderAsync: {ex.Message}");
return null;
}
}
}

View File

@@ -0,0 +1,86 @@
using Microsoft.AspNetCore.Components.Authorization;
namespace OrdersManagement.Services;
public class ServiceBase<T> where T : class
{
private readonly CustomAuthenticationStateProvider _authenticationStateProvider;
private readonly HttpClient _httpClient;
protected ServiceBase(IHttpClientFactory httpClientFactory, CustomAuthenticationStateProvider authenticationStateProvider)
{
_authenticationStateProvider = authenticationStateProvider;
_httpClient = httpClientFactory.CreateClient("FaKrosnoApi");
}
protected async Task<IEnumerable<T>?> GetListAsync(string request)
{
//Configure();
var response = await _httpClient.GetAsync(request);
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<IEnumerable<T>>();
}
protected async Task<T?> GetEntityAsync(string request)
{
//Configure();
var response = await _httpClient.GetAsync(request);
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<T>();
}
protected async Task<HttpResponseMessage> PostAsync(string request)
{
//Configure();
var response = await _httpClient.PostAsync(request, null);
response.EnsureSuccessStatusCode();
return response;
}
protected async Task<HttpResponseMessage> PostAsJsonAsync(string request, T obj)
{
//Configure();
var response = await _httpClient.PostAsJsonAsync(request, obj);
response.EnsureSuccessStatusCode();
return response;
}
protected async Task<HttpResponseMessage> PostAsJsonAsync(string request, object obj)
{
//Configure();
var response = await _httpClient.PostAsJsonAsync(request, obj);
response.EnsureSuccessStatusCode();
return response;
}
protected async Task<HttpResponseMessage> PutAsJsonAsync(string request, T obj)
{
//Configure();
var response = await _httpClient.PutAsJsonAsync(request, obj);
response.EnsureSuccessStatusCode();
return response;
}
protected async Task<HttpResponseMessage> DeleteAsync(string request)
{
//Configure();
var response = await _httpClient.DeleteAsync(request);
response.EnsureSuccessStatusCode();
return response;
}
private void Configure()
{
var token = _authenticationStateProvider.GetToken();
_httpClient.DefaultRequestHeaders.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
}
}

View File

@@ -0,0 +1,63 @@
using OrdersManagement.Models;
using OrdersManagementDataModel.Dtos;
namespace OrdersManagement.Services;
public class UserService(
IHttpClientFactory httpClientFactory,
CustomAuthenticationStateProvider authenticationStateProvider)
: ServiceBase<UserDto>(httpClientFactory, authenticationStateProvider)
{
private readonly HttpClient _httpClient = httpClientFactory.CreateClient("FaKrosnoApi");
public async Task<IEnumerable<UserDto>?> GetUsersAsync()
{
return await GetListAsync("api/Users");
}
public async Task<UserDto?> AuthenticateUserAsync(string login, string password)
{
try
{
var response = await PostAsJsonAsync("api/Users/login", new { Login = login, Password = password });
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadFromJsonAsync<LoginResponseDto>();
if (result?.Token == null) return null;
await authenticationStateProvider.MarkUserAsAuthenticated(result.Token);
return await GetUserByUsernameAsync(login);
}
catch (Exception ex)
{
Console.WriteLine($"Błąd logowania: {ex.Message}");
return null;
}
}
public async Task<UserDto?> GetUserAsync(Guid userId)
{
return await GetEntityAsync($"api/Users/by-id/?id={userId}");
}
public async Task<UserDto?> GetUserByUsernameAsync(string username)
{
return await GetEntityAsync($"api/Users/by-username/?username={username}");
}
public async Task<HttpResponseMessage> AddUserAsync(UserDto user)
{
return await PostAsJsonAsync("api/Users", user);
}
public async Task<HttpResponseMessage> UpdateUserAsync(UserDto user)
{
return await PutAsJsonAsync("api/Users", user);
}
public async Task<HttpResponseMessage> DeleteUserAsync(Guid userId)
{
return await DeleteAsync($"api/Users/?id={userId}");
}
}

View File

@@ -5,5 +5,10 @@
"Microsoft.AspNetCore": "Warning"
}
},
"Jwt": {
"Key": "a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6A7B8C9D0E1F",
"Issuer": "FaKrosnoApi",
"Audience": "FaKrosnoClient"
},
"AllowedHosts": "*"
}

View File

@@ -1,51 +1,3 @@
html, body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}
a, .btn-link {
color: #006bb7;
}
.btn-primary {
color: #fff;
background-color: #1b6ec2;
border-color: #1861ac;
}
.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}
.content {
padding-top: 1.1rem;
}
h1:focus {
outline: none;
}
.valid.modified:not([type=checkbox]) {
outline: 1px solid #26b050;
}
.invalid {
outline: 1px solid #e50000;
}
.validation-message {
color: #e50000;
}
.blazor-error-boundary {
background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
padding: 1rem 1rem 1rem 3.7rem;
color: white;
}
.blazor-error-boundary::after {
content: "An error has occurred."
}
.darker-border-checkbox.form-check-input {
border-color: #929292;
}

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Warstwa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="112.8 177 280.4 441.6" style="enable-background:new 112.8 177 280.4 441.6;" xml:space="preserve">
<style type="text/css">
.st0{fill:#706F6F;}
.st1{fill:#B12009;}
</style>
<g>
<path class="st0" d="M133.7,590.8l20.1-19.8h-13.2l-18.1,18.5V571h-9.7v46.9h9.7v-16.1l4.5-4.4l14.5,20.5h12.2L133.7,590.8
L133.7,590.8z M192.9,603.7c-1.1-2.9-2.5-5.1-4.3-6.7c0.2-0.1,0.4-0.1,0.5-0.3c1.4-0.8,2.6-1.8,3.6-2.9c1-1.2,1.7-2.5,2.2-4
s0.8-3.1,0.8-4.8c0-1.9-0.4-3.9-1.1-5.8c-0.8-1.9-1.9-3.6-3.5-4.9c-0.9-0.8-1.9-1.4-2.9-1.9c-1-0.4-2-0.8-3.1-1
c-1.1-0.2-2.1-0.3-3.3-0.4c-1.1,0-2.2-0.1-3.4-0.1h-21v46.9h9.7v-18.4h8.6c0.9,0,1.7,0.1,2.5,0.4c0.8,0.2,1.5,0.6,2.2,1.1
c0.6,0.5,1.2,1.1,1.7,1.7c0.5,0.7,0.9,1.4,1.2,2.3l4.6,12.8h10.2C198.1,617.9,192.9,603.7,192.9,603.7L192.9,603.7z M178,590.5
h-10.8v-10.9h11.6c6.4,0,7.3,2.7,7.3,5.3c0,2.1-0.5,3.5-1.5,4.3C183.7,589.8,181.9,590.5,178,590.5L178,590.5z M247.1,584.7
c-1.1-3-2.7-5.6-4.6-7.7c-2-2.1-4.4-3.8-7.2-5c-2.7-1.2-5.8-1.8-9-1.8s-6.3,0.6-9,1.8c-2.7,1.1-5.2,2.8-7.2,4.9
c-2,2.1-3.6,4.7-4.7,7.7c-1.1,2.9-1.6,6.3-1.6,9.8s0.5,6.8,1.6,9.8s2.7,5.6,4.7,7.7c2,2.1,4.4,3.8,7.2,5c2.8,1.2,5.8,1.7,9.1,1.7
s6.3-0.6,9.1-1.8c2.7-1.2,5.1-2.9,7.1-5.1c2-2.1,3.5-4.7,4.6-7.7c1.1-2.9,1.6-6.2,1.6-9.7C248.8,590.9,248.2,587.6,247.1,584.7
L247.1,584.7z M239.1,594.4c0,2.5-0.3,4.8-1,6.7c-0.6,1.9-1.5,3.5-2.7,4.8c-1.1,1.3-2.5,2.3-4,2.9c-1.6,0.7-3.3,1-5.2,1
s-3.6-0.3-5.2-1c-1.5-0.7-2.8-1.6-3.9-2.9c-1.2-1.3-2-2.9-2.7-4.8c-0.7-1.9-1-4.2-1-6.7s0.3-4.8,1-6.7c0.7-1.9,1.5-3.5,2.7-4.8
c1.1-1.3,2.4-2.2,4-2.9c1.6-0.7,3.3-1,5.2-1c1.8,0,3.5,0.3,5.1,1c1.5,0.6,2.9,1.6,3.9,2.9c1.1,1.3,2,2.9,2.7,4.8
C238.7,589.6,239.1,591.9,239.1,594.4L239.1,594.4z M292.4,599.2c-0.5-1.4-1.2-2.6-2.1-3.6c-0.9-1-1.9-1.9-3.1-2.6
c-1.1-0.7-2.3-1.3-3.5-1.7c-1.2-0.4-2.6-0.9-4.1-1.3s-3.3-0.9-5.3-1.3c-1.9-0.4-3.4-0.8-4.6-1.2c-1.1-0.3-1.9-0.7-2.5-1.1
c-0.5-0.3-0.8-0.6-1-1c-0.2-0.4-0.3-0.9-0.3-1.5c0-1.4,0.6-2.4,1.7-3.2c1.4-1,3.5-1.5,6.2-1.5c7.1,0,8.4,3.3,8.7,6.1l0.2,1.8h9.3
l-0.1-2c-0.1-2.3-0.6-4.4-1.5-6.3c-1-1.9-2.3-3.4-3.9-4.7c-1.6-1.3-3.6-2.2-5.8-2.9c-2.2-0.6-4.6-1-7.2-1c-2.5,0-4.8,0.3-6.8,1
c-2.1,0.7-4,1.6-5.5,2.8c-1.6,1.2-2.8,2.7-3.6,4.4c-0.9,1.7-1.3,3.6-1.3,5.6c0,1.9,0.3,3.5,1,5c0.6,1.5,1.6,2.8,3,4
c1.2,1,2.9,2,4.8,2.8c1.8,0.8,4,1.4,6.5,1.9s4.5,1.1,6.1,1.5c1.5,0.4,2.8,0.9,3.7,1.5c0.7,0.4,1.3,0.9,1.6,1.4s0.4,1.2,0.4,2
c0,0.8-0.2,1.5-0.5,2.1c-0.4,0.6-0.9,1.2-1.6,1.7s-1.6,0.9-2.7,1.2c-1.1,0.3-2.4,0.4-3.8,0.4c-1.5,0-2.9-0.2-4.1-0.5
c-1.2-0.3-2.3-0.8-3.2-1.4s-1.6-1.4-2.2-2.3c-0.6-0.9-0.9-2.1-1-3.4l-0.1-1.8h-7.3h-2v2c0.1,2.4,0.5,4.6,1.4,6.6
c0.9,2,2.2,3.8,4,5.3c1.7,1.5,3.8,2.6,6.3,3.4c2.4,0.8,5.3,1.1,8.5,1.1c2.5,0,4.9-0.3,7-1c2.2-0.7,4.1-1.7,5.7-3
c1.6-1.3,2.9-2.9,3.8-4.7c1-1.9,1.4-3.9,1.4-6.1C293.2,602.1,293,600.6,292.4,599.2L292.4,599.2z M330.3,571v29.5L310.7,571h-8.8
v46.9h9.4v-29.5l19.6,29.5h8.8V571H330.3L330.3,571z M391.6,584.7c-1.1-3-2.7-5.6-4.7-7.7s-4.4-3.8-7.2-5c-2.8-1.2-5.8-1.8-9-1.8
s-6.3,0.6-9,1.8c-2.7,1.1-5.2,2.8-7.2,4.9c-2,2.1-3.6,4.7-4.7,7.7c-1.1,2.9-1.6,6.3-1.6,9.8s0.6,6.8,1.6,9.8c1.1,3,2.7,5.6,4.7,7.7
c2,2.1,4.4,3.8,7.2,5c2.7,1.2,5.8,1.7,9.1,1.7c3.3,0,6.3-0.6,9-1.8c2.8-1.2,5.2-2.9,7.2-5.1c2-2.1,3.5-4.7,4.6-7.7
c1.1-2.9,1.6-6.2,1.6-9.7C393.2,590.9,392.6,587.6,391.6,584.7L391.6,584.7z M383.5,594.4c0,2.5-0.3,4.8-1,6.7
c-0.6,1.9-1.5,3.5-2.7,4.8c-1.1,1.3-2.5,2.3-4,2.9c-1.6,0.7-3.3,1-5.2,1c-1.9,0-3.6-0.3-5.1-1s-2.9-1.6-4-2.9
c-1.1-1.3-2-2.9-2.7-4.8c-0.6-1.9-1-4.2-1-6.7s0.3-4.8,1-6.7c0.7-1.9,1.6-3.5,2.7-4.8c1.1-1.3,2.5-2.2,4-2.9c1.6-0.7,3.3-1,5.2-1
c1.8,0,3.5,0.3,5.1,1c1.5,0.6,2.8,1.6,4,2.9c1.1,1.3,2,2.9,2.7,4.8C383.2,589.6,383.5,591.9,383.5,594.4L383.5,594.4z"/>
<path class="st1" d="M112.8,177v373h274.3V177H112.8L112.8,177z M365.1,528.1H134.7V198.9h230.4V528.1L365.1,528.1z M307.5,303.2
l-62-0.1v78.4h-25.9V281.1h87.9v-53.3H163.9l-0.1,223.8l55.8,55.9V403.6h25.9v103.8l29.6-29.5v-74.2h31.1l12.4,30.9l30-30
L307.5,303.2L307.5,303.2z M275.1,381.5v-55.7l22.2,55.7H275.1L275.1,381.5z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,9 @@
namespace OrdersManagementDataModel.Dtos;
public class FunctionDto
{
public int Id { get; set; }
public int RoleId { get; set; }
public string Name { get; set; }
public Guid RowPointer { get; set; }
}

View File

@@ -0,0 +1,8 @@
namespace OrdersManagementDataModel.Dtos;
public class RoleDto
{
public int Id { get; set; }
public string Name { get; set; }
public Guid RowPointer { get; set; }
}

View File

@@ -0,0 +1,12 @@
namespace OrdersManagementDataModel.Dtos;
public class TaskSchedulerDetailDto
{
public int Id { get; set; }
public Guid RowPointer { get; set; }
public int FkTaskScheduler { get; set; }
public DateTime JobRunDate { get; set; }
public string Log { get; set; }
public TaskSchedulerDto TaskSchedulerDto { get; set; }
}

View File

@@ -0,0 +1,20 @@
using Hangfire.Storage;
using OrdersManagementDataModel.Entities;
namespace OrdersManagementDataModel.Dtos;
public class TaskSchedulerDto
{
public int Id { get; set; }
public Guid RowPointer { get; set; }
public string Name { get; set; }
public string Path { get; set; }
public string CronOptions { get; set; }
public DateTime CreateDate { get; set; }
public DateTime ActiveFrom { get; set; }
public DateTime? ActiveUntil { get; set; }
public DateTime? LastExecution { get; set; }
public DateTime? NextExecution { get; set; }
public ICollection<TaskSchedulerDetailDto> TaskSchedulerDetails { get; set; } = new List<TaskSchedulerDetailDto>();
}

View File

@@ -0,0 +1,23 @@
namespace OrdersManagementDataModel.Dtos;
public class UserDto
{
public int Id { get; set; }
public string Login { get; set; }
public string PasswordHash { get; set; }
public bool IsTemporaryPassword { get; set; }
public bool IsActive { get; set; }
public DateTime? ActiveFrom { get; set; }
public DateTime? ActiveTo { get; set; }
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime? LastLoginDate { get; set; }
public int FailedLoginAttempts { get; set; }
public bool IsLocked { get; set; }
public DateTime? LockoutEndDate { get; set; }
public Guid RowPointer { get; set; }
public ICollection<UserRoleDto> UserRoles { get; set; } = new List<UserRoleDto>();
}

View File

@@ -0,0 +1,12 @@
namespace OrdersManagementDataModel.Dtos;
public class UserRoleDto
{
public int UserId { get; set; }
public int RoleId { get; set; }
public Guid RowPointer { get; set; }
public virtual UserDto User { get; set; }
public virtual RoleDto Role { get; set; }
}

View File

@@ -0,0 +1,11 @@
namespace OrdersManagementDataModel.Entities;
public class Function
{
public int Id { get; set; }
public int RoleId { get; set; }
public string Name { get; set; }
public Guid RowPointer { get; set; }
public Role Role { get; set; }
}

View File

@@ -0,0 +1,8 @@
namespace OrdersManagementDataModel.Entities;
public class Role
{
public int Id { get; set; }
public string Name { get; set; }
public Guid RowPointer { get; set; }
}

View File

@@ -0,0 +1,15 @@
namespace OrdersManagementDataModel.Entities;
public class TaskScheduler
{
public int Id { get; set; }
public Guid RowPointer { get; set; }
public string Name { get; set; }
public string Path { get; set; }
public string CronOptions { get; set; }
public DateTime CreateDate { get; set; }
public DateTime ActiveFrom { get; set; }
public DateTime? ActiveUntil { get; set; }
public ICollection<TaskSchedulerDetail> TaskSchedulerDetails { get; set; } = new List<TaskSchedulerDetail>();
}

View File

@@ -0,0 +1,12 @@
namespace OrdersManagementDataModel.Entities;
public class TaskSchedulerDetail
{
public int Id { get; set; }
public Guid RowPointer { get; set; }
public int FkTaskScheduler { get; set; }
public DateTime JobRunDate { get; set; }
public string? Log { get; set; }
public virtual TaskScheduler? TaskScheduler { get; set; }
}

View File

@@ -0,0 +1,23 @@
namespace OrdersManagementDataModel.Entities;
public class User
{
public int Id { get; set; }
public string Login { get; set; }
public string PasswordHash { get; set; }
public bool IsTemporaryPassword { get; set; }
public bool IsActive { get; set; }
public DateTime? ActiveFrom { get; set; }
public DateTime? ActiveTo { get; set; }
public string Email { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime CreatedDate { get; set; }
public DateTime? LastLoginDate { get; set; }
public int FailedLoginAttempts { get; set; }
public bool IsLocked { get; set; }
public DateTime? LockoutEndDate { get; set; }
public Guid RowPointer { get; set; }
public ICollection<UserRole> UserRoles { get; set; } = new List<UserRole>();
}

View File

@@ -0,0 +1,11 @@
namespace OrdersManagementDataModel.Entities;
public class UserRole
{
public int UserId { get; set; }
public int RoleId { get; set; }
public Guid RowPointer { get; set; }
public virtual User User { get; set; }
public virtual Role Role { get; set; }
}

Some files were not shown because too many files have changed in this diff Show More