From 656100d15e1583800a000732f73e5742361bdf79 Mon Sep 17 00:00:00 2001 From: sanchezvem Date: Sun, 24 May 2026 17:22:03 +0100 Subject: [PATCH] Refactor all code --- .../Request/CreateDeliveryNoteDto.cs | 6 +- PyroFetes/DTO/Price/Request/CreatePriceDto.cs | 21 +- PyroFetes/DTO/Price/Request/UpdatePriceDto.cs | 28 - PyroFetes/DTO/Price/Response/GetPriceDto.cs | 10 - .../DTO/Product/Request/CreateProductDto.cs | 15 - .../Request/CreateProductDeliveryDto.cs | 8 - .../Request/UpdateProductDeliveryDto.cs | 8 - .../Response/GetProductDeliveryDto.cs | 10 - .../Response/GetPurchaseOrderDto.cs | 1 + .../Request/CreatePurchaseProductDto.cs | 1 - .../Request/UpdatePurchaseProductDto.cs | 22 - .../Response/GetPurchaseProductDto.cs | 5 +- .../Request/CreateProductQuotationDto.cs | 1 - .../Request/CreateQuotationProductDto.cs | 16 +- .../Request/UpdateQuotationProductDto.cs | 23 - .../Response/GetQuotationProductDto.cs | 6 +- .../SettingDTO/Request/CreateSettingDto.cs | 4 +- .../PatchSettingElectronicSignatureDto.cs | 2 +- .../SettingDTO/Request/PatchSettingLogoDto.cs | 2 +- .../DTO/Supplier/Response/GetSupplierDto.cs | 2 - .../Deliverers/CreateDelivererEndpoint.cs | 11 +- .../Deliverers/DeleteDelivererEndpoint.cs | 14 +- .../Deliverers/GetAllDelivererEndpoint.cs | 4 - .../Deliverers/GetDelivererEndpoint.cs | 13 +- .../Deliverers/UpdateDelivererEndpoint.cs | 22 +- .../CreateDeliveryNoteEndpoint.cs | 40 +- .../DeleteDeliveryNoteEndpoint.cs | 11 +- .../GetAllDeliveryNoteEndpoint.cs | 4 +- .../DeliveryNotes/GetDeliveryNoteEndpoint.cs | 9 +- .../GetDeliveryNotePdfEndpoint.cs | 22 +- .../PatchRealDeliveryDateEndpoint.cs | 28 +- .../UpdateDeliveryNoteEndpoint.cs | 28 +- .../Endpoints/Prices/CreatePriceEndpoint.cs | 84 - .../Products/DeleteProductEndpoint.cs | 14 +- .../Products/GetAllProductsEndpoint.cs | 2 - .../GetAllProductsUnderLimitEndpoint.cs | 3 +- .../Endpoints/Products/GetProductEndpoint.cs | 9 +- .../PatchProductMinimalStockEndpoint.cs | 18 +- .../Products/UpdateProductEndpoint.cs | 30 +- .../AddProductFromPurchaseOrderEndpoint.cs | 32 + .../PurchaseOrders/CreatePurchaseOrder.cs | 48 +- ...DeleteProductFromPurchaseOrderEndpoint.cs} | 16 +- .../DeletePurchaseOrderEndpoint.cs | 19 +- .../GetAllPurchaseOrderEndpoint.cs | 2 - .../GetPurchaseOrderEndpoint.cs | 14 +- .../GetPurchaseOrderPdfEndpoint.cs | 21 +- ...PurchaseOrderPurchaseConditionsEndpoint.cs | 19 +- .../PatchPurchaseProductQuantityEndpoint.cs | 35 + .../CreatePurchaseProductEndpoint.cs | 56 - .../PatchPurchaseProductQuantityEndpoint.cs | 38 - .../CreateQuotationProductEndpoint.cs | 58 - .../AddProductoToQuotationEndpoint.cs | 35 + .../Quotations/CreateQuotationEndpoint.cs | 50 +- .../DeleteProductFromQuotationEndpoint.cs} | 15 +- .../Quotations/DeleteQuotationEndpoint.cs | 19 +- .../Quotations/GetAllQuotationEndpoint.cs | 3 - .../Quotations/GetQuotationEndpoint.cs | 10 +- .../Quotations/GetQuotationPdfEndpoint.cs | 18 +- .../PatchQuotationConditionsSaleEndpoint.cs | 15 +- .../PatchQuotationMessageEndpoint.cs | 35 + .../PatchQuotationProductQuantityEndpoint.cs | 20 +- .../Quotations/UpdateQuotationEndpoint.cs | 17 +- .../Settings/CreateSettingEndpoint.cs | 28 +- .../Settings/DeleteSettingEndpoint.cs | 12 +- .../Endpoints/Settings/GetSettingEndpoint.cs | 9 +- ...PatchSettingElectronicSignatureEndpoint.cs | 29 +- .../Settings/PatchSettingLogoEndpoint.cs | 25 +- .../Suppliers/AddProductToSupplierEndpoint.cs | 43 + .../Suppliers/CreateSupplierEndpoint.cs | 21 +- .../DeleteProductToSupplierEndpoint.cs} | 16 +- .../Suppliers/DeleteSupplierEndpoint.cs | 14 +- .../Suppliers/GetAllSuppliersEndpoint.cs | 1 - .../Suppliers/GetSupplierEndpoint.cs | 13 +- .../PatchPriceEndpoint.cs | 20 +- .../PatchSupplierDeliveryDelayEndpoint.cs | 17 +- .../Suppliers/UpdateSupplierEndpoint.cs | 26 +- .../Endpoints/Users/ConnectUserEndpoint.cs | 25 +- .../Endpoints/Users/CreateUserEndpoint.cs | 23 +- .../Endpoints/Users/DeleteUserEndpoint.cs | 10 +- .../Endpoints/Users/GetAllUsersEndpoint.cs | 1 - PyroFetes/Endpoints/Users/GetUserEndpoint.cs | 13 +- .../Users/PatchUserPasswordEndpoint.cs | 15 +- .../Endpoints/Users/UpdateUserEndpoint.cs | 27 +- .../GetTotalQuantityEndpoint.cs | 15 +- .../PatchWareHouseProductQuantityEndpoint.cs | 26 +- .../MappingProfiles/DtoToEntityMappings.cs | 68 +- .../MappingProfiles/EntityToDtoMappings.cs | 41 +- ...60524095820_ChangeDatabaseName.Designer.cs | 1983 +++++++++++++++++ .../20260524095820_ChangeDatabaseName.cs | 22 + PyroFetes/Program.cs | 2 +- PyroFetes/PyroFetes.csproj | 10 +- PyroFetes/PyroFetesDbContext.cs | 10 +- .../Services/Pdf/DeliveryNotePdfService.cs | 16 +- .../Services/Pdf/PurchaseOrderPdfService.cs | 16 +- PyroFetes/Services/Pdf/QuotationPdfService.cs | 17 +- .../Deliverers/GetDelivererByIdSpec.cs | 2 +- .../DeliveryNotes/GetAllDeliveryNoteSpec.cs | 16 + .../DeliveryNotes/GetDeliveryNoteByIdSpec.cs | 5 +- .../GetDeliveryNoteByIdWithProductsSpec.cs | 8 +- .../GetPriceByProductIdAndSupplierIdSpec.cs | 4 +- .../Products/GetProductByIdSpec.cs | 4 +- .../Products/GetProductsUnderLimitSpec.cs | 2 +- .../GetPurchaseOrderByIdSpec.cs | 7 +- .../GetPurchaseOrderByIdWithProductsSpec.cs | 10 +- ...roductByProductIdAndPurchaseOrderIdSpec.cs | 2 +- ...ionProductByProductIdAndQuotationIdSpec.cs | 2 +- .../Quotations/GetQuotationByIdSpec.cs | 5 +- .../GetQuotationByIdWithProductsSpec.cs | 8 +- .../Settings/GetSettingByIdSpec.cs | 2 +- .../Suppliers/GetSupplierByIdSpec.cs | 4 +- .../Specifications/Users/GetUserByIdSpec.cs | 2 +- .../Specifications/Users/GetUserByNameSpec.cs | 2 +- .../GetWarehouseProductByProductIdSpec.cs | 9 +- PyroFetes/data.sql | 986 ++++---- PyroFetes/docker-compose.yml | 33 - PyroFetes/wwwroot/Images/logo.jpg | Bin 47397 -> 0 bytes PyroFetes/wwwroot/Images/signature.png | Bin 10292 -> 0 bytes 117 files changed, 3317 insertions(+), 1562 deletions(-) delete mode 100644 PyroFetes/DTO/Price/Request/UpdatePriceDto.cs delete mode 100644 PyroFetes/DTO/Product/Request/CreateProductDto.cs delete mode 100644 PyroFetes/DTO/ProductDelivery/Request/CreateProductDeliveryDto.cs delete mode 100644 PyroFetes/DTO/ProductDelivery/Request/UpdateProductDeliveryDto.cs delete mode 100644 PyroFetes/DTO/PurchaseProduct/Request/UpdatePurchaseProductDto.cs delete mode 100644 PyroFetes/DTO/QuotationProduct/Request/UpdateQuotationProductDto.cs delete mode 100644 PyroFetes/Endpoints/Prices/CreatePriceEndpoint.cs create mode 100644 PyroFetes/Endpoints/PurchaseOrders/AddProductFromPurchaseOrderEndpoint.cs rename PyroFetes/Endpoints/{PurchaseProducts/DeletePurchaseProductEndpoint.cs => PurchaseOrders/DeleteProductFromPurchaseOrderEndpoint.cs} (51%) create mode 100644 PyroFetes/Endpoints/PurchaseOrders/PatchPurchaseProductQuantityEndpoint.cs delete mode 100644 PyroFetes/Endpoints/PurchaseProducts/CreatePurchaseProductEndpoint.cs delete mode 100644 PyroFetes/Endpoints/PurchaseProducts/PatchPurchaseProductQuantityEndpoint.cs delete mode 100644 PyroFetes/Endpoints/QuotationProducts/CreateQuotationProductEndpoint.cs create mode 100644 PyroFetes/Endpoints/Quotations/AddProductoToQuotationEndpoint.cs rename PyroFetes/Endpoints/{QuotationProducts/DeleteQuotationProductEndpoint.cs => Quotations/DeleteProductFromQuotationEndpoint.cs} (55%) create mode 100644 PyroFetes/Endpoints/Quotations/PatchQuotationMessageEndpoint.cs rename PyroFetes/Endpoints/{QuotationProducts => Quotations}/PatchQuotationProductQuantityEndpoint.cs (52%) create mode 100644 PyroFetes/Endpoints/Suppliers/AddProductToSupplierEndpoint.cs rename PyroFetes/Endpoints/{Prices/DeletePriceEndpoint.cs => Suppliers/DeleteProductToSupplierEndpoint.cs} (51%) rename PyroFetes/Endpoints/{Prices => Suppliers}/PatchPriceEndpoint.cs (59%) create mode 100644 PyroFetes/Migrations/20260524095820_ChangeDatabaseName.Designer.cs create mode 100644 PyroFetes/Migrations/20260524095820_ChangeDatabaseName.cs create mode 100644 PyroFetes/Specifications/DeliveryNotes/GetAllDeliveryNoteSpec.cs delete mode 100644 PyroFetes/docker-compose.yml delete mode 100644 PyroFetes/wwwroot/Images/logo.jpg delete mode 100644 PyroFetes/wwwroot/Images/signature.png diff --git a/PyroFetes/DTO/DeliveryNote/Request/CreateDeliveryNoteDto.cs b/PyroFetes/DTO/DeliveryNote/Request/CreateDeliveryNoteDto.cs index c2ee0d9d..b486e161 100644 --- a/PyroFetes/DTO/DeliveryNote/Request/CreateDeliveryNoteDto.cs +++ b/PyroFetes/DTO/DeliveryNote/Request/CreateDeliveryNoteDto.cs @@ -5,8 +5,8 @@ public class CreateDeliveryNoteDto public string? TrackingNumber { get; set; } public DateOnly EstimateDeliveryDate { get; set; } public DateOnly ExpeditionDate { get; set; } - + public int DelivererId { get; set; } - - public Dictionary? ProductQuantities { get; set; } + + public Dictionary? ProductQuantities { get; set; } } \ No newline at end of file diff --git a/PyroFetes/DTO/Price/Request/CreatePriceDto.cs b/PyroFetes/DTO/Price/Request/CreatePriceDto.cs index 26e52e75..c465649f 100644 --- a/PyroFetes/DTO/Price/Request/CreatePriceDto.cs +++ b/PyroFetes/DTO/Price/Request/CreatePriceDto.cs @@ -3,25 +3,6 @@ public class CreatePriceDto { public decimal SellingPrice { get; set; } - public int? SupplierId { get; set; } - public string? SupplierName { get; set; } - public string? SupplierEmail { get; set; } - public string? SupplierPhone { get; set; } - public string? SupplierAddress { get; set; } - public string? SupplierZipCode { get; set; } - public string? SupplierCity { get; set; } - public int SupplierDeliveryDelay { get; set; } - - public int? ProductId { get; set; } - public string? ProductReferences { get; set; } - public string? ProductName { get; set; } - public decimal ProductDuration {get; set;} - public int ProductCaliber { get; set; } - public string? ProductApprovalNumber { get; set; } - public decimal ProductWeight { get; set; } - public decimal ProductNec { get; set; } - public string? ProductImage { get; set; } - public string? ProductLink { get; set; } - public int ProductMinimalQuantity { get; set; } + public int ProductId { get; set; } } \ No newline at end of file diff --git a/PyroFetes/DTO/Price/Request/UpdatePriceDto.cs b/PyroFetes/DTO/Price/Request/UpdatePriceDto.cs deleted file mode 100644 index 1eac8278..00000000 --- a/PyroFetes/DTO/Price/Request/UpdatePriceDto.cs +++ /dev/null @@ -1,28 +0,0 @@ -namespace PyroFetes.DTO.Price.Request; - -public class UpdatePriceDto -{ - public int Id { get; set; } - public decimal SellingPrice { get; set; } - - public int SupplierId { get; set; } - public string? SupplierName { get; set; } - public string? SupplierEmail { get; set; } - public string? SupplierPhone { get; set; } - public string? SupplierAddress { get; set; } - public int SupplierZipCode { get; set; } - public string? SupplierCity { get; set; } - public int SupplierDeliveryDelay { get; set; } - - public int ProductId { get; set; } - public string? ProductReferences { get; set; } - public string? ProductName { get; set; } - public decimal ProductDuration {get; set;} - public decimal ProductCaliber { get; set; } - public int ProductApprovalNumber { get; set; } - public decimal ProductWeight { get; set; } - public decimal ProductNec { get; set; } - public string? ProductImage { get; set; } - public string? ProductLink { get; set; } - public int ProductMinimalQuantity { get; set; } -} \ No newline at end of file diff --git a/PyroFetes/DTO/Price/Response/GetPriceDto.cs b/PyroFetes/DTO/Price/Response/GetPriceDto.cs index 32ae0923..6657f2fb 100644 --- a/PyroFetes/DTO/Price/Response/GetPriceDto.cs +++ b/PyroFetes/DTO/Price/Response/GetPriceDto.cs @@ -2,18 +2,8 @@ public class GetPriceDto { - public int Id { get; set; } public decimal SellingPrice { get; set; } - public int SupplierId { get; set; } - public string? SupplierName { get; set; } - public string? SupplierEmail { get; set; } - public string? SupplierPhone { get; set; } - public string? SupplierAddress { get; set; } - public string? SupplierZipCode { get; set; } - public string? SupplierCity { get; set; } - public int SupplierDeliveryDelay { get; set; } - public int ProductId { get; set; } public string? ProductReference { get; set; } public string? ProductName { get; set; } diff --git a/PyroFetes/DTO/Product/Request/CreateProductDto.cs b/PyroFetes/DTO/Product/Request/CreateProductDto.cs deleted file mode 100644 index ddc689c3..00000000 --- a/PyroFetes/DTO/Product/Request/CreateProductDto.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace PyroFetes.DTO.Product.Request; - -public class CreateProductDto -{ - public string? References { get; set; } - public string? Name { get; set; } - public decimal Duration {get; set;} - public int Caliber { get; set; } - public string? ApprovalNumber { get; set; } - public decimal Weight { get; set; } - public decimal Nec { get; set; } - public string? Image { get; set; } - public string? Link { get; set; } - public int MinimalQuantity { get; set; } -} \ No newline at end of file diff --git a/PyroFetes/DTO/ProductDelivery/Request/CreateProductDeliveryDto.cs b/PyroFetes/DTO/ProductDelivery/Request/CreateProductDeliveryDto.cs deleted file mode 100644 index d993ad35..00000000 --- a/PyroFetes/DTO/ProductDelivery/Request/CreateProductDeliveryDto.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace PyroFetes.DTO.ProductDelivery.Request; - -public class CreateProductDeliveryDto -{ - public int ProductId { get; set; } - public int DeliveryNoteId { get; set; } - public int Quantity { get; set; } -} \ No newline at end of file diff --git a/PyroFetes/DTO/ProductDelivery/Request/UpdateProductDeliveryDto.cs b/PyroFetes/DTO/ProductDelivery/Request/UpdateProductDeliveryDto.cs deleted file mode 100644 index 7a6bb71d..00000000 --- a/PyroFetes/DTO/ProductDelivery/Request/UpdateProductDeliveryDto.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace PyroFetes.DTO.ProductDelivery.Request; - -public class UpdateProductDeliveryDto -{ - public int Quantity { get; set; } - public int ProductId { get; set; } - public int DeliveryNoteId { get; set; } -} \ No newline at end of file diff --git a/PyroFetes/DTO/ProductDelivery/Response/GetProductDeliveryDto.cs b/PyroFetes/DTO/ProductDelivery/Response/GetProductDeliveryDto.cs index 9fdbe043..92c78cfc 100644 --- a/PyroFetes/DTO/ProductDelivery/Response/GetProductDeliveryDto.cs +++ b/PyroFetes/DTO/ProductDelivery/Response/GetProductDeliveryDto.cs @@ -14,15 +14,5 @@ public class GetProductDeliveryDto public string? ProductLink { get; set; } public int ProductMinimalQuantity { get; set; } - public int DeliveryNoteId { get; set; } - public string? DeliveryNoteTrackingNumber { get; set; } - public DateOnly DeliveryNoteEstimateDeliveryDate { get; set; } - public DateOnly DeliveryNoteExpeditionDate { get; set; } - public DateOnly? DeliveryNoteRealDeliveryDate { get; set; } - - public int DeliveryNoteDeliverId { get; set; } - public string? DeliveryNoteDeliverTransporter { get; set; } - - public int Quantity { get; set; } } \ No newline at end of file diff --git a/PyroFetes/DTO/PurchaseOrder/Response/GetPurchaseOrderDto.cs b/PyroFetes/DTO/PurchaseOrder/Response/GetPurchaseOrderDto.cs index 20dbe4e6..f2d626ac 100644 --- a/PyroFetes/DTO/PurchaseOrder/Response/GetPurchaseOrderDto.cs +++ b/PyroFetes/DTO/PurchaseOrder/Response/GetPurchaseOrderDto.cs @@ -6,5 +6,6 @@ public class GetPurchaseOrderDto { public int Id { get; set; } public string? PurchaseConditions { get; set; } + public int SupplierId { get; set; } public List? Products { get; set; } } \ No newline at end of file diff --git a/PyroFetes/DTO/PurchaseProduct/Request/CreatePurchaseProductDto.cs b/PyroFetes/DTO/PurchaseProduct/Request/CreatePurchaseProductDto.cs index 1249b419..f23dfb0b 100644 --- a/PyroFetes/DTO/PurchaseProduct/Request/CreatePurchaseProductDto.cs +++ b/PyroFetes/DTO/PurchaseProduct/Request/CreatePurchaseProductDto.cs @@ -5,5 +5,4 @@ public class CreatePurchaseProductDto public int Quantity { get; set; } public int ProductId { get; set; } public int PurchaseOrderId { get; set; } - public string? PurchaseOrderPurchaseConditions { get; set; } } \ No newline at end of file diff --git a/PyroFetes/DTO/PurchaseProduct/Request/UpdatePurchaseProductDto.cs b/PyroFetes/DTO/PurchaseProduct/Request/UpdatePurchaseProductDto.cs deleted file mode 100644 index 8a718cbb..00000000 --- a/PyroFetes/DTO/PurchaseProduct/Request/UpdatePurchaseProductDto.cs +++ /dev/null @@ -1,22 +0,0 @@ -namespace PyroFetes.DTO.PurchaseProduct.Request; - -public class UpdatePurchaseProductDto -{ - public int ProductId { get; set; } - public int PurchaseOrderId { get; set; } - - public int Quantity { get; set; } - - public string? ProductReferences { get; set; } - public string? ProductName { get; set; } - public decimal ProductDuration {get; set;} - public int ProductCaliber { get; set; } - public string? ProductApprovalNumber { get; set; } - public decimal ProductWeight { get; set; } - public decimal ProductNec { get; set; } - public string? ProductImage { get; set; } - public string? ProductLink { get; set; } - public int ProductMinimalQuantity { get; set; } - - public string? PurchaseOrderPurchaseConditions { get; set; } -} \ No newline at end of file diff --git a/PyroFetes/DTO/PurchaseProduct/Response/GetPurchaseProductDto.cs b/PyroFetes/DTO/PurchaseProduct/Response/GetPurchaseProductDto.cs index cdfc15e6..e3233952 100644 --- a/PyroFetes/DTO/PurchaseProduct/Response/GetPurchaseProductDto.cs +++ b/PyroFetes/DTO/PurchaseProduct/Response/GetPurchaseProductDto.cs @@ -3,7 +3,7 @@ namespace PyroFetes.DTO.PurchaseProduct.Response; public class GetPurchaseProductDto { public int ProductId { get; set; } - public string? ProductReferences { get; set; } + public string? ProductReference { get; set; } public string? ProductName { get; set; } public decimal ProductDuration {get; set;} public int ProductCaliber { get; set; } @@ -15,8 +15,5 @@ public class GetPurchaseProductDto public int ProductMinimalQuantity { get; set; } public decimal ProductPrice { get; set; } - public int PurchaseOrderId { get; set; } - public string? PurchaseOrderPurchaseConditions { get; set; } - public int Quantity { get; set; } } \ No newline at end of file diff --git a/PyroFetes/DTO/QuotationProduct/Request/CreateProductQuotationDto.cs b/PyroFetes/DTO/QuotationProduct/Request/CreateProductQuotationDto.cs index 51b0771a..43bcca75 100644 --- a/PyroFetes/DTO/QuotationProduct/Request/CreateProductQuotationDto.cs +++ b/PyroFetes/DTO/QuotationProduct/Request/CreateProductQuotationDto.cs @@ -1,6 +1,5 @@ namespace PyroFetes.DTO.QuotationProduct.Request; -// Pour création global public class CreateProductQuotationDto { public int ProductId { get; set; } diff --git a/PyroFetes/DTO/QuotationProduct/Request/CreateQuotationProductDto.cs b/PyroFetes/DTO/QuotationProduct/Request/CreateQuotationProductDto.cs index a4e1e5aa..c7abdcf4 100644 --- a/PyroFetes/DTO/QuotationProduct/Request/CreateQuotationProductDto.cs +++ b/PyroFetes/DTO/QuotationProduct/Request/CreateQuotationProductDto.cs @@ -1,22 +1,8 @@ namespace PyroFetes.DTO.QuotationProduct.Request; -public class CreateQuotationProductDto +public class AddQuotationProductDto { public int Quantity { get; set; } - public int QuotationId { get; set; } - public string? QuotationMessage { get; set; } - public string? QuotationConditionsSale { get; set; } - public int ProductId { get; set; } - public int ProductReferences { get; set; } - public string? ProductName { get; set; } - public decimal ProductDuration {get; set;} - public int ProductCaliber { get; set; } - public string? ProductApprovalNumber { get; set; } - public decimal ProductWeight { get; set; } - public decimal ProductNec { get; set; } - public string? ProductImage { get; set; } - public string? ProductLink { get; set; } - public int ProductMinimalQuantity { get; set; } } \ No newline at end of file diff --git a/PyroFetes/DTO/QuotationProduct/Request/UpdateQuotationProductDto.cs b/PyroFetes/DTO/QuotationProduct/Request/UpdateQuotationProductDto.cs deleted file mode 100644 index a726136f..00000000 --- a/PyroFetes/DTO/QuotationProduct/Request/UpdateQuotationProductDto.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace PyroFetes.DTO.QuotationProduct.Request; - -public class UpdateQuotationProductDto -{ - public int Id { get; set; } - public int Quantity { get; set; } - - public int QuotationId { get; set; } - public string? QuotationMessage { get; set; } - public string? QuotationConditionsSale { get; set; } - - public int ProductId { get; set; } - public int ProductReferences { get; set; } - public string? ProductName { get; set; } - public decimal ProductDuration {get; set;} - public int ProductCaliber { get; set; } - public string? ProductApprovalNumber { get; set; } - public decimal ProductWeight { get; set; } - public decimal ProductNec { get; set; } - public string? ProductImage { get; set; } - public string? ProductLink { get; set; } - public int ProductMinimalQuantity { get; set; } -} \ No newline at end of file diff --git a/PyroFetes/DTO/QuotationProduct/Response/GetQuotationProductDto.cs b/PyroFetes/DTO/QuotationProduct/Response/GetQuotationProductDto.cs index 86643f91..087e844e 100644 --- a/PyroFetes/DTO/QuotationProduct/Response/GetQuotationProductDto.cs +++ b/PyroFetes/DTO/QuotationProduct/Response/GetQuotationProductDto.cs @@ -4,12 +4,8 @@ public class GetQuotationProductDto { public int Quantity { get; set; } - public int QuotationId { get; set; } - public string? QuotationMessage { get; set; } - public string? QuotationConditionsSale { get; set; } - public int ProductId { get; set; } - public string? ProductReferences { get; set; } + public string? ProductReference { get; set; } public string? ProductName { get; set; } public decimal ProductDuration {get; set;} public int ProductCaliber { get; set; } diff --git a/PyroFetes/DTO/SettingDTO/Request/CreateSettingDto.cs b/PyroFetes/DTO/SettingDTO/Request/CreateSettingDto.cs index 56146d3d..35abce90 100644 --- a/PyroFetes/DTO/SettingDTO/Request/CreateSettingDto.cs +++ b/PyroFetes/DTO/SettingDTO/Request/CreateSettingDto.cs @@ -2,6 +2,6 @@ namespace PyroFetes.DTO.SettingDTO.Request; public class CreateSettingDto { - public string? ElectronicSignature { get; set; } - public string? Logo { get; set; } + public IFormFile? ElectronicSignature { get; set; } + public IFormFile? Logo { get; set; } } \ No newline at end of file diff --git a/PyroFetes/DTO/SettingDTO/Request/PatchSettingElectronicSignatureDto.cs b/PyroFetes/DTO/SettingDTO/Request/PatchSettingElectronicSignatureDto.cs index 44e567e1..22406281 100644 --- a/PyroFetes/DTO/SettingDTO/Request/PatchSettingElectronicSignatureDto.cs +++ b/PyroFetes/DTO/SettingDTO/Request/PatchSettingElectronicSignatureDto.cs @@ -3,5 +3,5 @@ namespace PyroFetes.DTO.SettingDTO.Request; public class PatchSettingElectronicSignatureDto { public int Id { get; set; } - public string? ElectronicSignature { get; set; } + public IFormFile? ElectronicSignature { get; set; } } \ No newline at end of file diff --git a/PyroFetes/DTO/SettingDTO/Request/PatchSettingLogoDto.cs b/PyroFetes/DTO/SettingDTO/Request/PatchSettingLogoDto.cs index 58a952e6..24963df8 100644 --- a/PyroFetes/DTO/SettingDTO/Request/PatchSettingLogoDto.cs +++ b/PyroFetes/DTO/SettingDTO/Request/PatchSettingLogoDto.cs @@ -3,5 +3,5 @@ namespace PyroFetes.DTO.SettingDTO.Request; public class PatchSettingLogoDto { public int Id { get; set; } - public string? Logo { get; set; } + public IFormFile? Logo { get; set; } } \ No newline at end of file diff --git a/PyroFetes/DTO/Supplier/Response/GetSupplierDto.cs b/PyroFetes/DTO/Supplier/Response/GetSupplierDto.cs index 2edbe935..bea9b70f 100644 --- a/PyroFetes/DTO/Supplier/Response/GetSupplierDto.cs +++ b/PyroFetes/DTO/Supplier/Response/GetSupplierDto.cs @@ -1,5 +1,4 @@ using PyroFetes.DTO.Price.Response; -using PyroFetes.DTO.Product.Response; namespace PyroFetes.DTO.Supplier.Response; @@ -13,6 +12,5 @@ public class GetSupplierDto public string? ZipCode { get; set; } public string? City { get; set; } public int DeliveryDelay { get; set; } - public List? Products { get; set; } public List? Prices { get; set; } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Deliverers/CreateDelivererEndpoint.cs b/PyroFetes/Endpoints/Deliverers/CreateDelivererEndpoint.cs index 4eabfa5c..f5310452 100644 --- a/PyroFetes/Endpoints/Deliverers/CreateDelivererEndpoint.cs +++ b/PyroFetes/Endpoints/Deliverers/CreateDelivererEndpoint.cs @@ -6,9 +6,7 @@ using PyroFetes.Repositories; namespace PyroFetes.Endpoints.Deliverers; -public class CreateDelivererEndpoint( - DeliverersRepository deliverersRepository, - AutoMapper.IMapper mapper) : Endpoint +public class CreateDelivererEndpoint(DeliverersRepository deliverersRepository) : Endpoint { public override void Configure() { @@ -18,13 +16,12 @@ public class CreateDelivererEndpoint( public override async Task HandleAsync(CreateDelivererDto req, CancellationToken ct) { - Deliverer newDeliverer = new Deliverer() + Deliverer newDeliverer = new() { Transporter = req.Transporter, }; await deliverersRepository.AddAsync(newDeliverer, ct); - - await Send.OkAsync(mapper.Map(newDeliverer), ct); + await Send.NoContentAsync(ct); } -} +} \ No newline at end of file diff --git a/PyroFetes/Endpoints/Deliverers/DeleteDelivererEndpoint.cs b/PyroFetes/Endpoints/Deliverers/DeleteDelivererEndpoint.cs index a2981fe9..31ee0920 100644 --- a/PyroFetes/Endpoints/Deliverers/DeleteDelivererEndpoint.cs +++ b/PyroFetes/Endpoints/Deliverers/DeleteDelivererEndpoint.cs @@ -9,28 +9,26 @@ public class DeleteDelivererRequest { public int DelivererId { get; set; } } + public class DeleteDelivererEndpoint(DeliverersRepository deliverersRepository) : Endpoint { public override void Configure() { - Delete("/deliverers/{@id}", x=>new {x.DelivererId}); + Delete("/deliverers/{@Id}", x => new { x.DelivererId }); AllowAnonymous(); - } public override async Task HandleAsync(DeleteDelivererRequest req, CancellationToken ct) { - Deliverer? deliverer = await deliverersRepository.FirstOrDefaultAsync(new GetDelivererByIdSpec(req.DelivererId), ct); + Deliverer? deliverer = await deliverersRepository.SingleOrDefaultAsync(new GetDelivererByIdSpec(req.DelivererId), ct); - if (deliverer == null) + if (deliverer is null) { await Send.NotFoundAsync(ct); return; } - + await deliverersRepository.DeleteAsync(deliverer, ct); - - await Send.OkAsync(ct); + await Send.NoContentAsync(ct); } - } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Deliverers/GetAllDelivererEndpoint.cs b/PyroFetes/Endpoints/Deliverers/GetAllDelivererEndpoint.cs index 5710628f..b30d02fc 100644 --- a/PyroFetes/Endpoints/Deliverers/GetAllDelivererEndpoint.cs +++ b/PyroFetes/Endpoints/Deliverers/GetAllDelivererEndpoint.cs @@ -1,6 +1,4 @@ -using AutoMapper.QueryableExtensions; using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.Deliverer.Response; using PyroFetes.Repositories; @@ -12,12 +10,10 @@ public class GetAllDelivererEndpoint(DeliverersRepository deliverersRepository) { Get("/deliverers"); AllowAnonymous(); - } public override async Task HandleAsync(CancellationToken ct) { await Send.OkAsync(await deliverersRepository.ProjectToListAsync(ct), ct); } - } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Deliverers/GetDelivererEndpoint.cs b/PyroFetes/Endpoints/Deliverers/GetDelivererEndpoint.cs index 22a027f4..640d0c29 100644 --- a/PyroFetes/Endpoints/Deliverers/GetDelivererEndpoint.cs +++ b/PyroFetes/Endpoints/Deliverers/GetDelivererEndpoint.cs @@ -1,5 +1,4 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.Deliverer.Response; using PyroFetes.Models; using PyroFetes.Repositories; @@ -12,22 +11,19 @@ public class GetDelivererRequest public int DelivererId { get; set; } } -public class GetDelivererEndpoint( - DeliverersRepository deliverersRepository, - AutoMapper.IMapper mapper) : Endpoint +public class GetDelivererEndpoint(DeliverersRepository deliverersRepository, AutoMapper.IMapper mapper) : Endpoint { public override void Configure() { - Get("/deliverers/{@id}", x=>new {x.DelivererId}); + Get("/deliverers/{@Id}", x => new { x.DelivererId }); AllowAnonymous(); - } public override async Task HandleAsync(GetDelivererRequest req, CancellationToken ct) { - Deliverer? deliverer = await deliverersRepository.FirstOrDefaultAsync(new GetDelivererByIdSpec(req.DelivererId), ct); + Deliverer? deliverer = await deliverersRepository.SingleOrDefaultAsync(new GetDelivererByIdSpec(req.DelivererId), ct); - if (deliverer == null) + if (deliverer is null) { await Send.NotFoundAsync(ct); return; @@ -35,5 +31,4 @@ public class GetDelivererEndpoint( await Send.OkAsync(mapper.Map(deliverer), ct); } - } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Deliverers/UpdateDelivererEndpoint.cs b/PyroFetes/Endpoints/Deliverers/UpdateDelivererEndpoint.cs index ebf153ef..a9b38f52 100644 --- a/PyroFetes/Endpoints/Deliverers/UpdateDelivererEndpoint.cs +++ b/PyroFetes/Endpoints/Deliverers/UpdateDelivererEndpoint.cs @@ -1,5 +1,4 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.Deliverer.Request; using PyroFetes.DTO.Deliverer.Response; using PyroFetes.Models; @@ -8,32 +7,27 @@ using PyroFetes.Specifications.Deliverers; namespace PyroFetes.Endpoints.Deliverers; -public class UpdateDelivererEndpoint( - DeliverersRepository deliverersRepository, - AutoMapper.IMapper mapper) : Endpoint +public class UpdateDelivererEndpoint(DeliverersRepository deliverersRepository, AutoMapper.IMapper mapper) : Endpoint { public override void Configure() { - Put("/deliverers/{@id}", x=>new {x.Id}); + Put("/deliverers/{@Id}", x => new { x.Id }); AllowAnonymous(); - } public override async Task HandleAsync(UpdateDelivererDto req, CancellationToken ct) { - Deliverer? deliverer = await deliverersRepository.FirstOrDefaultAsync(new GetDelivererByIdSpec(req.Id), ct); + Deliverer? deliverer = await deliverersRepository.SingleOrDefaultAsync(new GetDelivererByIdSpec(req.Id), ct); - if (deliverer == null) + if (deliverer is null) { await Send.NotFoundAsync(ct); return; } - - deliverer.Transporter = req.Transporter; - - await deliverersRepository.UpdateAsync(deliverer,ct); - await Send.OkAsync(mapper.Map(deliverer), ct); + mapper.Map(req, deliverer); + + await deliverersRepository.SaveChangesAsync(ct); + await Send.NoContentAsync(ct); } - } \ No newline at end of file diff --git a/PyroFetes/Endpoints/DeliveryNotes/CreateDeliveryNoteEndpoint.cs b/PyroFetes/Endpoints/DeliveryNotes/CreateDeliveryNoteEndpoint.cs index 63d3103f..3266034c 100644 --- a/PyroFetes/Endpoints/DeliveryNotes/CreateDeliveryNoteEndpoint.cs +++ b/PyroFetes/Endpoints/DeliveryNotes/CreateDeliveryNoteEndpoint.cs @@ -1,6 +1,5 @@ using FastEndpoints; using PyroFetes.DTO.DeliveryNote.Request; -using PyroFetes.DTO.DeliveryNote.Response; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.Deliverers; @@ -12,8 +11,7 @@ public class CreateDeliveryNoteEndpoint( DeliveryNotesRepository deliveryNotesRepository, DeliverersRepository deliverersRepository, ProductsRepository productsRepository, - ProductDeliveriesRepository productDeliveriesRepository, - AutoMapper.IMapper mapper) : Endpoint + ProductDeliveriesRepository productDeliveriesRepository) : Endpoint { public override void Configure() { @@ -23,46 +21,44 @@ public class CreateDeliveryNoteEndpoint( public override async Task HandleAsync(CreateDeliveryNoteDto req, CancellationToken ct) { - Deliverer? deliverer = await deliverersRepository.FirstOrDefaultAsync(new GetDelivererByIdSpec(req.DelivererId), ct); - - if (deliverer == null) + Deliverer? deliverer = await deliverersRepository.SingleOrDefaultAsync(new GetDelivererByIdSpec(req.DelivererId), ct); + if (deliverer is null) { - await Send.StringAsync("No deliverer found", 404, cancellation: ct); + await Send.NotFoundAsync(ct); return; } - + //Creating the Delivery Note - DeliveryNote newDeliveryNote = new DeliveryNote() + DeliveryNote newDeliveryNote = new() { TrackingNumber = req.TrackingNumber, EstimateDeliveryDate = req.EstimateDeliveryDate, - ExpeditionDate = req.ExpeditionDate, - DelivererId = req.DelivererId, + ExpeditionDate = req.ExpeditionDate, + DelivererId = deliverer.Id, Deliverer = deliverer, - }; - + await deliveryNotesRepository.AddAsync(newDeliveryNote, ct); - foreach (var productQuantity in req.ProductQuantities!) + if (req.ProductQuantities is not null) { - Product? product = - await productsRepository.FirstOrDefaultAsync(new GetProductByIdSpec(productQuantity.Key), ct); - if (product != null) + foreach (KeyValuePair productQuantity in req.ProductQuantities) { - ProductDelivery productDelivery = new ProductDelivery() + Product? product = await productsRepository.SingleOrDefaultAsync(new GetProductByIdSpec(productQuantity.Key), ct); + if (product is null) continue; + ProductDelivery productDelivery = new() { DeliveryNote = newDeliveryNote, Quantity = productQuantity.Value, Product = product, + ProductId = product.Id, DeliveryNoteId = newDeliveryNote.Id }; - + await productDeliveriesRepository.AddAsync(productDelivery, ct); } - } - - await Send.OkAsync(mapper.Map(newDeliveryNote), ct); + + await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/DeliveryNotes/DeleteDeliveryNoteEndpoint.cs b/PyroFetes/Endpoints/DeliveryNotes/DeleteDeliveryNoteEndpoint.cs index 4fe76448..bc14d89e 100644 --- a/PyroFetes/Endpoints/DeliveryNotes/DeleteDeliveryNoteEndpoint.cs +++ b/PyroFetes/Endpoints/DeliveryNotes/DeleteDeliveryNoteEndpoint.cs @@ -1,9 +1,7 @@ using FastEndpoints; -using PyroFetes.Endpoints.Quotations; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.DeliveryNotes; -using PyroFetes.Specifications.Quotations; namespace PyroFetes.Endpoints.DeliveryNotes; @@ -17,22 +15,21 @@ public class DeleteDeliveryNoteEndpoint( { public override void Configure() { - Delete("/deliveryNotes/{@Id}", x => new {x.Id}); + Delete("/deliveryNotes/{@Id}", x => new { x.Id }); AllowAnonymous(); } public override async Task HandleAsync(DeleteDeliveryNoteRequest req, CancellationToken ct) { - DeliveryNote? deliveryNote = await deliveryNotesRepository.FirstOrDefaultAsync(new GetDeliveryNoteByIdSpec(req.Id), ct); + DeliveryNote? deliveryNote = await deliveryNotesRepository.SingleOrDefaultAsync(new GetDeliveryNoteByIdSpec(req.Id), ct); - if (deliveryNote == null) + if (deliveryNote is null) { await Send.NotFoundAsync(ct); return; } - + await deliveryNotesRepository.DeleteAsync(deliveryNote, ct); - await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/DeliveryNotes/GetAllDeliveryNoteEndpoint.cs b/PyroFetes/Endpoints/DeliveryNotes/GetAllDeliveryNoteEndpoint.cs index 7e126b83..56c19c63 100644 --- a/PyroFetes/Endpoints/DeliveryNotes/GetAllDeliveryNoteEndpoint.cs +++ b/PyroFetes/Endpoints/DeliveryNotes/GetAllDeliveryNoteEndpoint.cs @@ -1,6 +1,7 @@ using FastEndpoints; using PyroFetes.DTO.DeliveryNote.Response; using PyroFetes.Repositories; +using PyroFetes.Specifications.DeliveryNotes; namespace PyroFetes.Endpoints.DeliveryNotes; @@ -14,7 +15,6 @@ public class GetAllDeliveryNoteEndpoint(DeliveryNotesRepository deliveryNotesRep public override async Task HandleAsync(CancellationToken ct) { - await Send.OkAsync(await deliveryNotesRepository.ProjectToListAsync(ct), ct); + await Send.OkAsync(await deliveryNotesRepository.ProjectToListAsync(new GetAllDeliveryNoteSpec() ,ct), ct); } - } \ No newline at end of file diff --git a/PyroFetes/Endpoints/DeliveryNotes/GetDeliveryNoteEndpoint.cs b/PyroFetes/Endpoints/DeliveryNotes/GetDeliveryNoteEndpoint.cs index 90f33874..62597db6 100644 --- a/PyroFetes/Endpoints/DeliveryNotes/GetDeliveryNoteEndpoint.cs +++ b/PyroFetes/Endpoints/DeliveryNotes/GetDeliveryNoteEndpoint.cs @@ -10,26 +10,27 @@ public class GetDeliveryNoteRequest { public int DeliveryNoteId { get; set; } } + public class GetDeliveryNoteEndpoint( DeliveryNotesRepository deliveryNotesRepository, AutoMapper.IMapper mapper) : Endpoint { public override void Configure() { - Get("/deliveryNotes/{@id}", x=> new {x.DeliveryNoteId}); + Get("/deliveryNotes/{@Id}", x => new { x.DeliveryNoteId }); AllowAnonymous(); } public override async Task HandleAsync(GetDeliveryNoteRequest req, CancellationToken ct) { - DeliveryNote? deliveryNote = await deliveryNotesRepository.FirstOrDefaultAsync(new GetDeliveryNoteByIdSpec(req.DeliveryNoteId), ct); + DeliveryNote? deliveryNote = await deliveryNotesRepository.SingleOrDefaultAsync(new GetDeliveryNoteByIdSpec(req.DeliveryNoteId), ct); - if (deliveryNote == null) + if (deliveryNote is null) { await Send.NotFoundAsync(ct); return; } - + await Send.OkAsync(mapper.Map(deliveryNote), ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/DeliveryNotes/GetDeliveryNotePdfEndpoint.cs b/PyroFetes/Endpoints/DeliveryNotes/GetDeliveryNotePdfEndpoint.cs index 76bbbab8..19b47d1e 100644 --- a/PyroFetes/Endpoints/DeliveryNotes/GetDeliveryNotePdfEndpoint.cs +++ b/PyroFetes/Endpoints/DeliveryNotes/GetDeliveryNotePdfEndpoint.cs @@ -5,39 +5,37 @@ using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Services.Pdf; using PyroFetes.Specifications.DeliveryNotes; -using PyroFetes.Specifications.Quotations; namespace PyroFetes.Endpoints.DeliveryNotes; -public class GetDeliveryNotePdfEndpoint( - DeliveryNotesRepository deliveryNotesRepository, - IDeliveryNotePdfService deliveryNotePdfService) - : Endpoint +public class GetDeliveryNotePdfEndpoint(DeliveryNotesRepository deliveryNotesRepository, IDeliveryNotePdfService deliveryNotePdfService, SettingsRepository settingsRepository) : Endpoint { public override void Configure() { - Get("/deliveryNotes/{@Id}/pdf", x => new {x.Id}); + Get("/deliveryNotes/{@Id}/pdf", x => new { x.Id }); AllowAnonymous(); Description(b => b.Produces(200, MediaTypeNames.Application.Pdf)); } - + public override async Task HandleAsync(GetDeliveryNotePdfDto req, CancellationToken ct) { DeliveryNote? deliveryNote = await deliveryNotesRepository - .FirstOrDefaultAsync(new GetDeliveryNoteByIdWithProductsSpec(req.Id), ct); + .SingleOrDefaultAsync(new GetDeliveryNoteByIdWithProductsSpec(req.Id), ct); - if (deliveryNote == null) + Setting? setting = await settingsRepository.FirstOrDefaultAsync(ct); + + if (deliveryNote is null) { await Send.NotFoundAsync(ct); return; } - - var bytes = deliveryNotePdfService.Generate(deliveryNote, deliveryNote.ProductDeliveries!); + + byte[] bytes = deliveryNotePdfService.Generate(deliveryNote, deliveryNote.ProductDeliveries!, setting!); await Send.BytesAsync( bytes: bytes, contentType: "application/pdf", - fileName: $"bon-de-livraison-{deliveryNote.Id}.pdf", + fileName: $"bon-de-livraison-{deliveryNote.Id}{DateOnly.FromDateTime(DateTime.Now)}.pdf", cancellation: ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/DeliveryNotes/PatchRealDeliveryDateEndpoint.cs b/PyroFetes/Endpoints/DeliveryNotes/PatchRealDeliveryDateEndpoint.cs index 99c35c1e..a7100443 100644 --- a/PyroFetes/Endpoints/DeliveryNotes/PatchRealDeliveryDateEndpoint.cs +++ b/PyroFetes/Endpoints/DeliveryNotes/PatchRealDeliveryDateEndpoint.cs @@ -1,45 +1,41 @@ using FastEndpoints; using PyroFetes.DTO.DeliveryNote.Request; -using PyroFetes.DTO.DeliveryNote.Response; -using PyroFetes.DTO.PurchaseProduct.Request; using PyroFetes.Models; using PyroFetes.Repositories; -using PyroFetes.Specifications.Deliverers; using PyroFetes.Specifications.DeliveryNotes; namespace PyroFetes.Endpoints.DeliveryNotes; public class PatchRealDeliveryDateEndpoint( DeliveryNotesRepository deliveryNotesRepository, - AutoMapper.IMapper mapper) : Endpoint + AutoMapper.IMapper mapper) : Endpoint { public override void Configure() { - Patch("/deliveryNotes/{@id}", x=> new {x.Id}); + Patch("/deliveryNotes/{@Id}", x => new { x.Id }); AllowAnonymous(); } public override async Task HandleAsync(PatchDeliveryNoteRealDeliveryDateDto req, CancellationToken ct) { - DeliveryNote? deliveryNoteToPath = - await deliveryNotesRepository.FirstOrDefaultAsync(new GetDeliveryNoteByIdSpec(req.Id),ct); + DeliveryNote? deliveryNoteToPath = await deliveryNotesRepository.SingleOrDefaultAsync(new GetDeliveryNoteByIdSpec(req.Id), ct); - if (deliveryNoteToPath == null) + if (deliveryNoteToPath is null) { await Send.NotFoundAsync(ct); return; } - - if (deliveryNoteToPath.RealDeliveryDate != null) + + if (deliveryNoteToPath.RealDeliveryDate is not null) { - await Send.StringAsync("Impossible de modifier la date.", 400); + await Send.StringAsync("Impossible de modifier la date.", 400, cancellation: ct); return; } - - deliveryNoteToPath.RealDeliveryDate = req.RealDeliveryDate; - + + mapper.Map(req, deliveryNoteToPath); + await deliveryNotesRepository.UpdateAsync(deliveryNoteToPath, ct); - - await Send.OkAsync(mapper.Map(deliveryNoteToPath), ct); + + await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/DeliveryNotes/UpdateDeliveryNoteEndpoint.cs b/PyroFetes/Endpoints/DeliveryNotes/UpdateDeliveryNoteEndpoint.cs index 5d347cb8..6fccf9be 100644 --- a/PyroFetes/Endpoints/DeliveryNotes/UpdateDeliveryNoteEndpoint.cs +++ b/PyroFetes/Endpoints/DeliveryNotes/UpdateDeliveryNoteEndpoint.cs @@ -1,40 +1,32 @@ using FastEndpoints; using PyroFetes.DTO.DeliveryNote.Request; -using PyroFetes.DTO.DeliveryNote.Response; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.DeliveryNotes; namespace PyroFetes.Endpoints.DeliveryNotes; -public class UpdateDeliveryNoteEndpoint( - DeliveryNotesRepository deliveryNotesRepository, - AutoMapper.IMapper mapper) : Endpoint +public class UpdateDeliveryNoteEndpoint(DeliveryNotesRepository deliveryNotesRepository, AutoMapper.IMapper mapper) : Endpoint { public override void Configure() { - Put("/deliveryNotes/{@Id}", x => new {x.Id}); + Put("/deliveryNotes/{@Id}", x => new { x.Id }); AllowAnonymous(); } public override async Task HandleAsync(UpdateDeliveryNoteDto req, CancellationToken ct) { - DeliveryNote? deliveryNote = await deliveryNotesRepository.FirstOrDefaultAsync(new GetDeliveryNoteByIdSpec(req.Id), ct); - - if (deliveryNote == null) + DeliveryNote? deliveryNote = await deliveryNotesRepository.SingleOrDefaultAsync(new GetDeliveryNoteByIdSpec(req.Id), ct); + + if (deliveryNote is null) { await Send.NotFoundAsync(ct); return; } - - deliveryNote.TrackingNumber = req.TrackingNumber; - deliveryNote.EstimateDeliveryDate = req.EstimateDeliveryDate; - deliveryNote.ExpeditionDate = req.ExpeditionDate; - deliveryNote.RealDeliveryDate = req.RealDeliveryDate; - deliveryNote.DelivererId = req.DelivererId; - - await deliveryNotesRepository.UpdateAsync(deliveryNote, ct); - - await Send.OkAsync(mapper.Map(deliveryNote), ct); + + mapper.Map(req, deliveryNote); + + await deliveryNotesRepository.SaveChangesAsync(ct); + await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Prices/CreatePriceEndpoint.cs b/PyroFetes/Endpoints/Prices/CreatePriceEndpoint.cs deleted file mode 100644 index 5445c0db..00000000 --- a/PyroFetes/Endpoints/Prices/CreatePriceEndpoint.cs +++ /dev/null @@ -1,84 +0,0 @@ -using FastEndpoints; -using PyroFetes.DTO.Price.Request; -using PyroFetes.DTO.Price.Response; -using PyroFetes.Models; -using PyroFetes.Repositories; -using PyroFetes.Specifications.Prices; -using PyroFetes.Specifications.Products; -using PyroFetes.Specifications.Suppliers; - -namespace PyroFetes.Endpoints.Prices; - -public class CreatePriceEndpoint( - SuppliersRepository suppliersRepository, - ProductsRepository productsRepository, - PricesRepository pricesRepository, - AutoMapper.IMapper mapper) : Endpoint -{ - public override void Configure() - { - Post("/prices"); - AllowAnonymous(); - } - - public override async Task HandleAsync(CreatePriceDto req, CancellationToken ct) - { - // Gestion du fournisseur - Supplier? supplier = await suppliersRepository.FirstOrDefaultAsync(new GetSupplierByIdSpec(req.SupplierId), ct); - if (supplier == null) - { - supplier = new Supplier() - { - Name = req.SupplierName, - Email = req.SupplierEmail, - Phone = req.SupplierPhone, - Address = req.SupplierAddress, - City = req.SupplierCity, - ZipCode = req.SupplierZipCode, - DeliveryDelay = req.SupplierDeliveryDelay - }; - await suppliersRepository.AddAsync(supplier, ct); - } - - // Gestion du produit - Product? product = await productsRepository.FirstOrDefaultAsync(new GetProductByIdSpec(req.ProductId), ct); - if (product == null) - { - product = new Product() - { - Reference = req.ProductReferences, - Name = req.ProductName, - Duration = req.ProductDuration, - Caliber = req.ProductCaliber, - ApprovalNumber = req.ProductApprovalNumber, - Weight = req.ProductWeight, - Nec = req.ProductNec, - Image = req.ProductImage, - Link = req.ProductLink, - MinimalQuantity = req.ProductMinimalQuantity - }; - await productsRepository.AddAsync(product, ct); - } - - // Vérifie si le prix existe déjà pour ce fournisseur et produit - Price? existingPrice = await pricesRepository.FirstOrDefaultAsync(new GetPriceByProductIdAndSupplierIdSpec(req.ProductId, req.SupplierId), ct); - - if (existingPrice != null) - { - await Send.StringAsync("Le fournisseur a déjà un prix pour ce produit.", 400, cancellation: ct); - return; - } - - // Création du prix - var priceAdded = new Price() - { - SellingPrice = req.SellingPrice, - SupplierId = supplier.Id, - ProductId = product.Id - }; - await pricesRepository.AddAsync(priceAdded, ct); - - - await Send.OkAsync(mapper.Map(priceAdded), ct); - } -} diff --git a/PyroFetes/Endpoints/Products/DeleteProductEndpoint.cs b/PyroFetes/Endpoints/Products/DeleteProductEndpoint.cs index 1e481636..a7720644 100644 --- a/PyroFetes/Endpoints/Products/DeleteProductEndpoint.cs +++ b/PyroFetes/Endpoints/Products/DeleteProductEndpoint.cs @@ -1,8 +1,6 @@ using FastEndpoints; -using PyroFetes.Endpoints.Deliverers; using PyroFetes.Models; using PyroFetes.Repositories; -using PyroFetes.Specifications.Deliverers; using PyroFetes.Specifications.Products; namespace PyroFetes.Endpoints.Products; @@ -11,28 +9,26 @@ public class DeleteProductsRequest { public int ProductId { get; set; } } + public class DeleteProductEndpoint(ProductsRepository productsRepository) : Endpoint { public override void Configure() { - Delete("/products/{@id}", x=>new {x.ProductId}); + Delete("/products/{@Id}", x => new { x.ProductId }); AllowAnonymous(); - } public override async Task HandleAsync(DeleteProductsRequest req, CancellationToken ct) { - Product? product = await productsRepository.FirstOrDefaultAsync(new GetProductByIdSpec(req.ProductId), ct); + Product? product = await productsRepository.SingleOrDefaultAsync(new GetProductByIdSpec(req.ProductId), ct); - if (product == null) + if (product is null) { await Send.NotFoundAsync(ct); return; } - - await productsRepository.DeleteAsync(product, ct); + await productsRepository.DeleteAsync(product, ct); await Send.OkAsync(ct); } - } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Products/GetAllProductsEndpoint.cs b/PyroFetes/Endpoints/Products/GetAllProductsEndpoint.cs index 6b4f2e07..e6c9343e 100644 --- a/PyroFetes/Endpoints/Products/GetAllProductsEndpoint.cs +++ b/PyroFetes/Endpoints/Products/GetAllProductsEndpoint.cs @@ -1,7 +1,5 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.Product.Response; -using PyroFetes.Models; using PyroFetes.Repositories; namespace PyroFetes.Endpoints.Products; diff --git a/PyroFetes/Endpoints/Products/GetAllProductsUnderLimitEndpoint.cs b/PyroFetes/Endpoints/Products/GetAllProductsUnderLimitEndpoint.cs index 2057c35c..0b9768fb 100644 --- a/PyroFetes/Endpoints/Products/GetAllProductsUnderLimitEndpoint.cs +++ b/PyroFetes/Endpoints/Products/GetAllProductsUnderLimitEndpoint.cs @@ -1,4 +1,3 @@ -using AutoMapper; using FastEndpoints; using PyroFetes.DTO.Product.Response; using PyroFetes.Repositories; @@ -15,7 +14,7 @@ public class GetAllProductsUnderLimitEndpoint(ProductsRepository productsReposit } public override async Task HandleAsync(CancellationToken ct) - { + { await Send.OkAsync(await productsRepository.ProjectToListAsync(new GetProductsUnderLimitSpec(), ct), ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Products/GetProductEndpoint.cs b/PyroFetes/Endpoints/Products/GetProductEndpoint.cs index 705f5d21..efe2a7bd 100644 --- a/PyroFetes/Endpoints/Products/GetProductEndpoint.cs +++ b/PyroFetes/Endpoints/Products/GetProductEndpoint.cs @@ -1,5 +1,4 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.Product.Response; using PyroFetes.Models; using PyroFetes.Repositories; @@ -18,7 +17,7 @@ public class GetProductEndpoint( { public override void Configure() { - Get("/products/{@Id}", x => new {x.Id}); + Get("/products/{@Id}", x => new { x.Id }); AllowAnonymous(); } @@ -26,12 +25,12 @@ public class GetProductEndpoint( { Product? product = await productsRepository.FirstOrDefaultAsync(new GetProductByIdSpec(req.Id), ct); - if (product == null) + if (product is null) { await Send.NotFoundAsync(ct); return; } - - await Send.OkAsync(mapper.Map(product), ct); + + await Send.OkAsync(mapper.Map(product), ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Products/PatchProductMinimalStockEndpoint.cs b/PyroFetes/Endpoints/Products/PatchProductMinimalStockEndpoint.cs index 6d2cf8b0..40ebeba8 100644 --- a/PyroFetes/Endpoints/Products/PatchProductMinimalStockEndpoint.cs +++ b/PyroFetes/Endpoints/Products/PatchProductMinimalStockEndpoint.cs @@ -1,16 +1,12 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.Product.Request; -using PyroFetes.DTO.Product.Response; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.Products; namespace PyroFetes.Endpoints.Products; -public class PatchProductMinimalStockEndpoint( - ProductsRepository productsRepository, - AutoMapper.IMapper mapper) : Endpoint +public class PatchProductMinimalStockEndpoint(ProductsRepository productsRepository, AutoMapper.IMapper mapper) : Endpoint { public override void Configure() { @@ -20,17 +16,17 @@ public class PatchProductMinimalStockEndpoint( public override async Task HandleAsync(PatchProductMinimalStockDto req, CancellationToken ct) { - Product? product = await productsRepository.FirstOrDefaultAsync(new GetProductByIdSpec(req.Id), ct); - - if (product == null) + Product? product = await productsRepository.SingleOrDefaultAsync(new GetProductByIdSpec(req.Id), ct); + + if (product is null) { await Send.NotFoundAsync(ct); return; } - product.MinimalQuantity = req.MinimalQuantity; + mapper.Map(req, product); + await productsRepository.UpdateAsync(product, ct); - - await Send.OkAsync(mapper.Map(product), ct); + await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Products/UpdateProductEndpoint.cs b/PyroFetes/Endpoints/Products/UpdateProductEndpoint.cs index 0b37aa9a..81fccdd6 100644 --- a/PyroFetes/Endpoints/Products/UpdateProductEndpoint.cs +++ b/PyroFetes/Endpoints/Products/UpdateProductEndpoint.cs @@ -1,46 +1,32 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.Product.Request; -using PyroFetes.DTO.Product.Response; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.Products; namespace PyroFetes.Endpoints.Products; -public class UpdateProductEndpoint( - ProductsRepository productsRepository, - AutoMapper.IMapper mapper) : Endpoint +public class UpdateProductEndpoint(ProductsRepository productsRepository, AutoMapper.IMapper mapper) : Endpoint { public override void Configure() { - Put("/products/{@Id}", x => new {x.Id}); + Put("/products/{@Id}", x => new { x.Id }); AllowAnonymous(); } public override async Task HandleAsync(UpdateProductDto req, CancellationToken ct) { - Product? product = await productsRepository.FirstOrDefaultAsync(new GetProductByIdSpec(req.Id), ct); - - if (product == null) + Product? product = await productsRepository.SingleOrDefaultAsync(new GetProductByIdSpec(req.Id), ct); + + if (product is null) { await Send.NotFoundAsync(ct); return; } - product.Reference = req.References; - product.Name = req.Name; - product.Duration = req.Duration; - product.Caliber = req.Caliber; - product.ApprovalNumber = req.ApprovalNumber; - product.Weight = req.Weight; - product.Nec = req.Nec; - product.Image = req.Image; - product.Link = req.Link; - product.MinimalQuantity = req.MinimalQuantity; - + mapper.Map(req, product); + await productsRepository.UpdateAsync(product, ct); - - await Send.OkAsync(mapper.Map(product), ct); + await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/PurchaseOrders/AddProductFromPurchaseOrderEndpoint.cs b/PyroFetes/Endpoints/PurchaseOrders/AddProductFromPurchaseOrderEndpoint.cs new file mode 100644 index 00000000..9a02d203 --- /dev/null +++ b/PyroFetes/Endpoints/PurchaseOrders/AddProductFromPurchaseOrderEndpoint.cs @@ -0,0 +1,32 @@ +using FastEndpoints; +using PyroFetes.DTO.PurchaseProduct.Request; +using PyroFetes.Models; +using PyroFetes.Repositories; +using PyroFetes.Specifications.PurchaseProducts; + +namespace PyroFetes.Endpoints.PurchaseOrders; + +public class AddProductFromPurchaseOrderEndpoint(PurchaseProductsRepository purchaseProductsRepository, AutoMapper.IMapper mapper) : Endpoint +{ + public override void Configure() + { + Post("/purchaseOrders/{@PurchaseOrderId}/{@ProductId}", x => new { x.PurchaseOrderId, x.ProductId }); + AllowAnonymous(); + } + + public override async Task HandleAsync(CreatePurchaseProductDto req, CancellationToken ct) + { + PurchaseProduct? purchaseOrderProduct = + await purchaseProductsRepository.SingleOrDefaultAsync(new GetPurchaseProductByProductIdAndPurchaseOrderIdSpec(req.ProductId, req.PurchaseOrderId), ct); + if (purchaseOrderProduct is not null) + { + await Send.StringAsync("Le produit est déjà dans le bon de commande", 400, cancellation: ct); + return; + } + + purchaseOrderProduct = mapper.Map(req); + + await purchaseProductsRepository.AddAsync(purchaseOrderProduct, ct); + await Send.NoContentAsync(ct); + } +} \ No newline at end of file diff --git a/PyroFetes/Endpoints/PurchaseOrders/CreatePurchaseOrder.cs b/PyroFetes/Endpoints/PurchaseOrders/CreatePurchaseOrder.cs index b3ca8754..b30ec5d9 100644 --- a/PyroFetes/Endpoints/PurchaseOrders/CreatePurchaseOrder.cs +++ b/PyroFetes/Endpoints/PurchaseOrders/CreatePurchaseOrder.cs @@ -1,19 +1,18 @@ using FastEndpoints; using PyroFetes.DTO.PurchaseOrder.Request; -using PyroFetes.DTO.PurchaseOrder.Response; using PyroFetes.DTO.PurchaseProduct.Request; -using PyroFetes.DTO.PurchaseProduct.Response; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.Products; -using PyroFetes.Specifications.PurchaseOrders; +using PyroFetes.Specifications.PurchaseProducts; namespace PyroFetes.Endpoints.PurchaseOrders; public class CreatePurchaseOrder( PurchaseOrdersRepository purchaseOrdersRepository, ProductsRepository productsRepository, - AutoMapper.IMapper mapper) : Endpoint + PurchaseProductsRepository purchaseProductsRepository, + AutoMapper.IMapper mapper) : Endpoint { public override void Configure() { @@ -23,30 +22,35 @@ public class CreatePurchaseOrder( public override async Task HandleAsync(CreatePurchaseOrderDto req, CancellationToken ct) { - PurchaseOrder purchaseOrder = new PurchaseOrder - { - PurchaseConditions = req.PurchaseConditions ?? "Conditions non précisées", - PurchaseProducts = new List() - }; + PurchaseOrder purchaseOrder = mapper.Map(req); - foreach (var line in req.Products) + if (req.Products != null) { - var product = await productsRepository.GetByIdAsync(line.ProductId, ct); - if (product == null) + foreach (CreatePurchaseOrderProductDto line in req.Products) { - await Send.NotFoundAsync(ct); - return; + Product? product = await productsRepository.SingleOrDefaultAsync(new GetProductByIdSpec(line.ProductId), ct); + if (product is null) + { + await Send.NotFoundAsync(ct); + return; + } + + PurchaseProduct? purchaseProduct = + await purchaseProductsRepository.SingleOrDefaultAsync(new GetPurchaseProductByProductIdAndPurchaseOrderIdSpec(line.ProductId, purchaseOrder.Id), ct); + + if (purchaseProduct is not null) + { + await Send.StringAsync("Le produit est déjà dans le bon de commande", 400, cancellation: ct); + } + + PurchaseProduct? productOnPurchase = mapper.Map(line); + productOnPurchase.PurchaseOrderId = purchaseOrder.Id; + + await purchaseProductsRepository.AddAsync(productOnPurchase, ct); } - - purchaseOrder.PurchaseProducts.Add(new PurchaseProduct - { - ProductId = product.Id, - Quantity = line.Quantity, - }); } await purchaseOrdersRepository.AddAsync(purchaseOrder, ct); - - await Send.OkAsync(mapper.Map(purchaseOrder), ct); + await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/PurchaseProducts/DeletePurchaseProductEndpoint.cs b/PyroFetes/Endpoints/PurchaseOrders/DeleteProductFromPurchaseOrderEndpoint.cs similarity index 51% rename from PyroFetes/Endpoints/PurchaseProducts/DeletePurchaseProductEndpoint.cs rename to PyroFetes/Endpoints/PurchaseOrders/DeleteProductFromPurchaseOrderEndpoint.cs index 7ce0dffb..8f6274e4 100644 --- a/PyroFetes/Endpoints/PurchaseProducts/DeletePurchaseProductEndpoint.cs +++ b/PyroFetes/Endpoints/PurchaseOrders/DeleteProductFromPurchaseOrderEndpoint.cs @@ -1,10 +1,9 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.PurchaseProducts; -namespace PyroFetes.Endpoints.PurchaseProducts; +namespace PyroFetes.Endpoints.PurchaseOrders; public class DeletePurchaseProductRequest { @@ -12,27 +11,26 @@ public class DeletePurchaseProductRequest public int PurchaseOrderId { get; set; } } -public class DeletePurchaseProductEndpoint(PurchaseProductsRepository purchaseProductsRepository) : Endpoint +public class DeleteProductFromPurchaseOrderEndpoint(PurchaseProductsRepository purchaseProductsRepository) : Endpoint { public override void Configure() { - Delete("/purchaseProducts/{@ProductId}/{@PurchaseOrderId}", x => new {x.ProductId, x.PurchaseOrderId}); + Delete("/purchaseOrders/{@ProductId}/{@PurchaseOrderId}", x => new { x.ProductId, x.PurchaseOrderId }); AllowAnonymous(); } public override async Task HandleAsync(DeletePurchaseProductRequest req, CancellationToken ct) { - PurchaseProduct? purchaseProduct = await purchaseProductsRepository.FirstOrDefaultAsync( - new GetPurchaseProductByProductIdAndPurchaseOrderIdSpec(req.ProductId, req.PurchaseOrderId), ct); + PurchaseProduct? purchaseProduct = + await purchaseProductsRepository.SingleOrDefaultAsync(new GetPurchaseProductByProductIdAndPurchaseOrderIdSpec(req.ProductId, req.PurchaseOrderId), ct); - if (purchaseProduct == null) + if (purchaseProduct is null) { await Send.NotFoundAsync(ct); return; } - + await purchaseProductsRepository.DeleteAsync(purchaseProduct, ct); - await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/PurchaseOrders/DeletePurchaseOrderEndpoint.cs b/PyroFetes/Endpoints/PurchaseOrders/DeletePurchaseOrderEndpoint.cs index 580efb65..b3f077c9 100644 --- a/PyroFetes/Endpoints/PurchaseOrders/DeletePurchaseOrderEndpoint.cs +++ b/PyroFetes/Endpoints/PurchaseOrders/DeletePurchaseOrderEndpoint.cs @@ -1,5 +1,4 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.PurchaseOrders; @@ -11,13 +10,11 @@ public class DeletePurchaseOrderRequest public int Id { get; set; } } -public class DeletePurchaseOrderEndpoint( - PurchaseOrdersRepository purchaseOrdersRepository, - PurchaseProductsRepository purchaseProductsRepository) : Endpoint +public class DeletePurchaseOrderEndpoint(PurchaseOrdersRepository purchaseOrdersRepository) : Endpoint { public override void Configure() { - Delete("/purchaseOrders/{@Id}", x => new {x.Id}); + Delete("/purchaseOrders/{@Id}", x => new { x.Id }); AllowAnonymous(); } @@ -25,19 +22,13 @@ public class DeletePurchaseOrderEndpoint( { PurchaseOrder? purchaseOrder = await purchaseOrdersRepository.FirstOrDefaultAsync(new GetPurchaseOrderByIdSpec(req.Id), ct); - if (purchaseOrder == null) + if (purchaseOrder is null) { await Send.NotFoundAsync(ct); return; } - - if (purchaseOrder.PurchaseProducts != null && purchaseOrder.PurchaseProducts.Any()) - { - await purchaseProductsRepository.DeleteRangeAsync(purchaseOrder.PurchaseProducts, ct); - } - - await purchaseOrdersRepository.DeleteAsync(purchaseOrder, ct); - + + await purchaseOrdersRepository.DeleteAsync(purchaseOrder, ct); await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/PurchaseOrders/GetAllPurchaseOrderEndpoint.cs b/PyroFetes/Endpoints/PurchaseOrders/GetAllPurchaseOrderEndpoint.cs index 4bfd0123..8a3dd58e 100644 --- a/PyroFetes/Endpoints/PurchaseOrders/GetAllPurchaseOrderEndpoint.cs +++ b/PyroFetes/Endpoints/PurchaseOrders/GetAllPurchaseOrderEndpoint.cs @@ -1,7 +1,5 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.PurchaseOrder.Response; -using PyroFetes.DTO.PurchaseProduct.Response; using PyroFetes.Repositories; namespace PyroFetes.Endpoints.PurchaseOrders; diff --git a/PyroFetes/Endpoints/PurchaseOrders/GetPurchaseOrderEndpoint.cs b/PyroFetes/Endpoints/PurchaseOrders/GetPurchaseOrderEndpoint.cs index 2b66aee6..c9d906c7 100644 --- a/PyroFetes/Endpoints/PurchaseOrders/GetPurchaseOrderEndpoint.cs +++ b/PyroFetes/Endpoints/PurchaseOrders/GetPurchaseOrderEndpoint.cs @@ -1,7 +1,5 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.PurchaseOrder.Response; -using PyroFetes.DTO.PurchaseProduct.Response; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.PurchaseOrders; @@ -13,26 +11,24 @@ public class GetPurchaseOrderRequest public int Id { get; set; } } -public class GetPurchaseOrderEndpoint( - PurchaseOrdersRepository purchaseOrdersRepository, - AutoMapper.IMapper mapper) : Endpoint +public class GetPurchaseOrderEndpoint(PurchaseOrdersRepository purchaseOrdersRepository, AutoMapper.IMapper mapper) : Endpoint { public override void Configure() { - Get("/purchaseOrders/{@Id}", x => new {x.Id}); + Get("/purchaseOrders/{@Id}", x => new { x.Id }); AllowAnonymous(); } public override async Task HandleAsync(GetPurchaseOrderRequest req, CancellationToken ct) { - PurchaseOrder? purchaseOrder = await purchaseOrdersRepository.FirstOrDefaultAsync(new GetPurchaseOrderByIdSpec(req.Id), ct); + PurchaseOrder? purchaseOrder = await purchaseOrdersRepository.SingleOrDefaultAsync(new GetPurchaseOrderByIdSpec(req.Id), ct); - if (purchaseOrder == null) + if (purchaseOrder is null) { await Send.NotFoundAsync(ct); return; } - + await Send.OkAsync(mapper.Map(purchaseOrder), ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/PurchaseOrders/GetPurchaseOrderPdfEndpoint.cs b/PyroFetes/Endpoints/PurchaseOrders/GetPurchaseOrderPdfEndpoint.cs index a044b50c..05c1f86a 100644 --- a/PyroFetes/Endpoints/PurchaseOrders/GetPurchaseOrderPdfEndpoint.cs +++ b/PyroFetes/Endpoints/PurchaseOrders/GetPurchaseOrderPdfEndpoint.cs @@ -5,37 +5,40 @@ using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Services.Pdf; using PyroFetes.Specifications.PurchaseOrders; + namespace PyroFetes.Endpoints.PurchaseOrders; public class GetPurchaseOrderPdfEndpoint( PurchaseOrdersRepository purchaseOrdersRepository, - IPurchaseOrderPdfService purchaseOrderPdfService) + IPurchaseOrderPdfService purchaseOrderPdfService, + SettingsRepository settingsRepository) : Endpoint { public override void Configure() { - Get("/purchaseOrders/{@Id}/pdf", x => new {x.Id}); + Get("/purchaseOrders/{@Id}/pdf", x => new { x.Id }); AllowAnonymous(); Description(b => b.Produces(200, MediaTypeNames.Application.Pdf)); } - + public override async Task HandleAsync(GetPurchaseOrderPdfDto req, CancellationToken ct) { - PurchaseOrder? purchaseOrder = await purchaseOrdersRepository - .FirstOrDefaultAsync(new GetPurchaseOrderByIdWithProductsSpec(req.Id), ct); - - if (purchaseOrder == null) + PurchaseOrder? purchaseOrder = await purchaseOrdersRepository.SingleOrDefaultAsync(new GetPurchaseOrderByIdWithProductsSpec(req.Id), ct); + + if (purchaseOrder is null) { await Send.NotFoundAsync(ct); return; } + + Setting? setting = await settingsRepository.FirstOrDefaultAsync(ct); - var bytes = purchaseOrderPdfService.Generate(purchaseOrder, purchaseOrder.PurchaseProducts!); + byte[] bytes = purchaseOrderPdfService.Generate(purchaseOrder, purchaseOrder.PurchaseProducts!, setting!); await Send.BytesAsync( bytes: bytes, contentType: "application/pdf", - fileName: $"bon-de-commande-{purchaseOrder.Id}.pdf", + fileName: $"bon-de-commande-{purchaseOrder.Id}{DateOnly.FromDateTime(DateTime.Now)}.pdf", cancellation: ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/PurchaseOrders/PatchPurchaseOrderPurchaseConditionsEndpoint.cs b/PyroFetes/Endpoints/PurchaseOrders/PatchPurchaseOrderPurchaseConditionsEndpoint.cs index 7b5c1f5f..0adbae4c 100644 --- a/PyroFetes/Endpoints/PurchaseOrders/PatchPurchaseOrderPurchaseConditionsEndpoint.cs +++ b/PyroFetes/Endpoints/PurchaseOrders/PatchPurchaseOrderPurchaseConditionsEndpoint.cs @@ -1,17 +1,14 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.PurchaseOrder.Request; using PyroFetes.DTO.PurchaseOrder.Response; -using PyroFetes.DTO.PurchaseProduct.Response; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.PurchaseOrders; namespace PyroFetes.Endpoints.PurchaseOrders; -public class PatchPurchaseOrderPurchaseConditionsEndpoint( - PurchaseOrdersRepository purchaseOrdersRepository, - AutoMapper.IMapper mapper) : Endpoint +public class PatchPurchaseOrderPurchaseConditionsEndpoint(PurchaseOrdersRepository purchaseOrdersRepository, AutoMapper.IMapper mapper) + : Endpoint { public override void Configure() { @@ -21,16 +18,16 @@ public class PatchPurchaseOrderPurchaseConditionsEndpoint( public override async Task HandleAsync(PatchPurchaseOrderPurchaseConditionsDto req, CancellationToken ct) { - PurchaseOrder? purchaseOrder = await purchaseOrdersRepository.FirstOrDefaultAsync(new GetPurchaseOrderByIdSpec(req.Id), ct); - if (purchaseOrder == null) + PurchaseOrder? purchaseOrder = await purchaseOrdersRepository.SingleOrDefaultAsync(new GetPurchaseOrderByIdSpec(req.Id), ct); + if (purchaseOrder is null) { await Send.NotFoundAsync(ct); return; } - - purchaseOrder.PurchaseConditions = req.PurchaseConditions; - await purchaseOrdersRepository.UpdateAsync(purchaseOrder, ct); - await Send.OkAsync(mapper.Map(purchaseOrder), ct); + mapper.Map(req, purchaseOrder); + + await purchaseOrdersRepository.UpdateAsync(purchaseOrder, ct); + await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/PurchaseOrders/PatchPurchaseProductQuantityEndpoint.cs b/PyroFetes/Endpoints/PurchaseOrders/PatchPurchaseProductQuantityEndpoint.cs new file mode 100644 index 00000000..1453e0a8 --- /dev/null +++ b/PyroFetes/Endpoints/PurchaseOrders/PatchPurchaseProductQuantityEndpoint.cs @@ -0,0 +1,35 @@ +using FastEndpoints; +using PyroFetes.DTO.PurchaseProduct.Request; +using PyroFetes.DTO.PurchaseProduct.Response; +using PyroFetes.Models; +using PyroFetes.Repositories; +using PyroFetes.Specifications.PurchaseProducts; + +namespace PyroFetes.Endpoints.PurchaseOrders; + +public class PatchPurchaseProductQuantityEndpoint(PurchaseProductsRepository purchaseProductsRepository, AutoMapper.IMapper mapper) + : Endpoint +{ + public override void Configure() + { + Patch("/purchaseOrders/{@ProductId}/{@PurchaseOrderId}/Quantity", x => new { x.ProductId, x.PurchaseOrderId }); + AllowAnonymous(); + } + + public override async Task HandleAsync(PatchPurchaseProductQuantityDto req, CancellationToken ct) + { + PurchaseProduct? purchaseProduct = + await purchaseProductsRepository.SingleOrDefaultAsync(new GetPurchaseProductByProductIdAndPurchaseOrderIdSpec(req.ProductId, req.PurchaseOrderId), ct); + + if (purchaseProduct is null) + { + await Send.NotFoundAsync(ct); + return; + } + + mapper.Map(req, purchaseProduct); + + await purchaseProductsRepository.SaveChangesAsync(ct); + await Send.NoContentAsync(ct); + } +} \ No newline at end of file diff --git a/PyroFetes/Endpoints/PurchaseProducts/CreatePurchaseProductEndpoint.cs b/PyroFetes/Endpoints/PurchaseProducts/CreatePurchaseProductEndpoint.cs deleted file mode 100644 index 24fe1f75..00000000 --- a/PyroFetes/Endpoints/PurchaseProducts/CreatePurchaseProductEndpoint.cs +++ /dev/null @@ -1,56 +0,0 @@ -using FastEndpoints; -using Microsoft.EntityFrameworkCore; -using PyroFetes.DTO.PurchaseProduct.Request; -using PyroFetes.DTO.PurchaseProduct.Response; -using PyroFetes.Models; -using PyroFetes.Repositories; -using PyroFetes.Specifications.Products; -using PyroFetes.Specifications.PurchaseOrders; - -namespace PyroFetes.Endpoints.PurchaseProducts; - -public class CreatePurchaseProductEndpoint( - ProductsRepository productsRepository, - PurchaseOrdersRepository purchaseOrdersRepository, - PurchaseProductsRepository purchaseProductsRepository, - AutoMapper.IMapper mapper) : Endpoint -{ - public override void Configure() - { - Post("/purchaseProducts"); - AllowAnonymous(); - } - - public override async Task HandleAsync(CreatePurchaseProductDto req, CancellationToken ct) - { - Product? product = await productsRepository.FirstOrDefaultAsync(new GetProductByIdSpec(req.ProductId), ct); - if (product == null) - { - await Send.NotFoundAsync(ct); - return; - } - - PurchaseOrder? purchaseOrder = - await purchaseOrdersRepository.FirstOrDefaultAsync(new GetPurchaseOrderByIdSpec(req.PurchaseOrderId), ct); - - if (purchaseOrder == null) - { - purchaseOrder = new PurchaseOrder() - { - PurchaseConditions = req.PurchaseOrderPurchaseConditions ?? "Conditions non précisées" - }; - await purchaseOrdersRepository.AddAsync(purchaseOrder, ct); - } - - PurchaseProduct purchaseProduct = new PurchaseProduct() - { - ProductId = product.Id, - PurchaseOrderId = purchaseOrder.Id, - Quantity = req.Quantity - }; - - await purchaseProductsRepository.AddAsync(purchaseProduct, ct); - - await Send.OkAsync(mapper.Map(purchaseProduct), ct); - } -} \ No newline at end of file diff --git a/PyroFetes/Endpoints/PurchaseProducts/PatchPurchaseProductQuantityEndpoint.cs b/PyroFetes/Endpoints/PurchaseProducts/PatchPurchaseProductQuantityEndpoint.cs deleted file mode 100644 index d1aad89d..00000000 --- a/PyroFetes/Endpoints/PurchaseProducts/PatchPurchaseProductQuantityEndpoint.cs +++ /dev/null @@ -1,38 +0,0 @@ -using FastEndpoints; -using Microsoft.EntityFrameworkCore; -using PyroFetes.DTO.PurchaseProduct.Request; -using PyroFetes.DTO.PurchaseProduct.Response; -using PyroFetes.Models; -using PyroFetes.Repositories; -using PyroFetes.Specifications.PurchaseProducts; - -namespace PyroFetes.Endpoints.PurchaseProducts; - -public class PatchPurchaseProductQuantityEndpoint( - PurchaseProductsRepository purchaseProductsRepository, - AutoMapper.IMapper mapper) : Endpoint -{ - public override void Configure() - { - Patch("/purchaseProducts/{@ProductId}/{@PurchaseOrderId}/Quantity", x => new { x.ProductId, x.PurchaseOrderId }); - AllowAnonymous(); - } - - public override async Task HandleAsync(PatchPurchaseProductQuantityDto req, CancellationToken ct) - { - PurchaseProduct? purchaseProduct = - await purchaseProductsRepository.FirstOrDefaultAsync( - new GetPurchaseProductByProductIdAndPurchaseOrderIdSpec(req.ProductId, req.PurchaseOrderId), ct); - - if (purchaseProduct == null) - { - await Send.NotFoundAsync(ct); - return; - } - - purchaseProduct.Quantity = req.Quantity; - await purchaseProductsRepository.UpdateAsync(purchaseProduct, ct); - - await Send.OkAsync(mapper.Map(purchaseProduct), ct); - } -} \ No newline at end of file diff --git a/PyroFetes/Endpoints/QuotationProducts/CreateQuotationProductEndpoint.cs b/PyroFetes/Endpoints/QuotationProducts/CreateQuotationProductEndpoint.cs deleted file mode 100644 index 2c13b2e9..00000000 --- a/PyroFetes/Endpoints/QuotationProducts/CreateQuotationProductEndpoint.cs +++ /dev/null @@ -1,58 +0,0 @@ -using FastEndpoints; -using Microsoft.EntityFrameworkCore; -using PyroFetes.DTO.QuotationProduct.Request; -using PyroFetes.DTO.QuotationProduct.Response; -using PyroFetes.Models; -using PyroFetes.Repositories; -using PyroFetes.Specifications.Products; -using PyroFetes.Specifications.Quotations; - -namespace PyroFetes.Endpoints.QuotationProducts; - -public class CreateQuotationProductEndpoint( - QuotationProductsRepository quotationProductsRepository, - ProductsRepository productsRepository, - QuotationsRepository quotationsRepository, - AutoMapper.IMapper mapper) : Endpoint -{ - public override void Configure() - { - Post("/quotationProducts"); - AllowAnonymous(); - } - - public override async Task HandleAsync(CreateQuotationProductDto req, CancellationToken ct) - { - Product? product = await productsRepository.FirstOrDefaultAsync(new GetProductByIdSpec(req.ProductId), ct); - - if (product == null) - { - await Send.NotFoundAsync(ct); - return; - } - - Quotation? quotation = await quotationsRepository.FirstOrDefaultAsync(new GetQuotationByIdSpec(req.QuotationId), ct); - - if (quotation == null) - { - quotation = new Quotation() - { - Message = req.QuotationMessage ?? "", - ConditionsSale = req.QuotationConditionsSale, - }; - - await quotationsRepository.AddAsync(quotation, ct); - } - - QuotationProduct quotationProduct = new QuotationProduct() - { - ProductId = product.Id, - QuotationId = quotation.Id, - Quantity = req.Quantity - }; - - await quotationProductsRepository.AddAsync(quotationProduct, ct); - - await Send.OkAsync(mapper.Map(quotationProduct), ct); - } -} diff --git a/PyroFetes/Endpoints/Quotations/AddProductoToQuotationEndpoint.cs b/PyroFetes/Endpoints/Quotations/AddProductoToQuotationEndpoint.cs new file mode 100644 index 00000000..9d71325b --- /dev/null +++ b/PyroFetes/Endpoints/Quotations/AddProductoToQuotationEndpoint.cs @@ -0,0 +1,35 @@ +using FastEndpoints; +using PyroFetes.DTO.QuotationProduct.Request; +using PyroFetes.DTO.QuotationProduct.Response; +using PyroFetes.Models; +using PyroFetes.Repositories; +using PyroFetes.Specifications.QuotationProducts; + +namespace PyroFetes.Endpoints.Quotations; + +public class AddProductoToQuotationEndpoint( + QuotationProductsRepository quotationProductsRepository, + AutoMapper.IMapper mapper) : Endpoint +{ + public override void Configure() + { + Post("/quotations/{@Id}/products", x => new { x.ProductId, x.QuotationId }); + AllowAnonymous(); + } + + public override async Task HandleAsync(AddQuotationProductDto req, CancellationToken ct) + { + QuotationProduct? productQuotation = await quotationProductsRepository.SingleOrDefaultAsync(new GetQuotationProductByProductIdAndQuotationIdSpec(req.ProductId, req.QuotationId), ct); + + if (productQuotation is not null) + { + await Send.StringAsync("ce produit existe déjà dans le devis", 400, cancellation: ct); + return; + } + + QuotationProduct quotationProduct = mapper.Map(req); + + await quotationProductsRepository.AddAsync(quotationProduct, ct); + await Send.NoContentAsync(ct); + } +} \ No newline at end of file diff --git a/PyroFetes/Endpoints/Quotations/CreateQuotationEndpoint.cs b/PyroFetes/Endpoints/Quotations/CreateQuotationEndpoint.cs index a7003c86..c8ba9553 100644 --- a/PyroFetes/Endpoints/Quotations/CreateQuotationEndpoint.cs +++ b/PyroFetes/Endpoints/Quotations/CreateQuotationEndpoint.cs @@ -1,15 +1,19 @@ using FastEndpoints; using PyroFetes.DTO.Quotation.Request; using PyroFetes.DTO.Quotation.Response; +using PyroFetes.DTO.QuotationProduct.Request; using PyroFetes.Models; using PyroFetes.Repositories; +using PyroFetes.Specifications.Products; +using PyroFetes.Specifications.QuotationProducts; namespace PyroFetes.Endpoints.Quotations; public class CreateQuotationEndpoint( QuotationsRepository quotationsRepository, + QuotationProductsRepository quotationProductsRepository, ProductsRepository productsRepository, - AutoMapper.IMapper mapper) : Endpoint + AutoMapper.IMapper mapper) : Endpoint { public override void Configure() { @@ -19,32 +23,36 @@ public class CreateQuotationEndpoint( public override async Task HandleAsync(CreateQuotationDto req, CancellationToken ct) { - Quotation quotation = new Quotation - { - Message = req.Message, - ConditionsSale = req.ConditionsSale ?? "Conditions non précisées", - CustomerId = 1, // A changer - QuotationProducts = new List() - }; + Quotation quotation = mapper.Map(req); + quotation.CustomerId = 1; // TODO: A changer - foreach (var line in req.Products) + if (req.Products != null) { - var product = await productsRepository.GetByIdAsync(line.ProductId, ct); - if (product == null) + foreach (CreateProductQuotationDto line in req.Products) { - await Send.NotFoundAsync(ct); - return; + Product? product = await productsRepository.SingleOrDefaultAsync(new GetProductByIdSpec(line.ProductId), ct); + QuotationProduct? quotationProduct = + await quotationProductsRepository.SingleOrDefaultAsync(new GetQuotationProductByProductIdAndQuotationIdSpec(line.ProductId, quotation.Id), ct); + + if (product is null) + { + await Send.NotFoundAsync(ct); + return; + } + + if (quotationProduct is not null) + { + await Send.StringAsync("Le produit est déjà dans le devis", 400, cancellation: ct); + } + + QuotationProduct? productOnQuotation = mapper.Map(line); + productOnQuotation.QuotationId = quotation.Id; + + await quotationProductsRepository.AddAsync(productOnQuotation, ct); } - - quotation.QuotationProducts.Add(new QuotationProduct - { - ProductId = product.Id, - Quantity = line.Quantity, - }); } await quotationsRepository.AddAsync(quotation, ct); - - await Send.OkAsync(mapper.Map(quotation), ct); + await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/QuotationProducts/DeleteQuotationProductEndpoint.cs b/PyroFetes/Endpoints/Quotations/DeleteProductFromQuotationEndpoint.cs similarity index 55% rename from PyroFetes/Endpoints/QuotationProducts/DeleteQuotationProductEndpoint.cs rename to PyroFetes/Endpoints/Quotations/DeleteProductFromQuotationEndpoint.cs index 554ccd4d..569694e2 100644 --- a/PyroFetes/Endpoints/QuotationProducts/DeleteQuotationProductEndpoint.cs +++ b/PyroFetes/Endpoints/Quotations/DeleteProductFromQuotationEndpoint.cs @@ -1,10 +1,9 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.QuotationProducts; -namespace PyroFetes.Endpoints.QuotationProducts; +namespace PyroFetes.Endpoints.Quotations; public class DeleteQuotationProductRequest { @@ -12,28 +11,26 @@ public class DeleteQuotationProductRequest public int QuotationId { get; set; } } -public class DeleteQuotationProductEndpoint(QuotationProductsRepository quotationProductsRepository) : Endpoint +public class DeleteProductFromQuotationEndpoint(QuotationProductsRepository quotationProductsRepository) : Endpoint { public override void Configure() { - Delete("/quotationProducts/{@ProductId}/{@QuotationId}", x => new {x.ProductId, x.QuotationId}); + Delete("/quotations/{@ProductId}/{@QuotationId}", x => new { x.ProductId, x.QuotationId }); AllowAnonymous(); } public override async Task HandleAsync(DeleteQuotationProductRequest req, CancellationToken ct) { QuotationProduct? quotationProduct = - await quotationProductsRepository.FirstOrDefaultAsync( - new GetQuotationProductByProductIdAndQuotationIdSpec(req.ProductId, req.QuotationId), ct); + await quotationProductsRepository.SingleOrDefaultAsync(new GetQuotationProductByProductIdAndQuotationIdSpec(req.ProductId, req.QuotationId), ct); - if (quotationProduct == null) + if (quotationProduct is null) { await Send.NotFoundAsync(ct); return; } - + await quotationProductsRepository.DeleteAsync(quotationProduct, ct); - await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Quotations/DeleteQuotationEndpoint.cs b/PyroFetes/Endpoints/Quotations/DeleteQuotationEndpoint.cs index 80df36cf..737fa9e3 100644 --- a/PyroFetes/Endpoints/Quotations/DeleteQuotationEndpoint.cs +++ b/PyroFetes/Endpoints/Quotations/DeleteQuotationEndpoint.cs @@ -1,5 +1,4 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.Quotations; @@ -11,33 +10,25 @@ public class DeleteQuotationRequest public int Id { get; set; } } -public class DeleteQuotationEndpoint( - QuotationsRepository quotationsRepository, - QuotationProductsRepository quotationProductsRepository) : Endpoint +public class DeleteQuotationEndpoint(QuotationsRepository quotationsRepository) : Endpoint { public override void Configure() { - Delete("/quotations/{@Id}", x => new {x.Id}); + Delete("/quotations/{@Id}", x => new { x.Id }); AllowAnonymous(); } public override async Task HandleAsync(DeleteQuotationRequest req, CancellationToken ct) { - Quotation? quotation = await quotationsRepository.FirstOrDefaultAsync(new GetQuotationByIdSpec(req.Id), ct); + Quotation? quotation = await quotationsRepository.SingleOrDefaultAsync(new GetQuotationByIdSpec(req.Id), ct); - if (quotation == null) + if (quotation is null) { await Send.NotFoundAsync(ct); return; } - - if (quotation.QuotationProducts != null && quotation.QuotationProducts.Any()) - { - await quotationProductsRepository.DeleteRangeAsync(quotation.QuotationProducts, ct); - } - + await quotationsRepository.DeleteAsync(quotation, ct); - await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Quotations/GetAllQuotationEndpoint.cs b/PyroFetes/Endpoints/Quotations/GetAllQuotationEndpoint.cs index b4674f30..9d7059d5 100644 --- a/PyroFetes/Endpoints/Quotations/GetAllQuotationEndpoint.cs +++ b/PyroFetes/Endpoints/Quotations/GetAllQuotationEndpoint.cs @@ -1,8 +1,5 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.Quotation.Response; -using PyroFetes.DTO.QuotationProduct.Response; -using PyroFetes.Models; using PyroFetes.Repositories; namespace PyroFetes.Endpoints.Quotations; diff --git a/PyroFetes/Endpoints/Quotations/GetQuotationEndpoint.cs b/PyroFetes/Endpoints/Quotations/GetQuotationEndpoint.cs index bdc57c21..bc4b4fa7 100644 --- a/PyroFetes/Endpoints/Quotations/GetQuotationEndpoint.cs +++ b/PyroFetes/Endpoints/Quotations/GetQuotationEndpoint.cs @@ -1,7 +1,5 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.Quotation.Response; -using PyroFetes.DTO.QuotationProduct.Response; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.Quotations; @@ -19,20 +17,20 @@ public class GetQuotationEndpoint( { public override void Configure() { - Get("/quotations/{@Id}", x => new {x.Id}); + Get("/quotations/{@Id}", x => new { x.Id }); AllowAnonymous(); } public override async Task HandleAsync(GetQuotationRequest req, CancellationToken ct) { - Quotation? quotation = await quotationsRepository.FirstOrDefaultAsync(new GetQuotationByIdSpec(req.Id), ct); + Quotation? quotation = await quotationsRepository.SingleOrDefaultAsync(new GetQuotationByIdSpec(req.Id), ct); - if (quotation == null) + if (quotation is null) { await Send.NotFoundAsync(ct); return; } - + await Send.OkAsync(mapper.Map(quotation), ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Quotations/GetQuotationPdfEndpoint.cs b/PyroFetes/Endpoints/Quotations/GetQuotationPdfEndpoint.cs index 29201727..0c754504 100644 --- a/PyroFetes/Endpoints/Quotations/GetQuotationPdfEndpoint.cs +++ b/PyroFetes/Endpoints/Quotations/GetQuotationPdfEndpoint.cs @@ -10,33 +10,35 @@ namespace PyroFetes.Endpoints.Quotations; public class GetQuotationPdfEndpoint( QuotationsRepository quotationRepository, - IQuotationPdfService quotationPdfService) + IQuotationPdfService quotationPdfService, + SettingsRepository settingsRepository) : Endpoint { public override void Configure() { - Get("/quotations/{@Id}/pdf", x => new {x.Id}); + Get("/quotations/{@Id}/pdf", x => new { x.Id }); AllowAnonymous(); Description(b => b.Produces(200, MediaTypeNames.Application.Pdf)); } - + public override async Task HandleAsync(GetQuotationPdfDto req, CancellationToken ct) { - Quotation? quotation = await quotationRepository - .FirstOrDefaultAsync(new GetQuotationByIdWithProductsSpec(req.Id), ct); + Quotation? quotation = await quotationRepository.SingleOrDefaultAsync(new GetQuotationByIdWithProductsSpec(req.Id), ct); - if (quotation == null) + if (quotation is null) { await Send.NotFoundAsync(ct); return; } + + Setting? setting = await settingsRepository.FirstOrDefaultAsync(ct); - var bytes = quotationPdfService.Generate(quotation, quotation.QuotationProducts!); + byte[] bytes = quotationPdfService.Generate(quotation, quotation.QuotationProducts!, setting!); await Send.BytesAsync( bytes: bytes, contentType: "application/pdf", - fileName: $"devis-{quotation.Id}.pdf", + fileName: $"devis-{quotation.Id}{DateOnly.FromDateTime(DateTime.Now)}.pdf", cancellation: ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Quotations/PatchQuotationConditionsSaleEndpoint.cs b/PyroFetes/Endpoints/Quotations/PatchQuotationConditionsSaleEndpoint.cs index e8287f16..c0a80a89 100644 --- a/PyroFetes/Endpoints/Quotations/PatchQuotationConditionsSaleEndpoint.cs +++ b/PyroFetes/Endpoints/Quotations/PatchQuotationConditionsSaleEndpoint.cs @@ -9,7 +9,7 @@ namespace PyroFetes.Endpoints.Quotations; public class PatchQuotationConditionsSaleEndpoint( QuotationsRepository quotationsRepository, - AutoMapper.IMapper mapper) : Endpoint + AutoMapper.IMapper mapper) : Endpoint { public override void Configure() { @@ -19,18 +19,17 @@ public class PatchQuotationConditionsSaleEndpoint( public override async Task HandleAsync(PatchQuotationConditionsSaleDto req, CancellationToken ct) { - Quotation? quotation = await quotationsRepository.FirstOrDefaultAsync(new GetQuotationByIdSpec(req.Id), ct); - - if (quotation == null) + Quotation? quotation = await quotationsRepository.SingleOrDefaultAsync(new GetQuotationByIdSpec(req.Id), ct); + + if (quotation is null) { await Send.NotFoundAsync(ct); return; } - - quotation.ConditionsSale = req.ConditionsSale; - await quotationsRepository.UpdateAsync(quotation, ct); + mapper.Map(req, quotation); - await Send.OkAsync(mapper.Map(quotation), ct); + await quotationsRepository.SaveChangesAsync(ct); + await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Quotations/PatchQuotationMessageEndpoint.cs b/PyroFetes/Endpoints/Quotations/PatchQuotationMessageEndpoint.cs new file mode 100644 index 00000000..8de48b48 --- /dev/null +++ b/PyroFetes/Endpoints/Quotations/PatchQuotationMessageEndpoint.cs @@ -0,0 +1,35 @@ +using FastEndpoints; +using PyroFetes.DTO.Quotation.Request; +using PyroFetes.DTO.Quotation.Response; +using PyroFetes.Models; +using PyroFetes.Repositories; +using PyroFetes.Specifications.Quotations; + +namespace PyroFetes.Endpoints.Quotations; + +public class PatchQuotationMessageEndpoint( + QuotationsRepository quotationsRepository, + AutoMapper.IMapper mapper) : Endpoint +{ + public override void Configure() + { + Patch("/quotations/{@Id}/message", x => new { x.Id }); + AllowAnonymous(); + } + + public override async Task HandleAsync(PatchQuotationMessageDto req, CancellationToken ct) + { + Quotation? quotation = await quotationsRepository.SingleOrDefaultAsync(new GetQuotationByIdSpec(req.Id), ct); + + if (quotation is null) + { + await Send.NotFoundAsync(ct); + return; + } + + mapper.Map(req, quotation); + + await quotationsRepository.SaveChangesAsync(ct); + await Send.NoContentAsync(ct); + } +} \ No newline at end of file diff --git a/PyroFetes/Endpoints/QuotationProducts/PatchQuotationProductQuantityEndpoint.cs b/PyroFetes/Endpoints/Quotations/PatchQuotationProductQuantityEndpoint.cs similarity index 52% rename from PyroFetes/Endpoints/QuotationProducts/PatchQuotationProductQuantityEndpoint.cs rename to PyroFetes/Endpoints/Quotations/PatchQuotationProductQuantityEndpoint.cs index de8546ef..ad036271 100644 --- a/PyroFetes/Endpoints/QuotationProducts/PatchQuotationProductQuantityEndpoint.cs +++ b/PyroFetes/Endpoints/Quotations/PatchQuotationProductQuantityEndpoint.cs @@ -1,37 +1,35 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.QuotationProduct.Request; using PyroFetes.DTO.QuotationProduct.Response; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.QuotationProducts; -namespace PyroFetes.Endpoints.QuotationProducts; +namespace PyroFetes.Endpoints.Quotations; public class PatchQuotationProductQuantityEndpoint( QuotationProductsRepository quotationProductsRepository, - AutoMapper.IMapper mapper) : Endpoint + AutoMapper.IMapper mapper) : Endpoint { public override void Configure() { - Patch("/quotationProducts/{@ProductId}/{@QuotationId}/Quantity", x => new { x.ProductId, x.QuotationId }); + Patch("/quotations/{@ProductId}/{@QuotationId}/Quantity", x => new { x.ProductId, x.QuotationId }); AllowAnonymous(); } public override async Task HandleAsync(PatchQuotationProductQuantityDto req, CancellationToken ct) { QuotationProduct? quotationProduct = - await quotationProductsRepository.FirstOrDefaultAsync( - new GetQuotationProductByProductIdAndQuotationIdSpec(req.ProductId, req.QuotationId), ct); - if (quotationProduct == null) + await quotationProductsRepository.SingleOrDefaultAsync(new GetQuotationProductByProductIdAndQuotationIdSpec(req.ProductId, req.QuotationId), ct); + if (quotationProduct is null) { await Send.NotFoundAsync(ct); return; } + + mapper.Map(req, quotationProduct); - quotationProduct.Quantity = req.Quantity; - await quotationProductsRepository.UpdateAsync(quotationProduct, ct); - - await Send.OkAsync(mapper.Map(quotationProduct), ct); + await quotationProductsRepository.SaveChangesAsync(ct); + await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Quotations/UpdateQuotationEndpoint.cs b/PyroFetes/Endpoints/Quotations/UpdateQuotationEndpoint.cs index 3b1f47be..b383c719 100644 --- a/PyroFetes/Endpoints/Quotations/UpdateQuotationEndpoint.cs +++ b/PyroFetes/Endpoints/Quotations/UpdateQuotationEndpoint.cs @@ -9,7 +9,7 @@ namespace PyroFetes.Endpoints.Quotations; public class UpdateQuotationEndpoint( QuotationsRepository quotationsRepository, - AutoMapper.IMapper mapper) : Endpoint + AutoMapper.IMapper mapper) : Endpoint { public override void Configure() { @@ -19,18 +19,17 @@ public class UpdateQuotationEndpoint( public override async Task HandleAsync(UpdateQuotationDto req, CancellationToken ct) { - Quotation? quotation = await quotationsRepository.FirstOrDefaultAsync(new GetQuotationByIdSpec(req.Id), ct); - - if (quotation == null) + Quotation? quotation = await quotationsRepository.SingleOrDefaultAsync(new GetQuotationByIdSpec(req.Id), ct); + + if (quotation is null) { await Send.NotFoundAsync(ct); return; } + + mapper.Map(req, quotation); - quotation.ConditionsSale = req.ConditionsSale; - quotation.Message = req.Message; - await quotationsRepository.UpdateAsync(quotation, ct); - - await Send.OkAsync(mapper.Map(quotation), ct); + await quotationsRepository.SaveChangesAsync(ct); + await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Settings/CreateSettingEndpoint.cs b/PyroFetes/Endpoints/Settings/CreateSettingEndpoint.cs index 893996b9..a1a12cae 100644 --- a/PyroFetes/Endpoints/Settings/CreateSettingEndpoint.cs +++ b/PyroFetes/Endpoints/Settings/CreateSettingEndpoint.cs @@ -1,14 +1,11 @@ using FastEndpoints; using PyroFetes.DTO.SettingDTO.Request; -using PyroFetes.DTO.SettingDTO.Response; using PyroFetes.Models; using PyroFetes.Repositories; namespace PyroFetes.Endpoints.Settings; -public class CreateSettingEndpoint( - SettingsRepository settingsRepository, - AutoMapper.IMapper mapper) : Endpoint +public class CreateSettingEndpoint(SettingsRepository settingsRepository) : Endpoint { public override void Configure() { @@ -18,14 +15,21 @@ public class CreateSettingEndpoint( public override async Task HandleAsync(CreateSettingDto req, CancellationToken ct) { - Setting setting = new Setting() - { - ElectronicSignature = req.ElectronicSignature, - Logo = req.Logo - }; - - await settingsRepository.AddAsync(setting, ct); + // Encodage en base64 + using MemoryStream memoryStream = new(); + if (req.Logo != null) await req.Logo.CopyToAsync(memoryStream, ct); + byte[] logoBytes = memoryStream.ToArray(); - await Send.OkAsync(mapper.Map(setting), ct); + if (req.ElectronicSignature != null) await req.ElectronicSignature.CopyToAsync(memoryStream, ct); + byte[] signatureBytes = memoryStream.ToArray(); + + Setting setting = new() + { + ElectronicSignature = Convert.ToBase64String(signatureBytes), + Logo = Convert.ToBase64String(logoBytes) + }; + + await settingsRepository.AddAsync(setting, ct); + await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Settings/DeleteSettingEndpoint.cs b/PyroFetes/Endpoints/Settings/DeleteSettingEndpoint.cs index 2979b019..319acf93 100644 --- a/PyroFetes/Endpoints/Settings/DeleteSettingEndpoint.cs +++ b/PyroFetes/Endpoints/Settings/DeleteSettingEndpoint.cs @@ -1,5 +1,4 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.Settings; @@ -15,22 +14,21 @@ public class DeleteSettingEndpoint(SettingsRepository settingsRepository) : Endp { public override void Configure() { - Delete("/settings/{@Id}", x => new {x.Id}); + Delete("/settings/{@Id}", x => new { x.Id }); AllowAnonymous(); } - + public override async Task HandleAsync(DeleteSettingRequest req, CancellationToken ct) { - Setting? setting = await settingsRepository.FirstOrDefaultAsync(new GetSettingByIdSpec(req.Id), ct); + Setting? setting = await settingsRepository.SingleOrDefaultAsync(new GetSettingByIdSpec(req.Id), ct); - if (setting == null) + if (setting is null) { await Send.NotFoundAsync(ct); return; } - + await settingsRepository.DeleteAsync(setting, ct); - await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Settings/GetSettingEndpoint.cs b/PyroFetes/Endpoints/Settings/GetSettingEndpoint.cs index 17350084..a36dcd93 100644 --- a/PyroFetes/Endpoints/Settings/GetSettingEndpoint.cs +++ b/PyroFetes/Endpoints/Settings/GetSettingEndpoint.cs @@ -1,5 +1,4 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.SettingDTO.Response; using PyroFetes.Models; using PyroFetes.Repositories; @@ -18,15 +17,15 @@ public class GetSettingEndpoint( { public override void Configure() { - Get("/settings/{@Id}", x => new {x.Id}); + Get("/settings/{@Id}", x => new { x.Id }); AllowAnonymous(); } - + public override async Task HandleAsync(GetSettingRequest req, CancellationToken ct) { - Setting? setting = await settingsRepository.FirstOrDefaultAsync(new GetSettingByIdSpec(req.Id), ct); + Setting? setting = await settingsRepository.SingleOrDefaultAsync(new GetSettingByIdSpec(req.Id), ct); - if (setting == null) + if (setting is null) { await Send.NotFoundAsync(ct); return; diff --git a/PyroFetes/Endpoints/Settings/PatchSettingElectronicSignatureEndpoint.cs b/PyroFetes/Endpoints/Settings/PatchSettingElectronicSignatureEndpoint.cs index ca73c8c5..2aa7d4e1 100644 --- a/PyroFetes/Endpoints/Settings/PatchSettingElectronicSignatureEndpoint.cs +++ b/PyroFetes/Endpoints/Settings/PatchSettingElectronicSignatureEndpoint.cs @@ -1,36 +1,37 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.SettingDTO.Request; -using PyroFetes.DTO.SettingDTO.Response; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.Settings; namespace PyroFetes.Endpoints.Settings; -public class PatchSettingElectronicSignatureEndpoint( - SettingsRepository settingsRepository, - AutoMapper.IMapper mapper) : Endpoint +public class PatchSettingElectronicSignatureEndpoint(SettingsRepository settingsRepository) : Endpoint { public override void Configure() { - Patch("/settings/{@Id}/ElectronicSignature", x => new {x.Id}); + Patch("/settings/{@Id}/ElectronicSignature", x => new { x.Id }); AllowAnonymous(); } - + public override async Task HandleAsync(PatchSettingElectronicSignatureDto req, CancellationToken ct) { - Setting? setting = await settingsRepository.FirstOrDefaultAsync(new GetSettingByIdSpec(req.Id), ct); - - if (setting == null) + Setting? setting = await settingsRepository.SingleOrDefaultAsync(new GetSettingByIdSpec(req.Id), ct); + + if (setting is null) { await Send.NotFoundAsync(ct); return; } - setting.ElectronicSignature = req.ElectronicSignature; - await settingsRepository.UpdateAsync(setting, ct); - - await Send.OkAsync(mapper.Map(setting), ct); + // Encodage en base64 + using MemoryStream memoryStream = new(); + if (req.ElectronicSignature != null) await req.ElectronicSignature.CopyToAsync(memoryStream, ct); + byte[] signatureBytes = memoryStream.ToArray(); + + setting.ElectronicSignature = Convert.ToBase64String(signatureBytes); + + await settingsRepository.SaveChangesAsync(ct); + await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Settings/PatchSettingLogoEndpoint.cs b/PyroFetes/Endpoints/Settings/PatchSettingLogoEndpoint.cs index f180cbc7..e35bb204 100644 --- a/PyroFetes/Endpoints/Settings/PatchSettingLogoEndpoint.cs +++ b/PyroFetes/Endpoints/Settings/PatchSettingLogoEndpoint.cs @@ -1,36 +1,37 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.SettingDTO.Request; -using PyroFetes.DTO.SettingDTO.Response; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.Settings; namespace PyroFetes.Endpoints.Settings; -public class PatchSettingLogoEndpoint( - SettingsRepository settingsRepository, - AutoMapper.IMapper mapper) : Endpoint +public class PatchSettingLogoEndpoint(SettingsRepository settingsRepository) : Endpoint { public override void Configure() { - Patch("/settings/{@Id}/logo", x => new {x.Id}); + Patch("/settings/{@Id}/logo", x => new { x.Id }); AllowAnonymous(); } - + public override async Task HandleAsync(PatchSettingLogoDto req, CancellationToken ct) { - Setting? setting = await settingsRepository.FirstOrDefaultAsync(new GetSettingByIdSpec(req.Id), ct); + Setting? setting = await settingsRepository.SingleOrDefaultAsync(new GetSettingByIdSpec(req.Id), ct); - if (setting == null) + if (setting is null) { await Send.NotFoundAsync(ct); return; } - setting.Logo = req.Logo; - await settingsRepository.UpdateAsync(setting, ct); + // Encodage en base64 + using MemoryStream memoryStream = new(); + if (req.Logo != null) await req.Logo.CopyToAsync(memoryStream, ct); + byte[] logoBytes = memoryStream.ToArray(); - await Send.OkAsync(mapper.Map(setting), ct); + setting.Logo = Convert.ToBase64String(logoBytes); + + await settingsRepository.SaveChangesAsync(ct); + await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Suppliers/AddProductToSupplierEndpoint.cs b/PyroFetes/Endpoints/Suppliers/AddProductToSupplierEndpoint.cs new file mode 100644 index 00000000..6a342526 --- /dev/null +++ b/PyroFetes/Endpoints/Suppliers/AddProductToSupplierEndpoint.cs @@ -0,0 +1,43 @@ +using FastEndpoints; +using PyroFetes.DTO.Price.Request; +using PyroFetes.Models; +using PyroFetes.Repositories; +using PyroFetes.Specifications.Prices; +using PyroFetes.Specifications.Products; +using PyroFetes.Specifications.Suppliers; + +namespace PyroFetes.Endpoints.Suppliers; + +public class AddProductToSupplierEndpoint( + SuppliersRepository suppliersRepository, + ProductsRepository productsRepository, + PricesRepository pricesRepository, + AutoMapper.IMapper mapper) : Endpoint +{ + public override void Configure() + { + Post("/suppliers/{@SupplierId}/{@ProductId}/", x => new { x.SupplierId, x.ProductId }); + AllowAnonymous(); + } + + public override async Task HandleAsync(CreatePriceDto req, CancellationToken ct) + { + Supplier? supplier = await suppliersRepository.FirstOrDefaultAsync(new GetSupplierByIdSpec(req.SupplierId), ct); + Product? product = await productsRepository.SingleOrDefaultAsync(new GetProductByIdSpec(req.ProductId), ct); + if (supplier is null || product is null) + { + await Send.NotFoundAsync(ct); + return; + } + + Price? existingPrice = await pricesRepository.SingleOrDefaultAsync(new GetPriceByProductIdAndSupplierIdSpec(req.ProductId, req.SupplierId), ct); + if (existingPrice is not null) + { + await Send.StringAsync("Le fournisseur a déjà un prix pour ce produit.", 400, cancellation: ct); + return; + } + + await pricesRepository.AddAsync(mapper.Map(req), ct); + await Send.NoContentAsync(ct); + } +} \ No newline at end of file diff --git a/PyroFetes/Endpoints/Suppliers/CreateSupplierEndpoint.cs b/PyroFetes/Endpoints/Suppliers/CreateSupplierEndpoint.cs index afd95f21..6a137e68 100644 --- a/PyroFetes/Endpoints/Suppliers/CreateSupplierEndpoint.cs +++ b/PyroFetes/Endpoints/Suppliers/CreateSupplierEndpoint.cs @@ -1,14 +1,11 @@ using FastEndpoints; using PyroFetes.DTO.Supplier.Request; -using PyroFetes.DTO.Supplier.Response; using PyroFetes.Models; using PyroFetes.Repositories; namespace PyroFetes.Endpoints.Suppliers; -public class CreateSupplierEndpoint( - SuppliersRepository suppliersRepository, - AutoMapper.IMapper mapper) : Endpoint +public class CreateSupplierEndpoint(SuppliersRepository suppliersRepository, AutoMapper.IMapper mapper) : Endpoint { public override void Configure() { @@ -18,19 +15,7 @@ public class CreateSupplierEndpoint( public override async Task HandleAsync(CreateSupplierDto req, CancellationToken ct) { - Supplier? supplier = new Supplier() - { - Name = req.Name, - Email = req.Email, - Phone = req.Phone, - Address = req.Address, - City = req.City, - ZipCode = req.ZipCode, - DeliveryDelay = req.DeliveryDelay - }; - - await suppliersRepository.AddAsync(supplier, ct); - - await Send.OkAsync(mapper.Map(supplier), ct); + await suppliersRepository.AddAsync(mapper.Map(req), ct); + await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Prices/DeletePriceEndpoint.cs b/PyroFetes/Endpoints/Suppliers/DeleteProductToSupplierEndpoint.cs similarity index 51% rename from PyroFetes/Endpoints/Prices/DeletePriceEndpoint.cs rename to PyroFetes/Endpoints/Suppliers/DeleteProductToSupplierEndpoint.cs index 6ff65772..8c2e5144 100644 --- a/PyroFetes/Endpoints/Prices/DeletePriceEndpoint.cs +++ b/PyroFetes/Endpoints/Suppliers/DeleteProductToSupplierEndpoint.cs @@ -1,10 +1,9 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.Prices; -namespace PyroFetes.Endpoints.Prices; +namespace PyroFetes.Endpoints.Suppliers; public class DeletePriceRequest { @@ -12,26 +11,25 @@ public class DeletePriceRequest public int SupplierId { get; set; } } -public class DeletePriceEndpoint(PricesRepository pricesRepository) : Endpoint +public class DeleteProductToSupplierEndpoint(PricesRepository pricesRepository) : Endpoint { public override void Configure() { - Delete("/prices/{@ProductId}/{@SupplierId}", x => new {x.ProductId, x.SupplierId}); + Delete("/suppliers/{@SupplierId}/{@Product}", x => new { x.SupplierId, x.ProductId }); AllowAnonymous(); } public override async Task HandleAsync(DeletePriceRequest req, CancellationToken ct) { - Price? price = await pricesRepository.FirstOrDefaultAsync(new GetPriceByProductIdAndSupplierIdSpec(req.ProductId,req.SupplierId), ct); + Price? price = await pricesRepository.SingleOrDefaultAsync(new GetPriceByProductIdAndSupplierIdSpec(req.ProductId, req.SupplierId), ct); - if (price == null) + if (price is null) { await Send.NotFoundAsync(ct); return; } - - await pricesRepository.DeleteAsync(price, ct); - + + await pricesRepository.DeleteAsync(price, ct); await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Suppliers/DeleteSupplierEndpoint.cs b/PyroFetes/Endpoints/Suppliers/DeleteSupplierEndpoint.cs index 67860154..40f26556 100644 --- a/PyroFetes/Endpoints/Suppliers/DeleteSupplierEndpoint.cs +++ b/PyroFetes/Endpoints/Suppliers/DeleteSupplierEndpoint.cs @@ -1,5 +1,4 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.Suppliers; @@ -15,22 +14,21 @@ public class DeleteSupplierEndpoint(SuppliersRepository suppliersRepository) : E { public override void Configure() { - Delete("/suppliers/{@Id}", x => new {x.Id}); + Delete("/suppliers/{@Id}", x => new { x.Id }); AllowAnonymous(); } - + public override async Task HandleAsync(DeleteSupplierRequest req, CancellationToken ct) { - Supplier? supplier = await suppliersRepository.FirstOrDefaultAsync(new GetSupplierByIdSpec(req.Id), ct); + Supplier? supplier = await suppliersRepository.SingleOrDefaultAsync(new GetSupplierByIdSpec(req.Id), ct); - if (supplier == null) + if (supplier is null) { await Send.NotFoundAsync(ct); return; } - - await suppliersRepository.DeleteAsync(supplier, ct); - + + await suppliersRepository.DeleteAsync(supplier, ct); await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Suppliers/GetAllSuppliersEndpoint.cs b/PyroFetes/Endpoints/Suppliers/GetAllSuppliersEndpoint.cs index 3c655f8d..5a8bc289 100644 --- a/PyroFetes/Endpoints/Suppliers/GetAllSuppliersEndpoint.cs +++ b/PyroFetes/Endpoints/Suppliers/GetAllSuppliersEndpoint.cs @@ -1,5 +1,4 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.Supplier.Response; using PyroFetes.Repositories; diff --git a/PyroFetes/Endpoints/Suppliers/GetSupplierEndpoint.cs b/PyroFetes/Endpoints/Suppliers/GetSupplierEndpoint.cs index 50fbb54f..29ba25a8 100644 --- a/PyroFetes/Endpoints/Suppliers/GetSupplierEndpoint.cs +++ b/PyroFetes/Endpoints/Suppliers/GetSupplierEndpoint.cs @@ -1,5 +1,4 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.Supplier.Response; using PyroFetes.Models; using PyroFetes.Repositories; @@ -12,21 +11,19 @@ public class GetSupplierRequest public int Id { get; set; } } -public class GetSupplierEndpoint( - SuppliersRepository suppliersRepository, - AutoMapper.IMapper mapper) : Endpoint +public class GetSupplierEndpoint(SuppliersRepository suppliersRepository, AutoMapper.IMapper mapper) : Endpoint { public override void Configure() { - Get("/suppliers/{@Id}", x => new {x.Id}); + Get("/suppliers/{@Id}", x => new { x.Id }); AllowAnonymous(); } - + public override async Task HandleAsync(GetSupplierRequest req, CancellationToken ct) { - Supplier? supplier = await suppliersRepository.FirstOrDefaultAsync(new GetSupplierByIdSpec(req.Id), ct); + Supplier? supplier = await suppliersRepository.SingleOrDefaultAsync(new GetSupplierByIdSpec(req.Id), ct); - if (supplier == null) + if (supplier is null) { await Send.NotFoundAsync(ct); return; diff --git a/PyroFetes/Endpoints/Prices/PatchPriceEndpoint.cs b/PyroFetes/Endpoints/Suppliers/PatchPriceEndpoint.cs similarity index 59% rename from PyroFetes/Endpoints/Prices/PatchPriceEndpoint.cs rename to PyroFetes/Endpoints/Suppliers/PatchPriceEndpoint.cs index 23cb247c..b6ab7ac4 100644 --- a/PyroFetes/Endpoints/Prices/PatchPriceEndpoint.cs +++ b/PyroFetes/Endpoints/Suppliers/PatchPriceEndpoint.cs @@ -1,15 +1,14 @@ using FastEndpoints; using PyroFetes.DTO.Price.Request; -using PyroFetes.DTO.Price.Response; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.Prices; -namespace PyroFetes.Endpoints.Prices; +namespace PyroFetes.Endpoints.Suppliers; public class PatchPriceEndpoint( PricesRepository pricesRepository, - AutoMapper.IMapper mapper) : Endpoint + AutoMapper.IMapper mapper) : Endpoint { public override void Configure() { @@ -19,18 +18,17 @@ public class PatchPriceEndpoint( public override async Task HandleAsync(PatchPriceSellingPriceDto req, CancellationToken ct) { - Price? price = await pricesRepository.FirstOrDefaultAsync(new GetPriceByProductIdAndSupplierIdSpec(req.ProductId, req.SupplierId),ct); - - if (price == null) + Price? price = await pricesRepository.SingleOrDefaultAsync(new GetPriceByProductIdAndSupplierIdSpec(req.ProductId, req.SupplierId), ct); + + if (price is null) { await Send.NotFoundAsync(ct); return; } + + mapper.Map(req, price); - price.SellingPrice = req.SellingPrice; - - await pricesRepository.UpdateAsync(price, ct); - - await Send.OkAsync(mapper.Map(price), ct); + await pricesRepository.SaveChangesAsync(ct); + await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Suppliers/PatchSupplierDeliveryDelayEndpoint.cs b/PyroFetes/Endpoints/Suppliers/PatchSupplierDeliveryDelayEndpoint.cs index 0a832539..b058225f 100644 --- a/PyroFetes/Endpoints/Suppliers/PatchSupplierDeliveryDelayEndpoint.cs +++ b/PyroFetes/Endpoints/Suppliers/PatchSupplierDeliveryDelayEndpoint.cs @@ -1,5 +1,4 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.Supplier.Request; using PyroFetes.DTO.Supplier.Response; using PyroFetes.Models; @@ -8,29 +7,27 @@ using PyroFetes.Specifications.Suppliers; namespace PyroFetes.Endpoints.Suppliers; -public class PatchSupplierDeliveryDelayEndpoint( - SuppliersRepository suppliersRepository, - AutoMapper.IMapper mapper) : Endpoint +public class PatchSupplierDeliveryDelayEndpoint(SuppliersRepository suppliersRepository, AutoMapper.IMapper mapper) : Endpoint { public override void Configure() { - Patch("/suppliers/{@Id}/deliveryDelay", x => new {x.Id}); + Patch("/suppliers/{@Id}/deliveryDelay", x => new { x.Id }); AllowAnonymous(); } - + public override async Task HandleAsync(PatchSupplierDeliveryDelayDto req, CancellationToken ct) { - Supplier? supplier = await suppliersRepository.FirstOrDefaultAsync(new GetSupplierByIdSpec(req.Id), ct); + Supplier? supplier = await suppliersRepository.SingleOrDefaultAsync(new GetSupplierByIdSpec(req.Id), ct); - if (supplier == null) + if (supplier is null) { await Send.NotFoundAsync(ct); return; } supplier.DeliveryDelay = req.DeliveryDelay; - await suppliersRepository.UpdateAsync(supplier, ct); - + await suppliersRepository.SaveChangesAsync(ct); + await Send.OkAsync(mapper.Map(supplier), ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Suppliers/UpdateSupplierEndpoint.cs b/PyroFetes/Endpoints/Suppliers/UpdateSupplierEndpoint.cs index 79206ce2..d9f79f6d 100644 --- a/PyroFetes/Endpoints/Suppliers/UpdateSupplierEndpoint.cs +++ b/PyroFetes/Endpoints/Suppliers/UpdateSupplierEndpoint.cs @@ -1,43 +1,31 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.Supplier.Request; -using PyroFetes.DTO.Supplier.Response; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.Suppliers; namespace PyroFetes.Endpoints.Suppliers; -public class UpdateSupplierEndpoint( - SuppliersRepository suppliersRepository, - AutoMapper.IMapper mapper) : Endpoint +public class UpdateSupplierEndpoint(SuppliersRepository suppliersRepository, AutoMapper.IMapper mapper) : Endpoint { public override void Configure() { - Put("/suppliers/{@Id}", x => new {x.Id}); + Put("/suppliers/{@Id}", x => new { x.Id }); AllowAnonymous(); } public override async Task HandleAsync(UpdateSupplierDto req, CancellationToken ct) { Supplier? supplier = await suppliersRepository.FirstOrDefaultAsync(new GetSupplierByIdSpec(req.Id), ct); - - if (supplier == null) + if (supplier is null) { await Send.NotFoundAsync(ct); return; } - supplier.Name = req.Name; - supplier.Email = req.Email; - supplier.Phone = req.Phone; - supplier.Address = req.Address; - supplier.City = req.City; - supplier.ZipCode = req.ZipCode; - supplier.DeliveryDelay = req.DeliveryDelay; - - await suppliersRepository.UpdateAsync(supplier, ct); - - await Send.OkAsync(mapper.Map(supplier), ct); + mapper.Map(req, supplier); + + await suppliersRepository.SaveChangesAsync(ct); + await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Users/ConnectUserEndpoint.cs b/PyroFetes/Endpoints/Users/ConnectUserEndpoint.cs index 07e6eaaa..14314c0b 100644 --- a/PyroFetes/Endpoints/Users/ConnectUserEndpoint.cs +++ b/PyroFetes/Endpoints/Users/ConnectUserEndpoint.cs @@ -19,31 +19,30 @@ public class ConnectUserEndpoint(UsersRepository usersRepository) : Endpoint - { - o.SigningKey = "ThisIsASuperSecretJwtKeyThatIsAtLeast32CharsLong"; - o.ExpireAt = DateTime.UtcNow.AddMinutes(15); - if (user.Fonction != null) o.User.Roles.Add(user.Fonction); - o.User.Claims.Add(("Name", user.Name)!); - o.User.Claims.Add(("Id", user.Id.ToString())!); - }); + string jwtToken = JwtBearer.CreateToken(o => + { + o.SigningKey = "ThisIsASuperSecretJwtKeyThatIsAtLeast32CharsLong"; + o.ExpireAt = DateTime.UtcNow.AddMinutes(15); + if (user.Fonction is not null) o.User.Roles.Add(user.Fonction); + o.User.Claims.Add(("Name", user.Name)!); + o.User.Claims.Add(("Id", user.Id.ToString())!); + }); GetTokenDto responseDto = new() { Token = jwtToken }; - + await Send.OkAsync(responseDto, ct); } else await Send.UnauthorizedAsync(ct); diff --git a/PyroFetes/Endpoints/Users/CreateUserEndpoint.cs b/PyroFetes/Endpoints/Users/CreateUserEndpoint.cs index 73c557bd..a4f183a7 100644 --- a/PyroFetes/Endpoints/Users/CreateUserEndpoint.cs +++ b/PyroFetes/Endpoints/Users/CreateUserEndpoint.cs @@ -8,9 +8,7 @@ using PyroFetes.Specifications.Users; namespace PyroFetes.Endpoints.Users; -public class CreateUserEndpoint( - UsersRepository usersRepository, - AutoMapper.IMapper mapper) : Endpoint +public class CreateUserEndpoint(UsersRepository usersRepository) : Endpoint { public override void Configure() { @@ -20,17 +18,17 @@ public class CreateUserEndpoint( public override async Task HandleAsync(CreateUserDto req, CancellationToken ct) { - User? ckeckName = await usersRepository.FirstOrDefaultAsync(new GetUserByNameSpec(req.Name!), ct); - - if (ckeckName != null) + User? ckeckName = await usersRepository.SingleOrDefaultAsync(new GetUserByNameSpec(req.Name!), ct); + + if (ckeckName is not null) { - await Send.StringAsync("Ce nom d'utilisateur existe déjà.",409, cancellation: ct); + await Send.StringAsync("Ce nom d'utilisateur existe déjà.", 400, cancellation: ct); return; } - + string? salt = new Password().IncludeLowercase().IncludeUppercase().IncludeNumeric().LengthRequired(24).Next(); - - User user = new User() + + User user = new() { Name = req.Name, Password = BCrypt.Net.BCrypt.HashPassword(req.Password + salt), @@ -38,9 +36,8 @@ public class CreateUserEndpoint( Email = req.Email, Fonction = req.Fonction }; - + await usersRepository.AddAsync(user, ct); - - await Send.OkAsync(mapper.Map(user), ct); + await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Users/DeleteUserEndpoint.cs b/PyroFetes/Endpoints/Users/DeleteUserEndpoint.cs index 859d5486..32726e49 100644 --- a/PyroFetes/Endpoints/Users/DeleteUserEndpoint.cs +++ b/PyroFetes/Endpoints/Users/DeleteUserEndpoint.cs @@ -1,5 +1,4 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.Users; @@ -15,22 +14,21 @@ public class DeleteUserEndpoint(UsersRepository usersRepository) : Endpoint new {x.Id}); + Delete("/users/{@Id}", x => new { x.Id }); AllowAnonymous(); } public override async Task HandleAsync(DeleteUserRequest req, CancellationToken ct) { - User? user = await usersRepository.FirstOrDefaultAsync(new GetUserByIdSpec(req.Id), ct); + User? user = await usersRepository.SingleOrDefaultAsync(new GetUserByIdSpec(req.Id), ct); - if (user == null) + if (user is null) { await Send.NotFoundAsync(ct); return; } - + await usersRepository.DeleteAsync(user, ct); - await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Users/GetAllUsersEndpoint.cs b/PyroFetes/Endpoints/Users/GetAllUsersEndpoint.cs index 6a36ca98..46b50037 100644 --- a/PyroFetes/Endpoints/Users/GetAllUsersEndpoint.cs +++ b/PyroFetes/Endpoints/Users/GetAllUsersEndpoint.cs @@ -1,5 +1,4 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.User.Response; using PyroFetes.Repositories; diff --git a/PyroFetes/Endpoints/Users/GetUserEndpoint.cs b/PyroFetes/Endpoints/Users/GetUserEndpoint.cs index a03e04f6..c6b5d452 100644 --- a/PyroFetes/Endpoints/Users/GetUserEndpoint.cs +++ b/PyroFetes/Endpoints/Users/GetUserEndpoint.cs @@ -1,5 +1,4 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.User.Response; using PyroFetes.Models; using PyroFetes.Repositories; @@ -12,26 +11,24 @@ public class GetUserRequest public int Id { get; set; } } -public class GetUserEndpoint( - UsersRepository usersRepository, - AutoMapper.IMapper mapper) : Endpoint +public class GetUserEndpoint(UsersRepository usersRepository, AutoMapper.IMapper mapper) : Endpoint { public override void Configure() { - Get("/users/{@Id}", x => new {x.Id}); + Get("/users/{@Id}", x => new { x.Id }); AllowAnonymous(); } public override async Task HandleAsync(GetUserRequest req, CancellationToken ct) { - User? user = await usersRepository.FirstOrDefaultAsync(new GetUserByIdSpec(req.Id), ct); + User? user = await usersRepository.SingleOrDefaultAsync(new GetUserByIdSpec(req.Id), ct); - if (user == null) + if (user is null) { await Send.NotFoundAsync(ct); return; } - + await Send.OkAsync(mapper.Map(user), ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Users/PatchUserPasswordEndpoint.cs b/PyroFetes/Endpoints/Users/PatchUserPasswordEndpoint.cs index 1647bd41..d56153d7 100644 --- a/PyroFetes/Endpoints/Users/PatchUserPasswordEndpoint.cs +++ b/PyroFetes/Endpoints/Users/PatchUserPasswordEndpoint.cs @@ -1,5 +1,4 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.User.Request; using PyroFetes.DTO.User.Response; using PyroFetes.Models; @@ -8,9 +7,7 @@ using PyroFetes.Specifications.Users; namespace PyroFetes.Endpoints.Users; -public class PatchUserPasswordEndpoint( - UsersRepository usersRepository, - AutoMapper.IMapper mapper) : Endpoint +public class PatchUserPasswordEndpoint(UsersRepository usersRepository,AutoMapper.IMapper mapper) : Endpoint { public override void Configure() { @@ -20,9 +17,9 @@ public class PatchUserPasswordEndpoint( public override async Task HandleAsync(PatchUserPasswordDto req, CancellationToken ct) { - User? user = await usersRepository.FirstOrDefaultAsync(new GetUserByIdSpec(req.Id), ct); - - if (user == null) + User? user = await usersRepository.SingleOrDefaultAsync(new GetUserByIdSpec(req.Id), ct); + + if (user is null) { await Send.NotFoundAsync(ct); return; @@ -30,7 +27,7 @@ public class PatchUserPasswordEndpoint( user.Password = BCrypt.Net.BCrypt.HashPassword(req.Password + user.Salt); await usersRepository.UpdateAsync(user, ct); - - await Send.OkAsync(mapper.Map(user), ct); + + await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/Users/UpdateUserEndpoint.cs b/PyroFetes/Endpoints/Users/UpdateUserEndpoint.cs index 46eac236..ead9dbba 100644 --- a/PyroFetes/Endpoints/Users/UpdateUserEndpoint.cs +++ b/PyroFetes/Endpoints/Users/UpdateUserEndpoint.cs @@ -1,5 +1,4 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PasswordGenerator; using PyroFetes.DTO.User.Request; using PyroFetes.DTO.User.Response; @@ -9,43 +8,41 @@ using PyroFetes.Specifications.Users; namespace PyroFetes.Endpoints.Users; -public class UpdateUserEndpoint( - UsersRepository usersRepository, - AutoMapper.IMapper mapper) : Endpoint +public class UpdateUserEndpoint(UsersRepository usersRepository) : Endpoint { public override void Configure() { - Put("/users/{@Id}", x => new {x.Id}); + Put("/users/{@Id}", x => new { x.Id }); AllowAnonymous(); } public override async Task HandleAsync(UpdateUserDto req, CancellationToken ct) { - User? user = await usersRepository.FirstOrDefaultAsync(new GetUserByIdSpec(req.Id), ct); - User? ckeckName = await usersRepository.FirstOrDefaultAsync(new GetUserByNameSpec(req.Name!), ct); + User? user = await usersRepository.SingleOrDefaultAsync(new GetUserByIdSpec(req.Id), ct); + User? ckeckName = await usersRepository.SingleOrDefaultAsync(new GetUserByNameSpec(req.Name!), ct); - if (user == null) + if (user is null) { await Send.NotFoundAsync(ct); return; } - - if (ckeckName != null && ckeckName.Id != user.Id) + + if (ckeckName is not null && ckeckName.Id != user.Id) { - await Send.StringAsync("Ce nom d'utilisateur existe déjà.",409, cancellation: ct); + await Send.StringAsync("Ce nom d'utilisateur existe déjà.", 400, cancellation: ct); return; } string? salt = new Password().IncludeLowercase().IncludeUppercase().IncludeNumeric().LengthRequired(24).Next(); - + user.Name = req.Name; user.Password = BCrypt.Net.BCrypt.HashPassword(req.Password + salt); user.Salt = salt; user.Email = req.Email; user.Fonction = req.Fonction; - + await usersRepository.UpdateAsync(user, ct); - - await Send.OkAsync(mapper.Map(user), ct); + + await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/Endpoints/WareHouseProducts/GetTotalQuantityEndpoint.cs b/PyroFetes/Endpoints/WareHouseProducts/GetTotalQuantityEndpoint.cs index 01011189..f24ae3e6 100644 --- a/PyroFetes/Endpoints/WareHouseProducts/GetTotalQuantityEndpoint.cs +++ b/PyroFetes/Endpoints/WareHouseProducts/GetTotalQuantityEndpoint.cs @@ -1,7 +1,5 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.WareHouseProduct.Response; -using PyroFetes.Models; using PyroFetes.Repositories; using PyroFetes.Specifications.WarehouseProducts; @@ -20,21 +18,20 @@ public class GetTotalQuantityEndpoint( Get("/wareHouseProducts/{@ProductId}", x => new { x.ProductId }); AllowAnonymous(); } - + public override async Task HandleAsync(GetTotalQuantityRequest req, CancellationToken ct) { - bool exists = await warehouseProductsRepository.AnyAsync(new GetWarehouseProductByProductIdSpec(req.ProductId), ct); + bool exists = await warehouseProductsRepository.AnyAsync(new GetWarehouseProductByProductIdSpec(req.ProductId, null), ct); if (!exists) { await Send.NotFoundAsync(ct); return; } - - int? totalQuantityNullable = await warehouseProductsRepository. - SumAsync(new GetProductTotalQuantitySpec(req.ProductId), wp => wp.Quantity, ct); - - int totalQuantity = totalQuantityNullable ?? 0; + + int? totalQuantityNullable = await warehouseProductsRepository.SumAsync(new GetProductTotalQuantitySpec(req.ProductId), wp => wp.Quantity, ct); + + int totalQuantity = totalQuantityNullable ?? 0; GetTotalQuantityDto responseDto = new() { diff --git a/PyroFetes/Endpoints/WareHouseProducts/PatchWareHouseProductQuantityEndpoint.cs b/PyroFetes/Endpoints/WareHouseProducts/PatchWareHouseProductQuantityEndpoint.cs index 93a4e07c..ff41e56c 100644 --- a/PyroFetes/Endpoints/WareHouseProducts/PatchWareHouseProductQuantityEndpoint.cs +++ b/PyroFetes/Endpoints/WareHouseProducts/PatchWareHouseProductQuantityEndpoint.cs @@ -1,13 +1,13 @@ using FastEndpoints; -using Microsoft.EntityFrameworkCore; using PyroFetes.DTO.WareHouseProduct.Request; using PyroFetes.DTO.WareHouseProduct.Response; using PyroFetes.Models; +using PyroFetes.Repositories; +using PyroFetes.Specifications.WarehouseProducts; namespace PyroFetes.Endpoints.WareHouseProducts; -public class PatchWareHouseProductQuantityEndpoint(PyroFetesDbContext database) - : Endpoint +public class PatchWareHouseProductQuantityEndpoint(WarehouseProductsRepository warehouseProductsRepository) : Endpoint { public override void Configure() { @@ -17,25 +17,17 @@ public class PatchWareHouseProductQuantityEndpoint(PyroFetesDbContext database) public override async Task HandleAsync(PatchWareHouseProductQuantityDto req, CancellationToken ct) { - WarehouseProduct? wareHouseProduct = - await database.WarehouseProducts.SingleOrDefaultAsync( - wp => wp.ProductId == req.ProductId && wp.WarehouseId == req.WareHouseId, ct); - - if (wareHouseProduct == null) + WarehouseProduct? wareHouseProduct = await warehouseProductsRepository.FirstOrDefaultAsync(new GetWarehouseProductByProductIdSpec(req.ProductId, req.WareHouseId) , ct); + + if (wareHouseProduct is null) { await Send.NotFoundAsync(ct); return; } wareHouseProduct.Quantity = req.Quantity; - await database.SaveChangesAsync(ct); - - GetWareHouseProductDto responseDto = new() - { - ProductId = wareHouseProduct.ProductId, - WareHouseId = wareHouseProduct.WarehouseId, - Quantity = wareHouseProduct.Quantity - }; - await Send.OkAsync(responseDto, ct); + await warehouseProductsRepository.SaveChangesAsync(ct); + + await Send.NoContentAsync(ct); } } \ No newline at end of file diff --git a/PyroFetes/MappingProfiles/DtoToEntityMappings.cs b/PyroFetes/MappingProfiles/DtoToEntityMappings.cs index 132c1352..d79b9667 100644 --- a/PyroFetes/MappingProfiles/DtoToEntityMappings.cs +++ b/PyroFetes/MappingProfiles/DtoToEntityMappings.cs @@ -3,7 +3,6 @@ using PyroFetes.DTO.Deliverer.Request; using PyroFetes.DTO.DeliveryNote.Request; using PyroFetes.DTO.Price.Request; using PyroFetes.DTO.Product.Request; -using PyroFetes.DTO.ProductDelivery.Request; using PyroFetes.DTO.PurchaseOrder.Request; using PyroFetes.DTO.PurchaseProduct.Request; using PyroFetes.DTO.Quotation.Request; @@ -21,50 +20,65 @@ public class DtoToEntityMappings : Profile public DtoToEntityMappings() { CreateMap(); - CreateMap(); + CreateMap() + .ForMember(dest => dest.Id, opt => opt.Ignore()); CreateMap(); - CreateMap(); - CreateMap(); + CreateMap() + .ForMember(dest => dest.Id, opt => opt.Ignore()); + CreateMap() + .ForMember(dest => dest.Id, opt => opt.Ignore()); CreateMap(); - CreateMap(); - CreateMap(); + CreateMap() + .ForMember(dest => dest.ProductId, opt => opt.Ignore()) + .ForMember(dest => dest.SupplierId, opt => opt.Ignore()); - CreateMap(); - CreateMap(); - CreateMap(); - - CreateMap(); - CreateMap(); + CreateMap() + .ForMember(dest => dest.Id, opt => opt.Ignore()); + CreateMap() + .ForMember(dest => dest.Id, opt => opt.Ignore()); CreateMap(); - CreateMap(); + CreateMap() + .ForMember(dest => dest.Id, opt => opt.Ignore()); CreateMap(); - CreateMap(); - CreateMap(); + CreateMap() + .ForMember(dest => dest.ProductId, opt => opt.Ignore()) + .ForMember(dest => dest.PurchaseOrderId, opt => opt.Ignore()); - CreateMap(); - CreateMap(); + CreateMap() + .ForMember(dest => dest.Id, opt => opt.Ignore()); + CreateMap() + .ForMember(dest => dest.Id, opt => opt.Ignore()); CreateMap(); - CreateMap(); - CreateMap(); - CreateMap(); + CreateMap(); + CreateMap() + .ForMember(dest => dest.ProductId, opt => opt.Ignore()) + .ForMember(dest => dest.QuotationId, opt => opt.Ignore()); CreateMap(); - CreateMap(); - CreateMap(); + CreateMap() + .ForMember(dest => dest.Id, opt => opt.Ignore()); + CreateMap() + .ForMember(dest => dest.Id, opt => opt.Ignore()); CreateMap(); - CreateMap(); - CreateMap(); + CreateMap() + .ForMember(dest => dest.Id, opt => opt.Ignore()); + CreateMap() + .ForMember(dest => dest.Id, opt => opt.Ignore()); CreateMap(); - CreateMap(); - CreateMap(); + CreateMap() + .ForMember(dest => dest.Id, opt => opt.Ignore()); + CreateMap() + .ForMember(dest => dest.Id, opt => opt.Ignore()); - CreateMap(); + CreateMap() + .ForMember(dest => dest.ProductId, opt => opt.Ignore()) + .ForMember(dest => dest.WarehouseId, opt => opt.Ignore()); } } \ No newline at end of file diff --git a/PyroFetes/MappingProfiles/EntityToDtoMappings.cs b/PyroFetes/MappingProfiles/EntityToDtoMappings.cs index c74e6851..5604064b 100644 --- a/PyroFetes/MappingProfiles/EntityToDtoMappings.cs +++ b/PyroFetes/MappingProfiles/EntityToDtoMappings.cs @@ -24,46 +24,25 @@ public class EntityToDtoMappings : Profile CreateMap(); - CreateMap(); + CreateMap() + .ForMember(dest => dest.Products, opt => opt.MapFrom(src => src.ProductDeliveries)); CreateMap(); - - CreateMap(); - + + CreateMap() + .ForMember(dest => dest.References, opt => opt.MapFrom(src => src.Reference)); + CreateMap(); - // CreateMap(); - // - //CreateMap(); - - CreateMap() - .ForMember(dest => dest.Products, - opt => opt.MapFrom(src => src.PurchaseProducts)); - - CreateMap() - .ForMember(dest => dest.ProductId, opt => opt.MapFrom(src => src.ProductId)) - .ForMember(dest => dest.Quantity, opt => opt.MapFrom(src => src.Quantity)) - .ForMember(dest => dest.ProductName, opt => opt.MapFrom(src => src.Product.Name)) - .ForMember(dest => dest.ProductReferences, opt => opt.MapFrom(src => src.Product.Reference)) - .ForMember(dest => dest.ProductPrice, opt => opt.MapFrom(src => src.Product.Prices - .FirstOrDefault(p => p.SupplierId == src.PurchaseOrder!.SupplierId) - .SellingPrice)); - - // CreateMap(); - // - //CreateMap(); + .ForMember(dest => dest.Products, opt => opt.MapFrom(src => src.PurchaseProducts)); + CreateMap(); CreateMap() - .ForMember(dest => dest.Products, - opt => opt.MapFrom(src => src.QuotationProducts)); + .ForMember(dest => dest.Products, opt => opt.MapFrom(src => src.QuotationProducts)); - CreateMap() - .ForMember(dest => dest.ProductId, opt => opt.MapFrom(src => src.ProductId)) - .ForMember(dest => dest.Quantity, opt => opt.MapFrom(src => src.Quantity)) - .ForMember(dest => dest.ProductName, opt => opt.MapFrom(src => src.Product.Name)) - .ForMember(dest => dest.ProductReferences, opt => opt.MapFrom(src => src.Product.Reference)); + CreateMap(); CreateMap(); diff --git a/PyroFetes/Migrations/20260524095820_ChangeDatabaseName.Designer.cs b/PyroFetes/Migrations/20260524095820_ChangeDatabaseName.Designer.cs new file mode 100644 index 00000000..e644ca2b --- /dev/null +++ b/PyroFetes/Migrations/20260524095820_ChangeDatabaseName.Designer.cs @@ -0,0 +1,1983 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using PyroFetes; + +#nullable disable + +namespace PyroFetes.Migrations +{ + [DbContext(typeof(PyroFetesDbContext))] + [Migration("20260524095820_ChangeDatabaseName")] + partial class ChangeDatabaseName + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "8.0.20") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("PyroFetes.Models.Availability", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AvailabilityDate") + .HasColumnType("date"); + + b.Property("DeliveryDate") + .HasColumnType("date"); + + b.Property("ExpirationDate") + .HasColumnType("date"); + + b.Property("RenewallDate") + .HasColumnType("date"); + + b.HasKey("Id"); + + b.ToTable("Availabilities"); + }); + + modelBuilder.Entity("PyroFetes.Models.Brand", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("ProductId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ProductId"); + + b.ToTable("Brands"); + }); + + modelBuilder.Entity("PyroFetes.Models.City", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("ZipCode") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("Cities"); + }); + + modelBuilder.Entity("PyroFetes.Models.Classification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Classifications"); + }); + + modelBuilder.Entity("PyroFetes.Models.Color", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Colors"); + }); + + modelBuilder.Entity("PyroFetes.Models.Communication", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Calling") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("ContactId") + .HasColumnType("int"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Meeting") + .IsRequired() + .HasMaxLength(300) + .HasColumnType("nvarchar(300)"); + + b.HasKey("Id"); + + b.HasIndex("ContactId"); + + b.ToTable("Communications"); + }); + + modelBuilder.Entity("PyroFetes.Models.Contact", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("City") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("CustomerId") + .HasColumnType("int"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("PhoneNumber") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("Role") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("ZipCode") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("CustomerId"); + + b.ToTable("Contacts"); + }); + + modelBuilder.Entity("PyroFetes.Models.ContactServiceProvider", b => + { + b.Property("ContactId") + .HasColumnType("int"); + + b.Property("ServiceProviderId") + .HasColumnType("int"); + + b.HasKey("ContactId", "ServiceProviderId"); + + b.HasIndex("ServiceProviderId"); + + b.ToTable("ContactServiceProviders"); + }); + + modelBuilder.Entity("PyroFetes.Models.Contract", b => + { + b.Property("ShowId") + .HasColumnType("int"); + + b.Property("ServiceProviderId") + .HasColumnType("int"); + + b.Property("TermsAndConditions") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("ShowId", "ServiceProviderId"); + + b.HasIndex("ServiceProviderId"); + + b.ToTable("Contracts"); + }); + + modelBuilder.Entity("PyroFetes.Models.Customer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CustomerTypeId") + .HasColumnType("int"); + + b.Property("Note") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("CustomerTypeId"); + + b.ToTable("Customers"); + }); + + modelBuilder.Entity("PyroFetes.Models.CustomerType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("CustomerTypes"); + }); + + modelBuilder.Entity("PyroFetes.Models.Deliverer", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Transporter") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Deliverers"); + }); + + modelBuilder.Entity("PyroFetes.Models.DeliveryNote", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("DelivererId") + .HasColumnType("int"); + + b.Property("EstimateDeliveryDate") + .HasColumnType("date"); + + b.Property("ExpeditionDate") + .HasColumnType("date"); + + b.Property("RealDeliveryDate") + .HasColumnType("date"); + + b.Property("TrackingNumber") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.HasIndex("DelivererId"); + + b.ToTable("DeliveryNotes"); + }); + + modelBuilder.Entity("PyroFetes.Models.Effect", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Label") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.ToTable("Effects"); + }); + + modelBuilder.Entity("PyroFetes.Models.ExperienceLevel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("StaffId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("StaffId"); + + b.ToTable("ExperienceLevels"); + }); + + modelBuilder.Entity("PyroFetes.Models.HistoryOfApproval", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("DeliveryDate") + .HasColumnType("date"); + + b.Property("ExpirationDate") + .HasColumnType("date"); + + b.HasKey("Id"); + + b.ToTable("HistoryOfApprovals"); + }); + + modelBuilder.Entity("PyroFetes.Models.Material", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("WarehouseId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("WarehouseId"); + + b.ToTable("Materials"); + }); + + modelBuilder.Entity("PyroFetes.Models.MaterialWarehouse", b => + { + b.Property("MaterialId") + .HasColumnType("int"); + + b.Property("WarehouseId") + .HasColumnType("int"); + + b.HasKey("MaterialId", "WarehouseId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("MaterialWarehouses"); + }); + + modelBuilder.Entity("PyroFetes.Models.Movement", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Arrival") + .HasColumnType("datetime2"); + + b.Property("Date") + .HasColumnType("datetime2"); + + b.Property("DestinationWarehouseId") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.Property("SourceWarehouseId") + .HasColumnType("int"); + + b.Property("Start") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.HasIndex("DestinationWarehouseId"); + + b.HasIndex("SourceWarehouseId"); + + b.ToTable("Movements"); + }); + + modelBuilder.Entity("PyroFetes.Models.Price", b => + { + b.Property("ProductId") + .HasColumnType("int"); + + b.Property("SupplierId") + .HasColumnType("int"); + + b.Property("SellingPrice") + .HasColumnType("decimal(18,2)"); + + b.HasKey("ProductId", "SupplierId"); + + b.HasIndex("SupplierId"); + + b.ToTable("Prices"); + }); + + modelBuilder.Entity("PyroFetes.Models.Product", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ApprovalNumber") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Caliber") + .HasColumnType("int"); + + b.Property("ClassificationId") + .HasColumnType("int"); + + b.Property("Duration") + .HasColumnType("decimal(18,2)"); + + b.Property("Image") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Link") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.Property("MinimalQuantity") + .HasColumnType("int"); + + b.Property("MovementId") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Nec") + .HasColumnType("decimal(18,2)"); + + b.Property("ProductCategoryId") + .HasColumnType("int"); + + b.Property("Reference") + .IsRequired() + .HasMaxLength(20) + .HasColumnType("nvarchar(20)"); + + b.Property("Weight") + .HasColumnType("decimal(18,2)"); + + b.HasKey("Id"); + + b.HasIndex("ClassificationId"); + + b.HasIndex("MovementId"); + + b.HasIndex("ProductCategoryId"); + + b.ToTable("Products"); + }); + + modelBuilder.Entity("PyroFetes.Models.ProductCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("ProductCategories"); + }); + + modelBuilder.Entity("PyroFetes.Models.ProductColor", b => + { + b.Property("ProductId") + .HasColumnType("int"); + + b.Property("ColorId") + .HasColumnType("int"); + + b.HasKey("ProductId", "ColorId"); + + b.HasIndex("ColorId"); + + b.ToTable("ProductColors"); + }); + + modelBuilder.Entity("PyroFetes.Models.ProductDelivery", b => + { + b.Property("ProductId") + .HasColumnType("int"); + + b.Property("DeliveryNoteId") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.HasKey("ProductId", "DeliveryNoteId"); + + b.HasIndex("DeliveryNoteId"); + + b.ToTable("ProductDeliveries"); + }); + + modelBuilder.Entity("PyroFetes.Models.ProductEffect", b => + { + b.Property("ProductId") + .HasColumnType("int"); + + b.Property("EffectId") + .HasColumnType("int"); + + b.HasKey("ProductId", "EffectId"); + + b.HasIndex("EffectId"); + + b.ToTable("ProductEffects"); + }); + + modelBuilder.Entity("PyroFetes.Models.ProductTimecode", b => + { + b.Property("ProductId") + .HasColumnType("int"); + + b.Property("ShowId") + .HasColumnType("int"); + + b.Property("End") + .HasColumnType("decimal(18,2)"); + + b.Property("Start") + .HasColumnType("decimal(18,2)"); + + b.HasKey("ProductId", "ShowId"); + + b.HasIndex("ShowId"); + + b.ToTable("ProductTimecodes"); + }); + + modelBuilder.Entity("PyroFetes.Models.ProviderContact", b => + { + b.Property("ContactId") + .HasColumnType("int"); + + b.Property("ProviderId") + .HasColumnType("int"); + + b.HasKey("ContactId", "ProviderId"); + + b.HasIndex("ProviderId"); + + b.ToTable("ProviderContacts"); + }); + + modelBuilder.Entity("PyroFetes.Models.ProviderType", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Label") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("ProviderTypes"); + }); + + modelBuilder.Entity("PyroFetes.Models.PurchaseOrder", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("PurchaseConditions") + .IsRequired() + .HasMaxLength(300) + .HasColumnType("nvarchar(300)"); + + b.Property("SupplierId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("SupplierId"); + + b.ToTable("PurchaseOrders"); + }); + + modelBuilder.Entity("PyroFetes.Models.PurchaseProduct", b => + { + b.Property("ProductId") + .HasColumnType("int"); + + b.Property("PurchaseOrderId") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.HasKey("ProductId", "PurchaseOrderId"); + + b.HasIndex("PurchaseOrderId"); + + b.ToTable("PurchaseProducts"); + }); + + modelBuilder.Entity("PyroFetes.Models.Quotation", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ConditionsSale") + .IsRequired() + .HasMaxLength(300) + .HasColumnType("nvarchar(300)"); + + b.Property("CustomerId") + .HasColumnType("int"); + + b.Property("Message") + .IsRequired() + .HasMaxLength(200) + .HasColumnType("nvarchar(200)"); + + b.HasKey("Id"); + + b.HasIndex("CustomerId"); + + b.ToTable("Quotations"); + }); + + modelBuilder.Entity("PyroFetes.Models.QuotationProduct", b => + { + b.Property("ProductId") + .HasColumnType("int"); + + b.Property("QuotationId") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.HasKey("ProductId", "QuotationId"); + + b.HasIndex("QuotationId"); + + b.ToTable("QuotationProducts"); + }); + + modelBuilder.Entity("PyroFetes.Models.ServiceProvider", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Price") + .HasColumnType("decimal(18,2)"); + + b.Property("ProviderTypeId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("ProviderTypeId"); + + b.ToTable("ServiceProviders"); + }); + + modelBuilder.Entity("PyroFetes.Models.Setting", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("ElectronicSignature") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Logo") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Settings"); + }); + + modelBuilder.Entity("PyroFetes.Models.Show", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CityId") + .HasColumnType("int"); + + b.Property("Date") + .HasColumnType("date"); + + b.Property("Description") + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Place") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("nvarchar(120)"); + + b.Property("PyrotechnicImplementationPlan") + .IsRequired() + .HasMaxLength(500) + .HasColumnType("nvarchar(500)"); + + b.HasKey("Id"); + + b.HasIndex("CityId"); + + b.ToTable("Shows"); + }); + + modelBuilder.Entity("PyroFetes.Models.ShowMaterial", b => + { + b.Property("ShowId") + .HasColumnType("int"); + + b.Property("MaterialId") + .HasColumnType("int"); + + b.HasKey("ShowId", "MaterialId"); + + b.HasIndex("MaterialId"); + + b.ToTable("ShowMaterials"); + }); + + modelBuilder.Entity("PyroFetes.Models.ShowServiceProvider", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.HasKey("Id"); + + b.ToTable("ShowServiceProviders"); + }); + + modelBuilder.Entity("PyroFetes.Models.ShowStaff", b => + { + b.Property("StaffId") + .HasColumnType("int"); + + b.Property("ShowId") + .HasColumnType("int"); + + b.HasKey("StaffId", "ShowId"); + + b.HasIndex("ShowId"); + + b.ToTable("ShowStaffs"); + }); + + modelBuilder.Entity("PyroFetes.Models.ShowTruck", b => + { + b.Property("ShowId") + .HasColumnType("int"); + + b.Property("TruckId") + .HasColumnType("int"); + + b.HasKey("ShowId", "TruckId"); + + b.HasIndex("TruckId"); + + b.ToTable("ShowTrucks"); + }); + + modelBuilder.Entity("PyroFetes.Models.Sound", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Artist") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("nvarchar(120)"); + + b.Property("CreationDate") + .HasColumnType("datetime2"); + + b.Property("Duration") + .IsRequired() + .HasColumnType("int"); + + b.Property("Format") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)"); + + b.Property("Kind") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("nvarchar(120)"); + + b.Property("SoundCategoryId") + .HasColumnType("int"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.HasKey("Id"); + + b.HasIndex("SoundCategoryId"); + + b.ToTable("Sounds"); + }); + + modelBuilder.Entity("PyroFetes.Models.SoundCategory", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("SoundCategories"); + }); + + modelBuilder.Entity("PyroFetes.Models.SoundTimecode", b => + { + b.Property("ShowId") + .HasColumnType("int"); + + b.Property("SoundId") + .HasColumnType("int"); + + b.Property("End") + .HasColumnType("decimal(18,2)"); + + b.Property("Start") + .HasColumnType("decimal(18,2)"); + + b.HasKey("ShowId", "SoundId"); + + b.HasIndex("SoundId"); + + b.ToTable("SoundTimecodes"); + }); + + modelBuilder.Entity("PyroFetes.Models.Staff", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Email") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("nvarchar(120)"); + + b.Property("F4T2ExpirationDate") + .HasColumnType("date"); + + b.Property("F4T2NumberApproval") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("FirstName") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.Property("LastName") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.Property("Profession") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Staffs"); + }); + + modelBuilder.Entity("PyroFetes.Models.StaffAvailability", b => + { + b.Property("AvailabilityId") + .HasColumnType("int"); + + b.Property("StaffId") + .HasColumnType("int"); + + b.HasKey("AvailabilityId", "StaffId"); + + b.HasIndex("StaffId"); + + b.ToTable("StaffAvailabilities"); + }); + + modelBuilder.Entity("PyroFetes.Models.StaffContact", b => + { + b.Property("ContactId") + .HasColumnType("int"); + + b.Property("StaffId") + .HasColumnType("int"); + + b.HasKey("ContactId", "StaffId"); + + b.HasIndex("StaffId"); + + b.ToTable("StaffContacts"); + }); + + modelBuilder.Entity("PyroFetes.Models.StaffHistoryOfApproval", b => + { + b.Property("HistoryOfApprovalId") + .HasColumnType("int"); + + b.Property("StaffId") + .HasColumnType("int"); + + b.HasKey("HistoryOfApprovalId", "StaffId"); + + b.HasIndex("StaffId"); + + b.ToTable("StaffHistoryOfApprovals"); + }); + + modelBuilder.Entity("PyroFetes.Models.Supplier", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("City") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("DeliveryDelay") + .HasColumnType("int"); + + b.Property("Email") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Phone") + .IsRequired() + .HasMaxLength(30) + .HasColumnType("nvarchar(30)"); + + b.Property("ZipCode") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Suppliers"); + }); + + modelBuilder.Entity("PyroFetes.Models.Truck", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("MaxExplosiveCapacity") + .IsRequired() + .HasColumnType("float"); + + b.Property("Sizes") + .IsRequired() + .HasMaxLength(80) + .HasColumnType("nvarchar(80)"); + + b.Property("Status") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)"); + + b.Property("Type") + .IsRequired() + .HasMaxLength(40) + .HasColumnType("nvarchar(40)"); + + b.HasKey("Id"); + + b.ToTable("Trucks"); + }); + + modelBuilder.Entity("PyroFetes.Models.User", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Email") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Fonction") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Password") + .IsRequired() + .HasMaxLength(60) + .HasColumnType("nvarchar(60)"); + + b.Property("Salt") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("Users"); + }); + + modelBuilder.Entity("PyroFetes.Models.Warehouse", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("Address") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("City") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Current") + .HasColumnType("int"); + + b.Property("MaxWeight") + .HasColumnType("int"); + + b.Property("MinWeight") + .HasColumnType("int"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("ZipCode") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Warehouses"); + }); + + modelBuilder.Entity("PyroFetes.Models.WarehouseProduct", b => + { + b.Property("ProductId") + .HasColumnType("int"); + + b.Property("WarehouseId") + .HasColumnType("int"); + + b.Property("Quantity") + .HasColumnType("int"); + + b.HasKey("ProductId", "WarehouseId"); + + b.HasIndex("WarehouseId"); + + b.ToTable("WarehouseProducts"); + }); + + modelBuilder.Entity("PyroFetes.Models.Brand", b => + { + b.HasOne("PyroFetes.Models.Product", "Product") + .WithMany("Brands") + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Product"); + }); + + modelBuilder.Entity("PyroFetes.Models.Communication", b => + { + b.HasOne("PyroFetes.Models.Contact", "Contact") + .WithMany("Communications") + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Contact"); + }); + + modelBuilder.Entity("PyroFetes.Models.Contact", b => + { + b.HasOne("PyroFetes.Models.Customer", "Customer") + .WithMany("Contacts") + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Customer"); + }); + + modelBuilder.Entity("PyroFetes.Models.ContactServiceProvider", b => + { + b.HasOne("PyroFetes.Models.Contact", "Contact") + .WithMany("ContactServiceProviders") + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PyroFetes.Models.ServiceProvider", "ServiceProvider") + .WithMany("ContactServiceProviders") + .HasForeignKey("ServiceProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Contact"); + + b.Navigation("ServiceProvider"); + }); + + modelBuilder.Entity("PyroFetes.Models.Contract", b => + { + b.HasOne("PyroFetes.Models.ServiceProvider", "ServiceProvider") + .WithMany("Contracts") + .HasForeignKey("ServiceProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PyroFetes.Models.Show", "Show") + .WithMany("Contracts") + .HasForeignKey("ShowId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ServiceProvider"); + + b.Navigation("Show"); + }); + + modelBuilder.Entity("PyroFetes.Models.Customer", b => + { + b.HasOne("PyroFetes.Models.CustomerType", "CustomerType") + .WithMany("Customers") + .HasForeignKey("CustomerTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("CustomerType"); + }); + + modelBuilder.Entity("PyroFetes.Models.DeliveryNote", b => + { + b.HasOne("PyroFetes.Models.Deliverer", "Deliverer") + .WithMany("DeliveryNotes") + .HasForeignKey("DelivererId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Deliverer"); + }); + + modelBuilder.Entity("PyroFetes.Models.ExperienceLevel", b => + { + b.HasOne("PyroFetes.Models.Staff", "Staff") + .WithMany("ExperienceLevels") + .HasForeignKey("StaffId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Staff"); + }); + + modelBuilder.Entity("PyroFetes.Models.Material", b => + { + b.HasOne("PyroFetes.Models.Warehouse", "Warehouse") + .WithMany() + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("PyroFetes.Models.MaterialWarehouse", b => + { + b.HasOne("PyroFetes.Models.Material", "Material") + .WithMany("MaterialWarehouses") + .HasForeignKey("MaterialId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.HasOne("PyroFetes.Models.Warehouse", "Warehouse") + .WithMany("MaterialWarehouses") + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("Material"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("PyroFetes.Models.Movement", b => + { + b.HasOne("PyroFetes.Models.Warehouse", "DestinationWarehouse") + .WithMany("MovementsDestination") + .HasForeignKey("DestinationWarehouseId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("PyroFetes.Models.Warehouse", "SourceWarehouse") + .WithMany("MovementsSource") + .HasForeignKey("SourceWarehouseId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("DestinationWarehouse"); + + b.Navigation("SourceWarehouse"); + }); + + modelBuilder.Entity("PyroFetes.Models.Price", b => + { + b.HasOne("PyroFetes.Models.Product", "Product") + .WithMany("Prices") + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PyroFetes.Models.Supplier", "Supplier") + .WithMany("Prices") + .HasForeignKey("SupplierId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Product"); + + b.Navigation("Supplier"); + }); + + modelBuilder.Entity("PyroFetes.Models.Product", b => + { + b.HasOne("PyroFetes.Models.Classification", "Classification") + .WithMany("Products") + .HasForeignKey("ClassificationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PyroFetes.Models.Movement", "Movement") + .WithMany("Products") + .HasForeignKey("MovementId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PyroFetes.Models.ProductCategory", "ProductCategory") + .WithMany("Products") + .HasForeignKey("ProductCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Classification"); + + b.Navigation("Movement"); + + b.Navigation("ProductCategory"); + }); + + modelBuilder.Entity("PyroFetes.Models.ProductColor", b => + { + b.HasOne("PyroFetes.Models.Color", "Color") + .WithMany("ProductColors") + .HasForeignKey("ColorId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PyroFetes.Models.Product", "Product") + .WithMany("ProductColors") + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Color"); + + b.Navigation("Product"); + }); + + modelBuilder.Entity("PyroFetes.Models.ProductDelivery", b => + { + b.HasOne("PyroFetes.Models.DeliveryNote", "DeliveryNote") + .WithMany("ProductDeliveries") + .HasForeignKey("DeliveryNoteId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PyroFetes.Models.Product", "Product") + .WithMany("ProductDeliveries") + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DeliveryNote"); + + b.Navigation("Product"); + }); + + modelBuilder.Entity("PyroFetes.Models.ProductEffect", b => + { + b.HasOne("PyroFetes.Models.Effect", "Effect") + .WithMany("ProductEffects") + .HasForeignKey("EffectId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PyroFetes.Models.Product", "Product") + .WithMany("ProductEffects") + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Effect"); + + b.Navigation("Product"); + }); + + modelBuilder.Entity("PyroFetes.Models.ProductTimecode", b => + { + b.HasOne("PyroFetes.Models.Product", "Product") + .WithMany("ProductTimecodes") + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PyroFetes.Models.Show", "Show") + .WithMany("ProductTimecodes") + .HasForeignKey("ShowId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Product"); + + b.Navigation("Show"); + }); + + modelBuilder.Entity("PyroFetes.Models.ProviderContact", b => + { + b.HasOne("PyroFetes.Models.Contact", "Contact") + .WithMany() + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PyroFetes.Models.ServiceProvider", "Provider") + .WithMany() + .HasForeignKey("ProviderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Contact"); + + b.Navigation("Provider"); + }); + + modelBuilder.Entity("PyroFetes.Models.PurchaseOrder", b => + { + b.HasOne("PyroFetes.Models.Supplier", "Supplier") + .WithMany() + .HasForeignKey("SupplierId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Supplier"); + }); + + modelBuilder.Entity("PyroFetes.Models.PurchaseProduct", b => + { + b.HasOne("PyroFetes.Models.Product", "Product") + .WithMany("PurchaseProducts") + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PyroFetes.Models.PurchaseOrder", "PurchaseOrder") + .WithMany("PurchaseProducts") + .HasForeignKey("PurchaseOrderId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Product"); + + b.Navigation("PurchaseOrder"); + }); + + modelBuilder.Entity("PyroFetes.Models.Quotation", b => + { + b.HasOne("PyroFetes.Models.Customer", "Customer") + .WithMany("Quotations") + .HasForeignKey("CustomerId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Customer"); + }); + + modelBuilder.Entity("PyroFetes.Models.QuotationProduct", b => + { + b.HasOne("PyroFetes.Models.Product", "Product") + .WithMany("QuotationProducts") + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PyroFetes.Models.Quotation", "Quotation") + .WithMany("QuotationProducts") + .HasForeignKey("QuotationId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Product"); + + b.Navigation("Quotation"); + }); + + modelBuilder.Entity("PyroFetes.Models.ServiceProvider", b => + { + b.HasOne("PyroFetes.Models.ProviderType", "ProviderType") + .WithMany("ServiceProviders") + .HasForeignKey("ProviderTypeId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("ProviderType"); + }); + + modelBuilder.Entity("PyroFetes.Models.Show", b => + { + b.HasOne("PyroFetes.Models.City", "City") + .WithMany("Shows") + .HasForeignKey("CityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("City"); + }); + + modelBuilder.Entity("PyroFetes.Models.ShowMaterial", b => + { + b.HasOne("PyroFetes.Models.Material", "Material") + .WithMany("ShowMaterials") + .HasForeignKey("MaterialId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PyroFetes.Models.Show", "Show") + .WithMany("ShowMaterials") + .HasForeignKey("ShowId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Material"); + + b.Navigation("Show"); + }); + + modelBuilder.Entity("PyroFetes.Models.ShowStaff", b => + { + b.HasOne("PyroFetes.Models.Show", "Show") + .WithMany("ShowStaffs") + .HasForeignKey("ShowId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PyroFetes.Models.Staff", "Staff") + .WithMany("ShowStaffs") + .HasForeignKey("StaffId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Show"); + + b.Navigation("Staff"); + }); + + modelBuilder.Entity("PyroFetes.Models.ShowTruck", b => + { + b.HasOne("PyroFetes.Models.Show", "Show") + .WithMany("ShowTrucks") + .HasForeignKey("ShowId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PyroFetes.Models.Truck", "Truck") + .WithMany("ShowTrucks") + .HasForeignKey("TruckId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Show"); + + b.Navigation("Truck"); + }); + + modelBuilder.Entity("PyroFetes.Models.Sound", b => + { + b.HasOne("PyroFetes.Models.SoundCategory", "SoundCategory") + .WithMany("Sounds") + .HasForeignKey("SoundCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("SoundCategory"); + }); + + modelBuilder.Entity("PyroFetes.Models.SoundTimecode", b => + { + b.HasOne("PyroFetes.Models.Show", "Show") + .WithMany("SoundTimecodes") + .HasForeignKey("ShowId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PyroFetes.Models.Sound", "Sound") + .WithMany("SoundTimecodes") + .HasForeignKey("SoundId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Show"); + + b.Navigation("Sound"); + }); + + modelBuilder.Entity("PyroFetes.Models.StaffAvailability", b => + { + b.HasOne("PyroFetes.Models.Availability", "Availability") + .WithMany("StaffAvailabilities") + .HasForeignKey("AvailabilityId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PyroFetes.Models.Staff", "Staff") + .WithMany("StaffAvailabilities") + .HasForeignKey("StaffId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Availability"); + + b.Navigation("Staff"); + }); + + modelBuilder.Entity("PyroFetes.Models.StaffContact", b => + { + b.HasOne("PyroFetes.Models.Contact", "Contact") + .WithMany("StaffContacts") + .HasForeignKey("ContactId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PyroFetes.Models.Staff", "Staff") + .WithMany("StaffContacts") + .HasForeignKey("StaffId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Contact"); + + b.Navigation("Staff"); + }); + + modelBuilder.Entity("PyroFetes.Models.StaffHistoryOfApproval", b => + { + b.HasOne("PyroFetes.Models.HistoryOfApproval", "HistoryOfApproval") + .WithMany("StaffHistoryOfApprovals") + .HasForeignKey("HistoryOfApprovalId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PyroFetes.Models.Staff", "Staff") + .WithMany("StaffHistoryOfApprovals") + .HasForeignKey("StaffId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("HistoryOfApproval"); + + b.Navigation("Staff"); + }); + + modelBuilder.Entity("PyroFetes.Models.WarehouseProduct", b => + { + b.HasOne("PyroFetes.Models.Product", "Product") + .WithMany("WarehouseProducts") + .HasForeignKey("ProductId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("PyroFetes.Models.Warehouse", "Warehouse") + .WithMany("WarehouseProducts") + .HasForeignKey("WarehouseId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Product"); + + b.Navigation("Warehouse"); + }); + + modelBuilder.Entity("PyroFetes.Models.Availability", b => + { + b.Navigation("StaffAvailabilities"); + }); + + modelBuilder.Entity("PyroFetes.Models.City", b => + { + b.Navigation("Shows"); + }); + + modelBuilder.Entity("PyroFetes.Models.Classification", b => + { + b.Navigation("Products"); + }); + + modelBuilder.Entity("PyroFetes.Models.Color", b => + { + b.Navigation("ProductColors"); + }); + + modelBuilder.Entity("PyroFetes.Models.Contact", b => + { + b.Navigation("Communications"); + + b.Navigation("ContactServiceProviders"); + + b.Navigation("StaffContacts"); + }); + + modelBuilder.Entity("PyroFetes.Models.Customer", b => + { + b.Navigation("Contacts"); + + b.Navigation("Quotations"); + }); + + modelBuilder.Entity("PyroFetes.Models.CustomerType", b => + { + b.Navigation("Customers"); + }); + + modelBuilder.Entity("PyroFetes.Models.Deliverer", b => + { + b.Navigation("DeliveryNotes"); + }); + + modelBuilder.Entity("PyroFetes.Models.DeliveryNote", b => + { + b.Navigation("ProductDeliveries"); + }); + + modelBuilder.Entity("PyroFetes.Models.Effect", b => + { + b.Navigation("ProductEffects"); + }); + + modelBuilder.Entity("PyroFetes.Models.HistoryOfApproval", b => + { + b.Navigation("StaffHistoryOfApprovals"); + }); + + modelBuilder.Entity("PyroFetes.Models.Material", b => + { + b.Navigation("MaterialWarehouses"); + + b.Navigation("ShowMaterials"); + }); + + modelBuilder.Entity("PyroFetes.Models.Movement", b => + { + b.Navigation("Products"); + }); + + modelBuilder.Entity("PyroFetes.Models.Product", b => + { + b.Navigation("Brands"); + + b.Navigation("Prices"); + + b.Navigation("ProductColors"); + + b.Navigation("ProductDeliveries"); + + b.Navigation("ProductEffects"); + + b.Navigation("ProductTimecodes"); + + b.Navigation("PurchaseProducts"); + + b.Navigation("QuotationProducts"); + + b.Navigation("WarehouseProducts"); + }); + + modelBuilder.Entity("PyroFetes.Models.ProductCategory", b => + { + b.Navigation("Products"); + }); + + modelBuilder.Entity("PyroFetes.Models.ProviderType", b => + { + b.Navigation("ServiceProviders"); + }); + + modelBuilder.Entity("PyroFetes.Models.PurchaseOrder", b => + { + b.Navigation("PurchaseProducts"); + }); + + modelBuilder.Entity("PyroFetes.Models.Quotation", b => + { + b.Navigation("QuotationProducts"); + }); + + modelBuilder.Entity("PyroFetes.Models.ServiceProvider", b => + { + b.Navigation("ContactServiceProviders"); + + b.Navigation("Contracts"); + }); + + modelBuilder.Entity("PyroFetes.Models.Show", b => + { + b.Navigation("Contracts"); + + b.Navigation("ProductTimecodes"); + + b.Navigation("ShowMaterials"); + + b.Navigation("ShowStaffs"); + + b.Navigation("ShowTrucks"); + + b.Navigation("SoundTimecodes"); + }); + + modelBuilder.Entity("PyroFetes.Models.Sound", b => + { + b.Navigation("SoundTimecodes"); + }); + + modelBuilder.Entity("PyroFetes.Models.SoundCategory", b => + { + b.Navigation("Sounds"); + }); + + modelBuilder.Entity("PyroFetes.Models.Staff", b => + { + b.Navigation("ExperienceLevels"); + + b.Navigation("ShowStaffs"); + + b.Navigation("StaffAvailabilities"); + + b.Navigation("StaffContacts"); + + b.Navigation("StaffHistoryOfApprovals"); + }); + + modelBuilder.Entity("PyroFetes.Models.Supplier", b => + { + b.Navigation("Prices"); + }); + + modelBuilder.Entity("PyroFetes.Models.Truck", b => + { + b.Navigation("ShowTrucks"); + }); + + modelBuilder.Entity("PyroFetes.Models.Warehouse", b => + { + b.Navigation("MaterialWarehouses"); + + b.Navigation("MovementsDestination"); + + b.Navigation("MovementsSource"); + + b.Navigation("WarehouseProducts"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/PyroFetes/Migrations/20260524095820_ChangeDatabaseName.cs b/PyroFetes/Migrations/20260524095820_ChangeDatabaseName.cs new file mode 100644 index 00000000..727fd050 --- /dev/null +++ b/PyroFetes/Migrations/20260524095820_ChangeDatabaseName.cs @@ -0,0 +1,22 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace PyroFetes.Migrations +{ + /// + public partial class ChangeDatabaseName : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + + } + } +} diff --git a/PyroFetes/Program.cs b/PyroFetes/Program.cs index 83ef61b4..b0564138 100644 --- a/PyroFetes/Program.cs +++ b/PyroFetes/Program.cs @@ -80,7 +80,7 @@ app.UseAuthentication() }) .UseSwaggerGen(); -app.UseHttpsRedirection(); +// app.UseHttpsRedirection(); app.UseCors(); diff --git a/PyroFetes/PyroFetes.csproj b/PyroFetes/PyroFetes.csproj index 5aa90b1d..a492cc16 100644 --- a/PyroFetes/PyroFetes.csproj +++ b/PyroFetes/PyroFetes.csproj @@ -31,17 +31,9 @@ <_ContentIncludedByDefault Remove="wwwroot\Images\logo.jpg" /> - - - PreserveNewest - - - PreserveNewest - - - + diff --git a/PyroFetes/PyroFetesDbContext.cs b/PyroFetes/PyroFetesDbContext.cs index f8230eb8..7d8c9007 100644 --- a/PyroFetes/PyroFetesDbContext.cs +++ b/PyroFetes/PyroFetesDbContext.cs @@ -63,15 +63,13 @@ public class PyroFetesDbContext : DbContext protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { string connectionString = - "Server=localhost,1433;" + - "Database=pyrofetes-db;" + - "User Id=sa;" + - "Password=AdminMotDePasse!;" + + "Server=romaric-thibault.fr;" + + "Database=PyroFetes-Sujet2;" + + "User Id=pyrofetes;" + + "Password=Crablike8-Fringe-Swimmable;" + "TrustServerCertificate=true;"; optionsBuilder.UseSqlServer(connectionString); - - } // Models customization diff --git a/PyroFetes/Services/Pdf/DeliveryNotePdfService.cs b/PyroFetes/Services/Pdf/DeliveryNotePdfService.cs index e084ec2c..eae9b7e6 100644 --- a/PyroFetes/Services/Pdf/DeliveryNotePdfService.cs +++ b/PyroFetes/Services/Pdf/DeliveryNotePdfService.cs @@ -7,18 +7,18 @@ namespace PyroFetes.Services.Pdf; public interface IDeliveryNotePdfService { - byte[] Generate(DeliveryNote deliveryNote, List lignes); + byte[] Generate(DeliveryNote deliveryNote, List lignes, Setting setting); } public class DeliveryNotePdfService : IDeliveryNotePdfService { - public byte[] Generate(DeliveryNote deliveryNote, List lignes) + public byte[] Generate(DeliveryNote deliveryNote, List lignes, Setting setting) { - var logoPath = Path.Combine(AppContext.BaseDirectory, "wwwroot", "Images", "logo.jpg"); - var signaturePath = Path.Combine(AppContext.BaseDirectory, "wwwroot", "Images", "signature.png"); + byte[] logo = Convert.FromBase64String(setting.Logo!); + byte[] signature = Convert.FromBase64String(setting.ElectronicSignature!); int total = 0; int totalQuantity = 0; - var document = Document.Create(container => + Document document = Document.Create(container => { container.Page(page => { @@ -48,7 +48,7 @@ public class DeliveryNotePdfService : IDeliveryNotePdfService // Logo + société à droite row.ConstantItem(200).Column(col => { - col.Item().AlignRight().Height(70).Image(logoPath, ImageScaling.FitArea); + col.Item().AlignRight().Height(70).Image(logo, ImageScaling.FitArea); col.Item().Height(20); col.Item().AlignRight().Text("Pyro-Fêtes").SemiBold(); col.Item().Height(5); @@ -93,7 +93,7 @@ public class DeliveryNotePdfService : IDeliveryNotePdfService header.Cell().Element(CellHeader).AlignRight().Text("Total"); }); - foreach (var l in lignes) + foreach (ProductDelivery l in lignes) { table.Cell().Element(CellBody).Text(l.Product?.Name); table.Cell().Element(CellBody).AlignRight().Text(l.Quantity.ToString()); @@ -123,7 +123,7 @@ public class DeliveryNotePdfService : IDeliveryNotePdfService // Signature en bas à droite page.Footer().AlignRight().Column(col => { - col.Item().AlignRight().Height(100).Image(signaturePath, ImageScaling.FitArea); + col.Item().AlignRight().Height(100).Image(signature, ImageScaling.FitArea); }); }); }); diff --git a/PyroFetes/Services/Pdf/PurchaseOrderPdfService.cs b/PyroFetes/Services/Pdf/PurchaseOrderPdfService.cs index 6861e8bc..c5ef60e2 100644 --- a/PyroFetes/Services/Pdf/PurchaseOrderPdfService.cs +++ b/PyroFetes/Services/Pdf/PurchaseOrderPdfService.cs @@ -7,18 +7,18 @@ namespace PyroFetes.Services.Pdf; public interface IPurchaseOrderPdfService { - byte[] Generate(PurchaseOrder purchaseOrder, List lignes); + byte[] Generate(PurchaseOrder purchaseOrder, List lignes, Setting setting); } public class PurchaseOrderPdfService : IPurchaseOrderPdfService { - public byte[] Generate(PurchaseOrder purchaseOrder, List lignes) + public byte[] Generate(PurchaseOrder purchaseOrder, List lignes, Setting setting) { - var logoPath = Path.Combine(AppContext.BaseDirectory, "wwwroot", "Images", "logo.jpg"); - var signaturePath = Path.Combine(AppContext.BaseDirectory, "wwwroot", "Images", "signature.png"); + byte[] logo = Convert.FromBase64String(setting.Logo!); + byte[] signature = Convert.FromBase64String(setting.ElectronicSignature!); int totalQuantity = 0; decimal total = 0; - var document = Document.Create(container => + Document document = Document.Create(container => { container.Page(page => { @@ -42,7 +42,7 @@ public class PurchaseOrderPdfService : IPurchaseOrderPdfService // Logo + société à droite row.ConstantItem(200).Column(col => { - col.Item().AlignRight().Height(70).Image(logoPath, ImageScaling.FitArea); + col.Item().AlignRight().Height(70).Image(logo, ImageScaling.FitArea); col.Item().Height(20); col.Item().AlignRight().Text("Pyro-Fêtes").SemiBold(); col.Item().Height(5); @@ -90,7 +90,7 @@ public class PurchaseOrderPdfService : IPurchaseOrderPdfService header.Cell().Element(CellHeader).AlignRight().Text("Total"); }); - foreach (var l in lignes) + foreach (PurchaseProduct l in lignes) { decimal price = l.Product!.Prices! .FirstOrDefault(p => p.SupplierId == l.PurchaseOrder!.SupplierId) @@ -140,7 +140,7 @@ public class PurchaseOrderPdfService : IPurchaseOrderPdfService // Signature en bas à droite page.Footer().AlignRight().Column(col => { - col.Item().AlignRight().Height(100).Image(signaturePath, ImageScaling.FitArea); + col.Item().AlignRight().Height(100).Image(signature, ImageScaling.FitArea); }); }); }); diff --git a/PyroFetes/Services/Pdf/QuotationPdfService.cs b/PyroFetes/Services/Pdf/QuotationPdfService.cs index c5709e12..40e4b759 100644 --- a/PyroFetes/Services/Pdf/QuotationPdfService.cs +++ b/PyroFetes/Services/Pdf/QuotationPdfService.cs @@ -1,5 +1,4 @@ using PyroFetes.Models; -using QuestPDF.Companion; using QuestPDF.Fluent; using QuestPDF.Helpers; using QuestPDF.Infrastructure; @@ -8,17 +7,17 @@ namespace PyroFetes.Services.Pdf; public interface IQuotationPdfService { - byte[] Generate(Quotation quotation, List lignes); + byte[] Generate(Quotation quotation, List lignes, Setting setting); } public class QuotationPdfService : IQuotationPdfService { - public byte[] Generate(Quotation quotation, List lignes) + public byte[] Generate(Quotation quotation, List lignes, Setting setting) { - var logoPath = Path.Combine(AppContext.BaseDirectory, "wwwroot", "Images", "logo.jpg"); - var signaturePath = Path.Combine(AppContext.BaseDirectory, "wwwroot", "Images", "signature.png"); + byte[] logo = Convert.FromBase64String(setting.Logo!); + byte[] signature = Convert.FromBase64String(setting.ElectronicSignature!); int total = 0; - var document = Document.Create(container => + Document document = Document.Create(container => { container.Page(page => { @@ -42,7 +41,7 @@ public class QuotationPdfService : IQuotationPdfService // Logo + société à droite row.ConstantItem(200).Column(col => { - col.Item().AlignRight().Height(70).Image(logoPath, ImageScaling.FitArea); + col.Item().AlignRight().Height(70).Image(logo, ImageScaling.FitArea); col.Item().Height(20); col.Item().AlignRight().Text("Pyro-Fêtes").SemiBold(); col.Item().Height(5); @@ -90,7 +89,7 @@ public class QuotationPdfService : IQuotationPdfService header.Cell().Element(CellHeader).AlignRight().Text("Total"); }); - foreach (var l in lignes) + foreach (QuotationProduct l in lignes) { table.Cell().Element(CellBody).Text(l.Product?.Name); table.Cell().Element(CellBody).AlignRight().Text(l.Quantity.ToString()); @@ -134,7 +133,7 @@ public class QuotationPdfService : IQuotationPdfService // Signature en bas à droite page.Footer().AlignRight().Column(col => { - col.Item().AlignRight().Height(100).Image(signaturePath, ImageScaling.FitArea); + col.Item().AlignRight().Height(100).Image(signature, ImageScaling.FitArea); }); }); }); diff --git a/PyroFetes/Specifications/Deliverers/GetDelivererByIdSpec.cs b/PyroFetes/Specifications/Deliverers/GetDelivererByIdSpec.cs index 63763819..8477c0cd 100644 --- a/PyroFetes/Specifications/Deliverers/GetDelivererByIdSpec.cs +++ b/PyroFetes/Specifications/Deliverers/GetDelivererByIdSpec.cs @@ -3,7 +3,7 @@ using PyroFetes.Models; namespace PyroFetes.Specifications.Deliverers; -public sealed class GetDelivererByIdSpec : Specification +public sealed class GetDelivererByIdSpec : SingleResultSpecification { public GetDelivererByIdSpec(int delivererId) { diff --git a/PyroFetes/Specifications/DeliveryNotes/GetAllDeliveryNoteSpec.cs b/PyroFetes/Specifications/DeliveryNotes/GetAllDeliveryNoteSpec.cs new file mode 100644 index 00000000..30ef09ab --- /dev/null +++ b/PyroFetes/Specifications/DeliveryNotes/GetAllDeliveryNoteSpec.cs @@ -0,0 +1,16 @@ +using Ardalis.Specification; +using PyroFetes.Models; + +namespace PyroFetes.Specifications.DeliveryNotes; + +public class GetAllDeliveryNoteSpec : Specification +{ + public GetAllDeliveryNoteSpec() + { + Query + .Include(x => x.Deliverer) + .Include(x => x.ProductDeliveries)! + .ThenInclude(x => x.Product) + .Where(x => true); + } +} \ No newline at end of file diff --git a/PyroFetes/Specifications/DeliveryNotes/GetDeliveryNoteByIdSpec.cs b/PyroFetes/Specifications/DeliveryNotes/GetDeliveryNoteByIdSpec.cs index 2fc04947..e37a9046 100644 --- a/PyroFetes/Specifications/DeliveryNotes/GetDeliveryNoteByIdSpec.cs +++ b/PyroFetes/Specifications/DeliveryNotes/GetDeliveryNoteByIdSpec.cs @@ -3,11 +3,14 @@ using PyroFetes.Models; namespace PyroFetes.Specifications.DeliveryNotes; -public sealed class GetDeliveryNoteByIdSpec : Specification +public sealed class GetDeliveryNoteByIdSpec : SingleResultSpecification { public GetDeliveryNoteByIdSpec(int deliveryNoteId) { Query + .Include(x => x.Deliverer) + .Include(x => x.ProductDeliveries!) + .ThenInclude(x => x.Product) .Where(x => x.Id == deliveryNoteId); } } \ No newline at end of file diff --git a/PyroFetes/Specifications/DeliveryNotes/GetDeliveryNoteByIdWithProductsSpec.cs b/PyroFetes/Specifications/DeliveryNotes/GetDeliveryNoteByIdWithProductsSpec.cs index 5849019f..0eb3506b 100644 --- a/PyroFetes/Specifications/DeliveryNotes/GetDeliveryNoteByIdWithProductsSpec.cs +++ b/PyroFetes/Specifications/DeliveryNotes/GetDeliveryNoteByIdWithProductsSpec.cs @@ -3,13 +3,13 @@ using PyroFetes.Models; namespace PyroFetes.Specifications.DeliveryNotes; -public class GetDeliveryNoteByIdWithProductsSpec : Specification +public class GetDeliveryNoteByIdWithProductsSpec : SingleResultSpecification { public GetDeliveryNoteByIdWithProductsSpec(int deliveryNoteId) { Query - .Where(d => d.Id == deliveryNoteId) - .Include(d => d.ProductDeliveries!) - .ThenInclude(dp => dp.Product); + .Where(x => x.Id == deliveryNoteId) + .Include(x => x.ProductDeliveries!) + .ThenInclude(p => p.Product); } } \ No newline at end of file diff --git a/PyroFetes/Specifications/Prices/GetPriceByProductIdAndSupplierIdSpec.cs b/PyroFetes/Specifications/Prices/GetPriceByProductIdAndSupplierIdSpec.cs index 5f74c136..42a883bc 100644 --- a/PyroFetes/Specifications/Prices/GetPriceByProductIdAndSupplierIdSpec.cs +++ b/PyroFetes/Specifications/Prices/GetPriceByProductIdAndSupplierIdSpec.cs @@ -3,11 +3,11 @@ using PyroFetes.Models; namespace PyroFetes.Specifications.Prices; -public sealed class GetPriceByProductIdAndSupplierIdSpec : Specification +public sealed class GetPriceByProductIdAndSupplierIdSpec : SingleResultSpecification { public GetPriceByProductIdAndSupplierIdSpec(int? productId, int? supplierId) { Query - .Where(p => p.ProductId == productId && p.SupplierId == supplierId); + .Where(x => x.ProductId == productId && x.SupplierId == supplierId); } } \ No newline at end of file diff --git a/PyroFetes/Specifications/Products/GetProductByIdSpec.cs b/PyroFetes/Specifications/Products/GetProductByIdSpec.cs index db1421f7..24fb16ff 100644 --- a/PyroFetes/Specifications/Products/GetProductByIdSpec.cs +++ b/PyroFetes/Specifications/Products/GetProductByIdSpec.cs @@ -3,9 +3,9 @@ using PyroFetes.Models; namespace PyroFetes.Specifications.Products; -public sealed class GetProductByIdSpec : Specification +public sealed class GetProductByIdSpec : SingleResultSpecification { - public GetProductByIdSpec(int? productId) + public GetProductByIdSpec(int productId) { Query .Where(p => p.Id == productId) diff --git a/PyroFetes/Specifications/Products/GetProductsUnderLimitSpec.cs b/PyroFetes/Specifications/Products/GetProductsUnderLimitSpec.cs index 26c8d12f..23075f7c 100644 --- a/PyroFetes/Specifications/Products/GetProductsUnderLimitSpec.cs +++ b/PyroFetes/Specifications/Products/GetProductsUnderLimitSpec.cs @@ -9,6 +9,6 @@ public sealed class GetProductsUnderLimitSpec : Specification { Query .Include(p => p.QuotationProducts) - .Where(p => p.QuotationProducts.Any(q => q.Quantity < p.MinimalQuantity)); + .Where(p => p.QuotationProducts != null && p.QuotationProducts.Any(q => q.Quantity < p.MinimalQuantity)); } } \ No newline at end of file diff --git a/PyroFetes/Specifications/PurchaseOrders/GetPurchaseOrderByIdSpec.cs b/PyroFetes/Specifications/PurchaseOrders/GetPurchaseOrderByIdSpec.cs index 272ad75f..b9036860 100644 --- a/PyroFetes/Specifications/PurchaseOrders/GetPurchaseOrderByIdSpec.cs +++ b/PyroFetes/Specifications/PurchaseOrders/GetPurchaseOrderByIdSpec.cs @@ -3,12 +3,13 @@ using PyroFetes.Models; namespace PyroFetes.Specifications.PurchaseOrders; -public sealed class GetPurchaseOrderByIdSpec : Specification +public sealed class GetPurchaseOrderByIdSpec : SingleResultSpecification { public GetPurchaseOrderByIdSpec(int purchaseOrderId) { Query - .Include(po => po.PurchaseProducts) - .Where(po => po.Id == purchaseOrderId); + .Include(x => x.PurchaseProducts!) + .ThenInclude(x => x.Product) + .Where(x => x.Id == purchaseOrderId); } } \ No newline at end of file diff --git a/PyroFetes/Specifications/PurchaseOrders/GetPurchaseOrderByIdWithProductsSpec.cs b/PyroFetes/Specifications/PurchaseOrders/GetPurchaseOrderByIdWithProductsSpec.cs index 7bac3f87..5b1ae68b 100644 --- a/PyroFetes/Specifications/PurchaseOrders/GetPurchaseOrderByIdWithProductsSpec.cs +++ b/PyroFetes/Specifications/PurchaseOrders/GetPurchaseOrderByIdWithProductsSpec.cs @@ -3,14 +3,14 @@ using PyroFetes.Models; namespace PyroFetes.Specifications.PurchaseOrders; -public class GetPurchaseOrderByIdWithProductsSpec : Specification +public class GetPurchaseOrderByIdWithProductsSpec : SingleResultSpecification { public GetPurchaseOrderByIdWithProductsSpec(int purchaseOrderId) { Query - .Where(p => p.Id == purchaseOrderId) - .Include(p => p.PurchaseProducts!) - .ThenInclude(pp => pp.Product) - .ThenInclude(pp=> pp!.Prices); + .Where(x => x.Id == purchaseOrderId) + .Include(x => x.PurchaseProducts!) + .ThenInclude(p => p.Product) + .ThenInclude(p=> p!.Prices); } } \ No newline at end of file diff --git a/PyroFetes/Specifications/PurchaseProducts/GetPurchaseProductByProductIdAndPurchaseOrderIdSpec.cs b/PyroFetes/Specifications/PurchaseProducts/GetPurchaseProductByProductIdAndPurchaseOrderIdSpec.cs index 5d35c62c..2d801b6d 100644 --- a/PyroFetes/Specifications/PurchaseProducts/GetPurchaseProductByProductIdAndPurchaseOrderIdSpec.cs +++ b/PyroFetes/Specifications/PurchaseProducts/GetPurchaseProductByProductIdAndPurchaseOrderIdSpec.cs @@ -3,7 +3,7 @@ using PyroFetes.Models; namespace PyroFetes.Specifications.PurchaseProducts; -public sealed class GetPurchaseProductByProductIdAndPurchaseOrderIdSpec : Specification +public sealed class GetPurchaseProductByProductIdAndPurchaseOrderIdSpec : SingleResultSpecification { public GetPurchaseProductByProductIdAndPurchaseOrderIdSpec(int productId, int purchaseOrderId) { diff --git a/PyroFetes/Specifications/QuotationProducts/GetQuotationProductByProductIdAndQuotationIdSpec.cs b/PyroFetes/Specifications/QuotationProducts/GetQuotationProductByProductIdAndQuotationIdSpec.cs index 9c3b65a4..f0fb5364 100644 --- a/PyroFetes/Specifications/QuotationProducts/GetQuotationProductByProductIdAndQuotationIdSpec.cs +++ b/PyroFetes/Specifications/QuotationProducts/GetQuotationProductByProductIdAndQuotationIdSpec.cs @@ -3,7 +3,7 @@ using PyroFetes.Models; namespace PyroFetes.Specifications.QuotationProducts; -public sealed class GetQuotationProductByProductIdAndQuotationIdSpec : Specification +public sealed class GetQuotationProductByProductIdAndQuotationIdSpec : SingleResultSpecification { public GetQuotationProductByProductIdAndQuotationIdSpec(int productId, int quotationId) { diff --git a/PyroFetes/Specifications/Quotations/GetQuotationByIdSpec.cs b/PyroFetes/Specifications/Quotations/GetQuotationByIdSpec.cs index 5f1e1837..57cb7b75 100644 --- a/PyroFetes/Specifications/Quotations/GetQuotationByIdSpec.cs +++ b/PyroFetes/Specifications/Quotations/GetQuotationByIdSpec.cs @@ -3,12 +3,13 @@ using PyroFetes.Models; namespace PyroFetes.Specifications.Quotations; -public sealed class GetQuotationByIdSpec : Specification +public sealed class GetQuotationByIdSpec : SingleResultSpecification { public GetQuotationByIdSpec(int quotationId) { Query - .Include(q => q.QuotationProducts) + .Include(x => x.QuotationProducts!) + .ThenInclude(x => x.Product) .Where(x => x.Id == quotationId); } } \ No newline at end of file diff --git a/PyroFetes/Specifications/Quotations/GetQuotationByIdWithProductsSpec.cs b/PyroFetes/Specifications/Quotations/GetQuotationByIdWithProductsSpec.cs index 3e8d7243..93d7472e 100644 --- a/PyroFetes/Specifications/Quotations/GetQuotationByIdWithProductsSpec.cs +++ b/PyroFetes/Specifications/Quotations/GetQuotationByIdWithProductsSpec.cs @@ -3,13 +3,13 @@ using PyroFetes.Models; namespace PyroFetes.Specifications.Quotations; -public class GetQuotationByIdWithProductsSpec : Specification +public class GetQuotationByIdWithProductsSpec : SingleResultSpecification { public GetQuotationByIdWithProductsSpec(int quotationId) { Query - .Where(q => q.Id == quotationId) - .Include(q => q.QuotationProducts!) - .ThenInclude(qp => qp.Product); + .Where(x => x.Id == quotationId) + .Include(x => x.QuotationProducts!) + .ThenInclude(p => p.Product); } } \ No newline at end of file diff --git a/PyroFetes/Specifications/Settings/GetSettingByIdSpec.cs b/PyroFetes/Specifications/Settings/GetSettingByIdSpec.cs index cc786e40..fb919a8f 100644 --- a/PyroFetes/Specifications/Settings/GetSettingByIdSpec.cs +++ b/PyroFetes/Specifications/Settings/GetSettingByIdSpec.cs @@ -3,7 +3,7 @@ using PyroFetes.Models; namespace PyroFetes.Specifications.Settings; -public sealed class GetSettingByIdSpec : Specification +public sealed class GetSettingByIdSpec : SingleResultSpecification { public GetSettingByIdSpec(int settingId) { diff --git a/PyroFetes/Specifications/Suppliers/GetSupplierByIdSpec.cs b/PyroFetes/Specifications/Suppliers/GetSupplierByIdSpec.cs index add16994..c649454b 100644 --- a/PyroFetes/Specifications/Suppliers/GetSupplierByIdSpec.cs +++ b/PyroFetes/Specifications/Suppliers/GetSupplierByIdSpec.cs @@ -3,11 +3,13 @@ using PyroFetes.Models; namespace PyroFetes.Specifications.Suppliers; -public sealed class GetSupplierByIdSpec : Specification +public sealed class GetSupplierByIdSpec : SingleResultSpecification { public GetSupplierByIdSpec(int? supplierId) { Query + .Include(x => x.Prices!) + .ThenInclude(p => p.Product) .Where(x => x.Id == supplierId); } } \ No newline at end of file diff --git a/PyroFetes/Specifications/Users/GetUserByIdSpec.cs b/PyroFetes/Specifications/Users/GetUserByIdSpec.cs index db5c0be9..7cd8d7c2 100644 --- a/PyroFetes/Specifications/Users/GetUserByIdSpec.cs +++ b/PyroFetes/Specifications/Users/GetUserByIdSpec.cs @@ -3,7 +3,7 @@ using PyroFetes.Models; namespace PyroFetes.Specifications.Users; -public sealed class GetUserByIdSpec : Specification +public sealed class GetUserByIdSpec : SingleResultSpecification { public GetUserByIdSpec(int userId) { diff --git a/PyroFetes/Specifications/Users/GetUserByNameSpec.cs b/PyroFetes/Specifications/Users/GetUserByNameSpec.cs index daa75ad9..2affac1c 100644 --- a/PyroFetes/Specifications/Users/GetUserByNameSpec.cs +++ b/PyroFetes/Specifications/Users/GetUserByNameSpec.cs @@ -3,7 +3,7 @@ using PyroFetes.Models; namespace PyroFetes.Specifications.Users; -public sealed class GetUserByNameSpec : Specification +public sealed class GetUserByNameSpec : SingleResultSpecification { public GetUserByNameSpec(string userName) { diff --git a/PyroFetes/Specifications/WarehouseProducts/GetWarehouseProductByProductIdSpec.cs b/PyroFetes/Specifications/WarehouseProducts/GetWarehouseProductByProductIdSpec.cs index ff135c13..416c01ac 100644 --- a/PyroFetes/Specifications/WarehouseProducts/GetWarehouseProductByProductIdSpec.cs +++ b/PyroFetes/Specifications/WarehouseProducts/GetWarehouseProductByProductIdSpec.cs @@ -3,11 +3,16 @@ using PyroFetes.Models; namespace PyroFetes.Specifications.WarehouseProducts; -public sealed class GetWarehouseProductByProductIdSpec : Specification +public sealed class GetWarehouseProductByProductIdSpec : SingleResultSpecification { - public GetWarehouseProductByProductIdSpec(int productId) + public GetWarehouseProductByProductIdSpec(int productId, int? warehouseId = null) { Query .Where(x => x.ProductId == productId); + + if (warehouseId.HasValue) + { + Query.Where(x => x.WarehouseId == warehouseId.Value); + } } } \ No newline at end of file diff --git a/PyroFetes/data.sql b/PyroFetes/data.sql index 6a0d4af5..876af84f 100644 --- a/PyroFetes/data.sql +++ b/PyroFetes/data.sql @@ -4,336 +4,386 @@ -- Ordre d'insertion respectant les contraintes FK -- ============================================================ --- ------------------------------------------------------- --- 1. Settings --- ------------------------------------------------------- -INSERT INTO Settings ( Logo, ElectronicSignature) VALUES - ( 'assets/logo_pyrofetes.png', 'assets/signature_direction.png'); - -- ------------------------------------------------------- -- 2. Cities -- ------------------------------------------------------- -INSERT INTO Cities ( Name, ZipCode) VALUES - ( 'Paris', 75001), - ( 'Lyon', 69001), - ( 'Marseille', 13001), - ('Bordeaux', 33000), - ( 'Strasbourg', 67000), - ( 'Nantes', 44000), - ('Toulouse', 31000), - ( 'Lille', 59000), - ( 'Nice', 06000), - ('Montpellier', 34000); +INSERT INTO Cities (Name, ZipCode) +VALUES ('Paris', 75001), + ('Lyon', 69001), + ('Marseille', 13001), + ('Bordeaux', 33000), + ('Strasbourg', 67000), + ('Nantes', 44000), + ('Toulouse', 31000), + ('Lille', 59000), + ('Nice', 06000), + ('Montpellier', 34000); -- ------------------------------------------------------- -- 3. Classifications -- ------------------------------------------------------- -INSERT INTO Classifications ( Label) VALUES - ('F1 – Faible danger'), - ( 'F2 – Danger moyen'), - ( 'F3 – Danger élevé'), - ( 'F4 – Usage professionnel'), - ( 'T1 – Théâtral usage général'), - ( 'T2 – Théâtral usage professionnel'); +INSERT INTO Classifications (Label) +VALUES ('F1 – Faible danger'), + ('F2 – Danger moyen'), + ('F3 – Danger élevé'), + ('F4 – Usage professionnel'), + ('T1 – Théâtral usage général'), + ('T2 – Théâtral usage professionnel'); -- ------------------------------------------------------- -- 4. ProductCategories -- ------------------------------------------------------- -INSERT INTO ProductCategories ( Label) VALUES - ( 'Bouquet final'), - ( 'Chandelle romaine'), - ( 'Fontaine'), - ( 'Fusée'), - ( 'Mine'), - ( 'Pétard'), - ( 'Torche'), - ( 'Batterie'), - ( 'Cascades'), - ( 'Lanceur électrique'); +INSERT INTO ProductCategories (Label) +VALUES ('Bouquet final'), + ('Chandelle romaine'), + ('Fontaine'), + ('Fusée'), + ('Mine'), + ('Pétard'), + ('Torche'), + ('Batterie'), + ('Cascades'), + ('Lanceur électrique'); -- ------------------------------------------------------- -- 5. Colors -- ------------------------------------------------------- -INSERT INTO Colors ( Label) VALUES - ( 'Rouge'), - ( 'Vert'), - ( 'Bleu'), - ( 'Or'), - ( 'Argent'), - ( 'Blanc'), - ( 'Orange'), - ( 'Violet'), - ( 'Rose'), - ( 'Multicolore'); +INSERT INTO Colors (Label) +VALUES ('Rouge'), + ('Vert'), + ('Bleu'), + ('Or'), + ('Argent'), + ('Blanc'), + ('Orange'), + ('Violet'), + ('Rose'), + ('Multicolore'); -- ------------------------------------------------------- -- 6. Effects -- ------------------------------------------------------- -INSERT INTO Effects ( Label) VALUES - ( 'Craquement'), - ( 'Sifflement'), - ( 'Scintillement'), - ( 'Pluie dorée'), - ( 'Bouquet étoilé'), - ( 'Palmier'), - ( 'Chrysanthème'), - ( 'Peony'), - ( 'Comet'), - ( 'Strobe'), - ( 'Nishiki Kamuro'), - ('Pistil'); +INSERT INTO Effects (Label) +VALUES ('Craquement'), + ('Sifflement'), + ('Scintillement'), + ('Pluie dorée'), + ('Bouquet étoilé'), + ('Palmier'), + ('Chrysanthème'), + ('Peony'), + ('Comet'), + ('Strobe'), + ('Nishiki Kamuro'), + ('Pistil'); -- ------------------------------------------------------- -- 7. Movements (avant Products car FK) -- ------------------------------------------------------- -INSERT INTO Movements ( Date, Start, Arrival, Quantity, SourceWarehouseId, DestinationWarehouseId) VALUES - ('2024-01-10 08:00:00', '2024-01-10 08:00:00', '2024-01-10 14:00:00', 200, NULL, 1), - ( '2024-02-15 09:00:00', '2024-02-15 09:00:00', '2024-02-15 16:30:00', 150, NULL, 2), - ('2024-03-01 07:30:00', '2024-03-01 07:30:00', '2024-03-01 12:00:00', 80, 1, 3), - ( '2024-04-20 10:00:00', '2024-04-20 10:00:00', '2024-04-20 18:00:00', 300, 2, 1), - ( '2024-05-05 08:00:00', '2024-05-05 08:00:00', '2024-05-05 15:00:00', 120, 3, 2), - ('2024-06-14 06:00:00', '2024-06-14 06:00:00', '2024-06-14 10:00:00', 500, 1, NULL), - ( '2024-07-04 07:00:00', '2024-07-04 07:00:00', '2024-07-04 11:00:00', 250, 2, NULL), - ( '2024-08-12 09:00:00', '2024-08-12 09:00:00', '2024-08-12 17:00:00', 180, NULL, 3); +INSERT INTO Movements (Date, Start, Arrival, Quantity, SourceWarehouseId, DestinationWarehouseId) +VALUES ('2024-01-10 08:00:00', '2024-01-10 08:00:00', '2024-01-10 14:00:00', 200, NULL, 1), + ('2024-02-15 09:00:00', '2024-02-15 09:00:00', '2024-02-15 16:30:00', 150, NULL, 2), + ('2024-03-01 07:30:00', '2024-03-01 07:30:00', '2024-03-01 12:00:00', 80, 1, 3), + ('2024-04-20 10:00:00', '2024-04-20 10:00:00', '2024-04-20 18:00:00', 300, 2, 1), + ('2024-05-05 08:00:00', '2024-05-05 08:00:00', '2024-05-05 15:00:00', 120, 3, 2), + ('2024-06-14 06:00:00', '2024-06-14 06:00:00', '2024-06-14 10:00:00', 500, 1, NULL), + ('2024-07-04 07:00:00', '2024-07-04 07:00:00', '2024-07-04 11:00:00', 250, 2, NULL), + ('2024-08-12 09:00:00', '2024-08-12 09:00:00', '2024-08-12 17:00:00', 180, NULL, 3); -- ------------------------------------------------------- -- 8. Products -- ------------------------------------------------------- -INSERT INTO Products ( Reference, Name, Duration, Caliber, ApprovalNumber, Weight, Nec, Image, Link, MinimalQuantity, ClassificationId, ProductCategoryId, MovementId) VALUES - ( 'PYR-001', 'Bouquet Tricolore 30T', 45.5, 30, 'APP-2023-001', 1.200, 0.850, 'products/bouquet_tricolore.jpg', 'https://catalogue.pyrofetes.fr/PYR-001', 10, 4, 1, 1), - ( 'PYR-002', 'Chandelle Or 25T', 30.0, 25, 'APP-2023-002', 0.800, 0.560, 'products/chandelle_or.jpg', 'https://catalogue.pyrofetes.fr/PYR-002', 20, 3, 2, 2), - ( 'PYR-003', 'Fontaine Argentée 20T', 60.0, 20, 'APP-2023-003', 0.500, 0.300, 'products/fontaine_arg.jpg', 'https://catalogue.pyrofetes.fr/PYR-003', 15, 2, 3, 3), - ( 'PYR-004', 'Fusée Palmier 50T', 25.0, 50, 'APP-2023-004', 2.500, 1.800, 'products/fusee_palmier.jpg', 'https://catalogue.pyrofetes.fr/PYR-004', 5, 4, 4, 4), - ( 'PYR-005', 'Mine Chrysanthème 75T', 15.0, 75, 'APP-2023-005', 3.200, 2.400, 'products/mine_chrysantheme.jpg', 'https://catalogue.pyrofetes.fr/PYR-005', 5, 4, 5, 5), - ( 'PYR-006', 'Batterie Festival 100T', 120.0, 100, 'APP-2023-006', 8.000, 5.600, 'products/batterie_festival.jpg', 'https://catalogue.pyrofetes.fr/PYR-006', 3, 4, 8, 6), - ( 'PYR-007', 'Torche Colorée 15T', 90.0, 15, 'APP-2023-007', 0.300, 0.180, 'products/torche_coloree.jpg', 'https://catalogue.pyrofetes.fr/PYR-007', 30, 2, 7, 7), - ( 'PYR-008', 'Cascade Dorée 40T', 75.0, 40, 'APP-2023-008', 1.800, 1.200, 'products/cascade_doree.jpg', 'https://catalogue.pyrofetes.fr/PYR-008', 10, 4, 9, 8), - ( 'PYR-009', 'Peony Multicolore 60T', 30.0, 60, 'APP-2023-009', 4.500, 3.200, 'products/peony_multi.jpg', 'https://catalogue.pyrofetes.fr/PYR-009', 5, 4, 1, 1), - ( 'PYR-010', 'Lanceur 36 Tirs EL', 0.0, 0, 'APP-2023-010', 2.100, 0.000, 'products/lanceur_36.jpg', 'https://catalogue.pyrofetes.fr/PYR-010', 2, 6, 10,2), - ( 'PYR-011', 'Strobe Blanc Intense 25T', 45.0, 25, 'APP-2023-011', 0.900, 0.650, 'products/strobe_blanc.jpg', 'https://catalogue.pyrofetes.fr/PYR-011', 10, 3, 3, 3), - ( 'PYR-012', 'Comet Violet 30T', 20.0, 30, 'APP-2023-012', 1.100, 0.800, 'products/comet_violet.jpg', 'https://catalogue.pyrofetes.fr/PYR-012', 12, 3, 4, 4); +INSERT INTO Products (Reference, Name, Duration, Caliber, ApprovalNumber, Weight, Nec, Image, Link, MinimalQuantity, ClassificationId, ProductCategoryId, MovementId) +VALUES ('PYR-001', 'Bouquet Tricolore 30T', 45.5, 30, 'APP-2023-001', 1.200, 0.850, 'products/bouquet_tricolore.jpg', 'https://catalogue.pyrofetes.fr/PYR-001', 10, 4, 1, 2), + ('PYR-002', 'Chandelle Or 25T', 30.0, 25, 'APP-2023-002', 0.800, 0.560, 'products/chandelle_or.jpg', 'https://catalogue.pyrofetes.fr/PYR-002', 20, 3, 2, 2), + ('PYR-003', 'Fontaine Argentée 20T', 60.0, 20, 'APP-2023-003', 0.500, 0.300, 'products/fontaine_arg.jpg', 'https://catalogue.pyrofetes.fr/PYR-003', 15, 2, 3, 3), + ('PYR-004', 'Fusée Palmier 50T', 25.0, 50, 'APP-2023-004', 2.500, 1.800, 'products/fusee_palmier.jpg', 'https://catalogue.pyrofetes.fr/PYR-004', 5, 4, 4, 4), + ('PYR-005', 'Mine Chrysanthème 75T', 15.0, 75, 'APP-2023-005', 3.200, 2.400, 'products/mine_chrysantheme.jpg', 'https://catalogue.pyrofetes.fr/PYR-005', 5, 4, 5, 5), + ('PYR-006', 'Batterie Festival 100T', 120.0, 100, 'APP-2023-006', 8.000, 5.600, 'products/batterie_festival.jpg', 'https://catalogue.pyrofetes.fr/PYR-006', 3, 4, 8, 6), + ('PYR-007', 'Torche Colorée 15T', 90.0, 15, 'APP-2023-007', 0.300, 0.180, 'products/torche_coloree.jpg', 'https://catalogue.pyrofetes.fr/PYR-007', 30, 2, 7, 7), + ('PYR-008', 'Cascade Dorée 40T', 75.0, 40, 'APP-2023-008', 1.800, 1.200, 'products/cascade_doree.jpg', 'https://catalogue.pyrofetes.fr/PYR-008', 10, 4, 9, 8), + ('PYR-009', 'Peony Multicolore 60T', 30.0, 60, 'APP-2023-009', 4.500, 3.200, 'products/peony_multi.jpg', 'https://catalogue.pyrofetes.fr/PYR-009', 5, 4, 1, 6), + ('PYR-010', 'Lanceur 36 Tirs EL', 0.0, 0, 'APP-2023-010', 2.100, 0.000, 'products/lanceur_36.jpg', 'https://catalogue.pyrofetes.fr/PYR-010', 2, 6, 10, 2), + ('PYR-011', 'Strobe Blanc Intense 25T', 45.0, 25, 'APP-2023-011', 0.900, 0.650, 'products/strobe_blanc.jpg', 'https://catalogue.pyrofetes.fr/PYR-011', 10, 3, 3, 3), + ('PYR-012', 'Comet Violet 30T', 20.0, 30, 'APP-2023-012', 1.100, 0.800, 'products/comet_violet.jpg', 'https://catalogue.pyrofetes.fr/PYR-012', 12, 3, 4, 4); -- ------------------------------------------------------- -- 9. Brands -- ------------------------------------------------------- -INSERT INTO Brands ( Name, ProductId) VALUES - ( 'PyroMaster', 1), - ( 'GoldFlame', 1), - ( 'ArtificePlus', 2), - ( 'ArtificePlus', 3), - ( 'StarBurst', 4), - ( 'StarBurst', 5), - ( 'FestivalFire', 6), - ( 'TorchCo', 7), - ( 'GoldFlame', 8), - ( 'PyroMaster', 9), - ( 'ElecFire', 10), - ( 'PyroMaster', 11), - ( 'StarBurst', 12); +INSERT INTO Brands (Name, ProductId) +VALUES ('PyroMaster', 3), + ('GoldFlame', 3), + ('ArtificePlus', 10), + ('ArtificePlus', 3), + ('StarBurst', 4), + ('StarBurst', 5), + ('FestivalFire', 6), + ('TorchCo', 7), + ('GoldFlame', 8), + ('PyroMaster', 9), + ('ElecFire', 10), + ('PyroMaster', 11), + ('StarBurst', 12); -- ------------------------------------------------------- -- 10. ProductColors -- ------------------------------------------------------- -INSERT INTO ProductColors (ProductId, ColorId) VALUES - (1, 1), (1, 3), (1, 6), -- Bouquet Tricolore : rouge, bleu, blanc - (2, 4), -- Chandelle Or - (3, 5), -- Fontaine Argentée - (4, 4), (4, 2), -- Fusée Palmier : or, vert - (5, 7), (5, 4), -- Mine Chrysanthème : orange, or - (6, 10), -- Batterie Festival : multicolore - (7, 1), (7, 2), (7, 3), -- Torche : rouge, vert, bleu - (8, 4), (8, 5), -- Cascade Dorée : or, argent - (9, 10), -- Peony Multicolore - (11, 6), -- Strobe Blanc - (12, 8); -- Comet Violet +INSERT INTO ProductColors (ProductId, ColorId) +VALUES (3, 1), + (3, 3), + (3, 6), -- Bouquet Tricolore : rouge, bleu, blanc + (3, 4), -- Chandelle Or + (3, 5), -- Fontaine Argentée + (4, 4), + (4, 2), -- Fusée Palmier : or, vert + (5, 7), + (5, 4), -- Mine Chrysanthème : orange, or + (6, 10), -- Batterie Festival : multicolore + (7, 1), + (7, 2), + (7, 3), -- Torche : rouge, vert, bleu + (8, 4), + (8, 5), -- Cascade Dorée : or, argent + (9, 10), -- Peony Multicolore + (11, 6), -- Strobe Blanc + (12, 8); +-- Comet Violet -- ------------------------------------------------------- -- 11. ProductEffects -- ------------------------------------------------------- -INSERT INTO ProductEffects (ProductId, EffectId) VALUES - (1, 5), (1, 8), -- Bouquet : bouquet étoilé, peony - (2, 4), (2, 3), -- Chandelle Or : pluie dorée, scintillement - (3, 3), -- Fontaine : scintillement - (4, 6), (4, 9), -- Fusée Palmier : palmier, comet - (5, 7), (5, 1), -- Mine : chrysanthème, craquement - (6, 5), (6, 7), (6, 10), -- Batterie : bouquet, chrysanthème, strobe - (7, 3), (7, 2), -- Torche : scintillement, sifflement - (8, 4), (8, 11), -- Cascade : pluie dorée, Nishiki - (9, 8), (9, 12), -- Peony : peony, pistil - (11, 10), -- Strobe - (12, 9); -- Comet +INSERT INTO ProductEffects (ProductId, EffectId) +VALUES (3, 5), + (3, 8), -- Bouquet : bouquet étoilé, peony + (3, 4), + (4, 3), -- Chandelle Or : pluie dorée, scintillement + (3, 3), -- Fontaine : scintillement + (4, 6), + (4, 9), -- Fusée Palmier : palmier, comet + (5, 7), + (5, 1), -- Mine : chrysanthème, craquement + (6, 5), + (6, 7), + (6, 10), -- Batterie : bouquet, chrysanthème, strobe + (7, 3), + (7, 2), -- Torche : scintillement, sifflement + (8, 4), + (8, 11), -- Cascade : pluie dorée, Nishiki + (9, 8), + (9, 12), -- Peony : peony, pistil + (11, 10), -- Strobe + (12, 9); +-- Comet -- ------------------------------------------------------- -- 12. Warehouses -- ------------------------------------------------------- -INSERT INTO Warehouses ( Name, MaxWeight, [Current], MinWeight, Address, ZipCode, City) VALUES - ( 'Entrepôt Central Paris', 50000, 18500, 5000, '12 rue de la Pyrotechnie', '75019', 'Paris'), - ( 'Dépôt Sud Marseille', 30000, 12000, 3000, '8 avenue du Port Sec', '13016', 'Marseille'), - ( 'Stockage Est Strasbourg', 20000, 8200, 2000, '5 chemin des Entrepôts', '67200', 'Strasbourg'), - ( 'Site Ouest Nantes', 25000, 6500, 2500, '22 zone industrielle Ouest','44800', 'Nantes'); +INSERT INTO Warehouses (Name, MaxWeight, [ Current], MinWeight, Address, ZipCode, City) +VALUES ('Entrepôt Central Paris', 50000, 18500, 5000, '12 rue de la Pyrotechnie', '75019', 'Paris'), + ('Dépôt Sud Marseille', 30000, 12000, 3000, '8 avenue du Port Sec', '13016', 'Marseille'), + ('Stockage Est Strasbourg', 20000, 8200, 2000, '5 chemin des Entrepôts', '67200', 'Strasbourg'), + ('Site Ouest Nantes', 25000, 6500, 2500, '22 zone industrielle Ouest', '44800', 'Nantes'); -- ------------------------------------------------------- -- 13. WarehouseProducts -- ------------------------------------------------------- -INSERT INTO WarehouseProducts (ProductId, WarehouseId, Quantity) VALUES - (1, 1, 120), (1, 2, 60), - (2, 1, 200), (2, 3, 80), - (3, 1, 150), (3, 4, 90), - (4, 1, 40), (4, 2, 25), - (5, 1, 30), (5, 2, 15), - (6, 1, 20), (6, 3, 10), - (7, 2, 300), (7, 4, 180), - (8, 1, 75), (8, 2, 50), - (9, 1, 35), - (10, 1, 18), (10, 3, 12), - (11, 2, 60), - (12, 3, 45); +INSERT INTO WarehouseProducts (ProductId, WarehouseId, Quantity) +VALUES (3, 1, 120), + (3, 2, 60), + (3, 3, 80), + (3, 4, 90), + (4, 1, 40), + (4, 2, 25), + (5, 1, 30), + (5, 2, 15), + (6, 1, 20), + (6, 3, 10), + (7, 2, 300), + (7, 4, 180), + (8, 1, 75), + (8, 2, 50), + (9, 1, 35), + (10, 1, 18), + (10, 3, 12), + (11, 2, 60), + (12, 3, 45); -- ------------------------------------------------------- -- 14. Materials -- ------------------------------------------------------- -INSERT INTO Materials ( Name, Quantity, WarehouseId) VALUES - ( 'Câble électrique 50m', 40, 1), - ( 'Détonateur électrique', 500, 1), - ( 'Bouchon sécurité rouge', 300, 1), - ( 'Trépied aluminium', 25, 2), - ( 'Tuyau métallique 1m', 80, 2), - ( 'Boitier de tir 36 sorties', 10, 1), - ( 'Rallonge 10m IP67', 60, 3), - ( 'Mortier plastique 50mm', 200, 3), - ( 'Mortier acier 75mm', 100, 1), - ('Tableau de tir 100 CH', 5, 4), - ( 'Caisse de transport étanche',30, 2), - ( 'Lunettes de protection', 50, 1); +INSERT INTO Materials (Name, Quantity, WarehouseId) +VALUES ('Câble électrique 50m', 40, 1), + ('Détonateur électrique', 500, 1), + ('Bouchon sécurité rouge', 300, 1), + ('Trépied aluminium', 25, 2), + ('Tuyau métallique 1m', 80, 2), + ('Boitier de tir 36 sorties', 10, 1), + ('Rallonge 10m IP67', 60, 3), + ('Mortier plastique 50mm', 200, 3), + ('Mortier acier 75mm', 100, 1), + ('Tableau de tir 100 CH', 5, 4), + ('Caisse de transport étanche', 30, 2), + ('Lunettes de protection', 50, 1); -- ------------------------------------------------------- -- 15. MaterialWarehouses -- ------------------------------------------------------- -INSERT INTO MaterialWarehouses (MaterialId, WarehouseId) VALUES - (1, 1), (1, 3), - (2, 1), (2, 2), - (3, 1), - (4, 2), (4, 4), - (5, 2), (5, 3), - (6, 1), (6, 4), - (7, 3), - (8, 3), (8, 1), - (9, 1), - (10, 4), - (11, 2), - (12, 1), (12, 2); +INSERT INTO MaterialWarehouses (MaterialId, WarehouseId) +VALUES (1, 1), + (1, 3), + (2, 1), + (2, 2), + (3, 1), + (4, 2), + (4, 4), + (5, 2), + (5, 3), + (6, 1), + (6, 4), + (7, 3), + (8, 3), + (8, 1), + (9, 1), + (10, 4), + (11, 2), + (12, 1), + (12, 2); -- ------------------------------------------------------- -- 16. Suppliers -- ------------------------------------------------------- -INSERT INTO Suppliers ( Name, Email, Phone, Address, ZipCode, City, DeliveryDelay) VALUES - ('Pyrotechnie Ruggieri', 'commandes@ruggieri.fr', '01 47 00 11 22', '14 avenue de la Fête', '75015', 'Paris', 7), - ( 'Lacroix Défense Feux', 'pro@lacroix-feux.com', '04 78 92 00 10', '3 zone industrielle Nord','69130', 'Lyon', 10), - ( 'Jorge Banus Pyro', 'info@jorgebanus-pyro.es', '+34 952 810 000','Pol. Ind. Las Maravillas', '29600', 'Marbella', 21), - ('Brother Pyro Import', 'sales@brotherpyro.com', '+1 555 010 2020','1200 Fireworks Blvd', '30301', 'Atlanta', 30), - ( 'Nico Pyrotechnie', 'achats@nico-pyro.fr', '04 91 25 36 47', '27 impasse des Artifices','13010', 'Marseille', 5), - ( 'Surex Pyrotechnie', 'contact@surex.fr', '03 90 00 12 34', '10 rue Gutenberg', '67600', 'Sélestat', 6); +INSERT INTO Suppliers (Name, Email, Phone, Address, ZipCode, City, DeliveryDelay) +VALUES ('Pyrotechnie Ruggieri', 'commandes@ruggieri.fr', '01 47 00 11 22', '14 avenue de la Fête', '75015', 'Paris', 7), + ('Lacroix Défense Feux', 'pro@lacroix-feux.com', '04 78 92 00 10', '3 zone industrielle Nord', '69130', 'Lyon', 10), + ('Jorge Banus Pyro', 'info@jorgebanus-pyro.es', '+34 952 810 000', 'Pol. Ind. Las Maravillas', '29600', 'Marbella', 21), + ('Brother Pyro Import', 'sales@brotherpyro.com', '+1 555 010 2020', '1200 Fireworks Blvd', '30301', 'Atlanta', 30), + ('Nico Pyrotechnie', 'achats@nico-pyro.fr', '04 91 25 36 47', '27 impasse des Artifices', '13010', 'Marseille', 5), + ('Surex Pyrotechnie', 'contact@surex.fr', '03 90 00 12 34', '10 rue Gutenberg', '67600', 'Sélestat', 6); -- ------------------------------------------------------- -- 17. Prices (Product x Supplier) -- ------------------------------------------------------- -INSERT INTO Prices (ProductId, SupplierId, SellingPrice) VALUES - (1, 1, 12.50), (1, 2, 13.00), - (2, 1, 6.80), (2, 5, 7.20), - (3, 1, 4.50), (3, 5, 4.80), - (4, 2, 28.00), (4, 3, 26.50), - (5, 2, 35.00), (5, 3, 33.00), - (6, 1, 95.00), (6, 2, 98.50), - (7, 5, 3.20), (7, 6, 3.50), - (8, 1, 22.00), (8, 2, 23.50), - (9, 2, 42.00), (9, 4, 39.00), - (10,1, 185.00),(10,6, 190.00), - (11,5, 8.90), (11,6, 9.20), - (12,3, 14.00), (12,4, 13.50); +INSERT INTO Prices (ProductId, SupplierId, SellingPrice) +VALUES (1, 1, 12.50), + (1, 2, 13.00), + (2, 1, 6.80), + (2, 5, 7.20), + (3, 1, 4.50), + (3, 5, 4.80), + (4, 2, 28.00), + (4, 3, 26.50), + (5, 2, 35.00), + (5, 3, 33.00), + (6, 1, 95.00), + (6, 2, 98.50), + (7, 5, 3.20), + (7, 6, 3.50), + (8, 1, 22.00), + (8, 2, 23.50), + (9, 2, 42.00), + (9, 4, 39.00), + (10, 1, 185.00), + (10, 6, 190.00), + (11, 5, 8.90), + (11, 6, 9.20), + (12, 3, 14.00), + (12, 4, 13.50); -- ------------------------------------------------------- -- 18. Deliverers -- ------------------------------------------------------- -INSERT INTO Deliverers ( Transporter) VALUES - ( 'Chronopost Marchandises Dangereuses'), - ( 'DHL Fret Spécial'), - ( 'TNT Express ADR'), - ('Transport Pyro Interne'), - ( 'Geodis Fret'); +INSERT INTO Deliverers (Transporter) +VALUES ('Chronopost Marchandises Dangereuses'), + ('DHL Fret Spécial'), + ('TNT Express ADR'), + ('Transport Pyro Interne'), + ('Geodis Fret'); -- ------------------------------------------------------- -- 19. DeliveryNotes -- ------------------------------------------------------- -INSERT INTO DeliveryNotes (TrackingNumber, DelivererId, EstimateDeliveryDate, ExpeditionDate, RealDeliveryDate) VALUES - ('CPM-2024-001234', 1, '2024-01-12', '2024-01-09', '2024-01-12'), - ( 'DHL-2024-005678', 2, '2024-02-18', '2024-02-14', '2024-02-17'), - ( 'TNT-2024-009012', 3, '2024-03-05', '2024-03-01', '2024-03-06'), - ('INT-2024-000001', 4, '2024-04-22', '2024-04-20', '2024-04-22'), - ( 'GEO-2024-001111', 5, '2024-05-10', '2024-05-07', NULL); +INSERT INTO DeliveryNotes (TrackingNumber, DelivererId, EstimateDeliveryDate, ExpeditionDate, RealDeliveryDate) +VALUES ('CPM-2024-001234', 1, '2024-01-12', '2024-01-09', '2024-01-12'), + ('DHL-2024-005678', 2, '2024-02-18', '2024-02-14', '2024-02-17'), + ('TNT-2024-009012', 3, '2024-03-05', '2024-03-01', '2024-03-06'), + ('INT-2024-000001', 4, '2024-04-22', '2024-04-20', '2024-04-22'), + ('GEO-2024-001111', 5, '2024-05-10', '2024-05-07', NULL); -- ------------------------------------------------------- -- 20. ProductDeliveries -- ------------------------------------------------------- -INSERT INTO ProductDeliveries (ProductId, DeliveryNoteId, Quantity) VALUES - (1, 1, 60), (2, 1, 100), - (3, 2, 80), (4, 2, 20), - (5, 3, 15), (6, 3, 8), - (7, 4, 150), (8, 4, 40), - (9, 5, 30), (10,5, 6); +INSERT INTO ProductDeliveries (ProductId, DeliveryNoteId, Quantity) +VALUES (1, 1, 60), + (2, 1, 100), + (3, 2, 80), + (4, 2, 20), + (5, 3, 15), + (6, 3, 8), + (7, 4, 150), + (8, 4, 40), + (9, 5, 30), + (10, 5, 6); -- ------------------------------------------------------- -- 21. PurchaseOrders -- ------------------------------------------------------- -INSERT INTO PurchaseOrders ( PurchaseConditions, SupplierId) VALUES - ('Paiement à 30 jours – transport inclus – palette EUR 80x120', 1), - ('Paiement à 60 jours – Incoterm EXW Lyon – assurance acheteur', 2), - ('Paiement anticipé -2% – transport DDP Paris – emballage ADR inclus', 5), - ('Paiement à 45 jours – transport à la charge du vendeur jusqu au dépôt', 3), - ( 'Paiement à 30 jours – transport maritime consolidé', 4); +INSERT INTO PurchaseOrders (PurchaseConditions, SupplierId) +VALUES ('Paiement à 30 jours – transport inclus – palette EUR 80x120', 1), + ('Paiement à 60 jours – Incoterm EXW Lyon – assurance acheteur', 2), + ('Paiement anticipé -2% – transport DDP Paris – emballage ADR inclus', 5), + ('Paiement à 45 jours – transport à la charge du vendeur jusqu au dépôt', 3), + ('Paiement à 30 jours – transport maritime consolidé', 4); -- ------------------------------------------------------- -- 22. PurchaseProducts -- ------------------------------------------------------- -INSERT INTO PurchaseProducts (ProductId, PurchaseOrderId, Quantity) VALUES - (1, 1, 200), (2, 1, 300), (3, 1, 150), - (4, 2, 50), (5, 2, 30), (6, 2, 20), - (7, 3, 500), (8, 3, 100), - (9, 4, 40),(10, 4, 15), - (11,5, 100),(12, 5, 80); +INSERT INTO PurchaseProducts (ProductId, PurchaseOrderId, Quantity) +VALUES (1, 1, 200), + (2, 1, 300), + (3, 1, 150), + (4, 2, 50), + (5, 2, 30), + (6, 2, 20), + (7, 3, 500), + (8, 3, 100), + (9, 4, 40), + (10, 4, 15), + (11, 5, 100), + (12, 5, 80); -- ------------------------------------------------------- -- 23. ProviderTypes -- ------------------------------------------------------- -INSERT INTO ProviderTypes ( Label) VALUES - ( 'Sonorisation'), - ('Éclairage scénique'), - ( 'Sécurité / Protection'), - ( 'Logistique & Transport'), - ( 'Location de matériel'), - ( 'Médical / Secours'); +INSERT INTO ProviderTypes (Label) +VALUES ('Sonorisation'), + ('Éclairage scénique'), + ('Sécurité / Protection'), + ('Logistique & Transport'), + ('Location de matériel'), + ('Médical / Secours'); -- ------------------------------------------------------- -- 24. ServiceProviders -- ------------------------------------------------------- -INSERT INTO ServiceProviders ( Price, ProviderTypeId) VALUES - ( 4500.00, 1), - (3200.00, 1), - (5800.00, 2), - (2800.00, 3), - (7500.00, 3), - ( 1200.00, 4), - (73500.00, 5), - ( 900.00, 6); +INSERT INTO ServiceProviders (Price, ProviderTypeId) +VALUES (4500.00, 1), + (3200.00, 1), + (5800.00, 2), + (2800.00, 3), + (7500.00, 3), + (1200.00, 4), + (73500.00, 5), + (900.00, 6); -- ------------------------------------------------------- -- 25. CustomerTypes -- ------------------------------------------------------- -INSERT INTO CustomerTypes ( Label) VALUES - ( 'Mairie / Collectivité'), - ( 'Association'), - ( 'Entreprise privée'), - ( 'Particulier'), - ( 'Organisateur d événements'); +INSERT INTO CustomerTypes (Label) +VALUES ('Mairie / Collectivité'), + ('Association'), + ('Entreprise privée'), + ('Particulier'), + ('Organisateur d événements'); -- ------------------------------------------------------- -- 26. Customers @@ -344,272 +394,372 @@ INSERT INTO CustomerTypes ( Label) VALUES -- ------------------------------------------------------- - -- ------------------------------------------------------- -- 31. QuotationProducts -- ------------------------------------------------------- -INSERT INTO QuotationProducts (ProductId, QuotationId, Quantity) VALUES - (1, 1, 80), (4, 1, 30), (5, 1, 20), (6, 1, 5), (8, 1, 40), - (2, 2, 50), (3, 2, 40), (7, 2, 80), - (1, 3, 40), (6, 3, 3), (9, 3, 15), - (1, 4, 60), (4, 4, 20), (6, 4, 4), (7, 4,100), - (1, 5, 70), (5, 5, 15), (8, 5, 30), - (2, 6, 60), (3, 6, 50), (7, 6, 90); +INSERT INTO QuotationProducts (ProductId, QuotationId, Quantity) +VALUES (1, 1, 80), + (4, 1, 30), + (5, 1, 20), + (6, 1, 5), + (8, 1, 40), + (2, 2, 50), + (3, 2, 40), + (7, 2, 80), + (1, 3, 40), + (6, 3, 3), + (9, 3, 15), + (1, 4, 60), + (4, 4, 20), + (6, 4, 4), + (7, 4, 100), + (1, 5, 70), + (5, 5, 15), + (8, 5, 30), + (2, 6, 60), + (3, 6, 50), + (7, 6, 90); -- ------------------------------------------------------- -- 32. Staff -- ------------------------------------------------------- -INSERT INTO Staffs ( FirstName, LastName, Profession, Email, F4T2NumberApproval, F4T2ExpirationDate) VALUES - ( 'Antoine', 'Duval', 'Chef artificier', 'a.duval@pyrofetes.fr', 'F4-2021-00142', '2025-12-31'), - ( 'Camille', 'Renard', 'Artificier', 'c.renard@pyrofetes.fr', 'F4-2022-00255', '2026-06-30'), - ( 'Nicolas', 'Lefort', 'Artificier', 'n.lefort@pyrofetes.fr', 'F4-2020-00387', '2024-12-31'), - ( 'Emma', 'Vidal', 'Technicien pyrotechnie', 'e.vidal@pyrofetes.fr', 'T2-2023-00104', '2027-03-31'), - ( 'Julien', 'Moreau', 'Chef de chantier', 'j.moreau@pyrofetes.fr', 'F4-2021-00521', '2025-09-30'), - ( 'Laura', 'Blanc', 'Artificière', 'l.blanc@pyrofetes.fr', 'F4-2022-00698', '2026-12-31'), - ( 'Pierre', 'Garnier', 'Technicien électronique', 'p.garnier@pyrofetes.fr', 'T2-2021-00789', '2025-11-30'), - ( 'Marie', 'Lefebvre', 'Responsable sécurité', 'm.lefebvre@pyrofetes.fr', 'F4-2023-00901', '2027-06-30'), - ( 'Hugo', 'Simon', 'Artificier junior', 'h.simon@pyrofetes.fr', 'T1-2023-01023', '2025-06-30'), - ( 'Pauline', 'Robert', 'Coordinatrice logistique', 'p.robert@pyrofetes.fr', 'T2-2022-01145', '2026-09-30'); +INSERT INTO Staffs (FirstName, LastName, Profession, Email, F4T2NumberApproval, F4T2ExpirationDate) +VALUES ('Antoine', 'Duval', 'Chef artificier', 'a.duval@pyrofetes.fr', 'F4-2021-00142', '2025-12-31'), + ('Camille', 'Renard', 'Artificier', 'c.renard@pyrofetes.fr', 'F4-2022-00255', '2026-06-30'), + ('Nicolas', 'Lefort', 'Artificier', 'n.lefort@pyrofetes.fr', 'F4-2020-00387', '2024-12-31'), + ('Emma', 'Vidal', 'Technicien pyrotechnie', 'e.vidal@pyrofetes.fr', 'T2-2023-00104', '2027-03-31'), + ('Julien', 'Moreau', 'Chef de chantier', 'j.moreau@pyrofetes.fr', 'F4-2021-00521', '2025-09-30'), + ('Laura', 'Blanc', 'Artificière', 'l.blanc@pyrofetes.fr', 'F4-2022-00698', '2026-12-31'), + ('Pierre', 'Garnier', 'Technicien électronique', 'p.garnier@pyrofetes.fr', 'T2-2021-00789', '2025-11-30'), + ('Marie', 'Lefebvre', 'Responsable sécurité', 'm.lefebvre@pyrofetes.fr', 'F4-2023-00901', '2027-06-30'), + ('Hugo', 'Simon', 'Artificier junior', 'h.simon@pyrofetes.fr', 'T1-2023-01023', '2025-06-30'), + ('Pauline', 'Robert', 'Coordinatrice logistique', 'p.robert@pyrofetes.fr', 'T2-2022-01145', '2026-09-30'); -- ------------------------------------------------------- -- 33. ExperienceLevels -- ------------------------------------------------------- -INSERT INTO ExperienceLevels ( Label, StaffId) VALUES - ( 'Expert – +15 ans', 1), - ( 'Confirmé – 8 ans', 2), - ( 'Confirmé – 6 ans', 3), - ( 'Intermédiaire – 3 ans', 4), - ( 'Expert – +12 ans', 5), - ( 'Confirmé – 7 ans', 6), - ( 'Intermédiaire – 4 ans', 7), - ( 'Confirmé – 5 ans', 8), - ( 'Débutant – 1 an', 9), - ( 'Intermédiaire – 3 ans', 10); +INSERT INTO ExperienceLevels (Label, StaffId) +VALUES ('Expert – +15 ans', 1), + ('Confirmé – 8 ans', 2), + ('Confirmé – 6 ans', 3), + ('Intermédiaire – 3 ans', 4), + ('Expert – +12 ans', 5), + ('Confirmé – 7 ans', 6), + ('Intermédiaire – 4 ans', 7), + ('Confirmé – 5 ans', 8), + ('Débutant – 1 an', 9), + ('Intermédiaire – 3 ans', 10); -- ------------------------------------------------------- -- 34. HistoryOfApprovals -- ------------------------------------------------------- -INSERT INTO HistoryOfApprovals ( DeliveryDate, ExpirationDate) VALUES - ( '2021-03-15', '2025-12-31'), - ( '2022-06-01', '2026-06-30'), - ( '2020-09-10', '2024-12-31'), - ( '2023-01-20', '2027-03-31'), - ( '2021-09-05', '2025-09-30'), - ( '2022-12-15', '2026-12-31'), - ( '2021-11-01', '2025-11-30'), - ( '2023-06-10', '2027-06-30'), - ( '2019-03-15', '2021-03-14'), -- expirée (historique) - ('2023-09-01', '2026-09-30'); +INSERT INTO HistoryOfApprovals (DeliveryDate, ExpirationDate) +VALUES ('2021-03-15', '2025-12-31'), + ('2022-06-01', '2026-06-30'), + ('2020-09-10', '2024-12-31'), + ('2023-01-20', '2027-03-31'), + ('2021-09-05', '2025-09-30'), + ('2022-12-15', '2026-12-31'), + ('2021-11-01', '2025-11-30'), + ('2023-06-10', '2027-06-30'), + ('2019-03-15', '2021-03-14'), -- expirée (historique) + ('2023-09-01', '2026-09-30'); -- ------------------------------------------------------- -- 35. StaffHistoryOfApprovals -- ------------------------------------------------------- -INSERT INTO StaffHistoryOfApprovals (StaffId, HistoryOfApprovalId) VALUES - (1, 1), (2, 2), (3, 3), (4, 4), (5, 5), - (6, 6), (7, 7), (8, 8), (9, 9), (10,10), - (3, 1); -- Nicolas a eu une précédente approbation +INSERT INTO StaffHistoryOfApprovals (StaffId, HistoryOfApprovalId) +VALUES (1, 1), + (2, 2), + (3, 3), + (4, 4), + (5, 5), + (6, 6), + (7, 7), + (8, 8), + (9, 9), + (10, 10), + (3, 1); +-- Nicolas a eu une précédente approbation -- ------------------------------------------------------- -- 36. Availabilities -- ------------------------------------------------------- -INSERT INTO Availabilities (AvailabilityDate, DeliveryDate, ExpirationDate, RenewallDate) VALUES - ( '2024-07-14', '2024-07-14', '2024-07-15', '2025-07-14'), - ( '2024-07-14', '2024-07-14', '2024-07-15', '2025-07-14'), - ( '2024-08-15', '2024-08-15', '2024-08-16', '2025-08-15'), - ( '2024-08-15', '2024-08-15', '2024-08-16', '2025-08-15'), - ( '2024-09-21', '2024-09-21', '2024-09-22', '2025-09-21'), - ( '2024-12-31', '2024-12-31', '2025-01-01', '2025-12-31'), - ( '2024-07-04', '2024-07-04', '2024-07-05', '2025-07-04'), - ( '2024-06-21', '2024-06-21', '2024-06-22', '2025-06-21'); +INSERT INTO Availabilities (AvailabilityDate, DeliveryDate, ExpirationDate, RenewallDate) +VALUES ('2024-07-14', '2024-07-14', '2024-07-15', '2025-07-14'), + ('2024-07-14', '2024-07-14', '2024-07-15', '2025-07-14'), + ('2024-08-15', '2024-08-15', '2024-08-16', '2025-08-15'), + ('2024-08-15', '2024-08-15', '2024-08-16', '2025-08-15'), + ('2024-09-21', '2024-09-21', '2024-09-22', '2025-09-21'), + ('2024-12-31', '2024-12-31', '2025-01-01', '2025-12-31'), + ('2024-07-04', '2024-07-04', '2024-07-05', '2025-07-04'), + ('2024-06-21', '2024-06-21', '2024-06-22', '2025-06-21'); -- ------------------------------------------------------- -- 37. StaffAvailabilities -- ------------------------------------------------------- -INSERT INTO StaffAvailabilities (StaffId, AvailabilityId) VALUES - (1, 1), (2, 1), (5, 1), (8, 1), -- Paris 14 juillet - (1, 3), (3, 3), (6, 3), (7, 3), -- Marseille 15 août - (2, 5), (4, 5), (9, 5), -- Bordeaux - (1, 6), (2, 6), (5, 6), (10,6), -- Nouvel an - (3, 7), (6, 7), (8, 7), -- 4 juillet Lyon - (4, 8), (7, 8), (9, 8); -- Fête musique +INSERT INTO StaffAvailabilities (StaffId, AvailabilityId) +VALUES (1, 1), + (2, 1), + (5, 1), + (8, 1), -- Paris 14 juillet + (1, 3), + (3, 3), + (6, 3), + (7, 3), -- Marseille 15 août + (2, 5), + (4, 5), + (9, 5), -- Bordeaux + (1, 6), + (2, 6), + (5, 6), + (10, 6), -- Nouvel an + (3, 7), + (6, 7), + (8, 7), -- 4 juillet Lyon + (4, 8), + (7, 8), + (9, 8); +-- Fête musique -- ------------------------------------------------------- -- 38. StaffContacts -- ------------------------------------------------------- -INSERT INTO StaffContacts (StaffId, ContactId) VALUES - (1, 1), (1, 2), - (2, 4), - (5, 6), - (6, 3), - (8, 5), - (10,8); +INSERT INTO StaffContacts (StaffId, ContactId) +VALUES (1, 1), + (1, 2), + (2, 4), + (5, 6), + (6, 3), + (8, 5), + (10, 8); -- ------------------------------------------------------- -- 39. Trucks -- ------------------------------------------------------- -INSERT INTO Trucks ( Type, MaxExplosiveCapacity, Sizes, Status) VALUES - ( 'Fourgon 20m³', 500.0, '5.5m x 2.2m x 2.5m', 'Disponible'), - ( 'Semi-remorque ADR 82m³',3000.0, '13.6m x 2.4m x 2.8m','Disponible'), - ( 'Camion 40m³ frigorifié',1000.0, '7.2m x 2.4m x 2.6m', 'En maintenance'), - ( 'Fourgon 15m³', 300.0, '4.2m x 2.0m x 2.2m', 'Disponible'), - ( 'Pick-up plateau', 80.0, '2.0m x 1.8m x 0.5m', 'Disponible'); +INSERT INTO Trucks (Type, MaxExplosiveCapacity, Sizes, Status) +VALUES ('Fourgon 20m³', 500.0, '5.5m x 2.2m x 2.5m', 'Disponible'), + ('Semi-remorque ADR 82m³', 3000.0, '13.6m x 2.4m x 2.8m', 'Disponible'), + ('Camion 40m³ frigorifié', 1000.0, '7.2m x 2.4m x 2.6m', 'En maintenance'), + ('Fourgon 15m³', 300.0, '4.2m x 2.0m x 2.2m', 'Disponible'), + ('Pick-up plateau', 80.0, '2.0m x 1.8m x 0.5m', 'Disponible'); -- ------------------------------------------------------- -- 40. SoundCategories -- ------------------------------------------------------- -INSERT INTO SoundCategories (Name) VALUES - ( 'Ouverture / Intro'), - ( 'Corps de spectacle'), - ( 'Bouquet final'), - ( 'Transition'), - ( 'Ambiance'); +INSERT INTO SoundCategories (Name) +VALUES ('Ouverture / Intro'), + ('Corps de spectacle'), + ('Bouquet final'), + ('Transition'), + ('Ambiance'); -- ------------------------------------------------------- -- 41. Sounds -- ------------------------------------------------------- -INSERT INTO Sounds ( Name, Type, Artist, Duration, Kind, Format, CreationDate, SoundCategoryId) VALUES - ( '1812 Ouverture', 'Classique', 'Tchaïkovski', 900, 'Musique', 'WAV 48kHz 24bit', '2023-05-10', 1), - ( 'La Marseillaise Orchestrale','Hymne', 'Berlioz arr.', 210, 'Musique', 'WAV 48kHz 24bit', '2023-05-10', 1), - ( 'Also Sprach Zarathustra', 'Classique', 'Richard Strauss', 480, 'Musique', 'WAV 48kHz 24bit', '2023-06-01', 1), - ( 'Fanfare Spectacle 01', 'Fanfare', 'Studio Pyro', 60, 'Jingle', 'WAV 44.1kHz', '2024-01-15', 4), - ( 'Symphonie Feu & Lumière', 'Orchestral', 'Studio Pyro', 1200, 'Musique', 'WAV 48kHz 24bit', '2024-02-20', 2), - ( 'Rock the Fireworks', 'Rock', 'PyroRock Band', 780, 'Musique', 'MP3 320kbps', '2023-09-05', 2), - ( 'Electronic Fire Mix', 'Électronique', 'DJ Pyro', 960, 'Mix', 'WAV 44.1kHz', '2023-11-15', 2), - ( 'Finale Épique', 'Orchestral', 'Studio Pyro', 180, 'Musique', 'WAV 48kHz 24bit', '2024-01-15', 3), - ( 'Grand Finale 2024', 'Orchestral', 'Philharmonique Pyro', 240, 'Musique', 'WAV 48kHz 24bit', '2024-03-01', 3), - ( 'Ambiance Nocturne', 'Ambient', 'Sound Design Studio', 600, 'Musique', 'WAV 44.1kHz', '2023-07-20', 5); +INSERT INTO Sounds (Name, Type, Artist, Duration, Kind, Format, CreationDate, SoundCategoryId) +VALUES ('1812 Ouverture', 'Classique', 'Tchaïkovski', 900, 'Musique', 'WAV 48kHz 24bit', '2023-05-10', 1), + ('La Marseillaise Orchestrale', 'Hymne', 'Berlioz arr.', 210, 'Musique', 'WAV 48kHz 24bit', '2023-05-10', 1), + ('Also Sprach Zarathustra', 'Classique', 'Richard Strauss', 480, 'Musique', 'WAV 48kHz 24bit', '2023-06-01', 1), + ('Fanfare Spectacle 01', 'Fanfare', 'Studio Pyro', 60, 'Jingle', 'WAV 44.1kHz', '2024-01-15', 4), + ('Symphonie Feu & Lumière', 'Orchestral', 'Studio Pyro', 1200, 'Musique', 'WAV 48kHz 24bit', '2024-02-20', 2), + ('Rock the Fireworks', 'Rock', 'PyroRock Band', 780, 'Musique', 'MP3 320kbps', '2023-09-05', 2), + ('Electronic Fire Mix', 'Électronique', 'DJ Pyro', 960, 'Mix', 'WAV 44.1kHz', '2023-11-15', 2), + ('Finale Épique', 'Orchestral', 'Studio Pyro', 180, 'Musique', 'WAV 48kHz 24bit', '2024-01-15', 3), + ('Grand Finale 2024', 'Orchestral', 'Philharmonique Pyro', 240, 'Musique', 'WAV 48kHz 24bit', '2024-03-01', 3), + ('Ambiance Nocturne', 'Ambient', 'Sound Design Studio', 600, 'Musique', 'WAV 44.1kHz', '2023-07-20', 5); -- ------------------------------------------------------- -- 42. Shows -- ------------------------------------------------------- -INSERT INTO Shows (Name, Place, Description, Date, PyrotechnicImplementationPlan, CityId) VALUES - ( 'Feux du 14 Juillet Paris 2024', 'Trocadéro – Tour Eiffel', 'Grand spectacle national – 30 minutes – 120 000 spectateurs', '2024-07-14', 'plans/paris_14juillet_2024_v3.pdf', 1), - ( 'Festival Lumières Lyon 2024', 'Place Bellecour', 'Spectacle estival – 20 minutes – 50 000 spectateurs', '2024-08-03', 'plans/lyon_festival_2024_v2.pdf', 2), - ( 'Fête Nationale Marseille 2024', 'Vieux-Port', 'Show nautique et aérien – 25 minutes', '2024-07-14', 'plans/marseille_14juillet_2024_v1.pdf',3), - ('Gala Entreprise Paris 2024', 'Château de Versailles', 'Show privé soirée de gala – 15 minutes', '2024-09-21', 'plans/versailles_gala_2024_v2.pdf', 1), - ('Saint-Sylvestre Bordeaux 2024', 'Place de la Bourse', 'Feux du nouvel an – 20 minutes', '2024-12-31', 'plans/bordeaux_sylvestre_2024_v1.pdf', 4), - ('Fête de la Musique Nantes 2024', 'Île de Nantes', 'Show pyrotechnique de clôture – 10 minutes', '2024-06-21', 'plans/nantes_musique_2024_v1.pdf', 6), - ( 'Inauguration Parc Strasbourg 2025', 'Parc de l Orangerie', 'Feux d\inauguration – 12 minutes', '2025-04-15', 'plans/strasbourg_inaug_2025_v1.pdf', 5), - ('Feux Casino Nice 2024', 'Promenade des Anglais', 'Show prestige casino – 18 minutes', '2024-11-01', 'plans/nice_casino_2024_v2.pdf', 9); +INSERT INTO Shows (Name, Place, Description, Date, PyrotechnicImplementationPlan, CityId) +VALUES ('Feux du 14 Juillet Paris 2024', 'Trocadéro – Tour Eiffel', 'Grand spectacle national – 30 minutes – 120 000 spectateurs', '2024-07-14', + 'plans/paris_14juillet_2024_v3.pdf', 1), + ('Festival Lumières Lyon 2024', 'Place Bellecour', 'Spectacle estival – 20 minutes – 50 000 spectateurs', '2024-08-03', 'plans/lyon_festival_2024_v2.pdf', 2), + ('Fête Nationale Marseille 2024', 'Vieux-Port', 'Show nautique et aérien – 25 minutes', '2024-07-14', 'plans/marseille_14juillet_2024_v1.pdf', 3), + ('Gala Entreprise Paris 2024', 'Château de Versailles', 'Show privé soirée de gala – 15 minutes', '2024-09-21', 'plans/versailles_gala_2024_v2.pdf', 1), + ('Saint-Sylvestre Bordeaux 2024', 'Place de la Bourse', 'Feux du nouvel an – 20 minutes', '2024-12-31', 'plans/bordeaux_sylvestre_2024_v1.pdf', 4), + ('Fête de la Musique Nantes 2024', 'Île de Nantes', 'Show pyrotechnique de clôture – 10 minutes', '2024-06-21', 'plans/nantes_musique_2024_v1.pdf', 6), + ('Inauguration Parc Strasbourg 2025', 'Parc de l Orangerie', 'Feux d\inauguration – 12 minutes', '2025-04-15', 'plans/strasbourg_inaug_2025_v1.pdf', 5), + ('Feux Casino Nice 2024', 'Promenade des Anglais', 'Show prestige casino – 18 minutes', '2024-11-01', 'plans/nice_casino_2024_v2.pdf', 9); -- ------------------------------------------------------- -- 43. ShowStaffs -- ------------------------------------------------------- -INSERT INTO ShowStaffs (StaffId, ShowId) VALUES - (1,1),(2,1),(5,1),(8,1),(7,1), - (1,2),(3,2),(6,2),(10,2), - (2,3),(4,3),(6,3),(8,3), - (1,4),(5,4),(7,4), - (2,5),(3,5),(9,5),(10,5), - (4,6),(7,6),(9,6), - (1,7),(6,7),(8,7), - (2,8),(5,8),(7,8); +INSERT INTO ShowStaffs (StaffId, ShowId) +VALUES (1, 1), + (2, 1), + (5, 1), + (8, 1), + (7, 1), + (1, 2), + (3, 2), + (6, 2), + (10, 2), + (2, 3), + (4, 3), + (6, 3), + (8, 3), + (1, 4), + (5, 4), + (7, 4), + (2, 5), + (3, 5), + (9, 5), + (10, 5), + (4, 6), + (7, 6), + (9, 6), + (1, 7), + (6, 7), + (8, 7), + (2, 8), + (5, 8), + (7, 8); -- ------------------------------------------------------- -- 44. ShowTrucks -- ------------------------------------------------------- -INSERT INTO ShowTrucks (ShowId, TruckId) VALUES - (1,2),(1,4), - (2,1),(2,4), - (3,2),(3,5), - (4,1), - (5,2),(5,4), - (6,4),(6,5), - (7,1), - (8,2); +INSERT INTO ShowTrucks (ShowId, TruckId) +VALUES (1, 2), + (1, 4), + (2, 1), + (2, 4), + (3, 2), + (3, 5), + (4, 1), + (5, 2), + (5, 4), + (6, 4), + (6, 5), + (7, 1), + (8, 2); -- ------------------------------------------------------- -- 45. ShowMaterials -- ------------------------------------------------------- -INSERT INTO ShowMaterials (ShowId, MaterialId) VALUES - (1,1),(1,2),(1,3),(1,6),(1,9),(1,10),(1,12), - (2,1),(2,2),(2,4),(2,6),(2,8),(2,12), - (3,1),(3,2),(3,5),(3,6),(3,9), - (4,1),(4,2),(4,6),(4,7),(4,11), - (5,1),(5,2),(5,3),(5,6),(5,9), - (6,1),(6,4),(6,6),(6,8), - (7,1),(7,2),(7,6),(7,7), - (8,1),(8,2),(8,6),(8,10); +INSERT INTO ShowMaterials (ShowId, MaterialId) +VALUES (1, 1), + (1, 2), + (1, 3), + (1, 6), + (1, 9), + (1, 10), + (1, 12), + (2, 1), + (2, 2), + (2, 4), + (2, 6), + (2, 8), + (2, 12), + (3, 1), + (3, 2), + (3, 5), + (3, 6), + (3, 9), + (4, 1), + (4, 2), + (4, 6), + (4, 7), + (4, 11), + (5, 1), + (5, 2), + (5, 3), + (5, 6), + (5, 9), + (6, 1), + (6, 4), + (6, 6), + (6, 8), + (7, 1), + (7, 2), + (7, 6), + (7, 7), + (8, 1), + (8, 2), + (8, 6), + (8, 10); -- ------------------------------------------------------- -- 46. Contracts (Show x ServiceProvider) -- ------------------------------------------------------- -INSERT INTO Contracts (ShowId, ServiceProviderId, TermsAndConditions) VALUES - (1, 1, 'Prestation sono 4h – montage J-1 inclus – démo technique 13/07'), - (1, 4, 'Sécurité périmètre – 25 agents – 12h de présence'), - (2, 2, 'Sono scène + diffusion – installation J-1'), - (2, 3, 'Éclairage scénique 200 projecteurs LED'), - (3, 5, 'Sécurité renforcée port – zone pyro – 40 agents'), - (4, 1, 'Sono de prestige – régie son Versailles'), - (4, 3, 'Éclairage château – mapping vidéo inclus'), - (5, 2, 'Sono place de la Bourse – diffusion périmètre'), - (6, 7, 'Location groupe électrogène 100kVA'), - (7, 6, 'Transport matériel Strasbourg – 2 rotations'), - (8, 1, 'Sono promenade – diffusion linéaire'), - (8, 8, 'Équipe médicale de permanence – 4h'); +INSERT INTO Contracts (ShowId, ServiceProviderId, TermsAndConditions) +VALUES (1, 1, 'Prestation sono 4h – montage J-1 inclus – démo technique 13/07'), + (1, 4, 'Sécurité périmètre – 25 agents – 12h de présence'), + (2, 2, 'Sono scène + diffusion – installation J-1'), + (2, 3, 'Éclairage scénique 200 projecteurs LED'), + (3, 5, 'Sécurité renforcée port – zone pyro – 40 agents'), + (4, 1, 'Sono de prestige – régie son Versailles'), + (4, 3, 'Éclairage château – mapping vidéo inclus'), + (5, 2, 'Sono place de la Bourse – diffusion périmètre'), + (6, 7, 'Location groupe électrogène 100kVA'), + (7, 6, 'Transport matériel Strasbourg – 2 rotations'), + (8, 1, 'Sono promenade – diffusion linéaire'), + (8, 8, 'Équipe médicale de permanence – 4h'); -- ------------------------------------------------------- -- 47. SoundTimecodes (Show x Sound) -- ------------------------------------------------------- -INSERT INTO SoundTimecodes (ShowId, SoundId, Start, [End]) VALUES - (1, 1, 0.0, 900.0), - (1, 5, 900.0, 2100.0), - (1, 9, 2100.0, 2340.0), - (2, 3, 0.0, 480.0), - (2, 7, 480.0, 1440.0), - (2, 8, 1440.0, 1620.0), - (3, 2, 0.0, 210.0), - (3, 6, 210.0, 990.0), - (3, 9, 990.0, 1230.0), - (4, 10, 0.0, 600.0), - (4, 5, 600.0, 1500.0), - (4, 8, 1500.0, 1680.0), - (5, 7, 0.0, 960.0), - (5, 9, 960.0, 1200.0), - (8, 10, 0.0, 600.0), - (8, 5, 600.0, 1320.0), - (8, 9, 1320.0, 1560.0); +INSERT INTO SoundTimecodes (ShowId, SoundId, Start, [ End]) +VALUES (1, 1, 0.0, 900.0), + (1, 5, 900.0, 2100.0), + (1, 9, 2100.0, 2340.0), + (2, 3, 0.0, 480.0), + (2, 7, 480.0, 1440.0), + (2, 8, 1440.0, 1620.0), + (3, 2, 0.0, 210.0), + (3, 6, 210.0, 990.0), + (3, 9, 990.0, 1230.0), + (4, 10, 0.0, 600.0), + (4, 5, 600.0, 1500.0), + (4, 8, 1500.0, 1680.0), + (5, 7, 0.0, 960.0), + (5, 9, 960.0, 1200.0), + (8, 10, 0.0, 600.0), + (8, 5, 600.0, 1320.0), + (8, 9, 1320.0, 1560.0); -- ------------------------------------------------------- -- 48. ProductTimecodes (Product x Show) -- ------------------------------------------------------- -INSERT INTO ProductTimecodes (ProductId, ShowId, Start, [End]) VALUES +INSERT INTO ProductTimecodes (ProductId, ShowId, Start, [ End]) +VALUES -- Paris 14 juillet -(3, 1, 0.0, 60.0), -(7, 1, 30.0, 300.0), -(2, 1, 300.0, 600.0), -(1, 1, 600.0, 1200.0), +(3, 1, 0.0, 60.0), +(7, 1, 30.0, 300.0), +(2, 1, 300.0, 600.0), +(1, 1, 600.0, 1200.0), (8, 1, 1200.0, 1800.0), (4, 1, 1800.0, 2100.0), (5, 1, 2100.0, 2200.0), (6, 1, 2200.0, 2340.0), -- Lyon festival -(7, 2, 0.0, 240.0), -(2, 2, 240.0, 600.0), -(1, 2, 600.0, 1000.0), +(7, 2, 0.0, 240.0), +(2, 2, 240.0, 600.0), +(1, 2, 600.0, 1000.0), (9, 2, 1000.0, 1200.0), -- Marseille -(3, 3, 0.0, 90.0), -(7, 3, 60.0, 360.0), -(4, 3, 360.0, 900.0), -(6, 3, 900.0, 1230.0), +(3, 3, 0.0, 90.0), +(7, 3, 60.0, 360.0), +(4, 3, 360.0, 900.0), +(6, 3, 900.0, 1230.0), -- Gala Versailles -(10,4, 0.0, 60.0), -(2, 4, 60.0, 300.0), -(1, 4, 300.0, 700.0), -(6, 4, 700.0, 900.0), +(10, 4, 0.0, 60.0), +(2, 4, 60.0, 300.0), +(1, 4, 300.0, 700.0), +(6, 4, 700.0, 900.0), -- Bordeaux Sylvestre -(7, 5, 0.0, 300.0), -(1, 5, 300.0, 900.0), -(5, 5, 900.0, 1000.0), +(7, 5, 0.0, 300.0), +(1, 5, 300.0, 900.0), +(5, 5, 900.0, 1000.0), (6, 5, 1000.0, 1200.0); -- ------------------------------------------------------- -- 49. Users -- ------------------------------------------------------- -INSERT INTO Users (Name, Password, Salt, Email, Fonction) VALUES - ('admin', '$2a$12$hashed_password_admin', 'salt_admin_abc123', 'admin@pyrofetes.fr', 'Administrateur système'), - ('jean.dupuis', '$2a$12$hashed_password_jd', 'salt_jd_xyz789', 'j.dupuis@pyrofetes.fr', 'Directeur commercial'), - ('sophie.martin', '$2a$12$hashed_password_sm', 'salt_sm_qrs456', 's.martin@pyrofetes.fr', 'Responsable production'), - ('marc.leroy', '$2a$12$hashed_password_ml', 'salt_ml_tuv321', 'm.leroy@pyrofetes.fr', 'Gestionnaire stock'), - ( 'alice.henry', '$2a$12$hashed_password_ah', 'salt_ah_wxy654', 'a.henry@pyrofetes.fr', 'Chargée de projets'); \ No newline at end of file +INSERT INTO Users (Name, Password, Salt, Email, Fonction) +VALUES ('admin', '$2a$12$hashed_password_admin', 'salt_admin_abc123', 'admin@pyrofetes.fr', 'Administrateur système'), + ('jean.dupuis', '$2a$12$hashed_password_jd', 'salt_jd_xyz789', 'j.dupuis@pyrofetes.fr', 'Directeur commercial'), + ('sophie.martin', '$2a$12$hashed_password_sm', 'salt_sm_qrs456', 's.martin@pyrofetes.fr', 'Responsable production'), + ('marc.leroy', '$2a$12$hashed_password_ml', 'salt_ml_tuv321', 'm.leroy@pyrofetes.fr', 'Gestionnaire stock'), + ('alice.henry', '$2a$12$hashed_password_ah', 'salt_ah_wxy654', 'a.henry@pyrofetes.fr', 'Chargée de projets'); \ No newline at end of file diff --git a/PyroFetes/docker-compose.yml b/PyroFetes/docker-compose.yml deleted file mode 100644 index b486e83f..00000000 --- a/PyroFetes/docker-compose.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: 'pyrofetes-api' - -services: - sqlserver: - image: mcr.microsoft.com/mssql/server:2022-latest - container_name: ${COMPOSE_PROJECT_NAME}-sqlserver - ports: - - 127.0.0.1:1433:1433 - volumes: - - type: volume - source: sqlserver-volume - target: /var/opt/mssql - environment: - ACCEPT_EULA: "Y" - MSSQL_SA_PASSWORD: ${SA_PASSWORD} - MSSQL_PID: "Developer" - healthcheck: - test: ["CMD", "/opt/mssql-tools18/bin/sqlcmd", "-S", "localhost", "-U", "sa", "-P", "${SA_PASSWORD}", "-Q", "SELECT 1", "-No"] - interval: 10s - timeout: 5s - retries: 10 - start_period: 30s - networks: - - network - -networks: - network: - name: ${COMPOSE_PROJECT_NAME}-network - driver: bridge - -volumes: - sqlserver-volume: - driver: local diff --git a/PyroFetes/wwwroot/Images/logo.jpg b/PyroFetes/wwwroot/Images/logo.jpg deleted file mode 100644 index e459459759d1217e5d65d506dae8249f932963b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 47397 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 j{QvTsw*Q+S*!_{Q-FIXoPSo)mz(