From ff590302e208d545380a48528f705028495e9b39 Mon Sep 17 00:00:00 2001 From: sanchezvem Date: Fri, 17 Oct 2025 01:05:50 +0100 Subject: [PATCH] Created all endpoints for Quotation and QuotationProduct --- .../DTO/Quotation/Response/GetQuotationDto.cs | 1 + .../PatchQuotationProductQuantityDto.cs | 3 +- .../Response/GetQuotationProductDto.cs | 3 +- ...PurchaseOrderPurchaseConditionsEndpoint.cs | 2 +- .../CreateQuotationProductEndpoint.cs | 70 +++++++++++++++++++ .../DeleteQuotationProductEndpoint.cs | 36 ++++++++++ .../PatchQuotationProductQuantityEndpoint.cs | 36 ++++++++++ .../Quotation/DeleteQuotationEndpoint.cs | 41 +++++++++++ .../Quotation/GetAllQuotationEndpoint.cs | 48 +++++++++++++ .../Quotation/GetQuotationEndpoint.cs | 59 ++++++++++++++++ .../PatchQuotationConditionsSaleEndpoint.cs | 58 +++++++++++++++ 11 files changed, 353 insertions(+), 4 deletions(-) create mode 100644 PyroFetes/Endpoints/QuoationProduct/CreateQuotationProductEndpoint.cs create mode 100644 PyroFetes/Endpoints/QuoationProduct/DeleteQuotationProductEndpoint.cs create mode 100644 PyroFetes/Endpoints/QuoationProduct/PatchQuotationProductQuantityEndpoint.cs create mode 100644 PyroFetes/Endpoints/Quotation/DeleteQuotationEndpoint.cs create mode 100644 PyroFetes/Endpoints/Quotation/GetAllQuotationEndpoint.cs create mode 100644 PyroFetes/Endpoints/Quotation/GetQuotationEndpoint.cs create mode 100644 PyroFetes/Endpoints/Quotation/PatchQuotationConditionsSaleEndpoint.cs diff --git a/PyroFetes/DTO/Quotation/Response/GetQuotationDto.cs b/PyroFetes/DTO/Quotation/Response/GetQuotationDto.cs index 877c8e2..589197c 100644 --- a/PyroFetes/DTO/Quotation/Response/GetQuotationDto.cs +++ b/PyroFetes/DTO/Quotation/Response/GetQuotationDto.cs @@ -6,5 +6,6 @@ public class GetQuotationDto { public int Id { get; set; } public string? Message { get; set; } + public string? ConditionsSale { get; set; } public List? GetQuotationProductDto { get; set; } } \ No newline at end of file diff --git a/PyroFetes/DTO/QuotationProduct/Request/PatchQuotationProductQuantityDto.cs b/PyroFetes/DTO/QuotationProduct/Request/PatchQuotationProductQuantityDto.cs index 2428f49..3530d61 100644 --- a/PyroFetes/DTO/QuotationProduct/Request/PatchQuotationProductQuantityDto.cs +++ b/PyroFetes/DTO/QuotationProduct/Request/PatchQuotationProductQuantityDto.cs @@ -2,6 +2,7 @@ namespace PyroFetes.DTO.QuotationProduct.Request; public class PatchQuotationProductQuantityDto { - public int Id { get; set; } + public int ProductId { get; set; } + public int QuotationId { get; set; } public int Quantity { 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 c5a4ca0..4ef123b 100644 --- a/PyroFetes/DTO/QuotationProduct/Response/GetQuotationProductDto.cs +++ b/PyroFetes/DTO/QuotationProduct/Response/GetQuotationProductDto.cs @@ -2,7 +2,6 @@ namespace PyroFetes.DTO.QuotationProduct.Response; public class GetQuotationProductDto { - public int Id { get; set; } public int Quantity { get; set; } public int QuotationId { get; set; } @@ -10,7 +9,7 @@ public class GetQuotationProductDto public string? QuotationConditionsSale { get; set; } public int ProductId { get; set; } - public int ProductReferences { get; set; } + public string? ProductReferences { get; set; } public string? ProductName { get; set; } public decimal ProductDuration {get; set;} public decimal ProductCaliber { get; set; } diff --git a/PyroFetes/Endpoints/PurchaseOrder/PatchPurchaseOrderPurchaseConditionsEndpoint.cs b/PyroFetes/Endpoints/PurchaseOrder/PatchPurchaseOrderPurchaseConditionsEndpoint.cs index 1339f45..ee6bbff 100644 --- a/PyroFetes/Endpoints/PurchaseOrder/PatchPurchaseOrderPurchaseConditionsEndpoint.cs +++ b/PyroFetes/Endpoints/PurchaseOrder/PatchPurchaseOrderPurchaseConditionsEndpoint.cs @@ -7,7 +7,7 @@ using PyroFetes.DTO.PurchaseProduct.Response; namespace PyroFetes.Endpoints.PurchaseOrder; -public class PatchPurchaseProductQuantityEndpoint(PyroFetesDbContext database) : Endpoint +public class PatchPurchaseOrderPurchaseConditionsEndpoint(PyroFetesDbContext database) : Endpoint { public override void Configure() { diff --git a/PyroFetes/Endpoints/QuoationProduct/CreateQuotationProductEndpoint.cs b/PyroFetes/Endpoints/QuoationProduct/CreateQuotationProductEndpoint.cs new file mode 100644 index 0000000..e0c36e6 --- /dev/null +++ b/PyroFetes/Endpoints/QuoationProduct/CreateQuotationProductEndpoint.cs @@ -0,0 +1,70 @@ +using FastEndpoints; +using Microsoft.EntityFrameworkCore; +using PyroFetes.DTO.PurchaseProduct.Request; +using PyroFetes.DTO.PurchaseProduct.Response; +using PyroFetes.DTO.QuotationProduct.Request; +using PyroFetes.DTO.QuotationProduct.Response; + +namespace PyroFetes.Endpoints.QuoationProduct; + +public class CreateQuotationProductEndpoint(PyroFetesDbContext database) : Endpoint +{ + public override void Configure() + { + Post("/api/quotationProduct"); + AllowAnonymous(); + } + + public override async Task HandleAsync(CreateQuotationProductDto req, CancellationToken ct) + { + var product = await database.Products.FirstOrDefaultAsync(p => p.Id == req.ProductId, ct); + if (product == null) + { + await Send.NotFoundAsync(ct); + return; + } + + var quotation = await database.Quotations.FirstOrDefaultAsync(q => q.Id == req.QuotationId, ct); + + if (quotation == null) + { + quotation = new Models.Quotation() + { + Message = req.QuotationMessage ?? "", + ConditionsSale = req.QuotationConditionsSale, + }; + database.Quotations.Add(quotation); + await database.SaveChangesAsync(ct); + } + + var quotationProduct = new Models.QuotationProduct() + { + ProductId = product.Id, + QuotationId = quotation.Id, + Quantity = req.Quantity + }; + database.QuotationProducts.Add(quotationProduct); + await database.SaveChangesAsync(ct); + + var responseDto = new GetQuotationProductDto() + { + ProductId = product.Id, + ProductReferences = product.Reference, + ProductName = product.Name, + ProductDuration = product.Duration, + ProductCaliber = product.Caliber, + ProductApprovalNumber = product.ApprovalNumber, + ProductWeight = product.Weight, + ProductNec = product.Nec, + ProductImage = product.Image, + ProductLink = product.Link, + ProductMinimalQuantity = product.MinimalQuantity, + Quantity = quotationProduct.Quantity, + QuotationMessage = quotation.Message, + QuotationConditionsSale = quotation.ConditionsSale, + QuotationId = quotation.Id, + }; + + await Send.OkAsync(responseDto, ct); + } +} diff --git a/PyroFetes/Endpoints/QuoationProduct/DeleteQuotationProductEndpoint.cs b/PyroFetes/Endpoints/QuoationProduct/DeleteQuotationProductEndpoint.cs new file mode 100644 index 0000000..0f14336 --- /dev/null +++ b/PyroFetes/Endpoints/QuoationProduct/DeleteQuotationProductEndpoint.cs @@ -0,0 +1,36 @@ +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace PyroFetes.Endpoints.QuoationProduct; + +public class DeleteQuotationProductRequest +{ + public int ProductId { get; set; } + public int QuotationId { get; set; } +} + +public class DeleteQuotationProductEndpoint(PyroFetesDbContext database) : Endpoint +{ + public override void Configure() + { + Delete("/api/quotationProduct/{ProductId}/{QuotationId}", x => new {x.ProductId, x.QuotationId}); + AllowAnonymous(); + } + + public override async Task HandleAsync(DeleteQuotationProductRequest req, CancellationToken ct) + { + var quotationProduct = await database.QuotationProducts + .SingleOrDefaultAsync(qo => qo.ProductId == req.ProductId && qo.QuotationId == req.QuotationId, ct); + + if (quotationProduct == null) + { + await Send.NotFoundAsync(ct); + return; + } + + database.QuotationProducts.Remove(quotationProduct); + await database.SaveChangesAsync(ct); + + await Send.NoContentAsync(ct); + } +} \ No newline at end of file diff --git a/PyroFetes/Endpoints/QuoationProduct/PatchQuotationProductQuantityEndpoint.cs b/PyroFetes/Endpoints/QuoationProduct/PatchQuotationProductQuantityEndpoint.cs new file mode 100644 index 0000000..424228a --- /dev/null +++ b/PyroFetes/Endpoints/QuoationProduct/PatchQuotationProductQuantityEndpoint.cs @@ -0,0 +1,36 @@ +using FastEndpoints; +using Microsoft.EntityFrameworkCore; +using PyroFetes.DTO.QuotationProduct.Request; +using PyroFetes.DTO.QuotationProduct.Response; + +namespace PyroFetes.Endpoints.QuoationProduct; + +public class PatchQuotationProductQuantityEndpoint(PyroFetesDbContext database) : Endpoint +{ + public override void Configure() + { + Patch("/api/quotationProduct/{ProductId}/{QuotationId}/Quantity", x => new { x.ProductId, x.QuotationId }); + AllowAnonymous(); + } + + public override async Task HandleAsync(PatchQuotationProductQuantityDto req, CancellationToken ct) + { + var quotationProduct = await database.QuotationProducts.SingleOrDefaultAsync(qo => qo.ProductId == req.ProductId && qo.QuotationId == req.QuotationId, ct); + if (quotationProduct == null) + { + await Send.NotFoundAsync(ct); + return; + } + + quotationProduct.Quantity = req.Quantity; + await database.SaveChangesAsync(ct); + + GetQuotationProductDto responseDto = new() + { + ProductId = quotationProduct.ProductId, + QuotationId = quotationProduct.QuotationId, + Quantity = quotationProduct.Quantity + }; + await Send.OkAsync(responseDto, ct); + } +} \ No newline at end of file diff --git a/PyroFetes/Endpoints/Quotation/DeleteQuotationEndpoint.cs b/PyroFetes/Endpoints/Quotation/DeleteQuotationEndpoint.cs new file mode 100644 index 0000000..3077bc1 --- /dev/null +++ b/PyroFetes/Endpoints/Quotation/DeleteQuotationEndpoint.cs @@ -0,0 +1,41 @@ +using FastEndpoints; +using Microsoft.EntityFrameworkCore; + +namespace PyroFetes.Endpoints.Quotation; + +public class DeleteQuotationRequest +{ + public int Id { get; set; } +} + +public class DeleteQuotationEndpoint(PyroFetesDbContext database) : Endpoint +{ + public override void Configure() + { + Delete("/api/quotations/{Id}", x => new {x.Id}); + AllowAnonymous(); + } + + public override async Task HandleAsync(DeleteQuotationRequest req, CancellationToken ct) + { + var quotation = await database.Quotations + .Include(q => q.QuotationProducts) + .SingleOrDefaultAsync(q => q.Id == req.Id, ct); + + if (quotation == null) + { + await Send.NotFoundAsync(ct); + return; + } + + if (quotation.QuotationProducts != null && quotation.QuotationProducts.Any()) + { + database.QuotationProducts.RemoveRange(quotation.QuotationProducts); + } + + database.Quotations.Remove(quotation); + await database.SaveChangesAsync(ct); + + await Send.NoContentAsync(ct); + } +} \ No newline at end of file diff --git a/PyroFetes/Endpoints/Quotation/GetAllQuotationEndpoint.cs b/PyroFetes/Endpoints/Quotation/GetAllQuotationEndpoint.cs new file mode 100644 index 0000000..2dad3aa --- /dev/null +++ b/PyroFetes/Endpoints/Quotation/GetAllQuotationEndpoint.cs @@ -0,0 +1,48 @@ +using FastEndpoints; +using Microsoft.EntityFrameworkCore; +using PyroFetes.DTO.Quotation.Response; +using PyroFetes.DTO.QuotationProduct.Response; + +namespace PyroFetes.Endpoints.Quotation; + +public class GetAllQuotationEndpoint(PyroFetesDbContext database) : EndpointWithoutRequest> +{ + public override void Configure() + { + Get("/api/quotations"); + } + + public override async Task HandleAsync(CancellationToken ct) + { + var quotations = await database.Quotations + .Include(q => q.QuotationProducts!) + .ThenInclude(qp => qp.Product) + .Select(q => new GetQuotationDto + { + Id = q.Id, + Message = q.Message, + ConditionsSale = q.ConditionsSale, + GetQuotationProductDto = q.QuotationProducts.Select(qp => new GetQuotationProductDto + { + Quantity = qp.Quantity, + QuotationId = q.Id, + QuotationMessage = q.Message, + QuotationConditionsSale = q.ConditionsSale, + ProductId = qp.ProductId, + ProductReferences = qp.Product.Reference, + ProductName = qp.Product.Name, + ProductDuration = qp.Product.Duration, + ProductCaliber = qp.Product.Caliber, + ProductApprovalNumber = qp.Product.ApprovalNumber, + ProductWeight = qp.Product.Weight, + ProductNec = qp.Product.Nec, + ProductImage = qp.Product.Image, + ProductLink = qp.Product.Link, + ProductMinimalQuantity = qp.Product.MinimalQuantity, + }).ToList() + }) + .ToListAsync(ct); + + await Send.OkAsync(quotations, ct); + } +} \ No newline at end of file diff --git a/PyroFetes/Endpoints/Quotation/GetQuotationEndpoint.cs b/PyroFetes/Endpoints/Quotation/GetQuotationEndpoint.cs new file mode 100644 index 0000000..162245c --- /dev/null +++ b/PyroFetes/Endpoints/Quotation/GetQuotationEndpoint.cs @@ -0,0 +1,59 @@ +using FastEndpoints; +using Microsoft.EntityFrameworkCore; +using PyroFetes.DTO.Quotation.Response; +using PyroFetes.DTO.QuotationProduct.Response; + +namespace PyroFetes.Endpoints.Quotation; + +public class GetQuotationRequest +{ + public int Id { get; set; } +} + +public class GetQuotationEndpoint(PyroFetesDbContext database) : Endpoint +{ + public override void Configure() + { + Get("/api/quotations/{@Id}", x => new {x.Id}); + } + + public override async Task HandleAsync(GetQuotationRequest req, CancellationToken ct) + { + var quotation = await database.Quotations + .SingleOrDefaultAsync(x => x.Id == req.Id, ct); + + if (quotation == null) + { + await Send.NotFoundAsync(ct); + return; + } + + GetQuotationDto responseDto = new() + { + Id = quotation.Id, + Message = quotation.Message, + ConditionsSale = quotation.ConditionsSale, + GetQuotationProductDto = quotation.QuotationProducts + .Select(qp => new GetQuotationProductDto + { + Quantity = qp.Quantity, + QuotationId = quotation.Id, + QuotationMessage = quotation.Message, + QuotationConditionsSale = quotation.ConditionsSale, + ProductId = qp.ProductId, + ProductReferences = qp.Product.Reference, + ProductName = qp.Product.Name, + ProductDuration = qp.Product.Duration, + ProductCaliber = qp.Product.Caliber, + ProductApprovalNumber = qp.Product.ApprovalNumber, + ProductWeight = qp.Product.Weight, + ProductNec = qp.Product.Nec, + ProductImage = qp.Product.Image, + ProductLink = qp.Product.Link, + ProductMinimalQuantity = qp.Product.MinimalQuantity, + }).ToList() + }; + + await Send.OkAsync(responseDto, ct); + } +} \ No newline at end of file diff --git a/PyroFetes/Endpoints/Quotation/PatchQuotationConditionsSaleEndpoint.cs b/PyroFetes/Endpoints/Quotation/PatchQuotationConditionsSaleEndpoint.cs new file mode 100644 index 0000000..a7d520e --- /dev/null +++ b/PyroFetes/Endpoints/Quotation/PatchQuotationConditionsSaleEndpoint.cs @@ -0,0 +1,58 @@ +using FastEndpoints; +using Microsoft.EntityFrameworkCore; +using PyroFetes.DTO.PurchaseOrder.Request; +using PyroFetes.DTO.PurchaseOrder.Response; +using PyroFetes.DTO.PurchaseProduct.Response; +using PyroFetes.DTO.Quotation.Request; +using PyroFetes.DTO.Quotation.Response; +using PyroFetes.DTO.QuotationProduct.Response; + +namespace PyroFetes.Endpoints.Quotation; + +public class PatchQuotationConditionsSaleEndpoint(PyroFetesDbContext database) : Endpoint +{ + public override void Configure() + { + Patch("/api/quotations/{Id}/ConditionsSale", x => new { x.Id }); + AllowAnonymous(); + } + + public override async Task HandleAsync(PatchQuotationConditionsSaleDto req, CancellationToken ct) + { + var quotation = await database.Quotations.SingleOrDefaultAsync(x => x.Id == req.Id, ct); + if (quotation == null) + { + await Send.NotFoundAsync(ct); + return; + } + + quotation.ConditionsSale = req.ConditionsSale; + await database.SaveChangesAsync(ct); + + GetQuotationDto responseDto = new() + { + Id = quotation.Id, + Message = quotation.Message, + ConditionsSale = quotation.ConditionsSale, + GetQuotationProductDto = quotation.QuotationProducts.Select(qp => new GetQuotationProductDto + { + Quantity = qp.Quantity, + QuotationId = quotation.Id, + QuotationMessage = quotation.Message, + QuotationConditionsSale = quotation.ConditionsSale, + ProductId = qp.ProductId, + ProductReferences = qp.Product.Reference, + ProductName = qp.Product.Name, + ProductDuration = qp.Product.Duration, + ProductCaliber = qp.Product.Caliber, + ProductApprovalNumber = qp.Product.ApprovalNumber, + ProductWeight = qp.Product.Weight, + ProductNec = qp.Product.Nec, + ProductImage = qp.Product.Image, + ProductLink = qp.Product.Link, + ProductMinimalQuantity = qp.Product.MinimalQuantity, + }).ToList() + }; + await Send.OkAsync(responseDto, ct); + } +} \ No newline at end of file