Compare commits
23 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d17f2fb23e | |||
| 697e1431d9 | |||
| de6a1c5385 | |||
| 29759cf896 | |||
| f0ad9b536a | |||
| fb97729c71 | |||
| 1bd92a8732 | |||
| 8c38255ed9 | |||
| 639631a63b | |||
| 5869ae18c4 | |||
| fc9da89ebe | |||
| 76239b41bd | |||
| 88882f9db8 | |||
| 6339fbdb8c | |||
| 6f2c60e6c0 | |||
| cac880e35f | |||
| 897b036fc5 | |||
| 19c63ef317 | |||
| fdaead91ff | |||
| aa40ae2e7a | |||
| ed59efe4f8 | |||
| b13b8ebfb6 | |||
| 57646a1417 |
@@ -0,0 +1,7 @@
|
|||||||
|
namespace PyroFetes.DTO.Customer.Response;
|
||||||
|
|
||||||
|
public class GetCustomerDto
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string? Note { get; set; }
|
||||||
|
}
|
||||||
@@ -3,8 +3,6 @@ namespace PyroFetes.DTO.DeliveryNote.Request;
|
|||||||
public class CreateDeliveryNoteDto
|
public class CreateDeliveryNoteDto
|
||||||
{
|
{
|
||||||
public string? TrackingNumber { get; set; }
|
public string? TrackingNumber { get; set; }
|
||||||
public DateOnly EstimateDeliveryDate { get; set; }
|
|
||||||
public DateOnly ExpeditionDate { get; set; }
|
|
||||||
|
|
||||||
public int DelivererId { get; set; }
|
public int DelivererId { get; set; }
|
||||||
public int SupplierId { get; set; }
|
public int SupplierId { get; set; }
|
||||||
|
|||||||
@@ -5,5 +5,6 @@ namespace PyroFetes.DTO.PurchaseOrder.Request;
|
|||||||
public class CreatePurchaseOrderDto
|
public class CreatePurchaseOrderDto
|
||||||
{
|
{
|
||||||
public string? PurchaseConditions { get; set; }
|
public string? PurchaseConditions { get; set; }
|
||||||
|
public int SupplierId { get; set; }
|
||||||
public List<CreatePurchaseOrderProductDto>? Products { get; set; }
|
public List<CreatePurchaseOrderProductDto>? Products { get; set; }
|
||||||
}
|
}
|
||||||
@@ -6,5 +6,7 @@ public class CreateQuotationDto
|
|||||||
{
|
{
|
||||||
public string? Message { get; set; }
|
public string? Message { get; set; }
|
||||||
public string? ConditionsSale { get; set; }
|
public string? ConditionsSale { get; set; }
|
||||||
|
public int CustomerId { get; set; }
|
||||||
|
public int SupplierId { get; set; }
|
||||||
public List<CreateProductQuotationDto>? Products { get; set; }
|
public List<CreateProductQuotationDto>? Products { get; set; }
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace PyroFetes.DTO.Refresh.Request;
|
||||||
|
|
||||||
|
public class RefreshTokenDto
|
||||||
|
{
|
||||||
|
public string? Token { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
namespace PyroFetes.DTO.Refresh.Response;
|
||||||
|
|
||||||
|
public class GetRefreshTokenDto
|
||||||
|
{
|
||||||
|
public string? Token { get; set; }
|
||||||
|
}
|
||||||
@@ -5,7 +5,6 @@ public class GetUserDto
|
|||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
public string? Password { get; set; }
|
public string? Password { get; set; }
|
||||||
public string? Salt { get; set; }
|
|
||||||
public string? Fonction { get; set; }
|
public string? Fonction { get; set; }
|
||||||
public string? Email { get; set; }
|
public string? Email { get; set; }
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace PyroFetes.DTO.WareHouse.Response;
|
||||||
|
|
||||||
|
public class GetWareHouseDto
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
public string? Name { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using FastEndpoints;
|
||||||
|
using PyroFetes.DTO.Customer.Response;
|
||||||
|
using PyroFetes.Repositories;
|
||||||
|
|
||||||
|
namespace PyroFetes.Endpoints.Customers;
|
||||||
|
|
||||||
|
public class GetAllCustomersEndpoint(CustomersRepository customersRepository, AutoMapper.IMapper mapper) : EndpointWithoutRequest<List<GetCustomerDto>>
|
||||||
|
{
|
||||||
|
public override void Configure()
|
||||||
|
{
|
||||||
|
Get("/customers");
|
||||||
|
Roles("Admin","Employe");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task HandleAsync(CancellationToken ct)
|
||||||
|
{
|
||||||
|
await Send.OkAsync(await customersRepository.ProjectToListAsync<GetCustomerDto>(ct), ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ public class CreateDelivererEndpoint(DeliverersRepository deliverersRepository)
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Post("/deliverers");
|
Post("/deliverers");
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(CreateDelivererDto req, CancellationToken ct)
|
public override async Task HandleAsync(CreateDelivererDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public class DeleteDelivererEndpoint(DeliverersRepository deliverersRepository)
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Delete("/deliverers/{@Id}", x => new { x.DelivererId });
|
Delete("/deliverers/{@Id}", x => new { x.DelivererId });
|
||||||
AllowAnonymous();
|
Roles("Admin");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(DeleteDelivererRequest req, CancellationToken ct)
|
public override async Task HandleAsync(DeleteDelivererRequest req, CancellationToken ct)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ public class GetAllDelivererEndpoint(DeliverersRepository deliverersRepository)
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Get("/deliverers");
|
Get("/deliverers");
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(CancellationToken ct)
|
public override async Task HandleAsync(CancellationToken ct)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class GetDelivererEndpoint(DeliverersRepository deliverersRepository, Aut
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Get("/deliverers/{@Id}", x => new { x.DelivererId });
|
Get("/deliverers/{@Id}", x => new { x.DelivererId });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(GetDelivererRequest req, CancellationToken ct)
|
public override async Task HandleAsync(GetDelivererRequest req, CancellationToken ct)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ public class UpdateDelivererEndpoint(DeliverersRepository deliverersRepository,
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Put("/deliverers/{@Id}", x => new { x.Id });
|
Put("/deliverers/{@Id}", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin", "Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(UpdateDelivererDto req, CancellationToken ct)
|
public override async Task HandleAsync(UpdateDelivererDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public class CreateDeliveryNoteEndpoint(
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Post("/deliveryNotes");
|
Post("/deliveryNotes");
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(CreateDeliveryNoteDto req, CancellationToken ct)
|
public override async Task HandleAsync(CreateDeliveryNoteDto req, CancellationToken ct)
|
||||||
@@ -35,8 +35,8 @@ public class CreateDeliveryNoteEndpoint(
|
|||||||
DeliveryNote newDeliveryNote = new()
|
DeliveryNote newDeliveryNote = new()
|
||||||
{
|
{
|
||||||
TrackingNumber = req.TrackingNumber,
|
TrackingNumber = req.TrackingNumber,
|
||||||
EstimateDeliveryDate = req.EstimateDeliveryDate,
|
EstimateDeliveryDate = DateOnly.FromDateTime(DateTime.Today).AddMonths(2),
|
||||||
ExpeditionDate = req.ExpeditionDate,
|
ExpeditionDate = DateOnly.FromDateTime(DateTime.Today),
|
||||||
DelivererId = deliverer.Id,
|
DelivererId = deliverer.Id,
|
||||||
Deliverer = deliverer,
|
Deliverer = deliverer,
|
||||||
SupplierId = req.SupplierId,
|
SupplierId = req.SupplierId,
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class DeleteDeliveryNoteEndpoint(
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Delete("/deliveryNotes/{@Id}", x => new { x.Id });
|
Delete("/deliveryNotes/{@Id}", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(DeleteDeliveryNoteRequest req, CancellationToken ct)
|
public override async Task HandleAsync(DeleteDeliveryNoteRequest req, CancellationToken ct)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ public class GetAllDeliveryNoteEndpoint(DeliveryNotesRepository deliveryNotesRep
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Get("/deliveryNotes");
|
Get("/deliveryNotes");
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(CancellationToken ct)
|
public override async Task HandleAsync(CancellationToken ct)
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using FastEndpoints;
|
||||||
|
using PyroFetes.DTO.DeliveryNote.Response;
|
||||||
|
using PyroFetes.Repositories;
|
||||||
|
using PyroFetes.Specifications.DeliveryNotes;
|
||||||
|
|
||||||
|
namespace PyroFetes.Endpoints.DeliveryNotes;
|
||||||
|
|
||||||
|
public class GetAllDeliveryNotesNotArrivedEndpoint(DeliveryNotesRepository deliveryNotesRepository) : EndpointWithoutRequest<List<GetDeliveryNoteDto>>
|
||||||
|
{
|
||||||
|
public override void Configure()
|
||||||
|
{
|
||||||
|
Get("/deliveryNotes/validation");
|
||||||
|
Roles("Admin","Employe");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task HandleAsync(CancellationToken ct)
|
||||||
|
{
|
||||||
|
await Send.OkAsync(await deliveryNotesRepository.ProjectToListAsync<GetDeliveryNoteDto>(new GetAllDeliveryNotesByRealDateSpec(), ct), ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,7 +18,7 @@ public class GetDeliveryNoteEndpoint(
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Get("/deliveryNotes/{@Id}", x => new { x.DeliveryNoteId });
|
Get("/deliveryNotes/{@Id}", x => new { x.DeliveryNoteId });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(GetDeliveryNoteRequest req, CancellationToken ct)
|
public override async Task HandleAsync(GetDeliveryNoteRequest req, CancellationToken ct)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public class GetDeliveryNotePdfEndpoint(DeliveryNotesRepository deliveryNotesRep
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Get("/deliveryNotes/{@Id}/pdf", x => new { x.Id });
|
Get("/deliveryNotes/{@Id}/pdf", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
Description(b => b.Produces<byte[]>(200, MediaTypeNames.Application.Pdf));
|
Description(b => b.Produces<byte[]>(200, MediaTypeNames.Application.Pdf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class PatchRealDeliveryDateEndpoint(
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Patch("/deliveryNotes/{@Id}", x => new { x.Id });
|
Patch("/deliveryNotes/{@Id}", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(PatchDeliveryNoteRealDeliveryDateDto req, CancellationToken ct)
|
public override async Task HandleAsync(PatchDeliveryNoteRealDeliveryDateDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public class UpdateDeliveryNoteEndpoint(DeliveryNotesRepository deliveryNotesRep
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Put("/deliveryNotes/{@Id}", x => new { x.Id });
|
Put("/deliveryNotes/{@Id}", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(UpdateDeliveryNoteDto req, CancellationToken ct)
|
public override async Task HandleAsync(UpdateDeliveryNoteDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ public class DeleteProductEndpoint(ProductsRepository productsRepository) : Endp
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Delete("/products/{@Id}", x => new { x.ProductId });
|
Delete("/products/{@Id}", x => new { x.ProductId });
|
||||||
AllowAnonymous();
|
Roles("Admin");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(DeleteProductsRequest req, CancellationToken ct)
|
public override async Task HandleAsync(DeleteProductsRequest req, CancellationToken ct)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ public class GetAllProductsEndpoint(ProductsRepository productsRepository) : End
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Get("/products");
|
Get("/products");
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(CancellationToken ct)
|
public override async Task HandleAsync(CancellationToken ct)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ public class GetAllProductsUnderLimitEndpoint(ProductsRepository productsReposit
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Get("/products/underLimit");
|
Get("/products/underLimit");
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(CancellationToken ct)
|
public override async Task HandleAsync(CancellationToken ct)
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ public class GetProductEndpoint(
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Get("/products/{@Id}", x => new { x.Id });
|
Get("/products/{@Id}", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(GetProductRequest req, CancellationToken ct)
|
public override async Task HandleAsync(GetProductRequest req, CancellationToken ct)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public class PatchProductMinimalStockEndpoint(ProductsRepository productsReposit
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Patch("/products/{@Id}/MinimalStock", x => new { x.Id });
|
Patch("/products/{@Id}/MinimalStock", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(PatchProductMinimalStockDto req, CancellationToken ct)
|
public override async Task HandleAsync(PatchProductMinimalStockDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public class UpdateProductEndpoint(ProductsRepository productsRepository, AutoMa
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Put("/products/{@Id}", x => new { x.Id });
|
Put("/products/{@Id}", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(UpdateProductDto req, CancellationToken ct)
|
public override async Task HandleAsync(UpdateProductDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public class AddProductFromPurchaseOrderEndpoint(PurchaseProductsRepository purc
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Post("/purchaseOrders/{@PurchaseOrderId}/{@ProductId}", x => new { x.PurchaseOrderId, x.ProductId });
|
Post("/purchaseOrders/{@PurchaseOrderId}/{@ProductId}", x => new { x.PurchaseOrderId, x.ProductId });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(CreatePurchaseProductDto req, CancellationToken ct)
|
public override async Task HandleAsync(CreatePurchaseProductDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using FastEndpoints;
|
using FastEndpoints;
|
||||||
using PyroFetes.DTO.PurchaseOrder.Request;
|
using PyroFetes.DTO.PurchaseOrder.Request;
|
||||||
|
using PyroFetes.DTO.PurchaseOrder.Response;
|
||||||
using PyroFetes.DTO.PurchaseProduct.Request;
|
using PyroFetes.DTO.PurchaseProduct.Request;
|
||||||
using PyroFetes.Models;
|
using PyroFetes.Models;
|
||||||
using PyroFetes.Repositories;
|
using PyroFetes.Repositories;
|
||||||
@@ -12,12 +13,12 @@ public class CreatePurchaseOrder(
|
|||||||
PurchaseOrdersRepository purchaseOrdersRepository,
|
PurchaseOrdersRepository purchaseOrdersRepository,
|
||||||
ProductsRepository productsRepository,
|
ProductsRepository productsRepository,
|
||||||
PurchaseProductsRepository purchaseProductsRepository,
|
PurchaseProductsRepository purchaseProductsRepository,
|
||||||
AutoMapper.IMapper mapper) : Endpoint<CreatePurchaseOrderDto>
|
AutoMapper.IMapper mapper) : Endpoint<CreatePurchaseOrderDto, GetPurchaseOrderDto>
|
||||||
{
|
{
|
||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Post("/purchaseOrders");
|
Post("/purchaseOrders");
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(CreatePurchaseOrderDto req, CancellationToken ct)
|
public override async Task HandleAsync(CreatePurchaseOrderDto req, CancellationToken ct)
|
||||||
@@ -42,6 +43,7 @@ public class CreatePurchaseOrder(
|
|||||||
if (purchaseProduct is not null)
|
if (purchaseProduct is not null)
|
||||||
{
|
{
|
||||||
await Send.StringAsync("Le produit est déjà dans le bon de commande", 400, cancellation: ct);
|
await Send.StringAsync("Le produit est déjà dans le bon de commande", 400, cancellation: ct);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PurchaseProduct? productOnPurchase = mapper.Map<PurchaseProduct>(line);
|
PurchaseProduct? productOnPurchase = mapper.Map<PurchaseProduct>(line);
|
||||||
@@ -50,6 +52,6 @@ public class CreatePurchaseOrder(
|
|||||||
await purchaseProductsRepository.AddAsync(productOnPurchase, ct);
|
await purchaseProductsRepository.AddAsync(productOnPurchase, ct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
await Send.NoContentAsync(ct);
|
await Send.OkAsync(mapper.Map<GetPurchaseOrderDto>(purchaseOrder), ct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,7 @@ public class DeleteProductFromPurchaseOrderEndpoint(PurchaseProductsRepository p
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Delete("/purchaseOrders/{@ProductId}/{@PurchaseOrderId}", x => new { x.ProductId, x.PurchaseOrderId });
|
Delete("/purchaseOrders/{@ProductId}/{@PurchaseOrderId}", x => new { x.ProductId, x.PurchaseOrderId });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(DeletePurchaseProductRequest req, CancellationToken ct)
|
public override async Task HandleAsync(DeletePurchaseProductRequest req, CancellationToken ct)
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ public class DeletePurchaseOrderEndpoint(PurchaseOrdersRepository purchaseOrders
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Delete("/purchaseOrders/{@Id}", x => new { x.Id });
|
Delete("/purchaseOrders/{@Id}", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(DeletePurchaseOrderRequest req, CancellationToken ct)
|
public override async Task HandleAsync(DeletePurchaseOrderRequest req, CancellationToken ct)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using FastEndpoints;
|
using FastEndpoints;
|
||||||
using PyroFetes.DTO.PurchaseOrder.Response;
|
using PyroFetes.DTO.PurchaseOrder.Response;
|
||||||
using PyroFetes.Repositories;
|
using PyroFetes.Repositories;
|
||||||
|
using PyroFetes.Specifications.PurchaseOrders;
|
||||||
|
|
||||||
namespace PyroFetes.Endpoints.PurchaseOrders;
|
namespace PyroFetes.Endpoints.PurchaseOrders;
|
||||||
|
|
||||||
@@ -9,11 +10,11 @@ public class GetAllPurchaseOrderEndpoint(PurchaseOrdersRepository purchaseOrders
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Get("/purchaseOrders");
|
Get("/purchaseOrders");
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(CancellationToken ct)
|
public override async Task HandleAsync(CancellationToken ct)
|
||||||
{
|
{
|
||||||
await Send.OkAsync(await purchaseOrdersRepository.ProjectToListAsync<GetPurchaseOrderDto>(ct), ct);
|
await Send.OkAsync(await purchaseOrdersRepository.ProjectToListAsync<GetPurchaseOrderDto>(new GetAllPurchaseOrderSpec(), ct), ct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -16,7 +16,7 @@ public class GetPurchaseOrderEndpoint(PurchaseOrdersRepository purchaseOrdersRep
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Get("/purchaseOrders/{@Id}", x => new { x.Id });
|
Get("/purchaseOrders/{@Id}", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(GetPurchaseOrderRequest req, CancellationToken ct)
|
public override async Task HandleAsync(GetPurchaseOrderRequest req, CancellationToken ct)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public class GetPurchaseOrderPdfEndpoint(
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Get("/purchaseOrders/{@Id}/pdf", x => new { x.Id });
|
Get("/purchaseOrders/{@Id}/pdf", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
Description(b => b.Produces<byte[]>(200, MediaTypeNames.Application.Pdf));
|
Description(b => b.Produces<byte[]>(200, MediaTypeNames.Application.Pdf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class PatchPurchaseOrderPurchaseConditionsEndpoint(PurchaseOrdersReposito
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Patch("/purchaseOrders/{@Id}/PurchaseConditions", x => new { x.Id });
|
Patch("/purchaseOrders/{@Id}/PurchaseConditions", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(PatchPurchaseOrderPurchaseConditionsDto req, CancellationToken ct)
|
public override async Task HandleAsync(PatchPurchaseOrderPurchaseConditionsDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class PatchPurchaseProductQuantityEndpoint(PurchaseProductsRepository pur
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Patch("/purchaseOrders/{@ProductId}/{@PurchaseOrderId}/Quantity", x => new { x.ProductId, x.PurchaseOrderId });
|
Patch("/purchaseOrders/{@ProductId}/{@PurchaseOrderId}/Quantity", x => new { x.ProductId, x.PurchaseOrderId });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(PatchPurchaseProductQuantityDto req, CancellationToken ct)
|
public override async Task HandleAsync(PatchPurchaseProductQuantityDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public class AddProductoToQuotationEndpoint(
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Post("/quotations/{@Id}/products", x => new { x.ProductId, x.QuotationId });
|
Post("/quotations/{@Id}/products", x => new { x.ProductId, x.QuotationId });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(AddQuotationProductDto req, CancellationToken ct)
|
public override async Task HandleAsync(AddQuotationProductDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -17,13 +17,12 @@ public class CreateQuotationEndpoint(
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Post("/quotations");
|
Post("/quotations");
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(CreateQuotationDto req, CancellationToken ct)
|
public override async Task HandleAsync(CreateQuotationDto req, CancellationToken ct)
|
||||||
{
|
{
|
||||||
Quotation quotation = mapper.Map<Quotation>(req);
|
Quotation quotation = mapper.Map<Quotation>(req);
|
||||||
quotation.CustomerId = 1; // TODO: A changer
|
|
||||||
await quotationsRepository.AddAsync(quotation, ct);
|
await quotationsRepository.AddAsync(quotation, ct);
|
||||||
|
|
||||||
if (req.Products != null)
|
if (req.Products != null)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class DeleteProductFromQuotationEndpoint(QuotationProductsRepository quot
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Delete("/quotations/{@ProductId}/{@QuotationId}", x => new { x.ProductId, x.QuotationId });
|
Delete("/quotations/{@ProductId}/{@QuotationId}", x => new { x.ProductId, x.QuotationId });
|
||||||
AllowAnonymous();
|
Roles("Admin", "Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(DeleteQuotationProductRequest req, CancellationToken ct)
|
public override async Task HandleAsync(DeleteQuotationProductRequest req, CancellationToken ct)
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ public class DeleteQuotationEndpoint(QuotationsRepository quotationsRepository)
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Delete("/quotations/{@Id}", x => new { x.Id });
|
Delete("/quotations/{@Id}", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(DeleteQuotationRequest req, CancellationToken ct)
|
public override async Task HandleAsync(DeleteQuotationRequest req, CancellationToken ct)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using FastEndpoints;
|
using FastEndpoints;
|
||||||
using PyroFetes.DTO.Quotation.Response;
|
using PyroFetes.DTO.Quotation.Response;
|
||||||
using PyroFetes.Repositories;
|
using PyroFetes.Repositories;
|
||||||
|
using PyroFetes.Specifications.Quotations;
|
||||||
|
|
||||||
namespace PyroFetes.Endpoints.Quotations;
|
namespace PyroFetes.Endpoints.Quotations;
|
||||||
|
|
||||||
@@ -9,11 +10,11 @@ public class GetAllQuotationEndpoint(QuotationsRepository quotationsRepository)
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Get("/quotations");
|
Get("/quotations");
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(CancellationToken ct)
|
public override async Task HandleAsync(CancellationToken ct)
|
||||||
{
|
{
|
||||||
await Send.OkAsync(await quotationsRepository.ProjectToListAsync<GetQuotationDto>(ct), ct);
|
await Send.OkAsync(await quotationsRepository.ProjectToListAsync<GetQuotationDto>(new GetAllQuotationSpec(), ct), ct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -18,7 +18,7 @@ public class GetQuotationEndpoint(
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Get("/quotations/{@Id}", x => new { x.Id });
|
Get("/quotations/{@Id}", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(GetQuotationRequest req, CancellationToken ct)
|
public override async Task HandleAsync(GetQuotationRequest req, CancellationToken ct)
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public class GetQuotationPdfEndpoint(
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Get("/quotations/{@Id}/pdf", x => new { x.Id });
|
Get("/quotations/{@Id}/pdf", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
Description(b => b.Produces<byte[]>(200, MediaTypeNames.Application.Pdf));
|
Description(b => b.Produces<byte[]>(200, MediaTypeNames.Application.Pdf));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public class PatchQuotationConditionsSaleEndpoint(
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Patch("/quotations/{@Id}/saleConditions", x => new { x.Id });
|
Patch("/quotations/{@Id}/saleConditions", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(PatchQuotationConditionsSaleDto req, CancellationToken ct)
|
public override async Task HandleAsync(PatchQuotationConditionsSaleDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public class PatchQuotationMessageEndpoint(
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Patch("/quotations/{@Id}/message", x => new { x.Id });
|
Patch("/quotations/{@Id}/message", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(PatchQuotationMessageDto req, CancellationToken ct)
|
public override async Task HandleAsync(PatchQuotationMessageDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ public class PatchQuotationProductQuantityEndpoint(
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Patch("/quotations/{@ProductId}/{@QuotationId}/Quantity", x => new { x.ProductId, x.QuotationId });
|
Patch("/quotations/{@ProductId}/{@QuotationId}/Quantity", x => new { x.ProductId, x.QuotationId });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(PatchQuotationProductQuantityDto req, CancellationToken ct)
|
public override async Task HandleAsync(PatchQuotationProductQuantityDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -13,7 +13,8 @@ public class UpdateQuotationEndpoint(
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Put("/quotations/{@Id}", x => new { x.Id });
|
Put("/quotations/{@Id}", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(UpdateQuotationDto req, CancellationToken ct)
|
public override async Task HandleAsync(UpdateQuotationDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using FastEndpoints;
|
||||||
|
using FastEndpoints.Security;
|
||||||
|
using PyroFetes.DTO.Refresh.Request;
|
||||||
|
using PyroFetes.DTO.Refresh.Response;
|
||||||
|
using PyroFetes.Models;
|
||||||
|
using PyroFetes.Repositories;
|
||||||
|
using PyroFetes.Specifications.Users;
|
||||||
|
|
||||||
|
namespace PyroFetes.Endpoints.Refresh;
|
||||||
|
|
||||||
|
public class RefreshTokenEndpoint(UsersRepository usersRepository) : Endpoint<RefreshTokenDto, GetRefreshTokenDto>
|
||||||
|
{
|
||||||
|
public override void Configure()
|
||||||
|
{
|
||||||
|
Post("/refresh");
|
||||||
|
AllowAnonymous();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task HandleAsync(RefreshTokenDto req, CancellationToken ct)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
JwtSecurityTokenHandler handler = new();
|
||||||
|
JwtSecurityToken? token = handler.ReadJwtToken(req.Token);
|
||||||
|
string? username = token.Claims.FirstOrDefault(c => c.Type == "Name")?.Value;
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(username))
|
||||||
|
{
|
||||||
|
await Send.UnauthorizedAsync(ct);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
User? login = await usersRepository.SingleOrDefaultAsync(new GetUserByNameSpec(username), ct);
|
||||||
|
if (login == null)
|
||||||
|
{
|
||||||
|
await Send.UnauthorizedAsync(ct);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string jwtToken = JwtBearer.CreateToken(o =>
|
||||||
|
{
|
||||||
|
o.SigningKey = "v9!Qx7#Lk2@pZ8$wR6!tN5%uF3&cD9^mH1*eY4";
|
||||||
|
o.ExpireAt = DateTime.UtcNow.AddMinutes(15);
|
||||||
|
if (login.Fonction is not null) o.User.Roles.Add(login.Fonction);
|
||||||
|
o.User.Claims.Add(("Name", login.Name)!);
|
||||||
|
o.User.Claims.Add(("Id", login.Id.ToString())!);
|
||||||
|
});
|
||||||
|
|
||||||
|
GetRefreshTokenDto responseDto = new()
|
||||||
|
{
|
||||||
|
Token = jwtToken
|
||||||
|
};
|
||||||
|
|
||||||
|
await Send.OkAsync(responseDto, ct);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
await Send.UnauthorizedAsync(ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,15 +2,16 @@
|
|||||||
using PyroFetes.DTO.SettingDTO.Response;
|
using PyroFetes.DTO.SettingDTO.Response;
|
||||||
using PyroFetes.Models;
|
using PyroFetes.Models;
|
||||||
using PyroFetes.Repositories;
|
using PyroFetes.Repositories;
|
||||||
|
using PyroFetes.Services;
|
||||||
|
|
||||||
namespace PyroFetes.Endpoints.Settings;
|
namespace PyroFetes.Endpoints.Settings;
|
||||||
|
|
||||||
public class GetSettingEndpoint(SettingsRepository settingsRepository, AutoMapper.IMapper mapper) : EndpointWithoutRequest<GetSettingDto>
|
public class GetSettingEndpoint(SettingsRepository settingsRepository, StorageService storageService) : EndpointWithoutRequest<GetSettingDto>
|
||||||
{
|
{
|
||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Get("/settings/");
|
Get("/settings/");
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(CancellationToken ct)
|
public override async Task HandleAsync(CancellationToken ct)
|
||||||
@@ -23,6 +24,13 @@ public class GetSettingEndpoint(SettingsRepository settingsRepository, AutoMappe
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
await Send.OkAsync(mapper.Map<GetSettingDto>(setting), ct);
|
GetSettingDto settingDto = new()
|
||||||
|
{
|
||||||
|
Id = setting.Id,
|
||||||
|
ElectronicSignature = storageService.GetUrl(setting.ElectronicSignature!),
|
||||||
|
Logo = storageService.GetUrl(setting.Logo!)
|
||||||
|
};
|
||||||
|
|
||||||
|
await Send.OkAsync(settingDto, ct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,16 +2,18 @@
|
|||||||
using PyroFetes.DTO.SettingDTO.Request;
|
using PyroFetes.DTO.SettingDTO.Request;
|
||||||
using PyroFetes.Models;
|
using PyroFetes.Models;
|
||||||
using PyroFetes.Repositories;
|
using PyroFetes.Repositories;
|
||||||
|
using PyroFetes.Services;
|
||||||
|
|
||||||
namespace PyroFetes.Endpoints.Settings;
|
namespace PyroFetes.Endpoints.Settings;
|
||||||
|
|
||||||
public class PatchSettingElectronicSignatureEndpoint(SettingsRepository settingsRepository) : Endpoint<PatchSettingElectronicSignatureDto>
|
public class PatchSettingElectronicSignatureEndpoint(SettingsRepository settingsRepository, StorageService storageService) : Endpoint<PatchSettingElectronicSignatureDto>
|
||||||
{
|
{
|
||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Patch("/settings/electronicSignature");
|
Patch("/settings/electronicSignature");
|
||||||
AllowFormData();
|
AllowFormData();
|
||||||
AllowAnonymous();
|
Roles("Admin");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(PatchSettingElectronicSignatureDto req, CancellationToken ct)
|
public override async Task HandleAsync(PatchSettingElectronicSignatureDto req, CancellationToken ct)
|
||||||
@@ -24,12 +26,8 @@ public class PatchSettingElectronicSignatureEndpoint(SettingsRepository settings
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encodage en base64
|
string key = await storageService.UploadFile(req.ElectronicSignature!, "electronicSignature", ct);
|
||||||
using MemoryStream memoryStream = new();
|
setting.ElectronicSignature = key;
|
||||||
if (req.ElectronicSignature != null) await req.ElectronicSignature.CopyToAsync(memoryStream, ct);
|
|
||||||
byte[] signatureBytes = memoryStream.ToArray();
|
|
||||||
|
|
||||||
setting.ElectronicSignature = Convert.ToBase64String(signatureBytes);
|
|
||||||
|
|
||||||
await settingsRepository.SaveChangesAsync(ct);
|
await settingsRepository.SaveChangesAsync(ct);
|
||||||
await Send.NoContentAsync(ct);
|
await Send.NoContentAsync(ct);
|
||||||
|
|||||||
@@ -2,16 +2,17 @@
|
|||||||
using PyroFetes.DTO.SettingDTO.Request;
|
using PyroFetes.DTO.SettingDTO.Request;
|
||||||
using PyroFetes.Models;
|
using PyroFetes.Models;
|
||||||
using PyroFetes.Repositories;
|
using PyroFetes.Repositories;
|
||||||
|
using PyroFetes.Services;
|
||||||
|
|
||||||
namespace PyroFetes.Endpoints.Settings;
|
namespace PyroFetes.Endpoints.Settings;
|
||||||
|
|
||||||
public class PatchSettingLogoEndpoint(SettingsRepository settingsRepository) : Endpoint<PatchSettingLogoDto>
|
public class PatchSettingLogoEndpoint(SettingsRepository settingsRepository, StorageService storageService) : Endpoint<PatchSettingLogoDto>
|
||||||
{
|
{
|
||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Patch("/settings/logo");
|
Patch("/settings/logo");
|
||||||
AllowFormData();
|
AllowFormData();
|
||||||
AllowAnonymous();
|
Roles("Admin");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(PatchSettingLogoDto req, CancellationToken ct)
|
public override async Task HandleAsync(PatchSettingLogoDto req, CancellationToken ct)
|
||||||
@@ -24,12 +25,9 @@ public class PatchSettingLogoEndpoint(SettingsRepository settingsRepository) : E
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Encodage en base64
|
string key = await storageService.UploadFile(req.Logo!, "logo", ct);
|
||||||
using MemoryStream memoryStream = new();
|
|
||||||
if (req.Logo != null) await req.Logo.CopyToAsync(memoryStream, ct);
|
|
||||||
byte[] logoBytes = memoryStream.ToArray();
|
|
||||||
|
|
||||||
setting.Logo = Convert.ToBase64String(logoBytes);
|
setting.Logo = key;
|
||||||
|
|
||||||
await settingsRepository.SaveChangesAsync(ct);
|
await settingsRepository.SaveChangesAsync(ct);
|
||||||
await Send.NoContentAsync(ct);
|
await Send.NoContentAsync(ct);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public class AddProductToSupplierEndpoint(
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Post("/suppliers/{@SupplierId}/{@ProductId}/", x => new { x.SupplierId, x.ProductId });
|
Post("/suppliers/{@SupplierId}/{@ProductId}/", x => new { x.SupplierId, x.ProductId });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(CreatePriceDto req, CancellationToken ct)
|
public override async Task HandleAsync(CreatePriceDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ public class CreateSupplierEndpoint(SuppliersRepository suppliersRepository, Aut
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Post("/suppliers");
|
Post("/suppliers");
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(CreateSupplierDto req, CancellationToken ct)
|
public override async Task HandleAsync(CreateSupplierDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class DeleteProductToSupplierEndpoint(PricesRepository pricesRepository)
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Delete("/suppliers/{@SupplierId}/{@Product}", x => new { x.SupplierId, x.ProductId });
|
Delete("/suppliers/{@SupplierId}/{@Product}", x => new { x.SupplierId, x.ProductId });
|
||||||
AllowAnonymous();
|
Roles("Admin");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(DeletePriceRequest req, CancellationToken ct)
|
public override async Task HandleAsync(DeletePriceRequest req, CancellationToken ct)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public class DeleteSupplierEndpoint(SuppliersRepository suppliersRepository) : E
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Delete("/suppliers/{@Id}", x => new { x.Id });
|
Delete("/suppliers/{@Id}", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(DeleteSupplierRequest req, CancellationToken ct)
|
public override async Task HandleAsync(DeleteSupplierRequest req, CancellationToken ct)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ public class GetAllSuppliersEndpoint(SuppliersRepository suppliersRepository) :
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Get("/suppliers");
|
Get("/suppliers");
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(CancellationToken ct)
|
public override async Task HandleAsync(CancellationToken ct)
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public class GetSupplierEndpoint(SuppliersRepository suppliersRepository, AutoMa
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Get("/suppliers/{@Id}", x => new { x.Id });
|
Get("/suppliers/{@Id}", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(GetSupplierRequest req, CancellationToken ct)
|
public override async Task HandleAsync(GetSupplierRequest req, CancellationToken ct)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class PatchPriceEndpoint(
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Patch("/prices/{@ProductId}/{@SupplierId}/SellingPrice", x => new { x.ProductId, x.SupplierId });
|
Patch("/prices/{@ProductId}/{@SupplierId}/SellingPrice", x => new { x.ProductId, x.SupplierId });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(PatchPriceSellingPriceDto req, CancellationToken ct)
|
public override async Task HandleAsync(PatchPriceSellingPriceDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -12,7 +12,8 @@ public class PatchSupplierDeliveryDelayEndpoint(SuppliersRepository suppliersRep
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Patch("/suppliers/{@Id}/deliveryDelay", x => new { x.Id });
|
Patch("/suppliers/{@Id}/deliveryDelay", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(PatchSupplierDeliveryDelayDto req, CancellationToken ct)
|
public override async Task HandleAsync(PatchSupplierDeliveryDelayDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public class UpdateSupplierEndpoint(SuppliersRepository suppliersRepository, Aut
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Put("/suppliers/{@Id}", x => new { x.Id });
|
Put("/suppliers/{@Id}", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(UpdateSupplierDto req, CancellationToken ct)
|
public override async Task HandleAsync(UpdateSupplierDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ public class ConnectUserEndpoint(UsersRepository usersRepository) : Endpoint<Con
|
|||||||
{
|
{
|
||||||
string jwtToken = JwtBearer.CreateToken(o =>
|
string jwtToken = JwtBearer.CreateToken(o =>
|
||||||
{
|
{
|
||||||
o.SigningKey = "ThisIsASuperSecretJwtKeyThatIsAtLeast32CharsLong";
|
o.SigningKey = "v9!Qx7#Lk2@pZ8$wR6!tN5%uF3&cD9^mH1*eY4";
|
||||||
o.ExpireAt = DateTime.UtcNow.AddMinutes(15);
|
o.ExpireAt = DateTime.UtcNow.AddMinutes(15);
|
||||||
if (user.Fonction is not null) o.User.Roles.Add(user.Fonction);
|
if (user.Fonction is not null) o.User.Roles.Add(user.Fonction);
|
||||||
o.User.Claims.Add(("Name", user.Name)!);
|
o.User.Claims.Add(("Name", user.Name)!);
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class CreateUserEndpoint(UsersRepository usersRepository) : Endpoint<Crea
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Post("/users");
|
Post("/users");
|
||||||
AllowAnonymous();
|
Roles("Admin");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(CreateUserDto req, CancellationToken ct)
|
public override async Task HandleAsync(CreateUserDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ public class DeleteUserEndpoint(UsersRepository usersRepository) : Endpoint<Dele
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Delete("/users/{@Id}", x => new { x.Id });
|
Delete("/users/{@Id}", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(DeleteUserRequest req, CancellationToken ct)
|
public override async Task HandleAsync(DeleteUserRequest req, CancellationToken ct)
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ public class GetAllUsersEndpoint(UsersRepository usersRepository) : EndpointWith
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Get("/users");
|
Get("/users");
|
||||||
AllowAnonymous();
|
Roles("Admin");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(CancellationToken ct)
|
public override async Task HandleAsync(CancellationToken ct)
|
||||||
|
|||||||
@@ -6,22 +6,18 @@ using PyroFetes.Specifications.Users;
|
|||||||
|
|
||||||
namespace PyroFetes.Endpoints.Users;
|
namespace PyroFetes.Endpoints.Users;
|
||||||
|
|
||||||
public class GetUserRequest
|
public class GetUserEndpoint(UsersRepository usersRepository, AutoMapper.IMapper mapper) : EndpointWithoutRequest<GetUserDto>
|
||||||
{
|
|
||||||
public int Id { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public class GetUserEndpoint(UsersRepository usersRepository, AutoMapper.IMapper mapper) : Endpoint<GetUserRequest, GetUserDto>
|
|
||||||
{
|
{
|
||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Get("/users/{@Id}", x => new { x.Id });
|
Get("/user/");
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(GetUserRequest req, CancellationToken ct)
|
public override async Task HandleAsync(CancellationToken ct)
|
||||||
{
|
{
|
||||||
User? user = await usersRepository.SingleOrDefaultAsync(new GetUserByIdSpec(req.Id), ct);
|
int userId = int.Parse(User.FindFirst("Id")!.Value);
|
||||||
|
User? user = await usersRepository.SingleOrDefaultAsync(new GetUserByIdSpec(userId), ct);
|
||||||
|
|
||||||
if (user is null)
|
if (user is null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ public class PatchUserPasswordEndpoint(UsersRepository usersRepository, AutoMapp
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Patch("/users/{@Id}/password", x => new { x.Id });
|
Patch("/users/{@Id}/password", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(PatchUserPasswordDto req, CancellationToken ct)
|
public override async Task HandleAsync(PatchUserPasswordDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class UpdateUserEndpoint(UsersRepository usersRepository) : Endpoint<Upda
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Put("/users/{@Id}", x => new { x.Id });
|
Put("/users/{@Id}", x => new { x.Id });
|
||||||
AllowAnonymous();
|
Roles("Admin");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(UpdateUserDto req, CancellationToken ct)
|
public override async Task HandleAsync(UpdateUserDto req, CancellationToken ct)
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using FastEndpoints;
|
||||||
|
using PyroFetes.DTO.WareHouse.Response;
|
||||||
|
using PyroFetes.Repositories;
|
||||||
|
|
||||||
|
namespace PyroFetes.Endpoints.WareHouse;
|
||||||
|
|
||||||
|
public class GetAllWarehouseEndpoint(WareHouseRepository wareHouseRepository, AutoMapper.IMapper mapper) : EndpointWithoutRequest<List<GetWareHouseDto>>
|
||||||
|
{
|
||||||
|
public override void Configure()
|
||||||
|
{
|
||||||
|
Get("/wareHouses/");
|
||||||
|
Roles("Admin","Employe");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task HandleAsync(CancellationToken ct)
|
||||||
|
{
|
||||||
|
await Send.OkAsync(await wareHouseRepository.ProjectToListAsync<GetWareHouseDto>(ct), ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -16,7 +16,7 @@ public class GetTotalQuantityEndpoint(
|
|||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Get("/wareHouseProducts/{@ProductId}", x => new { x.ProductId });
|
Get("/wareHouseProducts/{@ProductId}", x => new { x.ProductId });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(GetTotalQuantityRequest req, CancellationToken ct)
|
public override async Task HandleAsync(GetTotalQuantityRequest req, CancellationToken ct)
|
||||||
|
|||||||
@@ -3,30 +3,36 @@ using PyroFetes.DTO.WareHouseProduct.Request;
|
|||||||
using PyroFetes.DTO.WareHouseProduct.Response;
|
using PyroFetes.DTO.WareHouseProduct.Response;
|
||||||
using PyroFetes.Models;
|
using PyroFetes.Models;
|
||||||
using PyroFetes.Repositories;
|
using PyroFetes.Repositories;
|
||||||
|
using PyroFetes.Specifications.WareHouse;
|
||||||
using PyroFetes.Specifications.WarehouseProducts;
|
using PyroFetes.Specifications.WarehouseProducts;
|
||||||
|
|
||||||
namespace PyroFetes.Endpoints.WareHouseProducts;
|
namespace PyroFetes.Endpoints.WareHouseProducts;
|
||||||
|
|
||||||
public class PatchWareHouseProductQuantityEndpoint(WarehouseProductsRepository warehouseProductsRepository) : Endpoint<PatchWareHouseProductQuantityDto, GetWareHouseProductDto>
|
public class PatchWareHouseProductQuantityEndpoint(WarehouseProductsRepository warehouseProductsRepository, WareHouseRepository wareHouseRepository , AutoMapper.IMapper mapper) : Endpoint<PatchWareHouseProductQuantityDto, GetWareHouseProductDto>
|
||||||
{
|
{
|
||||||
public override void Configure()
|
public override void Configure()
|
||||||
{
|
{
|
||||||
Patch("/wareHouseProducts/{@ProductId}/{@WareHouseId}/quantity", x => new { x.ProductId, x.WareHouseId });
|
Patch("/wareHouseProducts/{@ProductId}/{@WareHouseId}/quantity", x => new { x.ProductId, x.WareHouseId });
|
||||||
AllowAnonymous();
|
Roles("Admin","Employe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task HandleAsync(PatchWareHouseProductQuantityDto req, CancellationToken ct)
|
public override async Task HandleAsync(PatchWareHouseProductQuantityDto req, CancellationToken ct)
|
||||||
{
|
{
|
||||||
WarehouseProduct? wareHouseProduct = await warehouseProductsRepository.FirstOrDefaultAsync(new GetWarehouseProductByProductIdSpec(req.ProductId, req.WareHouseId), ct);
|
WarehouseProduct? wareHouseProduct = await warehouseProductsRepository.FirstOrDefaultAsync(new GetWarehouseProductByProductIdSpec(req.ProductId, req.WareHouseId), ct);
|
||||||
|
Warehouse? warehouse = await wareHouseRepository.SingleOrDefaultAsync(new GetWareHouseByIdSpec(req.WareHouseId), ct);
|
||||||
|
|
||||||
if (wareHouseProduct is null)
|
if (warehouse is null)
|
||||||
{
|
{
|
||||||
await Send.NotFoundAsync(ct);
|
await Send.NotFoundAsync(ct);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
wareHouseProduct.Quantity = req.Quantity;
|
if (wareHouseProduct is null) await warehouseProductsRepository.AddAsync(mapper.Map<WarehouseProduct>(req), ct);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wareHouseProduct.Quantity += req.Quantity;
|
||||||
await warehouseProductsRepository.SaveChangesAsync(ct);
|
await warehouseProductsRepository.SaveChangesAsync(ct);
|
||||||
|
}
|
||||||
|
|
||||||
await Send.NoContentAsync(ct);
|
await Send.NoContentAsync(ct);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -81,8 +81,6 @@ public class DtoToEntityMappings : Profile
|
|||||||
CreateMap<PatchUserPasswordDto, User>()
|
CreateMap<PatchUserPasswordDto, User>()
|
||||||
.ForMember(dest => dest.Id, opt => opt.Ignore());
|
.ForMember(dest => dest.Id, opt => opt.Ignore());
|
||||||
|
|
||||||
CreateMap<PatchWareHouseProductQuantityDto, WarehouseProduct>()
|
CreateMap<PatchWareHouseProductQuantityDto, WarehouseProduct>();
|
||||||
.ForMember(dest => dest.ProductId, opt => opt.Ignore())
|
|
||||||
.ForMember(dest => dest.WarehouseId, opt => opt.Ignore());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
|
using PyroFetes.DTO.Customer.Response;
|
||||||
using PyroFetes.DTO.Deliverer.Response;
|
using PyroFetes.DTO.Deliverer.Response;
|
||||||
using PyroFetes.DTO.DeliveryNote.Response;
|
using PyroFetes.DTO.DeliveryNote.Response;
|
||||||
using PyroFetes.DTO.Price.Response;
|
using PyroFetes.DTO.Price.Response;
|
||||||
@@ -11,6 +12,7 @@ using PyroFetes.DTO.QuotationProduct.Response;
|
|||||||
using PyroFetes.DTO.SettingDTO.Response;
|
using PyroFetes.DTO.SettingDTO.Response;
|
||||||
using PyroFetes.DTO.Supplier.Response;
|
using PyroFetes.DTO.Supplier.Response;
|
||||||
using PyroFetes.DTO.User.Response;
|
using PyroFetes.DTO.User.Response;
|
||||||
|
using PyroFetes.DTO.WareHouse.Response;
|
||||||
using PyroFetes.DTO.WareHouseProduct.Response;
|
using PyroFetes.DTO.WareHouseProduct.Response;
|
||||||
using PyroFetes.Models;
|
using PyroFetes.Models;
|
||||||
|
|
||||||
@@ -56,5 +58,9 @@ public class EntityToDtoMappings : Profile
|
|||||||
CreateMap<User, GetUserDto>();
|
CreateMap<User, GetUserDto>();
|
||||||
|
|
||||||
CreateMap<WarehouseProduct, GetWareHouseProductDto>();
|
CreateMap<WarehouseProduct, GetWareHouseProductDto>();
|
||||||
|
|
||||||
|
CreateMap<Warehouse, GetWareHouseDto>();
|
||||||
|
|
||||||
|
CreateMap<Customer, GetCustomerDto>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+32
-1
@@ -1,3 +1,5 @@
|
|||||||
|
using Amazon.S3;
|
||||||
|
using Amazon.S3.Model;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
using AutoMapper.EquivalencyExpression;
|
using AutoMapper.EquivalencyExpression;
|
||||||
using PyroFetes;
|
using PyroFetes;
|
||||||
@@ -7,6 +9,7 @@ using FastEndpoints.Security;
|
|||||||
using Microsoft.Net.Http.Headers;
|
using Microsoft.Net.Http.Headers;
|
||||||
using PyroFetes.MappingProfiles;
|
using PyroFetes.MappingProfiles;
|
||||||
using PyroFetes.Repositories;
|
using PyroFetes.Repositories;
|
||||||
|
using PyroFetes.Services;
|
||||||
using PyroFetes.Services.Pdf;
|
using PyroFetes.Services.Pdf;
|
||||||
using QuestPDF.Infrastructure;
|
using QuestPDF.Infrastructure;
|
||||||
|
|
||||||
@@ -17,7 +20,7 @@ QuestPDF.Settings.License = LicenseType.Community;
|
|||||||
|
|
||||||
// On ajoute ici FastEndpoints, un framework REPR et Swagger aux services disponibles dans le projet
|
// On ajoute ici FastEndpoints, un framework REPR et Swagger aux services disponibles dans le projet
|
||||||
builder.Services
|
builder.Services
|
||||||
.AddAuthenticationJwtBearer(s => s.SigningKey = "ThisIsASuperSecretJwtKeyThatIsAtLeast32CharsLong")
|
.AddAuthenticationJwtBearer(s => s.SigningKey = "v9!Qx7#Lk2@pZ8$wR6!tN5%uF3&cD9^mH1*eY4")
|
||||||
.AddAuthorization()
|
.AddAuthorization()
|
||||||
.AddFastEndpoints()
|
.AddFastEndpoints()
|
||||||
.SwaggerDocument(options => { options.ShortSchemaNames = true; })
|
.SwaggerDocument(options => { options.ShortSchemaNames = true; })
|
||||||
@@ -49,11 +52,14 @@ builder.Services.AddScoped<SuppliersRepository>();
|
|||||||
builder.Services.AddScoped<SettingsRepository>();
|
builder.Services.AddScoped<SettingsRepository>();
|
||||||
builder.Services.AddScoped<UsersRepository>();
|
builder.Services.AddScoped<UsersRepository>();
|
||||||
builder.Services.AddScoped<WarehouseProductsRepository>();
|
builder.Services.AddScoped<WarehouseProductsRepository>();
|
||||||
|
builder.Services.AddScoped<WareHouseRepository>();
|
||||||
|
builder.Services.AddScoped<CustomersRepository>();
|
||||||
|
|
||||||
// Ajout des services
|
// Ajout des services
|
||||||
builder.Services.AddScoped<IDeliveryNotePdfService, DeliveryNotePdfService>();
|
builder.Services.AddScoped<IDeliveryNotePdfService, DeliveryNotePdfService>();
|
||||||
builder.Services.AddScoped<IPurchaseOrderPdfService, PurchaseOrderPdfService>();
|
builder.Services.AddScoped<IPurchaseOrderPdfService, PurchaseOrderPdfService>();
|
||||||
builder.Services.AddScoped<IQuotationPdfService, QuotationPdfService>();
|
builder.Services.AddScoped<IQuotationPdfService, QuotationPdfService>();
|
||||||
|
builder.Services.AddScoped<StorageService>();
|
||||||
|
|
||||||
MapperConfiguration mappingConfig = new(mc =>
|
MapperConfiguration mappingConfig = new(mc =>
|
||||||
{
|
{
|
||||||
@@ -66,6 +72,31 @@ MapperConfiguration mappingConfig = new(mc =>
|
|||||||
AutoMapper.IMapper mapper = mappingConfig.CreateMapper();
|
AutoMapper.IMapper mapper = mappingConfig.CreateMapper();
|
||||||
builder.Services.AddSingleton(mapper);
|
builder.Services.AddSingleton(mapper);
|
||||||
|
|
||||||
|
// RUSTFS
|
||||||
|
IConfigurationSection config = builder.Configuration.GetSection("RustFS");
|
||||||
|
|
||||||
|
AmazonS3Client s3Client = new(
|
||||||
|
config["AccessKey"],
|
||||||
|
config["SecretKey"],
|
||||||
|
new AmazonS3Config
|
||||||
|
{
|
||||||
|
ServiceURL = config["ServiceUrl"],
|
||||||
|
ForcePathStyle = true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
ListBucketsResponse? buckets = await s3Client.ListBucketsAsync();
|
||||||
|
bool exist = buckets?.Buckets?.Any(x => x.BucketName == config["BucketName"]) == true;
|
||||||
|
if (!exist)
|
||||||
|
{
|
||||||
|
await s3Client.PutBucketAsync(new PutBucketRequest
|
||||||
|
{
|
||||||
|
BucketName = config["BucketName"]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
builder.Services.AddSingleton<IAmazonS3>(s3Client);
|
||||||
|
|
||||||
// On construit l'application en lui donnant vie
|
// On construit l'application en lui donnant vie
|
||||||
WebApplication app = builder.Build();
|
WebApplication app = builder.Build();
|
||||||
app.UseAuthentication()
|
app.UseAuthentication()
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
<PackageReference Include="Ardalis.Specification.EntityFrameworkCore" Version="9.3.1" />
|
<PackageReference Include="Ardalis.Specification.EntityFrameworkCore" Version="9.3.1" />
|
||||||
<PackageReference Include="AutoMapper" Version="15.0.1" />
|
<PackageReference Include="AutoMapper" Version="15.0.1" />
|
||||||
<PackageReference Include="AutoMapper.Collection" Version="11.0.0" />
|
<PackageReference Include="AutoMapper.Collection" Version="11.0.0" />
|
||||||
|
<PackageReference Include="AWSSDK.S3" Version="4.0.24" />
|
||||||
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
<PackageReference Include="BCrypt.Net-Next" Version="4.0.3" />
|
||||||
<PackageReference Include="FastEndpoints" Version="7.0.1" />
|
<PackageReference Include="FastEndpoints" Version="7.0.1" />
|
||||||
<PackageReference Include="FastEndpoints.Security" Version="7.0.1" />
|
<PackageReference Include="FastEndpoints.Security" Version="7.0.1" />
|
||||||
@@ -33,7 +34,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Folder Include="Migrations\" />
|
<Folder Include="Migrations\" />
|
||||||
<Folder Include="wwwroot\" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
using PyroFetes.Models;
|
||||||
|
|
||||||
|
namespace PyroFetes.Repositories;
|
||||||
|
|
||||||
|
public class CustomersRepository(PyroFetesDbContext pyrofetesContext, AutoMapper.IMapper mapper) : PyrofetesRepository<Customer>(pyrofetesContext, mapper);
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
using PyroFetes.Models;
|
||||||
|
|
||||||
|
namespace PyroFetes.Repositories;
|
||||||
|
|
||||||
|
public class WareHouseRepository(PyroFetesDbContext pyrofetesContext, AutoMapper.IMapper mapper) : PyrofetesRepository<Warehouse>(pyrofetesContext, mapper);
|
||||||
@@ -35,7 +35,8 @@ public class QuotationPdfService : IQuotationPdfService
|
|||||||
col.Item().Text("");
|
col.Item().Text("");
|
||||||
col.Item().Text("");
|
col.Item().Text("");
|
||||||
col.Item().Text("Client").SemiBold().FontSize(12);
|
col.Item().Text("Client").SemiBold().FontSize(12);
|
||||||
col.Item().Text($"{quotation.Customer}");
|
col.Item().Text($"{quotation.Customer?.Note}");
|
||||||
|
col.Item().Text($"{quotation.Customer?.CustomerType?.Label}");
|
||||||
});
|
});
|
||||||
|
|
||||||
// Logo + société à droite
|
// Logo + société à droite
|
||||||
|
|||||||
@@ -0,0 +1,37 @@
|
|||||||
|
using Amazon.S3;
|
||||||
|
using Amazon.S3.Model;
|
||||||
|
|
||||||
|
namespace PyroFetes.Services;
|
||||||
|
|
||||||
|
public class StorageService(IAmazonS3 amazonS3, IConfiguration config)
|
||||||
|
{
|
||||||
|
private readonly string _bucket = config["RustFs:BucketName"]!;
|
||||||
|
private readonly string _url = config["RustFs:ServiceUrl"]!;
|
||||||
|
|
||||||
|
public async Task<string> UploadFile(IFormFile file, string type, CancellationToken ct)
|
||||||
|
{
|
||||||
|
if (file.Length == 0) throw new Exception("Fichier vide");
|
||||||
|
|
||||||
|
string key = $"settings/{type}";
|
||||||
|
|
||||||
|
using MemoryStream memoryStream = new();
|
||||||
|
await file.CopyToAsync(memoryStream, ct);
|
||||||
|
memoryStream.Position = 0;
|
||||||
|
|
||||||
|
PutObjectRequest uploadRequest = new()
|
||||||
|
{
|
||||||
|
BucketName = _bucket,
|
||||||
|
ContentType = file.ContentType,
|
||||||
|
InputStream = memoryStream,
|
||||||
|
Key = key,
|
||||||
|
};
|
||||||
|
|
||||||
|
await amazonS3.PutObjectAsync(uploadRequest, ct);
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string? GetUrl(string key)
|
||||||
|
{
|
||||||
|
return string.IsNullOrEmpty(key) ? null : $"{_url}/{_bucket}/{key}";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ public class GetAllDeliveryNoteSpec : Specification<DeliveryNote>
|
|||||||
.Include(x => x.Deliverer)
|
.Include(x => x.Deliverer)
|
||||||
.Include(x => x.ProductDeliveries)!
|
.Include(x => x.ProductDeliveries)!
|
||||||
.ThenInclude(x => x.Product)
|
.ThenInclude(x => x.Product)
|
||||||
.Where(x => true);
|
.OrderBy(x => x.RealDeliveryDate)
|
||||||
|
.ThenByDescending(x => x.ExpeditionDate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
using Ardalis.Specification;
|
||||||
|
using PyroFetes.Models;
|
||||||
|
|
||||||
|
namespace PyroFetes.Specifications.DeliveryNotes;
|
||||||
|
|
||||||
|
public class GetAllDeliveryNotesByRealDateSpec : Specification<DeliveryNote>
|
||||||
|
{
|
||||||
|
public GetAllDeliveryNotesByRealDateSpec()
|
||||||
|
{
|
||||||
|
Query
|
||||||
|
.Include(x => x.Deliverer)
|
||||||
|
.Include(x => x.ProductDeliveries)!
|
||||||
|
.ThenInclude(x => x.Product)
|
||||||
|
.Where(x => x.RealDeliveryDate == null)
|
||||||
|
.OrderByDescending(x => x.ExpeditionDate);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,8 @@ public sealed class GetProductsUnderLimitSpec : Specification<Product>
|
|||||||
public GetProductsUnderLimitSpec()
|
public GetProductsUnderLimitSpec()
|
||||||
{
|
{
|
||||||
Query
|
Query
|
||||||
.Include(p => p.QuotationProducts)
|
.Include(x => x.WarehouseProducts)
|
||||||
.Where(p => p.QuotationProducts != null && p.QuotationProducts.Any(q => q.Quantity < p.MinimalQuantity));
|
.Where(x => x.WarehouseProducts != null && x.WarehouseProducts.Sum(p => p.Quantity) < x.MinimalQuantity
|
||||||
|
&& !x.ProductDeliveries!.Any(d => d.DeliveryNote!.RealDeliveryDate == null));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using Ardalis.Specification;
|
||||||
|
using PyroFetes.Models;
|
||||||
|
|
||||||
|
namespace PyroFetes.Specifications.PurchaseOrders;
|
||||||
|
|
||||||
|
public class GetAllPurchaseOrderSpec : Specification<PurchaseOrder>
|
||||||
|
{
|
||||||
|
public GetAllPurchaseOrderSpec()
|
||||||
|
{
|
||||||
|
Query
|
||||||
|
.Where(x => true)
|
||||||
|
.OrderByDescending(x => x.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
using Ardalis.Specification;
|
||||||
|
using PyroFetes.Models;
|
||||||
|
|
||||||
|
namespace PyroFetes.Specifications.Quotations;
|
||||||
|
|
||||||
|
public class GetAllQuotationSpec : Specification<Quotation>
|
||||||
|
{
|
||||||
|
public GetAllQuotationSpec()
|
||||||
|
{
|
||||||
|
Query
|
||||||
|
.Where(x => true)
|
||||||
|
.OrderByDescending(x => x.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,8 @@ public class GetQuotationByIdWithProductsSpec : SingleResultSpecification<Quotat
|
|||||||
.Where(x => x.Id == quotationId)
|
.Where(x => x.Id == quotationId)
|
||||||
.Include(x => x.QuotationProducts!)
|
.Include(x => x.QuotationProducts!)
|
||||||
.ThenInclude(x => x.Product)
|
.ThenInclude(x => x.Product)
|
||||||
.ThenInclude(x => x!.Prices);
|
.ThenInclude(x => x!.Prices)
|
||||||
|
.Include(x => x.Customer)
|
||||||
|
.ThenInclude(x => x!.CustomerType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
using Ardalis.Specification;
|
||||||
|
using PyroFetes.Models;
|
||||||
|
|
||||||
|
namespace PyroFetes.Specifications.WareHouse;
|
||||||
|
|
||||||
|
public class GetWareHouseByIdSpec : SingleResultSpecification<Warehouse>
|
||||||
|
{
|
||||||
|
public GetWareHouseByIdSpec(int id)
|
||||||
|
{
|
||||||
|
Query
|
||||||
|
.Where(x => x.Id == id);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
using FastEndpoints;
|
||||||
|
using FluentValidation;
|
||||||
|
using PyroFetes.DTO.User.Request;
|
||||||
|
|
||||||
|
namespace PyroFetes.Validators.Users;
|
||||||
|
|
||||||
|
public class ConnectUserDtoValidator : Validator<ConnectUserDto>
|
||||||
|
{
|
||||||
|
public ConnectUserDtoValidator()
|
||||||
|
{
|
||||||
|
RuleFor(x => x.Name)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage("Username is required")
|
||||||
|
.MaximumLength(50)
|
||||||
|
.WithMessage("Username cannot exceed 50 characters")
|
||||||
|
.MinimumLength(2)
|
||||||
|
.WithMessage("Username must exceed 2 characters");
|
||||||
|
|
||||||
|
RuleFor(x => x.Password)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage("Password is required");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using FastEndpoints;
|
||||||
|
using FluentValidation;
|
||||||
|
using PyroFetes.DTO.User.Request;
|
||||||
|
|
||||||
|
namespace PyroFetes.Validators.Users;
|
||||||
|
|
||||||
|
public class CreateUpdateUserDtoValidator: Validator<UpdateUserDto>
|
||||||
|
{
|
||||||
|
public CreateUpdateUserDtoValidator()
|
||||||
|
{
|
||||||
|
RuleFor(x => x.Email)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage("L'email est requis")
|
||||||
|
.MaximumLength(100)
|
||||||
|
.WithMessage("L'email ne doit pas dépasser plus de 100 caractères")
|
||||||
|
.EmailAddress()
|
||||||
|
.WithMessage("Adresse email invalide");
|
||||||
|
|
||||||
|
RuleFor(x => x.Password)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage("Le mot de passe est requis")
|
||||||
|
.MinimumLength(12)
|
||||||
|
.WithMessage("Le mot de passe doit contenir au minimum 12 caractères")
|
||||||
|
.Matches(@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*?[#?_!@$%^&*-])");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using FastEndpoints;
|
||||||
|
using FluentValidation;
|
||||||
|
using PyroFetes.DTO.User.Request;
|
||||||
|
|
||||||
|
namespace PyroFetes.Validators.Users;
|
||||||
|
|
||||||
|
public class CreateUserDtoValidator : Validator<CreateUserDto>
|
||||||
|
{
|
||||||
|
public CreateUserDtoValidator()
|
||||||
|
{
|
||||||
|
RuleFor(x => x.Email)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage("L'email est requis")
|
||||||
|
.MaximumLength(100)
|
||||||
|
.WithMessage("L'email ne doit pas dépasser plus de 100 caractères")
|
||||||
|
.EmailAddress()
|
||||||
|
.WithMessage("Adresse email invalide");
|
||||||
|
|
||||||
|
RuleFor(x => x.Password)
|
||||||
|
.NotEmpty()
|
||||||
|
.WithMessage("Le mot de passe est requis")
|
||||||
|
.MinimumLength(12)
|
||||||
|
.WithMessage("Le mot de passe doit contenir au minimum 12 caractères")
|
||||||
|
.Matches(@"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*?[#?_!@$%^&*-])");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,5 +4,11 @@
|
|||||||
"Default": "Information",
|
"Default": "Information",
|
||||||
"Microsoft.AspNetCore": "Warning"
|
"Microsoft.AspNetCore": "Warning"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"RustFS": {
|
||||||
|
"ServiceUrl": "https://stockage.sanchezvende.fr",
|
||||||
|
"AccessKey": "Admin_Beready_Exam2026",
|
||||||
|
"SecretKey": "4dm1n-Pr0j_2026-B3r34d7",
|
||||||
|
"BucketName": "images"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,50 +1,79 @@
|
|||||||
# Gestionnaire de Stocks et Commandes
|
# PyroFêtes — Système de gestion des stocks et des documents
|
||||||
|
|
||||||
Cette application web permet de **suivre les stocks**, **automatiser les commandes fournisseurs** et **gérer le cycle complet d’approvisionnement**.
|
> Application web de gestion des stocks, fournisseurs, devis, bons de commande et bons de livraison pour l'entreprise **PyroFêtes**.
|
||||||
Elle est conçue pour simplifier le travail des entreprises en offrant une vue en temps réel sur les produits, leurs fournisseurs et l’état des livraisons.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## ✨ Fonctionnalités principales
|
## Sommaire
|
||||||
|
|
||||||
### 1️⃣ Suivi et réapprovisionnement des stocks
|
- [Contexte](#contexte)
|
||||||
- Définissez un **niveau minimal de stock** pour chaque produit.
|
- [Fonctionnalités](#fonctionnalités)
|
||||||
- Surveillez les **niveaux en temps réel** grâce à une interface claire.
|
- [Stack technique](#stack-technique)
|
||||||
- Lorsqu’un produit atteint ou descend sous son seuil minimal, le système **génère automatiquement un bon de commande** pour le réapprovisionner.
|
- [Équipe](#équipe)
|
||||||
|
|
||||||
### 2️⃣ Gestion des fournisseurs
|
|
||||||
- Enregistrez les informations complètes des fournisseurs : nom, adresse, coordonnées, produits fournis, délais de livraison.
|
|
||||||
- **Associez un ou plusieurs fournisseurs** à chaque produit.
|
|
||||||
- Lorsqu’un bon de commande est créé, le système **propose automatiquement les fournisseurs appropriés**.
|
|
||||||
|
|
||||||
### 3️⃣ Devis et bons de commande
|
## Contexte
|
||||||
- Créez des **devis personnalisés** : sélection des produits, quantités, prix, ajout d’un logo, message ou conditions de vente.
|
|
||||||
- **Imprimez ou exportez** vos devis au format PDF.
|
|
||||||
- Générez des **bons de commande** en quelques clics, avec personnalisation (logo, conditions d’achat) et exportation en PDF.
|
|
||||||
|
|
||||||
### 4️⃣ Suivi des livraisons
|
PyroFêtes cherchait à remplacer ses processus manuels de gestion des stocks et de génération de documents commerciaux par un outil centralisé. Les objectifs principaux sont :
|
||||||
- **Transformez un bon de commande en bon de livraison** dès l’expédition des produits par le fournisseur.
|
|
||||||
- Enregistrez toutes les informations importantes : date d’expédition, transporteur, numéro de suivi, date prévue et date effective de livraison.
|
|
||||||
- Recevez des **alertes en cas de retard**.
|
|
||||||
- Gérez la **réception des produits** et vérifiez leur conformité.
|
|
||||||
|
|
||||||
---
|
- Automatiser le réapprovisionnement
|
||||||
|
- Gérer les fournisseurs et leurs conditions
|
||||||
|
- Éditer et exporter les documents commerciaux (devis, bons de commande, bons de livraison)
|
||||||
|
- Assurer un suivi fiable des livraisons et des réceptions
|
||||||
|
|
||||||
## 🗂️ Livrables prévus
|
|
||||||
- **Modèle de données** : diagramme de classes commun à tous les groupes.
|
|
||||||
- **Interface utilisateur** : maquettes ou prototypes interactifs.
|
|
||||||
- **Code source commenté** pour une meilleure compréhension.
|
|
||||||
- **Documentation technique** : description des fonctionnalités, architecture de l’application et API.
|
|
||||||
|
|
||||||
---
|
## Fonctionnalités
|
||||||
|
|
||||||
## 👥 Équipe
|
### Gestion des stocks
|
||||||
- **Mathys**
|
- Définition de seuils minimaux par produit
|
||||||
- **Enzo**
|
- Visualisation en temps réel du stock courant
|
||||||
- **Cristiano**
|
- Alertes automatiques en cas de stock sous le seuil
|
||||||
- **Arsène**
|
- Génération automatique de bons de commande
|
||||||
|
|
||||||
---
|
### Gestion des fournisseurs
|
||||||
|
- Enregistrement des fournisseurs (nom, adresse, coordonnées, conditions)
|
||||||
|
- Gestion des délais de livraison par produit
|
||||||
|
- Association de plusieurs fournisseurs à un produit (prix + délai)
|
||||||
|
- Suggestion automatique du fournisseur le plus pertinent
|
||||||
|
|
||||||
## 🚀 Objectif
|
### Devis & Bons de commande
|
||||||
Fournir un outil complet pour automatiser la gestion des stocks et des commandes, réduisant les erreurs humaines, améliorant le suivi des livraisons et facilitant la communication avec les fournisseurs.
|
- Création de devis et bons de commande (produits, quantités, prix, remises)
|
||||||
|
- Personnalisation des documents (logo, message, conditions)
|
||||||
|
- Export au format **PDF**
|
||||||
|
|
||||||
|
### Bons de livraison & Réceptions
|
||||||
|
- Transformation d'un bon de commande validé en bon de livraison
|
||||||
|
- Enregistrement des informations de livraison (transporteur, numéro de suivi, dates)
|
||||||
|
- Alertes en cas de retard de livraison
|
||||||
|
- Gestion des réceptions avec mise à jour automatique des stocks
|
||||||
|
|
||||||
|
|
||||||
|
## Stack technique
|
||||||
|
|
||||||
|
| Couche | Technologie |
|
||||||
|
|---|---|
|
||||||
|
| **Front-end** | Angular + NG-ZORRO + Tailwind CSS |
|
||||||
|
| **Back-end** | C# / .NET |
|
||||||
|
| **API** | REST (C#) |
|
||||||
|
| **Base de données** | SQL Server |
|
||||||
|
| **Gestion des tâches** | YouTrack |
|
||||||
|
| **Versioning** | Gitea |
|
||||||
|
| **Communication** | Discord + Présentiel |
|
||||||
|
|
||||||
|
|
||||||
|
## Équipe
|
||||||
|
|
||||||
|
| Membre | Rôle |
|
||||||
|
|---|---|
|
||||||
|
| Mathys Sanchez-Vendé | Développeur |
|
||||||
|
| Enzo Norguet | Développeur |
|
||||||
|
| Cristiano Henrique Gaspar | Développeur |
|
||||||
|
| Arsène | Développeur |
|
||||||
|
|
||||||
|
**Clients :** Mr Thibault Ferrand, Mr Douguet
|
||||||
|
|
||||||
|
|
||||||
|
## Sécurité
|
||||||
|
|
||||||
|
- Authentification sécurisée
|
||||||
|
- Gestion des accès et des permissions par rôle (Commercial / Administrateur)
|
||||||
|
- Protection des données utilisateurs
|
||||||
|
|||||||
Reference in New Issue
Block a user