From 45913112bea79f3cf515060e985010f6249d4f9e Mon Sep 17 00:00:00 2001 From: javiermengual Date: Thu, 5 Feb 2026 14:33:03 +0100 Subject: [PATCH] =?UTF-8?q?feat:=20A=C3=B1adido=20endpoints=20para=20Delet?= =?UTF-8?q?e=20Invoice=20y=20sus=20Lines=20,=20tambien=20corregido=20orden?= =?UTF-8?q?=20de=20Dto=20de=20GetById?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/InvoicesController.cs | 26 +++++++++++++++++++ .../Dtos/query/InvoiceDetailDto.cs | 4 +-- DoliMiddlewareApi/Dtos/query/InvoiceDto.cs | 4 +-- DoliMiddlewareApi/Mappers/InvoiceMapper.cs | 8 +++--- .../Services/Clients/DolibarrApiClient.cs | 8 ++++++ .../Services/Clients/IDolibarrApiClient.cs | 1 + DoliMiddlewareApi/Services/InvoiceService.cs | 16 ++++++++++++ 7 files changed, 59 insertions(+), 8 deletions(-) diff --git a/DoliMiddlewareApi/Controllers/InvoicesController.cs b/DoliMiddlewareApi/Controllers/InvoicesController.cs index 8ad227f..541947f 100644 --- a/DoliMiddlewareApi/Controllers/InvoicesController.cs +++ b/DoliMiddlewareApi/Controllers/InvoicesController.cs @@ -96,4 +96,30 @@ public class InvoicesController(InvoiceService invoiceService) : ControllerBase await invoiceService.ValidateInvoiceAsync(id); return NoContent(); } + + [HttpDelete("{id:int}")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + public async Task DeleteInvoice([Range(1, int.MaxValue)] int id) + { + await invoiceService.DeleteInvoiceAsync(id); + return NoContent(); + } + + [HttpDelete("{invoiceId:int}/lines/{lineId:int}")] + [ProducesResponseType(StatusCodes.Status204NoContent)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status400BadRequest)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status403Forbidden)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status404NotFound)] + [ProducesResponseType(typeof(ProblemDetails), StatusCodes.Status500InternalServerError)] + public async Task DeleteInvoiceLine( + [Range(1, int.MaxValue)] int invoiceId, + [Range(1, int.MaxValue)] int lineId) + { + await invoiceService.DeleteInvoiceLineAsync(invoiceId, lineId); + return NoContent(); + } } diff --git a/DoliMiddlewareApi/Dtos/query/InvoiceDetailDto.cs b/DoliMiddlewareApi/Dtos/query/InvoiceDetailDto.cs index 12a5cee..52af6b3 100644 --- a/DoliMiddlewareApi/Dtos/query/InvoiceDetailDto.cs +++ b/DoliMiddlewareApi/Dtos/query/InvoiceDetailDto.cs @@ -10,7 +10,7 @@ public class InvoiceDetailDto public decimal? Total { get; set; } public decimal? RemainToPay { get; set; } public string Status { get; set; } + public string? NotePublic { get; set; } + public string? NotePrivate { get; set; } public List? Lines { get; set; } - public string? note_public { get; set; } - public string? note_private { get; set; } } \ No newline at end of file diff --git a/DoliMiddlewareApi/Dtos/query/InvoiceDto.cs b/DoliMiddlewareApi/Dtos/query/InvoiceDto.cs index 66da608..92af20d 100644 --- a/DoliMiddlewareApi/Dtos/query/InvoiceDto.cs +++ b/DoliMiddlewareApi/Dtos/query/InvoiceDto.cs @@ -10,7 +10,7 @@ public class InvoiceDto public decimal? Total { get; set; } public decimal? RemainToPay { get; set; } public string Status { get; set; } + public string? NotePublic { get; set; } + public string? NotePrivate { get; set; } public string? ClientName { get; set; } - public string? note_public { get; set; } - public string? note_private { get; set; } } \ No newline at end of file diff --git a/DoliMiddlewareApi/Mappers/InvoiceMapper.cs b/DoliMiddlewareApi/Mappers/InvoiceMapper.cs index a6df167..e951d26 100644 --- a/DoliMiddlewareApi/Mappers/InvoiceMapper.cs +++ b/DoliMiddlewareApi/Mappers/InvoiceMapper.cs @@ -35,8 +35,8 @@ public static class InvoiceMapper : null, Status = ConvertStatusToWord(invoiceResponse.statut), - note_public = invoiceResponse.note_public, - note_private = invoiceResponse.note_private + NotePublic = invoiceResponse.note_public, + NotePrivate = invoiceResponse.note_private }; } @@ -54,8 +54,8 @@ public static class InvoiceMapper Total = baseDto.Total, RemainToPay = baseDto.RemainToPay, Status = baseDto.Status, - note_public = baseDto.note_public, - note_private = baseDto.note_private, + NotePublic = baseDto.NotePublic, + NotePrivate = baseDto.NotePrivate, Lines = data.Lines?.Select(MapToInvoiceLineDto).ToList() ?? new List() }; diff --git a/DoliMiddlewareApi/Services/Clients/DolibarrApiClient.cs b/DoliMiddlewareApi/Services/Clients/DolibarrApiClient.cs index c19c3ba..b8ff706 100644 --- a/DoliMiddlewareApi/Services/Clients/DolibarrApiClient.cs +++ b/DoliMiddlewareApi/Services/Clients/DolibarrApiClient.cs @@ -57,6 +57,14 @@ public class DolibarrApiClient(HttpClient httpClient, DolibarrTokenCacheService return await response.Content.ReadAsStringAsync(); } + public async Task DeleteAsync(string endpoint) + { + var request = new HttpRequestMessage(HttpMethod.Delete, endpoint); + AddDolibarrTokenHeader(request); + var response = await httpClient.SendAsync(request); + await EnsureSuccessOrThrowAsync(response, endpoint); + } + private void AddDolibarrTokenHeader(HttpRequestMessage request) { var dolibarrToken = tokenCacheService.GetDolibarrToken(); diff --git a/DoliMiddlewareApi/Services/Clients/IDolibarrApiClient.cs b/DoliMiddlewareApi/Services/Clients/IDolibarrApiClient.cs index 07c7ec1..e03cd8b 100644 --- a/DoliMiddlewareApi/Services/Clients/IDolibarrApiClient.cs +++ b/DoliMiddlewareApi/Services/Clients/IDolibarrApiClient.cs @@ -6,4 +6,5 @@ public interface IDolibarrApiClient Task> GetCollectionAsync(string endpoint) where T : class; Task PostAsync(string endpoint, object requestBody); Task PutAsync(string endpoint, object requestBody); + Task DeleteAsync(string endpoint); } diff --git a/DoliMiddlewareApi/Services/InvoiceService.cs b/DoliMiddlewareApi/Services/InvoiceService.cs index c7fcac3..d0e18b0 100644 --- a/DoliMiddlewareApi/Services/InvoiceService.cs +++ b/DoliMiddlewareApi/Services/InvoiceService.cs @@ -138,6 +138,22 @@ public class InvoiceService(IDolibarrApiClient apiClient) await apiClient.PostAsync($"invoices/{id}/validate", new { }); } + public async Task DeleteInvoiceAsync(int id) + { + var invoice = await apiClient.GetResourceAsync($"invoices/{id}"); + if (invoice.statut != "0") throw new ForbiddenException("Solo se pueden eliminar facturas en borrador (draft)"); + + await apiClient.DeleteAsync($"invoices/{id}"); + } + + public async Task DeleteInvoiceLineAsync(int invoiceId, int lineId) + { + var invoice = await apiClient.GetResourceAsync($"invoices/{invoiceId}"); + if (invoice.statut != "0") throw new ForbiddenException("Solo se pueden eliminar lĂ­neas de facturas en borrador (draft)"); + + await apiClient.DeleteAsync($"invoices/{invoiceId}/lines/{lineId}"); + } + private async Task> GetClientNamesAsync(List clientIds) { var uniqueIds = clientIds.Distinct().ToList();